pax_global_header00006660000000000000000000000064134005142100014500gustar00rootroot0000000000000052 comment=53d4b1fcb00d74bf1d3d772f278506db0b31950e gdl-0.9.9/000077500000000000000000000000001340051421000122655ustar00rootroot00000000000000gdl-0.9.9/.travis.yml000066400000000000000000000433341340051421000144050ustar00rootroot00000000000000language: cpp # TODO: investigate why MINI builds timeout on icc, while FULL ones not?! matrix: include: # - os: linux # env: COMPILER=icc CMAKE_BUILD_TYPE=Debug DEPS=MINI - os: linux env: COMPILER=gcc CMAKE_BUILD_TYPE=Debug DEPS=MINI - os: osx env: COMPILER=clang CMAKE_BUILD_TYPE=Debug DEPS=MINI - os: linux env: COMPILER=icc CMAKE_BUILD_TYPE=Debug DEPS=FULL - os: linux env: COMPILER=gcc CMAKE_BUILD_TYPE=Debug DEPS=FULL CODECOV=yes - os: osx env: COMPILER=clang CMAKE_BUILD_TYPE=Debug DEPS=FULL # - os: linux # env: COMPILER=icc CMAKE_BUILD_TYPE=Release DEPS=MINI - os: linux env: COMPILER=gcc CMAKE_BUILD_TYPE=Release DEPS=MINI - os: osx env: COMPILER=clang CMAKE_BUILD_TYPE=Release DEPS=MINI - os: linux env: COMPILER=gcc CMAKE_BUILD_TYPE=Release DEPS=FULL - os: linux env: COMPILER=icc CMAKE_BUILD_TYPE=Release DEPS=FULL - os: osx env: COMPILER=clang CMAKE_BUILD_TYPE=Release DEPS=FULL before_install: # TEMPORARILY disabling tests that did not work at "day zero" (i.e. SF -> github migration) - if [ $TRAVIS_OS_NAME == osx ]; then export SEDCMD="sed -i ''"; fi - if [ $TRAVIS_OS_NAME == linux ]; then export SEDCMD="sed -i"; fi - $SEDCMD '/test_bytscl.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_dicom.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_container.pro/d' testsuite/Makefile.am # TODO! not ready - $SEDCMD '/test_fft_leak.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_file_delete.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_file_search.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_file_test.pro/d' testsuite/Makefile.am # TODO! 2 errors on Dangling - $SEDCMD '/test_fix.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_formats.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_image_statistics.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_make_dll.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_n_tags.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_obj_isa.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_obj_new.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_plot_ranges.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_resolve_routine.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_rounding.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_simplex.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_step.pro/d' testsuite/Makefile.am # TODO! - if [ $TRAVIS_OS_NAME == osx ]; then $SEDCMD '/test_tic_toc.pro/d' testsuite/Makefile.am; fi # TODO! fails on OSX, e.g. https://travis-ci.org/gnudatalanguage/gdl/jobs/440977990 - $SEDCMD '/test_typename.pro/d' testsuite/Makefile.am # TODO! - $SEDCMD '/test_wait.pro/d' testsuite/Makefile.am # TODO! # https://github.com/travis-ci/travis-ci/issues/8613 - if [[ $TRAVIS_OS_NAME == 'linux' && $CXX == 'clang++' ]]; then export LD_LIBRARY_PATH=/usr/local/clang/lib:$LD_LIBRARY_PATH; fi # homebrew Python stuff... - if [ $TRAVIS_OS_NAME == osx ]; then brew upgrade python; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew install python@2; fi - if [ $TRAVIS_OS_NAME == osx ]; then /usr/bin/yes | /usr/local/bin/python -m pip uninstall numpy; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew remove numpy gdal postgis; fi - if [ $TRAVIS_OS_NAME == osx ]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON_LIBRARY=$(python-config --prefix)/lib/libpython2.7.dylib -DPYTHON_INCLUDE_DIR=$(python-config --prefix)/include/python2.7"; fi install: ## ## BUILD DEPENDENCIES ## # https://github.com/nemequ/icc-travis - if [ $COMPILER == icc ]; then wget "https://raw.githubusercontent.com/nemequ/icc-travis/master/install-icc.sh"; fi - if [ $COMPILER == icc ]; then sudo sh install-icc.sh; fi - if [ $COMPILER == icc ]; then source ~/.bashrc; fi - if [ $COMPILER == icc ]; then export CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_CXX_COMPILER=icpc -DCMAKE_C_COMPILER=icc"; fi # codecov - if [ -v CODECOV ]; then export APT_PACKAGES="$APT_PACKAGES lcov"; fi - if [ -v CODECOV ]; then wget -O CMakeModules/CodeCoverage.cmake https://raw.githubusercontent.com/bilke/cmake-modules/master/CodeCoverage.cmake; fi - if [ -v CODECOV ]; then TMPFILE=`tempfile` ;fi - if [ -v CODECOV ]; then tac src/CMakeLists.txt > $TMPFILE; fi - if [ -v CODECOV ]; then echo "set(CMAKE_CXX_FLAGS \${CMAKE_CXX_FLAGS_COVERAGE})" >> $TMPFILE; fi - if [ -v CODECOV ]; then echo "INCLUDE(CodeCoverage)" >> $TMPFILE; fi - if [ -v CODECOV ]; then tac $TMPFILE > src/CMakeLists.txt; fi - if [ -v CODECOV ]; then rm $TMPFILE; fi - if [ -v CODECOV ]; then echo "SETUP_TARGET_FOR_COVERAGE_LCOV(NAME codecov EXECUTABLE \${CMAKE_BUILD_TOOL} check)" >> testsuite/CMakeLists.txt; fi # pytest - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} python-pytest"; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then python2 -m pip install pytest; fi # CMake - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} cmake"; fi ## ## MANDATORY DEPENDENCIES ## # ncurses - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libncurses-dev"; fi # zlib - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} zlib1g-dev"; fi # gsl - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libgsl0-dev"; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} gsl"; fi # plplot - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libplplot-dev"; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} plplot"; fi ## ## OPTIONAL DEPENDENCIES ## # readline (OSX) / editline (Linux) - just to try both - TODO #TODO! - see https://github.com/gnudatalanguage/gdl/issues/227 # - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libeditline-dev"; fi # - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEDITLINE=ON -DREADLINE=OFF"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libreadline-gplv2-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEDITLINE=OFF -DREADLINE=ON"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} readline"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEDITLINE=OFF -DREADLINE=ON -DREADLINEDIR=/usr/local/opt/readline"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEDITLINE=OFF -DREADLINE=OFF"; fi # pnglib - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libpng-dev"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPNGLIB=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPNGLIB=OFF"; fi # OpenMP (for DEPS=FULL only if supported by the compile) - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DOPENMP=OFF"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} llvm libomp"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang"; fi # ImageMagick (Linux) / GraphicsMagick (OSX) - just to try both - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libmagick++-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGRAPHICSMAGICK=OFF -DMAGICK=ON"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} graphicsmagick"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGRAPHICSMAGICK=ON -DMAGICK=OFF"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGRAPHICSMAGICK=OFF -DMAGICK=OFF"; fi # wx - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libwxgtk2.8-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} wxwidgets"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DWXWIDGETS=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DWXWIDGETS=OFF"; fi # netcdf - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libnetcdf-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} netcdf"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DNETCDF=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DNETCDF=OFF"; fi # hdf4 - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libhdf4-alt-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DNETCDF=ON"; fi # TODO - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} hdf4"; fi # TODO - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DHDF=ON"; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DHDF=OFF"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DHDF=OFF"; fi # hdf5 - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libhdf5-serial-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} hdf5"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DHDF5=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DHDF5=OFF"; fi # fftw - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libfftw3-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} fftw"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DFFTW=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DFFTW=OFF"; fi # proj4 (only for Linux - TODO) - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libproj-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DLIBPROJ4=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DLIBPROJ4=OFF"; fi # MPICH - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libmpich-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} mpich"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DMPICH=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DMPICH=OFF"; fi # Python & NumPy (installing always as needed for the Python module build) - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} python-dev python-numpy-dev"; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} numpy"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON=OFF"; fi # udunits - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libudunits2-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} udunits"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DUDUNITS=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DUDUNITS=OFF"; fi # eigen - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then wget http://bitbucket.org/eigen/eigen/get/3.3.2.zip; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then unzip 3.3.2.zip; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEIGEN3DIR=../eigen-eigen-da9b4e14c255"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} eigen"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEIGEN3=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DEIGEN3=OFF"; fi # pslib (only Linux - TODO!) - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} pslib-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPSLIB=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPSLIB=OFF"; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DPSLIB=OFF"; fi # ECCODES API # - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libeccodes-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libgrib-api-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} eccodes"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGRIB=ON"; fi #- if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGRIB=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGRIB=OFF"; fi # QHULL - TODO: disabled for icc (see https://github.com/gnudatalanguage/gdl/issues/229) #- if [[ $COMPILER != icc && $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libqhull-dev"; fi #- if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libqhull-dev"; fi #- if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} qhull"; fi #- if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DQHULL=ON"; fi #- if [[ $COMPILER != icc && $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DQHULL=ON"; fi #- if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DQHULL=OFF"; fi # GLPK - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libglpk-dev"; fi - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} glpk"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGLPK=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DGLPK=OFF"; fi # X11 - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DX11=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DX11=OFF"; fi # TIFF/GeoTIFF - TODO: find appropriate libgeotiff package for linux - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libgeotiff-dev"; fi #- if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'osx' ]]; then export BREW_PACKAGES="${BREW_PACKAGES} libgeotiff"; fi - if [[ $DEPS == 'FULL' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DTIFF=ON -DGEOTIFF=ON"; fi - if [[ $DEPS == 'MINI' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DTIFF=OFF -DGEOTIFF=OFF"; fi # tirpc - TODO! # - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export APT_PACKAGES="${APT_PACKAGES} libtirpc-dev"; fi # - if [[ $DEPS == 'FULL' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DRPCDIR=/usr/include/tirpc/"; fi # - if [[ $DEPS == 'MINI' && $TRAVIS_OS_NAME == 'linux' ]]; then export CMAKE_ARGS="${CMAKE_ARGS} -DRPCDIR=/usr/include/"; fi # diagnostics - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then echo APT_PACKAGES $APT_PACKAGES; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then echo BREW_PACKAGES $BREW_PACKAGES; fi - echo CMAKE_ARGS $CMAKE_ARGS # apt-get/brew invocation - if [[ $TRAVIS_OS_NAME == 'linux' ]]; then sudo apt-get install --no-install-recommends -y $APT_PACKAGES; fi - if [[ $TRAVIS_OS_NAME == 'osx' ]]; then brew install $BREW_PACKAGES; fi script: - mkdir build - cd build - cmake $CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ../ - travis_wait 60 make -j 2 # travis_wait needed for icc - if [ -v CODECOV ]; then make codecov; else make check; fi - sudo make install - cmake $CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DPYTHON_MODULE=ON ../ - travis_wait 60 make -j 2 # travis_wait needed for icc - PYTHONPATH=$PYTHONPATH:`find . -name GDL.so | xargs dirname` python -m pytest ../testsuite/python/test-GDL.py after_script: - if [ $COMPILER == icc ]; then '[[ ! -z "${INTEL_INSTALL_PATH}" ]] && uninstall_intel_software'; fi after_failure: - cat testsuite/Testing/Temporary/LastTest.log after_success: - if [ -v CODECOV ]; then bash <(curl -s https://codecov.io/bash) -f codecov.info; fi gdl-0.9.9/AUTHORS000066400000000000000000000024451340051421000133420ustar00rootroot00000000000000Project founder: Marc Schellens (SF: m_schellens) Key maintainers: Alain Coulais (github: alaingdl) Gilles Duvert (github: GillesDuvert) Contributors (in many different ways: from incorporation of tiny code snippets, through maintanance, packaging to major code contributions; in alphabetical order): Juan A. Añel Sylwester Arabas (github: slayoo) Deepak Bandyopadhyay Axel Beckert Médéric Boquien (SF: medericboquien) Justin Bronn (SF: jbronn) Pierre Chanial (SF: pchanial) Gabor Cseh Markus Dittrich Takeshi Enomoto Sébastien Fabbro Sylvain Flinois Orlando Garcia Feal Christoph Fuchs Joel Gales (SF: jomoga) Nicolas Galmiche Sergio Gelato Greg Huey Grgory Jung (github: maynardGK), Lutz Kettner Gaurav Khanna (SF: khanna) Jos de Kloe Benjamin Laurent Justin Lecher Christopher Lee (SF: c_lee) Maxime Lenoir Gregory Marchal Sébastien Maret Craig B. Markwardt Thibaut Mermet Peter Messmer (SF: messmer) Léa Noreskal Jeong Bin Park Mathieu Pinter Orion Poplawski Rene Preusker Paul Ricchiazzi Amar Si Lounis Marius Schamschula Richard Schwartz Gürkan Sengün Danny Smith J.D. Smith Remi A. Solås Ole Streicher Thierry Thomas Mateusz Turcza Paul Wessel Bob Withers Joanna Woo H Xu gdl-0.9.9/CMakeLists.txt000066400000000000000000001244751340051421000150420ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir and Alain Coulais # # 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 2 of the License, or # (at your option) any later version. # cmake_minimum_required(VERSION 3.0 FATAL_ERROR) # requirement for CMAKE_CXX_STANDARD (3.2 for Apple, 3.1 for non-Apple: https://public.kitware.com/Bug/bug_relationship_graph.php?bug_id=15355) if (${CMAKE_VERSION} VERSION_LESS "3.2") string(FIND "${CMAKE_CXX_FLAGS}" "-std=c++11" tmp) if(tmp LESS 0) message(FATAL_ERROR "please upgrade CMake to a version 3.2 or higher OR rerun cmake with -DCMAKE_CXX_FLAGS=\"-std=c++11\"") endif() else() set(CMAKE_CXX_STANDARD 11) endif() cmake_policy(SET CMP0026 OLD) # LOCATION property project(GDL) set(CMAKE_CXX_STANDARD 11) # advice by Orion, mandatory for FC 28 set(CMAKE_POSITION_INDEPENDENT_CODE ON) # X.X.X git becomes release X.X.X+1 set(VERSION "0.9.9") enable_testing() # cf issue 511, managing MultiArch on Debian ... include(GNUInstallDirs) include(CheckIncludeFile) include(CheckIncludeFileCXX) include(CheckLibraryExists) include(CheckFunctionExists) include(CheckSymbolExists) include(CheckCSourceRuns) include(CheckCXXSourceCompiles) include(FindPkgConfig) include(FindPackageHandleStandardArgs) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/CMakeModules) #### Default cached values set(PYTHON_MODULE OFF CACHE BOOL "GDL: Build GDL as a Python module ?") set(X11 ON CACHE BOOL "GDL: Enable X11 ?") set(X11DIR "" CACHE PATH "GDL: Specify X11 directory tree") # GNU Readline or BSD Editline ? if Readline OK, we don't look for Editline. set(READLINE ON CACHE BOOL "GDL: Enable GNU Readline ?") set(READLINEDIR "" CACHE PATH "GDL: Specify the GNU Readline directory tree") set(EDITLINE ON CACHE BOOL "GDL: Enable BSD Editline ?") set(EDITLINEDIR "" CACHE PATH "GDL: Specify the BSD Editline directory tree") set(PLPLOTDIR "" CACHE PATH "GDL: Specify the plplot directory tree") set(GSLDIR "" CACHE PATH "GDL: Specify the GSL directory tree") set(ZLIBDIR "" CACHE PATH "GDL: Specify the Zlib directory tree") set(WXWIDGETS ON CACHE BOOL "GDL: Enable WxWidgets ?") set(WXWIDGETSDIR "" CACHE PATH "GDL: Specify WxWidgets directory tree") set(UDUNITS OFF CACHE BOOL "GDL: Enable UDUNITS-2 ?") set(UDUNITSDIR "" CACHE PATH "GDL: Specify the UDUNITS-2 directory tree") set(EIGEN3 ON CACHE BOOL "GDL: Enable Eigen3 ?") set(EIGEN3DIR "" CACHE PATH "GDL: Specify the Eigen3 directory tree") set(PSLIB ON CACHE BOOL "GDL: Enable pslib ?") set(PSLIBDIR "" CACHE PATH "GDL: Specify the pslib directory tree") set(PNGLIB ON CACHE BOOL "GDL: Enable libpng ?") set(PNGLIBDIR "" CACHE PATH "GDL: Specify the libpng directory tree") set(GRIB OFF CACHE BOOL "GDL: Enable GRIB ?") set(GRIBDIR "" CACHE PATH "GDL: Specifiy the ECMWF ecCodes or GRIB API directory tree") # set(QHULL OFF CACHE BOOL "GDL: Enable Qhull ?") # set(QHULLDIR "" CACHE PATH "GDL: Specifiy the QHULL directory tree") set(GLPK OFF CACHE BOOL "GDL: Enable GLPK (for function SIMPLEX) ?") set(GLPKDIR "" CACHE PATH "GDL: Specify the GLPK directory tree") # GraphicsMagick is a good alternative to ImageMagick, if GM OK, we don't look for IM set(GRAPHICSMAGICK ON CACHE BOOL "GDL: Enable GraphicsMagick ?") set(GRAPHICSMAGICKDIR "" CACHE PATH "GDL: Specify the GraphicsMagick directory tree") set(MAGICK ON CACHE BOOL "GDL: Enable ImageMagick ?") set(MAGICKDIR "" CACHE PATH "GDL: Specifiy the ImageMagick directory tree") set(TIFF ON CACHE BOOL "GDL: Enable libtiff ?") set(TIFFDIR "" CACHE PATH "GDL: Specify the libtiff directory tree") if(TIFF) set(GEOTIFF ON CACHE BOOL "GDL: Enable libgeotiff ?") set(GEOTIFFDIR "" CACHE PATH "GDL: Specify the libgeotiff directory tree") endif(TIFF) set(NETCDF ON CACHE BOOL "GDL: Enable NetCDF ?") set(NETCDFDIR "" CACHE PATH "GDL: Specifiy the netCDF directory tree") set(HDF ON CACHE BOOL "GDL: Enable Hdf ?") set(HDFDIR "" CACHE PATH "GDL: Specifiy the HDF directory tree") set(HDF5 ON CACHE BOOL "GDL: Enable Hdf5 ?") set(HDF5DIR "" CACHE PATH "GDL: Specifiy the HDF5 directory tree") set(FFTW ON CACHE BOOL "GDL: Enable FFTW ?") set(FFTWDIR "" CACHE PATH "GDL: Specifiy the FFTW directory tree") set(LIBPROJ4 OFF CACHE BOOL "GDL: Enable LIBPROJ4 ?") set(LIBPROJ4DIR "" CACHE PATH "GDL: Specifiy the LIBPROJ4 directory tree") set(MPICH OFF CACHE BOOL "GDL: Enable MPICH ?") set(MPICHDIR "" CACHE PATH "GDL: Specify the MPICH (experimental) directory tree") set(PYTHON ON CACHE BOOL "GDL: Enable Python ?") set(PYTHONDIR "" CACHE PATH "GDL: Specifiy the use Python directory tree") set(PYTHONVERSION "" CACHE STRING "GDL: Specify the Python version to use") set(GSHHS ON CACHE BOOL "GDL: Enable GSHHS ?") set(GSHHSDIR "" CACHE PATH "GDL: Specifiy the GSHHS directory tree") if(NOT WIN32) set(NCURSESDIR "" CACHE PATH "GDL: Specify the ncurses (or curses) directory tree") endif(NOT WIN32) set(OPENMP ON CACHE BOOL "GDL: Enable OpenMP ?") # Third party libraries set(JASPERDIR "" CACHE PATH "GDL: Specify the JasPer directory tree") set(JPEGDIR "" CACHE PATH "GDL: Specify the JPEG directory tree") set(SZIPDIR "" CACHE PATH "GDL: Specify the SZip directory tree") set(GDL_DATA_DIR "/share/gnudatalanguage" CACHE PATH "GDL: data directory relative to CMAKE_INSTALL_PREFIX") # check for 64-bit OS if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) set(HAVE_64BIT_OS 1) endif(${CMAKE_SIZEOF_VOID_P} EQUAL 8) #### check headers and libraries # dl check_library_exists(dl dlopen "" HAVE_DL) if(HAVE_DL) set(LIBRARIES ${LIBRARIES} dl) endif(HAVE_DL) # malloc stats check_function_exists(malloc_zone_statistics HAVE_MALLOC_ZONE_STATISTICS) check_function_exists(sbrk HAVE_SBRK) check_function_exists(mallinfo HAVE_MALLINFO) # mallocs check_include_file(malloc.h HAVE_MALLOC_H) check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H) # locale check_include_file(locale.h HAVE_LOCALE_H) # std includes.. check_include_file(stdint.h HAVE_STDINT_H) check_include_file(stdlib.h HAVE_STDLIB_H) check_include_file(string.h HAVE_STRING_H) check_include_file(strings.h HAVE_STRINGS_H) check_include_file(sys/stat.h HAVE_SYS_STAT_H) check_include_file(sys/types.h HAVE_SYS_TYPES_H) check_include_file(unistd.h HAVE_UNISTD_H) #check_include_file(ext/stdio_filebuf.h HAVE_EXT_STDIO_FILEBUF_H) #sometimes it compiles but stdio_filebuf is only in gcc-x-y-z directory tree... # would be silly not to use this functionality if present, so recheck: if (HAVE_EXT_STDIO_FILEBUF_H) else (HAVE_EXT_STDIO_FILEBUF_H) check_cxx_source_compiles(" #include int main(int argc, char **argv) { int i=0; i+=1; }" REALLY_HAVE_EXT_STDIO_FILEBUF_H) endif (HAVE_EXT_STDIO_FILEBUF_H) if (REALLY_HAVE_EXT_STDIO_FILEBUF_H) message(STATUS "INFO: will use GNU extensions for STDIO (useful for compressed I/O) since it seems accepted by your c++ compiler.") set (HAVE_EXT_STDIO_FILEBUF_H 1) endif (REALLY_HAVE_EXT_STDIO_FILEBUF_H) # dlfcn.h check_include_file(dlfcn.h HAVE_DLFCN_H) # inttypes.h check_include_file(inttypes.h HAVE_INTTYPES_H) # nexttoward check_library_exists(m nexttoward "" HAVE_NEXTTOWARD) # mpi check_include_file(mpi.h HAVE_MPI_H) # SA: whithout it compilation of antlr fails if there's a conflicting # version of antlr in system-wide directories include_directories(src) if (NOT WIN32) # Ncurses MANDATORY for readline on POSIX # -DNCURSESDIR=DIR set(CMAKE_PREFIX_PATH ${NCURSESDIR}) set(CURSES_NEED_NCURSES TRUE) find_package(Curses QUIET COMPONENTS initscr) mark_as_advanced(CURSES_CURSES_H_PATH CURSES_FORM_LIBRARY CURSES_HAVE_CURSES_H) if(CURSES_FOUND) set(HAVE_LIBNCURSES 1) set(LIBRARIES ${LIBRARIES} ${CURSES_LIBRARIES}) include_directories(${CURSES_INCLUDE_DIR}) else(CURSES_FOUND) # search for curses set(CURSES_NEED_NCURSES FALSE) find_package(Curses COMPONENTS initscr) set(HAVE_LIBCURSES ${CURSES_FOUND}) if(CURSES_FOUND) set(LIBRARIES ${LIBRARIES} ${CURSES_LIBRARIES}) include_directories(${CURSES_INCLUDE_DIR}) else(CURSES_FOUND) message(FATAL_ERROR "(N)Curses was not found.\n" "Use -DNCURSESDIR=DIR to specify the curses directory tree.\n" "(suitable Debian/Ubuntu package: libncurses-dev)\n") endif(CURSES_FOUND) endif(CURSES_FOUND) endif (NOT WIN32) # GNU Readline (GNU/Linux or OSX) or BSD Editline (OSX) # -DREADLINE=ON|OFF # -DREADLINEDIR=DIR or -DEDITLINEDIR=DIR if(READLINE) set(CMAKE_PREFIX_PATH ${READLINEDIR}) find_package(Readline QUIET) set(HAVE_LIBREADLINE ${READLINE_FOUND}) if(READLINE_FOUND) if(NOT WIN32) # readline needs (n)curses (not on Windows) set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARIES}) endif(NOT WIN32) check_library_exists("${READLINE_LIBRARIES}" rl_get_screen_size "" RL_GET_SCREEN_SIZE) if(NOT RL_GET_SCREEN_SIZE) message(STATUS "WARNING: Older GNU readline without rl_get_screen_size was found.\n" "For resized terminals the size might not be updated correctly.\n" "If this is a problem please install a recent version of readline.") endif(NOT RL_GET_SCREEN_SIZE) set(LIBRARIES ${LIBRARIES} ${READLINE_LIBRARIES}) include_directories(${READLINE_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES) else(READLINE_FOUND) if(EDITLINE) message(STATUS "WARNING: GNU readline was not found, now looking for BSD Editline.\n") else(EDITLINE) message(FATAL_ERROR "GNU readline was not found.\n" "Use -DREADLINEDIR=no to explicitely disable it.\n" "(suitable Debian/Ubuntu package: libreadline-gplv2-dev)\n" "(suitable Fedora package: readline-devel)") endif(EDITLINE) endif(READLINE_FOUND) endif(READLINE) # # if Readline found, we do not look for Editline # if(READLINE_FOUND) if (EDITLINE) message(STATUS "INFO: We prefer to use Readline than Editline.\n" "Feedback welcome on OSX Readline ...") set(EDITLINE OFF) endif(EDITLINE) endif(READLINE_FOUND) # BSD Editline (a BSD clone of GNU Readline, present by default on OSX) # -DEDITLINE=ON|OFF # -DEDITLINEDIR=DIR if(EDITLINE) set(CMAKE_PREFIX_PATH ${EDITLINEDIR}) find_package(Editline CONFIG) if(NOT EDITLINE_FOUND) find_package(Editline QUIET) endif(NOT EDITLINE_FOUND) set(HAVE_LIBEDITLINE ${EDITLINE_FOUND}) if(EDITLINE_FOUND) if(NOT WIN32) # readline needs (n)curses (not on Windows) set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARIES}) endif(NOT WIN32) set(LIBRARIES ${LIBRARIES} ${EDITLINE_LIBRARIES}) include_directories(${EDITLINE_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES) else(EDITLINE_FOUND) message(FATAL_ERROR "requested BSD Editline was not found.\n" "Use -DEDITLINE=no to explicitely disable it.\n") endif(EDITLINE_FOUND) endif(EDITLINE) # zlib MANDATORY # -DZLIBDIR=DIR set(CMAKE_PREFIX_PATH ${ZLIBDIR}) find_package(ZLIB QUIET) set(HAVE_LIBZ ${ZLIB_FOUND}) if(ZLIB_FOUND) set(LIBRARIES ${LIBRARIES} ${ZLIB_LIBRARIES}) include_directories(${ZLIB_INCLUDE_DIR}) else(ZLIB_FOUND) message(FATAL_ERROR "ZLib library is required but was not found.\n" "Use -DZLIBDIR=DIR to specify the zlib directory tree.\n" "(suitable Debian/Ubuntu package: zlib1g-dev)\n" "(suitable Fedora package: zlib-devel)") endif(ZLIB_FOUND) # libpng # -DPNGLIB=ON|OFF # -DPNGLIBDIR=DIR if(PNGLIB) set(CMAKE_PREFIX_PATH ${PNGLIBDIR}) find_package(PNG QUIET) set(USE_PNGLIB ${PNG_FOUND}) if(PNG_FOUND) set(LIBRARIES ${LIBRARIES} ${PNG_LIBRARIES}) set(LINK_DIRECTORIES ${LINK_DIRECTORIES} ${PNG_LIBRARY_DIRS}) include_directories(${PNG_INCLUDE_DIRS}) else(PNG_FOUND) message(FATAL_ERROR "libpng is required but was not found.\n" "Use -DPNGLIBDIR=DIR to specify the libpng directory tree.\n" "Use -DPNGLIB=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libpng-dev)\n" "(suitable Fedora package: libpng-devel)") endif(PNG_FOUND) endif(PNGLIB) # openmp # -DOPENMP=ON|OFF if(OPENMP) find_package(OpenMP QUIET) set(USE_OPENMP ${OPENMP_FOUND}) if(OPENMP_FOUND) add_definitions(${OpenMP_CXX_FLAGS}) if(MSVC) set(LIBRARIES ${LIBRARIES} vcomp) elseif(WIN32) set(LIBRARIES ${LIBRARIES} gomp pthread) else() set(LIBRARIES ${LIBRARIES} ${OpenMP_CXX_FLAGS}) endif() else(OPENMP_FOUND) message(FATAL_ERROR "Your compiler does not support OpenMP or OpenMP was not found" "note that disabling OpenMP will incur significant performance penalty !\n" "Use -DCMAKE_CXX_COMPILER=PATH and -DCMAKE_C_COMPILER=PATH to specify the compiler path." "(find_package(OpenMP) will find OpenMP only if both are set !)\n" "Use -DOPENMP=OFF to not use it.\n" "(suitable Homebrew compiler package: llvm)" "(suitable Homebrew library package: libomp)") endif(OPENMP_FOUND) else(OPENMP) # we need to define those semaphore posix symbols, do it with threads libs find_package(Threads) if(THREADS_FOUND) set(LIBRARIES ${LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) else(THREADS_FOUND) check_library_exists(rt sem_unlink "" HAVE_RT) if(HAVE_RT) set(LIBRARIES ${LIBRARIES} rt) else(HAVE_RT) message(FATAL_ERROR "Missing a POSIX semaphore symbols (rt or threads).\n") endif(HAVE_RT) endif(THREADS_FOUND) endif(OPENMP) # GSL MANDATORY # -DGSLDIR=DIR set(CMAKE_PREFIX_PATH ${GSLDIR}) find_package(GSL QUIET) set(HAVE_LIBGSL ${GSL_FOUND}) set(HAVE_LIBGSLCBLAS ${GSL_FOUND}) if(GSL_FOUND) set(LIBRARIES ${LIBRARIES} ${GSL_LIBRARIES}) include_directories(${GSL_INCLUDE_DIR}) else(GSL_FOUND) message(FATAL_ERROR "Gnu Scientific library (1.7 or higher) and libgslcblas are mandatory.\n" "Use -DGSLDIR=DIR to specify the gsl directory tree.\n" "(suitable Debian/Ubuntu package: libgsl0-dev)\n" "(suitable Fedora package: gsl-devel)") endif(GSL_FOUND) if(UNIX) set(CMAKE_PREFIX_PATH ${RPCDIR}) find_package(RPC QUIET) set(HAVE_RPC ${RPC_FOUND}) if(RPC_FOUND) set(LIBRARIES ${LIBRARIES} ${RPC_LIBRARIES}) include_directories(${RPC_INCLUDE_DIR}) else(RPC_FOUND) message(FATAL_ERROR "RPC support is mandatory.\n" "Note that SunRPC has been removed in glibc-2.26 and later, " "while being optional in earlier versions. Consider using the " "recommended and more modern libtirpc instead.\n" "Use -DRPCDIR=DIR to specify the rpc directory tree.\n") endif(RPC_FOUND) elseif (WIN32 AND NOT CYGWIN) set(CMAKE_PREFIX_PATH ${XDRDIR}) find_package(Xdr) set(HAVE_LIBXDR ${XDR_FOUND}) if(XDR_FOUND) set(LIBRARIES ${LIBRARIES} ${XDR_LIBRARY}) include_directories(${XDR_INCLUDE_DIR}) else(XDR_FOUND) message(FATAL_ERROR "bsd-xdr library is required but was not found.\n" "Use -DXDRDIR=DIR to specify the bsd-xdr directory tree.") endif(XDR_FOUND) set(CMAKE_PREFIX_PATH ${PCREDIR}) find_package(PCRE) set(HAVE_LIBPCRE ${PCRE_FOUND}) if(PCRE_FOUND) set(LIBRARIES ${LIBRARIES} ${PCRE_LIBRARIES}) include_directories(${PCRE_INCLUDE_DIR}) else(PCRE_FOUND) message(FATAL_ERROR "pcre library is required but was not found.\n" "Use -DPCREDIR=DIR to specify the pcre directory tree.") endif(PCRE_FOUND) LINK_LIBRARIES(shlwapi) endif() # PLplot MANDATORY # -DPLPLOTDIR=DIR set(CMAKE_PREFIX_PATH ${PLPLOTDIR}) find_package(Plplot QUIET) set(HAVE_LIBPLPLOTCXXD ${PLPLOT_FOUND}) if(PLPLOT_FOUND) set(LIBRARIES ${LIBRARIES} ${PLPLOT_LIBRARIES}) include_directories(${PLPLOT_INCLUDE_DIR}) else(PLPLOT_FOUND) message(FATAL_ERROR "plplot library is required but was not found.\n" "Use -DPLPLOTDIR=DIR to specify the plplot directory tree.\n" "(suitable Debian/Ubuntu packages: libplplot-dev, [plplot9-driver-xwin])" "(suitable Fedora package: plplot-devel)") endif(PLPLOT_FOUND) if(PLPLOT_FOUND) message(STATUS "Warning, if you have plplot version > 5.11 and wxWidgets enabled, please read carefully file README") check_library_exists("${PLPLOT_LIBRARIES}" c_plslabelfunc "" HAVE_PLPLOT_SLABELFUNC) if(NOT HAVE_PLPLOT_SLABELFUNC) message(FATAL_ERROR "please upgrade to plplot version > 5.9.6 (missing plslabelfunc") endif() set(CMAKE_REQUIRED_INCLUDES "${PLPLOT_INCLUDE_DIR}") set(CMAKE_REQUIRED_LIBRARIES "${PLPLOT_LIBRARIES}") #the following does not work with clang (???) check_library_exists("${PLPLOT_LIBRARIES}" c_plwidth "" HAVE_PLPLOT_WIDTH) #give it a 2nd try... if(NOT HAVE_PLPLOT_WIDTH) check_cxx_source_compiles("#include int main(int argc, char **argv) { plstream *p = new plstream(); PLFLT w = 0.5; p->width(w); }" HAVE_PLPLOT_WIDTH) if(HAVE_PLPLOT_WIDTH) set(HAVE_PLPLOT_WIDTH 1) endif(HAVE_PLPLOT_WIDTH) endif(NOT HAVE_PLPLOT_WIDTH) check_library_exists("${PLPLOT_LIBRARIES}" plstrl "" PLPLOT_PRIVATE_NOT_HIDDEN) if(PLPLOT_PRIVATE_NOT_HIDDEN) set(PLPLOT_PRIVATE_NOT_HIDDEN 1) else(PLPLOT_PRIVATE_NOT_HIDDEN) message(STATUS "Using a plplot library without private functions - workarounds will be used.") endif(PLPLOT_PRIVATE_NOT_HIDDEN) check_cxx_source_compiles("#include int main(){PLINT n; PLFLT x,y;plcallback::fill(n,&x,&y);}" PLPLOT_HAS_PLCALLBACK) if(PLPLOT_HAS_PLCALLBACK) set(PLPLOT_HAS_PLCALLBACK 1) endif(PLPLOT_HAS_PLCALLBACK) endif(PLPLOT_FOUND) # GraphicsMagick (GM) is an alternative to the classical ImageMagick Lib (IM). # It was experienced that GM was more stable in time than IM # # -DGRAPHICSMAGICK=ON|OFF # -DGRAPHICSMAGICKDIR=DIR # if(GRAPHICSMAGICK) set(CMAKE_PREFIX_PATH ${GRAPHICSMAGICKDIR}) find_package(GraphicsMagick QUIET) set(USE_MAGICK ${GRAPHICSMAGICK_FOUND}) if(GRAPHICSMAGICK_FOUND) include_directories(${GRAPHICSMAGICK_INCLUDE_DIR}) set(LIBRARIES ${LIBRARIES} ${GRAPHICSMAGICK_LIBRARIES}) else(GRAPHICSMAGICK_FOUND) message( STATUS "GRAPHICSMAGICK is strongly suggested but was not found. Use -DGRAPHICSMAGICKDIR=DIR to specify the GraphicsMagick directory tree. Use -DGRAPHICSMAGICK=OFF to not use it. (suitable Fedora package: GraphicsMagick-c++-devel Debian/Ubuntu package: libgraphicsmagick++1-dev)\n") message( STATUS "Looking for ImageMagick") endif(GRAPHICSMAGICK_FOUND) endif(GRAPHICSMAGICK) # # if GM found, we do not look for IM # if(GRAPHICSMAGICK_FOUND) if (MAGICK) message(STATUS "INFO: We prefer to use GraphicsMagick than ImageMagick") set(MAGICK OFF) endif(MAGICK) endif(GRAPHICSMAGICK_FOUND) # ImageMagick # -DMAGICK=ON|OFF # -DMAGICKDIR=DIR if(MAGICK) set(CMAKE_PREFIX_PATH ${MAGICKDIR}) find_package(ImageMagick QUIET COMPONENTS Magick++ MagickWand MagickCore) mark_as_advanced(ImageMagick_EXECUTABLE_DIR ImageMagick_Magick++_INCLUDE_DIR ImageMagick_Magick++_LIBRARY ImageMagick_MagickCore_INCLUDE_DIR ImageMagick_MagickCore_LIBRARY ImageMagick_MagickWand_INCLUDE_DIR ImageMagick_MagickWand_LIBRARY) set(USE_MAGICK ${ImageMagick_FOUND}) if(ImageMagick_FOUND) find_program(MAGICKXXCONFIG Magick++-config) if(MAGICKXXCONFIG) execute_process(COMMAND ${MAGICKXXCONFIG} "--libs" OUTPUT_VARIABLE MAGICKXXCONFIGLIBS OUTPUT_STRIP_TRAILING_WHITESPACE) set(LIBRARIES ${LIBRARIES} ${MAGICKXXCONFIGLIBS}) else(MAGICKXXCONFIG) message(FATAL_ERROR "ImageMagick is required but was not found (Magick++-config).\n" "Use -DMAGICKDIR=DIR to specify the ImageMagick directory.\n" "Use -DMAGICK=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libmagick++-dev)\n" "(suitable Fedora package: ImageMagick-c++-devel)") endif(MAGICKXXCONFIG) set(LIBRARIES ${LIBRARIES} ${ImageMagick_LIBRARIES}) include_directories(${ImageMagick_INCLUDE_DIRS}) set(MAGICK_LIBRARIES ${ImageMagick_LIBRARIES}) else(ImageMagick_FOUND) message(FATAL_ERROR "ImageMagick is required but was not found.\n" "Use -DMAGICKDIR=DIR to specify the ImageMagick directory.\n" "Use -DMAGICK=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libmagick++-dev)\n" "(suitable Fedora package: ImageMagick-c++-devel)") endif(ImageMagick_FOUND) endif(MAGICK) # if GM or IM activated, we check whether Plplot is OK for that if(USE_MAGICK AND NOT WIN32) check_library_exists("${PLPLOT_LIBRARIES}" plGetDrvDir "" HAVE_PLGETDRVDIR) if(HAVE_PLGETDRVDIR) message(STATUS "WARNING: Dynamic drivers may have to be disabled in plplot.\n" "To make plplot work with ImageMagick:\n" "use -DENABLE_DYNDRIVERS=OFF cmake option when compiling plplot or\n" "use -DMAGICK=OFF here to not use ImageMagick in GDL.") endif(HAVE_PLGETDRVDIR) endif(USE_MAGICK AND NOT WIN32) # wxWidgets # -DWXWIDGETS=ON|OFF # -DWXWIDGETSDIR=DIR set(wxWidgets_USE_DEBUG OFF) # Use release build if(WXWIDGETS) # # we check whether plplot was compiled within wxwidgets # # AC 2015/04/07 this is not working well, just on few cases :( # check_library_exists("${PLPLOT_LIBRARIES}" plD_DEVICE_INFO_wxwidgets "" HAVE_PLPLOT_WXWIDGETS) # if(NOT HAVE_PLPLOT_WXWIDGETS) # message(FATAL_ERROR "wxWidgets are required but PLplot wxWidgets NOT found.\n" # "If -DWXWIDGETS=ON (default) then PLplot must have be compiled with -DPLD_wxwidgets=ON\n" # "use -DWXWIDGETS=OFF to not use wxWidgets since it is not available here in PLplot") # endif(NOT HAVE_PLPLOT_WXWIDGETS) # set(CMAKE_PREFIX_PATH ${WXWIDGETSDIR}) find_package(wxWidgets COMPONENTS base core adv) set(HAVE_LIBWXWIDGETS ${wxWidgets_FOUND}) if(wxWidgets_FOUND) set(LIBRARIES ${LIBRARIES} ${wxWidgets_LIBRARIES}) set(LINK_DIRECTORIES ${LINK_DIRECTORIES} ${wxWidgets_LIBRARY_DIRS}) foreach(WXDEF ${wxWidgets_DEFINITIONS}) add_definitions(-D${WXDEF}) endforeach(WXDEF ${wxWidgets_DEFINITIONS}) include_directories(${wxWidgets_INCLUDE_DIRS}) else(wxWidgets_FOUND) message(FATAL_ERROR "wxWidgets are required but were not found.\n" "Use -DWXWIDGETSDIR=DIR to specify the wxWidgets directory tree.\n" "Use -DWXWIDGETS=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libwxgtk2.8-dev)\n" "(suitable Fedora package: wxGTK-devel)") endif(wxWidgets_FOUND) endif(WXWIDGETS) # libtiff # -DTIFF=ON|OFF # -DTIFFDIR=DIR if(TIFF) set(CMAKE_PREFIX_PATH ${TIFFDIR}) find_package(TIFF 4.0.3 QUIET) set(USE_TIFF ${TIFF_FOUND}) if(TIFF_FOUND) include_directories(${TIFF_INCLUDE_DIR}) set(LIBRARIES ${LIBRARIES} ${TIFF_LIBRARIES}) else(TIFF_FOUND) message(FATAL_ERROR "libtiff v4.0.3 or newer is required for TIFF support but was not found.\n" "Use -DTIFFDIR=DIR to specify the libtiff directory tree.\n" "Use -DTIFF=OFF to not use it.") endif(TIFF_FOUND) endif(TIFF) # libgeotiff # -DGEOTIFF=ON|OFF # -DGEOTIFFDIR=DIR if(GEOTIFF AND USE_TIFF) set(CMAKE_PREFIX_PATH ${GEOTIFFDIR}) find_package(GeoTIFF QUIET) set(USE_GEOTIFF ${GEOTIFF_FOUND}) if(GEOTIFF_FOUND) include_directories(${GEOTIFF_INCLUDE_DIR}) set(LIBRARIES ${LIBRARIES} ${GEOTIFF_LIBRARIES}) else(GEOTIFF_FOUND) message(FATAL_ERROR "libgeotiff is required for GeoTIFF support but was not found.\n" "Use -DGEOTIFFDIR=DIR to specify the libgeotiff directory tree.\n" "Use -DGEOTIFF=OFF to not use it.") endif(GEOTIFF_FOUND) endif(GEOTIFF AND USE_TIFF) # netCDF # -DNETCDF=ON|OFF # -DNETCDFDIR=DIR if(NETCDF) set(CMAKE_PREFIX_PATH ${NETCDFDIR}) find_package(NetCDF QUIET) if(NETCDF_FOUND) set(CMAKE_REQUIRED_INCLUDES ${NETCDF_INCLUDE_DIRS}) check_include_file_cxx(netcdf.h HAVE_NETCDF_H) if(HAVE_NETCDF_H) set(LIBRARIES ${LIBRARIES} ${NETCDF_LIBRARIES}) set(LINK_DIRECTORIES ${LINK_DIRECTORIES} ${NETCDF_LIBRARY_DIRS}) include_directories(${NETCDF_INCLUDE_DIRS}) set(USE_NETCDF 1) else(HAVE_NETCDF_H) message(FATAL_ERROR "NetCDF installation seems not to be usable.\n" "This suggests a conflicting netCDF-HDF4 installation e.g.\n" "- Uninstalling HDF4 after installation of NetCDF.\n" "- Installing NetCDF before HDF4.") endif(HAVE_NETCDF_H) set(CMAKE_REQUIRED_INCLUDES) # # are extensions NetCDF-4 available ?? check_library_exists("${NETCDF_LIBRARIES}" nc_inq_grps "" HAVE_NETCDF4) if(HAVE_NETCDF4) set(USE_NETCDF4 1) else(HAVE_NETCDF4) message(STATUS "warning, you don't have NetCDF-4 version" "some new NetCDF capabilities in NetCDF-4 (related to Groups) will not be usable") endif(HAVE_NETCDF4) else(NETCDF_FOUND) message(FATAL_ERROR "NetCDF version 3.5.1 or later is required but was not found.\n" "Use -DNETCDFDIR=DIR to specify the netcdf directory tree.\n" "Use -DNETCDF=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libnetcdf-dev)\n" "(suitable Fedora package: netcdf-devel)") endif(NETCDF_FOUND) endif(NETCDF) # hdf4 # -DHDF=ON|OFF # -DHDFDIR=DIR if(HDF) set(CMAKE_PREFIX_PATH ${HDFDIR} ${JPEGDIR} ${SZIPDIR}) find_package(HDF QUIET) set(USE_HDF ${HDF_FOUND}) if(HDF_FOUND) if(NETCDF) set(CMAKE_REQUIRED_LIBRARIES ${HDF_EXTRA_LIBRARIES}) check_library_exists("${HDF_LIBRARIES};${RPC_LIBRARIES}" sd_nccreate "" SD_NCCREATE) if(NOT SD_NCCREATE) message(FATAL_ERROR "HDF4 needs to be configured with the --disable-netcdf option " "in order to be used with the original netCDF library.") endif(NOT SD_NCCREATE) set(CMAKE_REQUIRED_LIBRARIES) endif(NETCDF) set(HDF_LIBRARIES ${HDF_LIBRARIES} ${HDF_EXTRA_LIBRARIES}) set(LIBRARIES ${LIBRARIES} ${HDF_LIBRARIES}) include_directories(${HDF_INCLUDE_DIR}) else(HDF_FOUND) message(FATAL_ERROR "HDF4 libraries were not found.\n" "Use -DHDFDIR=DIR to specify the HDF directory tree.\n" "Use -DHDF=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libhdf4-alt-dev)\n" "You can use -DJPEGDIR=DIR to specify the JPEG directory tree. " "You can also use -DSZIPDIR=DIR to specify SZip directory tree if " "HDF was compiled with SZip support.") endif(HDF_FOUND) endif(HDF) # hdf5 # -DHDF5=ON|OFF # -DHDF5DIR=DIR if(HDF5) set(CMAKE_PREFIX_PATH ${HDF5DIR} ${SZIPDIR}) find_package(HDF5 QUIET) set(USE_HDF5 ${HDF5_FOUND}) if(HDF5_FOUND) set(LIBRARIES ${LIBRARIES} ${HDF5_LIBRARIES}) include_directories(${HDF5_INCLUDE_DIRS}) find_package(MPI QUIET) if(MPI_FOUND) include_directories(${MPI_INCLUDE_PATH}) set(LIBRARIES ${LIBRARIES} ${MPI_LIBRARIES}) endif(MPI_FOUND) else(HDF5_FOUND) message(FATAL_ERROR "HDF version 5 is required but was not found.\n" "Use -DHDF5DIR=DIR to specify the HDF5 directory tree.\n" "Use -DHDF5=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libhdf5-serial-dev)\n" "(suitable Fedora package: hdf5-devel)") endif(HDF5_FOUND) endif(HDF5) # fftw # -DFFTW=ON|OFF # -DFFTWDIR=DIR if(FFTW) set(CMAKE_PREFIX_PATH ${FFTWDIR}) find_package(FFTW QUIET) set(USE_FFTW ${FFTW_FOUND}) if(FFTW_FOUND) set(LIBRARIES ${LIBRARIES} ${FFTW_LIBRARIES}) include_directories(${FFTW_INCLUDE_DIR}) else(FFTW_FOUND) message(FATAL_ERROR "FFTW3 is required but was not found.\n" "Use -DFFTWDIR=DIR to specify the FFTW directory tree.\n" "Use -DFFTW=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libfftw3-dev)\n" "(suitable Fedora package: fftw-devel)") endif(FFTW_FOUND) endif(FFTW) # libproj4 # -DLIBPROJ4=ON|OFF # -DLIBPROJ4DIR=DIR if(LIBPROJ4) set(CMAKE_PREFIX_PATH ${LIBPROJ4DIR}) find_package(Libproj4) if(LIBPROJ4_FOUND) else(LIBPROJ4_FOUND) find_package(Libproj4new) endif(LIBPROJ4_FOUND) if(LIBPROJ4_FOUND) set(CMAKE_REQUIRED_LIBRARIES ${LIBPROJ4_LIBRARIES} ${GSL_LIBRARIES} m) check_library_exists("${LIBPROJ4_LIBRARIES}" pj_init "" USE_LIBPROJ4_NEW) if(USE_LIBPROJ4_NEW) # check_library_exists("${LIBPROJ4_LIBRARIES}" proj_init "" USE_LIBPROJ4) # if(USE_LIBPROJ4) # define USE_LIB_PROJ4 in any case set(USE_LIBPROJ4 1) else(USE_LIBPROJ4_NEW) check_library_exists("${LIBPROJ4_LIBRARIES}" proj_init "" USE_LIBPROJ4) if(NOT USE_LIBPROJ4) # else(USE_LIBPROJ4) # check_library_exists("${LIBPROJ4_LIBRARIES}" pj_init "" USE_LIBPROJ4_NEW) # if(NOT USE_LIBPROJ4_NEW) message(FATAL_ERROR "Libproj4 is required but was not found.\n" "Use -DLIBPROJ4DIR=DIR to specify the Libproj4 directory tree.\n" "Use -DLIBPRJ4=OFF to not use it.") endif(NOT USE_LIBPROJ4) endif(USE_LIBPROJ4_NEW) # endif(NOT USE_LIBPROJ4_NEW) # endif(USE_LIBPROJ4) include_directories(${LIBPROJ4_INCLUDE_DIR}) set(LIBRARIES ${LIBRARIES} ${LIBPROJ4_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES) else(LIBPROJ4_FOUND) message(FATAL_ERROR "Libproj4 is required but was not found.\n" "Use -DLIBPROJ4DIR=DIR to specify the Libproj4 directory tree.\n" "Use -DLIBPRJ4=OFF to not use it.") endif(LIBPROJ4_FOUND) endif(LIBPROJ4) # mpich (experimental) # -DMPICH=ON|OFF # -DMPICHDIR=DIR if(MPICH) set(CMAKE_PREFIX_PATH ${MPICHDIR}) find_package(MPI QUIET) set(USE_MPI ${MPI_FOUND}) if(MPI_FOUND) include_directories(${MPI_INCLUDE_PATH}) set(LIBRARIES ${LIBRARIES} ${MPI_LIBRARIES}) else(MPI_FOUND) message(FATAL_ERROR "MPICH is required but was not found.\n" "Use -DMPICHDIR=DIR to specify the MPICH directory tree.\n" "Use -DMPICH=OFF to not use it.") endif(MPI_FOUND) endif(MPICH) # python # -DPYTHON=ON|OFF # -DPYTHON_MODULE # -DPYTHONDIR=DIR # -DPYTHONVERSION=VERSION if(PYTHON OR PYTHON_MODULE) if(PYTHON) set(PYTHONMSG "Use -DPYTHON=OFF to disable Python support.\n") endif(PYTHON) if(PYTHON_MODULE) set(PYTHON_MODULEMSG "Use -DPYTHON_MODULE=OFF to disable Python module.\n") endif(PYTHON_MODULE) if(PYTHONDIR) find_library(PYTHONLIBS NAMES python${PYTHONVERSION} PATHS ${PYTHONDIR} PATH_SUFFIXES lib lib/python${PYTHONVERSION}/config NO_DEFAULT_PATH NO_CMAKE_PATH ) string(COMPARE NOTEQUAL "${PYTHONLIBS}" "PYTHONLIBS-NOTFOUND" PYTHONLIBS_FOUND) if (NOT PYTHONLIBS_FOUND) message(FATAL_ERROR "Python libraries not found in ${PYTHONDIR}.") else() set(PYTHON_LIBRARIES "${PYTHONLIBS}") message("-- Found Python libs: ${PYTHONLIBS}") endif() find_path(PYTHON_INCLUDE_DIRS NAMES Python.h PATHS ${PYTHONDIR} PATH_SUFFIXES include include/python${PYTHONVERSION} NO_DEFAULT_PATH NO_CMAKE_PATH ) string(COMPARE NOTEQUAL "${PYTHONLIBS}" "PYTHON_INCLUDE_DIRS-NOTFOUND" PYTHONHEADERS_FOUND) if (PYTHONHEADERS_FOUND) message("-- Found Python headers: ${PYTHON_INCLUDE_DIRS}") set(PYTHON_INCLUDES "${PYTHON_INCLUDE_DIRS}") else() message(FATAL_ERROR "Python headers not found in ${PYTHONDIR}.") endif() find_program(PYTHON_EXECUTABLE NAMES python${PYTHONVERSION} PATHS ${PYTHONDIR} PATH_SUFFIXES bin NO_DEFAULT_PATH NO_CMAKE_PATH) string(COMPARE NOTEQUAL "${PYTHON_EXECUTABLE}" "PYTHON_EXECUTABLE-NOTFOUND" PYTHON_EXECUTABLE_FOUND) if(NOT PYTHON_EXECUTABLE_FOUND) message(FATAL_ERROR "Python executable not found in ${PYTHONDIR}.") else() message("-- Found Python executable: ${PYTHON_EXECUTABLE}") endif() else() if(NOT PYTHONVERSION) set(PYTHONVERSION 2) endif() find_package(PythonInterp) find_package(PythonLibs ${PYTHONVERSION}) if (NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING) message(STATUS "PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) message(STATUS "PYTHON_VERSION: " ${PYTHON_VERSION_STRING}) message(STATUS "PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) message(STATUS "PYTHONLIBS_VERSION: " ${PYTHONLIBS_VERSION_STRING}) message(FATAL_ERROR "Version mismatch between python interpreter and libraries") endif() endif() set(USE_PYTHON ${PYTHONLIBS_FOUND}) if(PYTHONLIBS_FOUND) find_package(Numpy QUIET) if(NOT PYTHON_NUMPY_FOUND) message(FATAL_ERROR "Python numpy package was not found.\n" "${PYTHONMSG} ${PYTHON_MODULEMSG}") endif(NOT PYTHON_NUMPY_FOUND) set(LIBRARIES ${LIBRARIES} ${PYTHON_LIBRARIES}) include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_NUMPY_INCLUDE_DIR}) else(PYTHONLIBS_FOUND) message(FATAL_ERROR "Python is required but was not found.\n" "Use -DPYTHONDIR=DIR to specify the Python directory tree.\n" "Use -DPYTHONVERSION=VERSION to help searching for the right version.\n" "(suitable Debian/Ubuntu package: python-dev)\n" "(suitable Fedora package: python-devel)\n" "${PYTHONMSG} ${PYTHON_MODULEMSG}") endif(PYTHONLIBS_FOUND) endif(PYTHON OR PYTHON_MODULE) # udunits # -DUDUNITS=ON|OFF # -DUDUNITSDIR=DIR if(UDUNITS) set(CMAKE_PREFIX_PATH ${UDUNITSDIR}) find_package(Udunits QUIET) set(USE_UDUNITS ${UDUNITS_FOUND}) if(UDUNITS_FOUND) set(LIBRARIES ${LIBRARIES} ${UDUNITS_LIBRARIES}) include_directories(${UDUNITS_INCLUDE_DIR}) else(UDUNITS_FOUND) message(FATAL_ERROR "UDUNITS-2 is required but was not found.\n" "Use -DUDUNITSDIR=DIR to specify the Udunits directory tree.\n" "Use -DUDUNITS=OFF to not use it.\n" "(suitable Debian/Ubuntu package: libudunits2-dev)\n" "(suitable Fedora package: udunits2-devel)") endif(UDUNITS_FOUND) endif(UDUNITS) # eigen3 # -DEIGEN3=ON|OFF # -DEIGEN3DIR=DIR if(EIGEN3) # cleaning Cache ... if (EIGEN3DIR) unset(EIGEN3_INCLUDE_DIR CACHE) endif(EIGEN3DIR) # set(CMAKE_PREFIX_PATH ${EIGEN3DIR}) find_package(Eigen3 3.2.4 QUIET) if(EIGEN3_TOO_OLD) # on iCore 3/5/7 we must have Eigen >=3.2.4 to avoid fatal error in "test_matrix_multiply.pro" message(FATAL_ERROR "\nEIGEN3 is required but the version found is TOO OLD." " Please download a recent version (>=3.2.4) in a local directory." " Then use -DEIGEN3DIR=DIR to specify the Eigen3 local directory tree.\n") else(EIGEN3_TOO_OLD) set(USE_EIGEN ${EIGEN3_FOUND}) if(EIGEN3_FOUND) include_directories(${EIGEN3_INCLUDE_DIR}) if(MINGW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-ipa-cp-clone") endif(MINGW) else(EIGEN3_FOUND) message(FATAL_ERROR "EIGEN3 is required but was not found.\n" "Use -DEIGEN3DIR=DIR to specify the Eigen3 directory tree.\n" "Use -DEIGEN3=OFF to not use it.\n" "(suitable Fedora package: eigen3-devel)\n" "(suitable Debian/Ubuntu package: libeigen3-dev)") endif(EIGEN3_FOUND) endif(EIGEN3_TOO_OLD) endif(EIGEN3) # pslib # -DPSLIB=ON|OFF # -DPSLIBDIR=DIR if(PSLIB) set(CMAKE_PREFIX_PATH ${PSLIBDIR}) find_package(libps QUIET) set(USE_PSLIB ${PSLIB_FOUND}) if(PSLIB_FOUND) set(LIBRARIES ${LIBRARIES} ${PSLIB_LIBRARIES}) #set(LINK_DIRECTORIES ${LINK_DIRECTORIES} ${PSLIB_LIBRARY_DIRS}) include_directories(${PSLIB_INCLUDE_DIR}) else(PSLIB_FOUND) message(FATAL_ERROR "pslib is required but was not found.\n" "Use -DPSLIBDIR=DIR to specify the pslib directory tree.\n" "Use -DPSLIB=OFF to not use it.\n" "(suitable Debian/Ubuntu package: pslib-dev)\n" "(suitable Fedora package: pslib-devel)") endif(PSLIB_FOUND) endif(PSLIB) # grib # -DGRIB=ON|OFF # -DGRIBDIR=DIR if(GRIB) set(CMAKE_PREFIX_PATH ${GRIBDIR} ${JASPERDIR} ${JPEGDIR}) find_package(Grib QUIET) set(USE_GRIB ${GRIB_FOUND}) if(GRIB_FOUND) set(LIBRARIES ${LIBRARIES} ${GRIB_LIBRARIES}) include_directories(${GRIB_INCLUDE_DIR}) else(GRIB_FOUND) message(FATAL_ERROR "ECMWF ecCodes or GRIB API is required but was not found.\n" "Use -DGRIBDIR=DIR to specify the ecCodes or GRIB API directory tree.\n" "Use -DGRIB=OFF to not use it.\n" "Use -DJASPERDIR=DIR and|or -DJPEGDIR=DIR to specify " "the directory trees of JasPer and openJPEG libraries.\n" "(suitable Debian/Ubuntu package: libeccodes-dev or libgrib-api-dev)\n" "(suitable Fedora package: grib_api-devel)\n" "(suitable Homebrew package: eccodes)\n") endif(GRIB_FOUND) endif(GRIB) # QHULL IS NOT NEEDED YET! # # Qhull (enable TRIANGULATE and QHULL commands) # # -DQHULL=ON|OFF # # -DQHULLDIR=DIR # if(QHULL) # set(CMAKE_PREFIX_PATH ${QHULLDIR}) # find_package(QHULL QUIET) # set(PL_HAVE_QHULL ${QHULL_FOUND}) # if(QHULL_FOUND) # set(LIBRARIES ${LIBRARIES} ${QHULL_LIBRARIES}) # include_directories(${QHULL_INCLUDE_DIR}) # else(QHULL_FOUND) # message(FATAL_ERROR "QHULL is required but was not found.\n" # "Use -DQHULLDIR=DIR to specify the QHULL directory tree.\n" # "Use -DQHULL=OFF to not use it.\n" # "(suitable Fedora package: libqhull-devel)") # endif(QHULL_FOUND) # endif(QHULL) # GLPK for Simplex ( Linear programming ) # GLPK (enable SIMPLEX command) # -DGLPK=ON|OFF # -DGLPKDIR=DIR if(GLPK) set(CMAKE_PREFIX_PATH ${GLPKDIR}) find_package(GLPK QUIET) set(USE_GLPK ${GLPK_FOUND}) if(GLPK_FOUND) set(LIBRARIES ${LIBRARIES} ${GLPK_LIBRARIES}) include_directories(${GLPK_INCLUDE_DIR}) else(GLPK_FOUND) message(FATAL_ERROR "GLPK (Gnu Linear Programming Kit) is required but was not found.\n" "Use -DGLPKDIR=DIR to specify the GLPK-devel directory tree.\n" "Use -DGLPK=OFF to not use it.\n") endif(GLPK_FOUND) endif(GLPK) #check_include_file(glpk.h HAVE_GLPK) # gshhs # -DGSHHS=ON|OFF if(GSHHS) set(USE_GSHHS 1) endif(GSHHS) # -DGSHHSDIR=DIR #not needed anymore, gshhs include is in src/ # set(CMAKE_PREFIX_PATH ${GSHHSDIR} src/) # find_path(GSHHS_INCLUDE_DIR gshhs.h) # mark_as_advanced(GSHHS_INCLUDE_DIR) # set(USE_GSHHS ${GSHHS_INCLUDE_DIR}) # if(USE_GSHHS) # include_directories(${GSHHS_INCLUDE_DIR}) # else(USE_GSHHS) # message(FATAL_ERROR "GSHHS is required but gshhs.h was not found.\n" # "Use -DGSHHSDIR=DIR to specify the GSHHS directory tree.\n" # "Use -DGSHHS=OFF to not use it.") # endif(USE_GSHHS) #endif(GSHHS) # # X11 if(X11) set(CMAKE_PREFIX_PATH ${X11DIR}) if(WIN32 AND NOT CYGWIN) find_package(Xportmingw QUIET) set(HAVE_X ${XPORTMINGW_FOUND}) set(USE_X ${XPORTMINGW_FOUND}) if(XPORTMINGW_FOUND) set(LIBRARIES ${LIBRARIES} ${XPORTMINGW_LIBRARIES}) include_directories(${XPORTMINGW_INCLUDE_DIR}) else(XPORTMINGW_FOUND) message("X11 was not found.\n" "Use -DX11DIR=DIR to specify the X11 directory tree.") endif(XPORTMINGW_FOUND) else(WIN32 AND NOT CYGWIN) find_package(X11 QUIET) set(HAVE_X ${X11_FOUND}) set(USE_X ${X11_FOUND}) if(X11_FOUND) set(LIBRARIES ${LIBRARIES} ${X11_LIBRARIES}) include_directories(${X11_INCLUDE_DIR}) else(X11_FOUND) message(FATAL_ERROR "X11 is required but was not found.\n" "Use -DX11DIR=DIR to specify the X11 directory tree.\n" "Use -DX11=OFF to not use it.") endif(X11_FOUND) endif(WIN32 AND NOT CYGWIN) endif(X11) add_subdirectory(src) if(NOT PYTHON_MODULE) add_subdirectory(testsuite) endif(NOT PYTHON_MODULE) install(FILES ${CMAKE_SOURCE_DIR}/AUTHORS ${CMAKE_SOURCE_DIR}/README DESTINATION ${CMAKE_INSTALL_PREFIX}/${GDL_DATA_DIR}) install(FILES ${CMAKE_SOURCE_DIR}/doc/gdl.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1) # substitute variables in configure.h.cmake and move it to configure.h configure_file(${CMAKE_SOURCE_DIR}/config.h.cmake ${CMAKE_BINARY_DIR}/config.h) # create a link src/gdl -> ${BUILD}/.../gdl # for windows, just copy the file if(NOT PYTHON_MODULE) get_target_property(GDLLOCATION gdl LOCATION) if(WIN32) add_custom_target(copy_gdl ALL ${CMAKE_COMMAND} -E copy ${GDLLOCATION} ${CMAKE_SOURCE_DIR}/src/gdl DEPENDS gdl) else(WIN32) add_custom_target(symlink_gdl ALL ${CMAKE_COMMAND} -E create_symlink ${GDLLOCATION} ${CMAKE_SOURCE_DIR}/src/gdl DEPENDS gdl) endif(WIN32) endif(NOT PYTHON_MODULE) # display macro macro(MODULE MOD NAME) if(${MOD}) message("${NAME} ON (libs:${${MOD}_LIBRARIES}; headers:${${MOD}_INCLUDE_DIR})") else(${MOD}) message("${NAME} OFF") endif(${MOD}) endmacro(MODULE) # python if(PYTHON_MODULE) set(BUILDTYPE "Python Module") else(PYTHON_MODULE) set(BUILDTYPE "Standalone") endif(PYTHON_MODULE) # IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) if(MSVC) SET(MACHINE_ARCH ${MSVC_C_ARCHITECTURE_ID}) IF(NOT MACHINE_ARCH) SET(MACHINE_ARCH ${MSVC_CXX_ARCHITECTURE_ID}) ENDIF(NOT MACHINE_ARCH) set_target_properties(gdl PROPERTIES LINK_FLAGS "/machine:${MACHINE_ARCH}") endif(MSVC) # AC, 12-oct-2011, solved by Marc # set_target_properties(gdl PROPERTIES LINK_FLAGS "-Wl,-z,muldefs") # set_target_properties(gdl PROPERTIES LINK_FLAGS "-z muldefs") # if(CMAKE_BUILD_TYPE STREQUAL None OR NOT CMAKE_BUILD_TYPE) set(FLAGS ${CMAKE_CXX_FLAGS}) elseif(CMAKE_BUILD_TYPE STREQUAL Debug) set(FLAGS ${CMAKE_CXX_FLAGS_DEBUG}) elseif(CMAKE_BUILD_TYPE STREQUAL Release) set(FLAGS ${CMAKE_CXX_FLAGS_RELEASE}) elseif(CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo) set(FLAGS ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) elseif(CMAKE_BUILD_TYPE STREQUAL MinSizeRel) set(FLAGS ${CMAKE_CXX_FLAGS_MINSIZEREL}) endif(CMAKE_BUILD_TYPE STREQUAL None OR NOT CMAKE_BUILD_TYPE) message(STATUS "Summary GDL - GNU DATA LANGUAGE [${BUILDTYPE}] System ${CMAKE_HOST_SYSTEM} Files generated ${CMAKE_GENERATOR} GDL output ${GDLLOCATION} Installation prefix ${CMAKE_INSTALL_PREFIX} C++ compiler ${CMAKE_CXX_COMPILER} ${FLAGS}") message("") message(STATUS "Options") if(OPENMP AND OPENMP_FOUND) message("OpenMP support ON (flag: ${OpenMP_CXX_FLAGS})") else(OPENMP AND OPENMP_FOUND) message("OpenMP support OFF") endif(OPENMP AND OPENMP_FOUND) set(WXWIDGETS_LIBRARIES ${wxWidgets_LIBRARIES}) module(WXWIDGETS "WxWidgets ") module(MAGICK "ImageMagick") module(TIFF "TIFF ") module(GEOTIFF "GeoTIFF ") module(NETCDF "NetCDF ") module(HDF "HDF4 ") module(HDF5 "HDF5 ") module(FFTW "FFTW ") module(LIBPROJ4 "Libproj4 ") set(MPICH_LIBRARIES ${MPI_LIBRARIES}) module(MPICH "MPICH ") module(PYTHON "Python ") module(UDUNITS "UDUNITS-2 ") module(EIGEN3 "EIGEN3 ") module(GRAPHICSMAGICK "GRAPHICSMAGICK") module(GRIB "GRIB ") # set(QHULL_LIBRARIES ${QHULL_LIBRARIES}) # module(QHULL "QHULL ") set(GLPK_LIBRARIES ${GLPK_LIBRARIES}) module(GLPK "GLPK ") set(GSHHS_LIBRARIES ${GSHHS_INCLUDE_DIR}) module(GSHHS "GSHHS ") module(PSLIB "pslib ") if(WIN32 AND NOT CYGWIN) module(XPORTMINGW "XPortMinGW (Win32 Xlib) ") else(WIN32 AND NOT CYGWIN) module(X11 "Xlib ") endif(WIN32 AND NOT CYGWIN) module(PNGLIB "libpng ") message("") message(STATUS "Mandatory modules") set(PLPLOT ON) set(READLINE ON) set(GSL ON) set(ZLIB ON) set(RPC ON) if(NOT WIN32) set(CURSES ON) endif(NOT WIN32) module(PLPLOT "Plplot ") module(READLINE "GNU Readline ") module(EDITLINE "BSD Editline ") module(GSL "GSL ") module(ZLIB "Zlib ") module(RPC "RPC ") if(NOT WIN32) module(CURSES "(N)curses ") endif(NOT WIN32) message("") gdl-0.9.9/CMakeModules/000077500000000000000000000000001340051421000145765ustar00rootroot00000000000000gdl-0.9.9/CMakeModules/FindEditline.cmake000066400000000000000000000015661340051421000201460ustar00rootroot00000000000000# # copyright : (c) 2016 Alain Coulais # # 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 2 of the License, or # (at your option) any later version. # # This is a derived work from FindReadline.cmake # # On OSX, we do not have the GNU Readline Lib. by default # but we do have access to a BSB clone, the Editline Lib. # Unfortunatly, few functions are not visible in Editline Lib. !! find_library(EDITLINE_LIBRARY NAMES edit) set(EDITLINE_LIBRARIES ${EDITLINE_LIBRARY}) find_path(EDITLINE_INCLUDE_DIR NAMES editline/readline.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Editline DEFAULT_MSG EDITLINE_LIBRARIES EDITLINE_INCLUDE_DIR) mark_as_advanced( EDITLINE_LIBRARY EDITLINE_LIBRARIES EDITLINE_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindEigen3.cmake000066400000000000000000000060341340051421000175160ustar00rootroot00000000000000# - Try to find Eigen3 lib # # This module supports requiring a minimum version, e.g. you can do # find_package(Eigen3 3.1.2) # to require version 3.1.2 or newer of Eigen3. # # Once done this will define # # EIGEN3_FOUND - system has eigen lib with correct version # EIGEN3_INCLUDE_DIR - the eigen include directory # EIGEN3_VERSION - eigen version # Copyright (c) 2006, 2007 Montel Laurent, # Copyright (c) 2008, 2009 Gael Guennebaud, # Copyright (c) 2009 Benoit Jacob # Redistribution and use is allowed according to the terms of the 2-clause BSD license. if(NOT Eigen3_FIND_VERSION) if(NOT Eigen3_FIND_VERSION_MAJOR) set(Eigen3_FIND_VERSION_MAJOR 2) endif(NOT Eigen3_FIND_VERSION_MAJOR) if(NOT Eigen3_FIND_VERSION_MINOR) set(Eigen3_FIND_VERSION_MINOR 91) endif(NOT Eigen3_FIND_VERSION_MINOR) if(NOT Eigen3_FIND_VERSION_PATCH) set(Eigen3_FIND_VERSION_PATCH 0) endif(NOT Eigen3_FIND_VERSION_PATCH) set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") endif(NOT Eigen3_FIND_VERSION) macro(_eigen3_check_version) file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) set(EIGEN3_VERSION_OK FALSE) else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) set(EIGEN3_VERSION_OK TRUE) endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) set(EIGEN3_TOO_OLD FALSE) # message(STATUS "version ${EIGEN3_TOO_OLD} ") if(NOT EIGEN3_VERSION_OK) set(EIGEN3_TOO_OLD TRUE) message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " "but at least version ${Eigen3_FIND_VERSION} is required") endif(NOT EIGEN3_VERSION_OK) endmacro(_eigen3_check_version) if (EIGEN3_INCLUDE_DIR) # in cache already _eigen3_check_version() set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) else (EIGEN3_INCLUDE_DIR) find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library PATHS ${CMAKE_INSTALL_PREFIX}/include ${KDE4_INCLUDE_DIR} PATH_SUFFIXES eigen3 eigen ) if(EIGEN3_INCLUDE_DIR) _eigen3_check_version() endif(EIGEN3_INCLUDE_DIR) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) mark_as_advanced(EIGEN3_INCLUDE_DIR) endif(EIGEN3_INCLUDE_DIR) gdl-0.9.9/CMakeModules/FindFFTW.cmake000066400000000000000000000013561340051421000171540ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # find_library(FFTW_LIBRARY NAMES fftw3) find_library(FFTWF_LIBRARY NAMES fftw3f) set(FFTW_LIBRARIES ${FFTW_LIBRARY} ${FFTWF_LIBRARY}) find_path(FFTW_INCLUDE_DIR NAMES fftw3.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDE_DIR) mark_as_advanced( FFTW_LIBRARY FFTWF_LIBRARY FFTW_LIBRARIES FFTW_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindGLPK.cmake000066400000000000000000000023441340051421000171410ustar00rootroot00000000000000# Find GLPK header and library. # # This module defines the following uncached variables: # GLPK_FOUND, if false, do not try to use GLPK. # GLPK_INCLUDE_DIRS, where to find glpk.h. # GLPK_LIBRARIES, the libraries to link against to use the GLPK library # GLPK_LIBRARY_DIRS, the directory where the GLPK library is found. find_path( GLPK_INCLUDE_DIR glpk.h PATHS /usr/local/include /usr/include ) if( GLPK_INCLUDE_DIR ) find_library( GLPK_LIBRARY NAMES libglpk.so libglpk.a PATHS /usr/lib64 /usr/local/lib /usr/lib ) if( GLPK_LIBRARY ) set(GLPK_LIBRARY_DIR "") get_filename_component(GLPK_LIBRARY_DIRS ${GLPK_LIBRARY} PATH) # Set uncached variables as per standard. set(GLPK_FOUND ON) set(GLPK_INCLUDE_DIRS ${GLPK_INCLUDE_DIR}) set(GLPK_LIBRARIES ${GLPK_LIBRARY}) endif(GLPK_LIBRARY) else(GLPK_INCLUDE_DIR) message(FATAL_ERROR "FindGLPK: Could not find glpk.h") endif(GLPK_INCLUDE_DIR) if(GLPK_FOUND) if(NOT GLPK_FIND_QUIETLY) message(STATUS "FindGLPK: Found both glpk.h and libglpk.a") endif(NOT GLPK_FIND_QUIETLY) else(GLPK_FOUND) if(GLPK_FIND_REQUIRED) message(FATAL_ERROR "FindGLPK: Could not find glpk.h and/or libglpk.a") endif(GLPK_FIND_REQUIRED) endif(GLPK_FOUND) gdl-0.9.9/CMakeModules/FindGSL.cmake000066400000000000000000000013651340051421000170330ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # find_library(GSL_LIBRARY NAMES gsl) find_library(GSLCBLAS_LIBRARY NAMES gslcblas) set(GSL_LIBRARIES ${GSL_LIBRARY} ${GSLCBLAS_LIBRARY}) find_path(GSL_INCLUDE_DIR NAMES gsl/gsl_math.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GSL DEFAULT_MSG GSL_LIBRARIES GSL_INCLUDE_DIR) mark_as_advanced( GSL_LIBRARY GSLCBLAS_LIBRARY GSL_LIBRARIES GSL_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindGeoTIFF.cmake000066400000000000000000000010641340051421000175650ustar00rootroot00000000000000# FindGeoTIFF # ----------- # Find the GeoTIFF library (libgeotiff) find_path(GEOTIFF_INCLUDE_DIR geotiff.h PATH_SUFFIXES geotiff libgeotiff) find_library(GEOTIFF_LIBRARY NAMES geotiff libgeotiff) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GeoTIFF DEFAULT_MSG GEOTIFF_INCLUDE_DIR GEOTIFF_LIBRARY) if(GEOTIFF_FOUND) set(GEOTIFF_LIBRARIES ${GEOTIFF_LIBRARY}) set(GEOTIFF_INCLUDE_DIRS ${GEOTIFF_INCLUDE_DIR}) endif(GEOTIFF_FOUND) mark_as_advanced( GEOTIFF_INCLUDE_DIR GEOTIFF_LIBRARY GEOTIFF_LIBRARIES GEOTIFF_INCLUDE_DIRS ) gdl-0.9.9/CMakeModules/FindGraphicsMagick.cmake000066400000000000000000000016621340051421000212620ustar00rootroot00000000000000# # copyright : (c) 2013 Sacha Hony # # 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 2 of the License, or # (at your option) any later version. # # http://sourceforge.net/tracker/?func=detail&aid=3611651&group_id=97659&atid=618685 # # Find the GraphicsMagick includes and library # find_library(GRAPHICSMAGICK_LIBRARY NAMES GraphicsMagick) find_library(GRAPHICSMAGICKXX_LIBRARY NAMES GraphicsMagick++) set(GRAPHICSMAGICK_LIBRARIES ${GRAPHICSMAGICK_LIBRARY} ${GRAPHICSMAGICKXX_LIBRARY}) find_path(GRAPHICSMAGICK_INCLUDE_DIR NAMES magick/api.h PATH_SUFFIXES GraphicsMagick) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GRAPHICSMAGICK DEFAULT_MSG GRAPHICSMAGICK_LIBRARIES GRAPHICSMAGICK_INCLUDE_DIR) mark_as_advanced( GRAPHICSMAGICK_LIBRARIES GRAPHICSMAGICK_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindGrib.cmake000066400000000000000000000027201340051421000172650ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # find_library(GRIB_LIBRARIES NAMES eccodes grib_api) find_path(GRIB_INCLUDE_DIR NAMES grib_api.h) include(FindPackageHandleStandardArgs) # since there's no grib_api.pc let's check if this installation of grib required jasper and jpeg include(CheckLibraryExists) set(CMAKE_REQUIRED_LIBRARIES m) check_library_exists(${GRIB_LIBRARIES} grib_index_new_from_file "" GRIB_COMPILES) if(GRIB_COMPILES) find_package_handle_standard_args(GRIB DEFAULT_MSG GRIB_LIBRARIES GRIB_INCLUDE_DIR) else(GRIB_COMPILES) find_package(Jasper) if(JASPER_FOUND) set(CMAKE_REQUIRED_LIBRARIES ${JASPER_LIBRARIES} m) check_library_exists(${GRIB_LIBRARIES} grib_index_new_from_file "" GRIB_COMPILES_JASPER) if(GRIB_COMPILES_JASPER) set(GRIB_LIBRARIES ${GRIB_LIBRARIES} ${JASPER_LIBRARIES}) set(GRIB_INCLUDE_DIR ${GRIB_INCLUDE_DIR} ${JASPER_INCLUDE_DIR}) find_package_handle_standard_args(GRIB DEFAULT_MSG GRIB_LIBRARIES GRIB_INCLUDE_DIR) endif(GRIB_COMPILES_JASPER) endif(JASPER_FOUND) endif(GRIB_COMPILES) set(CMAKE_REQUIRED_LIBRARIES) mark_as_advanced( GRIB_LIBRARIES GRIB_INCLUDE_DIR GRIB_COMPILES GRIB_COMPILES_JASPER ) gdl-0.9.9/CMakeModules/FindHDF.cmake000066400000000000000000000032431340051421000170040ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # # HDF_LIBRARIES # HDF_EXTRA_LIBRARIES find_package(JPEG) find_library(HDF_LIBRARY NAMES df dfalt PATH_SUFFIXES hdf) find_library(MFHDF_LIBRARY NAMES mfhdf mfhdfalt PATH_SUFFIXES hdf) set(HDF_LIBRARIES ${MFHDF_LIBRARY} ${HDF_LIBRARY}) find_path(HDF_INCLUDE_DIR NAMES hdf.h PATH_SUFFIXES hdf) include(CheckLibraryExists) include(FindPackageHandleStandardArgs) if(HDF_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES z ${JPEG_LIBRARIES}) check_library_exists("${HDF_LIBRARIES}" Hopen "" HDF_WO_SZIP) if(HDF_WO_SZIP) set(HDF_EXTRA_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) find_package_handle_standard_args(HDF DEFAULT_MSG HDF_LIBRARIES HDF_EXTRA_LIBRARIES HDF_INCLUDE_DIR) else(HDF_WO_SZIP) find_library(SZIP_LIBRARIES NAMES sz szip) if(SZIP_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${SZIP_LIBRARIES}) check_library_exists("${HDF_LIBRARIES}" Hopen "" HDF_W_SZIP) if(HDF_W_SZIP) set(HDF_EXTRA_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) find_package_handle_standard_args(HDF DEFAULT_MSG HDF_LIBRARIES HDF_EXTRA_LIBRARIES HDF_INCLUDE_DIR) endif(HDF_W_SZIP) endif(SZIP_LIBRARIES) endif(HDF_WO_SZIP) set(CMAKE_REQUIRED_LIBRARIES) endif(HDF_LIBRARIES) mark_as_advanced( HDF_LIBRARY MFHDF_LIBRARY HDF_LIBRARIES HDF_INCLUDE_DIR HDF_WO_SZIP HDF_EXTRA_LIBRARIES SZIP_LIBRARIES HDF_W_SZIP ) gdl-0.9.9/CMakeModules/FindImageMagick.cmake000066400000000000000000000252651340051421000205510ustar00rootroot00000000000000# - Find the ImageMagick binary suite. # This module will search for a set of ImageMagick tools specified # as components in the FIND_PACKAGE call. Typical components include, # but are not limited to (future versions of ImageMagick might have # additional components not listed here): # # animate # compare # composite # conjure # convert # display # identify # import # mogrify # montage # stream # # If no component is specified in the FIND_PACKAGE call, then it only # searches for the ImageMagick executable directory. This code defines # the following variables: # # ImageMagick_FOUND - TRUE if all components are found. # ImageMagick_EXECUTABLE_DIR - Full path to executables directory. # ImageMagick__FOUND - TRUE if is found. # ImageMagick__EXECUTABLE - Full path to executable. # ImageMagick_VERSION_STRING - the version of ImageMagick found # (since CMake 2.8.8) # # ImageMagick_VERSION_STRING will not work for old versions like 5.2.3. # # There are also components for the following ImageMagick APIs: # # Magick++ # MagickWand # MagickCore # # For these components the following variables are set: # # ImageMagick_FOUND - TRUE if all components are found. # ImageMagick_INCLUDE_DIRS - Full paths to all include dirs. # ImageMagick_LIBRARIES - Full paths to all libraries. # ImageMagick__FOUND - TRUE if is found. # ImageMagick__INCLUDE_DIRS - Full path to include dirs. # ImageMagick__LIBRARIES - Full path to libraries. # # Example Usages: # find_package(ImageMagick) # find_package(ImageMagick COMPONENTS convert) # find_package(ImageMagick COMPONENTS convert mogrify display) # find_package(ImageMagick COMPONENTS Magick++) # find_package(ImageMagick COMPONENTS Magick++ convert) # # Note that the standard FIND_PACKAGE features are supported # (i.e., QUIET, REQUIRED, etc.). #============================================================================= # Copyright 2007-2009 Kitware, Inc. # Copyright 2007-2008 Miguel A. Figueroa-Villanueva # Copyright 2012 Rolf Eike Beer # Copyright 2013 Nodar Kasradze : full (better ;) support of local install of IM # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # Define variables set(ENV{PATH} "${MAGICKDIR}/bin:$ENV{PATH}") set(ENV{PKG_CONFIG_PATH} "${MAGICKDIR}/lib/pkgconfig/:$ENV{PKG_CONFIG_PATH}") #--------------------------------------------------------------------- # Helper functions #--------------------------------------------------------------------- function(FIND_IMAGEMAGICK_API component header) set(ImageMagick_${component}_FOUND FALSE PARENT_SCOPE) find_path(ImageMagick_${component}_INCLUDE_DIR NAMES ${header} PATHS ${ImageMagick_INCLUDE_DIRS} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" PATH_SUFFIXES ImageMagick ImageMagick-6 DOC "Path to the ImageMagick include dir." ) find_library(ImageMagick_${component}_LIBRARY NAMES ${ARGN} PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH DOC "Path to the ImageMagick Magick++ library." ) find_library(ImageMagick_${component}_LIBRARY NAMES ${ARGN} PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/lib" DOC "Path to the ImageMagick Magick++ library." ) if(ImageMagick_${component}_INCLUDE_DIR AND ImageMagick_${component}_LIBRARY) set(ImageMagick_${component}_FOUND TRUE PARENT_SCOPE) list(APPEND ImageMagick_INCLUDE_DIRS ${ImageMagick_${component}_INCLUDE_DIR} ) list(REMOVE_DUPLICATES ImageMagick_INCLUDE_DIRS) set(ImageMagick_INCLUDE_DIRS ${ImageMagick_INCLUDE_DIRS} PARENT_SCOPE) list(APPEND ImageMagick_LIBRARIES ${ImageMagick_${component}_LIBRARY} ) set(ImageMagick_LIBRARIES ${ImageMagick_LIBRARIES} PARENT_SCOPE) endif() endfunction() function(FIND_IMAGEMAGICK_EXE component) set(_IMAGEMAGICK_EXECUTABLE ${ImageMagick_EXECUTABLE_DIR}/${component}${CMAKE_EXECUTABLE_SUFFIX}) if(EXISTS ${_IMAGEMAGICK_EXECUTABLE}) set(ImageMagick_${component}_EXECUTABLE ${_IMAGEMAGICK_EXECUTABLE} PARENT_SCOPE ) set(ImageMagick_${component}_FOUND TRUE PARENT_SCOPE) else() set(ImageMagick_${component}_FOUND FALSE PARENT_SCOPE) endif() endfunction() #--------------------------------------------------------------------- # Start Actual Work #--------------------------------------------------------------------- # Try to find a ImageMagick installation binary path. find_path(ImageMagick_EXECUTABLE_DIR NAMES mogrify${CMAKE_EXECUTABLE_SUFFIX} PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]" DOC "Path to the ImageMagick binary directory." NO_DEFAULT_PATH ) find_path(ImageMagick_EXECUTABLE_DIR NAMES mogrify${CMAKE_EXECUTABLE_SUFFIX} ) # Find each component. Search for all tools in same dir # ; otherwise they should be found # independently and not in a cohesive module such as this one. unset(ImageMagick_REQUIRED_VARS) unset(ImageMagick_DEFAULT_EXECUTABLES) foreach(component ${ImageMagick_FIND_COMPONENTS} # DEPRECATED: forced components for backward compatibility convert mogrify import montage composite ) if(component STREQUAL "Magick++") FIND_IMAGEMAGICK_API(Magick++ Magick++.h Magick++ CORE_RL_Magick++_ Magick++-6.Q16 Magick++-Q16 Magick++-6.Q8 Magick++-Q8 Magick++-6.Q16HDRI Magick++-Q16HDRI Magick++-6.Q8HDRI Magick++-Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY) elseif(component STREQUAL "MagickWand") FIND_IMAGEMAGICK_API(MagickWand wand/MagickWand.h Wand MagickWand CORE_RL_wand_ MagickWand-6.Q16 MagickWand-Q16 MagickWand-6.Q8 MagickWand-Q8 MagickWand-6.Q16HDRI MagickWand-Q16HDRI MagickWand-6.Q8HDRI MagickWand-Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY) elseif(component STREQUAL "MagickCore") FIND_IMAGEMAGICK_API(MagickCore magick/MagickCore.h Magick MagickCore CORE_RL_magick_ MagickCore-6.Q16 MagickCore-Q16 MagickCore-6.Q8 MagickCore-Q8 MagickCore-6.Q16HDRI MagickCore-Q16HDRI MagickCore-6.Q8HDRI MagickCore-Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickCore_LIBRARY) else() if(ImageMagick_EXECUTABLE_DIR) FIND_IMAGEMAGICK_EXE(${component}) endif() if(ImageMagick_FIND_COMPONENTS) list(FIND ImageMagick_FIND_COMPONENTS ${component} is_requested) if(is_requested GREATER -1) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_${component}_EXECUTABLE) endif() elseif(ImageMagick_${component}_EXECUTABLE) # if no components were requested explicitly put all (default) executables # in the list list(APPEND ImageMagick_DEFAULT_EXECUTABLES ImageMagick_${component}_EXECUTABLE) endif() endif() endforeach() if(NOT ImageMagick_FIND_COMPONENTS AND NOT ImageMagick_DEFAULT_EXECUTABLES) # No components were requested, and none of the default components were # found. Just insert mogrify into the list of the default components to # find so FPHSA below has something to check list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_mogrify_EXECUTABLE) elseif(ImageMagick_DEFAULT_EXECUTABLES) list(APPEND ImageMagick_REQUIRED_VARS ${ImageMagick_DEFAULT_EXECUTABLES}) endif() set(ImageMagick_INCLUDE_DIRS ${ImageMagick_INCLUDE_DIRS}) set(ImageMagick_LIBRARIES ${ImageMagick_LIBRARIES}) if(ImageMagick_mogrify_EXECUTABLE) execute_process(COMMAND ${ImageMagick_mogrify_EXECUTABLE} -version OUTPUT_VARIABLE imagemagick_version ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(imagemagick_version MATCHES "^Version: ImageMagick [0-9]") string(REGEX REPLACE "^Version: ImageMagick ([-0-9\\.]+).*" "\\1" ImageMagick_VERSION_STRING "${imagemagick_version}") endif() unset(imagemagick_version) endif() #--------------------------------------------------------------------- # Standard Package Output #--------------------------------------------------------------------- include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(ImageMagick REQUIRED_VARS ${ImageMagick_REQUIRED_VARS} VERSION_VAR ImageMagick_VERSION_STRING ) # Maintain consistency with all other variables. set(ImageMagick_FOUND ${IMAGEMAGICK_FOUND}) if (ImageMagick_FOUND) # run the Magick++ config program to get cxxflags execute_process( COMMAND sh "${ImageMagick_EXECUTABLE_DIR}/MagickCore-config" "--cxxflags" OUTPUT_VARIABLE IMAGEMAGICK_CXX_FLAGS RESULT_VARIABLE RET ERROR_QUIET ) if(RET EQUAL 0) string(STRIP "${IMAGEMAGICK_CXX_FLAGS}" IMAGEMAGICK_CXX_FLAGS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMAGEMAGICK_CXX_FLAGS}") else() # DBG_MSG_V("MagickCore-config --cxxflags command FAILED with RET=${RET}") message(WARNING "MagickCore-config --cxxflags command FAILED with RET=${RET}") endif() endif() #--------------------------------------------------------------------- # DEPRECATED: Setting variables for backward compatibility. #--------------------------------------------------------------------- set(IMAGEMAGICK_BINARY_PATH ${ImageMagick_EXECUTABLE_DIR} CACHE PATH "Path to the ImageMagick binary directory.") set(IMAGEMAGICK_CONVERT_EXECUTABLE ${ImageMagick_convert_EXECUTABLE} CACHE FILEPATH "Path to ImageMagick's convert executable.") set(IMAGEMAGICK_MOGRIFY_EXECUTABLE ${ImageMagick_mogrify_EXECUTABLE} CACHE FILEPATH "Path to ImageMagick's mogrify executable.") set(IMAGEMAGICK_IMPORT_EXECUTABLE ${ImageMagick_import_EXECUTABLE} CACHE FILEPATH "Path to ImageMagick's import executable.") set(IMAGEMAGICK_MONTAGE_EXECUTABLE ${ImageMagick_montage_EXECUTABLE} CACHE FILEPATH "Path to ImageMagick's montage executable.") set(IMAGEMAGICK_COMPOSITE_EXECUTABLE ${ImageMagick_composite_EXECUTABLE} CACHE FILEPATH "Path to ImageMagick's composite executable.") mark_as_advanced( IMAGEMAGICK_BINARY_PATH IMAGEMAGICK_CONVERT_EXECUTABLE IMAGEMAGICK_MOGRIFY_EXECUTABLE IMAGEMAGICK_IMPORT_EXECUTABLE IMAGEMAGICK_MONTAGE_EXECUTABLE IMAGEMAGICK_COMPOSITE_EXECUTABLE ) gdl-0.9.9/CMakeModules/FindLibproj4.cmake000066400000000000000000000013351340051421000200700ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # # for use of version from: # http://home.comcast.net/~gevenden56/proj/ find_library(LIBPROJ4_LIBRARIES NAMES proj4) find_path(LIBPROJ4_INCLUDE_DIR NAMES lib_proj.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LIBPROJ4 DEFAULT_MSG LIBPROJ4_LIBRARIES LIBPROJ4_INCLUDE_DIR) mark_as_advanced( LIBPROJ4_LIBRARIES LIBPROJ4_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindLibproj4new.cmake000066400000000000000000000013171340051421000206020ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # # for use of version from: # http://trac.osgeo.org/proj/ find_library(LIBPROJ4_LIBRARIES NAMES proj) find_path(LIBPROJ4_INCLUDE_DIR NAMES proj_api.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LIBPROJ4 DEFAULT_MSG LIBPROJ4_LIBRARIES LIBPROJ4_INCLUDE_DIR) mark_as_advanced( LIBPROJ4_LIBRARIES LIBPROJ4_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindNetCDF.cmake000066400000000000000000000015451340051421000174510ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # find_package(PkgConfig QUIET) pkg_check_modules(NETCDF netcdf) if(NETCDF_FOUND) # no netcdf.pc file find_package_handle_standard_args(NETCDF DEFAULT_MSG NETCDF_LIBRARIES) else(NETCDF_FOUND) # no netcdf.pc file find_library(NETCDF_LIBRARIES NAMES netcdf) find_path(NETCDF_INCLUDE_DIRS NAMES netcdf.h PATH_SUFFIXES netcdf-3) find_package_handle_standard_args(NETCDF DEFAULT_MSG NETCDF_LIBRARIES NETCDF_INCLUDE_DIRS) endif(NETCDF_FOUND) mark_as_advanced( NETCDF_INCLUDE_DIRS NETCDF_LIBRARIES ) gdl-0.9.9/CMakeModules/FindNumpy.cmake000066400000000000000000000032001340051421000175040ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # # - Find numpy # Find the native numpy includes # This module defines # PYTHON_NUMPY_INCLUDE_DIR, where to find numpy/arrayobject.h, etc. # PYTHON_NUMPY_FOUND, If false, do not try to use numpy headers. if (PYTHON_NUMPY_INCLUDE_DIR) # in cache already set (PYTHON_NUMPY_FIND_QUIETLY TRUE) endif (PYTHON_NUMPY_INCLUDE_DIR) #INCLUDE(FindPythonInterp) #SA: this is now done in CMakeLists.txt IF(PYTHON_EXECUTABLE) EXEC_PROGRAM ("${PYTHON_EXECUTABLE}" ARGS "-c \"import numpy; print (numpy.get_include())\"" OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR RETURN_VALUE PYTHON_NUMPY_NOT_FOUND) if (PYTHON_NUMPY_NOT_FOUND) set(PYTHON_NUMPY_FOUND FALSE) else() set (PYTHON_NUMPY_FOUND TRUE) set (PYTHON_NUMPY_INCLUDE_DIR ${PYTHON_NUMPY_INCLUDE_DIR} CACHE STRING "Numpy include path") endif() else() message(FATAL_ERROR "PYTHON_EXECUTABLE not defined!") ENDIF(PYTHON_EXECUTABLE) if (PYTHON_NUMPY_FOUND) if (NOT PYTHON_NUMPY_FIND_QUIETLY) message (STATUS "Numpy headers found") endif (NOT PYTHON_NUMPY_FIND_QUIETLY) else (PYTHON_NUMPY_FOUND) if (PYTHON_NUMPY_FIND_REQUIRED) message (FATAL_ERROR "Numpy headers missing") endif (PYTHON_NUMPY_FIND_REQUIRED) endif (PYTHON_NUMPY_FOUND) MARK_AS_ADVANCED (PYTHON_NUMPY_INCLUDE_DIR) gdl-0.9.9/CMakeModules/FindPCRE.cmake000066400000000000000000000012741340051421000171360ustar00rootroot00000000000000# # copyright : (c) 2012 Jeongbin Park # # 2012/Sep/18 Jeongbin Park added this file; to support Windows platform. # # 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 2 of the License, or # (at your option) any later version. # find_library(PCRE_LIBRARY NAMES pcre) set(PCRE_LIBRARIES ${PCRE_LIBRARY}) find_path(PCRE_INCLUDE_DIR NAMES regex.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PCRE DEFAULT_MSG PCRE_LIBRARIES PCRE_INCLUDE_DIR) mark_as_advanced( PCRE_LIBRARY PCRE_LIBRARIES PCRE_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindPdcurses.cmake000066400000000000000000000012601340051421000201700ustar00rootroot00000000000000# # 2014/Jun/25 Jeongbin Park added this file; to support Windows platform. # # 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 2 of the License, or # (at your option) any later version. # find_path(PDCURSES_INCLUDE_DIR curses.h) find_library(PDCURSES_LIBRARY pdcurses) set(PDCURSES_LIBRARIES ${PDCURSES_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PDCurses DEFAULT_MSG PDCURSES_LIBRARY PDCURSES_LIBRARIES PDCURSES_INCLUDE_DIR) mark_as_advanced(PDCURSES_LIBRARY PDCURSES_LIBRARIES PDCURSES_INCLUDE_DIR) gdl-0.9.9/CMakeModules/FindPlplot.cmake000066400000000000000000000066661340051421000176710ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # #test of rare case where old and new libraries are still present: terrible trouble! # the following code is justify to manage PLplot # on OSX 10.11 where the current versions of PLplot (30 August 2016) # packaged in Brew and Fink may be not OK with the CVS version of GDL # Then, when PLPLOTDIR is provide, it must be *strickly enforce*, # not looking at the lib. provided by Brew or Fink # set(PLPLOT_DEBUG off) if(PLPLOT_DEBUG) message(" ${PLPLOTDIR}") find_library(NEW_PLPLOT_LIBRARY NAMES plplot PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) find_library(OLD_PLPLOT_LIBRARY NAMES plplotd PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) message("new ${NEW_PLPLOT_LIBRARY}") message("old ${OLD_PLPLOT_LIBRARY}") endif(PLPLOT_DEBUG) if(PLPLOTDIR) message("Strickly enforce PLPLOTDIR=${PLPLOTDIR}") find_library(NEW_PLPLOT_LIBRARY NAMES plplot PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) if(NEW_PLPLOT_LIBRARY) find_library(PLPLOT_LIBRARY NAMES plplot PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) find_library(PLPLOTCXX_LIBRARY NAMES plplotcxx PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) endif(NEW_PLPLOT_LIBRARY) # find_library(OLD_PLPLOT_LIBRARY NAMES plplotd PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) if(OLD_PLPLOT_LIBRARY) find_library(PLPLOT_LIBRARY NAMES plplotd PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) find_library(PLPLOTCXX_LIBRARY NAMES plplotcxxd PATHS ${PLPLOTDIR} PATH_SUFFIXES lib NO_DEFAULT_PATH) endif(OLD_PLPLOT_LIBRARY) # find_path(PLPLOT_INCLUDE_DIR NAMES plplot/plplot.h PATHS ${PLPLOTDIR} PATH_SUFFIXES include NO_DEFAULT_PATH) else(PLPLOTDIR) message("Use fuzzy detection for PLplot lib. (e.g. in /usr/lib)") find_library(NEW_PLPLOT_LIBRARY NAMES plplot) if(NEW_PLPLOT_LIBRARY) find_library(PLPLOT_LIBRARY NAMES plplot) find_library(PLPLOTCXX_LIBRARY NAMES plplotcxx) endif(NEW_PLPLOT_LIBRARY) # find_library(OLD_PLPLOT_LIBRARY NAMES plplotd) if(OLD_PLPLOT_LIBRARY) find_library(PLPLOT_LIBRARY NAMES plplotd) find_library(PLPLOTCXX_LIBRARY NAMES plplotcxxd) endif(OLD_PLPLOT_LIBRARY) # find_path(PLPLOT_INCLUDE_DIR NAMES plplot/plplot.h) endif(PLPLOTDIR) #message("new ${NEW_PLPLOT_LIBRARY}") #message("old ${OLD_PLPLOT_LIBRARY}") if (NEW_PLPLOT_LIBRARY AND OLD_PLPLOT_LIBRARY) message(FATAL "Two incompatible plplot libraries are installed, probable trouble at compile time ahead.") endif (NEW_PLPLOT_LIBRARY AND OLD_PLPLOT_LIBRARY) # find_library(PLPLOT_LIBRARY NAMES plplot NO_DEFAULT_PATH) # find_library(PLPLOTCXX_LIBRARY NAMES plplotcxx NO_DEFAULT_PATH) #message(" ${PLPLOT_LIBRARY}") # normal situation : take care that PLPLOT_LIBRARIES and PLPLOT_INCLUDE_DIR prefix # must be the same !! set(PLPLOT_LIBRARIES ${PLPLOT_LIBRARY} ${PLPLOTCXX_LIBRARY}) #find_path(PLPLOT_INCLUDE_DIR NAMES plplot/plplot.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PLPLOT DEFAULT_MSG PLPLOT_LIBRARIES PLPLOT_INCLUDE_DIR) mark_as_advanced( PLPLOT_LIBRARY PLPLOTCXX_LIBRARY PLPLOT_LIBRARIES PLPLOT_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindQHULL.cmake000066400000000000000000000025131340051421000172670ustar00rootroot00000000000000# Find qhull header and library. # # This module defines the following uncached variables: # QHULL_FOUND, if false, do not try to use qhull. # QHULL_INCLUDE_DIRS, where to find qhull/qhull_a.h. # QHULL_LIBRARIES, the libraries to link against to use the qhull library # QHULL_LIBRARY_DIRS, the directory where the qhull library is found. find_path( QHULL_INCLUDE_DIR qhull/qhull_a.h libqhull/qhull_a.h PATHS /usr/local/include /usr/include ) if( QHULL_INCLUDE_DIR ) find_library( QHULL_LIBRARY NAMES libqhullstatic libqhull qhullstatic qhull PATHS /usr/lib64 /usr/local/lib /usr/lib ) if( QHULL_LIBRARY ) set(QHULL_LIBRARY_DIR "") get_filename_component(QHULL_LIBRARY_DIRS ${QHULL_LIBRARY} PATH) # Set uncached variables as per standard. set(QHULL_FOUND ON) set(QHULL_INCLUDE_DIRS ${QHULL_INCLUDE_DIR}) set(QHULL_LIBRARIES ${QHULL_LIBRARY}) endif(QHULL_LIBRARY) else(QHULL_INCLUDE_DIR) message(FATAL_ERROR "FindQHull: Could not find qhull_a.h") endif(QHULL_INCLUDE_DIR) if(QHULL_FOUND) if(NOT QHULL_FIND_QUIETLY) message(STATUS "FindQHull: Found both qhull_a.h and libqhull.a") endif(NOT QHULL_FIND_QUIETLY) else(QHULL_FOUND) if(QHULL_FIND_REQUIRED) message(FATAL_ERROR "FindQHull: Could not find qhull_a.h and/or libqhull.a") endif(QHULL_FIND_REQUIRED) endif(QHULL_FOUND) gdl-0.9.9/CMakeModules/FindRPC.cmake000066400000000000000000000007151340051421000170300ustar00rootroot00000000000000 include(FindPackageHandleStandardArgs) find_path(RPC_INCLUDE_DIR NAMES "rpc/rpc.h" PATH_SUFFIXES "tirpc") if(RPC_INCLUDE_DIR MATCHES "/tirpc/?$") find_library(RPC_LIBRARY NAMES tirpc) set(RPC_LIBRARIES ${RPC_LIBRARY}) find_package_handle_standard_args(RPC DEFAULT_MSG RPC_INCLUDE_DIR RPC_LIBRARY RPC_LIBRARIES) else() find_package_handle_standard_args(RPC DEFAULT_MSG RPC_INCLUDE_DIR) endif() mark_as_advanced(RPC_INCLUDE_DIR RPC_LIBRARY RPC_LIBRARIES) gdl-0.9.9/CMakeModules/FindReadline.cmake000066400000000000000000000014551340051421000201310ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # find_library(READLINE_LIBRARY NAMES readline) find_library(HISTORY_LIBRARY NAMES history) set(READLINE_LIBRARIES ${READLINE_LIBRARY} ${HISTORY_LIBRARY}) find_path(READLINE_INCLUDE_DIR NAMES readline/readline.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Readline DEFAULT_MSG READLINE_LIBRARIES READLINE_INCLUDE_DIR) mark_as_advanced( READLINE_LIBRARY HISTORY_LIBRARY READLINE_LIBRARIES READLINE_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindUdunits.cmake000066400000000000000000000012221340051421000200310ustar00rootroot00000000000000# # copyright : (c) 2010 Maxime Lenoir, Alain Coulais, # Sylwester Arabas and Orion Poplawski # # 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 2 of the License, or # (at your option) any later version. # find_library(UDUNITS_LIBRARIES NAMES udunits2) find_path(UDUNITS_INCLUDE_DIR NAMES udunits2.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(UDUNITS DEFAULT_MSG UDUNITS_LIBRARIES UDUNITS_INCLUDE_DIR) mark_as_advanced( UDUNITS_LIBRARIES UDUNITS_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/FindXdr.cmake000066400000000000000000000065221340051421000171430ustar00rootroot00000000000000# # The RealityGrid Steering Library # # Copyright (c) 2002-2010, University of Manchester, United Kingdom. # All rights reserved. # # This software is produced by Research Computing Services, University # of Manchester as part of the RealityGrid project and associated # follow on projects, funded by the EPSRC under grants GR/R67699/01, # GR/R67699/02, GR/T27488/01, EP/C536452/1, EP/D500028/1, # EP/F00561X/1. # # LICENCE TERMS # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # * Neither the name of The University of Manchester nor the names # of its contributors may be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Author: Robert Haines if(XDR_INCLUDE_DIR) # already in cache so be quiet set(XDR_FIND_QUIETLY TRUE) endif(XDR_INCLUDE_DIR) # if we have rpc.h then we may *need* it for xdr.h # so don't only look for xdr.h find_path(RPC_INCLUDE_DIR "rpc/rpc.h") # might only have xdr.h if(RPC_INCLUDE_DIR STREQUAL "RPC_INCLUDE_DIR-NOTFOUND") find_path(XDR_INCLUDE_DIR "rpc/xdr.h") if(NOT XDR_INCLUDE_DIR STREQUAL "XDR_INCLUDE_DIR-NOTFOUND") set(REG_HAS_XDR_H 1) endif(NOT XDR_INCLUDE_DIR STREQUAL "XDR_INCLUDE_DIR-NOTFOUND") else(RPC_INCLUDE_DIR STREQUAL "RPC_INCLUDE_DIR-NOTFOUND") set(REG_HAS_RPC_H 1) set(XDR_INCLUDE_DIR ${RPC_INCLUDE_DIR}) endif(RPC_INCLUDE_DIR STREQUAL "RPC_INCLUDE_DIR-NOTFOUND") # find the lib and add it if found find_library(XDR_LIBRARY NAMES rpc xdr_s xdr openxdr) if(NOT XDR_LIBRARY STREQUAL "XDR_LIBRARY-NOTFOUND") set(REG_EXTERNAL_LIBS ${REG_EXTERNAL_LIBS} ${XDR_LIBRARY}) endif(NOT XDR_LIBRARY STREQUAL "XDR_LIBRARY-NOTFOUND") mark_as_advanced(RPC_INCLUDE_DIR XDR_INCLUDE_DIR XDR_LIBRARY) # tend not to need a separate lib on Unix systems # do need one for Windows and Cygwin include(FindPackageHandleStandardArgs) if(UNIX) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XDR DEFAULT_MSG XDR_INCLUDE_DIR) else(UNIX) FIND_PACKAGE_HANDLE_STANDARD_ARGS(XDR DEFAULT_MSG XDR_INCLUDE_DIR XDR_LIBRARY) endif(UNIX)gdl-0.9.9/CMakeModules/FindXportmingw.cmake000066400000000000000000000015051340051421000205600ustar00rootroot00000000000000# # copyright : (c) 2014 Jeongbin Park # # 2014/Sep/24 Jeongbin Park added this file; to support Windows platform. # # 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 2 of the License, or # (at your option) any later version. # find_library(XPORTMINGWX11_LIBRARY NAMES x11) find_library(XPORTMINGWXAU_LIBRARY NAMES xau) set(XPORTMINGW_LIBRARIES ${XPORTMINGWX11_LIBRARY} ${XPORTMINGWXAU_LIBRARY}) find_path(XPORTMINGW_INCLUDE_DIR NAMES X11/X.h) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(XPORTMINGW DEFAULT_MSG XPORTMINGW_LIBRARIES XPORTMINGW_INCLUDE_DIR) mark_as_advanced( XPORTMINGW_LIBRARY XPORTMINGW_LIBRARIES XPORTMINGW_INCLUDE_DIR ) gdl-0.9.9/CMakeModules/Findlibps.cmake000066400000000000000000000013041340051421000175100ustar00rootroot00000000000000find_path(PSLIBPKG libps.pc PATH_SUFFIXES lib lib/pkgconfig lib64/pkgconfig) include(FindPackageHandleStandardArgs) if(PSLIBPKG) set(ENV{PKG_CONFIG_PATH} ${PSLIBPKG}) # pkg search path include(FindPkgConfig) pkg_search_module(PSLIB libps) if(PSLIB_FOUND) set(PSLIB_INCLUDE_DIR ${PSLIB_INCLUDEDIR}) find_package_handle_standard_args(PSLIB DEFAULT_MSG PSLIB_LIBRARIES PSLIB_INCLUDE_DIR) endif(PSLIB_FOUND) else() # no libps.pc file find_library(PSLIB_LIBRARIES NAMES libps pslib ps) find_path(PSLIB_INCLUDE_DIR NAMES libps/pslib.h) find_package_handle_standard_args(PSLIB DEFAULT_MSG PSLIB_LIBRARIES PSLIB_INCLUDE_DIR) endif() mark_as_advanced( PSLIBPKG PSLIB PSLIB_LIBRARIES PSLIB_INCLUDE_DIR ) gdl-0.9.9/COPYING000066400000000000000000000354331340051421000133300ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS gdl-0.9.9/ChangeLog000066400000000000000000020765311340051421000140550ustar00rootroot00000000000000GDL 0.9.6 2015-12-29 gilles-duvert * README: update on widget status * src/gdlwidget.cpp: minor adjustments for cosmetics (2). 2015-12-22 gilles-duvert * src/gdlwidget.cpp, src/widget.cpp: minor adjustments for cosmetics. 2015-12-21 gilles-duvert * src/libinit.cpp: removed unnecessary warnings about FONT * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/widget.cpp: Resizing affects (via TLB_SIZE_EVENT) ok now. Added DYNAMIC_RESIZE and changed way FRAME is handled. 2015-12-17 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/widget.cpp: added FONT= support. Also widget_info(/geometry) and alignments should be OK. Still pb with resizing (e.g.: ATV) when wxWidgets > 2.9 . Note that FONT values are wxWidgets/Windows names (like "Helvetica Oblique 32"). 2015-12-12 alaingdl * CMakeLists.txt, CMakeModules/FindEigen3.cmake: because old Eigen3 is not OK for moderm iCore 3/5/7, we check Eigen version (>= 3.2.4) now 2015-12-11 alaingdl * src/initsysvar.cpp: patch 88 to have reproducably buildable in Debian (__DATE__ changed as BUILD_DATE) 2015-12-03 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/gdlwxstream.cpp: Correct some bugs. Tested with wxWidgets 2.8 and 3.0 , plplot 5.9.9 and 5.11.1 (plplot-5.11.1 needs to be compiled with -DOLD_WXWIDGETS:BOOL=ON), their new wxdriver is too unstable 2015-12-02 gilles-duvert * testsuite/test_array_indices.pro: Test file for array_indices. * src/pro/array_indices.pro: R. Stockli added /DIMENSION Keyword. * CMakeLists.txt, config.h.cmake: Added finding QHULL, needed to have TRIANGULATE, QHULL et commands working at a future time. * CMakeModules/FindQHULL.cmake: New for finding QHULL, needed to have TRIANGULATE, QHULL et commands working at a future time. 2015-11-13 gilles-duvert * src/CMakeLists.txt, src/libinit_ac.cpp: Temporary removed reference to unfinished "smooth.cpp" work, whose compilation is not... smooth on some machines. To be removed when this function is deemed OK. 2015-10-23 gilles-duvert * src/plotting.cpp: patches for plplot compatibility: invalid use of HAVE_CONFIG in plplot public include. * src/gdlwidget.cpp, src/gdlwidgeteventhandler.cpp: patches for wxWidgets 3.x compatibility (more to come). * src/gdlgstream.hpp, src/gdlwxstream.cpp, src/image.hpp: patches for plplot compatibility: invalid use of HAVE_CONFIG in plplot public include. * CMakeLists.txt, CMakeModules/FindPlplot.cmake, config.h.cmake, src/plotting_contour.cpp: patches for plplot compatibility (library names, functions api, etc that keep changing with plot's whims). Thanks to Orion and Greg. * src/smooth.cpp: saved temporary version of smooth (better, but not yet useable) * src/file.cpp: added comment about PATH_MAX for Windows gurus 2015-10-21 gilles-duvert * src/str.cpp: solves bug #673 2015-10-14 m_schellens * src/dinterpreter.cpp: Fixed bug #667: Accept comma separated file names in .RUN command * CMakeModules/FindImageMagick.cmake, src/GDLLexer.cpp, src/dinterpreter.cpp, src/hdf_pro.cpp, src/typetraits.hpp: Fixed bug #663: Skip in GetLine functions comment lines like empty lines 2015-10-09 gilles-duvert * src/file.cpp: solves bug #672 2015-10-07 gilles-duvert * src/read.cpp: solves bug #670 2015-10-07 alaingdl * testsuite/test_file_search.pro: revisiting "test_file_search.pro", adding 2 problematic new cases (bug 672) * testsuite/add_error.pro, testsuite/test_reads.pro: iinitial import of ADD_ERROR, use to increment errors count and print a message 2015-10-06 gilles-duvert * src/gdlpsstream.cpp: pacify fussy (dumb?) compilers. * testsuite/test_bits_per_pix.pro: Test for support for BITS_PER_PIXEL in PostScript device. Not automatic: provides a ps file for each case, to be examined by eye. 2015-10-05 gilles-duvert * src/gdlpsstream.cpp: support for BITS_PER_PIXEL in PostScript device (correct now). 2015-10-04 alaingdl * src/basic_fun.cpp: trying to correct bug 669 : a=SHFIT(dist(10), [2,3]) should work ! * testsuite/Makefile.am, testsuite/test_window_background.pro: 2 new files for "make check" : "test_reads" and "test_postscript". For the PS, just to give a chance to look at the outputs ... A typo corrected in "test_window_background.pro". 2015-10-04 gilles-duvert * src/deviceps.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp, src/graphicsdevice.hpp, src/libinit.cpp, src/plotting_device.cpp: support for BITS_PER_PIXEL and !P.FONT in PostScript device. 2015-10-04 alaingdl * testsuite/test_reads.pro: initial import of TEST_READS (READS is currently not working with "," (comma) as separator) 2015-09-26 gilles-duvert * src/deviceps.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp: This revision should permit to plot images at the correct location for PostScript output. * src/plotting_device.cpp: corrected bug interpretation landscape or portrait * testsuite/test_tv_ps.pro: better test 2015-09-20 gilles-duvert * src/GDLLexer.cpp, src/gdlc.g: corrected bug where PSlibHacks was messing up the (otherwise correct) PostScript output. 2015-09-18 pjb7687 * src/basic_fun.cpp: Changing WIN32 -> _WIN32. WIN32 (without underscore) is not defined in some compilers. 2015-09-17 gilles-duvert * src/deviceps.hpp: corrected bug where PSlibHacks was messing up the (otherwise correct) PostScript output. * src/gdlpsstream.hpp: minor changes to keep cppcheck happy. 2015-09-16 alaingdl * src/basic_pro.cpp: fixing bug reported by EH on: message,'here', level=1, /info when we are already at the main level 2015-09-14 gilles-duvert * src/objects.cpp: reverted the change of IsFun(), we gained speed in procedure compilation, alas it had sideeffects. 2015-09-10 gilles-duvert * src/basic_fun.cpp, src/basic_pro.cpp: minor changes to keep cppcheck happy. 2015-09-10 alaingdl * NEWS: update * testsuite/Makefile.am, testsuite/test_message.pro: updating the code for "test_message.pro", add it to automatic "make check" 2015-09-09 gilles-duvert * src/libinit.cpp: Added dummy options to SHADE_SURF to gain compatibility. (noticeably with XSURFACE). * src/gdlwxstream.cpp: Enable plplot's wxWidgets backends 0,1 or 2 by setting env variable GDL_WX_BACKEND * src/plotting.cpp, src/plotting_oplot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp: Do we get both correct positioning & clipping, in !P.MULTI modes as well as when a projection is active? 2015-09-07 gilles-duvert * src/dialog.hpp, src/dialog.cpp: replaced macro to be compatible with wxWidgets ver. 2.8 according to https://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString 2015-09-07 alaingdl * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: adding LEVEL keyword in MESSAGE * testsuite/test_message.pro: initial import of "test_message.pro", a draft. * testsuite/test_xdr.pro: revisiting "test_xdr.pro", I had some troubles. 2015-09-06 gilles-duvert * src/deviceps.hpp, src/gdlwidget.cpp, src/gdlwidgeteventhandler.cpp, src/hdf5_fun.cpp, src/image.cpp, src/math_fun_ng.cpp: minor changes to keep cppcheck happy. 2015-09-06 alaingdl * testsuite/gdl_idl_fl.pro, testsuite/test_formats.pro, testsuite/test_plot_oo.pro: updating "test_plot_oo" in such a way it can count plotting types. SVG and PS outputs also possible. IDL and FL possible too. 2015-09-06 gilles-duvert * src/gdlsvgstream.cpp: removed memory leak 2015-09-05 gilles-duvert * src/plotting_oplot.cpp, src/plotting_plots.cpp: Enabled correct positioning in !P.MULTI mode + projections (hopefully) * src/plotting.cpp: Plotting routines that do not clear the plot must take care solely of changes in ![X|Y].S . AXIS should reset the plplot box if the SAVE argument is used. 2015-09-05 alaingdl * src/basic_pro.cpp: New version for HELP, calls=c based on SimpleDumpStack() in the same file. 2015-09-05 gilles-duvert * src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_oplot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp: Plotting routines that do not clear the plot must take care solely of changes in ![X|Y].S . AXIS should reset the plplot box if the SAVE argument is used. 2015-09-05 alaingdl * testsuite/Makefile.am, testsuite/test_pmulti_basic.pro: simple graphical test to see whether we introduce regression related to !p.multi and OPLOT. May be extensible for other Devices (PS, SVG ...) ? 2015-09-03 alaingdl * src/plotting.cpp, src/plotting_oplot.cpp: correcting OPLOT with log scale. Pb detected via Coyote Lib. and test case "additional_axes_plot" in debian/test/test_coyote.pro 2015-09-03 gilles-duvert * src/basic_pro.cpp: corrected regression introduced by 1.192 2015-09-03 alaingdl * src/plotting_plot.cpp: improving the way xLog and Ylog are managed (plot_oo or /xlog or /xtype) see "test_plot_oo.pro" for test case 2015-09-03 gilles-duvert * src/dcompiler.cpp, src/dcompiler.hpp, src/objects.cpp: by modifying the IsFun() method we gain speed in procedure compilation. 2015-09-03 alaingdl * src/basic_pro.cpp: change in Help, Calls=callStack to return also the current level ! 2015-09-02 gilles-duvert * src/gdlgstream.hpp: replaced FALSE by false * src/plotting.cpp: corrected memory leaks... * src/gdlgstream.hpp, src/plotting_device.cpp: corrected memory leak 2015-09-01 gilles-duvert * src/gdl.cpp, src/initsysvar.cpp, src/initsysvar.hpp: added gdl commandline option --fakerelease to have !VERSION.RELEASE match any value requested by a script. * NEWS, src/basic_fun.cpp: update routine_info to report all routines/functions if so desired. 2015-08-31 gilles-duvert * src/ifmt.cpp, src/ofmt.cpp: corrected calendar format for seconds in input/output. * src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_plot.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp: takes care of xtickunits option, better (but far from ideal) multi axis (option [XYZ]units) support. * src/libinit.cpp: added comment 2015-08-28 gilles-duvert * src/gdlc.g, src/GDLLexer.cpp: solves bug #663 2015-08-27 alaingdl * src/file.cpp, src/str.cpp: more changes related to wordexp in "file_info" and "file_test", related to problems in FILE_DELETE. 2015-08-26 gilles-duvert * src/gdlwxstream.cpp: Workaround try for pacifying fussy compilers arguing about an invalid type of parameter for SetLogicalFunction(). 2015-08-25 gilles-duvert * src/FMTOut.cpp, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.hpp, src/dstructgdl.hpp, src/format.out.g, src/nullgdl.cpp, src/nullgdl.hpp, src/ofmt.cpp: Formats X and strings were not correctly handled in the subcase of output calendar format. * src/libinit.cpp: option name MONTH -> MONTHS * src/gdlwxstream.cpp: corrected invalid type of parameter for SetLogicalFunction(). * src/default_io.cpp: changed again xdr complex-handling functions to pacify windows-based compilers. use testsuite/test_xdr.pro to check correctness. 2015-08-24 gilles-duvert * src/FMTOut.hpp, src/datatypes.hpp, src/format.out.g, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTLexer.cpp, src/FMTOut.cpp, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/dstructgdl.hpp, src/format.g, src/format.in.g, src/ifmt.cpp, src/nullgdl.cpp, src/nullgdl.hpp, src/ofmt.cpp, src/specializations.hpp: Completed support of calendar format codes, including repeat count for output format, still some unfinished work for input format. Also, corrected a bug in input formatting that preventing correct parsing in the presence of the "X" code or strings. * src/default_io.cpp: changed xdr complex-handling functions to prevent compiler problems. 2015-08-20 alaingdl * testsuite/Makefile.am, testsuite/test_window_background.pro: initial import to check whether the background color is OK for WINDOW or PLOT (as it was already OK with ERASE) The automatic test is working for DEVICE, /decomposed Visual test OK for DEVICE, decomposed=0 2015-08-19 gilles-duvert * src/FMTLexer.cpp, src/FMTOut.cpp, src/FMTParser.cpp, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.hpp, src/format.g, src/format.out.g, src/nullgdl.cpp, src/nullgdl.hpp, src/ofmt.cpp, src/specializations.hpp: Support of calendar format codes: output formatting OK with the exception of repeat count ( e.g.: in FORMAT='(2C())', the repeat count 2 is ignored) 2015-08-18 gilles-duvert * src/plotting.cpp, src/plotting_map_proj.cpp: replaced obsoleted finite() with isfinite() * src/devicewx.hpp, src/devicex.hpp, src/gdlwxstream.cpp: Added SET_GRAPHICS_FUNCTION for WXWidgets (e.g., use of cursor in astrolib's look.pro). Also corrected a logic bug that prevented setting graphic functions or cursor in some cases. * src/objects.cpp: temporary avoid to purge the memory reserved by commons during final exit (double delete for structures in common not handled would make GDL crash on exit in some cases). This tidying is not really necessary anyway. * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlwxstream.cpp, src/graphicsdevice.cpp, src/graphicsdevice.hpp, src/plotting.cpp, src/plotting_windows.cpp, src/gdlwinstream.cpp, src/gdlxstream.cpp, src/plotting_erase.cpp: Solved problems related to concurrency of background color and index 0 of current palette (a plplot "feature") by reserving the background color separately and using it only for the plplot equivalent of ERASE (bop()). The reserved background color should now be properly initialized in graphic windows creations (WINDOW, WSET) at least for X,WX and WIN (PS background is always white). Corrected also a bug related to improper use of CHANNEL value for per-channel ERASE. 2015-08-17 alaingdl * src/plotting_windows.cpp: In fact, it was not realized that we need to manage the background color in WINDOW. Should work now. This come from tests within Nika pipeline and HEALPix feedbacks. 2015-08-13 gilles-duvert * src/gdlxstream.cpp: should better correct color=0 bug 2015-08-11 alaingdl * src/gdlxstream.cpp: trying to solve the famous bug of white on white in Device, decomposed=0 plot, findgen(10), back=255, color=0 (mainy famous codes are suffering from that : PSM, Nika, Ulyss) 2015-08-01 alaingdl * src/least_squares.cpp: B argument to LA_LEAST_SQUARES can now be an array. Other details fixed. * src/pro/make_dll.pro: better version for MAKE_DLL, this one should works on Linux, may be OSX, please report any improvment. Needed by Nika2 pipeline. First commit after SourceForce crash in July 2015 2015-07-14 alaingdl * testsuite/Makefile.am, testsuite/test_la_least_square.pro, testsuite/test_la_least_squares.pro: bad name ... moving ... * src/CMakeLists.txt: I forgot to update it for LA_LEAST_SQUARES 2015-07-13 alaingdl * NEWS, src/least_squares.cpp, src/least_squares.hpp, src/libinit_jmg.cpp, testsuite/Makefile.am, testsuite/test_la_least_square.pro: initial import of LA_LEAST_SQUARES (+ tests), based on Eigen3. This code was need for Ulyss 2015-07-11 gilles-duvert * testsuite/test_tv.pro: Patched for bug #659 TEST_TV_OVER_BOX returns gracefully when "Saturn.jpg" is not found. And corresponding windows are not closed (which would generate an error). 2015-07-10 gilles-duvert * src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/FMTLexer.cpp, src/FMTOut.cpp, src/FMTParser.cpp, src/format.g, src/format.out.g: en route to correct support of calendar format codes (bis). * src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/FMTParser.cpp, src/FMTParser.hpp, src/FMTTokenTypes.hpp, src/FMTTokenTypes.txt, src/format.g, src/ofmt.cpp: en route to correct support of calendar format codes. 2015-07-10 alaingdl * testsuite/Makefile.am, testsuite/test_plot_oo.pro: checking whether the /Xlog and /Xtype keywords are enforced, in PLOT, PLOT_IO/OI/OO * src/pro/make_dll.pro: initial import of MAKE_DLL. This code is NOT finished. !Make_DLL already available in GDL. * src/initsysvar.cpp: adding !MAKE_DLL structure, code itself not ready * src/plotting_plot.cpp: correcting the logic for log related keywords in PLOT, PLOT_IO, PLOT_OI and PLOT_OO 2015-07-09 gilles-duvert * src/format.g: oops forgotten closing brace 2015-07-08 gilles-duvert * src/FMTParser.cpp, src/format.g, src/ofmt.cpp: definitely solves bug #660 2015-07-04 gilles-duvert * src/ofmt.cpp: partially solves bug #660 * src/libinit.cpp: make MESSAGE compatible with more than 1 argument (reloaded). 2015-07-02 alaingdl * NEWS, src/basic_pro.cpp, src/libinit.cpp, src/pro/resolve_all.pro: initial import of RESOLVE_ALL (*.pro), more keywords in RESOLVE_ROUTINE. This was needed for code Ulyss. Work by Ilia N. * src/basic_pro.cpp, src/libinit.cpp: various improvments in RESOLVE_ROUTINE (by Ilia N.) * src/pro/svsol.pro: initial import of SVSOL() as a pro file. Thanks to Eric H. Work and tests by Ilia N. 2015-07-01 gilles-duvert * src/libinit_jmg.cpp: max number of arguments was wrong for randomu, randomn and reform. * src/basic_pro.cpp: make MESSAGE compatible with more than 1 argument, but do nothing more that signal this is not supported. Solves some compatibilty issues. 2015-06-30 gilles-duvert * src/libinit_jmg.cpp: added L64 as ignored option, dirty-patching bug #662 2015-06-29 alaingdl * src/pro/handle_info.pro: patch by Jonathan W. 2015-06-13 gilles-duvert * src/default_io.cpp: removed patches that prevented test_xdr to run correctly on linux. Further changes for other architectures must be surrounded by #ifdef and well documented. * src/pro/interpol.pro: Applied Kalith's patch #86 to make INTERPOL support out-of-bounds scalar third argument 2015-06-11 gilles-duvert * src/hdf_pro.cpp: solves bug 649. Simplified some expressions equivalent to pointer on data. 2015-06-10 gilles-duvert * src/plotting.cpp, src/plotting_map_proj.cpp, src/pro/map_clip_set.pro, src/pro/xmanager.pro, src/pro/xregistered.pro: better support, although far from final, of map projections splitting and contour closing/filling. aligned more xmanager common on what idl does. * src/gdlwidget.cpp: solves temporary bug #655. See comments in bug report 2015-06-05 alaingdl * testsuite/Makefile.am, testsuite/test_file_copy.pro, testsuite/test_file_delete.pro, testsuite/test_ishft.pro, testsuite/test_netcdf.pro: fixing various details in codes in testsuite/ 2015-06-04 alaingdl * src/file.cpp, src/str.cpp: trying to solve the dynamic cast issue for input with wildmarks in various FILE* functions (patch bye Ilia N.) 2015-06-04 gilles-duvert * src/ofmt.cpp: corrected bug #654 * src/gdlwidget.cpp, src/gdlwidget.hpp: added code to handle better all types of buttons. * src/gdlwidget.cpp, src/widget.cpp: added tests whenever a static cast for a wxWidget is attempted. 2015-06-02 alaingdl * testsuite/Makefile.am, testsuite/test_bug_3275334.pro, testsuite/test_device.pro, testsuite/test_random.pro, testsuite/test_tv.pro: cleaning up few tests (being able to run on systems without X11 and WIN, only NULL) 2015-06-01 alaingdl * NEWS: update * src/math_fun_gm.cpp: correcting arrays combinations for few extra Math functions (cf "test_math_function_dim.pro") * src/pro/file_move.pro: initial import of pro FILE_MOVE (By Ilia N.) * testsuite/Makefile.am, testsuite/test_file_move.pro: initial import of "test_file_move.pro" * testsuite/test_math_function_dim.pro, testsuite/test_MathFunctionsDim.pro: renaming "test_MathFunctionsDim.pro" into "test_math_function_dim.pro" 2015-06-01 gilles-duvert * src/pro/ishft.pro: rewritten ishft using inputs from B. Dieckmann and new test cases. Should be written in C++ for performance. 2015-06-01 alaingdl * src/math_fun_ac.cpp, src/math_fun_ng.cpp: correcting Besel functions and Voigt to follow changes in IDL 8.4 for input ([1],[N]), which return now [1]. More to come : other Math. functions. 2015-05-29 pjb7687 * src/pro/xdisplayfile.pro: Allows zero-length string ("") for filename in Xdisplayfile. 2015-05-26 alaingdl * testsuite/test_file_info.pro, testsuite/test_file_test.pro: initial import of "test_file_info" (by Ilia), to be extend. Better messages for "test_file_test". Not tested on OSX and MSwin. * testsuite/Makefile.am, testsuite/test_file_test.pro, src/file.cpp: initial import of "test_file_test.pro", symlink now well detected in FILE_TEST(). work by I. Natchkebia 2015-05-22 gilles-duvert * src/ofmt.cpp: pass new (complete?) format test test_formats.pro 2015-05-22 alaingdl * src/pro/xdisplayfile.pro: adding /editable keyword in "xdisplayfile.pro". unfortunately we cannot add new lines :( few others tests added. * src/pro/dialog_message.pro: having same messages in boxes if wxwidgets or zenity 2015-05-21 alaingdl * testsuite/formats.idl, testsuite/test_formats.pro: rewriting of "test_formats.pro", adding a positive case (+12), regenerating the reference "formats.idl" 2015-05-21 gilles-duvert * testsuite/test_binfmt.pro, src/ofmt.cpp: solves bug #646 * src/ofmt.cpp: solves regression reported in #650 2015-05-15 alaingdl * testsuite/test_null.pro: correcting details in TEST_NULL * testsuite/test_systime.pro: more tests case for SYSTIME, a bug was pending due to lack of tests. 2015-05-13 alaingdl * src/basic_fun_cl.cpp: dimensions and range for input parameters were not properly tested in SYSTIME() ... * src/basic_pro_jmg.cpp, src/basic_pro_jmg.hpp, src/envt.cpp, src/libinit_jmg.cpp: better message for (scalar or 1 element array) But we have cases where we got (e.g) : wait, ['-1.01','12'] % WAIT: Parameter must be a scalar or 1 element array in this context: instead : % WAIT: Expression must be a scalar or 1 element array in this context: . 2015-05-10 alaingdl * src/pro/file_lines.pro: at the end, managing Directories in FILE_LINES() ! 2015-05-09 gilles-duvert * src/objects.cpp: Patch by GJ to have #threads computation faster for windows * src/gtdhelper.cpp, src/basic_fun_cl.cpp: Patch by GJ to have SYSTIME(1) working in windows * src/file.cpp: typo: debug print line was always printed 2015-05-08 pjb7687 * src/basic_fun.cpp: Applied patch #85 (bugfix) by Jacco A. de Zwart. 2015-05-07 alaingdl * CMakeLists.txt: the message returned if REQUIRED is used instead of COMPONENTS is not clear 2015-05-04 pjb7687 * src/file.cpp: Reverted HIDDEN and SYSTEM in FILE_INFO, which makes GDL crash. 2015-05-03 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/widget.cpp: Better treatment of xpad,ypad and what widget_info(./geometry ) returns. Patch should avoid size events to be propagated if they are due to an internal (e.g., widget_control) resize. (XDisplayFile working) plus a few improvements. 2015-04-30 pjb7687 * src/pro/xdisplayfile.pro: Added xdisplayfile 2015-04-29 gilles-duvert * src/basic_pro.cpp, src/dcompiler.cpp, src/libinit.cpp: Patch by GJ: HELP, /FULL and HIDDEN compilation option of procedures/functions basic_pro.cpp - (help_pro re-arranged a bit; isHidden() and fullKW used) libinit.cpp - (keyword FULL to help_pro) dcompiler.cpp - (omit notification of compilation) 2015-04-24 gilles-duvert * src/gshhs.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_oplot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_xyouts.cpp: added map projection support for axis; minor changes in other plotting routines, although they could have side-effects (please report). note: 3D plots and projections not yet compatible; contour splitting and closing when a projection is present are not reliable (do not report!). 2015-04-23 gilles-duvert * src/plotting_map_proj.cpp: final (?) solution to protect GDL from projections that have no inverse (proj.4 or libproj have tons of them): permits MAP_SET to work on all projections, and calling MAP_PROJ_INVERSE or PROJ_INV will not crash gdl. Too bad there is no internal function in libproj to test the absence of inverse. We are going to avoid using this library. * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp: correction to appropriately treat size events for widget_draw 2015-04-22 pjb7687 * src/includefirst.hpp: Added WIN32_LEAN_AND_MEAN to suppress warnings and reduce compilation time on Windows. 2015-04-21 gilles-duvert * src/plotting_plots.cpp, src/plotting_polyfill.cpp: aligned plotting_plots and plotting_polyfill codes since they are almost equivalent, adding in passing clip/noclip support for polyfill and removing a plots bug. * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/widget.cpp: Now using dynamic Connect() methods for most widgets events. Use a two-step method with timer to trigger a resize event only when user has finished resizing a frame. 2015-04-20 gilles-duvert * src/plotting_polyfill.cpp: polyfill was testing wrongly the Z variable size in the absence of a T3D keyword. 2015-04-17 gilles-duvert * src/plotting_map_proj.cpp: found a better place to protect GDL from projections that have no inverse in proj.4: permits MAP_SET to work on all projections, but MAP_PROJ_INVERSE throws an exception if the inverse function is not defined (*P->inv=0) in the proj.4 library. 2015-04-16 gilles-duvert * src/plotting_map_proj.cpp: protect against two projections that have no inverse in proj.4 (was killing GDL). 2015-04-16 pjb7687 * src/file.cpp: Greg's patch for file_search on Windows #2. 2015-04-15 gilles-duvert * src/gdlwidget.cpp: reverted to 1.91 version, 1.92 was crashing (under linux at least) 2015-04-15 pjb7687 * src/gdlwidget.cpp: Moved initialization code of theGDLApp to GDLWidget::Init(). Removed wxInitialize() and wxUninitialize(). * src/dstructgdl.hpp: Patch for clang++. * src/file.cpp: File.cpp patch by Greg Jung (Reverted the old filesearch/Patternsearch procedure). * CMakeLists.txt: Added compliation flag for Eigen3 on Windows (MinGW). Removed PDCurses dependency. 2015-04-14 gilles-duvert * src/pro/handle_create.pro, src/pro/handle_free.pro, src/pro/handle_info.pro, src/pro/handle_value.pro: Handle_*** pro files are here to mimic at lowest price old functions not supported anymore in IDL, but present in some old codes (cmsvlibn ps_form used by atv...) * src/pro/widget_message.pro: widget_message is just an old name of dialog_message. this file passes the arguments to dialog_message. * src/gdlwidget.cpp: gdl was writing a superfluous "end of line" in (multi-line) text widgets (ugly character in some implementation). 2015-04-14 alaingdl * src/objects.cpp: interverting 2 lines in "object.cpp" should solve a "widget" bug in Debin/Ubuntu OS 2015-04-13 gilles-duvert * src/gdlzstream.cpp: corrected bug #638 2015-04-13 pjb7687 * src/gdlwinstream.cpp: Return 'false' when user close plot window while CURSOR is active. * src/gdlwinstream.hpp, src/gdlwinstream.cpp: This solves Plplot window hang issue while CURSOR is active, when wxWidgets is not compiled with GDL. 2015-04-12 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/widget.cpp: UNITS keyword now correctly taken into account in widget creation and in WIDGET_CONTROL and WIDGET_INFO. Columns and Rows sizes of TABLE widget OK now. * src/devicewx.hpp: cosmetic changes * src/gdlwidgeteventhandler.cpp: wxFrame size event handling freezes some implementations. removed for the moment. 2015-04-12 pjb7687 * src/devicewin.cpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp: Patch to CURSOR on Windows. GDL does not hang anymore while clicking on another plot window. * src/gdlwidget.cpp: Changed set_value to always add newline (which is IDL's behavior). Also added code for proper handling of line ending on Windows (works with wx3.0 and above). * src/dialog.cpp: Added missing semicolon. * src/libinit.cpp: Correction of wrong definition of libinit_jp. 2015-04-11 pjb7687 * src/initsysvar.cpp, src/semshm.cpp: TCHAR -> WCHAR to compile non-unicode build of GDL. * src/basic_pro.cpp: Removed redundant tchar.h. * src/basic_pro.cpp, src/deviceps.hpp, src/basic_fun.cpp, src/basic_pro_jmg.cpp: TCHAR -> WCHAR to compile non-unicode build of GDL. * src/file.cpp: MSVC patch, and excluded checking of X_OK on Windows 2015-04-11 alaingdl * src/file.cpp, src/libinit.cpp: patch by Greg J. for file.cpp including several new TEST_ keywords. 2015-04-11 pjb7687 * src/dinterpreter.cpp: This patch removes trailing '\n' during no-readline mode. 2015-04-10 pjb7687 * src/dinterpreter.cpp: Changed to get the last char with brackets. Also added usleep for POSIX. * src/dinterpreter.cpp: Corrected wrong ifdef block. * src/gdl.cpp: Added an option for upcoming IDE. * src/dinterpreter.cpp: Changed DInterpreter::NoReadline() to properly handle events (using c++11 thread or pthread). 2015-04-09 gilles-duvert * testsuite/demo_widgets.pro: bug correction. 2015-04-09 pjb7687 * src/gdlwidget.hpp: Added missing if block. * src/gdlwidget.cpp, src/gdlwidget.hpp: Moved GDLApp initialization code before the events sending part. Alternative removing method is implemented for 'children' and 'followers'. * src/file.cpp: Added code to let MSVC check the fils is executable or not properly. * src/gdl.cpp: Changes due to Windows don't have set/getrlimits. 2015-04-08 alaingdl * src/pro/dialog_message.pro: explicitly splitting DIALOG_MESSAGE in two functions: DIALOG_MESSAGE_ZENITY and DIALOG_MESSAGE_WXWIDGETS * src/dialog.cpp: in DIALOG_PICKFILE(), in the WX version, when the path is not provided, we should work in current directory. But recent Gnome/Wx is using by default the previous path is no path provided ... (but case " DIALOG_PICKFILE(path='..')" and "FILE_SEARCH('..',/full)" are not working well now) * src/pro/dialog_pickfile.pro: in order to be able to run the Zenity-based version (e.g. regression tests), splitting DIALOG_PICKFILE in two: DIALOG_PICKFILE_WXWIDGETS and DIALOG_PICKFILE_ZENITY 2015-04-08 gilles-duvert * src/gdlwidget.cpp: bug correction. * src/gdl.cpp: added routine to augment stack size (at least up to the needs of the test_dicom procedure). Thanks to OP and discussion #338693. * src/dialog.cpp: DIALOG_MESSAGE_WXWIDGETS now accepts array of strings. * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/widget.cpp: Added WIDGET_INFO /REALIZED. 2015-04-07 alaingdl * src/file.cpp, src/libinit.cpp: adding 3 keywords to FILE_SEARCH: TEST_DIRECTORY, TEST_REGULAR and TEST_EXECUTABLE. Not sure /test_exe is OK. May be the code could be factorized ?! 2015-04-07 gilles-duvert * src/plotting.cpp, src/plotting.hpp, src/plotting_oplot.cpp, src/plotting_plots.cpp, src/plotting_xyouts.cpp, src/plotting_plot.cpp: solves bug #639 and a few unreported others... Removed templating of a few graphic functions since we accept only doubles. * testsuite/test_map.pro: noted a potential problem. * src/basic_pro.cpp: prevent throw on not-found files 2015-04-07 pjb7687 * src/dialog.cpp: Added code to support wx2.8, which does not have wxCANCEL_DEFAULT. 2015-04-07 alaingdl * CMakeLists.txt: desactivating a test for wxwidgets in plplot, not working widely now. 2015-04-07 pjb7687 * src/dialog.cpp, src/dialog.hpp: Added conversion code for all strings, assuming that all strings are encoded in UTF-8. 2015-04-06 pjb7687 * src/pro/polywarp.pro: Corrected typos 2015-04-05 gilles-duvert * src/plotting.cpp: added protection against invalid POSITION kw values. 2015-04-05 pjb7687 * src/pro/dialog_message.pro, src/pro/dialog_pickfile.pro: Added "on_error, 2". * src/pro/polywarp.pro: Added POLYWARP. * src/dialog.cpp, src/dialog.hpp, src/libinit_jp.cpp, src/pro/dialog_message.pro: New implenentation with wxWidgets is added. * src/pro/dialog_pickfile.pro: Corrected a typo * src/gdlwinstream.cpp: Bug fix on GetHwnd() 2015-04-04 pjb7687 * src/gdlwinstream.cpp: Manually destoy window when GDLWinstream is deleted. * src/file.cpp: Modified PatternSearch() to use proper path seperator. * src/libinit_jp.cpp, src/CMakeLists.txt, src/dialog.cpp, src/dialog.hpp, src/libinit.cpp: Added new implementaion of DIALOG_PICKFILE using wxWidgets. * testsuite/CMakeLists.txt: Added support for MSVC * src/pro/dialog_pickfile.pro: New implenentation with wxWidgets is added. * src/file.cpp: Updated FILE_DIRNAME, like IDL's behavior. 2015-04-04 gilles-duvert * README: update section on widgets * testsuite/demo_widgets.pro: removed test_widgets.pro and added demo_widgets.pro 2015-04-04 alaingdl * CMakeLists.txt: hope to have smater message * CMakeLists.txt: this one seems to be a better test ! (if plplot compiled with wxwidgets !) 2015-04-04 pjb7687 * src/basic_fun.cpp: Removed _UNICODE blocks. * src/basic_pro_jmg.cpp, src/libinit.cpp, src/basic_pro.cpp: Removed _UNICODE blocks. Also added new 'wait' implementation on Windows (need test). * src/gdlwinstream.cpp: Removed redundant HBITMAP 2015-04-03 gilles-duvert * src/pro/xmanager.pro, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/objects.cpp, src/widget.cpp: last batch of widget support --- almost complete now. * src/initsysvar.cpp: for some scripts we need to pretend to be better than 6.4 (and we are!) 2015-04-03 pjb7687 * src/pro/write_tiff.pro: Naive implementation of write_tiff * src/devicewin.cpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp: Improved redraw code 2015-04-03 alaingdl * CMakeLists.txt: 2 typos found * CMakeLists.txt: various changes : test if plplot is ON for wxwidgets, order of IM/GM tests 2015-04-03 pjb7687 * CMakeLists.txt: Changed CMake to link libgomp and libpthread, instead vcomp, with MinGW. 2015-04-02 pjb7687 * src/devicewin.cpp, src/devicewin.hpp: Put whole file into #ifdef _WIN32 block. 2015-04-02 alaingdl * CMakeLists.txt: better message when wXwidgets devel is not available. 2015-04-02 pjb7687 * src/file.cpp: Removed _UNICODE. Small correction on FILE_SERACH on Windows. * src/devicewin.cpp, src/devicewin.hpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp: Autoredraw TV image. Corrected several miswritten parts on PaintImage. More corrections are needed. 2015-04-01 pjb7687 * src/gdlwinstream.cpp: Removed debug purpose cout. * src/gdlwinstream.cpp: GIN now accepts mouse click events only in active window. Also paintimage will draw image with proper offset. * src/devicewin.cpp: Do not process event if no window opened. * src/devicewin.cpp: Rewrote code for setting intitial window size, using plplot intenal functions. * src/gdlwinstream.cpp: Changed color code to be unsigned char. * src/devicewin.cpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp: Removed 'resizing' code, which is duplicate with the original (in devicewin.cpp). Instead, set proper MaxSizes. Added code to set window title manually on Windows. 2015-03-31 pjb7687 * src/devicewin.cpp, src/devicewin.hpp: Tab correction * src/devicewin.cpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp: Moved resize / move code to WOpen. * src/gdlwinstream.cpp, src/gdlwinstream.hpp: Moved cursor data to gdlwinstream.cpp, in order to support MSVC. * src/default_io.cpp: A small patch for the last commit * src/gdlwinstream.cpp, src/gdlwinstream.hpp: Tab correction * src/gdlwinstream.cpp, src/gdlwinstream.hpp: Resize/repositions window after drawing image. Calculates more accurate cursor position using proper WINAPIs. Minor cursor correction (cosmetic). * src/gdlwinstream.cpp, src/gdlwinstream.hpp: Updated crosshair cursor to be more like as IDL's one. Also removed ClipCursor, which makes wrong behavior. 2015-03-30 pjb7687 * src/gdlwinstream.cpp: Removed redundant HDC. * src/gdlwinstream.cpp: Faster TV using GetDIBits and SetDIBitsToDevice. * src/plotting_windows.cpp: Initialize 'retainType' to be a proper value (=0) before using it. * src/basic_pro.cpp: On Windows, openr, openw, and openu now open file in binary mode. 2015-03-29 pjb7687 * src/str.cpp: std::toupper and std:: tolower -> toupper and tolower for Visual Studio * src/includefirst.hpp: Disable error C4716 (function must return a value) for Visual Studio * src/file.cpp: Enabled commented part of lib::file_readlink() * src/basic_pro.cpp, src/basic_pro.hpp: Tab correction 2015-03-28 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/objects.cpp, src/widget.cpp: improving widget_tree. 2015-03-27 gilles-duvert * src/ofmt.cpp: lots of change to exactly replicate (all?) the b,o,z,Z,i formatting. solves bug 634. Possible side-effects for windows port, to be tested. * testsuite/Makefile.am, testsuite/formats.idl, testsuite/test_formats.pro: added test_formats that test at once quite a large number of format pitfalls... * src/file.hpp: added necessary definition of new file_readlink function to permit compilation ;^) 2015-03-27 pjb7687 * src/file.cpp: Applied Greg Jung's 'small fix' (2015 Feb 02) * src/libinit.cpp: Merging Greg Jung's patch (2015 Jan 28) regarding FILE_SEARCH on Windows, and FILE_READLINK. * src/file.cpp: Merging Greg Jung's patch (2015 Jan 28) regarding FILE_SEARCH on Windows, and FILE_READLINK. (except the TEST keywords of FILE_SEARCH, because some part of the code conflicts with the current CVS.) 2015-03-26 pjb7687 * src/gdlwidget.cpp: Explicit cast of null pointer to (GDLWidgetBase*) * src/devicewin.hpp: Comment out DeviceWIN::WAddFree() which is not implemented yet. 2015-03-25 gilles-duvert * src/gsl_matrix.cpp: patched bug #636 * src/widget.cpp: removed unwanted reference to wx2.8/popupwin.h 2015-03-25 pjb7687 * src/devicewin.hpp: Added missing declaration of member function DeviceWIN::WAdd(). * src/file.cpp: Removing S_ISLNK check on Windows. Also fixes bugs on Windows part pattern matching (the original code tries to match two empty array, instead of actual contents). 2015-03-25 gilles-duvert * src/gdlwidget.cpp: bug correction 2015-03-25 pjb7687 * testsuite/CMakeLists.txt: Testsuite patch for Windows 2015-03-25 gilles-duvert * src/pro/Makefile.am: updated to most recent list of procedures. * src/pro/cw_bgroup.pro: incompatible with current widget support (only idl's cw_bgroup works). temporarily removed to avoid problems. * src/default_io.cpp, testsuite/Makefile.am, testsuite/idl.xdr, testsuite/test_xdr.pro: fixed all XDR and compressed XDR I/O problems (on linux, that is). reads and writes all types of values, structs etc maintaining compatibility with IDL xdr files. Added test_xdr in testsuite and in make check. 2015-03-23 gilles-duvert * testsuite/test_bug_635.f90, testsuite/test_bug_635.pro, testsuite/test_bug_635.dat: added test_bug_635 and related data. Test reading of structs in unformatted fortran data. Not inserted in 'make check' suite, however. * src/pro/unxregister.pro: important widget-related procedure to siletly remove a widget in the list of managed widgets. * src/basic_pro.cpp, src/dstructgdl.hpp: handles gracefully structures for unformatted fortran IO 2015-03-22 gilles-duvert * src/basic_pro.cpp: solves bug in readu when reading structs (byte length of struct is not sum of size of elements, due to, e.g., alignment padding) * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/widget.cpp, src/widget.hpp: widgets: added support for context_events and popups. 2015-03-20 gilles-duvert * src/CMakeLists.txt, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/objects.cpp, src/widget.cpp: widgets: removed gdlwidgetdraw.cpp (merged in gdlwidget.cpp). GROUP_LEADER OK. WIDGET_TREE partially written. Bugs corrections, etc. * src/devicewx.hpp: slightly better version of a pure wxWidgets 'X' device (to be continued, yet incompatible with pure X11 support). 2015-03-16 gilles-duvert * src/gdlxstream.cpp, src/gdlxstream.hpp: Better patch to speedup plots on X11 in decomposed=1 (practically the default for all displays). Will benefit only simple (line) plots, not filled contours. Goes around the limitation of plplot that handle truecolor or static displays as if they had only 256 colors available... 2015-03-14 gilles-duvert * src/hdf_fun.cpp, src/hdf_fun.hpp, src/libinit_jmg.cpp: added hdf_ishdf * src/hdf5_fun.cpp: h5f_is_hdf5 should not give error message. 2015-03-12 gilles-duvert * src/devicex.hpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp: patch (to be tested) to speedup plots on X11. 2015-03-11 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/widget.cpp: more widget_control options. removed some code clashing with old versions of wxWidgets. * src/graphicsdevice.hpp: more compliant with fussy compilers * src/image.cpp: cosmetic changes 2015-03-10 alaingdl * testsuite/test_moment.pro: because it seems that X11 output have been strongly slow down in "test_moment" since last year (june 2014), I separate the output display type. With set_plot, 'null' we can access to the computation time only. 2015-03-08 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/widget.cpp: added widget options delay_destroy, group_leader 2015-03-07 gilles-duvert * src/devicex.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/gdlwxstream.cpp, src/libinit_jmg.cpp, src/widget.cpp: much improved widget support. widget_table complete. * src/devicewx.hpp: cosmetic change * src/hdf5_fun.cpp: use now the true H5F_is_hdf5 * src/libinit.cpp: cosmetic changes for readability and robustness * src/objects.cpp: new structures for widget support * src/default_io.cpp, src/dstructgdl.hpp: added ToStreamRaw in default_io to help structure read/write in widget_table (and elsewhere, too) 2015-03-03 alaingdl * src/base64.hpp, src/basic_fun.cpp, src/gsl_fun.cpp, src/str.cpp: some extra std:: are needed to compile the CVS on OSX 9/10 with CLang 6 (std::tolower, std::toupper, std::isspace) * src/objects.cpp, src/basic_fun.cpp: preliminary version for SCOPE_TRACEBACK(/structure), but I did not find a way to provide the IS_FUNCTION information : help welcome ! 2015-03-02 alaingdl * src/basic_pro.cpp: adding HELP, /PATH, out=out * NEWS, src/basic_fun.cpp, src/basic_fun.hpp, src/libinit.cpp: initial import of SCOPE_TRACEBACK(), based on HELP, /traceback. /System and /Structure keywords are not ready. This feature was requested by Nika team (http://ipag.osug.fr/nika2/). 2015-02-25 alaingdl * src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/gdlwxstream.cpp, src/libinit_jmg.cpp, src/objects.cpp, src/widget.cpp, src/devicewx.hpp, src/devicex.hpp, src/gdlgstream.hpp, src/gdlwidget.cpp: Large modification for Widgets from G. Duvert. ATV is working fine for me ! 2015-02-24 alaingdl * src/image.hpp: this include is needed on some Ubuntu/Debian recent systems (not needed on Fedora ...) 2014-12-28 gilles-duvert * src/basic_pro.cpp, src/devicewin.cpp, src/devicewin.hpp, src/gdleventhandler.cpp, src/gdlsvgstream.cpp, src/gdlwinstream.cpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/initsysvar.cpp, src/plotting_windows.cpp: Last Windows version patches by Greg Jung * src/file.cpp, src/file.hpp, src/libinit.cpp: GDL now correctly detects symlinked directories and dangling symlinks. On unix-like systems, anyway. 2014-12-21 gilles-duvert * src/gdlwidget.cpp: explicit cast apparently needed by some compilers 2014-12-20 gilles-duvert * README: commented about the current widget status. * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/widget.cpp: Removed threading in widgets, resulting in stable performances and causality in crashes;^). Complex widgets are now possible (ex:atv.pro). Creation and destruction of widgets are OK. Table and Tree definitely need more work. * src/devicewin.hpp, src/devicewx.hpp, src/devicex.hpp, src/graphicsdevice.cpp, src/graphicsdevice.hpp, src/plotting_windows.cpp: reset number of windows to IDL value. Changed number of 'free' windows (window,/free). A temporary hack, renaming the "WX" device in "MAC", permits to avoid failing a test in coyotegraphics library. "WX", the wxWidgets X-like device should ultimately replace the 'X' device anyway. * src/pro/xmanager.pro: catch a possible error 2014-12-03 alaingdl * NEWS, doc/www/_news.inc.php: updating NEWS file. * src/initsysvar.cpp: adding new sys. var. !TRUE and !FALSE * src/basic_pro.cpp: temporary patch in HELP,/path when the !path is badbly formated. If a path is several times in !path is not managed now. HELP, /path, output=res is also not ready. * src/basic_fun_jmg.cpp, src/libinit_jmg.cpp: in ISA(), adding new keywords : BOOLEAN,INTEGER,FLOAT,COMPLEX,STRING 2014-11-27 gilles-duvert * src/image.cpp: insure that tvrd always returns data with correct (unPurged) dimensions. * src/datatypes.cpp: reset dim.Purge() in array constructors (was a very bad idea to remove them...) 2014-11-24 gilles-duvert * testsuite/test_widgets.pro: added several new events * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/widget.cpp: much improved widget support with all basic facilities present. Needs further work on thread safety and screen updating of widgets. * src/pro/cw_bgroup.pro, src/pro/xmanager.pro: corrected bug * src/objects.cpp: added new structures for widget events * src/plotting.cpp: cosmetic changes to improve readability * src/plotting_cursor.cpp: no message * src/magick_cl.cpp: use PaletteType instead of magic numbers * src/plotting_misc.cpp: correct behaviour of tvlct * src/plotting_device.cpp, src/plotting_windows.cpp, src/libinit.cpp: support for DEVICE,/COPY. * src/image.cpp, src/image.hpp: removed all instances of TVRD, added DEVICE,/COPY and factorized code for tv(), tvrd(). * src/graphicsdevice.cpp, src/graphicsdevice.hpp: support for DEVICE,/COPY. * src/gdlzstream.hpp, src/gdlzstream.cpp: removed all instances of TVRD, added DEVICE,/COPY and factorized code for tv(), tvrd(). * src/gdlxstream.cpp, src/gdlxstream.hpp: removed all instances of TVRD, added DEVICE,/COPY and factorized code for tv(), tvrd(). Support for WINDOW,/PIXMAP * src/gdlwxstream.cpp, src/gdlwxstream.hpp: removed all instances of TVRD, added DEVICE,/COPY and factorized code for tv(), tvrd(). * src/gdlgstream.hpp, src/gdlgstream.cpp: removed all instances of TVRD, added DEVICE,/COPY and factorized code. Also, trick silly plplot driver to keep fontsize constant whatever the page size. * src/dinterpreter.cpp: patch to have ".s" equivalent to ".step" * src/devicex.hpp, src/devicez.hpp, src/devicewx.hpp: removed all instances of TVRD, added DEVICE,/COPY and factorized code. * src/deviceps.hpp: trick silly plplot driver to keep fontsize constant whatever the page size. * src/datatypes.cpp: removed dim.Purge() in array constructors, since they conflict with several behaviours (like in tvrd). purge of superflous dimensions should be done case-by-case. *This patch may have unwanted effect elsewhere* * src/basic_fun.cpp: setting !err to the number of elements of "where" (compatibility with old *DL versions, not doing that creates unexpected problems with old procedures that still use !err). 2014-10-23 gilles-duvert * src/plotting_convert_coord.cpp: insure coordinate system type are initialised to some default value. 2014-10-13 alaingdl * doc/www/_news.inc.php: news in GDL web page * doc/www/_news.inc.php: 0.9.5 ! 2014-10-12 gilles-duvert * testsuite/test_widgets.pro, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/objects.cpp, src/pro/xmanager.pro, src/widget.cpp, src/basic_pro.cpp, src/gdlwidget.cpp, src/gdlwidgetdraw.cpp, src/pro/xregistered.pro: improvements in widgets. see test_widgets.pro as example. 2014-10-11 pjb7687 * CMakeModules/FindXportmingw.cmake, testsuite/CMakeLists.txt, CMakeLists.txt, config.h.cmake: Preliminary Xlib support for Win32 * src/smooth.cpp: To resolve MSVC's error C2668 2014-10-10 opoplawski * CMakeLists.txt: Fix Fedora hdf5-devel package name. 2014-10-07 m_schellens * CMakeLists.txt, ChangeLog: 0.9.5 release 2014-10-07 gilles-duvert * src/math_fun_jmg.cpp: simplified finite_helper since BaseGDL::ZERO works now. * src/initsysvar.cpp: Patched f_nan and d_nan to use the facility of the #NAN macro, see bug #621. Also, !error is not readonly at least from 6.4 2014-10-02 gilles-duvert * src/basic_fun.cpp, src/basic_fun.hpp, src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: Added scope_level (works) and pref_set (dummy procedure). * testsuite/test_postscript.pro: update to reflect our progress in compatibility. PostScript Image is correctly scaled at the size of the DATA coordinates. 2014-10-02 alaingdl * src/file.cpp, src/initsysvar.cpp: reverting change in expansion of GDL_PATH. Order in the GDL_PATH is again enforced. GDL 0.9.5: 2014-10-02 gilles-duvert * src/basic_fun.cpp, src/basic_fun.hpp, src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: Added scope_level (works) and pref_set (dummy procedure). * testsuite/test_postscript.pro: update to reflect our progress in compatibility. PostScript Image is correctly scaled at the size of the DATA coordinates. 2014-10-02 alaingdl * src/file.cpp, src/initsysvar.cpp: reverting change in expansion of GDL_PATH. Order in the GDL_PATH is again enforced. 2014-10-01 gilles-duvert * src/gdlwidgeteventhandler.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlwidget.hpp: changes to avoid using too recent wxWidgets features. Compiles with wxWidgets 2.8.12 and onwards, not necessarily with all functionalities though. 2014-09-29 gilles-duvert * src/widget.cpp: array of structs support for WIDGET_INFO, /GEOMETRY. * src/widget.cpp: improved widget_info default behaviour * src/plotting_contour.cpp: GJ avoided plplot bug when 1 level only * src/devicewin.cpp, src/devicewin.hpp, src/dinterpreter.cpp, src/gdlgstream.hpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp, src/initsysvar.cpp, src/libinit.cpp, src/basic_pro.cpp: Commited last changes by Greg Jung 2014-09-26 gilles-duvert * src/plotting.cpp, src/plotting_device.cpp, src/plotting_map_proj.cpp, src/plotting_misc.cpp: Accepts silently undefined Keywords * src/plotting_windows.cpp: replaced numerical positioning by keyword * src/plotting_contour.cpp: Accepts silently undefined Keywords * src/pro/smooth.pro: Bugs corrected (only 1D smoothing was made). Simpler and faster since /NAN and MISSING have been implemented in CONVOL. Also, permits dimensions 1 in smooth kernel, as IDL does (permits smoothing truecolor images [3,nx,ny] for example). * src/convol.cpp: protected CONVOL from undefined Keywords using KeywordSet function 2014-09-25 gilles-duvert * src/devicewx.hpp, src/devicex.hpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/image.cpp: removed references to free_mem, a private plplotP.h shortcut. * src/gdlsvgstream.cpp: Commited last changes by Greg Jung * src/devicex.hpp, src/devicewx.hpp: removed SetFocus, uneeded and confusing. * src/devicewin.cpp, src/devicewin.hpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp, src/CMakeLists.txt, src/basic_pro.cpp: Commited last changes by Greg Jung * src/gdlgstream.hpp: removed SetFocus, uneeded and confusing. * src/gtdhelper.cpp, src/gtdhelper.hpp, src/includefirst.hpp: Commited last changes by Greg Jung * src/gdlxstream.cpp, src/gdlxstream.hpp: removed SetFocus, uneeded and confusing. 2014-09-24 pjb7687 * src/devicewin.cpp: Corrected a small bug 2014-09-23 gilles-duvert * src/devicewin.cpp, src/devicewx.hpp, src/devicex.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/graphicsdevice.cpp, src/plotting_device.cpp: full set of devices (X, WX, WIN) and widgets now seem to get along almost nicely. * src/graphicsdevice.hpp: provided reasonable default values to some virtual methods. * src/plotting_misc.cpp: restored correct behaviour for GET_SCREENSIZE function. * src/plotting_windows.cpp: transferred GDL_GR_WIN_XXXXX environment variable detection to device Win * src/smooth.cpp, src/deviceps.hpp: use alloca() only for MSC_VER (Windows compiler) 2014-09-22 alaingdl * src/image.cpp: missing #ifdef for systemes without wxwidgets 2014-09-22 pjb7687 * src/image.cpp: Call GetImage() only with wxwidgets. * src/gdlgstream.cpp: Put alloca() into #ifdef block 2014-09-21 pjb7687 * src/gdlgstream.hpp: Changes on casting of pointer values * src/devicewx.hpp, src/devicex.hpp, src/gdlgstream.hpp: Resolved maxWin constants confliction. 2014-09-21 gilles-duvert * src/gdlwidgeteventhandler.cpp: patch use of wxString vs. std::string * src/devicex.hpp: removed old comments. Lets try plplot with threaded X11 windows. * src/gdlwxstream.hpp, src/image.cpp: Changes making coyotelib somewhat happy. * src/gdlwidgeteventhandler.cpp, src/libinit_jmg.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp: Modified BUTTON to have correct nested menus (option /MENU of WIDGET_BUTTON). Droplist and Combobox are two separate objects (different info structures). Plus a lot of minor improvements: coyotegraphics windows are operational now. Still problems with threads: spurious crashes in live update of button widgets. * src/pro/xmanager.pro: added CLEANUP, but it is a fake, needs KILL_NOTIFY to be written. Permits to have coyotegraphics running in a fashion. * src/gdlwxstream.cpp: added necessary functions (crudely) to get wX canvases behave equally toX windows. * src/gdlgstream.hpp: temporary patch before aligning TVRD on TV. * src/objects.cpp: Added struct WIDGET_GEOMETRY 2014-09-21 pjb7687 * src/plplot_wxwidgets.h, src/CMakeLists.txt, src/basic_pro.cpp, src/deviceps.hpp, src/devicewin.cpp, src/devicewin.hpp, src/devicewx.hpp, src/devicex.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlxstream.cpp, src/graphicsdevice.cpp, src/gtdhelper.cpp, src/gtdhelper.hpp, src/includefirst.hpp, src/initct.cpp, src/initsysvar.cpp, src/io.hpp, src/objects.cpp, src/plotting.cpp, src/plotting_misc.cpp, src/plotting_windows.cpp, src/smooth.cpp, src/str.cpp, src/terminfo.cpp: 1. Greg's Win32 patch, slightly modified to fit with the current CVS. It also contains windows focusing related patches on devicex.hpp and gdlxstream.cpp. 2. C99 compliant patch, substituted definitions of variable length arrays with using alloca(). 3. Preliminary WX implementations. Not available yet. 4. Resolved winsock2.h and windows.h order issue. To use sockets, include includefirst.hpp. 2014-09-19 gilles-duvert * CMakeLists.txt: removed finding gshhsdir (since now copy of gshhs.h is in src). Changed way to discriminate whether plplot version uses c_plwidth or not (problem with clang compiler) * src/gshhs.cpp: Restored initial gsshs.h file, with the minimum change (POINT-> GSHHS_POINT) to solve compilation on Windows while preserving all the other usual names. Reverted changes in gsshs.cpp to the minimum set of changes acceptable. * src/gshhs.h: Restored initial gsshs.h file, with the minimum change (POINT-> GSHHS_POINT) to solve compilation on Windows while preserving all the other usual names. 2014-09-19 pjb7687 * src/gshhs.h, src/basic_pro.cpp, src/gdlsvgstream.cpp, src/gshhg.h, src/gshhs.cpp: 1. Better mbcs/unicode support in basic_pro.cpp 2. Win32 altanative implementation without mkstemp in gdlsvgstream.cpp 3. Removing gshhs.h and adding gshhg.h to avoid confliction between POINT struct using in Windows API 2014-09-18 alaingdl * src/basic_pro.cpp: in HELP, when only one param, if it is a structure, details are shown. 2014-09-17 gilles-duvert * testsuite/test_widgets.pro: bug correction. * src/gdlwidget.hpp, src/gdlwidget.cpp: correct get_value for buttons, use of UpdateValue in texts, more thread-aware(?). * testsuite/test_widgets.pro: updated version showing scrolled widgets and widget interaction. And bugs, too^(( 2014-09-17 alaingdl * src/gdlwidget.hpp: here, we need to have a convertion into wxString to be able to compile ... 2014-09-17 gilles-duvert * src/gdlwidget.hpp: replaced SetLabelText by SetLabel for wxButton (correct documented way to update the button's text) 2014-09-16 gilles-duvert * src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/widget.cpp: Patches on a few bugs related to get_value and get_uvalue. Timid support of scrolled windows. Patched use of null col= and row= options 2014-09-16 alaingdl * src/basic_pro.cpp, src/file.cpp: corrections in patch from Greg J., related to MSwin port. * src/basegdl.hpp, src/file.cpp, src/initsysvar.cpp, src/libinit.cpp, src/str.cpp: applying patch from Greg, one important point is the ":" vs ";" dir. separator 2014-09-13 m_schellens * src/dcompiler.cpp: better error message for COMMON * src/dcompiler.cpp: fixed bug 625 (crash_common) 2014-09-12 alaingdl * src/basic_pro.cpp: finishing the outputs for Common in HELP. * src/basic_pro.cpp, src/dpro.cpp, src/envt.cpp: Finishing visibility of Var. declared by Common in HELP. Undefined (normal) variables are now also visible. * src/dpro.cpp, src/dpro.hpp: preparing being able to correctly print in HELP Variables defined through Common (e.g. common c, var & HELP, var --> "VAR (common_name) int = 2") 2014-09-12 gilles-duvert * src/gdlgstream.hpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlxstream.hpp: path to support cursor management in other devices than pure X11 * src/plotting_windows.cpp: changes in focus management 2014-09-11 alaingdl * testsuite/test_isa.pro, testsuite/test_levels.pro: initial import for "test_levels.pro", simple way to test HELP,/traceback and also the expected values for lines in code ... * src/basic_pro.cpp, src/libinit.cpp, src/str.cpp: 2 main changes : full realpath to routines files names are now always used (no more relative paths); HELP, /traceback 2014-09-11 gilles-duvert * src/plotting_cursor.cpp: correct behaviour of tvcrs(). 2014-09-10 alaingdl * src/basic_pro.cpp, src/gtdhelper.hpp, src/initsysvar.cpp, src/objects.cpp, src/semshm.cpp, src/terminfo.cpp: at the end, including the mingw patch from Greg. Sorry for delay. This code compiles on GNU/Linux. Test suite OK. Please check ! 2014-09-09 gilles-duvert * src/gdlwinstream.cpp: missing definitions * src/gdlwinstream.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlxstream.cpp, src/gdlzstream.cpp: replaced private method plP_esc by public method plcmd, removing dependency from plplotP.h *After this change a complete rebuild from scratch (rm CMakeCache.txt; make) is mandatory* * src/plotting_contour.cpp: added comment. 2014-09-08 gilles-duvert * src/plotting_windows.cpp: moved get_screen_size to plotting_misc + patches by GJ * src/plotting_misc.cpp: get_screen_size() general function now defined here * src/plotting_device.cpp: use device-dependent GetScreenSize() object property. * src/graphicsdevice.hpp: define GetScreenResolution object property. * src/gdlzstream.cpp: removed superfluous code and inclusion of private plplot include (last patch). to be tested. * src/gdlxstream.hpp: relocate plwxd dependency here * src/gdlwinstream.cpp, src/gdlwinstream.hpp: inserted Win patches proposed by GJ. Aligned to new PaintImage function. * src/gdlgstream.hpp: inserted Win patches proposed by GJ * src/devicex.hpp: new GetScreenResolution/GetScreenSize * src/devicewin.hpp: inserted Win patches proposed by GJ * src/gdlwidget.cpp, src/gdlwidgeteventhandler.cpp: removed superfluous devicex dependency * src/graphicsdevice.cpp, src/objects.cpp: moved X11 dependent code from objects.cpp to graphicsdevice.cpp where it belongs. * src/libinit.cpp: changes in function get_screen_size() * src/gdlwxstream.cpp, src/gdlxstream.cpp: removed superfluous tests * src/gdlgstream.cpp: corrected invalid useage of 'True'. 2014-09-08 alaingdl * src/gdlzstream.cpp: mandatory include to compiled without wxwidget ... not clear why it is OK when wxw is here ... 2014-09-06 gilles-duvert * src/devicez.hpp: finalized TV() for Z buffer * src/libinit.cpp: added a bunch of (unused by gdl yet) kw for device, with warning. 2014-09-05 gilles-duvert * src/devicez.hpp, src/gdlzstream.cpp, src/gdlzstream.hpp: Support of TV for Z-Buffer (almost OK) * src/image.cpp, src/image.hpp: removed unused functions * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp: removed unused function * src/plotting_image.cpp: bug correction: dimension mismatch was possible in some cases if a truecolor image was given without the /TRUE switch. 2014-09-05 alaingdl * src/smooth.hpp, src/smooth.cpp, src/CMakeLists.txt, src/Makefile.am, src/libinit_ac.cpp: initial import of 2 codes for (future) SMOOTH, to be carefully test. * src/gsl_fun.cpp, src/libinit_gm.cpp, src/math_fun_gm.cpp: finishing METHOD= keyword in IGAMMA(); ITER, ITMAX, EPS moved as WarnKey; cleaning few KeywordPresent()/KeywordSet() in "gsl_fun.cpp". 2014-09-04 gilles-duvert * src/gdlxstream.cpp: focus should stay on terminal when a X window is opened. 2014-09-04 m_schellens * src/envt.cpp: fixed EnvT::KeywordPresent( string) 2014-09-04 gilles-duvert * src/devicex.hpp: align GuiOpen with WOpen, commented unused code. * src/gdlwxstream.hpp, src/gdlwxstream.cpp: added method GetWindowDepth() to wxwidgets stream otherwise decomposed=1 does not work 2014-09-04 alaingdl * src/math_fun_gm.cpp: adding return values in METHOD keyword for IGAMMA() 2014-09-04 gilles-duvert * src/devicex.hpp, src/gdlsvgstream.cpp: better syntax thanks to clang compiler warnings 2014-09-03 gilles-duvert * src/devicex.hpp, src/gdlgstream.cpp: setting correct values for !D.N_COLORS and !P.COLOR provides better handling of colors in all outputs. * src/gdlpsstream.cpp, src/gdlsvgstream.cpp: commited Orion's patch proposed in bug 620 2014-09-02 gilles-duvert * src/libinit_jmg.cpp: updated a few KW for WIDGET_ * testsuite/demo_graphics2.pro, testsuite/demo_graphics3.pro: removed initial setup of device X for easy use with other devices. * src/devicex.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_erase.cpp, src/plotting_misc.cpp, src/plotting_shade_surf.cpp, src/plotting_xyouts.cpp: Changed color handling. Should improve plotting speed on decomposed=0 displays by a large factor. Hardcopies (PS, SVG) color accurate. see testsuite/demo_graphics*.pro. Tests welcome. * src/gdlsvgstream.hpp: trick to perhaps circumvent a libpng 'feature'. * src/gdlsvgstream.cpp, src/gdlsvgstream.hpp: hopefully correct use of USE_PNGLIB and png.h include file. * src/devicex.hpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/graphicsdevice.hpp, src/plotting_device.cpp, src/plotting_windows.cpp: solves bug #618 2014-09-02 alaingdl * src/plotting_axis.cpp, src/plotting_plot.cpp: adding [xyz]TYPE keywords to PLOT and AXIS * src/plotting_plot.cpp: adding xtype and ytype to PLOT (and PLOT_IO/OI/OO). * src/plotting_contour.cpp: adding xtype and ytype (no ztype) to CONTOUR. * src/libinit.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp: [xyz]type keywords still exist in SURFACE and SHADE_SURF. They are "stronger" than [xyz]log keywords. Cleaning in "libinit.cpp" since now we used keywords names instead keyword number. * src/plotting_windows.cpp: in "plotting_windows.cpp", purging last keywords called by numbers (dangerous if order changed) 2014-09-01 alaingdl * src/libinit_gm.cpp: adding 2 undocumented functions : NR_GAMMA et IDL_IGAMMA. Some cleaning are still necessairy in IGAMMA keywords (e.g iter not return, method not set ...) * src/gdlsvgstream.cpp: I need to add this line to be able to compile on Debian & Ubuntu OS, following https://bugs.launchpad.net/ubuntu/+source/libpng/+bug/218409 * CMakeLists.txt: patch 78 related to change in CMake 3.0 2014-09-01 gilles-duvert * src/devicesvg.hpp: svg device improvements * src/gdlgstream.hpp: corrected typo in definition of constant value. 2014-08-31 gilles-duvert * CMakeLists.txt: corrected typos for detection of libpng 2014-08-30 gilles-duvert * CMakeLists.txt, config.h.cmake: Should detect the presence of the libpng library (needed to activate the support of images (TV command) for SVG device. * src/gdlsvgstream.cpp, src/gdlsvgstream.hpp: Support of TV (images) in SVG device. Needs the presence of the libpng library to be activated. * src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_plot.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp: Use of Width(). Better support of CHARTHICK in graphic functions. Support of C_CHARTHICK in CONTOUR. * src/plotting_image.cpp, src/plotting_device.cpp: cosmetic changes * src/gdlpsstream.cpp: removed unused * src/gdlgstream.cpp, src/gdlgstream.hpp: introduce Width() that solves the problem of having to use either plwid(PLINT) or plwidth(PLFT) depending on plplot's version. * testsuite/demo_graphics1.pro, testsuite/demo_graphics2.pro, testsuite/demo_graphics3.pro: reset !P.MULTI when exiting these demo files 2014-08-30 m_schellens * src/prognodeexpr.cpp: fix problem with SAVE * README: added some info about ANTLR impact on sources * src/basic_fun_jmg.cpp, src/dcompiler.cpp, src/dpro.hpp, src/envt.hpp, src/prognodeexpr.cpp: fixed bug #613 (crash COMMON) and #614 (ROUTINE_NAMES with common block variable) 2014-08-29 alaingdl * src/FMTIn.cpp, src/FMTIn.hpp, src/format.in.g: should solved bug 617. The change is in "format.in.g", other files (here only "FMTIn.hpp" is chnaged) are regerenated running Antlr (version >= 2.7). See discussions in GDL Devel list ! 2014-08-28 gilles-duvert * src/plotting_plots.cpp, src/plotting_xyouts.cpp: bug correction (uninitialized coordinates for plplot) 2014-08-26 gilles-duvert * src/gdlwxstream.cpp, src/gdlwxstream.hpp: Support for TV in wxWidgets GUIs. * src/devicex.hpp: initialise colormap0 for wxWidgets (in relation with TV) * testsuite/demo_graphics2.pro: handles undecomposed displays too 2014-08-25 gilles-duvert * src/pro/read_image.pro: corrected typo in the previous commit 2014-08-23 m_schellens * src/GDLParser.cpp, src/gdlc.g, src/GDLLexer.cpp: bug #615 (slow compilation): further speed up 2014-08-22 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/gdlc.g, src/magick_cl.hpp: fixed bug #615 (slow compilation) 2014-08-20 gilles-duvert * testsuite/test_tv_ps.pro: new tests for TV for PS output. * testsuite/test_tv.pro: new tests for TV (channels, position) * src/CMakeLists.txt, src/deviceps.hpp, src/devicesvg.hpp, src/devicex.hpp, src/gdlgstream.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp, src/gdlsvgstream.cpp, src/gdlsvgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/libinit_jmg.cpp, src/plotting.hpp, src/plotting_image.cpp: Rewrote command "TV" in a more general way. Also for PS device (to be tested). Almost there for SVG (still needs png inline conversion). 2014-08-20 alaingdl * testsuite/test_map.pro: continuing improving "test_map.pro" * src/gdlgstream.hpp: one renaming was not done ... (mm2ndx) 2014-08-19 m_schellens * src/convert2.cpp, src/default_io.cpp, src/getas.cpp, src/str.cpp, src/str.hpp: make GDL understand dD instead of eE for exponentials in data streams (e. g. 3.3D05) 2014-08-19 gilles-duvert * src/plotting_contour.cpp: better handling of contour values. * src/plotting_cursor.cpp: cosmetic changes * src/gdlgstream.hpp, src/plotting_xyouts.cpp: renamed some internal functions * src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp: removed duplicate code * src/plotting_shade_surf.cpp: changes for /SHADES * src/image.cpp: Use MAX_COLOR consistently in this source file 2014-08-18 alaingdl * src/basic_fun_cl.cpp, src/basic_fun_cl.hpp, src/gshhs.cpp, src/gshhs.hpp, src/libinit_cl.cpp, src/libinit_jmg.cpp: Restoring being able to compile GDL without LibProj around. Moving GSHHG_EXISTS(), proj4_EXISTS(), proj4new_exists(). 2014-08-17 alaingdl * src/plotting_windows.cpp: patch from GJ for better MSwin support : win or X11 ... * src/gshhs.cpp: conditionnal compil' for Map_Continents ... 2014-08-14 alaingdl * src/envt.hpp, src/libinit_jmg.cpp, src/matrix_cholesky.cpp, src/matrix_invert.cpp: in "envt.hpp", removing GDL_STRING in GetNumericParDefined; using it in INVERT() and Cholesky codes. Clarifying inputs params in Cholesky codes. 2014-08-13 alaingdl * src/matrix_invert.cpp: forgot to remove a comment :( * src/basic_pro.cpp: min/maj OK for keyword Names= in HELP; filtering on Names= should work for /func, /pro, /routines, /source * src/matrix_invert.cpp: fixing input checks in INVERT() : it was possible to pass a vector (e.g. findgen(10)) without Throw, then code crashes ! 2014-08-12 alaingdl * testsuite/test_map.pro: not downloading again a file if already existing ! * testsuite/test_map.pro: continuing improving "test_map.pro" : mandatory files (if missing map routines and if missing GSHHS data) are downloaded "on demand". 2014-08-11 alaingdl * src/matrix_invert.cpp: We found that the Eigen Invert code is more sensitive to high dynamic range data in matrix to be inverted. If status is bad for the Invert Eigen (if GDL compiled with Eigen !), the Invert GSL way is run also. * src/basic_pro.cpp: various improvments in HELP keywords: HELP,/sys,/brief, HELP,/routine; HELP,/source; HELP,/source, name="*png" ... (it is not finished but much more convenient) 2014-08-10 m_schellens * src/dinterpreter.cpp: Fixed bug #604 (.continue not working at main level) 2014-08-10 alaingdl * src/basic_pro.cpp: details for HELP,/help and HELP,/info * src/pro/loadct.pro, src/pro/read_bmp.pro, src/pro/read_gif.pro, src/pro/read_image.pro, src/pro/read_png.pro, src/pro/read_tiff.pro, src/pro/read_xwd.pro, src/pro/write_bmp.pro, src/pro/write_gif.pro, src/pro/write_image.pro, src/pro/write_jpeg.pro, src/pro/write_pict.pro, src/pro/write_png.pro: correcting a bug in LOADCT, rgb_table=rgb_table; fixing details in various READ/WRITE routines for image formats. * src/libinit.cpp, src/libinit_jmg.cpp: adding warn keywords: FONT in DEVICE, DEFAULT_FONT & CLEAR_EVENTS in WIDGET_CONTROL 2014-08-09 m_schellens * src/basic_pro.cpp: Fixed ticket #611 (free lun in case of OPEN fails) * src/typedefs.hpp: fixed bug in ArrayGuard 2014-08-08 alaingdl * src/libinit_jmg.cpp: adding non-effective DEFAULT_FONT to Widget to go ahead in tests of Chianti code * src/read.cpp: in input (e.g. READS), the character "$" is not useful : we can remove it. 2014-07-31 alaingdl * src/dinterpreter.cpp: interverting Compile and Continue in "dinterpreter.cpp" in order to ensure ".c" will give ".continue". 2014-07-30 alaingdl * src/gshhs.cpp: removing not useful "cout" * testsuite/test_map.pro: helping diagnotic when running "test_map.pro". Do we have the gshhg lib and files ? Is GSHHS_DATA_DIR ok ? Do we have at least one of the projection lib. around ? * CMakeLists.txt, src/gshhs.cpp, src/gshhs.hpp, src/libinit_jmg.cpp: changes related to GSHHG: check for "gshhs.h" in src/; adding GSHHG_EXISTS(), PROJ4_EXISTS(), PROJ4NEW_EXISTS() internal procedures, to be used in testsuite/test_map.pro 2014-07-22 slayoo * src/ncdf_var_cl.cpp: commenting out a debug leftover in ncdf_var_cl.cpp 2014-07-21 alaingdl * src/dinterpreter.cpp, src/dpro.cpp, src/dpro.hpp: new command line first character : # : direct access to inline doc. (arg. number and list of keywords) ToString() method now avalaible for LibProLits, LibFunList, funList, proList. To be used also in HELP. 2014-07-18 alaingdl * src/basic_fun_jmg.cpp: rank is known to be not OK for Objects, we turn it inside ISA() ... * src/basic_fun.cpp: typo when moving lines in PTR_NEW() 2014-07-17 alaingdl * testsuite/test_isa.pro: continuing adding cases into "test_isa" ... * src/basic_fun.cpp: for PTR_NEW(), now multiple calls with PTR_NEW(!null) should work ! 2014-07-16 alaingdl * testsuite/test_isa.pro: continuing improving the coverage of "test_isa" for ISA() * src/basic_fun.cpp: PTR_NEW(input) should work when "input" is !null or undefined (with and without /no_copy). * testsuite/test_null.pro: more tests inside "test_null" * testsuite/test_isa.pro: adding tests into "test_isa": numbers types can be now scalar or array. * src/basic_fun_jmg.cpp, src/libinit_jmg.cpp: ISA() should now be complete. 2014-07-14 alaingdl * src/basic_fun_jmg.cpp, src/basic_pro.cpp: improvments in ISA(), for Objects and Undefined/!null; in HELP, now we clearly distinguish !Null and Undefined variables. 2014-07-14 gilles-duvert * testsuite/demo_graphics1.pro, testsuite/demo_graphics2.pro, testsuite/demo_graphics3.pro: three demo files, 1D, 2D and 3D examples. 2014-07-13 gilles-duvert * testsuite/test_device.pro: test on X11 window position was giving error even with idl. passed that test as warning only. * src/devicex.hpp, src/gdlgstream.hpp, src/gdlwinstream.cpp, src/gdlwxstream.cpp, src/gdlxstream.cpp, src/gdlxstream.hpp: Final changes to separate realm of properties related to the DEVICE with those related to the WINDOWs and the STREAMs. Accordingly, correct results for all currently supported DEVICE,GET_* and DEVICE,SET_* commands. 2014-07-12 slayoo * testsuite/Makefile.am, testsuite/test_bug_n000608.pro: adding test_bug_n000608.pro * testsuite/Makefile.am, testsuite/test_bug_n000607.pro: adding test_bug_n000607.pro 2014-07-12 m_schellens * src/basic_fun_jmg.cpp: Fixed SIZE for HASH and LIST 2014-07-11 gilles-duvert * src/deviceps.hpp, src/devicex.hpp, src/devicez.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlwxstream.cpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/graphicsdevice.hpp: nearly complete changes to separate realm of properties related to the DEVICE with those related to the WINDOWs and the STREAMs, i.e., better use of C++ objects. Support for some new DEVICE functions/keywords. Removed recent patches that did not maintain the aspect ratio of symbols and orientations after a redimensioning of windows. * src/initsysvar.cpp: removed recent patches that did not maintain the aspect ratio of symbols and orientations after a redimensioning of windows. * src/libinit.cpp: Added a few DEVICE functions/keywords. * src/plotting_device.cpp: nearly complete changes to separate realm of properties related to the DEVICE with those related to the WINDOWs and the STREAMs, i.e., better use of C++ objects. Add some new DEVICE functions/keywords. * src/plotting_windows.cpp: nearly complete changes to separate realm of properties related to the DEVICE with those related to the WINDOWs and the STREAMs, i.e., better use of C++ objects. * src/plotting.hpp: removed recent patches that did not maintain the aspect ratio of symbols and orientations after a redimensioning of windows. 2014-07-11 m_schellens * src/basic_op.cpp, src/default_io.cpp, src/nullgdl.cpp, src/prognodeexpr.cpp: fixed bug 607 and 608: \!NULL EQ/NE for objects and HELP output for pointers 2014-07-11 alaingdl * README, src/basic_fun_jmg.cpp, testsuite/test_isa.pro: continuing ISA(); small bug in TYPENAME(). 2014-07-07 alaingdl * testsuite/test_list.pro: update of "test_list.pro" to check list::IsEmpty(). But where is "test_hash.pro" ? * NEWS: update (ISA() and TYPENAME(), removing of LA_CHOLDC/LA_CHOLSOL) * src/hash.cpp, src/hash.hpp, src/list.cpp, src/list.hpp, src/overload.cpp: initial import for methods hash::isempty() and list::isempty() * testsuite/Makefile.am, testsuite/test_isa.pro: initial import of "test_isa.pro" written by Levan L. 2014-07-05 gilles-duvert * src/magick_cl.cpp: Patch to prevent 16 bit depth PNGs that Magick does not read well to be opened at all (image dimensions zero!) * CMakeModules/FindImageMagick.cmake: ImageMagick comes now in different version with 16 or 8 "quantum depth" (bytes per pixel color, essentially). I've aligned the .cmake with current distro's cmake. Then, I've added a way to find the necessary CXX_FLAGS that are needed to compile accordingly to the distribution's setup (otherwise there are compile warnings, if not bugs). * CMakeLists.txt: warning abour dynamic drivers potential problem needs to be rechecked -- added a conditional 'may'. 2014-07-04 alaingdl * src/basic_fun_jmg.cpp: initial import for ISA(). Object, List, hash are not ready. code by Levan L. 2014-07-03 alaingdl * MAP_INSTALL, testsuite/test_map.pro: one missing file in MAP_INSTALL, one new nice case for demo. 2014-07-03 gilles-duvert * src/magick_cl.cpp: added patch to save the day even in presence of magick's readIndexes() failure. 2014-07-03 alaingdl * MAP_INSTALL, src/file.cpp, src/file.hpp, src/initsysvar.cpp: Improving the way !GSHHS_DATA_DIR is managed in "initsysvar.cpp". Tests on the "gshhs.cpp" side are still not done. * CMakeLists.txt, src/gshhs.cpp, src/gshhs.h, src/initsysvar.cpp, src/initsysvar.hpp: 1/ adding official "gshhs.h" to avoid complicating install. 2/ change "CMakeList" to have GSHHS on by default 3/ creating an internal !GSHHS_DATA_DIR variable to provide the path to shorelines data files 2014-07-02 alaingdl * doc/udg/chapters/credits.tex: adding 2 students * INSTALL, config.h.in: moving files related to the "configure" way into obsolete/ * configure.in: In GDL, the "configure" is no more maintained (and some recent options are not available in), now we use CMake. We move "configure.in" into the new directory "obsolete/". 2014-07-01 gilles-duvert * src/pro/findex.pro: corrects bug #601 following new version found on the web. 2014-06-30 gilles-duvert * src/gshhs.cpp, src/libinit.cpp, src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_fun_jmg.hpp, src/math_utl.cpp, src/math_utl.hpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_convert_coord.cpp, src/plotting_cursor.cpp, src/plotting_map_proj.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp: large rewrites in 21 files to support for all mapping-related commands and graphics. Projection include is now plotting.hpp, definition (actual call to proj.4 library) is in plotting_map_proj.cpp. conversions from and to projections are done mainly in plotting.cpp (gdlProjForward()). Most of the graphics commands have been updated to support projections and associated connectivity problems (how a polygon can be splitted by a proection effect, etc) in better supported althought neither complete nor accurate. both libproj4 and proj.4.8 are ok to link with gdl. See MAP_INSTALL for additional hints. * src/gdlgstream.hpp: removed usage of _HAVE_CONFIG (unnecessary and causes confusion in plplot in some cases) * NEWS, MAP_INSTALL, testsuite/test_map.pro, src/pro/map_clip_set.pro: complete (?) support for all mapping-related commands and graphics. * src/deviceps.hpp: removed last two patches (crash). 2014-06-30 pjb7687 * src/deviceps.hpp: Initialize array after allocation, so that 'strlen' can properly find its length. 2014-06-30 alaingdl * src/libinit_jmg.cpp: suspending LA_CHOLDC and LA_CHOLSOL up we have a clean solution. 2014-06-29 gilles-duvert * src/gdlxstream.cpp: casted (char*) some elements of structure to prevent complains by gcc 4.8.2 2014-06-28 gilles-duvert * src/plotting.cpp: removed cause of warning by fussy compilers 2014-06-28 slayoo * testsuite/Makefile.am, testsuite/test_bug_n000542.pro: adding test_bug_n000542.pro 2014-06-27 alaingdl * src/file.cpp: better version for FILE_EXPAND_PATH() ... 2014-06-27 pjb7687 * src/deviceps.hpp, src/includefirst.hpp: Patch for MSVC: 1. Resolve Windows.h Winsock.h header issue 2. 'new' keyword is used for non-constant length of array allocation 2014-06-26 pjb7687 * CMakeModules/FindNumpy.cmake: Patch for future python3 support * src/basic_pro.cpp: Win32 patch: fnmatch -> PathMatchSpec * CMakeLists.txt, CMakeModules/FindPdcurses.cmake, CMakeModules/Findlibps.cmake, src/deviceps.hpp, src/initsysvar.cpp, src/objects.cpp, src/semshm.cpp, src/basic_pro.cpp: Win32 Support for additional libraries: wxwidgets, pslib, eigen3, and graphicsmagick++ Also includes correction of proper pslib header file path 2014-06-26 alaingdl * src/basic_fun.cpp: fixing 2 details in ROUTINE_INFO: must return "$MAIN$" for calls like "routine_info()" with or without routines already complided. "subList.resize( n);" are not need ! * src/basic_fun.cpp: details in ROUTINE_INFO: warning when no pro/fun already compiled, pro should return $MAIN$ first 2014-06-25 alaingdl * src/basic_pro.cpp, src/libinit.cpp: draft for HELP, /system_variables * src/envt.cpp: When a keyword is passed 2 times, we must Throw(), not just Warming(). * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: Preparing some rewriting in HELP. Internal help() renamed in help_pro(). Various keywords added into WarmKey list. Preparing keyword names='*filter*' 2014-06-22 gilles-duvert * src/default_io.cpp: better printed representation of arrays of string (nothing printed until the first non-null string) * src/ofmt.hpp: this patch permits to get correct representation of values when printed in free-format (as many digits printed as possible) 2014-06-21 gilles-duvert * src/plotting_contour.cpp: contour with 1d x,y was crashing gdl when a projection was set. 2014-06-18 gilles-duvert * src/plotting_convert_coord.cpp: corrected bug when only one monodimensional array (such as [0.1,0.1]) was passed to the function. 2014-06-17 slayoo * doc/udg/gdl.tex: fixing mwbk/hyperref/tex4ht compatibility issue (thanks to Deimantas Galcius! - http://tug.org/pipermail/tex4ht/2014q2/000957.html) 2014-06-13 gilles-duvert * CMakeLists.txt: Applied Orion's patch #77 2014-06-13 pjb7687 * src/devicewin.hpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp: Support for TV keyword on Windows platform * src/CMakeLists.txt: Hopefully it fixes the compilation on POSIX * src/datatypes.cpp, src/deviceps.hpp, src/devicewin.hpp, src/devicez.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/file.cpp, src/gdlwinstream.cpp, src/gdlwinstream.hpp, src/graphicsdevice.cpp, src/gtdhelper.hpp, src/initsysvar.cpp, src/io.cpp, src/io.hpp, src/libinit.cpp, src/math_fun_jmg.cpp, src/plotting_convert_coord.cpp, src/read.cpp, src/semshm.cpp, src/sigfpehandler.cpp, src/sigfpehandler.hpp, src/str.cpp, CMakeLists.txt, src/CMakeLists.txt, src/basegdl.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/basic_pro.hpp, src/basic_pro_jmg.cpp, src/basic_pro_jmg.hpp, src/convol.cpp: Support for MinGW - Almost the same one as Patch #76 2014-06-11 slayoo * src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/default_io.cpp, src/format.out.g: adding yet more compatibility fixes for std::cout comparisons for win32 2014-06-11 alaingdl * src/libinit_gm.cpp: adding quiet keywords to IGAMMA (iter, itmax, eps, method) 2014-06-11 slayoo * src/FMTOut.hpp, src/format.out.g: hopefully fixing win32 compatibility in format.out.g (when comparing a stream with std::cout) 2014-06-10 m_schellens * NEWS, src/basegdl.hpp: sync 2014-06-09 slayoo * doc/udg/gdldoc.sty: fixing duplicate index entries in LaTeX documentation 2014-06-08 slayoo * doc/udg/chapters/compile-cmake.tex, doc/udg/makeall, CMakeLists.txt, INSTALL.CMake: including CMake installation instructions in the docs * src/pro/online_help.pro: adding atril to the list of pdf viewers in online_help.pro 2014-06-05 gilles-duvert * src/plotting_convert_coord.cpp: corrected severe bug in convert_coord, same scaling was wrongly applied on X and Y axis. 2014-06-05 m_schellens * src/datatypesref.cpp, src/prognode.cpp: fixed object indexing (missing increment of ref counter) 2014-06-03 m_schellens * src/GDLInterpreter.cpp, src/dinterpreter.cpp, src/gdlc.i.g, src/prognode.cpp: fixed PCALLNode::Run() SetRetTree could be overwritten by CLEANUP method * src/envt.cpp, src/print.cpp: fixed: a=\!null & print, a * src/basic_fun_jmg.cpp: fixed ROUTINE_NAMES (wrong variable index, now use GetKW instead of GetPar) 2014-06-02 m_schellens * src/GDLInterpreter.hpp, src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/envt.cpp, src/gdlc.i.g, src/prognode.cpp: Suppress MESSAGE in ROUTINE_NAMES when called from EXECUTE 2014-05-27 gilles-duvert * src/gsl_fun.cpp: Finishing up the work started in previous version: correct behaviuor for /GRID and several last dims equal to 1. 2014-05-26 gilles-duvert * src/gsl_fun.cpp: Corrected bug (see discussion SF#338692) that prevented interpolation on an array whose last dimension was 1. 2014-05-19 alaingdl * src/pro/value_locate.pro: better input type checks + warning if input vector is not monotonic ... 2014-05-17 alaingdl * src/file.cpp: un-finished but not that bad code for FILE_EXPAND_PATH() 2014-05-16 gilles-duvert * src/pro/map_clip_set.pro: revised version. Splittings not yet fully accurate. 2014-05-15 alaingdl * src/file.cpp, src/file.hpp, src/libinit.cpp: interface for missing function FILE_EXPAND_PATH(). Code not finished. * src/file.cpp, testsuite/test_file_search.pro: in "file.cpp", correcting a bug in FileSearch() for FILE_SEARCH() with keyword /FULLY_QUALIFY_PATH. Preliminary associated test added. 2014-05-15 gilles-duvert * src/plotting_convert_coord.cpp: complete rewrite of convert_coord, all options supported * src/math_utl.hpp: removed commented code * src/plotting.cpp: projection limits support in axis range retrieving routine * src/devicex.hpp: Window positions are correct now. * src/datatypes.cpp: initied to zero arrays according to meaning of BaseGDL::ZERO. Was not enabled before (?) 2014-05-15 alaingdl * testsuite/banner_for_testsuite.pro, testsuite/test_modulo.pro, testsuite/test_routine_names.pro: small cleaning in testsuite 2014-05-11 gilles-duvert * src/plotting_contour.cpp, src/plotting_cursor.cpp: Corrected bug that crashed projections with libproj when they were OK with old libproj4. Needs to have different types depending which library is called. All this subtility will be displaced at a single place (plotting.cpp) in the future. * src/math_utl.hpp: Corrected bug that crashed projections with libproj when they were OK with old libproj4. * src/libinit_jmg.cpp: Added COASTS and CONTINENTS handling. * src/math_utl.cpp: Handles all historical projections, with all projection centers and most rotations. Goodes is goode's homolosine only with libproj not the good old libproj4. libproj may present new problems that libproj4 do not show. Work in progress, we may support ALL libproj projections in the end. * src/gshhs.cpp: Added COASTS and CONTINENTS handling. Corrected bug that removed the first segment of a polygon. Unfinished: push all the projection and !MAP.PIPELINE treatment out of this code. * src/magick_cl.cpp: magick_cl does not need math_utl.hpp * src/libinit.cpp: Added CLIP to shade_surf. * src/graphicsdevice.hpp: Added comment * MAP_INSTALL: location of gshh has been renamed. * src/pro/map_clip_set.pro: Adding /SHOW option 2014-05-07 alaingdl * src/basic_fun_jmg.cpp: small modification in "routine_names_value()" to avoid a Throw: with this change, "test_routine_names.pro" can run end-to-end and internal bugs visibles. * testsuite/test_routine_names.pro: adding "test_routine_names.pro" in testsuite * testsuite/Makefile.am: adding "test_routine_names.pro" in testsuite/ 2014-05-04 slayoo * testsuite/Makefile.am, testsuite/test_bug_n000587.pro: adding test for bug no. 587 (!stime) * testsuite/Makefile.am, testsuite/test_bug_n000597.pro: adding test for bug no. 597 (print,a eq !NULL) * testsuite/Makefile.am, testsuite/test_bug_n000599.pro: adding test for bug no. 599 (modulus issue) 2014-04-30 alaingdl * testsuite/Makefile.am, testsuite/test_obj_new.pro: this new test shows that we do have now a problem related to OBJ_NEW(). 2014-04-29 alaingdl * src/initsysvar.cpp, src/initsysvar.hpp, src/math_fun_ng.cpp, testsuite/Makefile.am, testsuite/test_voigt.pro: We create a !GDL_WARNING flag to inform when the outputs in calculations are known to be different between IDL and GDL. Now used only in VOIGT(), to be extended to BeselIJKY functions. Switch !GDL_WARING to 0 to be quiet. * src/math_fun_ng.cpp, src/voigt.cpp: in VOIGT(), correcting the Dim for the cases: VOIGT([1],1) and VOIGT(1,[1]). 2014-04-28 alaingdl * testsuite/test_modulo.pro: we may want to test the code with old GDL versions without TYPENAME() ... * src/basic_op_new.cpp: fixing Modulo() and DModulo() in "basic_op_new.cpp" (conflit with "basic_op.cpp" def.). This bug was found thanks to the test "test_modulo.pro". 2014-04-26 m_schellens * src/basic_op.cpp: use fmod(...) for modulo for DDouble and DFloat 2014-04-23 alaingdl * testsuite/Makefile.am: update * testsuite/test_bug_3147146.pro, testsuite/test_modulo.pro, testsuite/banner_for_testsuite.pro: *** empty log message *** 2014-04-07 alaingdl * src/basic_fun_jmg.cpp: TYPENAME() should be complete now but code review welcome especially for Structure, Obj, List, Hash ! * testsuite/test_typename.pro: few new test in "test_typename.pro" for Structures, Obj, List and Hash. * testsuite/test_structures.pro: few extra tests in "test_structures.pro" (using keywords in SIZE()) * src/basic_fun_jmg.cpp: adding keyword /Sname for SIZE() * src/basic_fun_jmg.cpp, src/libinit_jmg.cpp: in SIZE(), keywords must be exclusive (/sname to be done); adding two missing types in TYPENAME() (just Obj, List and Hash not ready) 2014-04-04 alaingdl * src/gdlxstream.hpp, src/devicex.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp: correcting bug 595 (window, 1 & window, 2, xsize=123 & wdelete : crash !) 2014-03-29 m_schellens * src/convert2.cpp, src/hash.cpp, src/list.cpp: Added COUNT and WHERE member functions for LIST and HASH 2014-03-28 m_schellens * src/list.hpp, src/overload.cpp, src/envt.cpp, src/envt.hpp, src/hash.cpp, src/hash.hpp, src/list.cpp: Added COUNT and WHERE member functions for LIST and HASH 2014-03-28 alaingdl * src/list.cpp, src/list.hpp, src/overload.cpp: adding list::count() just for the very basic value (not the where()) * testsuite/Makefile.am, testsuite/test_list.pro: initial import of "test_list.pro", just testing list.add() and list.count(), to be extended ... 2014-03-27 m_schellens * src/GDLTreeParser.cpp, src/gdlc.tree.g, src/ofmt.cpp: undo ticket #585: took back code changes. 2014-03-27 alaingdl * testsuite/Makefile.am, testsuite/test_device.pro, testsuite/test_typename.pro: Initial import for "test_typename.pro", 3 types missing. typos in "test_device.pro". * src/basic_fun_jmg.cpp, src/basic_fun_jmg.hpp, src/libinit_jmg.cpp: initial import for TYPENAME(), 3 types missing; preparing ISA() but not ready. 2014-03-25 alaingdl * src/pro/file_lines.pro: correcting FILE_LINE when first charactere is a "~" (HOME in Unix world) 2014-03-23 m_schellens * src/FMTLexer.cpp, src/FMTParser.cpp, src/FMTParser.hpp, src/fmtnode.hpp, src/format.g, src/ofmt.cpp: fixed ticket #583 string(90,'(I+3.2)') % Format parser: unexpected char: '+' 2014-03-22 m_schellens * src/nullgdl.cpp: fixed ticket #579 (NullGDL::GetTag(...) called) * src/ofmt.cpp: fixed ticket #584 (FORMAT="(A)" for BYTE) * src/GDLTreeParser.cpp, src/gdlc.tree.g: fixed ticket #585 (LIST as variable name) 2014-03-22 gilles-duvert * src/devicesvg.hpp, src/plotting_misc.cpp: SVG output is now color on white background. 2014-03-21 gilles-duvert * src/plotting.cpp: patch hopefully fixing wrong rounding of plot limits (logarithmic axis case) * src/deviceps.hpp: reverted patch by AC to temporarily solve bug #530, see patch in plotting.c. Added preliminary support for implicit SIZE for TV command * src/plotting.cpp: better solution to temporarily solve bug #530 2014-03-20 alaingdl * src/deviceps.hpp: temporary solution for bug 520 and having the good colors in PS output 2014-03-19 alaingdl * testsuite/test_device.pro: don't stop in test due to missing X11 device mode ! * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/initsysvar.cpp, src/plotting.hpp: correcting GetGeometry for X11: returning the x/y offsets. * testsuite/test_device.pro: extending "test_device" to X11 tests. 2014-03-18 alaingdl * testsuite/Makefile.am, testsuite/test_where.pro: adding a draft of "test_where.pro" to make very basic but useful tests on WHERE: when OpenMP was in use in WHERE code we had a no trivial bug, if OpenMP will come back in, we should be able to detect basic problems. * src/basic_pro.cpp, src/envt.cpp, src/envt.hpp, src/initsysvar.cpp, src/objects.cpp, src/objects.hpp, src/typedefs.hpp: Trying to fix CPU procedure (was crashing !). TPOOL_MIN_ELTS and TPOOL_MAX_ELTS are now fully managed in Long64. * src/datatypes.cpp: correcting bug 592 in WHERE just by removing the OpenMP directives. 2014-03-13 alaingdl * src/plotting_convert_coord.cpp: small improvments in consistency in CONVERT_COORD: if x or y or z in double, double computation. message that /T3D is not ready. * testsuite/Makefile.am, testsuite/test_convert_coord.pro: initial import of "test_convert_coord.pro", to be extended ... 2014-03-10 m_schellens * src/initsysvar.cpp, src/initsysvar.hpp, src/prognodeexpr.cpp: two points: (1) restoring \!stime; (2) in X mode, updating \!D.{x|y}_size (more elegant :-) 2014-03-10 alaingdl * src/initsysvar.cpp, src/initsysvar.hpp, src/prognodeexpr.cpp: two points: (1) restoring !stime; (2) in X mode, updating !D.{x|y}_size (not elegant but works !) 2014-02-28 gilles-duvert * src/basic_pro.cpp: Corrected bugs #591 and #590 (thanks to igor) 2014-02-27 alaingdl * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/libinit.cpp: fixing details in code (std::string) because it was not compiling on some recent distros/gcc. * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/plotting_device.cpp: Continuing adding keywords to DEVICE for X11 device type. To be add soon into HELP,/device ... * src/plotting_windows.cpp: re-introducing correction 1.19 : fix: WINDOW, WSET, WSHOW and WDELETE are defined only for device types X and WIN, should return "not defined" for other types of devices (set via SET_PLOT) 2014-02-26 alaingdl * src/plotting_windows.cpp: The procedure WINDOW should work when xsize or ysize keywords are negative. It is not a problem when keywords xpos or y pos are negative. * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/libinit.cpp, src/plotting_device.cpp: adding few keywords to DEVICE, now values of GET_WINDOW_POSITION keywords should be OK 2014-02-24 gilles-duvert * src/plotting.cpp, src/plotting_plots.cpp: Optimized use of color arrays (in PLOTS , COLOR=[...]) when array is only a 1 element vector. * src/dinterpreter.cpp, src/gdl.cpp: Reinstalled GDLEventHandler as default handler of readline events, even if it brings bug 562 back. The previous unfortunate patch removed completely the graphics event handling (window resizing, etc). Still not evident how to avoid bug 562 when editing the command line with keyboard arrows. 2014-02-24 alaingdl * src/plotting_windows.cpp: fix: WINDOW, WSET, WSHOW and WDELETE are defined only for device types X and WIN, should return "not defined" for other types of devices (set via SET_PLOT) 2014-02-21 alaingdl * NEWS: updating NEWS file (NULL device type added) * src/graphicsdevice.cpp, src/graphicsdevice.hpp, src/initsysvar.cpp, src/plotting_misc.cpp, src/basic_pro.cpp: Finishing (??) the case we are on a Unix like OS without X11 lib. Only 4 device types are then available. No more crash when trying to plot, or printing just !D. Default is then to be on NULL device. 2014-02-20 alaingdl * src/basic_pro.cpp, src/libinit.cpp: initial import of HELP,/DEVICE, not fully finished. * src/devicenull.hpp, src/graphicsdevice.cpp, src/graphicsdevice.hpp, src/initsysvar.cpp, src/plotting.hpp, src/plotting_misc.cpp, src/Makefile.am: adding NULL Device type. 2014-02-18 alaingdl * src/basic_pro_jmg.cpp: to have CALL_EXTERNAL working, we have to keep : RTLD_NOW || RTLD_GLOBAL in dlopen(). * src/basic_fun_jmg.cpp, src/objects.cpp: smarter return types (long64) for few fields in SIZE( /L64,/Struct) 2014-02-14 gilles-duvert * src/gdl.cpp, src/dinterpreter.cpp: Removed GDLEventHandler as default handler of readline events. Was the cause of bug 562. AFAIK the default libreadline event handler is sufficient here. * src/pro/moment.pro: Removed protection against zero-dim x since even zero-dim x have a mean (x) and moments (Nan). 2014-02-08 gilles-duvert * src/gdlxstream.cpp, src/gdlxstream.hpp: modified GetGin for simpler and faster use. Added GetExtendedGin for further reference (traps ^C). * src/devicex.hpp, src/graphicsdevice.hpp: added (still unused) SetFocus() * src/plotting_cursor.cpp: simplified cursor function * src/pro/read_ascii.pro: added documentation 2014-02-06 gilles-duvert * src/pro/strsplit.pro: strsplit now uses the ESCAPE and FOLD_CASE options available in strtok(). * src/basic_fun.cpp, src/libinit_mes.cpp: added FOLD_CASE to strtok, hence to strsplit! 2014-02-05 gilles-duvert * src/pro/read_ascii.pro: More robust tests of inconsistencies in definition of tags for output structure * src/pro/read_ascii.pro: Corrected improper behaviour where blanks and minus in tag names were not converted to underscores prior to creating the output structure. Also added check that tag names do not begin with a digit. * src/plotting_xyouts.cpp: Behaviour when coordinates of a XYOUTS are not arrays is now correct (value is repeated). 2014-01-25 gilles-duvert * src/plotting.cpp: this optimization should speed up plotting lines and symbols. 2014-01-23 alaingdl * src/libinit_jmg.cpp: if GDL is compiled without GSHHG (former GSHHS), an external MAP_CONTINENT can be used. 2014-01-22 alaingdl * src/ncdf_cl.cpp: restoring normal behavior of NCDF_OPEN (with URL/OpenDAP support), adding few extra messages or errors (default messages are not clear if files do not exist or cannot be read). * src/gsl_fun.cpp: in HISTOGRAM, testing if input array is an array. * src/ncdf4_group.cpp: Adding the 2 last missing function for NetCDF-4 support: NCDF_VARIDSINQ and NCDF_UNLIMDIMSINQ. This is not fully tested. * src/pro/tic.pro: detail in TIC 2014-01-22 gilles-duvert * src/pro/write_png.pro: transparency should work * src/magick_cl.cpp: support for transparent channels (works with write_png) 2014-01-21 gilles-duvert * src/magick_cl.cpp: added warning to inform about truncation of images by local implementation of Magick library. * src/plotting.hpp: updated comments and reset use of flush() that appear needed to finish all drawing sequences with X11. 2014-01-20 gilles-duvert * src/pro/showfont.pro: this version of showfont is faster (avoids bug #576) and looks better... * src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/plotting.hpp: Return of double buffering for X11 plots, with safe use of nonstandard graphic context write modes such as XOR. 2014-01-19 gilles-duvert * src/devicex.hpp: TV now supports non-truecolor vectors as input. * src/plotting.hpp: Removed double buffering. Was not compatible with non-standard modes (eg: device,set_graphics=6) which are used in all cursor-driven drawings (ex: DEFROI). * src/gdlxstream.cpp, src/plotting_cursor.cpp: Corrected bug #582 (/UP option not correctly working) * src/convol.sav.cpp, src/convol.opt.cpp: remove unwanted file 2014-01-18 slayoo * testsuite/CMakeLists.txt: CMake: adding handling for the 77 SKIP return code (as used by autoconf); making the tests depend on building gdl binary * testsuite/Makefile.am, testsuite/test_bug_3426399.pro: adding test for bug 3426399 * testsuite/Makefile.am, testsuite/test_bug_3394430.pro: adding test for bug 3394430 * testsuite/test_same_name.pro, testsuite/Makefile.am: adding test_same_name.pro 2014-01-14 slayoo * testsuite/test_bug_n000581.pro: adding test for bug 581 2014-01-14 alaingdl * testsuite/test_stregex.pro: adding new test case from bug report 581 in "test_stregex.pro". * src/basic_fun.cpp: trying to correct bug 581 in STREGEX when lenght= is used. 2014-01-14 slayoo * testsuite/Makefile.am, testsuite/test_bug_n000580.pro: test added for bug 580 2014-01-13 alaingdl * src/ncdf4_group.cpp: various fixes in NCDF_NCIDINQ for NetCDF-4 support. 2014-01-12 alaingdl * src/initsysvar.cpp: NewTag in SysVar must be in uper case to be OK. 2014-01-11 alaingdl * src/ncdf4_group.cpp: correcting typo in unfinished code, sorry. * src/ncdf_cl.cpp: details about NCDF_CREATE and NCDF_OPEN, testing also if lib. NetCDF-4 is available or not. 2014-01-10 alaingdl * src/ncdf4_group.cpp: the NetCDF code should remains compilable even old netcdf lib. only is available (before 4.1 is available) * src/libinit_cl.cpp, src/ncdf4_group.cpp, src/ncdf_att_cl.cpp, src/ncdf_cl.cpp, src/ncdf_cl.hpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp: continuing cleaning and improvments in NetCDF related codes (not finished) 2014-01-10 slayoo * testsuite/Makefile.am, testsuite/test_bug_3595172.pro: adding test for bug 3595172 2014-01-09 slayoo * testsuite/Makefile.am, testsuite/test_bug_2949487.pro: adding test fo bug 2949487 2014-01-09 alaingdl * src/libinit_cl.cpp: typo in ifdef/endif for new netcdf-4 functions * src/libinit_cl.cpp: some new netCDF-4 functions should not be visible without NetCDF-4 ! * NEWS, src/CMakeLists.txt, src/Makefile.am, src/libinit_cl.cpp, src/ncdf4_group.cpp, src/ncdf_cl.cpp, src/ncdf_cl.hpp, src/ncdf_var_cl.cpp: initial import of new NetCDF-4 capabilities (groups related) * CMakeLists.txt, config.h.cmake: preparing extension to some NetCDF-4 finctionnalities. 2014-01-08 gilles-duvert * src/convol.cpp, src/datatypes.cpp: specialization of convol() for ULONG and ULONG64 2014-01-08 alaingdl * src/libinit_jmg.cpp, src/widget.cpp: attempt adding EVENT_FUNC keyword into WIDGET_CONTROL (preparing GDL Widgets for ATV !) * NEWS, src/initsysvar.cpp: adding !Const * src/gdlwidget.cpp: change needed on CentOS (GCC 4.1.2, wx-2.8) for using wxTreeItemId::wxTreeItemId(long int) 2014-01-05 gilles-duvert * CMakeLists.txt: corrected typo in message about gshhs. 2014-01-04 slayoo * testsuite/Makefile.am: updating testsuite/Makefile.am * testsuite/test_bug_3285659.pro: adding test_bug_3285659.pro 2014-01-04 gilles-duvert * testsuite/test_convol.pro: convol() now correctly behaves for all combinations of options and data types. this is a sample test file. * src/CMakeLists.txt, src/convol.cpp, src/convol_inc0.cpp, src/convol_inc1.cpp, src/convol_inc2.cpp, src/datatypes.cpp: convol() now correctly behaves for all combinations of options and data types. 2014-01-02 slayoo * testsuite/test_bug_2892631.pro: adding test_bug_2892631.pro * testsuite/test_bug_2876372.pro: adding test_bug_2876372.pro 2013-12-30 slayoo * testsuite/test_bug_3572473.pro: adding test_bug_3572473.pro 2013-11-26 alaingdl * src/pro/tic.pro, src/pro/toc.pro: fixing details in TIC and TOC. 2013-11-26 m_schellens * src/basic_fun.cpp, src/datatypes.cpp, src/initsysvar.cpp, src/prognodeexpr.cpp, testsuite/test_suite.pro: fixed NE and EQ with \!NULL 2013-11-26 alaingdl * NEWS: updating NEWS * src/pro/tic.pro, src/pro/toc.pro, src/pro/Makefile.am: initial import of TIC and TOC (both as pro and func), currently not working due to issue on !null EQ/NE * testsuite/test_null.pro, testsuite/Makefile.am: initial import of test cases on logical operatios (NE and EQ) with !null 2013-11-25 slayoo * src/gsl_fun.cpp: fixing OSX Mavericks clang compilation issue (tracker bug no. 577) 2013-11-22 m_schellens * src/datatypes.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp: OpemMP for CatInsert * src/basic_pro.cpp, src/datatypes.cpp, src/gdlarray.hpp: fixed CPU 2013-11-21 gilles-duvert * testsuite/test_widgets.pro: added a commented text that generates a crash if uncommented. Patch welcome. * src/initsysvar.cpp: reverted passing TPOOL_MIN_ELTS and TPOOL_MAX_ELTS to Long64 since it will need some careful editing in basic_pro.cpp and envt.cpp to prevent the commabd 'CPU' to crash. * src/convol_inc0.cpp: put back a missing line 2013-11-20 m_schellens * src/datatypes.cpp: OMP for WHERE 2013-11-18 gilles-duvert * src/plotting_misc.cpp: tentative patch for bug #530. * src/deviceps.hpp: reverted code to prevent crash when writing eps color files. 2013-11-18 m_schellens * src/default_io.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp, src/widget.hpp: WIDGET_TREE and WIDGET_TABLE preparations 2013-11-18 alaingdl * src/basic_fun.cpp: GDL_TMPDIR/IDL_TMPDIR now by default in /var/tmp, using available on Linux and OSX. MSwin way not ready. * src/initsysvar.cpp: in !cpu, two fields now in Long64 2013-11-15 m_schellens * src/pro/xmanager.pro: initial import (xmanager.pro) 2013-11-15 slayoo * doc/udg/makeall: updating doc/udg/makeall with checks for missing executables (thanks Alain!) * doc/udg/README.txt: updating doc/udg/README.txt * doc/udg/gdl.tex: getting rid of copernicus.bst dependency 2013-11-12 slayoo * doc/udg/gdl.tex: old-mwcls+natbib workaround 2013-11-07 gilles-duvert * src/basegdl.cpp, src/convol_inc1.cpp, src/nullgdl.cpp, src/CMakeLists.txt, src/basegdl.hpp, src/basic_fun.cpp, src/convol.cpp, src/convol_inc0.cpp, src/datatypes.cpp, src/datatypes.hpp, src/libinit.cpp, src/nullgdl.hpp: Support for /NAN, MISSING=, INVALID=, /EDGE_NULL in CONVOL. To be improved, EDGE_NULL is not fully functional. Possible other features. Scaling for BYTEs was and is still wrong. Removed use of convol_inc2.cpp to simplify maintainance at the expanse of readability... 2013-11-05 m_schellens * config.h.in: update test 2013-11-04 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/widget.cpp: GDLWidgetTree preparations 2013-11-04 alaingdl * src/pro/Makefile.am: configure checked for missing files 2013-11-04 m_schellens * src/widget.cpp: GDLWidgetTable preparations 2013-11-03 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/libinit_jmg.cpp, src/prognodeexpr.cpp, src/widget.cpp, testsuite/test_widgets.pro: GDLWidgetTable preparations 2013-11-02 m_schellens * src/GDLInterpreter.cpp, src/basic_fun.cpp, src/prognode.cpp, src/prognodeexpr.cpp: fixed return of local parmeter in UD functions 2013-10-30 m_schellens * src/libinit_jmg.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/widget.cpp, testsuite/test_widgets.pro: WIDGET_CONTROL,SET_BUTTON working. Update test. 2013-10-30 alaingdl * src/gdlwidget.cpp: being able to compile CVS even without WxWidgets 2013-10-30 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/pro/cw_bgroup.pro: CW_BGROUP * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp, src/objects.cpp, src/widget.cpp: widget system ok 2013-10-29 alaingdl * src/pro/interpol.pro: tricky bug in INTERPOL, found thanks to another bug in external code ! 2013-10-29 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgeteventhandler.cpp: corrected wxWidgets comments (2.8 compatibility) * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/widget.cpp, src/widget.hpp: two phase initialization of widgets * src/gdlwidgeteventhandler.cpp, src/objects.cpp, src/plotting.hpp, src/typedefs.hpp, src/widget.cpp, src/widget.hpp, src/gdleventhandler.cpp, src/gdleventhandler.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp: introduced OnShow() for GDLWidgets 2013-10-28 m_schellens * src/gdlwidgeteventhandler.cpp, src/plotting.hpp, src/widget.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp: wxWidgets 2.8 compatibility * src/gdlwidget.hpp, src/plotting.hpp, src/gdlwidget.cpp: corrected thread handling 2013-10-27 m_schellens * src/plotting.hpp, src/gdlwidget.hpp, src/gdlwidget.cpp, src/gdlwidgetdraw.cpp, src/gdlwidgeteventhandler.cpp, src/widget.cpp, src/libinit_jmg.cpp, src/objects.cpp, src/CMakeLists.txt, src/Makefile.am: WIDGET_SLIDER. All widgets working. 2013-10-26 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/libinit_jmg.cpp, src/plotting_contour.cpp, src/widget.cpp, src/widget.hpp: changed widget thread handling * src/gdleventhandler.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/objects.cpp, src/plotting.hpp, src/widget.cpp: tab widget (incomplete) 2013-10-25 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/objects.cpp, src/widget.cpp: text event handling 2013-10-25 alaingdl * src/libinit.cpp, src/plotting.hpp, src/plotting_plot.cpp: adding PLOT_IO, PLOT_OO, PLOT_OI. 2013-10-24 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/objects.cpp, src/plotting.hpp, src/widget.cpp: WIDGET_LABEL and WIDGET_TEXT update 2013-10-24 slayoo * CMakeLists.txt: updated package hints in CMakeLists.txt 2013-10-24 alaingdl * testsuite/test_bug_3244840.pro, testsuite/test_format.pro, testsuite/test_readf.pro, testsuite/Makefile.am: moving "test_bug_3244840.pro" test into a new file "test_format.pro" dedicated to various tests on Formating issues. To be extended. 2013-10-24 slayoo * doc/www/_news.inc.php, doc/www/downloads.php: updating news and urls 2013-10-24 alaingdl * src/widget.cpp: continuing being able to compile without WxWidget * src/plotting.hpp: removing #define HAVE_PLPLOT_WIDTH, this is managed outside and depend on plplot version 2013-10-24 m_schellens * src/gdlwidget.hpp: WIDGET_DROPLIST and WIDGET_COMBOBOX (incomplete) 2013-10-23 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/libinit_jmg.cpp, src/objects.cpp, src/plotting.hpp, src/widget.cpp, src/widget.hpp: WIDGET_DROPLIST and WIDGET_COMBOBOX (incomplete) * src/read.cpp: Fixed bug #573 'readf errors' * src/basic_pro.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp: Radio button and check box events 2013-10-23 alaingdl * src/plotting.hpp: removing #define HAVE_PLPLOT_WIDTH, this is managed outside and depend on plplot version 2013-10-23 m_schellens * src/gdlwidget.hpp, src/gdlwidget.cpp, src/gdlwxstream.cpp, src/libinit_jmg.cpp, src/plotting.hpp, src/widget.cpp: prepared [NON]EXCLUSIVE bases. 2013-10-22 alaingdl * src/libinit_jmg.cpp: now, the two versions of INVERT() are stored in "matrix_invert.hpp" (GSL and Eigen3) * src/gsl_fun.cpp, src/gsl_fun.hpp: removing "invert_fun" from "gsl_fun.cpp/hpp" * src/CMakeLists.txt, src/Makefile.am, src/matrix_invert.cpp, src/matrix_invert.hpp: initial import of revised version of INVERT() with Eigen3, allowing usage of /GSL or /EIGEN (Eigen is the default when compiled with, GSL always available since GSL is a mandatory dependance) (INVERT() with Eigen is about 4 times faster than GSL (1600^2 on 8cores)) 2013-10-22 m_schellens * src/gdlwidgetdraw.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/libinit_jmg.cpp, src/widget.cpp, src/widget.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp: WIDGET_DRAW: resize parent 2013-10-22 alaingdl * src/plotting.hpp, src/devicex.hpp, src/gdlwidget.hpp, src/gdlwxstream.cpp: being able to compile without WxWidget and with older plplot versions (< 5.9.10) 2013-10-21 m_schellens * src/gdlwidget.cpp, src/devicex.hpp, src/gdlwidget.hpp, src/plotting.hpp, src/plotting_windows.cpp: GUI cleanup 2013-10-21 alaingdl * src/gdleventhandler.cpp, src/devicex.hpp, src/gdlwxstream.hpp, src/gdlwidget.cpp: being able to compile without WxWidget 2013-10-21 m_schellens * src/plotting.hpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_convert_coord.cpp, src/plotting_cursor.cpp, src/plotting_device.cpp, src/plotting_misc.cpp, src/plotting_windows.cpp, src/plotting_xyouts.cpp, src/CMakeLists.txt, src/Makefile.am, src/deviceps.hpp, src/devicesvg.hpp, src/devicex.hpp, src/devicez.hpp, src/gdleventhandler.cpp, src/gdlgstream.cpp, src/gdlpsstream.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlxstream.cpp, src/gdlzstream.cpp, src/gdlzstream.hpp, src/graphics.cpp, src/graphics.hpp, src/graphicsdevice.cpp, src/graphicsdevice.hpp, src/image.cpp, src/initct.cpp, src/initsysvar.cpp, src/math_fun_jmg.cpp, src/objects.cpp: some rearragement for WIDGET_DRAW 2013-10-21 alaingdl * src/plotting.hpp: conflicting #define HAVE_PLPLOT_WIDTH for old plplot versions (< 5.9.10) 2013-10-21 m_schellens * src/plotting_contour.cpp, src/plotting_xyouts.cpp, src/widget.cpp, src/devicex.hpp, src/gdlgstream.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/graphics.cpp, src/graphics.hpp, src/plotting.cpp, src/plotting.hpp: WIDGET_DRAW working (initial version - not complete) 2013-10-20 gilles-duvert * testsuite/test_zip.pro: added tests to check that readf() works well after a stat() or (equivalent) a point_lun of nonzero argument. Removed unnecessary calls to specific linux external spawn commands. 2013-10-18 m_schellens * src/gdlwxstream.cpp, src/gdlgstream.hpp: WIDGET_DRAW almost working 2013-10-17 m_schellens * src/devicex.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/widget.cpp: WIDGET_DRAW (not working) * src/gdlgstream.hpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp, src/devicex.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp: WIDGET_DRAW implementation (not yet working) 2013-10-16 m_schellens * src/libinit_jmg.cpp, src/widget.cpp, src/widget.hpp, src/CMakeLists.txt, src/Makefile.am, src/gdlgstream.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlwidgetdraw.cpp, src/gdlwxstream.cpp, src/gdlwxstream.hpp: WIDGET_DRAW function (not yet working) * src/devicex.hpp, src/dstructgdl.cpp: sync 2013-10-15 m_schellens * src/gdlwidget.cpp, src/gdlwidget.hpp, src/objects.cpp: widets working. * src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp: fixes for widgets 2013-10-14 m_schellens * src/gdlwidget.hpp, src/gdlwidget.cpp, src/widget.cpp: widgets update. Not yet working. 2013-10-13 m_schellens * src/gdleventhandler.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp: correct widget event handling 2013-10-12 gilles-duvert * src/io.cpp: This patch seems to fix the 'seek position' problem encountered when reading compressed streams. 2013-10-12 m_schellens * src/basic_pro.cpp, src/gdleventhandler.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp: fixes for widget system 2013-10-11 gilles-duvert * src/base64.hpp, src/basic_fun.cpp: changes to avoid warnigs by xcode under Mac OS X 10.9 (Mavericks). (Reported by M.S., HMUG packager). 2013-10-11 alaingdl * doc/www/_news.inc.php, doc/www/resources.php: continuing adding news (link to adass paper) * doc/www/_news.inc.php: few extra links 2013-10-10 m_schellens * src/widget.cpp: fix problem when building w/o wxWidgets * src/CMakeLists.txt, src/gdlwidget.cpp, src/gdlwidget.hpp, src/nullgdl.cpp, src/widget.cpp, src/widget.hpp: reorganize widget handling (not ok yet - but better than before) 2013-10-10 gilles-duvert * CMakeLists.txt, config.h.cmake: check for HAVE_EXT_STDIO_FILEBUF_H would fail for many platforms because the include file is hidden in the gcc directories. This patch hopefully helps finding this useful addition, that permits to read/ (write?) compressed files. 2013-10-08 gilles-duvert * src/pro/read_jpeg2000.pro: new: READ_JPEG2000 (needs **Magick with libjasper). Reads JP2 and the rare JPC flavor. * src/pro/read_jpeg.pro: added support for JNG style JPEG (needs **Magick with libjasper) * src/pro/read_jpeg.pro, src/pro/read_png.pro: Reverted to previous version --- !ORDER should not be checked in read_* files. Only /ORDER is relevant. * src/pro/read_jpeg.pro, src/pro/read_png.pro: Added support for !ORDER system variable * src/pro/read_gif.pro: removed commented part about "order" (kw not used) * src/devicex.hpp: Rewritten TV and TVRD to support ORDER kw and cured some bugs (truecolor, orientation). * src/initsysvar.cpp, src/initsysvar.hpp: Added TV_ORDER(), support for !ORDER system variable 2013-10-08 alaingdl * src/gdljournal.cpp, src/math_fun_jmg.cpp: continuing correcting errors found by "cppcheck", here a bad delete. 2013-10-07 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp: cleanup * src/gdlc.i.g: applied patch #35 * src/GDLInterpreter.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp: some cleanup * HACKING: applied patch #35 * src/gshhs.cpp, src/plotting_map_proj.cpp: applied patch #72 2013-10-06 m_schellens * src/datatypes.cpp: for windows 2013-10-06 gilles-duvert * src/devicex.hpp: correct for bug #572 * src/libinit.cpp, src/plotting_device.cpp: added GET_WINDOW_POSITION kw and function * src/plotting_windows.cpp, src/gdlxstream.cpp: added comments 2013-10-06 m_schellens * CMakeLists.txt, CMakeModules/FindLibproj4.cmake, CMakeModules/FindLibproj4new.cmake: use 1st http://home.comcast.net/~gevenden56/proj/ then http://trac.osgeo.org/proj/ for projections * src/math_utl.cpp, src/math_utl.hpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_convert_coord.cpp, src/plotting_cursor.cpp, src/plotting_map_proj.cpp, src/plotting_xyouts.cpp, CMakeLists.txt, CMakeModules/FindLibproj4.cmake, src/math_fun_jmg.cpp: use http://trac.osgeo.org/proj/ for projections * CMakeLists.txt: removed patch #42 * CMakeLists.txt: applied patch #42 * CMakeLists.txt, testsuite/Makefile.am, testsuite/try: applied patch #44 * src/plotting.cpp, src/plotting_contour.cpp, src/plotting_xyouts.cpp: some changes for new plplot::width * CMakeLists.txt, config.h.cmake, src/allix.hpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/deviceps.hpp, src/dnode.cpp, src/dpro.cpp, src/envt.cpp, src/envt.hpp, src/gdlexception.cpp, src/gdlexception.hpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_xyouts.cpp, src/prognode.cpp, src/prognodeexpr.cpp: applied reorder and plwidth patches * src/basic_pro.cpp, src/objects.cpp: for windows * src/file.cpp, src/objects.cpp: linux after windows compatibility, all tests ok 2013-10-05 m_schellens * src/dirent.c, src/dirent.h, src/file.cpp, src/gdlgstream.hpp, src/gshhs.cpp, src/gshhs.hpp, src/io.cpp, src/math_fun_gm.hpp, src/new.cpp, src/new.hpp, src/objects.cpp, src/plotting_axis.cpp, src/plotting_convert_coord.cpp, src/plotting_cursor.cpp, src/plotting_erase.cpp, src/plotting_map_proj.cpp, src/plotting_misc.cpp, src/plotting_polyfill.cpp, src/plotting_windows.cpp, src/plotting_xyouts.cpp, src/basic_pro.cpp: linux compatibility 2013-10-04 m_schellens * src/dirent.h, src/basic_fun_cl.cpp, src/deviceps.hpp, src/devicewin.hpp, src/dimension.hpp, src/dinterpreter.cpp, src/dirent.c, src/file.cpp, src/gdlgstream.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gsl_fun.cpp, src/math_fun_ac.cpp, src/math_fun_gm.cpp, src/math_fun_jmg.cpp, src/matrix_cholesky.cpp, src/objects.cpp, src/plotting.cpp, src/plotting_plot.cpp: Windows VS2010 compatibility 2013-10-03 alaingdl * src/basic_pro.cpp: missing closedir, as detected by "cppchecker" (line 339: (error) Resource leak: dirp) 2013-10-02 m_schellens * src/gsl_matrix.cpp, src/prognode.cpp, src/prognode_lexpr.cpp, src/GDLInterpreter.cpp: avoid some unnecessary copying in WHILE/REPEAT/CASE/IF statements * src/gsl_matrix.cpp: moved GDLGuard 2013-10-02 alaingdl * src/gsl_matrix.cpp: correcting gsl_permutation_* issue for LUDC/LUSOL (bug #570), patch by Orion P. * src/pythongdl.cpp: correcting issue in Python binding, patch by Orion P. 2013-10-01 m_schellens * src/gdlc.i.g: a bit cleanup * src/GDLInterpreter.hpp, src/gdlc.i.g: some comments * src/GDLInterpreter.cpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/convert2.cpp, src/datalistt.hpp, src/devicex.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/gsl_fun.cpp, src/ncdf_var_cl.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: correction for DEREFNode to extend lifetime of ptr till end of function 2013-09-29 gilles-duvert * NEWS: updated the description to match the graphic status at the time of 0.9.4 * src/gsl_fun.cpp: interpolate now accepts COMPLEX and DCOMPLEX types. 2013-09-29 slayoo * doc/www/_news.inc.php: doc/www/_news: 0.9.4 release 2013-09-29 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/assocdata.hpp, src/dinterpreter.cpp, src/gdlc.i.g, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: ASSOC fix for structs. Use no assoc array index where possible. 2013-09-28 m_schellens * CMakeLists.txt, configure.in: 0.9.4 CVS * src/prognode.cpp, src/prognode_lexpr.cpp: optimized reference parameter passing with ++/-- 2013-09-27 m_schellens * testsuite/test_suite.pro, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g, src/gdlc.i.g, src/prognode.cpp: DEC/INC EvalRefCheck optimization (no temporary anymore) * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/dcompiler.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp: corrected reference parameter passing with ++/-- GDL 0.9.4: 2013-09-26 m_schellens * ChangeLog, README: gdl 0.9.4 * src/prognode.cpp, src/prognodeexpr.cpp, src/basic_fun.cpp, src/envt.hpp: fixed return by reference for return of local variables * src/basic_fun.cpp, src/dcompiler.cpp, src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp: fixed reference parameters with ++ -- r+ 2013-09-26 m_schellens * src/prognode.cpp, src/prognodeexpr.cpp, src/basic_fun.cpp, src/envt.hpp: fixed return by reference for return of local variables * src/basic_fun.cpp, src/dcompiler.cpp, src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp: fixed reference parameters with ++ -- r+ 2013-09-25 m_schellens * src/prognode.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: trinary operator optimizations * src/pro/str_sep.pro: working STR_SEP * src/pro/factorial.pro, src/GDLInterpreter.hpp, src/envt.cpp, src/envt.hpp, src/gdlarray.hpp, src/gdlc.i.g, src/prognode.cpp: ref check function return value * src/basic_fun.cpp, src/prognode.cpp: fixed ParameterDirect (wrong return reference set) * testsuite/test_suite.pro, src/GDLTreeParser.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/GDLInterpreter.cpp: fixed pass by reference for functions as parameters 2013-09-24 slayoo * doc/www/faq.php: updating FAQ entry on CATCH 2013-09-24 gilles-duvert * src/math_utl.cpp: functions machar_[s,d] must not be optimized by clever compilers such as icc -- will then loop forever... Perhaps should be revised... * src/math_fun_jmg.cpp: permits to compile with icc 2013-09-24 m_schellens * src/envt.cpp, src/gsl_fun.cpp, src/prognode.cpp, src/widget.cpp: fixed widget.cpp * src/GDLTreeParser.cpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/overload.cpp, src/prognode.cpp, src/prognodeexpr.cpp, src/GDLInterpreter.cpp: sync 2013-09-23 m_schellens * src/envt.hpp, src/gdlc.i.g, src/gsl_fun.cpp, src/list.cpp, src/math_fun_gm.cpp, src/overload.cpp, src/prognode.cpp, src/typedefs.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/datalistt.hpp, src/dvar.cpp: small optimizations 2013-09-23 alaingdl * src/initsysvar.cpp: correcting typo in "initsysvar.cpp" * src/initsysvar.cpp, src/objects.cpp: removing a comment; adding a "bluid_date" in !GDL 2013-09-23 m_schellens * src/dstructdesc.hpp, src/envt.cpp, src/envt.hpp, src/list.cpp, src/list.hpp, src/overload.cpp: Made LIST HEAP_GC friendly 2013-09-22 m_schellens * src/basic_fun_jmg.cpp: small changes relating to OVERWRITE keywords * src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/gsl_fun.cpp, src/libinit.cpp: Fixes for changed API for library functions: left-return values must be explicitely set * src/fftw.cpp, src/gsl_fun.cpp, src/libinit_jmg.cpp, src/basic_fun.cpp, src/envt.cpp, src/prognodeexpr.cpp: fixed regression test_bug_3152899 * src/default_io.cpp, src/devicex.hpp, src/dinterpreter.cpp, src/dstructgdl.hpp, src/envt.cpp, src/envt.hpp, src/gdlarray.hpp, src/gdlc.i.g, src/gsl_fun.cpp, src/hdf5_fun.cpp, src/io.cpp, src/libinit.cpp, src/libinit_ac.cpp, src/libinit_cl.cpp, src/libinit_gm.cpp, src/libinit_jmg.cpp, src/libinit_mes.cpp, src/libinit_ng.cpp, src/list.cpp, src/math_fun_gm.cpp, src/math_fun_jmg.cpp, src/math_fun_ng.cpp, src/math_utl.cpp, src/ncdf_var_cl.cpp, src/overload.cpp, src/plotting.cpp, src/plotting_map_proj.cpp, src/prognode.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/widget.cpp, src/GDLInterpreter.hpp, src/assocdata.cpp, src/assocdata.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/basic_op.cpp, src/basic_pro.cpp, src/basic_pro_jmg.cpp, src/GDLInterpreter.cpp: Changed API for library functions: left-return values must be explicitely set 2013-09-20 gilles-duvert * src/gsl_matrix.cpp: apparently the permutation order 's' is not used here. * src/plotting_cursor.cpp: variable "idata" was used before its value was set... 2013-09-19 alaingdl * testsuite/test_bug_3104326.pro: revisiting this test to check 3 important points when Execution is halted (line number in file, path to the file, name of the pro/func) * src/basic_pro.cpp, src/libinit.cpp: adding (obsolete) keyword /All_Keys to HELP procedure, with few useful examples. 2013-09-17 gilles-duvert * src/getas.cpp, src/hash.cpp, src/hash.hpp, src/list.hpp, src/matrix_cholesky.cpp, src/overload.cpp: added linefeed at end of file -- was generating warnings for some compilers. * src/gsl_fun.cpp: patch to stop ekopath's 'pathcc' compiler error. * src/math_fun_gm.cpp, src/plotting_contour.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp, src/antlr/ASTFactory.hpp: support for ekopath's 'pathcc' compiler * src/plotting.cpp, src/plotting_convert_coord.cpp, src/plotting_plots.cpp, src/plotting_xyouts.cpp: removed simple nan-test that apparently is 'optimized' by compilers 2013-09-17 m_schellens * src/assocdata.cpp, src/assocdata.hpp, src/basic_pro.cpp: fixed bug #557 * src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/list.cpp, src/GDLInterpreter.cpp: fixed bug emerging from test_bug_3300626 2013-09-17 alaingdl * src/gdlgstream.hpp: fixing warning format in a "fprintf" * src/dstructgdl.cpp, src/envt.cpp: continuing cleaning code using CLang options (here dangling Else) * src/file.cpp: continuing cleaning code using CLang options (here 2x dangling Else) * src/dpro.cpp: continuing cleaning code using CLang options (here dangling Else) * src/datatypesref.cpp: continuing cleaning code using CLang options (here 2x dangling Else) * src/basic_fun_jmg.cpp, src/arrayindex.cpp: continuing cleaning code using CLang options (here dangling Else) * src/datatypes.cpp: continuing cleaning code using CLang options (here 2x dangling Else) * src/gdlgstream.hpp: CLang complains here due to [-Wlogical-op-parentheses] * src/list.cpp, src/str.cpp, src/read.cpp: continuing cleaning code using CLang options (here dangling Else) 2013-09-16 alaingdl * src/gsl_fun.cpp: "dangling else", thanks to CLang warnings. * src/gsl_fun.cpp: fixing trivial warning coming from CLang default compilation. * src/GDLInterpreter.hpp, src/devicex.hpp, src/plotting_windows.cpp, src/widget.cpp: starting fixing obvious bugs (= instead ==) or "dangling else", thanks to CLang warnings. 2013-09-16 m_schellens * src/list.cpp: fixed LIST with negative LENGTH KW 2013-09-10 gilles-duvert * src/basic_pro.cpp: option LAST_MESSAGE for HELP now correctly supports the presence of the OUTPUT keyword 2013-09-07 gilles-duvert * src/basic_pro.cpp: Corrected positive year dates that were wrong by 1 day. Note that Julian date does not vary between 5 and 15 October 1582 (correct behaviour). 2013-09-04 gilles-duvert * src/plotting.cpp: solves bug #565 2013-08-30 alaingdl * src/pro/calendar.pro: fixing a (old) input conversion error (bug #218) in CALENDAR. * testsuite/Makefile.am, testsuite/test_array_equal.pro, testsuite/test_netcdf.pro: initial import of "test_array_equal.pro" (some basic test cases for ARRAY_EQUAL were wrong) and "test_netcdf.pro", a to-be-finished merging of various tests cases for NetCDF format. * src/basic_fun.cpp: correction a bug in ARRAY_EQUAL when one of the inputs arrays is an array with only one element: ARRAY_EQUAL(1,[1,1]) is True, ARRAY_EQUAL([1],[1,1]) is False !! Test cases to be put in the testsuite. * src/envt.cpp: in "envt.cpp", GetParDefined() should throw when the variable is undefined OR explicitly equal to !Null * testsuite/test_strsplit.pro: Adding few tests cases in TEST_STRSPLIT related to Length= keyword. A bug related to ARRAY_EQUAL() was also corrected. * src/ncdf_var_cl.cpp: Correcting bug #524 NCDF_VARGET fails for string array, thanks to Harald. (test case to be add in testsuite/) 2013-08-29 gilles-duvert * src/plotting_windows.cpp, src/devicex.hpp: Adds support for preference values GDL_GR_[WIN or X]_WIDTH, HEIGHT and QSCREEN. To be used as their *DL equivalents in the environment. 2013-08-26 gilles-duvert * src/plotting_contour.cpp: solves bug #561 ( contour desperately stuck ) 2013-08-26 alaingdl * src/plotting_contour.cpp: clarifying logic in CONTOUR inputs to avoid crashing without x/y and /irregular 2013-08-22 alaingdl * src/datatypes.cpp: I revert this change in CONVOL input types, because it is not compilable with "old" GCC (4.3, 4.4). Looking for a more partable version. 2013-08-11 alaingdl * testsuite/test_idl_validname.pro: new test cases in "test_idl_validname.pro" * src/pro/idl_validname.pro: three improvments in pro IDL_VALIDNAME: 1/ input as list of string OK, 2/ thanks to patch 66, better management of 3 special chars: $, ! and \, 3/ "!" at first place and /convert_all is well managed. 2013-08-05 alaingdl * src/datatypes.cpp: in CONVOL(), allowing Ulong and Ulong64 (work by Nodar K.). 2013-08-04 alaingdl * src/basic_pro_jmg.cpp: In CALL_EXTERNAL C code, removing fixed defaultAlign = 16 (Eigen Case). This is problematic for structures on 32b linux. * src/basic_pro_jmg.cpp: for CALL_EXTERNAL, pbs running "test_ce.pro" : applying patch 69 from Orion, plus an extra test for string. Now all tests but "struct" OK ! 2013-08-03 gilles-duvert * src/ofmt.cpp: c++ code ready for C() format. Needs separate work on antlr code... 2013-08-02 gilles-duvert * src/gdlgstream.hpp: corrected wrong orientation of XOUTS characters when axes are inverted * src/plotting.cpp: corrected wrong orientation of symbols when axes are inverted * src/plotting_xyouts.cpp: corrected wrong orientation of XOUTS characters when axes are inverted 2013-08-01 gilles-duvert * src/basic_pro_jmg.cpp: solves bug #559 however reason why the string pointer was corrupted to begin with is unclear for me. 2013-07-31 gilles-duvert * testsuite/test_strsplit.pro: test for bug #554 and others related to use of LENGTH Keyword * src/pro/strsplit.pro: should solve bug #554 and other related to use of LENGTH Keyword * src/matrix_cholesky.cpp: should solve bug #555 2013-07-26 m_schellens * src/basic_op.cpp, src/datatypes.cpp, src/hash.cpp, src/hash.hpp, src/list.cpp, src/list.hpp, src/overload.cpp, src/prognode.cpp: IsTrue for LIST and HASH 2013-07-26 gilles-duvert * src/plotting.cpp: cosmetic changes after patch #68 * src/plotting_contour.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp, src/plotting_plot.cpp: applied patch #68 * src/pro/oploterr.pro: behaviour of oploterr should be to clip errorbars... 2013-07-26 m_schellens * src/math_fun.cpp, src/pythongdl.cpp: fix for python module 2013-07-25 gilles-duvert * src/pro/delvar.pro: implements delvar as a procedure using code from old version of delvarx.pro (under BSD license) 2013-07-25 m_schellens * src/math_fun.cpp, src/basic_fun.cpp, src/datatypes.hpp, src/dpro.cpp, src/dpro.hpp, src/dstructgdl.hpp, src/typedefs.hpp: sync * src/envt.hpp, src/extrat.cpp, src/hash.cpp, src/math_fun_jmg.cpp, src/typedefs.hpp, src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/dcommon.hpp, src/dpro.hpp, src/dstructdesc.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/dvar.hpp, src/envt.cpp: replaced deque by vector where possible 2013-07-24 gilles-duvert * src/pro/ploterr.pro: trick to plot errorbars waaay faster using nan-separated values in arrays. * src/pro/oploterr.pro: introduced simple oploterr version as in idl. 2013-07-24 m_schellens * src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/pro/strsplit.pro: fixed STRSPLIT * src/basic_fun.cpp, src/datatypesref.cpp, src/hash.cpp: some fixed for HASH * src/dinterpreter.cpp, src/hash.cpp: sync 2013-07-23 m_schellens * src/hash.cpp, src/list.cpp, NEWS, src/dinterpreter.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: dot access for GDL_OBJECTs (left and right-side) 2013-07-22 alaingdl * src/basic_pro.cpp: adding working TRANSFER_COUNT keyword for READU/WRITEU, this is used in a procedure (BLKSHIFT) in the AstroLib (work by Nodar K.) * src/libinit.cpp: in RESTORE, we need to have obsolete keyword (without effect) for CMSVlib. 2013-07-21 m_schellens * NEWS, src/GDLInterpreter.hpp, src/basic_op.cpp, src/hash.cpp, src/overload.cpp: HASH complete 2013-07-19 m_schellens * src/hash.cpp, src/hash.hpp, src/overload.cpp: sync 2013-07-18 m_schellens * NEWS, src/basic_pro.cpp, src/hash.cpp, src/list.cpp, src/list.hpp: HASH::HASH___OverloadPlus (no structs yet) 2013-07-18 alaingdl * NEWS: initial import of CHOLSOL/CHOLDC and LA_CHOLSOL/LA_CHOLDC using Eigen3 (Work by Nodar K.) * src/matrix_cholesky.hpp, src/CMakeLists.txt, src/Makefile.am, src/datatypes.cpp, src/gsl_fun.hpp, src/libinit_jmg.cpp, src/matrix_cholesky.cpp: Initial import of CHOLSOL/CHOLDC and LA_CHOLSOL/LA_CHOLDC using Eigen3. This is not optimal because Eigen3 does not separate the steps, then computations are done 2 times. Work by Nodar K. Also temporary change in CONVOL to help compiling on older GCC compilers. 2013-07-18 m_schellens * src/gdlc.i.g, src/hash.cpp, src/hash.hpp, src/list.cpp, src/objects.cpp, src/objects.hpp, src/overload.cpp, src/prognode.cpp, src/GDLInterpreter.hpp, src/basegdl.hpp, src/datatypesref.cpp: HASH: ToStruct, Keys, Values, HasKey 2013-07-18 alaingdl * src/basic_fun.cpp, src/basic_fun.hpp, src/libinit.cpp: back to a working version for the CVS, due to files related to changes in CONVOL 2013-07-17 m_schellens * src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.hpp, src/hash.cpp, src/hash.hpp, src/libinit.cpp, src/list.cpp, src/overload.cpp: HASH::REMOVE (pre-alpha) 2013-07-17 alaingdl * src/convol.hpp, src/libinit.cpp: CONVOL: one file forgotten, one typo in new calling name * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/convol.cpp, src/datatypes.cpp, src/libinit.cpp, src/nullgdl.cpp, src/nullgdl.hpp: two new keywords managed inside CONVOL(): BIAS and NORMALIZE (see request in bug report 542). Work by Nodar K. 2013-07-17 m_schellens * src/gdlarray.hpp, src/hash.cpp, src/hash.hpp, src/list.cpp, src/objects.cpp, src/overload.cpp: HASH::_OverloadBracketsRightSide 2013-07-17 alaingdl * src/pro/write_png.pro: correcting bug 553 (good order for 2D image and R,G,B keywords) 2013-07-16 m_schellens * src/basic_pro.cpp, src/hash.cpp: fixed HELP output for arrays * src/basic_fun.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypesref.cpp, src/default_io.cpp, src/hash.cpp, src/hash.hpp, src/libinit.cpp, src/list.hpp: HASH (still alpha) 2013-07-15 m_schellens * src/nullgdl.hpp, src/objects.cpp, src/overload.cpp, src/prognode.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/hash.cpp, src/nullgdl.cpp: hash (pre-alpha) * src/prognodeexpr.cpp: fixed test_bug_3152829 2013-07-15 alaingdl * testsuite/CMakeLists.txt: including Orion' patch to catch when the test case fully crashes GDL. 2013-07-15 m_schellens * src/hash.cpp: sync * src/CMakeLists.txt, src/Makefile.am, src/hash.cpp, src/hash.hpp: add files for HASH 2013-07-13 m_schellens * NEWS: Full support of LIST * src/datatypesref.cpp: Fixed LIST::NewIx * src/GDLInterpreter.cpp, src/basic_pro.cpp, src/default_io.cpp, src/gdlc.i.g, src/list.cpp, src/list.hpp, src/prognode_lexpr.cpp: HELP and PRINT support for LIST * src/list.cpp, src/list.hpp, src/overload.cpp: full support for LIST except for PRINT and HELP * src/basic_fun.cpp, src/basic_op.cpp, src/basic_op_add.cpp, src/basic_op_sub.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/envt.cpp, src/envt.hpp, src/list.cpp, src/list.hpp, src/overload.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: added operations for LIST 2013-07-12 m_schellens * src/list.cpp, src/list.hpp, src/overload.cpp: LIST::REMOVE and LIST::REVERSE procedures 2013-07-12 alaingdl * src/Makefile.am: 4 missing files in "Makefile.am" for the "configure" way (OK on Debian stable) 2013-07-11 m_schellens * src/envt.cpp, src/envt.hpp, src/list.cpp, src/objects.hpp: Correct cleanup for LIST 2013-07-10 m_schellens * src/list.cpp, src/overload.cpp: ADD::REMOVE (still alpha) * src/basic_fun.cpp, src/list.cpp, src/list.hpp, src/overload.cpp: LIST::REMOVE (alpha version) 2013-07-09 m_schellens * src/list.cpp, src/list.hpp: add * src/CMakeLists.txt, src/GDLInterpreter.hpp, src/basic_fun.cpp, src/basic_pro.hpp, src/gdlc.i.g, src/overload.cpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/overload.hpp, src/specializations.hpp, src/datalistt.hpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp, src/dpro.cpp: LIST::ADD 2013-07-08 alaingdl * src/dinterpreter.cpp: switching back the default history to 200: convenient, and similar behavior on the other side ;-) * src/gsl_fun.cpp: In QROMB and QROMO, better management of keyword EPS=, thanks to patch 67. At the same time, correcting a long living bug in the order of parameters when calling GSL function : gsl_integration_qag(). Please report pbs !! 2013-07-05 alaingdl * testsuite/test_bug_3057520.pro, testsuite/test_bug_3275334.pro: just giving a message before exiting. 2013-07-04 m_schellens * src/envt.cpp, src/gdlarray.hpp, src/gdlc.i.g, src/objects.cpp, src/overload.cpp, src/GDLInterpreter.cpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/basic_pro_jmg.cpp: LIST (function and right[]) 2013-07-03 m_schellens * src/envt.hpp, src/gdlc.i.g, src/libinit.cpp, src/prognode.cpp, src/prognodeexpr.cpp, src/typedefs.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/deviceps.hpp, src/envt.cpp: fixed TEST_PS_DECOMPOSED 2013-07-02 alaingdl * testsuite/test_ce.pro, testsuite/test_python_module_0.pro, testsuite/test_python_module_1.pro: the field "!system.os_name" is now always in Lower Case. 2013-07-01 m_schellens * src/GDLInterpreter.cpp, src/arrayindex.cpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/basic_fun.hpp, src/envt.hpp, src/gdlc.i.g, src/libinit.cpp, src/objects.cpp, src/overload.cpp, src/prognode.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: fixed a = ptr_new(1) & *a= reform(*a, /over) & *a= reform(*a, /over) bug 2013-07-01 alaingdl * src/str.cpp: Work by Nodar K. One more attempt to better processing of space(s) within WordExp(). This time, names with multi consecutives spaces should be well managed. * src/file.cpp, src/file.hpp, src/libinit.cpp: import of internal C++ versions of FILE_BASENAME() and FILE_DIRNAME(), with a better management of (some) special chars. (e.g. see bug 550). * src/basic_pro.cpp: removing useless comment ! * src/pro/Makefile.am, src/pro/file_basename.pro, src/pro/file_basename_old.pro, src/pro/file_dirname.pro, src/pro/file_dirname_old.pro: moving into obsoleting names the two functions file_basename.pro file_dirname.pro to be substitute to C++ versions. 2013-06-29 m_schellens * src/datalistt.hpp, src/envt.hpp, src/libinit_cl.cpp, src/libinit_jmg.cpp, src/prognode.cpp: some more small optimizations * src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/gdlc.i.g, src/prognode_lexpr.cpp, src/GDLInterpreter.cpp: some optimizations * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/dpro.hpp, src/envt.hpp, src/gdlc.g, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: several optimizations 2013-06-26 gilles-duvert * src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.hpp, src/format.out.g, src/nullgdl.cpp, src/nullgdl.hpp, src/ofmt.cpp, src/specializations.hpp: first steps to support calendar format C(). * src/libinit.cpp: added CHANNEL as unsupported option for plot routines (was not present). Needs however to be fully supported. 2013-06-26 m_schellens * src/FMTTokenTypes.txt, src/basic_fun_jmg.cpp, src/cformat.g, src/libinit_mes.cpp, src/print.cpp, src/pro/str_sep.pro, src/CFMTLexer.cpp, src/CFMTLexer.hpp, src/CFMTTokenTypes.hpp, src/CFMTTokenTypes.txt, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/FMTLexer.cpp, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/FMTParser.cpp, src/FMTParser.hpp, src/FMTTokenTypes.hpp: fixed cformat issue (uncommented 'ALL') 2013-06-26 alaingdl * src/libinit.cpp: forgot to update helpKeys (re-ordered and also /path_cache and /help added) * src/basic_pro.cpp: in HELP, adding keywords /Path_cache and /help in JULDAY, full management of 3 to 6 inputs params. * src/envt.cpp, src/envt.hpp: /bin/bash: q: command not found (only available now in HELP pro and Besel functions !) 2013-06-24 m_schellens * src/envt.cpp, src/envt.hpp: FreeListT for EnvUDT * src/envt.cpp, src/envt.hpp, src/extrat.cpp, src/gsl_fun.cpp, src/math_fun.cpp, src/read.cpp, src/basic_fun.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypesref.cpp, src/dstructdesc.cpp: removed dynamic_cast<>s * src/gsl_fun.cpp: fixed bug #548 (HISTOGRAM,OMAX=value with BYTE) 2013-06-23 m_schellens * src/arrayindexlistnoassoct.hpp, src/gdlexception.cpp, src/gdlexception.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: made ARRAYEXPR node distinugish between indexee and index error. Needed for ARRAYEXPR_FCALL resolving. 2013-06-22 m_schellens * src/prognodeexpr.cpp: changed order to try in ARRAYEXPR_FCALL nodes 2013-06-21 m_schellens * src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/pro/smooth.pro, src/typedefs.hpp: memory management optimization 2013-06-18 gilles-duvert * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: Added JULDAY! 2013-06-17 m_schellens * src/assocdata.cpp, src/assocdata.hpp, src/datatypes.cpp, src/datatypes.hpp: sync * src/basic_pro.cpp, src/typedefs.hpp: cleanup * src/basic_pro_jmg.cpp, src/dstructdesc.hpp, src/gsl_fun.cpp, src/typedefs.hpp: fixed memeory leak in call_external 2013-06-14 alaingdl * src/file.cpp, src/str.cpp: trying to improve WordExp(), work by Nodar K. 2013-06-13 m_schellens * src/math_fun.cpp, src/ncdf_att_cl.cpp, src/fftw.cpp, src/gsl_matrix.cpp: fixed bug with wrong sizeof(long - should be Dlong) * src/basic_fun_cl.cpp: fixed mismatched new[] delete (removed the allocation) 2013-06-12 m_schellens * src/CFMTTokenTypes.hpp, src/CFMTTokenTypes.txt, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/FMTParser.cpp, src/FMTParser.hpp, src/FMTTokenTypes.hpp, src/FMTTokenTypes.txt, src/cformat.g, src/format.g, NEWS, src/CFMTLexer.cpp, src/CFMTLexer.hpp: fixed C string grammar (still not implemented) 2013-06-12 gilles-duvert * src/plotting.cpp, src/plotting.hpp: handle X11 window resizes better, writes [XYZ].REGION, uses !P.REGION etc. * src/plotting_plot.cpp: plot knows about !P.NSUM 2013-06-12 alaingdl * src/plotting.cpp: trying to manage !P.region when !P.position is equivalent to unset. 2013-06-11 m_schellens * NEWS, src/GDLInterpreter.hpp, src/arrayindex.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/gdl.cpp, src/gdlc.i.g, src/gdlexception.cpp, src/objects.cpp: Added .RESET_SESSION and .FULL_RESET_SESSION commands * src/dinterpreter.cpp, src/dinterpreter.hpp, src/gdlc.g, src/gdlc.i.g, src/graphics.cpp, src/objects.cpp, src/objects.hpp, src/GDLInterpreter.hpp, src/GDLLexer.cpp, src/GDLParser.cpp, src/arrayindex.hpp, src/dcommon.cpp: .RESET command (not complete yet); Fixed bug with ARRAYEXPR_FCALL and more than 8 parameters 2013-06-11 alaingdl * src/basic_fun_cl.cpp: fixing a small memory leak in SYSTIME() (Nodar) 2013-06-10 gilles-duvert * src/plotting.cpp: oops, small ticks were not small anymore... 2013-06-10 alaingdl * configure.in: updating the Configure way with new capabilities ralted to plplot. 2013-06-09 gilles-duvert * src/plotting.cpp: removed a memory loss * src/gdlgstream.hpp, src/gdlgstream.cpp: change in TranslateFormatCodes to avoid Valgrind complaining. previous version would return the c_str() of a std::string created in the function. Apparently the std::string is deleted on return, and the c_str() was pointing to a deallocated memory. Current version manages the string on the caller side. 2013-06-08 gilles-duvert * src/plotting_shade_surf.cpp: better defaults for shading lightsource. plplot's shading is definitely not very efficient, alas. * src/devicex.hpp: should solve bug 535 2013-06-07 gilles-duvert * src/plotting.cpp, src/plotting_axis.cpp: variant of gdlAxis to handle special case of AXIS command (to have correct ticklengths) * src/plotting_plots.cpp: bug in use of !P.T3D and 3 parameters * src/plotting.hpp, src/plotting_contour.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_polyfill.cpp, src/plotting_shade_surf.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp: support for use of !P.T3D * src/gshhs.cpp: temporarily solves ticket 474. A severe rewriting is needed to handle all the special projection cases especially for contour filling (poles, projection limits but also map levels: ponds in inslands in lakes in continents...) 2013-06-07 alaingdl * CMakeLists.txt: Better management of GM and IM: when GM available, using it. If GM not available, if IM available, using IM. The selection of IM or GM if both presents should still be possible (-DGRAPHICSMAGICK=off). Tested on CentOS and OSX. Patch by Nodar K. with Alain C. * CMakeModules/FindImageMagick.cmake: change in the file provided by CMake to support local install of IM (tested on CentOs and OSX) 2013-06-06 alaingdl * src/objects.cpp: fixing warning when computing Thread Numbers (NK) 2013-06-03 m_schellens * src/magick_cl.cpp: fixed memory leak in magick_write 2013-06-03 alaingdl * src/gdl.cpp, src/objects.cpp: when not compiled with Eigen3, must add in these 2 files. * src/plotting.cpp: needed on OSX with gcc 4.2.1 2013-06-01 m_schellens * src/basic_fun.cpp, src/gdlgstream.hpp: bugfix: replaced Guard with ArrayGuard 2013-05-31 gilles-duvert * src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: solves last bug on poly_2d #3613920 2013-05-30 alaingdl * src/basic_pro.cpp, src/gdl.cpp, src/objects.cpp, src/objects.hpp: On muticores with non null load, performances are strongly dependant to a pertinent choice of OMP_NUM_THREADS value. A mechanism is proposed to estimate a optimal value for the number of Threads, is applied at startup time and propagated into !cpu.TPOOL_NTHREADS (work by Nodar K.) 2013-05-30 gilles-duvert * src/plotting_windows.cpp: annotations * src/plotting_cursor.cpp: correct warping of pointer (command tvcrs) * src/gdlxstream.cpp: erase was not properly erasing window when subpages were present. Also, correct warping of pointer (command tvcrs) * src/gdlxstream.cpp, src/gdlgstream.hpp, src/gdlxstream.hpp, src/plotting.hpp: uses pixmap double-buffering provided by plplot to speed up operations with X11 windows. to be tested. could solve bug 3612116, also. 2013-05-29 alaingdl * src/basic_pro.cpp: in pro CPU, restore= and /reset are exclusive. 2013-05-26 gilles-duvert * src/plotting_shade_surf.cpp, src/plotting_surface.cpp, src/plotting_contour.cpp: solves bug #3613926 by removing unfortunate optimization 2013-05-25 gilles-duvert * src/plotting_surface.cpp, src/plotting_shade_surf.cpp: handles correctly combinations of min/max_values and zrange. 2013-05-24 gilles-duvert * src/plotting_contour.cpp: better handling of 1 contour and associated c_color vector * src/gsl_fun.cpp, src/interp_multid.h, testsuite/test_congrid.pro: solves bug #3612274! 2013-05-21 gilles-duvert * src/basic_pro.cpp, src/libinit.cpp: Support for MESSAGE, /REISSUE_LAST and corresponding HELP, /LAST_MESSAGE (used in, e.g., CoyoteGraphics library) * src/gdlgstream.hpp: change to enable compiling gdl on old plplot versions while a new feature depending on the presence of the 'pllegend' function has been added. 2013-05-18 cokhavim * src/gdlgstream.hpp: In gdlGetmmStringLength moved legend position to avoid showing up in postscripts * src/deviceps.hpp: Added improvements for encapsulated postscripts * src/gdlgstream.cpp: GetGeometry outpus incorrect dimensions for PS device * src/plotting.cpp: Increased default top margin slightly to accomodate subscripts and superscripts 2013-05-17 alaingdl * src/Makefile.am: Missing new filename "plotting_shade_surf.cpp" in src/Makefile.am 2013-05-16 gilles-duvert * config.h.cmake, CMakeLists.txt: change to enable compiling gdl on old plplot versions while a new feature depending on the presence of the 'pllegend' function has been added. * src/deviceps.hpp, src/devicesvg.hpp, src/devicex.hpp: due to popluar demand ;^), reinstalled colormap initialisation for colormap#1 in device[ps,x,svg]. * src/plotting.cpp: Patch for Bug item #3613383, 2013-05-16 alaingdl * src/basic_fun.cpp: removing extra "cout <<" * src/basic_fun.cpp, src/libinit.cpp: Initial management of /source keyword in ROUTINE_INFO() [bug report 3612842]. Not ready when no parameter provided (in that case, all compiled procedures or functions name/path informations must returned) 2013-05-16 gilles-duvert * src/devicex.hpp, src/plotting_windows.cpp: when opening several windows whose position are not given, dispatch them at the 4 corners of display in sequence. handy and mimics the (default) 'Tile' of IDL_GR_WIN_LAYOUT preference (such external preferences not being part of gdl yet) * src/plotting_xyouts.cpp: removed unnecessary warning 2013-05-16 alaingdl * src/gsl_fun.cpp: managing /Double keyword for INVERT() (patch by Nodar K.) 2013-05-15 gilles-duvert * CMakeLists.txt, config.h.cmake, src/gdlgstream.hpp, src/plotting_xyouts.cpp: Solves problems related to variable string lengths in XYOUTS (Hersey chars are not monospaced): if the plplot shared library contains the private function plstrl(), it is used. If not, (Ubuntu, debian) implemented a workaround by using a feature of pllegend(). Needs a full recompilation (after removing CMakeCache.txt and config.h). * doc/udg/README.txt: added infos about absent style files seemingly needed on my distro. 2013-05-14 alaingdl * src/pro/dialog_pickfile.pro: in gnome3, we need to tell to Zenity the current path :( 2013-05-13 gilles-duvert * src/plotting_xyouts.cpp: returned string width in option width= of xyouts is inexact since glyphs have a variable spacing. Added a warning about this. Since using plplot's private headers is not permitted (use of plstrl()) , one could consider adding the functionality to plplot (i.e., that plstrl() be public) or get access to a copy of the current PLStream structure and use its information. 2013-05-12 gilles-duvert * src/plotting.cpp: test patch: changed axis labelling to be clearer and more similar to original layout (exponents no more at end of axis etc). * src/plotting.hpp: removed some private structs from plotting.hpp to plotting.cpp 2013-05-10 gilles-duvert * src/plotting_polyfill.cpp, src/CMakeLists.txt, src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_convert_coord.cpp, src/plotting_erase.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp: Added almost full support for 3D plots in CONTOUR,PLOT,PLOTS,OPLOT,XYOUTS,SURFACE,SHADE_SURF,CONVERT_COORD,T3D,SCALE3,POLYFILL,SET_SHADING,AXIS(not complete). Still lacking 3D support:TV,TVSCL enabled /IRREGULAR for CONTOUR. * src/deviceps.hpp, src/devicesvg.hpp, src/devicex.hpp: removed colormap initialisation in device[ps,x,svg] since it seems to slow the display and does not appear to be needed. * src/plotting_windows.cpp: give window creation in "wset,0" same properties as a normal window (except backingStore) * src/plotting_shade_surf.cpp: adding shade_surf 2013-05-08 gilles-duvert * testsuite/CMakeLists.txt: Applied Orion's patch #3606092. Solves indeed the hangups of 'make check' when using CMake. 2013-05-07 m_schellens * CMakeLists.txt, CMakeModules/FindNetCDF.cmake, configure.in, src/ncdf_att_cl.cpp, src/ncdf_cl.hpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp: applied patch ID: 3608649 * src/basic_fun.cpp, src/datatypes.cpp, src/gsl_fun.cpp, src/math_fun_ac.cpp, src/math_fun_gm.cpp, src/math_fun_jmg.cpp, src/plotting.cpp, src/plotting_plot.cpp, src/plotting_polyfill.cpp: applied patch ID: 3612678 (with some mods) * src/antlr/LLkParser.cpp, src/gdlc.g: added some comments * src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/antlr/LLkParser.cpp, src/gdlc.g, testsuite/test_suite.pro: fixed deref for arrayexpr_mfcall (bug tracker ID: 3612104) 2013-05-06 gilles-duvert * src/deviceps.hpp: Added Joanna's patches #3612688 while reverting some code back to before rev.1.37 ( since forcing background erase in gdlpsstream.cpp rev. 1.7 was not a good solution to bug #361189) -- now we seem to have both PS and EPS color/bw landscape/portrait outputs generally quite good, * src/plotting_misc.cpp: Previous patch (inverting !P.COLOR and !P.BACKGROUND values when device=PS) had side effects. * src/gdlgstream.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp: Reverted last patch (1.6) -- forcing background erase was not a good solution. 2013-05-06 m_schellens * src/pro/read_ascii.pro: fixed DATA_START for READ_ASCII * src/libinit_cl.cpp: added missing KLISTEND 2013-04-30 gilles-duvert * src/plotting_misc.cpp: Joanna Patch item #3611949. thanks. * src/deviceps.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp, src/gdlgstream.hpp: Should solve Bug #3611897. By forcing background to erase the PS plot, one can have the correct background even on the first page. Note that now PS behave exactly as X, i.e., PS has also the option DECOMPOSED and color tables varies accordingly. 2013-04-29 alaingdl * src/deviceps.hpp: patch 3611949 by Joanna to restore Horizontal/Vertical placements in PostScript. * src/deviceps.hpp: better version for bug 3611898. I suspect we can play directly with Lun ... * src/deviceps.hpp: first attempt to solve bug report 3611898. But it is not enough 2013-04-26 alaingdl * src/deviceps.hpp: patch 3611864: two corrections: orientation (value for "sdiori" should be in expressed related to !pi/2) and color. 2013-04-24 alaingdl * CMakeLists.txt: in CMake way, if both packets present, we prefer to use GraphicsMagick than ImageMagick 2013-04-23 alaingdl * CMakeModules/FindGraphicsMagick.cmake, CMakeLists.txt: initial import of patch 3611651 to activate GraphicsMagick instead of ImageMagick in the CMake way. 2013-04-18 alaingdl * src/pro/online_help.pro: in ONLINE_HELP, activating book= and /full_path keywords, used inside HEALPix lib. 2013-04-11 gilles-duvert * src/libinit.cpp: changes related to options accepted now by plotting_surface. * src/plotting_surface.cpp: intermediate version before tackling the T3D transforms. 2013-04-11 alaingdl * testsuite/test_matrix_multiply.pro, testsuite/Makefile.am: new test for matrix multiplication, using matrix with rotation property. Types 14 and 15 are not ready on the GDL side due to INVERT(). May be INVERT has to be rewrite using Eigen3 ? 2013-04-11 gilles-duvert * src/plotting.cpp: solves bug #3610459 2013-04-11 alaingdl * src/pro/diag_matrix.pro: in DIAG_MATRIX(), type for output should be derived from the type of the input vector ! 2013-04-09 gilles-duvert * src/plotting_cursor.cpp: solves bug #3608752 2013-04-07 m_schellens * src/basic_op.cpp, src/datatypes.hpp, src/specializations.hpp: took change of Data_ template back (too early) 2013-04-04 m_schellens * src/dinterpreter.cpp: fixed usage of Guard * src/datatypes.hpp, src/math_fun_ac.cpp: added some clarifiying macros 2013-04-02 m_schellens * src/basegdl.hpp, src/math_fun_ac.cpp, src/prognodeexpr.cpp: refactored complex-double type promotion 2013-03-28 alaingdl * src/pro/matrix_multiply.pro: removing usage of MATMUL() 2013-03-27 m_schellens * src/datatypes.hpp, src/test_template_grouping.cpp: enabled default template parameters 2013-03-26 m_schellens * src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/math_fun_ac.cpp, src/prognodeexpr.cpp: eigen3 with matrix operator working * src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/libinit_ac.cpp, src/math_fun_ac.cpp, src/math_fun_ac.hpp, src/nullgdl.cpp, src/nullgdl.hpp, src/specializations.hpp: depoyed eigen3 for matrix operator (still buggy) 2013-03-25 m_schellens * src/GDLTreeParserTokenTypes.txt, src/arrayindex.hpp, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/gdlc.i.g, src/nullgdl.cpp, src/nullgdl.hpp, src/specializations.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp: test overload funtion with template 2013-03-25 opoplawski * CMakeLists.txt: Make cmake look for python 2 or PYTHONVERSION if specified * testsuite/test_ce.pro: Make test_ce.pro look in current directory for libtest_ce.so for cmake builds 2013-03-25 m_schellens * src/datatypes.cpp, src/datatypes.hpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_surface.cpp, src/prognode.cpp, src/typedefs.hpp, src/typetraits.hpp: fixed usage of Guard (replaced usage of operator=) 2013-03-25 alaingdl * src/datatypes.hpp: commenting c++11 line apparently not need/used now 2013-03-22 m_schellens * src/datatypes.hpp: commented out c++11 stuff * src/deviceps.hpp, src/devicex.hpp, src/dinterpreter.cpp, src/envt.cpp, src/envt.hpp, src/fftw.cpp, src/gdlarray.hpp, src/gdlc.i.g, src/gdlwidget.cpp, src/gsl_fun.cpp, src/gsl_matrix.cpp, src/magick_cl.cpp, src/math_fun.cpp, src/math_fun_ac.cpp, src/math_fun_gm.cpp, src/math_fun_jmg.cpp, src/ncdf_cl.cpp, src/ncdf_var_cl.cpp, src/newprognode.cpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_convert_coord.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp, src/print.cpp, src/prognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/pythongdl.cpp, src/read.cpp, src/typedefs.hpp, src/widget.cpp, CMakeLists.txt, src/GDLInterpreter.cpp, src/accessdesc.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp, src/dcompiler.cpp: replaced obsoleted std::auto_ptr with Guard 2013-03-21 m_schellens * src/basic_op.cpp, src/basic_op_add.cpp, src/basic_op_div.cpp, src/basic_op_mult.cpp, src/basic_op_new.cpp, src/basic_op_sub.cpp, src/datatypes.cpp, src/dstructgdl.cpp: moved DStructGDL invalid functions 2013-03-21 alaingdl * testsuite/test_bytscl.pro: initial of "test_bytscl.pro", not finished and not included in automatic test suite. We do have a problem when using /nan in BYTSCL() ... 2013-03-20 gilles-duvert * src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: Preparation for all (?) gridding-related functions that can (easily?) be added using QHULL Library which is also a dependency (optional) of plplot. * src/basic_fun.cpp: patched incorrect behaviour for TOP > 255. Possibly caused problems in (related) tvscl, hist_equal. 2013-03-19 m_schellens * src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/dpro.hpp, src/typedefs.hpp, src/typetraits.hpp: added new type trait IS_FLOAT * src/gdlarray.hpp, src/libinit_ac.cpp, src/math_fun_ac.cpp: un-uncommented some GDLArray members * src/gdlarray.hpp: fixed bug in GDLArray's allocation logic 2013-03-18 m_schellens * src/gdlarray.hpp, src/typedefs.hpp, src/typetraits.hpp: restructure and refactoring for easier addition of new types 2013-03-16 m_schellens * src/basic_op_add.cpp, src/basic_pro_jmg.cpp, src/datatypes.cpp, src/datatypes.hpp, src/specializations.hpp, src/typedefs.hpp, src/typetraits.cpp, src/typetraits.hpp, src/basegdl.hpp: refactoring, preparation for new types 2013-03-16 gilles-duvert * src/gdlgstream.cpp: patch should cure bug reported by AC (incorrect behaviour for !P.MULTI=[2,0,0]) 2013-03-14 alaingdl * src/math_fun_ac.cpp: continue being able to compile without Eigen3 2013-03-13 m_schellens * src/math_fun.cpp: deployed eigen3 for SQRT 2013-03-12 m_schellens * src/basic_op_add.cpp: own specialization adding a scalar string to avoid eigen usage * src/envt.hpp: added some const specifiers to ForLoopInfo * src/basic_op_add.cpp: fixed bug with string addition * src/CFMTLexer.cpp, src/cformat.g: applied change suggested by patch tracker ID: 3465879 * src/math_fun.cpp, src/overload.cpp, src/typedefs.hpp, src/basic_fun.cpp, src/basic_op.cpp, src/basic_op_add.cpp, src/basic_op_div.cpp, src/basic_op_mult.cpp, src/basic_op_new.cpp, src/basic_op_sub.cpp, src/basic_pro.cpp, src/convert2.cpp, src/datatypesref.cpp, src/fftw.cpp: introduced OMPInt for OpenMP loop variables * src/basic_op.cpp, src/basic_op_add.cpp, src/basic_op_div.cpp, src/basic_op_mult.cpp, src/basic_op_sub.cpp, src/ncdf_var_cl.cpp: updated some int to string conversions 2013-03-11 m_schellens * src/magick_cl.cpp, src/ncdf_cl.cpp, src/ncdf_var_cl.cpp: updated some int to string conversions 2013-03-10 m_schellens * src/basic_op.cpp, src/basic_op_new.cpp, src/math_fun.cpp: use eigen3 for + - and * * src/basic_op.cpp, src/basic_op_new.cpp, src/math_fun.cpp: use eigen3 for + - and * (incomplete) * src/libinit_ac.cpp, src/math_fun_ac.cpp, src/math_fun_ac.hpp, src/typedefs.hpp: deploy eigen3 noalias() 2013-03-09 gilles-duvert * src/libinit.cpp, src/plotting_device.cpp, src/plotting_windows.cpp: support for "RETAIN" in DEVICE. Will not really do anything useful, though, until some other patch informs plplot of the necessity to redraw the plot. 2013-03-08 m_schellens * src/ofmt.cpp: Fixed binary output format * src/plotting_oplot.cpp, src/arrayindex.hpp, src/basic_op.cpp, src/deviceps.hpp, src/gdlgstream.hpp, src/math_utl.hpp, src/ofmt.cpp, src/overload.cpp, src/plotting.cpp, src/plotting_contour.cpp: applied patch ID: 3606722 * src/math_fun_ac.cpp: sync 2013-03-08 alaingdl * src/math_fun_ac.cpp: in "math_fun_ac.cpp" being able to compile without Eigen3; 2013-03-08 m_schellens * src/math_fun_ac.cpp: refactoring for matmul_fun * src/math_fun_ac.cpp: correct output type for matmul_fun * src/math_fun_ac.cpp: optimization for matmul_fun * src/math_fun_ac.cpp: fix error message 2013-03-07 m_schellens * src/math_fun_ac.cpp: Aligned access in malmul_fun * src/dstructgdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/typedefs.hpp, src/dstructdesc.hpp, src/includefirst.hpp: alignment for eigne3 (also for structs) * src/datatypes.cpp, src/includefirst.hpp, src/math_fun_ac.cpp, src/math_fun_ac.hpp, src/typedefs.hpp: eigen3 alignment for GDLArray 2013-03-06 gilles-duvert * src/math_fun_ac.cpp: Last and final optimizations: directly address memory location using Map<> object instead of MatrixXX, added GDL_FLOAT case to speed up this last case. 2013-03-06 m_schellens * src/math_fun_ac.cpp: optimizations for MATMUL 2013-03-05 gilles-duvert * src/pro/matrix_multiply.pro: Modified matmul_fun to accept also complex and dcomplex matrices. Modified matrix_multiply accordingly. * src/math_fun_ac.cpp: Modified matmul_fun to accept also complex and dcomplex matrices. Behaviour is now idem idl for Vectors (implicit transposition) Acceleration even better due to Eigen's use of .transpose() and direct copy of arrays with memcpy(). 2013-03-05 alaingdl * src/pro/online_help.pro: is ONLINE_HELP, better management of default browser * src/pro/online_help.pro: details for ONLINE_HELP: trying to use default browser if any; "open" for OSX ... 2013-03-04 m_schellens * src/dinterpreter.cpp: removed: return CC_OK; for ? command :-) * src/dinterpreter.cpp: added: return CC_OK; for ? command 2013-03-04 alaingdl * src/pro/online_help.pro: ONLINE_HELP: correct help header; testing if computing node; managing void "name" input * src/pro/online_help.pro: limited changes in ONLINE_HELP, more to come. * src/dinterpreter.cpp: removing useless comments. * src/dinterpreter.cpp: activating "?" command, calling ONLINE_HELP (e.g.: ?fft) * src/pro/Makefile.am: I forgot to add these 2 files names here ... 2013-03-01 alaingdl * src/pro/doc_library.pro, src/pro/online_help.pro: initial import of DOC_LIBRARY (Feature request 3606434) and ONLINE_HELP procedures. 2013-02-28 m_schellens * src/arrayindexlistnoassoct.hpp, src/basic_fun.cpp, src/basic_op_new.cpp, src/envt.hpp: fixed extra allocation in Data_::PowIntNew. bug tracker ID: 3605947 2013-02-26 alaingdl * src/gsl_fun.cpp: temporary solution for bug report 3602623 related to inaccurary in bins computations for histograms in the GSL, sensitive on 64b versions ... 2013-02-25 alaingdl * src/ncdf_var_cl.cpp: correcting bug 3605899: creating big NetCDF files (> 4 GB). Tested OK on CentOS 5.8 64b by AC. 2013-02-20 alaingdl * testsuite/test_histo.pro: adding "TEST_UNITY_BIN_HISTO" procedure into "test_histo.pro" to trace bug 3602623. Up to now, this bug occurs only on 64b computers, not on 32b, GSL versions chenged nothing. * src/pro/interpol.pro: correcting small regression when testing size of inputs for INTERPOL(/spline) 2013-02-19 alaingdl * CMakeLists.txt, configure.in: for CMake, now default is trying to use Eigen3 if found in default place (/usr/include/eigen3) or if path provided (-DEIGEN3DIR= then checked and found) then same for Configure (--with-eigen3=). Both ways checked with success on U 12.04 with libeigen3-dev. 2013-02-18 alaingdl * src/pro/interpol.pro: correcting INTERPOL() when we have NaN or Inf values in third vector (bug 3602770) * CMakeModules/FindEigen3.cmake: initial input of this file for patch 3603806 (Eigen3 support in CMake) * CMakeLists.txt, config.h.cmake: applying patch 3603806 to have Eigen3 choice in CMake 2013-02-06 gilles-duvert * NEWS: update for summary of GD's recent changes * src/plotting_contour.cpp, src/plotting_plot.cpp: corrected regression: plot,findgen(4),color=0,background=255 would not change background correctly since it is changed only at subpage change, which was called before setting background value. To be checked for the other plotting functions on which i have not yet worked. 2013-02-05 alaingdl * INSTALL, NEWS, README: updating informative files about Eigen lib. usage. * src/libinit_ac.cpp, src/math_fun_ac.cpp, src/pro/matrix_multiply.pro: extension of MATMUL, to exploit /atranspose and /btranspose. Change into z=MATRIX_MULTIPLY() to switch with or without Eigen disponibility. 2013-02-05 m_schellens * src/basic_pro.cpp, src/libinit.cpp: started SOURCE_FILES keyword for HELP 2013-02-04 alaingdl * configure.in: managing Include Path for Eigen is still a work in progress, sorry ... * src/libinit_ac.cpp, src/math_fun_ac.cpp, src/math_fun_ac.hpp, configure.in: initial import of fast matrix multiplication code res=MATMUL(a,b) based on external library Eigen 2013-01-29 alaingdl * testsuite/Makefile.am: new "test_structures.pro" file for test suite 2013-01-29 gilles-duvert * src/devicex.hpp, src/graphics.hpp, src/plotting_windows.cpp: First pass to implement support for RETAIN=0,1,2 in window. Should be revised to fully mimic IDL's behaviour. Difficulty: backing store is noticeably device and OS dependent... 2013-01-29 m_schellens * testsuite/test_structures.pro, src/prognodeexpr.cpp: fixed indexed structure access. Bug tracker ID: 3601949 2013-01-28 alaingdl * testsuite/test_structures.pro: adding a test for internal indexing in structures, to avoid any future regression ... (was bug 3601949) 2013-01-26 gilles-duvert * CMakeLists.txt, config.h.cmake: should permit, through the use of HAS_PLPLOT_SLABELFUNC, to disable the user-format option for labels of axis in plplot, functionality which is at the basis of the support of [XYZ]TICKFORMAT, [XYZ]TICKNAME etc but which has only been introduced in plplot after 5.9.6 (as far as I can guess). 2013-01-25 gilles-duvert * src/plotting.cpp: severe regression corrected: 'x' modifier for plbox() is in plplot > 5.9.7 and does not replace the 't' option, only modifies it. I restore the 't' option (draw labels) and labels should reappear for older plplot versions. 2013-01-23 gilles-duvert * src/gdlxstream.cpp, src/devicex.hpp, src/gdlgstream.hpp, src/gdlxstream.hpp, src/graphics.hpp, src/libinit.cpp, src/plotting.hpp, src/plotting_cursor.cpp, src/plotting_device.cpp, src/plotting_windows.cpp: Added full support for CURSOR command, which is interruptible by control-c (rewrote the plplot's cursor function. Note that cursor as in plplot can be moved by the arrow keys with the modifiers keys as accelerators, useful for fine positioning and absent from idl). Now RDPIX procedure works. Added cursor-related functions TVCRS (for completeness: since PlPlot's X11 window is not fully event-driven the cursor positioning has no visible effect---help welcome), EMPTY (idem), DEVICE options CURSOR_CROSSHAIR, CURSOR_STANDARD, CURSOR_ORIGINAL and GET/SET_GRAPHICS_FUNCTION (GXoR, GXand, etc). Disabled by default the focus in the X11 graphics windows as idl does. * CMakeLists.txt, src/plotting.cpp: Modified plotting.cpp and CMakelists.txt to fix problem of absence of 'plslabelfunc()' in old plplot versions. * src/devicez.hpp: uncommented useful lines! 2013-01-14 m_schellens * src/envt.hpp: made call to member expilcit * src/basic_op.cpp: changed loop var to SizeT in MatrixOp 2013-01-13 alaingdl * src/pro/wmenu.pro, src/pro/zenity_check.pro: typos when improving ZENITY_CHECK() * src/pro/dialog_pickfile.pro, src/pro/wmenu.pro, src/pro/zenity_check.pro: fixing details in DIALOG_PICKFILE, WMENU and ZENITY_CHECK 2013-01-11 m_schellens * src/new.cpp: sync 2013-01-10 gilles-duvert * src/plotting.cpp, src/plotting.hpp: Support for [XYZ]Tickformat with format='an external function' or format='(a valid GDL format)'. The C() time format code and LABEL_DATE() functions have yet to be written for this part to be complete, however. 2013-01-09 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g: optimization setting \!ERROR_STATE * src/basic_pro.cpp, src/GDLInterpreter.cpp, src/gdlc.i.g, src/initsysvar.cpp, src/initsysvar.hpp, src/io.cpp: set \!ERROR_STATE 2013-01-08 m_schellens * src/basic_pro.cpp, src/gdlexception.hpp, src/io.cpp, src/gdlc.i.g, src/gdlexception.cpp, src/gdlxstream.cpp, src/GDLInterpreter.cpp, src/accessdesc.hpp, src/allix.cpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/datatypes.cpp: infrastructure for error codes 2013-01-08 alaingdl * doc/www/_news.inc.php: updating last builds (Gentoo, Debian); links. 2013-01-08 gilles-duvert * src/plotting.cpp: oops, DeviceToNorm should not be used, only DeviceTo NormedDevice is consistent with the rest of coordinates transforms unless special cases. 2013-01-08 m_schellens * src/basic_pro.cpp, src/GDLInterpreter.cpp, src/dinterpreter.cpp, src/envt.hpp, src/gdlc.i.g, src/gdlgstream.cpp, src/prognode.cpp: working CATCH 2013-01-08 gilles-duvert * src/plotting.cpp: solves bug 2880540 (plots the non-zero values of a dataset in logscale). 2013-01-07 m_schellens * src/GDLInterpreter.hpp, src/dinterpreter.cpp, src/gdlc.i.g, src/plotting_contour.cpp: refactoring 2013-01-05 gilles-duvert * src/plotting_plot.cpp: solves bug 2880540 (2nd part, plot,[-1,1],/ylog) * src/plotting.cpp: In view of bug 2880540 (solved), it is better for the time to avoid plplot getting loose on crazy coordinates. 2013-01-04 m_schellens * src/GDLInterpreter.hpp, src/accessdesc.hpp, src/dinterpreter.cpp, src/envt.cpp, src/gdlc.i.g, src/prognodeexpr.cpp: refactoring for GDL_OBJECT::Get/SetProperty 2013-01-04 gilles-duvert * src/plotting.cpp: plslabelfunc() and associated "o" option for custom axis labelling is not present until plplot v.5.9.5 I remove the few lines associated with the use of custom labeling with HAVE_PLPLOT_BEFORE_5994, but the labeling will be bad! Users should update their plplot version to the last one. * src/plotting_contour.cpp: removed attempt to record path, should solve problems arising from changes in fill() definition which varies with plplot versions. * src/plotting.cpp: supports request #3389025 in that !P.LINESTYLE works with CONTOUR. (not described in the IDL documentation, but the case nevertheless) 2013-01-03 gilles-duvert * src/gshhs.cpp, src/libinit.cpp, src/libinit_jmg.cpp, src/plotting_cursor.cpp, src/plotting_map_proj.cpp, src/plotting_surface.cpp: miminum set of changes to be compatible with new plotting routines etc. * src/plotting_misc.cpp: code layout changed as in NetBeans for readability. * src/plotting_device.cpp: gets /XSIZE etc options correctly to pass to, e.g., PS device. * src/plotting_plots.cpp: All keywords supported except Z and T3D Provides /CONTINUE Correct handling of log/DATA/NORMAL/DEVICE coordinates CLIP ok. * src/plotting_oplot.cpp: All keywords supported. Correct handling of log/DATA/NORMAL/DEVICE overplots CLIP ok. * src/plotting_polyfill.cpp: miminum changes to be compatible with new plotting.cpp version. Still lacking: IMAGE_COORD, IMAGE_INTERp, PATTERN, TRANSPARENT,T3D,Z. * src/plotting_xyouts.cpp: Support of all options except TEXT_AXES and T3D Better than IDL: ORIENTATION, ALIGNMENT, CHARSIZE, CHARTHICK and COLOR may be vectors. * src/plotting.cpp, src/plotting.hpp: large changes to provide new functionalities and use our overloading of several plplot functions. All symbols now exactly as IDL. * src/plotting_contour.cpp: Support of all options except ZVALUE, ZAXIS,CELL_FILL, C_ANNOTATIONS, CLOSED, DOWNHILL, IRREGULAR, TRIANGULATION,PATH_*** Correct implementation of Z, [X,Y], i.e., contours may be skewed, rotated, etc depending on X and Y. Better than IDL: - a new ZLOG option makes log contours as well. - C_ORIENTATION, C_SPACING are also vectors. - log axes give better results - good contouring of Not-A-Number values in Z and MIN_VALUE/MAX_VALUE - CLIP ok. Automatic limits in some cases still different from idl. * src/plotting_axis.cpp: Support of all 2D options (i.e., all X*** and Y***) Formatting of strings by XTICKFORMAT not yet working. TICKLAYOUT=2 not implemented * src/plotting_plot.cpp: Support of all 2D options except 'FONT' and 'T3D'. All symbols exactly as IDL. Formatting of strings by XTICKFORMAT not yet working. TICKLAYOUT=2 not implemented Automatic limits in some cases still different from idl. * src/graphics.hpp: SetColor() has now 1 arg. * src/gdlgstream.cpp, src/gdlgstream.hpp: overloading of many useful plplot functions to keep track of positions, sizes, etc. Possibly overkill. * src/gdlxstream.cpp: instrumented according to our overloading of several plplot functions. * src/gdlpsstream.hpp: better plplot options management * src/devicesvg.hpp: setup of initial values to satisfy our overloading of several plplot functions. * src/deviceps.hpp: setup of initial values to satisfy our overloading of several plplot functions. workaround for bugs in plplot+pslib drivers. Not entirely convincing though. * src/devicewin.hpp: setup of initial values to satisfy our overloading of several plplot functions. Not tested on windows. * src/devicez.hpp: setup of initial values to satisfy our overloading of several plplot functions. * src/devicex.hpp: defaulted initial position top right of screen. setup of initial values to satisfy our overloading of several plplot functions. * src/initsysvar.cpp: updated clip box values * src/pro/loadct.pro, src/image.cpp, src/image.hpp: command LOADCT supports BOTTOM, NCOLORS, RGB_TABLE, SILENT * src/gdlwidget.cpp: change needed to compile with my g++ 4.4.3 x86_64-manbo-linux-gnu (?) * src/envt.cpp, src/envt.hpp: added KeywordPresent with string instead of id. 2013-01-02 gilles-duvert * CMakeModules/Findlibps.cmake: needed to find libps on some 64 bits architectures 2013-01-02 alaingdl * doc/www/contribute.html, doc/www/credits.html, doc/www/download.html, doc/www/feedback.html, doc/www/home.html, doc/www/index.html, doc/www/menu.html, doc/www/require.html, doc/www/resources.html, doc/www/screenshot.html, doc/www/support.html, doc/www/tdl.html: small changes to be OK with http://validator.w3.org/ * doc/www/_news.inc.php, doc/www/credits.php, doc/www/faq.php, doc/www/menu.html: updating informations: 0.9.3 delivered (news), MSwin version, credit (JBPark) 2012-12-30 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/accessdesc.hpp, src/gdlc.i.g, src/prognodeexpr.cpp: refactorizations GDL 0.9.3: 2012-12-27 m_schellens * CMakeLists.txt, configure.in, src/GDLInterpreter.cpp, src/accessdesc.hpp, src/dstructgdl.cpp, src/gdlc.i.g, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: GDL 0.9.3 2012-12-21 m_schellens * src/gdlc.i.g, src/GDLInterpreter.cpp: replaced dynamic_cast * src/basic_op.cpp, src/basic_op_new.cpp, src/datatypes.hpp, src/overload.cpp, src/prognodeexpr.cpp, src/specializations.hpp: Added _overloadMinus for GDL_OBJECT 2012-12-20 m_schellens * src/math_fun_jmg.cpp: slight improvements for check_math_fun * src/math_fun_jmg.cpp: Fixed CHECK_MATH; bug tracker ID: 3597463 2012-12-19 m_schellens * src/basic_op.cpp, src/basic_op_new.cpp, src/datatypes.hpp, src/dinterpreter.cpp, src/overload.cpp, src/prognodeexpr.cpp, NEWS: completed _overloadPlus * src/datatypes.hpp, src/objects.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/specializations.hpp, src/typedefs.hpp, ChangeLog, NEWS, src/basegdl.hpp, src/basic_op.cpp: preparations for _overloadPlus 2012-12-18 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/dinterpreter.cpp, src/dinterpreter.hpp, src/objects.hpp: implemented .SKIP command * src/prognodeexpr.cpp, src/GDLTreeParser.cpp, src/gdlc.tree.g, src/prognode_lexpr.cpp: ARRAYEXPR_FCALL ambiguity some minor improvements 2012-12-18 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/dinterpreter.cpp, src/dinterpreter.hpp, src/objects.hpp: implemented .SKIP command * src/prognodeexpr.cpp, src/GDLTreeParser.cpp, src/gdlc.tree.g, src/prognode_lexpr.cpp: ARRAYEXPR_FCALL ambiguity some minor improvements 2012-12-17 m_schellens * src/GDLTreeParser.cpp, src/gdlc.tree.g, src/newprognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: Fixed ARRAYEXPR_FCALL ambiguity * src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g, src/gdlc.tree.g, src/newprognode.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLParser.cpp: in progress: ARRAYEXPR_FCALL ambiguity 2012-12-17 alaingdl * src/plotting_plot.cpp: Being able managning Log. plots with negative values only (bug report 3595172). Please notice PLplot is not able to manage "xtick/ytick" in plbox() when "l" option activated. 2012-12-13 m_schellens * src/GDLInterpreter.hpp, src/GDLParser.cpp, src/assocdata.hpp, src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/gdlc.g, src/gdlc.i.g, src/overload.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/specializations.hpp, src/typedefs.hpp: Added _overloadEQ and _overloadNE 2012-12-11 m_schellens * src/overload.cpp: A bit cleanup * src/allix.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basic_pro.cpp, src/dimension.hpp, src/envt.hpp, src/overload.cpp: Completed GDL_OBJECT::_overloadBracketsRightSide 2012-12-10 m_schellens * src/nullgdl.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: Changed some warning messages * src/arrayindexlistt.hpp, src/overload.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/typedefs.hpp: Corrections for bracketsLeftSideOverload. Prepared bracketsRightSideOverload. * src/dpro.cpp, src/dpro.hpp, src/overload.cpp: Changed DPro::AddPar(...) for prettier definition of internal UD subroutines * src/basic_fun.cpp, src/default_io.cpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/overload.cpp, src/prognode_lexpr.cpp: Added internal GDL_OBJECT::_overloadBracketsLeftSide procedure. * src/GDLInterpreter.cpp, src/gdlc.i.g, src/prognode.hpp, src/prognode_lexpr.cpp: avoid copy or rvalue for call of internal GDL_Object::_overloadBracketsLeftSide 2012-12-09 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/prognode_lexpr.cpp: Completed implementation of GDL_Object::_overloadBracketsLeftSide * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/datatypes.cpp, src/dcompiler.cpp, src/dnode.hpp, src/envt.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/newprognode.cpp, src/print_tree.cpp, src/prognode_lexpr.cpp, src/prognodeexpr.hpp: fixed constant array generation for array indices (compiled already from GDLTreeParser) * src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp: InitAsOverloadIndex member functions for ArrayIndexList... classes 2012-12-08 m_schellens * testsuite/test_stregex.pro, src/arrayindex.cpp, src/arrayindex.hpp: OverloadIndexNew member functions for [C]ArrayIndex... classes * src/GDLTreeParser.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/dcompiler.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, testsuite/test_suite.pro, src/GDLInterpreter.cpp: fixed (recently changed (for overload)) array indexing * src/dnode.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypesref.cpp, src/dcompiler.cpp, src/dcompiler.hpp, src/dinterpreter.cpp: Preparation of array indices (CArrayIndex...) for object overload indexing (keep original types of indices accessible) 2012-12-07 alaingdl * src/basic_fun.cpp: revisited MEDIAN code for dim= keyword. (TEST_NANS_IN_SORT_AND_MEDIAN and TEST_MINMAX both OK) 2012-12-06 m_schellens * src/ofmt.cpp, src/overload.cpp: fixed binary output for LONG64 * src/overload.cpp, src/GDLInterpreter.cpp, src/dpro.hpp, src/dstructdesc.hpp, src/gdlc.i.g, src/objects.cpp, src/overload.hpp, src/prognode.cpp, src/prognode.hpp: full implementation of GDL_OBJECT::_overloadIsTrue function 2012-12-05 m_schellens * src/typedefs.hpp: removed debug setting * src/gsl_fun.cpp, src/typedefs.hpp: proper return value conversion for GDL function used by QROMB * src/dpro.cpp, src/gsl_fun.cpp: fixed memory leak in QROMB function. Bug tracker ID: 3592762 * src/GDLInterpreter.hpp, src/dpro.cpp, src/dpro.hpp, src/gdlc.i.g, src/overload.cpp, src/prognode.cpp, src/prognode.hpp: Implemented WRAPPED_FUN/PRONode (call c++ functions as GDL subroutines) 2012-12-04 m_schellens * src/print_tree.cpp, src/basic_pro.cpp, src/dpro.cpp, src/dpro.hpp, src/libinit.cpp, src/print_tree.hpp: fixed print_tree for circular ProgNodeP trees * src/dinterpreter.cpp, src/dpro.cpp: disabled debug output for CVS * src/dinterpreter.cpp, src/dpro.cpp, src/prognode.hpp: Fixed: BREAK when loop is last statement in subroutine 2012-12-02 m_schellens * src/datatypes.cpp, src/nullgdl.hpp: rename IsNULL function * src/GDLInterpreter.hpp, src/basic_pro_jmg.cpp, src/datatypes.cpp, src/dinterpreter.cpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/gsl_fun.cpp, src/math_fun_ng.cpp, src/nullgdl.cpp, src/nullgdl.hpp, src/specializations.hpp, src/widget.cpp: implemented _overloadIsTrue 2012-12-01 m_schellens * src/GDLParser.cpp, src/gdlc.g, src/objects.cpp, src/objects.hpp, src/prognode.cpp: made GDL_OBJECT's name a constant 2012-11-30 m_schellens * src/prognode.cpp, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/dcompiler.cpp, src/dstructdesc.cpp, src/dstructdesc.hpp, src/gdlc.g, src/gdlexception.cpp, src/objects.cpp, src/overload.cpp, src/overload.hpp: full infrastructure for operator overloading (not depoyed yet) 2012-11-29 m_schellens * src/prognodeexpr.cpp, src/topython.cpp, src/typetraits.cpp, src/CMakeLists.txt, src/Makefile.am, src/accessdesc.hpp, src/assocdata.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/basic_pro_jmg.cpp, src/convert2.cpp, src/datatypes.cpp, src/dstructdesc.cpp, src/dstructdesc.hpp, src/envt.cpp, src/envt.hpp, src/gdlexception.cpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun_jmg.cpp, src/ncdf_var_cl.cpp, src/nullgdl.cpp, src/objects.cpp, src/overload.cpp, src/overload.hpp: operator overloading (only basic definitions - not supported yet) 2012-11-28 alaingdl * src/basic_pro.cpp, src/libinit.cpp, src/objects.cpp: Initial (unfinished) import of keyword /pref in HELP * src/preferences.hpp, src/Makefile.am, src/preferences.cpp: very preliminary (and not working) import of a way to process external text files for setting variables like GDL_GR_X_HEIGHT (ToDo: SET_PREF/GET_PREF) 2012-11-27 alaingdl * src/gdl.cpp, doc/gdl.1: preparing ingesting external preference file (gdl -pref=/path/to/PrefFile) 2012-11-26 alaingdl * src/pro/zenity_check.pro: setting !zenity.version to -1 when no Zenity found. Used in WMENU() 2012-11-25 alaingdl * src/pro/save.pro: extending SAVE from 30 params to 100. Only limited tests done ... 2012-11-21 alaingdl * configure.in: applying patch from Debian (0.9.2-4 fix-muldefs) * doc/gdl.1: applying patch from Debian 0.9.2-4 (hyphen-used-as-minus-sign and one typo) 2012-11-21 m_schellens * src/io.cpp, src/io.hpp, src/objects.cpp: Fixed GET_LUN bug (TEST_GET_LUN) 2012-11-20 m_schellens * src/objects.cpp: added some struct descriptors (commented out) 2012-11-20 alaingdl * src/libinit.cpp: in DEVICE, warning keyword TRUE_COLOR (for compatibility with Pluto 4.0 code) * src/devicex.hpp: typo: removing double declaration * src/devicex.hpp: desactivating useless debuging "cout << " * src/plotting_device.cpp: missing WordExp() when writing SVG or PS files. * src/magick_cl.cpp: missing WordExp() in MagickPing and MagickWrite; now we can query and write in ~/ directory ! 2012-11-19 alaingdl * src/pro/Makefile.am, src/pro/wmenu.pro: initial import of WMENU(), with a Zenity based version (working) and a text-based version (to be verified ASAP) 2012-11-16 alaingdl * src/pro/dialog_message.pro: correcting compatibility issues with old zenity versions in DIALOG_MESSAGE 2012-11-15 alaingdl * src/pro/dialog_message.pro, testsuite/test_dialog_message.pro: finishing refinements in DIALOG_MESSAGE and related test cases in TEST_DIALOG_MESSAGE 2012-11-15 m_schellens * src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/basic_fun_jmg.hpp, src/libinit_jmg.cpp, src/prognodeexpr.cpp: fixed ROUTINE_NAMES,/FETCH (lead to crash in cmsvlib) 2012-11-15 alaingdl * src/pro/dialog_message.pro, src/pro/zenity_check.pro: revised DIALOG_MESSAGE but not fully finished; new !zenity structure to be faster and with less redundant messages when using obsolete zenity code * testsuite/test_dialog_message.pro: initial import of TEST_DIALOG_MESSAGE, interactive tests case for revisited DIALOG_MESSAG. 2012-11-14 alaingdl * src/pro/Makefile.am: stupid typo in new function name :( * src/pro/dialog_pickfile.pro: updating DIALOG_PICKFILE: large part of code moved into ZENITY_CHECK() * src/pro/dialog_message.pro: updating DIALOG_MESSAGE: large part of code moved into ZENITY_CHECK() * src/pro/Makefile.am, src/pro/zenity_check.pro: creating ZENITY_CHECK(), a function checking the availability of "zenity" in the path and also checks the version. This code was common in DIALOG_PICKFILE and DIALOG_MESSAGE and this should help for future maintenance and extensions 2012-11-13 alaingdl * src/pro/restore.pro: in RESTORE, fixing feature request 3581835 and various tricks around filename 2012-11-13 m_schellens * src/antlr/LLkParser.cpp, src/antlr/Parser.cpp, src/antlr/Parser.hpp: sync 2012-11-12 alaingdl * config.h.cmake: tuning HAVE_PLPLOT_BEFORE_5994 to have success on more than Debian ;-) * configure.in, src/plotting_xyouts.cpp: tuning HAVE_PLPLOT_BEFORE_5994 to have success on latest Debian too ;-) 2012-11-12 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g: Line numbers in IF statements; bug tracker ID: 3579702 * testsuite/test_suite.pro, src/GDLParser.cpp, src/gdlc.g: parser error with: tmp=cos(str.data(0).value); bug tracker ID: 3579499 * src/prognodeexpr.cpp, src/typedefs.hpp: Fixed segfault with undefined variable; bug tracker ID: 3585392 2012-11-10 alaingdl * CMakeLists.txt: first attempt managing recent plplot lib. with CMake ... * src/plotting_xyouts.cpp: typo in plotting_xyouts.cpp 2012-11-09 alaingdl * src/plotting_xyouts.cpp, configure.in: trying to manage hidden symbols in recent Debian plplot 5.9.9-4 in XYOUTS; patch 3575295 from Joanna 2012-11-07 slayoo * configure.in: removing color-tests from configure.in - it causes problems, and the autotools-based install is anyhow going to be obsoleted soon... 2012-11-07 alaingdl * doc/www/resources.php: updating ADASS refs * doc/www/credits.php: adding my 2 students this summer 2012 * src/antlr/LLkParser.cpp: desactiviating verbose mode in interpretor "trace" ! 2012-11-07 slayoo * gsl.m4: removing the gsl.m4 file * src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in, testsuite/Makefile.in, depcomp, doc/Makefile.in, install-sh, ltmain.sh, missing, mkinstalldirs, src/Makefile.in, INSTALL, Makefile.cvs, Makefile.in, aclocal.m4, config.guess, config.h.in, config.sub, configure: removing autotools-generated files from the repository * AUTHORS, doc/udg/chapters/credits.tex, doc/www/credits.php: adding Gilles to the author lists 2012-11-06 m_schellens * src/antlr/LLkParser.cpp, src/GDLParser.cpp, src/gdlc.g: nicer tracing 2012-10-29 gilles-duvert * src/interp_multid.h: Solved bug keyword "Missing" not working for upper side in 1D INTERPOLATE. The range for interpolation was deemed valid including the upper boundary, when in IDL thid is not the case. 2012-10-18 alaingdl * src/pro/str_sep.pro, testsuite/test_str_sep.pro: improvment of STR_SEP, should be OK for Separator with more than one element. Unfinished for pecular cases with one element. * testsuite/test_str_sep.pro: adding news cases failing with current STR_SEP code (to be updated soon ;-) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_get_lun.pro: inclusion of "test_get_lun.pro" in the "make check" test suite. Currently, this test fails. 2012-10-12 m_schellens * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: HEAP_FREE initial version 2012-10-10 alaingdl * testsuite/test_deriv.pro, src/pro/deriv.pro: continuing cleaning DERIV() 2012-10-09 m_schellens * HACKING, src/deviceps.hpp, src/gshhs.cpp, src/typedefs.hpp: renamed GSLGuard to GDLGuard; redefined FILEGuard 2012-10-09 alaingdl * testsuite/test_qromo.pro, src/gsl_fun.cpp: improving QROMO when diverging at one of the boundaries: switch from QAG to QAGS. General case not ready, but testsuite improved ... * src/pro/deriv.pro: better behavior, we desactivate extra checks ... 2012-10-08 alaingdl * src/typedefs.hpp: missing for Ubuntu OS ... * src/gsl_fun.cpp: in QROMO, allowing paired sizes for inputs [1][N] or [N][1] should give [N] 2012-10-05 m_schellens * src/gsl_fun.cpp, src/typedefs.hpp: Fixed several memory leaks 2012-10-04 m_schellens * src/deviceps.hpp, src/gshhs.cpp, src/gsl_fun.cpp, src/gsl_matrix.cpp, src/math_fun.cpp, src/typedefs.hpp, CMakeModules/Findlibps.cmake: removed LIBPS_LIBRARY_DIRS from CMake pslib stuff; added exception savety 2012-10-03 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_nans_in_sort_and_median.pro: Why this important test on MEDIAN() and SORT() with NaN wasn't in the automatic test suite ? We do have a serious problem ! * testsuite/test_random.pro, testsuite/test_wait.pro: typos: STOP forgot in "test_random"; wait is unaccurate on Suse :( 2012-10-02 m_schellens * src/CFMTLexer.cpp, src/CFMTLexer.hpp, src/CFMTTokenTypes.hpp, src/CFMTTokenTypes.txt, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTParser.cpp, src/FMTParser.hpp, src/FMTTokenTypes.hpp, src/FMTTokenTypes.txt, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/format.out.g: Fixed : format code; Bug ID: 3572473 * src/basic_fun.cpp, src/envt.cpp, src/envt.hpp, src/typedefs.hpp: Fixed SCOPE_VARFETCH; Bug tracker ID: 3573558 * src/basegdl.hpp: include xdr.h for windows, rpc.h otherwise * src/read.cpp: fixed READ; bug tracker ID: 3573790 2012-10-02 alaingdl * src/basegdl.hpp: reverting change in "basegdl.hpp" (bug 3573468) for #include (we cannot compile on OSX with #include ) * src/gsl_fun.cpp: two problems in RANDOM: checking when amplitude for Binonial is below 1; removing regression introduced mid-july when "seed" is not set outside. * testsuite/test_random.pro: improvment in "test_random.pro": being less sensitive for small amp. in Binomial; introducing new basic tests to check very basic regressions ... * testsuite/test_wait.pro: relaxing tol. error for TEST_WAIT 2012-10-01 alaingdl * testsuite/test_scope_varfetch.pro: following bug report 3573558: extended test cases for SCOPE_VARFETCH * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_ptrarr.pro: initial import of "test_ptrarr.pro", related to bug report 3573202 2012-10-01 m_schellens * src/arrayindexlistnoassoct.hpp: Fixed salar array indexing (return scalar if all indices are scalar); bug tracker ID: 3573202 2012-09-28 alaingdl * src/gtdhelper.cpp, src/gtdhelper.hpp: initial import of 2 missing files for compilation under MSwin. * CMakeModules/FindPCRE.cmake, CMakeModules/FindXdr.cmake: initial import of 2 missing CMake-related files for compilation under MSwin: FindPCRE.cmake FindXdr.cmake 2012-09-20 alaingdl * testsuite/test_fft_dim.pro: deeper test cases for DIM keyword in FFT * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_systime.pro, testsuite/test_wait.pro: 3 new tests in automatic "make check". * testsuite/test_call_function.pro, testsuite/test_call_procedure.pro: following idea in bug report 3569697, improved tests (on keyword values too) for CALL_FUNCTION and CALL_PROCEDURE 2012-09-19 m_schellens * testsuite/test_call_function.pro, testsuite/test_call_procedure.pro, configure: sync * src/GDLInterpreter.cpp, src/gdlc.i.g: New GDL_... type codes for ANTLR files * src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLLexer.cpp, src/GDLTokenTypes.hpp, src/GDLTreeParserTokenTypes.hpp, src/envt.cpp, src/extrat.cpp, src/extrat.hpp: Fixed keyword handling for CALL_FUNCTION and CALL_PROCEDURE (when calling user defined subroutines) * src/extrat.cpp: Fixed behaviour of _EXTRA (bug tracker ID: 3568388) 2012-09-18 alaingdl * src/basic_op.cpp: better accuracy in Modulo with Double * src/file.cpp, src/file.hpp, src/libinit.cpp: recovering FILE_SEARCH for non MSwin OS * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: recovering SPAWN capability under non-MSwin OS 2012-09-18 m_schellens * src/math_fun_gm.cpp, src/math_fun_jmg.cpp, src/math_fun_ng.cpp, src/nullgdl.cpp, src/ofmt.cpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_map_proj.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_windows.cpp, src/read.cpp, src/semshm.cpp, src/sigfpehandler.cpp, src/sigfpehandler.hpp, src/str.cpp, CMakeLists.txt, src/CMakeLists.txt, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_pro.cpp, src/basic_pro.hpp, src/basic_pro_jmg.cpp, src/basic_pro_jmg.hpp, src/color.cpp, src/convert2.cpp, src/datatypes.cpp, src/datatypes.hpp, src/default_io.cpp, src/deviceps.hpp, src/devicewin.hpp, src/devicez.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/dnode.cpp, src/file.cpp, src/file.hpp, src/gdl.cpp, src/gdlgstream.hpp, src/gdljournal.cpp, src/gdlpsstream.hpp, src/gdlwidget.hpp, src/gdlwinstream.hpp, src/graphics.cpp, src/grib.cpp, src/gsl_fun.cpp, src/includefirst.hpp, src/initsysvar.cpp, src/io.cpp, src/io.hpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun_ac.cpp: applied patches 2 and 3 from tracker ID 3568748 (windows compatibility) * HACKING: remarks on exception save programming * src/math_fun_ng.cpp, src/prognode_lexpr.cpp, src/allix.cpp: sync 2012-09-18 alaingdl * testsuite/test_extra_keywords.pro: new file TEST_EXTRA_KEYWORD to test whether the _extra keywords are well managed. 2012-09-18 m_schellens * src/dll/two.cpp, src/arrayindexlistt.hpp, src/assocdata.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/basic_op.cpp, src/basic_op_new.cpp, src/basic_pro.cpp, src/basic_pro_jmg.cpp, src/convert2.cpp, src/datatypes.cpp, src/datatypesref.cpp, src/default_io.cpp, src/devicex.hpp, src/dstructdesc.cpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/envt.cpp, src/envt.hpp, src/extrat.cpp, src/extrat.hpp, src/fftw.cpp, src/gdlpython.cpp, src/gdlxstream.cpp, src/gsl_fun.cpp, src/gsl_matrix.cpp, src/hdf_fun.cpp, src/magick_cl.cpp, src/math_fun.cpp, src/math_fun_ac.cpp, src/math_fun_gm.cpp, src/math_fun_jmg.cpp, src/math_fun_ng.cpp, src/math_utl.cpp, src/math_utl.hpp, src/ncdf_att_cl.cpp, src/ncdf_cl.cpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp, src/nullgdl.cpp, src/ofmt.cpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_convert_coord.cpp, src/plotting_map_proj.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_surface.cpp, src/plotting_windows.cpp, src/plotting_xyouts.cpp, src/print.cpp, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/pythongdl.cpp, src/read.cpp, src/strassenmatrix.hpp, src/topython.cpp, src/typedefs.hpp, src/typetraits.cpp, src/widget.cpp, src/FMTIn.cpp, src/FMTInTokenTypes.hpp, src/FMTLexer.cpp, src/FMTOut.cpp, src/FMTOutTokenTypes.hpp, src/FMTParser.cpp, src/FMTTokenTypes.hpp, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLLexer.cpp, src/GDLTokenTypes.hpp, src/GDLTreeParserTokenTypes.hpp, src/accessdesc.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistnoassoct.hpp: applied patch 1 from tracker ID: 3568748 (rename GDL types to GDL_...) 2012-09-18 alaingdl * testsuite/test_call_function.pro, testsuite/test_call_procedure.pro: adding more explicit messages when problems encoutered runnning TEST_CALL_FUNCTION and TEST_CALL_PROCEDURE * testsuite/test_call_procedure.pro: adding explicit messages when problems encoutered 2012-09-16 alaingdl * src/plotting.cpp: applying patch 3567803 by S. Hony for histogram plot. 2012-09-14 alaingdl * CMakeModules/FindNetCDF.cmake, CMakeModules/Findlibps.cmake, CMakeLists.txt: including patch 3538449 for CMake way (better way to find external libs. NetCDF and LibPS) * src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/objects.cpp, src/widget.cpp, src/widget.hpp, NEWS: applying patch 3567344: new widgets WIDGET_LIST and CW_GROUP 2012-09-13 m_schellens * src/read.cpp: skip till end of line when reading multiple parameters with READF 2012-09-13 alaingdl * src/gsl_fun.cpp: fixing general case in FFT() when using GSL way only 2012-09-12 m_schellens * src/gsl_fun.cpp: fixed memeory leak in random_template 2012-09-12 alaingdl * testsuite/test_fft.pro, testsuite/test_fft_dim.pro: test cases for FFT, unfinished :( 2012-09-11 m_schellens * src/basegdl.hpp, src/basic_fun.cpp, src/envt.cpp, src/extrat.cpp, src/gsl_fun.cpp, src/nullgdl.cpp, src/nullgdl.hpp: fixed several memory leaks in fft_template (gsl fft version) 2012-09-09 alaingdl * testsuite/test_fft.pro, src/gsl_fun.cpp: FFT in the GSL way was not OK when input was in double * NEWS, src/gsl_fun.cpp: sorry, I put the wrong version for corrected FFT using GSL ... 2012-09-07 slayoo * src/convert2.cpp: fixing overzealous error-reporting in convert2.cpp version 1.30 - see bug no. 3565657 (thanks Gilles) 2012-09-07 alaingdl * src/gsl_fun.cpp: various changes for FFT(): should work for DIMENSION keyword and when FFTw is not used. More test cases especially when DIM is used are needed. * src/envt.cpp: EnvT::KeywordSet() (in "envt.cpp") must behave as KEYWORD_SET() in "basic_fun.cpp". 2012-09-07 gilles-duvert * testsuite/test_bug_3483402.pro: add test_bug_3483402.pro , closes the corresponding ticket. * testsuite/Makefile.am: added testsuite/test_bug_3483402.pro 2012-09-05 gilles-duvert * src/plotting.cpp: box aspect correct with /ISOTROPIC and /[X|Y]LOG * src/plotting_oplot.cpp: Should solve bug #3563928. 2012-09-04 gilles-duvert * src/plotting.cpp: Modified support for '/ISOTROPIC' in graphic commands to align boxes more in the IDL style. * src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_contour.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_surface.cpp: Support for '/ISOTROPIC' in graphic commands. 2012-08-30 alaingdl * src/basic_fun.cpp, src/libinit.cpp: adding keyword /Double in function COMPLEX() 2012-08-18 slayoo * src/convert2.cpp, src/dnode.cpp, testsuite/Makefile.am, testsuite/test_bug_3559291.pro: fixing bug no. 3559291 (float('1.5D-1') != 0.15) 2012-08-17 alaingdl * configure.in: sorry for not updated the main "configure.in" including src/pro/envi/Makefile 2012-08-16 alaingdl * src/devicex.hpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/libinit.cpp, src/plotting_windows.cpp, NEWS: Initial import of keyword ICONIC in WSHOW. The SHOW param. is not efficient ? Help welcome to fix the sub-window value when iconifying. 2012-08-14 alaingdl * src/pro/read_bmp.pro, src/pro/read_gif.pro, src/pro/read_image.pro, src/pro/read_jpeg.pro, src/pro/read_pict.pro, src/pro/read_png.pro, src/pro/read_tiff.pro, src/pro/read_xwd.pro, src/pro/strmatch.pro, src/pro/strsplit.pro: Since now GDL enforces scalar type in FOR loop, we have to take care with STRLEN when the input is a one element array. All the READ_(images) procedures don't really checked whether we try to read back more than one and only one file * src/pro/Makefile.am, src/pro/Makefile.in: fixing details in MakefileS related to new Envi sub-dir. 2012-08-13 alaingdl * src/pro/image_statistics.pro: adding Labeled keyword to the IMAGE_STATISTICS procedure, thanks to Sixy6e 2012-08-12 alaingdl * NEWS, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/STATUS, src/pro/UrgentNeed.txt, src/pro/rot.pro: initial import of ROT, calling internal POLY_2D code * NEWS: few updates in NEWS 2012-08-11 alaingdl * src/pro/write_jpeg.pro, src/pro/write_png.pro: revisiting buggy WRITE_JPEG and WRITE_PNG: gray images can now be stored, but not via best pure Gray type; Order was activated for missing cases in WRITE_PNG (tested on Saturn.jpg for WRITE_JPEG and WRITE_PNG, color and Gray) 2012-08-02 gilles-duvert * src/pro/mean.pro: patched MEAN so it continues to work with non-arrays. 2012-08-02 m_schellens * src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/prognode.cpp, src/specializations.hpp, NEWS, README: Promotion of FOR loop index variable type 2012-07-25 m_schellens * src/basic_fun.cpp, src/prognodeexpr.cpp: Improved SCOPE_VARFETCH * src/basic_fun.cpp, src/basic_fun.hpp, src/basic_fun_jmg.cpp, src/basic_fun_jmg.hpp, src/datatypes.cpp, src/libinit.cpp, src/libinit_jmg.cpp, src/prognodeexpr.cpp: Fixed SCOPE_VARFETCH 2012-07-24 alaingdl * src/pro/interpol.pro: detail of test version in INTERPOL, sorry * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/interpol.pro: since "scope_varfetch.pro" was removed from src/pro/, we need to removed it in the Makefile.(am/in) 2012-07-24 slayoo * src/pro/scope_varfetch.pro: removing GDL-written version of scope_varfetch from the repository 2012-07-24 m_schellens * NEWS: Update NEWS * src/gdlc.tree.g, src/libinit_jmg.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/basic_fun_jmg.cpp, src/basic_fun_jmg.hpp, configure: Working trinary operator for undefined l-values. SCOPE_VARFETCH (only LEVEL keyword). 2012-07-23 m_schellens * src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp: trinary operator redefined, working for r-values only. L-value support to be done * src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/Makefile.in, src/datatypes.cpp, src/datatypesref.cpp, src/dcompiler.cpp, src/dcompiler.hpp, src/gdl.cpp, src/gdlc.tree.g, src/gsl_fun.cpp, src/gsl_matrix.cpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun_jmg.cpp, src/prognodeexpr.cpp, HACKING, NEWS, README, configure.in: Proper error handling for GSL. Some minor corrections. 2012-07-22 m_schellens * src/nullgdl.cpp, src/nullgdl.hpp: add files for \!NULL 2012-07-21 m_schellens * src/CMakeLists.txt, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/Makefile.am, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/basic_pro_jmg.cpp, src/datalistt.hpp, src/datatypes.cpp, src/default_io.cpp, src/dnode.cpp, src/dvar.cpp, src/envt.cpp, src/extrat.hpp, src/gdlc.g, src/gdlc.tree.g, src/gdlwidget.cpp, src/grib.cpp, src/gsl_fun.cpp, src/gsl_matrix.cpp, src/hdf_pro.cpp, src/initsysvar.cpp, src/libinit.cpp, src/ncdf_att_cl.cpp, src/ncdf_cl.cpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp, src/plotting_misc.cpp, src/prognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/pythongdl.cpp, src/typedefs.hpp, src/typetraits.cpp, src/widget.cpp: \!NULL sysvar (full support). Proper error handling for GSL functions (set up framework + partial implementation) 2012-07-18 m_schellens * src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp: Fixed array indexing with negative scalars (introduced in last commit) 2012-07-17 m_schellens * src/pythongdl.cpp: Fixed compile error when compiled as python module. * src/GDLTreeParser.cpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/basegdl.hpp, src/dcompiler.cpp, src/dimension.hpp, src/gdlc.tree.g, src/prognode.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: Fixed lvaue handling for parameters with trinary operator. Fixed return of scalar/single element array for array indexing. 2012-07-16 m_schellens * src/gdlc.i.g, src/GDLInterpreter.cpp, src/envt.cpp, src/envt.hpp, src/extrat.cpp, src/extrat.hpp: Fixed keyword parameters to CALL_FUNCTION and CALL_PROCEDURE 2012-07-14 alaingdl * testsuite/test_moment.pro: is this way, can work with GDL, new 8 and old IDL versions * src/gsl_fun.cpp: typo ... * src/gsl_fun.cpp, src/pro/moment.pro, testsuite/test_moment.pro: validity of Dimension keyword is now tested ASAP in MOMENT(); visual tests for this keyword; a cout less in FZ_ROOTS ... 2012-07-14 m_schellens * src/GDLInterpreter.cpp, src/arrayindex.hpp, src/gdlc.i.g: fixed bug with array indexing in lhs dot expressions 2012-07-13 alaingdl * NEWS: news in NEWS ! * src/pro/kurtosis.pro, src/pro/mean.pro, src/pro/moment.pro, src/pro/skewness.pro, src/pro/stddev.pro, src/pro/variance.pro: updating MEAN(), STDDEV(), VARIANCE(), SKEWNESS(), KURTOSIS() to have Dim= keyword since it is now available via the MOMENT() function. (Tests needed :( 2012-07-11 m_schellens * src/dinterpreter.cpp: Fixed proper handling of _retTree in stopped subroutines 2012-07-11 alaingdl * testsuite/test_strsplit.pro: adding 4 new test cases into TEST_STRSPLIT * src/pro/strsplit.pro: STRSPLIT(): a detail in a test ... * src/pro/strsplit.pro: in STRSPLIT(), we must return strarr even with single element except for '' ! 2012-07-10 m_schellens * src/arrayindexlistnoassoct.hpp, src/convert2.cpp, src/datatypes.cpp: fixed bug when copying byte to string array element, COPY_BYTE_AS_INT behaviour in Convert2 was changed 2012-07-05 alaingdl * src/gsl_fun.cpp, testsuite/test_fft_dim.pro: FFT( dim= ) should worked now. Test using TEST_FFT_DIM, improvment welcome ! * testsuite/test_fx_root.pro, src/gsl_fun.cpp: improvments in FX_ROOT(): when x_i is a root, short-cut; pure complex code in do-loop. Revisited TEST_FX_ROOT, comparison with NEWTON in simple cases. * testsuite/test_dicom.pro: limited extension of TEST_DICOM, cannot reproduce bug 3150207, but "new" bug when this test called with /version * src/gsl_fun.cpp: in FX_ROOT, when result is a real, return a real ... 2012-07-04 alaingdl * src/pro/file_lines.pro: correcting bugs 3175753 and 3189065 for FILE_LINES(); now FILE_LINES() can manage input files list; but still having pbs when files name prefixed or suffixed by white spaces ... (due to known hard bug 3439079 in WordExp() in "str.cpp") 2012-07-02 m_schellens * src/envt.cpp, src/envt.hpp, src/gsl_fun.cpp: Fixed keyword support for CALL_FUNCTION/PROCEDURE 2012-07-02 gilles-duvert * src/gdlwidget.cpp: compilation with gcc 4.4.3 (linux) was complaining about a possible confusion on this call: gdlwidget.cpp: In constructor 'GDLWidgetDropList::GDLWidgetDropList(WidgetIDT, BaseGDL*, BaseGDL*, DString, DLong, DLong)': gdlwidget.cpp:629: error: call of overloaded 'wxString(wxCStrData, wxMBConvStrictUTF8&)' is ambiguous /usr/local/include/wx-2.9/wx/string.h:1309: note: candidates are: wxString::wxString(const wchar_t*, const wxMBConv&) /usr/local/include/wx-2.9/wx/string.h:1296: note: wxString::wxString(const unsigned char*, const wxMBConv&) /usr/local/include/wx-2.9/wx/string.h:1283: note: wxString::wxString(const char*, const wxMBConv&) Solved by forcing type const wchar_t*, proceed with fingers crossed. 2012-06-29 alaingdl * testsuite/test_call_function.pro, testsuite/test_call_procedure.pro: adding keyword in call to CALL_FUNCTION and CALL_PROCEDURE. Both fail today :( 2012-06-28 alaingdl * src/math_fun_jmg.cpp: not clear if my pragma give better times in FINITE() ! * testsuite/test_finite.pro, src/math_fun_jmg.cpp: correcting bug into FINITE(, sign=) [various OS don't behave the same]. should be OK on INT related and FLOAT related types, not ready for complex. Extending "test_finite". 2012-06-28 m_schellens * src/pro/Makefile.in, src/pro/dicom/Makefile.in, testsuite/Makefile.in, doc/Makefile.in, src/CMakeLists.txt, src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/fftw.cpp, Makefile.in, configure: Fixed direct function call via CALL_FUNCTION 2012-06-28 slayoo * src/plotting_surface.cpp: switching from plmesh to plstream::mesh in plotting_surface() 2012-06-28 alaingdl * NEWS: now FX_ROOT() in GDL, coded in c++ by B. Laurent. 2012-06-27 alaingdl * src/gsl_fun.cpp: quiet work inside FX_ROOT(). check on p0 (3 elmnts) not finished. * testsuite/test_fx_root.pro: test for FX_ROOT() : one new test on roots values * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3441031.pro, testsuite/test_call_function.pro, testsuite/test_call_procedure.pro, testsuite/test_execute.pro: 1/ adding 2 new tests : "test_call_procedure', "test_call_function" (now failing on intrinsic functions), 2/ extending "test_execute", moving "test_bug_3441031" inside "test_execute". 3/ adding "test_call_procedure', "test_call_function", "test_fx_root", "test_fz_roots" in Makefile 4/ removing "test_bug_3441031" from Makefile 2012-06-27 slayoo * src/plot3d_nr.cpp, src/Makefile.am, src/Makefile.in, src/plotting_surface.cpp: removing plot3d_nr.cpp (thanks to Joel for providing instructions) 2012-06-27 alaingdl * testsuite/test_fx_root.pro: initial import of TEST_FX_ROOT * src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit_ac.cpp: initial import of C++ version of FX_ROOT() 2012-06-20 alaingdl * NEWS, testsuite/Makefile.am, testsuite/Makefile.in: details (update NEWS !) * src/math_fun_jmg.cpp, src/libinit_jmg.cpp: adding SIGN Keyword in FINITE ... (M. Pinter) * src/plotting_oplot.cpp: correcting a bug detected in OPLOT via "test_healpix.pro" * testsuite/test_moment.pro: for old idl version, no DIM in MOMENT ... * testsuite/test_finite.pro, testsuite/test_moment.pro: initial import of TEST_FINITE, including new SIGN keyword tests. 2012-06-19 alaingdl * testsuite/test_moment.pro, testsuite/test_qromo.pro: fixing details in test cases QROMO and MOMENT. 2012-06-16 alaingdl * NEWS: details in what we changed * src/gsl_fun.cpp: correcting code ... isfinite instead lot of tests ... * src/pro/moment.pro, testsuite/test_moment.pro: revisited MOMENT (new keywords, esp. DIM !) * testsuite/test_qromo.pro: update test cases for QROMO (we should now cover all the cases) * src/gsl_fun.cpp: revised version of QROMO by M. Pinter. Should cover all the cases. Good management of NaN/Inf ... * testsuite/test_fz_roots.pro: tests cases for FZ_ROOTS (preliminary version, errors accumulation not managed !) * src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit_ac.cpp, NEWS: initial import of FZ_ROOTS, but works only for input polynomials with real coefs. We used the same code in the GSL than the IMSL_ZEROPOLY code ... 2012-06-12 alaingdl * src/pro/tvscl.pro: we decided to overcome NaN problems in TVSCL. 2012-05-25 alaingdl * src/pro/read_png.pro: with a fake extra INTERNAL_READ_PNG, pro and func do work transparently. * src/pro/hist_equal.pro, src/libinit.cpp: adding quiet /COMPILE_FULL_FILE in RESOLVE_ROUTINE; typo corrected in HIST_EQUAL. 2012-05-22 alaingdl * src/pro/hist_equal.pro, testsuite/test_hist_equal.pro: initial import of HIST_EQUAL; associated test suite. 2012-05-16 alaingdl * src/pro/standardize.pro: fixing the sign pb in STANDARDIZE 2012-05-14 alaingdl * testsuite/test_standardize.pro, testsuite/test_zip.pro: details in tests ... * src/pro/hist_equal.pro: fake temporary file (sync. with SF to do) * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/STATUS: I forgot to update Makefile.am in src/pro with new files HIST_EQUAL and STANDARDIZE * testsuite/test_zip.pro: revised TEST_ZIP because "stat" options are various ... 2012-05-12 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in: adding "test_standardize" in testsuite * testsuite/test_standardize.pro, src/pro/standardize.pro, NEWS: initial import of STANDARDIZE and related test file 2012-05-10 alaingdl * configure.in: Only in classic "configure" way, you can choice between ImageMagick (--with-Magick, default) or GraphicsMagick (--with-GraphicsMagick, off by default, if you used it, please desactivate IM via : --without-Magick). Both ways should give same results on PNG and JPEG. * src/magick_cl.cpp: QUERY_IMAGE should now be OK for ALL JPEG and PNG, please report problems, with link to images giving problems ! * configure.in: adding --with-GraphicsMagick=DIR as an alternative to ImageMagick. Tested on Ubuntu 10.04 with success. * testsuite/test_read_standard_images.pro, src/magick_cl.cpp: extended test suite for PNG and JPEG formats. Useful comments in magick wrapper for later work ... 2012-05-08 alaingdl * doc/www/_news.inc.php, src/pro/smooth.pro, testsuite/test_smooth.pro: SMOOTH: revised faster algo for 2D smooth; test_smooth.pro updated too. 2012-04-30 alaingdl * doc/www/_news.inc.php, doc/www/resources.php: correcting broken links to ADASS 2011 paper 2012-04-13 gilles-duvert * INSTALL: Reverted to version 1.21 by Slayoo + a small addendum on libtool problems that I encounter often... * testsuite/test_random.pro: more precise "verbose" mode. test fails randomly, which is normal with random numbers ;^)) * testsuite/test_congrid.pro: test fails on byte arrays, but this is due to the conversion from double to byte by gdl basics, not by interpolate. This shoudl be investigated separately. I've changed the byte arrays to double by default, keeping byte as an option 2012-04-13 alaingdl * src/interp_multid.h: adding a missing file for revised version of INTERPOLATE 2012-04-13 gilles-duvert * src/gsl_fun.cpp, src/libinit_jmg.cpp: I more or less rewrote INTERPOLATE to support all documented (and some undocumented) features. I added a gsl-like handling of multi-D interpolation (which could be ported easily to gsl), but gsl does not have the same parametric cubic convolution as we want, and does not know about missing values, hence the necessity to overload its basic methods and structures. I added the /NEAREST_NEIGHBOUR option in the list of INTERPOLATE options since it makes for a very simple CONGRID procedure, and could be possibly of use elsewhere. * src/pro/congrid.pro: supports all options now that interpolate has the /nearest_neighbour option. * src/basic_fun.cpp: small typo 2012-03-20 gilles-duvert * src/extrat.cpp: It looks to me that if a kw is in the "warnkey" list it should be considered as valid kw for the "_STRICT_EXTRA" kw passing mechanism. * src/libinit.cpp: added several keywords to the "warnKey" list of axis, surface and contour. These keywords are to be really supported at some point but it is possible to ignore thme and still have correct outputs, in particular with procedures like the coyotegraphics where *all* the possible keywords are used, even with default values. 2012-03-17 alaingdl * src/devicex.hpp: TVRD: beeing able to manage x0, y0, Nx, Ny parameters; no check made :( maybe mirroring effect pending 2012-03-15 alaingdl * src/devicex.hpp, src/pro/loadct.pro: better management for color tables in LOADCT (good resultS around Coyote lib.) 2012-03-13 alaingdl * src/plotting_erase.cpp: ERASE: working version for Decompose == 0 or 1 * src/libinit.cpp, src/plotting_erase.cpp, NEWS: color keyword or parameter for ERASE (maybe not OK when not in /decomposed). Now default !p.background is also take into account. Preparing support for Coyote Lib. 2012-03-06 alaingdl * testsuite/test_image_statistics.pro: easy switch introducing fake error in this script. 2012-03-05 gilles-duvert * src/plotting.cpp, src/plotting.hpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp: Corrected regression introduced in previous version: while that version was correctly supporting the MIN_VALUE and MAX_VALUE keywords for PLOT and OPLOT when they were present, it was forcing these values even in the absence of the keywords, and even worse, for the PLOTS command. 2012-03-05 alaingdl * testsuite/test_interpol.pro, src/pro/interpol.pro: bug corrected in INTERPOL; better testsuite for this function. 2012-02-28 alaingdl * src/pro/findex.pro, src/pro/interpol.pro: INTERPOL.pro: temporary solution for bug 3495104. Not the final answer ... 2012-02-21 alaingdl * testsuite/test_bug_3441031.pro: no blocking version of the test. This test was generating a crash before mid-Nov. 2011. 2012-02-21 slayoo * testsuite/test_bug_3152892.pro: commiting a forgotten file 2012-02-20 slayoo * testsuite/test_bug_3488003.pro, testsuite/Makefile.am: adding test routine for bug no. 3488003 * doc/www/_news.inc.php: website update (Ubutnu package) 2012-02-20 m_schellens * src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp: fixed an indexing issue (bug ID 3488003) * src/Makefile.in, src/gdlwidget.cpp, src/math_fun_jmg.cpp, src/widget.cpp, testsuite/Makefile.in, configure: corrected EXECUTE like calls to fit new stack handling 2012-02-19 slayoo * CMakeLists.txt, configure.in: adding a warning about the planned move from Autotools to CMake to configure.in 2012-02-16 gilles-duvert * src/devicex.hpp: solves bug 3477639 * src/devicex.hpp: solves bug 3485528 and possibly 3434849. 2012-02-15 alaingdl * src/pro/write_image.pro: initial version of WRITE_IMAGE * src/pro/write_image.pro, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/read_image.pro, src/pro/read_png.pro: initial import of READ_IMAGE(). WRITE_IMAGE to be add later. 2012-02-13 alaingdl * testsuite/test_ludc_lusol.pro: in LUDC and LUSOL, we can now testing Float and Double. * src/gsl_matrix.cpp, src/libinit_ac.cpp: for DETERM, LUDL, LUSOL, extension to "any" input types (not only double). Details may not be fully fixed (exception catching, keywords ...) Help welcome. 2012-02-10 alaingdl * testsuite/test_congrid.pro: adding a self consistant test (which is not working now !) 2012-02-08 slayoo * CMakeLists.txt, configure.in: adding Fedora package name hints to CMakeLists.txt and configure.in 2012-02-07 alaingdl * src/pro/read_jpeg.pro: typo ... * src/pro/read_jpeg.pro, src/pro/read_png.pro: testing agreement of formats before efective reading * src/pro/read_jpeg.pro, src/pro/read_png.pro, src/magick_cl.cpp: improved reading of JPEG (gray + colors) and PNG files (1,2,3 & 4 channels) * src/plotting_misc.cpp: when TVLCT applyed, we have to upgrade the color table (check OK on X) 2012-02-06 alaingdl * testsuite/test_read_standard_images.pro: more reliable behavior * testsuite/test_tvlct.pro: direct switch into TrueColor mode * testsuite/test_read_standard_images.pro, testsuite/test_tvlct.pro: initial import of two tests : reading 2 JPEG and 4 PNG as basic cases; verifying TVLCT is working ... 2012-02-03 alaingdl * src/gsl_matrix.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_trisol.pro, NEWS: better version for TRISOL (any input types); TEST_TRISOL self-consistant. * testsuite/test_congrid.pro: in such a way, can be tested on both ways ... * src/devicex.hpp, src/plotting_windows.cpp: correcting Window, xpos= , ypos= (bug 3482821) 2012-02-02 alaingdl * src/gsl_matrix.cpp, src/gsl_matrix.hpp, src/libinit_ac.cpp: initial import of a working draft for TRISOL only for inputs in Double. To be extend to any types. * src/pro/read_png.pro: coorecting order when reading PNG. Tested on various files with success. 2012-01-30 gilles-duvert * src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp: Silently takes care of different sizes in X and Y dimensions for PLOT, PLOTS and OPLOT. test, e.g.: plot,findgen(1000),findgen(100)*5,/POL oplot,findgen(1000),findgen(10)*5,/POL,psym=4 2012-01-28 alaingdl * src/plotting.cpp: {X|Y}range keyword in type double should be managed ... * src/pro/read_jpeg.pro: correction in READ_JPEG when GrayScale, bug report 3471918 2012-01-27 alaingdl * src/pro/Makefile.am: in src/pro/Makefile.am, *.pro list must be alphabeticaly ordered 2012-01-27 gilles-duvert * src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp: Better support of the Log options (and values in CRANGE). PLOTS can now plot outside box in DATA mode. Cursor give correct data values even in log plots. valmin, valmax are handled at plot level, not at box limits. passes all the graphic tests. Removed temporarily support for 'clip" , to be continued. axis: changes only to follow changes in a function call arguments. * src/plotting_contour.cpp, src/plotting_cursor.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp: Better support of the Log options (and values in CRANGE). PLOTS can now plot outside box in DATA mode. Cursor give correct data values even in log plots. valmin, valmax are handled at plot level, not at box limits. passes all the graphic tests. Removed temporarily support for 'clip" , to be continued. Polyfill and surface: changes only to follow changes in a function call arguments. 2012-01-26 gilles-duvert * src/gdlxstream.cpp: It seems to me that this small patch mimics better the *DL behaviour and its doc (?) * testsuite/test_plotting_ranges.pro: updated test to sync with new capability, CRANGE OK in /YLOG mode 2012-01-25 gilles-duvert * src/plotting.cpp: changed pow(x,10) in pow(10,x) 2012-01-25 alaingdl * src/plotting.cpp: hum, better way to have the !X.type info at the right places for get/set !{xyz}.crange * src/plotting.cpp: small change for !X.CRange (!Y.crange and !Z.crange too !) to manage Log. plots. 2012-01-24 gilles-duvert * INSTALL: Added a comment about how to update aclocal to local version of libtool if there is a problem. Tested on Mandriva Linux, your mileage may vary. 2012-01-24 alaingdl * doc/udg/README.txt: initial import of an HowTo to help compiling the documentation. * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/get_login_info.pro: initial import of GET_LOGIN_INFO * testsuite/test_congrid.pro: TEST_CONGRID now needs ImageMagick, we have to exist if not linked to. * testsuite/test_read_jpeg.pro: missing factor parameter when screen too small * testsuite/test_diag_matrix.pro: initial import of TEST_DIAG_MATRIX. This test is not really self-testing :( * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/diag_matrix.pro, src/pro/la_invert.pro: initial import of DIAG_MATRIX and LA_INVERT (both need by iCosmo) 2012-01-23 m_schellens * src/arrayindex.cpp: fixed assoc var with one index * src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/gsl_fun.cpp: fixed assoc var with one index (ArrayIndexListOneT) 2012-01-23 alaingdl * src/plotting_oplot.cpp: same typo in OPLOT * src/plotting_plot.cpp: correcting a typo in PLOT, simplest case broken (plot, indgen(10)) 2012-01-23 gilles-duvert * src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_xyouts.cpp: Corrected bugs that prevented correct positioning of datapoints (lines, psyms...) with commands PLOTS, XYOUTS and OPLOT when PLOT was done with /[X|Y]LOG. Added support for NSUM=xxx and /POLAR options used in PLOT, OPLOT. Treatment for DATAMIN,DATAMAX and CLIP is not OK however. needs some more changes. Debugged the /NORMAL, /DEVICE and /CONTINUE option of PLOTS. Should be OK even for some (not all) cases when !P.MULTI is not 0. Added SIZE=xxx undocumented option as a replacement for CHARSIZE for the XYOUTS command (support for several legacy procedures). * testsuite/test_poly2d.pro: changed missing value to 128 to better show the influence of the "missing=xxx" keyword. Also, serves as test of my ability to commit patches... 2012-01-22 alaingdl * NEWS, src/gsl_fun.cpp, src/libinit_ac.cpp, testsuite/test_qromo.pro: small improvments in QROMO (but not finished at all) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_qromb.pro, testsuite/test_qromo.pro: initial import of TEST_QROMB and TEST_QROMO. To be expanded ... 2012-01-21 alaingdl * src/gsl_fun.cpp: NEWTON mus accepted "singleton" too; temporary change in QROMO for ]a,b[ range (to be generalize ASAP) 2012-01-20 alaingdl * src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit_ac.cpp: QROMO: initial import of limited version only for range [a,+inf]; help welcome. * src/gsl_fun.cpp: QROMB: better management of inputs (vectors, matrix); IDL doc. is wrong for that ([1],[8]) return [8], not [1] 2012-01-12 alaingdl * NEWS: update * src/libinit_ac.cpp: introducing QSIMP, using QROMB ... * src/gsl_fun.cpp: managing arrays in QROMB 2012-01-10 alaingdl * NEWS, src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit_ac.cpp: initial import for QROMB, not ready for arrays. 2012-01-07 m_schellens * src/arrayindex.hpp, src/arrayindex.cpp: Fixed bug ID 3464519 2012-01-05 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_random.pro: initial import of TEST_RANDOM, very basic tests to check consistancy of basic computations (gamma and binomial cases) * NEWS: details in NEWS ... * src/gsl_fun.cpp: in RANDOM(N/U): now, Binomial keyword works; serious rewriting; conflicting keywords detected. 2012-01-04 alaingdl * src/gsl_fun.cpp: in RANDOM(U/N), better management of GAMMA values (exit if <= 0.; put to 1 if 0.0 < Gamma < 1.0) 2012-01-03 slayoo * src/deviceps.hpp: TV/PostScript: plplot compatibility fix * doc/udg/examples/obj_class_1/obj_class_1.out.txt, doc/udg/routines/appleman.pro.tex, doc/udg/examples/call_external_0/call_external_0.pro, doc/udg/examples/file_lines_0/file_lines_0.out.txt, doc/udg/examples/h5_get_libversion_0/h5_get_libversion_0.out.txt, doc/udg/diag/broken-references, doc/udg/chapters/credits.tex, doc/udg/gdl.tex, doc/udg/makeall: doc/udg update 2012-01-03 alaingdl * CMakeLists.txt: correcting typo in CMakeLists.txt 2012-01-02 slayoo * CMakeLists.txt, CMakeModules/FindNumpy.cmake: CMake: working version of PYTHONDIR and PYTHONVERSION support * doc/gdl.1: manpage updae * src/deviceps.hpp, src/dinterpreter.cpp, src/gdlgstream.hpp, src/libinit_jmg.cpp, src/pro/appleman.pro, src/typedefs.hpp: misc cleanups 2012-01-02 alaingdl * src/gdlgstream.hpp: correcting bug introduced by Sylwester to have X11 plots ... 2011-12-31 slayoo * config.h.cmake: fixing CMake support for PSlib 2011-12-30 alaingdl * src/math_fun_jmg.cpp: removing comment in POLY_2D * src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: managing keyword Missing for POLY_2D [patch from G. Duvert] (see TEST_POLY2D_NEW in testsuite/test_poly2d.pro). When no missing value, case of <> [sic] is still pending ... * testsuite/test_get_kbrd.pro: hum, I forgot to manage "wait" keyword in third case ... * testsuite/test_get_kbrd.pro: initial import of TEST_GET_KBRD. 3 main cases are tested. * src/basic_fun.cpp: in GET_KBRD(), better management of GET_KBRD(0) (see testsuite/test_get_kbrd.pro) [should be retest on OSX] * src/pro/identity.pro: in IDENTITY, bug corrected when N=1 * src/pro/appleman.pro: small changes, one in order to have return of the array without internal TV * testsuite/test_congrid.pro, testsuite/test_postscript.pro, testsuite/test_ps_decomposed.pro: various minor bugs corrections and few extensions (TEST_POSTSCRIPT_APPLEMAN ;-) 2011-12-29 slayoo * src/deviceps.hpp: PostScript: fixing a memory leak in TV 2011-12-28 slayoo * src/deviceps.hpp, src/devicez.hpp, src/graphics.cpp: TV: a draft of PostScript support (tracker items 3460150 and 3110007) * src/gdlgstream.hpp, src/gdlpsstream.hpp: gdlpsstream.hpp: correcting typo (ps-ttf -> psttf) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3453775.pro: adding a test for bug no. 3453775 * doc/www/resources.php: doc/www: adding a link in the resources section 2011-12-27 slayoo * doc/www/images/Colourise.css, doc/www/_header.inc.php, doc/www/_news.inc.php: doc/www: website update 2011-12-21 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_congrid.pro: initial import of TEST_CONGRID. maybe not needed in "make check" as long as we don't have null test * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/bilinear.pro, src/pro/congrid.pro, NEWS: initial import of CONGRID and BILINEAR (both in GDL syntax, in src/pro), thanks to G. Duvert 2011-12-16 alaingdl * src/gsl_fun.cpp: a bug corrected in INTERPOLATE (patch by G. Duvert); we still do not have a good testsuite for INTERPOLATE. 2011-12-15 alaingdl * testsuite/test_poly2d.pro: revisiting TEST_POLY2D. more simple way to show few problems in POLY_2D 2011-12-14 m_schellens * src/basic_fun_jmg.cpp: Adapt ROUTINE_NAMES to new callstack layout 2011-12-13 alaingdl * src/CMakeLists.txt, src/gsl_matrix.hpp: adding new files (gsl_matrix.hpp and gsl_matrix.cpp) in CMakeLists.txt 2011-12-13 m_schellens * src/prognode.cpp, src/prognode.hpp: Fixed break with breakTarget == NULL. Bug ID 3454317 2011-12-09 alaingdl * NEWS, src/gsl_matrix.cpp, src/gsl_matrix.hpp, src/libinit_ac.cpp: initial import of DETERM(), only for type DOUBLE (help welcome) * src/gsl_matrix.cpp, NEWS: alignment bug in LUDC * testsuite/test_ludc_lusol.pro: details in TEST_LUDC_LUSOL * testsuite/Makefile.am, testsuite/test_ludc_lusol.pro: typo corrected in TEST_LUDC_LUSOL * src/Makefile.am, src/Makefile.in, src/gsl_matrix.cpp, src/gsl_matrix.hpp, src/libinit_ac.cpp: initial import of C++ LUDC and LUSOL (based on GDL). Work BUT only on DOUBLE ... Help needed. * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/ludc.pro: removing the fake LUDC, to be remplace by a draft of LUDC/LUSOL pair in C++ * testsuite/test_ludc_lusol.pro: initial import for TEST_LUDC_LUSOL tests (very preliminary). * src/plotting.cpp: patch by G. Duvert correcting in USERSYM behavior of !P.CHARSIZE, !P.SYMSIZE, /CHARSIZE= and /SYMSIZE= 2011-12-08 m_schellens * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/specializations.hpp, src/typedefs.hpp: Fixed SHIFT(a,0). Bug ID 3453775 2011-12-07 m_schellens * src/envt.cpp: Fixed EnvBaseT::Caller() 2011-12-06 alaingdl * NEWS: upgrade of NEWS * src/gsl_fun.cpp, src/libinit_jmg.cpp: new keyword /nan added to HISTOGRAM. It is not fully finished/tested but working in basic cases. * testsuite/test_histo.pro: upgrade of TEST_HISTO for to be introduced new keyword /Nan 2011-12-05 m_schellens * src/basic_fun.cpp, src/prognodeexpr.cpp: fixed wrong delete in lib::execute function * src/gdlwidget.cpp: corrected callstack handling 2011-12-05 alaingdl * src/pro/Makefile.am, src/pro/Makefile.in: missing two new files (READ_GIF and WRITE_GIF) in Makefile* 2011-12-03 m_schellens * src/GDLInterpreter.hpp, src/basic_fun.cpp, src/envt.hpp, src/gdlc.i.g, src/print.cpp, src/prognodeexpr.cpp: EnvStackT now with EnvUDT instead EnvBaseT * src/basic_pro.cpp, src/envt.cpp, src/envt.hpp, src/gsl_fun.cpp, src/prognode.cpp, src/prognodeexpr.cpp, src/basic_fun.cpp: EnvT for library functions is no longer pushed onto the call stack. Fix for random_fun binominalKey 2011-11-30 alaingdl * src/gsl_fun.cpp: code like RANDOMN(seed,10, BINOMIAL=[3,.5]) is wrong ... (should return int-like values) * src/pro/read_gif.pro, src/pro/write_gif.pro: initial inclusion of READ_GIF and WRITE_GIF. Very limited functionalities but OK to read and write GIF derivated from testsuite/Saturn.jpg (256 colors) * src/pro/read_jpeg.pro: typo in READ_JPEG 2011-11-30 m_schellens * src/basic_fun.cpp, src/gdlc.i.g, src/str.cpp, src/str.hpp: Faster STRUPCASE and STRLOWCASE 2011-11-29 alaingdl * testsuite/test_str_functions.pro: testing also /reverse_offset in STRMID (test is not perfect) * src/libinit.cpp: reverting typo in "libinit.cpp" for keyword /rever in STRMID() 2011-11-28 alaingdl * src/plotting.cpp, testsuite/test_usersym.pro: correcting bug related to USERSYM: beeing able to manage 1 or 2 points only on plot 2011-11-25 m_schellens * src/gdlc.i.g, src/GDLInterpreter.cpp: sync 2011-11-25 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3441031.pro: adding test_bug_3441031.pro 2011-11-25 m_schellens * src/GDLInterpreter.cpp, src/prognodeexpr.cpp, src/arrayindexlistnoassoct.hpp, src/gdlc.i.g, src/libinit.cpp: Fixed bug ID 3441031 2011-11-24 m_schellens * src/basic_fun.cpp: insert some assert macros * src/math_fun.cpp: optimization for IMAGINARY and CONJ * src/basic_fun.cpp, src/basic_fun.hpp, src/envt.hpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp: direct call for several functions * src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp: direct call EXP function 2011-11-22 alaingdl * src/pro/usersym.pro: since a working C++ code for USERSYM was added today, the fake "usersym.pro" can be removed ! * src/pro/Makefile.am, src/pro/Makefile.in: STRMATCH was added in CVS, USERSYM was moved as a C++ code. * src/initsysvar.cpp, src/initsysvar.hpp, src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_oplot.cpp: initial import for USERSYM procedure, thanks to a contribution by Gilles Duvert 2011-11-22 slayoo * src/pro/strmatch.pro, testsuite/test_strmatch.pro: STRMATCH: yet another improvement * src/pro/strmatch.pro, testsuite/test_strmatch.pro: STRMATCH: improvement * src/pro/strmatch.pro, testsuite/Makefile.am, testsuite/test_strmatch.pro: STRMATCH: initial import 2011-11-20 m_schellens * src/str.cpp: removed escaping of space in WordExp function * src/devicex.hpp: fixed bug ID 3438651 2011-11-18 m_schellens * src/basic_fun.cpp, src/basic_fun.hpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp: direct call API for more library functions * src/objects.cpp, src/str.cpp: changed WordExp: esc only non escaped blanks * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dpro.cpp, src/dpro.hpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp, src/prognodeexpr.cpp: faster ALOG ALOG10 N_ELEMENTS 2011-11-16 alaingdl * testsuite/test_mpfit.pro: managing multiple occurences in TEST_MPFIT 2011-11-16 slayoo * doc/www/faq.php: doc/www: a new faq item * src/gshhs.cpp: MAP_CONTINENTS: fixing argument number check * doc/www/resources.php: doc/www: resources.php: adding a link to Alain's ADASS XXI talk * doc/www/_news.inc.php: doc/www: news updates 2011-11-16 alaingdl * src/pro/Makefile.am, src/pro/Makefile.in: fixing files list in Makefile* * testsuite/test_file_copy.pro, testsuite/test_file_delete.pro: limited updates preparing next better tests ... * src/pro/usersym.pro: initial import of a fake USERSYM to avoid stopping codes just because we don't know how to write USERSYM * src/pro/read_ascii.pro, src/pro/read_jpeg.pro, src/pro/read_png.pro, src/pro/read_xwd.pro: better management when we try to read a directory when a real file is expected. * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test-read_ascii.pro, testsuite/test_image_statistics.pro: initial import of TEST_IMAGE_STATISTICS; correction in TEST-READ_ASCII to be able to go to the end. 2011-11-15 m_schellens * src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dpro.cpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.g, src/gdlc.tree.g, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp, src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp: direct calls for lib functions 2011-11-15 slayoo * doc/www/_news.inc.php: www: typo fix 2011-11-15 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_fun.cpp, src/gdlc.g, src/gdlc.tree.g, src/newprognode.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: FCALL_N_ELEMENTSNode 2011-11-15 alaingdl * src/pro/image_statistics.pro: hum, we need to use /double ... * src/pro/image_statistics.pro: type conversion for 3 outputs of IMAGE_STATISTICS 2011-11-15 slayoo * doc/www/_news.inc.php: www: Macports port news (0.9.2) 2011-11-14 slayoo * doc/www/_news.inc.php: www: ArchLinux package news (0.9.2) 2011-11-14 alaingdl * src/pro/Makefile.am, src/pro/Makefile.in: adding IMAGE_STATISTICS.pro in Makefile files 2011-11-14 m_schellens * src/getas.cpp: com,ented out typename * src/getas.cpp: add file * src/arrayindex.cpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/convert2.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/newprognode.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: faster 2D indexing 2011-11-13 slayoo * doc/www/_news.inc.php: www: Fedora 0.9.2 package info * doc/www/_news.inc.php: www: FreeBSD 0.9.2 port info 2011-11-12 slayoo * doc/www/_header.inc.php, doc/www/faq.php: www: adding FAQ page 2011-11-10 alaingdl * src/pro/image_statistics.pro: initial import of IAMGE_STATISTICS procedure, coded in GDL syntax. 4 keywords are missing 2011-11-09 alaingdl * testsuite/test_read_jpeg.pro: adding a call to READ_JPEG, /Gray * src/pro/read_jpeg.pro: /Gray should work now in READ_JPEG (tested on testsuite/Saturn.jpg) * src/magick_cl.cpp: MAGICK_QUANTIZE don't need 2 mandatory arg.; small code factoring; order changed for lisibility 2011-11-09 slayoo * doc/www/_news.inc.php: www: news about 0.9.2 release and ADASS XXI 2011-11-09 m_schellens * CMakeLists.txt, configure, configure.in: GDL 0.9.2 CVS GDL 0.9.2: 2011-11-08 m_schellens * configure, configure.in, src/typedefs.hpp, ChangeLog, NEWS, src/str.cpp: release 2011-11-08 alaingdl * NEWS: details in NEWS * src/initsysvar.cpp: in !version, OS must be in lower case for Linux and Darwin ... 2011-11-07 m_schellens * src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/arrayindex.cpp, src/arrayindexlistnoassoct.hpp, src/envt.cpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp: optimized parameter passing * src/prognodeexpr.cpp: fix bug 3300626 * src/arrayindex.hpp, src/arrayindexlistt.hpp: sync * src/CMakeLists.txt, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/Makefile.am, src/Makefile.in, src/arrayindex.cpp, src/arrayindexlistnoassoct.hpp, src/arrayindexlistt.hpp, src/basic_pro.cpp, src/dnode.cpp, src/dnode.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp: add file 2011-11-06 m_schellens * src/basic_fun.cpp: Fixed STREGEX * src/arrayindex.hpp, src/envt.cpp: re-fix bug 3300626 2011-11-06 alaingdl * CMakeLists.txt: version 0.9.2 in CMake way ;-) * src/devicex.hpp: correcting bug 3433502 in TV 2011-11-05 m_schellens * src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/envt.cpp, src/envt.hpp, src/prognode.cpp, src/typedefs.hpp: bug fixes * src/GDLInterpreter.cpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/datalistt.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp: removal of ArrayIndexT::Index() 2011-11-04 m_schellens * src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/dnode.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.hpp: implemented check for number of arguments to subroutines (TEST_DERIV bug) 2011-11-03 m_schellens * src/basic_op.cpp, src/basic_op_new.cpp, src/sigfpehandler.cpp: fixed error handling at division by 0 2011-11-03 slayoo * doc/www/resources.php: www: adding a link to Mark Pipers website to resources.php * doc/www/_header.inc.php: ITT -> Exelis in website header 2011-11-03 m_schellens * src/arrayindex.hpp, src/arrayindexlistt.hpp, src/datatypes.cpp, src/prognode_lexpr.cpp: optimization for Index with single element 2011-11-02 alaingdl * src/pro/idl_validname.pro: we subsitute to the current limited version of IDL_VALIDNAME() a version provided by Hon Xu * testsuite/test_idl_validname.pro: before running TEST_IDL_VALIDNAME, we need to be sure STREGEX is working. * testsuite/Makefile.am, testsuite/Makefile.in: adding two files (test_idl_validname.pro and test_stregex.pro) in Makefile.am in order to be run ... * testsuite/test_idl_validname.pro: one more case ($) in "test_idl_validname.pro" 2011-11-02 m_schellens * src/basic_op.cpp, src/basic_op_new.cpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/prognodeexpr.cpp: optimization for scalar division and modulo * src/prognode.cpp, src/prognodeexpr.cpp, src/GDLInterpreter.cpp, src/gdlc.i.g, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.hpp: cleanup * ltmain.sh, src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognodeexpr.cpp, src/prognodeexpr.hpp: fix make build system 2011-11-01 m_schellens * doc/Makefile.in, src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in, testsuite/Makefile.in, Makefile.in, aclocal.m4, configure: fix make build system * src/gdlc.i.g, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp: fixed bug around lib_function_call * src/GDLInterpreter.cpp, src/gdlc.i.g, src/newprognode.cpp, src/prognode.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: sync 2011-10-31 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp: new Eval functions replacing calls in GDLInterpreter * src/CMakeLists.txt, src/GDLInterpreter.cpp, src/Makefile.am, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: Eval for DOTNode 2011-10-31 slayoo * src/magick_cl.cpp: Magick: adding a FIXME-throw in readindexes() * src/deviceps.hpp: PostScript: handling case when getlogin() returns a null pointer (apparently it happens!) * src/deviceps.hpp, NEWS, README: PostScript: making advantage of the change in plspage() introduced in plplot 5.9.9 2011-10-31 m_schellens * src/prognode.hpp, src/prognode_lexpr.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g, src/newprognode.cpp: replacing parts of gdlc.i.g 2011-10-29 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/prognode.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: Removed _retTree setting in Eval functions 2011-10-29 slayoo * src/deviceps.hpp: fixing device,/close behaviour when no plot was created before * src/deviceps.hpp, testsuite/test_ps_decomposed.pro: fixing bug 3428043 (PSlib was changing locale of GDL) 2011-10-29 m_schellens * testsuite/Makefile.am, testsuite/test_ce.pro: undo testsuite changes * testsuite/Makefile.am, testsuite/test_ce.pro, src/GDLInterpreter.cpp, src/gdlc.i.g, src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp: More LEval/Eval functions * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g: Interpreter improvements 2011-10-28 alaingdl * CMakeLists.txt, testsuite/test_healpix.pro: option -muldefs no more needed in CMake; update for HealPix tests when PNG not available * testsuite/test_stregex.pro: initial import of TEST_STREGEX, not finished. 2011-10-28 m_schellens * src/basic_fun.cpp: Fixed STREGEX with /EXTRACT * src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/arrayindexlistt.hpp, src/datalistt.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: custom new/delete for Env[UD]T 2011-10-26 m_schellens * src/allix.cpp, src/allix.hpp, src/arrayindex.cpp, src/arrayindexlistt.hpp: introduced ArrayIndexListMultiAllIndexedT * src/allix.cpp, src/allix.hpp, src/arrayindexlistt.hpp, src/prognodeexpr.cpp, config.h.in, configure: Faster sequential indexing 2011-10-25 m_schellens * src/pro/Makefile.in, src/pro/dicom/Makefile.in, testsuite/Makefile.in, doc/Makefile.in, src/Makefile.in, src/antlr/Makefile.in, Makefile.in, aclocal.m4: fix linking * src/arrayindex.hpp, src/envt.hpp, src/typedefs.hpp: inline specialized GDLArray functions 2011-10-25 alaingdl * CMakeLists.txt: typo netDCF / netCDF * testsuite/test_ps_decomposed.pro: now, if bad locale when calling "test_ps_decomposed.pro", problem. 2011-10-24 m_schellens * src/prognode.hpp: inline 2011-10-23 m_schellens * src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in, testsuite/Makefile.in, doc/Makefile.in, src/Makefile.in, src/allix.cpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/envt.hpp, src/typedefs.hpp, Makefile.in, aclocal.m4, configure: Improved indexing. Fixed bug tracker ID 3426399 (\!sysvar.tag crash) 2011-10-20 m_schellens * src/basic_op.cpp: Fixed: OrOpInvS called OrOp (instead of OrOpS) 2011-10-20 alaingdl * src/math_fun_ac.cpp: correcting small bug in X/Y lengths checks for "spl_init_fun(x,y, ...)" 2011-10-20 m_schellens * src/gsl_fun.cpp, src/typedefs.hpp: Fixing bug in BaseGDL* zeropoly(EnvT*) (causing failure in test_zeropoly.pro) 2011-10-19 m_schellens * src/GDLInterpreter.cpp, src/accessdesc.hpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/datatypes.cpp, src/gdlc.i.g, src/specializations.hpp: fixed handling of temporary array indices * src/allix.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/dimension.hpp, src/dvar.hpp: non-copy dim stride 2011-10-18 alaingdl * testsuite/test_healpix.pro: initial import of test for the HealPix Library. Thanks to E. Hivon. * NEWS: news in NEWS 2011-10-18 m_schellens * src/allix.hpp, src/arrayindex.cpp, src/arrayindexlistt.hpp, src/allix.cpp: 2D index optimization * src/arrayindex.cpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/datalistt.hpp, src/datatypes.cpp, src/datatypes.hpp, src/envt.cpp, src/prognode.cpp: sync 2011-10-17 m_schellens * src/allix.hpp, src/basic_op_new.cpp: sync * src/convert2.cpp: one element optimization for Convert2 2011-10-17 alaingdl * src/CMakeLists.txt: adding two new files for CMake 2011-10-17 m_schellens * src/Makefile.am, src/Makefile.in, src/allix.cpp, src/arrayindexlistt.hpp: fast indexing with only one variable dimension (e. g. a[1,*]) * src/allix.cpp, src/arrayindex.cpp: sync * src/allix.cpp: add file * src/Makefile.am, src/Makefile.in, src/allix.hpp, src/arrayindex.cpp, src/arrayindexlistt.hpp, src/dimension.hpp: indexing 2011-10-14 m_schellens * src/datatypes.cpp: sync * src/prognodeexpr.cpp: All OpNew functions utilized * src/datatypes.cpp, src/prognodeexpr.cpp: OpNew functions utilized. Faster TRANSPOSE 2D 2011-10-13 m_schellens * src/datatypes.cpp: Fast SHIFT for all dimensions and types * src/datatypes.cpp: fast SHIFT 3D and 4D (STRING only 1D and 2D) * src/datatypes.cpp, src/dstructgdl.cpp, src/typedefs.hpp: Fast SHIFT for 1D and 2D cases * src/datatypes.cpp, src/typedefs.hpp: GDLArray buffer cache 2011-10-12 alaingdl * doc/gdl.1: upgrade of man page, in concordance to new options in main "gdl". * src/gdl.cpp: short and long (-h, --help) ways to call options, we always forgot the good way to call them. No effect on options known by IDL. * src/basic_fun.cpp: improvments in STREGEX, but not finished :( (no test in testsuite; STRMATCH still missing) 2011-10-12 m_schellens * src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp, src/basic_op_new.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/prognodeexpr.cpp, src/sigfpehandler.cpp, src/specializations.hpp: 37 new operator functions (not utilized yet) * src/basic_op_new.cpp, src/dimension.hpp, src/prognodeexpr.cpp, src/basegdl.hpp: added file for RetNew operators 2011-10-11 alaingdl * CMakeLists.txt: 1/ now, we mandatory need the "-z muldefs" flag at linking in CMake way. See altenative in CMakeList.txt. 2/ typo PSLIBS --> PSLIB 2011-10-11 m_schellens * src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_op.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dimension.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/math_fun_ng.cpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/typedefs.hpp: For Eval(): AddNew, AddSNew and friends. GDLArray optimization * src/allix.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun_jmg.cpp, src/datalistt.hpp, src/datatypes.cpp, src/dimension.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/gsl_fun.cpp, src/math_fun_jmg.cpp: stride storage for dimension 2011-10-10 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basegdl.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g: Customized container for FoorLoopInfoT * src/GDLInterpreter.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basegdl.hpp, src/datalistt.hpp, src/datatypes.cpp, src/datatypesref.cpp, src/envt.cpp, src/envt.hpp, src/typedefs.hpp: New ExprListT definition 2011-10-08 m_schellens * src/Makefile.am, src/Makefile.in, src/accessdesc.hpp, src/allix.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basegdl.cpp, src/basegdl.hpp, src/convert2.cpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp: Sequential indexing. Fixed Convert2(STRING). 2011-10-07 m_schellens * src/arrayindex.hpp, src/basic_op.cpp, src/arrayindex.cpp: optimizations for scalar handling (especially with OpenMP) * src/accessdesc.hpp, src/allix.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/dimension.hpp: indexing optimizations * src/allix.hpp: add allix.hpp 2011-10-06 m_schellens * src/accessdesc.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp, src/dimension.hpp, src/dstructgdl.cpp, src/gdlc.tree.g, src/typedefs.hpp, src/GDLTreeParser.hpp, src/Makefile.am, src/Makefile.in: more efficient indexing (5x faster for indexed case) 2011-10-04 m_schellens * src/Makefile.am, src/Makefile.in, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/datatypes.cpp, src/typedefs.hpp: indexing speed up 2011-09-29 m_schellens * src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basic_fun.cpp, src/basic_op.cpp, src/basic_pro.cpp, src/convert2.cpp, src/datatypes.cpp, src/fftw.cpp, src/math_fun.cpp, src/strassenmatrix.hpp, src/typedefs.hpp: tracing for OMP calls 2011-09-25 alaingdl * src/math_fun.cpp: bad name for a counter in LAGUERE(), no time to fix 2011-09-25 m_schellens * src/basic_op.cpp, src/convert2.cpp, src/datatypes.cpp, src/magick_cl.cpp, src/math_fun.cpp, src/arrayindex.hpp, src/basic_fun.cpp: Removed usage of OpenMP for all simple copy operations 2011-09-24 m_schellens * src/arrayindex.hpp, src/arrayindexlistt.hpp, src/typedefs.hpp: changed defintion of AllIxT 2011-09-23 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g, src/prognode.hpp: Lookup table for NonCopyNode() * src/magick_cl.cpp: fix g++ segfault with -O2 and OpenMP 2011-09-20 m_schellens * src/GDLInterpreter.hpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/basic_pro.cpp, src/dinterpreter.cpp, src/dstructdesc.cpp, src/gdlc.g, src/gdlc.i.g, src/pro/Makefile.in, src/pythongdl.cpp, testsuite/Makefile.in, config.h.in: Made GDL distinguish PRO and FUNCTION when searching for a subroutine (bug tracker ID 3394134) 2011-09-19 slayoo * CMakeLists.txt, INSTALL, NEWS, README, configure.in, doc/udg/chapters/math-func.tex, doc/udg/makeall, doc/www/requirements.php, src/gdlpsstream.cpp, src/gdlpsstream.hpp, src/graphics.hpp, src/initsysvar.cpp, src/initsysvar.hpp, src/libinit.cpp, src/plotting.cpp, src/plotting_contour.cpp, src/plotting_device.cpp, CMakeModules/Findlibps.cmake, src/deviceps.hpp: non-Encapsulated PostScript support along with XSIZE, YSIZE, XOFFSET, YOFFSET, PORTRAIT, LANDSCAPE and SCALE_FACTOR settings support for PostScript output (requires pslib - http://pslib.sourceforge.net/) 2011-09-01 slayoo * testsuite/test_sem.pro: test_sem.pro: uncommenting debug printfs 2011-08-31 m_schellens * src/basic_fun_jmg.cpp: fixed MAKE_ARRAY(/STRING, /INDEX,...) * src/Makefile.in, src/dstructdesc.hpp, src/pro/dicom/Makefile.in, config.h.in: allignment for structs 2011-08-31 alaingdl * testsuite/test_spher_harm.pro: fixing doc.; this code required at least IDL 8.0 on IDL side 2011-08-31 slayoo * testsuite/test_spher_harm.pro: test_spher_harm: making it work with IDL too (epsilon 1e-7 -> 1e-6) 2011-08-30 alaingdl * testsuite/test_spher_harm.pro: hum, stupid typo (duplicate begin ...) * testsuite/Makefile.in, testsuite/image_test.pro, testsuite/test_spher_harm.pro: fixing details in testsuite/ * src/pro/write_bmp.pro, src/pro/write_jpeg.pro, src/pro/write_pict.pro, src/pro/write_png.pro: some cleaning in the WRITE_* procedures, not finished. N_PARAMS() tests not done :( * src/pro/save.pro: details in SAVE * testsuite/image_test.pro: rewriting the "IMAGE_TEST" procedure to be usable, using the "Saturn.jpg" internal file. Some tests in initial version are missing (ToDo) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_postscript.pro, testsuite/test_systime.pro: 1/ very preliminary test suite for the PostScript output (esp. XOFFSET and YOFFSET keywords are not working now) 2/ initial import of TEST_SYSTIME. The related bug was corrected in "gdl.cpp" by Sylwester. When an external library (e.g. ImageMagick) is compiled with "bad" locale, it may propagate inside GDL (one consequence: breaking SYSTIME(), another bad format in "printf"). 2011-08-29 slayoo * src/gdl.cpp: adding a note on why setlocale() has to be called after LibInit() * src/gdl.cpp: trying to fix MagickInit-locale conflict * doc/www/resources.php, doc/www/_news.inc.php: website update 2011-08-27 alaingdl * src/pro/write_jpeg.pro: in WRITE_JPEG, changing q*1U to UINT(q) (blocking bug); other "input checks" changes 2011-08-24 slayoo * doc/udg/chapters/cmdline.tex, doc/udg/chapters/credits.tex, doc/udg/chapters/debug.tex, doc/udg/chapters/dynload.tex, doc/udg/chapters/exec.tex, doc/udg/chapters/filesys.tex, doc/udg/chapters/image.tex, doc/udg/chapters/io-ascii.tex, doc/udg/chapters/io-bin.tex, doc/udg/chapters/io-fits.tex, doc/udg/chapters/io-grib.tex, doc/udg/chapters/io-hdf4.tex, doc/udg/chapters/io-hdf5.tex, doc/udg/chapters/io-idlsave.tex, doc/udg/chapters/io-img.tex, doc/udg/chapters/io-netcdf.tex, doc/udg/chapters/io.tex, doc/udg/chapters/math-basic.tex, doc/udg/chapters/math-bits.tex, doc/udg/chapters/math-constants.tex, doc/udg/chapters/math-fourier.tex, doc/udg/chapters/math-func.tex, doc/udg/chapters/math-geom.tex, doc/udg/chapters/math-interpol.tex, doc/udg/chapters/math-la.tex, doc/udg/chapters/math-multiroots.tex, doc/udg/chapters/math-ode.tex, doc/udg/chapters/math-poly.tex, doc/udg/chapters/math-rng.tex, doc/udg/chapters/math-stats.tex, doc/udg/chapters/math-wavelet.tex, doc/udg/chapters/net.tex, doc/udg/chapters/os.tex, doc/udg/chapters/plot-2d.tex, doc/udg/chapters/plot-3d.tex, doc/udg/chapters/plot-colours.tex, doc/udg/chapters/plot-fonts.tex, doc/udg/chapters/plot-map.tex, doc/udg/chapters/plot-misc.tex, doc/udg/chapters/plot-raster.tex, doc/udg/chapters/plot-term.tex, doc/udg/chapters/plot-windows.tex, doc/udg/chapters/python-in-gdl.tex, doc/udg/chapters/python-module.tex, doc/udg/chapters/strings.tex, doc/udg/chapters/syntax-arguments.tex, doc/udg/chapters/syntax-array.tex, doc/udg/chapters/syntax-errhandle.tex, doc/udg/chapters/syntax-flowcon.tex, doc/udg/chapters/syntax-heap.tex, doc/udg/chapters/syntax-help.tex, doc/udg/chapters/syntax-infnans.tex, doc/udg/chapters/syntax-oop.tex, doc/udg/chapters/syntax-ops.tex, doc/udg/chapters/syntax-stru.tex, doc/udg/chapters/syntax-sysvars.tex, doc/udg/chapters/syntax-types.tex, doc/udg/chapters/syntax-udsub.tex, doc/udg/chapters/syntax.tex, doc/udg/chapters/time.tex, doc/udg/chapters/widgets.tex, doc/udg/diag/broken-references, doc/udg/examples/get_login_info_0/get_login_info_0.out.txt, doc/udg/examples/showfont_4/gdl.ps, doc/udg/examples/showfont_7/gdl.ps, doc/udg/gdl.tex: doc/udg update * doc/www/resources.php: doc/www: updating resources.php with links to three other papers mentioning use of GDL 2011-08-22 opoplawski * src/deviceps.hpp, src/devicesvg.hpp, src/devicewin.hpp, src/devicex.hpp, src/devicez.hpp: Make setopt usage conditional on HAVE_OLDPLPLOT * src/deviceps.hpp, src/devicesvg.hpp, src/devicewin.hpp, src/devicex.hpp, src/devicez.hpp: SetOpt() was removed in plplot 5.9.8, use setopt() instead * src/gdlgstream.cpp: Use std::string() in gdlgstream.cpp to avoid ambiguity 2011-08-22 slayoo * src/libinit.cpp: DEVICE: ignoring XOFFSET and YOFFSET 2011-08-20 alaingdl * src/pro/idl_validname.pro: improvment of IDL_VALIDNAME, but not finished * testsuite/test_idl_validname.pro: initial import of test for IDL_VALIDNAME (not finished) * src/initsysvar.cpp: initial import of a EPOCH field in the !GDL structure * src/basic_fun.cpp: in STRCMP(), 2 bugs corrected when 2 arrays of string are provided. 2011-08-19 alaingdl * testsuite/test_file_which.pro, src/pro/file_which.pro: fixing last "/" in FILE_WHICH(), improving the related test file * testsuite/test_bug_3286031.pro, testsuite/test_bug_3376577.pro, testsuite/test_strsplit.pro: cleanup in 3 files in testsuite/ * CMakeModules/FindFFTW.cmake, CMakeModules/FindGSL.cmake, CMakeModules/FindGrib.cmake, CMakeModules/FindHDF.cmake, CMakeModules/FindLibproj4.cmake, CMakeModules/FindNetCDF.cmake, CMakeModules/FindNumpy.cmake, CMakeModules/FindPlplot.cmake, CMakeModules/FindReadline.cmake, CMakeModules/FindUdunits.cmake, CMakeLists.txt: update GDL version in CMakeLists.txt; copyright and GNU GPL licences added to all CMake files in dir. CMakeModules/ * quick_start_GDL.sh: in the script for quick start, preserving GDL_PATH/GDL_STARTUP 2011-08-18 slayoo * src/magick_cl.cpp: MAGICK_READ: fixing alpha channel read 2011-08-18 alaingdl * src/pro/idl_validname.pro: adding two fake keywords in IDL_VALIDNAME (/CONVERT_ALL] [, /CONVERT_SPACES) in order to be able to run End-To-End test of HealPix test program from E. Hivon. * src/pro/read_jpeg.pro: hum, bad if/then/else correction * src/pro/read_png.pro: better inputs checks for READ_PNG * src/pro/query_bmp.pro, src/pro/query_dicom.pro, src/pro/query_gif.pro, src/pro/query_image.pro, src/pro/query_jpeg.pro, src/pro/query_pict.pro, src/pro/query_png.pro, src/pro/query_ppm.pro, src/pro/query_tiff.pro, src/pro/read_jpeg.pro: now, we check we have compiled with ImageMagick support for these pro/functs which are using this external lib. * src/magick_cl.cpp: in MAGICK_OPEN, when filename is non existant, it is better to exist ... 2011-08-17 alaingdl * testsuite/test_interpolate_missing.pro: initial import (at the right place) of this file for testsuite 2011-08-17 slayoo * NEWS: NEWS update * testsuite/Makefile.am, testsuite/Makefile.in, src/gsl_fun.cpp, src/libinit_jmg.cpp: INTERPOLATE: support for the MISSING keyword 2011-08-16 slayoo * src/libinit_cl.cpp, src/magick_cl.cpp: moving fix of bug 3376577 from magick_open info libinit (so magick_create and magick_ping also benefit from it) 2011-08-15 slayoo * src/pro/findex.pro, src/pro/interpol.pro: fixing 3104537 in interpo.pro (patch by boudgdl) * doc/www/resources.php: adding a link to the redbranch blog in the resources section of the website 2011-08-12 alaingdl * doc/www/_news.inc.php: bad formatting news column * doc/www/_news.inc.php, doc/www/index.php, doc/www/requirements.php: few news; typo; details for libs. * src/pro/strsplit.pro: various bugs solved in STRSPLIT * testsuite/test_strsplit.pro: correcting and improving testsuite for STRSPLIT 2011-08-11 slayoo * doc/www/requirements.php: updating TeXtoIDL website address 2011-08-10 slayoo * doc/www/_footer.inc.php, doc/www/credits.php: Website update (incl. change of license for the website content so it is compatible with Wikipedia) * src/magick_cl.cpp: update to the fix of bug 3376577 2011-08-09 slayoo * src/gdlgstream.hpp: commiting changes suggested at https://sourceforge.net/projects/gnudatalanguage/forums/forum/338692/topic/4562373 * src/magick_cl.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3376577.pro: fixing bug 3376577 in Magick++ routines (fix by Lorenzo/lclem) * NEWS: NEWS update * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/idl_validname.pro: IDL_VALIDNAME: initial import (by Rene Preusker) 2011-07-11 slayoo * NEWS: NEWS update 2011-07-08 slayoo * doc/www/_header.inc.php: doc/www: new website 2011-07-08 alaingdl * doc/www/credits.php: itypo in Sylwester email 2011-07-08 slayoo * doc/www/_footer.inc.php, doc/www/_header.inc.php, doc/www/_news.inc.php, doc/www/contribute.html, doc/www/credits.html, doc/www/credits.php, doc/www/documentation.php, doc/www/download.html, doc/www/downloads.php, doc/www/feedback.html, doc/www/gdl.css, doc/www/home.html, doc/www/images/Colourise.css, doc/www/images/bg.jpg, doc/www/images/bullet.gif, doc/www/images/footer-top.jpg, doc/www/images/header-search.jpg, doc/www/index.html, doc/www/index.php, doc/www/menu.html, doc/www/require.html, doc/www/requirements.php, doc/www/resources.html, doc/www/resources.php, doc/www/screenshot.html, doc/www/screenshots.php, doc/www/screenshots/make_thumbnails, doc/www/screenshots/screenshot01_thumb.png, doc/www/screenshots/screenshot02_thumb.png, doc/www/screenshots/screenshot03_thumb.png, doc/www/screenshots/screenshot04_thumb.png, doc/www/screenshots/screenshot05_thumb.png, doc/www/screenshots/screenshot06_thumb.png, doc/www/screenshots/screenshot07_thumb.png, doc/www/screenshots/screenshot08_thumb.png, doc/www/screenshots/screenshot09_thumb.png, doc/www/screenshots/screenshot10_thumb.png, doc/www/screenshots/screenshot11_thumb.png, doc/www/screenshots/screenshot12_thumb.png, doc/www/screenshots/screenshot13_thumb.png, doc/www/support.html, doc/www/support.php, doc/www/tdl.html: doc/www: new website * src/gshhs.cpp: plotting: uploading missing files * src/plotting.hpp, src/plotting_axis.cpp, src/plotting_erase.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp: plotting: uploading missing changes 2011-07-07 slayoo * src/libinit.cpp, src/plotting_contour.cpp: CONTOUR: the C_COLORS keyword * AUTHORS, doc/udg/diag/broken-references, doc/udg/gdl.tex, doc/udg/chapters/credits.tex, doc/udg/chapters/semshm.tex: doc/udg update 2011-07-06 slayoo * src/basic_fun.cpp, src/libinit.cpp, testsuite/Makefile.am, testsuite/Makefile.in: fixing bug no. 3151760 2011-07-05 slayoo * src/deviceps.hpp: one compiler warning less * CMakeLists.txt: CMake: fix for supporting SPAWN, UNIT... * src/devicex.hpp: one compiler warning less 2011-07-04 slayoo * src/semshm.cpp: semshm.cpp: include fix * src/CMakeLists.txt: updating CMakeLists.txt - new files * src/io.hpp: io.hpp: fixing include issue 2011-07-03 slayoo * doc/udg/examples/showfont_3/gdl.ps, doc/udg/examples/showfont_4/gdl.ps, doc/udg/examples/showfont_7/gdl.ps, doc/udg/examples/surface_ax/gdl.ps, doc/udg/examples/surface_ax/surface_ax.out.txt, doc/udg/examples/surface_ax/surface_ax.pro, doc/udg/examples/surface_az/gdl.ps, doc/udg/examples/surface_az/surface_az.out.txt, doc/udg/examples/surface_az/surface_az.pro, doc/udg/routines/str-sep.fun.tex, doc/udg/routines/surface.pro.tex, doc/udg/diag/broken-references, doc/udg/examples/dist_0/gdl.ps, doc/udg/examples/file_lines_0/file_lines_0.out.txt, doc/udg/examples/routine_names_s_functions/routine_names_s_functions.out.txt: doc/udg update * src/basic_pro.cpp, src/plotting_contour.cpp, src/plotting_surface.cpp: SURFACE: using AutoIntvAC for xStart etc * testsuite/test_plotting_ranges.pro, src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp: CONTOUR: logscale plots when explicitely specifying X/Y values (tracker item no. 3321973) 2011-07-02 slayoo * src/devicex.hpp, src/initsysvar.cpp, src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_contour.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_surface.cpp, src/plotting_windows.cpp: SURCAFE: updating !Z.CRANGE; !P.T: initial values; default window size as a function of screen resolution (IDL behaviour); PLOTS: towards 3D support * src/semshm.cpp: semaphores: fixing on_exit behaviour (by Mateusz Turcza) 2011-07-01 slayoo * NEWS: NEWS update * testsuite/test_sem.pro: sanitizing test_sem.pro * src/basic_pro.cpp, testsuite/Makefile.am, testsuite/test_sem.pro, src/Makefile.am, src/Makefile.in, src/libinit.cpp, src/semshm.cpp, src/semshm.hpp: SEM_CREATE, SEM_LOCK, SEM_RELEASE, SEM_DELETE: initial import (by Mateusz Turcza) * src/hdf5_fun.cpp, src/hdf_fun.cpp, src/libinit_jmg.cpp, src/ncdf_cl.cpp: filename expansion in NCDF_OPEN, H5F_OPEN, HDF_OPEN & HDF_SD_START (tracker item no. 3164308) 2011-06-29 slayoo * src/basic_fun.cpp, src/envt.cpp, src/envt.hpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3313522.pro: fixing bug 3313522 2011-06-28 slayoo * testsuite/test_bug_3275334.pro: skipping test_bug_3275334.pro when X-server connection not available * src/gshhs.cpp: plotting routines: first step towards code clean-up * NEWS, configure.in, testsuite/Makefile.am, testsuite/test_spawn_unit.pro, src/basic_pro.cpp, src/io.cpp, src/io.hpp, src/libinit.cpp: SPAWN: support for the UNIT keyword (relies on GNU extensions to libstdc++, patch by Greg Huey) * src/ncdf_cl.cpp: NCDF_CONTROL: fixing error message (tracker item no. 3192226) * src/pro/dicom/Makefile.in, src/pro/dicom/gdlffdicom__assoc__define.pro, src/pro/dicom/gdlffdicom__assoc__test.pro, src/pro/dicom/gdlffdicom__define.pro, src/pro/dicom/gdlffdicom__test.pro, src/pro/dicom/gdlffdicom_copy_lun.pro, src/pro/dicom/gdlffdicom_date.pro, src/pro/dicom/gdlffdicom_time.pro, src/pro/dicom/gdlffdicom_trim.pro, COPYING: FSF address update in various files * src/Makefile.am, src/plotting.cpp, src/plotting.hpp, src/plotting_axis.cpp, src/plotting_contour.cpp, src/plotting_cursor.cpp, src/plotting_erase.cpp, src/plotting_misc.cpp, src/plotting_oplot.cpp, src/plotting_plot.cpp, src/plotting_plots.cpp, src/plotting_polyfill.cpp, src/plotting_surface.cpp, src/plotting_xyouts.cpp, src/Makefile.in: plotting routines: first step towards code clean-up 2011-06-18 slayoo * src/pro/UrgentNeed.txt: updating src/pro/UrgentNeed.txt 2011-06-15 alaingdl * src/pro/dialog_pickfile.pro: correcting a bug due to the fact that very long results from Zenity may be cut in several parts (1024 here) and need to be joined. 2011-06-07 alaingdl * testsuite/image_test.pro, testsuite/test-read_ascii.pro, testsuite/test-swap_endian.pro, testsuite/test-total.pro, testsuite/test_erfinv.pro, testsuite/test_plot_linestyle.pro, testsuite/test_suite.pro: 1/ all progs. are changed to Procedures to help compilation tests. 2/ we changed the way isGDL test is done * src/pro/dialog_pickfile.pro: Fixing parentheses around STRPOS 2011-06-06 alaingdl * src/pro/dialog_pickfile.pro: Using ":" as separator for zenity was not the best idea because some ESO FITS are using ":" inside the date format (in the file names); we move to "|" and also prepare a keyword: ZENITY_SEP to have more flexibility. 2011-05-13 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3152899.pro: adding test routine for bug no. 3152899 * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3300626.pro: adding test routine for bug no. 3300626 * testsuite/test_bug_3147733.pro, testsuite/Makefile.am, testsuite/Makefile.in: adding test routine for bug no. 3147733 * testsuite/test_bug_3290532.pro, testsuite/Makefile.am, testsuite/Makefile.in: adding test_bug_3290532.pro * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3189072.pro: adding test_bug_3189072.pro * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3286031.pro: adding test_bug_3286031.pro 2011-05-12 m_schellens * src/arrayindex.hpp, src/arrayindexlistt.hpp: Fixed ASSOC var indexing with a variable. Bug tracker ID 3300626 2011-05-11 m_schellens * src/GDLInterpreter.cpp, src/default_io.cpp, src/gdlc.i.g, src/print.cpp: Fixed bug tracker ID 3290532 and 3286031 2011-05-09 m_schellens * src/envt.hpp, src/fftw.cpp, src/gsl_fun.cpp, src/prognode.cpp: removed EnvT::StealLocalParUndefGlobal function * src/antlr/Makefile.in, src/pro/Makefile.in, testsuite/Makefile.in, src/Makefile.in, src/prognode.cpp: Fixed segfault in ASSIGN_REPLACENode::Run(). See Bug tracker ID 3152899 2011-05-06 slayoo * src/math_fun_gm.cpp, testsuite/Makefile.am, testsuite/test_bug_3298378.pro: fixing bug 3298378 (scalar return values from BETA, IGAMMA and EXPINT) 2011-05-04 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3296360.pro: adding test_bug_3296360.pro * src/typedefs.hpp: fixing bug no. 3296360 * testsuite/test_str_sep.pro: adding test_str_sep.pro 2011-05-02 slayoo * testsuite/Makefile.in, testsuite/Makefile.am, testsuite/test_bug_3275334.pro: adding test_bug_3275334.pro * src/devicex.hpp: TVRD: fixing bug no. 3275334 * testsuite/libtest_ce.cpp: fixing format labels in libtest_ce.cpp * src/gsl_fun.cpp: IMSL_CONSTANT: fixing wrong unit of Gravity * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_clip.pro, testsuite/test_fix.pro, testsuite/test_plotting_ranges.pro, testsuite/test_zzz.pro: testsuit update * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/README, testsuite/test_angles.pro, testsuite/test_bug_3189068.pro, testsuite/test_nans_in_sort_and_median.pro, testsuite/test_zzz.pro, testsuite/try: testsuite update 2011-05-01 slayoo * src/prognode.cpp: fixing memory leak bug no. 3282679 (and probably 3292468) 2011-04-27 slayoo * doc/udg/examples/call_external_0/CMakeLists.txt, doc/udg/examples/call_external_0/call_external_0.out.txt, doc/udg/examples/call_external_0/call_external_0.pro, doc/udg/examples/call_external_0/libexample.c: doc/udg: adding call_external example to the repository * doc/udg/examples/routine_names_0/library.pro, doc/udg/examples/routine_names_0/routine_names_0.out.txt, doc/udg/examples/routine_names_0/routine_names_0.pro, doc/udg/examples/routine_names_arg_name/procedure.pro, doc/udg/examples/routine_names_arg_name/routine_names_arg_name.out.txt, doc/udg/examples/routine_names_arg_name/routine_names_arg_name.pro, doc/udg/examples/routine_names_fetch/routine_names_fetch.out.txt, doc/udg/examples/routine_names_fetch/routine_names_fetch.pro, doc/udg/examples/routine_names_level/func.pro, doc/udg/examples/routine_names_level/routine_names_level.out.txt, doc/udg/examples/routine_names_level/routine_names_level.pro, doc/udg/examples/routine_names_s_functions/routine_names_s_functions.out.txt, doc/udg/examples/routine_names_s_functions/routine_names_s_functions.pro, doc/udg/examples/routine_names_s_procedures/routine_names_s_procedures.out.txt, doc/udg/examples/routine_names_s_procedures/routine_names_s_procedures.pro, doc/udg/examples/routine_names_store/routine_names_store.out.txt, doc/udg/examples/routine_names_store/routine_names_store.pro, doc/udg/examples/routine_names_variables/procedure.pro, doc/udg/examples/routine_names_variables/routine_names_variables.out.txt, doc/udg/examples/routine_names_variables/routine_names_variables.pro: doc/udg: adding routine_names examples to the repository * doc/udg/routines/acos.fun.tex, doc/udg/routines/asin.fun.tex, doc/udg/routines/atan.fun.tex, doc/udg/routines/ceil.fun.tex, doc/udg/routines/complex.fun.tex, doc/udg/routines/conj.fun.tex, doc/udg/routines/cos.fun.tex, doc/udg/routines/cosh.fun.tex, doc/udg/routines/file-mkdir.pro.tex, doc/udg/routines/floor.fun.tex, doc/udg/routines/hist-2d.fun.tex, doc/udg/routines/hist-nd.fun.tex, doc/udg/routines/idl-base64.fun.tex, doc/udg/routines/imaginary.fun.tex, doc/udg/routines/logical-and.fun.tex, doc/udg/routines/logical-or.fun.tex, doc/udg/routines/logical-true.fun.tex, doc/udg/routines/magick-writeindexes.pro.tex, doc/udg/routines/product.fun.tex, doc/udg/routines/ptrarr.fun.tex, doc/udg/routines/round.fun.tex, doc/udg/routines/routine-names.fun.tex, doc/udg/routines/sin.fun.tex, doc/udg/routines/sinh.fun.tex, doc/udg/routines/sqrt.fun.tex, doc/udg/routines/strcompress.fun.tex, doc/udg/routines/strlen.fun.tex, doc/udg/routines/strlowcase.fun.tex, doc/udg/routines/strmid.fun.tex, doc/udg/routines/strpos.fun.tex, doc/udg/routines/strput.pro.tex, doc/udg/routines/strtrim.fun.tex, doc/udg/routines/strupcase.fun.tex, doc/udg/routines/tan.fun.tex, doc/udg/routines/tanh.fun.tex, doc/udg/routines/total.fun.tex: doc/udg: new routine descriptions (mostly only the OpenMP info) * doc/udg/diag/broken-references, doc/udg/gdldoc.sty, doc/udg/makeall: doc/udg: doc scripts/styles/diag update * doc/udg/routines/abs.fun.tex: doc/udg updates: indexing routines which use OpenMP * doc/udg/routines/call-external.fun.tex: doc/udg updates: CALL_EXTERNAL docs * doc/udg/routines/exp.fun.tex, doc/udg/routines/fft.fun.tex, doc/udg/routines/where.fun.tex: doc/udg updates: indexing routines which use OpenMP 2011-04-26 slayoo * configure.in: quick'n'dirty solution to problems with compilation with GRIB when GRIB itself requires libpng (only autotools, not in CMake files) * src/libinit.cpp, src/plotting.hpp, src/plotting_map_proj.cpp: fixing compilation issue without Python 2011-04-18 slayoo * src/basic_fun_jmg.cpp, testsuite/Makefile.am, testsuite/test_bug_3288652.pro: ROUTINE_NAMES: fixing bug 3288652 2011-04-17 slayoo * src/libinit.cpp: PLOT: moving not supported keywords to a warn-list 2011-04-15 slayoo * doc/udg/diag/broken-references, doc/udg/examples/file_basename_2/file_basename_2.out.txt, doc/udg/examples/file_basename_2/file_basename_2.pro, doc/udg/examples/ncdf_exists_0/ncdf_exists_0.pro: doc/udg: various updates * doc/udg/examples/imsl_constant_0/imsl_constant_0.out.txt, doc/udg/examples/imsl_constant_0/imsl_constant_0.pro, doc/udg/routines/imsl-constant.fun.tex, doc/udg/routines/imsl-zeropoly.fun.tex: doc/udg: imcl_constant example 2011-04-14 slayoo * src/CMakeLists.txt, src/Makefile.am: src/Makefile.am: not installing the Python library to default system library location * CMakeModules/FindPythonLibs.cmake: removing FindPythonLibs.cmake 2011-04-12 slayoo * doc/udg/routines/dist.fun.tex, doc/udg/routines/imsl-zeropoly.fun.tex, doc/udg/examples/dist_0/dist_0.out.txt, doc/udg/examples/dist_0/dist_0.pro, doc/udg/examples/dist_0/gdl.ps, doc/udg/examples/imsl_zeropoly_0/gdl.ps, doc/udg/examples/imsl_zeropoly_0/imsl_zeropoly_0.out.txt, doc/udg/examples/imsl_zeropoly_0/imsl_zeropoly_0.pro: doc/udg: new examples (imsl_zeropoly, dist) * src/basic_pro.cpp: CATCH: warning the user just once that it is not implemented * src/file.cpp, src/file.hpp, src/libinit.cpp, src/pro/Makefile.in: FILE_MKDIR: initial import * src/pro/Makefile.am, src/pro/scope_varfetch.pro, testsuite/Makefile.am, testsuite/test_scope_varfetch.pro: SCOPE_VARFETCH: initial import * src/gdlgstream.cpp, src/plotting.cpp, src/plotting.hpp, src/plotting_xyouts.cpp: XYOUTS: handling P.MULTI vs. P.POSITION, support for ORIENTATION with logscales, making ORIENTATION work with arbitrary axis scales * INSTALL.CMake, README, testsuite/README: doc updates * doc/udg/examples/compile_opt_0/compile_opt_0.out.tex, doc/udg/examples/helloworld_2/gdl.ps, doc/udg/examples/loadct_0/gdl.ps, doc/udg/examples/python_fun_0/python_fun_0.out.txt, doc/udg/examples/showfont_11/gdl.ps, doc/udg/examples/showfont_11/showfont_11.out.txt, doc/udg/examples/showfont_11/showfont_11.pro, doc/udg/examples/showfont_12/gdl.ps, doc/udg/examples/showfont_12/showfont_12.out.txt, doc/udg/examples/showfont_12/showfont_12.pro, doc/udg/examples/showfont_13/gdl.ps, doc/udg/examples/showfont_13/showfont_13.out.txt, doc/udg/examples/showfont_13/showfont_13.pro, doc/udg/examples/showfont_14/gdl.ps, doc/udg/examples/showfont_14/showfont_14.out.txt, doc/udg/examples/showfont_14/showfont_14.pro, doc/udg/examples/showfont_15/gdl.ps, doc/udg/examples/showfont_15/showfont_15.out.txt, doc/udg/examples/showfont_15/showfont_15.pro, doc/udg/examples/showfont_16/gdl.ps, doc/udg/examples/showfont_16/showfont_16.out.txt, doc/udg/examples/showfont_16/showfont_16.pro, doc/udg/examples/showfont_17/gdl.ps, doc/udg/examples/showfont_17/showfont_17.out.txt, doc/udg/examples/showfont_17/showfont_17.pro, doc/udg/examples/showfont_18/gdl.ps, doc/udg/examples/showfont_18/showfont_18.out.txt, doc/udg/examples/showfont_18/showfont_18.pro, doc/udg/examples/showfont_20/gdl.ps, doc/udg/examples/showfont_20/showfont_20.out.txt, doc/udg/examples/showfont_20/showfont_20.pro, doc/udg/examples/showfont_3/gdl.ps, doc/udg/examples/showfont_3/showfont_3.out.txt, doc/udg/examples/showfont_3/showfont_3.pro, doc/udg/examples/showfont_4/gdl.ps, doc/udg/examples/showfont_4/showfont_4.out.txt, doc/udg/examples/showfont_4/showfont_4.pro, doc/udg/examples/showfont_5/gdl.ps, doc/udg/examples/showfont_5/showfont_5.out.txt, doc/udg/examples/showfont_5/showfont_5.pro, doc/udg/examples/showfont_6/gdl.ps, doc/udg/examples/showfont_6/showfont_6.out.txt, doc/udg/examples/showfont_6/showfont_6.pro, doc/udg/examples/showfont_7/gdl.ps, doc/udg/examples/showfont_7/showfont_7.out.txt, doc/udg/examples/showfont_7/showfont_7.pro, doc/udg/examples/showfont_8/gdl.ps, doc/udg/examples/showfont_8/showfont_8.out.txt, doc/udg/examples/showfont_8/showfont_8.pro, doc/udg/examples/showfont_9/gdl.ps, doc/udg/examples/showfont_9/showfont_9.out.txt, doc/udg/examples/showfont_9/showfont_9.pro, doc/udg/routines/showfont.pro.tex, doc/udg/chapters/syntax-udsub.tex, doc/udg/diag/broken-references, doc/udg/examples/calendar_0/gdl.ps, doc/udg/examples/colours_0/gdl.ps, doc/udg/examples/colours_1/gdl.ps, doc/udg/makeall, doc/udg/makeclean: doc/udg: various updates including SHOWFONT examples 2011-04-11 slayoo * src/gdlpython.cpp, src/gdlpython.hpp: reverting a previous (working) version of gdlpython.* * src/libinit.cpp, src/plotting_axis.cpp, src/plotting_contour.cpp: XYOUTS: handling XLOG and YLOG keywords * src/plotting.cpp: ignoring !P.MULTI when !POSITION set in PLOT and other plotting routines * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_misc.cpp: moving ERASE,SET_PLOT and TVLCT to a separate file (plotting_misc.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_map_proj.cpp: moving MAP_PROJ_FORWARD and MAP_PROJ_INVERSE to a separate file (plotting_map_proj.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_convert_coord.cpp: moving CONVERT_COORD to a separate file (plotting_convert_coord.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_windows.cpp: moving WINDOW,WSET,WSHOW,WDELETE,GET_SCREEN_SIZE to a separate file (plotting_windows.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_polyfill.cpp: moving POLYFILL to a separate file (plotting_polyfill.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_xyouts.cpp: moving XYOUTS to a separate file (plotting_xyouts.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting.hpp, src/plotting_plots.cpp: moving PLOTS to a separate file (plotting_plots.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_axis.cpp: moving AXIS to a separate file (plotting_axis.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_surface.cpp: moving SURFACE to a separate file (plotting_surface.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting.hpp, src/plotting_contour.cpp: moving CONTOUR to a separate file (plotting_contour.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_cursor.cpp: moving CURSOR to a separate file (plotting_cursor.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_device.cpp: moving DEVICE to a separate file (plotting_device.cpp) * src/CMakeLists.txt, src/Makefile.am, src/Makefile.in, src/plotting.cpp, src/plotting_oplot.cpp: moving OPLOT to a separate file (plotting_oplot.cpp) 2011-04-10 slayoo * src/Makefile.in, src/antlr/Makefile.in: Makefile.in update * src/antlr/CMakeLists.txt: cmake: updating antlr/CMakeLists.txt forgotten in one of previous commits * src/libinit.cpp: device: ignoring yet some more font-related keywords * src/pro/Makefile.in: src/pro/Makefile.in update * src/CMakeLists.txt, src/Makefile.am, src/plotting.cpp, src/plotting.hpp, src/plotting_plot.cpp: moving PLOT to a separate file (plotting_plot.cpp) * src/arrayindex.hpp, src/arrayindexlistt.hpp, src/datatypes.cpp, src/dinterpreter.hpp, src/envt.hpp, src/io.hpp: clang compatibility (mostly getting rid of compiler warnings) 2011-04-09 slayoo * doc/udg/examples/compile_opt_0/compile_opt_0.out.txt, doc/udg/examples/helloworld_2/gdl.ps, doc/udg/examples/loadct_0/gdl.ps, doc/udg/gdl.tex, doc/udg/chapters/syntax-compileopt.tex, doc/udg/chapters/testsuite.tex, doc/udg/examples/calendar_0/gdl.ps, doc/udg/examples/colours_0/gdl.ps, doc/udg/examples/colours_1/gdl.ps: doc/udg: various updates... * doc/udg/examples/openr_2/openr_2.pro, doc/udg/examples/query_bmp_0/query_bmp_0.pro, doc/udg/gdl.tex, doc/udg/gdldoc.sty, doc/udg/makeall, doc/udg/makeclean: doc/udg: various updates * doc/udg/examples/compile_opt_0/compile_opt_0.out.tex, doc/udg/examples/compile_opt_0/compile_opt_0.pro, doc/udg/examples/compile_opt_0/example.pro, doc/udg/examples/compile_opt_1/compile_opt_1.out.txt, doc/udg/examples/compile_opt_1/compile_opt_1.pro, doc/udg/examples/compile_opt_1/example.pro: doc/udg: adding two examples for compile_opt * src/basic_pro.cpp: CATCH: warning the user that cathing is not implemented yet * doc/udg/examples/calendar_0/calendar_0.out.txt, doc/udg/examples/colours_0/colours_0.out.txt, doc/udg/examples/colours_1/colours_1.out.txt, doc/udg/examples/correlate_0/correlate_0.out.txt, doc/udg/examples/correlate_1/correlate_1.out.txt, doc/udg/examples/correlate_2/correlate_2.out.txt, doc/udg/examples/execute_0/execute_0.out.txt, doc/udg/examples/exit_0/exit_0.out.txt, doc/udg/examples/exp_0/exp_0.out.txt, doc/udg/examples/fft_1/fft_1.out.txt, doc/udg/examples/file_basename_0/file_basename_0.out.txt, doc/udg/examples/file_basename_1/file_basename_1.out.txt, doc/udg/examples/file_basename_2/file_basename_2.out.txt, doc/udg/examples/file_lines_0/file_lines_0.out.txt, doc/udg/examples/foreach_0/foreach_0.out.txt, doc/udg/examples/foreach_1/foreach_1.out.txt, doc/udg/examples/get_login_info_0/get_login_info_0.out.txt, doc/udg/examples/goto_0/goto_0.out.txt, doc/udg/examples/h5_get_libversion_0/h5_get_libversion_0.out.txt, doc/udg/examples/helloworld_0/helloworld_0.out.txt, doc/udg/examples/helloworld_1/helloworld_1.out.txt, doc/udg/examples/helloworld_2/helloworld_2.out.txt, doc/udg/examples/if_0/if_0.out.txt, doc/udg/examples/if_1/if_1.out.txt, doc/udg/examples/if_2/if_2.out.txt, doc/udg/examples/imsl_binomialcoef_0/imsl_binomialcoef_0.out.txt, doc/udg/examples/imsl_binomialcoef_1/imsl_binomialcoef_1.out.txt, doc/udg/examples/ncdf_exists_0/ncdf_exists_0.out.txt, doc/udg/examples/obj_class_0/obj_class_0.out.txt, doc/udg/examples/obj_class_1/obj_class_1.out.txt, doc/udg/examples/openr_2/openr_2.out.txt, doc/udg/examples/parse_url_0/parse_url_0.out.txt, doc/udg/examples/pm_0/pm_0.out.txt, doc/udg/examples/ptr_free_0/ptr_free_0.out.txt, doc/udg/examples/python_fun_0/python_fun_0.out.txt, doc/udg/examples/query_bmp_0/query_bmp_0.out.txt, doc/udg/examples/scope_0/scope_0.out.txt, doc/udg/examples/string_4/string_4.out.txt, doc/udg/examples/strjoin_0/strjoin_0.out.txt, doc/udg/examples/strjoin_1/strjoin_1.out.txt, doc/udg/examples/abs_0/abs_0.out.txt, doc/udg/examples/strjoin_2/strjoin_2.out.txt: doc/udg: adding text output files for examples into the repository (they are all auto-generted during makeall run but keeping them in the repository can help to track regressions) * doc/udg/examples/obj_new_0/obj_new_0.out.txt, doc/udg/examples/obj_new_0/obj_new_0.pro, doc/udg/examples/obj_new_0/test__define.pro: doc/udg: adding an OBJ_NEW example * doc/udg/examples/loadct_0/listct.pro, doc/udg/examples/loadct_0/loadct_0.out.txt, doc/udg/examples/loadct_0/loadct_0.pro, doc/udg/examples/loadct_1/loadct_1.out.txt, doc/udg/examples/loadct_1/loadct_1.pro: doc/udg: adding LOADCT examples * doc/udg/routines/loadct.pro.tex, doc/udg/routines/obj-new.fun.tex: doc/udg: LOADCT docs with two examples (incl. graphical colour-table list) 2011-04-08 slayoo * testsuite/CMakeLists.txt: cmake/testsuite: cleanup in testsuite/CMakeLists.txt * src/gdlpython.cpp, src/gdlpython.hpp: fixing compilation issue with python * CMakeLists.txt, testsuite/CMakeLists.txt, testsuite/test_ce.pro: cmake: fxing issue with conflicting system-wide antlr headers, testsuite upgrades (list of test routines is now automatically extracted from Makefile.am, the libtest_ce.so and launchtest are now excluded from the all target but built during make-check) 2011-04-05 slayoo * src/libinit.cpp, src/libinit_jmg.cpp, src/widget.cpp, src/widget.hpp, src/gdlpython.cpp: TV: accepting the DEVICE keyword (corresponding to the current default behaviour); including WIDGET_* and PYTHON routines in the library routine list regardless of GDL configuration, and warning the user of missing features if necesarry 2011-04-03 alaingdl * testsuite/test_ce.pro: inline compilation for OSX now OK in "test_ce.pro" 2011-04-01 alaingdl * testsuite/test_ce.pro: improved version of TEST_CE.pro with the hope to have "dynamic" compilation of the lib. 2011-04-01 slayoo * src/pro/loadct.pro: LOADCT: not prompting for an argument when GET_NAMES is set (tracker item no. 3206594) 2011-03-30 slayoo * src/ofmt.hpp, testsuite/Makefile.am, testsuite/test_bug_3244840.pro: fixing bug 3244840 (bogus formatting of float zero after printing a string) * src/pro/Makefile.am, testsuite/Makefile.am, testsuite/test_file_which.pro, src/pro/file_which.pro: FILE_WHICH: initial import (patch by H Xu - xuhdev) * testsuite/test_correlate.pro, src/pro/correlate.pro: CORRELATE: support for the single-argument case * CMakeLists.txt, src/CMakeLists.txt: yet another cmake patch by Orion * CMakeLists.txt: cmake: numarray -> numpy transition (patch by Orion) * CMakeModules/FindNetCDF.cmake: cmake: patch by Orion to get netcdf working with centos 5 * CMakeModules/FindNumpy.cmake: cmake: as suggested by Orion, removing FindPythonLibs.cmake and adding FindNumpy.cmake 2011-03-29 m_schellens * configure.in: Put back CVS label for version string * configure.in, config.h.in, src/pro/Makefile.in, testsuite/Makefile.in: sync for release 2011-03-29 slayoo * NEWS: NEWS update * src/libinit.cpp: DEVICE: ignoring SET_FONT kw * src/libinit.cpp: WSHOW: ignoring ICONIC kw * src/pro/Makefile.am, testsuite/Makefile.am, src/pro/correlate.pro, testsuite/test_correlate.pro: CORRELATE: initial import (still without the single-argument option) 2011-03-28 slayoo * src/libinit.cpp, src/devicex.hpp, src/graphics.hpp, src/plotting.cpp: DEVICE: support for the WINDOW_STATE keyword * CMakeModules/FindNetCDF.cmake: cmake/netcdf fix (tracker item no. 3058299, patch by Orion Poplawski) * CMakeLists.txt: cmake/hdf4 fix (tracker item no. 3058299, patch by Orion Poplawski) * configure.in, src/gsl_fun.cpp: fixing bug no. 3233853 (Udunits-2 include path) * testsuite/Makefile.am, testsuite/test_bug_3199465.pro: adding test_bug_3199465.pro * testsuite/Makefile.am, testsuite/test_bug_3189068.pro: adding test_bug_3189068.pro * NEWS: updating NEWS (0.9.1) 2011-03-22 m_schellens * NEWS, src/gsl_fun.cpp: Included patch for udunits2. Bug tracker ID 3233853 * ChangeLog: Update ChangeLog GDL 0.9.1: 2011-03-18 slayoo * configure, gdl/configure: updating configure to reflect changes in configure.in (tracker item no. 3221630) 2011-03-17 slayoo * gdl/src/gdl.cpp, src/gdl.cpp: fixing behaviour with non-comma locale-defined decimal separators (tracker item no. 3164856) 2011-03-14 m_schellens * gdl/src/GDLInterpreter.cpp, gdl/src/GDLInterpreter.hpp, gdl/src/dinterpreter.cpp, gdl/src/envt.hpp, gdl/src/gdlc.i.g, gdl/src/image.cpp, gdl/src/prognode.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/dinterpreter.cpp, src/envt.hpp, src/gdlc.i.g, src/image.cpp, src/prognode.cpp: Fixed infinite recursion when struct are referenced but not defined in STRUCTNAME__DEFINE. Bug tracker ID 3189072 2011-03-13 m_schellens * gdl/src/envt.cpp, gdl/src/envt.hpp, src/envt.cpp, src/envt.hpp: Made HEAP_GC consider EnvBaseT::toDestroy list * gdl/src/envt.cpp, gdl/src/io.cpp, gdl/src/io.hpp, src/envt.cpp, src/io.cpp, src/io.hpp: Fixed bug tracker ID 3189068. PRINTF to closed stream segfault * gdl/src/envt.cpp, src/envt.cpp: Fixed bug tracker ID 3199465. HEAP_GC segfault. * gdl/src/GDLInterpreter.cpp, gdl/src/GDLInterpreter.hpp, gdl/src/envt.cpp, gdl/src/envt.hpp, gdl/src/gdlc.i.g, gdl/src/prognode.cpp, gdl/src/prognodeexpr.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognodeexpr.cpp: Fixed bug tracker ID 3152892. Temprorary pointers were garbage collected too early. 2011-03-12 m_schellens * gdl/src/envt.hpp, gdl/src/fftw.cpp, gdl/src/gsl_fun.cpp, src/envt.hpp, src/fftw.cpp, src/gsl_fun.cpp: Bug tracker ID: 3152899 - now input variable is explicitely undefined 2011-03-11 m_schellens * doc/Makefile.in, gdl/doc/Makefile.in, gdl/src/GDLInterpreter.hpp, gdl/src/Makefile.in, gdl/src/antlr/Makefile.in, gdl/src/envt.cpp, gdl/src/fftw.cpp, gdl/src/gdlc.i.g, gdl/src/gsl_fun.cpp, gdl/src/pro/Makefile.in, gdl/src/pro/dicom/Makefile.in, gdl/src/prognode.cpp, gdl/testsuite/Makefile.in, src/GDLInterpreter.hpp, src/Makefile.in, src/antlr/Makefile.in, src/envt.cpp, src/fftw.cpp, src/gdlc.i.g, src/gsl_fun.cpp, src/pro/Makefile.in, src/pro/dicom/Makefile.in, src/prognode.cpp, testsuite/Makefile.in, Makefile.in, aclocal.m4, gdl/Makefile.in, gdl/aclocal.m4: Fixed: FFT: segfault when overwriting a heap variable - Bug tracker ID: 3152899 2011-03-03 slayoo * gdl/doc/udg/examples/execute_0/execute_0.pro, gdl/doc/udg/makeall, gdl/doc/udg/routines/execute.fun.tex: doc/udg updates (EXECUTE + fixes in makeall) 2011-03-03 alaingdl * gdl/src/pro/dialog_message.pro, src/pro/dialog_message.pro: improved version of DIALOG_MESSAGE 2011-03-02 slayoo * gdl/testsuite/test_idl8.pro, testsuite/test_idl8.pro: adding test for a single-element negative array addressing to test_idl8.pro 2011-03-01 slayoo * configure.in, gdl/configure.in, gdl/src/pro/Makefile.am, src/pro/Makefile.am: Debian compatibility fixes in configure.in 2011-03-01 alaingdl * NEWS, gdl/NEWS: I just add ref. to new DIALOG_MESSAGE * gdl/src/pro/dialog_message.pro, src/pro/dialog_message.pro: initial import of DIALOG_MESSAGE, derived from DIALOG_PICKFILE, provided by P. Corona. You must have "zenity" to be able to use this functionality. 2011-02-28 slayoo * gdl/doc/udg/chapters/routine-list.tex, gdl/doc/udg/examples/helloworld_2/helloworld_2.pro, gdl/doc/udg/makeall, gdl/doc/udg/makeclean, gdl/doc/udg/routinelist.pro, gdl/doc/udg/routines/imsl-binomialcoef.fun.tex: doc/udg update: keywords are now listed in alphabetical order; some cosmetic changes and minor fixes 2011-02-27 slayoo * gdl/doc/udg/examples/if_0/if_0.pro, gdl/doc/udg/examples/if_1/if_1.pro, gdl/doc/udg/examples/if_2/if_2.pro, gdl/doc/udg/examples/if_2/replace_with_nans.pro, gdl/doc/udg/examples/imsl_binomialcoef_0/imsl_binomialcoef_0.pro, gdl/doc/udg/examples/imsl_binomialcoef_0/pascal.pro, gdl/doc/udg/examples/imsl_binomialcoef_1/imsl_binomialcoef_1.pro, gdl/doc/udg/examples/ncdf_exists_0/ncdf_exists_0.pro, gdl/doc/udg/examples/obj_class_0/alcoholic_drink__define.pro, gdl/doc/udg/examples/obj_class_0/beer__define.pro, gdl/doc/udg/examples/obj_class_0/drink__define.pro, gdl/doc/udg/examples/obj_class_0/obj_class_0.pro, gdl/doc/udg/examples/obj_class_1/obj_class_1.pro, gdl/doc/udg/examples/openr_2/openr_2.pro, gdl/doc/udg/examples/parse_url_0/parse_url_0.pro, gdl/doc/udg/examples/pm_0/pm_0.pro, gdl/doc/udg/examples/ptr_free_0/ptr_free_0.pro, gdl/doc/udg/examples/python_fun_0/python_fun_0.pro, gdl/doc/udg/examples/query_bmp_0/query_bmp_0.pro, gdl/doc/udg/examples/scope_0/scope_0.pro, gdl/doc/udg/examples/string_4/string_4.pro, gdl/doc/udg/examples/strjoin_0/strjoin_0.pro, gdl/doc/udg/examples/strjoin_1/strjoin_1.pro, gdl/doc/udg/examples/strjoin_2/strjoin_2.pro, gdl/doc/udg/routines/abs.fun.tex, gdl/doc/udg/routines/appleman.pro.tex, gdl/doc/udg/routines/array-indices.fun.tex, gdl/doc/udg/routines/calendar.pro.tex, gdl/doc/udg/routines/call-external.fun.tex, gdl/doc/udg/routines/correlate.fun.tex, gdl/doc/udg/routines/exit.pro.tex, gdl/doc/udg/routines/exp.fun.tex, gdl/doc/udg/routines/fft.fun.tex, gdl/doc/udg/routines/file-basename.fun.tex, gdl/doc/udg/routines/file-lines.fun.tex, gdl/doc/udg/routines/get-login-info.fun.tex, gdl/doc/udg/routines/h5-get-libversion.fun.tex, gdl/doc/udg/routines/imsl-binomialcoef.fun.tex, gdl/doc/udg/routines/linkimage.pro.tex, gdl/doc/udg/routines/ll-arc-distance.fun.tex, gdl/doc/udg/routines/map-continents.pro.tex, gdl/doc/udg/routines/ncdf-exists.fun.tex, gdl/doc/udg/routines/ncdf-varput.pro.tex, gdl/doc/udg/routines/newton.fun.tex, gdl/doc/udg/routines/obj-class.fun.tex, gdl/doc/udg/routines/openr.pro.tex, gdl/doc/udg/routines/parse-url.fun.tex, gdl/doc/udg/routines/pm.pro.tex, gdl/doc/udg/routines/ptr-free.pro.tex, gdl/doc/udg/routines/python.fun.tex, gdl/doc/udg/routines/query-bmp.fun.tex, gdl/doc/udg/routines/string.fun.tex, gdl/doc/udg/routines/strjoin.fun.tex, gdl/doc/udg/routines/where.fun.tex, gdl/doc/udg/chapters/about.tex, gdl/doc/udg/chapters/api.tex, gdl/doc/udg/chapters/coding.tex, gdl/doc/udg/chapters/compile-autotools.tex, gdl/doc/udg/chapters/compile-cmake.tex, gdl/doc/udg/chapters/compilers.tex, gdl/doc/udg/chapters/credits.tex, gdl/doc/udg/chapters/debug.tex, gdl/doc/udg/chapters/dochowto.tex, gdl/doc/udg/chapters/docs.tex, gdl/doc/udg/chapters/feedback.tex, gdl/doc/udg/chapters/internals.tex, gdl/doc/udg/chapters/io-ascii.tex, gdl/doc/udg/chapters/io-csv.tex, gdl/doc/udg/chapters/io-dicom.tex, gdl/doc/udg/chapters/io-grib.tex, gdl/doc/udg/chapters/io-hdf4.tex, gdl/doc/udg/chapters/io-idlsave.tex, gdl/doc/udg/chapters/io-netcdf.tex, gdl/doc/udg/chapters/io.tex, gdl/doc/udg/chapters/license.tex, gdl/doc/udg/chapters/math-basic.tex, gdl/doc/udg/chapters/math-fitting.tex, gdl/doc/udg/chapters/math-fourier.tex, gdl/doc/udg/chapters/math-multiroots.tex, gdl/doc/udg/chapters/math-ode.tex, gdl/doc/udg/chapters/math-rng.tex, gdl/doc/udg/chapters/openmp.tex, gdl/doc/udg/chapters/plot-2d.tex, gdl/doc/udg/chapters/plot-3d.tex, gdl/doc/udg/chapters/plot-colours.tex, gdl/doc/udg/chapters/plot-fonts.tex, gdl/doc/udg/chapters/plot-map.tex, gdl/doc/udg/chapters/python.tex, gdl/doc/udg/chapters/routine-list.tex, gdl/doc/udg/chapters/strings.tex, gdl/doc/udg/chapters/syntax-arguments.tex, gdl/doc/udg/chapters/syntax-array.tex, gdl/doc/udg/chapters/syntax-errhandle.tex, gdl/doc/udg/chapters/syntax-flowcon.tex, gdl/doc/udg/chapters/syntax-oop.tex, gdl/doc/udg/chapters/syntax-scope.tex, gdl/doc/udg/chapters/syntax-types.tex, gdl/doc/udg/chapters/syntax.tex, gdl/doc/udg/chapters/toc.tex, gdl/doc/udg/chapters/widgets.tex, gdl/doc/udg/examples/_post, gdl/doc/udg/examples/_pre, gdl/doc/udg/examples/abs_0/abs_0.pro, gdl/doc/udg/examples/calendar_0/calendar_0.pro, gdl/doc/udg/examples/colours_0/colours_0.pro, gdl/doc/udg/examples/colours_1/colours_1.pro, gdl/doc/udg/examples/correlate_0/correlate_0.pro, gdl/doc/udg/examples/correlate_1/correlate_1.pro, gdl/doc/udg/examples/correlate_2/correlate_2.pro, gdl/doc/udg/examples/exit_0/exit_0.pro, gdl/doc/udg/examples/exp_0/exp_0.pro, gdl/doc/udg/examples/fft_1/fft_1.pro, gdl/doc/udg/examples/fft_1/stddevfft.pro, gdl/doc/udg/examples/fft_1/stddevsum.pro, gdl/doc/udg/examples/file_basename_0/file_basename_0.pro, gdl/doc/udg/examples/file_basename_1/file_basename_1.pro, gdl/doc/udg/examples/file_basename_2/file_basename_2.pro, gdl/doc/udg/examples/file_lines_0/file_lines_0.pro, gdl/doc/udg/examples/foreach_0/foreach_0.pro, gdl/doc/udg/examples/foreach_1/example.pro, gdl/doc/udg/examples/foreach_1/foreach_1.pro, gdl/doc/udg/examples/get_login_info_0/get_login_info_0.pro, gdl/doc/udg/examples/goto_0/example.pro, gdl/doc/udg/examples/goto_0/goto_0.pro, gdl/doc/udg/examples/h5_get_libversion_0/h5_get_libversion_0.pro, gdl/doc/udg/examples/helloworld_0/helloworld_0.pro, gdl/doc/udg/examples/helloworld_1/helloworld_1.pro, gdl/doc/udg/examples/helloworld_2/helloworld_2.pro, gdl/doc/udg/gdl.bib, gdl/doc/udg/gdl.pro, gdl/doc/udg/gdl.tex, gdl/doc/udg/gdldoc.sty, gdl/doc/udg/makeall, gdl/doc/udg/makeclean, gdl/doc/udg/natbib.cfg, gdl/doc/udg/routinefiles.awk, gdl/doc/udg/routinelist.awk, gdl/doc/udg/routinelist.pro: doc/udg: initial import * gdl/src/gdlpsstream.cpp, gdl/src/gdlpsstream.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp: PostScript: fixing bogus empty first page bug (tracker item no. 3029064) * configure.in, gdl/configure.in: configure.in: adding hints for Debian/Ubuntu users * gdl/testsuite/checks, testsuite/checks: fixing backslash escape warning * gdl/src/pro/identity.pro, gdl/src/pro/trace.pro, src/pro/identity.pro, src/pro/trace.pro, gdl/src/pro/checks, src/pro/checks: minor fixes in src/pro/ 2011-02-22 alaingdl * gdl/src/basic_fun_jmg.cpp, src/basic_fun_jmg.cpp: correcting a problem in FSTAT(nlun) when "nlun" is not open 2011-01-23 slayoo * doc/www/screenshot.html, doc/www/tdl.html, gdl/doc/www/screenshot.html, gdl/doc/www/tdl.html: fixing two typos in doc/www (reported by Reuben Thomas) 2011-01-19 slayoo * gdl/testsuite/CMakeLists.txt, testsuite/CMakeLists.txt: cmake: update of test-routine list 2011-01-17 slayoo * gdl/src/print.cpp, src/print.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_2876161.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_2876161.pro: PRINT: fixing behaviur with e.g. print,[1],1,[1] (tracker item no. 2876161) 2011-01-16 slayoo * gdl/src/plotting.cpp, src/plotting.cpp: XYOUTS: fixing vertical position of text (moving it half the charsize up) - tracker item no. 2982623 * gdl/src/libinit.cpp, gdl/src/plotting.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_2610174.pro, src/libinit.cpp, src/plotting.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_2610174.pro: XYOUTS: adding support for the WIDTH keyword (trakcer item no. 2610174) 2011-01-15 slayoo * gdl/src/basic_fun.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_2876150.pro, src/basic_fun.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_2876150.pro: fixing string(1,"()") (tracker item no. 2876150) * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_2974380.pro, gdl/testsuite/test_known_bugs.pro, testsuite/Makefile.am, testsuite/test_bug_2974380.pro, testsuite/test_known_bugs.pro: adding test_bug_2974380.pro * gdl/src/ncdf_att_cl.cpp, gdl/testsuite/test_bug_3100945.pro, src/ncdf_att_cl.cpp, testsuite/test_bug_3100945.pro: NCDF_ATTNAME: fixing argument handling (tracker item no. 3100945) 2011-01-14 slayoo * gdl/src/ncdf_cl.cpp, src/ncdf_cl.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3055720.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3055720.pro: fixing error message in ncdf_varput (tracker item no. 3055720) * gdl/src/ncdf_dim_cl.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3057511.pro, gdl/testsuite/test_bug_3057520.pro, gdl/testsuite/test_bug_3061072.pro, src/ncdf_dim_cl.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3057511.pro, testsuite/test_bug_3057520.pro, testsuite/test_bug_3061072.pro: NCDF_DIMDEF: requireing dimension size for limited dims (tracker item no. 3057511) * gdl/src/ncdf_var_cl.cpp, src/ncdf_var_cl.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3057520.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3057520.pro: NCDF_VARPUT: checking OFFSET kw. dimensions (tracker item no. 3057520) * gdl/src/ncdf_att_cl.cpp, gdl/src/ncdf_cl.cpp, gdl/src/ncdf_var_cl.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3061072.pro, src/ncdf_att_cl.cpp, src/ncdf_cl.cpp, src/ncdf_var_cl.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3061072.pro: proper behaviour with non-existent attributes and variables in NCDF_VARID and NCDF_ATTNAME (tracker item no. 3061072) 2011-01-05 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3151760.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3151760.pro: test_bug_3151760.pro 2011-01-03 slayoo * configure.in, gdl/configure.in: configure.in: trying to be backward compatible (color-tests) * gdl/src/topython.cpp, src/topython.cpp: copying data to Python instead passing a soon-invalid pointer (tracker item no. 3148396) 2011-01-02 slayoo * doc/www/contribute.html, doc/www/require.html, doc/www/screenshot.html, doc/www/screenshots/screenshot13.png, doc/www/screenshots/screenshot13_thumb.png, gdl/doc/www/contribute.html, gdl/doc/www/require.html, gdl/doc/www/screenshot.html, gdl/doc/www/screenshots/screenshot13.png, gdl/doc/www/screenshots/screenshot13_thumb.png: doc/www update (numarray -> Numpy) 2011-01-01 slayoo * README, gdl/README, gdl/src/FMTParser.cpp, gdl/src/format.g, gdl/src/ofmt.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3147181.pro, src/FMTParser.cpp, src/format.g, src/ofmt.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3147181.pro: fixing two formatting bugs: 3147181 & 2555865 2010-12-31 slayoo * gdl/doc/misc/gdlffdicom.html, gdl/doc/misc/gdlffdicom__assoc.html, gdl/src/pro/dicom/Makefile.am, gdl/src/pro/dicom/Makefile.in, gdl/src/pro/dicom/gdlffdicom__assoc__define.pro, gdl/src/pro/dicom/gdlffdicom__assoc__test.pro, gdl/src/pro/dicom/gdlffdicom__assoc_generateuid.pro, gdl/src/pro/dicom/gdlffdicom__define.pro, gdl/src/pro/dicom/gdlffdicom__dictionary.pro, gdl/src/pro/dicom/gdlffdicom__test.pro, gdl/src/pro/dicom/gdlffdicom_copy_lun.pro, gdl/src/pro/dicom/gdlffdicom_date.pro, gdl/src/pro/dicom/gdlffdicom_time.pro, gdl/src/pro/dicom/gdlffdicom_trim.pro, src/pro/dicom/Makefile.am, src/pro/dicom/Makefile.in, src/pro/dicom/gdlffdicom__assoc__define.pro, src/pro/dicom/gdlffdicom__assoc__test.pro, src/pro/dicom/gdlffdicom__assoc_generateuid.pro, src/pro/dicom/gdlffdicom__define.pro, src/pro/dicom/gdlffdicom__dictionary.pro, src/pro/dicom/gdlffdicom__test.pro, src/pro/dicom/gdlffdicom_copy_lun.pro, src/pro/dicom/gdlffdicom_date.pro, src/pro/dicom/gdlffdicom_time.pro, src/pro/dicom/gdlffdicom_trim.pro: updating gdlffdicom to v20100309 (http://idl.barnett.id.au/idl-code/dicom20100309.zip) * gdl/testsuite/test_python.pro, testsuite/test_python.pro: test_python.pro update * gdl/src/gdl.cpp, gdl/src/gdlpython.cpp, gdl/src/gdlpython.hpp, gdl/src/objects.cpp, gdl/src/pythongdl.cpp, gdl/src/topython.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/test_python.pro, gdl/testsuite/test_python_module_1.pro, src/gdl.cpp, src/gdlpython.cpp, src/gdlpython.hpp, src/objects.cpp, src/pythongdl.cpp, src/topython.cpp, testsuite/Makefile.am, testsuite/test_python.pro, testsuite/test_python_module_1.pro, PYTHON.txt, README, configure.in, gdl/PYTHON.txt, gdl/README, gdl/configure.in, gdl/src/datatypes.cpp, gdl/src/datatypesref.cpp, src/datatypes.cpp, src/datatypesref.cpp: numarray -> Numpy transition (based on the patch by Orion Poplawski, the Gentoo GDL patch by Sebastien Fabbro and a helpful post by Ondrej Certik: http://mail.scipy.org/pipermail/numpy-discussion/2009-October/045888.html) 2010-12-29 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3091610.pro, gdl/testsuite/test_common.pro, gdl/testsuite/test_python_module_1.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3091610.pro, testsuite/test_common.pro, testsuite/test_python_module_1.pro: testsuite update * configure.in, gdl/configure.in: fixing Python module compilation on OSX * gdl/src/basic_fun.cpp, src/basic_fun.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/test_python_module_0.pro, gdl/testsuite/test_python_module_1.pro, gdl/testsuite/test_python_module_2.pro, testsuite/Makefile.am, testsuite/test_python_module_0.pro, testsuite/test_python_module_1.pro, testsuite/test_python_module_2.pro: fixing Python module + test_python_module* test routines (tracker item no. 3127190) 2010-12-28 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_2846561.pro, testsuite/Makefile.am, testsuite/test_bug_2846561.pro: adding test_bug_2846561.pro * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_2555865.pro, testsuite/Makefile.am, testsuite/test_bug_2555865.pro: adding test_bug_2555865.pro * gdl/src/FMTLexer.cpp, gdl/src/FMTOut.cpp, gdl/src/FMTParser.cpp, gdl/src/FMTParser.hpp, gdl/src/assocdata.hpp, gdl/src/basegdl.cpp, gdl/src/basegdl.hpp, gdl/src/convert2.cpp, gdl/src/datatypes.hpp, gdl/src/default_io.cpp, gdl/src/dstructgdl.hpp, gdl/src/fmtnode.hpp, gdl/src/format.g, gdl/src/format.out.g, gdl/src/gdl.cpp, gdl/src/ofmt.cpp, gdl/src/ofmt.hpp, gdl/src/specializations.hpp, gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_1779553.pro, gdl/testsuite/test_bug_3147146.pro, gdl/testsuite/test_deriv.pro, gdl/testsuite/test_dicom.pro, gdl/testsuite/test_grib.pro, gdl/testsuite/test_minmax.pro, gdl/testsuite/test_rk4.pro, gdl/testsuite/try, src/FMTLexer.cpp, src/FMTOut.cpp, src/FMTParser.cpp, src/FMTParser.hpp, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/convert2.cpp, src/datatypes.hpp, src/default_io.cpp, src/dstructgdl.hpp, src/fmtnode.hpp, src/format.g, src/format.out.g, src/gdl.cpp, src/ofmt.cpp, src/ofmt.hpp, src/specializations.hpp, testsuite/Makefile.am, testsuite/test_bug_1779553.pro, testsuite/test_bug_3147146.pro, testsuite/test_deriv.pro, testsuite/test_dicom.pro, testsuite/test_grib.pro, testsuite/test_minmax.pro, testsuite/test_rk4.pro, testsuite/try: zero padding in format strings, testsuite update 2010-12-16 alaingdl * gdl/src/plotting.cpp, src/plotting.cpp: continuing improving XYOUTS, PLOTS and POLYFILL. May have effects on others graphic routines (CONTOUR, SURFACE , ...) * gdl/src/plotting.cpp, src/plotting.cpp: extra factor 1.1111 for Y axis; option /device in XYOUTS and PLOTS (correcting bug 3085586). Maybe new bug for /data introduced but easy to see and solve. 2010-12-06 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, testsuite/Makefile.am, testsuite/Makefile.in: adding test_common.pro to the make-check file list 2010-12-04 m_schellens * gdl/src/io.cpp, src/io.cpp: fixed problem with CentOS (missing != operator) 2010-12-03 m_schellens * gdl/src/dinterpreter.cpp, src/dinterpreter.cpp: prevent identical lines being added to history * gdl/src/envt.hpp, gdl/src/io.cpp, gdl/src/io.hpp, src/envt.hpp, src/io.cpp, src/io.hpp, gdl/src/basic_pro_jmg.cpp, gdl/src/envt.cpp, src/basic_pro_jmg.cpp, src/envt.cpp: LONG64 for POINT_LUN (bug tracker ID: 3126348) * gdl/src/dpro.cpp, gdl/src/prognode.hpp, src/dpro.cpp, src/prognode.hpp, gdl/testsuite/Makefile.in, testsuite/Makefile.in: handle empty subroutine tree (NULL) (bug tracker ID: 3079713) 2010-11-30 alaingdl * gdl/testsuite/test_common.pro, testsuite/test_common.pro: initial import of a fast way to check if "common" are OK at compilation level (.r step) 2010-11-29 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3104326.pro, testsuite/Makefile.am, testsuite/test_bug_3104326.pro: test_bug_3104326.pro * gdl/testsuite/Makefile.am, gdl/testsuite/test_step.pro, testsuite/Makefile.am, testsuite/test_step.pro: test_step.pro * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3104209.pro, testsuite/Makefile.am, testsuite/test_bug_3104209.pro: test_bug_3104209.pro * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3085858.pro, testsuite/Makefile.am, testsuite/test_bug_3085858.pro: test_bug_3085858.pro * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3091599.pro, testsuite/Makefile.am, testsuite/test_bug_3091599.pro: test_bug_3091599.pro 2010-11-28 m_schellens * gdl/src/GDLInterpreter.cpp, gdl/src/GDLInterpreter.hpp, gdl/src/dinterpreter.cpp, gdl/src/dinterpreter.hpp, gdl/src/gdlc.i.g, gdl/src/objects.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/gdlc.i.g, src/objects.hpp: .STEP command * gdl/src/dstructgdl.cpp, src/dstructgdl.cpp: STRUCT: Made single array index access return array[1] (bug tracker ID: 3091599) * gdl/src/arrayindex.hpp, gdl/src/basegdl.cpp, gdl/src/basegdl.hpp, gdl/src/datatypes.cpp, gdl/src/datatypes.hpp, gdl/src/datatypesref.cpp, src/arrayindex.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp: Fixed negative index access * gdl/src/GDLInterpreter.cpp, gdl/src/GDLLexer.hpp, gdl/src/dinterpreter.cpp, gdl/src/gdlc.g, gdl/src/gdlc.i.g, gdl/src/prognode.cpp, src/GDLInterpreter.cpp, src/GDLLexer.hpp, src/dinterpreter.cpp, src/gdlc.g, src/gdlc.i.g, src/prognode.cpp: Fixed line number reporting for the call stack dump 2010-11-25 m_schellens * gdl/src/prognode.cpp, src/prognode.cpp: Clearer error message for CONTINUE outside loops 2010-11-24 m_schellens * configure.in, gdl/configure.in, gdl/src/gdl.cpp, gdl/src/includefirst.hpp, src/gdl.cpp, src/includefirst.hpp: Fixed preprocessor's HAVE_LIBREADLINE handling with python 2010-11-22 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3081887.pro, gdl/testsuite/test_plotting_ranges.pro, testsuite/Makefile.am, testsuite/test_bug_3081887.pro, testsuite/test_plotting_ranges.pro: testsuite update 2010-11-21 m_schellens * gdl/src/GDLInterpreter.cpp, gdl/src/dinterpreter.cpp, gdl/src/gdlc.i.g, gdl/src/pro/Makefile.in, gdl/testsuite/Makefile.in, src/GDLInterpreter.cpp, src/dinterpreter.cpp, src/gdlc.i.g, src/pro/Makefile.in, testsuite/Makefile.in: fixed _retTree for indexable_expr (bug tracker ID: 3081887) 2010-11-17 slayoo * gdl/src/gdlgstream.cpp, gdl/src/gdlpython.cpp, gdl/src/plot3d_nr.cpp, gdl/src/plotting.cpp, gdl/testsuite/libtest_ce.cpp, gdl/testsuite/test_ce.pro, src/gdlgstream.cpp, src/gdlpython.cpp, src/plot3d_nr.cpp, src/plotting.cpp, testsuite/libtest_ce.cpp, testsuite/test_ce.pro: fixing compiler warnings with GCC 4.4; temporarily commenting out a part of testsuite/libtest_ce.cpp (the rest works) 2010-11-15 slayoo * gdl/src/gdlwidget.cpp, src/gdlwidget.cpp: fixing compatibility with old (2007) libstdc++ (cf. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31005) * INSTALL.CMake, gdl/INSTALL.CMake: INSTALL.CMake: adding info about the Debug mode 2010-11-12 alaingdl * CMakeLists.txt, gdl/CMakeLists.txt: defaut compilation mode with CMake switched to "Release" in order to have good perfs' 2010-11-07 slayoo * gdl/src/basic_pro.cpp, src/basic_pro.cpp: EXIT: fixed segfault when compiled with wxWidgets and no X-server connection available (tracker item no. 2946058, patch by Orion Poplawski) * gdl/src/plotting.cpp, src/plotting.cpp: CONTOUR: better input dimesion check (tracker item no. 3055761) * gdl/src/pro/interpol.pro, gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3104349.pro, src/pro/interpol.pro, testsuite/Makefile.am, testsuite/test_bug_3104349.pro: INTERPOL: sanity check added (tracker item no. 3104349) 2010-11-06 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/test_bug_3104214.pro, testsuite/Makefile.am, testsuite/test_bug_3104214.pro, gdl/src/plotting.cpp, src/plotting.cpp: PLOTS vs. logscale fix (tracker item no. 3104214) 2010-10-28 slayoo * gdl/testsuite/libtest_ce.cpp, testsuite/libtest_ce.cpp: libtest_ce.cpp: GCC 4.3.3 (e.g.) compatibility fix 2010-10-27 slayoo * configure.in, gdl/configure.in, gdl/doc/misc/README.call_external, gdl/src/basic_pro_jmg.cpp, gdl/src/basic_pro_jmg.hpp, gdl/src/libinit_jmg.cpp, src/basic_pro_jmg.cpp, src/basic_pro_jmg.hpp, src/libinit_jmg.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/libtest_ce.cpp, gdl/testsuite/test_ce.pro, testsuite/Makefile.am, testsuite/libtest_ce.cpp, testsuite/test_ce.pro: CALL_EXTERNAL: initial import (patch by Christoph Fuchs, tracker item no. 3096214) 2010-10-26 alaingdl * gdl/testsuite/test_mpfit.pro, testsuite/test_mpfit.pro: adding keyword /debug in TEST_MPFIT ... 2010-10-26 slayoo * gdl/src/gshhs.cpp, gdl/src/plotting.cpp, gdl/src/plotting.hpp, src/gshhs.cpp, src/plotting.cpp, src/plotting.hpp, gdl/testsuite/test_clip.pro, testsuite/test_clip.pro: default range (if called before plot) and corrected clipping behaviour in XYOUTS, POLYFILL and PLOTS (patch from Joanna, tracker item no. 3029409) 2010-10-26 alaingdl * gdl/src/pro/restore.pro, gdl/src/pro/save.pro, src/pro/restore.pro, src/pro/save.pro: better messages when CMSV lib. not in the GDL/IDL_PATH * gdl/testsuite/test_get_screen_size.pro, gdl/testsuite/test_mpfit.pro, testsuite/test_get_screen_size.pro, testsuite/test_mpfit.pro: adding details to improve tests and warnings 2010-10-25 m_schellens * gdl/src/dstructgdl.hpp, src/dstructgdl.hpp: Fixed Clear() for tag by tag created structs (bug tracker ID: 3091610) 2010-10-23 slayoo * gdl/src/libinit.cpp, gdl/src/plotting.cpp, src/libinit.cpp, src/plotting.cpp: POLYFILL: support for LINE_FILL, SPACING, LINESTYLE, ORIENTATION and THICK (thanks to Joanna, tracker item no. 3029507) 2010-10-17 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_ps_decomposed.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_ps_decomposed.pro, gdl/src/deviceps.hpp, src/deviceps.hpp: decomposed colours with PostScript + test routine test_ps_decomposed.pro 2010-10-16 alaingdl * gdl/testsuite/test_strsplit.pro, testsuite/test_strsplit.pro, gdl/src/pro/strsplit.pro, src/pro/strsplit.pro: correcting bugs in STRSPLIT(); updating TEST_STRSPLIT in consequence. 2010-10-14 slayoo * gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3054361.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3054361.pro: testsuite/test_bug_3054361.pro: initial import * gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_bug_3086851.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3086851.pro: testsuite/test_bug_3086851.pro: initial import 2010-10-13 alaingdl * gdl/src/pro/strsplit.pro, src/pro/strsplit.pro: STRSPLIT: /REGEX and /PRESERVE_NULL should be compatible (may not work due to the complexity of STRSPLIT(), but "test_strsplit.pro" was OK) * gdl/testsuite/CMakeLists.txt, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_moment.pro, testsuite/CMakeLists.txt, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_moment.pro: adding TEST_MOMENT in testsuite * gdl/src/libinit_cl.cpp, gdl/src/ncdf_cl.cpp, gdl/src/ncdf_cl.hpp, src/libinit_cl.cpp, src/ncdf_cl.cpp, src/ncdf_cl.hpp: renaming all occurences of NCDF_EPOCH to CDF_EPOCH * gdl/src/pro/moment.pro, src/pro/moment.pro: correcting bug for Kurtosis in MOMENT() 2010-10-08 alaingdl * gdl/src/libinit_cl.cpp, gdl/src/ncdf_cl.cpp, gdl/src/ncdf_cl.hpp, src/libinit_cl.cpp, src/ncdf_cl.cpp, src/ncdf_cl.hpp: initial import of interface for NCDF_EPOCH, code not working ... 2010-10-01 alaingdl * gdl/testsuite/CMakeLists.txt, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, testsuite/CMakeLists.txt, testsuite/Makefile.am, testsuite/Makefile.in: upgrading list of files used in launchers of test/check * gdl/testsuite/test_mpfit.pro, testsuite/test_mpfit.pro: initial import of TEST_MPFIT, fast test of widely used Lib. MPFIT * gdl/quick_start_GDL.sh, quick_start_GDL.sh: adding the option for keeping current GDL_PATH when running "fast launcher" 2010-09-21 alaingdl * gdl/src/libinit_ac.cpp, gdl/src/math_fun_ac.cpp, gdl/src/math_fun_ac.hpp, src/libinit_ac.cpp, src/math_fun_ac.cpp, src/math_fun_ac.hpp: Initial import of missing functions PREWITT(), SOBEL() and ROBERTS(). Interfaces only, code not finished. 2010-09-20 alaingdl * gdl/src/math_fun_ac.cpp, src/math_fun_ac.cpp: fixing memory leak in SPL_INIT (bug 3070190) * gdl/src/basic_pro_jmg.cpp, src/basic_pro_jmg.cpp: removing useless comment in revisited WAIT 2010-09-16 slayoo * doc/www/resources.html, gdl/doc/www/resources.html: fixed broken link to a relocated bu.edu website 2010-09-15 alaingdl * gdl/src/basic_pro_jmg.cpp, src/basic_pro_jmg.cpp: WAIT: using nanosleep to avoid using 100% of CPU for long waits ... but keeping old code to have accurates small waits ;-) 2010-09-14 m_schellens * NEWS, gdl/NEWS, gdl/src/basic_fun.cpp, src/basic_fun.cpp: Set constant terminal with of 80 for STRING(/PRINT) (bug tracker ID: 3054361) 2010-09-10 slayoo * doc/www/contribute.html, doc/www/download.html, doc/www/home.html, gdl/doc/www/contribute.html, gdl/doc/www/download.html, gdl/doc/www/home.html: doc/www updates corresponding to the 0.9 release 2010-09-09 alaingdl * gdl/src/pro/save.pro, src/pro/save.pro: consequence of change 1.131 in "basic_fun.cpp" when calling EXECUTE, array not allowed now ... * gdl/testsuite/test_known_bugs.pro, testsuite/test_known_bugs.pro: correcting small bug in "test_known_bugs.pro" * CMakeLists.txt, gdl/CMakeLists.txt: upgrading version number (rc4 is over) 2010-09-02 opoplawski * gdl/CMakeModules/FindHDF.cmake: Search hdf sub-directories - finds hdf4 on Fedora * CMake.tar.gz, CMakeLists.txt, INSTALL.CMake, README.CMake, config.h.cmake, gdl/CMake.tar.gz, gdl/CMakeLists.txt, gdl/CMakeModules/FindFFTW.cmake, gdl/CMakeModules/FindGSL.cmake, gdl/CMakeModules/FindGrib.cmake, gdl/CMakeModules/FindHDF.cmake, gdl/CMakeModules/FindLibproj4.cmake, gdl/CMakeModules/FindNetCDF.cmake, gdl/CMakeModules/FindPlplot.cmake, gdl/CMakeModules/FindPythonLibs.cmake, gdl/CMakeModules/FindReadline.cmake, gdl/CMakeModules/FindUdunits.cmake, gdl/INSTALL.CMake, gdl/README.CMake, gdl/config.h.cmake, gdl/src/CMakeLists.txt, gdl/src/antlr/CMakeLists.txt, gdl/testsuite/CMakeLists.txt, src/CMakeLists.txt, src/antlr/CMakeLists.txt, testsuite/CMakeLists.txt: Check in CMake files into tree 2010-08-31 slayoo * gdl/src/basic_fun.cpp, gdl/src/envt.cpp, gdl/src/libinit.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_fixprint.pro, src/basic_fun.cpp, src/envt.cpp, src/libinit.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_fixprint.pro: FIX: support for TYPE=7 and /PRINT + test routine (test_fixprint.pro) 2010-08-30 alaingdl * CMake.tar.gz, gdl/CMake.tar.gz: Still improving the CMake alternative. Now target (gdl) don't loose PATH to alternative librairies (pb on Debian where we need dedicated Image Magick version). * CMake.tar.gz, gdl/CMake.tar.gz: better management of alternative path to ImageMagick lib. (need a "by-hand" Image Magick Lib. under Debian to avoid a known pb with Plplot (two seccessive calls to WINDOW will crash, see testsuite/test_known_bugs.pro)) 2010-08-27 slayoo * gdl/src/basic_fun.cpp, gdl/testsuite/Makefile.am, gdl/testsuite/Makefile.in, gdl/testsuite/test_execute.pro, src/basic_fun.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_execute.pro: EXECUTE: disallowing array arguments for compatibility with IDL 2010-08-26 alaingdl * gdl/src/pro/Makefile.am, gdl/src/pro/Makefile.in, src/pro/Makefile.am, src/pro/Makefile.in: adding new function SWAP_ENDIAN_INPLACE in Makefile.am and Makefile.in * gdl/src/pro/dialog_pickfile.pro, src/pro/dialog_pickfile.pro: missing a ")" in DIALOG_PICKFILE ... * gdl/src/default_io.cpp, gdl/src/file.cpp, src/default_io.cpp, src/file.cpp: default_io: being able to read (big) compressed files file.cpp: for FILE_SEARCH() * gdl/src/pro/swap_endian_inplace.pro, src/pro/swap_endian_inplace.pro: initial import of SWAP_ENDIAN_INPLACE(), derivate work from SWAP_ENDIAN(). This function is needed for the PDS Library (Planetary Data System, http://pds.nasa.gov/) * gdl/src/pro/dialog_pickfile.pro, src/pro/dialog_pickfile.pro: in DIALOG_PICKFILE, typos, and also new keywords: Display_name and Ressource_name * CMake.tar.gz, gdl/CMake.tar.gz: Upgrade of CMake tar (the alternative way to compile GDL) 2010-08-25 alaingdl * gdl/src/plotting.cpp, src/plotting.cpp: preliminary version for AX and AZ keywords in SURFACE 2010-08-25 slayoo * gdl/testsuite/README, gdl/testsuite/test_clip.pro, gdl/testsuite/test_fix.pro, gdl/testsuite/test_nans_in_sort_and_median.pro, gdl/testsuite/test_zzz.pro, testsuite/README, testsuite/test_clip.pro, testsuite/test_fix.pro, testsuite/test_nans_in_sort_and_median.pro, testsuite/test_zzz.pro: skipping known-bug cases in testsuite when not run using the CVS version of gdl 2010-08-25 m_schellens * gdl/src/Makefile.am, gdl/src/Makefile.in, src/Makefile.am, src/Makefile.in, configure.in, gdl/configure.in: Fixed inconsistency * ChangeLog, README, configure.in, gdl/ChangeLog, gdl/README, gdl/configure.in, gdl/src/GDLInterpreter.hpp, gdl/src/gdlc.i.g, gdl/src/gdlwidget.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g, src/gdlwidget.cpp: release GDL 0.9 * CMake.tar.gz, README.CMake, README.GRIB, README_GRIB, gdl/CMake.tar.gz, gdl/README.CMake, gdl/README.GRIB, gdl/README_GRIB: added CMake GDL 0.9: 2010-08-25 m_schellens * CMake.tar.gz, README.CMake, README.GRIB, README_GRIB: added CMake 2010-08-23 m_schellens * src/default_io.cpp, NEWS: Handle test files with CR delimiter 2010-08-18 alaingdl * src/plotting.cpp: in WINDOW, allowing title= no present OR to be converted (1e1 must be converted in 10.000) 2010-08-16 slayoo * src/gdlgstream.cpp: fixing lowercase gamma letter in greek script (reported by lolkje on the SF GDL forum) 2010-08-12 m_schellens * src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp: Implemented optional loop index (or hash value) variable for FOREACH 2010-08-11 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g: Added optional loop index (or hash value) variable to FOREACH (not functional yet) 2010-08-05 m_schellens * src/basic_pro.cpp: Changed default behaviour to not assume variable lenght VMS files (see bug tracker ID: 3028279) * src/ncdf_cl.cpp, src/ncdf_var_cl.cpp: Fixed error reporting for netCDF dimension IDs * src/GDLTreeParser.cpp, src/dcompiler.cpp, src/dinterpreter.cpp, src/dpro.cpp, src/gdlc.tree.g: Fixed optimization for self assignment * config.h.in, src/GDLInterpreter.cpp, src/GDLParser.cpp, src/gdlc.i.g: Fixed error message reporting (bug tracker ID: 2999950) 2010-07-27 slayoo * testsuite/test_idl8.pro, testsuite/test_pmulti.pro, testsuite/test_spher_harm.pro, testsuite/test_zeropoly.pro: updating testsuite to match the change in FOREACH syntax * src/GDLParser.cpp, src/gdlc.g: FOREACH: using COMMA instead of OF as in IDL8 (foreach i, arr do ...) 2010-07-25 slayoo * src/CFMTLexer.cpp, src/CFMTLexer.hpp, src/CFMTTokenTypes.hpp, src/CFMTTokenTypes.txt, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/FMTParser.cpp, src/FMTParser.hpp, src/FMTTokenTypes.hpp, src/FMTTokenTypes.txt, src/basegdl.hpp, src/cformat.g, src/format.g, src/format.in.g, src/format.out.g, src/ofmt.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_binfmt.pro: binary format codes for PRINT/STRING/READS/... (tracker item no. 3031999) 2010-07-23 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_bug_3033108.pro: testsuite/test_bug_3033108.pro: initial import 2010-07-19 slayoo * testsuite/test_clip.pro: test_clip.pro: adding PLOTS and XYOUTS (tracker item no. 3029082) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_clip.pro: adding test_clip.pro to the testsuite (tracker item no. 3029085) 2010-07-16 alaingdl * src/datatypes.cpp: correcting bug 3030379 in REVERSE when call with odd elements and without /overwrite 2010-06-29 slayoo * src/convert2.cpp: STRING: fixing bug 3022828 * src/gdlgstream.cpp, src/plotting.cpp: SET_PLOT: fixing bug 2913872 2010-06-29 alaingdl * testsuite/test_float2string.pro, testsuite/test_point_lun.pro: initial import of 2 new tests, not added in Makefile.am, not well packeged now ... * testsuite/Makefile.in, testsuite/Makefile.am: sing space between ".pro" and "\" * src/pro/Makefile.in: idem: missing files * src/pro/Makefile.am: adding missing new files. * src/pro/escape_special_char.pro: removing stupid duplication of keyword ! * NEWS: mention of Maxime' work on compressed files * testsuite/test_zip.pro: initial import of a testsuite around /compress keyword ... (Maxime L.) * src/assocdata.cpp, src/basic_fun_jmg.cpp, src/gzstream.hpp, src/io.cpp, src/print.cpp, src/read.cpp: Now, compress files (using gzip) should work (impacts on : readf, printf, seek, point_lun). Fstat outputs: size changed, new compress flag. Work done by Maxime L. 2010-06-29 slayoo * src/ncdf_cl.cpp: NCDF_*: fixing inf. loop in error message, corrected variable ids in error messages 2010-06-29 alaingdl * src/pro/file_copy.pro, src/pro/file_delete.pro: initial import of 2 new functionnalities: FILE_COPY and FILE_DELETE (writtent by Lea N.) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_file_basename.pro, testsuite/test_file_copy.pro, testsuite/test_file_delete.pro, testsuite/test_file_dirname.pro, testsuite/test_strsplit.pro: initial import of a serie of tests (written by Lea) for new functionnalities: file_copy, file_delete and also corrected/improved codes: file_basename, file_dirname (escaping), strsplit Makefile.am and Makefile.in updated. * src/pro/strsplit.pro: some improvments in STRPLIT() bye Lea, including /preserve_null * src/pro/file_expand_path.pro: initial import of FILE_EXPAND_PATH (by Lea) 2010-06-28 alaingdl * src/pro/escape_special_char.pro: initial import of ESCAPE_SPECIAL_CHAR(), used by some procedures managing Strings ... (e.g.: file_basename.pro, file_dirname.pro, file_delete.pro, file_copy.pro, ...) * src/pro/file_basename.pro, src/pro/file_dirname.pro: Escaping special Chars in FILE_DIRNAME and FILE_BASENAME 2010-06-25 alaingdl * src/file.cpp: correction for "." in FILE_SEARCH (Lea) 2010-06-23 slayoo * src/pro/dialog_pickfile.pro: DIALOG_PICKFILE: referencing Macports instead of Darwinports (the latter is bogus, see: http://trac.macports.org/wiki/DarwinPortsFraud) 2010-06-22 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_file_search.pro: initial import of "test_file_search.pro" (Makefile* upgrade done) * src/file.cpp: Activating the /FOLD_CASE keyword in FILE_SEARCH (code by M. Lenoir) * NEWS: upgrading informations in NEWS (important bugs corrections and new features) * src/pro/dialog_pickfile.pro: URL to Zenity HowTo install on OSX; unifying return to null string when failures. 2010-06-22 slayoo * doc/www/credits.html, doc/www/require.html: doc/www updates (fixed broken links in require.html) 2010-06-22 alaingdl * src/pro/dialog_pickfile.pro: Initial import of DIALOG_PICKFILE(), implementation by Maxime Lenoir. This code is using "zenity" (gdialog is now an alias to zenity). This code should work on most Linux distros (tested on CentOS 5.4, Mandriva 2010, Ubuntu 9.04) and OSX (tested on 10.6.2, after installation of Gnome Package). Keyword "filter" works since Zenity >= 2.23.1 2010-06-21 alaingdl * src/pro/str_sep.pro: correcting obsolete STR_SEP routine using /preverse_null in STRSPLIT; test at the end of the file. 2010-06-15 alaingdl * configure: upgrading "configure" in order to have the HAVE_X working ... * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_readf.pro: Initial import for "test_readf.pro" for testing CR/LF/(CR+LF) readings in ASCII files Makefile.am and Makefile.in in testsuite/ also upgraded * testsuite/test_fft_leak.pro: A /continue was missing in test_fft_leak.pro 2010-06-11 slayoo * configure.in, src/basegdl.hpp, src/basic_fun.cpp, src/deviceps.hpp, src/devicex.hpp, src/dinterpreter.hpp, src/file.cpp, src/gdlgstream.hpp, src/gdlwinstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/graphics.cpp, src/math_fun_jmg.hpp, src/plotting.cpp, src/str.cpp: OpenBSD compatibility fixes, making Xlib an optional dependency * src/basic_fun_jmg.cpp, src/objects.cpp: FSTAT: support for large (> 2GB) files (tracker item no. 3014216) 2010-06-09 slayoo * configure.in: configure: simplifying wxWidgets detection - now only wx-config is checked what should help od Fedora 2010-06-08 slayoo * NEWS, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/imsl_erf.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_erfinv.pro: IMSL_ERF: initial import + test-routine 2010-06-07 alaingdl * testsuite/test_fft_leak.pro: improvments (allowing not to exist with /no_exit, /force mentionned if Linux ...) * src/gsl_fun.cpp: when using GSL version of FFT, correcting input conversion for three types (now testsuite/test_fft.pro works for GSL only and also FFTw) * testsuite/Makefile.am, testsuite/Makefile.in: adding TEST_FFT_LEAK.pro in "make check" * testsuite/test_fft_leak.pro: initial import of TEST_FFT_LEAK.pro, checking memory leak when using GSL FFT or FFTw libs. * src/fftw.cpp: FFTw: correction of memory leak by Léa, using fftw_destroy_plan(p). See test_fft_leak.pro in testsuite/ 2010-06-05 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_get_screen_size.pro, testsuite/test_pmulti.pro: testsuite: adding test_pmulti, skipping test_get_screen_size if no X connection is available * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_nans_in_sort_and_median.pro: adding test_nans_in_sort_and_median.pro (cf. tracker item no. 2985552) * configure.in: configure: compatibility with grib_api 1.9.0 2010-06-04 slayoo * src/basic_pro.cpp: WRITEU: preventing segfault writing to freed/unopened lun (tracker item no. 3007448) * src/gdlwidget.cpp: unicode-wxWidgets compatibility fixes in gdlwidget.cpp (tracker item no. 3005435) * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_memory.pro: adding test_memory.pro * configure.in: configure: fixing auto-detection of FFTW 2010-06-01 alaingdl * src/deviceps.hpp: correcting rounding errors in functions SetXPageSize and SetYPageSize, affecting !D.X_SIZE in postscript mode 2010-05-31 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in: updating Makefile.am and Makefile.in to include "test_spl_init.pro" in testsuite/. Also changing place of "test_get_screen_size" in list (alpha order) * testsuite/test_spl_init.pro: initial import of TEST_SPL_INIT in testsuite/ (by Lea N.) * src/math_fun_ac.cpp: Adding YP0 and YPN_1 keywords to SPL_INIT 2010-05-31 slayoo * NEWS, src/dimension.hpp, src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit.cpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_spher_harm.pro: SPHER_HARM: initial import (using GSL gsl_sf_legendre_sphPlm) + test routine 2010-05-28 slayoo * src/pro/deriv.pro: DERIV: enabling error-reporting via MESSAGE 2010-05-27 jomoga * src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp: Further widget updates 2010-05-16 m_schellens * testsuite/test_suite.pro, config.h.in, src/GDLInterpreter.cpp, src/datalistt.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, testsuite/Makefile.am: sync 2010-05-05 m_schellens * src/typedefs.hpp, src/GDLInterpreter.cpp, src/basegdl.hpp, src/gdlc.i.g: enable memstats 2010-05-04 m_schellens * src/GDLInterpreter.cpp, src/dpro.hpp, src/gdlc.i.g, src/newprognode.cpp, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/typedefs.hpp: fixed FOR loops within $ 2010-05-03 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_get_screen_size.pro, testsuite/test_product.pro: Less messages in TEST_PRODUCT; adding revised TEST_GET_SCREEN_SIZE in "make check" 2010-05-03 m_schellens * src/GDLInterpreter.cpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/datatypes.cpp, src/gdlc.i.g, src/newprognode.cpp: add file 2010-05-01 m_schellens * src/GDLInterpreter.hpp, src/Makefile.am, src/Makefile.in, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun_cl.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/envt.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/GDLInterpreter.cpp: removed unnecessary copying in deref, IF, SWITCH, CASE 2010-04-27 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basegdl.hpp, src/datatypes.cpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: interpreter improvements 2010-04-26 slayoo * src/gshhs.cpp, src/plotting.cpp: POLYFILL: mapping support 2010-04-22 slayoo * MAP_INSTALL, src/gshhs.cpp, src/gshhs.hpp, src/libinit.cpp, src/libinit_jmg.cpp: some GSHHS-related cleanups 2010-04-22 alaingdl * src/pro/Makefile.in, src/pro/Makefile.am: forgot to include LUDC.pro in the Makefile.* files :( 2010-04-22 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/Makefile.in, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/envt.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/math_fun_jmg.cpp, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/specializations.hpp, src/typedefs.hpp, src/widget.cpp: optimized interpreter 2010-04-21 alaingdl * src/libinit.cpp, src/libinit_jmg.cpp: moving new SA declarations from "libinit.cpp" to "libinit_jmg.cpp" to keep map_* together and protected by the optionnal block for LIBPROJ4 #if defined(USE_LIBPROJ4) * src/pro/ludc.pro: LUDC.pro: initial import of a fake one to be able to run the full time_test3 suite * src/file.cpp: trying to manage "~" in GDL_PATH, also for EXPAND_PATH. No management of redundant entry (like "."); not sure path expansion always done ... 2010-04-21 slayoo * MAP_INSTALL: adding a hint to the MAP_INSTALL file * NEWS: update of the NEWS file * src/gshhs.cpp, src/gshhs.hpp, src/libinit.cpp, src/plotting.hpp, src/Makefile.am, src/plotting.cpp, INSTALL, MAP_INSTALL, README, configure.in: MAP_CONTINENTS: initial import (a lot needs to be done... but it works; uses GSHHS - a GPL-licensed shoreline database) 2010-04-20 m_schellens * src/basic_op.cpp, src/datatypes.cpp, src/gdlc.i.g, src/prognode.cpp, src/typedefs.hpp: commented out OpenMP usage for mere copy 2010-04-20 slayoo * doc/www/screenshot.html, src/deviceps.hpp, src/grib.cpp, src/grib.hpp, src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_device.pro: DEVICE: support for the INCHES kw, updating !D when called with XSIZE, YSIZE; test_device.pro; some other tiny cleanups 2010-04-20 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g, src/prognode.cpp: reduced overhead between statements 2010-04-19 m_schellens * src/GDLInterpreter.cpp, src/basic_fun.cpp, src/gdlc.i.g: reduced overhead between statements * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLLexer.hpp, src/GDLParser.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/dinterpreter.cpp, src/dpro.cpp, src/envt.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/libinit.cpp, src/objects.hpp, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/str.cpp: Fixed STRMID for 64 bit systems 2010-04-19 jomoga * src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit_jmg.cpp, src/objects.cpp, src/widget.cpp: Update widget code 2010-04-19 m_schellens * testsuite/Makefile.in, src/prognode.cpp: fixed FOR_STEP handling also negative steps 2010-04-18 m_schellens * src/str.cpp: debug info for STRMID * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp: interpreter optimizations 2010-04-17 slayoo * configure.in: making the plplot-modules/imagemagick message a warning (instead of an error) 2010-04-17 m_schellens * src/dinterpreter.cpp, src/dpro.cpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.g, src/gdlc.i.g, src/math_fun_jmg.cpp, src/prognode.cpp, src/prognode.hpp, src/widget.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_fun.cpp: changed internal representation of FOR/FOREACH loops 2010-04-16 m_schellens * src/basic_fun.cpp: removed OpenMP usage in STRMID * src/basic_fun.cpp: changed OpenMP options for STRMID 2010-04-16 alaingdl * testsuite/Makefile.am, testsuite/test_str_functions.pro: introduction of TEST_STR_FUNCTIONS in the "make check" testsuite * src/pro/strsplit.pro: updating STRSPLIT, correcting bugs * testsuite/test_str_functions.pro: initial import of TEST_STR_FUNCTIONS, regrouping tests on functions working on STRING, like STRMID, STRSPLIT, ... (to be included in "make check") 2010-04-16 slayoo * doc/www/screenshots/screenshot12.png, doc/www/screenshots/screenshot12_thumb.png, doc/www/screenshot.html: doc/www: adding a new screenshot (by Michal Piadlowski) 2010-04-16 m_schellens * src/basic_fun.cpp: fixed MEDIAN with NaN for floating types (1 dimensional case only) 2010-04-15 m_schellens * src/basic_fun.cpp: fixed SORT for floating types 2010-04-15 alaingdl * src/pro/str_sep.pro, src/pro/strsplit.pro: STR_SEP: rewriting and now managing sep. string with more than only one char STRSPLIT: cleanup and improvments 2010-04-14 m_schellens * src/GDLInterpreter.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g: make CLEANUP call when object is garbage collected 2010-04-14 alaingdl * src/pro/tvscl.pro: in TVSCL, return when input array not given or without elements * testsuite/test_read_jpeg.pro: better management of big images/small screen (and vertical/horizontal modes) 2010-04-13 m_schellens * src/envt.cpp: fixed reference counting in OBJ_DESTROY 2010-04-12 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g: add comment * src/strassenmatrix.hpp: fixed openmp * src/gdljournal.cpp, src/initsysvar.cpp: changed \!GDL sysvar, true GDL version for journal files * src/GDLInterpreter.cpp, src/basic_fun.cpp, src/gdlc.i.g: fixed EXECUTE messaging * src/envt.cpp, src/gsl_fun.cpp, src/hdf_pro.cpp, src/prognode.hpp, src/read.cpp: removed warning * NEWS, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/dcompiler.cpp, src/dinterpreter.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp: fixed IF_ELSE * src/dcompiler.cpp, src/dinterpreter.cpp, src/prognode.hpp, src/prognodeexpr.cpp: fixed empty block handling * src/dcompiler.cpp, src/prognode.hpp: fixed IF_ELSE * src/GDLInterpreter.hpp, src/gdlc.i.g: localization info for out of scope message * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dcompiler.cpp, src/gdlc.g, src/gdlc.i.g, src/prognode.hpp, src/prognodeexpr.cpp: optimized implementation of REPEAT/WHILE loops 2010-04-11 slayoo * src/gsl_fun.cpp, src/libinit_jmg.cpp: cosmetics... 2010-04-11 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLParser.cpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/basic_fun_jmg.cpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp: implemented special handling for N_ELEMENTS 2010-04-10 m_schellens * src/GDLTreeParser.cpp, src/basic_pro_jmg.cpp, src/envt.cpp, src/gdlc.tree.g, src/prognodeexpr.cpp: fixed error message info * src/envt.cpp: fixed WARNING message * src/read.cpp: Fixed behaviour of READ from cin * src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dcompiler.cpp, src/dinterpreter.cpp, src/dnode.cpp, src/dnode.hpp, src/dpro.cpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp: fixed error message info 2010-04-09 alaingdl * testsuite/test_tv.pro: more tests for TV: positionning and all Colors Tables 2010-04-09 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_fix.pro: adding test_fix.pro to the make-check list * src/pro/Makefile.am, src/pro/Makefile.in: reordering file list in src/pro/Makefile.* * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/findex.pro, src/pro/interpol.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_interpol.pro: INTERPOL: initial import (using FINDEX and SPL_INTERP, QUADRATIC and LSQUADRATIC not implemented yet) 2010-04-08 slayoo * src/pro/restore.pro: RESTORE: fixing compatibility with current CMSVLIB version; allowing restoration of more than 30 variables 2010-04-08 alaingdl * testsuite/test_tv.pro: adding TEST_TV_DAMIER in TEST_TV to check whether positionning with TV is OK or not * testsuite/Saturn.jpg, testsuite/test_read_jpeg.pro: reading back a JPEG file and testing TVSCL ... (initial import of Saturn.jpg and test_read_jpeg.pro) 2010-04-08 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_idl8.pro: adding test_idl8.pro with short tests of new features: FOREACH statement, negative indices, dot op. for member routine access 2010-04-07 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/checks, testsuite/test_zeropoly.pro, testsuite/test_zzz.pro, testsuite/try: testsuite: checking if all .pro files in testsuite are included in the make-check rule, fixing memory leak in test_zeropoly * src/basic_fun.cpp: adding a specialization for DComplexGDL in product_template() (fixes compilation problem with OpenMP enabled) * src/basic_fun.cpp, src/libinit.cpp, testsuite/test_hist_2d.pro: TOTAL/PRODUCT: support for the PRESERVE_TYPE keyword; test_hist_2d.pro: making the tests shorter 2010-04-07 m_schellens * src/antlr/LLkParser.cpp, src/antlr/Parser.cpp, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTreeParser.hpp, src/basic_pro_jmg.cpp, src/basic_pro_jmg.hpp, src/dinterpreter.cpp, src/gdlc.g, src/gdlc.tree.g, src/libinit_jmg.cpp: fixed tag access 2010-04-06 slayoo * testsuite/test_url.pro: test_url: fixing behaviour on terminals with small number of columns 2010-04-06 m_schellens * NEWS: update NEWS * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/arrayindex.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/gdlc.i.g, src/typedefs.hpp: support negative index ranges -1 is the last element, -2 the one before the last and so on 2010-04-06 alaingdl * testsuite/test_url.pro: try to improve TEST_URL without stopping the "make check" run ... 2010-04-06 m_schellens * NEWS: update NEWS * src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/GDLInterpreter.cpp: added FOREACH statement, syntax: FOREACH loopVar OF array DO 2010-04-05 m_schellens * src/dinterpreter.cpp: enabled auto printing of expressions again (was off dor debug) * src/GDLTreeParser.cpp, src/basic_fun.cpp, src/datatypes.cpp, src/gdlc.tree.g, src/prognodeexpr.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/antlr/LLkParser.cpp, src/antlr/Parser.cpp, src/antlr/TreeParser.cpp, src/dinterpreter.cpp, src/dnode.hpp, src/gdlc.g, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt: allow DOT \(.\) for member function calls 2010-04-02 alaingdl * testsuite/test_known_bugs.pro: Quickly testing known problems 2010-03-31 m_schellens * src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_pro.cpp, src/datatypesref.cpp, src/gdlc.g, src/gdlwidget.cpp, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, README: fixed reference counting 2010-03-30 slayoo * configure.in: configure: checking if plplot uses dynamic drivers when compiling with ImageMagick * testsuite/test_constants.pro: test_constants.pro: re-enabling some tests which do not need UDUNITS 2010-03-30 alaingdl * testsuite/test_constants.pro, testsuite/test_fft.pro: Reducing amount of un-useful messages for "make check"; desactivating UDUNITS if not available 2010-03-30 slayoo * src/libinit.cpp, src/plotting.cpp, src/plotting.hpp: POLYFILL: initial import (just an early draft) 2010-03-27 m_schellens * src/dinterpreter.cpp, src/libinit_jmg.cpp, src/widget.cpp: added keywords to keyword list for WIDGET_CONTROL * src/math_fun.cpp: improved accuracy of TAN for COMPLEX (by using double precision internally) * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlpsstream.cpp, src/gdlpsstream.hpp, src/gdlsvgstream.cpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/gdlzstream.cpp: working plplot 2010-03-26 m_schellens * src/gdlxstream.cpp, src/gdlgstream.hpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/gdlxstream.hpp, src/widget.cpp, gdl.kdevelop: fixed plplot issues * gdl.kdevelop, src/devicex.hpp: *** empty log message *** * src/gdlpsstream.hpp, configure, configure.in, gdl.kdevelop, src/datatypes.cpp: made wroking reference counting independent from use of python 2010-03-25 jomoga * src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp, src/widget.hpp: Added functionality 2010-03-25 m_schellens * gdl.kdevelop: removed debug message 2010-03-24 m_schellens * src/gdlgstream.hpp, configure.in, gdl.kdevelop, configure: removed debug message * src/devicex.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, gdl.kdevelop: sync 2010-03-22 slayoo * testsuite/test_gc.pro, testsuite/Makefile.am, testsuite/Makefile.in: test_gc.pro: initial import 2010-03-20 slayoo * src/plotting.cpp: AXIS: support for the /SAVE keyword 2010-03-16 m_schellens * src/Makefile.am, src/Makefile.in, src/deviceps.hpp, configure, configure.in, gdl.kdevelop: removed ` at end of line 1057 2010-03-16 alaingdl * src/libinit.cpp, src/plotting.cpp: Adding keyword GET_SCREEN_SIZE in DEVICE 2010-03-15 alaingdl * configure, configure.in: Correcting typo in 2 configure files ... 2010-03-15 slayoo * src/sigfpehandler.cpp: sigfpehandler.cpp: adding the system include needed for SIGFPE in GCC 4.3 2010-03-14 m_schellens * src/plotting.cpp: insert checks for sigControlC * src/dcompiler.cpp, src/dinterpreter.cpp, src/gdl.cpp, gdl.kdevelop: catch GDLRetAllException wiht -e 2010-03-13 m_schellens * src/basic_pro.cpp, src/dinterpreter.cpp, src/dinterpreter.hpp: prevent GDL from deleting history file * src/dinterpreter.cpp, src/read.cpp, src/sigfpehandler.cpp: fixed control-C and fpe handling * src/dinterpreter.cpp, src/dinterpreter.hpp, src/io.cpp, src/read.cpp: get input from READ thru readline * src/plotting.cpp, src/envt.hpp: working [XY]RANGE for AXIS * src/GDLInterpreter.hpp, src/convert2.cpp, src/gdlc.i.g: Changed string lenght of string for (unsigned)long to string conversion 2010-03-12 m_schellens * src/GDLInterpreter.hpp, src/gdlc.i.g: reference counting this time without debug messages :-) * src/accessdesc.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp: reference counting this time without fail (so far :-) * src/GDLInterpreter.hpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp, src/gdlc.i.g, src/objects.hpp: corrections for reference counting (more pemding, but previous version was broken 2010-03-11 m_schellens * src/GDLInterpreter.hpp, src/assocdata.hpp, src/basegdl.hpp, src/datatypes.cpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/envt.cpp, src/gdlc.i.g: reference counting for structures 2010-03-10 m_schellens * src/datatypes.cpp, src/GDLInterpreter.hpp, src/Makefile.am, src/Makefile.in, src/datatypesref.cpp, src/gdlc.i.g: reference counting for objects and pointer (only prints an info on out of scope, changes nothing) 2010-03-09 m_schellens * src/antlr/RefCount.hpp, src/GDLInterpreter.hpp, src/Makefile.am, src/Makefile.in, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/datatypesref.cpp, src/gdlc.i.g, src/objects.hpp: reference counting for objects and pointer (only prints an info on out of scope, changes nothing) 2010-03-08 m_schellens * src/io.hpp, src/io.cpp, src/magick_cl.cpp, src/basic_pro.cpp: expand path for ImageMagick-related routines 2010-03-07 m_schellens * src/GDLInterpreter.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_op.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/gdlc.i.g, src/specializations.hpp, src/strassenmatrix.hpp: handle nested ON_ERROR,2 2010-02-26 alaingdl * doc/www/download.html: fixing typo for link 2010-02-23 slayoo * src/plotting.cpp: CONTOUR: support for [x|y]style 2010-02-22 alaingdl * doc/www/screenshot.html: Including Saturn Legend * doc/www/screenshots/screenshot11.png, doc/www/screenshots/screenshot11_thumb.png: Initial import for Saturn page 2010-02-22 slayoo * MAP_INSTALL, README: correcting libproj4 url in README and MAP_INSTALL * src/plotting.cpp: AXIS: support for axes with arbitrary origin (patch from Joanna / cokhavim) 2010-02-20 slayoo * src/libinit.cpp, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/STATUS, src/pro/UrgentNeed.txt, src/pro/hist_2d.pro, src/pro/hist_nd.pro, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_hist_2d.pro, testsuite/test_rebin.pro, src/basic_fun.cpp, src/dpro.cpp: HIST_2D: initial import (using a GPL-licensed HIST_ND) + test routine REBIN: support for specifying new dimensions as an array + test routine dpro.cpp/DLibFunRetNew() - support for specifying warnKeywords TOAL/PRODUCT: ignoring PRESERVE_TYPE keyword (treating as warnKeyword) 2010-02-20 m_schellens * configure.in, src/GDLInterpreter.hpp, src/gdlc.i.g, configure: included suggestion for directly linking dl, see https://sourceforge.net/tracker/?func=detail&aid=2952365&group_id=97659&atid=618683 2010-02-19 m_schellens * src/print.cpp, README, configure, configure.in, gdl.kdevelop: made FORMAT accept (but ignore) an empty format string 2010-02-19 alaingdl * testsuite/test_fft.pro: error in call to EXIT ... * testsuite/test_fft.pro: improved TEST_FFT to test in N dims consitancy of direct then forward FFTs. 2010-02-17 m_schellens * src/math_utl.hpp, doc/www/home.html, configure.in, gdl.kdevelop, configure: use FFTW automatically if found 2010-02-17 slayoo * testsuite/Makefile.am, testsuite/Makefile.in, testsuite/README, testsuite/test_suite.pro: adding test_suite.pro to the make-check rule 2010-02-13 slayoo * INSTALL, README, testsuite/README: initial import of gdl/testsuite/README, minor updates in gdl/README and gdl/INSTALL 2010-02-12 slayoo * src/pythongdl.cpp: pythongdl.cpp: Python >2.4 compatibility (Py_ssize_t) * configure.in, src/antlr/Makefile.am, src/antlr/Makefile.in, src/gdlpython.cpp, src/pythongdl.cpp: not installing libantrl.a during make-install (gdl is statically linked with it), fixing a missing include in pythongdl.cpp, informing about the build type (standalone/Python module) in the post-configure message 2010-02-11 slayoo * src/pro/README.txt, src/math_utl.hpp: GCC 4.5 compatibility (math_utl.hpp); corrected some typos in the src/pro/README.txt file noted by the Debian packager * doc/www/download.html: doc/www: adding info about the Debian GNU/kFreeBSD packages 2010-02-11 alaingdl * testsuite/Makefile.am, testsuite/Makefile.in: upgrading automatic test suite files in directory testsuite/ * testsuite/test_fft.pro: Initial important of "test_fft.pro", a preliminary version of a testsuite for FFT * src/fftw.cpp: Important change in FFT when using FFTw lib. This bug correction is not now propagated in FFT when using GSL (in "gsl_fun.cpp") Please test using "test_fft.pro" * testsuite/test_product.pro: Wider tests for PRODUCT(), including /int, /nan, and dim param. * src/basic_fun.cpp: dding management of keyword /Integer to PRODUCT function (see test_product.pro) This Keyword is used in current Astron Lib. 2010-02-09 alaingdl * src/libinit.cpp: adding INTEGER keyword in the PRODUCT function 2010-02-08 slayoo * doc/Makefile, testsuite/Makefile, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_product.pro: adding test_product.pro to the make-check rule, removing doc/Makefile and testsuite/Makefile files 2010-02-08 alaingdl * testsuite/test_product.pro: Initial import for TEST_PRODUCT.pro: testing some options of PRODUCT function 2010-02-07 m_schellens * doc/www/credits.html: alphabetic order * src/dinterpreter.cpp: Corrected error reporting for GDLDirectPrint(tm) 2010-02-06 m_schellens * gdl.kdevelop, src/dinterpreter.cpp: command line calculator mode - just type an expression GDL prints it 2010-02-05 m_schellens * src/dnode.cpp: test CVS access 2010-02-03 m_schellens * doc/www/credits.html: rc4 2010-02-02 m_schellens * src/lapack.cpp: add file * src/GDLParser.cpp, src/Makefile.am, src/Makefile.in, src/dnode.cpp, src/dnode.hpp, src/gdlc.g, README, config.h.in, configure: Fixed missing promption of integer constants with DEFINT32 set 2010-02-01 slayoo * configure.in: configure: adding -lrps flag to LIBS for the Cygwin case (patch from Mateusz Turcza) * configure.in: autodetection of OpenMP using AC_CHECK_HEADERS(omp.h) 2010-01-31 slayoo * configure.in: re-enabling autodetection of Ubuntu-style wxWidgets installation; change of GDL version number * src/widget.cpp: fixing widget.cpp after a change in arguments of GDLParser constructor 2010-01-30 slayoo * NEWS: update of the NEWS file (.9rc4 section) 2010-01-30 m_schellens * configure.in, gdl.kdevelop, configure: handling --with-openmp * ChangeLog, NEWS: update NEWS GDL 0.9rc4: 2010-01-30 m_schellens * ChangeLog, Makefile.in, configure, doc/www/credits.html, gdl.kdevelop, src/deviceps.hpp, src/graphics.hpp, src/libinit.cpp, src/plotting.cpp: Applied patch (tracker item 2860573) adding XSIZE, YSIZE, COLOR for PS output to DEVICE (patch from Joanna/cokhavim) 2010-01-29 slayoo * testsuite/Makefile, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_base64.pro, testsuite/test_constants.pro, testsuite/test_nestedloop.pro: testsuite: including test_base64, test_constants and test_nestedloop in the make-check rule * doc/Makefile, doc/Makefile.am, doc/Makefile.in, doc/gdl.1, testsuite/Makefile, testsuite/Makefile.am, testsuite/Makefile.in, testsuite/test_angles.pro, testsuite/test_multiroots.pro, testsuite/test_url.pro, testsuite/test_wavelet.pro, testsuite/test_zeropoly.pro, testsuite/try, Makefile.am, configure.in: including some of the tests from the testsuite in a make-check rule, adding a manpage (+including it in the make-install rule) * src/gdlgstream.hpp: fixing memory leak in GDLGStream::checkPlplotDriver() (thanks Alain/Valgrind) 2010-01-28 m_schellens * src/GDLInterpreter.cpp, src/GDLParser.hpp, src/dinterpreter.cpp, src/dpro.cpp, src/dpro.hpp, src/gdlc.g, src/gdlc.i.g: Fixed some uninitialized value issues detected with valgrind 2010-01-28 slayoo * doc/www/screenshot.html: doc/www: adding screenshots of GDL running on Windows under Cygwin and coLinux * src/file.cpp, src/gsl_fun.cpp, src/plotting.cpp, src/str.cpp: Cygwin and GCC 3.4.4 compatibility fixes (patch by Mateusz Turcza) * src/deviceps.hpp, src/devicesvg.hpp, src/devicewin.hpp, src/devicex.hpp, src/devicez.hpp: helping the compiler to disambiguate plstream->spause() calls and thus fixing compatibility with GCC 3.4.4 (patch by Mateusz Turcza) * README, configure.in: checking for GSL >=1.7 which is requiered to use both FFT and DWT at the same time 2010-01-27 slayoo * doc/www/menu.html, doc/www/screenshot.html, doc/www/screenshot.png: doc/www: update of the screenshots section * src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit.cpp, testsuite/test_zeropoly.pro: IMSL_ZEROPOLY: initial import (using gsl_poly_complex_solve()) 2010-01-25 m_schellens * src/FMTOut.hpp, src/format.out.g, gdl.kdevelop, src/FMTParser.cpp, src/print.cpp: fixed T,TL,TR format codes 2010-01-23 slayoo * src/ncdf_cl.cpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp, src/ncdf_att_cl.cpp: NCDF_*: fixes in error handling, support for LENGTH keyword in NCDF_ATTPUT; allowing to specify the global atribute number in NCDF_ATTNAME; outputing byte arrays instead of strings in NCDF_ATTGET; compatibility with netcd-4 (file handles are now Long instead of Int) * src/fftw.cpp, src/libinit_jmg.cpp: FFT: preventing bogus memory freeing with dcomplex input (tracker item no. 2935682) 2010-01-22 slayoo * doc/www/download.html: doc/www: update of the Download section- adding info about CVS access, links to packaged versions, and a note encouraging to use packages based on current release 2010-01-20 m_schellens * doc/www/support.html, doc/www/tdl.html, doc/www/contribute.html, doc/www/credits.html, doc/www/download.html, doc/www/feedback.html, doc/www/gdl.css, doc/www/home.html, doc/www/index.html, doc/www/menu.html, doc/www/require.html, doc/www/resources.html, doc/www/screenshot.html, doc/www/screenshot.png: Added source of http://gnudatalanguage.sourceforge.net/ to doc/www 2010-01-20 slayoo * testsuite/test_wavelet.pro, src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit.cpp: WTN: initial import (using GSL DWT routines) + test-routine (test_wavelet.pro) * src/pro/array_indices.pro, src/pro/calendar.pro, src/pro/file_basename.pro, src/pro/file_dirname.pro, src/pro/imsl_zerosys.pro, src/pro/ishft.pro, src/pro/last_item.pro, src/pro/lmgr.pro, src/pro/loadct.pro, src/pro/map_clip_set.pro, src/pro/matrix_multiply.pro, src/pro/path_sep.pro, src/pro/poly.pro, src/pro/poly_area.pro, src/pro/py_plot.pro, src/pro/py_print.pro, src/pro/query_bmp.pro, src/pro/query_dicom.pro, src/pro/query_gif.pro, src/pro/query_image.pro, src/pro/query_jpeg.pro, src/pro/query_pict.pro, src/pro/query_png.pro, src/pro/query_ppm.pro, src/pro/query_tiff.pro, src/pro/read_bmp.pro, src/pro/read_dicom.pro, src/pro/read_jpeg.pro, src/pro/read_pict.pro, src/pro/read_png.pro, src/pro/read_tiff.pro, src/pro/read_xwd.pro, src/pro/restore.pro, src/pro/rstrpos.pro, src/pro/showfont.pro, src/pro/str_sep.pro, src/pro/uniq.pro, src/pro/write_bmp.pro, src/pro/write_jpeg.pro, src/pro/write_pict.pro, src/pro/write_png.pro, src/pro/appleman.pro: adding on_error,2 for routines implemented in GDL 2010-01-18 slayoo * src/magick_cl.cpp: making ImageMagick format decoder warning non fatal (tracker item no 2934374) 2010-01-17 m_schellens * src/GDLParser.cpp, src/gdlc.g: Honor more than one COMPILE_OPT within $ * src/GDLLexer.hpp, src/GDLParser.hpp, src/dinterpreter.cpp, src/envt.hpp, src/gdlc.g: Honor COMPILE_OPT within $ and EXECUTE 2010-01-16 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_fun.cpp, src/dcompiler.cpp, src/dinterpreter.cpp, src/dpro.hpp, src/envt.hpp, src/gdlc.g, src/math_fun_jmg.cpp: Honor COMPILE_OPT within $ and EXECUTE * src/devicex.hpp: Fixed segfault caused by TVRD with no window open * gdl.kdevelop, src/datatypes.cpp, src/devicex.hpp: Corrected error message for constant indices 2010-01-16 slayoo * src/dcompiler.cpp, src/gdlexception.cpp, src/gdlexception.hpp: adding a warning about compiling an obsolete routine when it is compiled for the first time, thus changing the behaviour below: GDL> !WARN.OBS_ROUTINES=1 GDL> for i=0, 2 do a=rstrpos(' ',' ') % Compiled module: RSTRPOS. GDL> for i=0, 2 do a=rstrpos(' ',' ') % Routine compiled from an obsolete library: RSTRPOS into: GDL> !WARN.OBS_ROUTINES=1 GDL> for i=0, 2 do a=rstrpos(' ',' ') % Routine compiled from an obsolete library: RSTRPOS % Compiled module: RSTRPOS. GDL> for i=0, 2 do a=rstrpos(' ',' ') % Routine compiled from an obsolete library: RSTRPOS 2010-01-15 slayoo * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt: progagating changes in gdlc.g (previous commit) to gdlc.i.g- and gdlc.tree.g-related GDL*.pp files * src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/gdlc.g, src/GDLLexer.hpp: support for numeric constants in explicit binary format, e.g. a='1010101'b (tracker item no. 2932619) 2010-01-14 slayoo * src/pro/file_lines.pro: FILE_LINES: spawning subprocesses with /NOSHELL keyword to prevent execution of shell startup file (patch by Lucio Baggio, patch-tracker item no. 2932168) 2010-01-10 m_schellens * src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in, Makefile.in, aclocal.m4, config.h.in, configure, configure.in, gdl.kdevelop, ltmain.sh, src/Makefile.in, src/basic_op.cpp, src/datatypes.cpp, src/default_io.cpp: Fixed line number reporting 2010-01-05 slayoo * configure, configure.in, config.h.in: configure script: support for the Debian naming of the HDF4 libraries from the hdf4-alt packages (compiled with --disable-netcdf) 2010-01-04 slayoo * src/hdf5_fun.cpp: HDF5 1.6 compatibility fix (in error handling) 2010-01-03 slayoo * src/hdf5_fun.cpp, src/hdf5_fun.hpp, src/libinit_mes.cpp: error-handling in HDF5-related routines; initial import of: h5f_is_hdf5_fun, h5_get_libversion_fun, h5d_get_type_fun h5t_get_size_fun, h5a_open_name_fun, h5a_open_idx_fun, h5a_get_name_fun, h5a_get_space_fun, h5a_get_type_fun, h5a_get_num_attrs_fun, h5g_open_fun, h5a_close_pro, h5t_close_pro, h5g_close_pro, h5a_read 2010-01-02 slayoo * src/devicex.hpp, src/plotting.cpp: CONTOUR: fixing colours of axes in CONTOUR (.../forum/338692/topic/3306795); making the initial "DECOMPOSED" setting of the X device dependtant on the colour depth reported by the X-server 2010-01-01 slayoo * src/gdlgstream.hpp, src/libinit.cpp: UINDGEN: correcting the keyword list (indKey -> NULL); gdlgstream.hpp: informing the user that the PLplot warning about too few items on the terminal list can be ignored 2009-12-29 slayoo * src/pro/Makefile.am, src/pro/Makefile.in: adding rstrpos.pro to the make-install list * src/pro/rstrpos.pro, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basegdl.hpp, src/dcompiler.cpp, src/dcompiler.hpp, src/dinterpreter.cpp, src/dnode.cpp, src/dnode.hpp, src/dpro.cpp, src/dpro.hpp, src/gdlc.g, src/gdlc.tree.g, src/gdlexception.cpp, src/gdlexception.hpp, src/initsysvar.cpp, src/initsysvar.hpp, src/strassenmatrix.hpp, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp: support for COMPILE_OPT OBSOLETE; initial import of RSTRPOS (obsolete) 2009-12-26 slayoo * src/pro/Makefile.in, src/pro/dicom/Makefile.in, Makefile.in, aclocal.m4, config.guess, config.sub, configure, configure.in, depcomp, install-sh, missing, mkinstalldirs, src/Makefile.in, src/antlr/Makefile.in: configuration files: disabling the automake maintainer mode by default - configuration files are not regenerated by default even if timestamps suggest this should be done (what happens often after a CVS update) 2009-12-23 slayoo * src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in, config.h.in, configure, configure.in, aclocal.m4, Makefile.in: after running autoupdate and autoreconf -i * ltmain.sh: after running libtoolize (trying to fix the "X--tag=CXX: command not found" problem) * src/Makefile.am, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/checks: adding poly_area.pro to the make-install list in the src/pro/Makefile.am 2009-12-22 m_schellens * src/strassenmatrix.hpp: improved tolerance for older OpenMP * src/pro/poly_area.pro, src/Makefile.am, src/basic_op.cpp: add file 2009-12-20 slayoo * src/file.cpp, src/gdl.cpp: GCC 4.3.4 compatibility fix (PATH_MAX undefined) * configure, configure.in: configure: handling both single-port (Macports default) and multi-port (Debian default) installations of wxWidgets 2009-12-16 slayoo * Makefile.in, aclocal.m4, config.h.in, configure, configure.in, src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in: re-enabling autodetection of OpenMP (needs autoconf >=2.63) 2009-12-12 m_schellens * config.h.in, configure, configure.in, gdl.kdevelop, src/strassenmatrix.hpp, Makefile.in, aclocal.m4, ltmain.sh, src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in: working configuration files 2009-12-12 slayoo * src/dinterpreter.cpp, src/dinterpreter.hpp, src/gdl.cpp, src/magick_cl.cpp: support for specifying batch files at command line, e.g. $gdl script1.pro script2.pro support for the '-e' command-line option - execute a single statement and exit QUERY_*: fix for the empty-argument case 2009-12-12 m_schellens * src/basic_op.cpp, src/strassenmatrix.hpp, gdl.kdevelop, src/Makefile.am, src/Makefile.in: strassen algorithm for matrix multiplication (deactivated) 2009-12-11 slayoo * src/pro/STATUS, src/pro/UrgentNeed.txt: update of src/pro/STATUS and src/pro/UrgentNeed.txt * src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp: CROSSP: initial import 2009-12-10 slayoo * src/pro/Makefile.in: after running autoreconf * src/pro/Makefile.am, src/pro/query_dicom.pro, src/magick_cl.cpp: QUERY_DICOM: initial import 2009-12-09 slayoo * Makefile.in, aclocal.m4, config.h.in, configure, ltmain.sh, src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in: after running autoreconf and libtoolize * src/pro/STATUS: (that's a comment for patchset 1026 commited a few minutes ago): - initial import of QUERY_BMP, QUERY_GIF, QUERY_IMAGE, QUERY_JPEG, QUERY_PICT, QUERY_PNG, QUERY_PPM and QUERY_TIFF (using Magick++'s ping functionality) - wxWidgets: - compatibility-fixes allowing compilation both with unicode- and non-unicode wxWidgets - adding some already referenced keywords to the keyword lists in libinit_jmg.cpp - configure script: - using a non-mangled function name in AC_CHECK_LIB (cross-compiler compatibility) - acquireing the wxWidgets library name from wx-config (basename+release, previously hardcoded) - checking if wx-config is callable before trying to link with wxWidgets - allowing indication of the wxWidgets installation prefix (--with-wxWidgets=DIR) * src/pro/Makefile.am, src/pro/Makefile.in, src/pro/checks, src/pro/dicom/Makefile.in, src/pro/query_bmp.pro, src/pro/query_gif.pro, src/pro/query_image.pro, src/pro/query_jpeg.pro, src/pro/query_pict.pro, src/pro/query_png.pro, src/pro/query_ppm.pro, src/pro/query_tiff.pro, configure.in, ltmain.sh, src/Makefile.in, src/antlr/Makefile.in, src/gdlwidget.cpp, src/libinit_cl.cpp, src/libinit_jmg.cpp, src/magick_cl.cpp, src/magick_cl.hpp, aclocal.m4, config.h.in, configure, Makefile.in: gdl 2009-12-06 slayoo * src/plotting.cpp: CONTOUR: reverting to previous (IDL-compatible) contour-level-choice mechanism * src/hdf_fun.cpp: HDF_SD_DIMGETID: correcting double error-message prefixes 2009-12-05 slayoo * src/pro/Makefile.am, src/pro/Makefile.in: fix for the last commit (in src/pro/Makefile.in) * src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/dicom/Makefile.in, config.h.in, configure, configure.in, ltmain.sh, Makefile.in, aclocal.m4: using OpenMP only if the compiler supports it (by means of the AC_OPENMP macro) 2009-11-28 m_schellens * src/gdlgstream.hpp: resolved const char** to/from char** compile error * Makefile.in, aclocal.m4, configure, src/Makefile.in, src/antlr/Makefile.in, src/devicez.hpp, src/gdlgstream.hpp, src/pro/Makefile.in, src/pro/dicom/Makefile.in: fixed z buffer error condition (switched back to previous version, no OpenMP support) 2009-11-27 m_schellens * src/accessdesc.hpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basic_op.cpp, gdl.kdevelop: fixed line number reporting for struct and array expressions 2009-11-27 slayoo * src/magick_cl.cpp, src/gdlgstream.hpp: - fixing random behaviour of GDLGStream::checkPlplotDriver() - cleanup of error mesaages in Magick-related routines (removing double prefixes) 2009-11-25 slayoo * src/devicex.hpp, src/graphics.cpp, src/graphics.hpp, src/libinit.cpp, src/plotting.cpp: - !DEVICE.N_COLORS in now dependant on the actual X-window setting - DEVICE: support for the GET_VISUAL_DEPTH keyword - plotting.cpp : making all variables pointing to SysVar::D() non-static in order to allow the code that uses them to track changes in !D caused for example by set_plot 2009-11-24 jomoga * src/basic_fun.cpp: Change [0] to [s] in (*stringExpr)[s].substr in stregex_fun * testsuite/test_poly2d.pro: Initial import 2009-11-23 slayoo * testsuite/example.grib, testsuite/test_grib.pro: adding the GRIB test files * Makefile.in, README_GRIB, aclocal.m4, config.h.in, configure, configure.in, src/Makefile.am, src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/grib.cpp, src/grib.hpp, src/libinit.cpp, src/pro/Makefile.in, src/pro/dicom/Makefile.in: - update in locale_get() reflecting the change in IDL 7.1.1 (now it's returning locale of the parent process, tracker item: 2880186) - initial import of GRIB-1/2 file format support using the ECMWF GRIB API - configure: checking if netcdfcpp.hpp is usable (conflicting hdf4/netcdf installation issue) - configure: moving definition of defaults to the header of configure.in - handling "cannot connect to X-server" (previously plPlot exited GDL, tracker item: 2877007) 2009-11-22 m_schellens * Makefile.in, aclocal.m4, configure, src/Makefile.in, src/antlr/Makefile.in, src/gdlgstream.hpp, src/magick_cl.cpp, src/pro/Makefile.in, src/pro/dicom/Makefile.in: corrected memory allocation * configure, configure.in, gdl.kdevelop, src/accessdesc.hpp, src/basic_pro.cpp, src/basic_pro.hpp, src/initsysvar.cpp, src/initsysvar.hpp, src/io.hpp, src/libinit.cpp, src/objects.cpp, src/objects.hpp: Add CPU procedure 2009-11-21 m_schellens * src/datatypes.cpp, src/basic_fun.cpp, src/basic_pro.cpp, src/devicex.hpp, src/devicez.hpp, src/fftw.cpp, src/magick_cl.cpp, src/typedefs.hpp: enhanced thread pool support using OpenMP 2009-11-20 m_schellens * src/GDLInterpreter.cpp, src/basegdl.hpp, src/convert2.cpp, src/datatypes.cpp, src/gdlc.i.g, src/math_fun.cpp, src/real2int.hpp: enhanced thread pool support using OpenMP 2009-11-18 m_schellens * src/GDLInterpreter.cpp, src/accessdesc.hpp, src/basic_op.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/gdlc.i.g, src/gzstream.hpp, src/initsysvar.cpp, src/initsysvar.hpp, src/io.cpp, src/objects.cpp, src/objects.hpp, gdl.kdevelop: added initial thread pool support using OpenMP 2009-11-17 slayoo * config.h.in, configure, configure.in: removing a netCDF header check from the last commit (does not work with custom INCLUDES path) 2009-11-16 slayoo * src/antlr/Makefile.in, src/pro/Makefile.in, src/pro/dicom/Makefile.in, Makefile.in, README, aclocal.m4, config.h.in, configure, configure.in, src/Makefile.in, src/devicesvg.hpp, src/gdlgstream.hpp, src/gdlsvgstream.hpp: configure: - checking if netCDF installation is usable (HDF4 installation conflict) - checking if HDF4 was compiled with --disable-netcdf (+ README update) plplot: - throwing a GDL exception if plplot lacks requested driver - fixing SVG plotting after previous X-win plots (clearing driver options) - SVG: using svgcairo instead of svg driver if present 2009-11-13 m_schellens * src/basic_pro.cpp, src/basic_pro_jmg.cpp, src/dinterpreter.cpp, src/io.cpp, src/io.hpp: fixed startup file bug 2009-11-11 slayoo * src/basic_fun.cpp: STREGEX: preventing bogus call to basic_string::substr(-1,...) (tracker item no. 2895655) * src/basic_pro_jmg.cpp: POINT_LUN: assuring the 2nd par is a global par 2009-11-09 m_schellens * src/GDLInterpreter.cpp, src/basic_fun.cpp, src/gdlc.i.g, src/gdlexception.hpp: fixed error info for errors during parameter initialization 2009-11-08 m_schellens * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/default_io.cpp, src/envt.cpp, src/extrat.cpp, src/gsl_fun.cpp: correct alignment for all types in PRINT and REVERSE(/OVERWRITE) 2009-11-08 slayoo * src/ncdf_var_cl.cpp: NCDF_VARINQ: fixing failed-assertion condition (dimension(0)) with scalar variables 2009-11-07 slayoo * src/basic_pro.cpp, src/envt.cpp, src/gdlexception.cpp, src/gdlexception.hpp: some more error-message decoration cosmetics 2009-11-07 m_schellens * src/GDLInterpreter.hpp, src/GDLParser.cpp, src/GDLTreeParser.cpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/GDLInterpreter.cpp: correct line numbers of error messages in interupted subroutines * src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/dinterpreter.cpp, src/dpro.cpp, src/envt.cpp, src/gdlc.i.g, src/gdlc.tree.g: Removed even more inconsistencies in deocration of error messages 2009-11-06 m_schellens * src/basic_fun.cpp, src/dpro.cpp, src/envt.hpp, src/gdlexception.cpp, src/gdlexception.hpp: Removed more inconsistencies in deocration of error messages * src/assocdata.cpp, src/basic_pro.cpp, src/envt.cpp, src/plotting.cpp: Removed inconsistencies in deocration of error messages 2009-11-05 m_schellens * src/dinterpreter.cpp, src/dinterpreter.hpp, src/envt.hpp, src/gdl.cpp, src/gdlexception.cpp, src/gdlexception.hpp, src/objects.cpp, src/objects.hpp: Add calling function's name to text of GDLException by default 2009-11-05 slayoo * src/gdl.cpp: making the -quiet option compatible with -arg and -args 2009-11-05 m_schellens * src/convert2.cpp, src/dinterpreter.cpp, src/envt.cpp, src/envt.hpp, src/gsl_fun.cpp: utilized SetPar() in invert_fun 2009-11-04 slayoo * src/devicex.hpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/libinit.cpp, src/plotting.cpp: WSHOW: initial import (ICONIC kwrd not implemented yet) * src/datatypes.cpp, src/gsl_fun.cpp, src/math_fun_jmg.cpp, src/ncdf_att_cl.cpp, src/ncdf_var_cl.cpp: INVERT: fixing a segfault condition with non-global parameter; removing some duplicate prefixes in error messages 2009-11-03 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basegdl.cpp, src/basegdl.hpp, src/convert2.cpp, src/dinterpreter.cpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/math_fun.cpp, src/prognode.cpp: added identifier info in several error messages 2009-11-02 m_schellens * src/basic_fun.cpp: Fixed CREATE_STRUCT() (no parameters) 2009-11-01 m_schellens * src/basic_fun_jmg.cpp, src/prognode.cpp, README, ChangeLog: ROUTINE_NAMES * src/datatypes.cpp: More verbose error messages * src/basic_fun_jmg.cpp, src/gdlc.i.g, src/prognode.cpp: Fixed ROUTINE_NAMES(/FETCH) 2009-11-01 slayoo * src/plotting.cpp: CURSOR: support for lat/lon query on maps 2009-11-01 m_schellens * src/basic_fun_jmg.cpp: Fixed ROUTINE_NAMES(/FETCH) * src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/datatypes.cpp, src/pro/Makefile.in, src/pro/dicom/Makefile.in, Makefile.in, aclocal.m4, configure, gdl.kdevelop: Fixed STRSPLIT() 2009-11-01 slayoo * src/gdl.cpp: -quiet command line option 2009-11-01 m_schellens * src/datatypes.cpp: More verbose error messages * src/basic_fun_jmg.cpp, src/gdlc.i.g, src/prognode.cpp: Fixed ROUTINE_NAMES(/FETCH) 2009-11-01 slayoo * src/plotting.cpp: CURSOR: support for lat/lon query on maps 2009-11-01 m_schellens * src/basic_fun_jmg.cpp: Fixed ROUTINE_NAMES(/FETCH) * src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/datatypes.cpp, src/pro/Makefile.in, src/pro/dicom/Makefile.in, Makefile.in, aclocal.m4, configure, gdl.kdevelop: Fixed STRSPLIT() 2009-11-01 slayoo * src/gdl.cpp: -quiet command line option 2009-10-31 slayoo * src/pro/checks: src/pro/checks: making it work under all locales * src/Makefile.in, src/antlr/Makefile.in, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/checks, src/pro/dicom/Makefile.am, src/pro/dicom/Makefile.in, Makefile.in, aclocal.m4, configure, configure.in: fixing and re-enabling make-install rules for .pro files (+ one make-check rule for checking if all .pro files from src/pro will be installed) 2009-10-31 m_schellens * src/envt.hpp, src/basic_pro.cpp, src/envt.cpp: corrected HELP output for expressions 2009-10-31 slayoo * src/gsl_fun.cpp, src/ncdf_var_cl.cpp, testsuite/nc_test.pro: LA_TRIRED: checking if the first argument is an array (tracker item no: 2889764) NCDF_VARGET: fixing a segfault condition (tracker item no: 2878720) nc_test.pro: commenting out catch-dependant checks 2009-10-30 slayoo * src/gdl.cpp, testsuite/test_plotting_ranges.pro: MPI: warning the user if MPI changes the working directory of GDL * src/gsl_fun.cpp, src/plotting.cpp, testsuite/test_histo.pro, testsuite/test_plotting_ranges.pro, src/envt.hpp: PLOT/OPLOT: not accepting scalar arguments FFT: sanity check for the rank of argument CONTOUR/SURFACE: sanity checks for the rank and type of arguments HISTOGRAM: correcting binsize definition when max and nbins set, better INPUT-kw-related error message test_histo.pro: testing binsize selection test_plotting_ranges: initial import (testing axis range selection) envt.hpp: adding GetParNumericArrayDefined() 2009-10-27 m_schellens * src/GDLInterpreter.hpp, src/GDLInterpreterOptimized.cpp, src/GDLInterpreterOptimized.inc, src/Makefile.am, src/Makefile.in, src/gdlc.i.g: removed obsolete files 2009-10-26 m_schellens * src/GDLTreeParser.cpp, src/pro/Makefile.in: deactivate GDL_DEBUG define setting (gdlc.tree.g) 2009-10-26 alaingdl * src/plotting.cpp: Better automatic range in PLOT. NOT propagated in CONTOUR and SURFACE (sorry). LOG case still to do. 2009-10-25 m_schellens * src/envt.cpp, src/pro/Makefile.in, testsuite/test_suite.pro: more verbose info on expression parameters 2009-10-25 alaingdl * testsuite/test_get_screen_size.pro, src/plotting.cpp: in GET_SCREEN_SIZE, param DISPLAY now working 2009-10-25 slayoo * src/plotting.cpp, testsuite/test_plotting_misc.pro: CONTOUR: partial support for contouring on maps (+ some tests in test_plotting_misc.pro) 2009-10-24 medericboquien * src/antlr/CharScanner.hpp: Make GDL compile with gcc 4.4. 2009-10-23 m_schellens * Makefile.in, aclocal.m4, configure, gdl.kdevelop, src/GDLInterpreter.cpp, src/Makefile.in, src/antlr/Makefile.in, src/dinterpreter.cpp, src/gdlc.i.g, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/dicom/Makefile.in: Fixed wrong handling of CONTINUE under certain conditions in nested loops 2009-10-23 slayoo * testsuite/test_nestedloop.pro: adding test_nestedloop.pro to the testsuite 2009-10-21 slayoo * src/pro/dicom/Makefile.am, src/pro/dicom/Makefile.in, src/basic_fun.cpp, src/pro/Makefile.am, src/pro/Makefile.in: fixing EXTRA_DIST value in src/pro/Makefile.am; GETENV: error message when called with /ENV and a positional parameter 2009-10-19 slayoo * Makefile.am, Makefile.in, aclocal.m4, config.h.in, configure, configure.in, src/Makefile.am, src/Makefile.in, src/antlr/Makefile.in, src/gdl.cpp, src/pro/Makefile.am, src/pro/Makefile.in, src/pro/dicom/Makefile.am, src/pro/dicom/Makefile.in: installing library .pro files and basic docs during make install; setting default library-routine search path if GDL_PATH/IDL_PATH not defined; welcome message changes 2009-10-18 alaingdl * NEWS: upgrading NEWS file (creating 0.9rc4 entry) * src/libinit.cpp, src/plotting.cpp, src/plotting.hpp: initial import of GET_SCREEN_SIZE(); in CURSOR, verification if we are in X mode * testsuite/test_get_screen_size.pro: initial import of TEST_GET_SCREEN_SIZE, function to be imported in CVS * testsuite/test_voigt.pro: detail in TEST_VOIGT, restoring !p.multi ... 2009-10-18 slayoo * src/gsl_fun.cpp, src/pro/read_ascii.pro: READ_ASCII: printing error message when DATA_START exceeds file length; IMSL_BINOMIALCOEF: sanity check for number of arguments added 2009-10-18 m_schellens * src/basic_pro.cpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructdesc.cpp, src/dstructdesc.hpp, src/dstructgdl.hpp, src/mpi.cpp, src/specializations.hpp, src/typetraits.hpp: Fixed BYTEORDER for STRUCT * src/GDLInterpreter.hpp, src/gdlc.i.g, src/print.cpp, src/prognode.cpp: sync 2009-10-17 slayoo * src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit.cpp, NEWS: IMSL_BINOMIALCOEF: initial import 2009-10-17 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdl.cpp, src/gdlc.i.g, src/pro/array_indices.pro: Corrected beahvior of call_fun and call_lfun for RC_ABORT return code. Old behavior lead to endless loop at startup in some conditions. 2009-10-16 m_schellens * src/basic_fun.cpp: Fixed STRMID for missing 3rd parameter * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g, src/prognode.hpp: Fixed line tracking for error reporting 2009-10-15 m_schellens * src/initsysvar.cpp: imporved \!VERSION * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/basic_fun_cl.cpp, src/datatypes.cpp, src/dinterpreter.cpp, src/dpro.cpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/gdlexception.cpp, src/print_tree.cpp, src/specializations.hpp: improved line number tracking for error reporting 2009-10-14 slayoo * src/datatypes.cpp: [F,D,L,...]INDGEN: making the values of the resulting array more precise for large arrays (demo: print, (findgen(40000000))[40000000-1]) 2009-10-14 m_schellens * src/basic_fun_jmg.cpp, src/dinterpreter.cpp, src/envt.cpp: Proper ROUTINE_NAMES(/STORE) 2009-10-13 m_schellens * src/deviceps.hpp, src/pro/loadct.pro: Set \!D.TABLE_SIZE from 0 to 256 2009-10-13 slayoo * testsuite/test_multiroots.pro: update of test_multiroots.pro after the two known bugs were fixed * src/basic_fun.cpp, src/basic_pro_jmg.cpp: GCC 3.4.3 compatibility fixes (WAIT, GET_LOGIN_INFO) 2009-10-12 m_schellens * src/basic_fun.cpp, src/str.cpp: Fixed STRMID for negative values of 3rd parameter * src/print.cpp: Corrected output of trailing newline after empty string output for PRINT (and PRINTF) * src/basic_fun_jmg.cpp: Corrected name lookup in ROUTINE_NAMES * src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/FMTParser.cpp, src/gsl_fun.cpp: fixed guarding bug within newton_broyden function set 2009-10-11 alaingdl * src/pro/restore.pro: Revert my change in RESTORE 2009-10-10 m_schellens * src/print.cpp: changed output of trailing newline after empty string output for PRINT (and PRINTF) * src/file.cpp: strip of trailing '/' in FILE_TEST * src/basic_fun.cpp: STRPOS does no longer ignore undefined 3rd parameter * src/basic_fun.cpp, src/basic_pro_jmg.cpp, src/dinterpreter.cpp: Corrected wrong error message due to pre-evaluation of constant functions 2009-10-09 m_schellens * src/basic_pro_jmg.cpp: made WAIT control-c interuptible 2009-10-09 slayoo * src/pro/file_basename.pro: FILE_BASENAME: better handling of empty and space-only strings 2009-10-08 m_schellens * src/basic_fun_jmg.cpp: fixed ARG_NAME keyword in ROUTINE_NAMES for values larger than current level * src/accessdesc.hpp: fixed STRUCT access of non struct struct member (e. g. a={b:0}&print,a.b.c ) * src/default_io.cpp: read ASCII file not ending with newline character 2009-10-08 alaingdl * src/pro/restore.pro: correction RESTORE to be OK with last CMSV lib, delivered 09/05/05 * src/basic_fun.cpp, src/libinit.cpp: re-enter the Length Keyword in N_TAGS; we don't know how to distinguish with /data_length 2009-10-07 slayoo * src/plotting.cpp: ![X,Y].RANGE support in plotting routines (patch from Joanna/cokhavim) 2009-10-07 alaingdl * src/pro/dist.pro: DIST, like many others, should run when call like dist([2,2]) * src/libinit_jmg.cpp: add 2 undocument params in CHECK_MATH() and also keep memory of value, but INT error still not managed * testsuite/test_check_math.pro: test suite for CHECK_MATH() * quick_start_GDL.sh: re-import this script to help beginners to quickly starts GDL with paths (now this script complains if not run properly) * quick_start_GDL.sh: temporary removing of this file to change it into 755 mode * src/math_fun_jmg.cpp: add 2 undocument params in CHECK_MATH() and also keep memory of value, but INT error still not managed 2009-10-05 m_schellens * Makefile.in, aclocal.m4, configure, configure.in, gdl.kdevelop, src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTParser.cpp, src/FMTParser.hpp, src/FMTTokenTypes.hpp, src/FMTTokenTypes.txt, src/Makefile.in, src/antlr/Makefile.in, src/format.g, src/gdlwidget.hpp, src/ofmt.cpp: Allow neg. width for A format code 2009-10-05 slayoo * src/plotting.cpp: PLOT: adjusting axes when charsize changed (patch from Joanna/cokhavim, tracker item no 2859179) * src/libinit.cpp, src/plotting.cpp: CONTOUR: support for the /OVERPLOT keyword (patch from Joanna/cokhavim) 2009-10-02 slayoo * src/basic_fun.cpp, src/dpro.hpp, src/libinit.cpp, src/pro/file_basename.pro: FILE_BASENAME: support for array argument; ROUTINE_INFO: support for PARAMETERS keyword 2009-10-01 alaingdl * quick_start_GDL.sh: A quick start script for beginners, with easy switch for Valgrind ... * testsuite/test_valgrind.pro: quick check of problems in Contour/Surface with Valgrind: to be extended 2009-09-29 alaingdl * src/plotting.cpp: better freeing/delete in Contour/Surface, thanks to Valgrind 2009-09-26 slayoo * configure, testsuite/test_multiroots.pro: fixing common block name conflict (with RK4) in test_mutiroots.pro; running aclocal/autoconf/automake after version number change 2009-09-26 alaingdl * src/basic_fun.cpp: removing comments/debug info in MEDIAN() * testsuite/test_dims_of_arrays.pro, testsuite/test_outofmem.pro: Exemples of bad inputs when creating arrays ... 2009-09-25 alaingdl * configure.in, src/basic_fun.cpp: Better check of Array dims 2009-09-24 slayoo * ChangeLog, NEWS: updating NEWS and Changelog GDL 0.9rc3: 2009-09-11 m_schellens * testsuite/test_suite.pro, src/GDLInterpreter.cpp, src/envt.hpp, src/gdlc.i.g: Corrected GOTO out of loops within outer blocks * src/datatypes.cpp: corrected array to tag of struct array assignment 2009-09-10 slayoo * src/gsl_fun.cpp: IMSL_CONSTANT: gcc 3.3 compatibility fix * src/basic_fun.cpp, src/basic_fun.hpp, src/file.cpp, src/libinit.cpp: FILE_SEARCH: support for FULLY_QUALIFY_PATH kw.; GET_DRIVE_LIST: initial import; DEVICE: ignoring RETAIN kw. 2009-09-09 slayoo * testsuite/test_constants.pro: IMSL_CONSTANT: new test routine (test_constants.pro) * src/Makefile.in, src/antlr/Makefile.in, src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit.cpp, config.h.in, configure, configure.in, Makefile.in, README, aclocal.m4: - configure/HDF4/HDF5: linking with SZIP if needed (thanks to David Nicholls; previously pointed out in the HDF Group report - http://www.hdfgroup.org/pubs/papers/2009-06_oss_eval.pdf) - HISTOGRAM: using system nexttoward() if available - IMSL_CONSTANT: initial import 2009-09-01 slayoo * src/read.cpp: READF: bugfix - allowing reads from standard input (lun 0) 2009-08-31 slayoo * src/pro/calendar.pro, testsuite/test_histo.pro, src/gsl_fun.cpp: HISTOGRAM: fixing inclusive ranges definition (tracker item no 2846561) + test_histo_basic in test_histo.pro; CALENDAR: always using the C locale (mimicking IDL and avoidin non-printable characters) 2009-08-28 alaingdl * src/pro/spl_init.pro, src/pro/spl_interp.pro: Removing files which have been in fact duplicated then renamed ... * src/pro/spl_init_old.pro, src/pro/spl_interp_old.pro: Renaming the version of SPL_* in GDL syntax to avoid conflits * src/math_fun_ac.cpp, src/math_fun_ac.hpp: Initial import of C++ version of SPL_INIT and SPL_INTERP (y0= and yn_1= not ready) Experimental /help mechanism for Bessel family and SPL_* * src/envt.hpp, src/libinit_ac.cpp: adding e->HELP(*mess, nb_mines) for easy help 2009-08-27 slayoo * src/basic_pro.hpp, src/libinit.cpp, src/print.cpp: PM: initial import 2009-08-26 slayoo * src/base64.hpp, src/basic_fun.cpp, src/basic_fun.hpp, src/gsl_fun.cpp, src/libinit.cpp, src/pro/STATUS, src/pro/imsl_zerosys.pro, testsuite/test_base64.pro: initial import of IDL_BASE64 (+ test routine) and IMSL_ZEROSYS (via NEWTON(..., /HYBRID)) * src/pro/calendar.pro: CALENDAR: initial import 2009-08-23 m_schellens * src/plotting.cpp: applied patches for CONTOUR and XYOUTS from Joanna (cokhavim) * src/antlr/Makefile.in, src/basic_fun.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/Makefile.in, configure, gdl.kdevelop, Makefile.in, README, aclocal.m4: GET_KBRD patch from Fernando Silveira 2009-08-18 slayoo * src/dinterpreter.cpp: fixing two segfault conditions caused by getenv() returning NULL (SHELL and HOME env. variables) 2009-08-15 slayoo * src/basic_fun.cpp, src/basic_fun.hpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/libinit.cpp, src/libinit_jmg.cpp: GET_LOGIN_INFO(): initial import MAKE_ARRAY(): /PTR & /OBJ keywords, /INDEX keyword support for strings HELP: reporting structure data lengths 2009-08-13 slayoo * src/basic_fun.cpp, src/basic_fun.hpp, src/gdl.cpp, src/libinit.cpp: COMMAND_LINE_ARGS(): initial import 2009-08-12 slayoo * src/basic_pro.cpp: SPAWN: fixing segfault when SHELL env. variable not set 2009-08-11 slayoo * src/pro/moment.pro: MOMENT: MAXMOMENT kw support + update of the documentation header 2009-08-09 slayoo * src/plotting.cpp: header-file fix in plotting.cpp (bug introduced in rev. 1.86) * src/initsysvar.cpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp, testsuite/test_angles.pro: - making !DTOR & !RADEG values more precise - ATAN(): - /PHASE keyword support - array-scalar argument combination support - two-complex-arguments case support - precision fixes (atan(float, float) -> float(atan(double, double))) - LL_ARC_DISTANCE(): initial import - new test-routine for angle-related stuff: ATAN(), LL_ARC_DISTANCE(), !PI, !DPI, !DTOR, !RADEG 2009-08-07 slayoo * config.h.in, configure, configure.in, src/basic_fun.cpp, src/basic_fun.hpp, src/libinit.cpp, testsuite/test_url.pro: PARSE_URL() and LOCALE_GET(): initial import + test routine (test_url.pro) 2009-08-01 slayoo * src/basegdl.hpp, src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit.cpp, src/plotting.cpp, testsuite/test_multiroots.pro: NEWTON()/BROYDEN() using GSL multiroots: initial import + test routine 2009-07-30 alaingdl * TODO, src/math_fun_ac.cpp, testsuite/test_besel.pro, testsuite/test_tv.pro: BESEL family functions: non integer order, X neg, Complex, and better management of arrays dimensions 2009-07-29 alaingdl * testsuite/test_besel.pro: do right calls to Bessel K and Y ! 2009-07-28 slayoo * src/pro/read_xwd.pro: READ_XWD: fixing a conditional statement typo (thaen -> then) 2009-07-25 alaingdl * src/math_fun_gm.cpp, src/math_fun_ng.cpp: Better management of the dimensions of output arrays for several mathematical functions, including BETA and VOIGT. Besel family should be corrected too very soon. Please try that with "test_MathFunctionsDim.pro". Behavior is not exactly the same than IDL (here we do the calculus when [1][n]) * testsuite/test_MathFunctionsDim.pro, testsuite/test_minmax.pro: new test for testing Math Functions Dimensions ... 2009-07-23 slayoo * AUTHORS: adding myself to the AUTHORS file 2009-07-22 slayoo * src/deviceps.hpp, src/devicesvg.hpp, src/devicewin.hpp, src/devicex.hpp, src/devicez.hpp, src/gdlsvgstream.cpp, src/gdlsvgstream.hpp, src/basic_pro.cpp: EXIT: fixing segfault if HOME env. var undefined; SVG: fixing end-of-page bahaviour 2009-07-18 slayoo * src/libinit.cpp, src/plotting.cpp, src/gdlsvgstream.hpp: plotting: partial labelling support, treating OVERPLOT as a warnKeyword, error-message cosmetics; SVG: using svg terminal instead of svgcairo 2009-07-17 alaingdl * src/basic_fun.cpp, src/libinit.cpp: bug in N_TAGS(): rename keyword /LENGTH to /DATA_LENGTH * testsuite/test_ntags.pro: adding a new file (test_ntags.pro) in testsuite/ for testing N_TAGS() (written by T. Mermet) 2009-07-16 slayoo * src/ncdf_var_cl.cpp: NCDF_VARGET: 64-bit fix (SizeT->Dlong for transposed_dim_length[]) + some code cleanup 2009-07-15 slayoo * src/ncdf_var_cl.cpp: NCDF_VARPUT: fixing random behaviour due to type mismatch (size_t -> int) of the 5th argument to nc_inq_var() * src/ncdf_att_cl.cpp: NCDF_ATTPUT: fixing invalid keyword numbering 2009-07-03 slayoo * PYTHON.txt, src/datatypes.hpp, src/pro/STATUS, src/pro/UrgentNeed.txt, HACKING: misc. minor updates in readme/doc files, etc 2009-06-30 alaingdl * testsuite/test_minmax.pro: just changing 755 to 644 atributes for this file * src/pro/strsplit.pro: STRSPLIT: will allow 'str' and ['str'] 1D strings 2009-06-26 alaingdl * testsuite/test_voigt.pro: TEST_VOIGT: better messages * src/pro/path_sep.pro: PATH_SEP: now return good type STRING = '/', before STRING = Array[1] 2009-06-21 slayoo * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/libinit.cpp, src/specializations.hpp, testsuite/test_minmax.pro: MIN/MAX: DIMENSION keyword support; bugfixes in REVERSE and MEDIAN; dimension-slicing test routine (in test_minmax) 2009-06-19 slayoo * src/ncdf_att_cl.cpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp: fixes/code-cleanup in NCDF routines (VARPUT, DIMINQ, ATTGET) 2009-06-14 slayoo * src/devicesvg.hpp, src/gdlsvgstream.cpp, src/gdlsvgstream.hpp: adding SVG-terminal files (missing in previous commit) * src/antlr/Makefile.in, src/libinit.cpp, src/ncdf_var_cl.cpp, src/plotting.cpp, src/typedefs.hpp, INSTALL, Makefile.in, configure, configure.in, src/Makefile.am, src/Makefile.in, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun.hpp, src/basic_fun_cl.cpp, src/datatypes.cpp, src/datatypes.hpp, src/devicez.hpp, src/graphics.cpp, src/initsysvar.cpp, src/io.cpp: - REVERSE: initial import - SYSTIME: correction for /JULIAN flag; conflicting keywords message - SVG terminal (via set_plot, 'svg') - switching off HIGHWATER memory accounting using mallinfo() (too slow) - configure: LDFLAGS from Magick++Config; test if adding X library path helps - ROTATE: better error message - NCDF_VARPUT: fixing uninitialized variable bug 2009-06-09 slayoo * configure, configure.in: configure: correcting (again) the check for presence of numarray * configure, configure.in: configure: correcting the check for presence of numarray * src/basic_pro.hpp, src/io.cpp, src/io.hpp, src/libinit.cpp, src/basic_pro.cpp: FLUSH: initial import (patch from Orion Poplawski) * config.guess, config.sub, configure, configure.in, ltmain.sh: after running libtoolize (tracker item no 2770126) 2009-06-07 slayoo * configure, configure.in: configure: detecting numarray, printing summary information * src/default_io.cpp: 64-bit OSX fix (xdr_long()/xdr_u_long() argument types) - patch from Martin Otte * configure.in, configure: support for linux ppc64 (patch from Orion Poplawski) * src/basic_fun.cpp: MEDIAN: memory leak fix + change DIM into DIMENSION (tracker bug id 1805751) 2009-06-06 slayoo * src/basic_fun_jmg.cpp: fixing datatype (sign) conflict in IDL_SIZE structure assignment (SF tracker bug id 2801342) 2009-05-28 slayoo * src/dinterpreter.cpp, src/gdl.cpp, src/pro/STATUS, MAP_INSTALL: setting history-file lenght in startup file using !EDIT_INPUT + updates in MAP_INSTALL and pro/STATUS 2009-05-26 slayoo * src/antlr/Makefile.in, Makefile.in, configure, configure.in, src/Makefile.in: using nc-config (if present) to determine netcdf LIBS/INCLUDES 2009-05-22 slayoo * src/gdlgstream.cpp, src/gdlgstream.hpp, src/pro/showfont.pro: embedded formatting commands + initial import of SHOWFONT 2009-05-20 slayoo * src/dstructgdl.hpp: removal of one static_cast() which was causing gcc warnings 2009-05-17 slayoo * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: CALDAT: initial import 2009-05-13 slayoo * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun.hpp, src/basic_pro.cpp, src/libinit.cpp, src/objects.cpp, config.h.in, configure, configure.in: MEMORY(): initial import + HELP,/MEMORY 2009-05-09 jomoga * src/export.hpp: Zero out arrays of necessary 2009-05-02 slayoo * src/file.cpp, src/file.hpp, src/libinit.cpp, src/objects.cpp: FILE_INFO: initial import 2009-04-30 slayoo * configure, configure.in: better ncurses/curses check, preventing linking both libraries * Makefile.in, aclocal.m4, config.h.in, configure, configure.in, src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/datatypes.hpp, src/file.cpp, src/fmtnode.cpp, src/includefirst.hpp: OpenSolaris compatibility fixes 2009-04-28 slayoo * src/file.cpp, src/file.hpp, src/libinit.cpp: FILE_SAME: initial import * src/file.cpp, src/libinit.cpp: FILE_TEST: handling /NOEXPAND_PATH keyword 2009-04-17 slayoo * src/basic_fun.cpp: STRING: segfault fix for the previous revision * src/basic_fun.cpp: STRING: handling VMS compatibility syntax; demo: help,string(1,"(G)") 2009-04-10 slayoo * src/pro/restore.pro: RESTORE: fixing a typo in variable (filename) name 2009-04-06 slayoo * src/print.cpp: PRINT/PRINTF: handling VMS compatibility syntax; demo: print, "$(F)", 1 2009-03-31 jomoga * src/fftw.cpp: Fix /OVERWRITE with non-global parm bug in FFT 2009-03-24 slayoo * src/basic_pro.cpp: SPAWN: undoing bitwise shit in EXIT_STATUS value; demo: spawn, "exit -1", e=i & help, i * src/dinterpreter.cpp: preventing compiler warning due to ignored return value of a call to system() * src/basic_pro.cpp: SPAWN: setting EXIT_STATUS parameter when nParam==0; demo: spawn, exit=i & help, i 2009-03-23 m_schellens * gdl.kdevelop, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/devicex.hpp, src/dimension.hpp, src/envt.cpp, src/envt.hpp, src/gsl_fun.cpp, src/magick_cl.cpp, src/math_fun.cpp, src/math_fun_jmg.cpp, src/plotting.cpp: *** empty log message *** 2009-03-23 slayoo * src/gsl_fun.cpp: HISTOGRAM: setting OMIN/OMAX type according to the type of input data (tracker item no. 2699831) 2009-03-22 slayoo * src/typedefs.hpp, testsuite/test_outofmem.pro: converting bad_alloc exceptions when allocation arrays into GDLExceptions + test_outofmem.pro * src/basic_pro.cpp: OPENW: allowing /APPEND flag for non-existant files (tracker item no 2103871) 2009-03-20 slayoo * testsuite/test_plotting_misc.pro: test routine for various plotting issues 2009-03-19 slayoo * src/plotting.cpp: cosmetic changes to error messages 2009-03-18 slayoo * src/plotting.cpp: recovering changes from rev 1.73 lost in rev 1.76 (Joel: Add support for NORMAL/TO_DEVICE (xy->ll) in CONVERT_COORD) * src/plotting.cpp: XYOUTS: correction for DATA coordinates, demo: !P.MULTI=[0,2,1]&plot,findgen(10)&xyouts,.5,.5,a * src/plotting.cpp: PLOTS: correction for DATA coordinates, demo: !P.MULTI=[0,2,1]&plot,findgen(10)&plots,[0,1],[0,2] * src/gdlgstream.cpp: better default font size for terminals other than X (notably PS) * src/plotting.cpp: CONTOUR: avoiding plplot error messages when filling (shade_max must exceed shade_min) 2009-03-17 m_schellens * src/envt.hpp: gcc 4.4 compatibility (patch from opoplawski) * src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/basic_fun.cpp, src/gdlc.g: allow tag names with leading '\!' 2009-03-17 slayoo * src/ncdf_dim_cl.cpp: NCDF_DIMINQ: accepting long integers as file and dimension ids 2009-03-16 slayoo * src/pro/read_ascii.pro: handling both whitespace and tab as delimiter by default; using FILE_LINES instead of spawning wc * src/basic_fun.cpp: CREATE_STRUCT: accepting excl. mark as a first char of a tag name (tracker item no. 2688389) * src/hdf5_fun.hpp: HDF5 v1.8 compatibility fix (tracker item no. 2680132, help forum thread no. 2988711) 2009-03-15 jomoga * src/objects.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp, src/widget.hpp: Added widget functionality 2009-03-12 jomoga * src/fftw.cpp: Fix auto_ptr bug wite DOUBLE 2009-03-11 slayoo * src/libinit_jmg.cpp: MAKE_ARRAY: keyword name changed from INT to INTEGER * src/gsl_fun.cpp: binsize = (max - min) / (nbins - 1) when NBINS specified with neither MAX nor BINSIZE 2009-03-06 slayoo * src/gsl_fun.cpp: LOCATION keyword set correctly when HISTOGRAM called with NBINS and without BINSIZE or MAX, demo: print, histogram([1.,2.], n=3, l=l) & print, l 2009-03-06 alaingdl * src/devicex.hpp: in TV, managing [1,n,m], [n,1,m] and [n,m,1] cases when TRUE=0 2009-03-05 alaingdl * testsuite/test_tv.pro, INSTALL: testing all permutations for TV 2009-03-03 m_schellens * Makefile.in, aclocal.m4, configure, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/Makefile.am, src/Makefile.in, src/antlr/Makefile.in, src/datalistt.hpp, src/dinterpreter.cpp, src/dpro.cpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp: imroved DataListT an empty procedure call by extimated 40% 2009-02-26 m_schellens * gdl.kdevses: removed gdl.kdevses (storing actual kdevelop session details) from repository * src/GDLTreeParser.hpp, src/datatypes.cpp, src/gdlc.tree.g: detect change of type of FOR index variable 2009-02-23 slayoo * src/Makefile.in, src/antlr/Makefile.in, Makefile.in, aclocal.m4, configure: after running aclocal, automake, autoconf * configure, configure.in: determining ImageMagick flags using Magick++-config (tracker entry no 1963366) 2009-02-21 jomoga * src/math_fun_jmg.cpp, src/math_utl.cpp, src/math_utl.hpp, src/plotting.cpp, MAP_INSTALL, config.h.in, configure, configure.in: Add support for new LIBPROJ4 2009-02-18 slayoo * src/plotting.cpp: fixing segfault when contouring NaNs, e.g.: contour, replicate(!VALUES.F_NAN,3,3) 2009-02-10 slayoo * src/pro/file_lines.pro: no longer calling awk to parse wc output (tracker entry no 1980041) 2009-02-10 alaingdl * TODO, src/pro/file_lines.pro: upgrade of ToDo list; bug in FILE_LINES when last line does not have a LF 2009-02-08 m_schellens * gdl.kdevelop, PYTHON.txt: GDL as a python module tested * gdl.kdevses, src/Makefile.am, src/Makefile.in: made python modulw work (not tested) 2009-02-07 slayoo * src/ncdf_var_cl.cpp: reading text data in NCDF_VARGET/NCDF_VARGET1 (tracker bug no 2109502) 2009-02-04 alaingdl * src/hdf_fun.cpp, src/hdf_pro.cpp: data type change (DLong -> int32) in hdf_* (thanks to Sylvester A.) 2009-01-27 alaingdl * src/str.cpp: bug correction in CD for OSX, thanks to Sylvester A. 2009-01-26 m_schellens * src/GDLTreeParser.cpp, src/basic_fun_jmg.cpp, src/dcompiler.hpp, src/gdlc.tree.g: allow common blocks outside subroutines 2009-01-25 m_schellens * ChangeLog, NEWS, configure, configure.in, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/basic_fun_jmg.cpp, src/dcompiler.cpp, src/dcompiler.hpp, src/gdlc.g, src/gdlc.tree.g, src/prognode.cpp, src/prognode.hpp: allow common blocks outside subroutines GDL 0.9rc2: 2009-01-20 m_schellens * src/prognodeexpr.cpp: Copy sibling nodes for constant REF expressions * src/basic_fun_jmg.cpp, src/hdf_fun.cpp, src/hdf_fun.hpp, src/hdf_pro.cpp, src/hdf_pro.hpp, src/libinit_jmg.cpp, src/prognode.hpp, src/prognodeexpr.cpp: Copy sibling nodes for constant REF_CHECK expressions (e. g. REFORM(INDGEN(100),10,10) 2009-01-19 m_schellens * gdl.kdevses, src/basic_fun.cpp, src/libinit.cpp: undocumented BYTSCL accepting three parameters (value,min,max) from Sylvester Arabas 2009-01-12 jomoga * src/basic_fun_jmg.cpp: Fix seg fault in SIZE when structure undefined 2008-12-09 m_schellens * src/gdlexception.hpp, src/str.hpp, src/typedefs.hpp, src/gdlexception.cpp: changed assert to exception for error diagnostics 2008-12-08 m_schellens * gdl.kdevses, src/basic_fun.cpp, src/basic_fun.hpp, src/libinit.cpp, src/typedefs.hpp: fixed REGEXP with /SUBEXPR 2008-12-01 alaingdl * NEWS, src/pro/spl_init.pro, src/pro/spl_interp.pro: initial import for SPL_INIT() and SPL_INTERP(), GDL syntax; thanks to Ph. Prugniel, Lyon's Obs. 2008-11-27 m_schellens * src/basic_fun.cpp: fixed 64bit incompatibility 2008-11-18 alaingdl * src/plotting.cpp: recovering /fill and details in CONTOUR 2008-11-16 m_schellens * gdl.kdevelop, gdl.kdevses, src/antlr/Parser.cpp, src/antlr/TreeParser.cpp, src/basic_fun.cpp: g++ 4.3 compatibility 2008-11-15 m_schellens * src/ncdf_var_cl.cpp, src/plotting.cpp: from Sylwester Arabas 2008-10-19 m_schellens * src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/gdlc.tree.g: ignore something like a=(a=a) (so it is allowed even if a is undefined) * src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/gdlc.tree.g: accept self assignment of undefined variables 2008-10-13 m_schellens * gdl.kdevelop, gdl.kdevses, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g: fixed print, ', ', FORMAT='(A)' 2008-09-25 alaingdl * src/pro/matrix_multiply.pro: missing ";" 2008-09-22 jomoga * src/basic_fun.cpp: Add SUBEXPR keyword support for STREGEX * src/basic_fun_jmg.cpp, src/libinit_jmg.cpp: Add S_FUNCTIONS/S_PROCEDURES keywords for ROUTINE_NAMES * src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp: Add stub for RESOLVE_ROUTINE 2008-09-06 jomoga * src/typedefs.hpp: GDLArray buffer default set to scalar size rather than to NULL 2008-08-29 m_schellens * src/gdlexception.cpp, src/libinit.cpp, src/prognode.hpp, src/prognodeexpr.cpp: correct transforming of parameter_def siblings wich are constant expressions 2008-08-29 alaingdl * NEWS, src/basic_fun.cpp: in MEDIAN(), managing "width" parameter (by Nicolas Galmiche) [please report bugs to Alain C.] 2008-08-28 m_schellens * src/prognode.cpp, src/prognodeexpr.cpp: corrected the advancing of the actual node pointer (_t) in struct Eval() functions 2008-08-26 m_schellens * src/GDLTreeParser.cpp, src/dpro.cpp, src/dpro.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/libinit.cpp, src/print_tree.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/GDLInterpreter.cpp, gdl.kdevelop, gdl.kdevses: precalculation for (selected) constant parmeter functions. Optimization of lib function calls 2008-08-17 m_schellens * src/prognodeexpr.cpp, src/prognodeexpr.hpp: precalculation for constant arrays composed of constant expressions * src/prognode.hpp, src/prognodeexpr.cpp, src/prognodeexpr.hpp: precalculation for constant expressions and constant arrays, a major improvement * src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dnode.cpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/prognode.cpp, src/GDLTreeParser.hpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreter.cpp: speedup for constant arrays 2008-08-16 m_schellens * src/prognodeexpr.cpp: removed duplicate ARRAYDEFNode::Eval() 2008-08-15 m_schellens * src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/typedefs.hpp, src/gdlc.tree.g, src/datatypes.hpp, src/gdlc.i.g, src/GDLInterpreter.hpp, src/basegdl.cpp, src/basegdl.hpp, src/GDLInterpreter.cpp, gdl.kdevelop: made memory deallocation more solid 2008-08-09 m_schellens * gdl.kdevelop, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/dstructgdl.hpp, src/gdlc.i.g, src/prognode.cpp, src/prognode.hpp, src/prognodeexpr.cpp, src/typedefs.hpp: interpreter optimization 2008-08-03 m_schellens * src/prognodeexpr.cpp, src/prognodeexpr.hpp, src/real2int.hpp, src/dpro.hpp, src/gdlc.i.g, src/gdlexception.hpp, src/print_tree.hpp, src/prognode.cpp, src/prognode.hpp, src/Makefile.am, src/Makefile.in, src/convert2.cpp, src/dnode.cpp, src/dnode.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterOptimized.cpp, src/GDLInterpreterOptimized.inc, gdl.kdevses: fixed conversion of real to unsigned interger types 2008-08-01 alaingdl * MAP_INSTALL: info about 2 news projections (7, 17); mapping is working for x86_64 2008-07-31 alaingdl * NEWS: what's new ?! * testsuite/test_contour_extra.pro: Testing new capabilities in CONTOUR (Levels=, Nlevels= and /FILL) * src/plotting.cpp: add /FILL and Nlevels= to CONTOUR * src/basegdl.hpp: numbering the TYPE value in comments (no effect) * testsuite/test_fix.pro: test for FIX since type 12, 13 and 15 where found broken by Nicolas for negatives values 2008-07-28 alaingdl * testsuite/test_map.pro: 2 new Projections in examples (TEST_MAP) 2008-07-25 m_schellens * src/gdl.cpp, configure.in, configure: more precise version info on startup 2008-07-25 jomoga * src/hdf_pro.cpp: Fix start/count keyword ordering bug in HDF_SD_ADDDATA * src/plotting.cpp: Add support for NORMAL/TO_DEVICE (xy->ll) in CONVERT_COORD * src/math_utl.cpp: Add support for ROBINSON & SATELLITE projections 2008-07-25 alaingdl * src/GDLInterpreterOptimized.cpp: bug correction 2008-07-23 m_schellens * src/GDLInterpreterOptimized.cpp, src/GDLInterpreterOptimized.inc: adding file 2008-07-17 alaingdl * testsuite/test_rk4.pro, NEWS, TODO: Updated NEWS, TODO list, and testsuite/test_rk4.pro * src/math_fun_ng.cpp, src/math_fun_ng.hpp: Initial import of RK4() version by Nicolas Galmiche * testsuite/test_rk4.pro: Testsuite for RK4 based on Nose-Hoover equation (Thanks to S. Arabas) 2008-07-16 m_schellens * src/GDLInterpreter.hpp, src/Makefile.am, src/Makefile.in, src/antlr/Makefile.in, src/gdl.cpp, src/gdlc.i.g, src/GDLInterpreter.cpp, gdl.kdevses, configure, Makefile.in, aclocal.m4: startup message slightly changed 2008-07-07 jomoga * src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: Rename RK4 to RK4JMG 2008-06-10 jomoga * src/datalistt.hpp: Add pop_back() to DataListT class * src/libinit_jmg.cpp, src/math_fun_jmg.hpp, src/math_fun_jmg.cpp: Add rk4_fun * src/envt.hpp: add DelEnv() * src/dpro.hpp: Add DelVar() 2008-06-06 alaingdl * src/math_fun_ng.cpp, src/libinit_ng.cpp: for VOIGT(): add forgotten file "src/libinit_ng.cpp"; correction in "src/math_fun_ng.cpp" * src/antlr/Makefile.in, src/Makefile.in, src/Makefile.am, configure, aclocal.m4, Makefile.in: since 3 new files in src/, need to change src/Makefile.am and propagate changes via (aclocal, autoconf & automake) * NEWS: what's new in 0.9rc1 ?! * src/voigt.cpp, src/math_fun_ng.hpp, src/math_fun_ng.cpp, src/libinit.cpp: initial import of codes for function VOIGT() * src/pro/real_part.pro: initial import of function REAL_PART() in GDL syntax * testsuite/test_voigt.pro: initial import of test suite for VOIGT() 2008-05-28 jomoga * src/fftw.cpp: Fix memory leak 2008-05-05 m_schellens * src/basic_pro.cpp, src/gdlc.g, src/gdlc.tree.g, src/GDLTreeParser.cpp, src/GDLLexer.cpp, src/GDLParser.cpp: changes reported to be necessary for g++ 4.3 2008-05-01 m_schellens * src/antlr/CharScanner.hpp, gdl.kdevelop: g++ 4.3 compatibility * testsuite/test_suite.pro, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/Makefile.in, src/antlr/Makefile.in, src/gdlc.g, src/typedefs.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, gdl.kdevelop, gdl.kdevses, configure, Makefile.in, aclocal.m4: allow floats without exponent number like 1e 2008-04-30 alaingdl * src/gdljournal.cpp: for JOURNAL: working gethostname() on Mac OS X and Debian ... 2008-04-17 alaingdl * src/pro/factorial.pro: FACTORIAL(): correcting bug when inputs are Integers; managing arrays * testsuite/test_factorial.pro: Testing the FACTORIAL() function 2008-04-06 m_schellens * src/pro/read_ascii.pro: Made for READ_ASCII DATA_START independent of HEADER * src/Makefile.in, src/Makefile.am: removed double linking of plot3d_nr.cpp * src/basic_pro.cpp, gdl.kdevelop, configure.in, ChangeLog, README, config.h.in, configure: 0.9rc1 GDL 0.9rc1: 2008-04-03 m_schellens * src/plot3d_nr.cpp, gdl.kdevelop, configure.in, configure, config.h.in: sync 2008-04-03 alaingdl * src/pro/skip_lun.pro, testsuite/test_skip_lun.pro: SKIP_LUN: initial import; should work for /lines, don't know if other cases (byte) OK * src/devicex.hpp: TV: improved message when 3D array have wrong size 2008-04-02 alaingdl * src/devicex.hpp: in TV, better handling of input arrays with bad dimensions 2008-03-28 alaingdl * NEWS, TODO: revisiting the TODO list * testsuite/test_widgets.pro: basic tests for Widgets. GDL must have been compiled with lib WXWIDGETS * src/pro/smooth.pro: in SMOOTH(), mananing 0- and 1-elem input and bad type (Struc and String) * testsuite/test_cursor.pro: a small change in TEST_CURSOR * testsuite/test_invert_matrix.pro: improved INVERT() testsuite (and benchmark frame included) 2008-03-27 jomoga * src/math_fun_jmg.cpp: Allow sub-pixel interpolation for translations in POLY_2D 2008-03-26 alaingdl * src/devicex.hpp: managing in TV the ORDER keyword (see also !order) * src/basic_pro.cpp: now compiled and work with and without libREADLINE ! 2008-03-20 alaingdl * testsuite/test_surface_basic.pro, testsuite/test_contour_basic.pro: managing non square cases too ! * src/plotting.cpp: correcting SURFACE (when not square, or x,y provided) 2008-03-19 alaingdl * src/plotting.cpp: details in CURSOR; bugs due to zValT in SURFACE * testsuite/test_surface_basic.pro, testsuite/test_contour_basic.pro: test suite for CONTOUR and SURFACE * testsuite/test_cursor.pro, testsuite/test_get_lun.pro: Testing GET_LUN 2008-03-14 alaingdl * src/plotting.cpp, src/real2int.hpp: Recovering the working CURSOR version ! 2008-03-13 jomoga * src/plotting.cpp: Use transpose in SURFACE for rect case 2008-03-13 m_schellens * src/plot3d_nr.cpp: undo last (accidental) commit for plplot3d_nr.cpp * src/typedefs.hpp, src/plotting.cpp, src/real2int.hpp, src/specializations.hpp, src/datatypes.hpp, src/plot3d_nr.cpp, src/convert2.cpp, src/datatypes.cpp, src/arrayindex.hpp: remove (comment out) GDLarray min() max() 2008-03-12 alaingdl * testsuite/test_byte_conversion.pro: Testing conversion to Byte for large Float and Double ... * src/real2int.hpp, src/convert2.cpp: Float2Byte and Double2Byte need a modulus to work fine 2008-03-12 jomoga * src/plot3d_nr.cpp: Port to plplot-5.9 * src/typedefs.hpp: Fix min()/max() functions 2008-03-12 alaingdl * src/plotting.cpp: Updating CURSOR for RDPIX full compatibility * src/basic_pro_jmg.cpp: Working version of WAIT (see test_wait.pro) * testsuite/test_wait.pro: Testing (new version of) WAIT 2008-03-12 m_schellens * src/real2int.hpp, src/convert2.cpp: fix BYTE function overflow behaviour for real values 2008-03-11 m_schellens * src/plotting.cpp, src/format.out.g, src/gdlgstream.cpp, src/plot3d_nr.cpp, src/Makefile.am, src/Makefile.in, src/devicex.hpp, src/format.g, src/FMTParser.hpp, src/FMTTokenTypes.hpp, src/FMTTokenTypes.txt, src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTOutTokenTypes.hpp, src/FMTOutTokenTypes.txt, src/FMTParser.cpp, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, ChangeLog, configure: fix FORMAT="(/)" bug 2008-03-11 alaingdl * src/initsysvar.cpp, src/libinit_jmg.cpp: addinf !ORDER system variable (used in TV, TVSCL and TVRD, needed by RDPIX ...) 2008-03-06 jomoga * src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp, src/widget.hpp: Add WIDGET_TEXT * src/objects.cpp: Add WIDGET_TEXT structure * src/libinit_jmg.cpp: Add widget routines * src/libinit.cpp: Remove widget routines 2008-03-03 alaingdl * src/gsl_fun.cpp: improvment of INVERT : one element array, checking if square matrix, String ... * src/pro/matrix_multiply.pro: Initial import of MATRIX_MULTIPLY * testsuite/test_invert_matrix.pro: Extensive tests of INVERT() (matrix inversion) 2008-03-01 alaingdl * NEWS, src/plotting.cpp, src/plotting.hpp: Initial import of CURSOR. Some limitations, help welcome ! * testsuite/test_cursor.pro: two basics tests for CURSOR procedure 2008-02-26 alaingdl * src/libinit.cpp: initial import of interface for CURSOR procedure, re-import of RECALL_COMMANDS() * src/initsysvar.cpp, src/initsysvar.hpp: initial import for !mouse (to be used by CURSOR ...) 2008-02-15 jomoga * src/libinit.cpp: Add additional widget keywords * src/gdlwidget.cpp, src/gdlwidget.hpp, src/widget.cpp, src/widget.hpp: Add WIDGET_INFO & WIDGET_EVENT * src/objects.cpp: Add WIDGET_BUTTON structure * src/gdl.cpp: Remove widget initialization * src/basic_pro.cpp: Add widget initialization 2008-02-15 alaingdl * src/basic_pro.cpp, src/basic_pro.hpp: initial input of code for function RECALL_COMMANDS() and equivalent keyword in HELP proc. * src/libinit.cpp: add function RECALL_COMMANDS() and keyword /RECALL in HELP procedure 2008-02-07 alaingdl * src/libinit.cpp: new keywords for PLOT, CONTOUR, ... * testsuite/test_titles.pro: demo suite for title, subtitle, ... and title formatting capabilities (initial import) * testsuite/test_axis.pro: demo of AXIS capabilities (initial import) * testsuite/test_greek_letters.pro: Greek Letters demo (initial import) 2008-02-01 jomoga * configure, configure.in, src/basic_pro.cpp, src/gdl.cpp, src/gdlwidget.cpp, src/gdlwidget.hpp, src/libinit.cpp, src/widget.cpp, src/widget.hpp: (Very) Preliminary implementation of widgets GDL 0.9pre6: 2007-12-21 alaingdl * INSTALL, NEWS, src/basic_pro.cpp, src/dinterpreter.cpp, src/gdljournal.cpp: history file management (~/.gdl/history) 2007-12-09 m_schellens * src/basic_fun_jmg.cpp, src/objects.cpp: moved definition of IDL_SIZE into InitStructs function (objects.cpp) 2007-12-07 jomoga * src/basic_fun_jmg.cpp: Initialize dims to 0 in SIZE w/STRUCTURE keyword 2007-12-05 jomoga * src/datatypes.cpp: Fix CShift bug 2007-11-08 m_schellens * src/antlr/Makefile.in, src/Makefile.in, src/assocdata.cpp, src/assocdata.hpp, gdl.kdevelop, gdl.kdevses, configure, Makefile.in, aclocal.m4: added missing new/delete operators for ASSOC types 2007-10-27 m_schellens * ChangeLog, NEWS, gdl.kdevses: sync with tagged 2007-10-22 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/gdlc.i.g: fixed append int to struct array bug * gdl.kdevelop, gdl.kdevses, src/dstructdesc.hpp, src/typetraits.cpp, src/typetraits.hpp: ref count for DStructDesc 2007-10-22 jomoga * src/math_utl.cpp: Change Get to GetTag (structure method) 2007-10-22 m_schellens * src/default_io.cpp, gdl.kdevelop, gdl.kdevses: Fixed reading/writing for struct arrays 2007-10-20 m_schellens * src/typetraits.cpp, src/typetraits.hpp, testsuite/test_suite.pro, src/devicez.hpp, src/dstructdesc.cpp, src/dstructdesc.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/envt.cpp, src/extrat.cpp, src/gdl.cpp, src/gdlc.i.g, src/gdlexception.cpp, src/gdljournal.cpp, src/graphics.hpp, src/ifmt.cpp, src/initsysvar.cpp, src/math_fun_gm.cpp, src/ncdf_att_cl.cpp, src/ncdf_var_cl.cpp, src/plotting.cpp, src/specializations.hpp, src/typedefs.hpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/accessdesc.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/default_io.cpp, src/devicex.hpp, gdl.kdevses: more effective internal memory handling for structs 2007-09-17 m_schellens * src/basic_fun.cpp: fixed: strpos takes any to string convertible type as 2nd parameter * src/datatypes.hpp, src/dstructgdl.hpp, src/arrayindex.hpp: fixed: a[[scalar]] returns one element array 2007-09-12 jomoga * src/ncdf_var_cl.cpp: Fix VARPUT bugs 2007-09-11 jomoga * src/ncdf_var_cl.cpp: Fix input parameter bugs 2007-09-10 jomoga * src/libinit_cl.cpp, src/ncdf_att_cl.cpp, src/ncdf_dim_cl.cpp: Fix various input parameter bugs 2007-09-08 m_schellens * src/basic_op.cpp, src/typedefs.hpp: Fixed AND for FLOAT 2007-09-07 m_schellens * src/basic_op.cpp: Fixed AND bug 2007-09-06 jomoga * src/ncdf_var_cl.cpp: Change var_id to varid 2007-09-05 jomoga * src/ncdf_var_cl.cpp: Allow varid to be variable name in VARGET, VARGET1, VARPUT 2007-09-05 alaingdl * testsuite/test_plot_benchmark.pro: correcting bug when selecting only one test * src/pro/file_basename.pro, src/pro/file_dirname.pro: initial import of File_Basename and File_Dirname, thanks to S. Masson 2007-09-03 m_schellens * src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dimension.hpp, src/typedefs.hpp, src/typetraits.hpp, gdl.kdevelop, gdl.kdevses: Introduced GDLArray 2007-09-01 m_schellens * src/ofmt.cpp, src/topython.cpp, gdl.kdevses, src/basic_op.cpp, src/convert2.cpp, src/convol.cpp, src/datatypes.cpp, src/default_io.cpp, src/dstructgdl.hpp, src/ifmt.cpp: channel all data (dd member) access through [] operator 2007-08-30 m_schellens * aclocal.m4, configure, gdl.kdevelop, gdl.kdevses, src/Makefile.in, src/antlr/Makefile.in, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, Makefile.in: custom operator new/delete 2007-08-30 jomoga * src/ncdf_var_cl.cpp: Preliminary fix for INT bug in NCDF_VARGET 2007-08-25 jomoga * src/basic_fun.cpp, src/libinit.cpp: Add support for DIM & DOUBLE keywords in MEDIAN 2007-08-23 jomoga * src/libinit_jmg.cpp, src/gsl_fun.cpp, src/gsl_fun.hpp: Add LA_TRIRED routine 2007-08-21 m_schellens * src/dnode.hpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dnode.cpp, src/GDLLexer.cpp, gdl.kdevses: Fixed discrepency in conversion of constant numbers 2007-08-13 jomoga * src/basic_fun.cpp: Fix indexing bug in MEDIAN with EVEN keyword 2007-08-08 m_schellens * NEWS, gdl.kdevses, src/libinit_cl.cpp, src/ncdf_att_cl.cpp, src/ncdf_var_cl.cpp: Applied two patches from Sylwester Arabas 2007-07-09 alaingdl * NEWS, testsuite/test_plot_benchmark.pro: remove 3 duplicated lines in NEWS; bug in "test_plot_benchmark.pro" 2007-07-05 m_schellens * src/basic_pro.cpp, configure.in, configure: sync 0.9pre5 * gdl.kdevses, NEWS, README, configure: edit 2007-06-28 jbronn * configure.in: fixed python configure bug (no sub version numbers, e.g., 2.5 not 2.5.1) 2007-06-25 alaingdl * testsuite/test_plot_benchmark.pro, testsuite/test_plot_linestyle.pro, NEWS: info in NEWS; correction of details in "test_plot_benchmark.pro" and "test_plot_linestyle.pro" 2007-06-23 m_schellens * src/basic_fun.cpp, src/basic_pro.cpp, src/convert2.cpp, src/envt.cpp, src/envt.hpp, src/basegdl.hpp, gdl.kdevses, gdl.kdevelop: Full ON_IOERROR support 2007-06-19 m_schellens * src/io.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/basic_fun.cpp, src/basic_pro.cpp, src/gdlc.i.g, gdl.kdevses: ON_IOERROR support 2007-06-19 jomoga * src/export.hpp: Change to GDL_VarCopy() * src/basic_pro_jmg.cpp: Small changes to LINKIMAGE * src/export.hpp: Initial import. 2007-06-18 m_schellens * gdl.kdevelop, src/dinterpreter.cpp, src/gdl.cpp: init readline already before interpreter is instantiated 2007-06-18 alaingdl * src/plotting.cpp: several important changes in "plotting.cpp" -- autoscaling providing better mimic of IDL except when all data are equal -- providing 6 linestyle, managing keyword versus !p.linestyle -- rewriting of "draw_polyline" using <> to improve speed for large datasets * testsuite/test_histo.pro: initial import of a test program for histogram with 2 procedures * testsuite/test_plot_inf_nan.pro, testsuite/test_plot_info.pro, testsuite/test_plot_linestyle.pro, testsuite/test_map.pro, testsuite/test_minmax.pro, testsuite/test_plot_basic.pro, testsuite/test_plot_benchmark.pro: initial import of 5 programs for checking plotting options (/nan now works on Nan and +-Inf; linestyle, "fast" plot) 2007-06-11 m_schellens * gdl.kdevelop, configure, configure.in, README: sync 2007-06-10 m_schellens * src/math_fun_ac.cpp: small corrections 2007-06-07 alaingdl * src/basic_fun.cpp, src/datatypes.cpp: In "basic_fun.cpp", correcting /Nan keyword for Min() and Max() In "datatypes.cpp", managing -/+ Inf and also solve case when NaN is first element. * testsuite/test_minmax.pro: Add testsuite/test_minmax.pro, a serie of tests for Min() and Max() 2007-06-03 m_schellens * src/antlr/Makefile.in, src/terminfo.cpp, src/Makefile.in, configure.in, gdl.kdevses, aclocal.m4, config.h.in, configure, Makefile.in: Some small changes for OS X 2007-06-02 m_schellens * src/basic_fun_jmg.cpp, src/dstructgdl.hpp: use of New( dim, BaseGDL::INIT * src/assocdata.cpp, src/dstructgdl.hpp: Fixed ASSOC for STRUCTS * src/assocdata.cpp, src/basic_fun.cpp: Fixed ASSOC for structs and 1 element arrays * gdl.kdevelop, gdl.kdevses, src/Makefile.in, src/basic_pro.cpp, src/terminfo.cpp: Fixed APPEND keyword for OPENW 2007-05-29 alaingdl * src/libinit_gm.cpp, src/math_fun_gm.cpp, src/math_fun_gm.hpp: Initial import of GAUSSINT() using gsl_sf_erf() * testsuite/test_gammas.pro: removing +-Inf for plotting in test_gammas * NEWS: the new functions (erf, erfc, ...) are added in NEWS 2007-05-25 alaingdl * src/Makefile.am, src/Makefile.in: Makefile should now link to Gregory's files ... (libinit_gm.cpp, math_fun_gm.*) * src/basic_fun_cl.cpp, src/basic_fun_cl.hpp, src/libinit_cl.cpp: Since reworked of Gregory, GAMMA(), LnGAMMA(), IGamma() and BETA() are removed from C. Lee codes. * src/math_fun_gm.cpp, src/math_fun_gm.hpp: Initial import of Gregory's work in C++: ERF(), ERFC(), EXPINT() and ERRORF() (clone of ERF() for old IDL codes) Rework of functions with weakness in many cases: GAMMA(), LnGAMMA(), IGamma() and BETA(). These functions were previously in "basic_fun_cl.*" where they have been removed. (please see related test functions in testsuite/) [tested on x86, x86_64 and MacOS] * src/libinit.cpp, src/libinit_gm.cpp: Initial import of libinit_gm.cpp (Gregory's functions to come) Modification of libinit.cpp to take into account libinit_gm.cpp * testsuite/test_erfs.pro, testsuite/test_expint.pro, testsuite/test_gammas.pro: adding 3 files in testsuite/ for testing: ERF(), ERFC(), GAMMA(), LnGAMMA(), IGamma(), BETA() and EXPINT() Files are : test_erfs.pro test_expint.pro test_gammas.pro * testsuite/test_map.pro: removing useless warning of x86_64 bugs in test_map 2007-05-23 jomoga * src/gsl_fun.cpp: Fix random Poisson for large mu 2007-05-10 jomoga * src/terminfo.cpp: Fix bug with initscr() for batch or ssh mode 2007-05-08 jomoga * src/plotting.cpp: Fix DEVICE & NORMAL bug in xyouts,plots * src/basic_fun_jmg.cpp, src/hdf_fun.cpp, src/hdf_pro.cpp, src/gsl_fun.cpp, src/math_fun_jmg.cpp, src/ncdf_var_cl.cpp, src/plotting.cpp: Change cast in 1st arg to dim() from SizeT to DLong to fix alloc buf on x86_64 2007-05-07 jomoga * src/gsl_fun.cpp: Add 3D support for INTERPOLATE 2007-05-01 jomoga * src/basic_pro.cpp: Allow leading '~/' in OPEN filenames 2007-04-25 jomoga * src/initsysvar.cpp: Apply patch for environment variable GDL_DIR 2007-04-22 m_schellens * src/file.cpp, src/Makefile.in: Fixed FILE_SEARCH multiple repetition of dir in result strings 2007-04-21 alaingdl * src/libinit_ac.cpp: forgotten file for BESELx functions (sorry) 2007-04-20 alaingdl * NEWS: updated "NEWS" for Bessel Functions initial import * src/Makefile.am, src/libinit.cpp, src/math_fun_ac.cpp, src/math_fun_ac.hpp: initial import for BESEL {I,J,K,Y} functions * testsuite/test_besel.pro: initial import for test BESEL {I,J,K,Y} functions 2007-04-18 jomoga * src/math_utl.cpp: Fix CONIC p0lon/lat bug * src/plotting.cpp: Fix !p.multi bugs introduced by map support 2007-04-17 alaingdl * testsuite/test_map.pro: TEST_MAP: checking if data are in !dir; more explicite messages 2007-04-16 jomoga * src/plotting.cpp: Fix PS newpage plotting bug * src/gdlgstream.cpp, src/gdlpsstream.hpp: Remove PS eop() function 2007-04-11 m_schellens * src/math_fun.cpp: All types for SVDC * src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp, configure, configure.in, gdl.kdevses: SVDC 2007-04-07 m_schellens * src/dnode.cpp: short circuit for logical 'or' and 'and' * src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp, src/datatypes.hpp, src/dnode.cpp, src/dstructgdl.hpp, src/specializations.hpp: Changed scalar op one_element_array result to array 2007-04-06 m_schellens * src/dcompiler.cpp, gdl.kdevses: Changed order of function/variable lookup 2007-04-02 jomoga * src/basic_fun.cpp: Trap 0 values in dimensions for array generator functions. 2007-03-31 m_schellens * src/dcompiler.cpp: Changed: variable and function ambiguity: variables precede now * src/convert2.cpp, gdl.kdevses: Fixed conversion of empty string to byte 2007-03-29 m_schellens * src/envt.cpp: Fix for HEAP_GC 2007-03-28 jomoga * src/print.cpp: Fix MSG_NOSIGNAL compile problem on OS X 2007-03-28 m_schellens * gdl.kdevses, src/envt.cpp: Handle nested HEAP_GC calls from CLEANUP 2007-03-27 jomoga * NEWS, src/devicex.hpp: Add support for TRUE/CHANNEL keywords in TVRD for X 2007-03-25 m_schellens * src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp, src/datatypes.hpp, src/dnode.cpp, src/dstructgdl.hpp, src/specializations.hpp: Speedup for POW 2007-03-24 m_schellens * gdl.kdevses, src/basic_op.cpp, configure, configure.in: added -ltermcap to LDFLAGS in 2007-03-24 jomoga * src/devicez.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/gdlzstream.cpp, src/gdlzstream.hpp, src/graphics.hpp, src/plotting.cpp: Add support for bkgr color in ERASE/Fix zbuf fill problem 2007-03-23 jomoga * src/math_utl.cpp: Add support for Oblique Cylindrical projection 2007-03-22 m_schellens * src/envt.cpp, src/print.cpp: fixed printf,-1,var 2007-03-21 m_schellens * src/GDLTreeParser.cpp, src/basic_pro.cpp, src/dnode.cpp, src/gdlc.tree.g: Fixed problem (segfault) compiling subroutines containing only common blocks 2007-03-20 m_schellens * gdl.kdevses, src/devicex.hpp: Fixed: segfault closing X graphic window 2007-03-19 m_schellens * src/basic_pro.hpp, src/envt.cpp: Proper message for HEAP_GC,/VERBOSE * gdl.kdevses, src/envt.cpp: Fixed HEAP_GC (freeing of objects without CLEANUP method) * gdl.kdevses, src/datatypes.cpp: Fixed assignment bug: struct.tag=[one_element_array] 2007-03-19 jomoga * src/pro/value_locate.pro: Remove 'default', Add 'is_defined' and 'is_scalar' * src/math_fun_jmg.cpp: Fix memory overwrite in poly_2d_fun for BYTE arrays 2007-03-19 alaingdl * src/basic_pro.cpp: Try to correct a bug in DEFSYSV when the Variable is not defined (previously, if x is undefined, this will crash : DEFSYSV, '!x', x). 2007-03-19 jomoga * src/libinit.cpp: Change max # params in ERASE to 1 for background color * src/plotting.cpp: Add support for non-X devices in CONVERT_COORD * src/libinit_jmg.cpp: Add TYPE keyword to hdf_sd_attrinfo * src/initsysvar.cpp, src/initsysvar.hpp: Add support for Device system variable access * src/hdf_pro.cpp: Add support for string attributes * src/hdf_fun.cpp: Remove cout statement 2007-03-18 m_schellens * src/envt.cpp, NEWS, src/GDLInterpreter.hpp, src/basic_pro.cpp, src/basic_pro.hpp, src/dstructdesc.hpp, src/envt.hpp, src/gdlc.i.g, src/libinit.cpp, src/math_fun.cpp, src/typedefs.hpp: Added HEAP_GC * configure.in, configure: changed configure.in for checking gsl version 1.4 or higher 2007-03-17 m_schellens * Makefile.in, gdl.kdevses, src/Makefile.in, src/antlr/Makefile.in, src/datatypes.cpp, src/devicex.hpp: Fixed WSET (ProcessDeleted did set actWin) bug 2007-03-15 alaingdl * gsl.m4: initial import for "gsl.m4" which is used by "configure.in" to check the GSL version * configure.in, INSTALL, README, config.h.in, configure: changes in configure.in : checking GSL version (>= 1.4), Zlib presence details in README and INSTALL 2007-03-14 jomoga * src/plotting.cpp: Fix cast in TYPE write in set_mapset 2007-03-09 jomoga * src/gdlpsstream.hpp, src/gdlgstream.cpp: Fix initial blank page for PS output 2007-03-09 alaingdl * src/pro/findfile.pro: bug Keyword --> keyword_set ;-) 2007-03-08 alaingdl * src/pro/findfile.pro: add very basic FINDFILE (as a .pro) since oftenly used in old codes. please consider FILE_SEARCH --provided by GDL-- instead. 2007-03-04 jomoga * src/gzstream.hpp: Initial import. * src/assocdata.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_pro.cpp, src/datatypes.hpp, src/default_io.cpp, src/dstructgdl.hpp, src/gdljournal.cpp, src/io.cpp, src/io.hpp, src/specializations.hpp: Add partial support for COMPRESS keyword in OPEN (read only) 2007-03-02 jomoga * configure, configure.in: Check for libfftw3f library 2007-03-02 alaingdl * README: how to really have FFTw in GDL ! 2007-02-28 alaingdl * src/pro/save.pro, testsuite/test_map.pro, testsuite/test_restore.pro, testsuite/test_save.pro, MAP_INSTALL, src/pro/restore.pro: add options and several checks when using SAVE and RESTORE, especially the verbose keyword in RESTORE and the check of unamed variables in SAVE in testsuite/, add TEST_SAVE and TEST_RESTORE for fast basic tests in testsuite/, add TEST_MAP for quicky run a demo for MAP_SET,/continent ! 2007-02-28 jomoga * src/basic_fun_jmg.hpp: Fix title statement * src/hdf_fun.cpp, src/hdf_fun.hpp, src/hdf_pro.cpp, src/hdf_pro.hpp: Transfer include mfhdf.h statement from include to source files * src/libinit_jmg.cpp: Remove dpro.hpp statement 2007-02-27 jomoga * INSTALL, MAP_INSTALL, NEWS: Update libproj4 info 2007-02-25 jomoga * src/libinit.cpp, src/math_fun.cpp: ADD L64 keyword to ROUND 2007-02-21 jomoga * src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: Add TRIGRID function * MAP_INSTALL: Initial import. 2007-02-17 m_schellens * src/accessdesc.hpp, src/datatypes.cpp, src/datatypes.hpp: fixed assignment of arrays to struct expressions * gdl.kdevses, src/basic_pro.cpp: allow all types for REPLICATE_INPLACE 2007-02-13 jomoga * src/math_utl.cpp, src/math_utl.hpp, src/plotting.cpp, src/plotting.hpp: Transfer map_init() from plotting.cpp to math_utl.cpp 2007-02-09 jomoga * src/read.cpp: Replace 'push_back' loop with 'append' method in READF 2007-02-08 jomoga * src/basic_fun.cpp: Set default pattern to ' ' in STRTOK for /REGEX 2007-02-06 jomoga * src/gsl_fun.cpp: Speed up INTERPOLATE 2007-02-06 m_schellens * configure.in, gdl.kdevelop, gdl.kdevses, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/arrayindex.cpp, src/arrayindexlistt.hpp, src/basic_pro.cpp, src/basic_pro.hpp, src/dstructgdl.hpp, src/gdlc.tree.g, src/libinit.cpp, configure: REPLICATE_INPLACE from Sergio Gelato 2007-02-06 jomoga * src/pro/read_jpeg.pro: 16-bit image redux 2007-02-05 jomoga * src/pro/read_jpeg.pro: Convert 16-bit image to byte 2007-02-04 jomoga * src/plotting.cpp: Add TO_DEVICE keyword support for ll->xy map conversions * src/libinit_jmg.cpp: Add XSIZE/YSIZE keywords to tvKey 2007-02-02 jomoga * src/plotting.cpp, src/plotting.hpp: Add map support to XYOUTS 2007-02-01 jomoga * src/libinit.cpp: Add 'Z' to xyoutsKey 2007-01-30 m_schellens * Makefile.in, aclocal.m4, config.h.in, configure, gdl.kdevelop, gdl.kdevses, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTInTokenTypes.hpp, src/FMTInTokenTypes.txt, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/Makefile.in, src/antlr/Makefile.in, src/assocdata.cpp, src/basic_fun.cpp, src/datatypes.cpp, src/gsl_fun.hpp, src/ifmt.cpp, src/io.cpp, src/io.hpp: Fixed ASSOC bug (bug tracker ID 1631690) 2007-01-29 jomoga * src/plotting.cpp: Add MERCATOR projection. Fix grid/cont line jumps 2007-01-25 jomoga * NEWS: SOCKET & FFT/DIMENSION keyword support * src/fftw.cpp, src/gsl_fun.cpp: Add support for DIMENSION keyword in FFT 2007-01-19 jomoga * src/basic_fun.cpp, src/basic_pro.hpp, src/io.cpp, src/io.hpp, src/libinit.cpp, src/print.cpp, src/read.cpp, src/basic_pro.cpp: Add SOCKET support 2007-01-07 jomoga * src/basic_fun_jmg.cpp: Rewrite ROUTINE_NAMES without pop_back 2006-12-30 m_schellens * src/basic_pro.cpp, src/libinit.cpp, src/ncdf_att_cl.cpp, src/ncdf_var_cl.cpp: Added the unofficial CALLS keyword to HELP 2006-12-29 m_schellens * gdl.kdevses, src/dcompiler.cpp, src/dcompiler.hpp: purge common blocks before recursive compilation 2006-12-21 jomoga * src/gsl_fun.cpp: Fix 'ny' for vector output 2006-12-19 jomoga * src/pro/ishft.pro: Fix for column vectors 2006-12-19 alaingdl * src/pro/restore.pro, src/pro/save.pro: since EXECUTE is now working in GDL, finalization of CMSVlib checks and users informations in SAVE/RESTORE 2006-12-19 m_schellens * gdl.kdevses, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basic_fun.cpp, src/gdlc.i.g: Corrected return value of EXECUTE * AUTHORS, src/arrayindex.hpp, src/arrayindexlistt.hpp: made something like a[3,i] scalar 2006-12-18 alaingdl * src/pro/README.txt, src/pro/UrgentNeed.txt: dd direct link to http://idlastro.gsfc.nasa.gov/idllibsrch.html which provides some files from the IDL lib. 2006-12-15 alaingdl * src/pro/restore.pro, src/pro/save.pro: add in headers of these 2 files link to the external CMSV lib. add a test to check wether the CMSV lib. is available or not * src/pro/README.txt, src/pro/UrgentNeed.txt: typo corrected 2006-12-15 m_schellens * gdl.kdevses, src/extrat.cpp: Fixed problem with _EXTRA=undefined keywords 2006-12-14 alaingdl * src/pro/README.txt, src/pro/STATUS, src/pro/UrgentNeed.txt: add README.txt in order to give explainations about the content of this directory. add UrgentNeed.txt in order to indicate clearly the most urgent procedures and is someone has started to work on. update STATUS since I have added few files * src/pro/file_lines.pro: add FILE_LINES, pro file of a function appering in IDL 5.5 2006-12-11 alaingdl * AUTHORS, NEWS: add Alain as tester in AUTHORS' list; typo for integer in NEWS * testsuite/test_colors.pro, testsuite/test_op_elem.pro, testsuite/test_op_power.pro: add 3 test files : one for checking colors, 2 for time test. 2006-12-02 m_schellens * src/ncdf_att_cl.cpp, src/ncdf_var_cl.cpp: Included patch from opoplawski 2006-11-27 jomoga * NEWS: Update NEWS * src/basic_pro.cpp, src/io.cpp, src/io.hpp: Remove streamVMS support; Add variable-length file support * src/gdljournal.cpp: Conform to new Open method * src/default_io.cpp: Remove XDR conversion for BYTE (Not in IDL) * src/basic_pro_jmg.cpp: Remove streamVMS adjustment from POINT_LUN 2006-11-22 jomoga * src/basic_pro.cpp: STREAM keyword only supported in VMS * src/basic_pro_jmg.cpp: Add STREAM file fix to POINT_LUN 2006-11-22 m_schellens * src/gdljournal.cpp, src/initsysvar.cpp, src/initsysvar.hpp, src/libinit.cpp, configure.in, src/GDLInterpreter.cpp, src/basic_pro.cpp, src/gdl.cpp, src/gdlc.i.g: 0.9pre3 2006-11-21 jomoga * src/gdl.cpp: Remove HELP,/INFO message 2006-11-20 jomoga * NEWS: Update NEWS * src/basic_pro.cpp, src/gdljournal.cpp, src/io.cpp, src/io.hpp: Add support for STREAM keyword in OPEN 2006-11-17 jomoga * src/initsysvar.cpp: Change MAP structure tag to UP_NAME * NEWS: Update NEWS * src/basic_pro.cpp, src/libinit.cpp: Add support for PROCEDURES, FUNCTIONS keywords in HELP 2006-11-16 m_schellens * src/datatypes.cpp, src/io.cpp: Fixed XDR bug 2006-11-15 m_schellens * src/basic_fun_jmg.cpp, configure, configure.in: Made REFORM conforming (no folding of all dimensions anymore) 2006-11-13 m_schellens * src/basegdl.cpp, src/typetraits.cpp: proper type names 2006-11-11 m_schellens * configure, configure.in, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/default_io.cpp, src/io.cpp, src/io.hpp, config.h.in: Proper handling of XDR structure, OS X 10.5 compliance 2006-11-10 m_schellens * src/datatypes.cpp: Fixed problem with gcc 4.1.1 error: specialization after instantiation 2006-11-04 jomoga * src/pro/value_locate.pro: Fix concatenation problems 2006-11-04 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, src/gdlc.tree.g, testsuite/test_suite.pro: fixed left assignment (soemthing like: ((a=2))=3) 2006-11-01 m_schellens * src/dnode.cpp, src/dnode.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, testsuite/test_suite.pro, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/arrayindexlistt.hpp, src/GDLLexer.cpp, configure.in, gdl.kdevelop, gdl.kdevses, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, README: fixed op= (+=, *= ...) for indexed expressions on the left side 2006-10-30 jomoga * NEWS: update NEWS 2006-10-25 jomoga * src/basic_pro.cpp: HELP displays compiled pro/fun * src/basic_fun_jmg.cpp: ROUTINE_NAMES returns compiled pro/fun if no keywords specified 2006-10-23 m_schellens * testsuite/test_suite.pro, src/dstructgdl.hpp, src/gdlc.i.g, src/dstructgdl.cpp, src/GDLInterpreter.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/dstructdesc.cpp, Doxyfile, gdl.kdevelop, gdl.kdevses: Allow named struct tags to be converted to first definition in redefiniton (raised an error before) 2006-10-23 jomoga * src/basic_fun_jmg.cpp: Fix seg fault with ROUTINE_NAMES if no keywords 2006-10-20 jomoga * src/gsl_fun.cpp: Implement INPUT keyword in HISTOGRAM 2006-10-19 jomoga * src/pro/value_locate.pro: Modified to return array with same dimensions as second argument 2006-10-18 jomoga * src/gdlgstream.cpp, src/gdlgstream.hpp: Use decomposed value in Background() method 2006-10-17 jomoga * src/libinit.cpp, src/math_fun.cpp: Support for L64 keyword in CEIL/FLOOR * src/plotting.cpp: Fix various COLOR/BACKGROUND bugs 2006-10-16 alaingdl * src/initsysvar.cpp: add a "!GDL" constant system variable in order to easily distinguish IDL and GDL (sometimes we know some tricky differences between both) 2006-10-12 jomoga * src/gdlgstream.cpp, src/gdlgstream.hpp: Use decomposed value in Color method * src/plotting.cpp: Get # of colors from DEVICE system variable * src/devicex.hpp: Change default N_COLORS to 16777216 2006-10-11 jomoga * src/dnode.cpp: Fix AdjustType bug (1st operand determines type) 2006-10-11 alaingdl * testsuite/test_uf77.pro: add a demo file in order to test /f77unformatted writeu/readu 2006-10-08 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, gdl.kdevses: Changed structs to be arrays 2006-10-05 m_schellens * NEWS: update NEWS * src/gdlc.i.g, src/pro/deriv.pro, src/pro/smooth.pro, testsuite/test_deriv.pro, testsuite/test_smooth.pro: Added SMOOTH and DERIV from Alain Coulais * src/gdlc.i.g, src/GDLInterpreter.cpp, src/dcompiler.cpp, gdl.kdevses: Fixed bug with FOR statement when the loop contains EXECUTE and within this a new variable is created 2006-09-28 jomoga * src/pro/ishft.pro: Get name right in header * src/pro/ishft.pro: Initial import 2006-09-27 m_schellens * src/ofmt.cpp: Fixed I format code zero padding (I0x formats are not supported) * src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/math_fun.cpp: log10( valarray<...>) for ALOG10, gcc 3.2.x compliance for ALOG and ALOG10 2006-09-27 jomoga * src/Makefile.in: Recommit V 1.47 * src/antlr/Makefile.in: Recommit V 1.32 * src/Makefile.in, src/antlr/Makefile.in, src/plotting.cpp: Fix bug [1560714] (PLOTS log scaling)plotting.cpp 2006-09-26 m_schellens * src/FMTOut.cpp, src/basic_pro.cpp, src/format.out.g: Fixed 'z' format code * src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/plotting.cpp, Makefile.in, configure, configure.in: Fixed offset without dim1,... for type conversion functions (BYTE, FIX, LONG, ...) 2006-09-26 jomoga * src/GDLInterpreter.cpp: Add support for ON_IOERROR 2006-09-25 jomoga * config.h.in, configure, configure.in: Fix 64-bit OS check 2006-09-24 jomoga * src/basic_fun_jmg.cpp: Fix st_atim bug [1563930] 2006-09-22 m_schellens * configure.in, config.h.in, configure, gdl.kdevses, src/plotting.cpp: Handle something like PLOT,/XLOG,/YLOG,[x,x],[y,y] 2006-09-21 jomoga * src/specializations.hpp: Install Patch [ 1561592 ] * src/basic_fun_jmg.cpp: Add ATIME, CTIME, MTIME to FSTAT 2006-09-20 jomoga * src/typedefs.hpp: Make SizeT typedef 32/64 OS-dependent * configure.in, config.h.in, configure: Check for 64-bit OS 2006-09-19 jomoga * src/plotting.cpp: Change wIx from int to DLong in wdelete 2006-09-18 m_schellens * src/arrayindex.hpp, src/arrayindexlistt.hpp, src/default_io.cpp, src/dstructgdl.hpp, gdl.kdevelop: Fixed boundary check for ArrayIndexListMultiT ALLONE 2006-09-17 m_schellens * src/FMTIn.cpp, src/FMTOut.cpp, src/format.in.g, src/format.out.g, gdl.kdevelop, gdl.kdevses: fixed T format code (starts from 1) 2006-09-16 m_schellens * src/FMTOut.cpp, src/FMTOut.hpp, src/convert2.cpp, src/format.g, src/format.out.g, src/ofmt.cpp, src/str.cpp: Fixed T format code (now count from 1, before fomr 0) 2006-09-15 jomoga * src/plotting.cpp: Add support for ORTHOGRAPHIC,STEREO,AZIMUTHAL,GNOMIC,CONIC,LAMBERT,AITOFF projections * src/devicex.hpp, src/devicez.hpp, src/image.hpp, src/libinit_jmg.cpp: Add support for CHANNEL keyword in TV/TVSCL 2006-09-14 m_schellens * src/ofmt.cpp: Fixed I format code (removed zero padding) * src/datatypes.cpp, src/dstructgdl.cpp, gdl.kdevses, src/FMTIn.hpp, src/default_io.cpp, src/format.in.g, src/gdlc.i.g, src/gdlexception.hpp, src/io.cpp, testsuite/test_suite.pro: Fixed assignment 'at' (one dim index: var[0]=...) for multi dim var 2006-09-13 jomoga * src/plotting.cpp: Change INF to NAN in CONVERT_COORD * src/basic_fun_jmg.cpp: Fix REFORM with 1 parameter 2006-09-12 m_schellens * src/convert2.cpp: Removed warning message for converting empty string to DOUBLE * src/default_io.cpp: Made read strings without FORMAT handle DOS mode files 2006-09-08 jomoga * src/basic_fun_jmg.cpp: Fix ROUTINE_NAMES GetPar (STORE) bug 2006-09-07 m_schellens * src/accessdesc.hpp, src/basic_fun.cpp: tags containing one element are skiped from dimension 2006-09-06 m_schellens * src/basic_fun.cpp: Minor chnages to CREATE_STRUCT * src/basic_pro.cpp: Output of HELP,/STRUCT for struct arrays 2006-09-04 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g, testsuite/test_suite.pro, gdl.kdevses: Fixed: CASE with empty statement list 2006-09-03 jomoga * src/basic_fun_jmg.cpp: Fix structure store bug in ROUTINE_NAMES * src/basic_fun.cpp: Structure variable bug fixes * src/GDLInterpreter.cpp: Make new structure single-element array rather than scalar * src/libinit.cpp, src/basic_pro.cpp: Add support for OUTPUT in HELP 2006-09-02 jomoga * src/pro/str_sep.pro: Initial import 2006-09-01 jomoga * src/pro/restore.pro, src/pro/save.pro: Add GPL license 2006-08-31 jomoga * src/basic_fun.cpp: Fix CREATE_STRUCTURE for undefined name 2006-08-30 jomoga * src/basic_fun_jmg.cpp: Add /STRUCTURE to SIZE * src/initsysvar.cpp, src/initsysvar.hpp: Add !CPU system variable * src/pro/write_png.pro: Fix /ORDER bug * src/pro/map_clip_set.pro: Initial import 2006-08-25 m_schellens * gdl.kdevses, src/basic_pro.cpp: CLOSE,/ALL now also frees LUNs 2006-08-25 jomoga * config.h.in: Preliminary support for map projections 2006-08-24 jomoga * INSTALL, NEWS, src/libinit_jmg.cpp, src/plotting.cpp, src/plotting.hpp, configure, configure.in: Preliminary support for map projections 2006-08-23 jomoga * src/pro/last_item.pro, src/pro/value_locate.pro: Inital import * NEWS: Support for XDR I/O & POLY_2D * src/basegdl.cpp, src/basegdl.hpp, src/basic_pro.cpp, src/datatypes.hpp, src/default_io.cpp, src/dstructgdl.hpp, src/gdljournal.cpp, src/io.cpp, src/io.hpp, src/print.cpp, src/specializations.hpp, src/assocdata.cpp: Support for XDR I/O 2006-08-06 m_schellens * src/extrat.cpp: Made empty _EXTRA values undefined * src/arrayindex.hpp, gdl.kdevses: made [*] to return one-dim index (not preserve indices) 2006-08-03 jomoga * src/math_fun_jmg.cpp: Fix perfect square test for coeff array 2006-08-02 jomoga * src/initsysvar.cpp, src/initsysvar.hpp: Add !MAP system variable 2006-07-30 m_schellens * gdl.kdevses, src/extrat.cpp, testsuite/test_suite.pro: Fixed _EXTRA with undefined variable bug 2006-07-29 m_schellens * src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/arrayindex.cpp, src/gdlc.tree.g: Fixed indexing with loop variable bug 2006-07-27 jomoga * src/math_fun_jmg.cpp: Fix SQRT cast bug 2006-07-18 jomoga * src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: Add POLY_2D function 2006-07-08 m_schellens * src/basic_fun.cpp: Fixed N_PARAMS for member subroutines * src/basic_fun.cpp: Allow structs for KEYWORD_SET (always 1) 2006-06-24 m_schellens * gdl.kdevses, src/GDLTreeParser.hpp, src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/file.cpp, src/gdlc.tree.g: Indexing bug (arg[0,0]) and STRUCT_ASSIGN bug 2006-06-20 jomoga * src/basic_fun.cpp, src/libinit_mes.cpp, src/pro/strsplit.pro: Add REGEX keyword support to strtok * src/basic_fun_cl.cpp: Fix gsl_exp bug (1509339) 2006-06-16 m_schellens * gdl.kdevses, src/GDLParser.cpp, src/gdlc.g: Fixed named struct syntax bug 2006-06-14 m_schellens * src/datatypes.hpp, src/dnode.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp: fixed binary operator results if one operand is an one element array 2006-06-13 m_schellens * src/basic_op.cpp, src/specializations.hpp: Allow EQ and NE for ptr and objects * INSTALL, PYTHON.txt, README: Corrected spelling (pyhton -> python) * src/basic_fun.cpp, src/libinit.cpp, NEWS, gdl.kdevelop, gdl.kdevses: INTEGER Keyword for TOTAL (by Erin Sheldon) 2006-06-06 m_schellens * src/gdlc.g, src/GDLLexer.cpp: Fixed U suffix for decimal constants 2006-06-04 m_schellens * gdl.kdevses, src/convert2.cpp: Suppress warning for conversion of null string 2006-05-31 m_schellens * README, gdl.kdevses: Notification for the need of development packages * src/ofmt.cpp: Correct zero padding for I format 2006-05-22 m_schellens * configure, configure.in, gdl.kdevses: Make configure look in additional direcotries fro HDF(4/5) includes and libs 2006-05-19 m_schellens * src/basic_pro.cpp: Raise error for XDR keyword for OPEN procedures * src/plotting.cpp: Fixed XYOUTS [XY]LOG keyword * NEWS, gdl.kdevelop, gdl.kdevses, src/plotting.cpp: sync 2006-05-17 retsil * src/pro/dicom/gdlffdicom__assoc__define.pro, src/pro/dicom/gdlffdicom__define.pro, src/pro/dicom/gdlffdicom__dictionary.pro, src/pro/dicom/gdlffdicom_copy_lun.pro, src/pro/dicom/gdlffdicom_date.pro, src/pro/dicom/gdlffdicom_time.pro, src/pro/dicom/gdlffdicom_trim.pro: Adding code for the GDLffDICOM class. This class reads and writes to DICOM files. 2006-05-16 m_schellens * README, src/initsysvar.cpp: Added GDLffDICOM object * gdl.kdevses, src/gdlgstream.cpp, src/gdlgstream.hpp, src/plotting.cpp, gdl.kdevelop: Joel: fixed \!P.MULTI bug 2006-05-10 m_schellens * src/accessdesc.hpp, configure, Makefile.in, aclocal.m4: removed rank restrictions for struct assignment * src/Makefile.in, src/antlr/Makefile.in, src/gdl.cpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/plotting.cpp, testsuite/test_suite.pro, configure.in, gdl.kdevelop, ChangeLog, HACKING, INSTALL, NEWS, README, configure: syncing CVS with release 2006-04-05 jomoga * src/gdlgstream.cpp, src/gdlgstream.hpp: Fix color='ff'x bug * src/plotting.cpp: Fix oplot P.MULTI bug/Fix color='ff'x bug 2006-03-31 m_schellens * many changes (ChangeLog incomplete due to CVS server problems) * please see NEWS for an overview GDL 0.8.11: 2005-10-17 m_schellens * AUTHORS, HACKING, INSTALL, NEWS, README, src/basic_pro.cpp: update 2005-10-14 m_schellens * src/arrayindex.hpp: sync 2005-10-13 m_schellens * gdl.kdevelop, src/basic_pro.cpp, src/gdljournal.cpp, src/io.cpp, src/io.hpp: Added F77_UNFORMATTED error message (OPEN) 2005-10-12 m_schellens * src/assocdata.cpp, src/assocdata.hpp, src/envt.hpp, src/arrayindex.hpp: Some bugfixes 2005-10-11 m_schellens * gdl.kdevelop, src/FMTIn.cpp, src/FMTLexer.cpp, src/FMTOut.cpp, src/FMTParser.cpp, src/GDLInterpreter.cpp, src/Makefile.am, src/Makefile.in, src/datatypes.cpp, src/dcompiler.cpp, src/format.g, src/format.in.g, src/format.out.g, src/gdlc.i.g: Fixed: some shadowed variables 2005-10-07 medericboquien * NEWS: Adding GAUSS_PDF and GAUSS_CVF functions 2005-10-05 m_schellens * src/GDLInterpreter.cpp, src/Makefile.in, src/arrayindexlistt.hpp, src/datatypes.hpp, src/dcompiler.cpp, src/fftw.cpp, src/libinit_jmg.cpp, src/math_fun.cpp, config.h.in, configure, configure.in, gdl.kdevelop: Fixed array indexing error 2005-10-04 jomoga * NEWS, configure.in, src/Makefile.in, src/libinit_jmg.cpp: Support for FFTW * src/fftw.cpp, src/fftw.hpp: Initial import 2005-10-03 m_schellens * src/basic_fun_cl.cpp, src/libinit.cpp, src/math_fun.cpp, src/math_fun.hpp, src/new.cpp, src/new.hpp: Added GAUSS_PDF and GAUSS_CVF functions. More precise SYSTIME function 2005-09-30 m_schellens * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun.hpp, src/datatypes.cpp, src/datatypes.hpp, src/libinit.cpp: Added ROTATE function * src/basic_fun.cpp, src/ofmt.hpp: fixed F FORMAT bug * src/arrayindex.cpp, src/arrayindexlistt.hpp, NEWS: fixed array index bug 2005-09-29 m_schellens * src/basic_fun.cpp, src/basic_fun.hpp, src/gdlc.i.g, src/libinit.cpp: Added CREATE_STRUCT function * src/arrayindex.cpp, src/arrayindex.hpp, src/arrayindexlistt.hpp: array index bugfix 2005-09-28 jomoga * src/plotting.cpp: Fix plvpor bug in CONTOUR 2005-09-27 m_schellens * src/arrayindex.cpp: add file * src/GDLTreeParser.hpp, src/Makefile.am, src/Makefile.in, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/dnode.hpp, src/dstructgdl.cpp, src/gdlc.i.g, src/gdlc.tree.g, src/GDLInterpreter.cpp, src/GDLTreeParser.cpp: scalar array index optimization 2005-09-26 m_schellens * Makefile.in, aclocal.m4, configure, gdl.kdevses, src/GDLInterpreter.hpp, src/Makefile.in, src/antlr/Makefile.in, src/gdlc.i.g, src/plotting.cpp: Fixed recognition of PLOT,/[XY]LOG keywords 2005-09-24 m_schellens * Makefile.in, aclocal.m4, config.h.in, configure, configure.in, gdl.kdevelop, gdl.kdevses, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/Makefile.in, src/antlr/Makefile.in, src/dinterpreter.cpp, src/extrat.hpp, src/gdlc.i.g, src/initsysvar.cpp: Added DIR system variable 2005-09-22 m_schellens * src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/Makefile.am, src/Makefile.in, src/accessdesc.hpp, src/antlr/Makefile.in, src/arrayindex.hpp, src/arrayindexlistt.hpp, src/assocdata.cpp, src/datatypes.cpp, src/dnode.cpp, src/dstructgdl.cpp, src/gdlc.tree.g, src/typedefs.hpp, Makefile.in, aclocal.m4, configure, gdl.kdevelop: array index optimization 2005-09-20 m_schellens * gdl.kdevses, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/gdlc.tree.g, src/math_fun.cpp, Makefile.in, aclocal.m4, configure: optimizations * Makefile.in, aclocal.m4, configure, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/dimension.hpp: array index optimization 2005-09-19 m_schellens * src/dimension.hpp: dimension optimization * configure, configure.in, src/envt.cpp, src/envt.hpp, src/extrat.cpp: Subroutine call optimization (EnvT) 2005-09-18 m_schellens * src/dinterpreter.cpp, src/gdl.cpp: Make GDL handle non-tty input. * Makefile.in, aclocal.m4, configure, gdl.kdevelop, gdl.kdevses, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/basic_fun.cpp, src/basic_pro.cpp, src/dcompiler.cpp, src/dcompiler.hpp, src/dinterpreter.cpp, src/dnode.cpp, src/dnode.hpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/extrat.cpp, src/extrat.hpp, src/gdl.cpp, src/gdlc.i.g, src/gdlc.tree.g: EnvT optimization. Startup file is not prepended with users home anymore. 2005-09-16 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basegdl.cpp, src/basegdl.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dinterpreter.cpp, src/dpro.cpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/libinit.cpp, src/math_fun.cpp: Fixed EXIT_STATUS for SPAWN procedure 2005-09-14 m_schellens * src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/basic_op.cpp, src/datatypes.cpp, src/gdlc.tree.g, src/plotting.cpp, src/pro/read_pict.pro: Fixed scalar +(operator) array bug 2005-09-13 m_schellens * src/datatypes.cpp: Fixed problem with New( dim, BaseGDL::INIT) 2005-09-12 m_schellens * configure, src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/libinit.cpp, src/new.cpp, src/new.hpp, Makefile.in, NEWS, aclocal.m4: Fixed bug in COMPLEX(arr,scalar) 2005-09-11 m_schellens * Makefile.in, aclocal.m4, configure, gdl.kdevses, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/dnode.cpp, src/dnode.hpp, src/gdlc.tree.g: Fixed ^ operator bug. 2005-09-09 jomoga * src/devicex.hpp: Fix closed window core dump * src/math_fun_jmg.cpp: Fix ambiguous sqrt call in radon 2005-09-09 m_schellens * src/GDLInterpreter.cpp, src/arrayindex.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/gdlc.i.g: AssignAt optimization * Makefile.in, aclocal.m4, configure, src/GDLInterpreter.cpp, src/GDLLexer.cpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/basegdl.cpp, src/basegdl.hpp, src/datatypes.cpp, src/datatypes.hpp, src/dnode.cpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/libinit.cpp, src/math_fun.cpp, src/pro/test_suite.pro: Index optimization 2005-09-08 m_schellens * gdl.kdevelop, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/arrayindex.hpp, src/dinterpreter.cpp, src/dnode.cpp, src/dnode.hpp, src/gdlc.tree.g: comp_assign_expr (+=,*=,...) fix. 2005-09-07 m_schellens * configure, src/GDLInterpreter.cpp, src/datatypes.cpp, src/gdlc.i.g, src/pro/test_suite.pro: NewIx... return statement fix * src/antlr/Makefile.in, Makefile.in, aclocal.m4, configure, configure.in, gdl.kdevelop, gdl.kdevses, src/Makefile.in, src/arrayindex.hpp, src/basic_op.cpp, src/datatypes.cpp: Index optimization * src/GDLInterpreter.cpp, src/accessdesc.hpp, src/arrayindex.hpp, src/assocdata.cpp, src/assocdata.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/gdlc.i.g, src/typedefs.hpp: Indexing optimization. 2005-09-05 m_schellens * NEWS, src/basic_fun.cpp, src/basic_fun.hpp, src/libinit.cpp: STRCMP function * NEWS, src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/basic_op.cpp, src/datatypes.cpp, src/dnode.cpp, src/dnode.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/specializations.hpp: unary minus optimization for constants 2005-09-01 m_schellens * Makefile.in, aclocal.m4, configure, gdl.kdevses, src/GDLInterpreter.cpp, src/GDLParser.cpp, src/GDLTreeParser.cpp, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dnode.cpp, src/dstructgdl.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g: Operator optimizations. 2005-08-30 jomoga * src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_fun_jmg.hpp: Add support for RADON function * src/initsysvar.cpp: Add MAP system variable 2005-08-25 m_schellens * gdl.kdevelop, gdl.kdevses, src/basegdl.cpp, src/basegdl.hpp, src/basic_op.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dnode.cpp: Optimize ^ r expressions * src/arrayindex.hpp: array index optimization 2005-08-24 m_schellens * src/basegdl.hpp, src/basic_op.cpp, src/dnode.cpp: Significant speedup for complex^int 2005-08-23 m_schellens * Makefile.in, aclocal.m4, configure, gdl.kdevelop, gdl.kdevses, src/arrayindex.hpp: Fixed array index memory leak * README, src/basic_op.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dnode.cpp, src/dnode.hpp: Avoid copying in r_expr 2005-08-22 m_schellens * src/Makefile.in, src/antlr/Makefile.in, src/dnode.cpp, src/dnode.hpp, src/gdlc.i.g: Avoid copying in r_expr 2005-08-19 m_schellens * src/basic_op.cpp, src/dinterpreter.cpp, src/dnode.cpp, gdl.kdevses: Cleaned up right expression evaluation 2005-08-18 m_schellens * src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/basic_fun.cpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/dnode.cpp, src/dnode.hpp, src/dpro.hpp, src/gdlc.i.g: Introduced heterogenous AST 2005-08-17 m_schellens * src/basic_fun.cpp, src/dinterpreter.cpp, src/dnode.cpp, src/dnode.hpp, src/gdlc.tree.g, gdl.kdevelop: transfer files 2005-08-16 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g, src/gdlc.i.g, src/pro/test_suite.pro, configure: Fixed || operator bug * configure, configure.in: FC4 complicance for netCDF HDF4 and Magick * INSTALL, Makefile.in, NEWS, README, aclocal.m4, configure, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/Makefile.in, src/antlr/Makefile.in, src/gdlc.g, src/print_tree.cpp: Fixed LOG_NEG (~) operator syntax bug. 2005-08-14 m_schellens * src/arrayindex.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, gdl.kdevelop, gdl.kdevses, src/basegdl.cpp, src/basegdl.hpp, src/dstructgdl.hpp, src/specializations.hpp: WHERE optimization 2005-08-11 m_schellens * src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/datatypes.cpp, Makefile.in, aclocal.m4, configure, gdl.kdevses, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/accessdesc.hpp, src/dcompiler.cpp, src/dcompiler.hpp, src/dnode.cpp, src/dnode.hpp, src/gdlc.i.g, src/gdlc.tree.g: Array index optimization 2005-08-09 m_schellens * src/arrayindex.hpp, src/datatypes.cpp, src/dimension.hpp, src/dstructgdl.cpp, src/initct.cpp: Optimization for InsAt (b[0]=a) * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/Makefile.in, src/antlr/Makefile.in, src/arrayindex.hpp, src/datatypes.cpp, src/dcompiler.cpp, src/gdlc.i.g, configure, Makefile.in, aclocal.m4: Avoid extra copying in replace assignment 2005-08-07 m_schellens * src/antlr/Makefile.in, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/Makefile.in, src/basic_op.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, configure.in, gdl.kdevses, configure, Makefile.in, aclocal.m4: Avoid additional copy in replace assignment 2005-08-05 m_schellens * src/plotting.cpp, src/dpro.cpp, gdl.kdevses: Fixed AXIS bug 2005-08-03 jomoga * src/plotting.cpp: Fix plot/oplot/erase bugs 2005-07-29 m_schellens * src/dpro.cpp, src/gdlc.i.g, gdl.kdevses, src/GDLInterpreter.cpp: Fixed bug which made GDL crash on empty subroutines 2005-07-27 jomoga * src/libinit.cpp, src/plotting.hpp, src/plotting.cpp: Preliminary version of CONTOUR 2005-07-26 m_schellens * src/format.g, src/plotting.cpp: Fixed PLOT/OPLOT no erase bug. 2005-07-25 jomoga * src/devicex.hpp: Fix memory leak in plimage_gdl 2005-07-25 m_schellens * src/pro/regression-total.pro, src/FMTLexer.cpp, src/format.g: Fixed H format code. * src/pro/dist.pro, src/pro/kurtosis.pro, src/pro/mean.pro, src/pro/meanabsdev.pro, src/pro/moment.pro, src/pro/skewness.pro, src/pro/stddev.pro, src/pro/strsplit.pro, src/pro/variance.pro, NEWS: NAN keyword for MOMENT related functions. * src/Makefile.in, src/antlr/Makefile.in, src/basic_fun.cpp, src/basic_pro.cpp, src/basic_pro.hpp, src/dimension.hpp, src/gdljournal.cpp, src/initsysvar.cpp, configure, Makefile.in, aclocal.m4: Added keywords: NAN for TOTAL, STRUCTURES fro HELP. Small correction for JOUNRAL. 2005-07-21 jomoga * src/plotting.cpp: Fix xrange plot bug 2005-07-14 m_schellens * src/default_io.cpp, src/io.hpp, gdl.kdevelop, gdl.kdevses: EOF function: EOF status was not reset properly. Fixed. 2005-07-12 m_schellens * src/pro/primes.pro: file removal * README: Update HDF5 and netCDF problems. * src/hdf5_fun.cpp, gdl.kdevelop, gdl.kdevses: Compliance with HDF 1.6.4 2005-07-12 c_lee * src/pro/poly.pro: POLY function to calculate polynomials 2005-07-10 m_schellens * src/gsl_fun.cpp, gdl.kdevelop, gdl.kdevses: Fixed INTERPOLATE bug. * src/Makefile.in, src/antlr/Makefile.in, src/basic_pro.cpp, gdl.kdevelop, gdl.kdevses, configure, Makefile.in, aclocal.m4: Fixed HELP,/LIB: number of printed functions. GDL 0.8.10: 2005-07-08 m_schellens * INSTALL: INSTALL update * src/basic_op.cpp: POW optimization 2005-07-07 m_schellens * src/basic_op.cpp: Changed raise to power calculation for integral types * src/antlr/Makefile.in, src/basic_op.cpp, src/convert2.cpp, src/default_io.cpp, src/gdlc.i.g, src/initsysvar.cpp, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/Makefile.am, src/Makefile.in, configure.in, configure, INSTALL, Makefile.in, PYTHON.txt, README, aclocal.m4: Fixed inconistency with return type of ^ operator for integer types 2005-07-06 m_schellens * src/basic_fun_jmg.cpp, src/dstructdesc.hpp: VALUE keyword for MAKE_ARRAY. 2005-07-05 m_schellens * src/basic_fun_cl.cpp: Extensions to LEGENDRE. Fixed memory leaks 2005-07-03 m_schellens * gdl.kdevelop, gdl.kdevses, src/ncdf_var_cl.cpp: remove some diagnostic prints. 2005-07-02 m_schellens * src/libinit_cl.cpp, src/magick_cl.cpp: 4 parameters for NCDF_ATTPUT. Fixed memory leak in magick_writeColorTable * src/antlr/Makefile.in, src/plotting.cpp, src/pythongdl.cpp, src/Makefile.in, src/magick_cl.cpp, src/ofmt.hpp, gdl.kdevelop, gdl.kdevses, configure, Makefile.in, aclocal.m4: avoid linker error under OS X 2005-07-01 jomoga * src/gsl_fun.cpp: Fix memory leak in INTERPOLATE 2005-07-01 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/dinterpreter.cpp, src/gdlc.i.g, gdl.kdevses: Code refactorization * src/convert2.cpp: double to string conversion * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/arrayindex.hpp, src/dinterpreter.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/includefirst.hpp, src/pro/test_suite.pro, NEWS, config.h.in, configure, configure.in: stride index support ([n:n:n]) 2005-06-29 jomoga * src/plotting.cpp: Support for YNOZERO 2005-06-29 m_schellens * src/gdlc.i.g, src/GDLInterpreter.cpp, src/arrayindex.hpp, src/datatypes.cpp, src/dnode.cpp, src/dnode.hpp, src/dstructgdl.cpp, NEWS, gdl.kdevses: move ConvertAST to source file. Fixed arrayindex list BuildIx memory leak. 2005-06-28 jomoga * src/devicex.hpp, src/devicez.hpp, src/gdlzstream.cpp, src/gdlzstream.hpp, src/graphics.hpp, src/plotting.cpp, src/plotting.hpp: Support for additional plotting keywords and COLORBAR * src/libinit.cpp: Added AXIS,ERASE routines * src/gsl_fun.cpp: interpolation scalar bug fix 2005-06-28 m_schellens * src/print.cpp, src/print_tree.cpp, src/print_tree.hpp: PRINT, correction. * src/GDLInterpreter.hpp, src/GDLTreeParser.cpp, src/arrayindex.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dcompiler.cpp, src/dcompiler.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/dnode.cpp, src/dnode.hpp, src/dpro.cpp, src/dpro.hpp, src/dstructgdl.hpp, src/envt.cpp, src/envt.hpp, src/gdlc.i.g, src/gdlc.tree.g, src/gdlexception.cpp, src/gdlexception.hpp, src/objects.cpp, src/GDLInterpreter.cpp: ProgNode type for interpreter. 2005-06-21 m_schellens * src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLTreeParser.cpp, src/Makefile.in, src/antlr/Makefile.in, src/dinterpreter.cpp, src/gdlc.g, configure.in, Makefile.in, aclocal.m4, configure: Make .RUN handle files without subroutine. 2005-06-20 m_schellens * src/dinterpreter.cpp, src/pythongdl.cpp, configure.in, gdl.kdevelop, gdl.kdevses, configure, Makefile.in, README, aclocal.m4: python module 2005-06-17 m_schellens * src/dinterpreter.cpp, src/dinterpreter.hpp, src/envt.cpp, src/print.cpp, src/pythongdl.cpp: python module 2005-06-16 m_schellens * src/antlr/Makefile.in, src/datatypes.hpp, src/Makefile.in: GCC 4.0 compliancy * src/datatypes.cpp, src/gdlc.tree.g, src/gdlexception.hpp, src/gdlpython.cpp, src/gdlpython.hpp, src/pythongdl.cpp, src/topython.cpp: python module 2005-06-15 m_schellens * src/Makefile.am, src/Makefile.in, src/antlr/Makefile.am, src/antlr/Makefile.in, src/cformat.g, src/dpro.hpp, src/format.g, src/format.in.g, src/format.out.g, src/gdl.cpp, src/gdlc.i.g, src/gdljournal.cpp, src/gdlpython.cpp, src/includefirst.hpp, src/print_tree.cpp, src/pythongdl.cpp, src/sigfpehandler.hpp, src/CFMTLexer.cpp, src/FMTIn.cpp, src/FMTIn.hpp, src/FMTLexer.cpp, src/FMTLexer.hpp, src/FMTOut.cpp, src/FMTOut.hpp, src/FMTParser.cpp, src/FMTParser.hpp, src/GDLInterpreter.cpp, configure.in, gdl.kdevses, ltmain.sh, Makefile.in, config.guess, config.sub, configure: python module 2005-06-13 m_schellens * src/dinterpreter.cpp: .R equivalent to .RUN 2005-06-10 m_schellens * src/gdlpython.cpp, gdl.kdevelop, gdl.kdevses, Doxyfile, src/envt.cpp, src/extrat.cpp, src/file.cpp, src/format.in.g, src/gdl.cpp, src/gdleventhandler.cpp, src/gdlexception.cpp, src/gdlgstream.cpp, src/gdlpsstream.cpp, src/gdlwidget.cpp, src/gdlwinstream.cpp, src/gdlxstream.cpp, src/gdlzstream.cpp, src/getfmtast.cpp, src/graphics.cpp, src/gsl_fun.cpp, src/hdf5_fun.cpp, src/hdf_fun.cpp, src/hdf_pro.cpp, src/image.cpp, src/includefirst.hpp, src/initct.cpp, src/initsysvar.cpp, src/io.cpp, src/libinit.cpp, src/libinit_cl.cpp, src/libinit_jmg.cpp, src/libinit_mes.cpp, src/magick_cl.cpp, src/math_fun.cpp, src/math_fun_jmg.cpp, src/math_utl.cpp, src/ncdf_att_cl.cpp, src/ncdf_cl.cpp, src/ncdf_dim_cl.cpp, src/ncdf_var_cl.cpp, src/objects.cpp, src/plotting.cpp, src/print.cpp, src/read.cpp, src/sigfpehandler.cpp, src/str.cpp, src/typedefs.hpp, src/typetraits.cpp, src/widget.cpp, src/FMTIn.cpp, src/FMTIn.hpp, src/assocdata.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun_cl.cpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/basic_pro_jmg.cpp, src/convert2.cpp, src/datatypes.cpp, src/dcommon.cpp, src/dcompiler.cpp, src/dinterpreter.cpp, src/dnode.cpp, src/dpro.cpp, src/dpro.hpp, src/dstructdesc.cpp, src/dstructgdl.cpp, src/dvar.cpp, configure.in, config.h.in, configure: python module 2005-06-06 m_schellens * src/FMTIn.cpp, src/FMTIn.hpp, src/format.in.g: Fixed READS 'z' format code bug. 2005-06-03 m_schellens * src/basic_fun.cpp, src/basic_fun_cl.cpp, src/gdlc.i.g, src/GDLInterpreter.cpp, configure: Fixed return from FOR bug. 2005-06-01 m_schellens * src/devicex.hpp, src/envt.cpp, src/envt.hpp, src/graphics.hpp, src/libinit.cpp, src/plotting.cpp, src/plotting.hpp: DEVICE,GET_DECOMPOSED. Consistent using CHARSIZE as float (instead of double). 2005-05-31 m_schellens * src/pro/loadct.pro, src/devicex.hpp, src/graphics.cpp, src/graphics.hpp, src/image.cpp, src/libinit_jmg.cpp: common block COLORS for LOADCT * src/image.cpp, config.h.in, configure, configure.in: remove wxWidgets from configure script. * src/pro/lmgr.pro, src/Makefile.am, src/Makefile.in, src/gdlwidget.cpp, src/gdlwidget.hpp, src/graphics.cpp, src/graphics.hpp, src/image.cpp, src/libinit_jmg.cpp, src/widget.cpp, configure.in, gdl.kdevses, config.h.in, configure: LMGR function. 2005-05-24 jomoga * src/gsl_fun.cpp, src/gsl_fun.hpp, src/libinit_jmg.cpp: Initial version of INTERPOLATE 2005-05-12 m_schellens * src/default_io.cpp, src/ifmt.cpp, src/io.hpp, README: Fixed input and eof detection. 2005-05-10 m_schellens * src/devicex.hpp: Second parameter for TV. 2005-05-09 m_schellens * src/arrayindex.hpp, src/envt.cpp, src/plotting.cpp: Removed BACKGROUND keyword check from XYOUTS. * src/accessdesc.hpp, src/arrayindex.hpp, src/datatypes.cpp, src/devicex.hpp, src/dstructgdl.cpp: Set AllIxT to valarray. * src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/gdlc.g: Allow BREAK, CONTINUE as identifiers. 2005-04-30 c_lee * src/plotting.cpp, src/plotting.hpp: more refactoring (xyouts) * src/plotting.cpp, src/plotting.hpp: refactored to common plot subroutines (crange, type) * src/plotting.cpp, src/plotting.hpp: refactored to common plot subroutines (color, background, symsize,psym, line) * src/datatypes.hpp: include cassert 2005-04-28 jomoga * src/gdlxstream.hpp, src/devicex.hpp: TV writes to off-screen window 2005-04-28 m_schellens * NEWS, src/gdlc.i.g, src/math_fun.cpp, src/pro/appleman.pro, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/accessdesc.hpp, src/arrayindex.hpp, src/basegdl.hpp, src/basic_fun_cl.cpp, src/basic_op.cpp, src/convert2.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, ChangeLog, INSTALL, README: Optimization for complex (pow, abs). Non-copy constants 2005-04-22 m_schellens * src/basic_pro.cpp, src/datatypes.cpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/gdl.cpp, src/math_fun_jmg.cpp, src/pro/test_suite.pro, ChangeLog, NEWS: OS X compilance. GDL 0.8.9: 2005-04-21 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/dcompiler.cpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/dpro.cpp, src/dpro.hpp, src/gdlc.i.g, src/gdleventhandler.cpp, src/pro/test_suite.pro, ChangeLog: Added .RUN command. 2005-04-20 jomoga * src/libinit_jmg.cpp, src/basic_pro_jmg.hpp, src/basic_pro_jmg.cpp: Added WAIT procedure 2005-04-20 m_schellens * src/dcompiler.cpp, src/dcompiler.hpp, src/dpro.hpp, src/gdlc.tree.g, src/GDLTreeParser.cpp: correct common blocks and gotos for command line. 2005-04-19 m_schellens * src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dcompiler.cpp, src/devicez.hpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/dpro.hpp, src/gdl.cpp, src/gdlc.g, src/gdlc.tree.g, src/gdlzstream.hpp, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp: Accept main programs. * src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlzstream.hpp: plplot mem driver eop() workaround. 2005-04-18 m_schellens * src/devicex.hpp, src/basic_op.cpp, src/deviceps.hpp, src/devicewin.hpp, src/devicez.hpp, src/graphics.hpp, src/image.cpp, src/libinit.cpp, src/plotting.cpp, src/plotting.hpp, src/sigfpehandler.cpp, ChangeLog: Fixed MOD 0 bug. 2005-04-15 m_schellens * src/devicez.hpp, gdl.kdevses: Fixed SetResolution bug. 2005-04-14 m_schellens * src/devicez.hpp, src/image.cpp: Fixed TV for z-buffer device. * src/devicez.hpp, src/Makefile.in, src/deviceps.hpp, src/devicex.hpp, src/gdlzstream.cpp, src/gdlzstream.hpp, src/graphics.cpp, src/graphics.hpp, src/image.cpp, src/libinit.cpp, src/plotting.cpp, src/Makefile.am: Added z-buffer device. 2005-04-13 m_schellens * src/devicex.hpp, src/graphics.hpp, src/libinit.cpp, src/plotting.cpp: DECOMPOSED keyword for DEVICE. * src/gstream.hpp, src/gdlgstream.cpp: Fix for multiple plots in one window. 2005-04-12 m_schellens * src/GDLInterpreter.cpp, src/gdlc.i.g: Line number output for interrupts (cntrl-c). 2005-04-11 m_schellens * src/pro/test_suite.pro, src/deviceps.hpp, src/devicewin.hpp, src/gdlc.i.g, src/gdlgstream.cpp, src/gdlgstream.hpp, src/plotting.cpp, src/GDLInterpreter.cpp: Fixed OPLOT, PLOTS for /DEVICE, /NORMAL. Code cleanup. 2005-04-09 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdlc.i.g: Avoid copying for indexed expressions. 2005-04-07 m_schellens * src/FMTOut.cpp, src/FMTParser.cpp, src/format.g, src/format.out.g: Fixed format-code 'x' bug. 2005-04-06 m_schellens * ChangeLog, src/image.cpp: Proper multi-plot handling for TV. 2005-04-05 jomoga * src/image.cpp: Compatible with PLPLOT-5.5.0 2005-04-05 m_schellens * src/basic_pro.cpp, src/libinit.cpp, ChangeLog: NTOHL, NTOHS, HTONL, HTONS keywords to BYTEORDER. 2005-04-04 m_schellens * src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.hpp, src/libinit.cpp, src/specializations.hpp: NAN keyword for MAX, MIN, BYTSCL. SUBSCRIPT_MIN/MAX for MAX/MIN. 2005-04-01 m_schellens * src/dcompiler.cpp: Fix: Allowed x=x(0) for a function x (defined in x.pro). 2005-03-31 m_schellens * src/dcompiler.cpp: Fix: Allowed x=x(0) for a function x. * src/image.cpp: Removed debug output. * src/GDLInterpreter.cpp, src/basic_fun_jmg.cpp, src/dcompiler.cpp, src/gdlc.tree.g, src/image.cpp: Allowed x=x(0) for a function x (defined in x.pro). 2005-03-30 m_schellens * gdl.kdevses, src/image.cpp: Fixed TV bug. 2005-03-29 m_schellens * gdl.kdevses, src/gdlgstream.cpp, src/plotting.cpp: plplot 5.5.0 compatibility. 2005-03-24 jomoga * src/image.cpp: Fix orientation bug in TVRD 2005-03-24 m_schellens * src/devicex.hpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/plotting.cpp: Constant charsize for graphics. 2005-03-23 jomoga * src/image.cpp: Fix orientation bug in TV 2005-03-23 m_schellens * src/pro/test_suite.pro, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/gdl.cpp, src/gdlc.i.g, src/gsl_fun.cpp, README: Fixed braced (r)expr bug. 2005-03-22 m_schellens * src/basic_fun.cpp, HACKING, README, gdl.kdevses: ULONARR, LON64ARR, ULON64ARR bugfix. 2005-03-21 jomoga * src/image.hpp, src/image.cpp: Support for TRUE keyword in TV 2005-03-21 c_lee * src/basic_fun_jmg.cpp: CL: update make_array to use TYPE keyword and sorted argument precendence (fixed) * src/basic_fun_jmg.cpp: CL: update make_array to use TYPE keyword and sorted argument precendence 2005-03-19 m_schellens * src/gsl_fun.cpp: Fixed RANDOM bug. 2005-03-18 m_schellens * src/plotting.cpp: PLOT: POSITION keyword. 2005-03-17 m_schellens * src/arrayindex.hpp, src/basic_pro.cpp, src/datatypes.cpp, src/datatypes.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/gdl.cpp, src/libinit.cpp, src/pro/test_suite.pro, configure, configure.in: Fixed assignment bug. * src/basic_fun.cpp: Fixed ASSOC bug. 2005-03-16 jomoga * src/basic_fun_jmg.cpp: Set FLOAT as default for make_array 2005-03-16 m_schellens * src/basic_fun.cpp, src/libinit.cpp: Sorted libFunList and libProList. * src/GDLInterpreter.cpp, src/gdlc.i.g, ChangeLog: Fixed interpreter memory leak. 2005-03-15 m_schellens * src/pro/test_suite.pro, src/GDLInterpreter.cpp, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g: Cleaned up compiler/interpreter. * src/pro/dist.pro, src/pro/tvscl.pro, src/gdlc.tree.g, src/GDLTreeParser.cpp: Add dist.pro and tvscl.pro 2005-03-14 m_schellens * src/pro/test_suite.pro, src/gdlc.tree.g, src/GDLTreeParser.hpp, src/dcompiler.cpp, src/dinterpreter.cpp, src/gdlc.g, src/gdlc.i.g, src/GDLParser.cpp, src/GDLTreeParser.cpp, src/GDLInterpreter.hpp, src/GDLLexer.cpp, src/GDLInterpreter.cpp: Allow assignment for parameters/keywords. 2005-03-13 m_schellens * src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/dcompiler.cpp, src/dinterpreter.cpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/GDLInterpreter.cpp, gdl.kdevses, gdl.kdevelop, src/pro/test_suite.pro, src/dcommon.cpp, src/dcommon.hpp, src/dcompiler.hpp, src/dpro.hpp, src/envt.cpp, src/envt.hpp: maintenance. 2005-03-10 m_schellens * src/pro/test_suite.pro, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basegdl.hpp, src/dnode.hpp, src/gdlc.g, src/gdlc.i.g, src/gdlc.tree.g, src/gdlexception.hpp, src/gdlpython.cpp, src/print_tree.cpp, gdl.kdevses: Allow braced indexed expressions as l-values. Line number info. 2005-03-08 m_schellens * src/basic_fun.hpp, src/basic_fun_jmg.cpp, src/libinit.cpp, src/pro/test_suite.pro, src/GDLInterpreter.cpp, src/basic_fun.cpp, ChangeLog: Added TEMPORARY function. * src/pro/test_suite.pro, src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/basic_fun.cpp, src/datalistt.hpp, src/dstructgdl.hpp, src/envt.hpp, src/gdlc.i.g: Allow library functions as l-functions. Fixed REPLICATE for structs. 2005-03-07 m_schellens * src/pro/test_suite.pro, src/GDLInterpreter.cpp, src/datalistt.hpp, src/envt.hpp, src/gdlc.i.g, src/print.cpp: Return reference variable via library function (/OVERWRITE) now works. * src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_fun.cpp, src/dinterpreter.cpp, src/gdlc.g, src/gdlc.tree.g, src/GDLInterpreter.cpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp: Made RETURN not a reserved word. 2005-03-06 messmer * src/print.cpp: Removed '\n' if the last element to print is a scalar null string (''). * src/basic_fun.cpp: arr was limited to n scalar arguments to specify the array dimension. IDL, however, also allows a single array-valued argument. This little patch should enable now stuff like a = indgen([2,3]) or a =[[1,2],[3,4]] & print, reform(a, [1,4]). 2005-03-03 m_schellens * src/basic_fun.cpp, src/basic_fun.hpp, src/datatypes.cpp, src/libinit.cpp, ChangeLog, HACKING: Add ROUTINE_INFO. 2005-03-01 jomoga * src/libinit_jmg.cpp: Added UNIFORM keyword RANDOMU/RANDOMN 2005-03-01 m_schellens * src/gsl_fun.cpp, ChangeLog: Corrected RANDOMU/N. * src/gsl_fun.cpp: New RANDOMU/N keywords. 2005-02-28 m_schellens * src/dpro.hpp, src/envt.cpp, src/gsl_fun.cpp, src/dpro.cpp: Functionality for warn keywords. * src/gsl_fun.cpp, configure.in, configure: Cosmetic change. 2005-02-27 jomoga * src/libinit_jmg.cpp, src/dinterpreter.cpp, src/dinterpreter.hpp, src/math_fun_jmg.hpp, src/math_fun_jmg.cpp: Support for CHECK_MATH 2005-02-25 c_lee * src/basic_fun_cl.cpp, src/libinit_cl.cpp: adding warnings for IGAMMA unsupported keywords 2005-02-25 m_schellens * src/dpro.cpp, src/dpro.hpp: Added warn keyword list. * src/dcompiler.cpp, src/dcompiler.hpp: Corrected common block handling of compiler. 2005-02-25 jomoga * src/math_fun_jmg.cpp: Support for DOUBLE keyword in MACHAR * src/libinit_jmg.cpp, src/gsl_fun.hpp, src/gsl_fun.cpp: Improved support of RANDOMU, RANDOMN 2005-02-24 m_schellens * src/basic_fun.cpp, TODO: Add all keywords to INDGEN. * src/pro/test_suite.pro, src/dcommon.cpp, src/dcompiler.cpp, src/dcompiler.hpp, src/dinterpreter.cpp, src/dpro.cpp, src/dpro.hpp, src/envt.cpp, src/gdl.cpp, src/libinit_jmg.cpp, src/math_fun_jmg.cpp, src/math_utl.cpp, src/math_utl.hpp, src/objects.cpp, src/str.hpp: Allow multiple common blocks in one subroutine. 2005-02-24 c_lee * src/basic_fun_cl.cpp, src/basic_fun_cl.hpp, src/libinit_cl.cpp: Fixed keywords in IGAMMA and BETA, commented out unsupported keywordsin IGAMMA. added DOUBLE keyword to BETA 2005-02-22 m_schellens * src/pro/factorial.pro, src/pro/swap_endian.pro: Add SWAP_ENDIAN, FACTORIAL * src/math_fun_jmg.cpp, ChangeLog: Update ChangeLog. Some small improvements. * src/math_fun.cpp, src/sigfpehandler.cpp, src/sigfpehandler.hpp, src/Makefile.am, src/Makefile.in, src/basic_fun_cl.cpp, src/basic_op.cpp, src/basic_pro.cpp, src/devicex.hpp, src/gdl.cpp, src/gdlgstream.cpp, src/gdlgstream.hpp, src/gdlxstream.cpp, src/gdlxstream.hpp, src/image.cpp, src/initsysvar.cpp, configure.in, configure: SIGFPE handler. 2005-02-21 jomoga * src/libinit.cpp: Add TYPE keyword to FIX * src/libinit_jmg.cpp: Add TVRD & FINITE * src/basic_fun.cpp: Support for TYPE keyword in FIX * src/math_fun_jmg.hpp, src/math_fun_jmg.cpp: Support for FINITE function * src/image.hpp, src/image.cpp: Support for TVRD 2005-02-18 m_schellens * src/Makefile.in, src/antlr/Makefile.in, src/basic_op.cpp, src/pro/test_suite.pro, configure, Makefile.in, aclocal.m4: Fixed # operator (1D # 2D). 2005-02-17 m_schellens * src/basic_pro.cpp, src/basic_pro.hpp, src/dinterpreter.cpp, src/libinit.cpp, src/topython.cpp, ChangeLog, INSTALL, README, gdl.kdevses: Add SPAWN procedure. 2005-02-15 m_schellens * src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_fun.cpp, src/gdlc.g, src/GDLInterpreter.cpp, README: Allow leading '!' also in struct names. GDL 0.8.8: 2005-02-14 m_schellens * src/GDLInterpreter.cpp, src/GDLInterpreter.hpp, src/GDLInterpreterTokenTypes.hpp, src/GDLInterpreterTokenTypes.txt, src/GDLLexer.cpp, src/GDLLexer.hpp, src/GDLParser.cpp, src/GDLParser.hpp, src/GDLTokenTypes.hpp, src/GDLTokenTypes.txt, src/GDLTreeParser.cpp, src/GDLTreeParser.hpp, src/GDLTreeParserTokenTypes.hpp, src/GDLTreeParserTokenTypes.txt, src/basic_fun.cpp, src/default_io.cpp, src/gdlc.g, src/gdlc.tree.g, ChangeLog, README: Widen rules for struct tag names to allow a leading '!'. * src/GDLLexer.cpp, src/basegdl.cpp, src/basegdl.hpp, src/basic_fun.cpp, src/basic_fun.hpp, src/basic_pro.cpp, src/basic_pro.hpp, src/datatypes.cpp, src/datatypes.hpp, src/default_io.cpp, src/dinterpreter.cpp, src/gdlc.g, src/libinit_mes.cpp, src/ofmt.hpp, ChangeLog, README: Include subroutines by Peter Messmer. 2005-02-12 jomoga * src/image.cpp, src/libinit_jmg.cpp: X,Y support for TV 2005-02-10 m_schellens * ChangeLog, gdl.kdevses: ChangeLog update. * src/GDLInterpreter.hpp, src/GDLLexer.cpp, src/dinterpreter.cpp, src/gdlc.g, src/gdlc.i.g, src/str.cpp, src/str.hpp: made @ honor !PATH * src/Makefile.in, src/antlr/Makefile.in, src/default_io.cpp, src/dstructdesc.cpp, src/dstructdesc.hpp, src/dstructgdl.cpp, src/dstructgdl.hpp, src/extrat.cpp, src/gdlc.i.g, src/ifmt.cpp, src/initsysvar.cpp, src/ncdf_att_cl.cpp, src/ofmt.cpp, src/typetraits.cpp, src/typetraits.hpp, src/GDLInterpreter.cpp, configure.in, gdl.kdevses, configure, ChangeLog, Makefile.in, aclocal.m4: Changed handling of unnamed struct descriptors. 2005-02-08 jomoga * src/gsl_fun.hpp, src/gsl_fun.cpp: Improved FFT routine; OMIN,OMAX keyword support HISTOGRAM 2005-02-08 m_schellens * src/plotting.cpp: Fixed TVLCT bug. 2005-02-03 m_schellens * src/antlr/Makefile.in, src/Makefile.in, src/basic_op.cpp, src/convol.cpp, src/convol_inc0.cpp, src/convol_inc1.cpp, src/convol_inc2.cpp, src/datatypes.cpp, src/ofmt.cpp, aclocal.m4, configure, ChangeLog, Makefile.in: g++ 3.4 compliance 2005-01-29 c_lee * src/antlr/Makefile.in, src/Makefile.in, src/libinit.cpp, src/plotting.cpp, aclocal.m4, configure, Makefile.in: Added NOCLIP support to PLOTS/OPLOT. Added XYOUTS command with support for COLOR, ORIENTATION, ALIGNMENT,CHARSIZE,CLIP,DEVICE,DATA,COLOR. Also supports array format for COLOR, ORIENTATION keywords, and X, Y, STRING arguments. Does not support the pseudo line continuation using only 1 argument. 2005-01-26 m_schellens * src/GDLInterpreter.cpp, src/basic_fun.cpp, src/basic_fun.hpp, src/basic_fun_jmg.cpp, src/basic_op.cpp, src/datalistt.hpp, src/datatypes.cpp, src/envt.hpp, src/extrat.cpp, src/gdlc.i.g, src/libinit.cpp, ChangeLog: Fixed OR and AND bug. Fixed lib function /OVERWRITE bug. 2005-01-20 m_schellens * src/basic_fun.hpp, src/basic_fun_jmg.cpp, src/basic_pro.cpp, src/basic_pro.hpp, src/libinit.cpp, src/basic_fun.cpp, ChangeLog: Added SWAP_ENDIAN and BYTEORDER. Fixed /OVERWRITE bug in REFORM. 2005-01-19 m_schellens * src/GDLInterpreter.cpp, src/basic_fun.cpp, src/basic_fun.hpp, src/datatypes.hpp, src/dstructdesc.cpp, src/dstructgdl.cpp, src/gdlc.i.g, src/libinit.cpp, ChangeLog, INSTALL, README: Added OBJ_ISA. Changed struct compatibility checking. 2005-01-18 m_schellens * src/basic_fun.cpp, src/basic_fun.hpp, src/dstructdesc.hpp, src/libinit.cpp: Added OBJ_CLASS function. 2005-01-17 m_schellens * src/GDLTreeParser.cpp, src/basic_op.cpp, src/default_io.cpp, src/gdlc.tree.g, src/libinit.cpp, src/plotting.cpp: fixed bug concerning braced variables passed by reference; added PLOTS procedure (2D only) 2005-01-14 m_schellens * src/plotting.cpp, src/libinit_cl.cpp, gdl.kdevses: re-insert JOURNAL into lib procedure list, removed diagnostic message in OPLOT 2004-12-14 m_schellens * src/basic_fun_cl.cpp: small corrections. * src/basic_fun_cl.cpp, src/basic_fun_cl.hpp, src/initsysvar.cpp, src/initsysvar.hpp, src/libinit_cl.cpp, src/plotting.cpp, ChangeLog: added LEGENDRE, IGAMMA, LNGAMMA and BETA functions from cl 2004-12-09 m_schellens * ALL FILES Initial import. gdl-0.9.9/HACKING000066400000000000000000000340541340051421000132620ustar00rootroot00000000000000GDL HACKING HOWTO ================= A NOTE ON EXCEPTION SAVE PROGRAMMING ==================================== Exception save programming takes into account, that in C++ exceptions can be thrown anytime. The purpose of exception save programming is to keep a program always in a consistent state even if an exception occurs. Most often this is about avoiding memory leaks. They occur when a object is allocated on the heap and an exception is thrown. Then the allocated heap memory is never returned. The local pointer to the heap memory is destroyed when the function it was defined in goes out of scope. In GDL this happens always when there is some error in a GDL program, as this errors lead to the throw of an exception. A way to avoid such memory leaks is to define for every such allocated memory a "guard". This is a local object which is destroyed when the function is left. In it's destructor it frees the heap memory of the heap object or more general, it performs a proper cleanup of the newly created object. Of course the guard must be informed when some other entity takes care of the new heap object (e. g. it is returned from a function). GDL provides serveral kinds of such guards: for normal objects Guard<> is used (to set the guarded object free Release() must be called). For array objects (destroyed by "delete[]" instead of "delete") GDL provides the templated ArrayGuard<> class. For objects with a cleanup function (e. g. GSL objects) the use of use GDLGuard is recommended. Please see the source code for examples. As this is not a proper place to discuss exception save programming in detail, here are just some rules of thumb, when this might concern a code contributor: - you need almost always a guard when using (operator) new somwhere in your code - objects returned from Convert2(..., COPY) methods are to be guarded as well - same for objects created with Dup() methods. General: One of the main ideas of this project is to be able to eventually use the huge code base written in IDL. Therefore any extension to GDL should be done with compatibility as the highest priority in mind. Extensions of the language are welcome also, but then the routine names should not collide with IDL routine names. Therefore as a standard, if you want to port a library XXX to GDL with non compatible functions make the (GDL-)names XXX_ROUTINENAME. And if you implement a non IDL routine, bear in mind that some documentation is needed in order to be able to use it. Furthermore please keep in mind that GDL should be able to compile at least under GNU/Linux (GCC), OS X and (soon) windows (MSVC). Therefore the code should be as portable as possible (note that it is not mandatory to make it run on all platforms, just portability should be kept in mind avoiding any obvious obstacles like compiler specific extensions). Extensions can be also done in python. See file PYTHON.txt for details. In the distribution there is an empty file: new.cpp This file is part of the project (will be compiled and linked). It is intended for quick and easy extensions to GDL. Furthermore there is a new.hpp file which is included (#include "new.hpp") in libinit.cpp (see below). If you use these files, you don't need to edit any build system related files for your extension. This hacking guide isn't far from complete yet and intended to be extended. Please send questions. For now just some basic instructions: Base class for all GDL data types is declared in basegdl.hpp. The data structure is declared in datatypes.hpp (all types except structs) and dstructgdl.hpp. For assoc variables in assocdata.hpp. If you want to write a new library function or procedure, look at basic_fun.cpp and basic_pro.cpp for examples. The library functions communicate with the rest via the environment. See envt.hpp for the library function programming interface. Three steps to install a new library subroutine: 1. Write it. Source in new.cpp header in new.hpp (use namespace lib). 2. Make it known to the interpreter: Add (preferable at the bottom) in libinit.cpp: new DLibPro( subroutine name, GDL name, max. number of arguments, keyword list); if the max. number of args is -1 an arbitrary number is allowed (like for the PRINT procedure) (new DLibFunRetNew( subroutine name ...) for functions, new DLibFun( subroutine name ...) for functions which might return an existing value) For the keyword list look at libinit.cpp for examples. Using GSL (the Gnu Scinetific Library) Since 0.9.3: When you write routines utilizing the GSL, all GSL objects allocated with the paricular gsl_..._alloc(...) functions should be guarded, using GSLGuard. Please look in src/gsl_fun.cpp for examples. GDL sets its own error handler for GSL. This way, errors in GSL functions are properly handled and do not crash (via a call to abort()) GDL anymore. The API (from envt.hpp) ======================= implement a new library function: this example function simply returns its number of parameters #include "envt.hpp" namespace lib { BaseGDL* example( EnvT* e) { SizeT nPar = e->NParam(); BaseGDL* result = new DUIntGDL( nPar); return result; } } returns the actual number of paramters passed to a library function minPar is the minimal number of paramters the function needs (if less it throws) SizeT NParam( SizeT minPar = 0); raise an exception from within a library function automatically cares for adding line/column info and the function name. 's' should be set to the 'raw' error message: void Throw( const std::string& s); Within our example function the call would look like: e->Throw( "An error occured."); 'guards' a newly created variable which should be deleted upon library routines exit (normal or on error) elimates the need of auto_ptr void Guard( BaseGDL* toGuard); Eg.: char* tempVal = new DIntGDL( 10); e->Guard( tempVal); Note that all guarded objects are deleted with 'delete', ie. you cannot guard arrays this way (which require 'delete[]', see ArrayGuard<> class). New since GDL 0.9.4: In the rare case that a library function returns an existing variable (as opposed to a new one), it must notify the interprefer about it by calling EnvBaseT::SetPtrToReturnValue( BaseGDL** ptrToRetVal). Such a function must be a declared (in libinit.cpp) as a DLibFun, never as DLibFunRetNew. While any other library function should be declared as DLibFunRetNew. for library functions (keyword must be an exact match) returns the index of keyword k int KeywordIx( const std::string& k); Eg.: static int structureIx = e->KeywordIx( "STRUCTURE"); returns environment data, by value (but that by C++ reference) BaseGDL*& GetKW(SizeT ix) { return env[ix];} Eg.: BaseGDL* structureData = e->GetKW( structureIx); returns the ix'th parameter (NULL if not defined) BaseGDL*& GetPar(SizeT i); the next are variations of GetKW() or GetPar() with some additional checks: get i'th parameter throws if not defined (ie. never returns NULL) BaseGDL*& GetParDefined(SizeT i); //, const std::string& subName = ""); throw for STRING, STRUCT, PTR and OBJECT useful if a function only accepts numeric data BaseGDL*& GetNumericParDefined( SizeT ix); get i'th parameter throws if not global (might be NULL), for assigning a new variable to BaseGDL*& GetParGlobal(SizeT i); next are some variations of GetKW() or GetPar() with perform a conversion into an desired type: get the pIx'th paramter and converts it to T if necessary implies that the parameter must be defined if it converts it cares for the destruction of the copy CAUTION: this is for *read only* data, as the returned data might be a copy or not template T* GetParAs( SizeT pIx) same as before for keywords template T* GetKWAs( SizeT ix) next two same as last two, but return NULL if parameter/keyword is not defined template T* IfDefGetParAs( SizeT pIx); same as before for keywords template T* IfDefGetKWAs( SizeT ix); returns the struct of a valid object reference or throws DStructGDL* GetObjectPar( SizeT pIx); for use within library functions consider to use (note: 'static' is the point here): static int kwIx = env->KeywordIx( "KEYWORD"); bool kwSet = env->KeywordSet( kwIx); instead of: bool kwSet = env->KeywordSet( "KEYWORD"); this one adds some overhead, but is easy to use bool KeywordSet( const std::string& kw); this one together with a static int holding the index is faster (after the first call) bool KeywordSet( SizeT ix); keyword present (but might be an undefined variable) bool KeywordPresent( SizeT ix); local/global keyword/paramter global -> passed in GDL by reference local -> passes in GDL by value bool LocalKW( SizeT ix); bool GlobalKW( SizeT ix); bool LocalPar( SizeT ix); bool GlobalPar( SizeT ix); next two to set keywords/paramters note that the value MUST be created in the library function with operator new Before it must be tested with KeywordPresent() or NParam() if the keyword/paramter is present this is not done automatically because its more effective, to create the data (newVal) only if its necessary if the functions throw, they delete newVal before -> no guarding of newVal is needed void SetKW( SizeT ix, BaseGDL* newVal); void SetPar( SizeT ix, BaseGDL* newVal); Assure functions: if name contains "Par" they must be used for paramters, else for keywords (the error messages are defined for this usage and the indexing is done respectively) next two: NO CONVERSION (throw if wrong type) NOTE: only few functions need to be so restrictive converts parameter to scalar, throws if parameter is of different type, non-scalar or not defined template void AssureScalarPar( SizeT pIx, typename T::Ty& scalar); same as before for keywords template void AssureScalarKW( SizeT ix, typename T::Ty& scalar); void AssureGlobalPar( SizeT pIx); void AssureGlobalKW( SizeT ix); if keyword 'kw' is not set, 'scalar' is left unchanged void AssureLongScalarKWIfPresent( const std::string& kw, DLong& scalar); converts keyword 'kw' if necessary and sets 'scalar' void AssureLongScalarKW( const std::string& kw, DLong& scalar); converts ix'th keyword if necessary and sets 'scalar' void AssureLongScalarKW( SizeT ix, DLong& scalar); converts parameter 'ix' if necessary and sets 'scalar' void AssureLongScalarPar( SizeT ix, DLong& scalar); same as for Long void AssureDoubleScalarKWIfPresent( const std::string& kw, DDouble& scalar); void AssureDoubleScalarKW( const std::string& kw, DDouble& scalar); void AssureDoubleScalarKW( SizeT ix, DDouble& scalar); void AssureDoubleScalarPar( SizeT ix, DDouble& scalar); same as for Long void AssureStringScalarKWIfPresent( const std::string& kw, DString& scalar); void AssureStringScalarKW( const std::string& kw, DString& scalar); void AssureStringScalarKW( SizeT ix, DString& scalar); void AssureStringScalarPar( SizeT ix, DString& scalar); About defining GDL structs in C++ ================================= 'structList' contains a list of 'DStructDesc*' (struct descriptors). For each structure, there must be exactly one descriptor but there might be any number of instances (DStructGDL). You have to distinguish between instances and descriptors. For descriptors (DStructDesc) there is only (dstructdesc.hpp): void AddTag( const std::string& tagName, BaseGDL* data); this one does NOT grab the data, hence no new operator. This is used in 'InitStructs()' (objects.cpp) for defining some structures where there is no initial instance. For instances (actually holding the data) there are (dstructgdl.hpp): template< class DataGDL> void InitTag(const std::string& tName, const DataGDL& data) For already defined structures (DStructDesc exists). And: void DStructGDL::NewTag(const string& tName, BaseGDL* data) For defining the descriptor AND the instance at the same time. Used for example in initsysvar.cpp. This one grabs the data (hence it has to be created newly with new). Note that if there is already an instance elsewhere, DStructDesc must not be changed anymore. Within GDL this is checked (it is not allowed for a named struct to be redefiend after defiened once), but from C++ its the programmers responsibility. Generally: For defining a system variable NewTag should be used, for returning a named struct, its descritor should be defined in 'InitStructs()' and in the library function 'var = new DstructGDL(...)' and 'var->InitTag(...)' should be used. ('should' means here 'I cannot think of any other usage so far') Short overview of how GDL works internally ========================================== Programs (*.pro files) or command line input is parsed (GDLLexer.cpp, GDLParser.cpp generated with ANTLR from gdlc.g). These results in an abstract syntax tree (AST) consisting of 'DNode' (dnode.hpp). This systax tree is further manipulated (compiled) with a tree parser (GDLTreeParser.cpp generated with ANTLR from gdlc.tree.g, dcompiler.hpp). Here the AST is splitted into the different functions/procedures and the DNode(s) are annotated with further information and converted to ProgNode(s). Then these compiled (ProgNode) ASTs are interpreted (GDLInterpreter.cpp generated with ANTLR from gdlc.i.g, dinterpreter.cpp). LINKIMAGE ========= Joel Gales provided support for the LINKIMAGE procedure. It allows users to add their own routines as dynamic libraries to GDL. LINKIMAGE currently only works for the GNU/Linux version. Note that you cannot use shared libraries written for IDL without change. There is a simple example in "src/dll/two.cpp". To use it: 1. Build the shared library: g++ -I/(GDL header file directory) -c two.cpp (64 bit: g++ -DHAVE_64BIT_OS -I/(GDL header file directory) -c two.cpp -fpic) g++ -shared -lm -lc -o two.so two.o 2. Run LINKIMAGE: GDL> linkimage,'TWO','/usr/local/src/gdl-0.9/src/dll/two.so',1,'two_fun' with: 'TWO' is the GDL function name '/usr/local/src/gdl-0.9/src/dll/two.so' is the location of the DLL 1 tells GDL that the TWO function is a function, use "0" for a procedure 'two_fun' is the entry point for this function within the "two.cpp" file GDL> print,two(findgen(3)) 0.000000 2.00000 4.00000 gdl-0.9.9/INSTALL.CMake000066400000000000000000000067521340051421000143070ustar00rootroot00000000000000Be sure that you have at least CMake 3.0 (cmake --version) (with CMake <=3.2, an additional flag is needed, see below) Create a new directory where the objects and executables will be built, e.g. $ mkdir build; cd !$ Then run cmake pointing it to the root directory of gdl: $ cmake .. If using CMake <=3.2, you will be prompted to include "-std=c++11" in the -DCMAKE_CXX_FLAGS argument value You can optionally specify a custom install prefix, e.g.: $ cmake .. -DCMAKE_INSTALL_PREFIX=$PWD/../install The default build mode is "Release" which enables compiler optimisations and disables storing debugging symbols in the GDL binary. To use the "Debug" mode type: $ cmake .. -DCMAKE_BUILD_TYPE=Debug To use a non-default C++ compiler, one needs to call e.g.: $ cmake .. -DCMAKE_CXX_COMPILER=clang++ Numerous features of GDL rely on external libraries. These features can be enabled or disabled using CMake options. Most of the optional features have a flag that controls enabling/disabling the feature (e.g. EIGEN3, FFTW, HDF5, MAGICK, PSLIB, GRAPHICSMAGICK, GRIB, GSHHS, HDF, ...) and a flag that allows to specify a custom location of a given package (e.g. EIGEN3DIR, FFTWDIR, HDF5DIR, ...). Both the on/off and the path-spec options are passed to CMake as command=line options prefixed with "-D", e.g.: $ cmake .. -DREADLINE=OFF' # to disable readline $ cmake .. -DFFTWDIR=/opt/local/ # alternative FFTW path Other options include: - PYTHONVERSION to chose a particular Python version if multiple are installed on the system, - GDL_DATA_DIR (default: /share/gnudatalanguage) to specify a custom installation location for GDL files (a subdirectory of the main installation prefix) The list of all GDL-related options accepted by CMake along with their default values can be obtained by calling: $ cmake .. -LAH | grep -A1 "// GDL: " Results are cached. So if you need to specify a new libraries that have already been found you have to delete CMakeCache.txt and rerun cmake. If you are on a Unix system, you can run `make' to begin compilation (optionally with the number of concurrent processes specified using the -j option): $ make -j 3 For other systems, a native project file will be produced. To launch the tests, run: $ make check To install, type: $ make install Other useful commands include `make help' to view a list of targets and `make edit_cache' to edit cache results (variables defined in advanced mode shouldn't be edited). examples: mkdir gdl-clang cd gdl-clang cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -DPYTHON=NO -DCMAKE_CXX_FLAGS_RELEASE=" -Wno-return-type -Wno-switch -Wno-format -O3 " -DPLPLOTDIR="somewhere" -DLIBPROJ4=YES -DGSHHS=YES -DGSHHSDIR="/where/is/gshhs" -DHDF=YES -DUDUNITS=YES -DUDUNITSDIR=/usr/include/udunits2 -DGLPK=OFF ../gdl-lastversionfromcvs make -j 4 sudo make install or mkdir gdl-gcc cd gdl-gcc cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON=YES -DCMAKE_CXX_FLAGS_RELEASE=" -Wno-return-type -Wno-switch -Wno-format " -DPLPLOTDIR="somewhere" -DLIBPROJ4=YES -DGSHHS=YES -DGSHHSDIR="/where/is/gshhs" -DHDF=YES -DUDUNITS=YES -DUDUNITSDIR=/usr/include/udunits2 -DGLPK=OFF ../gdl-lastversionfromcvs make -j 4 sudo make install For a special compilation with all the options for fast code, including targeting the machine's processor type, use for example: -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE="-O3 -fno-math-errno -fno-signaling-nans -msse2 -march=native -DNDEBUG" more aggressive optimisations may invalidate tests about NaNs for example. gdl-0.9.9/MAP_INSTALL000066400000000000000000000132111340051421000140110ustar00rootroot00000000000000Revised version by Gilles Duvert on July 2014 To provide map projections support your first need to make sure the proj.4 library is installed. There are two libraries, the 'classic PROJ.4' library maintained by the original author, G. Evenden: http://home.comcast.net/~gevenden56/proj/ (http://home.comcast.net/~gevenden56/proj/libproj4.3_20081120.tar.bz2) and a more complete (but by no means bug free!) fork of this library available at http://trac.osgeo.org/proj. Both work with GDL and provide all projection-related internal facilities. We tend to prefer G. Evenden's trimmed classical version since it handles correctly rotations and has fever crashes. Unfortunately the fancy interrupted Goode Homomsine is not present in GE's library. It is recommendend to recompile either of these libraries instead of using the version that may come with your software distribution (but it can work, too). If GDL does not find (lib)proj4 files automatically, use "-DLIBPROJ4=YES" "-DLIBPROJ4DIR=DIR" as arguments for cmake. (were 'DIR' is the location of the compiled library. To finish the support of projections in GDL, first the following additional PRO files must be acquired and placed in a directory of the GDL PATH: http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_grid.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_horizon.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_image.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_patch.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_point_valid.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_proj_image.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_proj_info.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_proj_init_commonblock.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_proj_init_common.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_proj_init.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_satellite_limit.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_set.pro http://idlastro.gsfc.nasa.gov/ftp/exelislib/map_struct_append.pro (cd src/pro/ ; mkdir map; cd map; grep 'gsfc.nasa' ../../../MAP* | xargs wget) Note that 'map_continents.pro' is not in this list. map_continents is inside GDL. If these .pro files are not available, google is your friend;^). These are proprietary files and not part of the GDL distribution. They do lots of complicated things in a not-very-general way, and should be rewritten completely for GDL. As GDL uses Proj.4 and Proj know all the tricks used in these procedures, it should not be such a terrible job. Help would be most appreciated. See below for an example where new projections are used that do not need the above procedures... =========================================================================== MAP_CONTINENTS is implemented in GDL using the GSHHSG (Global Self-consistent, Hierarchical, High-resolution Geography Database) available under the GNU GPL. To provide support for MAP_CONTINENTS the database files and one header file (gshhs.h) need to be downloaded e.g. from: ftp://ftp.soest.hawaii.edu/pwessel/gshhsg see file ftp://ftp.soest.hawaii.edu/pwessel/gshhg/README.TXT for complete description. The header file for the 2.0 dataset is in the gshhs_1.12_src.zip file. The datafiles (*.b) are in the gshhs_2.0.tbz file. When compiling GDL, the "-DGSHHS=YES" option must be given (not enabled by default), optionally with an argument pointing to the GSHHS installation prefix: -DGSHHSDIR="DIR" Warning: At execution time, GDL will look for the GSHHS datafiles (gshhs_f.b, gshhs_l.b, etc...) in the $GSHHS_DATA_DIR. Before running GDL you can setup this variable (e.g. in bash : export GSHHS_DATA_DIR=/my/path/to/gshhs/). When GDL is compiled, if $GSHHS_DATA_DIR unknown, if $GDLDATADIR exists and if $GDLDATADIR/../gshhs/ exist too, this path is used as a defaut directory for gshhs data. So the files can/must be put there. (we need a more flexible solution - FIXME!) Reference: Wessel, P. and Smith, W.H.F., 1996. A global, self-consistent, hierarchical, high-resolution shoreline database. J. Geophys. Res., 101(B4): 8741--8743. =========================================================================== NOTE ON PROJECTION-RELATED PROCEDURES IN GDL (and IDL) =========================================================================== All the historical projections are supported fully (Godde's Homolosine will not be truncated if you link with G.Evenden's library). The GCTP supplementary projections are at least partially supported. They lack the proper initialisation of the map.pipeline array, which governs the clipping and avoids spurious lines. Moreover, ALL the projections in the PROJ.4 library linked with GDL are supported via a trick: passing a valid PROJ.4 command line in the projection name of a map structure, with the projection number set to 999 example: a=!map a.up_name="+proj=mbtfpq +a=1" a.projection=999 map_clip_set,/TRANSFORM,map=a b=map_proj_forward(lon, lat,map=a) a.uv_box=[min(b(0,*)),min(b(1,*)),max(b(0,*)),max(b(1,*))]; (lon and lat being a table of "test" longitudes and latitudes) plot, a.uv_box[[0,2]],a.uv_box[[1,3]],/NODATA, /ISOTROPIC, XSTYLE=1, YSTYLE=1 map_continents,map=a map_grid,map=a Some warnings: - MAP_SET is straightforward to use but is restricted to historical projections. - MAP_PROJ_INIT is very long to compile (GDL bug!) but gives access to all projections. However some projections may crash with MAP_PROJ_INIT since proj.4 is not protected at all (against null pointers, unknown projection inverses, etc...). We recommend G.Ewenden's library which is not so "good programmer practice" but has more "good sense"! Joel Gales, Gilles Duvert PS (by AC): a demo ("test_map.pro") is now available in the testsuite/gdl-0.9.9/NEWS000066400000000000000000001214121340051421000127650ustar00rootroot000000000000000.6: initial release 0.6.1: made GDL compile with g++ 3.3 (datatypes.hpp) 0.6.2: fixed bug with # and ## operator (basic_op.cpp) added -I.. cpp option (Makefile.am) 0.7: added graphic support (PLOT, WINDOW, WDELETE, SET_PLOT, WSET) some small bug fixes. 0.7.1: added 64 bit integer support (LONG64, ULONG64) added python support (PYTHON function and procedure) completed type functions for all types (ULONG, UINT, ...) completed INDGEN and INTARR functions for all types New library routines: SYSTIME, LEGENDRE, MACHAR, FFT, TVLCT, MAX, MIN, TOTAL, ARRAY_EQUAL, CATCH, ON_ERROR Library routines written in GDL (check out *.pro files not starting with test_) several bugfixes: conversion between BYTE and STRING. GOTO within IF statement. Memory leakage concatenating struct arrays. 0.7.2: Bugfix: dereferenced pointers are now passed by reference 0.8: added netCDF support. several new library routines. support for .COMPILE command. Improved formatted and unformatted output. Improved configure script. Extended and cleaned up the API for library routines (envt.hpp) Fixed: GOTO,undefined_label made GDL crash. Several other bugfixes. 0.8.1: Updated the configuration files (automake). 0.8.2: added HDF support. added support for several image file formats. changed the code and configuration files to make GDL build also on Mac OS X. bug fix for TRANSPOSE function. 0.8.3: now netCDF and HDF can be used together (there were linker errors in 0.8.2). updated some obsolete commands in configure.in more complete HDF support. added DEFSYSV procedure. addef CONJ and IMAGINARY functions. 0.8.4: introduced _STRICT_EXTRA solved remaining problem of using netCDF and HDF together. HELP now reports variable names correctly. the line continuation operator ($) is now also recognized in interactive mode. Added SORT, UNIQ, SHIFT (1 dim only), STRTOK, FILE_TEST, CD, HISTOGRAM and REFORM function. Added LOADCT, CD and TV procedure. Basic HDF5 support. 0.8.5: Fixed bug in STRING with PRINT or FORMAT keywords set. Fixed bug in STRMID with 3rd parameter undefined or not given. Added MESSAGE procedure (some keywords not enforced) Added FILE_SEARCH, ARG_PRESENT and EOF functions. Fixed bug in AssignAt functions. Fixed subtle bug concerning arrays() and function() which made GDL not recognize library functions when identifier was used before as array. 0.8.6: Added CONVOL function (very fast). Added EXP function. Added JOURNAL procedure. Completed SHIFT for multiple dimensions. HISTOGRAM now supports REVERSE_INDICES keyword. HELP,/LIB sorts now the output. Made # and ## operators IDL conforming for 1 dimensional arrays. N_ELEMENTS now returns LONG (before ULONG) 0.8.7: Support for GDL_PATH (falls back to IDL_PATH) environment variable. Added EXPAND_PATH, ARRAY_INDICES, REBIN, LEGENDRE, IGAMMA, LNGAMMA, BETA functions. Added OPLOT procedure. Bugfixes for ATAN (with 2 floats), CONVOL (1-dim kernel), MESSAGE (prefix). 0.8.8: Added OBJ_CLASS, OBJ_ISA, N_TAGS, SWAP_ENDIAN, BYTSCL functions. Added PLOTS, XYOUTS (both 2D only), BYTEORDER procedures. Improved FFT. OMIN,OMAX keyword support for HISTOGRAM. Fixed braced reference argument bug. Changed equality checking to compatibility checking for struct array definitions. Added structure compatibility check for assignment to struct arrays. Fixed offset bug for conversion functions (BYTE, FIX, ...). Fixed libfunction returning parameter bug. Fixed AND, OR operator bug. Fixed TVLCT bug. @file now honors !PATH. Changed configure.in to support python on OS X (fink) Added SETENV, STRUCT_ASSIGN pro. Added GETENV, STREGEX, TAG_NAMES functions. Minor adjustments of default output (no FORMAT keyword). Widen struct tag name rules: "!", "!$" and "!TEXT" are allowed. System variables can be named "!$", or "!$TEXT". 0.8.9: Added SPAWN, WAIT procedure. Added FINITE, ROUTINE_INFO, TEMPORARY functions. Added DIST function and TVSCL procedure (as .pro files). !EXCEPT system variable. Changed common block compilation. Allow RETURN as jump label (remove it from reserved words) Allow library functions to return their own parameters if used in a return statement. Allow library functions as l-functions. Fixed assignment to indexed array at one position (insert at) for indices which are 0. Cleaned up Compiler/Interpreter. Added NAN keywords to BYTSCL, MIN, MAX. Added SUBSCRIPT_MIN/MAX keywords to MAX/MIN. Added NTOHL, NTOHS, HTONL, HTONS keywords to BYTEORDER. Added z-buffer device Fixed MOD division by zero for integers. Support for files with main programs. Fixed COMMON and GOTO for interactive use. Added .RUN command True color support for TV (X-device). 0.8.10: Optimization (~10%): Arrayindexing, non-copy constants, Complex (pow, abs). Optimization (>200%): Dedicated ProgNodes for compiled programs Fixed RETURN statement in FOR loops. Made GDL buildable as a python module. .RUN handle files without subroutines. GCC 4.0 compilance. INTERPOLATE function. Fixed eof detection on input. Implemented strided index support. Improved raise to power (^ operator) for integer types. 0.8.11: Added CONTOUR procedure. Added CREATE_STRUCT, RADON, LAGUERRE, STRCMP, GAUSS_PDF, GAUSS_CVF functions. Added STRUCTURES keyword to HELP. Added NAN keyword to TOTAL. Sub-millisecond resolution for SYSTIME function Added !DIR system variable Much faster array indexing. Much faster operators (+-/*^...) Faster FFT (requires FFTW library: http://www.fftw.org/download.html) 0.9: Added HEAP_GC, PRODUCT, FILEPATH, MEDIAN (no filtering), READ_ASCII, PUSHD, POPD, PRINTD, PRIMES, NORM, T_PDF, POLY_2D routines. Support for SAVE and RESTORE through Craig Markwardt's CMSVLIB library. Added SMOOTH and DERIV as external functions. Full support of ON_IOERROR Full support of F77_UNFORMATTED. Support for XDR I/O. Fixed positional index (value and dimension) returned by STREGEX. HELP without parameters and keywords puts out a list of all local variables as well as compiled procedures and functions. Add support for PROCEDURES & FUNCTIONS keywords in HELP Made GDL compile under x86_64 linux. Fixed incompatibility with # operator and one-dim vectors. Speedup for ^ operator for integer types. Speedup (>100x!) for REVERSE_INDICES of HISTOGRAM. Implement INPUT keyword in HISTOGRAM. Support for non-rectangular (x,y 2d arrays) calls to SURFACE and CONTOUR. Support for DICOM files (GDLffDICOM object). INTEGER keyword for TOTAL. Add support for variable-length VMS files. Add support for CHANNEL keyword in TV/TVSCL. Add support for TRUE/CHANNEL keywords in TVRD (X only) Add support for DIMENSION keyword in FFT. Add REGEX keyword support to STRTOK. Add preliminary support for MPI. Add initial support for SOCKET. Preliminary support for map projections. (requires libproj4 from (http://members.verizon.net/~vze2hc4d/proj4/lbp4_050319S.tar.gz) Add initial support for BESELI, BESELJ, BESELK and BESELY but only for integer order due to limitations of GSL Bessel functions Added Erf() [and Errorf() for compatibility], Erfc(), Expint(), Gaussint(). Fixed I/O of Gamma(), Igamma(), LnGamma() and Beta() +-Inf now managed in MIN and MAX (if called with /Nan) NaN and +-Inf now properly managed in PLOT, OPLOT, PLOTS Speedup in PLOT, OPLOT, PLOTS for large data sets (see test_plot_benchmark.pro) Add 6 linestyles (via !p.linestyle or keyword) for PLOT, OPLOT, PLOTS Improved memory management. Improved new implementation of struct arrays. Management of an history (ASCII) file save in ~/.gdl/history (with memory of previous sessions) Add initial CURSOR, limited but functionnal (know limitations documented in program) and !mouse 0.9rc1: fixing memory leak in FFT when using FFTw lib. fixing FACTORIAL (GDL syntax) add SKIP_LUN (used by Astron Lib.; GDL syntax) add VOIGT() function (in C++) based on Wells' paper. add REAL_PART() function (GDL syntax) add RK4() function (in C++) in CONTOUR: throw when levels= are not ordered, manage NaN and Inf values, add Nlevels= and /Fill Two new projections in MAP_SET: Satellite and Robinson Preliminary version for Width parameter in MEDIAN() initial import for SPL_INIT() and SPL_INTERP() (GDL syntax) 0.9rc2: undocumented BYTSCL accepting three parameters (value,min,max) g++ 4.3 compatibility ignore something like a=(a=a) (so it is allowed even if a is undefined) accept self assignment of undefined variables fixed print, ', ', FORMAT='(A)' Add SUBEXPR keyword support for STREGEX Add S_FUNCTIONS/S_PROCEDURES keywords for ROUTINE_NAMES in MEDIAN(), managing "width" parameter precalculation for (selected) constant parmeter functions. precalculation for constant arrays composed of constant expressions precalculation for constant expressions and constant arrays, a major improvement speedup for constant arrays add FILL and NLEVELS for CONTOUR Initial import of RK4 initial import of codes for function VOIGT initial import of function REAL_PART in GDL syntax allow floats without exponent number like 1e FACTORIAL correcting bug when inputs are Integers; managing arrays Made for READ_ASCII DATA_START independent of HEADER 0.9rc3: interpreter: - corrected GOTO out of loops within outer blocks - corrected array to tag of struct array assignment - $: fixing two segfault conditions when SHELL or HOME env. variables not set - allowing tag names with leading '!' - imroved DataListT an empty procedure call by extimated 40% - detecting change of type of FOR index variable - allowing common blocks outside subroutines library routines: - ATAN: precision fixes (atan(float, float) -> float(atan(double, double))), /PHASE keyword support, array-scalar argument combination support, two-complex-arguments case support - BESEL*: non integer order, X neg, Complex, and better management of arrays dimensions - BETA: better management of the dimensions of output arrays - BROYDEN: initial import - CALENDAR: initial import - CALDAT: initial import - CD: avoiding segfault on OSX (wordexp() bug) - COMMAND_LINE_ARGS: initial import - CONTOUR: avoiding plplot error messages when filling, fixing segfault when contouring NaNs, smarter contour-level choice, partial labelling support - CREATE_STRUCT: accepting excl. mark as a first char of a tag name - EXIT: fixing segfault if HOME env. var undefined - EXPINT: better management of the dimensions of output arrays - FILE_INFO: initial import - FILE_LINES: no longer calling awk to parse wc output - FILE_SAME: initial import - FILE_SEARCH: support for FULLY_QUALIFY_PATH kw. - FILE_TEST: handling /NOEXPAND_PATH keyword - FFT: Fix /OVERWRITE with non-global parm bug (FFTW), fix auto_ptr bug with DOUBLE - FLUSH: initial import - GET_DRIVE_LIST: initial import - GET_KBRD: reading only one character (setting stdin to non-echo and non-canonical mode) - GET_LOGIN_INFO: initial import - HISTOGRAM: fixing inclusive ranges definition setting OMIN/OMAX type according to the type of input data binsize = (max - min) / (nbins - 1) when NBINS specified with neither MAX nor BINSIZE LOCATION keyword set correctly when HISTOGRAM called with NBINS and without BINSIZE or MAX - HELP: reporting structure data lengths, /MEMORY keyword support - IDL_BASE64: initial import - IGAMMA: better management of the dimensions of output arrays - IMSL_CONSTANT: initial import (using UDUNITS-2) - IMSL_ZEROSYS: initial import - LL_ARC_DISTANCE: initial import - LOCALE_GET: initial import - MAKE_ARRAY: /PTR & /OBJ keywords, /INDEX keyword support for strings - MAKE_ARRAY: keyword name changed from INT to INTEGER - MAX: DIMENSION keyword support - MIN: ditto - MEDIAN: memory leak fix + change DIM into DIMENSION - MEMORY: initial import - MOMENT: MAXMOMENT kw support + update of the documentation header - N_TAGS: rename keyword /LENGTH to /DATA_LENGTH - NCDF_ATTGET: code cleanup + fixes - NCDF_ATTPUT: fixing invalid keyword numbering - NCDF_DIMINQ: accepting long integers as file and dimension ids - NCDF_VARGET: 64-bit fix (SizeT->Dlong for transposed_dim_length[]) reading text data - NCDF_VARGET1: reading text data - NCDF_VARPUT: fixing random behaviour due to type mismatch (size_t -> int), fixing uninitialized variable bug - NEWTON: initial import - OPENW: allowing /APPEND flag for non-existant files - PARSE_URL: initial import - PATH_SEP: now return good type STRING = '/', before STRING = Array[1] - PLOTS: correction for DATA coordinates - PM: initial import - PRINT: handling VMS compatibility syntax; demo: print, "$(F)", 1 - PRINTF: ditto - READ_ASCII: handling both whitespace and tab as delimiter by default; using FILE_LINES instead of spawning wc - READ_XWD: fixing a conditional statement typo - READF: bugfix - allowing reads from standard input (lun 0) - REVERSE: initial import - ROTATE: better error message - SIZE: fixing datatype (sign) conflict in IDL_SIZE structure assignment - SHOWFONT: initial import - SPAWN: fixed segfault when SHELL env. variable not set, undoing bitwise shift in EXIT_STATUS value; demo: spawn, "exit -1", e=i & help, i setting EXIT_STATUS parameter when nParam==0; demo: spawn, exit=i & help, i - SPL_INIT: initial import of C++ version (y0= and yn_1= not ready) - SPL_INTERP: ditto - STRING: handling VMS compatibility syntax; demo: help,string(1,"(G)") - STRSPLIT: will allow 'str' and ['str'] 1D strings - SYSTIME: correction for /JULIAN flag; conflicting keywords message - TV: managing [1,n,m], [n,1,m] and [n,m,1] cases when TRUE=0 - VOIGT: better management of the dimensions of output arrays - XYOUTS: axis thickness fix, DATA coordinates fix configure script: - HDF4/HDF5: linking with SZIP if needed - detecting presence of Python numarray package - printing summary information - support for linux ppc64 - using nc-config (if present) to determine netcdf LIBS/INCLUDES - using Magick++Config (if present) to determine Magick LIBS/INCLUDES - better ncurses/curses check, preventing linking both libraries other: - embedded formatting commands for plotting routines (TEXTOIDL works) - !DTOR & !RADEG values more precise - SVG terminal available via set_plot, 'svg' - misc. minor updates in readme/doc files - several new test routines - input/output: 64-bit OSX fix (xdr_long()/xdr_u_long() argument types) - allowing setting history-file lenght in startup file using !EDIT_INPUT - OpenSolaris compatibility fixes - handling some out-of-memory exceptions - gcc 4.4 compatibility fix - HDF5: v1.8 compatibility fix - widgets: some new functionality - mapping: support for new LIBPROJ4 0.9rc4: in short: --------- - thread pool support using OpenMP (G++ >= 4.2), - enhanced error-reporting (line numbering, message decoration, etc.) - new library routines, including: CPU, CROSSP, GET_SCREEN_SIZE, IMSL_BINOMIALCOEF, IMSL_CONSTANT, IMSL_ZEROPOLY, QUERY_*, WSHOW, WTN (wavelet transform), ... - enhanced HDF5 (15 new routines) and netCDF support - support for GRIB 1/2 file format (read-only, using ECMW GRIB_API) - several new command-line options, support for specifying batch files at command-line - bug-fixes in library routines and the interpreter - new plotting functionalities (contouring on maps, color PostScript output, ...) - enhanced detection of libraries in the configure script - enhanced "make install" and "make check" rules - compatibility fixes for various GCC versions and UNIX flavours in detail: -------------- interpreter: - fixed/enhanced numerous error-reporting related features including: line number tracking, error message "decoration" (prefixes etc.), inclusion of string-representation of error-related values in error messages - fixed STRUCT access of non struct struct member (e. g. a={b:0}&print,a.b.c ) - corrected beahvior of call_fun and call_lfun for RC_ABORT return code, old behavior lead to endless loop at startup in some conditions - fixed wrong handling of CONTINUE under certain conditions in nested loops - support for COMPILE_OPT OBSOLETE & !WARN.OBS_ROUTINES - support for numeric constants in explicit binary format, e.g. a='1010101'b - honouring COMPILE_OPT within $ and EXECUTE library routines: - BROYDEN: fixed behaviour with constant-returning functions - BYTEORDER: support for structures - CHECK_MATH: 2 undocument params and also keep memory of value - CONTOUR: memory-leak fix (thanks to Valgrind), support for the /OVERPLOT keyword, partial support for contouring on maps, more sanity checks for argument types, better filled-contour level-choice mechanism, fixing axis colour - CPU: initial import - CREATE_STRUCT: fixed behaviour with no parameters - CROSSP: initial import - CURSOR: verification if we are in X mode, support for lat/lon query on maps - DEVICE: support for /COLOR, XSIZE and YSIZE for PostScript driver, support for the GET_VISUAL_DEPTH keyword - DIST: runs correctly when called like dist([2,2]) - FFT: sanity check for the rank of argument, preventing bogus memory freeing with dcomplex input - FILE_BASENAME: support for array argument, better handling of empty and space-only strings - FILE_LINES: spawning subprocesses with /NOSHELL keyword to prevent execution of shell startup file - FILE_TEST: stripping the trailing '/' if present - [F,D,L,...]INDGEN: making the values of the resulting array more precise for large arrays (demo: print, (findgen(40000000))[40000000-1]) - GET_SCREEN_SIZE: initial import - GETENV: error message when called with /ENV and a positional parameter - GRIBAPI_*: initial import of GRIB-1/2 file format support using the ECMWF GRIB API - H5F_IS_HDF5, H5_GET_LIBVERSION, H5D_GET_TYPE, H5T_GET_SIZE, H5A_OPEN_NAME, H5A_OPEN_IDX, H5A_GET_NAME, H5A_GET_SPACE, H5A_GET_TYPE, H5A_GET_NUM_ATTRS, H5G_OPEN, H5A_CLOSE, H5T_CLOSE, H5G_CLOSE, H5A_READ: initial import - HELP: corrected output for expressions - HISTOGRAM: correcting binsize definition when max and nbins set, better INPUT-kw-related error message - IMSL_BINOMIALCOEF: initial import - IMSL_ZEROPOLY: initial import (using gsl_poly_complex_solve()) - IMSL_ZEROSYS: fixed behaviour with constant-returning functions - INVERT: fixing a segfault condition with non-global parameter - LA_TRIRED: checking if the first argument is an array - LOADCT: set !D.TABLE_SIZE from 0 to 256 - LOCALE_GET: returning locale of the parent process - N_TAGS: support for LENGTH keyword (currently equal to DATA_LENGTH) - NCDF_ATTGET: outputing byte arrays instead of strings - NCDF_ATTNAME: allowing to specify the global atribute number - NCDF_ATTPUT: support for LENGTH keyword - NCDF_VARGET: fixing a segfault condition - NCDF_VARINQ: fixing failed-assertion condition (dimension(0)) with scalar variables - NCDF_*: fixes in error handling, compatibility with netcd-4 (file handles are now Long instead of Int) - NEWTON: fixed behaviour with constant-returning functions - OPLOT: sanity checks for the rank of arguments - PLOT: adjusting axes when charsize changed, better automatic range selection, sanity checks for the rank of arguments - POINT_LUN: assuring the 2nd par is a global par - POLY_AREA: initial import - PRINT/PRINTF: changed output of trailing newline after empty string output, corrected alignment for all types - RSTRPOS: initial import - READ_TIFF: ignoring errors related to GeoTIFF fields in TIFF files - QUERY_BMP, QUERY_DICOM, QUERY_GIF, QUERY_IMAGE, QUERY_JPEG, QUERY_PICT, QUERY_PNG: QUERY_PPM, QUERY_TIFF: initial import (using Magick++'s ping functionality) - READ_ASCII: printing error message when DATA_START exceeds file length - REVERSE: support for /OVERWRITE keyword - ROUTINE_INFO: support for PARAMETERS keyword - ROUTINE_NAMES: fixed ARG_NAME keyword for values larger than current level, corrected name lookup, proper behaviour with the /STORE kw., fixed support for /FETCH kw. - STREGEX: preventing bogus call to basic_string::substr(-1,...) - STRMID: fixed behaviour for negative values of 3rd parameter - STRPOS: does no longer ignore undefined 3rd parameter - STRSPLIT: fixed probem related with STRTOK bug - STRTOK: fixed output dimensions - SURFACE: memory-leak fix (thanks to Valgrind), more sanity checks for argument types - TVRD: fixed segfault with no window open - WAIT: allowing interruption with control-c - WSHOW: initial import (ICONIC kwrd not implemented yet) - WTN: initial import (using GSL DWT routines) configuration/installation: - installing library .pro files, manpage and basic docs during make install - setting default library-routine search path if GDL_PATH/IDL_PATH not defined - checking if HDF4 was compiled with --disable-netcdf - checking if netCDF installation is usable (HDF4 installation conflict) - configure: checking if netcdfcpp.hpp is usable (conflicting hdf4/netcdf installation issue) - fixes in wxWidgets detection code - support for the Debian naming of the HDF4 libraries from the hdf4-alt packages (compiled with --disable-netcdf) - checking for GSL >=1.7 which is requiered to use both FFT and DWT at the same time other: - adding a manpage - Cygwin compatibility fixes (as of version 1.7.1, Cygwin still needs a patch for rpc and fenv) - adding on_error,2 for all routines implemented in GDL - error reporting for HDF5 support - Strassen algorithm for matrix multiplication (needs manual enabling) - !DEVICE.N_COLORS in now dependant on the actual X-window setting - handling "cannot connect to X-server" via a GDL error message - initial thread pool support using OpenMP - checking if PLplot supports the requested driver (ps, xwin, mem) and informing the user via a GDL error message if not - SVG plots: swithing between svg and svgcairo drivers by checking which drivers are supported by PLplot - support for -quiet and -e command-line options and for specifying batch files at command-line; ignoring numerous license-related options for compatibility - warning the user if MPI changes the working directory of GDL - welcome message changes (informing about the library-routine search path) - more meaningful contnents of the !VERSION structure - GCC 3.4.3, 3.4.4, 4.3.4, and 4.4 compatibility fixes - support for reading ASCII files not ending with newline character - ![X,Y].RANGE support in plotting routines - Allow neg. width for A format code, fixed T,TL,TR format codes - sanity checks in array-returning library routines preventing segfaults when called with invalid arguments - new test-routines: test_dims_of_arrays.pro, test_valgrind.pro, test_check_math.pro, test_get_screen_size.pro, test_nestedloop.pro, test_plotting_misc.pro, test_plotting_ranges.pro, test_grib.pro, test_poly2d.pro, test_wavelet.pro - inclusion of some of the test-routines in the "make check" rule - quick_start_GDL.sh script - making the initial "DECOMPOSED" setting of the X device dependant on the colour depth reported by the X-server 0.9: - FOREACH statement, syntax: FOREACH loopVar,array[,indexVar] DO - member function and procedure calls with '.' e. g.: object.aProcedure - support of negative index ranges. -1 is the last element, -2 the one before the last and so on. E.g.: array[-7:-5] - new widget features incl. WIDGET_DROPLIST - automatic garbage collection - numerous bugfixes (incl. SAVE/RESTORE, WRITEU, ...) - memory leak in FFT when using FFTw lib should be solved - all input types OK in FFT when using GSL FFT - new routines: HIST_2D, INTERPOL, MAP_CONTINENTS, POLYFILL, RESOLVE_ROUTINE, SPHER_HARM, IMSL_ERF - new keywords/calling sequences handled: - DEVICE, /INCHES, GET_SCREEN_SIZE - PRODUCT, /PRESERVE_TYPE, /INTEGER - REBIN: support for specifying new dimensions as an array - TOTAL, /PRESERVE_TYPE - FILE_SEARCH, /FOLD_CASE - STRSPLIT, /preserve_null - new test routines (invoked during "make check") - DIALOG_PICKFILE, based on Zenity, OK on most Linux and OSX - FILE_DELETE, FILE_COPY and FILE_EXPAND_PATH - SPL_INIT: now y0= and yn_1= ready - Compressed files should be well processed now (readf, printf, fstat, point_lun, ...). See test_zip.pro 0.9.1: - fixes/improveents in: CONTOUR, DIALOG_PICKFILE, EXECUTE, EXIT, FIX (TYPE=7 and /PRINT), FFT, FSTAT, HEAP_GC, MOMENT, NCDF_ATTNAME, NCDF_DIMDEF, NCDF_VARID, NCDF_VARPUT, INTERPOL, PLOTS, POINT_LUN (64-bit addressing), POLYFILL (support for LINE_FILL, SPACING, LINESTYLE, ORIENTATION and THICK), PRINT, PRINTF, SAVE/RESTORE, SPL_INIT (mem leak), STRSPLIT, SURFACE (added AX,AZ), WAIT, XYOUTS (support for the WIDTH kw), DEVICE (WINDOW_STATE kw) - other improvements: fixed reading of (big) compressed files, decomposed colours with PostScript, gdlffdicom update (v20100309), new test routines, improved cmake configuration (still experimental), fixed behaviour with non-comma locale-defined decimal separators - early draft of GDL User's & Developer's guide: source files in doc/udg, current pdf version at: http://gnudatalanguage.sf.net/gdl.pdf - Python bridge: Numarray -> NumPy transition (several known bugs still exist) - the .STEP command - new routines: CALL_EXTERNAL (by Christoph Fuch), DIALOG_MESSAGE, ROBERTS, SWAP_ENDIAN_INPLACE, CORRELATE 0.9.2: - tremendous speed improvements: Indexing, subroutine calls, operators (especially for scalar values in conjunction with OpenMP), ... - UNIT keyword for SPAWN (thanks to a patch by Greg Huey) - fixed ASSOC var indexing with a variable - new routines: FILE_MKDIR, FILE_WHICH (patch by H Xu), IDL_VALIDNAME (by Rene Preusker), SCOPE_VARFETCH, SEM_CREATE, SEM_LOCK, SEM_RELEASE, SEM_DELETE (SEM_* routines by Mateusz Turcza), - fixes/enhancements in: BETA, CONTOUR, CORRELATE, DIALOG_PICKFILE, EXPINT, HDF_OPEN, H5F_OPEN, HDF_SD_START, IGAMMA, IMSL_CONSTANT, INTERPOL, LOADCT, NCDF_CONTROL, NCDF_OPEN, ROUTINE_NAMES, TV, TVRD, XYOUTS (!P.MULTI vs. !P.POSITION, ORIENTATION with logscales), INTERPOLATE (the MISSING kw) - fixes in STREGEX, STRPOS, STRSPLIT - non-Encapsulated PostScript support along with XSIZE, YSIZE, XOFFSET, YOFFSET, PORTRAIT, LANDSCAPE and SCALE_FACTOR settings support for PostScript output (requires pslib - http://pslib.sourceforge.net/ and makes advantage of PLplot fixes introduced in PLplot 5.9.9) - memory leak fix (bug introduced in the previous version) - various testsuite & docs updates (incl. docs and examples for CALL_EXTERNAL) - fix in WordExp() when filename argument contain whitespaces (useful in various cases, including OPENR/W, FILE_MKDIR, ...) [AC 2012/01/04: not finished :( - !version.os now in lower case for Linux and Darwin 0.9.3: - activities on speed improvements continuing - Initial import of STRMATCH() - Initial import of USERSYM - SCOPE_VARFETCH (only LEVEL keyword supported) - keyword /NaN for HISTOGRAM - Initial import of LUDC, LUSOL and DETERM, OK now only for DOUBLE - Initial import of ROT, CONGRID and BILINEAR - Initial import of TV for PS output - fix in RANDOMN/RANDOMU (Binomial OK, conflicting keywords detected ...) - Initial import for QROMB(), QSIMP() (based on QROMB) and QROMO() - Initial import for TRISOL() - fix in ERASE for background color (preparing Coyote lib. support) - Initial import of STANDARDIZE and HIST_EQUAL - improvment in MAGICK related codes, especially MAGICK_PING (pb with ImageMagick (IM) in Ubuntu 12.04; GraphicsMagick can also be used instead of IM) - FZ_ROOTS: initial import (same way than IMSL_ZEROPOLY using gsl_poly_complex_solve(), only real coefs. for input poly) - FX_ROOT: initial import. in c++ - keyword DIM in MOMENT(), MEAN(), STDDEV(), VARIANCE(), SKEWNESS(), KURTOSIS() (requested DIM and other improvments) - keyword SIGN in FINITE - support for empty arrays and !NULL system variable - promotion of FOR loop index variable type - various improvments on READ_JPEG, READ_PNG, WRITE_JPEG, WRITE_PNG - keyword ICONIC in WSHOW - keyword ISOTROPIC in PLOT, CONTOUR - new widget features incl. WIDGET_LIST and CW_GROUP - various fix in FFT: DIM keyword, memory leak when using GSL - support for some overloaded operators (_overloadIsTrue, _overloadPlus, _overloadMinus, _overloadBracketsLeftSide, _overloadBracketsRightSide, _overloadEQ, _overloadNE) - support for .SKIP [NSteps] command 0.9.4: - when compiled with Eigen3 library, significant speed improvement in MATRIX_MULTIPLY() (and # operators), especially on multi-cores Basic loading management included (if some core are busy). - LIST and HASH are fully supported even left-side struct access is possible e. g.: GDL> h = HASH('key',{tag1:1}) & h['key'].tag1 = 3 this even works with all (derived) GDL_OBJECTs: In this case (a variable set to) !NULL is passed as the OBJREF parameter to the OBJECT::_OVERLOADBRACKETSLEFTSIDE member procedure, it must in turn set this OBJREF parameter (the variable) to a POINTER to the heap variable to access. - .RESET_SESSION and .FULL_RESET_SESSION commands - CHOLSOL/CHOLDC using Eigen3 (sub-optimal but efficient for big matrix on multicores) (LA_CHOLSOL/LA_CHOLDC removed for technical issues) - large change in various graphic/plotting keywords (see below). 3D options supported, but some limitations due to the use of the plplot library. - PLOT, OPLOT: All keywords supported except FONT and CHANNEL, Correct handling of log/DATA/NORMAL/DEVICE coordinates and CLIPPING. - PSYMs shapes now identical to IDL's. - PLOTS: idem as above, all keywords now supported. - XYOUTS: idem as above, one-argument support (XYOUTS,"string"). Enhancement wrt. reference program: color,size,angle,etc of text are vectors. FONT and TEXT_AXES not supported. - CONTOUR: Support of all options except CELL_FILL, C_ANNOTATIONS, CLOSED, DOWNHILL, IRREGULAR, TRIANGULATION,PATH_*** Correct implementation of Z, [X,Y], i.e., contours may be skewed, rotated, etc depending on X and Y. Better than IDL: - a new ZLOG option makes log contours as well. - C_ORIENTATION, C_SPACING are also vectors. - log axes give better results - good contouring of Not-A-Number values in Z and MIN_VALUE/MAX_VALUE - CLIPPING ok. - Automatic limits in some cases still different from IDL. - AXIS and boxes in plots: all [XYZ]TICK[***] options supported except TICKV and a few TICKFORMAT specifics. - CURSOR: full support for CURSOR command, which is interruptible by control-c and has all the options. - SURFACE: all Keywords supported except "LEGO" and "CHANNEL". - Added SHADE_SURF (slow and imperfect shading from the plplot library). - Added cursor-related functions TVCRS and command EMPTY. - Added DEVICE options CURSOR_CROSSHAIR, CURSOR_STANDARD, CURSOR_ORIGINAL and GET/SET_GRAPHICS_FUNCTION (GXoR, GXand, etc). - Disabled by default the focus in the X11 graphics windows as IDL does and repositioned WINDOWS by default to top-right of screen. Screen size and behaviour using GDL_GR_X_WIDTH, GDL_GR_Y_WIDTH and GDL_GR_X_QSCREEN environment variables (X window) (GDL_GR_WIN_WIDTH, GDL_GR_WIN_WIDTH and GDL_GR_WIN_QSCREEN under windows) - WSHOW works irregularly, depending on the window manager. 0.9.5: - lot of improvments in Widgets related code. Available widgets: WIDGET_DRAW(!), WIDGET_BASE, WIDGET_BUTTON, WIDGET_DROPLIST, WIDGET_COMBOBOX, WIDGET_LIST, WIDGET_SLIDER, WIDGET_TAB, WIDGET_TEXT, WIDGET_LABEL, CW_BGROUP (Note: Not all keywords are supported yet (however, they are accepted) but almost all functional keywords. This means: Programs using these widgets should work but maybe look a bit different) Controlling routines: WIDGET_EVENT, WIDGET_CONTROL, XMANAGER - TIC and TOC - !CONST system variable - initial import of NetCDF-4 related codes: NCDF_GROUPSINQ, NCDF_GROUPNAME, NCDF_GROUPDEF, NCDF_FULLGROUPNAME, NCDF_GROUPPARENT, NCDF_DIMIDSINQ, NCDF_NCIDINQ, NCDF_VARIDSINQ - introducing the NULL device type, better result on Unix like system without X11 (e. g. computing nodes on HPC) - better free format for print, preserving precision digits. - ISA() and TYPENAME() 0.9.6: - support for projections now complete. See MAP_INSTALL for details. - new keywords (BOOLEAN,INTEGER,FLOAT,COMPLEX,STRING) in ISA() - two new system variables: !TRUE and !FALSE - initial import for SCOPE_TRACEBACK() (/sys and /struct not ready) - combination of input arrays in math. special functions now ok with IDL - SVSOL(); RESOLVE_ALL, more keywords in RESOLVE_ROUTINE - initial import of LA_LEAST_SQUARES (for Ulyss), required Eigen3 - keyword LEVEL in MESSAGE - support for Calendar format codes in input/output - better handling of multiaxes in plot - option --fakerelease for gdl: "$gdl --fakerelease 6.2" will pretend that the software release is 6.2 by setting !VERSION.RELASE to that value. !VERSION.RELASE is often tested by procedures to decide whether some function or option should be used. It is sometimes possible to use this option to fool a procedure that request a specific value of !VERSION.RELEASE 0.9.7 - Huge gains in plotting speed for X device by bypassing plplot's X11 color handling. Especially noticeable for remote X11 displays. - Widget numbering scheme aligned to IDL's. - Patched several buggy output formats (PRINT, etc). - better report of memory size (MEMORY command) for unix. - .RESET_SESSION OK. - better behaviour of WRITE_GIF and WRITE_PNG as well as other graphic formats. - Correct setup of !D.N_COLORS and !P.COLOR when switching devices and decomposed state. - Window-related commands (WSET,EMPTY,WINDOW...) now correctly handle the managed/widget/free/absent cases. - ISHFT() now an internal C++ function (for speed). - Begun implementation of TRIANGULATE when GDL is compiled with the QHULL library. Only the most basic support is provided. - Experimental: use device wxWidgets as replacement of X11 and WIN devices (of course when GDL is linked with the wxWidgets library). This is at the moment triggered by the environment variable GDL_USE_WX="YES" : setting this variable, the device 'X' or 'WIN' will actually be a wxWidgets device, with antialiasing and trueType fonts. - Experimental: calling GDL with option "--fussy" or setting the environment variable "GDL_IS_FUSSY" enforces the STRICTARR compiling scheme (array index always between "[]"). This generally speeds up procedure compilation. 0.9.8 - internal SAVE and RESTORE. CMSVLIB not required anymore, and references to it removed in the documentation. - better L64 support (N_ELEMENTS, SIZE) - better TOTAL for large numbers or special types - update RANDOM ... - revisited MAKE_DLL & CALL_EXTERNAL - MIN, MAX /ABSOLUTE. - support of DEVICE,SET_CHARACTER_SIZE, and consequently a better positioning and sizes of plots. - TRIANGULATE and TRIGRID complete (including spherical triangulation) using Renka's legacy algorithms. 0.9.9 - build requirements and development hosting changes: - development hosting moved from SourceForge to Github - introduction of continuous integration services with Linux, OSX and Windows builds - C++11 and CMake 3 requirements - OpenMP required by default - dropped support for OLDPLPLOT - support for using eccodes instead of grib_api - language/interpretter: - auto-print feature - implicit array generation, ex: array=[0.1:3.5:0.33] - many HASH and LIST handling improvements - DELVAR and .RNEW - STATIC and NOSAVE compile options - new functionalities: - major TIFF improvement and GEOTIFF support - LINFIT, DILATE, ERODE, SOBEL, PREWITT, ROBERTS - NCDF4_EXISTS and H5F_CREATE - HELP improvements for objects, structures, etc - performance improvements: - WHERE speedup - parallelized FINITE, MIN and MAX - RANDOM functions (RANDOMUn RANDOMN etc) rewritten using dSFMT, both simd-accelerated and parallelized - FILE_LINES, FILE_LINK, FILE_COPY, FILE_MOVE reimplemented in C++ - other enhancements: - reimplemented PARSEL_URL - added support for START and INCREMENT to MAKE_ARRAY - /ABSOLUTE keyword for MAX and MIN - /L64 keyword for WHERE - CONTOUR, SURFACE and SHADE_SURF accept degenerated N-D equivalents to 2D arrays - preservation of types by TOTAL - FIX & ROUND improvements - colormap initialisation fix - corrected os_name reporting in !version for OSX - fixed behaviour with no X-server connection available - several files cleaned up or moved to obsolete folder - Windows fixes for STRTRIM and SYSTIME - FreeBSD fixes for sincos - improvements in idlneturl class - numerous compiler warnings addressed - pytest-based Python module testsuite - new tests, test cleanups gdl-0.9.9/PYTHON.txt000066400000000000000000000076131340051421000140560ustar00rootroot00000000000000GDL can embed python as well as being embedded in python. 1. Writing GDL extensions in python 2. Calling GDL from python 1. Writing GDL extensions in python =================================== Since version 0.7.1 GDL provides two additional subroutines: A PYTHON function and a PYTHON procedure. Both are very similar, the difference is, that any result returned in the procedures is quietly ignored, while for the function an exception is raised if python's None is returned except the DEFAULTRETURN keyword is set to a value, in which case that value is returned in case of 'None'. the syntax is: PYTHON,python_module[,python_function[,arg1,...,argN]],ARGV=argv res = PYTHON(python_module[,python_function[,arg1,...,argN]],ARGV=argv, DEFAULTRETURN=defaultreturn) python_module the python module to load python_function the python function to call. If this paramter is not specified, only the module is loaded and initialized. Note that the module intitialization is done only the first time a python module is loaded. arg1,...,argN arguments to be passed to the python function scalars and one dimensional arrays are passed as python scalars, an array is passed as a python Numpy array. Numpy is a popular extension to python. Using it let python be integrated in GDL quite seamlessly. See: http://numpy.scipy.org/ for details. ARGV set this keyword to a string or string array which is set to the command line options for python. The first element is the (faked) name of the python executable. With this pythons search path for modules (sys.path) can be manipulated. If this keyword is set, no parameter (python_module) need to be specified. DEFAULTRETURN default return value, returned if the python function returns 'None'. Note that for a GDL extension, you probably have to write a GDL program file (.pro) containing a function/procedure which uses the PYTHON function/procedure and a python module (.py) which gets called by PYTHON within your subroutine. For an as simple as it gets example see the files gdl/py/python_print.py and gdl/pro/py_print.pro If you have the python package 'matplotlib' installed (see: http://matplotlib.sourceforge.net), you can test the (little) more elaborate example in. gdl/py/python_plot.py and gdl/pro/py_plot.pro (Note that the matplotlib library has much more capabilities then used here.) For the version of python and its packages used please refer to the README file. If you have any suggestions or needs for extensions of the python interface please see "CONTACT" in the README file. 2. Calling GDL from python ========================== NOTE: Due to the neglectible feedback, the python module development is currently on hold. If you use it, you are urged to let us know. Since version 0.8.9 GDL can be embedded into python. See INSTALL to learn how to build the GDL python module. Form within python, the usage is: first the GDL module must be imported: import GDL then this module provides three python functions: GDL.pro( PROCEDURE_NAME [, args [, keywords]]) result = GDL.function( FUNCTION_NAME [, args [, keywords]]) GDL.script( SCRIPT_FILE_NAME) for calling a GDL procedure, function and script file. PROCEDURE_NAME, FUNCTION_NAME and SCRIPT_FILE_NAME must be scalar strings. args are the arguments. They are converted to GDL. keywords are the keywords. They are converted to GDL. if an arg or a keyword is a tuple, they are NOT copied back when the GDL subroutine returns. This is done to save resources. (Only the first item of each tuple is passed to GDL). GDL arrays are passed to/from GDL as python Numpy arrays. Numpy is a popular extension to python. See: http://numpy.scipy.org/ for details. Example: >>> import GDL >>> print GDL.function("sin",(1,)) 0.841470956802 gdl-0.9.9/README000066400000000000000000000415161340051421000131540ustar00rootroot00000000000000 GDL - GNU Data Language ======================= A free IDL (Interactive Data Language) compatible incremental compiler (capable of running programs written in IDL/GDL). IDL is a registered trademark of Harris Geospatial (see: http://harrisgeospatial.com/). HOMEPAGE: ========= http://gnudatalanguage.sourceforge.net FEATURES: ========= Full syntax compatibility with IDL up to version 7.1... ... and trying to be up-to-date with 8.x, see below. All IDL language elements up to IDL version 7.1 are supported, including: Pointer, objects, structs, arrays, system variables, common blocks, assoc variables, all operators, all datatypes, _EXTRA, _STRICT_EXTRA and _REF_EXTRA keywords... GDL provides all of the GUI support (widgets) of IDL (see below). Supported IDL 8.0 language elements: FOREACH loop negative array indices garbage collection pointers and objects call methods on an object using "." (e. g. object.aMemberProcedure,arg1) empty arrays and !NULL system variable automatic promotion of FOR loop variable types LIST and HASH types Not yet supported: simplified property access on objects (e. g. object.aProperty = value & print,object.aProperty) In general GDL should run correctly an IDL procedure, even one from the /lib folder of an IDL distribution. (Note that most of theses procedures---some can be found on the web---have not yet been rewritten for GDL, help is welcome.). The file input output system is fully implemented including full support of F77_UNFORMATTED. netCDF files are fully supported. HDF4 files are supported. Basic support for HDF5 files. DICOM files are supported via the GDLffDICOM object (http://idl.barnett.id.au/idl-projects) (files in the src/pro/dicom subdirectory). Overall more than 400 library routines are implemented. For a list enter HELP,/LIB at the command prompt and look for library routines written in GDL in the src/pro subdirectory. Graphical output is almost completely implemented (no object-graphics). The PLOT, OPLOT, PLOTS, XYOUTS, SURFACE, CONTOUR and TV commands (along with WINDOW, WDELETE, SET_PLOT, WSET, TVLCT, LOADCT) are working (most keywords, !P system variable tags and multi-plots are supported) for X windows, z-buffer and postscript output. GDL has an interface to python. Python can be embedded into GDL and GDL can be compiled as a python module. See the file PYTHON.txt for details. For the thread pool OpenMP is utilized if the compiler supports it. REQUIREMENTS: ============= In short: Mandatory libraries: plplot http://plplot.sourceforge.net/source/index.html gsl http://www.gnu.org/software/gsl readline http://ftp.gnu.org/pub/gnu/readline/readline-4.3.tar.gz zlib http://www.zlib.net/ Optional libraries: Eigen http://eigen.tuxfamily.org ImageMagick http://www.imagemagick.org/www/download.html netCDF *) ftp://ftp.unidata.ucar.edu/pub/netcdf HDF4 *) ftp://ftp.ncsa.uiuc.edu/HDF/HDF/HDF_Current HDF5 ftp://ftp.ncsa.uiuc.edu/HDF/HDF5/current FFTW http://www.fftw.org/download.html python http://www.python.org libproj4 (consult the MAP_INSTALL file) UDUNITS-2 http://www.unidata.ucar.edu/software/udunits/ GRIB API http://www.ecmwf.int/products/data/software/grib_api.html GSHHS (consult the MAP_INSTALL file) wxWidgets http://www.wxwidgets.org/ pslib http://pslib.sourceforge.net/ glpk https://www.gnu.org/software/glpk/ : only to have the linear programming function SIMPLEX() available. Only with python: numpy http://numpy.scipy.org/ *) please see below for potential problems using netCDF and HDF4 COMPILING: ---------- At least g++ 3.2 (or a similar C++ standard conforming compiler) is needed for compiling GDL. Note that due to problems with static casts g++ 3.3.1 does NOT compile GDL, but 3.3.2 and 3.4.1 work fine again. GDL compiles under Mac OS X (10.2, 10.3) with g++ 3.3 . If you install the libraries as precompiled packages rather than compiling them from sources, please note that depending on your distribution, you may need development packages as well. Examples are (for Fedora): plplot-devel ImageMagick-devel ImageMagick-c++-devel Look at the *INSTALL* files. LINE EDITING: ------------- Better than IDL, GDL has modern line editing and line history features. The GNU readline library 4.3 is needed (actually GDL should compile without, but its very inconvenient to use that way, furthermore proper event handling for graphic windows requires readline). You can get it at: http://ftp.gnu.org/pub/gnu/readline/readline-4.3.tar.gz GRAPHICS AND DEPENDENCIES: -------------------------- For the graphics support of GDL, the plplot library version >5.9.6 is necessary. PLplot >= 5.9.9 is recommended, but plplot > 10 is tricky (see below). To download plplot please look here: http://plplot.sourceforge.net/source/index.html A possible problem was reported: On opening more than one window, plplot causes a segmentation fault if GDL is compiled with ImageMagick. This happens if plplot uses dynamic drivers. The current solution is to disable dynamic drivers for plplot (-DENABLE_DYNDRIVERS=OFF option for cmake). Current ubuntu/debian distributions are using dynamic drivers, so plplot needs to be compiled from source there. Disabling dyndrivers apparently is not necessary anymore. plplot > 5.11 needs absolutely to be compiled with its "old" wxWidgets driver, using the Cmake switch -DOLD_WXWIDGETS:BOOL=ON . Otherwise the WIDGET_DRAW and possibly the graphics window *will not work*. Plplot is not flexible enough to provide both drivers, and the new driver insists on making its own windows! Distributions that provide plplot and plplot-devel have probably not used -DOLD_WXWIDGETS:BOOL=ON so you'll need to compile plplot yourself with this option (and the options -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE='-O3' for efficiency), install it somewhere (so add also the with option -DCMAKE_INSTALL_PREFIX="somewhere"), and provide -DPLPLOTDIR="somewhere" while cmaking GDL. MATCH FUNCTIONS & MORE: ----------------------- GDL uses the GNU Scientific Library (GSL). Please see file HACKING if you want to write functions extending GDL (i. e. add a library subroutine) which use GSL for proper handling of GSL obects in GDL. (Minimal version is 1.7, which is now checked via "gsl.m4". Note that version 1.1.1 was reported to NOT work with GDL) You find it at: http://www.gnu.org/software/gsl MAKE GDL FASTER: ---------------- GDL uses Eigen for fast matrix multiplication. (optional) The Eigen library version 3.1 or later is highly recommended for a performance boost, expecially on multi-cores. To be found at: http://eigen.tuxfamily.org, but is probably installed on your computer and will be found by the installer. The simpliest way to compile with it is to copy all the header files under sub-directory src/Eigen. Another solution is to provide full path to the include files (e.g. --with-eigen=/home/toto/Eigen3.1.4/include/eigen3/ in that case Eigen would have been prepared using: cmake . -DCMAKE_INSTALL_PREFIX=/home/toto/Eigen3.1.4/ ) The FFTW library is (optionally) used for the FFT function. It is available at: http://www.fftw.org/download.html It is NOT used by default. If you want to use it, use --with-fftw=DIR as a command line option to 'configure', where DIR denotes the directory into which FFTW was installed ('/lib' is appended for the library, '/include' for the include files). Using FFTW results in an about double as fast FFT function. Take care that you have to compile the "normal" and the "single" version of the library (resp. libfftw3.a and libfftw3f.a). First one is the default. You have to activate the single flag (./configure --enable-single) when recompiling FFTw3. Please also notice that the test when runnig GDL configure "checking for fftw_malloc in -lfftw3... yes" will failed if libfftw3f.a is missing. As mentionned in the log. of ./configure, if FFTw is not used, the default (GSL) fft routine is used instead. WIDGETS: -------- GDL supports GUI (widget) programming (initial effort by Joel Gales rewritten by Gilles Duvert) using the wxWidgets library. It is required by default. If you don't want to use it, use --with-wxWidgets=no (configure) or -DWXWIDGETS=off (CMake) wxWidgets can be obtained from: http://www.wxwidgets.org/downloads The wxWidget version must be 2.8.1 or higher. Unfortunately the wxWidget implementation of the plplot graphic library has changed between plplot 5.9.9 and plplot 5.11, and there are incompatibilities between plplot versions ans wxWidget versions. Stable behaviour has been obtained with plplot 5.9.9 and wxWidgets 2.8. The WIDGET_*... functions are all implemented (use HELP,/LIB for an overview). Only a few rarely seen options have not been written yet (please report in case of need). They have not been tested outside the linux "mageia" distribution yet, so errors and crashes are possible. Most procedures using widgets available (e.g., in the astrolib library) use so-called "compound widgets" (CW_xxxxx functions that are written in IDL, like CW_FIELD). Those have not been rewritten in GDL (and some have not been thoroughly tested). Those are not present in the GDL distribution (copyright issues), must be obtained separately (google is your friend) and put in the GDL path before use. DATA FORMATS: ============= HDF4 Files: ---------- The HDF4 format is (not completely yet) supported (thanks to Joel Gales). If you want to use it, you need the HDF library (here HDF always means version 4). Note that if you plan to use netCDF also, it might be necessary to install HDF4 before netCDF due to same named but different header files which are overwritten by the HDF4 version otherwise. HDF4 is required by default. If you don't want to use it, use --with-hdf=no (configure) or -DHDF=off (CMake) Note that HDF in turn needs other libraries. Check out the homepage for more information: http://hdf.ncsa.uiuc.edu/ The HDF library can be downloaded from: ftp://ftp.ncsa.uiuc.edu/HDF/HDF/HDF_Current HDF5: ----- Basic support for HDF5 is now provided (thanks to Peter Messmer). If you want to use it, you need the HDF5 library. It is required by default. If you don't want to use it, use --with-hdf5=no (configure) or -DHDF5=off (CMake) Note that HDF5 in turn needs other libraries. Check out the homepage for more information: http://hdf.ncsa.uiuc.edu/HDF5 The HDF5 library can be downloaded from: ftp://ftp.ncsa.uiuc.edu/HDF/HDF5/current NETCDF: ------- The netCDF format is fully supported (thanks to Christopher Lee). If you want to use netCDF, you need the netCDF library (even if HDF4 is used, the netCDF library is needed, as the HDF library does not contain all needed netCDF functions. Note that it might be necessary to install netCDF after HDF4 due to same named, but different header files. If the header files of HDF4 and netCDF are in different directories make sure, that the directory containing netCDF's version gets searched first, ie. put an explicit path for netCDF even if it is in the default include path, eg: --with-netcdf=/usr (configure) or -DNETCDFDIR=/usr (CMake)) netCDF is used by default. If you don't want to use it, use --with-netcdf=no (configure) or -DNETCDF=off (CMake) as a command line option to 'configure'. netCDF is available from: ftp://ftp.unidata.ucar.edu/pub/netcdf From the HDF4 INSTALL file: To use the HDF/MFHDF libraries (libdf.a, libmfhdf.a) with the original netCDF library (libnetcdf.a), the HDF4 distribution must be configured with the --disable-netcdf configuration flag. This will rename the HDF version of the C interface (ncxxx) of the HDF4 netCDF APIs to sd_ncxxx and will disable the HDF4 NC Fortran interfaces to avoid name clashes with the original netCDF C and Fortran APIs from libnetcdf.a. IMAGE FORMATS: -------------- In order to read and write images in several formats (e.g. JPEG, PNG), GDL uses ImageMagick. It is required by default. If you don't want to use it, use --with-Magick=no ImageMagick can be obtained from: http://www.imagemagick.org/www/download.html MAP PROJECTIONS and GEOPHYSICS: ---------------- GDL contains now a complete support to MAP projection, using the proj4 or libproj library. Please see MAP_INSTALL file. It is NOT used by default. If you want to use it, use --with-libproj4=DIR GDL uses GSHHS to implement MAP_CONTINENTS - see MAP_INSTALL (optional) PYTHON INTERFACE: ----------------- GDL has an interface to python (see http://www.python.org). GDL can be used as a python module and python can be used from within GDL. See INSTALL for details on how to build each version. As so far there are only two example GDL extensions written in python its use is optional for now but required by default. If you don't want to use it, use --with-python=no as a command line option to 'configure'. If you want to use it you need python and the python package Numpy. (http://numpy.scipy.org/). The GDL configure script will determine the installed python version automatically. For this the python executable must be installed. The python version can be explictely set with --enable-python_version=VERSION# (eg. --enable-python_version=2.3). Note: For embedding python as it is done by GDL, the python dynamic library is needed which is *not* build by default. You need to run 'configure' for python with the '--enable-shared' option. Please see the python README file for details. For nice graphical output the python package matplotlib (http://matplotlib.sourceforge.net) is used in one of the examples. See the file PYTHON.txt for more details. OTHER SUPPORT LIBRARIES: ------------------------ GDL supports unit converion in IMSL_CONSTANT using the UDUNITS-2 library (http://www.unidata.ucar.edu/software/udunits/) If you want to use it, use --with-udunits=DIR GDL supports the GRIB file format - see README_GRIB (optional) GDL uses pslib for fine-tuning PostScript output. (optional) GDL 0.9 was developed using ANTLR 2.7, but unless you want to change the grammar (*.g files) you don't need ANTLR (for building GDL). All relevant ANTLR files are included in the package. For editing however, there are several antlr-grammar (*.g) files among the sources. ANTLR generates from this grammar-files c++ source files. ANTLR generated files should not be changed directly as the changes would be undone if someone regenerates those files. Instead the relevant grammar file (mentioned in the header of the generated file) must be edited and run through ANTLR. All source files generated by ANTLR start with a capital character. All regular source files start with a small character. For more information on ANTRL see: http://www.antlr.org GDL is developed by some using NetBeans (https://netbeans.org/) although a KDevelop project file is included in the tarball, so if you have KDevelop you should be able to use it with GDL seamlessly. INSTALLATION: ============= Please see the *INSTALL* file(s) for details. For an alternative installation using CMake see INSATLL.CMake . For french readers, please have a look to http://aramis.obspm.fr/~coulais/IDL_et_GDL/memo_GDL.html which explain how to install GDL and most libraries from scratch and without being root. CONTRIBUTIONS: ============== GDL 0.9 is actively developed, but due to the vast amount of subroutines to implement, GDL is still in beta state. Even though it is commonly used by clever people for several tasks, there are many things to be done. Bug reports, feedback in general and interested people who would like to join this project are welcome. Extensions to GDL can be made in C++, GDL or python. Urgent things to do are: THE DOCUMENTATION! Testing and test routines written in GDL, HACKING: ======== please see file HACKING for details. There you find also information about LINKIMAGE. CONTACT: ======== Comments are welcome. Let me know what you use GDL for. Or if you don't, why not. Which functionality are you missing/would appreciate most for comming versions. For bug reports, complaints, suggestions and comments, please use the issue-tracking tool at: https://github.com/gnudatalanguage/gdl LICENSE: ======== 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 2 of the License, 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. (It should be included in this package in the file COPYING ) gdl-0.9.9/README.GRIB000066400000000000000000000122541340051421000136730ustar00rootroot00000000000000GRIB file format support in GDL is implemented using the ECMWF ecCodes library (the legacy ECMWF GRIB_API library is supported as well). Naming of GDL routines resembles the one from F90 GRIB API interface (it was developed prior to appearance of GRIB support in IDL). The routines are not documented for the moment so please: - refer to ecCodes API manual for explanation, - look in the testsuite/test_grib.pro file for an example of usage, - read the following few lines. Currently the followng routines are implemented: * GRIB files related: file_id = grib_open_file(filename) | opens a file and returns an id that is used to refer to it grib_count_in_file(file_id) | returns the number of messages in file grib_close_file, file_id | closes a file * GRIB messages related: | mesg_id = grib_new_from_file(file_id) | decodes a message into memory (multiple calls yield subsequent messages) grib_release, mesg_id | frees the decoded message from memory mesg_id = grib_clone(another_mesg_id) | clones a message * routines for extracting data from GRIB messages: | grib_get, mesg_id, keyname, values | extracts data associated with "keyname" into variable _values_ grib_get_data, mesg_id, lats, lons, data | extracts the "values" key into variable _data_ placing the latitude, | longitude values in variables _lats_ and _lons_ grib_get_size, mesg_id, keyname | returns number of elements in the "keyname" In the above list: - mesg_id, file_id are id numbers similiar to these returned by ncdf_open or hdf_sd_start - keyname is a string, for example "values" or "numberOfPointsAlongAParallel" - lats, lons, values are ment to be identifiers of variables that will be fed with data The table below tries to summarize how the GDL interface relates to Fortran and C interfaces. (the table is still not complete) ._ this column shows if the routine is implemented in GDL / (,,!'' indicates known problems with implementation) | --- | ---------------------------------------------------------------------- | V GDL fun/pro | F90 counterpart | C routines called ---------------------------------------------------------------------------- F | + grib_open_file() | grib_open_file | fopen I | - /ro, /rw | mode | L | + grib_close_file() | grib_close_file | fclose E | + grib_count_in_file() | grib_count_in_file | grib_count_in_file ---------------------------------------------------------------------------- M | + grib_new_from_file | grib_new_from_file | grib_handle_new_from_file E | - grib_new_from_message | grib_new_from_message | grib_handle_new_from_message (...multi_message?, ..._message_copy) S | - grib_new_from_template | grib_new_from_template | grib_handle_new_from_template S | + grib_release | grib_release | grib_handle_delete A | + grib_clone | grib_clone | grib_handle_clone G | ! grib_get_message_size | E | - grib_copy_message | | - grib_write | ---------------------------------------------------------------------------- D | + grib_get_data | grib_get_data | grib_iterator_new A | + | | grib_iterator_next T | + | | grib_iterator_delete A | + | | ... GDL::grib_get_data | - /float | grib_get_data_real4 | | - /double | grib_get_data_real8 | | + grib_get_size | | - grib_get_offset | - grib_get_element | + grib_get | grib_get | grib_get_long | + | | grib_get_long_array | + | | grib_get_double | + | | grib_get_double_array | - missing= | grib_set_missing | | - offset=, count= | grib_get_element | | - grib_set | grib_set | ------------------------------------------------------------------------ N | | grib_find_nearest E | A | R | E | S | T | ------------------------------------------------------------------------ K | - grib_keys | grib_keys_iterator_new E | - | grib_keys_iterator_next Y | - | grib_keys_iterator_delete S | - | grib_keys_iterator_get_name | - | grib_keys_iterator_rewind | - /skip_readonly | grib_skip_readonly | - /skip_duplicates | grib_skip_duplicates | - /skip_coded | grib_skip_coded | - /skip_computed | grib_skip_computed ------------------------------------------------------------------------ N | | grib_check | / | | grib_dump | A | | gdl-0.9.9/README.md000066400000000000000000000275701340051421000135570ustar00rootroot00000000000000[![Linux/OSX Build Status](https://travis-ci.org/gnudatalanguage/gdl.svg?branch=master)](https://travis-ci.org/gnudatalanguage/gdl) [![Windows Build status](http://ci.appveyor.com/api/projects/status/github/gnudatalanguage/gdl?branch=master&svg=true)](https://ci.appveyor.com/project/slayoo/gdl/branch/master) [![Coverage Status](https://img.shields.io/codecov/c/github/gnudatalanguage/gdl/master.svg)](https://codecov.io/github/gnudatalanguage/gdl?branch=master) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/e5de1c1571c649279dad18d5d8590789)](https://www.codacy.com/app/slayoo/gdl?utm_source=github.com&utm_medium=referral&utm_content=gnudatalanguage/gdl&utm_campaign=Badge_Grade) [![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) GDL - GNU Data Language ======================= GDL is a free/libre/open source incremental compiler compatible with IDL (Interactive Data Language) and to some extent with PV-WAVE. Together with its library routines it serves as a tool for data analysis and visualization in such disciplines as astronomy, geosciences and medical imaging. GDL development had been started by **Marc Schellens** back in early noughties and has since continued with help of a team of maintainers, developers, packagers and thanks to feedback from users. IDL is a registered trademark of [Harris Geospatial Solutions](https://www.harrisgeospatial.com). PV-WAVE is a product of [Rogue Wave Software](https://www.roguewave.com). Overview -------- GDL is a domain-specific programming language and a data analysis environment. As a language, it is dynamically-typed, array-oriented, vectorised and has object-oriented programming capabilities. GDL library routines handle numerical calculations, data visualisation, signal/image processing, interaction with host OS and data input/output. GDL supports several data formats such as netCDF, HDF4, HDF5, GRIB, PNG, TIFF, DICOM, etc. Graphical output is handled by X11, PostScript, SVG or z-buffer terminals, the last one allowing output graphics (plots) to be saved in a variety of raster graphics formats. GDL features integrated debugging facilities. The built-in widget functionality enables development of GUI-based software. GDL has also a Python bridge (Python code can be called from GDL; GDL can be compiled as a Python module). Development and maintenance of GDL is carried out targeting Linux, BSD, OSX and Windows (MinGW, Cygwin). Other open-source numerical data analysis tools similar to GDL include [SciPy](http://www.scipy.org/), [GNU Octave](http://www.gnu.org/software/octave/), [Scilab](http://www.scilab.org/), [PDL](http://pdl.perl.org/), [NCL](http://www.ncl.ucar.edu/), [R](http://www.r-project.org/), [Yorick](http://yorick.sourceforge.net/). Dependencies and package availability ------------------------------------- Packaged versions of GDL are available for several Linux distributions, BSD and Mac OS X. Please note that several features of GDL depend on compile-time configuration, and might not be available in pre-built or pre-configured packages. The table below summarises GDL mandatory and optional dependencies along with the availability of the optional functionalities in packages (as of April 2018): | | [Fedora](https://src.fedoraproject.org/rpms/gdl) | [Debian](https://packages.debian.org/sid/gnudatalanguage) | [Ubuntu](http://packages.ubuntu.com/gnudatalanguage) | [Gentoo](https://packages.gentoo.org/packages/dev-lang/gdl) | [Arch](https://aur.archlinux.org/packages/gnudatalanguage/) | [FreeBSD](https://svnweb.freebsd.org/ports/head/science/gnudatalanguage/) | [Homebrew](https://github.com/brewsci/homebrew-science/blob/master/Formula/gnudatalanguage.rb) | [Macports](https://github.com/macports/macports-ports/tree/master/math/gnudatalanguage) | | --------------------------------------------------------------------------------------- | :----: | :--------: | :----: | :----: | :---: | :-------: | :------: | :------: | | latest release | 0.9.8 | 0.9.8 | 0.9.8 | 0.9.6 | 0.9.7 | 0.9.8 | 0.9.7 | 0.9.7 | | [readline](http://thrysoee.dk/editline/)/[editline](http://thrysoee.dk/editline/) | + (r) | + (r) | + (r) | + (r) | + (r) | + (r) | + (r) | + | | [\[n\]curses](https://www.gnu.org/software/ncurses/) | + (n) | + (n) | + (n) | + (n) | + | + (n) | + (n) | + (n) | | [zlib](https://zlib.net/) | + | + | + | + | + | + | + | + | | [GSL](https://www.gnu.org/software/gsl/) | + | + | + | + | + | + | + | + | | [plplot](https://plplot.sourceforge.net) | + | + | + | + | + | + | + | + | | [OpenMP](http://www.openmp.org/) | + | + | + | + | + | + | - | + | | [Magick++](https://imagemagick.org/) / [GraphicsMagick](http://graphicsmagick.org/) | + (G) | + (G) | + (G) | + (G/I) | - | + (G) | + (G) | + (G) | | [wxWidgets](https://www.wxwidgets.org/) | + | + | + | + | + | + | - | - | | [netCDF](https://www.unidata.ucar.edu/software/netcdf/) | + | + | + | + | + | + | + | + | | [HDF4](https://support.hdfgroup.org/products/hdf4/) | + | + | + | + | - | - | - | + | | [HDF5](https://support.hdfgroup.org/HDF5/) | + | + | + | + | - | + | + | + | | [FFTW](http://www.fftw.org/) | + | + | + | + | + | + | + | + | | [PROJ.4](http://proj4.org/) | - | - | - | + | - | + | - | + | | [GSHHG](http://www.soest.hawaii.edu/wessel/gshhg/) | - | - | - | + | - | - | - | + | | [MPICH](https://www.mpich.org/) | - | - | - | - | - | + | - | + | | [Python](https://www.python.org/)/[NumPy](http://www.numpy.org/) | + | + | + | + | + | + | - | + | | [udunits](https://www.unidata.ucar.edu/software/udunits/) | + | + | + | + | + | + | + | + | | [Eigen](https://eigen.tuxfamily.org/) | + | + | + | + | + | + | + | + | | [pslib](http://pslib.sourceforge.net/) | + | + | + | + | + | + | - | + | | [ecCodes](https://software.ecmwf.int/wiki/display/ECC/ecCodes+Home)/[GRIB](https://software.ecmwf.int/wiki/display/GRIB) | + | + | + | + | + | + | - | + | | [GLPK](https://www.gnu.org/software/glpk/) | - | - | - | - | - | + | - | - | | [Python](https://www.python.org/) module | + (python2-gdl) | + ([python-gdl](https://packages.debian.org/python-gdl)) | + ([python-gdl](https://packages.ubuntu.com/python-gdl)) | + | - | - | - | - | Build-time dependencies ----------------------- Build and test automation is carried out using [CMake](http://cmake.org/). GDL interpreter has been developed using [ANTLR v2](http://www.antlr2.org) but unless you want to change the grammar (\*.g files) you don't need ANTLR. All relevant ANTLR files are included in the source tree. Support, feedback and contributions ----------------------------------- Your comments are welcome! Let us know what you use GDL for. Or if you don't, why not. Which functionality are you missing/would appreciate most for coming versions. Please use the github issue-tracking system to report bugs, complaints, suggestions and comments. Code enhancements in the form of pull requests are very welcome! Note that contributions can be made in C++, IDL/GDL or Python, as well as by providing enhancements and extensions of the README files, diagnostic messages, etc. Among the major challenges GDL development is facing currently, there are: - [enhancing test coverage](https://codecov.io/github/gnudatalanguage/gdl?branch=master) by writing test programs in GDL - streamlining development and maintainance of GDL reference docs and examples (using the [Jupyter kernel](https://github.com/gnudatalanguage/idl_kernel)?) - bringing in into the team the needed know-how to address the [backlog of ANTLR-related issues](https://github.com/gnudatalanguage/gdl/labels/antlr) - increasing presence within and interoperability with the Python ecosystem, including adding support for Python 3 (calling GDL from Python 2 and calling Python 2 from GDL is already implemented!) Help welcome! Information resources --------------------- As GDL is aimed as a drop-in replacement for IDL, resources for IDL constitute valuable sources of information for GDL users as well. These include: - the [official IDL documentation](https://www.harrisgeospatial.com/docs/) - the [idl-pvwave Google Group](https://groups.google.com/forum/#!forum/idl-pvwave) - the [comp.lang.idl-pvwave usenet group archives](http://www.idlcoyote.com/comp.lang.idl-pvwave/) (dating back to 1991!) - Wikipedia article on [IDL](https://en.wikipedia.org/wiki/IDL_\(programming_language\)) and references therein - websites of IDL gurus including [David Fanning](http://www.idlcoyote.com/) and [Michael Galloy](http://michaelgalloy.com/) - numerous [tutorials and lecture notes](https://www.google.com/search?q=interactive+data+language) introducing IDL There are several open source packages compatible or interoperable with GDL, including: - the [MPFIT]() curve fitting library written in IDL (also available as a [Debian package](https://packages.debian.org/gdl-mpfit)) - the [IDL Astronomy User's Library](https://idlastro.gsfc.nasa.gov/) written in IDL (also available as a [Debian package](https://packages.debian.org/gdl-idlastro)) - the [Coyote](https://www.idlcoyote.com) library of IDL-written utilities (also available as a [Debian package](https://packages.debian.org/gdl-coyote)) - the [TeXtoIDL](http://physics.mnstate.edu/craig/textoidl/) package - the [gdlde](https://github.com/gnudatalanguage/gdlde) IDE - the [IDL/GDL Jupyter kernel](https://github.com/gnudatalanguage/idl_kernel) - the [IDLWAVE Emacs mode](https://www.gnu.org/software/emacs/manual/html_mono/idlwave.html) - IDL [syntax highlighting module for Vim](https://github.com/vim/vim/blob/master/runtime/syntax/idlang.vim) - the [SingleCompile extension for Vim](https://github.com/vim-scripts/SingleCompile) Alain Coulais maintains the [GDL-accounces mailing list](https://sympa.obspm.fr/wws/info/gdl-announces). There have been quite some [mentions of GDL in scientific literature](https://scholar.google.com/scholar?q="gnu+data+language") which also provide example use cases. The Coulais et al. papers from the ADASS conferences are the best way to cite GDL as of now. Acknowledgements ---------------- GDL development had been carried out at [SourceForge](http://sourceforge.net/) in years 2003-2018 - thank you! gdl-0.9.9/appveyor.yml000066400000000000000000000745211340051421000146660ustar00rootroot00000000000000image: Visual Studio 2015 branches: only: - master clone_folder: c:\projects\gdl configuration: - Release - Debug environment: matrix: - platform: mingw64630i686 # - platform: mingw64630x8664 # 64bit unsupported yet matrix: fast_finish: true init: - git config --global core.autocrlf input install: - ren "C:\Program Files\Git\usr\bin\sh.exe" _sh.exe - ps: >- if ($env:platform -Match "mingw64630i686") { $env:PATH="C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin;$env:PATH" md c:\projects\gdl\win32libs md c:\projects\gdl\win32libs\bin md c:\projects\gdl\win32libs\lib md c:\projects\gdl\win32libs\include # Python $env:PYTHON_ROOT="C:\Python27" # WxWidgets cd c:\projects\gdl\win32libs appveyor DownloadFile https://github.com/wxWidgets/wxWidgets/releases/download/v3.0.4/wxWidgets-3.0.4.7z 7z x wxWidgets-3.0.4.7z -y -o"wxWidgets-3.0.4" cd c:\projects\gdl\win32libs\wxWidgets-3.0.4\build\msw #GD : try to add UNICODE=1 as this is reported as useful. mingw32-make SHELL=cmd -f makefile.gcc setup_h BUILD=release UNICODE=1 SHARED=1 USE_GUI=1 USE_XRC=0 USE_HTML=0 USE_WEBVIEW=0 USE_MEDIA=0 USE_AUI=0 USE_RIBBON=0 USE_PROPGRID=0 USE_RICHTEXT=0 USE_STC=0 USE_OPENGL=0 VENDOR=gdl DEBUG_FLAG=1 mingw32-make SHELL=cmd -f makefile.gcc -j4 BUILD=release UNICODE=1 SHARED=1 USE_GUI=1 USE_XRC=0 USE_HTML=0 USE_WEBVIEW=0 USE_MEDIA=0 USE_AUI=0 USE_RIBBON=0 USE_PROPGRID=0 USE_RICHTEXT=0 USE_STC=0 USE_OPENGL=0 VENDOR=gdl DEBUG_FLAG=1 # a strange problem when building wxWidgets is that some characters mysterioulsy disappear from the make-generated commands. #inserting lines as below is not a solution as the characters disappearing are changing! # let's however make it find the silly 'coredll_headerctrlgo' file : copy c:\projects\gdl\win32libs\wxWidgets-3.0.4\build\msw\gcc_mswudll\coredll_headerctrlg.o c:\projects\gdl\win32libs\wxWidgets-3.0.4\build\msw\gcc_mswudll\coredll_headerctrlgo #and try to finsih build: mingw32-make SHELL=cmd -f makefile.gcc -j4 BUILD=release UNICODE=1 SHARED=1 USE_GUI=1 USE_XRC=0 USE_HTML=0 USE_WEBVIEW=0 USE_MEDIA=0 USE_AUI=0 USE_RIBBON=0 USE_PROPGRID=0 USE_RICHTEXT=0 USE_STC=0 USE_OPENGL=0 VENDOR=gdl DEBUG_FLAG=1 $env:WXWIDGETS_ROOT="c:\projects\gdl\win32libs\wxWidgets-3.0.4" # BSD-XDR cd c:\projects\gdl\win32libs appveyor DownloadFile https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/bsd-xdr/bsd-xdr-1.0.0.tar.gz tar zxf bsd-xdr-1.0.0.tar.gz cd bsd-xdr-1.0.0 sed -i 's/%hh/%/g' src\test\test_data.c md mingw md mingw\lib mingw32-make -f Makefile -j4 PLATFORM=mingw STAMP=clean TEST_PROGS="" top_srcdir="c:\projects\gdl\win32libs\bsd-xdr-1.0.0" recursive-all mv mingw\libxdr.dll.a c:\projects\gdl\win32libs\lib mv rpc c:\projects\gdl\win32libs\include mv mingw\mgwxdr-0.dll c:\projects\gdl\win32libs\bin # PLplot cd c:\projects\gdl\win32libs appveyor DownloadFile http://downloads.sourceforge.net/project/plplot/plplot/5.13.0%20Source/plplot-5.13.0.tar.gz tar zxf plplot-5.13.0.tar.gz md plplot-5.13.0/build cmake "plplot-5.13.0" "-Bplplot-5.13.0/build" -G "MinGW Makefiles" "-DCMAKE_BUILD_TYPE=$($env:CONFIGURATION)" -DCMAKE_CXX_FLAGS_RELEASE='-O3' -DCMAKE_INSTALL_PREFIX=c:\projects\gdl\win32libs -DOLD_WXWIDGETS:BOOL=ON -DENABLE_wxwidgets:BOOL=ON -DwxWidgets_LIB_DIR=$env:WXWIDGETS_ROOT\lib\gcc_dll -DwxWidgets_CONFIGURATION=mswu -DENABLE_MIX_CXX=ON cd plplot-5.13.0/build mingw32-make -j4 mingw32-make install # Eigen cd c:\projects\gdl\win32libs appveyor DownloadFile https://bitbucket.org/eigen/eigen/get/3.3.4.tar.bz2 -FileName eigen-eigen-5a0156e40feb.tar.bz2 tar jxf eigen-eigen-5a0156e40feb.tar.bz2 md eigen-eigen-5a0156e40feb/build cmake "eigen-eigen-5a0156e40feb" "-Beigen-eigen-5a0156e40feb/build" -G "MinGW Makefiles" "-DCMAKE_BUILD_TYPE=$($env:CONFIGURATION)" -DCMAKE_INSTALL_PREFIX=c:\projects\gdl\win32libs cd eigen-eigen-5a0156e40feb/build mingw32-make install # GSL cd c:\projects\gdl\win32libs appveyor DownloadFile http://ftpmirror.gnu.org/gsl/gsl-2.4.tar.gz tar zxf gsl-2.4.tar.gz c:\msys64\usr\bin\bash.exe -lc 'export PATH=$PATH:/c/mingw-w64/i686-6.3.0-release-posix-dwarf-rt_v5-rev1/mingw32/bin && export LDFLAGS=-L/c/mingw-w64/i686-6.3.0-release-posix-dwarf-rt_v5-rev1/mingw32/i686-w64-mingw32/lib && export CPPFLAGS=-I/c/mingw-w64/i686-6.3.0-release-posix-dwarf-rt_v5-rev1/mingw32/i686-w64-mingw32/include && cd /c/projects/gdl/win32libs/gsl-2.4 && ./configure --build=i686-w64-mingw32 --host=i686-w64-mingw32 --prefix /c/projects/gdl/win32libs && make -j4 && make install' # GNUWin32 (GNU Readline, Zlib, libPNG, PCRE, libtiff) # TODO: Find appropriate libtiff with TIFFField, TIFFFieldWithTag and TIFFFieldName (and libgeotiff?) # (Remember to remove -DTIFF=OFF -DGEOTIFF=OFF from build_script when done) cd c:\projects\gdl\win32libs appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/readline/5.0-1/readline-5.0-1-lib.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/zlib/1.2.3/zlib-1.2.3-lib.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/libpng/1.2.37/libpng-1.2.37-lib.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/pcre/7.0/pcre-7.0-lib.zip #appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/tiff/3.8.2-1/tiff-3.8.2-1-lib.zip 7z x readline-5.0-1-lib.zip 7z x zlib-1.2.3-lib.zip 7z x libpng-1.2.37-lib.zip 7z x pcre-7.0-lib.zip #7z x tiff-3.8.2-1-lib.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/readline/5.0-1/readline-5.0-1-bin.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/zlib/1.2.3/zlib-1.2.3-bin.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/libpng/1.2.37/libpng-1.2.37-bin.zip appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/pcre/7.0/pcre-7.0-bin.zip #appveyor DownloadFile https://downloads.sourceforge.net/project/gnuwin32/tiff/3.8.2-1/tiff-3.8.2-1-bin.zip 7z x readline-5.0-1-bin.zip -y 7z x zlib-1.2.3-bin.zip -y 7z x libpng-1.2.37-bin.zip -y 7z x pcre-7.0-bin.zip -y #7z x tiff-3.8.2-1-bin.zip -y } # - if %platform%==mingw64630x8664 set PATH=C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw32\bin;%PATH% # - if %platform%==mingw64630x8664 set PYTHON_ROOT=C:\Python27-x64 before_build: # disabling tests that failed from the get-go on Windows (temporarily!) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_3300626.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_3275334.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_3104214.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_2876161.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_2610174.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_1779553.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_3394430.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_3595172.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_635.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_709.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_719.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_n000587.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_n000608.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bug_n000720.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_byte_conversion.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_bytscl.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_call_external.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_chisqr_cvf.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_clip.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_congrid.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_constants.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_container.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_contour.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_correlate.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_device.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_dicom.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_execute.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_extra_keywords.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_fft_dim.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_basename.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_copy.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_fft_leak.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_dirname.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_lines.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_move.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_test.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_file_which.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_fix.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_finite.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_fixprint.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_formats.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_fx_root.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_fz_roots.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_gc.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_get_lun.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_get_screen_size.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_gh00178.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_hist_2d.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_idlneturl.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_indgen.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_interpol.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_l64.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_la_least_squares.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_ludc_lusol.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_make_dll.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_math_function_dim.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_matrix_multiply.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_memory.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_message.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_moment.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_multiroots.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_obj_isa.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_obj_new.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_plot_oo.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_plot_ranges.pro' -NotMatch) #AC 2018 : should be OK now - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_plot_usersym.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_plotting_ranges.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_pmulti.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_point_lun.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_postscript.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_product.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_ps_decomposed.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_python.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_image_statistics.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_n_tags.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_nans_in_sort_and_median.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_nestedloop.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_parse_url.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_python_module_0.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_python_module_1.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_python_module_2.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_qhull.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_random.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_readf.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_resolve_routine.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_same_name.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_simplex.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_spawn_unit.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_spher_harm.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_spl_init.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_step.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_str_sep.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_stregex.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_strmatch.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_strsplit.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_structures.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_systime.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_tic_toc.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_total.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_rounding.pro' -NotMatch) #AC 2018 : should be OK now? Not at all! - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_tv.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_typename.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_wait.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_wavelet.pro' -NotMatch) #GD: works now # - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_where.pro' -NotMatch) #AC 2018 : should be OK now ? NOPE! - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_window_background.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_wordexp.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_zeropoly.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_zip.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_delvarrnew.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_list.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_obj_valid.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_make_array.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_ptr_valid.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_binfmt.pro' -NotMatch) - ps: Set-Content -Path "C:\projects\gdl\testsuite\Makefile.am" -Value (get-content -Path "C:\projects\gdl\testsuite\Makefile.am" | Select-String -Pattern 'test_tiff.pro' -NotMatch) build_script: - cd c:\projects - md c:\projects\gdl\build - set CMAKE_LIBRARY_PATH=c:\projects\gdl\win32libs\lib - set CMAKE_INCLUDE_PATH=c:\projects\gdl\win32libs\include - cmake gdl -Bc:\projects\gdl\build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_CXX_FLAGS_RELEASE="-O3 -DNDEBUG" -DCMAKE_CXX_FLAGS="-Werror" -DWXWIDGETSDIR=%WXWIDGETS_ROOT% -DCMAKE_INSTALL_PREFIX:PATH=c:\projects\gdl\install\gdl -DGRAPHICSMAGICK=OFF -DMAGICK=OFF -DPSLIB=OFF -DNETCDF=OFF -DHDF=OFF -DHDF5=OFF -DFFTW=OFF -DGSHHS=OFF -DPYTHON=OFF -DTIFF=OFF -DGEOTIFF=OFF - cd c:\projects\gdl\build - mingw32-make -j4 - mingw32-make install # tests # TODO: copy those to the artefact dir - set PATH=%PATH%;C:/projects/gdl/win32libs/lib - set PATH=%PATH%;C:/projects/gdl/win32libs/bin - set PATH=%PATH%;C:/projects/gdl/win32libs/wxWidgets-3.0.4/lib/gcc_dll - set PATH=%PATH%;C:/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/i686-w64-mingw32/lib - mingw32-make check on_failure: - ps: cat c:\projects\gdl\build\testsuite\Testing\Temporary\LastTest.log after_build: - robocopy /move /e c:\projects\gdl\win32libs\bin c:\projects\gdl\install\gdl\bin || exit 0 - copy C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin\*.dll c:\projects\gdl\install\gdl\bin - cd c:\projects\gdl\install - 7z a gdl_build.zip gdl artifacts: - path: install\gdl_build.zip name: GDL deploy: release: gdl-master-build$(appveyor_build_version) description: 'Test release' provider: GitHub auth_token: secure: IhTPN2ggVb/gSjAnDAGleGO8+QQJETWjbuNtAvwQcJgEzKcZK944bMDIxSuLASgw draft: false prerelease: false on: branch: master # release from master branch only appveyor_repo_tag: true # deploy on tag push only #on_finish: # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) gdl-0.9.9/config.h.cmake000066400000000000000000000042051340051421000147630ustar00rootroot00000000000000#ifndef __CONFIG_H__ #define __CONFIG_H__ #define EXEC_PREFIX "@CMAKE_INSTALL_PREFIX@" #define GDLDATADIR "@CMAKE_INSTALL_PREFIX@@GDL_DATA_DIR@" #define VERSION "@VERSION@" #define _CRT_SECURE_NO_WARNINGS #cmakedefine HAVE_X 1 #cmakedefine HAVE_64BIT_OS 1 #cmakedefine HAVE_DLFCN_H 1 #cmakedefine HAVE_GSHHS_H 1 #cmakedefine HAVE_INTTYPES_H 1 #cmakedefine HAVE_LIBCURSES 1 #cmakedefine HAVE_LIBGSL 1 #cmakedefine HAVE_LIBGSLCBLAS 1 #cmakedefine HAVE_LIBNCURSES 1 #cmakedefine HAVE_LIBPLPLOTCXXD 1 #cmakedefine HAVE_LIBREADLINE 1 #cmakedefine HAVE_LIBEDITLINE 1 #cmakedefine HAVE_LIBWXWIDGETS 1 #cmakedefine HAVE_LIBZ 1 #cmakedefine HAVE_LOCALE_H 1 #cmakedefine HAVE_SBRK 1 #cmakedefine HAVE_MALLINFO 1 #cmakedefine HAVE_MALLOC_H 1 #cmakedefine HAVE_MALLOC_MALLOC_H 1 #cmakedefine HAVE_MALLOC_ZONE_STATISTICS 1 #cmakedefine HAVE_MEMORY_H 1 #cmakedefine HAVE_NEXTTOWARD 1 #cmakedefine HAVE_PLPLOT_WIDTH 1 #cmakedefine PLPLOT_PRIVATE_NOT_HIDDEN 1 #cmakedefine PLPLOT_HAS_PLCALLBACK #define _WCHAR_H_CPLUSPLUS_98_CONFORMANCE_ 1 #ifndef HAVE_STDINT_H #cmakedefine HAVE_STDINT_H 1 #endif #ifndef HAVE_STDLIB_H #cmakedefine HAVE_STDLIB_H 1 #endif #ifndef HAVE_STRINGS_H #cmakedefine HAVE_STRINGS_H 1 #endif #ifndef HAVE_STRING_H #cmakedefine HAVE_STRING_H 1 #endif #ifndef HAVE_SYS_STAT_H #cmakedefine HAVE_SYS_STAT_H 1 #endif #ifndef HAVE_SYS_TYPES_H #cmakedefine HAVE_SYS_TYPES_H 1 #endif #ifndef HAVE_UNISTD_H #cmakedefine HAVE_UNISTD_H 1 #endif #ifndef HAVE_EXT_STDIO_FILEBUF_H #cmakedefine HAVE_EXT_STDIO_FILEBUF_H 1 #endif #cmakedefine OLD_DARWIN #cmakedefine PYTHON_MODULE 1 #cmakedefine RL_GET_SCREEN_SIZE 1 #cmakedefine STDC_HEADERS 1 #cmakedefine USE_FFTW 1 #cmakedefine USE_GRIB 1 #cmakedefine USE_GLPK 1 #cmakedefine USE_GSHHS 1 #cmakedefine USE_HDF 1 #cmakedefine USE_HDF5 1 #cmakedefine USE_LIBPROJ4 1 #cmakedefine USE_LIBPROJ4_NEW 1 #cmakedefine USE_MAGICK 1 #cmakedefine USE_MPI 1 #cmakedefine USE_NETCDF 1 #cmakedefine USE_NETCDF4 1 #cmakedefine USE_OPENMP 1 #cmakedefine USE_PYTHON 1 #cmakedefine USE_TIFF 1 #cmakedefine USE_GEOTIFF 1 #cmakedefine USE_UDUNITS 1 #cmakedefine USE_PSLIB 1 #cmakedefine USE_EIGEN 1 #cmakedefine USE_PNGLIB 1 #cmakedefine USE_X 1 #endif gdl-0.9.9/doc/000077500000000000000000000000001340051421000130325ustar00rootroot00000000000000gdl-0.9.9/doc/gdl.1000066400000000000000000000143141340051421000136650ustar00rootroot00000000000000.TH GDL 1 "2017-01-06" "The GDL Team" .SH NAME gdl \- GNU Data Language incremental compiler .SH SYNOPSIS .B gdl .RI [\-\-help] .RI [\-h] .RI [\-\-version] .RI [\-v] .RI [\-V] .RI [[\-]\-quiet] .RI [\-q] .RI [ \-arg value ] .RI [ \-args ... ] .RI [ \-e statement ] .RI [ \-pref=/path/to/preferenceFile ] .RI [ batch_file ... ] .SH DESCRIPTION .B gdl is an incremental compiler for the GNU Data Language (GDL). GDL is being developed with the aim of providing an open\-source drop\-in replacement for ITTVIS Interactive Data Language (IDL). It is also partially compatible with Visual Numerics (VN) PV\-WAVE. IDL and PV\-WAVE are registered trademarks of ITTVIS and VN, respectively. GDL and its library routines are designed as a tool for numerical data analysis and visualisation. GDL is dynamically typed, vectorized and has object\-oriented programming capabilities. The library routines handle numerical calculations, data visualisation, signal/image processing, file input/output (incl. graphical and scientific data formats such as TIFF, PNG, netCDF, HDF etc) and interaction with host OS. Information on GDL/IDL/PV\-WAVE syntax and library routines can be found in e.g.: \- GDL documentation draft at: http://gnudatalanguage.sf.net/gdl.pdf \- IDL manual on\-line @ NASA.gov: http://idlastro.gsfc.nasa.gov/idl_html_help/home.html \- ITTVIS (ittvis.com) and Visual Numerics (vni.com) websites \- comp.lang.idl\-pvwave newsgroup \- newsletter at: https://sympa.obspm.fr/wws/info/gdl-announces A vast part of GDL library routines is implemented using open\-source libraries including GSL, plPlot, and optionally: readline, FFTW, Eigen3, ImageMagick, netCDF, HDF4, HDF5, libproj4, UDUNITS\-2, libps and others. .SH OPTIONS .TP .B \-\-help (or \-h) Show summary of options .TP .B \-\-version (or \-v, \-V) Show version of program .TP .B \-\-quiet (or \-quiet, \-q) Suppress welcome messages .TP .B \-arg value Tells COMMAND_LINE_ARGS() to report the following argument (may be specified more than once) .TP .B \-args ... Tells COMMAND_LINE_ARGS() to report all following arguments .TP .B \-e statement Execute given statement and exit (last occurance taken into account only, executed after startup file, may not be specified together with batch files) .TP .B \-pref=/path/to/PreferenceFile (only partially working now) setting using external text file few variables including default preferences (e.g. X11 Windows Size) .TP .B \-\-fakerelease version setting !VERSION.RELASE to that value. !VERSION.RELASE is often tested by procedures to decide whether some function or option should be used. It is sometimes possible to use this option to fool a procedure that request a specific value of !VERSION.RELEASE .TP The \-demo, \-em, \-novm, \-queue, \-rt, \-ulicense and \-vm options are ignored for compatibility with IDL. .TP A list of batch files to be executed before entering the interactive mode (but after executing a startup file, if specified) may be given when not using the \-e option. .SH FILES .TP .B $DATADIR/gnudatalanguage/lib/*.pro Library routines implemented in GDL. $DATADIR is specified during compilation and usually translates to /usr/share, /usr/local/share or alike. GDL includes this directory in its search path unless GDL_PATH or IDL_PATH env. variables are set (see below). .TP .B $HOME/.gdl/history A file used for storing the history of commands issued in the interactive mode .SH ENVIRONMENT The following environment variables have special meaning to .BR gdl . The .B GDL_* variant, if defined, takes precedence over any corresponding .B IDL_* variant. .TP .B GDL_PATH, IDL_PATH The GDL command (script) search path. .TP .B GDL_STARTUP, IDL_STARTUP A file of commands to be executed on startup. .TP .B GDL_TMPDIR, IDL_TMPDIR A directory in which temporary files may be created. .TP .B HOME, SHELL Variables influencing shell invocations from within GDL (SPAWN procedure and the $ interpreter command). Value of HOME determines as well the location of the GDL history\-file. .TP .B PATH Determines search path when spawning child processes using the SPAWN procedure with the /NOSHELL keyword set. .TP .B PYTHONPATH Influences behaviour of PYTHON procedure and PYTHON() function (available if GDL is compiled with support for calling Python code) .TP .B GDL_MPI A message to be sent out using MPI_Send before initialization of the interpreter (available if GDL is compiled with support for MPI) .TP .B DISPLAY, XENVIRONMENT Tell GDL how to connect to the X server .TP .B PLPLOT_DRV_DIR Override the default location of PLplot dynamic drivers. .TP .B LC_* The locale\-related settings accessible via LOCALE_GET() (GDL always uses the C locale internally) .TP .B GDL_GR_WIN_HEIGHT Sets the preference for the default height of a Windows(tm) graphic window .TP .B GDL_GR_WIN_QSCREEN if set to true (1) this will prevent the use of the GDL_GR_WIN_HEIGHT and GDL_GR_WIN_WIDTH preferences and the default dimensions of graphic windows will be 1/4 of the screen dimensions .TP .B GDL_GR_WIN_WIDTH Sets the preference for the default width of a Windows(tm) graphic window .TP .B GDL_GR_X_HEIGHT Sets the preference for the default height of an X11 graphic window .TP .B GDL_GR_X_QSCREEN if set to true (1) this will prevent the use of the GDL_GR_X_HEIGHT and GDL_GR_X_WIDTH preferences and the default dimensions of graphic windows will be 1/4 of the screen dimensions .TP .B GDL_GR_X_WIDTH Sets the preference for the default width of an X11 graphic window .TP .B GDL_WX_BACKEND can be set to [0,1,2] which will select, respectively, the backends 0,1 or 2 of plplot's old wxWidgets driver (plplot versions < 5.10). Backend 2 has antialiasing enabled. .TP .B GSHHS_DATA_DIR If not automatically found, tells GDL where the gshhs files (coasts rivers, etc) are located. .SH BUGS Please report bugs, comments, patches or feature requests at http://sf.net/projects/gnudatalanguage/ .SH AUTHOR The primary author of GDL is Marc Schellens . A list of contributors is available in the AUTHORS file shipped with GDL, and on the project website (see above). .PP The original version of this manual page was written by Sergio Gelato . It is currently a part of the GDL package, and is maintained by the GDL Team. .SH SEE ALSO netcdf(3), hdf(1), gsl(3) gdl-0.9.9/doc/misc/000077500000000000000000000000001340051421000137655ustar00rootroot00000000000000gdl-0.9.9/doc/misc/README.call_external000066400000000000000000000131371340051421000174660ustar00rootroot00000000000000/*************************************************************************** call_external - CALL_EXTERNAL function for GDL ------------------- begin : October 16, 2010 copyright : (C) 2010 by Christoph Fuchs email : j.c.fuchs@gmx.de ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ CALL_EXTERNAL: call a routine from a sharable object library This is the Linux/Unix implementation of call_external for GDL, and should compile on systems which support dlopen/dlsym/dlclose. It should work as close as possible as in IDL (exceptions see below). It has been tested on Linux (SuSe 11, both 32 and 64 bit) Solaris 5.10 (x86 32bit) INSTALLATION ============ 1. Copy new.cpp and new.hpp to the src directory of your gdl-0.9 distribution 2. Edit libinit.cpp and enter the following lines near the end of the file (before the //sort ) // call_external const string call_externalKey[] = {"VALUE", "ALL_VALUE", "RETURN_TYPE", "B_VALUE", "I_VALUE", "L_VALUE", "F_VALUE", "D_VALUE", "UI_VALUE", "UL_VALUE", "L64_VALUE", "UL64_VALUE", "S_VALUE", "UNLOAD", "ALL_GDL", "STRUCT_ALIGN_BYTES", KLISTEND }; new DLibFun(lib::call_external, string("CALL_EXTERNAL"), -1, call_externalKey); 3. make && make install TEST ==== 1. Generate a shared object file from test_ce.c (see comments in this file) 2. Start gdl and enter the command test_ce SYNTAX ======= ret = CALL_EXTERNAL(image, entry [, p1, ... pn] [, keywords] ) Arguments: image (string) Name of the sharable object entry (string) Name of the routine in image p1, ..., pn (any) Any number of parameters passed to the routine Keywords: (*)=extension in GDL, not in IDL RETURN_TYPE=n Indicates the type of the return value of the called routine, this value will be returned by CALL_EXTERNAL to GDL. n is an integer with the same meaning as e.g. the type field of the SIZE function (see basegdl.hpp for a list of types). Possible values for n are those for numeric types except COMPLEX and DCOMPLEX. The default value is n=3 (GDL type LONG, which corresponds to C type int). Alternatively one of the following keywords may be used: /B_VALUE equivalent to RETURN_TYPE=1 (BYTE) /I_VALUE equivalent to RETURN_TYPE=2 (INTEGER) /L_VALUE (*) equivalent to RETURN_TYPE=3 (LONG) (default) /F_VALUE equivalent to RETURN_TYPE=4 (FLOAT) /D_VALUE equivalent to RETURN_TYPE=5 (DOUBLE) /UI_VALUE equivalent to RETURN_TYPE=12 (UINT) /UL_VALUE equivalent to RETURN_TYPE=13 (ULONG) /L64_VALUE equivalent to RETURN_TYPE=14 (LONG64) /UL64_VALUE equivalent to RETURN_TYPE=15 (ULONG64) /S_VALUE equivalent to RETURN_TYPE=6 (STRING, the called function should return char*) /ALL_VALUE The default is to pass all parameters by reference. If this keyword is set, all parameters are passed by value. /ALL_GDL (*) Pass all parameters as BaseGDL* Alternatively these methods can be requested for each parameter individually with the following keyword: VALUE=array where array is an integer array with as many elements as parameters. If the i_th element of array is 0, the i_th parameter will be passed by reference to an equivalent C variable, strings are passed by reference to a C structure struct { int len; short unused; char* string; } and GDL structures are passed by reference to equivalent C structures. Changes made to any variables are reflected back to GDL. If the i_th element of array is >0, the i_th parameter will be passed by value, strings are passed as char*. Only scalar parameters which are small enough to fit into a pointer (void*) can be passed by value this way. Changes made to these parameters are not reflected back to GDL. (*) If the i_th element of array is <0, then the i_th parameter will be passed directly as BaseGDL*. Shared objects which use this feature can be used only with GDL, but not with IDL. /UNLOAD Unload the shared object after calling the routine STRUCT_ALIGN_BYTES=n (*) Assume that structures in the shared object are aligned at boundaries of n bytes, where n should be a power of 2. If n=0 or if this keyword is not given, the default machine dependent alignment is assumed (normally 4/8 bytes on 32/64 bit systems). It should only be necessary to use this keyword if the called shared object has been compiled with a different alignment, e.g. with #pragma pack(n) Keywords from IDL which are not supported in GDL: CDECL (relevant for MS Windows only) WRITE_WRAPPER all AUTO_GLUE keywords (you have to write and compile your routines yourself :-) gdl-0.9.9/doc/misc/gdlffdicom.html000077500000000000000000000074271340051421000167660ustar00rootroot00000000000000 gdlffdicom.html

GDLffDICOM

GDLffDICOM is an adaptation of IDLffDICOM to achieve several outcomes.

  • Better runtime error handling
  • Ability to read a broader range of DICOM files
  • Limited ability to write DICOM files
  • Drop in replacement of IDLffDICOM

Better runtime handling

GDLffDICOM is written completely in IDL. Whilst this decreases performance, it also ensures that all runtime errors are not fatal and can be captured. This is advantageous over IDLffDICOM, which is written in C/C++ and can cause IDL to terminate abnormally if an error is encountered.

Ability to read a broader range of DICOM files

GDLffDICOM can read a slightly borader range of DICOM files than IDLffDICOM. GDLffDICOM is more lenient about accepting non-compliant tags. You can also avoid further parsing errors by using the GDLffDIOM__assoc class.

Limited ability to write DICOM files

GDLffDICOM allows you to associate the image data of a DICOM file with an IDL variable. This provides a reasonably efficient method of altering the pixel data in a DICOM file. Other DICOM tags can be set via the GDLffDICOM::SetValue method and are written to a DICOM file using the GDLffDICOM::Commit function.

Drop-in replacement of IDLffDICOM

The GDLffDICOM method signature is almost identical to IDLffDICOM. This allows you to avoid significant alteration of code if you wish to only use a small portion of GDLffDICOMs features.

Authors Node

GDLffDICOM has acquired its name from the GNU Data Language (GDL) project.  Whilst GDLffDICOM might work with GDL it may not exclusively work on either platform. It has only been named with the GDL prefix so it can be effectively maintained by both the IDL and GDL community without namespace issues.

gdl-0.9.9/doc/misc/gdlffdicom__assoc.html000077500000000000000000000123321340051421000203040ustar00rootroot00000000000000 gdlffdicom__assoc.html

GDLffDICOM__assoc

The GDLffDICOM__assoc class provides methods to read and update images embedded in a DICOM Part 10 file. The GDLffDICOM__assoc class takes advantage to the IDL assoc function to allow for direct access to frame data in the DICOM file. Such direct access means that you cannot make alter the image dimensions.

The GDLffDICOM__assoc class also provides a method for generating a new SOP Instance UID. Generating a new UID is necessary if you intend on altering the DICOM file. If you do not generate a new UID then you may experience data loss:

  • A vendor may not import your image because it appears to already exist in their database. (Expected behavior according to the DICOM standard)
  • A vendor will overwrite any images in their database which appear to have the same UID.

Limitations

  •  Because of the nature of direct access, changes to DICOM files are committed immediately, thus there is no way to rollback in the event of an error.
  •  The GDLffDICOM__assoc class does not support the manipulation of image dimensions.
  • By default, the GDLffDICOM__assoc class does not recognise sequences of tags. Thus, GDLffDICOM__assoc will completely skip over sequences which have their length explicitly set unless you use the /INDEX_SEQUENCES keyword

Example

; Initialise the DICOM update class

du = obj_new('GDLffDICOM__assoc')

; Open and parse the DICOM file

if (du -> open('image.dcm')) then begin

; Associate the image embedded in the file

images = du -> assoc(COUNT=count)

; Display the slices

for i=0l,count-1l do tvscl, images[i], i

; Close the file

du -> close

endif

; Cleanup

obj_destroy, du

gdl-0.9.9/obsolete/000077500000000000000000000000001340051421000141015ustar00rootroot00000000000000gdl-0.9.9/obsolete/Doxyfile000066400000000000000000000226401340051421000156130ustar00rootroot00000000000000# Doxyfile 1.4.1-KDevelop #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = gdl.kdevelop PROJECT_NUMBER = 0.9 OUTPUT_DIRECTORY = CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = /usr/local/gdl/ STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = YES FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = /usr/local/gdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.C \ *.H \ *.tlh \ *.diff \ *.patch \ *.moc \ *.xpm \ *.dox RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO gdl-0.9.9/obsolete/INSTALL.configure000066400000000000000000000260331340051421000171160ustar00rootroot00000000000000IMPORTANT WARNING ================= July 2, 2014 The "configure" way is no more maintained in GDL. To avoid confict with Debian and Ubuntu packaging which are looking for "configure" related files, we move then into this "obsolete/" sub-directory. The "configure" way is still working (used in 2014 on various OS like CentOS, Debian and Ubuntu) but it does not covered all the options we have now in CMake and we don't plan to update the "configure" files. You can still regenerated the "configure" file by moving "config.h.in" and "configure.in" in the root of the GDL project, then doing few commands ($ mkdir m4 not need on most OS, but needed on old CentOS !) $ autoreconf -vfi $ ./configure $ make e.g. on a 8-cores with lot of RAM : $ ./configure --without-python --with-hdf=no --with-hdf5=no --with-pslib=no \ --with-plplotdir=$HOME/GDL/plplot-5.9.6/Compilation/ \ --with-Magick=$HOME/GDL/ImageMagick-6.5.9-0/Compilation \ --without-GraphicsMagick --with-eigen3=$HOME/GDL/Eigen/Eigen3.1.2/ $ make -j 20 Experiences gain during last 3 years indicated that it is more tricky to maintain the "configure" way than the "CMake" way. CMake in now under "new BSD license" and is packaged in most Linux distributions. It is very easy to compiled it from source under other OS like OSX. QUICK INSTALLATION: =================== (If you encounter any problems, please read on further, also have a look at the REQUIREMENTS section in the README file.) * unpack the tarball under any directory (tar xfvz gdl-VERION.tar.gz) * change to the new subdirectory gdl-VERSION * type "./configure" (use './configure --help' for a list of options) * type "make" (use 'make -j N' to run N parallel processes) * optionally type "make check" to test the build * type "make install" to deploy GDL binary (gdl), libraries, manpage, etc See INSTALL.CMake on instructions how to configure GDL using CMake. If you know IDL, you should feel very familiar with GDL. A list of command-line options is available both in the manpage and after typing "gdl --help". Some GDL test files are in the gdl/testsuite subdirectory (test_*.pro) Note: When compiling you might get some warnings: "datatype.cpp: comparison is always false due to limited range of data type" That's OK. Please see the comment in datatypes.cpp near the warning for an explanation. If you have an old Plplot version (before 5.9.0) you must say it using --enable-oldplplot If you are compiling GDL source from the repository (i.e. not a release), and not using CMake, first you have to generate the "configure" script and other related files by invoking "autoreconf -i". BUILDING GDL AS A PYTHON MODULE: ================================ to build the GDL python module, configure must be run with the --enable-python_module option (i.e. if you wish to use the GDL standalone version *and* use GDL from within python, you need to build (configure/make) it twice. For python standards, the installation procedure is quite 'unconventional' but simple: You need to run configure with the --enable-python_module option. All other options are the same: [OS X note: Due to some incompatibilities, on OS X you might have to recreate the configure script (this is if the building of libantlr aborts with an error message): alocal && automake && autoconf ] ./configure --enable-python_module make The result is a dynamic library file "libgdl.so.0.0.0" ("libgdl.0.0.0.dylib" on OS X) in the "src/.libs" subdir. Copy these library into your python site-packages (e.g. /usr/lib/python2.3/site-packages) directory as GDL.so (same name on OS X) (note the capital letters) and you are done. See PYTHON.txt for further information. OPTIONS TO CONFIGURE SCRIPT: ============================ Apart form the further down mentioned options, the following options can be used: --enable-python_module build the GDL python module instead of the standalone program (default). See above. --enable-python_version=VERSION# the configure script tries to automatically determine which python version is actually used. With this option the version can be expicitely set (e.g. --enable-python_version=2.6). --with-ncursesdir=DIR to specify the ncurses (or curses) directory tree --with-readlinedir=DIR to specify the GNU readline directory tree --with-libzdir=DIR to specify the Zlib directory tree --with-openmp=no to disable the OpenMP support (e.g. for GCC <4.2) --with-gsldir=DIR to specify the GSL directory tree --with-plplotdir=DIR to specify the plplot directory tree --enable-oldplplot to specify that you have an older than 5.9.0 plplot lib. --with-Magick=DIR to specify the ImageMagick directory tree --with-Magick=no to not use ImageMagick --with-netcdf=DIR to specify the netcdf directory tree --with-netcdf=no to not use netcdf --with-fftw=DIR to specify the FFTW directory tree --with-fftw=no to not use FFTW --with-eigen=DIR to specify the Eigen3 directory tree ... and so on for: wxWidgets, hdf, hdf5, fftw, libproj4, python, udunits, grib, GSHHS, and others - see README file for details (REQUIREMENTS section). For example, if you have python installed in /usr/local, use ./configure --with-python=/usr/local Basic Installation Instructions =============================== The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. gdl-0.9.9/obsolete/README.txt000066400000000000000000000022501340051421000155760ustar00rootroot00000000000000 some informations about these files and this directory 1/ procedures from the IDL library Most of the files here are re-implementation of the open source files available in the IDL lib directory. Since the original library is under Copyright, we cannot copy it directly in GDL. Then we need to develop a clone for some of the most useful procedures in this library. Some of these routines can be found and downloaded from http://idlastro.gsfc.nasa.gov/idllibsrch.html but we cannot include them now in GDL. Please see STATUS for a list of the files, if they are needed, or not, written (in GDL or C++) with perfect clone or less perfect Please see UrgentNeed.txt for the most urgent needed procedures. You can notify me (at : alaingdl AT users.sourceforge.net ) if you start to work on one of these procedures. I can help you to put them in the CVS. 2/ Other files some other files are put here, which are not in the IDL lib. path, but correspond to procedures available in IDL, in binary (executable build in) form. Here they are re-implemented in GDL langage. e.g.: save.pro restore.pro read_jpeg.pro read_png.pro write_jpeg.pro write_png.pro file_lines.pro tvscl.pro smooth.pro gdl-0.9.9/obsolete/STATUS000066400000000000000000000131631340051421000150530ustar00rootroot00000000000000=============================================================================== Implementation status of the IDL 5.4 routine library =============================================================================== Codes: = : implementation complete # : implementation complete (but in C++) + : implementation complete + added functionality ~ : partial implementation - : implementation not required ! : non-implemented routines having priority Most important are: congrid, crvlength, curvefit, determ, hist_equal, interpol, int_tabulated, lin_fit, poly_fit, rot, spline, svdfit See the file UrgentNeed.txt for atributed tasks =============================================================================== !a_correlate.pro adapt_hist_equal.pro !amoeba.pro annotate.pro arrow.pro ascii_template.pro !bar_plot.pro #beta.pro ~bilinear.pro binary_template.pro bin_date.pro !binomial.pro bisect_pdf.pro blk_con.pro box_cursor.pro !c_correlate.pro #caldat.pro =calendar.pro cdf_exists.pro !chebyshev.pro !chisqr_cvf.pro !chisqr_pdf.pro cir_3pnt.pro colormap_applicable.pro !comfit.pro !complexround.pro cond.pro ~congrid.pro !coord2to3.pro !correlate.pro !cramer.pro create_view.pro #crossp.pro !crvlength.pro ct_luminance.pro cti_test.pro !curvefit.pro cv_coord.pro cvttobm.pro cw_animate.pro cw_arcball.pro cw_bgroup.pro cw_clr_index.pro cw_colorsel.pro cw_defroi.pro cw_dice.pro cw_field.pro cw_filesel.pro cw_form.pro cw_fslider.pro cw_light_editor.pro cw_orient.pro cw_palette_editor.pro cw_pdmenu.pro cw_rgbslider.pro cw_tmpl.pro cw_zoom.pro defroi.pro +deriv.pro derivsig.pro #determ.pro dialog_read_image.pro dialog_write_image.pro digital_filter.pro dissolve.pro =dist.pro dl_dos.pro dl_mac.pro dl_unix.pro dl_vms.pro doc_library.pro efont.pro !eigenvec.pro eos_exists.pro eos_gd_query.pro eos_pt_query.pro eos_query.pro eos_sw_query.pro !errplot.pro expand.pro extrac.pro extract_slice.pro !f_cvf.pro =factorial.pro !file_which.pro =file_sep.pro =filepath.pro ; /tmp is hardcoded flick.pro flow3.pro !f_pdf.pro funct.pro fv_test.pro #fx_root.pro gamma_ct.pro #gamma.pro !gauss2dfit.pro #gauss_cvf.pro !gaussfit.pro #gauss_pdf.pro #get_screen_size.pro -graphics_times2.pro -graphics_times3.pro -graphics_times.pro gs_iter.pro !hanning.pro hdf_exists.pro !h_eq_ct.pro !h_eq_int.pro !hilbert.pro =hist_2d.pro ~hist_equal.pro hls.pro hsv.pro !ibeta.pro =identity.pro idl_crank.pro idlgrarc__define.pro idlgrcolorbar__define.pro idlgrlegend__define.pro -idlinfo.pro #igamma.pro image_cont.pro insget.pro insput.pro insvis.pro !int_2d.pro !int_3d.pro !int_tabulated_2d.pro !int_tabulated.pro ~interpol.pro julday.pro krig2d.pro =kurtosis.pro kw_test.pro label_date.pro !ladfit.pro #laguerre.pro leefilt.pro !linfit.pro ljlct.pro #ll_arc_distance.pro !lmfit.pro !lmfunct.pro =loadct.pro lu_complex.pro !m_correlate.pro map_2points.pro map_continents.pro map_grid.pro map_image.pro map_patch.pro map_set.pro md_test.pro =meanabsdev.pro =mean.pro mesh_obj.pro !min_curve_surf.pro mk_html_help.pro modifyct.pro =moment.pro morph_close.pro morph_gradient.pro morph_hitormiss.pro morph_open.pro morph_thin.pro morph_tophat.pro mpeg_close.pro mpeg_open.pro mpeg_put.pro mpeg_save.pro multi.pro #ncdf_exists.pro =norm.pro !oploterr.pro <-- should easily be derived from PLOTERR !p_correlate.pro plot_3dbox.pro +ploterr.pro <-- extra useful keyword (hat ...) plot_field.pro !pnt_line.pro polar_contour.pro polar_surface.pro poly_area.pro !poly_fit.pro =poly.pro polywarp.pro =popd.pro =primes.pro =printd.pro profile.pro profiles.pro project_vol.pro ps_show_fonts.pro psafm.pro pseudo.pro =pushd.pro =query_bmp.pro query_dicom.pro =query_gif.pro ~query_image.pro =query_pict.pro ~query_ppm.pro query_srf.pro query_wav.pro !r_correlate.pro !r_test.pro ranks.pro rb_routines.pro rdpix.pro =read_ascii.pro ~read_binary.pro ; TEMPLATE keyword missing =read_bmp.pro =read_dicom.pro ~read_gif.pro ~read_image.pro read_interfile.pro =read_pict.pro read_ppm.pro read_spr.pro read_srf.pro read_sylk.pro read_wave.pro read_wav.pro read_x11_bitmap.pro =read_xwd.pro recon3.pro reduce_colors.pro !regress.pro resolve_all.pro ~reverse.pro ; OVERWRITE keyword missing (implemented in C++) ~rot.pro rs_test.pro !s_test.pro savgol.pro scale3d.pro scale3.pro search2d.pro search3d.pro setup_keys.pro !sfit.pro shade_surf_irr.pro show3.pro =showfont.pro showinfo.pro =skewness.pro skey_dec.pro skey_hp.pro skey_ibm.pro skey_mips.pro skey_sgi.pro skey_sun.pro slicer3.pro slide_image.pro sph_4pnt.pro spher_harm.pro sph_scat.pro !spline_p.pro !spline.pro ~standardize.pro =stddev.pro streamline.pro stretch.pro =strsplit.pro surfr.pro !svdfit.pro svdfunct.pro svdleg.pro =swap_endian.pro !t_cvf.pro !t_pdf.pro !t3d.pro tek_color.pro -testdemo.pro -test_hp.pro -test_lj.pro -test_pcl.pro -test_true.pro threed.pro timegen.pro -time_test2.pro -time_test3.pro -time_test.pro tm_test.pro +trace.pro ; allow scalar and 1~element vector trackball__define.pro tri_surf.pro ts_coef.pro ts_diff.pro ts_fcast.pro ts_smooth.pro =uniq.pro =variance.pro vector_field.pro velovect.pro vel.pro ; Alain C.: I have a wrtten authorisation by the original author to put in in CVS. To Do ASAP !! vert_t3d.pro !voronoi.pro warp_tri.pro wf_draw.pro =write_bmp.pro ~write_gif.pro ~write_image.pro write_nrif.pro =write_pict.pro write_ppm.pro write_spr.pro write_srf.pro write_sylk.pro write_wave.pro write_wav.pro xmanager.pro xmng_tmpl.pro xregistered.pro !xsq_test.pro zoom_24.pro zoom.pro gdl-0.9.9/obsolete/TODO000066400000000000000000000104521340051421000145730ustar00rootroot00000000000000 Last update by Alain on 30 July 2009 Updated by Alain on 28 March 2008 This file contains: -- a ToDo list of missing commands -- a ToDo list related to system variables -- a ToDo list of missing Functions and Procedures -- a ToDo list of incomplete Functions and Procedures, missing keywords and limited/buggy functionnalities in existing func/pro -- some comments -- a DONE list containing info for future troubles/needs ToDo list of missing commands (not exhaustive, most requested) .rnew .skip .reset_session ToDo list related to system variables !ERROR, !ERR and !ERROR_STATE are not properly set by all library functions !EDIT_INPUT, preferences IDL_EDIT_INPUT, IDL_RBUF_PERSIST and IDL_RBUF_SIZE. ToDo list of Functions and Procedures * WMENU function Category: user interface Langage: GDL, later may be in C++ with widgets ! Difficulty: easy Contact: Alain Comments: undocumented feature coming from the old IDL versions (before 4.0). A draft exists, substiting the X11 interface by a console one. ToDo list of incomplete Function/Procedure, missing keywords ... * ON_ERROR and CATCH procedures Category: system Langage: C++ Difficulty: unknow Contact: Marc Comments: ON_ERROR and CATCH are not fully implemented (GDL recognizes them, but does not perform any action, ie. in case of error, the data is not used). * HELP Category: system Langage: C++ Difficulty: unknow Contact: Comments: some useful keywords are not handle * PLOT, OPLOT, PLOTS, CONTOUR, SURFACE, AXIS, XYOUTS Category: display Langage: C++ Difficulty: parts are obvious, other may be impossible with plplot lib! Contact: Alain Comments: some useful keywords are not handle * USERSYM Category: display Langage: C++ (linked to plplot library Difficulty: may be impossible with plplot lib! Contact: Joel or Alain Comments: * TVRD : keyword !order Category: display Langage: C++ (in devicex.hpp) Difficulty: unknow. Contact: Alain Comments: to be complete for !order keyword (managed in TV). A priori, the method p->Rotate(7) cannot be used on Byte arrays. * LA_ serie (based on the LAPACK routines) Category: numeric Langage: a priori C++ Difficulty: some existing algo, not under GPL ?? Contact: Comments: different personns have asked ... It is better to implement it in C/C++ because it is computer intensif Comments; About recently added Pro/Functions I move here some important procedures and functions which have been recently added; because they are important, they need to extensively tested. * MEDIAN: implementation of parameter "width" was done in summer 2008 Category: numeric Langage: C++ Difficulty: very difficult Contact: Alain Comments: codes in C/C++ in public domain or under GPL available, "interfaces" missing. Please make biblio before writing it, it is not obvious. Availability/efficienty of algo depend on data type !! It is better to implement it in C/C++ because it is computer intensif. --> Not sure all the cases have been tested. Please report tests and problems. * SPLINE serie (SPL_INIT, SPL_INTERP) Category: numeric Langage: C++ Difficulty: existing algo in NR, not under GPL. Contact: Alain Comments: A working version in GDL syntax has been put in CVS under src/pro It is better to implement it in C/C++ because it is computer intensif. * INVERT function : some exceptions Category: numeric Langage: C++ (in gsl_fun.cpp) Difficulty: easy. Contact: Alain Comments: the last exceptions shjould have been cleaned (input size, no-square matrix, string conversion should work). Very easy but could be time consuming if extensive tests. See currents tests in testsuite/test_invert_matrix.pro DONE and revisited * BESELI/BESELJ/BESELK Category: numeric Langage: C++ (in math_fun_ac.cpp) Difficulty: unknow. Contact: Alain Comments: 1/ some details need to be fix when the arrays are not commensurable. It is highly probable that other functions do suffer from the same problems. Some have been corrected (the GAMMA/BETA family) and can be used as template. 2/ since mid-2008 (?) GSL does include non integer Besel functions ... The Besel family has been revisted during summer 2009. Non integer orders have been added. Boundaries tests should be OK. Clean processing of input arrays dimensionning was take into account, with consequence on other functions like VOIGT, BETA ... (see examples in testsuite/test_MathFunctionsDim.pro and also bugs in IDL) gdl-0.9.9/obsolete/UrgentNeed.txt000066400000000000000000000020671340051421000167070ustar00rootroot00000000000000 Some of these routines can be find and downloaded from http://idlastro.gsfc.nasa.gov/idllibsrch.html but we cannot includ them now in GDL. ! : non-implemented routines having priority Please indicate what you are doing and starting time !a_correlate.pro !amoeba.pro !bar_plot.pro !binomial.pro !c_correlate.pro !chebyshev.pro !chisqr_cvf.pro !chisqr_pdf.pro !comfit.pro !complexround.pro !coord2to3.pro !cramer.pro !crvlength.pro !curvefit.pro !eigenvec.pro !errplot.pro !f_cvf.pro !f_pdf.pro !fx_root.pro !gauss2dfit.pro !gaussfit.pro !hanning.pro --> AC 2006/12/14 !h_eq_ct.pro !h_eq_int.pro !hilbert.pro !hist_equal.pro !ibeta.pro !int_2d.pro !int_3d.pro !int_tabulated_2d.pro !int_tabulated.pro !ladfit.pro !linfit.pro !lmfit.pro !lmfunct.pro !m_correlate.pro !min_curve_surf.pro !oploterr.pro <-- should easily be derived from PLOTERR !p_correlate.pro !pnt_line.pro !poly_fit.pro !r_correlate.pro !r_test.pro !regress.pro !s_test.pro !sfit.pro !spline_p.pro !spline.pro !standardize.pro !svdfit.pro !t_cvf.pro !t_pdf.pro !t3d.pro !voronoi.pro !xsq_test.pro gdl-0.9.9/obsolete/config.h.in000066400000000000000000000106331340051421000161270ustar00rootroot00000000000000/* config.h.in. Generated from configure.in by autoheader. */ /* --exec-prefix or default */ #undef EXEC_PREFIX /* $datadir/gnudatalanguage */ #undef GDLDATADIR /* Define if 64-bit OS */ #undef HAVE_64BIT_OS /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_EXT_STDIO_FILEBUF_H /* Define to 1 if you have the header file. */ #undef HAVE_GSHHS_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `curses' library (-lcurses). */ #undef HAVE_LIBCURSES /* Define to 1 if you have the `gsl' library (-lgsl). */ #undef HAVE_LIBGSL /* Define to 1 if you have the `gslcblas' library (-lgslcblas). */ #undef HAVE_LIBGSLCBLAS /* Define to 1 if you have the ncurses library (-lncurses). */ #undef HAVE_LIBNCURSES /* plplot library */ #undef HAVE_LIBPLPLOTCXXD /* GNU readline library */ #undef HAVE_LIBREADLINE /* wxWidgets library */ #undef HAVE_LIBWXWIDGETS /* Zlib library */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the `mallinfo' function. */ #undef HAVE_MALLINFO /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_MALLOC_H /* Define to 1 if you have the `malloc_zone_statistics' function. */ #undef HAVE_MALLOC_ZONE_STATISTICS /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `nexttoward' function. */ #undef HAVE_NEXTTOWARD /* Define if you have a plplot version prior to 5.9.0 */ #undef HAVE_OLDPLPLOT /* plplot slabel library */ #undef HAVE_PLPLOT_SLABELFUNC /* Define to 1 if you have the `sbrk' function. */ #undef HAVE_SBRK /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UDUNITS2_UDUNITS2_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define if you want to enable calls to Xlib */ #undef HAVE_X /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Pre-10.4.8 version of OS X */ #undef OLD_DARWIN /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* plplot private pb. library */ #undef PLPLOT_HAS_LEGEND /* plplot private pb. library */ #undef PLPLOT_PRIVATE_NOT_HIDDEN /* Define if you want to build the GDL python module */ #undef PYTHON_MODULE /* GNU readline with rl_get_screen_size */ #undef RL_GET_SCREEN_SIZE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you want to use Eigen lib. */ #undef USE_EIGEN /* Define if you want to use FFTW */ #undef USE_FFTW /* Define if you want to use GRIB */ #undef USE_GRIB /* Define if you want to use GSHHS */ #undef USE_GSHHS /* Define if you want to use HDF */ #undef USE_HDF /* Define if you want to use HDF5 */ #undef USE_HDF5 /* Define if you want to use LIBPROJ4 */ #undef USE_LIBPROJ4 /* Define if you want to use new LIBPROJ4 */ #undef USE_LIBPROJ4_NEW /* Define if you want to use GraphicsMagick */ #undef USE_MAGICK /* Define if you want to use MPI */ #undef USE_MPI /* Define if you want to use netCDF */ #undef USE_NETCDF /* Define if you want to use pslib */ #undef USE_PSLIB /* Define if you want to use python */ #undef USE_PYTHON /* Define if you want to use UDUNITS-2 */ #undef USE_UDUNITS /* Version number of package */ #undef VERSION gdl-0.9.9/obsolete/configure.in000066400000000000000000001320571340051421000164220ustar00rootroot00000000000000AC_INIT(gdl, 0.9.4 CVS) AC_CONFIG_MACRO_DIR([m4]) dnl == Configuration (of the configure script) ============ dnl ======================================================== dnl default: build standalone version on GDL PYTHON_MODULE="no" dnl optional-packages defaults: dnl - yes = require by default dnl - no = needs explicit enabling if test "x$with_readlinedir" = "x"; then with_readlinedir=yes; fi if test "x$with_wxWidgets" = "x"; then with_wxWidgets=yes; fi if test "x$with_udunits" = "x"; then with_udunits=no; fi if test "x$with_grib" = "x"; then with_grib=no; fi if test "x$with_Magick" = "x"; then with_Magick=yes; fi if test "x$with_GraphicsMagick" = "x"; then with_GraphicsMagick=no; fi if test "x$with_eigen3" = "x"; then with_eigen3=auto; fi if test "x$with_netcdf" = "x"; then with_netcdf=yes; fi if test "x$with_hdf" = "x"; then with_hdf=yes; fi if test "x$with_hdf5" = "x"; then with_hdf5=yes; fi if test "x$with_fftw" = "x"; then with_fftw=auto; fi if test "x$with_libproj4" = "x"; then with_libproj4=no; fi if test "x$with_mpich" = "x"; then with_mpich=no; fi if test "x$with_python" = "x"; then with_python=yes; fi if test "x$with_gshhs" = "x"; then with_gshhs=no; fi if test "x$with_pslib" = "x"; then with_pslib=yes; fi dnl default DATADIR subdirectory datasubdir="gnudatalanguage" dnl == some basics ========================================= dnl ======================================================== AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE AC_LANG(C++) AC_PROG_CXX AC_PROG_RANLIB AC_PROG_LIBTOOL dnl == Checking for 64-bit OS ============================== dnl ======================================================== AC_LANG_SAVE AC_LANG_C AC_MSG_CHECKING(for 64-bit OS) AC_TRY_RUN([ int main () { if (sizeof(long) == 8) { return 0; } return 1; } ], result="yes", result="no", result="maybe" ) AC_MSG_RESULT($result) if test "$result" = "yes"; then AC_DEFINE([HAVE_64BIT_OS], [1], [Define if 64-bit OS]) fi AC_SUBST(HAVE_64BIT_OS) AC_LANG_RESTORE AC_SEARCH_LIBS([dlopen], [dl]) if test x"$ac_cv_search_dlopen" = x-ldl; then LIBS="$LIBS -ldl" fi dnl == Python module (calling GDL from Python) ============= dnl ======================================================== dnl check if we build GDL standalone or the python module AC_ARG_ENABLE(python_module, [ --enable-python_module make GDL python module (default: standalone version)], [ PYTHON_MODULE="$enableval" ]) if test "x$PYTHON_MODULE" = "xyes"; then AC_DEFINE([PYTHON_MODULE], [1], [Define if you want to build the GDL python module]) fi AM_CONDITIONAL(BUILDASLIBRARY, test "x$PYTHON_MODULE" = "xyes") dnl == Checking presence of various headers/libs ========== dnl ======================================================== dnl related to portability of MEMORY() AC_CHECK_FUNCS([malloc_zone_statistics sbrk mallinfo]) AC_CHECK_HEADERS([malloc.h malloc/malloc.h]) dnl related to portability of LOCALE_GET() AC_CHECK_HEADERS([locale.h]) dnl used in histogram AC_CHECK_FUNCS([nexttoward]) dnl used by SPAWN, UNIT= AC_CHECK_HEADERS([ext/stdio_filebuf.h]) dnl == ncurses ============================================= dnl ======================================================== AC_ARG_WITH(ncursesdir, [ --with-ncursesdir=DIR specify the ncurses (or curses) directory tree ], [ LIBS="$LIBS -L$withval/lib" INCLUDES="$INCLUDES -I$withval/include" ]) AC_CHECK_LIB(ncurses, initscr, [AC_DEFINE([HAVE_LIBNCURSES],[1], [Define to 1 if you have the ncurses library (-lncurses).]) LIBS="-lncurses $LIBS"],AC_CHECK_LIB(curses, initscr)) dnl == readline ============================================ dnl ======================================================== dnl readline (we need *GNU* readline) AC_ARG_WITH(readlinedir, [ --with-readlinedir=DIR specify the GNU readline directory tree ], [ with_readlinedir="$withval"]) if test "x$with_readlinedir" != "xno"; then if test "x$with_readlinedir" != "xyes"; then dnl make sure this directory get in the path first dnl as OS X provides another readline library LIBS="-L$with_readlinedir/lib -L$with_readlinedir $LIBS -lreadline" INCLUDES="$INCLUDES -I$with_readlinedir/include -I$with_readlinedir" else LIBS="$LIBS -lreadline" fi AC_CHECK_LIB(readline, stifle_history, [ AC_DEFINE( [HAVE_LIBREADLINE], [1], [GNU readline library])], [ echo "" echo "Error! GNU readline was not found." echo " Use --with-readlinedir=no to expicitely disable it" echo " Check the README or use configure --help for other libraries needed" echo "" echo " (suitable Debian/Ubuntu package: libreadline5-dev)" echo " (suitable Fedora package: readline-devel)" exit -1 ]) AC_CHECK_LIB(readline, rl_get_screen_size,[ AC_DEFINE([RL_GET_SCREEN_SIZE], [1], [GNU readline with rl_get_screen_size])], [ echo "" echo "Warning! Older GNU readline without 'rl_get_screen_size' was found." echo " For resized terminals the size might not be updated correctly" echo " If this is a problem please install a recent version of readline" ]) fi dnl == zlib ================================================ dnl ======================================================== AC_ARG_WITH(zlibdir, [ --with-zlibdir=DIR specify the Zlib directory tree ], [with_zlib="$withval" ]) if test "x$with_zlib" = "x"; then with_zlib=yes fi if test "x$with_zlib" = "xno"; then echo "" echo "Error! ZLIB library is obligatory." exit -1 fi if test "x$with_zlib" != "xyes"; then LIBS="$LIBS -L$with_zlib/lib -lz" INCLUDES="$INCLUDES -I$with_zlib/include" else LIBS="$LIBS -lz" fi AC_CHECK_LIB(z, gzopen, [AC_DEFINE([HAVE_LIBZ], [1], [Zlib library])], [ echo "" echo "Error! zlib library is required but was not found" echo " Use --with-zlibdir=DIR to specify the zlib directory tree" echo "" echo " (suitable Debian/Ubuntu package: zlib1g-dev)" echo " (suitable Fedora package: zlib-devel)" exit -1 ]) dnl == OpenMP ============================================== dnl ======================================================== dnl AC_OPENMP dnl AC_PREREQ([2.63]) dnl if test "x$OPENMP_CXXFLAGS" != "x"; then dnl dnl this is just to force recompilation when OpenMP setting is changed dnl AC_DEFINE([HAVE_OPENMP], [1], [Use OpenMP]) dnl CPPFLAGS="$CPPFLAGS $OPENMP_CXXFLAGS" dnl LDFLAGS="$LDFLAGS $OPENMP_CXXFLAGS" dnl fi AC_ARG_WITH(openmp, [ --with-openmp=no disable OpenMP utilization ], [with_openmp="$withval" ]) dnl default yes if omp.h found openmp_autodetected=no if test "x$with_openmp" = "x"; then AC_CHECK_HEADERS("omp.h", [ with_openmp=yes openmp_autodetected=yes echo "" echo "OpenMP enabled (omp.h file was found)." echo "Try --with-openmp=no if your compiler does not support it (e.g. GCC < 4.2)" echo "" ], [ with_openmp=no echo "" echo "OpenMP disabled (omp.h file was not found)." echo "Try --with-openmp=yes if your compiler does support it (e.g. GCC >= 4.2)" echo "" ]) fi if test "x$with_openmp" != "xno"; then CPPFLAGS="$CPPFLAGS -fopenmp" LDFLAGS="$LDFLAGS -fopenmp" fi dnl == GSL ================================================= dnl ======================================================== AC_ARG_WITH(gsldir, [ --with-gsldir=DIR specify the GSL directory tree ], [with_gsl="$withval" ]) if test "x$with_gsl" = "x"; then with_gsl=yes fi if test "x$with_gsl" = "xno"; then echo "" echo "Error! Gnu Scientific Library (1.7 or higher) is mandatory" exit -1 fi if test "x$with_gsl" != "xyes"; then LIBS="$LIBS -L$with_gsl/lib -lgsl -lgslcblas" INCLUDES="$INCLUDES -I$with_gsl/include" else LIBS="$LIBS -lgsl -lgslcblas" fi AC_CHECK_LIB(gsl, gsl_ran_binomial_knuth, [], [ echo "" echo "Error! Gnu Scientific Library (1.7 or higher) is mandatory" echo "" echo " (suitable Debian/Ubuntu package: libgsl0-dev)" echo " (suitable Fedora package: gsl-dev)" echo " (suitable Gentoo package: sci-libs/gsl)" exit -1 ]) AC_CHECK_LIB(gslcblas, cblas_drot, [], [ echo "" echo "Error! libgslcblas (part of GSL) is mandatory" exit -1 ]) dnl == PLPlot ============================================== dnl ======================================================== AC_ARG_WITH(plplotdir, [ --with-plplotdir=DIR specify the plplot directory tree ], [with_plplot="$withval" ]) if test "x$with_plplot" = "x"; then with_plplot=yes fi if test "x$with_plplot" = "xno"; then echo "" echo "Error! PLPLOT library is mandatory." exit -1 fi OLDPLPLOT="no" AC_ARG_ENABLE(oldplplot, [ --enable-oldplplot use plplot version prior to 5.9.0], [ OLDPLPLOT="$enableval" ]) if test "x$OLDPLPLOT" = "xyes"; then AC_DEFINE([HAVE_OLDPLPLOT], [1], [Define if you have a plplot version prior to 5.9.0]) fi if test "x$with_plplot" != "xyes"; then LIBS="$LIBS -L$with_plplot/lib -lplplotd -lplplotcxxd" INCLUDES="$INCLUDES -I$with_plplot/include" else LIBS="$LIBS -lplplotd -lplplotcxxd" fi dnl LIBS="$LIBS /usr/local/lib/libplplotd.a /usr/local/lib/libplplotcxxd.a" AC_CHECK_LIB(plplotcxxd, plsexit, [AC_DEFINE([HAVE_LIBPLPLOTCXXD], [1], [plplot library])], [ echo "" echo "Error! plplot library is required but was not found" echo " Use --with-plplotdir=DIR to specify the plplot directory tree" echo "" echo " (suitable Debian/Ubuntu packages: libplplot-dev, [plplot9-driver-xwin])" echo " (suitable Fedora package: plplot-devel)" echo " (suitable Gentoo package: sci-libs/plplot)" exit -1 ]) dnl recent plplot (5.9.9-4) in Debian unstable version have hidden symbols AC_CHECK_LIB(plplotcxxd, c_plslabelfunc, [AC_DEFINE([HAVE_PLPLOT_SLABELFUNC], [1], [plplot slabel library])], [ echo "" echo "Warning, due to old plplot library, [XYZ]TICKFORMAT option for plot axis will not be supported." echo "you should upgrade to plplot version > 5.9.6" echo "" ]) AC_CHECK_LIB(plplotcxxd, plstrl, [AC_DEFINE([PLPLOT_PRIVATE_NOT_HIDDEN], [1], [plplot private pb. library])], [ echo "" echo "Using a plplot library without private functions - workarounds will be used." echo "" ]) AC_CHECK_LIB(plplotcxxd, c_pllegend, [AC_DEFINE([PLPLOT_HAS_LEGEND], [1], [plplot private pb. library])], [ echo "" echo "Your plplot lib is too old for some gdl functions, please upgrade." echo "" ]) if test "x$with_Magick" != "xno"; then # https://sourceforge.net/tracker/index.php?func=detail&aid=2974380&group_id=97659&atid=618683 AC_CHECK_LIB(plplotd, plGetDrvDir, [ echo "" echo "Warning! Dynamic drivers have to be disabled in plplot" echo " to make plplot work with ImageMagic:" echo " - use the -DENABLE_DYNDRIVERS=OFF cmake option when" echo " compiling plplot to disable dynamic drivers in plplot, or" echo " - use --with-Magick=no here to not use ImageMagick in GDL." echo "" ]) fi dnl == wxWidgets =========================================== dnl ======================================================== AC_ARG_WITH(wxWidgets, [ --with-wxWidgets=DIR use wxWidgets (with optional path DIR) ], [with_wxWidgets="$withval" ]) if test "x$with_wxWidgets" != "xno"; then if test "x$with_wxWidgets" = "xyes"; then AC_PATH_PROG(wxConfig, wx-config, no) else AC_PATH_PROG(wxConfig, wx-config, no, "$with_wxWidgets/bin") fi if test "x$wxConfig" = "xno"; then echo "" echo "Error! wxWidgets version 2.8 or later is required but was not found (wx-config program not found)" echo " Use --with-wxWidgets=DIR to specify the wxWidgets directory tree" echo " Use --with-wxWidgets=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libwxgtk2.8-dev)" echo " (suitable Fedora package: wxGTK-devel)" echo " (suitable Gentoo package: x11-libs/wxGTK)" exit -1 else LIBS="$LIBS `wx-config --libs`" INCLUDES="$INCLUDES `wx-config --cxxflags`" dnl SA: this is needed to compile on Leopard dnl (see e.g. the "OpenGL bug section" in http://wiki.finkproject.org/index.php/Fink:Packaging:Preparing_for_10.5#OpenGL_Bug) dnl LDFLAGS="$LDFLAGS -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib" fi AC_DEFINE([HAVE_LIBWXWIDGETS], [1], [wxWidgets library]) # SA: the code below worked for me on Ubuntu and Macports... but it does not work e.g. on Fedora # #tmp="`wx-config --basename`-`wx-config --release`" #AC_CHECK_LIB($tmp, wxFatalSignalHandler, # [AC_DEFINE([HAVE_LIBWXWIDGETS], [1], [wxWidgets library])], [ # dnl SA: handling the multi-port wxWidgets installation case # tmp="`wx-config --basename --toolkit=base`-`wx-config --release`" # AC_CHECK_LIB($tmp, wxInteger_compare, [AC_DEFINE([HAVE_LIBWXWIDGETS], [1])], [ # echo "" # echo "Error! wxWidgets version 2.8 or later is required but was not found" # echo " Use --with-wxWidgets=DIR to specify the wxWidgets directory tree" # echo " Use --with-wxWidgets=no to not use it" # echo " Check the README or use configure --help for other libraries needed" # echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" # exit -1 # ]) #]) fi dnl == ImageMagick ========================================= dnl ======================================================== AC_ARG_WITH(Magick, [ --with-Magick[=DIR] use ImageMagick package (with optional path DIR) ], [with_Magick="$withval" ]) if test "x$with_Magick" != "xno"; then if test "x$with_Magick" = "xyes"; then AC_PATH_PROG(MagickConfig, Magick++-config, no) else AC_PATH_PROG(MagickConfig, Magick++-config, no, "$with_Magick/bin") fi if test "x$MagickConfig" = "xno"; then AC_MSG_ERROR(ImageMagick is required but was not found (Magick++-config program not found) Use --with-Magick=DIR to specify the ImageMagick directory tree Use --with-Magick=no to not use it (suitable Debian/Ubuntu package: libmagick++-dev) (suitable Fedora package: ImageMagick-c++-devel) ) else LIBS="$LIBS `$MagickConfig --libs`" INCLUDES="$INCLUDES `$MagickConfig --cppflags`" LDFLAGS="$LDFLAGS `$MagickConfig --ldflags`" fi AC_CHECK_LIB( Magick++, GetMagickVersion, [AC_DEFINE([USE_MAGICK], [1], [Define if you want to use ImageMagick])], [ AC_MSG_CHECKING(if adding X library path helps) AC_MSG_RESULT(?) AC_PATH_X LDFLAGS="$LDFLAGS -L$x_libraries" AC_CHECK_LIB(Magick++, GetMagickReleaseDate, AC_DEFINE([USE_MAGICK], [1]), [ echo "" echo "Error! ImageMagick version 5.5.7 or later is required but was not found" echo " Use --with-Magick=DIR to specify the ImageMagick directory tree" echo " Use --with-Magick=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = mandatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libmagick++-dev)" echo " (suitable Fedora package: ImageMagick-c++-devel)" echo " (suitable Fedora package: media-gfx/imagemagick)" exit -1 ]) ] ) fi dnl == GraphicsMagick ====================================== dnl ======================================================== AC_ARG_WITH(GraphicsMagick, [ --with-GraphicsMagick[=DIR] use GraphicsMagick package (with optional path DIR) ], [with_GraphicsMagick="$withval" ]) if test "x$with_GraphicsMagick" != "xno"; then if test "x$with_GraphicsMagick" = "xyes"; then AC_PATH_PROG(GraphicsMagickConfig, GraphicsMagick++-config, no) else AC_PATH_PROG(GraphicsMagickConfig, GraphicsMagick++-config, no, "$with_GraphicsMagick/bin") fi if test "x$GraphicsMagickConfig" = "xno"; then AC_MSG_ERROR(GraphicsMagick is required but was not found (GraphicsMagick++-config program not found) Use --with-GraphicsMagick=DIR to specify the GraphicsMagick directory tree Use --with-GraphicsMagick=no to not use it (suitable Debian/Ubuntu package: libmagick++-dev) (suitable Fedora package: GraphicsMagick-c++-devel) ) else LIBS="$LIBS `$GraphicsMagickConfig --libs`" INCLUDES="$INCLUDES `$GraphicsMagickConfig --cppflags`" LDFLAGS="$LDFLAGS `$GraphicsMagickConfig --ldflags`" fi AC_CHECK_LIB( GraphicsMagick++, GetMagickVersion, [AC_DEFINE([USE_MAGICK], [1], [Define if you want to use GraphicsMagick])], [ AC_MSG_CHECKING(if adding X library path helps) AC_MSG_RESULT(?) AC_PATH_X LDFLAGS="$LDFLAGS -L$x_libraries" AC_CHECK_LIB(GraphicsMagick++, GetMagickReleaseDate, AC_DEFINE([USE_MAGICK], [1]), [ echo "" echo "Error! GraphicsMagick version 1.3 or later is required but was not found" echo " Use --with-GraphicsMagick=DIR to specify the GraphicsMagick directory tree" echo " Use --with-GraphicsMagick=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = mandatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libgraphicsmagick++-dev)" echo " (suitable Fedora package: graphicsMagick-c++-devel)" echo " (suitable Fedora package: media-gfx/igraphicsmagick)" exit -1 ]) ] ) fi dnl == Eigen3 ================================================= dnl ======================================================== if test "x$with_eigen3" = "xauto"; then AC_CHECK_FILE("/usr/include/eigen3/signature_of_eigen3_matrix_library", [with_eigen3=yes], [with_eigen3=no]) if test "x$with_eigen3" = "xyes"; then AC_DEFINE([USE_EIGEN], [1], [Define if you want to use Eigen lib.]) INCLUDES="$INCLUDES -I/usr/include/eigen3/" fi else AC_ARG_WITH(eigen3, [ --with-eigen3=DIR specify the Eigen3 package ((with optional path DIR) ], [with_eigen3="$withval" ]) if test "x$with_eigen3" != "xno"; then AC_DEFINE([USE_EIGEN], [1], [Define if you want to use Eigen lib.]) INCLUDES="$INCLUDES -I$with_eigen3" fi fi dnl == netCDF ============================================== dnl ======================================================== AC_ARG_WITH(netcdf, [ --with-netcdf[=DIR] use netCDF package (with optional path DIR) ], [with_netcdf="$withval" ]) if test "x$with_netcdf" != "xno"; then if test "x$with_netcdf" = "xyes"; then AC_PATH_PROG(nc_config, nc-config, no) else AC_PATH_PROG(nc_config, nc-config, no, "$with_netcdf/bin") fi if test "x$nc_config" != "xno"; then LIBS="$LIBS `$nc_config --libs`" INCLUDES="$INCLUDES `$nc_config --cflags`" ncdfincdir="`$nc_config --prefix`/include" else if test "x$with_netcdf" != "xyes"; then LIBS="$LIBS -L$with_netcdf/lib -lnetcdf" ncdfincdir="$with_netcdf/include" else LIBS="$LIBS -L/usr/lib/netcdf-3 -lnetcdf" ncdfincdir="/usr/include/netcdf-3" fi INCLUDES="$INCLUDES -I$ncdfincdir" fi AC_CHECK_LIB(netcdf, nc_open, [AC_DEFINE([USE_NETCDF], [1], [Define if you want to use netCDF])], [ echo "" echo "Error! netCDF version 3.5.1 or later is required but was not found" echo " Use --with-netcdf=DIR to specify the netcdf directory tree" echo " Use --with-netcdf=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libnetcdf-dev)" echo " (suitable Fedora package: netcdf-devel)" echo " (suitable Fedora package: sci-libs/netcdf-cxx )" exit -1 ]) AC_CHECK_HEADERS("netcdf.h", [], [ AC_CHECK_HEADERS("$ncdfincdir/netcdf.h", [], [ echo "" echo "Error! netCDF installation seems not to be usable" echo " This suggests a conflicting netCDF-HDF4 installation, e.g." echo " - uninstalling HDF4 after installation of netCDF" echo " - installing netCDF before HDF4" exit -1 ]) ]) fi dnl == HDF (version 4) ===================================== dnl ======================================================== AC_ARG_WITH(hdf, [ --with-hdf[=DIR] use HDF package (with optional path DIR) ], [with_hdf="$withval" ]) if test "x$with_hdf" != "xno"; then # on Debian the no-netcdf flavour of HDF4 libraries has an alt-suffixed naming _LIBS=$LIBS _INCLUDES=$INCLUDES for sfx in "dfalt" "df"; do if test "x$with_hdf" != "xyes"; then LIBS="$_LIBS -L$with_hdf/lib -L$with_hdf/lib/hdf -lmfh$sfx -l$sfx -ljpeg -lz" INCLUDES="$_INCLUDES -I$with_hdf/include -I$with_hdf/include/hdf" else LIBS="$_LIBS -L/usr/lib/hdf -lmfh$sfx -l$sfx -ljpeg -lz" INCLUDES="$_INCLUDES -I/usr/include/hdf" fi AC_CHECK_LIB($sfx, Hopen, [AC_DEFINE([USE_HDF], [1], [Define if you want to use HDF])], AC_MSG_CHECKING([if linking with SZIP helps]) echo "" AC_CHECK_LIB($sfx, Hclose, [ LIBS="$LIBS -lsz" AC_DEFINE([USE_HDF], [1], [Define if you want to use HDF]) ], [ if test $sfx != "dfalt"; then echo "" echo "Error! HDF4 libraries were not found" echo " Use --with-hdf=DIR to specify the HDF directory tree" echo " Use --with-hdf=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libhdf4-alt-dev)" exit -1 else continue # switchng to non-alt-suffixed naming fi ], [-lsz]) ) AC_CHECK_LIB(mfh$sfx, SDstart, [AC_DEFINE([USE_HDF], [1], [Define if you want to use HDF])], [ echo "" echo "Error! HDF4 libraries were not found" echo " Use --with-hdf=DIR to specify the HDF directory tree" echo " Use --with-hdf=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libhdf4-alt-dev)" exit -1 ]) # checking if HDF4 was compiled with the '--disable-netcdf' option if test "x$with_netcdf" != "xno"; then AC_CHECK_LIB(mfh$sfx, sd_nccreate, [], [ echo "" echo "Error! HDF4 needs to be configured with the --disable-netcdf option" echo " in order to be used with the original netCDF library" echo " (-alt suffixed HDF4 packages in case of Debian)" echo " Check the INSTALL file of the HDF4 package for details" echo "" echo " (suitable Debian/Ubuntu package: libhdf4-alt-dev)" echo " ^^^" exit -1 ]) fi # all went OK with the alt-suffixed naming -> skipping tests for the non-alt-suffixed naming if test $sfx == "dfalt"; then break; fi done fi dnl == HDF5 ================================================ dnl ======================================================== AC_ARG_WITH(hdf5, [ --with-hdf5[=DIR] use HDF5 package (with optional path DIR) ], [with_hdf5="$withval" ]) if test "x$with_hdf5" != "xno"; then if test "x$with_hdf5" != "xyes"; then LIBS="$LIBS -L$with_hdf5/lib -L$with_hdf5/lib/hdf -L$with_hdf5/lib/hdf5 -lhdf5" INCLUDES="$INCLUDES -I$with_hdf5/include -I$with_hdf5/include/hdf -I$with_hdf5/include/hdf5" else INCLUDES="$INCLUDES -I/usr/include/hdf -I/usr/include/hdf5" LIBS="$LIBS -L/usr/lib/hdf -L/usr/lib/hdf5 -lhdf5" fi AC_CHECK_LIB(hdf5, H5Fopen, [AC_DEFINE([USE_HDF5], [1], [Define if you want to use HDF5])], AC_MSG_CHECKING([if linking with SZIP helps]) echo "" AC_CHECK_LIB(hdf5, H5Fclose, [ LIBS="$LIBS -lsz" AC_DEFINE([USE_HDF5], [1], [Define if you want to use HDF5]) ], [ echo "" echo "Error! HDF version 5 is required but was not found" echo " Use --with-hdf5=DIR to specify the HDF5 directory tree" echo " Use --with-hdf5=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libhdf5-serial-dev)" echo " (suitable Fedora package: hdf-devel)" exit -1 ], [-lsz])) fi dnl == FFTW ================================================ dnl ======================================================== if test "x$with_fftw" = "xauto"; then AC_CHECK_LIB(fftw3, fftw_malloc, [ AC_CHECK_LIB(fftw3f, fftwf_malloc, [with_fftw=yes], [with_fftw=no]) ], [with_fftw=no]) fi AC_ARG_WITH(fftw, [ --with-fftw[=DIR] use FFTW package (with optional path DIR) ], [with_fftw="$withval" ]) if test "x$with_fftw" != "xno"; then if test "x$with_fftw" != "xyes"; then LIBS="$LIBS -L$with_fftw/lib -lfftw3" INCLUDES="$INCLUDES -I$with_fftw/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -lfftw3" fi AC_CHECK_LIB(fftw3, fftw_malloc, [AC_DEFINE([USE_FFTW], [1], [Define if you want to use FFTW])], [ echo "" echo "Error! FFTW3 version 3 is required but was not found" echo " Use --with-fftw=DIR to specify the FFTW directory tree" echo " Use --with-fftw=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libfftw3-dev)" echo " (suitable Fedora package: fftw-devel)" exit -1 ]) fi if test "x$with_fftw" != "xno"; then if test "x$with_fftw" != "xyes"; then LIBS="$LIBS -L$with_fftw/lib -lfftw3f" INCLUDES="$INCLUDES -I$with_fftw/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -lfftw3f" fi AC_CHECK_LIB(fftw3f, fftwf_malloc, [AC_DEFINE([USE_FFTW], [1], [Define if you want to use FFTW])], [ echo "" echo "Error! FFTW3F version 3 is required but was not found" echo " Use --with-fftw=DIR to specify the FFTW directory tree" echo " Use --with-fftw=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" exit -1 ]) fi dnl == LIBPROJ4 ============================================ dnl ======================================================== AC_ARG_WITH(libproj4, [ --with-libproj4[=DIR] use LIBPROJ4 package (with optional path DIR) ], [with_libproj4="$withval" ]) if test "x$with_libproj4" != "xno"; then if test "x$with_libproj4" != "xyes"; then LIBS="$LIBS -L$with_libproj4/lib -lproj4" INCLUDES="$INCLUDES -I$with_libproj4/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -lproj4" fi AC_CHECK_LIB(proj4, proj_init, [AC_DEFINE([USE_LIBPROJ4], [1], [Define if you want to use LIBPROJ4])], []) AC_CHECK_LIB(proj4, proj_init, [AC_DEFINE([USE_LIBPROJ4_NEW], [1], [Define if you want to use new LIBPROJ4])], [ AC_CHECK_LIB(proj4, pj_init, [AC_DEFINE([USE_LIBPROJ4], [1], [Define if you want to use LIBPROJ4])], [ echo "" echo "Error! LIBPROJ4 is required but was not found" echo " Use --with-libproj4=DIR to specify the LIBPROJ4 directory tree" echo " Use --with-libproj4=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" exit -1 ]) ]) fi dnl == MPICH =============================================== dnl ======================================================== AC_ARG_WITH(mpich, [ --with-mpich[=DIR] use MPICH (experimental) (with optional path DIR) ], [with_mpich="$withval" ]) if test "x$with_mpich" != "xno"; then if test "x$with_mpich" != "xyes"; then LIBS="$LIBS -L$with_mpich/lib -lmpich" INCLUDES="$INCLUDES -I$with_mpich/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -lmpich" fi AC_CHECK_LIB(mpich, MPI_Init, [AC_DEFINE([USE_MPI], [1], [Define if you want to use MPI])], [ echo "" echo "Error! MPICH is required but was not found" echo " Use --with-mpich=DIR to specify the MPICH directory tree" echo " Use --with-mpich=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" exit -1 ]) fi dnl == Python (calling Python from GDL) ==================== dnl ======================================================== AC_ARG_WITH(python, [ --with-python[=DIR] use Python package (with optional path DIR) ], [with_python="$withval" ]) if test "x$with_python" != "xno"; then AM_PATH_PYTHON AC_ARG_ENABLE(python_version, [ --enable-python_version set explicit python version to use (eg. 2.6)], [ PYTHON_VERSION="$enableval" ]) if test "x$PYTHON_VERSION" = "x"; then AC_MSG_CHECKING([for Python version]) queryfile=$ac_confdir/query_version.py echo "# tmp file auto (re)generated by GDL configure. Please delete" > $queryfile echo import sys >> $queryfile echo print \'%s.%s\' % sys.version_info[\[0:2\]] >> $queryfile dnl echo print sys.version.split\(\'.\'\)[\[0\]]+\".\"+sys.version.split\(\'.\'\)[\[1\]] >> $queryfile PYTHON_VERSION=`python $queryfile` rm $queryfile AC_MSG_RESULT([$PYTHON_VERSION]) fi if test "x$with_python" != "xyes"; then LIBS="$LIBS -L$with_python/lib" LIBS="$LIBS -L$with_python/lib/python$PYTHON_VERSION/config -lpython$PYTHON_VERSION" PYTHON_INCLUDES="$with_python/include/python$PYTHON_VERSION" else LIBS="$LIBS -lpython$PYTHON_VERSION" PYTHON_INCLUDES="/usr/include/python$PYTHON_VERSION" fi AC_CHECK_LIB(python$PYTHON_VERSION, Py_Initialize, [AC_DEFINE([USE_PYTHON],[1],[Define if you want to use python])], [ echo "" echo "Error! Python version $PYTHON_VERSION is required but was not found" echo " Use --with-python=DIR to specify the python directory tree" echo " Use --with-python=no to not use it" echo "" echo " (suitable Debian/Ubuntu package: python$PYTHON_VERSION-dev)" echo " (suitable Fedora package: python-devel)" exit -1 ]) AC_CHECK_HEADER($PYTHON_INCLUDES/Python.h, [], [ echo "" echo "Error! Python header file not found (missing '-devel' package?)" echo " Use --with-python=no to disable Python support" exit -1 ]) OLDCPPFLAGS=$CPPFLAGS AC_MSG_CHECKING([for Numpy include directory]) pinc=`echo "import numpy; print numpy.get_include()" | $PYTHON - 2>/dev/null` AC_MSG_RESULT([${pinc:-unknown}]) test -n "$pinc" && PYTHON_INCLUDES="$PYTHON_INCLUDES -I$pinc" CPPFLAGS="$CPPFLAGS -I$PYTHON_INCLUDES" AC_CHECK_HEADER([numpy/arrayobject.h], [], [ echo "" echo "Error! Python numpy package was not found" echo " Use --with-python=no to disable Python support" echo "" echo " (suitable Debian/Ubuntu package: python-numpy)" exit -1 ], [#include ]) CPPFLAGS=$OLDCPPFLAGS unset OLDCPPFLAGS INCLUDES="$INCLUDES -I$PYTHON_INCLUDES" fi dnl == UDUNITS-2 =========================================== dnl ======================================================== AC_ARG_WITH(udunits, [ --with-udunits[=DIR] use UDUNITS-2 package (with optional path DIR) ], [with_udunits="$withval" ]) if test "x$with_udunits" != "xno"; then if test "x$with_udunits" != "xyes"; then LIBS="$LIBS -L$with_udunits/lib -ludunits2" INCLUDES="$INCLUDES -I$with_udunits/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -ludunits2" fi AC_CHECK_LIB(udunits2, ut_get_unit_by_name, [AC_DEFINE([USE_UDUNITS], [1], [Define if you want to use UDUNITS-2])], [ echo "" echo "Error! UDUNITS-2 is required but was not found" echo " Use --with-udunits=DIR to specify the UDUNITS-2 directory tree" echo " Use --with-udunits=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libudunits2-dev)" echo " (suitable Fedora package: udunits2-devel)" exit -1 ]) AC_CHECK_HEADERS(udunits2/udunits2.h) fi dnl == GRIB ================================================ dnl ======================================================== AC_ARG_WITH(grib, [ --with-grib[=DIR] use GRIB package (with optional path DIR) ], [with_grib="$withval" ]) if test "x$with_grib" != "xno"; then if test "x$with_grib" != "xyes"; then LIBS="$LIBS -L$with_grib/lib -lgrib_api" INCLUDES="$INCLUDES -I$with_grib/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -lgrib_api" fi AC_CHECK_LIB(grib_api, grib_handle_new_from_file, [ AC_DEFINE([USE_GRIB], [1], [Define if you want to use GRIB]) ], [ AC_MSG_CHECKING([if linking with Jasper helps]) echo "" AC_CHECK_LIB(grib_api, grib_handle_clone, [ LIBS="$LIBS -ljasper" AC_DEFINE([USE_GRIB], [1], [Define if you want to use GRIB]) ], [ AC_MSG_CHECKING([if linking with Jasper and OpenJPEG helps]) echo "" AC_CHECK_LIB(grib_api, grib_handle_delete, [ LIBS="$LIBS -ljasper -lopenjpeg" AC_DEFINE([USE_GRIB], [1], [Define if you want to use GRIB]) ], [ AC_MSG_CHECKING([if linking with Jasper and OpenJPEG and PNG helps]) echo "" AC_CHECK_LIB(grib_api, grib_handle_new_from_message, [ LIBS="$LIBS -ljasper -lopenjpeg -lpng" AC_DEFINE([USE_GRIB], [1], [Define if you want to use GRIB]) ], [ echo "" echo "Error! GRIB is required but was not found" echo " Use --with-grib=DIR to specify the GRIB directory tree" echo " Use --with-grib=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: libgrib-api-dev)" echo " (suitable Fedora package: grib_api-devel)" exit -1 ], [-ljasper -lopenjpeg -lpng]) ], [-ljasper -lopenjpeg]) ], [-ljasper]) ] ) fi dnl == GSHHS =============================================== dnl ======================================================== AC_ARG_WITH(gshhs, [ --with-gshhs[=DIR] use GSHHS package (with optional path DIR) ], [with_gshhs="$withval" ]) if test "x$with_gshhs" != "xno"; then if test "x$with_gshhs" != "xyes"; then INCLUDES="$INCLUDES -I$with_gshhs/include" fi AC_CHECK_HEADERS(gshhs.h, [ AC_DEFINE([USE_GSHHS], [1], [Define if you want to use GSHHS]) ], [ echo "" echo "Error! GSHHS is required but gshhs.h was not found" echo " Use --with-gshhs=DIR to specify the GSHHS directory tree" echo " Use --with-gshhs=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" exit -1 ]) fi dnl == Xlib ================================================ dnl ======================================================== AC_PATH_X if test "x$no_x" = "xyes"; then echo "" echo "Warning! X Window System not detected, building with Xlib calls disabled" echo " Use --x-includes=DIR and --x-libraries=DIR to pass any needed paths" echo "" else AC_DEFINE([HAVE_X], [1], [Define if you want to enable calls to Xlib]) fi dnl == pslib =============================================== dnl ======================================================== AC_ARG_WITH(pslib, [ --with-pslib[=DIR] use pslib package (with optional path DIR) ], [with_pslib="$withval" ]) if test "x$with_pslib" != "xno"; then if test "x$with_pslib" != "xyes"; then LIBS="$LIBS -L$with_pslib/lib -lps" INCLUDES="$INCLUDES -I$with_pslib/include" else INCLUDES="$INCLUDES -I/usr/include" LIBS="$LIBS -lps" fi AC_CHECK_LIB(ps, PS_new, [AC_DEFINE([USE_PSLIB], [1], [Define if you want to use pslib])], [ echo "" echo "Error! pslib is required but it was not found" echo " Use --with-pslib=DIR to specify the pslib directory tree" echo " Use --with-pslib=no to not use it" echo " Check the README or use configure --help for other libraries needed" echo " (--with-xxxdir = obligatory, --with-xxx = optional (--with-xxx=no to disable))" echo "" echo " (suitable Debian/Ubuntu package: pslib-dev)" echo " (suitable Fedora package: pslib-devel)" exit -1 ]) fi dnl == installation paths ================================== dnl ======================================================== AC_DEFUN([AC_DEFINE_DIR], [ prefix_NONE= exec_prefix_NONE= test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn dnl refers to ${prefix}. Thus we have to use `eval' twice. eval ac_define_dir="\"[$]$2\"" eval ac_define_dir="\"$ac_define_dir\"" AC_SUBST($1, "$ac_define_dir") AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3]) test "$prefix_NONE" && prefix=NONE test "$exec_prefix_NONE" && exec_prefix=NONE ]) AC_DEFINE_DIR([EXEC_PREFIX], [exec_prefix], [--exec-prefix or default]) #AC_DEFINE([EXEC_PREFIX],[\"`echo ${exec_prefix}`\"],[GDL installation directory]) AC_DEFINE_DIR([GDLDATADIR], [datadir/$datasubdir], [$datadir/gnudatalanguage]) dnl == OS-/architecture-dependant options ================== dnl ======================================================== DARWIN="no" case "${host}" in *darwin*) DARWIN="yes" esac dnl check for specific architecture case "${host}" in powerpc-*-darwin* ) dnl PowerPC Darwin based distributions (including Mac OS X) LDFLAGS="$LDFLAGS -bind_at_load" ;; powerpc*-*-linux* ) LDFLAGS="$LDFLAGS -rdynamic" ;; *linux*) dnl Linux dnl LINKIMAGE support dnl (-ltermcap was reported to solve problems with readline) dnl LDFLAGS="$LDFLAGS -ltermcap -rdynamic -z muldefs" LDFLAGS="$LDFLAGS -rdynamic -Wl,-z,muldefs" ;; *solaris* ) LIBS="$LIBS -lsocket -lnsl" ;; *cygwin* ) LIBS="$LIBS -lrpc" ;; dnl *) dnl AC_MSG_ERROR(unknown system type ${host}.) dnl ;; esac dnl check if old darwin (needs some workarounds) case "${host}" in *darwin6*) dnl Jaguar AC_DEFINE([OLD_DARWIN], [1], [Pre-10.5 version of OS X]) ;; *darwin7*) dnl Panther AC_DEFINE([OLD_DARWIN], [1], [Pre-10.5 version of OS X]) ;; *darwin8.8*) dnl newer Tiger ;; *darwin8.9*) dnl newer Tiger ;; *darwin8.10*) dnl newer Tiger ;; *darwin8.11*) dnl newer Tiger ;; *darwin8.12*) dnl newer Tiger ;; *darwin8.13*) dnl newer Tiger ;; *darwin8.14*) dnl newer Tiger ;; *darwin8.15*) dnl newer Tiger ;; *darwin9*) dnl Leopard ;; *darwin8*) dnl Tiger AC_DEFINE([OLD_DARWIN], [1], [Pre-10.4.8 version of OS X]) ;; esac dnl for src/Makefile.am: OS X linker does not know -z AM_CONDITIONAL(DARWIN, test "x$DARWIN" = "xyes") dnl == some final instructions ============================= dnl ======================================================== EXT_LIBS="$EXT_LIBS $LIBS" EXT_INCLUDES="$EXT_INCLUDES $INCLUDES" AC_SUBST(EXT_LIBS) AC_SUBST(EXT_INCLUDES) dnl some stuff copied from wxWindows dnl install checks dnl defines INSTALL with the appropriate command AC_PROG_INSTALL dnl make install path absolute (if not already); dnl will fail with (some) MSDOS paths case ${INSTALL} in /* ) # Absolute ;; ?:* ) # Drive letter, considered as absolute. ;; *) INSTALL=`pwd`/${INSTALL} ;; esac case "${host}" in dnl The other BSD's should probably go in here too, since this is dnl to workaround a strange static lib BSDism. dnl Mac OS X install seems to ignore -p option... *-*-darwin* ) INSTALL_PROGRAM="cp -fp" INSTALL_DATA="cp -fp" ;; *) ;; esac dnl echo LIBS $LIBS dnl echo INCLUDES $INCLUDES dnl Checks for header files. dnl AC_HEADER_STDC dnl Checks for typedefs, structures, and compiler characteristics. dnl AC_C_CONST dnl Checks for library functions. dnl AC_CHECK_FUNCS(strdup strtod strtol abs) dnl perform program name transformation dnl AC_ARG_PROGRAM AC_CONFIG_FILES(Makefile src/Makefile src/antlr/Makefile src/pro/Makefile src/pro/dicom/Makefile src/pro/envi/Makefile testsuite/Makefile doc/Makefile) AC_OUTPUT dnl == summary table ======================================= dnl ======================================================== echo " GDL - GNU Data Language ----- compilation options: --------------------------- System: $host Installation prefix: $prefix C++ compiler: $CXX $CXXFLAGS OpenMP support: `if test "x$with_openmp" = "xno"; then echo 'no'; else echo 'yes'; fi` Build type: `if test "x$PYTHON_MODULE" = "xyes"; then echo 'library (Python module)'; else echo 'standalone (other: Python module)'; fi` ----- optional libraries (consult README/INSTALL): --- wxWidgets: `if test no = $with_wxWidgets; then echo 'no'; else echo yes; fi` Magick: `if test no = $with_Magick; then echo 'no'; else echo yes; fi` GraphicsMagick: `if test no = $with_GraphicsMagick; then echo 'no'; else echo yes; fi` Eigen: `if test no = $with_eigen; then echo 'no'; else echo yes; fi` NetCDF: `if test no = $with_netcdf; then echo 'no'; else echo yes; fi` HDF4: `if test no = $with_hdf; then echo 'no'; else echo yes; fi` HDF5: `if test no = $with_hdf5; then echo 'no'; else echo yes; fi` FFTW: `if test no = $with_fftw; then echo 'no (GSL version used)'; else echo yes; fi` libproject: `if test no = $with_libproj4; then echo 'no (see also MAP_INSTALL)'; else echo yes; fi` MPICH: `if test no = $with_mpich; then echo 'no (needs explicit enabling)'; else echo yes; fi` Python: `if test no = $with_python; then echo 'no (see also PYTHON.txt)'; else echo \"yes ($PYTHON_VERSION)\"; fi` UDUNITS-2: `if test no = $with_udunits; then echo 'no (needs explicit enabling)'; else echo yes; fi` GRIB: `if test no = $with_grib; then echo 'no (needs explicit enabling)'; else echo yes; fi` GSHHS: `if test no = $with_gshhs; then echo 'no (see also MAP_INSTALL)'; else echo yes; fi` Xlib: `if test xyes = x$no_x; then echo 'no'; else echo yes; fi` pslib: `if test no = $with_pslib; then echo 'no'; else echo yes; fi` ----- notes on auxiliary files: ---------------------- - consult MAP_INSTALL for details concerning auxiliary files needed for mapping support - SAVE and RESTORE procedures require *.pro files from the CMSVLIB package (see README for details) ------------------------------------------------------ `if test yes = $openmp_autodetected; then echo ' ----- note on OpenMP support -------------------------' echo ' OpenMP was autodetected, use --with-openmp=no if your' echo ' compiler does not support it (e.g. GCC < 4.2)' echo ' ------------------------------------------------------'; fi` use 'make' to build and 'make install' to install GDL (optional 'make check' tests the build - experimental) " echo " *********************** WARNING ****************************** We plan to drop support for Autotools-based configuration (i.e. the configure script) and switch to CMake. If possible, please try to compile GDL with CMake (e.g. by typing \"cmake .\" instead of \"./configure\") and please do report any problems. Consult INSTALL.CMake for help on passing options to CMake. ************************************************************** " dnl == EOF ================================================= gdl-0.9.9/obsolete/gdl.kdevelop000066400000000000000000000232521340051421000164060ustar00rootroot00000000000000 Marc Schellens m_schellens@users.sourceforge.net 0.9 KDevAutoProject C++ C++ Code . false Python gdl src/gdl debug true /home/marc/gdl/debug/src/gdl false executable / true /home/marc/gdl/debug/src true false false optimized kdevgccoptions kdevgppoptions kdevg77options -O2 -DNDEBUG -msse3 -mfpmath=sse,387 --enable-debug=full --with-netcdf=no --with-python=no --with-hdf=no --with-hdf5=no --with-plplot=/usr --with-python=no --disable-python_module --with-wxWidgets=no --with-Magick=yes --enable-oldplplot --with-readlinedir=yes --with-hdf=yes --with-hdf5=yes --with-plplotdir=/usr/local --with-python=yes --disable-python_module --with-netcdf=no --disable-oldplplot --with-openmp=no --with-libproj4=no --with-mpich=/usr/lib/mpich --with-wxWidgets=yes --with-Magick=yes debug kdevgccoptions kdevgppoptions kdevg77options -O0 -g3 --with-python=yes --with-hdf=no --with-hdf5=no --with-netcdf=/usr/local --disable-python_module default -pg kdevgccoptions kdevgppoptions kdevg77options -O3 -g3 -DNDEBUG true 2 false 0 true ada ada_bugs_gcc bash bash_bugs clanlib w3c-dom-level2-html fortran_bugs_gcc gnome1 gnustep gtk gtk_bugs haskell haskell_bugs_ghc java_bugs_gcc java_bugs_sun kde2book opengl pascal_bugs_fp php php_bugs perl perl_bugs python python_bugs qt-kdev3 ruby ruby_bugs sdl w3c-svg sw w3c-uaag10 wxwindows_bugs Guide to the Qt Translation Tools Qt Assistant Manual Qt Designer Manual Qt Reference Documentation qmake User Guide KDE Libraries (Doxygen) html/ html/ false false *.o,*.lo,CVS false false .hpp .cpp true true true false true true true 250 400 250 false 0 true true false std=_GLIBCXX_STD;__gnu_cxx=std true false false false true true true false .; false false set m_,_ theValue true true false 3 /usr/share/qt3 3 EmbeddedKDevDesigner false true Vertical true true true false true true 10 true true true true -C /home/marc/gdl/tags gdl-0.9.9/obsolete/strassenmatrix.hpp000066400000000000000000001524031340051421000177060ustar00rootroot00000000000000#ifndef STRASSENMATRIX_HPP__ #define STRASSENMATRIX_HPP__ #define USE_STRASSEN_MATRIXMULTIPLICATION #ifdef USE_STRASSEN_MATRIXMULTIPLICATION // optimized strassen matrix multiplication // to be included by basic_op.cpp // problem: this implementation only scales to up to 7 processors // and the omp task construct seems to be only available from OpenMP 3 on // this means it will not use OpenMP at all on non up to date machines // #include "typedefs.hpp" // #ifdef _OPENMP // #include // #endif //const SizeT minStrassenMatrixSize = 500; const SizeT minStrassenMatrixResolveSize = 32; const SizeT minStrassenMatrixResolveSize2 = minStrassenMatrixResolveSize^2; const SizeT minStrassenMatrixResolveSize3 = minStrassenMatrixResolveSize^3; // B has always greater (or equal) indices template< typename T> void SMAdd( SizeT mSz, SizeT abx, SizeT aby, T *A, SizeT ax, SizeT ay, SizeT as, SizeT bx, SizeT by, T *C, long cxLim, long cyLim)// C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; T*& B = A; SizeT& bs = as; long i; long j; long mSzX = (cxLim>mSz)?mSz:cxLim; long mSzY = (cyLim>mSz)?mSz:cyLim; // ax is always smaller or equal to bx, same for ay and by // hence axLim is greater or equal then bxLim, same for ayLim and byLim long axLim,ayLim,bxLim,byLim; if( (bx+mSz)>=abx) { bxLim=abx-bx; if( (by+mSz)>=aby) byLim=aby-by; else byLim=mSz; } else { if( (by+mSz)>=aby) byLim=aby-by; else { for (long i=0; i=abx) { axLim=abx-ax; if( (ay+mSz)>=aby) ayLim=aby-ay; else ayLim=mSz; } else { if( (ay+mSz)>=aby) ayLim=aby-ay; else { if( bxLim > cxLim) bxLim = mSzX; if( byLim > cyLim) byLim = mSzY; for (i=0; i cxLim) axLim = mSzX; if( ayLim > cyLim) ayLim = mSzY; if( bxLim > cxLim) bxLim = mSzX; if( byLim > cyLim) byLim = mSzY; for (i=0; i // void SMAddNoCheck( SizeT mSz, // T *A, SizeT ax, SizeT ay, SizeT as, /* (ax,ay) = origin of A submatrix */ // SizeT bx, SizeT by, /* (bx,by) = origin of B submatrix */ // T *C, SizeT cx, SizeT cy, SizeT cs) /* (cx,cy) = origin of C submatrix */ // { // T*& B = A; // SizeT& bs = as; // // for (long i=0; i void SMSub1( SizeT mSz, SizeT abx, SizeT aby, T *A, SizeT ax, SizeT ay, SizeT as, SizeT bx, SizeT by, T *C, long cxLim, long cyLim)// C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; T*& B = A; SizeT& bs = as; long i; long j; // C is not checked (does not need to) long mSzX = (cxLim>mSz)?mSz:cxLim; long mSzY = (cyLim>mSz)?mSz:cyLim; // ax is always smaller or equal to bx, same for ay and by // hence axLim is greater or equal then bxLim, same for ayLim and byLim long axLim,ayLim,bxLim,byLim; if( (bx+mSz)>=abx) { bxLim=abx-bx; if( (by+mSz)>=aby) byLim=aby-by; else byLim=mSz; } else { if( (by+mSz)>=aby) byLim=aby-by; else { for (long i=0; i=abx) { axLim=abx-ax; if( (ay+mSz)>=aby) ayLim=aby-ay; else ayLim=mSz; } else { if( (ay+mSz)>=aby) ayLim=aby-ay; else { for (i=0; i cxLim) axLim = mSzX; if( ayLim > cyLim) ayLim = mSzY; if( bxLim > cxLim) bxLim = mSzX; if( byLim > cyLim) byLim = mSzY; for (i=0; i void SMSub2( SizeT mSz, SizeT abx, SizeT aby, T *A, SizeT ax, SizeT ay, SizeT as, SizeT bx, SizeT by, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; T*& B = A; SizeT& bs = as; long i; long j; // C is not checked (does not need to) long mSzX = (cxLim>mSz)?mSz:cxLim; long mSzY = (cyLim>mSz)?mSz:cyLim; // ax is always smaller or equal to bx, same for ay and by // hence axLim is greater or equal then bxLim, same for ayLim and byLim long axLim,ayLim,bxLim,byLim; if( (ax+mSz)>=abx) { axLim=abx-ax; if( (ay+mSz)>=aby) ayLim=aby-ay; else ayLim=mSz; } else { if( (ay+mSz)>=aby) ayLim=aby-ay; else { for (long i=0; i=abx) { bxLim=abx-bx; if( (by+mSz)>=aby) byLim=aby-by; else byLim=mSz; } else { if( (by+mSz)>=aby) byLim=aby-by; else { for (i=0; i cxLim) axLim = mSzX; if( ayLim > cyLim) ayLim = mSzY; if( bxLim > cxLim) bxLim = mSzX; if( byLim > cyLim) byLim = mSzY; for (i=0; i void SMNegate( SizeT mSz, SizeT abx, SizeT aby, T *A, SizeT ax, SizeT ay, SizeT as, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; long i; long j; // C is not checked (does not need to) // ax is always smaller or equal to bx, same for ay and by // hence axLim is greater or equal then bxLim, same for ayLim and byLim long axLim,ayLim; if( (ax+mSz)>=abx) { axLim=abx-ax; if( (ay+mSz)>=aby) ayLim=aby-ay; else ayLim=mSz; } else { if( (ay+mSz)>=aby) ayLim=aby-ay; else { for (long i=0; i void SMM( SizeT mSz, long l, long m, long n, // A[l,m]#B[m,n]=C[l,n] T *A, SizeT ax, SizeT ay, SizeT as, T *B, SizeT bx, SizeT by, SizeT bs, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; long i, j, k; const SizeT cx=0; const SizeT cy=0; SizeT& cs=mSz; long mSzX = (mSz>cxLim)?cxLim:mSz; long mSzY = (mSz>cyLim)?cyLim:mSz; if( (ax+mSz)>=n) n-=ax; else n=mSz; if( (by+mSz)>=l) l-=by; else l=mSz; if( ay>bx) if( (ay+mSz)>=m) m-=ay; else m=mSz; else if( (bx+mSz)>=m) m-=bx; else m=mSz; if( n > cxLim && l > cyLim) { for (i=0; i cxLim) n = cxLim; if( l > cyLim) l = cyLim; for (i=0; i void SMMNoCheckAB( SizeT mSz, // A[l,m]#B[m,n]=C[l,n] T *A, SizeT ax, SizeT ay, SizeT as, T *B, SizeT bx, SizeT by, SizeT bs, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; // const SizeT cx=0; // const SizeT cy=0; // SizeT& cs=mSz; long mSzX = (mSz>cxLim)?cxLim:mSz; long mSzY = (mSz>cyLim)?cyLim:mSz; for (long i=0; i void SMNoCheckAB( T* buf, SizeT mSz, // A[l,m]#B[m,n]=C[l,n] T *A, SizeT ax, SizeT ay, SizeT as, T *B, SizeT bx, SizeT by, SizeT bs, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; if( mSz <= minStrassenMatrixResolveSize) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim) <= minStrassenMatrixResolveSize2)) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim * mSz) <= minStrassenMatrixResolveSize3)) { SMMNoCheckAB( mSz, A, ax, ay, as, B, bx, by, bs, C, cxLim, cyLim);//, cx, cy, cs); return; } // divide and rule long n_2 = mSz >> 1; SizeT n_22 = n_2 * n_2; // T* buf = new T[n_22 * 9]; T*& a_cum = buf; T* b_cum = a_cum + n_22; T* p1 = b_cum + n_22; T* p2 = p1 + n_22; T* p3 = p2 + n_22; T* p4 = p3 + n_22; T* p5 = p4 + n_22; T* p6 = p5 + n_22; T* p7 = p6 + n_22; T* subBuf = p7 + n_22; SizeT ax2 = ax+n_2; SizeT ay2 = ay+n_2; SizeT bx2 = bx+n_2; SizeT by2 = by+n_2; /* p1 = (a11 + a22) x (b11 + b22) */ T* A11 = &A[ax*as+ay]; T* A21 = &A[ax2*as+ay]; T* A12 = &A[ax*as+ay2]; T* A22 = &A[ax2*as+ay2]; T* B11 = &B[bx*bs+by]; T* B21 = &B[bx2*bs+by]; T* B12 = &B[bx*bs+by2]; T* B22 = &B[bx2*bs+by2]; long xLim = (cxLim > n_2) ? n_2: cxLim; long yLim = (cyLim > n_2) ? n_2: cyLim; long xLim2 = cxLim - n_2; long yLim2 = cyLim - n_2; assert( xLim2 <= n_2); assert( yLim2 <= n_2); /* p1 = (a11 + a22) x (b11 + b22) */ SizeT cumIx = 0; for (long i=0; i(n_2,l,m, A, ax, ay, as, ax+n_2, ay+n_2, a_cum); //SMAdd(n_2,m,n, B, bx, by, bs, bx+n_2, by+n_2, b_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p1, xLim, yLim); /* p4 = a22 x (b21 - b11) */ cumIx = 0; for (long i=0; i(n_2,m,n, B, bx+n_2, by, bs, bx, by, b_cum); SMNoCheckAB(subBuf,n_2, A, ax+n_2, ay+n_2, as, b_cum, 0, 0, n_2, p4, xLim, yLim); /* p5 = (a11 + a12) x b22 */ for (long i=0; i(n_2,l,m, A, ax, ay, as, ax, ay+n_2, a_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, B, bx+n_2, by+n_2, bs, p5, xLim, yLim); /* p7 = (a12 - a22) x (b21 + b22) */ cumIx = 0; for (long i=0; i(n_2,l,m, A, ax, ay+n_2, as, ax+n_2, ay+n_2, a_cum); // SMAdd(n_2,m,n, B, bx+n_2, by, bs, bx+n_2, by+n_2, b_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p7, xLim, yLim); // we are in SMNoCheckAB if( cxLim >= mSz && cyLim >= mSz) { /* p2 = (a21 + a22) x b11 */ cumIx = 0; for (long i=0; i(n_2,l,m, A, ax+n_2, ay, as, ax+n_2, ay+n_2, a_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, B, bx, by, bs, p2, xLim2, yLim); /* p3 = a11 x (b12 - b22) */ for (long i=0; i(n_2,m,n, B, bx, by+n_2, bs, bx+n_2, by+n_2, b_cum); SMNoCheckAB(subBuf,n_2, A, ax, ay, as, b_cum, 0, 0, n_2, p3, xLim, yLim2); /* p6 = (a21 - a11) x (b11 + b12) */ cumIx = 0; for (long i=0; i(n_2,l,m, A, ax+n_2, ay, as, ax, ay, a_cum); // SMAdd(n_2,m,n, B, bx, by, bs, bx, by+n_2, b_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p6, xLim2, yLim2); SizeT pIndex = 0; SizeT n_2_mSz = n_2 * mSz; SizeT n_2_mSz_n_2 = n_2_mSz + n_2; for( SizeT ix=0;ix= mSz && cyLim >= mSz) // { // SizeT pIndex = 0;//ix*n_2+iy; // for( SizeT ix=0;ix= cxLim) // x limited { cx11Lim = cxLim; if( n_2 >= cyLim) { cy11Lim = cyLim; // do12 = false; // do21 = false; // do22 = false; for( SizeT ix=0;ixmSz)?n_2:cyLim_n_2; } } else { cx11Lim = n_2; if( n_2 >= cyLim) { cy11Lim = cyLim; do12 = false; do21 = true; do22 = false; cy21Lim = cyLim; cx21Lim = (cxLim>mSz)?n_2:cxLim_n_2; } else { cy11Lim = n_2; do12 = true; do21 = true; do22 = true; cx12Lim = n_2; cy12Lim = (cyLim>mSz)?n_2:cyLim_n_2; cx21Lim = (cxLim>mSz)?n_2:cxLim_n_2; cy21Lim = n_2; cx22Lim = (cxLim>mSz)?n_2:cxLim_n_2; cy22Lim = (cyLim>mSz)?n_2:cyLim_n_2; } } for( SizeT ix=0;ix(n_2,m,n, B, bx, by+n_2, bs, bx+n_2, by+n_2, b_cum); SMNoCheckAB(subBuf,n_2, A, ax, ay, as, b_cum, 0, 0, n_2, p3, xLim, yLim2); for( SizeT ix=0;ix(n_2,l,m, A, ax+n_2, ay, as, ax+n_2, ay+n_2, a_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, B, bx, by, bs, p2, xLim2, yLim); for( SizeT ix=0;ix(n_2,l,m, A, ax+n_2, ay, as, ax, ay, a_cum); // SMAdd(n_2,m,n, B, bx, by, bs, bx, by+n_2, b_cum); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p6, xLim2, yLim2); for( SizeT ix=0;ix void SMCheckA( T* a_cum, SizeT mSz, SizeT l, SizeT m, SizeT n, // A[l,m]#B[m,n]=C[l,n] T *A, SizeT ax, SizeT ay, SizeT as, T *B, SizeT bx, SizeT by, SizeT bs, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; if( (ax)>=n || (ay)>=m) { // SizeT mSz2 = mSz * mSz; for (SizeT ix=0; ix(a_cum,mSz, A, ax, ay, as, B, bx, by, bs, C, cxLim, cyLim); return; } if( mSz <= minStrassenMatrixResolveSize) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim) <= minStrassenMatrixResolveSize2)) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim * mSz) <= minStrassenMatrixResolveSize3)) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim * ((ay < mSz)?ay:mSz)) <= minStrassenMatrixResolveSize3)) // if( mSz <= minStrassenMatrixResolveSize) { SMM( mSz, l, m, n, A, ax, ay, as, B, bx, by, bs, C, cxLim, cyLim);//, cx, cy, cs); return; } // divide and rule long n_2 = mSz >> 1; SizeT n_22 = n_2 * n_2; // T* buf = new T[n_22 * 9]; // T*& a_cum = buf; T* b_cum = a_cum + n_22; T* p1 = b_cum + n_22; T* p2 = p1 + n_22; T* p3 = p2 + n_22; T* p4 = p3 + n_22; T* p5 = p4 + n_22; T* p6 = p5 + n_22; T* p7 = p6 + n_22; T* subBuf = p7 + n_22; bool ax2Out = (ax+n_2)>=n; bool ay2Out = (ay+n_2)>=m; long xLim = (cxLim > n_2) ? n_2: cxLim; long yLim = (cyLim > n_2) ? n_2: cyLim; long xLim2 = cxLim - n_2; long yLim2 = cyLim - n_2; assert( xLim2 <= n_2); assert( yLim2 <= n_2); /* p1 = (a11 + a22) x (b11 + b22) */ SMAdd(n_2,m,l, B, bx, by, bs, bx+n_2, by+n_2, b_cum, n_2, yLim); if( ax2Out || ay2Out) { SMNoCheckAB(subBuf,n_2, A, ax, ay, as, b_cum, 0, 0, n_2, p1, xLim, yLim); } else { SMAdd(n_2,n,m, A, ax, ay, as, ax+n_2, ay+n_2, a_cum, xLim, n_2); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p1, xLim, yLim); } /* p5 = (a11 + a12) x b22 */ if( ay2Out) { SMCheckA(subBuf,n_2,l,m,n, A, ax, ay, as, B, bx+n_2, by+n_2, bs, p5, xLim, yLim); } else { SMAdd(n_2,n,m, A, ax, ay, as, ax, ay+n_2, a_cum, xLim, n_2); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, B, bx+n_2, by+n_2, bs, p5, xLim, yLim); } if( cyLim > n_2) { /* p3 = a11 x (b12 - b22) */ SMSub1(n_2,m,l, B, bx, by+n_2, bs, bx+n_2, by+n_2, b_cum, n_2, yLim2); SMCheckA(subBuf,n_2,l,m,n, A, ax, ay, as, b_cum, 0, 0, n_2, p3, xLim, yLim2); } if( cxLim > n_2 && cyLim > n_2) { /* p6 = (a21 - a11) x (b11 + b12) */ if( ax2Out) SMNegate(n_2,n,m, A, ax, ay, as, a_cum, xLim2, n_2); else SMSub2(n_2,n,m, A, ax+n_2, ay, as, ax, ay, a_cum, xLim2, n_2); SMAdd(n_2,m,l, B, bx, by, bs, bx, by+n_2, b_cum, n_2, yLim2); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p6, xLim2, yLim2); } long cx11Lim; long cy11Lim; long cx12Lim; long cy12Lim; long cx21Lim; long cy21Lim; long cx22Lim; long cy22Lim; long cxLim_n_2 = cxLim - n_2; long cyLim_n_2 = cyLim - n_2; bool do12, do21, do22; if( n_2 >= cxLim) // x limited { cx11Lim = cxLim; if( n_2 >= cyLim) { cy11Lim = cyLim; do12 = false; do21 = false; do22 = false; } else { cy11Lim = n_2; do12 = true; do21 = false; do22 = false; cx12Lim = cxLim; cy12Lim = (cyLim>mSz)?n_2:cyLim_n_2; } } else { cx11Lim = n_2; if( n_2 >= cyLim) { cy11Lim = cyLim; do12 = false; do21 = true; do22 = false; cy21Lim = cyLim; cx21Lim = (cxLim>mSz)?n_2:cxLim_n_2; } else { cy11Lim = n_2; do12 = true; do21 = true; do22 = true; cx12Lim = n_2; cy12Lim = (cyLim>mSz)?n_2:cyLim_n_2; cx21Lim = (cxLim>mSz)?n_2:cxLim_n_2; cy21Lim = n_2; cx22Lim = (cxLim>mSz)?n_2:cxLim_n_2; cy22Lim = (cyLim>mSz)?n_2:cyLim_n_2; } } if( ax2Out && ay2Out) // no p2 p4 p7 { for( SizeT ix=0;ix(n_2,n,m, A, ax+n_2, ay+n_2, as, a_cum, xLim, n_2); else SMSub1(n_2,n,m, A, ax, ay+n_2, as, ax+n_2, ay+n_2, a_cum, xLim, n_2); SMAdd(n_2,m,l, B, bx+n_2, by, bs, bx+n_2, by+n_2, b_cum, n_2, yLim); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p7, xLim, yLim); } if( ax2Out) // no p2 p4 { for( SizeT ix=0;ix n_2) { /* p2 = (a21 + a22) x b11 */ if( ay2Out) { SMCheckA(subBuf,n_2,l,m,n, A, ax+n_2, ay, as, B, bx, by, bs, p2, xLim2, yLim); } else { SMAdd(n_2,n,m, A, ax+n_2, ay, as, ax+n_2, ay+n_2, a_cum, xLim2, n_2); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, B, bx, by, bs, p2, xLim2, yLim); } } if( ay2Out) // no p7 p4 { for( SizeT ix=0;ix(n_2,m,l, B, bx+n_2, by, bs, bx, by, b_cum, n_2, yLim); SMCheckA(subBuf,n_2,l,m,n, A, ax+n_2, ay+n_2, as, b_cum, 0, 0, n_2, p4, xLim, yLim); // we are in SMCheckA if( cxLim >= mSz && cyLim >= mSz) { SizeT pIndex = 0; SizeT n_2_mSz = n_2 * mSz; SizeT n_2_mSz_n_2 = n_2_mSz + n_2; for( SizeT ix=0;ix void SMCheckB( T* a_cum, SizeT mSz, SizeT l, SizeT m, SizeT n, // A[l,m]#B[m,n]=C[l,n] T *A, SizeT ax, SizeT ay, SizeT as, T *B, SizeT bx, SizeT by, SizeT bs, T *C, long cxLim, long cyLim) // C has always dimensions mSy*mSz { if( cxLim <= 0 || cyLim <=0) return; if( (bx)>=m || (by)>=l) { // SizeT mSz2 = mSz * mSz; for (SizeT ix=0; ix(a_cum,mSz, A, ax, ay, as, B, bx, by, bs, C, cxLim, cyLim); return; } if( mSz <= minStrassenMatrixResolveSize) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim) <= minStrassenMatrixResolveSize2)) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim * mSz) <= minStrassenMatrixResolveSize3)) // if( (mSz <= minStrassenMatrixResolveSize) || ((cxLim * cyLim * ((bx < mSz)?bx:mSz)) <= minStrassenMatrixResolveSize3)) // if( mSz <= minStrassenMatrixResolveSize) { SMM( mSz, l, m, n, A, ax, ay, as, B, bx, by, bs, C, cxLim, cyLim);//, cx, cy, cs); return; } // divide and rule long n_2 = mSz >> 1; SizeT n_22 = n_2 * n_2; // T* buf = new T[n_22 * 9]; // T*& a_cum = buf; T* b_cum = a_cum + n_22; T* p1 = b_cum + n_22; T* p2 = p1 + n_22; T* p3 = p2 + n_22; T* p4 = p3 + n_22; T* p5 = p4 + n_22; T* p6 = p5 + n_22; T* p7 = p6 + n_22; T* subBuf = p7 + n_22; bool bx2Out = (bx+n_2)>=m; bool by2Out = (by+n_2)>=l; long xLim = (cxLim>n_2)?n_2:cxLim; long yLim = (cyLim>n_2)?n_2:cyLim; long xLim2 = cxLim - n_2; long yLim2 = cyLim - n_2; assert( xLim2 <= n_2); assert( yLim2 <= n_2); /* p1 = (a11 + a22) x (b11 + b22) */ SMAdd(n_2,n,m, A, ax, ay, as, ax+n_2, ay+n_2, a_cum, xLim, n_2); if( bx2Out || by2Out) { SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, bx, by, bs, p1, xLim, yLim); } else { SMAdd(n_2,m,l, B, bx, by, bs, bx+n_2, by+n_2, b_cum, n_2, yLim); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p1, xLim, yLim); } if( cxLim > n_2) { /* p2 = (a21 + a22) x b11 */ SMAdd(n_2,n,m, A, ax+n_2, ay, as, ax+n_2, ay+n_2, a_cum, xLim2, n_2); SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, bx, by, bs, p2, xLim2, yLim); } /* p4 = a22 x (b21 - b11) */ if( bx2Out) SMNegate(n_2,m,l, B, bx, by, bs, b_cum, n_2, yLim); else SMSub2(n_2,m,l, B, bx+n_2, by, bs, bx, by, b_cum, n_2, yLim); SMNoCheckAB(subBuf,n_2, A, ax+n_2, ay+n_2, as, b_cum, 0, 0, n_2, p4, xLim, yLim); if( cxLim > n_2 && cyLim > n_2) { /* p6 = (a21 - a11) x (b11 + b12) */ SMSub2(n_2,n,m, A, ax+n_2, ay, as, ax, ay, a_cum, xLim2, n_2); if( by2Out) { SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, bx, by, bs, p6, xLim2, yLim2); } else { SMAdd(n_2,m,l, B, bx, by, bs, bx, by+n_2, b_cum, n_2, yLim2); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p6, xLim2, yLim2); } } long cx11Lim; long cy11Lim; long cx12Lim; long cy12Lim; long cx21Lim; long cy21Lim; long cx22Lim; long cy22Lim; long cxLim_n_2 = cxLim - n_2; long cyLim_n_2 = cyLim - n_2; bool do12, do21, do22; if( n_2 >= cxLim) // x limited { cx11Lim = cxLim; if( n_2 >= cyLim) { cy11Lim = cyLim; do12 = false; do21 = false; do22 = false; } else { cy11Lim = n_2; do12 = true; do21 = false; do22 = false; cx12Lim = cxLim; cy12Lim = (cyLim>mSz)?n_2:cyLim_n_2; } } else { cx11Lim = n_2; if( n_2 >= cyLim) { cy11Lim = cyLim; do12 = false; do21 = true; do22 = false; cy21Lim = cyLim; cx21Lim = (cxLim>mSz)?n_2:cxLim_n_2; } else { cy11Lim = n_2; do12 = true; do21 = true; do22 = true; cx12Lim = n_2; cy12Lim = (cyLim>mSz)?n_2:cyLim_n_2; cx21Lim = (cxLim>mSz)?n_2:cxLim_n_2; cy21Lim = n_2; cx22Lim = (cxLim>mSz)?n_2:cxLim_n_2; cy22Lim = (cyLim>mSz)?n_2:cyLim_n_2; } } SizeT pIndex = 0;//ix*n_2+iy; if( bx2Out && by2Out) // no p3 p5 p7 { for( SizeT ix=0;ix(subBuf,n_2, l,m,n, A, ax, ay, as, B, bx, by+n_2, bs, p3, xLim, yLim2); } else { SMSub1(n_2,m,l, B, bx, by+n_2, bs, bx+n_2, by+n_2, b_cum, n_2, yLim2); SMNoCheckAB(subBuf,n_2, A, ax, ay, as, b_cum, 0, 0, n_2, p3, xLim, yLim2); } } if( bx2Out) // no p5 p7 { for( SizeT ix=0;ix(n_2,n,m, A, ax, ay+n_2, as, ax+n_2, ay+n_2, a_cum, xLim, n_2); if( by2Out) { SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, bx+n_2, by, bs, p7, xLim, yLim); } else { SMAdd(n_2,m,l, B, bx+n_2, by, bs, bx+n_2, by+n_2, b_cum, n_2, yLim); SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p7, xLim, yLim); } if( by2Out) // no p3 p5 { for( SizeT ix=0;ix(n_2,n,m, A, ax, ay, as, ax, ay+n_2, a_cum, xLim, n_2); SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, bx+n_2, by+n_2, bs, p5, xLim, yLim); // we are in SMCheckB if( cxLim >= mSz && cyLim >= mSz) { SizeT pIndex = 0; SizeT n_2_mSz = n_2 * mSz; SizeT n_2_mSz_n_2 = n_2_mSz + n_2; for( SizeT ix=0;ix void dumpmatrix( T* A, SizeT mSz) { for( SizeT j=0; j void SM1( SizeT mSz, SizeT l, SizeT m, SizeT n, T *A, T *B, T *C) { const SizeT& as = m; const SizeT& bs = l; const SizeT& cs = l; assert( mSz > minStrassenMatrixResolveSize); // divide and rule long n_2 = mSz >> 1; SizeT n_22 = n_2 * n_2; T* p1 = new T[n_22 * 7]; T* p2 = p1 + n_22; T* p3 = p2 + n_22; T* p4 = p3 + n_22; T* p5 = p4 + n_22; T* p6 = p5 + n_22; T* p7 = p6 + n_22; long xLim = (n>n_2)?n_2:n; long yLim = (l>n_2)?n_2:l; long xLim2 = n - n_2; long yLim2 = l - n_2; assert( xLim2 <= n_2); assert( yLim2 <= n_2); // #pragma omp parallel #pragma intel omp taskq { /* p1 = (a11 + a22) x (b11 + b22) */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMAdd(n_2,n,m, A, 0, 0, as, 0+n_2, 0+n_2, a_cum, xLim, n_2); SMAdd(n_2,m,l, B, 0, 0, bs, 0+n_2, 0+n_2, b_cum, n_2, yLim); #ifdef SM_DUMP cout << "1***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(a_cum,n_2); dumpmatrix(b_cum,n_2); #endif SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p1, xLim, yLim); // SM(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p2); #ifdef SM_DUMP dumpmatrix(p1,n_2); // dumpmatrix(p2,n_2); #endif delete[] subBuf; } /* p4 = a22 x (b21 - b11) */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMSub2(n_2,m,l, B, 0+n_2, 0, bs, 0, 0, b_cum, n_2, yLim); #ifdef SM_DUMP cout << "4***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(b_cum,n_2); #endif SMCheckA(subBuf,n_2,l,m,n, A, 0+n_2, 0+n_2, as, b_cum, 0, 0, n_2, p4, xLim, yLim); #ifdef SM_DUMP dumpmatrix(p4,n_2); #endif delete[] subBuf; } /* p5 = (a11 + a12) x b22 */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMAdd(n_2,n,m, A, 0, 0, as, 0, 0+n_2, a_cum, xLim, n_2); #ifdef SM_DUMP cout << "5***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(a_cum,n_2); #endif SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, 0+n_2, 0+n_2, bs, p5, xLim, yLim); #ifdef SM_DUMP dumpmatrix(p5,n_2); #endif delete[] subBuf; } /* p7 = (a12 - a22) x (b21 + b22) */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMSub1(n_2,n,m, A, 0, 0+n_2, as, 0+n_2, 0+n_2, a_cum,xLim,n_2); SMAdd(n_2,m,l, B, 0+n_2, 0, bs, 0+n_2, 0+n_2, b_cum, n_2, yLim); #ifdef SM_DUMP cout << "7***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(a_cum,n_2); dumpmatrix(b_cum,n_2); #endif SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p7, xLim, yLim); // SM(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p7); #ifdef SM_DUMP dumpmatrix(p7,n_2); #endif delete[] subBuf; } /* p2 = (a21 + a22) x b11 */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMAdd(n_2,n,m, A, 0+n_2, 0, as, 0+n_2, 0+n_2, a_cum, xLim2, n_2); #ifdef SM_DUMP cout << "2***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(a_cum,n_2); #endif SMCheckB(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, B, 0, 0, bs, p2, xLim2, yLim); #ifdef SM_DUMP dumpmatrix(p2,n_2); #endif delete[] subBuf; } /* p3 = a11 x (b12 - b22) */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMSub1(n_2,m,l, B, 0, 0+n_2, bs, 0+n_2, 0+n_2, b_cum,n_2,yLim2); #ifdef SM_DUMP cout << "3***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(b_cum,n_2); #endif SMCheckA(subBuf,n_2,l,m,n, A, 0, 0, as, b_cum, 0, 0, n_2, p3, xLim, yLim2); #ifdef SM_DUMP dumpmatrix(p3,n_2); #endif delete[] subBuf; } /* p6 = (a21 - a11) x (b11 + b12) */ // #pragma omp task private( subBuf, a_cum, b_cum) default(shared) #pragma intel omp task default(shared) { T* subBuf = new T[ 5 * n_22]; T* a_cum = subBuf + 3 * n_22; T* b_cum = subBuf + 4 * n_22; SMSub2(n_2,n,m, A, 0+n_2, 0, as, 0, 0, a_cum,xLim2,n_2); SMAdd(n_2,m,l, B, 0, 0, bs, 0, 0+n_2, b_cum, n_2, yLim2); #ifdef SM_DUMP cout << "6***" << endl; #endif #ifdef SM_DUMP_CUM dumpmatrix(a_cum,n_2); dumpmatrix(b_cum,n_2); #endif SMNoCheckAB(subBuf,n_2, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p6, xLim2, yLim2); // SM(subBuf,n_2,l,m,n, a_cum, 0, 0, n_2, b_cum, 0, 0, n_2, p6); #ifdef SM_DUMP dumpmatrix(p6,n_2); #endif delete[] subBuf; } #pragma intel omp taskwait } // task /* c11 = p1 + p4 - p5 + p7 */ bool do12;// = true; bool do21;// = true; bool do22;// = true; long cxLim, cyLim; if( 0+n_2 >= l) { cyLim = l-0; if( 0+n_2 >= n) { cxLim = n-0; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for for( long ix=0;ix n_2 cyLim = n_2; if( 0+n_2 >= n) { // n non linear dimension < n (C[l,n]) cxLim = n-0; do12 = true; do21 = false; do22 = false; } else { cxLim = n_2; do12 = true; do21 = true; do22 = true; } } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for for( long ix=0;ix l) { cyLim = l-n_2; } else { cyLim = n_2; } if( 0+n_2 > n) { cxLim = n;//-(0+n_2); } else { cxLim = n_2; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for for( long ix=0;ix l) { cyLim = l;//l-(0+n_2); } else { cyLim = n_2; } if( 0+mSz > n) { cxLim = n-n_2; } else { cxLim = n_2; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for for( long ix=0;ix l) { cyLim = l-(0+n_2); } else { cyLim = n_2; } if( 0+mSz > n) { cxLim = n-(0+n_2); } else { cxLim = n_2; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for for( long ix=0;ix$R %u]@N,>wxLj B!nsXCl* jASKP9j52aGL }_HPډ2(bCc=G9rR?*9r|<̑N8Gzͣ#M[Y;;X^RՈ}5&)X(@q kI9}L`p0Ҩa.(A`7ǘQUl6N>#.+ЏF)1@dA wK  Yphm8kȀZÊPIgpOK CpV.¿?wizƫ{tCm|P:l:eLCKlq/S['5L)fgG ꈤ@\HU8,'{{r m1A|Lm@90.B܌?Q;0 q& skƙ&E[>& $$;j  C#oa\. 3+u@扜L&&c@ P:}vEyҮUIM.N"1fhQi2;ҩk,&EI·Ӈ<5|ܫ] mݙ>ٟӺ\= 5\O%!cmRU uڮ ,*;Tn.W9R( T|Lk{e~!L?oX5{VBq[)3  $NOzl7.l!mѣYj!%S?<[|/e# =\HiwwxtVk IMD4l*m܊U/,0h+|bcA- &X/O@o _r7ސk4K+F }+Lo2AU ߍc Sv c/CDWWLb4=PUxo$&x.8wW })܎TvWm̸SẺ`@q |09;b4wQ%ĖW5n#ބ>soS:N,%ـN@ lb%Hs 43p%_~:R.f 4?Z&ɰ9hx_2- A <_?_?_gGE~O _*.VJLo^Ɉy$mZrm3ޠOX_݈ πfcE&%. aQ79Қus[Ǯg+ =PERǤiT3n XB6 @"ԆY |ż[#gAg*6؝:.}r@5~s@ gvL4U .d( 4; zT|@3UL0kdSsaSSOrkv(y9x bv(w8j#q'̖9\L xLlHO>. cFMQhfU[Oy2UjCcdIȦ]#m=vF[TR%}[ ϣZyN .A7k i S%B (jto4 tY!6us%-t giI/:QcdԵn;`Q z u$nqZ]7< toYw pB35[ON±E"Nٍ@s )$`羞rέ/,QcBP9#(Cc2=9mCCgv-k5րdBF:w:<aP9gZHn'd >yvT "A@Yp#,(7DG#>} =*;QooԂAh?⚭Ei4zJڛjΪ3OGϩgT3;d`1Afu H?1!djg O"Sjig rș~_ `,0#8ڋ|cYb =4+JeO.5&\h}4 XC*bpCO47W_1{?̿2_R*GqqRsG?w?O묏4?UO=Or7{F z= n%S3|G6jz[θ<7)e3 &~O*_Ym~70Jϓ÷A.LEwz3BL>ЏmBL7 ƎcWdGb/U $/$/5 <qD~=c踋U82e޽+A\W#Ibա;QSb7{'7qt>Ibvw# =i_d?67?!V rYp)oOVXSoߣOh|;:3Tl%G?7Wu:} />HPQ=Gϝ^[~4GjaW],킺:O}׷ra??l2aiX O2ߍ@'q'}hM=8zV&[-n+&1Nt0A$CHAECў`M҃}x?7h_Eo}2aU^g@^fȖcڑ $%C!:IJBl'":n4]=0gIܘtB4iQ>OcCƍ $ -C 30ny"'&i 0Rfct'8Ɓy(Fbm%98 _2;yzC@ eVzO䩲8O14.w9[I¬TOn|jEUϽxn1L?oHu{VBi9[%G5C~lcigJCoj{a07L?oHu{޵67k̇S*dTݺE NtS]VNctnW $N=Lu[Җ#>(o#)b1WN|gmJQ(T(iW>_mN[u>y wng@e'r.&3Ǜ6te"8mrYU\0Z,NԮmh;rdk8ݢ,M_jw%I?B- `Q, Jaʊ2vr]~, n [W+ t ҊbOGABOEf ~w-cnaWU\.JTgsU{r!6ȥ*+EXA[>ߚ\B+^:Sչ.< Foo}Q6uO<綕H s}a&tN3 \됭b<,')D9r[3nːR‚$ 2mF&(΋:^JY]jv.ڙ.5-SL~*Ixwh/Jx.16[;_j3?Gײɥ7GX%Pa o4=Uk7EB t'G(Onn_._mNx\[7j0/;T(#knU(gX; nfߠȜr2]2شEyUW(LV6u(y>:vAf)^*&AN[VˆtX\T2 %>tGxJoB/_A?mV!쿹A<23l\.4GdjlOovɐ ٰ I3ip`A%0R>X R r;*䦉M>BnW8zW;}k a}BеKjg`[:#ݵ-"UKBg:C5 ^P]8=4o4?~{5=|9w: q w㿑l5oN~n7Z w2 <,4֢;\@~Q:m(WΡD9)~x}h g?&';Roi.-=]} b\ (F?sSꎘx/=_vK?6 o}QVS;m lj4-"|z2ϸH)x,_NkU׶"# <"7@;-y$n,sd q7fs?}-_NЍUxJ ,JRngDR{!y/Ӈx(f6}y<_Hϯ~E1J9[XuSsI+|CbSbz+_srr"je. VpChT$xau' ѿ' PI4ΒϢS:iRS ƣO#4oc#x|}(g㿿;WVQ4diS nK!K"`MC?]Lp e\VJq剔&l=.ƣdQ^!jAUA2`ORJp1<M tzeTB ƖH/^&9I_еg(XS&[ȶǦA 2% ٻ4:}ǐwSwmqmqU |[#^p"q@PT"6Q F?V &ݽalq]Z;\l醫pۿࡷ*rA%{-PƭnPsPQ֧B50>๹4 Y2^R̮%v9o+YN;]̞3lBے1!Vw\3U{k=/)*C#K~a$[ )w/{ҁ#rYQO麖SvJO>:uQP\Hb9ϫY7Eь_%x@UNt|B˸)P_쮰CT{r<׏ /-@N5O;M<@u5f;/]Ui(2|y1T]X@LWw{4lm`CK՜+)n8t Tr ^5 6X_iF9m/mZ^l Ү\?6X_i͜s~)8tV?.W)W,4yT?WSR6A?\ |sjF֘|ZBЁrC-3̼*JFpV_WQwv-G'jw>hWB M r`Ik&e 骴/T{vuᶜ;6X_i~7NTsAQ\_9m BHi?ws*VF~wmO߀^o4^n>x4_5|  m(ܧqA5PsAIltP%>+"Aʍ7sj7wehtNG?Z6|[O,ӵ6!E|@mFP 㺧!xm CJuP̓xW,4*ncyй^(qDx we_g ӯ]wu .G'I%h^W~HMG;i a],|‹[ e]A4S46GW"ߪ._m(F7? d寛Imcm),JbGݼl>0dʪj]CȎ&g𿟌i F4ʿN. sk 4WvSc/}F~ ;27C?vA{I4.% eǡ%L?̸wju< `}QMM\|0]ԙv,xf+g 1Q~8@NPԣj4~uE %W6 e?_? [ Z7[Дb_;tFi?{9\ڽLJt\ |/ByތC}AQ<9g>"y!tB(@Yf;M>k][sx츶uigBZ$oQ( (ci-:999:,z3$yQ|0$N$FZ?]DXB'ӓ?Vn/I68-=~J6?}QivK?mtw9{8':LY3uXڲe [;MJ?8/\%E@3苆,s%WMƥضr-릪w5t*W>hrJ~`]Y)Wc)$20.kWY??0X=3=Ziiu'-@P" :\'KT ʹFnL-ziTcEB HJ(^s&>gEuf[bWmwe?6wz bY=>$hN'$X%Q[7 '> $o tɗǑ$ c{gڹn⇒&AHޫfd\,"vÿ qzBlQࡾpa_(AJiaJ#$-lD[fF1t|+%؟ɱ4ZRҽނ36U)A/0BSrvv*+: KTժw0U:3[S>iDt>J iRl)]]~6o <Q4O",;GZ8fz2&[,jE;%0a2+4Ϳyh JҎ Nʬ#$H/KN +|+žp?"o|\Y]8DGJ^yž7 P"jcDM~Wx00Kk|$c;S2,!c?xm-Yr0ٻw=C[n%ᕏ/! 4-cصga+}lg/ĝ6ʧݭF e/xP,o`zo4 ߰iyH%Gɖ/)xKpw.p׿yK#d.L 2kr{z9Y̠;Ӧ_T7p;ܖ*V %?VWYTWwQ_ZxC>|‰&6z`d;5-p$xxooo60N2ZR׋P9"AЎե3q}ÙUx**fj4,{U@ʅoϧul`흆?WX -T۰LںH-H?%V[c`ui݃`)?kw\;: LӰtx\T}k=s jڮ},lmo-41qth*%0WY o6NCj*z"L4zSț>?oW+o xj _0i$UΩ¯S8=h\)Jʖc؍ WS/TU f4.p?U0y|2"T9R~Z1PrJ"9|4@>9@#>f>ǃHb+XU}}tGu6`lld8`>^ }ot+XY$\7^< a~L٭8ކ;a{ 1i^4'>F)oqbeӝ? p\o!܎+axfxcTz5vv>\̠ak .8t7w7x " wp -@!x("Y[XFӽf=z-,7 y`64؁A7\]Io̓p928 p X8xx'# p9@28}tV@oC7K B 7 =пa:ykD ^Pmhwb>KE'x һxTs|~pzrc\x[YC8gÉ'G7^LL7$6dc.E6:Οw˖`mUJI#T]\m!IMr?=TnCCTsfH–* `G},-&ňWަeN9%r@wwU{a=ae-S>Gp ?Uõ?XLNumm׻pt$1a|MD6YR}"bJ&k [5ͮ.;*+i2R&G./+?+ _0,{o*Z hQ5JꘆO'*ɠ|WLWfad4,}k?%x?Ko&v(RzV@7H>NR\kZ;NQ 뒍NG;wPǰ'N$Ho 4,%khOsH(ٲ(49d'˖WG2M:rU?EЌ3dɒ f7kNɝ$u9 /k45rM힜f2 I.\%"֕F%E5t єDxDnH#j'm™'EV@[E$:UbMCw H f+au$"m8 ξR1RCz\,Uљshjv;¹%-F՜c=ǃmbTA)C\1aNƦ0$V9TUWRQV=/3r帥qyqqqqq㫡Ǒx-[=NlJ$ɮǕ]-[v=X7B745Y0[!O WWv5_՜9aWs®U㲫q80Qm[#Cn@ UNG:gCkr1ġ_RO1Mkڎk|&Aop|mNkiWkPbCm4#)eQ9RBk&8N tª:K,cYla^YXq-E3dFNNȢ%Q񻒌lƑix'2ǐ+w- A@YJ4 N>Q3=Bw]`gAj*.{*O8$ݐ50zմԤÚaCy\uDض8]Hįk1GHKnNz ݤGm؋Dv4Pe!]5)| 0)0延hMVOnJgF79ZWaQA1MTO 4A,mK l_0PtoBEi1O6Eg W 2LyN,vbn'Jͱuۿ(@JwqŀLuE#z-h} Hhj`@Ja4$-!̑c-r)b zSL;nR|\\p5FYd2\\essyiWGc=z\;d9iX^z\#| ,u]Yu0eг=Nz"=DC,fXA``hx/G@J {A<dۂ@:hcl! T@cs+i)AInv6):ȏYɬZ S".HtN$% t^LRk2)ѽR+iinbrzZ nᶧHIt0$WgFL7:1 IР "@,2n*?-g$$+˧Jfr}ҵdf{HW7\IFL!n!>mjf抌Vpr&~il%ҩ[8sjI%+ccx)ș8E8{y韇/`zhpG6 !m?ĈW7Tmc״{Pr"pz` xZD=y5z0·>`6`I|񶢞-?{ xnC#+#x7B`#~z*_=_z9O|Ilx^P63Ne\(ҴiX2!3)=Ynlcْ`qr;uact:Xkh\ih[ڂ{'~ q~lk2& H/2\ {Q?,_GGN=AJ: ,ƾ;Tw6pEŸcԳ#%u[{8%lxkKq81.->WFg-EQȳG8Dś`Coo= kk(z;8Za`[$pt/}θP7'qt,~I?J]cK%LmYGOaupnPqtTQ9϶qպGxMm2)GPbӏm九 ­D0R"; SAl{>H=K1 YJ<~\J8a>N v:J`1{r;b{1R6=DH8 wc4/=֟YN$j|/O/[%x[.o>z6^܏hy~̎S<>}W'?|W7|ȫaBGM%(Q{q_Q[-ff1" ~؋BHYޢ;|J14խg7˱{4/ N1ؼ1[/n ųO Ytֲ=]6^mo@|a[ԣg.2܋]w15ƳM;Dz)Υ<||㝇r7ϾrˎM֓owqCO$9=h~=ugw}كO>%#[~S?w4dwN'c=m[awOwMD\։1{pz@|[!@xOkQ#[F)F U}xQwK2ߏ GD'qTd9Ҏ1sEǼ8D1bofY1;uįߺdN_*g/dѫI\qPC; .ڜ$c%)vtthj/gc'I{nF~8%:R_K1agţ) x_,5 nڞ\]Nų0gb̷~rqDЇ@`#@^ -7<\=ԓa9>~1\p 1Japs^ 䣱jd_Q8Jء G?,!BXrջ8:b<x+cs<w3D!mX7}ghx7O|O? &pU +$N a}4s,ucQv0bC'O/@5!rxLWO6GĦ-D6u ?y䗒 :-fd386mmmM/L"RVrIb|<ӡN7F|_ÌLJhGt.쓵jn:IaŽɇ׍K.WS,p;9)&y8kJ?zvx8<ADD:ß!~` 7 7"Oj%b_Yb[6H>Y}śQ "_T싑}1\/*oq"p_U*_ W*_\*1^/P#Ur_U*9R/EUr_V%Ur_TeUU W*9\/*4Z + QtlY_Q_J<}(6{5@l# % /6 qOD{KGHBסGNGxxw=|-!j4>mc3b"2V~bÃlQx)*DEFT=\gZʭx[=X aWƾ-WCejl^ |(;.Wej%2{5\f`-dj^z=|%z=\BKurCŞP hԯO2870r6">dW9WIj47~E95DiO#>0Q#>sɧH0"5>} Vb#${.>BZ+ZXce&(.38Hx878Q#N B C Jp{>q;xia'n%ӟݝ4zk4J&dmߦ8&,S<Qr=)`DtK>. 52grak0$g[v_W ^'P޳hp{Ϟ՚9^p11{übyZp:x(?z{wmlqf`b?!E}t v֫40'/1OeVk?ÓiL(vDį8.f;!{# B ^=;4r'_bL#jUŸ/ՆF˕ÕHne4;[˯A􀫏9(>`Dް콥Fd g[T6 ^#YYfg>%g@ww]m{6]+(72) @S .$zo,!E,FETXY?zd-e [>".~&0NOp=%"Lpg@b4è˧k{{0Y]qL8RT zz LD!1~O\fc Ss9hgLRBg7ዂ) 6}qhβxy%7~ν6KX=~c`;\i=zsk}K Ĺ)sՎOccS_;~|/kXw^z/mm! 6l} ҽ>7?D$_S(z3DW |qO֖p/ lStl2Ѕ>ʯnH\?>x>qxGa#qӧjAD!OQ,EGz)s|O,4?}Lxy Ƹt!{t(x3bǪA?.P2*^|tV떪Ƚo8vĻ]z(6n1d0kO/A 6C"c\,([ePc*+"B|43%RLe4ebEl/~.pOw /9gqn>}ps**,fc>(qKO(cJY"d9?×hGUk81 we: :S:lNT\.QCÓl5V ;Ϟ?p$"Ι Ġz)g&njnZ6ϟɳI6CѲe|:=rMųZs Tn^b75a㵇K/]{nl#cS=بM0cS *0).:3M~XC jD >Nj0 *cDE3hIO\ qpѩWa8.CȽQ Ʊߍb§RX*FZfë{x5nFը=W`Ɇr{x^-Wj=Wը=R{x=b= Cz=^nez^/ףz=ף ؑr$Tr`v+_}X1={fo{zƊ7҃Gɂ?sQQEOgdQ zw\(C>RIi~,>t[R0Q<H1|HU㸰QF{%ou4[G}"Kq9^)[˚r˰mM> @FL/F{qsjG{p̲Ϯ-,\72LG̢m.|K/7xgmF|s $=:<;FeT˔dKs dCt\X.b&v JY} |Eo~vl~7x*pkbp4HŮpFhOm=xbO">x5F;!Qvn.a_nI+x V70[f߯-#z\%—Q/* zmzI>̵v ^Ysy 7_Z#=MHB06bx'эAUXĎu=]ENO̚_Jb{R̐H~B6dH8Ҧ|>_q珖T2{}A\r1~܂ Ә/;Ubm=BJv"'R.4hKL^JB5h]Ju%/NE9L)|Olmcr$Sx/Ý0UPD+`cWn꓍wC)eb}QZQ'I#!KICJ ]²`WIH.*݁#! 61"|P#Dz7}xk 9#t/xu,9x,]Z)gD3:{dl "ըS>:u EҖc!WQ ٘`܇Fta-K8c_>r7Kc|?5^DR;I5C" I)zDH9>$՘48IwDîC{*q=ߐnCz I:6}V;1$ÈB%"F>Zri!.E] xDil=}m Sqy+pkѓ!w~DW"_pocyúV#X־ į1u _ˆ|W<ĕPm>GT "lUGqJ`B+qal{w{yR{CSLJsB;_z9&CiZB^l/ST#DG|GQzzM1OL`E&P㒆+XS/o]6?NJ"V~mTDWm~㱼)plz/:8>sEQ!Tߺ/Ý8u/{MS{OOg_JFak[e/etij]_*OK),|8_YUV!0&8z?lTUU]WEm":+SF_Iqchk%o~%}|XFw#/ E+[u_EPm4E׵/~X_|ZZc_z+ av{ nzm+i7Ժ3+/{Qcަ.ͯ+io%aov?EY7gG'kvp'^+wDM t>.;SG Om\F_%aov޿"diiw%aǻ ]'0~puQo|g.Եd=@>~P٘|,e HNM&\ƔJpW/U=$SMkZA^Kp7Gz?/ys?:?_ts7gfw{Yvz<_\Ɯ67ٱ^e->X!A##$EY l5&9 ~Hu߳Nk?xvmWc_E?j_l Hue+ ywpu+JMa7;,kmpToi*l:O<þ"T٥ c_)JpJ'Snv|z7?_ou7ogjg?.E{!R7og Kg'g?[4"LQ[a?aǻtw%a7;ipJLU3lm<ހpu=]I. RSnˮ{e|VS07;iJWq8q֋|{wW_ݟ8矾Ϋ.M1WC>?Z c?Ue5 <1##ټa;.9S;:)iʀ +G7[چlmÿottx'rE)U|tWR&B俼-ް"Lr8u~έrw.A|Q[47G[ߖޓަ:[:1.%Fb>d"応mCjDäʏNg3*-h1Hbt?uV2v2Mo媵?F䖠e|JNe]/s.UdYS[ =TagY0S粿 ̰e4pЂU[p:L͈֭i J*`+w3JĮu jMZbl,XW6]*)VF``ͽ.jOtrD%h@ 54h:`4k!4"u\2 EД$~'7X Blqʹi}6A-e!C$U3J@fCA F s^יŌXR.4mȘBnڲjUd &654 Tu@iK5k`FJ5+s`D-GVXUQyUxUUHU0dȎ@`%/E:R#HVq<4 _tk@G(Tk)01#](lEV Z0DD)h`?2RDvP2GЗm d.Ѿ?707(k/UhvL,j0 v8r\M)<<8zKZƎ,;.;4TQCD?6+cSSWcSQ4.t Njlwun8t48$cYk6J$!` ƬՈK$e*.¡؛fQpuqgUmcSaG4 t.-t<'^".I3N}Yh~Ű&d '}Dx垈`'6Lڶv_4v$̎Z$@_  a;cRLJ?n h^_wyʷK}{%nPuMnn@ӁJS=1h>/C„#WEQw{Ru\upc֮@ BU)DJMVO*ɢDCQ!&l9_vsKq~yA9 p5<_;ֲtA 5R;OSw!-NOə!3s?,k}8e^̬,K+UzmX}t&F+%-G_Y&d(`2 l`>WRrYG'Ӏ+ vei"e촯na{N(Sa#[<ҁIrD3*95V6Q~ئtSf'4"0,GSÊ5X*Ov4G+aE 7E8#Ӷ=]QJ?)_Lm _aTvmgYpdiiw\:4i)ēJw`pG(д"m}{!-OBQiN&e`QZq3< T[LћIė%QAS`ִ kL}#E} vf*@hB\͓aӐRjaInM+t.]=.2CyJ8%˒~nTzj]]1઱80 >-tL&јӺC$suh Oti @ZvIPӠnrNd0 |aWyD Tk‚g͝: hj꓈TAx17=!0׭ np2K.0vZ(axL Z`A8x$d((,+@eX"H,K\8 `ez 8QѸ*?!AKk(u* кUr8ꁽ D"/\G:⡗A-a؄5M eGIp a'&0F".IK( K>jGp,ݰexh`j5PemFhͰnAP+́ P)@A$JN%a ?e(Cu\6$HP3*PfdjGXV;PQk ұiW8"r?m@w!(OP;U12C3A@D@`I3$%}Ij A* &kP"RD3Gyb?m~pUR 'yqI2XWr-XQ#ڟ ݭh Jx3*XvUqKUa P 8`\0'8n-6"<`Za;?tu @L&5p` :TF0Wnv~e踯G3*TM/2T u)ңa4e >i|=-HwjcV41lr8v<Q?S6dT!#diPJ+TAM@ K I%=84"rpOU*J7 ;޸d0BqDK %pOŋ#84gK65iڂdx\荝%d~" TJ4v ؎.-Oˊi RJF}xp-ծeP(juv{))Й,I;giQ)'vpƑ=v-Ԝ!MtNѐ8patVQH7wU4utSI%H%td(8qBGg|84X.1a2>3>:F)")0qk-uhܴƧUM0PK^ô+ u4Hq@n/At44hn6,K%`cč"T*MM<\LX@kq:qewn ޻")fW!*ƣ':/a9zmӳٹ5}޿-ފam!"o%yg/eK+n"L4.Z1E2i|vnJl`r[\a-?k>]6{řnq)俳c}mx UCgGDnu{?xYJ\q0U3SU]JOZI_[ <\{k=Wf.mE9}{%>Ώί•6U_-Ւ_M?Z޿O Er"hOp3`טUJMa7;jp7nJW&u;?Ͼ?|} 3ey{/}|{j5΀\}gj3$L<%EY~_fWgfxjx~v7?";n^fsn_QE6w]XE6upAdx2۟J0?_mjWq8q֋|{wW_ݟ8Ys@a4; >AlF(K7ӳ# nwr<\|1<I8G%A1!Q.͏iDdҙ$=7,"?-௃}skSBH6Ώwlȏ1EycBy2 ?&ʑap-+`qr~l[}w<_9OGw"W\UG|H+sKNb [-b(ف9_:sV; 1 *8ے{"۴\g?ñ|ov/1"Do' ,lnW{%m}&U~tr8pLDQiA[E/5xL ١4rk$-A8嵅q9!4!_]P13x =TagY0S粿 ̰Mr =uVzEiZo.& _g /0{9m`>1;*Pe`'G&}J2p&=&XB /R?Gf@萄1Zix1u<`,x r(*`u{ T1PN=ާ!cCǀy f1`> 1;  C sBt"=.Z'Cwx2VQYwume:|*-DϨwy,~sSg :m; PME), 6`I Ky6z&H6*)M}sohN LR q.$T>uѺeP)HBsa]>EJ _[#o_54m롮BF3ڀ%i4.׏vuxS\.Z+`auaVV^b[7em)}Fy.E#]okl*_-XvO+e\q[P9*}uYPr!0}s;3M_@*WLC2TDGGDo&iXck+B΁=Ӧ[[J Pa2HJI&mЎ[/0[&p"c_`^[](*uf^0At:+/>#*ig9ŐDnB2':*>`oK{#b6ԟb k㮰Emj$e^.$ J0;Uڕ%0} -PՁ@yWYPF`N:A0J'!ckPw!׺ bk6[`-r QWtnZt3:h4g ۘӬ% N04B)[ n5Pl"XW$F|Pㄱf e@Yp8iCP,}!+XWOSujN֩:5[flSujN֩:5[flZZg /Zs>lceL jˀQm)T!Tˡ>D:<W<c1ݱֺZc` yLiYk_% pHcRaJt(S ,jsZ#̘Fqm0`rh.[HXӣ`F{0>OG>OE0 }RO %O}xl_ =ݚO_ϖ >| P aኅaP:% #{4\^!>K ,W~Q >v[H@1̚&h\ _"!.>ezRڋ]U \Sk<\"RʯgY2 C%3j7TYj_e~2k4Ki|ٕ ²w *{ 1dӅd27TYՔy[+Dc<~Ά&H`[T$ />c,ZG>vɠ3@C z#n*|_ k@W#I2W#) _ A@Hi4}iPc!:?,OPQ8p߲'uvJ*_#$bQ4ֈm:k,MŃiIBNBye|˃ /0 .7(:Gڜ{["XBf`LV|~ آsŖΗאKV^ X]UU va#p:T (됌D#3RF jNVcY02-UUA vq2VUz+2lSjiXH_DEj}GsP42Jw"cPI/-ҡ@\[Jb@*|`H Lej _r2W@X W5zi9*5C9T& _^ V:SNc]6 iff|`/8hi,轙2eX DXOg.6SC9Ȗ4t`*R < hA%*Cf] p"L k^9N Ke'źn೸~Ov!Y^эԥ'?kc+ ϛ*H+_Oa7;jpe(Wm&0.+]$,}[߷޼\4 W{zs%aovit{=OtMt=Ot{=Ot{=Ot-7W OC0?]|7~󟢽;(ZzWze찤_E__LWN`2ce͎O 0Ogs8pѓp7z |Q~ O<1 &uܘp 4[I.;jo)Qo~p_d\.azg%aovXiU+keå? +aovCf]EXRK{_}wz{%a7;,inpWNVzwG3x? _r,tp'{1֓Gµ_{wZ]I.U9FiF++m_Eio)D߳<@9t5SCK~giwaW ,Jovm_?[畄ͧϞm?x>Yd?õ+]/ՄRg_8?0SVuCmZy> VԠy%ȸr+ SH~Ǖ_b\I3{?\?+ i=\_4[I.eiwESMKyq7/+[ٿOw<>̦t>•'aՒj_rEֺZIn@WhV&P( n={>5_{OM 찤w|Wfzi%ٛ*jܛ.=<^?= _?LCs{?,QMSUuwomplM?prxt׹nrUWySy;l >>=/gll1? ٞh~7ݺ}r9~v8ϲ{{{g9s8{[G\X"]܏G'ٽ?έY~CJb/_|8Oxiv>E-?z4O ,ʧheiF2xzv\|1I8G%A1!Q.͏iDdҙ$=7,"?-௃})!bvv|d$wG;6qyǀ"߼l!.?.މ\Q jsUil/#m;/g{+7ly7-|E応/_s❋rpi's<)$:`>n {U, -Ɩ~Cbn @ 7"ސ@< ӐgSP@, -xԴ BfڒC DHKuF< C*1 Q[Z]qǴK'K/ /nLIA?V {-Ԯ#L0M!4 rHn8n1B֭2MkiM+0I9hJe*t&,ja99QMҨFoBLɩ NSGr:J'bml`N3Nx*CPU}ZA0P[rphi?#UYYT  Oh?5m|j605=tx֢Tдi+1&h@9`YF\ n oPv\ꮨqءu=v%|ّsE"дo0mK~y*uy~ueQMwph:.Lۑ/D]YYa* tS.Jq^ȿF󷍂N͛BˎP~Vz[B[9 ppk-}xP3use]BUe !փEmYj\ɚ}<$CuVk)#M9ivgW, ysaW[r `*M!+/(U>8 A(ml*jJ?¶Ve07+p8CkaĠj CxkrL@Mv%ؒ[h7ʳxOQ0!hr4Z6AEQat?!("PS~uU6Aׅj vħX|J*U>@ gnY&;9nX[_@.4atSU8!M2?l}=A-DP#h1T^jm[5(Apx΍;sCK&3M8ɚ ВT |-4|f-%k@81B4uV!Q>-3K}pVހ58 v4854]W/i8:AeX48rq AܪF1lhRbhS237"@8%uJ &`R56gE4Ԫm+W0]jVJ!MdtU#@0?0a6\5@ |aVYaNB$@M kL!3Ze V`0Ƭ(wA"z.p&ӧN7ux]o)e|M'[㻺]Յx;X+;񝧷 Q/u*WJDYWi5 BS-*g2P/Tqn}C"@<tk@-%dhĬe@@Xq&$kT`Ҡ/F@M2$ ZGLC.u`VL`y*+$+qD(w(? VUPGHjqI%MՂmԾ?O9ۂ>A]j'HFeHDnr]Vu du(3WO+Z ZqV+j@/(F ZU0rV=Xk+Wr J3X`l\D dePGվnMM%u[K`ɂQ&0(%v*?GP藇 )Tte LSzv[Nm\߽R8%Kj?ũpv5 E"Y]MAj+qd: sZN/1Nj>[c jґFAMR"-T|,1XAW8d#-@ugk`3QQVq ;*-}_+XW|#ĭlR5DúgkJXľK;Ϡ$=[놙AMYTc0ԴŝE/aص݉ 7(ʦ}J.Qw R}-pd4>[c ̿5jɵɊQ^H\;pV]j0v`GqdQMEsHQ N1]VkXWhqg#^ F;İxf¯i\[ؕԼzU 4SaԺ͋<ݦ,VfaCc* 'ö:ɪaAF9WeWaU&\(/Wc $Ƴ.21l-θj>F`!gʚU81jb+0Xv*k~pSO'j~ t"+,,K aLYy0Y2ӅZN/1el %6#@8aLPӕ C-M"dD J"33\0ELd Fb&u(hhb fhջ+q6 J_6A: Uİ Y5OX&MZВbOBྣAA`!odYlp4 khn'l nkJ%, N°nl&%l n8R(Fa ;X--edf"XKkh; |F@Xa.;E6IdFMvGMѺP,O %mrSic]!CG%&>#[=F\ 3aYId;8NdnjBdۧ -5Q~\hzTqŽİUߎF@Xp?M8,@Xy뺺gC`Y„v p&92l![]@CX-ƯU34تa'+ª dV&gQ| UX8 m~EGV=wHqkgxv֔U3o mDE+5l]0_uLME} P% SVֳ%Z‚ oIu}#2ia fvxMd#` {6]EGIEx/aK`8Z&$ | n1/*1gq}jlK`t_.yF/YlD&BW2戹>RҾjnk:o wd8+SpC(xF[ Ԡ,ž ip\&:- <)paedc)]85_)c+S.hrx`"&'Z_n; ߶.jQɌ]I"ޡ*S&%Y]vֲ֨h:1XIZK8Zŭe U^l-c0]rc0ŭH,[(NuqkK|]NkE^LnXv,贽G|-S|S?*|X5.oeUE q+co3,7cm ny[Yic袕 H|{sͧ[xGw"3kh(#\cz'nJ2C3wp\4US2on>$-Өp  tkJ2Nt Д_4V]&Mi V5^gdS+hlVC~`Y6\cӲ`n_6p'P6V68 aIʱވA} pM]lK n`]u%8uS`pWw?(v *-YlpĜǖ:+l( b[*G7n(zJ1وbUhQ0n|-ݍk q8 6%|gp &8Y7j#6~#]Gprψr}/;[]RxS[{ |ZztM\⒗jplZP. \^˚Ie ozձee8l=u9u9zG#r H瞨p1=un:Wu99%ï38a={X Ƚ r.!UJ(`iWeUֿ pŷraᘄ߂f ajtVVUkhT5 vFV'!pZEu䐀cbۂU(a}UW]J)tER]cp nZzU'5줕W]c0pQK|XzPUT|vr8AsY[ sATaMj0T^U4ԹXzd|3Y%c0l+F{T%0>V䎞*U/b$U rX4N[E Jj$>JT x(F\:Xxx?x =iAOFE< €]+,< 0*KQc0lF5;eĊA%Y(Djhe,*|3V1 rnr#\8ѕ \ER~0iʰ{5i/[Z0 F/N4tZ8^Z0;*oS{E}8a!ִ(5*pSD) u1Z{=@[6Rrq0.N7& ~K`bp>ׁ+́=',9E\q=N8*W6ګMK!>T;yGH8Gn|. z6["1L=0["ZrUlvlxvƟ+3W_m?}0}V~}|X~̯^○$L!j2.{j/yE 7#??,E?\ہL&0Fg~9J7| ·y__'=yo|T}O|`1;Nο~ex•ӳUe\}gj5Vf k~/Ňs}dq7֝nNh2N?o)$ߣ.˵USO*o0TW1+L1U0?ÅSj"t2;n=T`v~Cۨ,M+^ zU]M*찤+.ߘ_In~k}^|8-Y;0 M]./㽓Ƿr5(3|R[lqv\ݙ<뿧_`:_?LWXoc>g5ғ_E{?\ug =]IpzbfAu\dWOvS ?c5crWf^o2JMJ[u~ݼw_l?ѓN*p3翕*W܉oߺ7[ܣtf9\a7tk%aovXCfZ]EXZ찴_Epw$geV_swz%aovRk6Sdɛ[ p_u]WawWzI_/G K[?+ KW]VK5{?\UoUJo`m?GXfo'?YL?$LZ&U_|vЗp>lr:07;k_3@u*x/ t_eV&x~{ 30ѓ=Uz<ߚ|v4[?=?X?zP~Hci _ju+ Sk_8XIUܸo߹;93W}9\/kLVfeuk*PQo%a7; mp7Wl箾< ؘw׹(z Hn?eéÇ}WMWf.]NJC~cgz.K{ W=_+ SÒKM/W?">?_b'Z)",}'~h' F?07;D dL?(\X.Z)ՄpaF{ f:۟NfPpO!"?pxbˏ ;H@0DYڿ?@dp;C).9|0?=3{F1j/Vf?O >C7QIPLjHK#qpѣ.t&I:'K脪g `2DܚĔh1;;>?ͻ{Y`LK\3b6AD˂f,(=Q0pu(Z3  0SëےA~ !2ra"^Sk r4L@c2 MPk `N Hy/5+`@ȇ&PSZehVm ZVAG/:fѨ|@N0S/d-C2ReSU!LЌ Зm`mLt aRtۦd0nP:.-8M0]d支ؙ' ۚ`&pcAm4n]L"2ܱ1t4nܘk2 z"mv ݂}qĴ &R2MM8͠/ ;=P.t}MF`$:)߱)Ui@t e0)ɜnM |S" {1^_RTAym`&pkt3U8yZZoMP5AD˥֪NA_[2e %YC,@5-LAbcY[کlZı6'ɴm[YuE!XcBPMlAT J] e! !2AB2RQx}I:ؐ aCa|3qh 7tk)_K-i bmm!0`]i`V13nڀ1Mif L=`ԼD0^cfLgkcP:3TtXi4UifL]pӉ- ¬-FuX:r% IL'0D wx8|c<%TH:0f*CaE[nF }R 엕 .`klD-h583h 9`)tZ-W]-WClDw┲"p8/hq FZ Ke̫Y8AY$zʎ ̫Ci:l-WanrK;C֧ yYYO6Sֶ4 t8-p{ka UnyOV"A0 +IVϨ|@T WPVJURgT!X3sM=M)5u%NCY94kW$F a;)xJaoLNA2'Ťxba}3,+tܪA8VXXŭdkUuz&2@FYR5N5VpKƅN`Ev_8J<fJ.b'ݡը< Ap0&WR%0߲%qTWf4кhzh C#|rc%Ѷ~SU?j.\ 'qi'`x4Z0b[[mݹE f ++HuG3CoV.{[6[+8zpCGQ( 2#0pH pqr0p*ISxyOK2C t`ssN誆gU9HW [*tDxTt۩tw G ek5 BJ`yտ,tSP+90ƪ"\3w 챮':r0X"`M΄y **@k5[C8auy\wViPM V c1(|A Sض E:+vmK hK &oa*Ѷ"N`et8*!`b<,-=tipBbP8mC! NJ\T'sY:hp W-{$:q:OqBK֭ˇO(*KWnvkU)J{8l7Xu|UJ WR^.)VZ=8(9 W myX(F :wp#[>B:*+7\Kؓx:tBN% ȂmUe 76.EZ^7p0/W(GJ蠄7 _pà*JpFM-JFӈ4O#thL+r|EZ-tB#t0OJGXعСi[XsBH UV*yW6p|FΆKElnX58aXQ\*Qǁiy3>*N*kau2ZU*kaa%t,tVYW3,t`W|m ; 6ʛ p"[Zh-<'Ф{!  ksmV"H+V;!xFXp|U U6*[L+tVٰUw6{%%o̞SlXXF˴B#agbB9asb{'lưС|lU ϩUm\^d}M`41\ X XV#|V*ឡkkJبF?6ZS յȍQ-lT ϩUFJ3ܡsjaZXV#s-<VUjae_UV R *uǭJ ԝAXVi 9J }SaJ#s#liaFب)eZFب6j4JVi*.#<4*f_cDn(4*M#4<1*FXViUͭheaFX1r=6jZUFxN#l5FM'4D5F[9[aʶRiUb lUfMy< llU*[a|*𕭰VXe+wn<am-tVrڡAJxζ mŘ6 MF[9[aVxVxֈRiG*[9[am+l;GxVxζi":a]y'FNXe'N}:aAXe(- ̽y'l6 턍v#NxNh'lsNXe׈RV Uv*;;VىQf'VىxV _ Uv*;1\V :9J Am]l$De8xNU"-ۨEZ[X 0QhJU(=**C%VBJ$Uz*jC-S :4BFmDjg%]/tB-t0b#FFhdFM+rӊШiF} :VYQʒ=eZ֡VY|s›iU9q?VY*RXeY >b#`{ LƉ;n+6`+ak> ds%s:`j%6`q3i.h< wH 0mMYH'O$YF 7ZqܕpacNb^%\9.:kZ1L i^ 'i.Uygʑg`E4HKO*?-kyB|1QA .x tN3ݲƸrB0PQZ*I%gZ=L+5\pF0"Z%݈'Z=GօQã/,JxmqxY/N<ƴ j+.4u4P %B0>P R0O*qUѠn`ILIkIN x<:Ӭ-3|> _"6{?\/v:R6?"LfK_e"Y?-Nnͱ-ݝyy7wvn^|Ng;8 o u7%zn~n >&uXϣ7?| Cr瘧$LQÕe]j*BZCONa7;{?\_io%a??:/fgILKs`07;_WjWoȎE1섾2}750:55pod\L1Wf~_V*BZCo[Oa7;{?\u;YIsZ"L#jJߕV>;>fZg / eJo="? z!m"ߔ}kSNU;f~:Zdnnq8ޝOfg۟@dq"B0o,hщE?۔I/d TN_g`OG6|sxv~8}?}GϿ){*:J$u]A(Z^1d>ts%aovWk{Ut}myzƻ%ޅЂ]_3^ir6$?>$Li37 ,,}~ÏG'G5_fZ_I?m_b;HM՘iwDpn2paF{ V+ 0;??YN`Fxtݾe'll,C~'wrKf~}S?p7}Y.Vo;}vtg&;qhyG'oo'unv[Uwnӭ"c{׳|i(!-{Mղi=]Mz|~u(HgxN;9SEwУti}:U]^Nʯ«pbZ_I7;\kw Uoƨi@4M?WT.-Y+ SÅ.Ucjߺ+ Sy.U }¯?ZIk~?$ӳ?anӍ0>:y)x;PVUW-g^O0o3^I߲lߩ_Ix7;>K\w(~<ݙ?^x`~bzw \/ϴ0kǻqipup޿SE]N뿫K@W)SL%NRiItϕ'GofۙA~nz翾yu)bY>90z???B?Gr7]˯|ʍEBۺkvem|?<:O>qv~~<LmTֳWUv~'T uO#b-tcKNgdm}ȏN>J;O[ٙNhXB2sŻY~pf fh .Sպ)[fކuZK(T.۱F0 zYtMYsHq2;{3YQH|-j"en8Y'Gk5ϧܙ϶mu۬W6ۓ67G'38`-h@b̪zrG̰]ʺ6ǣ'8?WVqj–mwx?*?= \1>k<(l{ W| hi<4%Z/ͧi+lXfh}FiχօZw2TƶO҉f`=?֭CэM9{Ț'%~yOO=?Y=};8~ϱ!)cKWj<ˆϚ]r󿢙0p5/\0+?겞~W޺9"}ߺ_}u{*a~~5̯2f*s AɫCDί2Efe+ A]۫in nWpsi`}rI0;̏/6 >(AǢ@dp;C.9|0?=3{F1j/Vf?O /A7QIPLjHK#qpѣ.t&I:'K脪g `2D}Glޝ {%c|7Ʋ4e@~L?#ۛ-vm[Vc*0Y~.|\F::\^>:+F\ky?8[[/ a{Elg.z/vR:sV; x~>-ÛoKK~IL~or-x0?91.%Fb>hX}3?Yg/gs{/Qo0i٧c$J Z-y[j폄%C96?.ǃS"f;Dܻ j7F9~DC*{FqԹm*3l{YAMr =uVZ6eݩm.?|%iC%:Xkoj t>@oT tmYxܮP>@GuEGŗER,8cT2`' 4v0{LYt2dc2`Ψ}p~;FMȏ=!i>MB~1u`iL۷It:DP tH"0Ҧbx Y=1{ ׀`ivq@5z U1LQz 1`b> f1{L9uǀ{ Mk@@3ihCtNZ/D^[8xY42\<.'Ńsx2D6Y&hI֔+ 6u; ׭-S\jLɪXdiD { VV)#rA)yl(!,Ipy^ҕiP>mѺEқs< ds)PGz Xl6`Q@ C]P[ڠ8.⨆Zk@.8/=klʮlc Е 屚\dȅҡD5h]h8e-\Yl]YP; 4L5B4(AAZ[&p!Sa9}3ڱ`4EűKV!צ bLVɨk pds[y-X!S6k p;ք\Z+u(#pO8& 1Hcp|l@^yj<-8̩ᕇ^UBPlA`Ǻ*3);۔1NiTZMVOg03l\Tu9PM|3bTPӸnaPK` |z[PYЗ-4ql˰M[e2X 2(,Â,:XeX[-82˵ ۀk_FM2j|}ЕQӆҠXT8֕Vڗ.|`cL.+gGYu P#ّU Ўu1#5QT5`** @E= Y|p~h]e0 L2kFY|y uaFu0ctrf9c4$1nHBW"frTCUAk+ӕr&h05Œi6 vPh!f^1_'>}zQKxR NOx #oBz_ROl)]m`Aic(C:\C@th@0VUƴEK24(4pe`;̚ւ̠wN'ذ E0&ְ|Ҍևc:s[CDX,ج;t.pVK (yQF1 '%% 3ػB_l7/j4{/bӢ sFXWh[Q2`!ʖN+%dYcIV\xDA4΀yxeN.l`=*l`•B4BgQPMK64݃5O2;m|[,EEf٢,6B5[+Ea8uز@;CT6h=:> ܈e@WCS\.hU4?5uâU0 oA+I-akS]4iU`@ibm`#Ňi+V08N&n_c JVXY 7m-M@V YŞϏ/R|=-(=9P =fE y>U|,h|d-cY".hϱ@0=_Yz>|(z>OUqkQ\\aZjB..V<,-rC.sB%jDy>cVjEZ! =;ND:ey>Yx<x>G%$ 0=B ɕ;9m%dUAWt4 YYB)<_k@|@ O\:{pH_jdPwUvpIue%ar/uOQ$,>G 0hsWprlxvƧ |}Ӊp=k~X~U1Y{○$Lf+_n_zJAM[]}Ë8og';.ǣ޻O u?\Ŧ>s'?*G:>-7u7,xwto<M+4֛7P>eogwy}p>O](?F#{r KKsu3}o5a7K7SzÅ+Z*p?\oL=}g%?|*ӄpa '+J%hT7FM711111+A{<vJwY6`+ [Qˌ|lm ͙u/!1M 2@Q=pۖsǦ96RSSxl;`mYed6l$JJ4K5>ŏ|ŎX 7*1q/ Xx 쳪_MPMxu0[!Fq$PbӮ96ɒV8T?^ZbKڤl8ۖ ~]F/d66͒&,85ް N o)[WK5k6#w$ԙ`L@~|ɲ}c̀@=ΖeͶ:$AئYq&~lk.(5 Gr7/6\ݍ0bfšq6ۆE wBv8[57ujTI&ye5<2hwnأGÆװ5cm%Oe5 ^8ۖl5!Imdk6a=0R8u҉ȝ$׏MG'rH@jM 6rA([k $Cl,8T?B˒ၠ) 1ㆇC$m?K%<ٮ%vlFFN<-lyixorm/Zbfx&%eWIF6 ac"ЗT_MԵye cfxᙾ-aek $Ke-dlx-;dˆ&7ΖǗ-^˕&iL®eEJbtxyZiQ˞%lyZ$ٲGnthm%X~l6ۖ{Z_JىَBKly|K?dfiRlx;GMeKQ/yJulx^!i:l6lx]bxK, lxI%,ed sl61gi)[gx /cm%CX!AΈ@%A-*PEl#;I~L0ZTR u Oɲ}h q Ds H2i2ljUѱ.(5 Gv%f[?U)L'Cl,u8T?Nvf[*\]&f;6Ǚ"ЕT!If+ذ@621qa>l-/6u)HC5ɲ}p7_7@Q=ʖyɖ=rͦS'$KBlr7/e'f;6lS2[E/bfISx]oTa'cR {mM>I~?^v s*aR#'{ ۚ$ز5\M_Mgh受͆װc Hv qfË%l,Zeivl{ 8[RUi6wBB/&YG&K=}qن8/d|96͒&,.KS(w#l`{-H`K, MDgh受͆95ol=ζ, lxS'W٦Y3f+K5o0Egm#ЗT/ئY3ǎ,lQ=ʶZ ֚/|e.´(J"駒iѐRI \4Wo5 &gEbXRiô휚7yX(ek8K-{d6T'W&Y3f+K5o0EeW-~]+Kl,ZevNWX(eA^reim% $46?B;6o [|eEu$W&Y3/9 ;eC:1Q /%[6<–Mgh受͆װc Hvbxl|5 m%:C+l_vN6y2-5j%U/l,Ze Ȇ$D.S _j$K9TZ xWllW |}K=,Pjdd"䩓+Kl, \e򕥚/Dg)m#ЗT/ئY2/yΩ5OxIhdi[ռSax#Rl,Zd6<ΩyeKq%P7y 4KxVxQ󕥚7"IG=60[k"ЗT|96?^,%-5 Gٲ+K5_RmH&)#&RI \4oo?nyZבF^8[񕥚/|eN, M ?^v9RݢolQ=ʖyɖ=2oɕAI lRLlvlx!i q;6<Ω˖٣l_UW}jS'W٦Y3fj~eKQ<l:.Cl,ZeuMHvbxly>5 \Su};IҏS FKJ D6Y6H7MaZlmlT Mreim%:+욳Yf5g)1qkIsI`m/ئY3/94|[D,[jd8K̖~i+Kl,Zd󕥦T,00);mlml_MDgh受]qKt`j+KK؆J62 Mgh受͆7" L o)[%f7U $KRdٮ@N×zX^¶, \ݼ$W٦Yf5%lôX 4KxVxنqX(er-C[?M% ?6?N6_YjnQ÷Xgcɖ /4ɕAi F`/K:T jQ\Ydf / oD ^Dr8> _i_AI~ꬩrP@dٮ@jvlu5 PheeYuHMd?Bk|}K=Q<AI }-c 8Kl[6uiP@dٮ@N×zXeWl] 4KxWlR×z{YeqOӲ$W٦Y3n8wX(eOÛ<,l)$KtVxlx&˖y٣l+K[3|I46?^6ˎN8[.QA$O MDgh受͆7" /%'U/4]/$I?u$4T*-<+6Y6;/D'f;V%fiѼɣ+Kl, \ei;/lQ=ʶ, sYB/Zek% ei 0-b6@_R#Rl,Zev+K,[jd+K6%vM'W٦Y3W4ohaR {mYlvreim%:C+k-oEg Wm#ЗT_j~.Jұ~l:wJ'pל6-4"d'f;ʖ,1["Hreim%:+lYY`$W Hbɛ<:46?^v9y;G&˖٣l gIewtreim%u_*?, cJ1?h !SEl, \e5|eS$;1qMRI 4KxVx gI@Rbl5גjYBlAI u,c-.1qgٖlx_Md?NvɆ7,32ֻف%Y%Y7-3XIȳ;R]叇+GvsvyM:Vqj#QnY aKZx/uҮVqUv)v)@.}íS9goKP: i>..QȖޥZxxB,a'Q\lʗ|E_:noc rrrM$%7-z_V"yv'Y aK_x,nSXIϮϾ+td)u.]{h׼9nY7-z簚nȳ[BXg-<]9#nZԹZ"*l]叇{קHp{Oy_ @ֹt叛Pń၇{ {J,:n׹t3|s_QCXC"ɑv'xZjZth .ȖΥk.<]9rs#$K!lvQ6dGPW?M=نCiyJ=)GЧCWi?`u gSۺ^Quw{U?l=G i_ˏ|O_36]mGj lk79 9WߜG"@@9b'8Ŷ;V9-\i) ^W\E!,ۄbs/ӻH",0v}9a$ڝg_R椮rnľٶ{Po_f7B1D1E426`7Osmf!7rNjw}lbkcx/ 6Gߜ ":{Wv'}Q'_a'8Gl QNv8>TVf^9gR^n۽$x`xHK"8ط:cXl> a1,$xMb|Et^]tCX: {sa!*qK7VW%1C֊?HѰw8r{BoUNH4%U>sۊ6XcXlF&wcvGCߜ] 8InXƝ®po$bqNzS} BB(-+aok۽*!4Et:..]ae32#,jAne޷Jd$E| 7#C^asn5<C mC bBAs۳Bs/Et ZW!ep-,JlOǹCou>aQ_eα׫ , # 8')>Xp +²2* WI ߂tlH5q'܊Z7r}럢eȮHE4rbPc:Бs _7"aݰ0zyL{9)DtnCRl[@j 0ؘlv.!$ņٞ1`jVBmpP@1,1ҝ>Fm=˝a%!Dt#Kw #\O;nk+."U?_5 5M 6n}G`ma!$,hD>gc``G?>@R1` @l$\T_(P{_n`xH1{` r@X#Vl偨p;B/I/%^97b?a^m2ȉdu唈jg& 'NdmtAne޷2,}| ) @蟈ǴW_zID=@zư};J/ 78ه x>Iidh~iIAm?Z's҉>",ݙ +l-)39ne&)>#a1,6`78 iCsxߜN K',7$-qO:=ۿME`Cl"{CRjDJ#'c:ne&i> #R`w|rm(mmfx{@:ٻm(cXlb#,"%Il av'Mtتln(m a#lؤ29$E a U-aL59`p8`;cG 7k^# % ;-:?C  RcXlP`#g;;ܮH:"{0Kdl}q_nNt:Wu27 0 8C/aD':{ 2` 0aYK/[06|.HY֒†*V%b! ²bQ_,vŒB",+²nm|Aneޗ"XKDJb 6nܭb(QX4sF҉>Xp+26FK 9= [Ed7$ņ1Kd[{fOǹCsIGqf~ FT7w JT76ĹtOooY2x!zVmcBފi%AͶ{cr}럦c爔FN 6n;m;hbqH:9|A-3"Vؘ 6朶ItwQP(ưb#,b۾قtγ> )Rg uT76/2˴LJ @XBFAFAF}Yl$\66(ڶ/2_$lD+R%,Gڎ'ܤk!;E<4[SEw61 QG)aIҝviHidl-AF Kѥ/2_$<,9dt 2EFg!K%dt鋌.&iH.RP(Kѥ/2:/D]/KtŶ[u*`.AF_t V/2:?9 dti{Y!nV}l#DWj{R`X K%]/[TI$n 2]" "Ke Fҙ"pn+ P-)>e|H{@dt)aݏ`"$ r2!,ݍ!ڹmoELt9b#,h s:#%th/.AіhK'\k1?F҉> )B] X֒Btε"eJ6]-A]f]:,6.dt1i8<dt`;lG׻9 v`#,b s  ,!KYV$ P@Kѥ/2_dÑ K%鋌b#BFP@K(Υ/2_ I2]"T>V$5= м/m$쟊UM1,6`cfءb s8#AF*nYD UTwrJHNqPa}n/K2ItwQK(cXl`#,⋌.-ps %R2/G|dIIv0ȁ.AFĮ5CyG;-:m 2%F….PK_dtl8ɣ}zI2:` 0"唐= 2]B% 6PL(a%%$dt 2]Bu0}Yl$\TTg EFc8:ٻ%d1lb15Qq|#> t^8簟{k۽\v*-?:ɣ} H M)@l3sPf_ʗSB>7l#8{2Cޖ.8{2Ϟ +>c 4`O.g]DAYdG;6 hŨy3S>Ñ_ V܅+lM2 8W3;e d  /-:2[u43 h9q.g]WɐeH2dt2Ñ!˨e2dty*gP婌`Ϝ)!ːe!Pe(TFgg]l8{rN;={r?93Ξ81'p ^s?[7-?'yd_!oPWFH匡DF`Met{u;Q6N]$Ed1l0 .pBŖ2:=s0$ ].CFg %{GX"CF!S:é`H.CF!ː婌.. Q@(婌`O{]wOɐ傿LFb'8Gl%Tl\aO\UuSҡ;c?aY0.CFp FkTVpynFIn) !ːerE,̹rm$qffFu Dؘ Q@({羴<2dt^f7!3]FXBŖgkZs=o{@2dt_fxi e0a E[ig]WUl8{rN=9~>92TgVQ + dte& 3#v<89|H{@:ǀjۑs!Us($\=uS6Rpd@FWpd=aCFWP,/ a9YsWٰN"EX&a9,gΝχ@F7'ڡs',qhg@V7Ď@ni޴>džJ!)B] cCFW sf2:=s*6Q +茣3] ]A8Wf2:=uS6lR + dte& #6*2YsWٰaD6J5`6n+( mevŞ9wnA~?c8:ǹR$4K E[Fg}ʆ {@ dtsRLF7a [I>&$5uY5<6Dg@V.1l0 bkVpd,̹lpG'u5`ҹZbO ts<Ð83]C:}zjd1l0 >Q@+Pmt{U6lR +T3]IA@FW +3Ş:)6) dt22хH dt+kmwSgC cޤUyl8ɣ>ʂ+ Ty0aʂ+ dt2R'C =uS6lFR + dte& 10HPbϜ;GQM@FW +Y&b\P,LFgg]eÆc8JeX")BFW +3]*`4$Zsa]ԭ@FW +3]%'LFgg]eÆmoE:C&OX0͂ .+'\^"fwYfsUN(8HP9 !+VvLFgWH:9$E .a6.dt2],̹lcD@V +ѕ.`c*2YsWp12]A0bK$s dte&SyH{@ dtTLFbcVy`]NKsWp129)r&aw爍jAz1l0cwlBU+sm$c /ێ 5wV*dtuvŞ9w wQ!8f87+ =q._?v ;He9`CV_ bO wlD ұ;c?a ]BVg2:=s91oE|Mr|rU*mn5CyTwl#DUˬ7$\' {U6ܱMBFWqc\8:х QLF{ܙ$ ]R 5wVꆰ,ԹOpNqI2  pQ(İ%\=sLMBFW!uULFbkkPՙbOkC:BFW!YfaanR!6|MLE`͚7럫cIHma*dt53&s7=s;I2 ]BFWg2[eUZEqdt{ܧlx`H':{BYuvdFX:Ysg:N"ڡs',qf9 ,gkZsc8:߂lр 9PU(`M=s*҉V ;G Gk[p!f ט7s!DARLưsvw;-:$EˬȎp!(՝5I{ܹNDgRWQ(8Ξ 1w3On{U6<} :k,#lP(a9bO щ>a ]Eu F(ULFggΝA{>TadtBYdt6dt LFgg]e{@*dtsҡ:7~vV*dtyC`(a^h@`͎MSy^`7) Kn(a=g5T e2vJlTlb;βh";'b(a #{#Pl(5v'.e%dt 2`s26.dt E[s29wJtaΞݝ6ml9wms`@AXHǶun%dt E[+>B^"ܝoy_<.`g0۽n=:2]::%ؐ5dt 2dt!sgdHPk(5蚓ѭ1w3ˊp29Rg rIC kNFb;βhI2`s26.dt 2c s3 @F7%99I.gO s7/pV}p[=o2`#C8 GY6 @dCFP P@k5' s6,wPlNF i6=pcskι[y GSR;{ vw}xιKdhrF:sk qb;箪a9#= 5AFנ:kP'C`!to~s]dzea_pЭ\3~jZmPUEzşz Nukw_.Fk?tE̶]rخ.Cw̾{r߮#]c9lyRa~Gx,%9_uر Wc{2?י2?fe~:/LaЕُE~m^_^~^~OYPk)9vg)ضv욧ءv`Cׁpe7\A7F}G'9, Z6  , O!聽U.D>0=tс=aƏo1ΌBYe5@jy~`{Nr #6cb ,2k[3#ajs7;`"m `_;2x69I ~2oz(? -"avC4Oc+@΀vվHamyQmY93ުIi`@ڷOǽƵ{}43;W@Z"R6a|r|!,g;,kIQ`1l0 7ƨ%\==`rCRܐdiܐ̷lOm>jߖ|7;ܚ>V\mOJ#"pv`O;@zZӓ"ܡKH5ջs5=YW!I4,ZMleBT7Aେ ,6Z L2. ˄dmi& T3rJ09a-v,YD Ҍ0~3o(}[k5o?!s Havsvw;bϜsK".bE­VP" Xe*"a0wBln-qf{\` 3 cCXNr1l7Cs;BsWP   cBlp 6 vιkyfn[m[Qm?c(1M_XG0х6n{HicsCv7s11uPcce;);rBl/u{ j:a=$k'$9$@ǟG^td @R<`  utQb{5=X9aaXa#XR8n@o PX~?Nt0̱;?Ӿy$kN YG?% 5=, #vߠʈ쌤KDJ#ZR?;<Ğ>2P<8:&OǴWNqM[t!*Q.leATqbO46WAX$ETcXU7y BUeL!s ̌ ² )$YT_6./^(ν!DimaX")$قt01%vEXVFO w|p;<4K>_W֭NtOv`#WVn!DqEdRpcdlQ|ݶ{Ǎ#K>Čuj_O˝nX,C a?3v9wwQ{P&a lp 6²!*ژpClLR03n)6}~²;nιS0m )r/=$]`!,)^`XR8Q@{Kwy핸/-I/'[a# :cL!W@`f}z#\d11`FXc^imE˰t wXͽvAC3 U} )| X`A:nbr̸}k m -pnv'q c s~f܉>{G^ap(m/FŸ-ĞHx{!,_H56 Wت}^2G\~fBw mnB&dtdtхι{⧵dtndtdtѭw8l6ضOyx ]珘CtڝT_01`ءb܅!9D6dtdt l7666'v9$E6T7'[a# %ebX\BXRP&aߝb#,bۜsK6’ZR n۽\'g<CnfHɍyC}/xAne+*O@޶A]f|>HmCr2{m{?t Вu 0 _gvsh7#9]9C BFAFg C9D2nns2s nnnns26. hsх_;mPP( ۜnFXDх_;^ ,C{܈e 6 {1BCOT$E˜1*om(mB1rC<dtdt0ϯHmr2{61}ڳ 2VJ1*-!wwCAmmnAdtmmх~x", 5AFAuAѶ9]=[ znrJl.,9`CѶ;FW_W[B.P KNF.p 7w8E1`f+ 7bXnŹsq1gO&dt gO&w [ 7 pdяB/Ν'twSR;{ vwրg=9 ~h"r'[%%(mns? ҼI!y J!)B] 3dž.A:P@KBl\j|Hȝ"e A c#BFP@K(%' Ufy5F7@z!)nH[.;#6*6p'Κ K I:k 9vҒBB0Aіh ;ava} EX& l-)$TTg 6q.a5AF7'EX:PnB_#\nhd[Y.Dn 2֭2:[ٓBoUȆ.A]f #{rpt.2B/Νwt0PAjwRD;{raȎZBqNK/ΝKT e2@e<Tl\aqh ].Rg U+lM ]r2{roPH 2].:n ].AFO8Ҿvv7uJ.κJXD_s7`cbV1L.AF'%wnúC"r.RP(K%'[ac(aBl|Ct ]B[*`9",.Ğ E ].CFQNFFE0QNFb;l`9W%" e2dt+lp E[n19j?>4eÒ*uƀr%T3m6ps,"gK'|re2m0w3MuEMN0Kq|e-C]q|eWα!ːe=qcv2;GoFNt.n게/?{rF dt!s+YwD6n˨Y\d/1wC0w;w]͹n˨°ƬUZFq.B/ᤊ ]-CF!NF`#,hNFbsrJ: OXBFf۽|=0_"p#סD.s`cKmqC;G~"r';HUưn[eUZAq8]흣lbȞc8GGx| 1͔W," dt2:k &2]8]=9y dt2]8 [ @FWpdяBlW,"w)ҝ=;Gl%Ξ,/pCu+ˆ~RcX7`'(yٓ!w ^"r'3`pn[@FW +NFb;猲ʻn@sH芓ѭp!+芓х9 dtBY8 {sp%1*\'"<a#p': Rg H.,ؒT dt2dt!w߆29)`?n+P(ڊ5CymXgD0 "{}4z.(r#sUd n2:` @lp 6*dt!Aq73H10ȞckVpf@%nFSR Dٓ_'ATgdt!ΕǀΞ8gP' sFs߰܉VC:~2E[p!VsuSܝoy(oXD.s 3>?HcK<2y[::\`6 hŹn '7c=a#p':{bKd10`#,b ;GE]Rg paVݤ XP@+' ݅mFsc#p@FW +'[`CFW +P(ڊ.QcHm /9b#,b+'܆;F1&9WHP+NFb;l"C [N2:@PU' s(+dt:k* E[u2;GENq9p \C9n32J]EBFWnb#,_F޹aH Kn~:nX;Va*7'_wٯ;HmY`%;1{=\qdB]VqdugO.!U*sBl ;ٻUd10pa;FN1 Y8`IEV!6;Gu ]BFWQNF>i\:aF7tRE'[&era~3Kj 7!ᎯC݉>Dj1lb10HPsŹs}7 ]E% ]EV3BsG7C *dtA0bk X!U' s ,!uU誓ѭ+#6mBl4LI%9.an흓~0gONIqdugO~~>9Yqdя| ^s?[ %p>d-{DJ;I61w. xl!uYG]cCFg1څ:]휃l4@z ]E0:V*WT+dt2dt!wNр !U'[a# Xqy[pBl4 K$Ed10ؐƨp 7vAs?ݔtl[OX6 E[ <=Bf_h!߹;B|H?۰5%vC`Z:].dt2`u26dt2ZEq:]=:W ˊ&+dtVJl%mboCXNIv*mdt1,gKwaY=^S@Xb[=|=p!Ƅ?xK #vwxt^&b,Z:NX>_Ӯg;ڧ,v~'=ϜKϻfEϼj~pN5^KL~:;>{u=K9O?s3fcYӼ=BKy  gY Ϧ#E{İuN.(?}sMDudQ&"l\2GSOui[{uow|z.E%%jx*xsC4ù:̹,&Ev{\2Ye1lCr^v;$2u9X!MҢ{`wy.E%m{nV|w\>?}ewOl\25[KIIO=s؞/Rx//#Xcx**B%*^_._Fޥv[up7)ix^˗wiQ;ۥMmE{ |aXE E._>^(!f#Cض¢{|aX:˗sl5{KLJlIsӢ{ c`PӼ˗wi|$mRbKI/\¦xIi8eӼ{*|:̮{Ý["TN._a/;y4H._F%"1MHO?+Ypaw$ج\-.7jVńCspi{r6ͻ2j_<)t_FF2Sc6+¸{!աtȘ/CXR|?,DxsOa}J=}3~͇ޥc}\4-*/ 1 X}VW͹:![WLnxsX=S#u.s% (};^q7U,'W^U1_ޥcSx1aUUxK%*j *r*_y{̗QCITrM6OH9Ɨ\`KXۦx a=m7/Sm_ޥ2>~XN¢=Ul5 5Fֹde4ܩ^SbkʗM X^Ӈ\`KuƍSbk_vW) ₩˗sɜJ]+Jow7U5lxowr״d|EQCɗ׮]Ӣ]Ӣ]zwriѮiѮԹ+tqZ:A[Ӣ]]H 9Ɨ=_F%sj?ĦsحDۑMֻ'ߨoB;\-aOP.%skVMx %R+4G%wߨoB86VWL)0{/(/#fUrrWր تr6e]T};!# E{ {SOz!t|:fU&žM9l_X< [z&Urr&\`߿8 aKQíS9'"Ϗi=)akx5/CXҬnYfos]"oKMrx@c Rrvju)lKmֹ4v[m;DLӺ4eJTI )&o(r'}ͫzGܴsOaH?I"ȖΥYշS圤"i=r  wiR,'"]&aOOֹ4vKYIVfˬakwvP |h|e|@+\̪\ǹuFY3+t/͜ekKϻ5.l'2< [:fU.Jl*0nS˔'dwO/K1y3Gn/UI#nZԹʗ[+ e\U};ٝJl*=s&+˗z *U};j>^k2ͻ˗U>NuȨCҬYNn%ZBws/`5-Jõ!c aKog9]RbU1lʗUӢЩc aKogywgSbkʗUC:i|IؾBT ֹ4v[i|Iz{5a~RP2.MtI*0=\ixMƹZ\m;ߔP\-a+3|kix@8 &?,'I#BZԹ_w`p2u.ִͪHۺ4մHU5zysҡi Ls`MTJ*$yDu.ͪI$mQHܴjAXz,%s6KK;V(IAd).M궝oJ;\-aO>w3&_so_/K19ͪ,",!,z=_ 'd`s\U};ٝwOH9.,Ӭ%Yʒ,eF$K'_ <'Y aK{\,KII 9lϗ}c)TN:fUrvgao[`x*d'Y aG2wF)IEd[ eBYrr"JjfI4wȤYN,,4i`߿-yw6NBXz\j"l"ԟ,-`>Rd);R]T}$KY圬"iQJd`xI,ΥYշJl*0nxsؾ7OӼ{IBXҬY o |J{H% ֻ4v)/[>. V ,QO6Yrx@RLγogyw;YҢ{咅}˗gU,Rd)K3r.Ma|\˗gv(_* )lQ,Uֻ4fI9YEqӢ=3l\2n^*0n/}>.ow|zj_ΥYݶM x4N'ח+?|_yV,o%r'xZ*_JU*d'Y aKog9SMqӢ{%aq+td).MִH&viDYxֹ4vK*dIM9lV';R]T};˻;U*u)ƗP@$K!;skΒ,eITD{ܛ%%ʒ,宯y$AZ;dR,'ER1lI%ʒ,e'Y aKpí$KY%qӢ{e$IJ?YE$K!siV͒,es,AQv˒dzD.MYΥ7-SX/[p?/Wt(!owE"Qi=Mr Ye1|_eV,'waa6)l fOO|_e,K6v{S֢OQ8R\U}$KE圢"i=KBIBXD]$Y*/E3޼lfOOsֹ4v)o |J}\$)ɗ]^)_br,wSMZO XKIJ?EE$K!siV,gwfy%VSBXҤ[$Y*ST`2.l簻O_*K!siV-,I$KEVcI>E$K!xB;n XD=IBXҤnY9Oo)D%|)um$A%24uȬYNn%Bpa|\ͻC/CXDYN4x7~/`>% [#6WΥYշHTT)*Ɲ} ]. VR2.M,onI L..氽 oi=$K!siV-,I$KEVROQ8R]]$Y*M:VKJAT*>|/ ˗:vwT_ i=մȒ l\U}$KEva;%Lq|z&Uߢ#9E%qӢ=UTݪ@x._brU};˻;U)*=sX/ uIBXDY9Oo)D`X:fu7%Tn._.aOIcI}D=Hu}e|q)4w\"Q|?dI?!+XSYF%);'YZj>NX}*'Y aKY^? []Ttva;|\~$Kݲz,j> R阸\|Ͻ2QC.2/zWwHS%1J$؟᪎Nz>S=}>^%ߩu)lKPSU'Y aKYؼVdJEd]2`߿M)/#ѥZSEw߂_UΩ,sXIS(d).}T^{p+& 2q <Ɇ@u.]k*VMmӺOoU DܲtcB]h;S}aο;*I3r2dInyw,Υ<+n}ͫSui=մHuOUSBXgW<ܚU}W}KTdiy*T ֹtɗqV"2.{HT 7=BXҧ#&UwD$YTz,Υkks+ܝoJsGԭa6/ ]rrmn};D*Qi=ՅF#v/#X,ͭWID=#VqS8 aKWyvsU*Nx7[j>J?UEꎨ aKͯp<%6yM:KU]`KWu+ܒ,UITDvj,U)DIBXg1o+܇ƗB%)IT%ˮro(!RǏ5~tv4 tJ"[:Ǜ$KM圦"i=Mr E1e]nnn}UU4L)ow|zʍ/#ѥZ wE">lm/ 7ֻ9zs+ܝoFR[.6˻Υ wgڦui {j5),]o7uHom-YMn}I6%6zFCf, ۗi$K!si,&>YN$Y7-zʗ,5~.7O-aK5V$K3B,a%/%_׼kB(! vrM5wD=EV%ۧEME$K!wsvrVbp2`߿ͦy,Υ˗s=W%Yj,5 wZ`iңb\C$<0pǰ[BM6ܲ4V%Y*YŰKUI-KZF^vu|].xz*I#BZ4p_ vWgEb]nn") ܲh`{R&ӼzjŲ{]]'\q"i`XM M9v,иYMM'Khz%%YfC3t)OoRRI,s=]KVMxYŰ$..Qe?KkԬCspQbX>ɗ9!+ةKB9(.Q`>4U vҽ}nmY}>.oi=MƗvҽ}> 7>< ˷p+&ށv v)A+} 4˗ƨY*..VS>Kƶ,xmx1)IKKԳ7/E|c,_fr-d'u..Qi*_JȳY43성mӴH]qӢJd`qȳ|i`.}ƶV,*0YJnY\ƶ"], j[**dfag.]K c[IvivMVKJAgK;q>-al{(b¡4Oo:n-K3h)I~LQ,dg%xMtងmiA%%Y vҵ1dP9EqӢθϚq^۵ ԭѴk0/AHyy-TDZ)~Rٲ]e;/>,>b.>v.?|ޯQx]~.?[,\~՟m7|[~ư-?[eX>/?[/?[k/?3ߗؗ~_~cן=w̏|o<~ 8)ݤ(^l~wiϾ Y{O3?9~>>o|ˆO)}T/6YcԶׯN][ӟ}}y۾8zM{GÝvG_mNڞM v0~]L/Νt黝@@ahNp?ڹ sq;݀O9]9д{ǍC/ΝtH",~}+lDWcCo*jg& طs;v':xIhޗ9Bi m1,6`78G}!S_엶?]N9bk ߿l8wrsŹn %&"ʝ+aBX3C/ΝnR{v'EX:a 9b#,_ח{asn2a]T_`K%q_ŹsZ!,j?W؛>94n#,76s׊mwS$˼/si}($EmưS;9^;=A":{7!)&$m6C5`hB`C/Ν'qt IQ֑m2!lOǹCC/Ω#sHa W[>6㍴N(Сد4=I5]ap㍌OY9Dt4]Q~),3Arfp׺,wNthޗ9ׯsHidlnDN7T9|k6>9 S 0Cp{\z ( %1d1,6`c(aQQs7v%łԖIm/#vQX lJq!n² )|;&`[0dˊt]_SUD Ҋ_r~3˚%܊;F%Fa@D\m1,6`c;bwG%^k>Ӏ'oDJ#C vÒBwl?#sZb"R`pn ݆;:ܡدR=InډNu] Q 6cb%, D2mw:;[Cg1`GXH;쎰ܿF1z;r wm|Aneޗ]}|m) 0ؘ혻H;k_=sA7s#e;26ZpooJ"@RDp|l),Q|:{ܭ-8stQ|XWa.e g]7o`õVc_x34:ߜԵC&wXw;qyckf ט7럳tN/ SAZ#R9aWOsC,s&I4;wHi`@};qig;ς5 l7gz1l0 ~ik/Dkp ̹3hӇWiiй[K kOǽf#\=ssq7aBR106a7|roӆ|N'WO~N$~ xx0~3-} HJ vRTa`@ۆ*چ83sKT6d1l0 p˄HŞ9))&eBRD0 [u U-;np-̹G7s3R D=_'ANƘ o{HYs7!ʼYq€2u޶]bO<$ߌrns#h@՟mFRHc<{sf !̹Kb @d$ETȎu 7ot;;Ğ9wݤh @X$E a6.[AXe$\=sXm(c`@FXDE$\=syXR72XRͶ~[1w_"iݡyUDvER%"6nɼV3I{-^6`(Qut7 0 DHokgݚ_cbC­VYd #\l6K{\ ,f~Y&abn 57dVigP B0l0 ƬaȎچ83{;  6F;pw$5=$ZfsߘD'){Ha6b]bϜ 2 wP"; Um?lwd(ag70nnCu ؐmn(m(m3Ş9w_Lc @XRPAFdt!6 6*m&3.5a 5`6&mPmPm3Ş8w_b `XH$,gӐ=Mlp 9­̛ϹЉviHi`@%aLxL{=s:mp&HdtId {;x& bϜ;+%dtրP"†.AF KѥbϜ\ii& p \,̹rxkB 0 Da [,̹NukrF:C&=,5dOѥaYi^{Ly.6>@ [2].AFf2:=qP"dt 24хHѥ,̹gcnI_NId6 h)1*&[0,̹?-.) Bl r6qn{}1a9%EXYXNO.aY <+sgw4a9%EXr`w E[ʯG 7#Ꭿȓk͛uߺ{")B]&Rc`@܀%$Zsg=50le΀й[K 97K{uU3q`Z~#R6`-)ZBqNK/A0 KI BFf2{sFXBM"AF KYfaan K(%LFg8f* K$Ei& p!KPʰ WǝV}lDs"R`1wAF s'Rb]Bl 6u2w_vN1 ZYfC@XbZj `q'Ut9dt A`pQL a3^;oElt9bc[jANIIʹ ˆodt\C|AJ=Bʼ/M/HP9VcUN%Ҏ,pW'8]Bul$\@@`dts%*u ]Bl,)t0* w|) 2]B0хXR@0AіhK3ŝF%, 6PLP%(Ĺ-MI3 ;'OOwC2o?< ) 5X爝h:RxFN14v\rpt.67MĞ:f3X:ǹ;HFvӐ=_ ɞ79(/:ٻed1,6`kb'8MgĞt].P ]~o^Z&[u43 h2:px/2dt2 ]Fu0dt!v'qx`+k十5JΪD82 U^)Bl݄}!BF'%tU ]F.P!3]]ءbl(a ].Rg EvrpF0CF!3Ş:; |.CF!ː噌.FE0CF!3^Mx o.C!ː噌.pOP噌bqpt^97b?a ]ο;'܌c*ND{eެ.-" 82g$E˜aDؚeHrNLFg]WtNqI2:`  p!ːeLFg8 2dtR ].dt!6FJdt{]qe2 ]F0aCFQef2:Ź_݀ ooOl* eĹv]{ aetkP'rbxpp#\\Ka}^)CؐYlBE29w]U.i5 _fT..1wC0jO5#ѹ:*.s(cd1wa\vkιk^f7!NFnl%mb;9m K2mdt!vmϗJ",_'$Tg|mXR_s?[:K,_g7Y0-C]f}#{ &(˯nwYȞcw`l;Bl Y68AA?dt+l-T hŹn s[APVpeqgO#G 7v݂{-Rg pa9dž Xpey!,.,",_cX~~>׆+)8b;̯@F7'-ptL_s/xpbLy{a}0@V.11` ~%хι0]'8Ȇ@F -P +(芓х9 (pI2`q26.dt\q2{t^m~,S + dtظb#?AVmt!sZO 6J5`L+l-)T mn s adt_'WqK(J 75Cy?{uE2]A8W.v]k n겂/;{rF dхأs:/EvV^akVP,(up.vmm_D EX1,W>9 Q@+(w]휻4@Fw '[ack1ހ +l=h+f@Fg b%+ dt+k;24ϵ7D6,8"{+ ,J!Թ4 + dtVZ,+ sBlg{c ^T$Ŋ ]q2vsFXB̹O2,QcK$sJcXa;Ք a @FW +'[a#BFWpdяBs䨟="hם=;Gl%Ξ,'~[:8 s|y[⎯\`CFg1XNFbϜjPD6dt2:k96n dtBѹ j dt2dt+l$\ hŹdt!9W.T e2dt+lpZ8]K$(ѕ B8 u ž:'GINFp]@Vmt7DC 9­EyA믒IiX7`1 ϻLKsT**u2`  78G G3xơD휻ꅯ{k H Hm[ؚUYQ@Uwf=sdA9 9bX;W0WD R~Yٓ_ 6dt!̹{1a9%ڡs',!PU(% {rw,nu!)B] giIB:Ol.FS"{BV.3: [K މEP&a݀96na#*mt!9w$@'u T>,تTT~v87s5Rdt2 ]Eu:2*`BFW.Ğ: j;Fu2/9bc[5kא|!g 2*`CAFל.v=-Z k5VJ U]9]=ql5dtV x\sK_jk5dtsldt E[s2{_jk5Fp]9 [K i6mFתmwS]+m 겆+;rvх3j]':{Ru 0 ؐYl dt!sB^"g.FkZ%^;.s 3ƒs%{_nUR=)  Xׁmu-3ՋH_u_־kZ\ھkZ\c<:SbX<-ZbYyhrkZ9z\#cr?ky]Cog}8}?ŹϗgznԄmmk{l:>/}`kߠŵ?}9@zD4,6`+.-'R͓d1,6`kbg8v=@;0<1k[\|`4y`4y̮G_ÝF8h]bJXWcOزk^ehgB܀hx ^#\h?.TDi m1,6`787`wGɳNHQ8 "{.Iidl qnWŹspLs )"a;. i8Eb vsFXnYvsO7a^밴;rsۯm['sTQDs$!,gwH:Fܐ-7p˿ ~2K*HkDJb vETrB/ΝۻMiu;i_"`p =1#sXDuR09ng~:.GzG! @X&$Emư=e62!,s g7a9%EXήGaw瀝7Ybq\L| ^97b?a m?gJuS1pBϹ/ UހUA2۽ ܹEsH58]`#j[N7ڹ|u8I nXƝFXDEY's2eAR,ai² j۽ D9B` 0;>9+²",sc@EXH+²~ q`#,k xp+::}音V/ 5 5lp 6nuposU$Ŋ1`=؇l+yq{cq,<4 %n s(w:1wk5eCX]\S/Νn²aX0mKw x㍆wB/ΝUnnBC( b7e;n=½8womޑpww v7vpwV__{HiXhm0eGXnWŹ 1رXc,uXac(awbq @dHƀudldOǹC/ΝnFuX'\{nr ,_bqJu⁄{ ,ݡ +l,)l偨pBsRWIm/#vdwǁI׺ ,W}swڿ0OiHidl.mY'sFn@s;HwV8lqx`ŹsU7߷,ڝ_": }ZK*sŹsQ7@〗Cڝts[ua/tkposϻoᅿT_zv'WqU_;=0,gKw(7p,)BqCsxk@XRBLln=:c;*v9wXR@0&6P|mG!?H_'!6n: ݿ ~2KH)A#R`p7666' 8'>@@Z6 gL!ڹYP݀m/Rs Ű_jT':SAj?nzf hs\bqK]T6d1,6`8GGNFbq 2 2 2:ks- wP¾!ȡy&x;-:ǀҗm3Mm?Ge ۜn]Ut/sх_ 2 2VvBX&FO@FRg H밴تlnmmNFbqʋ 2 2 2 2VHm )!9]9hf:ߊt~;#,+Q}/xpD#uP0ՉmLư1,' sfR-#!۠.^`kA:f۽\sf;0NqI2:` { X`#BFAFAF9]3 plmI BF9 #\Tl\a;pݽ V 2 :ks;%9nrJ,.,Ð 6kp+a=Dtyu)VHm(m(mNFb;/a=}{ӻH b,SDŽ`3XuL!s*Ž 2bJ5`6nn(ma9ns8^ 2 2 2 V@FAuAѶ9]ٓ˹Hͅ;Gl%mхأs.vSҡm%dtmm[ b5cr _qn;"{GRSDJ#XRؑ?pClu䷝"eq(F1zyL{3_7#\ˬn6FFm;7vΙj/T42 :cr  hdtхأsTq݆dt+l$\666' sT66H666'[ac ;KwC2 Ij;Rcc{sNp4gιEv.Rg p- ~mn!s24;H+F gOrأs /%*u /;{rFXdt!s )жέa E[rk93XT87#pnL_'Wqx=$ׁ^s?[ǬX$ I%ˬ0d ].PKNFb;̢5@G$He2.p dt!nU IQ֒;nL!sY ,bzadt 섄*`,A&%s݌ ,QK(cc;9b#,b 9wVA' ,C:~2E[-%p!VsuSXiLypM";#)B] 3dž.A:P@K829].15k%ɝ=F….PKNFbO.4 -RP(K82 gO#62#*r3M7!, f~Y܃m?W~?v!8d1?8IB0PK3A KѥAF`c[*>J/Dqi8?5*s/2b(aءb {朻PD2H10";–. j{J@F ư Us(θLup 9,?t%d1l0 b#,bKmp ĹKdtրIXXR.jOǵIµ3 @XNIm3a'~OO9­̛OLȄ3!Ȏw,)ǴW3ܵ":{RuqtEvhwPb$L=n@'5`2UN%dti$\=qnsOt2]. 2%6dt Ut ,1IP=gٻ%d1l0 `#,bK$nKXD+ҡ:7~E[2ᎯuSXd-GC*UpOՂVΐeH2 hW'#mq2lp.4TZ0l0 V͐e2swpŭ![exqd.N";Įp=Sc,̹2_KD+ҡ:7aM-AŞ9wgONIqd~Mr|re2m5XsͿ8HYXNs/xpbpy6,.1l0 Ɲoq<$Zso ]ސ.sD΅ZRȐιq$Zsמ]Kːe2eK{ 9tHPY֑mUΐe 9gOfFq]Fu0ȶؘ Q@(6 pC'.P(ưeYި%\f =ƒn+quι몚\Չ>!)BF'a l$\T hŹn ]½ C.@FW u+Jr FXBVmt!sT:;ߊth[OXBFWh+P.jn* 74^; %^iR U]qb;+N#S +%]i.ظ XP@+(w]ٮM:܉EPVpeqgO15K=Ymt!d|N1I:kdbnRP,8Kw]O|<N"EXcX~9;X3K ~5/oA s%x*6p{`l|pbJ}>G/ uHa lT' 6u 7'|5zN6BFW!yf2 ]EBFWmt!?38f]nqU*dt;F [ X:PUw]휻 uItO66V8p xƄb;/{K*dt%J5` KK U E[ +l_7y ))r|rU*mnjTW fbXq|eB]Vq|e\csF/a؉ޅԭB]VqeΞ\bCFg+э_Uc"eրP :V9B:WQ@k,8G;9-6 0\E!Qmt/ΝnbVH*dt2&6m51*A#0D ұrn~2 E[&p!VsuSXÝovW(jj m) 0 dt2:p8+dt2 ]22*`E8Wc݈vNt.*u2` a [et#0yU*dtրuXZlM*dt E[et#08{rN=9aY6r.U˹-H ²| q`#,q$8{-Hk:ϥA"ıW 6F#vw<9\؉N 9V2 ]BFWc݈9N!U*dt5MpQUj,8{*dt"BFWc#\p\azo7aJ5`@X"CFWrpo/h ݔ2'*Tgjn!0w3nyqra({jk EokX]E8Wc݈9N!U*dt5ؐYlTl5э_BFWqeŁր/m1wa E[8{*Ξ",'  E[et#83Re|;l( x_@XHʹ K*mz {}|Ieb9 _I2g,6 s?{cq: ]BFg U#G2)gCйYCeVˈsׇ*t=8Ft^2E=8D-Ԝ_bxlyׇK<OmCCFo //C =nwxK,u\rOh^j_2S;g}#9Rx8#uV}??M;d|l[{?){[שy>??{lԟ?!wi{w'pv3hHH)ݺwgf ֹtq,'waf֥9lw}S"[:fvӥ**Bŗ,zURUO)^'[:n7!Bo{ȥ>1i> R\VcΊ{[u9`߿ͦyȞǾ,!QC}YDBpa:ɥ4iKqݥ.l>\vg{ĠdKXΏ}&&w1lI.V҇e\ Waa6MԘ/CXҵ=1F)*^.氇>Ԧxc aKP5xۦ|)6xsحD"\|Ͻ2vHdKY^!Jl[6])t1_Υ[aүwӴ.Ma2ͻ˗6Y_I-%O&aUubPJc aK-=[RLb1_.`\I|:εSR'EvW)i>=5BXV /[ޟR89+r66_>^(!qJl*_fj ֹ=5OH9[q5:.eL]EӢypsXMK6ͻ6.[p+FEEW[jQ4( +#u.me(ˢ+c-`w$ت|: ui {j6ͻ˗W:u̗QCn5p`¶*¸{xUͧC|:+bۥ` a=m7 [#6WΥ0[VK*v}˗E|EsWiQh.rMv_vMve}̗ XM+tqZ:fzϮ%]ak|yS2u.MK*l#nZpa/Uޡ;|:=L1oB;\-a;gXŽ.>p+&i\Zށi>=5=BXҹqw |^^zc%1$ke?VFIREXBXpa:C6WΥxg9 i==`UI/Θ/CX)$ _ &žra;qLט/CX}P{*^.}>.7OE-aKGO圤"i=`7ކ_٦7#ƥ5xz+m4\r|O24ul}Jl[ a=ŪJ?yHq7Ķ"lri_*_v؟OJ1_1:˻;UI*=s>-2 <y@'mNI9?I&ok}S2u.6t%EzR9lӧS @Ǘ!Ј聗Yg%)l d ˗y=o_Q4b<,gk>OHn :yaKy6"<ǰ]2`߿=Lk>u.crNEqӢ{ [/UJEE92u.ͶtwwT7-zY.VW1_` wg9T`2.}>.o|zj̗!s<+VU%o+.UjZxUW]|Ͻ2Q, r}W%ZBXts/`/EU_US|:Q#nM[Ub1lVCͪЩc aK-%ݔؚƗvzRnyTe\pw%%EABʗMV~<"[:7/5EzS7YqoVk[U5}mΥ ֈڦui S}5^:8 rrBw&m;d˔gl|=g[J:钾¢{iViǭǯֹ4]5-R9'#nZpOa}V"VΥ $KI$o$KI $Qrֹtsk|9!T-*dyM@p `%NºY6VJU`2ca%Yi=$K!}*(;[rNdIܴOʗ[K <'Y aK)~p+& 4q oK4r'IP~)0uUqްy_q$ma{RͻCd),n~ %%6zwξ$K9V8R;Yv߰prQb+ʗYC<h|IX< [N#Vn^QbSpq[LjsRSlX{5T9'"Ϗi=4l'K#%/4~4/n^L+.𖰏K(חg*_~2e`/&j{+C$VKjZ"Ovֹt z,ez 9l/S 4reoLz5rN)E[e~rC-RORus79YEqӢg -j("Ov,@PpZ oi>=5/CXҵLP:~\RK$nZpa/%YeIrsr״LoC&/3 Ϸ廾w}IFV"IBY$K!s:!pwH(KE$nZpa5OXedy,~'v~[a+RVp;P) 봺| ֹtq}(Tɒ,=sXKխ>Y$K!W~>Jrp+t]ֹtE}Vq*$ k?>y< CMgnxsXu]сpWw{Oohi<}5{5!w~D=#9l lW@zYgYWr0%sتO`d)`Or(Mn!OQ8R%y`^͛["RQN%L)'Y aKl`Ý"HW8RxqzgUp.í*^.𖰏Klˮr~{ǗQCRsbwD="E6%V8R=l8UVxE&s>-4r'9DKFy䒾{Gܴ^表Sϝ|#D> CʛnnIEE*"qӢ{ax'Y aKW꡼VMmӺOo)DIBX> [7!T#ְϧER"QOI._vu{e|1_F3>!Y-=sXˬak ֹt (Nx7~/`5`0/Cyn T`K ]4O)|/#XwnngysKTT`";n dwO9R#nnu3B;n {J:jHS$ vrdvv)ژ/װK=zlZF^}m>hw{;˻C$)=SXIF;08R;aw{$KE"Qm]j>.UPQ 'Y a'Wlnog9]Rb=DEVR,~<ݲP>#-,s%ETDJ7%Sc:μr>;.4j!,o-RYzXIfw8R;sjrEE?ml_FKSE$K!̥keUrNUGܴh`\OU'Y a'.uŭdd'J$BU$K!̥k.㽸x,UIMVR᪎N\樟)3*/)`x:&/syۍ/#frb;!TzDHn+ɒPSU'Y ag.]kM[a+Rp6"[L)'Y ag.]+ƶY_,UIMVROU:R;q^'pwHU9#nZdXI OU'Y ag.]kYKxB ]a[U*Ru,3? Iְϧq>UjnY!.4 uȵֹ}w;Uc,l=$K*Ty,3?ܚSU7-X}V<՝\:ӹ>p+lE:p6մHU~$K [\:ƶ$KEw$KURxtH6^L;n {DXD=IBؙKZgífR {ުRU)jsR>(4j!ZgOֿ;dWbg;K46'\:ӹ܏KJCdiak vҵ֙%ߩƝ} X/ S#BؙKT+On L{xSVI%JT%Y,YVR*O:R;sMfm)$_N`._ʗ+zޞKkԬC.aGi}ihv3rld+ؙKx{6I L{l, bWO5'Y ag.XpTEXEX,lتOv1삝/-̥KQl=Cwy7 K})^'N\zMڛ f<դ jRa;s7۟,b,&_SdI$iFt!|[fr42,o%iǝ}sXITi*4'Y ag.]O?'94iTDEw`qӜd)tm?|> [ݲtចm}S|iag.]O?Ħ[MVRu&OKI30O圦"iUIĥόVMm3ri{j5)ZrR .5.4 uȵ3+|,Ӣ$1ܓV%2ͻCd)t ꈺ&NGܴh`/%Yj*4y,3EΊm?T7-"re)t-rKVdd'2x'$YjN\99p%Yj,5IMRhKԜd)]^?}o^IE$nZd#X/ dC|+J5w]hԬC.d;PMyb$nZ4p$K"t&_v%jwsK$Yj*0IL)oi=$K!̥K0W9I$nZ4pʗ[5 $KIBؙKȼal+RS9#nZ4p\$KßK ;s: 㔛[&RN|\.=jNN\z]6nބP玨[ޟk:阸\|Ͻ2Qƿ~:DMc$l#XKINk;Bg/-̥<˻;%i EPS5'Y ag.]'|.zrIԤ"2ܓ)m5ͧ&\N\pW&ɒi*_nt;Q=DIBؙK׉;ƶ/&<x,b%*$jvu"}MmF.M`[M&Q3,]ok|9اqF:{ivJla:]3ɗvҭ:7_ܝD˔Ew`XI I|iag.݊sݧENu.if&&% ;sVlwӧfR {ڥ ڥ c;sVlF7JP#ְ$..Q>,YؙK׏Cc7%T#ְKz'_sy{/Q%l%6zDHK |i`qW۶Ln}>.oi=̖Ra"xqx*KHlO]EqӢM.V">,Y/.G]]*"%+ɒ`߿MyLdaABRMxK $..QϞ\ Ϟ~HrZp)!:DS:=MEv$K9*..V_\л]R9goKPbn6U%%K,x3q x˦|W5#vwQhԗ~lw;D=E17a5$E*3ɒT~-.QdI*Bg&YkUu˒iQm`5-RjWgWgw,_\^rv"]EqӢZ"*KqKKKEd'{"C/~ F! ,3B @=ޟ$KNu.~|+4_͊C9YN}|hZ$9>-uCK>-CK]R\<=-XϏ=?|_ogg{?*>ܛ y}G۳Y_w_<Oͷ @kry=>k[2F#??Loxj9_ί_ɺ׷﻽#δ/!h?}Ha+.l79$9Wр>\~HH7۶-AbOna;p]h@s>?]`W|r<~WY H~ >__&qsZ^ROI]:ƾٶ{ Uol_ftypCF4F>,ݶ{]휻סӮIw8"{U~/^a;.}O]EtvB]NvsFXl{tFڨu;im *,z;nL!s0,f` { X`u܆c sw0`CXnH/a Ml冨3Z\ĘpC\\!L"ↄf41`w8rBl @d'$E p=,`qnVejJ$$Emтưǀ6i^ cvK9D< I1!&e܉+ 爍FBd!s:+4BB(M+aok۽Ye=:a0kO_?w O.caWkp+\ ۿ ~2]tY1"PAZ#R蟊xL{휻.UzҖ[}zq 7e~&7] b ɶ{a{r"8W@Z@t. a8ι!mnѧwuH6 0=,!߹Cѹy6$6}~rC2ߒm?kT;;4O㷖$ŭF40ǮD3&9wl=3;tHic{'ۆږX-vم^ɸEt.*u e2b#,"F"l\3D1 44[u U -!,8 sCHưǀ6.[˜ k%b{Lߊ8 vw㍼> )Ұn bV1,wx3".bE­˸C"Vl,)T;ek2J5[u*`B-AF.vΝ;4n6dt 2]Bu09  2ZBq.9]휻Op>ekI2:` { X`cKl(ReT[p@C|\rkLJ]wb~US@j ̱1w3HPs휻kCӂ.UP^`c*`mn!w$D0 Ց0 c0zF-58 swA~Nt.*u 2` { X`ck Qdt!wfAyrJ:OX6|@F K r"l] hpnFdt_'Adt 2d7 vmu9­ssCRte[a#BFP@K(%' s/2}zI2:` ̱+#6dt!\%C  !KY^acIUZ:c sO!+I%dt dt+l$\TTg dt!s?$YI':{B 0=,15K5~@V %e(2mp _m 4]x} H M)| X`!82dt!w+ℌ'3m게';{r]Ut{L!w) ӻ;Hw68"{9`_q[휻 C'tӀ Vܕ+lM2 8W޹Ƈ NȐ^[@u0; [uaxĹvݥ!2dtR ].; 9bpO8ҼZXn(R?>DglH5wưn[C 8W޹#E2dtY_Nl{pn#P22 ]vι[=?CF!ːe貓ѭpQ̐e貓х޹j ]F.P!NF2FXBŖ.vg<i~.CF!\`kI!CFhPe' sgOI|ٓ_'sٓG?kp+|)&]O-2ew|  21,' s>a (R  0=, #6FPe' s.a~.CF!He貓хι[iRud2dt2dt l2\v2{tn \m<) NFNpK]4>CF7'ڃsK', 6enw|*74u&P스XFvؐeH2 h"9]휻a~'8{Qa lP(e;X3]PB!82 ]v26a [vk޹kg28r0a E[vkι{P))ҝ= Pe(ڲх޹Ƈ;7aRݝ#6|mHk.FxFNtn2ؐ9Q8]흻6at.XR087ƒst>pCluPt!9WHf2sBlܽ~3dtBY.;2:-;]k!rΐe2dt lM (e貓хι{ov9g2dt2`v26.dteFpkmwSǹ[ha06Jw_ݠN7*-)btRWP(+'[ag8G G+x7v{Ǯ26u նs l Pn휻WE ,!+=Yٓ l PqY.i;i'[",_.,9b8Z%s>*~% dtsҡm[c?aC; mbּ!v@pK\ܧm<Nt!)B] 3dž@:O8]CNZ +茣NFF…VP+NFbQ"7O2[@FWnP' sޱ'cl6J5` 6n+( mFb{箽c7nHH|ӘpWZR( mFb;cC+[ ", vwKJ.Y8m?F#+$vU7jymDusX.@FلpW!g;|H{ec~ uKPhXu` ][ٓ\lC;v{e$EZLdON%4RD`m]{a;i5t0aQMdO39h%4dsm]{Ǟi;i5t.j4@Xu`@KP%6:ې=v].S8`dt3lM 2]22:ے+@9 K%#a#BF Kѥd.l/quՔ{f~cχ28 W&W&_ KѥlJ ے^]B.Q KFF7F)`#CŖŶ䮽cχW6AF KԵȞ`L%蒑ѹ؆ܽwʦ̰DR.AFn.`.I%!앭م-AF'Ǫcl'_6$Eˌ!K%-m,#s %^n&H%dt\lKn-dt R]. ngP%#s!rN%:unD2G-AF&lNѥtͰQCF ))N+ EXJK`&W!L7yxvj5?Rm02[(;rqY 0Ҏ䈭[F0!`M 9lJ̐e~FF%L\~ 6o} r-/ Sxi]531ڏ:',!Pe(ڲѹ#r׹ Q2 AF:PΓp?8/`KV  oPF`HxoϰGsN>͐e1.C]52v[:Crg0a_Z.CFѩ3l2 ",~G.%"dtrqlph% 9lʐeH2dt2ldt3lU-6*ldt.rؚ!ːeZބeI.mto&ܐ1?UVqb/Fw-x2?--CF#kvkΦ ].CF!FF7ò.`F-9[j]t2e_fs nٓ\!韱>9 KqeNKs=$w63TC?8do.ȁ,Cі.R ̌$v%G ٱpW! uo4?W8cI5t"e289a aW3H-]F!ːe.92 ]F-CF$2dtox]Fw0  ohe4y=$w62+ːet2e2ldt3lTĆ-Cі\.e(2m\$CF764277],CіM%c~ fAe촨NHPFa#BF@kpM:fFYٜ=9ڭF lmvkd$NvCu`6nf44osG䮷Cd$NrB!±CZFs.= ^f{.S(ːe#`CFbހ-="w32n`?aC;3dt2yCh.C#{95jtkDa~PJ@F!FFb]~t@FW ːe#c  \12:{D dtFY ;3f${HzU +tZFaaBA@FW +FFb]2> dt2]12 6dt2Y=$w* :2/ Λ,#a#v;­_ZF qo4?t+ n겂+9rwE`=$w~ dtցQd;ؐHʺg⌌v  T !c6.dt \12:{DaS@FWpey2bet r@V-.IP +x]ZV 2Ue="w5| vF!+VF7~9@uVh+T f .T p-Qd{2%0daTJ4rjalEQ&Z}{i>-WUi}> %ާҶk>oۧ47~!~~Cчneӫ|rܵGzcQws=$w4Z]c֎t7E [k;(|Jd{D~iJ*}O0`4cێ=e;*nCrKS",M9u]׸bk#{HziQ;ht<9I\F ѯ\Fsw1?Fcqs. aW3J \q"{kl]wn}?gvn#rKSz*3J:ai#rKSCKsJa;S!lˑ~󱟰Ўk(%˪(%-׽/i8vQY3ɼ%{H.*TD~[#oOa#V^B $(6CrBYQ$ńP˘fث5˄0#rfeBRLpFaa'eB2O׉%{H.;!,PcosFXfSb]ϯ2rd4#,(,acG 7#Bnp~B3ncqwF`cqW7;\!TkQ6J {6#v\'npƁR`Vv+rs k[AXesk=$L]euAU[,65ب7 )svSb$܂BA(6 ]nqAb/*jEnoaogg<ސp7Tj f["̽S>No3Jzl6)2;\]GY? Ćejs Dľ!-{H.{CdH;vέ/`8s=$*tG#)x#a#ai#r;⎄#,A 3l9]1~}={`I˪ ,g~Q!`~&('\nu~F K},x F3ȍ"mvv`n=$Uh5t̮)vU-/:ˁ6g#rT,:Wk;vy{j-`e@9\+g\!,2XU#r(\Wǎe2=mOj蘟&hX@îDigp!BӁ3J'{ltuouFD="wqD^ÁƱ;h 9W"Cr: (Dairain. C%7~2 ׉%{H.*40,GF 7SɾDe\[.F=R0/fЈR"")c6nDu4ܵ8l#*\#:J6*Q`eSbW"zU5FdNz k;~&.*{@n:LH Fts  ] ͹% n=$oᖡsv(c6*ahv{H-CH Iq`.D2k;gnF_Xt׽]2t:[Q:9ac햱v˩?k.C'9T(~Z,v79#fVT';W :f298;` *aYt{DnᮆNѩk.%g(~=|[EX`oENAX}=|[Q9 v% ƶ8vp7<,/#a@wΏ^ !)n18;`G+Q%Ovvx5t:(pHaC2߶v\'np?a]ˆRbGRHŜ0ޑpwa.jtIցAdZέ:q>a.5nN4uxHѭѭѭ#]d{x[WVtV4V֑F`ހm'ýBFBFS:0؊bk+.J;7H-] ̌",(,C EԄ\f 7so8?fx5tpm0RHѭhhέ#]dysv!c6*';̃BFfЩkE+hkaX`O{nnnEwp\l9ѭPP#]d{x[Qe#6u$ lv w533ڍ}r>ѭPP&\e7 :@R܂gNvxx!g~Qdy m+e-Q)a#n];x="gwѭ*\Zݜ.6*\bQ`pWCѭ5죰7ApEmn'ýBFBFBF;dt.6.dt+h+sHF>2R22u$sQ;|+,qcn2Ώ^ FW]c r `gvdydt2N](=lỴ:qۛv`w=7`-%9UgOai+\ې:fFY=9Vb#,qd2:ے;)8L3@h `Mېv g~sbw w1?ep3\$ +zF{E]h4dsmɝƢ^  [L4U 䈍@XXVFar׾hwWCHzSp瀉 )ގęa[r羪hpB@R ",np P(dsm]] N]@L4=L#a lΰ kkM[dtcݸ%7~2E[-p!V3UWX$\=;?hw(BDR82\@-`et!wm`vxٓuY@w0س''H4s%-h7nȽa&Be_ؖ:-gOhΞ||sE"m\lCz|jgfaiΞ|]{ͱSn2U>9& :|PhXu`w(}u !h#dtqER8В`BtΌ3os !h#dtuYK9. &a\4gOؖ0-9HhɁƱ{9`$\ې%;BF!5 [}]-B6`nᮆ~fF|Is盃.Buh&*Vs.3_g|ڔ.jcՁ!v-}r2]6䮧MEt"e2hdt3rF hdt.!w=MIvx5t:an〉 ]s(cDXmɝ#I2'9{r.`911,M C[фL&,F)!w-] ̌v ˄EԄ Z)%J";CF!k0=ΐe2h2ldt.!w ˽+E0(FF7Vf2m\lCzTuQГN]FL4=L {vL-skMk,G ,=RԵc/zPe(`sm]mr%rhaidtoo2 Y-/&/j^??rmg9O(2g F2Wΰ7φaedt.%w u9u2n게/9{r ]@XXFFbrry#UِeZȞa!hUldt.%wa(FS\H FcՁ1v71q4ym]mrVW,2dtR ]. {9`Cіp]lCї붺ǁ-9e(2m9؄ 2|sݳsvʵԔ)0Zx}dc9|*{qr=ss>tݤ~ƻvoP;bЙW玿 vL+F{W*׿_YL:t|>}w6]_~oC>Vss{*TN#{}E LrĄ_~%ߨ~?Tn;%S|x~W8'~=Py\eeĕ\>tA\Ϥv}땁K-έ?нWkOV^7e?{SXſ:~|(_q}uZ>~k||"?'/Ϥ |\.{pN?ӷc}c~ o}>U19}88~ݾ='g:܊?t@t>|Q.duC9u&U??޵Zr8 ׿G1!q[y81 ң1-?BQ \O†uW_S3gJf}CDrP2eP%!lַ5S ]WMaQc:wePTa'caC}RsHc.yr*&qLZE:_R9ԧ t.A .bv D E_b; %` ]JlWa_ݚ3S&_zA Ķ2[l aw}K{U"L>[VU®a%Y0s ǩф'@X9&Dm- =l;EBgҁ J ۠epkRz~ 6_~Bhm>( cX {Tɗu mxA-(_1l% `k)Cj+l[.A8WmaϊnLɗ_Pm,ߎAxRzl,p(eK,JleQojYDXE+bk(ݷ!h+m%m>믥>3exJlE*_oC|6~ۛoSb۔$7fo M_fe/Qܔ6,Nu=ײheӲhSLjYDXeMe6m M{6՗mv_rnL҃5R> +/Jj笵%=UThqW KvH)޶o`P>ۋ0 J v)%*|7gLϡyA j{{}Kd!4Mc.̩\gW 2ma&$kB `-m_n ңj{` BKvH:KT+/*5bv[}54{/>7xK$ R#cSXCZ#xxj5yd=ǰ( vUM})] vC { khL&_/yS&_zN ׇCôZ9l+1!lք(V Cc3ؿTDIme͏a/+WP'ɗC> +T;'#eQSfҵ\3h[W9_A ƶ 1l 2R,JHW  l[*)vP)L}(݇^/*ң"=g%:6$JR |W]^jsr֗6zjBtGVy*#GN4y/()l&Ӷ !lmS ׽>3enQ:W}윎V^ %&KڷZPJ&_z#Jasj੝mzv`(V'/ؿKJlj05m az\)/?t=SYSh[زIL aeVٚxYM|\_S _Į\s%*_f-nYM`EY-+_fلV"ª lg·LFyV%m؎`KmS ׵3UL`KZJA ܨǰʗEeZ?AMJד/vݛ"(ҋ~VaxE_~1k5vDR}5xvRaSfj՛ۿMsj8!|SnJl M)?KR:>CI8Q=ղH}Vl6(]:ƶEj5ydu-ߒdI}D=(Z] *vx3؇R*JAWkɗ%.6_:Nr?]./V_.q~c&ɒlӣj{[ek@(J/׺,j.Y/\re@zk(ɬ6luY$RtJ26}G)j.9QM٦Gۀ-XedɆ`lk(]:.d)6a;dI)#YraV੝%Ymz۶ʗ[Š <#YraQV~xXD=06J=ü Î <} D,WK_r'IP&_zN ':KD=mB,lmS O?'H\XCjp l?$i;&ʗ,ň[c$K.R9W:lZyMgRbKʗQ%F4a;M/ Sf#J|xIM ƶ 1l] O(JAc3XK)m՗jmzTma%Dzdl ;tiiT%x3؇` yjʗ%&_zN 9bֱkB$߉ =/ e&خ'9$iTDM!.JU'ɓdɅRp-Rd)DF4%=SFJNv%EHW)R- Ŭ<%h Abo PDij s WS_zN '$WˠJGm D IFZJP}1trN2d06Î.kiLۼ;t+hǵ%njIgZt6Z-R(IE$=UAXD=H\ؿlR\ JR%#Y;Jv/鈺A9n|KNN$zR0%_)|9e'~޻ym>*GV2l,p8 JU9$I4m~ }/R[RbSSOiXx&_z{GvR੝$YmzTma/շJj$5y,AI'mQH{J/ S'gwX;ji['Rmo [{ JRdA%lpB׫X{BEyu ¹޶ղ(kYC3'$e,R;'I$=oIek׭(2)[ý,R;'#ªNK_ɗҵ Om#&uo`_ )#YraPҋT#>IXJpozcb]vkˢH%z6lǰ, ׵b$K.R>Td{(Q1 l}$Rc.su__N&Zo4eQ|'K#ma%Yj`Uj\l$K.tnWyVJ%ile`_M)#Yra-s7{ ƶn,eIdUCXKIZ?YMl$K.RnvUdsT޶o`Pg$Ks[R,O|YAl^h:5Wx^#Y,QO !$Kjd5y,ҵA?^!~{lkYuZeلVyVfҹ=^!Vf-t&^cۄV"lɒ, vDF2dIQgہU!R'=3eezOSLMȵ\a)Iv'nZK L`-_PR!(QVMegtkva%J%i;&/ S'#\{w0m#`jl EH&,muLȵ#ݛy_$)4;ư, S)FJ׆tСzCHE$= X}j#Yra ՜:Gᱭ[^|6a;qZ3S}ta-՜Sb[dUCXK>% |JWg5[`;()j6=zlak}*$ꁱtuVӽՁx4OW D%|)uPs&t7/4r2r51ӽh=eQJl4V%4{BdɅ&fжnzdUCXKIZ?EMb$K.tҥbnlxQ;#=M"vY-K.tҽ/䱭|)RQmvSNVHTdɅΞ]$KE"ɒlӣj{[{}a)%Y*FJt 7H[T"mzê$JɆJ2R5(uJTwSt*Eۼb$=m,o.t5ӽ/~ۖdHT`m#Y6`_)#Yra-}ۼ9E%٦GVR}"PdIƦպKV੝Smzn$XIJKPZ'ے,ITDm$KX%Y*:GH\XCj{_>x d*׾$K9D=265in, *diP2D=[1(_uf^h:e'\ږkWAԛ6p%|6sV%a,Rfҵ\덨T+/ے,m4Ma%YMmSɒ k(]rخVJZ-KMcX-Է[\XC:{tdlrL"]M٦G1mV<06eO锲MMM*v7o+ v/=؞RE{V~F%(ns[diiuΥv/u]sIjmuLȵ(׮$qjrxeHtՒO~gζkp.qvm놹]u>tvϢЕݖއ<Cׯt;AC׼]M?f?z{?gq7=OYlilCk ڮoh]ɒ~=*~xe7n~_61x_Z=ޯ+ۙU~-76noԯn;ⶳ_eV_]!Cpk~w_?c? -ч_^G~;eӫ[_,Su5<%~:<#et]v ֽ_s+Hx܇.6|}tq@8/{)gϟOVZqs^'_wxk ZI!7|>xg|j|k56Ff\a"r68hѵL.(I5N_kr 2fEweLrGXm\E~brFa 'Ek\8{@nnt`hԌ=r#;,qk=qKB>UW#t{n-)0ZeYv\'np[o`X")R_pqs횸a2, Ɓa[1",13Ul动XgAmOtΏ^IqEn3::b#,+ Ju ",`_3qf="w=ch@)E 4uxHڦ,5A@då]{k@TX$ŀP˘f䈍z# F2{Dz:P$~:qUe= wKBϼt蛋#2",p^f 7so4?#ԖJ\AdHi3qFlDR /{@M5$$\mƏQ: ^ D8s:=$^[UN2tCpO4K;޳eI˄4;\QX^ omsvnBXf;#,3bp[!~*1 LceF2ϱ?mͨp˪,uo8?綁om$\2 aiNs`gq -Q:;`k HFbA2].dt6dt2].dtiz|[t N]@,@FF2:; b$kGsG:0a4cI@0@F #]="wmq233FS bw w\f 7so8?٬2tpЛi5Jzl=, dta$kG䮽cAoMsv! х. Glk(kνc8VNvatk>9{GX@-` F=F<х#ޏ`@F76?э7"2]h^o|Alk.3_7=xuYasp! h4HFbN.6&ߏExqd.dt.6Ja [b]^.(rpf-BGkCrn ,F'G7],BG2{Hz!ǂEXw)䈍-p n*(6~W$WC@.Ʊ2:vE:EX.}X䈝@49v؆UY6 h7nͱġ E[jּ!6@|pS\,>2 J")B]fhg ]tΌ12:ې0,>@%]CfH%4s\lC9%܄RPM%Hdt 2ddt3rFXBŖɭɔDp Kx]Bu 6FLP%(ڒymG_\HO3l=RH&mɼ6.r):EXJKR 7 B u@_\WC@ꖠ.Ʊǁ16dt-n gO&#s rL:Ȇ.A]:`"{vpt."\/\M(9TC' F屏v7 lN krh`XFL4=Lw6h *dFbr׾8].S8`dt3lM 2]22:ېp@9 K%#a#BF Kѥd.l/qu/%\o9 W&W&_ Kѥܗ.!wSWϸu@zQJ(nRFb 6g=[}%D6dt ց>gj'tdt 2ddt.!wn60,!K%#a# Ka'\ې_swI%Hdt 2ddt3lbfXn0hQ E[^}br3?h?nͱ.CіhFFbr;k=Cń Pe(bn2E{f~U{TJd2e-c 4!w-.k ;\]N_=r)FoI:@Cn[F0Wѹ؆ua]Fw=Lphm]z= ːe2dtfتp[l%Tl\lCz6:.CF:`rI.mto&ܐ1?UVn{f~531?Zerd`k7ېe2dt2ldt3l=,f42s\lCz:[F.Qqe6gOΰQ6K=6'ˡnܒc?a43Ρ ait{rχ(!K(r:PesmKO;F v%G ٱpW!g^z2I2m{` aW'\ېWȆ.CFghɍ!ː3qFFbrqF6:9880F2h͹lFbrqaN]F,CFn Pe(ڲymȵKO:PpGFqKn%dt E[62:ېkˡQѽ~92Tg\l-]f 7sOzE˶:9 )B]r0=F….7IvOnoWt` FYٜ=9ڭF l_؆\zm@dmtց>gX @Ҽ6k2 ]Fw=L 9The4粑ѹ؆\Ď ]F.Q!FF7F[62:ېkڊ96ڍ[rs',qhg.CF5oevw9uOzm8 w<ЂBuD{.CF6k*].CFn] +4 s\lC]6HTЩ+h芑Ͱ#;hp=-2]Au[ 2]12:{DnByQ + dt&ؐ Tgbdt.ܽj]xYpޤh;hS/ˀC`-&zޤTRuY_9@;"7B X @FW.kE ]tʲ"B[\ !+8duxH4 s\g5T2/ Λ,#ag#_U#rG FW6ց~+ {GX] ~UbݺC,8(dt`?FW:+P`*?ep3Fs+ps5trWFaʔ@@A)bZD:fFhp#J[1k#rJT1(JƁQd{:0͂Z6grlqa ];Xn ]@VN8[Q(Ҝ=6m%)ՆpHx531ڏ]r',!+P(J b5sYue7 0Np8Ώa~P:? N@/ dt-A)aCFW +芑ѹ#rד g-ѕp!+FF7ڭFXfDE${D: f":u7)4 dt\[%3,!+#a#BFW +a9H-0{2Q芑ѽ~5XepYnڭ Bb7K&ͺ9?p7989am  *{D8o8ۿ:S:0l2.`A@FWnxmp˲a`126n8Lɂes="wiwZCKsJmsL1nx+C533ڍ=r#@VviG]D^\ L}#盃@uVh+M2E{hZQ .k99gHv {DZnx!vnm%tG\i6χ.}PW@<l{] )7x>t׃C6]m]["7χ=wCѶCn?*Х>Nsڑݗ >ބRC׉/{>tu|zo>t}w[-{1{oSܧ Fv\i^ONاݛzO Β}Mد~=ܧCWx:-W˽>T;Wk?}nx{Ǡk`>(6}q^SwB:g;e3r}kϜ8b3Nu>x:01>sp^{vbl95?Χuޱ%nǖvN۱ oop:vlB}ӟ?wձcێo-K\䀍sG9bɕvlzs=$we;[vlQ ;U[ɮq3xCX="wlG~F%7’׽Ʊ_G;wN?8UW#uo4?$CKU:(0ZZ0,u<hkp7|s&nEX AmGZu\ ")H+rjf{rEZm]pW! uo4?Eێe蜟 189ag#62\Ϣ͙2t:<]?[mB[w;7p[4Ed f1^ian="w֪42tn@R HaFaa'#62 *8{@>U*C?3#7~2qAb]e*4",GF#rjE95A -vp ^f 7so4?W (%"6uFoup m`ϰGJqeZ|ERcqsA XW26#rW M설 aXLH)gY.&V a 4uxH sBX&b[^ЄLpk 4بpQ1p[ B3rdOXf$3q&܌[Yu uo4?WXfDvFR3J';ow`X")Qqe4gOΰQPĨm2߁-983؎3k؆ܱ8AndH77P@uhpSt/3s<p0$B.k99'ؐE"h͹hdt.!w,`WrFXBwpw$2U>9 8J MF&(%qӗ.!w:P FUJ9V`KFLhoV22:ې;J8A.hr&'J ]].mG PX&Hdt 2ddt3 ]Z}u{r8w2]qfz Kx1\‹ᒑѹ؆q2(Ҝ=pfٓ G?Γp?8/3slpP)p>dZ=tq`ꑂv ې;?c-n 2j"{mR"dtcvp.AF KFFbrn@9$EdtfH&-ep]\>;%4@ [n-m $FqKn%FhKPmt7Dd gg$AgN>Lw*\4Rd`m TC9dt A880F….МKFFbrÇ 2/ΛL%#ah 6cOy-9%(m\lCn9ɡQ=ٓoo2Y-ݓ+Ç(Ҝ=#6%m)لpW!gz!c~.Ʊǁ rv%J;}u :v쌤uq%7s)vLymj(%𖸄ɁƱǁ 6)dTh%4dsm:Kte 2ddt3rFXBŖ6%dt 2cldt E[22:'ρˡQe AF:KPbn9/3sPcl n%dsmJ%te 2ddtlF dFbr^"2N]뀉 ]s(ӆ42:ې;NZ8.AFpd2gOΰpL82ddt.!w1pa92LXα+9`CFbK`M'@F74ڏroQ@іhp!V3UWPnK =3?6 uq A2gmG`m TC/r2 ]Bw= 3dt2ZFs.m d2:u ]62v9bgͰ'\ېN %7#.`-Cі\lCn$CFr&,؋)dt3Tg6ٜb?@X",;[J Dc&?epof~2g F3'l GDXߦY@dCF.k':l2s ": UXAI게 hp!he4r'`!w4+et2erqw G DooZ9{GXE[ }N~Ch?h@X7ac?dt E[6ep3ϱ?pnxF@]0?(S ː{N|fu@zN]F,CF<lZlBD`u2rf"2N]<[l32 ]dt7䎧%dt2 ]lp!Pe(r' Qu`GXĎ:`WrƋrZ;S7' a92ڏgz',qfƋ2^ Mx盹J{f~Ǿu~pOgN4IU{N|OreZ`CF!ːer' [S^)g$Ō ]dtsrF lΰߐ;lՁoIց8'`ox1\Ƌr' CZ`X")BF'|l$\t3dt0, ~Cm?@F74 ].o²~5Kr6k2$߂|Wk۽7sQ9`[{@@ Fb/2po9|R@dCF!kGv ].!q}y}-VӐ^we>*c|=_W+·B?_7tw/8?Q4.~x֏-gNS_IG"`KdrR CcεK~Nr \+%yRR}a%YH LrLg,/yR%*v}2Kx 25O) 4g_TjUk6=zGe! vKsI~iB&`q £R4!E&˔ZϽQc㰭?ؚmA~Ң] \᧔B KlL-/R, [R- werL۲ˠoEIoŗrUJlkMa~xϗ`_I˵Vu%IN_ Qb[cν Q^fL/˵נeP? ʗxY,(t/FYT{JAN9+r ʗA-dSJ^P>3oe S"JHYɣֶ[ux7XS <`TA `oJUh-|㏹@ՃOHԄ(b Q}>`a/1%mepw ¹Hִ4gJ)6t?NZ%EpR=w!`R30!?RO.X Oc.s/ńMHl ңE}/mepw ¹z\Z?aASZm>, lӣ/R#cEI$L2[>%`xj/QRvWPy-u=.?anL?*|oxuMm`7}K joQ/Q휠&lӣR}j<_5|`jle[}57{<_=%9!xKʗ[K 4ϗOIزeR/$/&_>c.s Ze%Az~B,"Jͬɿ/6+e-hZe7g~9_f[YdP?yˢU&k:[Q,*17*䁱_-)ҋݽy>l׽>35_=%oPW"V+7޶6mj @3!MMz} ˵/QʑvNPayn_Bgݵ,RyZK ,Pd)H$YmzjI>AKR4mUuPOKzؿ O)D(uP埮LHrN2p݄T/ׄ/QJG)m6͔c_T#Q휨&O݂J*䉾dSZx,E5۟$K}55{|ҿS;'J$=o)kxjD_/(!ؖ]xdɇEI,EɆ`ɗk]5(uJߙkB(QkGo'dXedɆ`()l%Yj05?[I חOJ9Q%٦Go)I$دxAK9 JlA2((V_ΗA70?CWE)DKxA^S!R'JyuUKb|YOD=<ʗ,8%JU9%߉4;"J׭%KCc[aؒKڞm z\Z?Q%~NIvNM/٦G))_o%oQ9QM٦G)$O%J<`;ҦS@(fɗRI,_ )f%6zzN$K}55{B|ҿۼ;Q٦G))_J3n/Y,R;'#=%-O,g[d)DdIfxϔ/Y()%YmzRЖd)A͋Ed,EɆb1rӲ(uJߙkB-R6=z;!,5Ȓ E_/()l%YR5?[IkiLm^vNdI{Jʗ[EVw/]vNTG[J,5 V^b /;؇,r| f {O>3$KI$R*_oI 2)Ij6=zKIV&O%K(/m+$YJR5^`_>_AI'RdI{Jʗ,%I}D=)|YAꯔ|/'$6,ʫceQֲH$%-Ij6=zOI%auk$KE,%5m~)u \*>_KJ:.$Ymz$K}a)tL\2KI703GaJU) Q%ˁv)%*I Jdzׄ/] ߚ?mJl?Ib$K$KI$QVROR'ҿT#IoJzlӣT_V&%޲`jlxz˒`_ )IiW}vNڵVIR$Q%H%*$Iɗew 9_VW|'K#݄dIغ,jd#Ywv$~J)knLe#Y,ϦgQz˒lӣ[*]v[AIvNVG[J,5jN)I%Yj05)^`_MN)%QRK$=o)k6YˬKf|rU}6=z;!, +K %Yʝd_Sd)mzR%*#ɓ;ҿd)rd)K`jloSdI2)x[t K'R޲))x[XD=yuK\ eN{*G;YGmJV'ya?:/؞meDY,RSR}rֲH ajYZ?YM-J< R6=zOI` _kJERd We)DSR *'ɒza)$ˢxwIW.|ۼ;YvS{\ %I;Y$KSX՗S)%ǥ jM˿SbdI{Jʗ[e~|)R(KE$-%IXzrWlRR/@We)Dy7R?ra[p݄T/4kB`W(I9E%٦G)H}a%YHZ93`$vmdn߭/. nSJ,_ȗg#ﶽ(|o^{KVN(ݰAjFo=C E습?=Wo?!u|H#HV~ҪdHE3ek.Q)IPI|O ۤeޠD=[#Ym-m ^C%6z;XKI[FIETDMRd׭&Fה$YM a, ʿ/Ks6eI{Jʗ[mll[B?m93 %/(mHdI{J%l;?_Rx]ޔR@mɗ:ஹDSpo'$iBt[d ,w}s[3|O>.PLm}}~څWv׭qrJNv _>rD^cxܠ|q^?_[|ílD8(@8 CDtZ_ӢU.[>ߎ"H;B߷_,C˲OomD({c=N~Z?'p }h}-}]E3rN /^.!w:e0qKnoN\s z{>.;04% {7Wb"5r6̯AoQ<̱or-vة9s*y^??!$ׇU"hq6̰ { vumȭ " "{YmZ#{]7I}Ҏ[brqY5)$ E/}dϰp}!,'\ېK_nKj(r1a9 Gl储Xbr@F[ K$eѭ&;R|Yv\'O.!:>KƏa`5FX˵/K'\׽~~;ZN~c3l$\z7A`}u |҇W H w@ vYu؋Vm>"I1]qKn؆`ж"t Bϼt#ꍈ628H*CP%3Eaq?mQUWXO{f~iӇ^71q@dG$X,gIaPؤҎ{$\lCȓоPK˄pOԇ  7dˌL}u fuYeehFXfs\ѱpW!g'xZlcq:0FcW'\ې{aix"_=tq`]Hę^.vrbY=t `VPT$\~s3P6jzkXp ΰaYfSm5U⾩P+ K$ł q{CX"oNI%N6冤!n̈́ wC!,7f["̽yd8Pk-{F}-6nn2[\ydP{ wò 6.@[vV_oiݎޑѩkmdW% hˎMߐӺaqGwp1olaQaiv: ΎEX:`Wr^ؙb뀼ZeUC?cf< 58yeL{3?hٮ:50=twΘ rݸΏIr˧@%c onyv {6(VuYkl6{Qb#,Db+\{H!q%hЎ'Zl=Rٌ[nlK r,ԫIQ]ÁƱSɾO+b=UH~x L*i~558vpW$2Up=c΍Bv 1"n͎Ʊ(rAîDit'ws[їI1'(tw\Xe$q>v.cHz+h{eHs]=#rp]l5~ BAR,He9a]P6˂(}uymB@XЩk0 &++hkAQUm]Aׁr-\KsUeAɎڊlN c aBo׽v rcT wC/# uo&8脈c`F)`#Cn})brWr@doXS:`"{붷:q})b;R22A89`CF 9Z="wlA@XSQBFZl%Tly#rG@XBFBF:0 K}V(V(V+G;Ordar]9A_cb s"̽eGˡ:zE5FX瀇G i3s Zv { v ;_H ѵRb ].@F FFb{ 0`T|02n@0М FFb+%:u2989ag#6*`dt.j 0,GFGn]R%{. K*/Uk7s*p͏exa0=tsÖ.@F #sGRw "dt2`dt3l$\@@`="gk]9׸@trF-FQ{#r u?F逑ͰQ6!g Y?)rV ˡQem3;7 ,Fa#JP8vp#n8H{qj5FRLF:<rv%J;>S@F P\r)H̸N O2х*T9'IC-9'Sܫ! 4dtf+a [02:{D>dtt7 4dt\9I K$EfHBfXڄ[jep3Fslg8dky^Z ,! tX瀇.`(˂42:{D)D rhaYa9®䈍z*PENIN!h7v ,@F ͋/ D*pqMJ!)B]fpV;8@:@ \2J dtA8:b#BF6\9.S( #a@ ;bp'uRvjdt#aE[02:{Dy#,wT;)}6) : P{D)D EXJN[ayp?8x`~ehmkp;hA-I$(#dtցAdjGHwiu  n0Z@n.oN%{D-. I:gqAXS(cD`UY>y^Rl!! ~ 8uWṵ78L3!f ].BFFF7. &n6.;AW֠>6{82U^4JnWF"dtq'f{?2N]D,BFn@HPuPJl6[D"dtցQd{jGt#dt2hdt.e"dt2].  ]aidt."a [N4䈍E[42:{D>Ө~fFKn%dt1~:q6FTe8={qj_#"ew~6Fb#?Aі\7xH!hѵ5z ?nx EX21v&a E[ 6 ]f 7sJuYMd2]B-9|]n RuYɜ=9F`#"˗srLDd (bkLhyJ.|R'<ӨNr;0lw|s(@Kh%6: 9"%te 2بplP%_Fc!B2]u݊9.AF Kѥd.l/CXJ׽e"W&_:0W&_ Kѥ)%> RuY_9ƆF!|]k ]u`-6n%dtɗoȡ K%dtɗ p!Kh%4/y.S(K%_F7FKl4TlɗodtioaG(_F7Fd2lΰߐc!(җэooKP%(`&ܽ`~ f2UgJc kL6oȡ~+0Z4+;hy)It:%M0\[a ]c0,7` oNEN,/ KSx؆T͝ rd_f{!`#,hVFa@Xv K2m!V3UWXo{I2@;?cU2sfja@%`4xF[2Fi3l: ~-:uhs@Qadt. K$EtZaoK$s4r`XxKj2dt2`626.dt9 ,\lHe@;3fر 7d@2$_7sϾkXT%atFq0Jr.GVvsw@F!5 [2.`F-G-}'u: ].;ٓ3l$\t3Ξ81۷}R(Ҝ=6Ρ۱36ƅHBX KڙhPesmȍ (2~盃.CuhˍȘ2E{q-SxI겖Cs oϰ 9-n2hs ]@-mȍk2F6ց>gxe42dtټ6Ƶ dtox]Fw0 Pe(ڲym΁hA]!`#,bFFbdtcݸ! K2m\l…X\V]E`w2P傤uq AE-o >؆Nٓym A880 ]ZFsN6؆ٰܸvC.Q&&X5 QaFb^!,!Եa9V$ ׉+\ې?Ӏ.CF!f#`CF̐e貑ѹ؆ܸnlT1ѽ䈍z*yC`\ Q\6W2s~PJxX㦱Ȟ`hءbFFbdt2N]@c]AV +FFbrg2];Xn[,芑ѹ؆ܰ)t e2bdt3rAt>؆ܰ) dt&,ؐ mbdt.!7|`S +x] dtfzPpf@VS/'\=3?"W eWs| {lvXFFbʰمԭ@]&n&ؐѵzV\Vѹ؆N@dCFW k#{vpV +FFbrZ@FWVV,FF72&lN 3] FW +FF7AؐѕW.!7|Q -9x]@Vp j*˼um\@Wp|eA8 `~PJK ې2,83;8X X@+hsm i ,8o@FWnRFXB3lCnL@FW +ѵ`oR +P(ڊѹ؆ܸ ˑQ9{ vPCuVb>)rq!#8'`?l%m%لpW!gg| [ɌOf<}r׋xd'3?O#~2Lf$|'3~2'3~'3~2'3|'3|2'3d~ߟ'3Cߣ^<_y?xݩ_sþuo}zڨv=ݱUmA;}g{7W5v+Ջ~.dgh3#\A4:vq.#\p=s~ h`+Qys*MRm6(lgf3`g3{uw(𰃾9m6i3vs KmUhXa *68{D<㒡$EmI!,7[qA=?Ӈ;",W$IvEX_a#rE\mf3{"̽cX!b~2f(kp3'c~|WlbșBMatvwv@b A;{Xzclvt`g{UXjk3qaP#rʽˀnpqsFַaf="g+(rv%숰ߎ)\2Ϭegb{FOXFAbh5neUfh~󃤨_w~(bBMe3UleBTg#rk0ꄰLH n ,]줰LH):qG aжEBX&Tuwhx9Taf="ghFXAXr 62ǎnF/#\$YFMvˈc6*kf{= Һ2bF80(%\]?یd^qAmGZDڭ`V6nk,f{M , ꂪ ,8FQelG{p ~ 80H.vQXTeoun="+ ߟ f{CP=o 6Mnep3]6Ӫoq>Ƹo3JǺƖۆ2eCX[{}=~0Rbò 9~bRFbX۠hG"{GRѝhDf>3q=r:Z[NrH;c H;&;rGXb!Ce]$ wGX#fx`#,wD|:\q59`W/`8|n {YN@3J']ZI qQmߐ;Gd`t rn7|s&nأ`!"@uf{gŋNzЫ~ѵOȵSj-{c!w<$oao;˘8傰\ ðEX.4ؕW:vpW=,3Xn|~g~VDܚc-vy½ߐK8D(hv[\ֽ׉7r[ rD^Á1b-~ᡁ9oq]:f7 6)6EEPZꀡn<#c?aގ^h%C?3Ksvͩd_"2-vpuf@|n|~j{:8D$Řy>AnGRHeGv#xڂblwgnyKuaN݂FhsQ6O;>Kvg5t:G ԵnG .֎+$|@0,GF 9vTPK&Ug fIۆ}{~VVaJ  ݊ڊjet!w<ևKZPɁƱǁ v9b361 -sk}ӁFwqCn#,v[@[e6C AN kEwp5oqakU 9'SlCxnQ N݊Fh{`'#vQѹ=9qnGm+dt+dt+dtՋlVVV&UD{uE`8NV?VD޴|ѥ3Mc;~Ǽ6(z?+dt+dt+dt+dtͰ3CEsn52:'(C'HSQBF {9`e`T 6Bo{=JǁnEq a9VdEpnn52:ې;q\@XBFBFBF  25 ?>#s{r,`o%;Tg+mSl/'Cxhum+e ěa#BF9m5"v\VC")BF'&بpl\lCy25cN]@3l\@[ ò߂bJ! dt+dt+dt+ͰQ@FBuBѶm5+^ ̌",Ko+9b#,h[6 h7nͱnmm-6Bf.{\X[p]ٚŭ[u 5ęa[RX) pKK[c\d?̒ &zָX)D. Q&źk  2wƸbr)t.h \m]U8V0SOYώ`YbF@ H FaۚZd-] 4Z@r.Xm2kzw $_{r]`^lmCYe›2u-??3qi~tqq].F FV$ @ HK)P)f-F@ F wz,lE6_m_gG6DXJd%<45vRbF` 2wئq@gF={-]@0 2❡ѹ85+ht4 {`#" Ї2e04:C["S(bx ݈ -mCcY%ht4Qll)FJmCYR(sX=d@G6Ezv~UPDʀ=!GgOl)fW0a>} bHęo2 {Xc7J9 ex<@P(0֖BuΌ3ѹƸ"]-]6jJo`HE{ŶL -(b  Fa㦷3(].F7(`itlM"htF[4:bY)`J(o/7], f SNzr)niht`w -p p$͙ozf~c@u`E}4n= 6ƕV A` `+AHeht.(N8.";M6ݐHE$96'(P- Q&Ś;ll [4ѹK:U4]nPvțFh`ECsq2Qn f@`E0en'9/Գ⵲K RG 6p]V{^JƸgl~>Bf{`k)1bG!g^JƸg( N%dFgoN&ht\l(\,ht 4].7I.F 6%Pht 4dht;lm)pKLFb.i񻠟i<~4ӫ>q&qn±^su3slgzħJ%؇zO3?m!(F7z`#F@K%CsqJ T].;8bg!g.1n@K%dFj D0p)-b]8htR`PQ`,` p44:۴ -Bav_qĆ[= 6uSS^ؐ1?^AG 」Zt,6=UV.F7(ga+@KH%蒡ѹƸ] 4BFֻ[B3YM2˶CRX Zl0Rvlq*+x4n%ht F[24:rv[.-M_o4Y-%pSL/Գ=K e rp|-NK`՜lF7b2˜FbLS 3pHۨ9ƖNKH% sm^4]Bv0YZBr.m{Rn [.F n ݈ -m]}[.NѸ=㖠%0m؀ *su33xv2uFq~6xwC0F@1nJR'pH[.%dh ɹdNsmuVn%$_&{r Ddht.1n ]BnT[y,`Bt- o= _GJ(4n9%ib[ڎU4P蒡7`cd{alp,%;EmӠ}ч]ԯ/wCE-)Z_TW/T~Q ׇ. j8}լE]T=~K.]c7LJrfծj jyQkg.3¬j,/yX^jiOStE֙|2 ,okGO UN͵Y_TOHX_Tܺo;D\_T#w[6 ~|z G?!}SyhB|s/qS{|߯?_[*=_v-K~wy[Y{ï࿺vKKw3 -lKԍXq| F%@دt G¶I| t~?:ido`Llu%lkѶe]Gv,Ѥ la03'\XcR$#>R>&]xIo{[z`ڟaf(if1OX9^җ$vᢾ'=x)IΔ=;VkG*.mRW-Pw U&)%=/[*^&//]XWmx,vIh%(Yx9~/]l(ERIM*+=k5֗#lx^=VQKU=-z/ߎ@(^/3Se^_Nsоr1I@h^*^-5Ve. ³lG>CwV/v#{ d`xE_~1j1^E@QF)/)8)  k;F}& l);g*^ZrSwxy굈D~k$yz̟z-:Zt*Vfi עSEB)96kL*[E֗N-1m7Z_RD:҅}V`;!Kn{))Dٗq5OY L]staI5u*![ED-[]vϷtiqB$2ׂv]Ȗ-ݤ~W [XcR}Q+>i8mw$xgv2RkZJ!r#[Ԩ'Y&Ⱥ" staIUVV( l%ɤ5lOS Op9^V'0r[vc^Г<_M 5l-WP'(#a[XcR5~*[tNPG#{ e`PvƤ4y Dl OWi= l׋>S҅5&wWc}d_ݤ(O4zd/aeԲ5&^Z4bN)3!uGB-^d 8&G 4zda&D:q~̻ `VB^eKzSĈn`'"<5&]ݾ#[nؔ`dnM=M)>  JstaIx m֗J焞lj^*^*o//]XcR}6BKLԣ*ttlxKج0Le/֗-]?NחRFVUۥ|d+rOVEYa8g҅5&Q]Q]$עLvxZr>{(KQ$}w`EY?Qʒ kLTۥ|L $P2Ro,9*ttf ({[fX9*t & 8(E,ŗG-nK(JJ-8#KȎ%p["8|&0Hb}$FQ9Q%ɦFF[-͔B(KP\XcRM϶(RT:'*#葽ei}ZjTۥ|d+)46y}5q̔,֤#[( v[CT(R$`mz@ .g)Pfv+Q'x9hҔR|OȪR"NGј`L`u`Ҕ5.giYQ(Rg=}ϔISzƤZC>{II-}K<8]&ˤeR?QI ZUEYJD%y$uKX/ 8#R`m2mY]Gv@/){>._OLKvoY]R/oIdQ}b~v4bKO);!w_ȪRޚEUe)*䉆jnȪR>ө&RdSGVKʒ kM*#KkLlkX)K7H殡mY]$s(KMzƒk=, eɅ&yUۥS霨$dS.{ %am(ʒ (jYQ(Rh=m`;eID(Kxy1[%H@[ GQ}o"ًM^DY"EQ,֤Z4HQ(ReIQ6(KQ$O4%+QTEYJD%y$%%nu—okM5BKye)*Dٗq5rEDP\EIi(Ѝ,Eu"ECY*^^'#a[XcREQtQ}$=װZ_ 6p__/?̷݂N);!~&5K$z$uK e]/=X[]+pGQ}o%0K`p2i _kϔ5жR>&]xI`ImװlMJ$%y,QTDYJJ$%y$l__Aɵ eɅ5&QTDYJ/yz M kϔyW`I~Uv)?Krql:9Dꁄ'^vv|+f})e0gyG.孹;Ijn OkXKQR?IId)K5IT}o$I3-=װI&_\tsaq7z:+)4^PDI L;hOx*>Nv) l18#{ 4|&$x.(T}o1I AzO6[ҲՓ֘jhǩ$RR:')3XgkS& VxZj m8Uۥe`do s}5p̔,֤%Һ=x,%Q$uKXKQR?IId(K.1ж8TDYJ%$=װZ_V x/[ܝMR+pǩ.=!Y/QkaEG@8UߛDYJ,%%mװ$_ }҃&5R}oRtNeIQUT*!\*p</=Xkyǥ .=J$%y$uKX/ +Sd(K.1жK]R0L>DI "HZr(׋znX]LoIkQ}H=i,ջ/Mp+yUjS}\RޚD4 װ, ˕֚tWඏKI$NV׭$O2%֚tжK]G۩%e7KX J$Q lkL5Rne))tʒdSGV, +DI%֚tжK]{:IJH65겗Z_V'RO2-\EqB78 'v$P(]&^4\?.&r|ez&,`(K}5p&$ʒ 8}\jQE"H65겗=^ %! v s`m?x.3EfYgZԭaL%.I0=XkR괳Cx,e%ٳaEYLʒ >ز(KY,ʒdS.{ s}cɵEY%֘TkhY,nQH#{ e`OYwJ/ \wRvB qXKyOEY,"ɦF] VVYl(K.yWඏKU2Y,RVimv Ӕ}5q̔,֤}\*ʢ,es(KM%VYeCYra]Jǩ.=Jd%y$u+XQX9hCP\XcRm;͢,eQXDlxk>._3Lʒ kM*Y-V:M-lfJ6q9x.Mp @;l} S.E47neI_Y eCYraIwn@KyO;YɦF]6$jtP\EWqb!/EYb M\4`=93ekL5`!(RV:'$葽eI_YeC eɅ&zQ-B0x8X9hCٜj m(X8 'v,Px)vtKOc4rrWfrV`g=O V%zpL,֤} K:I65겗z-R*+ɦ 8}?Ձ./dSGVy䁰5)׋Vri@,Aq5,e1r㙵kL5#c!u "eӢn |K,eQ}H=P\Xk]C>2E(3-궰$Dˢx9~RvB |'D,RR.{&:H8M`Ǩ(KH=ɤ5 Lf}ZY,Ngn}\);xE k51t*)#Ԩ^2IJ _9eɃ&@G,Re)EDنU.@,Q(SHKY Tx}%Q>Y|xA-|UjqTHX^1_tPvBG  TS-5mI "RQ:(#Ԩ^$$S]Gv,٤%lOS ד>ST:֘TkhGB|. $Iְl-/9 gkM*ZQ`㽌`e]ƤZC}!إ,ɤx T *e]4!UN]Q.CMI&)$Ԩ^*^T)JCYraI}D-(KE!|$葽2 r<%y9eɅ&zQVDyOM Aq5%S81ж`6Iғ<_Mk>.7O Z,, ei MOL Ey+KO);!b8ū]}#Ԩ^4ע$O1%֘T+pR>Dd]4`>3e(K.5)N=,jQW):eIQMNV(S)K.1ж٥|S$dSGIU(S eɅ&5BP"R eis}5p̔,֤}XTDY*,I65겗,(K%xw-î=QLHZ&=u^QIz- =װz-LE:1Z q`!(RQ:(#Ԩ^1OX}KW eɅ5&q`!/EY*J0 M\4`-2҃&5ㅅ(KE"ʒdS.{ xUAT eɅ&YeBP"nQHQ8axE_,IҶE8 G鮢p񊉗E񖮟\KW);!/b!w(3ɞ'd "Օ3K֚tWඏz$uKXKQ+j mxa!xvHE$葽!mʒ kM* s֔,Sʾ lC=1жo,/9/Pg GtRAT)K.5鮡mX(3-l7 r& N&a`>3eZԹ֤ZC[?R>&)$Ԩ^*^*ou*s*sʒ kM5o ]{:-:"lje`EY`x"Z m{b8 'vSS 3x)vtKOLR[֏"<=u*4ɞ'd {jBNtq'ļyƤz~reT:eI#{ +ʒ`N~N%yNCYraInx?ANsN%y$uKX/ +S_P\XkRm[?^w) lJ0 a;eI^2҃5&ֻСU]R/oIkQ}Nz akMsǡNQEY: ei DX-D9R;cSjV$fτ(#Ԩ2 :ZzwHu)o٢,b g]Ê$_2%֚T[HOQNsN$Ԩ^*^*oussS\Xcz8KLZ ۸VEJ%֚T[֏#It$Ԩ^]MykZ S\XkRm[?P٥|S.dS.{ %` :/|҅5&湦BKY I;tשnuNY://nEKMQNUNHmSkNPd]H ",A֘ZF:ReR:eI#ۃb39Z>zsQ-lj!IX|nDgګHkg$ǘ^oX;u?Ej9Vz[qպE$ iU碚lzd_(6Ugcq*URcqU4=ihmsDBX|8U7zq^uK}ɕWݤ|>Ug~Ս_uk𫯮|5kWy>w 9~袖T?>}ϧߏ|}?M_^wt<_7y^rOB~.3;?ï׽V/+ÍpݼgS_!> Umx :[ĝ'y/L52}(C&x9W_=h_Z+XJҥ?Z 㑪2[M )PU5a2T+Gq $V @hcӸ=v#=NøO5-ɫe 3+v71qp ni*\Eo{{v/ niּ; sFk.|([~BdqKaLk8;AW7sTPo~}s[,D& (ZqDAP<pթ= l # CX^[r"Aʢ&g{? >q^lzK CPR_P`P+FU{5Ag>.b! gA1 eLsvqz#M͘,l%hv/A-\>xa3={Jrqt}-D"~K\9-#2nٲY/[^*KW m@P?x7›]9xo4'Ab)Pl,% r؋\H}@ (R 9eR"a'4vy<¹tG³?-q v7+-؋oyNp˄pta0n&z؋ڃFu!:gv-3yøO\7c;&UXSoQAح8DnsRɱƖB7Oc͏ q}+xėoO( <-ճ+gUD]-p5.6lv .L'k{QL:=FP,xwT25q&z؋JցHmb>F[Vl܂ <閆a/IZpAD=ᖶi+ny+NpOMN󻛫ނӚpW@3;BFwc2{(/ OlhX `_ٞX"Xa/h6.Ş(b# FE ɹ5\{lOR*[^X\x_pKaE΀ ^P[#V[.ɸ-vwK:Tv5qw`/`K.g-TG-^0`OB|nޢEk>z򬮀'ChRG vd̏'gMZZX&A^z9Bźk ƍ2rl+{'+nuW]ͽj[c 02^jO5A۸ Bᖶ[[ --Z#<Ժɦ򅠨~P`P)p`@M=UFPN~6Bl`~a'WmRem{ꭚV6F*%VAȞP*(Θx4j#թƝzzBأ7w #бlKYZ6]d$ʤأ[n#62+BrmA߽jM !4 ɸ &hG[yb[%P;gCnCP鶰FEX<1ڹX:INCu[;bGnԻ|:Dzf~B w/AXJ6= l#vqZkMxvDPT?Il55q&zƸv(N+C!Mrap<@;;l7oWej̀P|$%2ueR`P+Ǝ0pH&zƸvXGN t+Lݨq dt cM lss g[ -s[fe+܌w6 Ezf~AeuxsRG 6nƻ[R"ñLoWOmő?22bFX˘~;lpll)d8iba*#ó b wPx(,ߏa'δwqC Qo~/X 6*<@;-16QݳBog`cozVb[שּ1J[ \qP`u&}-9a++鶮 2]ԍZq 8' lXJvp,{m?ZQ~{w7Pbw7d'zƸNU]gv;(bklFl%Xlѹָic5,(>@;@;0nFY4426Uu˯046.htXgmѹƸ[.JPer-ԏ[9=師B&GXS``܈-C)g^ָ5b-:@=.Z)[P@ dFfacKYZsuq5%4]. ; n,`, 6&'-~epwAE. Q&6XpK smC;F:gv-A`E0enYmQ5gnFAx/~ P*(V:8:ч2}e44:W[pΨ=Ao`E;˘8:Bp]lc\ݾn9 <<B 5>a@/z\bjqP}x TAs:[y,`D-F;lkܽ۞<%4ovʛD4ӌHE$$sm<(ᎠEP"ht4hht;} rlE6A2K O=3?vdDJ)0((RbF`-f)aځmTG1d[-P"4dqvJ #ht4].Y].=j^ּxB w."S(ECakoĆ[ 6&'Gc;FAэ n֖B.hFb>X[3$pG\ E5'z=1p,v[imّPѾ2.l0+wňDcmwFCxt."htR`P+N0X 6]QPAEF总>E袡ѹƸUT %4].F n ]D0"Fb[ QA htvn dquh|BpGBde4􀛰np4p] `L`ŌO(|XcFAHŌxght.1bcBxt=zfFdأnF$"s4tquh|KTG"^FECac)1`-bm7j8;F2娀q5v"4#mhkسqJ#zO-M=v@`E0ڢѹƸBjLPpwA?;pKsl[n F[,66 bzf~FIQu+.AG56ht3v7r ŶݯmPA'.[ccKԹy'W.1b~Bx.FA 9wF$"s\lc\}-{5,J#htDY.4n [44:W_{LB w.FA0nF4Z.m@h(ᎠE"hthht;l\"N8.^6^xwnT\ԗ*PmH8-} hxk1`ȱb.v{O%de 4dht;㈝ahybUU]Э@yOmN&L&\{i\;d.F{2ޓl }(z\&CsWnY_"JPk>#vɑŶƕzQ8;F:gv-Ѵ3іhKCcqb~N ۪gL"x@PlV`KlsϏѹv)qojNDx.F@ 546.ht \24:{hmT'n 4]24vqĆ[Ŗ ŶƝ'9(N%F0nit YF[-\lnr^HD wt 4@(o0w-,`,&[lVVB% 4Pe``n@n# LԳ[.we2".Anֻ[Bdht.,{w*.VAQls XFb[ңQe /Ƴ7H%$$smp> m(Ų2)0(Y6h ,6a]v"Jht 4Lݠ7I&ht\lwm/;F@K%蒡pAK%R+a,UMvSUB+U]Lh_ʃb]%6W&L%R6 fLֶQ@K%$htvXJ `%Csm;F 4:g񪍼k %]mVedأ \64:ײNw:PAe$2ht6ؠэXoŖ Ŷa/ 24:wo_TwA@+` DؠP Peht.1TwAq4لbl\ hɹbht.11[^%4& htvpc~tqdW4p N+8nT$xFWr~tq ٵbGBA+FN+`0J0+?6 Ezv~*%Q6q Ƴ7eJ#¼pqV4TwAE Q&K[15]lc\j:U4b)1(`<{(4 h4:aUU4FW@+dpA+`0ڊѹƸFE|%]N(c8`Vb[%? $J4awVh+\ۤ*˜gnȴ U]Э` L>1?XNc͏Yzسql|KT ht4y)FW@+Csqu!5% htDYn62+ Ŷ]X#tdFfa+oR,H芡ѹƸPLЮA4`146.ht4RsuqqcF ]14=v7nKX܂w6_SOkr]^ IAG 6V6;Xl+\W_[Scʢ FW@+ԍ ^cFW,H芡ѹָwm /w7df' Z?X6Ƶ#{ %]N(c8b-ӑ6Ƶ<* .g'tOmxV.qq ZB wz-/[́FW:+`K6 Ezf~A{{ m@Plaa#F;lkܽOBxn4ttgJ]ZKKK]_R\"U/-ٚj嗸+/-5T}%OZ/3^voknvqkד:Am1J;軖|Mg=,_s/9Y&_qV3/8B+_LpVsݒ3g}@gϪLo?{Q[-~rO85嚠3wg(O_~~ZjVe!RkUo_\j*&/淿W|_p{W]^\"/o/RwL=K+3|/kۻuπ?-)jQ^3{qnkoӮ3oiSz(W6~;[v9~gѸ蚷j:|5pJV:͝ny-MdWE*ˑ4)v/7`#ZV ta[;/"I=?B#tP+0Ƹ\K%V B0`_٪=5qFlkyQ/򔠏q*T]hO˴aT-2+\v{E*ϕŀ;8b-”ٹָ5>KN8aw xa30xƸ/ pKӛbݿENĚ {*f3Y/Գs ZD,%"&l\- 1m{v{`_0 X&zָȕ8ZQ !(lTar˄`0gz»Ƹb]56VpL0+\ۺ`1~%g#tnns} nmRe\,sQB-ó3bΞP*(Θxs.Xcm "%6AQlP`PQ`z.pB26r~ѩL[U[´am[xE)R.5.y%%Vo~A(,X<5q6մu(i1~ ߟ=%z]a\ Sfb[ŋ.tߟ=y}b;`cqbqڀ{mp0K O=;?߈8XRLAKcS=qF\}$~H(ֳا~'55qf)ak5 'A.EAAIB&LOx{i\W? x!^X\&n7`-/x)sW"t+x?(rK[ u cM ʸ JG*Ao^* Gq'4[I*<۸By;l\aHν^;`k H=-[xgO`gGl ^2oʸV/섎c8[n'8&o wzu[O+Gn nj.ʸV- +Zqh{e\#3tK~vB|b71qpp ؾqʸF@+-WBᖦ7[;-Qm'r~ϬF@#tPlV w–#ʸZIQJ%'B#FGؤa M ¸PwԲη[B0vs>@;a[{e\fnuAq^z¸g9H/yWƵ> (>L݁D𰵍7bG -*GqDAVt+2uuɁ,aht.ҸE!uththtmO|sZ=/pqW՜[]|%?c݄C0D+JAait ㈍aitʸ[htht2u+/%yx cM*+jҭ.chthtR`PlRFE4:{a\;b .nhthtm#6Scvwˀ`_Xgn wXq[O+(n.ֻ0citʸʐ)(n.b6.htGR""Y2u{vAb6V4:{e\}5/(:@;@;4 &hhty+yA݁aitl\dLpKKWƵw(~vBi>6mGv('pw[O_P}T2 p,^Z (F7*.htG.X#ʸ|txg!;xXnHn(WƵWnF"g[xy+ZInuA?;7nY rv+j)CAV ,+M؀{bKaB|nj~jDVDP<'M x'VϮa^W'J{v. ],%\lp'lJ9;`/kG(:@;Nl)]6+bcKԹ [.V#ʸvvt ݁ p<@;;V4{e\};;X\lMl%XlNJF7b [hththt+7.|cM m VTj̉ҭ.VJ%''J[XV <ֻ[@0 "2.jFq5?st 旾!niN`'U" @ HI{e\W}U. S( х wz,э CBV.F@Xbʛht4lE6v˶[O xvƻ[RbP`vƻ[R4dWUr.F@ хfY@0  +݈4N> A1 Dp #62+V4{e\=mxVg%htQ[:ؠdht4эKnP.F@ хF.d@ǰэ+jpx(p˥P{r- DI`KapXpGS_=!y8Bf,6zOPqzO:+jZ @PlV7ƻs}(Én^Wub)].f0DpA ''W4{e\-YO2u2)0(6)`F7b-/xŊF7b/. S7*rK[Y].ht#Ҹ!qZ(rE[`ÒF[Nk'gB|nj~jvAo"mцg[]."+݈qGwA?B#j-|㈝`hU?[v B0lGlE4ӌ`E0 s$G\ `jc"'u_ǀ{mq[,!oq{rݍ`n^xݙ#~vBn ]-_&Fۤ VwPo};.v٬6.mX aFAHE$碥yָר|> [N u[4:W{-5P.F0Ɩ ]4:{65A%"NFCa#" :n9\W*)pKd"eR`PQ` ,2p]lc\ێCN:'- 9m6d6v=23\UT'L}s[+㉠v٨`FACѾ2=ڒJJޓvYDhzOpAHE$碡ѹƸ6 }{vF,e4'wxw E3ѹƸn,qv"-pA9O%HE smQd@E"vțF:`ECsq FV [ne` wpvO[s[*,%pΛ= lv.}ӱ楄mkԍ^*|j)AXW`-]B0!X\lkܽ*ve]m\`+&dht 4dht.1m_׉[&Pht 4dht;4Waz%ht 4ACakK!Fp0\p\q58 -Bᖦsh{2#<B|nHh_2ߞP*XbRB0a/D> [n0>` cm[b\b'ht 4QձV:8F@K%CsW=o'0A4]246. @^w}fDp`%CsgBe5^ Z8cwit F[Nk/@noG΃ KJ%/þ0?X""ˬp=՗\B.cht 4 fF.!KFb[Xӆ'^&L%Cac)1`pK0\lk\>6HIvA?;x6n4F[-mi7( 'B{2ޓ{́F:K`%Csq7)K(~vBᖦ[lMm zf~*'-o4APLB6e(Ŷq7Jht)#(]6+0it ԹZp,smlPBq4WtU(iKBG 62VH%$$smBD\4L]B,F n]``%CsqF H.F@0n.FhK`%Csqy|-q-v@K`%0Rdx"N=3?D;]ot\^#8>${dS#_6aǤ6ʺ( ?cpcnswOǓ6#3!EH|ل-2 ;%M؋ԭqWGU#[| 0l3%a;_Ll<_2)H`Flx)7%{e$}^Y^8aL/n`sg+ S`{]xÝIx= k>3K֙P`;YB6`/;+IB?[滿S lG Q`;# xaX$u_e$twA˦Fl>? }yKz>HlmP` A_pgaCw00l3~7N%+B@K$e& Z _eŤ#AFlž2IQޤ9/pnLa#af*]ޭtˣ\'ח"H6*rlM|u>ѣ؋zܽ$rBl^zH\g\Dn^IEIKVytMؚ"rx)IΔVkG*=+\D/)%=/xULZ'g9^}\z/xl3r%(/[KS4e9U.V 5Z֗c$/.%"4rۢrl/a__Fe>R>&)|لU,z-*Zj`/;$\S|)T`+E ȗM$++// Oh}Iٿ8aO9= %^erST^Q'm&w)Y# 5!Y&gB~٣ѳ]ǤK/G 4Zo~ K.svp!=I65e/X9<$mw)Ia3}\a~}˜ܥ|L:%@9#o/[!;x2e9i;KY ؎K0ܘ44` {>3/Y]$sBO|I65e +(䑰-o&.=J%y$-d6$j)$`1I]G<] A>^= _a~}˜ܥM(OYI#_6`eԲ5&^Z42RL6zFl&MVQ3u1Gܥ|SxJ%UDVvԷ liJRm//Y]$lj&V!//˜ܥ|SMIɦFlX9^җ~eR޲[әq؊֗P;^QV'->^2mw)E4eVjE"+rW+e.R~xǛ`{J6t ~}YG]ܥ'D ŽR#_6a` a/_ 6O"%f;"ey g]c^pH &h-KE[~<$l- bI65eVk*Έ~,2l_zP/ÝIls< b_(K/(ǻ~q :9v-_x=.=LȗM/JpI}3KL)H{ʤ](Re)*4ޙXQOT'xP_vOmw) 7x)7OI e..3Y^{`LOI e.)E4;{z"EQˣ f%H@[~m&w)Qp7!E}5 6!(RT:'$ȗMآoh:EYPο2,Š/EYPr}a/Ͽ2R>ؔ`dxy}5 6SPο2R~xǛ`oIkQ}H=$mw)?KrMI(}wTnP;/G}j3KyO;Q FlF4>A//{ԧ6(KQ(R,{ga`=3S˿2R&%-6)^&-[JH7vpe)*lj X/ 8#R`&]R>j}Ix9qzg/̗@9^; |KZ'keg[滿b/{ԗ6Dz/VROT'BYG}i3KLH=M%auu~,]eܥ|dH A/nKX)K/|i;KytNeI/= 7\[I e..=JD%y$-dVKj) Ptevpe)"dkNY?Q(R,&^z-5E V_&D]G^"dⶄk(KQ(Rtefre)EYlj&DYJD%y//EYJD%y$ {$[]/|a;㉲`#rED] ,Eu"_(KZEQ}H={b^hanydԁ./dS[VK+}˟es -2I ;I F5lI.JBM`Ihv>nDYJ" l 2 ʳI1 'E&]xI`ImװlMJ$%yDYZZԕ|-RR:')#Ԩ^d\{,-`I'楗<]=a6i s} glkLBIo!P2}NN$z ቗dnJbpB.{ Y$H`umװE&u$٤2vp-RVimo +ʒ`=aMOI!,I65j7= 7\[ח.ʤO$eqXDM&lI=e) sjp7r HR LwB}(E$hmaEY`Ewa&GO嶢,e% `{R₩af.ʤ/=N2IM%ɦFlVRynuY}1Kve}([؂!;>? r<ц l2#=ɖ㉲"dρ}56Sa/G؅IwϔIvI@0?Ϸ5Sr<-_)dzn$دpYmr\veg-:Y,RdSIe`T_r]dQR, {/=؞0|fj/_>QEYJdQ$M-(K:(A}3'r@9^Z81 r<цtve}8]|x+ )Kn/[:iGv,sz=NExT)JH65eVyV_b(K./&y/EY*J0 riJZ3SxGO"ʒdS#WxUAT eɅŤO=x-RE$ȗMXVuP\_LΤ 9*jWxYny21뚋QKY ,na+'j8 w&Mt))i(K.ޤo=QO[ u{-tssx2u/yք(3h 4!w)))R`[}}9Vvq$0I`;kmL:֚TN\xd9EYlje/a/:99ʒkLe[Pe鴔%+vƤè+[8Gt))L;hOL2ro׻m{:Ti=NԄ2τ"֘cSS%ɦF%(K:&^%/dעSSIɦFMVKԗ4%֘tʖ㉲t*4Ȟo)K}L҅5&T'W6(NjaoIkQ}Nz akLtwe(i(K{fa(K[=?] 9Nxz T`GQ=e`uu eɅ5&-In+) {v5(K}m eɅ5&}VҾC&)%ɦF5V>H=g kLFЩtΩ$dSGVKD9/]Xcx=u*46-zWAvI˖- ei۾%QNQ}NzbekooRfB#\}G#{ x)ҩϩ$i(K.1i<-NwNz$=, 9 eɅ5&-ǧV,J0 ۮaZ,ѩya9Mt_vIt$Ԩ]MySSI\Xcg3ŗ}bI65zdaD/^_Ƥh9:խ)Ke h)JiܹJ Y>Ex:/Aq5^t ))`ggڗݙ#wG~2yFDz'E/_O{]v_,_/B?E׋>5zQp"䰾]"^_dE,o׋2E_w~>}ޏ< ^w|/~ݻ￿#sIЍ7'I~h~߯׽޻gu17ؽs>,_PnȺnvk ~^wUofHUD4%KS*cWUy]W:%wAg0k?whA{aȻx}:uimKm}jƞ&}ƪA[X!Cz![Bq3nrdi?w.ҸpG^Im\ >ag|sjŶƝ.R g Bfݽþ`_:봎^w'R? Y 5c8%{8nomUPo~tճK}V }~ O(|`Oq83Lث/H 2NVu܅0nKWo2\.Ҹ á%3*ת.%CMWvqĆ[ Ge$V Ch8݀agʺ^9ĭ2s|^1tKEfAAI7wiA6xuAUX?B:>d܀ <Ǽ]oKKQo5?uEO.Wݲؤ]`O 2E`.]) bsƭ÷~<3q\{e\u6t؋ؤb+`M٦s{{vnZƞɺ0Xo[sMEuq^i4J%c\o!3'_"VnѮp{ݘs"N=3?@%El0FfW0aFux{vPmd 6Npxg\lk\ nn,!B !LXJ83Ͱ]q g[&koNUoW[&)|s?6:Ƹ|D1_=TQ`]Pzv ʸO|D%A-pM xxw-غ0ݴ]lkQ/D~DAmoP`a+S!8g2f2ߌ A`-M6n[tKp=qIsYC x"ȞpK8a < '!̻oE@>?x:#tPQ`wc:6{iQ³OlhX `_ٞX"Xfa[n_5~_xw{ u@{!9LWjZ[^X\x_pKӣaE΀ ^w/ѷW~vBo{>qfa[^7W}.~B5 l7>xrˆ=?mp;s=G =TlVΘ ʸ{6Q=ԽAIqv7rluqA9C'Ѿב Nk ƭ_Ra?2^WS'j nZ [&;lm)^KeVҸ_[Փ 8@|:LqwZp/> +x2n`~qLa}ۺp,Uo9?wRS @P<'J 8o}~Lmqfwl.7twB bߜݎGt,a[wfqč}f2)0(XcmĆ[xExl[}wTn"F x4nɁ,p=l[~5mxK!(pKa,&x .1+ `wވ#G7F"K W=o3'4٠soc,%B6XJ eؖQkbyA1³#zzO `+,߯q'n.1*nBPL/섀,ځa:ƸJ9pKd$ʤأ;8b-"6?j)è2!("S7*0[[ Gq9ƸB}R [mG[f,>2 niGl32Vnٮp3 vY۽tp³OJ%6xw;8X^)\ti $w7bw7d'3ؖ^tkƨݐ;(bklFl%Xlѹؖ(dF[n7A04:W+C[[FwFwFw4\l۩}[-/{nzױn65`ڞ@.;.u:((N0nRμu^~Qyv.Fga-F@ Csq5j&cT@K].F n ].F@ FbZ>ͼᨀJDY.;8b-_ CsqY1pK2u-7ʛdht4:aN6.l0L6.ht \04:{Q@ 83#6e{vt'Rͬ A ԍ `cKYZ&z؋E`ɧAht4`046.F[04:wUE?*D. Q&źklpl%Xl^;*\ ޻ qK"mpAV35U#p\O=;?wX L 4xBdW`tpu.eDhht.}RQ:d-]{2ޓ;o.c&z؋6UHIAqO>a@/z\b۝h,=&([^e9!yID0"A  d7h@HI{i\};P)f-F'f} rlE6A2K Own@3>Bջ7]l-%Flvآ9IŶqG:K0'jE sH亦0A4]446.1-\lkܽm'( %2u2)0(XckoĆ[ 63=Ze#4]nT`v"htF[44:w/)ƭ"ޓ`oNޓc6Ez\w?EL6.ht1b)XFb/9+jAuIAN0X Ŷ%]1* ]nT D0.F ^4ĨX4].4,`D-"9 ŶSwX׎ 3&~ ECaGl%Xlö/ԥH -Bdq˄ ht4:7a;Uc%S㩷(kH63b>vQ`2n-PӬp=|v&qэj 6. \44:UTM -HE袡mA`ECsq5bդ4ݨq 6&E$"ht\|è4]Dv04"N ݆ۮqU5nzv~j8n ZJ$˖V^4L5vrXۼyؖFW!B*wL]B,F;8bg!=GlE(\yOƭN&L&=lk\e|B4]BdzOnAK&Lq ŶW=H۵]R(erݍ#vɑ^P{EHVBdqK4L`%0XAӁB9.3 L.:gmI!@7A4PCa#F@KH%Csϓ+ R-F@KF.0pKؒѹضBK֋p:S. 8[cm)c?LqZ"cWqB"p7RH&m^t[.- n``n@o#\0SֿU?PPe:((nֻ[Bdht.5 (.]6*`<{tpu.!"\E"e /Ƴ7H%$$smtXV#Q&źk  dq'Wh̟@K%d nIB0F@KFb/F Dht 4dht;l\ht 4lEswU=~<\ MXJ}eBV ,Ѿ2}e.FYJxض7J DY.K,dht.ҸfP].!S7*`<{tpB0F@KFb[bE:|6e%"ht 4dht;l\dht-MqXS4[.F n- 'ѹؿcpi3n~4K8rzřo涮*˜gGEc^Aо2`YbF@K8-p,Cs9].Fp{`#F@K%Csqŋ~]-F'źklplŖ ŶƩSѠGht 4Lݨ\͹þH%蒡ѹ؋~ѥ dVya]N2ָt -BᖆF v7pK  emAz6AuߎA ;F7beömCY)2#S7*02 d=>%)]&0x;K9s m:[g] 'jr}8`і_ :öƥ8/Jc/;]AM(pA+H$犡Ѹ<\$TeA]14vq>a(0o1V"_jP7NK1wOJ[J/F ]14_o m%n6Ezv~Έ>@>?xܣ}h v`p`1n_ л[A Q&K[15]lk\Axv Ġ Z4`b]m"htA(+0`#FW:+`CsqjwA?;pK{nh+plqP -WBdqK mlYUc3\~So (bpqqB. ht4hYJA+ ht\ٸE T+H芡6`-3\q yPn ]AnT`v&YZmsLDP ;X n ]p]lk^(%n)4bht`? x apnp/pŜ檷Uw3 yb6V6;Xl+\WMFW0 X@+ApQe9`146LdAbkָ_E:. [ޓ`w j3_t_/|l.҇w]Nj\TKbv>HEoû(?:g!g^;3~z}W{N]mk|Ss>׼qS+W¸Mz4y횄{5ƹ|IRu{=C4M*۫6j-|Y iBi݅* Un̮ir͇S^.T]1 」eee[8\B1ۅA.`kB1ۅEEeNctr\S ¸ B}vQ뢰?xpK,/SfDp.,/`0cߪJ.Ǽ. => HR[8:qbǹy]c[0H>?B'J 8S`4c:ΒI <ƩP*Xb _ 9xE?8@hpM xMP1 ?-ve\ $TO>q&i84jDfܩ;ܿ8NUny (ad܀hy X6m&y}~2fGجa8)fw͎lqZ񟍻U1q8qDU1Nju ikCߜَ p`V;Y+ 7-u5vqĆ[x)q>TSn:G؏[ub)1(`<{}g{b)q^OYJxثVXMUźK BšB3=]a#3⅀{a-s6ހ ʄgu56.}LWer˗ [k엺=#|}ǹ@|nr~*AI>? B' 8 0?r2MWՋ1(wqa } rlog'|w8q ߏqL o{T!T ioVek~p)/^-3D3#6xJG\ 6[ :q'o zWS)gGRY[`ac.ʸF^-P*6)a|sGGcS]湨7 XJo`5vRb[xEaR =dM8sJ2z0n%7us ׈7`/hOAJ(#G7"η0=]~+-D˜b  p=!`3+xvE0+\{i9#A@ ޓ;l}( niht.5.p˥P= ͡f,LcMW ]\ 0=v7 9 mf)g.CeD $tP+nĆ#p,Csqw<4v٨ ԹZ8XFbZf6F2CP FAEdpA`E0ڢѹָ}]uY M0t`w -p|:p]n <3"yAG56|bq~wsq(v2iW}ɸ5݄{Ŷ}A坦 `)]N uV=1mG=}btWnDYDhzO%6PD06"lѸ=hSęƚ.5.pN~vBIf~EXg67t"N=;?.cmцs ]."FbbB> [N [44:Wk쟋pzU.F0Ɩ ]44:xSn"vFb[ai%E}fD{`c;`-b5.aWГ5F:'؏[Fh`b.jmX{d4gik!RFGDPlT,%ؠEP"PFFb[آ>MIDz[,d4'wE$"s\lcӂ^rBt.HIAG 6Cit.5`}m8."S7*`[bɎZ.\lk\R.!@E"vțF:`ECsgb.<p˥P5/8b-h |:p]F"=RIXW`ht雎5/%\lk\m.†V.Fvآ%dh[ 6Ƶ^O*+a\`+&dht 4dht.1r6 4[.F n}8`F^9ָtQ$? F@K [[ 4KFb[3.žFBɵP= ͡fBɄ֏en6Ezf~Zn賿(CJ؇3wָᵿ .n 4xq04@ /?F@Kэ ̬ 4].mkź"@K%htv tKp=lc\O#'"S(blpGl%Xl\lk\E yhtkx2n%NK`%0p]Ș@|p[v^x)\zyB`Zt,q)"tA@K%dXW` ]p24:P#}f /MJA1_KPt"e:(6< MPʱ^-% <.3 K %Ph)ñit.]qj@8BqH[Bv[ g$sŶƝTEx.!S(K%CaGl%Xl\ջI($F@Kэ \cF@K`%0ڒѹث-v4 r)nY[o4Y-p;Y͹@|n y6`sR9=T֭,`.FywW{u3;|j$%de 4dhtlF7b{2\Uv] AKԍ `+,8~&\UҬ] -AK%LY> =.ѹث\sP9/8`FbKRpn)t-9=fnbS2`OEqQ;9t+.EˌlO9h\EM`ZJd2ht A(694 ]F-#9 ŶDž>tWe$ʤX/']cGG C3Vv x4n-,`-іit.΋!Ϡe% `q5K[ Y YM2ؖr(@R(~;|[˜檷`=}bt!c~N=!4c~goOG ± ^D]٠eFQ4 \F-p,CsVYT\vAq`edأ4ZFr./ E HIAG vq>a(ߜFb/<!AˠeF ~}--m`/z*y Jh[{.uhܠt@|nޢUUvA x܇ b24 dn'Ejf22u ]64 6ht#6!± ^}.O]Э@8`+,8~&.8{SnAbM6.ht F[64:{.g'Kl{nq0\N#g8_Ξ]F<c?nfe 8Uc3<+#}eNxħJ%6'Av1x؋3ͮ(* qeFC瀻.FAˠe{8%4L]F,F n`-mOȬ/0E*Ƞe22uد &Y24:{65o߁.6A4:)0(a#" A˅n9\WS"ɠ-F Ǹn d[/:6Zw+f,&WV݁Cuc$@z?R@)06$߂|g|s3s]0w-70Fb-mʪ%I\^5 ]5D2 ]F-CF6]k쟋K.c˼a`626nL3CuhfcM8w=CR{vuK(ڲѹؽs~d+V7Uόk7a7mygX8w^/J˽ϓ.Cuh˻M6" % oP>C6.dt>OӞa[-t ]F.P:گtKc\윰mD+sѵFyW7ע_%\tmȷůifCPy.U>4z/y.rrtWk /<ݏھ_/ڙs?mݻ-ZGU)Inڽ\t޾^[#Һ̷?ݯ^:+o_pu۟<].ܯ]O(hxeC++kWV-i{-/|.H.~$Eg 2ZsjB;]cb 9ss_~\ןZP7]s~+Pn\ۆsg۶[l|Hx\Â+ÃHl3?4 Uhޣzw\ 6!0ufW fOHf'ջy3ɥs. kMw†+M)`.,KYY/Ys[جS ]Wɦ#w,Gw"EGr®'_ga.5C8; w^EX ܲp[ <~S {?~-}QFQǛ\v`}rpC\ښ!eaG.=V|]:֋݄G!(l-@׺,bPT)ХrM s·۝KaR[FaXޢe;rZbEdfƦx׭i>=5ʗ ХsÂSb[v*Q9^{jUQl`G.]B/xWުĶ*_ uxZ]"lwI &_>1; :1j!b'.yXQb[%E[`7yYGt8XA-E5M%|^uiwOQl`agIk>( Bd^|Y4lxo/[ءKv)6%MIrSm`5$oL4--Jr6F:Z P04-44-ڔA`5-"2Ӣvҹ})l7}4$(lؽ7/w|zj0laG.]kyx&uI圵y^E|Q }/[ءK? iW x(|%*bC5ŭM%<`Ž\@ :nzJ&_[_5kٚ&Ε<0;綰Y!3ؑK8H+ѝwKH:nvKU',Ql`.yͽ(lU5{[54ͻQl`.vSYx(:K"Ȧ#n)l,Gwn"D[FnrIo/ءK"]_+gD5}\;tWXCӼ{j5r>:ʗQeJlkva\fubUP<$]DvZ.)\X *vr9oowT7-zVa봨U`= Vr+pޥ1l4K` rI*0{ [zJ4wɃO΅^/*ң"=g%Za5$QChe\uw{ ׾C<Rs)qgk>&KHZ%_ƥ.{6C _V}.s[zǭJlYoK&Y2kؚxYM|cn~hfkQz:Jl99*_fM^Y|ڍ*95-JlY2kjZDX 5B'҅il[a[؊Ɨv [jR߿MKvz oWV5H(z|Y4lU'#)`suf]慢H/,zǰEX^/wɃMt;nO6[O)ok|zsM۾MK(Y;(h-ۖBpakR![/]X-ڹ `=qI8jZU:[wa؝Ď["s=Տ/]X%T?7ܷK*DIޥ!$K}E~؞[rNTGܴX_ƥ{ q#$Y7-zǰRF $Kq1rӢ斵i5t==>95((BdVc:-KS:%MaK6⎻N9QEqӢ{ [`%k?ta{C~ ];n$KQ1$KumwO>_ƥkoǭS9'J$nZpa/UAxϗ.qR[t /7}\O`K8q#|¶ٺ4}Oy_(Ql$KRIc/]LܣcufkO1*Is2eJw>_ƥk\~\Rb..a/%Y[|MΝ:CLJlI2jMaƗUq} Ҝ[T`jMa|\߿yT2҃]:υ5T9'"Kܴf=% [%l k\:x>/7}\D1/ˬ|K(!ҜSZ^O_Be3zDH1ƗմHE|yMǭd)Jp2`ݚS}taK׷p.nW9'fMT`EV"խJ? %ֺt~9nO在"iQa5P'ۖ ;zJGvzQKU`jkiOOKe,,EI$KE5臰ʗ,E $K|iZ[y۷y(!Z5}iZ$9,CXM$YEIֿ]AD%YEM5OXedyf^q*FSk,EI L 1SnuqG|Ze~x*DIM*VRu(O'&_zG$Yځ.j_:qӢvj>NXD= Z~ d)Jl67|\%m ϗ?> QCzKww^I!l 4Io/="`uI$QiQ;\`RVO1|Z ytn]wrH%M*vKU'ȓ&_zvz̨)I$YJ*0,MadI߿ybk]:CNfayd)i(U`Jdi [jb)bjC2Y+gH[LMa+QZߖ˪2{5K(!Wy6U!$zDH1lKV'&_z֥slwU;006Υ!l 42yv/U2IrNEiQU΃!/֥p+$KIڢ$iQjAXD=H\Xҹz#`e f <ݕ JR%#Yraγ&mQ7"TxS)qr'IԓɗUdn~K(!n|,_ˣ[ !,CX˨a ֺt&\̷rtƗ4 Ɨ ;(aK-T`[ưOiXx&_z֥s7s!x˝x*$IM*VRuOR'ɒ kknK$KIڢ$iQ-ra5$OEd$K.uMI$R67KR%)R2R>IR63jP/vdYӢ:0-d{eM$J,lk\vVrNdIܴ&=% [3H\XR'fuܚT7-CX/R7҃TZd)Dbo [ 42%ֺt.j̢-F bo {?%m$Iak]:uYYY>CB}*&_Na˻2|Y@g$רͬ*,|'I#BZ.r`%Yao`$K.uMx3$KiSbےCdi4O:ɗ]x*fv;\׉CIUCXKTI*Kֺtw$ITI*UNYj`g$Iɗ`Iyfǭ|k>SmVqUBI k\vnIF <#Y>OI] l/[_e;㝧TvWh|'KXnv%Y+UFwfRY>_$$oc$]ɗu:_*]DXDfN42KJ=Xҹn,_Tɒ,U$K}e~_fmpܲ>ҿ]llVYU[R5}؎a%YkӼ;J.UP߼;d3҃.E H%;#Yj>i19.mT,R|'Kxׯj|IX.V'QOMܕ/[K(!#s}:lr`+_[3rld3Xw:]rE"RQv[%K55ͫ,%6jZ+ڢS$Y7-zǰYO)61l5;+z֥Ah9><]7ygo %. ϗ.ui 蠝vΥxHAT  s +gHROI"O4io~ͻF)H_^+rwD=ʾ1$K}~=enYxJl:eIܴra/U*3҃5.AtDq۝*yM1l_6 uE"QiQ*_JTT)*#YraKFlYUrt*U!lK-N9˜nsve9*05&_a7*I,֥\I$KE%qӢ=~ڒ,#Yra1 ڼ"mQHܴj|IX $*Kmpܢ)IP1ܹF7׼N17-zǰzV:5,I L6 l-S 42%֞:5rNdIܴ*_nU$*,#YraK͢#Q%Y**yM1&+R)x}taa7\Q$KE"di$KEzT)K{$;u#B٢n{?%mW!\6q|(!ͪU2EwD=&lǰʗ,VW6N/]X{8+Μ=,|H#nZpa5-"ڗS=ekOc鎟7$Y**IM1VECTdɅ.5ucaͽ+|].V'P1,ƥ(j,fEO$Kv۴/i=r E1%ָ~Ta|mui {ڤ ڤ ڌdɅ5.5_oڢn@(AfOIMRMH\XR *us%fy-Ó/?~-zk~k*DztD="E{˥ &_zƥ ٛ$K۪&QOݺ4]|\߿yjk\j>4A.%&*Wc:K"fsaK8ݧYAQYTbSGܴX<,%v\ŭdi67dI߿y,֥9D *gH &Sdigg &_Vu/=i9V'C6nfOMC:SB?-raKMb&ҦrΦ"iQJqȳɒ k\j>cídiSv[˔57ͻdɅ5.5r<,ܴEݦr&ɒi=UTj 3%ֺ/E* )` $ ָ| Mal]ށ6 6)Ftݭ|wc_Qk5tH];i'C$n7ͧCL`Kȉ$K$KE{+ɒ`_J?<,ƥFu~hyrdS9gSGܴj>NXq$)K.q5y/uҦSmVqU6)6)6sʒ k]jtMZ[rV4Ul|\uMRMMaKIBMH氏KUƓg+&_Kޢ׼́FQC:U"5-|gGܴj|IXMTٌdɅ5." *˗[MۄV%T6,%cí׼9NY7-CXMT679eɅ.be9S"iQa5Pd3XR#ڎHM`wDێ3Kֺ3"T$Yڴ[ݦ}Kmpܒcy{FRuNE8?k?k|]"ɑN4մH3mm)l ;t<BM]EIN4q_G'l2ٟyRy\t.K9]冓"g]tyE0\릧?//ً@<l؋E'"gG-Eqk3"xo."Dl."i+ R)^N*W"9_E7nOf.?V E>>[ً ?.H/sF:^UWoc}|[;e˩Nv7_˹1u)U;ZR u7C f9`X4B/r~N[j9^FƧ~w_b]mվ޸8? A 4u>dhC]!%3.캾k~[t'ӹUu9vГ o;'; kn E vsFXn15]9V_Ettֶ}aYa"ծ#L3&U3`}?9wEI?mEy?*x47.蟂{4Gkh$mYjW " Qm Ti@iҶ}젰ZeYb~:n% 1aMW",QXzO. r%ǬEDt.<ư{s^+bps1`EXje~Hi: K{UXjy׷qkLoK05QmuE5": @R:΀P.$uk۵F :cK@RԱ017b$\V0J йe$6`6 )$܀aEE#E `;i $E %\;+,y(mv(6C59~ 9'!0U6#Z҃B;tnhG pbpғq8a6F=vu<`[gq[s7a];n4hG; 213^) asZSu+)2Np˄֓ Gz I10 K{SX&$q`K{o@FXH32r`(sHiXo.OӞazm+ư`c? F-й,WXVF8ؘ$qep[so3A6bI P;lu[0,˂,bIt%bA-2 K#\boˍQ1H-йՌB7冤!Ҁmܐ̷жl0wo"ܭ5o?Qo s-{43mm+m`bm Pb(T'€ư6Q@[v`brs7Td@cXon(6#箣w[;f~;11Kۮ7CV|GXI(,igؾsu5 D15۹;Ԅ[F 1Jy9BggvivHz :(yF :! #{} =R`듂vQmG!M=z˪N%a+/ h+sb =ڕaNpQF ȹcEY&QNug(,=lMn۵F :uZR>w%䴭\C%ܺsxnfްsMV@(=l$4ȹCKVӀgJ݊BY(= 50FsەBy";, ܭ1 =mEpEm ˰4 ]ʭ @X v+)l0VdEpEmEqn 8`RwST5aJ݊B h 0h]1x ]lWvkz0vι)v K lڶkqsAD %Su+3Rh``?14y4I1m?c6v]-v P"")UF W[~ ٞv87`2FmM;leBT]lW[1X @X&$ETZyO +kmdm纪a5a6 h { `# &eBX&p=lwvj2cOK';c`#,3"nFo#\0 3nWq.=*j )6=L1wk1,n/nZ @dg$Ōnc >qF#=L\Sp.h5CXe7}c$܂3 h+sv7w; @XRP&&`cQ%yֹs 7Z$<9 B1('تֶkYm7:hQ ~ TWs {ǓyCXn K;­;f5 8?φ=R0m0eCXd[.7@z2V cc(`3.,/T @…nE58ĆnEpEmn5[vͳ-KVVTW  U22um7H=+现KHVVVs l厨0{ֹZ9Y5a9"ڝsSJA[_q&$noMJLIAlpΰsWIܢ1:W@ZD6dt2ldtav8p=޹rgxbZ5`sx]v04L (7Gss^`B@$]0ΰ1iQaNus'Mʫ!inc?a-@qR5ljrH4GONTgl­b56"L1w˘AF  8w)x&w5 92ns s7TCf r?wsszP (ɀưǀ 6FF-FE?usqπ.RPLXNU7 qO.ub. rH4~\ 2]( Ŷ-ݘa?s.@C/ @lP5E{#ToI26=L#6aC`]l\Xc ]5D[]Jۮgm֟{Pdt2`LdOpQ (aim;z#*u]MXN1mP$\:w.f;r'TZLXNIUE[ 3lݘac'!{|+,6ۄ[f ^g'$k]%Ұj[ 7BFd֏mmbﬕ GMdO3#6$\:_A:j@ι1Ԑ=eŶ]m'.KĮC`4ϰ5F"sbnI2BFe~2h aG8G Gzֹ].BF/Ŝan!؇2.;:&\l_Z\Xf(gؕJ+#l XMdO5wؾ2BF!Jxؽs59 "dtQ]I2ϰ, !щsmOv]Z.RQ(Es^ {s.FEp]l%jrV\F"dt#anQE袑ѹֹxD6 #dt2].  2Y-mʆv}z%H ?svxp85ϥrWFH"eWh"{9bcXFFb[β)DHѵȞ`k!E袑ѹƹGen2].BFn ].BFŶ]8Yg.RQ(E#`CFbc[42::we2[Hƀ~) [uam*]l%G; ,K#]ES6"3Re1a9Ǯa E[42::w.BJvι)E("m؄ *&z "{CR2i?cdt.uڞ ]0 ݒGJêcl|R0zvy :wmOnW9WwQ(kWsΰ1wkPE#ssV!ETZLX!F"dt\lܵ=)2].:n ]D-86ۓ[[.B!E#ac`cn[s3Ͻ=Z}'̷sd@cX5`p[ĞbKo3wsVX Kҵmw΍JB0ޚFzؽsޞ~J{2AF Kw?a<O.uڞRE.Peza9FX. #ssZW>3Ү97~v&dti9.qvݘ4>O.6l-vp? ċp3lhuNo%:|-A]Я`CF y 8uUf]-AF8jdt3爍@-mC~Ȇ.AF`"{O 2Z.mZsm%FPLFF7it UY-p=l>8ڙ'RP(a爍-~b[V^t!ib?a ]-AіM۪`gcv<?ODR2\B-addt.uN 7J@ޖ.K&  2ZBq.m[޸x*u 2V cg8GleDTlss|}^ `X Ű1{GXbȎZ.3m X].AFPLFF7V$ K%#ssܻW3A K%#ac`c[J6b6$_پ5O0^ R WʀưjWHPlunH`].R`"{rpB0 KFFbP עT"CR.:n*`.AFŶ^cpRfX")P KFF7!KQamC^].AF`dt3l|R.`ᒑѹֹaީ`;$E5{O~6L{2aTl­g9fY0R,`y[D2]o g%#ss؞QO %d@ccs]ؒѹֹa)u BF k 0 wrp. KFFb[bj@sH%TͰpQL(%璑ѹؽsncdtioao2ddt3l|kPsm[1;e吴kwMit E[jN!0o"~g Yo0VR<ۖF> +K۾3l\08c]NV Uðj[s*`F-8ƚ.uapO2 /3̐e#a'8GG x%.qۓ뒫 HKn`k!Par\lʋ?c!)fϓ.CuhFFbPWUCRbr]#6[F ag퟈ad?|P10ƙoq"g2dt2~52 ]F-8ޱ( RƉqe貑Ͱ1mPes=^%N˨Ե` E[6ѹϜ*gBZ|IsAF:Pe#s祅dtcRa [.6$6Uyu" J/Mq=j B]&0bcKl2 {Ja=?l s7Tޓ3lP( s7{rjŢJt:N˨0wuS\6ѹՊ+ilKT2 e21]Qbc`c[62:{z=VW0. Žm΍!˨f2dt\ar ݘ3L#<2dtXܭ-jj?psX(jc(u_%m/F ;rdtEGWoT e;{c]@(P+]Q.§]R`ucl 2]2:(0 ù ܍"Ovv7ktёKH dt2bdtlZl%Tl\lw(\e2 6l 0a9'4 mnX-T'\NnUZ5]lv^tj@(72>lYP@+(Ήs؆FH dt2bdt3 爍mcE1}f]un]}u!DbdޓCR=Yޓ?']@VMUf ^gYC`@.k}0=?=2.~o^YB]A7[]>g~\|+nk$ߋow"e;]^}lEη4]t87)]tǓaEʖu#eӻHu7ukEy$z0jv_לo;?O;Nj*8gן/i:|YٸNimDd6x_suߛ0v5!^8gֵ?^w e'g.{|[MÎv7n8Mw,j3{EmvF1;رEOIa+}11T6rެy |Ǣ vw3>akbG8oNvAnlTNHHc۶;hb7\l[FE\\Xncݎnaoxruڸ:jWlm6]qk>CRkؗsvyrF O]lZԋ2|6UuQ Ŷ{T "{}ׅgmIid-뢶qfQqQ"#ӹ0AON ,grsm׎3dfq;2wE`Em]Զm#~Zv+i}dϰw8XvQm=$ÀuR`a K-j[!B?uZ}E(9$EBau= Wme@XvunHHb}fKG#2)X/τoͱxжkJUS10\l,ȇAR3k@?cA2۵L`QWϰp`n}'Bb`a"@OF[DG&$ń01\̰W9`#, aiz )&p6u <];(D %"bL) p#ӴgƹC*66F:Ds$ 6F=vu<擂;KW>),iHim;铂mԏp]l'0E\tI1aˆba# 8>&,ٻH(ɀư't&6˄{]Ef~adLXNw%y^v8p3Fmew3|Q۵QN0w#l2n9r?wss][t\@b]0zHm{~-(ɀưj``#, b&;3~AX$ETZlc%KImb=a9$EX=*~`'ANAXŞMvm&Ga9"EX=*~`W瀽a-em{ y},~%!)n!m aG8aWG'\:ސj6$mk۵b>z:GDs;O .f  h s655 ,Q[P(alpln7 6a|ۯ npw|R@5O3l|R@pٷ];7a )rv}rPnnsxnf<'N#HGJܼb+ᮐѭ((έFFb/jmn+n+e211`]xLs_lxr;Hwnmsn#,5w[Q@[e6H߀a~HQ\i3l*WTWV96 E]TVd@cc;9b872:8|wh (xr-@F/ŜaKFBFBFBF.66veNv3s0!VӀҥm3Mc~ǜb#{nnnn52vƓ8$_V#s ҊJ݊B jdt3; ,$\|!Dѭ5>,gتѭѭFFb[ i@!)BFBF  25 ?>#ss0(όt8vuaG s؏p]l4_Ctn+e"m #6Fedt.qX2 @dCFB]`"{ Kۮ'\8|1BuJ@FBF'&HѭѭѭFFb幾ѭԭ(ѭFF7x*\s{cbѭԵK1gZ ҶkǙa皅q;ŕ3#EX&s0dl <5f-5fiA~[ o[.k|0J6.dt+ h+sѹv+䷕]$Ed@cc#22:{ڽO_51wC5`Z+ hkaXK0\s05222f@FBuBѶ=rGVCRea9Ůa Ejdt.ȹ吴k nmm-6Bfn{LXfox׼a>l Iq ) pIaC2Ol&z#-9$EZGPba4s. [7p.kWsΰ1%6 hΨ=b;;2ƀ}.6&(ѭFFb&%dt+dt+Ͱp![Q@[Q[8wjmnn526Foٮ<&8@{fިp0Ò!m W8GGx9]@5`.nU.mvy#pbb5 H  %\ ON瀽'°p[s΀aJ]@,``akb#,d02:{.vm fE[0kس pnD(<{%eGtf"('aH-@] C&ؐ hŹ`dt.s%@.a.vsF ,#sG{d W$E0l[}}o۵ 9×ˀ",npQ P(99sKT e213ÎpK99wT{CҮ:7~2E[-p!V3USXap[snȎHP!  FFb;V`(y[,:ޓ3l$\ hŹ`dt.0'Ž׽'R Q( 2'garg97a0C5`pm?/]]@F TͰU7 s\s8R]. # B W!By9 k"d %2n /4l;c(`#Cȹc9Ko"2J]k(=l8Wpk5C dtAb# e\s%*u2`CFb#,b FFb;V ,! ѵ 'Bm8#sGjrH4{OOg=#xj}f ^7I6W 'd(:>)lfiϰgoǀg [q=9ܭhwP\s<!k  %\ldt2]Fb;V6H 肑M! a#,8w{d@cXkn-=r\Uvm׹;P(Bs n[5e|sL.3c#dtҹZ|+ѹ#U+ O uxJ2ZDq.:4he~2hdt3 爽<{\}f]{蜃]RE[\ M0>`!)fϓ.BuhFFbp J",ޓ?sԄ[F 1Hy?"Tp[La~gQnq]\.3LkI!B:gOǙ\a[]-B]:`#g].6g 8"dtBY.Z;9b#d2:{>HqVӀ RpC[*`>1",ᜎ2"dt{OF  U}(cbX>I(3!M4K8`c3ӨDiמ9c?a0-Bp!V3US ̛%u%^HPfCl"sXVFaϝKU9$E"05F….QVFapI2J]D,BFl%Tlё9?313,Qk eO F(baXG߼XhPЂO aY~eO F"mbϝس6BF7&EX21vuKb 6a($95o>8;b[,bh`CFbc'HFbpC ]5ҹZX#]#q^ޓqm hacaȎZDqNSJt.~ (ɀ0߀Z-\s2]1 Q7.BhvD)r~dtE[m­b56"̼A+^0߀s]ÔV={>ƣEG}X&|l %ZG#xC^)K=F2sUόkϜ뱟fi)mvI?mT&޼yd]|]mKJ#kޓ/`ޓ._%:CRqt' 2].2s(&n 2]et爝h<..?AF KԵ9å'cp*dt 2:b# K%_Fcp%ƤK_F7Ʈa [jN!2 W!i}E8YtwH|X?1 "!K5` K(%/CU>F"G2:[s4Tg 6qNع˜c:l(Rz; % oKP>;Fyr>OӞa Ipb\u_9it-6!#it.qm 3>)ր>g h 2:pΰqn7a ].:n*`B-8vO-AF KFF7FXBіŶ'?i吴k7~2E[-p!V3USXOy#=x`J1>6n&dts7۞u+ %Җ KFF7it UZBq.o}WgO p؋>)dT3m6pΰon5*CF7&EXAF:P$ϟܶ}um>d i+ggCA`mv[eH2e_f2"6UЁl2e}dϰUΐep62:8w=~ 8.:&O.(es;z6%~ e貑Ͱw8l(r`T#\8:rDڷ[OXBFhP`.jj*˜gm> CiHic0.CFqmH!ːe貑M!˨f2s\l7]T2 e21IqPe#ssïQ2 ]5$ &2 E[-;z0"'`'!;im\l H)6f؏s 6{OdnBo#\k^?"zCB b[Ɍ+پrn]%O?us}lِescl2dt2 ]62:8z8].  U ].mv[+eT2 e2ldt3lpl%FFbq%"*u}Xΰw%9dt0,bWVgdtCR貑~NPe(rs [s[j~m}PR@_;22 hŹldt.}?hAF!uːe貑M!kPe#s[Gdt_flxFs7lyi?m9v:.,3#EXnsn]9Pe(39wľ-{ )²{'vuP}qx#O~ߋ RD iv`?a ]-Cіwp!V3US3 g;ߋD/HPqI9ӮS|Zs\!;^Ұ΀{dk[79/:?s?ҕg)u;Ez*]tIuO[.i6EO^Y/JWZ\|Iݙ@Muϊp<(9Z]tLy[Dk=E*N:3\#>BOxێ΍L]t/*zuqNW3Αfx.]4Zy 1[eJk@v9qzG¢ $W1?Tro:" "\wv`\lwz"\& wS""LMuɁ5*[|z*\j`.po)=]Cl>%Ž\:4;/y".nZq;R]%s CFr :ˣ:XBZq;E.vwv=H"w \v͇pkK4 v!^RaaہR_,ޢ[Ft;nޒEE[FfXޢe;rxĶ"ܚ+j^ץi>=5ʗ Х*V%Mzn |YaXI I&_>1w43j>ӝIĶueV~61(tAlaG.mOlqԌ[Pܴ㶰_[gf|Ž\:6( ¥i.9^Pi=tpG _zʗ8M  AlaG.G;SEzJu&x0Wka.-}b N/[Fr ۨC:nC]Ql`G.!;%¢ہ4zHz 3xͷ#π-wҴ(54-JbQ:zV:p|q/%LQ9{$ 8RiOO -p'KJlIoKs`/Yxi/ؿo)x>aVQKUhTUns(_6F :rM*KHZnV |Ž\2+˗h>^!-l|h|5*eb>4V%%:v`/EEC͢l|h,Gw*ˢ v`\A,~Ẏrp+/= <vS) o _|,C۔6%MρU4lxo3rӴĦ7| [v*ѺǦy>ʗ~Y]7 Ta林k+.ewހPχ}\ww 3La.+g@7}\+pWxy|Ycny 2j/2"!k=جrm>2ȗ//~\E;v`w=:*3ȗ-ȥ{!ow.k 7-:l`x*l;r|h,waahKl 4/__f󡱲.m"D[FnzJuVު[|h,[G.VP|A~͇rtj͖ulK-a/2Vb[w2`~B@__f󡱲|]R9'"Kܴv`HOPGdSؑK O圠"iQFX T vXYnE L (_: _`|^tpեH, lTFXE-/͌tH2+a19`:D:qO~̇rt^qq^UFVd3ؑKCcer'%6A:)/4J|2pI-E*WA`/+Kxi/__[@n9AEqӢہ-r tKȭJlYogrfdzpMleO֨a+ĖCzn iQVιi>2ʗ~̇rĖ5-Q:ʗYӢ|VQd>4Vow%|5ȣEK/AE`G.Vb+_{v`c 4O( Qd>4V%EzQ:nVsqrQ^__& |B^$MM[t߽ Ɨ//tJ{ev=A"_vw`vR:_xwns.YXMT% 4ar tPuI地kZ,곀5-R*Tv 4VVI["7-s؃3dVө3$lZ{ R)H{*QS(O| l/?~-ݯƨr9B?q_I!E@R/Хtmp*+KDzFҁR xΥf~J,Ezng`%Y쿨O\x#R ;_xrDD[F|)/OE8,O O,Gwff*Q9Y.V"OIZᇠs?U ؤ"jG eBQ|iQsKjFI45jܫa@QQk?Y:-iE ХsU(RT9'J$nZs[آTSJ,őde^}0.*Y*DyMdU=dWV +ĦS=<i=5,zN,!/ o<%=$a;ʭVϐP7}\DQHλew L5Sttev;QҢF>ށaX$켘0d)J%]:[|zjTl`%`k>)q6)_& [U*l ;tܤ+` (RT9'#nZs[X/ <#Qfõ&T[e-缢 L (_:u>._p a1U&OKaq>1/ l/:y/k"Um*ICG'VROT'$K-|e_@0kZ$NGܴ]j|IX,Gw&&Fy lKV]\XUືoJ*05&lǰOy~R@%wiFld)I$Y7-'{H$I$#YraK׈>~V xf9`x$#YraK׿އ%4 al]ށ?ɗ[nB'5t*򨰍Jl180`ͻCb/]X5b W"4O`3X5b ע%TiWM`7$X~R k\FlZHd)Ddo [k54ͻdɅ] kV%%$S2 eҰU"Ȧƥk̵^[6 =Տ/]X5\krNdIܴ*_n!\*>_K-ע#r9IEqӢ{%axڢ.ɒ k\Fl˵V f<ݕ JRak\oԇ3$T.}>OIcI}D=,]wW*g$(!g*?I$i,a%Ye`sk\Fl]_;Izg$KX ǭ"O2%ָt^tV0sncXuQR'I)K.lңѺ:4 %ug6%j}鲑,]*/%YR5}2`ݚS}taJ>jw]Uɒ,gV%N':(ɒ ;usp+ q <Ɇ9eɅ:}ŭMo>>Owe D9e[>95j0c;$+Is{qV%~6ͻCdɅ5.]_*:&{H ׏=\XҕMnmQ7 (-Sd)K%FŽ\V xf9`xbeQnsw/]L\`v,|'K#BZpauQ{{ϗ.q}vwnKs.a5*o=Kָt-f,R|'Kxׯj>J?YElsaKĦ"i=`U;ɗqZY,RF4U-@,Q(ɒ k\SՆ[Rn~J,eI}D=y7-ݯ|wȭË$WuZt6 !,"PNIdSXƌ"RQ9#nZpa\lwI ҅5.'pLEEf)4Ǘ.qQ-cp&Law=:l-oA҅5.][۽+gD(xS%Fy-ָFw}Qf_ƥ[l9y^ERI#)qC$K#B,a/%ok^[K(!ɳNJTbʗ஘ ưQKiQQd3ؑKvl,zncZi=e$K.u\gO=,ڢStʒiQ&=%U)*sʒ k\:ort"]EqӢ{ %ST)F)E"RF4~SFZNM=HT"=)%Y*F4ULJ T$YY͗ஹ4>r~ŰjWrE#=մH3 JF׼k\_$Y**yM1^־tH\XҹVc۬|)RQ6r [˔4ͧL`KG1$KE"ɒi=UTݪH T$Y*FZfǶ,iTDE{8axڢɒ ۻ_^7 al\ށ6+EWL,_v<)tJ?tr~@Pܕ&QOuV"v+Bϗ.u@~J:eH T$Y ֺt~@PH氏KUISS@5t5T@ Jl=cX/:&_z֥r^dm") ܲHCZi^=ɒ k\oIiK7-zǰuZ$/VCl_wa_>˕3$,nqIRm2La*gD5g.uwM M H\.I.ilQ7$K>D=sKkhC$,Jl4δ`wuȮq؜pIMMMƻvZǗ < ]qN"L" MsR[57ͻu.,KJl,܄UTjSgSgpI{l,mmR܀dUIԳNYja=*gH6g.uwMM -|)uPcB'L">IrkSua7u&tH?-ra.MMM%q", ȳNYja`ݢK7a5$OmSZ.a x,m*05k`dI߿MyJ\$we xGuSCRM0`$KBI6#Y.VCzFtݝtw{ vEVӗPM"\,BH\.a ,mR5?, ׵i=5:e6I6s6$nZr7ʗ[mllSZKCЦrΦ"io4$Opp+*05#l|\UMM "`tlup+ <#YOIMRM|Y4--i>mԏ+I#nZsVRMMEH\.i˅Nw6zM|nJqȳɒ %XYnMT`j-a5-RhSg]pISM\Vs5խ6~6y)K-$Yڤ-ڤ"7- %` v<2B"+gD5g.uwMm:eiMw-jJ \~tOۮiNPj-a5-1HB$K pXpW'c$K.cϋ2Jw&"DcQϋa%>Oy~w.7.T7ewJ^t~]T*ME P)bX*/%TDvD(0D(0D\$3~w\o߫ocY|[;˩]gsܘw-g^Ngx߿w}<}-k9_뾗f{IkX<=]͠k3}P:S;W׷{4K?/@mNj7S[똮%a3.l-vOƫ`OsZuD(oo;4tf<p ln“ MmunZtnִk1nE}2,w EX {ǓE]`kGwj7<̱oZGSsҢQ6Ug`7OU HC0.pc{¥Bv"{J]I87j)`_qfŔmF7]V E [ WrAX=luۻK-oڕaiag8Gl储0K\lܵ^]%\u`K%e]v>ƹkY׻+R뱮C",iOoa",ߖv5zm= m m#)j h a#jշeZƹKi>M?ۀp =r{e\ƹKn@d$E- #{<Ķt/6|ưǀ 6V+ŃYb玏--K~ ?{{soDY%bM<}"~ HaՀ xضv1o",׼TEDvDR#3A4?}us9Xs'aJB $Y?pst0wKJh% h { `c(`#,l8b -z7!,jWض[&Ia0Im׎K9HEX&$ńwBXfH CK6_}q׻a9"܇ǹaãpW!L3Pݤ E6=L115`8w> Dv+=R0ւ/`/8w8nP )#al$܂[h`$mvvs:AeAR,HNɫ3爍, :6]G躽˰DR,6`oK$ݶkǙujDwܐ7$ ai6'a#n=o aلaf ^7ka$&:a듂tbFՎBa )jnb<9 iE3{#Ǻ}>UCl\0~kkpxpW$6UAmϵy@uf13pîgp[s! GJ#;DnEL46˄Hb;6{aI!0K;B&mlGsj*l7꟫)$ł1apleATm]sc]eրAXت(2U#]Mp9vYe9qNGw7%~ ߟ9v.7ƨ# p5o? e[EJl!m 1h!V[1.ȹcm s7TZFac*mv`(bDmb( ݊ p![Q\Q@[Q[8m=znEnElnm&b3^m52:{uBۻKVZabn E Ejdt.9[LD)r>9 ك6nnж6"̼Q\ǂUN M) IAدOӞaJtniqH:<爽 3Ү={r=odt90o{Ly?˧ xgCR0{ ҹZX#]="dtAn ],_FcϟvwS ^)RP( х'bvF)}p[l|R@0@uhǓ"Hn]v|+,϶ ǹp73~vwb< uyuH`CFb#2HFb~ħJt*ubc*`D-BF{ONtq$s1wf\bxr!2b]et>v FXBӔ{OXBV @XIOXBFhPő ,Kx1v}rIBuh&܂O mEyÃEty[apl"dt>OӞa~H"hP526F=vu<nK;i@}rHfO UZ.dt-'OE"dt|l"\et='w$KH"dt28ѹ6KHFbϟE"dtnXQ7.4n[sF njٶ-̷րy%v}}mwh[Sd.ᔸCdtɗ , P@K(%sto[@Z@|b8G'ur|z"+adt րym!K&C/<a~ܲxR={rk, &8:O:G nOM?mֽ`?%D>2:8J)2AF Kf']B-AF|]]m$8]Bu0dt.6.dt \ZO"dt BY.2:ѵOP%s j.NKԵnO UE[-\{ ",}>CXBіMaCtfn-A]0O 6dt 2ZBq.dt-zt%:zRuY{rn@,_Fcxr޲ȎV7n[B0"2<9ԣ+8O-'!; h ŹdNssaG>@FPK(%#cc`cI 2]kY9.AF Kѥd.loh7!y_!}e&ؾ2a].e3sR5` ]N4UXPL(%璕yƹh_wWJ%dt&a [2:E(UsoIlM 2T&z8mw!K%dtfH%=c22:8Uso>) I15{Oa'S F яp]L+Ws7He W&}2 edt.qD6dt 2l K%蒑ѹƹcؠw1.AF KFF7F….PKFFbj (K$Edtf[22:wn=~BFvv" 026&; %96aaidt?'Tg ԜFwCOwxnf(*y+)mKJ~} xdb簃wonB h { `pFC 8w|#nēK M mun[f ]6kؽs;x0,7n -p'AN,/ ~bO~.)6f؏s 6ldt.qo ,]un%dt E[^L۪,skcZ4x@I2c@?cU2s'\8s#al}R8i3lQJBYhs+\޹{HԵa9H(mRz2 ].:n ]F-86a%n2 ]62vsp4&ܐې|!~dt E[ndt7DFtfiսuYCs ӴgƹmG2dtR ]hs ]@-;z22Nk #{O 8.!4:822N˨f#a E[6ѹ95}&C'؏s 6*ldt.qޅnLڵ[OXBFhPb.jj*˜gU> "eƀ&;I1bd0w0wCu0'gؘ Q@(Ήs;WpZuoned@cm sa!*it.qL za ]F5&Umv\?us7@ ].:n ]F0CF!FFbaۻэI#1ހ-7k5!BywCF`(cَn"{D[62:wn;95@F`r ]@Vh+FFbw{2 N+#aBfE[Y-jjp]L (6n Ol_9?g\޹L >)H e216` ]oeE`m;>"!+ѵ=V9@FWP@+#ss`jл ᷰⷀ`12vƓ8?sbo}-4]12 ] ~Vb玑߻ Iv KFWh+P`Fb5s[5e|s3s|.xWTmL C?Pn׶`(o"CpQs7aP@+(ΉsmyKon^7Y +FF7PFXB]?%dt2ր4xr&2E[t2[0,GK0dꬤv\=zrk1 !,Gt{O~kPdnBo#\Hߘ7x1. W5@F7$t2ϓ+D OMsԶq\#[0lex3l|,yr2])fa5s7T e2R ÆF @VAmGOZ^ 6,؇lK=zrW5a9$EXn;®O am-ѓt )r$vuP}qxأ'wFv刴oOn%dtE[m…XVME 5o%i}$EˌwI9Ӯ3H-+s[Il[Rn=KkK]=t!Ka;G@T?5?-V!xHد'ұ'ұ'ұ'!DgS/sp{?GZ2g;u?28?2 ]r'D ܺ'_/_2ݹ OIEN@oB2M|7`?׊| GxI|x%kySymnw]NWx9߿m9Ʊ߁Kn}V3n#N"8~{ν/#NA_kΕgzͱÉsLĉi5mG,m[{MԞh^~eo`4ݱ oǪ[GX7Kn8M-w,=qMd#ʎv; w8l w щsy ~lj;5r厅o;;9Qvbxw(c [SKv ww$Ŷ*?U|%Xc},f1UJ<59͐Ev KmǶ}uy8US#a{i@iHic ڵb0;.ƀ9-Nږ=7bIqE]v "ldj wEo#\k{]? 6̰3#62 \tlNv -m{[]?[-|[ݶk#\{cXZvҀ ciQݷ Џp]l%GN3ѻI1 e0a9Npˀ0K\lǫ Evֹ9on۵6tqm:dSD iDXFsE r"1]­ ߜ ċp3m u/?H:hJ̰pnӴg؃ (t|ERC0!1bC%DvBR" {UX&$qfxhڝ_DsHZ&H 焰L'\8w tQx ,FZ&;#,3laϝu>Ҿ=q`?ashOep3nmTYg&윂dDvFR#A4Ҷk=l\3R9Jd$E &H@( ,m>P7#ŝmmc~U0w+V0fؘ5˂h sHqwV`W0n rCv~Vb皑":oP'JO F_00K\l\3%[[(F 6Mnm((- ƿfE'J-,-,'J3#6rAT,8 iaװdY׶]; b"V3OceEdHkHidkr?fx{\q HGJZ\'Wq D--(ɀư;`(`#,?Q9$ŀԉWmu '``r~:nt;2"8`]\F!,b{riS `XH 1vuaWG 7"0ǻκh+o0&11ǮM=9l7n)t hIAlv;G9$ZU xKQDi;铂x(-(Ήs=wDnAL4aipsjT Iր8VdApAmIK=e&İDRLH.8 6n9#,3&ܺsxnf޼N!0韌[) s h1w˘e$ߌܭǞ;wR 2bc`#gVvG=ܹVFdׂjWҭmOk/`_qfxs ,H ²òFEp)˂,nέ ",>?sFXbϝ[aXH9]omi۵8ȹ 6 %S7|3ǻ߶ 2 FRp0y۶* m?cwν9щ6V9> (BBF'j1%6dt+Tlѹɝx@FBFR`O`n BF;ǥ5!)BF:  U5!,\l8)&a]6mk~;HqZ ,}0a'!;TgМFwCl6"̼Q4Gʀ"mևQd[].Q9לz[-BF':<爝h`r#dtAAڶ뜇[fE8g#箵(;pn0a'AN,.k:`^ؗ rD/{\-=t*gFڵ}|',!PE(bnXVM`Y7sϊu1{'i?g /sHP5v296.Ny {蜙G"PƑsvsFXuI8单aJ]k`bK$sb`X,'"7 E"1 F….Buhn=r?Diq:Gl%Tl1؄pW!#?`TWgې6u8Qs*6pΰG' !Ե"- Q@s{U'#dt2`4{Oΰ3F{2bhdt.ȹw˰DRD,bhacKlCb284rDڷ=FOXb3Reyr%m؄[jmEyWҰac*`.AFJ;w`{!K%dti$q]@ޓɜFb{!!KԵF U}(ӆZ޹}_בKdt {O&  U}(LFFbF0,G˭9`CFbKfcM8: ֹ9;9P%(S.jj*>}95:!.3t3?H,O.q{4Ȑe01`!ːe2sٜFb7@zJ]F,CF&'; >9| xrmMI! hPesm^ ,Uڕtsf0^I! :Psm;CRͱsNp49<5e!̙oyv4x#fl_!uPel_ {,+8&d`"2 uYkIcl2s"6' X"eA0F….Q˫Iqo#Wʨed@cc;9bopoNss()BF!ːѵK1g;o(r`XW%LH2;~dt E[6mEmއ>Ua dt2:qNs]H# Ec숡D@h9?KzِeTZȞaQ̐e9Ŷ΍f2 ].CFn ],Cі6 gƕ3#=:l L=&G a9"}%68.`lřoj*˜`ʜOGJ#Oo҆A۵&a(]u$16dt2 ].M ˨e2dtͱ#6FPesݟ&v xrHԵ՜lM2e it.u. `X")BF'êcl$\T3dt0,n6ae|gdtCRr1a9~kP4s6$߂|g|3o[,} Rsd@cF`c`#CŖK?ushf ].CFG2:a_qFFb"7`sxo:n6Pe(ڲX? 7ai]#6ldtGa9"ڝsSx@іwe?qa9" 9 Pe(nr@\g % oP>C6.dt>OӞa[ޣueT2 ejNߓBK>?\{7a1?|qEd\mx҅?=&0E/CG`/Eo_?// ~K%<%d?uf˯{O.zMKdzQw2Zsxk=B7acb o{}ZSy_s.xݻ jw]N5|G5i-ϯjb;E~lw,ל%Ê/)z_5޴|8nb5 ch]_ޟ/{"zn?v³f%l1Xu6rGlM^=}pbU{弾7Jx4{BZ4>aϿv͛Adwؕyyo;0pmpi 㮰G07ͻD6]jSS:`wKYY/YtsO`RVO)v^%pxs?]x6w\|K=xX*mEn®O 43|cny2*;2G#tHaqaMآ)rikOKaýUug|7#l.:l ;w)+WWow.AAKnm`xKK'[dfƦ9s^ukOO I=<%eoxSoEȗR|ruevĶ*_ G$Z]"lwI &_>1;%/~:Dm-E";:ϗ7/06(9s %_yTKV%%DL/ |YaMŠ~˿/,"-!- <`wB_/r| |4L ۤiQkGVӢ|MH.ȅY )FIoK?{$=/)|u*ؒeRy5\lVe%k\`]kMlscB'mԏ@0+l[.! xVvͧCrr@05_4,o܀- [=6g?\@avgQb+%E>7a5-"E32ϗ_Ɨ;V4"w/4ͧrrG.<%EW*_ [7ކ/M)mJo^%axfioQܔhmӴheӴhS/7M)t/7=Ɨ{|>/[w|zj>CljM9k-MVRuuW }/%k!Ǝro@G>.V0@&]7 lK>x+Mأtc]Y>B5yA^OIw}BsK @3ro'CCZn6C:a`s;rZ{sjP}{n iQrIvҵj;h܋vYEXSAzu>._CӼ{jv}>oTå$$B2<R#)ȥK^O圠"iQnrIo/[ؑKޱQA*|®ށSɗk_<)tAltHVkX!Jlkva\fubUP<$\k["]E. ^e}~B@ e ;rZ홏owT7-:-j`x*l;p)^ n^-缂 L =5_#.!幠rI*0ہ-zJE= ti1~xQA?+Yq[ب%a5 D/㪻[=xͷF:,,G5%E=5ȗ-ȥKRsn^Vbz;'^/Yx?fF:{t[N!,XˬiQk>+t _%)YíiQVbʗYC<[V"j:y/[ؑKpU=|[܃u`K-S ׵i=UtV-,KJl%P2xQ{ʗEV~<"\.EۢUNEzQ`mo[U=2#UΏF7'lK>x4\{oSlek0loM ۦݔ$L)}m/[yؾU,Kzo!En|5n6,!RS8YR QO%K=q

* A dynamic array is used to buffer up all the input characters. Normally, * "k" characters are stored in the buffer. More characters may be stored * during guess mode (testing syntactic predicate), or when LT(i>k) is * referenced. * Consumption of characters is deferred. In other words, reading the next * character is not done by consume(), but deferred until needed by LA or LT. *

* * @see antlr.CharQueue */ class ANTLR_API CharBuffer : public InputBuffer { private: // character source ANTLR_USE_NAMESPACE(std)istream& input; public: /// Create a character buffer CharBuffer(ANTLR_USE_NAMESPACE(std)istream& input_); /// Get the next character from the stream int getChar(); private: // NOTE: Unimplemented CharBuffer(const CharBuffer& other); CharBuffer& operator=(const CharBuffer& other); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CharBuffer_hpp__ gdl-0.9.9/src/antlr/CharInputBuffer.hpp000066400000000000000000000034471340051421000177440ustar00rootroot00000000000000#ifndef INC_CharInputBuffer_hpp__ # define INC_CharInputBuffer_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharInputBuffer.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ # include # include # ifdef HAS_NOT_CCTYPE_H # include # else # include # endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** CharInputBuffer.hpp provides an InputBuffer for plain character arrays (buffers). */ class CharInputBuffer : public InputBuffer { public: /** Construct a CharInputBuffer.hpp object with a char* buffer of 'size' * if 'owner' is true, then the buffer will be delete[]-ed on destruction. * @note it is assumed the buffer was allocated with new[]! */ CharInputBuffer( unsigned char* buf, size_t size, bool owner = false ) : buffer(buf) , ptr(buf) , end(buf + size) , delete_buffer(owner) { } /** Destructor * @note If you're using malloced data, then you probably need to change * this destructor. Or better use this class as template for your own. */ ~CharInputBuffer( void ) { if( delete_buffer && buffer ) delete [] buffer; } /** Reset the CharInputBuffer to initial state * Called from LexerInputState::reset. * @see LexerInputState */ virtual inline void reset( void ) { InputBuffer::reset(); ptr = buffer; } virtual int getChar( void ) { return (ptr < end) ? *ptr++ : EOF; } protected: unsigned char* buffer; ///< the buffer with data unsigned char* ptr; ///< position ptr into the buffer unsigned char* end; ///< end sentry for buffer bool delete_buffer; ///< flag signifying if we have to delete the buffer }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif gdl-0.9.9/src/antlr/CharScanner.cpp000066400000000000000000000074471340051421000171030ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharScanner.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include "antlr/CharScanner.hpp" #include "antlr/CommonToken.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_C_USING(exit) CharScanner::CharScanner(InputBuffer& cb, bool case_sensitive ) : saveConsumedInput(true) //, caseSensitiveLiterals(true) , caseSensitive(case_sensitive) , literals(CharScannerLiteralsLess(this)) , inputState(new LexerInputState(cb)) , commitToPath(false) , tabsize(8) , traceDepth(0) { setTokenObjectFactory(&CommonToken::factory); } CharScanner::CharScanner(InputBuffer* cb, bool case_sensitive ) : saveConsumedInput(true) //, caseSensitiveLiterals(true) , caseSensitive(case_sensitive) , literals(CharScannerLiteralsLess(this)) , inputState(new LexerInputState(cb)) , commitToPath(false) , tabsize(8) , traceDepth(0) { setTokenObjectFactory(&CommonToken::factory); } CharScanner::CharScanner( const LexerSharedInputState& state, bool case_sensitive ) : saveConsumedInput(true) //, caseSensitiveLiterals(true) , caseSensitive(case_sensitive) , literals(CharScannerLiteralsLess(this)) , inputState(state) , commitToPath(false) , tabsize(8) , traceDepth(0) { setTokenObjectFactory(&CommonToken::factory); } void CharScanner::consume() { if (inputState->guessing == 0) { int c = LA(1); if (caseSensitive) { append(c); } else { // use input.LA(), not LA(), to get original case // CharScanner.LA() would toLower it. append(inputState->getInput().LA(1)); } // RK: in a sense I don't like this automatic handling. if (c == '\t') tab(); else inputState->column++; } inputState->getInput().consume(); } //bool CharScanner::getCaseSensitiveLiterals() const //{ return caseSensitiveLiterals; } void CharScanner::panic() { ANTLR_USE_NAMESPACE(std)cerr << "CharScanner: panic" << ANTLR_USE_NAMESPACE(std)endl; exit(1); } void CharScanner::panic(const ANTLR_USE_NAMESPACE(std)string& s) { ANTLR_USE_NAMESPACE(std)cerr << "CharScanner: panic: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; exit(1); } /** Report exception errors caught in nextToken() */ void CharScanner::reportError(const RecognitionException& ex) { ANTLR_USE_NAMESPACE(std)cerr << ex.toString().c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Parser error-reporting function can be overridden in subclass */ void CharScanner::reportError(const ANTLR_USE_NAMESPACE(std)string& s) { if (getFilename() == "") ANTLR_USE_NAMESPACE(std)cerr << "error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; else ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Parser warning-reporting function can be overridden in subclass */ void CharScanner::reportWarning(const ANTLR_USE_NAMESPACE(std)string& s) { if (getFilename() == "") ANTLR_USE_NAMESPACE(std)cerr << "warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; else ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; } void CharScanner::traceIndent() { for( int i = 0; i < traceDepth; i++ ) ANTLR_USE_NAMESPACE(std)cout << " "; } void CharScanner::traceIn(const char* rname) { traceDepth++; traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "> lexer " << rname << "; c==" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; } void CharScanner::traceOut(const char* rname) { traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "< lexer " << rname << "; c==" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; traceDepth--; } #ifndef NO_STATIC_CONSTS const int CharScanner::NO_CHAR; const int CharScanner::EOF_CHAR; #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/CharScanner.hpp000066400000000000000000000322361340051421000171020ustar00rootroot00000000000000#ifndef INC_CharScanner_hpp__ #define INC_CharScanner_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharScanner.hpp,v 1.3 2009-10-24 16:20:01 medericboquien Exp $ */ #include // g++-4.3 needs this #include #include // g++-4.4 needs this #include #include #ifdef HAS_NOT_CCTYPE_H #include #else #include #endif #if ( _MSC_VER == 1200 ) // VC6 seems to need this // note that this is not a standard C++ include file. # include #endif #include #include #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API CharScanner; ANTLR_C_USING(tolower) #ifdef ANTLR_REALLY_NO_STRCASECMP // Apparently, neither strcasecmp nor stricmp is standard, and Codewarrior // on the mac has neither... inline int strcasecmp(const char *s1, const char *s2) { while (true) { char c1 = tolower(*s1++), c2 = tolower(*s2++); if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } #else #ifdef NO_STRCASECMP ANTLR_C_USING(stricmp) #else ANTLR_C_USING(strcasecmp) #endif #endif /** Functor for the literals map */ class ANTLR_API CharScannerLiteralsLess : public ANTLR_USE_NAMESPACE(std)binary_function { private: const CharScanner* scanner; public: #ifdef NO_TEMPLATE_PARTS CharScannerLiteralsLess() {} // not really used, definition to appease MSVC #endif CharScannerLiteralsLess(const CharScanner* theScanner) : scanner(theScanner) { } bool operator() (const ANTLR_USE_NAMESPACE(std)string& x,const ANTLR_USE_NAMESPACE(std)string& y) const; // defaults are good enough.. // CharScannerLiteralsLess(const CharScannerLiteralsLess&); // CharScannerLiteralsLess& operator=(const CharScannerLiteralsLess&); }; /** Superclass of generated lexers */ class ANTLR_API CharScanner : public TokenStream { protected: typedef RefToken (*factory_type)(); public: CharScanner(InputBuffer& cb, bool case_sensitive ); CharScanner(InputBuffer* cb, bool case_sensitive ); CharScanner(const LexerSharedInputState& state, bool case_sensitive ); virtual ~CharScanner() { } virtual int LA(unsigned int i); virtual void append(char c) { if (saveConsumedInput) { int l = text.length(); if ((l%256) == 0) text.reserve(l+256); text.replace(l,0,&c,1); } } virtual void append(const ANTLR_USE_NAMESPACE(std)string& s) { if (saveConsumedInput) text+=s; } virtual void commit() { inputState->getInput().commit(); } virtual void consume(); /** Consume chars until one matches the given char */ virtual void consumeUntil(int c) { for(;;) { int la_1 = LA(1); if( la_1 == EOF_CHAR || la_1 == c ) break; consume(); } } /** Consume chars until one matches the given set */ virtual void consumeUntil(const BitSet& set) { for(;;) { int la_1 = LA(1); if( la_1 == EOF_CHAR || set.member(la_1) ) break; consume(); } } /// Mark the current position and return a id for it virtual unsigned int mark() { return inputState->getInput().mark(); } /// Rewind the scanner to a previously marked position virtual void rewind(unsigned int pos) { inputState->getInput().rewind(pos); } /// See if input contains character 'c' throw MismatchedCharException if not virtual void match(int c) { int la_1 = LA(1); if ( la_1 != c ) throw MismatchedCharException(la_1, c, false, this); consume(); } /** See if input contains element from bitset b * throw MismatchedCharException if not */ virtual void match(const BitSet& b) { int la_1 = LA(1); if ( !b.member(la_1) ) throw MismatchedCharException( la_1, b, false, this ); consume(); } /** See if input contains string 's' throw MismatchedCharException if not * @note the string cannot match EOF */ virtual void match( const char* s ) { while( *s != '\0' ) { // the & 0xFF is here to prevent sign extension lateron int la_1 = LA(1), c = (*s++ & 0xFF); if ( la_1 != c ) throw MismatchedCharException(la_1, c, false, this); consume(); } } /** See if input contains string 's' throw MismatchedCharException if not * @note the string cannot match EOF */ virtual void match(const ANTLR_USE_NAMESPACE(std)string& s) { size_t len = s.length(); for (size_t i = 0; i < len; i++) { // the & 0xFF is here to prevent sign extension lateron int la_1 = LA(1), c = (s[i] & 0xFF); if ( la_1 != c ) throw MismatchedCharException(la_1, c, false, this); consume(); } } /** See if input does not contain character 'c' * throw MismatchedCharException if not */ virtual void matchNot(int c) { int la_1 = LA(1); if ( la_1 == c ) throw MismatchedCharException(la_1, c, true, this); consume(); } /** See if input contains character in range c1-c2 * throw MismatchedCharException if not */ virtual void matchRange(int c1, int c2) { int la_1 = LA(1); if ( la_1 < c1 || la_1 > c2 ) throw MismatchedCharException(la_1, c1, c2, false, this); consume(); } virtual bool getCaseSensitive() const { return caseSensitive; } virtual void setCaseSensitive(bool t) { caseSensitive = t; } virtual bool getCaseSensitiveLiterals() const=0; /// Get the line the scanner currently is in (starts at 1) virtual int getLine() const { return inputState->line; } /// set the line number virtual void setLine(int l) { inputState->line = l; } /// Get the column the scanner currently is in (starts at 1) virtual int getColumn() const { return inputState->column; } /// set the column number virtual void setColumn(int c) { inputState->column = c; } /// get the filename for the file currently used virtual const ANTLR_USE_NAMESPACE(std)string& getFilename() const { return inputState->filename; } /// Set the filename the scanner is using (used in error messages) virtual void setFilename(const ANTLR_USE_NAMESPACE(std)string& f) { inputState->filename = f; } virtual bool getCommitToPath() const { return commitToPath; } virtual void setCommitToPath(bool commit) { commitToPath = commit; } /** return a copy of the current text buffer */ virtual const ANTLR_USE_NAMESPACE(std)string& getText() const { return text; } virtual void setText(const ANTLR_USE_NAMESPACE(std)string& s) { text = s; } virtual void resetText() { text = ""; inputState->tokenStartColumn = inputState->column; inputState->tokenStartLine = inputState->line; } virtual RefToken getTokenObject() const { return _returnToken; } /** Used to keep track of line breaks, needs to be called from * within generated lexers when a \n \r is encountered. */ virtual void newline() { ++inputState->line; inputState->column = 1; } /** Advance the current column number by an appropriate amount according * to the tabsize. This method needs to be explicitly called from the * lexer rules encountering tabs. */ virtual void tab() { int c = getColumn(); int nc = ( ((c-1)/tabsize) + 1) * tabsize + 1; // calculate tab stop setColumn( nc ); } /// set the tabsize. Returns the old tabsize int setTabsize( int size ) { int oldsize = tabsize; tabsize = size; return oldsize; } /// Return the tabsize used by the scanner int getTabSize() const { return tabsize; } /** Terminate program using exit() * @deprecated will be removed in the next release. It is not used. */ virtual void panic(); /** Terminate program using exit() * @deprecated will be removed in the next release. It is not used. */ virtual void panic(const ANTLR_USE_NAMESPACE(std)string& s); /** Report exception errors caught in nextToken() */ virtual void reportError(const RecognitionException& e); /** Parser error-reporting function can be overridden in subclass */ virtual void reportError(const ANTLR_USE_NAMESPACE(std)string& s); /** Parser warning-reporting function can be overridden in subclass */ virtual void reportWarning(const ANTLR_USE_NAMESPACE(std)string& s); virtual InputBuffer& getInputBuffer() { return inputState->getInput(); } virtual LexerSharedInputState getInputState() { return inputState; } /** set the input state for the lexer. * @note state is a reference counted object, hence no reference */ virtual void setInputState(LexerSharedInputState state) { inputState = state; } /// Set the factory for created tokens virtual void setTokenObjectFactory(factory_type factory) { tokenFactory = factory; } /** Test the token text against the literals table * Override this method to perform a different literals test */ virtual int testLiteralsTable(int ttype) const { ANTLR_USE_NAMESPACE(std)map::const_iterator i = literals.find(text); if (i != literals.end()) ttype = (*i).second; return ttype; } /** Test the text passed in against the literals table * Override this method to perform a different literals test * This is used primarily when you want to test a portion of * a token */ virtual int testLiteralsTable(const ANTLR_USE_NAMESPACE(std)string& txt,int ttype) const { ANTLR_USE_NAMESPACE(std)map::const_iterator i = literals.find(txt); if (i != literals.end()) ttype = (*i).second; return ttype; } /// Override this method to get more specific case handling virtual int toLower(int c) const { // test on EOF_CHAR for buggy (?) STLPort tolower (or HPUX tolower?) // also VC++ 6.0 does this. (see fix 422 (is reverted by this fix) // this one is more structural. Maybe make this configurable. return (c == EOF_CHAR ? EOF_CHAR : tolower(c)); } /** This method is called by YourLexer::nextToken() when the lexer has * hit EOF condition. EOF is NOT a character. * This method is not called if EOF is reached during * syntactic predicate evaluation or during evaluation * of normal lexical rules, which presumably would be * an IOException. This traps the "normal" EOF condition. * * uponEOF() is called after the complete evaluation of * the previous token and only if your parser asks * for another token beyond that last non-EOF token. * * You might want to throw token or char stream exceptions * like: "Heh, premature eof" or a retry stream exception * ("I found the end of this file, go back to referencing file"). */ virtual void uponEOF() { } /// Methods used to change tracing behavior virtual void traceIndent(); virtual void traceIn(const char* rname); virtual void traceOut(const char* rname); #ifndef NO_STATIC_CONSTS static const int EOF_CHAR = EOF; #else enum { EOF_CHAR = EOF }; #endif protected: ANTLR_USE_NAMESPACE(std)string text; ///< Text of current token /// flag indicating wether consume saves characters bool saveConsumedInput; factory_type tokenFactory; ///< Factory for tokens bool caseSensitive; ///< Is this lexer case sensitive ANTLR_USE_NAMESPACE(std)map literals; // set by subclass RefToken _returnToken; ///< used to return tokens w/o using return val /// Input state, gives access to input stream, shared among different lexers LexerSharedInputState inputState; /** Used during filter mode to indicate that path is desired. * A subsequent scan error will report an error as usual * if acceptPath=true; */ bool commitToPath; int tabsize; ///< tab size the scanner uses. /// Create a new RefToken of type t virtual RefToken makeToken(int t) { RefToken tok = tokenFactory(); tok->setType(t); tok->setColumn(inputState->tokenStartColumn); tok->setLine(inputState->tokenStartLine); return tok; } /** Tracer class, used when -traceLexer is passed to antlr */ class Tracer { private: CharScanner* parser; const char* text; Tracer(const Tracer& other); // undefined Tracer& operator=(const Tracer& other); // undefined public: Tracer( CharScanner* p,const char* t ) : parser(p), text(t) { parser->traceIn(text); } ~Tracer() { parser->traceOut(text); } }; int traceDepth; private: CharScanner( const CharScanner& other ); // undefined CharScanner& operator=( const CharScanner& other ); // undefined #ifndef NO_STATIC_CONSTS static const int NO_CHAR = 0; #else enum { NO_CHAR = 0 }; #endif }; inline int CharScanner::LA(unsigned int i) { int c = inputState->getInput().LA(i); if ( caseSensitive ) return c; else return toLower(c); // VC 6 tolower bug caught in toLower. } inline bool CharScannerLiteralsLess::operator() (const ANTLR_USE_NAMESPACE(std)string& x,const ANTLR_USE_NAMESPACE(std)string& y) const { if (scanner->getCaseSensitiveLiterals()) return ANTLR_USE_NAMESPACE(std)less()(x,y); else { #ifdef NO_STRCASECMP return (stricmp(x.c_str(),y.c_str())<0); #else return (strcasecmp(x.c_str(),y.c_str())<0); #endif } } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CharScanner_hpp__ gdl-0.9.9/src/antlr/CharStreamException.hpp000066400000000000000000000013101340051421000206100ustar00rootroot00000000000000#ifndef INC_CharStreamException_hpp__ #define INC_CharStreamException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharStreamException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API CharStreamException : public ANTLRException { public: CharStreamException(const ANTLR_USE_NAMESPACE(std)string& s) : ANTLRException(s) {} ~CharStreamException() throw() {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CharStreamException_hpp__ gdl-0.9.9/src/antlr/CharStreamIOException.hpp000066400000000000000000000014301340051421000210430ustar00rootroot00000000000000#ifndef INC_CharStreamIOException_hpp__ #define INC_CharStreamIOException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharStreamIOException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API CharStreamIOException : public CharStreamException { public: ANTLR_USE_NAMESPACE(std)exception io; CharStreamIOException(ANTLR_USE_NAMESPACE(std)exception& e) : CharStreamException(e.what()), io(e) {} ~CharStreamIOException() throw() {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CharStreamIOException_hpp__ gdl-0.9.9/src/antlr/CircularQueue.hpp000066400000000000000000000031431340051421000174570ustar00rootroot00000000000000#ifndef INC_CircularQueue_hpp__ #define INC_CircularQueue_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CircularQueue.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif // Resize every 5000 items #define OFFSET_MAX_RESIZE 5000 template class ANTLR_API CircularQueue { public: CircularQueue() : storage() , m_offset(0) { } ~CircularQueue() { } /// Clear the queue inline void clear( void ) { m_offset = 0; storage.clear(); } /// @todo this should use at or should have a check inline T elementAt( unsigned int idx ) const { return storage[idx+m_offset]; } void removeFirst() { if (m_offset >= OFFSET_MAX_RESIZE) { storage.erase( storage.begin(), storage.begin() + m_offset + 1 ); m_offset = 0; } else ++m_offset; } inline void removeItems( unsigned int nb ) { if (m_offset >= OFFSET_MAX_RESIZE) { storage.erase( storage.begin(), storage.begin() + m_offset + nb ); m_offset = 0; } else m_offset += nb; } inline void append(const T& t) { storage.push_back(t); } inline unsigned int entries() const { return storage.size() - m_offset; } private: typename ANTLR_USE_NAMESPACE(std)vector storage; unsigned int m_offset; CircularQueue(const CircularQueue&); const CircularQueue& operator=(const CircularQueue&); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CircularQueue_hpp__ gdl-0.9.9/src/antlr/CommonAST.cpp000066400000000000000000000037711340051421000165100ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonAST.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/config.hpp" #include "antlr/CommonAST.hpp" #include "antlr/ANTLRUtil.hpp" #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif const char* const CommonAST::TYPE_NAME = "CommonAST"; CommonAST::CommonAST() : BaseAST() , ttype( Token::INVALID_TYPE ) , text("") { } CommonAST::CommonAST(RefToken t) : BaseAST() , ttype( t->getType() ) , text( t->getText() ) { } CommonAST::~CommonAST() { } const char* CommonAST::typeName( void ) const { return CommonAST::TYPE_NAME; } CommonAST::CommonAST(const CommonAST& other) : BaseAST(other) , ttype(other.ttype) , text(other.text) { } RefAST CommonAST::clone( void ) const { CommonAST *ast = new CommonAST( *this ); return RefAST(ast); } ANTLR_USE_NAMESPACE(std)string CommonAST::getText() const { return text; } int CommonAST::getType() const { return ttype; } void CommonAST::initialize(int t,const ANTLR_USE_NAMESPACE(std)string& txt) { setType(t); setText(txt); } void CommonAST::initialize(RefAST t) { setType(t->getType()); setText(t->getText()); } void CommonAST::initialize(RefToken t) { setType(t->getType()); setText(t->getText()); } #ifdef ANTLR_SUPPORT_XML void CommonAST::initialize( ANTLR_USE_NAMESPACE(std)istream& in ) { ANTLR_USE_NAMESPACE(std)string t1, t2, text; // text read_AttributeNValue( in, t1, text ); read_AttributeNValue( in, t1, t2 ); #ifdef ANTLR_ATOI_IN_STD int type = ANTLR_USE_NAMESPACE(std)atoi(t2.c_str()); #else int type = atoi(t2.c_str()); #endif // initialize first part of AST. this->initialize( type, text ); } #endif void CommonAST::setText(const ANTLR_USE_NAMESPACE(std)string& txt) { text = txt; } void CommonAST::setType(int type) { ttype = type; } RefAST CommonAST::factory() { return RefAST(new CommonAST); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/CommonAST.hpp000066400000000000000000000025131340051421000165060ustar00rootroot00000000000000#ifndef INC_CommonAST_hpp__ #define INC_CommonAST_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonAST.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API CommonAST : public BaseAST { public: CommonAST(); CommonAST( RefToken t ); CommonAST( const CommonAST& other ); virtual ~CommonAST(); virtual const char* typeName( void ) const; /// Clone this AST node. virtual RefAST clone( void ) const; virtual ANTLR_USE_NAMESPACE(std)string getText() const; virtual int getType() const; virtual void initialize( int t, const ANTLR_USE_NAMESPACE(std)string& txt ); virtual void initialize( RefAST t ); virtual void initialize( RefToken t ); #ifdef ANTLR_SUPPORT_XML virtual void initialize( ANTLR_USE_NAMESPACE(std)istream& in ); #endif virtual void setText( const ANTLR_USE_NAMESPACE(std)string& txt ); virtual void setType( int type ); static RefAST factory(); static const char* const TYPE_NAME; protected: int ttype; ANTLR_USE_NAMESPACE(std)string text; }; typedef ASTRefCount RefCommonAST; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CommonAST_hpp__ gdl-0.9.9/src/antlr/CommonASTWithHiddenTokens.cpp000066400000000000000000000032451340051421000216400ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonASTWithHiddenTokens.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/config.hpp" #include "antlr/AST.hpp" #include "antlr/BaseAST.hpp" #include "antlr/CommonAST.hpp" #include "antlr/CommonASTWithHiddenTokens.hpp" #include "antlr/CommonHiddenStreamToken.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif const char* const CommonASTWithHiddenTokens::TYPE_NAME = "CommonASTWithHiddenTokens"; // RK: Do not put constructor and destructor into the header file here.. // this triggers something very obscure in gcc 2.95.3 (and 3.0) // missing vtables and stuff. // Although this may be a problem with with binutils. CommonASTWithHiddenTokens::CommonASTWithHiddenTokens() : CommonAST() { } CommonASTWithHiddenTokens::~CommonASTWithHiddenTokens() { } void CommonASTWithHiddenTokens::initialize(int t,const ANTLR_USE_NAMESPACE(std)string& txt) { CommonAST::initialize(t,txt); } void CommonASTWithHiddenTokens::initialize(RefAST t) { CommonAST::initialize(t); } void CommonASTWithHiddenTokens::initialize(RefToken t) { CommonAST::initialize(t); hiddenBefore = static_cast(t.get())->getHiddenBefore(); hiddenAfter = static_cast(t.get())->getHiddenAfter(); } RefAST CommonASTWithHiddenTokens::factory() { return RefAST(new CommonASTWithHiddenTokens); } RefAST CommonASTWithHiddenTokens::clone( void ) const { CommonASTWithHiddenTokens *ast = new CommonASTWithHiddenTokens( *this ); return RefAST(ast); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/CommonASTWithHiddenTokens.hpp000066400000000000000000000030001340051421000216320ustar00rootroot00000000000000#ifndef INC_CommonASTWithHiddenTokens_hpp__ #define INC_CommonASTWithHiddenTokens_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonASTWithHiddenTokens.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** A CommonAST whose initialization copies hidden token * information from the Token used to create a node. */ class ANTLR_API CommonASTWithHiddenTokens : public CommonAST { public: CommonASTWithHiddenTokens(); virtual ~CommonASTWithHiddenTokens(); virtual const char* typeName( void ) const { return CommonASTWithHiddenTokens::TYPE_NAME; } /// Clone this AST node. virtual RefAST clone( void ) const; // Borland C++ builder seems to need the decl's of the first two... virtual void initialize(int t,const ANTLR_USE_NAMESPACE(std)string& txt); virtual void initialize(RefAST t); virtual void initialize(RefToken t); virtual RefToken getHiddenAfter() const { return hiddenAfter; } virtual RefToken getHiddenBefore() const { return hiddenBefore; } static RefAST factory(); static const char* const TYPE_NAME; protected: RefToken hiddenBefore,hiddenAfter; // references to hidden tokens }; typedef ASTRefCount RefCommonASTWithHiddenTokens; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CommonASTWithHiddenTokens_hpp__ gdl-0.9.9/src/antlr/CommonHiddenStreamToken.cpp000066400000000000000000000021231340051421000214170ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonHiddenStreamToken.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/CommonHiddenStreamToken.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif CommonHiddenStreamToken::CommonHiddenStreamToken() : CommonToken() { } CommonHiddenStreamToken::CommonHiddenStreamToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt) : CommonToken(t,txt) { } CommonHiddenStreamToken::CommonHiddenStreamToken(const ANTLR_USE_NAMESPACE(std)string& s) : CommonToken(s) { } RefToken CommonHiddenStreamToken::getHiddenAfter() { return hiddenAfter; } RefToken CommonHiddenStreamToken::getHiddenBefore() { return hiddenBefore; } RefToken CommonHiddenStreamToken::factory() { return RefToken(new CommonHiddenStreamToken); } void CommonHiddenStreamToken::setHiddenAfter(RefToken t) { hiddenAfter = t; } void CommonHiddenStreamToken::setHiddenBefore(RefToken t) { hiddenBefore = t; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/CommonHiddenStreamToken.hpp000066400000000000000000000017411340051421000214310ustar00rootroot00000000000000#ifndef INC_CommonHiddenStreamToken_hpp__ #define INC_CommonHiddenStreamToken_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonHiddenStreamToken.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API CommonHiddenStreamToken : public CommonToken { protected: RefToken hiddenBefore; RefToken hiddenAfter; public: CommonHiddenStreamToken(); CommonHiddenStreamToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt); CommonHiddenStreamToken(const ANTLR_USE_NAMESPACE(std)string& s); RefToken getHiddenAfter(); RefToken getHiddenBefore(); static RefToken factory(); void setHiddenAfter(RefToken t); void setHiddenBefore(RefToken t); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CommonHiddenStreamToken_hpp__ gdl-0.9.9/src/antlr/CommonToken.cpp000066400000000000000000000015741340051421000171400ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonToken.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/CommonToken.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif CommonToken::CommonToken() : Token(), line(1), col(1), text("") {} CommonToken::CommonToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt) : Token(t), line(1), col(1), text(txt) {} CommonToken::CommonToken(const ANTLR_USE_NAMESPACE(std)string& s) : Token(), line(1), col(1), text(s) {} ANTLR_USE_NAMESPACE(std)string CommonToken::toString() const { return "[\""+getText()+"\",<"+type+">,line="+line+",column="+col+"]"; } RefToken CommonToken::factory() { return RefToken(new CommonToken); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/CommonToken.hpp000066400000000000000000000032321340051421000171360ustar00rootroot00000000000000#ifndef INC_CommonToken_hpp__ #define INC_CommonToken_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CommonToken.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API CommonToken : public Token { public: CommonToken(); CommonToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt); CommonToken(const ANTLR_USE_NAMESPACE(std)string& s); /// return contents of token ANTLR_USE_NAMESPACE(std)string getText() const { return text; } /// set contents of token void setText(const ANTLR_USE_NAMESPACE(std)string& s) { text = s; } /** get the line the token is at (starting at 1) * @see CharScanner::newline() * @see CharScanner::tab() */ int getLine() const { return line; } /** gt the column the token is at (starting at 1) * @see CharScanner::newline() * @see CharScanner::tab() */ int getColumn() const { return col; } /// set line for token void setLine(int l) { line = l; } /// set column for token void setColumn(int c) { col = c; } bool isInvalid() const { return type==INVALID_TYPE; } ANTLR_USE_NAMESPACE(std)string toString() const; static RefToken factory(); protected: // most tokens will want line and text information int line; int col; ANTLR_USE_NAMESPACE(std)string text; private: CommonToken(const CommonToken&); const CommonToken& operator=(const CommonToken&); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_CommonToken_hpp__ gdl-0.9.9/src/antlr/IOException.hpp000066400000000000000000000017611340051421000171000ustar00rootroot00000000000000#ifndef INC_IOException_hpp__ #define INC_IOException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: IOException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** Generic IOException used inside support code. (thrown by XML I/O routs) * basically this is something I'm using since a lot of compilers don't * support ios_base::failure. */ class ANTLR_API IOException : public ANTLRException { public: ANTLR_USE_NAMESPACE(std)exception io; IOException( ANTLR_USE_NAMESPACE(std)exception& e ) : ANTLRException(e.what()) { } IOException( const ANTLR_USE_NAMESPACE(std)string& mesg ) : ANTLRException(mesg) { } virtual ~IOException() throw() { } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_IOException_hpp__ gdl-0.9.9/src/antlr/InputBuffer.cpp000066400000000000000000000034541340051421000171370ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: InputBuffer.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/config.hpp" #include "antlr/InputBuffer.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** Ensure that the character buffer is sufficiently full */ void InputBuffer::fill(unsigned int amount) { syncConsume(); // Fill the buffer sufficiently to hold needed characters while (queue.entries() < amount + markerOffset) { // Append the next character queue.append(getChar()); } } /** get the current lookahead characters as a string * @warning it may treat 0 and EOF values wrong */ ANTLR_USE_NAMESPACE(std)string InputBuffer::getLAChars( void ) const { ANTLR_USE_NAMESPACE(std)string ret; for(unsigned int i = markerOffset; i < queue.entries(); i++) ret += queue.elementAt(i); return ret; } /** get the current marked characters as a string * @warning it may treat 0 and EOF values wrong */ ANTLR_USE_NAMESPACE(std)string InputBuffer::getMarkedChars( void ) const { ANTLR_USE_NAMESPACE(std)string ret; for(unsigned int i = 0; i < markerOffset; i++) ret += queue.elementAt(i); return ret; } /** Return an integer marker that can be used to rewind the buffer to * its current state. */ unsigned int InputBuffer::mark() { syncConsume(); nMarkers++; return markerOffset; } /** Rewind the character buffer to a marker. * @param mark Marker returned previously from mark() */ void InputBuffer::rewind(unsigned int mark) { syncConsume(); markerOffset = mark; nMarkers--; } unsigned int InputBuffer::entries() const { //assert(queue.entries() >= markerOffset); return queue.entries() - markerOffset; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/InputBuffer.hpp000066400000000000000000000066501340051421000171450ustar00rootroot00000000000000#ifndef INC_InputBuffer_hpp__ #define INC_InputBuffer_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: InputBuffer.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** A Stream of characters fed to the lexer from a InputStream that can * be rewound via mark()/rewind() methods. *

* A dynamic array is used to buffer up all the input characters. Normally, * "k" characters are stored in the buffer. More characters may be stored during * guess mode (testing syntactic predicate), or when LT(i>k) is referenced. * Consumption of characters is deferred. In other words, reading the next * character is not done by conume(), but deferred until needed by LA or LT. *

* * @see antlr.CharQueue */ class ANTLR_API InputBuffer { public: /** Create a character buffer */ InputBuffer() : nMarkers(0) , markerOffset(0) , numToConsume(0) { } virtual ~InputBuffer() { } /// Reset the input buffer to empty state virtual inline void reset( void ) { nMarkers = 0; markerOffset = 0; numToConsume = 0; queue.clear(); } /** This method updates the state of the input buffer so that * the text matched since the most recent mark() is no longer * held by the buffer. So, you either do a mark/rewind for * failed predicate or mark/commit to keep on parsing without * rewinding the input. */ inline void commit( void ) { nMarkers--; } /** Mark another character for deferred consumption */ virtual inline void consume() { numToConsume++; } /** Ensure that the character buffer is sufficiently full */ virtual void fill(unsigned int amount); /** Override this in subclasses to get the next character */ virtual int getChar()=0; /** Get a lookahead character */ virtual inline int LA(unsigned int i) { fill(i); return queue.elementAt(markerOffset + i - 1); } /** Return an integer marker that can be used to rewind the buffer to * its current state. */ virtual unsigned int mark(); /// Are there any marks active in the InputBuffer virtual inline bool isMarked() const { return (nMarkers != 0); } /** Rewind the character buffer to a marker. * @param mark Marker returned previously from mark() */ virtual void rewind(unsigned int mark); /** Get the number of non-consumed characters */ virtual unsigned int entries() const; ANTLR_USE_NAMESPACE(std)string getLAChars() const; ANTLR_USE_NAMESPACE(std)string getMarkedChars() const; protected: // char source // leave to subclasses // Number of active markers unsigned int nMarkers; // = 0; // Additional offset used when markers are active unsigned int markerOffset; // = 0; // Number of calls to consume() since last LA() or LT() call unsigned int numToConsume; // = 0; // Circular queue CircularQueue queue; /** Sync up deferred consumption */ void syncConsume(); private: InputBuffer(const InputBuffer& other); InputBuffer& operator=(const InputBuffer& other); }; /** Sync up deferred consumption */ inline void InputBuffer::syncConsume() { if (numToConsume > 0) { if (nMarkers > 0) markerOffset += numToConsume; else queue.removeItems( numToConsume ); numToConsume = 0; } } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_InputBuffer_hpp__ gdl-0.9.9/src/antlr/LLkParser.cpp000066400000000000000000000031521340051421000165400ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: LLkParser.cpp,v 1.8 2013-05-07 13:13:52 m_schellens Exp $ */ #include "antlr/LLkParser.hpp" #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_USING_NAMESPACE(std) /**An LL(k) parser. * * @see antlr.Token * @see antlr.TokenBuffer * @see antlr.LL1Parser */ // LLkParser(int k_); LLkParser::LLkParser(const ParserSharedInputState& state, int k_) : Parser(state), k(k_) { } LLkParser::LLkParser(TokenBuffer& tokenBuf, int k_) : Parser(tokenBuf), k(k_) { } LLkParser::LLkParser(TokenStream& lexer, int k_) : Parser(new TokenBuffer(lexer)), k(k_) { } void LLkParser::trace(const char* ee, const char* rname) { // only show non-guessing (production) calls if(inputState->guessing>0) return; traceIndent(); cout << ee << rname << ((inputState->guessing>0)?"; ?: ":"; <: "); for (int i = 1; i <= k+3; i++) { if (i != 1) { //cout << ", "; cout << " "; } //cout << "LA(" << i << ")=="; string temp; try { temp = LT(i)->getText().c_str(); } catch( ANTLRException& ae ) { temp = "[error: "; temp += ae.toString(); temp += ']'; } if( temp == "\n") cout << "\\n"; else cout << temp; } cout << endl; } void LLkParser::traceIn(const char* rname) { traceDepth++; trace("> ",rname); } void LLkParser::traceOut(const char* rname) { trace("< ",rname); traceDepth--; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/LLkParser.hpp000066400000000000000000000030611340051421000165440ustar00rootroot00000000000000#ifndef INC_LLkParser_hpp__ #define INC_LLkParser_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: LLkParser.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /**An LL(k) parser. * * @see antlr.Token * @see antlr.TokenBuffer * @see antlr.LL1Parser */ class ANTLR_API LLkParser : public Parser { public: LLkParser(const ParserSharedInputState& lexer, int k_); LLkParser(TokenBuffer& tokenBuf, int k_); LLkParser(TokenStream& lexer, int k_); /** Consume another token from the input stream. Can only write sequentially! * If you need 3 tokens ahead, you must consume() 3 times. *

* Note that it is possible to overwrite tokens that have not been matched. * For example, calling consume() 3 times when k=2, means that the first token * consumed will be overwritten with the 3rd. */ virtual inline void consume() { inputState->getInput().consume(); } virtual inline int LA(unsigned int i) { return inputState->getInput().LA(i); } virtual inline RefToken LT(unsigned int i) { return inputState->getInput().LT(i); } protected: /// the lookahead this LL(k) parser is using. int k; private: void trace(const char* ee, const char* rname); public: virtual void traceIn(const char* rname); virtual void traceOut(const char* rname); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_LLkParser_hpp__ gdl-0.9.9/src/antlr/LexerSharedInputState.hpp000066400000000000000000000066121340051421000211410ustar00rootroot00000000000000#ifndef INC_LexerSharedInputState_hpp__ #define INC_LexerSharedInputState_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: LexerSharedInputState.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** This object contains the data associated with an * input stream of characters. Multiple lexers * share a single LexerSharedInputState to lex * the same input stream. */ class ANTLR_API LexerInputState { public: /** Construct a new LexerInputState * @param inbuf the InputBuffer to read from. The object is deleted together * with the LexerInputState object. */ LexerInputState(InputBuffer* inbuf) : column(1) , line(1) , tokenStartColumn(1) , tokenStartLine(1) , guessing(0) , filename("") , input(inbuf) , inputResponsible(true) { } /** Construct a new LexerInputState * @param inbuf the InputBuffer to read from. */ LexerInputState(InputBuffer& inbuf) : column(1) , line(1) , tokenStartColumn(1) , tokenStartLine(1) , guessing(0) , filename("") , input(&inbuf) , inputResponsible(false) { } /** Construct a new LexerInputState * @param in an istream to read from. * @see antlr.CharBuffer */ LexerInputState(ANTLR_USE_NAMESPACE(std)istream& in) : column(1) , line(1) , tokenStartColumn(1) , tokenStartLine(1) , guessing(0) , filename("") , input(new CharBuffer(in)) , inputResponsible(true) { } /** Reset the LexerInputState with a specified stream and filename. * This method is a hack, dunno what I was thinking when I added it. * This should actually be done in a subclass. * @deprecated */ virtual void initialize( ANTLR_USE_NAMESPACE(std)istream& in, const char* file = "" ) { column = 1; line = 1; tokenStartColumn = 1; tokenStartLine = 1; guessing = 0; filename = file; if( input && inputResponsible ) delete input; input = new CharBuffer(in); inputResponsible = true; } /** Reset the LexerInputState to initial state. * The underlying InputBuffer is also reset. */ virtual void reset( void ) { column = 1; line = 1; tokenStartColumn = 1; tokenStartLine = 1; guessing = 0; input->reset(); } /** Set the file position of the SharedLexerInputState. * @param line_ line number to be set * @param column_ column number to be set */ void setPosition( int line_, int column_ ) { line = line_; column = column_; } virtual ~LexerInputState() { if (inputResponsible) delete input; } int column; int line; int tokenStartColumn; int tokenStartLine; int guessing; /** What file (if known) caused the problem? */ ANTLR_USE_NAMESPACE(std)string filename; InputBuffer& getInput(); private: /// Input buffer we use InputBuffer* input; /// Who is responsible for cleaning up the InputBuffer? bool inputResponsible; // we don't want these: LexerInputState(const LexerInputState&); LexerInputState& operator=(const LexerInputState&); }; inline InputBuffer& LexerInputState::getInput() { return *input; } /// A reference counted LexerInputState object typedef RefCount LexerSharedInputState; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_LexerSharedInputState_hpp__ gdl-0.9.9/src/antlr/MismatchedCharException.cpp000066400000000000000000000062021340051421000214330ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: MismatchedCharException.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/CharScanner.hpp" #include "antlr/MismatchedCharException.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif MismatchedCharException::MismatchedCharException() : RecognitionException("Mismatched char") {} // Expected range / not range MismatchedCharException::MismatchedCharException( int c, int lower, int upper_, bool matchNot, CharScanner* scanner_ ) : RecognitionException("Mismatched char", scanner_->getFilename(), scanner_->getLine(), scanner_->getColumn()) , mismatchType(matchNot ? NOT_RANGE : RANGE) , foundChar(c) , expecting(lower) , upper(upper_) , scanner(scanner_) { } // Expected token / not token MismatchedCharException::MismatchedCharException( int c, int expecting_, bool matchNot, CharScanner* scanner_ ) : RecognitionException("Mismatched char", scanner_->getFilename(), scanner_->getLine(), scanner_->getColumn()) , mismatchType(matchNot ? NOT_CHAR : CHAR) , foundChar(c) , expecting(expecting_) , scanner(scanner_) { } // Expected BitSet / not BitSet MismatchedCharException::MismatchedCharException( int c, BitSet set_, bool matchNot, CharScanner* scanner_ ) : RecognitionException("Mismatched char", scanner_->getFilename(), scanner_->getLine(), scanner_->getColumn()) , mismatchType(matchNot ? NOT_SET : SET) , foundChar(c) , set(set_) , scanner(scanner_) { } ANTLR_USE_NAMESPACE(std)string MismatchedCharException::getMessage() const { ANTLR_USE_NAMESPACE(std)string s; switch (mismatchType) { case CHAR : s += "expecting '" + charName(expecting) + "', found '" + charName(foundChar) + "'"; break; case NOT_CHAR : s += "expecting anything but '" + charName(expecting) + "'; got it anyway"; break; case RANGE : s += "expecting token in range: '" + charName(expecting) + "'..'" + charName(upper) + "', found '" + charName(foundChar) + "'"; break; case NOT_RANGE : s += "expecting token NOT in range: " + charName(expecting) + "'..'" + charName(upper) + "', found '" + charName(foundChar) + "'"; break; case SET : case NOT_SET : { s += ANTLR_USE_NAMESPACE(std)string("expecting ") + (mismatchType == NOT_SET ? "NOT " : "") + "one of ("; ANTLR_USE_NAMESPACE(std)vector elems = set.toArray(); for ( unsigned int i = 0; i < elems.size(); i++ ) { s += " '"; s += charName(elems[i]); s += "'"; } s += "), found '" + charName(foundChar) + "'"; } break; default : s += RecognitionException::getMessage(); break; } return s; } #ifndef NO_STATIC_CONSTS const int MismatchedCharException::CHAR; const int MismatchedCharException::NOT_CHAR; const int MismatchedCharException::RANGE; const int MismatchedCharException::NOT_RANGE; const int MismatchedCharException::SET; const int MismatchedCharException::NOT_SET; #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/MismatchedCharException.hpp000066400000000000000000000036631340051421000214500ustar00rootroot00000000000000#ifndef INC_MismatchedCharException_hpp__ #define INC_MismatchedCharException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: MismatchedCharException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class CharScanner; class ANTLR_API MismatchedCharException : public RecognitionException { public: // Types of chars #ifndef NO_STATIC_CONSTS static const int CHAR = 1; static const int NOT_CHAR = 2; static const int RANGE = 3; static const int NOT_RANGE = 4; static const int SET = 5; static const int NOT_SET = 6; #else enum { CHAR = 1, NOT_CHAR = 2, RANGE = 3, NOT_RANGE = 4, SET = 5, NOT_SET = 6 }; #endif public: // One of the above int mismatchType; // what was found on the input stream int foundChar; // For CHAR/NOT_CHAR and RANGE/NOT_RANGE int expecting; // For RANGE/NOT_RANGE (expecting is lower bound of range) int upper; // For SET/NOT_SET BitSet set; protected: // who knows...they may want to ask scanner questions CharScanner* scanner; public: MismatchedCharException(); // Expected range / not range MismatchedCharException( int c, int lower, int upper_, bool matchNot, CharScanner* scanner_ ); // Expected token / not token MismatchedCharException( int c, int expecting_, bool matchNot, CharScanner* scanner_ ); // Expected BitSet / not BitSet MismatchedCharException( int c, BitSet set_, bool matchNot, CharScanner* scanner_ ); ~MismatchedCharException() throw() {} /** * Returns a clean error message (no line number/column information) */ ANTLR_USE_NAMESPACE(std)string getMessage() const; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_MismatchedCharException_hpp__ gdl-0.9.9/src/antlr/MismatchedTokenException.cpp000066400000000000000000000124521340051421000216420ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: MismatchedTokenException.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/MismatchedTokenException.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif MismatchedTokenException::MismatchedTokenException() : RecognitionException("Mismatched Token: expecting any AST node","",-1,-1) , token(0) , node(nullASTptr) , tokenNames(0) , numTokens(0) { } // Expected range / not range MismatchedTokenException::MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefAST node_, int lower, int upper_, bool matchNot ) : RecognitionException("Mismatched Token","",-1,-1) , token(0) , node(node_) , tokenText( (node_ ? node_->toString(): ANTLR_USE_NAMESPACE(std)string("")) ) , mismatchType(matchNot ? NOT_RANGE : RANGE) , expecting(lower) , upper(upper_) , tokenNames(tokenNames_) , numTokens(numTokens_) { } // Expected token / not token MismatchedTokenException::MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefAST node_, int expecting_, bool matchNot ) : RecognitionException("Mismatched Token","",-1,-1) , token(0) , node(node_) , tokenText( (node_ ? node_->toString(): ANTLR_USE_NAMESPACE(std)string("")) ) , mismatchType(matchNot ? NOT_TOKEN : TOKEN) , expecting(expecting_) , tokenNames(tokenNames_) , numTokens(numTokens_) { } // Expected BitSet / not BitSet MismatchedTokenException::MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefAST node_, BitSet set_, bool matchNot ) : RecognitionException("Mismatched Token","",-1,-1) , token(0) , node(node_) , tokenText( (node_ ? node_->toString(): ANTLR_USE_NAMESPACE(std)string("")) ) , mismatchType(matchNot ? NOT_SET : SET) , set(set_) , tokenNames(tokenNames_) , numTokens(numTokens_) { } // Expected range / not range MismatchedTokenException::MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefToken token_, int lower, int upper_, bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ) : RecognitionException("Mismatched Token",fileName_,token_->getLine(),token_->getColumn()) , token(token_) , node(nullASTptr) , tokenText(token_->getText()) , mismatchType(matchNot ? NOT_RANGE : RANGE) , expecting(lower) , upper(upper_) , tokenNames(tokenNames_) , numTokens(numTokens_) { } // Expected token / not token MismatchedTokenException::MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefToken token_, int expecting_, bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ) : RecognitionException("Mismatched Token",fileName_,token_->getLine(),token_->getColumn()) , token(token_) , node(nullASTptr) , tokenText(token_->getText()) , mismatchType(matchNot ? NOT_TOKEN : TOKEN) , expecting(expecting_) , tokenNames(tokenNames_) , numTokens(numTokens_) { } // Expected BitSet / not BitSet MismatchedTokenException::MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefToken token_, BitSet set_, bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ) : RecognitionException("Mismatched Token",fileName_,token_->getLine(),token_->getColumn()) , token(token_) , node(nullASTptr) , tokenText(token_->getText()) , mismatchType(matchNot ? NOT_SET : SET) , set(set_) , tokenNames(tokenNames_) , numTokens(numTokens_) { } ANTLR_USE_NAMESPACE(std)string MismatchedTokenException::getMessage() const { ANTLR_USE_NAMESPACE(std)string s; switch (mismatchType) { case TOKEN: s += "expecting " + tokenName(expecting) + ", found '" + tokenText + "'"; break; case NOT_TOKEN: s += "expecting anything but " + tokenName(expecting) + "; got it anyway"; break; case RANGE: s += "expecting token in range: " + tokenName(expecting) + ".." + tokenName(upper) + ", found '" + tokenText + "'"; break; case NOT_RANGE: s += "expecting token NOT in range: " + tokenName(expecting) + ".." + tokenName(upper) + ", found '" + tokenText + "'"; break; case SET: case NOT_SET: { s += ANTLR_USE_NAMESPACE(std)string("expecting ") + (mismatchType == NOT_SET ? "NOT " : "") + "one of ("; ANTLR_USE_NAMESPACE(std)vector elems = set.toArray(); for ( unsigned int i = 0; i < elems.size(); i++ ) { s += " "; s += tokenName(elems[i]); } s += "), found '" + tokenText + "'"; } break; default: s = RecognitionException::getMessage(); break; } return s; } ANTLR_USE_NAMESPACE(std)string MismatchedTokenException::tokenName(int tokenType) const { if (tokenType == Token::INVALID_TYPE) return ""; else if (tokenType < 0 || tokenType >= numTokens) return ANTLR_USE_NAMESPACE(std)string("<") + tokenType + ">"; else return tokenNames[tokenType]; } #ifndef NO_STATIC_CONSTS const int MismatchedTokenException::TOKEN; const int MismatchedTokenException::NOT_TOKEN; const int MismatchedTokenException::RANGE; const int MismatchedTokenException::NOT_RANGE; const int MismatchedTokenException::SET; const int MismatchedTokenException::NOT_SET; #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/MismatchedTokenException.hpp000066400000000000000000000061131340051421000216440ustar00rootroot00000000000000#ifndef INC_MismatchedTokenException_hpp__ #define INC_MismatchedTokenException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: MismatchedTokenException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API MismatchedTokenException : public RecognitionException { public: MismatchedTokenException(); /// Expected range / not range MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefAST node_, int lower, int upper_, bool matchNot ); // Expected token / not token MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefAST node_, int expecting_, bool matchNot ); // Expected BitSet / not BitSet MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefAST node_, BitSet set_, bool matchNot ); // Expected range / not range MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefToken token_, int lower, int upper_, bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ); // Expected token / not token MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefToken token_, int expecting_, bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ); // Expected BitSet / not BitSet MismatchedTokenException( const char* const* tokenNames_, const int numTokens_, RefToken token_, BitSet set_, bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ); ~MismatchedTokenException() throw() {} /** * Returns a clean error message (no line number/column information) */ ANTLR_USE_NAMESPACE(std)string getMessage() const; public: /// The token that was encountered const RefToken token; /// The offending AST node if tree walking const RefAST node; /// taken from node or token object ANTLR_USE_NAMESPACE(std)string tokenText; /// Types of tokens #ifndef NO_STATIC_CONSTS static const int TOKEN = 1; static const int NOT_TOKEN = 2; static const int RANGE = 3; static const int NOT_RANGE = 4; static const int SET = 5; static const int NOT_SET = 6; #else enum { TOKEN = 1, NOT_TOKEN = 2, RANGE = 3, NOT_RANGE = 4, SET = 5, NOT_SET = 6 }; #endif public: /// One of the above int mismatchType; /// For TOKEN/NOT_TOKEN and RANGE/NOT_RANGE int expecting; /// For RANGE/NOT_RANGE (expecting is lower bound of range) int upper; /// For SET/NOT_SET BitSet set; private: /// Token names array for formatting const char* const* tokenNames; /// Max number of tokens in tokenNames const int numTokens; /// Return token name for tokenType ANTLR_USE_NAMESPACE(std)string tokenName(int tokenType) const; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_MismatchedTokenException_hpp__ gdl-0.9.9/src/antlr/NoViableAltException.cpp000066400000000000000000000024171340051421000207230ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: NoViableAltException.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/NoViableAltException.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_USING_NAMESPACE(std) NoViableAltException::NoViableAltException(RefAST t) : RecognitionException("NoViableAlt","",-1,-1), token(0), node(t) { } NoViableAltException::NoViableAltException( RefToken t, const ANTLR_USE_NAMESPACE(std)string& fileName_ ) : RecognitionException("NoViableAlt",fileName_,t->getLine(),t->getColumn()), token(t), node(nullASTptr) { } ANTLR_USE_NAMESPACE(std)string NoViableAltException::getMessage() const { if (token) { if( token->getType() == Token::EOF_TYPE ) return string("unexpected end of file"); else if( token->getType() == Token::NULL_TREE_LOOKAHEAD ) return string("unexpected end of tree"); else return string("unexpected token: ")+token->getText(); } // must a tree parser error if token==null if (!node) return "unexpected end of subtree"; return string("unexpected AST node: ")+node->toString(); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/NoViableAltException.hpp000066400000000000000000000020001340051421000207140ustar00rootroot00000000000000#ifndef INC_NoViableAltException_hpp__ #define INC_NoViableAltException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: NoViableAltException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API NoViableAltException : public RecognitionException { public: const RefToken token; const RefAST node; // handles parsing and treeparsing NoViableAltException(RefAST t); NoViableAltException(RefToken t,const ANTLR_USE_NAMESPACE(std)string& fileName_); ~NoViableAltException() throw() {} /** * Returns a clean error message (no line number/column information) */ ANTLR_USE_NAMESPACE(std)string getMessage() const; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_NoViableAltException_hpp__ gdl-0.9.9/src/antlr/NoViableAltForCharException.cpp000066400000000000000000000020731340051421000221660ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: NoViableAltForCharException.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/NoViableAltForCharException.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif NoViableAltForCharException::NoViableAltForCharException(int c, CharScanner* scanner) : RecognitionException("NoViableAlt", scanner->getFilename(), scanner->getLine(),scanner->getColumn()), foundChar(c) { } NoViableAltForCharException::NoViableAltForCharException( int c, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_, int column_) : RecognitionException("NoViableAlt",fileName_,line_,column_), foundChar(c) { } ANTLR_USE_NAMESPACE(std)string NoViableAltForCharException::getMessage() const { return ANTLR_USE_NAMESPACE(std)string("unexpected char: ")+charName(foundChar); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/NoViableAltForCharException.hpp000066400000000000000000000020551340051421000221730ustar00rootroot00000000000000#ifndef INC_NoViableAltForCharException_hpp__ # define INC_NoViableAltForCharException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: NoViableAltForCharException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ # include # include # include # ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { # endif class ANTLR_API NoViableAltForCharException : public RecognitionException { public: NoViableAltForCharException(int c, CharScanner* scanner); NoViableAltForCharException(int c, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_, int column_); virtual ~NoViableAltForCharException() throw() { } /// Returns a clean error message (no line number/column information) ANTLR_USE_NAMESPACE(std)string getMessage() const; protected: int foundChar; }; # ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } # endif #endif //INC_NoViableAltForCharException_hpp__ gdl-0.9.9/src/antlr/Parser.cpp000066400000000000000000000144601340051421000161410ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: Parser.cpp,v 1.5 2012-11-13 14:30:14 m_schellens Exp $ */ // g++-4.3 needs this #include #include #include "antlr/Parser.hpp" #include "antlr/BitSet.hpp" #include "antlr/TokenBuffer.hpp" #include "antlr/MismatchedTokenException.hpp" //#include "antlr/ASTFactory.hpp" #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_C_USING(exit) /**A generic ANTLR parser (LL(k) for k>=1) containing a bunch of * utility routines useful at any lookahead depth. We distinguish between * the LL(1) and LL(k) parsers because of efficiency. This may not be * necessary in the near future. * * Each parser object contains the state of the parse including a lookahead * cache (the form of which is determined by the subclass), whether or * not the parser is in guess mode, where tokens come from, etc... * *

* During guess mode, the current lookahead token(s) and token type(s) * cache must be saved because the token stream may not have been informed * to save the token (via mark) before the try block. * Guessing is started by: *

    *
  1. saving the lookahead cache. *
  2. marking the current position in the TokenBuffer. *
  3. increasing the guessing level. *
* * After guessing, the parser state is restored by: *
    *
  1. restoring the lookahead cache. *
  2. rewinding the TokenBuffer. *
  3. decreasing the guessing level. *
* * @see antlr.Token * @see antlr.TokenBuffer * @see antlr.TokenStream * @see antlr.LL1Parser * @see antlr.LLkParser */ bool DEBUG_PARSER=false; Parser::Parser(TokenBuffer& input) : inputState(new ParserInputState(input)), astFactory(0), traceDepth(0) { } Parser::Parser(TokenBuffer* input) : inputState(new ParserInputState(input)), astFactory(0), traceDepth(0) { } Parser::Parser(const ParserSharedInputState& state) : inputState(state), astFactory(0), traceDepth(0) { } Parser::~Parser() { } /** Consume tokens until one matches the given token */ void Parser::consumeUntil(int tokenType) { while (LA(1) != Token::EOF_TYPE && LA(1) != tokenType) consume(); } /** Consume tokens until one matches the given token set */ void Parser::consumeUntil(const BitSet& set) { while (LA(1) != Token::EOF_TYPE && !set.member(LA(1))) consume(); } /**Make sure current lookahead symbol matches token type t. * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ void Parser::match(int t) { if ( DEBUG_PARSER ) { traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "enter match(" << t << ") with LA(1)=" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; } if ( LA(1)!=t ) { if ( DEBUG_PARSER ) { traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "token mismatch: " << LA(1) << "!=" << t << ANTLR_USE_NAMESPACE(std)endl; } throw MismatchedTokenException(getTokenNames(), getNumTokens(), LT(1), t, false, getFilename()); } else { // mark token as consumed -- fetch next token deferred until LA/LT consume(); } } /**Make sure current lookahead symbol matches the given set * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ void Parser::match(const BitSet& b) { if ( DEBUG_PARSER ) { traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "enter match(" << "bitset" /*b.toString()*/ << ") with LA(1)=" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; } if ( !b.member(LA(1)) ) { if ( DEBUG_PARSER ) { traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "token mismatch: " << LA(1) << " not member of " << "bitset" /*b.toString()*/ << ANTLR_USE_NAMESPACE(std)endl; } throw MismatchedTokenException(getTokenNames(), getNumTokens(), LT(1), b, false, getFilename()); } else { // mark token as consumed -- fetch next token deferred until LA/LT consume(); } } void Parser::matchNot(int t) { if ( LA(1)==t ) { // Throws inverted-sense exception throw MismatchedTokenException(getTokenNames(), getNumTokens(), LT(1), t, true, getFilename()); } else { // mark token as consumed -- fetch next token deferred until LA/LT consume(); } } void Parser::panic() { ANTLR_USE_NAMESPACE(std)cerr << "Parser: panic" << ANTLR_USE_NAMESPACE(std)endl; exit(1); } /** Parser error-reporting function can be overridden in subclass */ void Parser::reportError(const RecognitionException& ex) { ANTLR_USE_NAMESPACE(std)cerr << ex.toString().c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Parser error-reporting function can be overridden in subclass */ void Parser::reportError(const ANTLR_USE_NAMESPACE(std)string& s) { if ( getFilename()=="" ) ANTLR_USE_NAMESPACE(std)cerr << "error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; else ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Parser warning-reporting function can be overridden in subclass */ void Parser::reportWarning(const ANTLR_USE_NAMESPACE(std)string& s) { if ( getFilename()=="" ) ANTLR_USE_NAMESPACE(std)cerr << "warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; else ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Set or change the input token buffer */ // void setTokenBuffer(TokenBuffer* t); void Parser::traceIndent() { for( int i = 0; i < traceDepth; i++ ) ANTLR_USE_NAMESPACE(std)cout << " "; ANTLR_USE_NAMESPACE(std)cout << ANTLR_USE_NAMESPACE(std)setw(3) << traceDepth << " "; } void Parser::traceIn(const char* rname) { traceDepth++; if(inputState->guessing>0) return; for( int i = 0; i < traceDepth; i++ ) ANTLR_USE_NAMESPACE(std)cout << " "; ANTLR_USE_NAMESPACE(std)cout << "> " << rname << "; LA(1)==" << LT(1)->getText().c_str() << ((inputState->guessing>0)?" [guessing]":"") << ANTLR_USE_NAMESPACE(std)endl; } void Parser::traceOut(const char* rname) { if(inputState->guessing<=0) { for( int i = 0; i < traceDepth; i++ ) ANTLR_USE_NAMESPACE(std)cout << " "; ANTLR_USE_NAMESPACE(std)cout << "< " << rname << "; LA(1)==" << LT(1)->getText().c_str() << ((inputState->guessing>0)?" [guessing]":"") << ANTLR_USE_NAMESPACE(std)endl; } traceDepth--; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/Parser.hpp000066400000000000000000000154101340051421000161420ustar00rootroot00000000000000#ifndef INC_Parser_hpp__ #define INC_Parser_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: Parser.hpp,v 1.2 2012-11-13 14:30:14 m_schellens Exp $ */ #include #include #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif extern bool DEBUG_PARSER; /** A generic ANTLR parser (LL(k) for k>=1) containing a bunch of * utility routines useful at any lookahead depth. We distinguish between * the LL(1) and LL(k) parsers because of efficiency. This may not be * necessary in the near future. * * Each parser object contains the state of the parse including a lookahead * cache (the form of which is determined by the subclass), whether or * not the parser is in guess mode, where tokens come from, etc... * *

* During guess mode, the current lookahead token(s) and token type(s) * cache must be saved because the token stream may not have been informed * to save the token (via mark) before the try block. * Guessing is started by: *

    *
  1. saving the lookahead cache. *
  2. marking the current position in the TokenBuffer. *
  3. increasing the guessing level. *
* * After guessing, the parser state is restored by: *
    *
  1. restoring the lookahead cache. *
  2. rewinding the TokenBuffer. *
  3. decreasing the guessing level. *
* * @see antlr.Token * @see antlr.TokenBuffer * @see antlr.TokenStream * @see antlr.LL1Parser * @see antlr.LLkParser * * @todo add constructors with ASTFactory. */ class ANTLR_API Parser { protected: Parser(TokenBuffer& input_); Parser(TokenBuffer* input_); Parser(const ParserSharedInputState& state); public: virtual ~Parser(); /** Return the token type of the ith token of lookahead where i=1 * is the current token being examined by the parser (i.e., it * has not been matched yet). */ virtual int LA(unsigned int i)=0; /// Return the i-th token of lookahead virtual RefToken LT(unsigned int i)=0; /** DEPRECATED! Specify the factory to be used during tree building. (Compulsory) * Setting the factory is nowadays compulsory. * @see setASTFactory */ virtual void setASTNodeFactory( ASTFactory *factory ) { astFactory = factory; } /** Specify the factory to be used during tree building. (Compulsory) * Setting the factory is nowadays compulsory. */ virtual void setASTFactory( ASTFactory *factory ) { astFactory = factory; } /** Return a pointer to the ASTFactory used. * So you might use it in subsequent treewalkers or to reload AST's * from disk. */ virtual ASTFactory* getASTFactory() { return astFactory; } /** Get the root AST node of the generated AST. When using a custom AST type * or heterogenous AST's, you'll have to convert it to the right type * yourself. */ virtual RefAST getAST() = 0; /// Return the filename of the input file. virtual inline ANTLR_USE_NAMESPACE(std)string getFilename() const { return inputState->filename; } /// Set the filename of the input file (used for error reporting). virtual void setFilename(const ANTLR_USE_NAMESPACE(std)string& f) { inputState->filename = f; } virtual void setInputState(ParserSharedInputState state) { inputState = state; } virtual inline ParserSharedInputState getInputState() const { return inputState; } /// Get another token object from the token stream virtual void consume()=0; /// Consume tokens until one matches the given token virtual void consumeUntil(int tokenType); /// Consume tokens until one matches the given token set virtual void consumeUntil(const BitSet& set); /** Make sure current lookahead symbol matches token type t. * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ virtual void match(int t); virtual void matchNot(int t); /** Make sure current lookahead symbol matches the given set * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ virtual void match(const BitSet& b); /** Mark a spot in the input and return the position. * Forwarded to TokenBuffer. */ virtual inline unsigned int mark() { return inputState->getInput().mark(); } /// rewind to a previously marked position virtual inline void rewind(unsigned int pos) { inputState->getInput().rewind(pos); } /// Parser error-reporting function can be overridden in subclass virtual void reportError(const RecognitionException& ex); /// Parser error-reporting function can be overridden in subclass virtual void reportError(const ANTLR_USE_NAMESPACE(std)string& s); /// Parser warning-reporting function can be overridden in subclass virtual void reportWarning(const ANTLR_USE_NAMESPACE(std)string& s); /** Give panic message and exit the program. can be overridden in subclass * @deprecated this method is unused and will dissappear in the next release */ virtual void panic(); /// get the token name for the token number 'num' virtual const char* getTokenName(int num) const = 0; /// get a vector with all token names virtual const char* const* getTokenNames() const = 0; /** Get the number of tokens defined. * This one should be overridden in subclasses. */ virtual int getNumTokens(void) const = 0; /** Set or change the input token buffer */ // void setTokenBuffer(TokenBuffer* t); virtual void traceIndent(); virtual void traceIn(const char* rname); virtual void traceOut(const char* rname); protected: // void setTokenNames(const char** tokenNames_); ParserSharedInputState inputState; // /// AST return value for a rule is squirreled away here // RefAST returnAST; /// AST support code; parser and treeparser delegate to this object ASTFactory *astFactory; // used to keep track of the indentation for the trace int traceDepth; /** Utility class which allows tracing to work even when exceptions are * thrown. */ class Tracer { /*{{{*/ private: Parser* parser; const char* text; public: Tracer(Parser* p,const char * t) : parser(p), text(t) { parser->traceIn(text); } ~Tracer() { #ifdef ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION // Only give trace if there's no uncaught exception.. // if(!ANTLR_USE_NAMESPACE(std)uncaught_exception()) #endif parser->traceOut(text); } private: Tracer(const Tracer&); // undefined const Tracer& operator=(const Tracer&); // undefined /*}}}*/ }; private: Parser(const Parser&); // undefined const Parser& operator=(const Parser&); // undefined }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_Parser_hpp__ gdl-0.9.9/src/antlr/ParserSharedInputState.hpp000066400000000000000000000040531340051421000213130ustar00rootroot00000000000000#ifndef INC_ParserSharedInputState_hpp__ #define INC_ParserSharedInputState_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ParserSharedInputState.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** This object contains the data associated with an * input stream of tokens. Multiple parsers * share a single ParserSharedInputState to parse * the same stream of tokens. */ class ANTLR_API ParserInputState { public: /** Construct a new ParserInputState * @param in the TokenBuffer to read from. The object is deleted together * with the ParserInputState object. */ ParserInputState( TokenBuffer* in ) : guessing(0) , filename() , input(in) , inputResponsible(true) { } /** Construct a new ParserInputState * @param in the TokenBuffer to read from. */ ParserInputState( TokenBuffer& in ) : guessing(0) , filename("") , input(&in) , inputResponsible(false) { } virtual ~ParserInputState() { if (inputResponsible) delete input; } TokenBuffer& getInput( void ) { return *input; } /// Reset the ParserInputState and the underlying TokenBuffer void reset( void ) { input->reset(); guessing = 0; } public: /** Are we guessing (guessing>0)? */ int guessing; /** What file (if known) caused the problem? * @todo wrap this one.. */ ANTLR_USE_NAMESPACE(std)string filename; private: /** Where to get token objects */ TokenBuffer* input; /// Do we need to free the TokenBuffer or is it owned by another.. bool inputResponsible; // we don't want these: ParserInputState(const ParserInputState&); ParserInputState& operator=(const ParserInputState&); }; /// A reference counted ParserInputState typedef RefCount ParserSharedInputState; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ParserSharedInputState_hpp__ gdl-0.9.9/src/antlr/RecognitionException.cpp000066400000000000000000000032461340051421000210440ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: RecognitionException.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/RecognitionException.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif RecognitionException::RecognitionException() : ANTLRException("parsing error") , line(-1) , column(-1) { } RecognitionException::RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s) : ANTLRException(s) , line(-1) , column(-1) { } RecognitionException::RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_,int column_) : ANTLRException(s) , fileName(fileName_) , line(line_) , column(column_) { } ANTLR_USE_NAMESPACE(std)string RecognitionException::getFileLineColumnString() const { ANTLR_USE_NAMESPACE(std)string fileLineColumnString; if ( fileName.length() > 0 ) fileLineColumnString = fileName + ":"; if ( line != -1 ) { if ( fileName.length() == 0 ) fileLineColumnString = fileLineColumnString + "line "; fileLineColumnString = fileLineColumnString + line; if ( column != -1 ) fileLineColumnString = fileLineColumnString + ":" + column; fileLineColumnString = fileLineColumnString + ":"; } fileLineColumnString = fileLineColumnString + " "; return fileLineColumnString; } ANTLR_USE_NAMESPACE(std)string RecognitionException::toString() const { return getFileLineColumnString()+getMessage(); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/RecognitionException.hpp000066400000000000000000000035611340051421000210510ustar00rootroot00000000000000#ifndef INC_RecognitionException_hpp__ # define INC_RecognitionException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: RecognitionException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ # include # include # ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { # endif class ANTLR_API RecognitionException : public ANTLRException { public: RecognitionException(); RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s); RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_,int column_); virtual ~RecognitionException() throw() { } /// Return file where mishap occurred. virtual ANTLR_USE_NAMESPACE(std)string getFilename() const { return fileName; } /** * @return the line number that this exception happened on. */ virtual int getLine() const { return line; } /** * @return the column number that this exception happened on. */ virtual int getColumn() const { return column; } #if 0 /** * @deprecated As of ANTLR 2.7.0 */ virtual ANTLR_USE_NAMESPACE(std)string getErrorMessage() const { return getMessage(); } #endif /// Return complete error message with line/column number info (if present) virtual ANTLR_USE_NAMESPACE(std)string toString() const; /// See what file/line/column info is present and return it as a string virtual ANTLR_USE_NAMESPACE(std)string getFileLineColumnString() const; protected: ANTLR_USE_NAMESPACE(std)string fileName; // not used by treeparsers int line; // not used by treeparsers int column; // not used by treeparsers }; # ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } # endif #endif //INC_RecognitionException_hpp__ gdl-0.9.9/src/antlr/RefCount.hpp000066400000000000000000000026201340051421000164320ustar00rootroot00000000000000#ifndef INC_RefCount_hpp__ #define INC_RefCount_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: RefCount.hpp,v 1.2 2010-03-09 23:54:39 m_schellens Exp $ */ #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif template class ANTLR_API RefCount { private: struct Ref { T* const ptr; unsigned int count; Ref(T* p) : ptr(p), count(1) {} ~Ref() {delete ptr;} Ref* increment() {++count;return this;} bool decrement() {return (--count==0);} private: Ref(const Ref&); Ref& operator=(const Ref&); }* ref; public: explicit RefCount(T* p = 0) : ref(p ? new Ref(p) : 0) { } RefCount(const RefCount& other) : ref(other.ref ? other.ref->increment() : 0) { } ~RefCount() { if (ref && ref->decrement()) delete ref; } RefCount& operator=(const RefCount& other) { Ref* tmp = other.ref ? other.ref->increment() : 0; if (ref && ref->decrement()) delete ref; ref = tmp; return *this; } operator T* () const { return ref ? ref->ptr : 0; } T* operator->() const { return ref ? ref->ptr : 0; } T* get() const { return ref ? ref->ptr : 0; } template operator RefCount() { return RefCount(ref); } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_RefCount_hpp__ gdl-0.9.9/src/antlr/SemanticException.hpp000066400000000000000000000016351340051421000203340ustar00rootroot00000000000000#ifndef INC_SemanticException_hpp__ #define INC_SemanticException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: SemanticException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API SemanticException : public RecognitionException { public: SemanticException(const ANTLR_USE_NAMESPACE(std)string& s) : RecognitionException(s) { } SemanticException(const ANTLR_USE_NAMESPACE(std)string& s, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_,int column_) : RecognitionException(s,fileName_,line_,column_) { } ~SemanticException() throw() { } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_SemanticException_hpp__ gdl-0.9.9/src/antlr/String.cpp000066400000000000000000000022731340051421000161520ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: String.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/String.hpp" #include #ifdef HAS_NOT_CSTDIO_H #include #else #include #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_C_USING(sprintf) ANTLR_USE_NAMESPACE(std)string operator+( const ANTLR_USE_NAMESPACE(std)string& lhs, const int rhs ) { char tmp[100]; sprintf(tmp,"%d",rhs); return lhs+tmp; } /** Convert character to readable string */ ANTLR_USE_NAMESPACE(std)string charName(int ch) { if (ch == EOF) return "EOF"; else { ANTLR_USE_NAMESPACE(std)string s; #ifdef ANTLR_CCTYPE_NEEDS_STD if( ANTLR_USE_NAMESPACE(std)isprint( ch ) ) #else if( isprint( ch ) ) #endif { s.append("'"); s += ch; s.append("'"); // s += "'"+ch+"'"; } else { s += "0x"; unsigned int t = ch >> 4; if( t < 10 ) s += t | 0x30; else s += t + 0x37; t = ch & 0xF; if( t < 10 ) s += t | 0x30; else s += t + 0x37; } return s; } } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/String.hpp000066400000000000000000000011501340051421000161500ustar00rootroot00000000000000#ifndef INC_String_hpp__ #define INC_String_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: String.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_API ANTLR_USE_NAMESPACE(std)string operator+(const ANTLR_USE_NAMESPACE(std)string& lhs,const int rhs); ANTLR_API ANTLR_USE_NAMESPACE(std)string charName(int ch); #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_String_hpp__ gdl-0.9.9/src/antlr/Token.cpp000066400000000000000000000031221340051421000157560ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: Token.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/Token.hpp" #include "antlr/String.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif // The below initialization ICED AIX Visualage CC //ANTLR_API RefToken Token::badToken(new Token(Token::INVALID_TYPE, "")); // this seemed to work // RK: maybe the above one is necessary for MSVC DLL build. // leaving it unchanged untill after testing.. ANTLR_API RefToken Token::badToken = RefToken(new Token(Token::INVALID_TYPE, "")); Token::Token() : type(INVALID_TYPE) { } Token::Token(int t) : type(t) { } Token::Token(int t, const ANTLR_USE_NAMESPACE(std)string& txt) : type(t) { setText(txt); } int Token::getColumn() const { return 0; } int Token::getLine() const { return 0; } ANTLR_USE_NAMESPACE(std)string Token::getText() const { return ""; } int Token::getType() const { return type; } void Token::setColumn(int) {} void Token::setLine(int) {} void Token::setText(const ANTLR_USE_NAMESPACE(std)string&) {} void Token::setType(int t) { type = t; } ANTLR_USE_NAMESPACE(std)string Token::toString() const { return "[\""+getText()+"\",<"+type+">]"; } Token::~Token() {} ANTLR_API RefToken nullToken; #ifndef NO_STATIC_CONSTS const int Token::MIN_USER_TYPE; const int Token::NULL_TREE_LOOKAHEAD; const int Token::INVALID_TYPE; const int Token::EOF_TYPE; const int Token::SKIP; #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/Token.hpp000066400000000000000000000040241340051421000157650ustar00rootroot00000000000000#ifndef INC_Token_hpp__ #define INC_Token_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: Token.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** A token is minimally a token type. Subclasses can add the text matched * for the token and line info. */ class ANTLR_API Token; typedef RefCount RefToken; class ANTLR_API Token { public: // constants #ifndef NO_STATIC_CONSTS static const int MIN_USER_TYPE = 4; static const int NULL_TREE_LOOKAHEAD = 3; static const int INVALID_TYPE = 0; static const int EOF_TYPE = 1; static const int SKIP = -1; #else enum { MIN_USER_TYPE = 4, NULL_TREE_LOOKAHEAD = 3, INVALID_TYPE = 0, EOF_TYPE = 1, SKIP = -1 }; #endif // each Token has at least a token type int type; //=INVALID_TYPE; public: // the illegal token object static RefToken badToken; // = new Token(INVALID_TYPE, ""); Token(); Token(int t); Token(int t, const ANTLR_USE_NAMESPACE(std)string& txt); virtual int getColumn() const; virtual int getLine() const; virtual ANTLR_USE_NAMESPACE(std)string getText() const; virtual int getType() const; virtual void setColumn(int c); virtual void setLine(int l); virtual void setText(const ANTLR_USE_NAMESPACE(std)string& t); virtual void setType(int t); virtual ANTLR_USE_NAMESPACE(std)string toString() const; virtual ~Token(); private: Token(const Token&); const Token& operator=(const Token&); }; extern ANTLR_API RefToken nullToken; #ifdef NEEDS_OPERATOR_LESS_THAN // RK: Added after 2.7.2 previously it was undefined. // AL: what to return if l and/or r point to nullToken??? inline bool operator<( RefToken l, RefToken r ) { return nullToken == l ? ( nullToken == r ? false : true ) : l->getType() < r->getType(); } #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_Token_hpp__ gdl-0.9.9/src/antlr/TokenBuffer.cpp000066400000000000000000000042211340051421000171110ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenBuffer.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/TokenBuffer.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /**A Stream of Token objects fed to the parser from a TokenStream that can * be rewound via mark()/rewind() methods. *

* A dynamic array is used to buffer up all the input tokens. Normally, * "k" tokens are stored in the buffer. More tokens may be stored during * guess mode (testing syntactic predicate), or when LT(i>k) is referenced. * Consumption of tokens is deferred. In other words, reading the next * token is not done by conume(), but deferred until needed by LA or LT. *

* * @see antlr.Token * @see antlr.TokenStream * @see antlr.TokenQueue */ /** Create a token buffer */ TokenBuffer::TokenBuffer( TokenStream& input_ ) : input(input_) , nMarkers(0) , markerOffset(0) , numToConsume(0) { } TokenBuffer::~TokenBuffer( void ) { } /** Ensure that the token buffer is sufficiently full */ void TokenBuffer::fill(unsigned int amount) { syncConsume(); // Fill the buffer sufficiently to hold needed tokens while (queue.entries() <= (amount + markerOffset)) { // Append the next token queue.append(input.nextToken()); } } /** Get a lookahead token value */ int TokenBuffer::LA(unsigned int i) { fill(i); return queue.elementAt(markerOffset+i-1)->type; } /** Get a lookahead token */ RefToken TokenBuffer::LT(unsigned int i) { fill(i); return queue.elementAt(markerOffset+i-1); } /** Return an integer marker that can be used to rewind the buffer to * its current state. */ unsigned int TokenBuffer::mark() { syncConsume(); nMarkers++; return markerOffset; } /**Rewind the token buffer to a marker. * @param mark Marker returned previously from mark() */ void TokenBuffer::rewind(unsigned int mark) { syncConsume(); markerOffset=mark; nMarkers--; } /// Get number of non-consumed tokens unsigned int TokenBuffer::entries() const { return queue.entries() - markerOffset; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/TokenBuffer.hpp000066400000000000000000000055021340051421000171210ustar00rootroot00000000000000#ifndef INC_TokenBuffer_hpp__ #define INC_TokenBuffer_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenBuffer.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /**A Stream of Token objects fed to the parser from a TokenStream that can * be rewound via mark()/rewind() methods. *

* A dynamic array is used to buffer up all the input tokens. Normally, * "k" tokens are stored in the buffer. More tokens may be stored during * guess mode (testing syntactic predicate), or when LT(i>k) is referenced. * Consumption of tokens is deferred. In other words, reading the next * token is not done by conume(), but deferred until needed by LA or LT. *

* * @todo: see if we can integrate this one with InputBuffer into one template * or so. * * @see antlr.Token * @see antlr.TokenStream * @see antlr.TokenQueue */ class ANTLR_API TokenBuffer { public: /** Create a token buffer */ TokenBuffer(TokenStream& input_); virtual ~TokenBuffer(); /// Reset the input buffer to empty state inline void reset( void ) { nMarkers = 0; markerOffset = 0; numToConsume = 0; queue.clear(); } /** Get a lookahead token value */ int LA( unsigned int i ); /** Get a lookahead token */ RefToken LT( unsigned int i ); /** Return an integer marker that can be used to rewind the buffer to * its current state. */ unsigned int mark(); /**Rewind the token buffer to a marker. * @param mark Marker returned previously from mark() */ void rewind(unsigned int mark); /** Mark another token for deferred consumption */ inline void consume() { numToConsume++; } /// Return the number of entries in the TokenBuffer virtual unsigned int entries() const; private: /** Ensure that the token buffer is sufficiently full */ void fill(unsigned int amount); /** Sync up deferred consumption */ void syncConsume(); protected: /// Token source TokenStream& input; /// Number of active markers unsigned int nMarkers; /// Additional offset used when markers are active unsigned int markerOffset; /// Number of calls to consume() since last LA() or LT() call unsigned int numToConsume; /// Circular queue with Tokens CircularQueue queue; private: TokenBuffer(const TokenBuffer& other); const TokenBuffer& operator=(const TokenBuffer& other); }; /** Sync up deferred consumption */ inline void TokenBuffer::syncConsume() { if (numToConsume > 0) { if (nMarkers > 0) markerOffset += numToConsume; else queue.removeItems( numToConsume ); numToConsume = 0; } } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenBuffer_hpp__ gdl-0.9.9/src/antlr/TokenStream.hpp000066400000000000000000000013011340051421000171340ustar00rootroot00000000000000#ifndef INC_TokenStream_hpp__ #define INC_TokenStream_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStream.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** This interface allows any object to pretend it is a stream * of tokens. * @author Terence Parr, MageLang Institute */ class ANTLR_API TokenStream { public: virtual RefToken nextToken()=0; virtual ~TokenStream() { } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStream_hpp__ gdl-0.9.9/src/antlr/TokenStreamBasicFilter.cpp000066400000000000000000000017211340051421000212450ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamBasicFilter.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/TokenStreamBasicFilter.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** This object is a TokenStream that passes through all * tokens except for those that you tell it to discard. * There is no buffering of the tokens. */ TokenStreamBasicFilter::TokenStreamBasicFilter(TokenStream& input_) : input(&input_) { } void TokenStreamBasicFilter::discard(int ttype) { discardMask.add(ttype); } void TokenStreamBasicFilter::discard(const BitSet& mask) { discardMask = mask; } RefToken TokenStreamBasicFilter::nextToken() { RefToken tok = input->nextToken(); while ( tok && discardMask.member(tok->getType()) ) { tok = input->nextToken(); } return tok; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/TokenStreamBasicFilter.hpp000066400000000000000000000020341340051421000212500ustar00rootroot00000000000000#ifndef INC_TokenStreamBasicFilter_hpp__ #define INC_TokenStreamBasicFilter_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamBasicFilter.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** This object is a TokenStream that passes through all * tokens except for those that you tell it to discard. * There is no buffering of the tokens. */ class ANTLR_API TokenStreamBasicFilter : public TokenStream { /** The set of token types to discard */ protected: BitSet discardMask; /** The input stream */ protected: TokenStream* input; public: TokenStreamBasicFilter(TokenStream& input_); void discard(int ttype); void discard(const BitSet& mask); RefToken nextToken(); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamBasicFilter_hpp__ gdl-0.9.9/src/antlr/TokenStreamException.hpp000066400000000000000000000014201340051421000210150ustar00rootroot00000000000000#ifndef INC_TokenStreamException_hpp__ #define INC_TokenStreamException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API TokenStreamException : public ANTLRException { public: TokenStreamException() : ANTLRException() { } TokenStreamException(const ANTLR_USE_NAMESPACE(std)string& s) : ANTLRException(s) { } virtual ~TokenStreamException() throw() { } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamException_hpp__ gdl-0.9.9/src/antlr/TokenStreamHiddenTokenFilter.cpp000066400000000000000000000102701340051421000224170ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamHiddenTokenFilter.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/TokenStreamHiddenTokenFilter.hpp" #include "antlr/CommonHiddenStreamToken.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /**This object filters a token stream coming from a lexer * or another TokenStream so that only certain token channels * get transmitted to the parser. * * Any of the channels can be filtered off as "hidden" channels whose * tokens can be accessed from the parser. */ TokenStreamHiddenTokenFilter::TokenStreamHiddenTokenFilter(TokenStream& input) : TokenStreamBasicFilter(input) { } void TokenStreamHiddenTokenFilter::consume() { nextMonitoredToken = input->nextToken(); } void TokenStreamHiddenTokenFilter::consumeFirst() { consume(); // Handle situation where hidden or discarded tokens // appear first in input stream RefToken p; // while hidden or discarded scarf tokens while ( hideMask.member(LA(1)->getType()) || discardMask.member(LA(1)->getType()) ) { if ( hideMask.member(LA(1)->getType()) ) { if ( !p ) { p = LA(1); } else { static_cast(p.get())->setHiddenAfter(LA(1)); static_cast(LA(1).get())->setHiddenBefore(p); // double-link p = LA(1); } lastHiddenToken = p; if (!firstHidden) firstHidden = p; // record hidden token if first } consume(); } } BitSet TokenStreamHiddenTokenFilter::getDiscardMask() const { return discardMask; } /** Return a ptr to the hidden token appearing immediately after * token t in the input stream. */ RefToken TokenStreamHiddenTokenFilter::getHiddenAfter(RefToken t) { return static_cast(t.get())->getHiddenAfter(); } /** Return a ptr to the hidden token appearing immediately before * token t in the input stream. */ RefToken TokenStreamHiddenTokenFilter::getHiddenBefore(RefToken t) { return static_cast(t.get())->getHiddenBefore(); } BitSet TokenStreamHiddenTokenFilter::getHideMask() const { return hideMask; } /** Return the first hidden token if one appears * before any monitored token. */ RefToken TokenStreamHiddenTokenFilter::getInitialHiddenToken() { return firstHidden; } void TokenStreamHiddenTokenFilter::hide(int m) { hideMask.add(m); } void TokenStreamHiddenTokenFilter::hide(const BitSet& mask) { hideMask = mask; } RefToken TokenStreamHiddenTokenFilter::LA(int) { return nextMonitoredToken; } /** Return the next monitored token. * Test the token following the monitored token. * If following is another monitored token, save it * for the next invocation of nextToken (like a single * lookahead token) and return it then. * If following is unmonitored, nondiscarded (hidden) * channel token, add it to the monitored token. * * Note: EOF must be a monitored Token. */ RefToken TokenStreamHiddenTokenFilter::nextToken() { // handle an initial condition; don't want to get lookahead // token of this splitter until first call to nextToken if ( !LA(1) ) { consumeFirst(); } // we always consume hidden tokens after monitored, thus, // upon entry LA(1) is a monitored token. RefToken monitored = LA(1); // point to hidden tokens found during last invocation static_cast(monitored.get())->setHiddenBefore(lastHiddenToken); lastHiddenToken = nullToken; // Look for hidden tokens, hook them into list emanating // from the monitored tokens. consume(); RefToken p = monitored; // while hidden or discarded scarf tokens while ( hideMask.member(LA(1)->getType()) || discardMask.member(LA(1)->getType()) ) { if ( hideMask.member(LA(1)->getType()) ) { // attach the hidden token to the monitored in a chain // link forwards static_cast(p.get())->setHiddenAfter(LA(1)); // link backwards if (p != monitored) { //hidden cannot point to monitored tokens static_cast(LA(1).get())->setHiddenBefore(p); } p = lastHiddenToken = LA(1); } consume(); } return monitored; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/TokenStreamHiddenTokenFilter.hpp000066400000000000000000000043611340051421000224300ustar00rootroot00000000000000#ifndef INC_TokenStreamHiddenTokenFilter_hpp__ #define INC_TokenStreamHiddenTokenFilter_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamHiddenTokenFilter.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /**This object filters a token stream coming from a lexer * or another TokenStream so that only certain token channels * get transmitted to the parser. * * Any of the channels can be filtered off as "hidden" channels whose * tokens can be accessed from the parser. */ class ANTLR_API TokenStreamHiddenTokenFilter : public TokenStreamBasicFilter { // protected BitSet discardMask; protected: BitSet hideMask; private: RefToken nextMonitoredToken; protected: /** track tail of hidden list emanating from previous * monitored token */ RefToken lastHiddenToken; RefToken firstHidden; // = null; public: TokenStreamHiddenTokenFilter(TokenStream& input); protected: void consume(); private: void consumeFirst(); public: BitSet getDiscardMask() const; /** Return a ptr to the hidden token appearing immediately after * token t in the input stream. */ RefToken getHiddenAfter(RefToken t); /** Return a ptr to the hidden token appearing immediately before * token t in the input stream. */ RefToken getHiddenBefore(RefToken t); BitSet getHideMask() const; /** Return the first hidden token if one appears * before any monitored token. */ RefToken getInitialHiddenToken(); void hide(int m); void hide(const BitSet& mask); protected: RefToken LA(int i); public: /** Return the next monitored token. * Test the token following the monitored token. * If following is another monitored token, save it * for the next invocation of nextToken (like a single * lookahead token) and return it then. * If following is unmonitored, nondiscarded (hidden) * channel token, add it to the monitored token. * * Note: EOF must be a monitored Token. */ RefToken nextToken(); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamHiddenTokenFilter_hpp__ gdl-0.9.9/src/antlr/TokenStreamIOException.hpp000066400000000000000000000015501340051421000212510ustar00rootroot00000000000000#ifndef INC_TokenStreamIOException_hpp__ #define INC_TokenStreamIOException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamIOException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class TokenStreamIOException : public TokenStreamException { public: TokenStreamIOException() : TokenStreamException() { } TokenStreamIOException(const ANTLR_USE_NAMESPACE(std)exception& e) : TokenStreamException(e.what()) , io(e) { } ~TokenStreamIOException() throw() { } private: ANTLR_USE_NAMESPACE(std)exception io; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamIOException_hpp__ gdl-0.9.9/src/antlr/TokenStreamRecognitionException.hpp000066400000000000000000000017111340051421000232210ustar00rootroot00000000000000#ifndef INC_TokenStreamRecognitionException_hpp__ #define INC_TokenStreamRecognitionException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamRecognitionException.hpp,v 1.1.1.1 2004-12-09 15:10:21 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class TokenStreamRecognitionException : public TokenStreamException { public: TokenStreamRecognitionException(RecognitionException& re) : TokenStreamException(re.getMessage()) , recog(re) { } ~TokenStreamRecognitionException() throw() { } ANTLR_USE_NAMESPACE(std)string toString() const { return recog.getFileLineColumnString()+getMessage(); } private: RecognitionException recog; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamRecognitionException_hpp__ gdl-0.9.9/src/antlr/TokenStreamRetryException.hpp000066400000000000000000000012671340051421000220540ustar00rootroot00000000000000#ifndef INC_TokenStreamRetryException_hpp__ #define INC_TokenStreamRetryException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamRetryException.hpp,v 1.1.1.1 2004-12-09 15:10:21 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class TokenStreamRetryException : public TokenStreamException { public: TokenStreamRetryException() {} ~TokenStreamRetryException() throw() {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamRetryException_hpp__ gdl-0.9.9/src/antlr/TokenStreamSelector.cpp000066400000000000000000000047661340051421000206520ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamSelector.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/TokenStreamSelector.hpp" #include "antlr/TokenStreamRetryException.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** A token stream MUX (multiplexor) knows about n token streams * and can multiplex them onto the same channel for use by token * stream consumer like a parser. This is a way to have multiple * lexers break up the same input stream for a single parser. * Or, you can have multiple instances of the same lexer handle * multiple input streams; this works great for includes. */ TokenStreamSelector::TokenStreamSelector() : input(0) { } TokenStreamSelector::~TokenStreamSelector() { } void TokenStreamSelector::addInputStream(TokenStream* stream, const ANTLR_USE_NAMESPACE(std)string& key) { inputStreamNames[key] = stream; } TokenStream* TokenStreamSelector::getCurrentStream() const { return input; } TokenStream* TokenStreamSelector::getStream(const ANTLR_USE_NAMESPACE(std)string& sname) const { inputStreamNames_coll::const_iterator i = inputStreamNames.find(sname); if (i == inputStreamNames.end()) { throw ANTLR_USE_NAMESPACE(std)string("TokenStream ")+sname+" not found"; } return (*i).second; } RefToken TokenStreamSelector::nextToken() { // keep looking for a token until you don't // get a retry exception for (;;) { try { return input->nextToken(); } catch (TokenStreamRetryException&) { // just retry "forever" } } } TokenStream* TokenStreamSelector::pop() { TokenStream* stream = streamStack.top(); streamStack.pop(); select(stream); return stream; } void TokenStreamSelector::push(TokenStream* stream) { streamStack.push(input); select(stream); } void TokenStreamSelector::push(const ANTLR_USE_NAMESPACE(std)string& sname) { streamStack.push(input); select(sname); } void TokenStreamSelector::retry() { throw TokenStreamRetryException(); } /** Set the stream without pushing old stream */ void TokenStreamSelector::select(TokenStream* stream) { input = stream; } void TokenStreamSelector::select(const ANTLR_USE_NAMESPACE(std)string& sname) { inputStreamNames_coll::const_iterator i = inputStreamNames.find(sname); if (i == inputStreamNames.end()) { throw ANTLR_USE_NAMESPACE(std)string("TokenStream ")+sname+" not found"; } input = (*i).second; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/TokenStreamSelector.hpp000066400000000000000000000053021340051421000206420ustar00rootroot00000000000000#ifndef INC_TokenStreamSelector_hpp__ #define INC_TokenStreamSelector_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TokenStreamSelector.hpp,v 1.1.1.1 2004-12-09 15:10:21 m_schellens Exp $ */ #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** A token stream MUX (multiplexor) knows about n token streams * and can multiplex them onto the same channel for use by token * stream consumer like a parser. This is a way to have multiple * lexers break up the same input stream for a single parser. * Or, you can have multiple instances of the same lexer handle * multiple input streams; this works great for includes. */ class ANTLR_API TokenStreamSelector : public TokenStream { protected: /** The set of inputs to the MUX */ #ifdef OS_NO_ALLOCATOR typedef ANTLR_USE_NAMESPACE(std)less lessp; typedef ANTLR_USE_NAMESPACE(std)map inputStreamNames_coll; #else typedef ANTLR_USE_NAMESPACE(std)map inputStreamNames_coll; #endif inputStreamNames_coll inputStreamNames; /** The currently-selected token stream input */ TokenStream* input; /** Used to track stack of input streams */ #ifdef OS_NO_ALLOCATOR typedef ANTLR_USE_NAMESPACE(std)stack > streamStack_coll; #else typedef ANTLR_USE_NAMESPACE(std)stack streamStack_coll; #endif streamStack_coll streamStack; public: TokenStreamSelector(); ~TokenStreamSelector(); void addInputStream(TokenStream* stream, const ANTLR_USE_NAMESPACE(std)string& key); /// Return the stream from which tokens are being pulled at the moment. TokenStream* getCurrentStream() const; TokenStream* getStream(const ANTLR_USE_NAMESPACE(std)string& sname) const; RefToken nextToken(); TokenStream* pop(); void push(TokenStream* stream); void push(const ANTLR_USE_NAMESPACE(std)string& sname); /** Abort recognition of current Token and try again. * A stream can push a new stream (for include files * for example, and then retry(), which will cause * the current stream to abort back to this.nextToken(). * this.nextToken() then asks for a token from the * current stream, which is the new "substream." */ void retry(); /** Set the stream without pushing old stream */ void select(TokenStream* stream); void select(const ANTLR_USE_NAMESPACE(std)string& sname); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TokenStreamSelector_hpp__ gdl-0.9.9/src/antlr/TreeParser.cpp000066400000000000000000000066501340051421000167630ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TreeParser.cpp,v 1.3 2010-04-05 01:22:05 m_schellens Exp $ */ // g++-4.3 needs this #include #include #include "antlr/TreeParser.hpp" #include "antlr/ASTNULLType.hpp" #include "antlr/MismatchedTokenException.hpp" #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ANTLR_C_USING(exit) TreeParser::TreeParser() : astFactory(0) , inputState(new TreeParserInputState()) , traceDepth(0) { } TreeParser::TreeParser(const TreeParserSharedInputState& state) : astFactory(0) , inputState(state) , traceDepth(0) { } TreeParser::~TreeParser() { } /** The AST Null object; the parsing cursor is set to this when * it is found to be null. This way, we can test the * token type of a node without having to have tests for null * everywhere. */ RefAST TreeParser::ASTNULL(new ASTNULLType); void TreeParser::match(RefAST t, int ttype) { if (!t || t == ASTNULL || t->getType() != ttype ) throw MismatchedTokenException( getTokenNames(), getNumTokens(), t, ttype, false ); } /** Make sure current lookahead symbol matches the given set * Throw an exception upon mismatch, which is caught by either the * error handler or by the syntactic predicate. */ void TreeParser::match(RefAST t, const BitSet& b) { if ( !t || t==ASTNULL || !b.member(t->getType()) ) throw MismatchedTokenException( getTokenNames(), getNumTokens(), t, b, false ); } void TreeParser::matchNot(RefAST t, int ttype) { if ( !t || t == ASTNULL || t->getType() == ttype ) throw MismatchedTokenException( getTokenNames(), getNumTokens(), t, ttype, true ); } void TreeParser::panic() { ANTLR_USE_NAMESPACE(std)cerr << "TreeWalker: panic" << ANTLR_USE_NAMESPACE(std)endl; exit(1); } /** Parser error-reporting function can be overridden in subclass */ void TreeParser::reportError(const RecognitionException& ex) { ANTLR_USE_NAMESPACE(std)cerr << ex.toString().c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Parser error-reporting function can be overridden in subclass */ void TreeParser::reportError(const ANTLR_USE_NAMESPACE(std)string& s) { ANTLR_USE_NAMESPACE(std)cerr << "error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Parser warning-reporting function can be overridden in subclass */ void TreeParser::reportWarning(const ANTLR_USE_NAMESPACE(std)string& s) { ANTLR_USE_NAMESPACE(std)cerr << "warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; } /** Procedure to write out an indent for traceIn and traceOut */ void TreeParser::traceIndent() { for( int i = 0; i < traceDepth; i++ ) ANTLR_USE_NAMESPACE(std)cout << " "; ANTLR_USE_NAMESPACE(std)cout << ANTLR_USE_NAMESPACE(std)setw(3) << traceDepth << ": "; } void TreeParser::traceIn(const char* rname, RefAST t) { traceDepth++; traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "> " << rname << "(" << (t ? t->toString().c_str() : "null") << ")" << ((inputState->guessing>0)?" [guessing]":"") << ANTLR_USE_NAMESPACE(std)endl; } void TreeParser::traceOut(const char* rname, RefAST t) { traceIndent(); ANTLR_USE_NAMESPACE(std)cout << "< " << rname << "(" << (t ? t->toString().c_str() : "null") << ")" << ((inputState->guessing>0)?" [guessing]":"") << ANTLR_USE_NAMESPACE(std)endl; traceDepth--; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/TreeParser.hpp000066400000000000000000000076421340051421000167720ustar00rootroot00000000000000#ifndef INC_TreeParser_hpp__ #define INC_TreeParser_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TreeParser.hpp,v 1.1.1.1 2004-12-09 15:10:21 m_schellens Exp $ */ #include #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API TreeParser { public: TreeParser(); TreeParser(const TreeParserSharedInputState& state); virtual ~TreeParser(); /// Get the AST return value squirreled away in the parser virtual RefAST getAST() = 0; /** Make sure current lookahead symbol matches the given set * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ virtual void match(RefAST t, const BitSet& b); /** Specify the AST factory to be used during tree building. (Compulsory) * Setting the factory is compulsory (if you intend to modify * the tree in the treeparser). The AST Factory is shared between * parser (who builds the initial AST) and treeparser. * @see Parser::getASTFactory() */ virtual void setASTFactory(ASTFactory* factory) { astFactory = factory; } /// Return pointer to ASTFactory virtual ASTFactory* getASTFactory() const { return astFactory; } /// Get the name for token 'num' virtual const char* getTokenName(int num) const = 0; /// Return the number of tokens defined virtual int getNumTokens() const = 0; /// Return an array of getNumTokens() token names virtual const char* const* getTokenNames() const = 0; /// Parser error-reporting function can be overridden in subclass virtual void reportError(const RecognitionException& ex); /// Parser error-reporting function can be overridden in subclass virtual void reportError(const ANTLR_USE_NAMESPACE(std)string& s); /// Parser warning-reporting function can be overridden in subclass virtual void reportWarning(const ANTLR_USE_NAMESPACE(std)string& s); /** Give panic message and exit the program. can be overridden in subclass * @deprecated this method is unused and will dissappear in the next release */ virtual void panic(); /// These are used during when traceTreeParser commandline option is passed. virtual void traceIndent(); virtual void traceIn(const char* rname, RefAST t); virtual void traceOut(const char* rname, RefAST t); /** The AST Null object; the parsing cursor is set to this when * it is found to be null. This way, we can test the * token type of a node without having to have tests for 0 * everywhere. */ static RefAST ASTNULL; protected: virtual void match(RefAST t, int ttype); virtual void matchNot(RefAST t, int ttype); /* Where did this rule leave off parsing; avoids a return parameter */ //RefAST _retTree; /* AST return value for a rule is squirreled away here */ //RefAST returnAST; /** AST support code; parser and treeparser delegate to this object */ ASTFactory* astFactory; /// The input state of this tree parser. TreeParserSharedInputState inputState; /** Used to keep track of indent depth with -traceTreeParser */ int traceDepth; /** Utility class which allows tracing to work even when exceptions are * thrown. */ class Tracer { private: TreeParser* parser; const char* text; RefAST tree; public: Tracer(TreeParser* p, const char* t, RefAST a) : parser(p), text(t), tree(a) { parser->traceIn(text,tree); } ~Tracer() { parser->traceOut(text,tree); } private: Tracer(const Tracer&); // undefined const Tracer& operator=(const Tracer&); // undefined }; private: // no copying of treeparser instantiations... TreeParser(const TreeParser& other); TreeParser& operator=(const TreeParser& other); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TreeParser_hpp__ gdl-0.9.9/src/antlr/TreeParserSharedInputState.hpp000066400000000000000000000022131340051421000221270ustar00rootroot00000000000000#ifndef INC_TreeParserSharedInputState_hpp__ #define INC_TreeParserSharedInputState_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: TreeParserSharedInputState.hpp,v 1.1.1.1 2004-12-09 15:10:21 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** This object contains the data associated with an * input AST. Multiple parsers * share a single TreeParserSharedInputState to parse * the same tree or to have the parser walk multiple * trees. */ class ANTLR_API TreeParserInputState { public: TreeParserInputState() : guessing(0) {} virtual ~TreeParserInputState() {} public: /** Are we guessing (guessing>0)? */ int guessing; //= 0; private: // we don't want these: TreeParserInputState(const TreeParserInputState&); TreeParserInputState& operator=(const TreeParserInputState&); }; typedef RefCount TreeParserSharedInputState; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_TreeParserSharedInputState_hpp__ gdl-0.9.9/src/antlr/config.hpp000066400000000000000000000200371340051421000161540ustar00rootroot00000000000000#ifndef INC_config_hpp__ #define INC_config_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: config.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ /* * Just a simple configuration file to differentiate between the * various compilers used and reconfigure stuff for any oddities of the * compiler in question. * * These are the defaults. Per compiler these are amended. */ #define ANTLR_USE_NAMESPACE(_x_) _x_:: #define ANTLR_USING_NAMESPACE(_x_) using namespace _x_; #define ANTLR_CXX_SUPPORTS_NAMESPACE 1 #define ANTLR_C_USING(_x_) #define ANTLR_API #ifndef CUSTOM_API # define CUSTOM_API #endif #define ANTLR_IOS_BASE ios_base /** define if cctype functions/macros need a std:: prefix. A lot of compilers * define these as macros, in which case something barfs. */ #define ANTLR_CCTYPE_NEEDS_STD /// Define if C++ compiler supports std::uncaught_exception #define ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION #define ANTLR_ATOI_IN_STD /******************************************************************************/ /*{{{ Microsoft Visual C++ */ // NOTE: If you provide patches for a specific MSVC version guard them for // the specific version!!!! // _MSC_VER == 1100 for Microsoft Visual C++ 5.0 // _MSC_VER == 1200 for Microsoft Visual C++ 6.0 // _MSC_VER == 1300 for Microsoft Visual C++ 7.0 #if defined(_MSC_VER) && !defined(__ICL) // This warning really gets on my nerves. // It's the one about symbol longer than 256 chars, and it happens // all the time with STL. # pragma warning( disable : 4786 4231 ) # ifdef ANTLR_CXX_USE_STLPORT # undef ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION # endif # if ( _MSC_VER < 1300 ) && ( defined(ANTLR_EXPORTS) || defined(ANTLR_IMPORTS) ) # error "DLL Build not supported on these MSVC versions." // see comment in lib/cpp/src/dll.cpp # endif // For the DLL support originally contributed by Stephen Naughton // If you are building statically leave ANTLR_EXPORTS/ANTLR_IMPORTS undefined // If you are building the DLL define ANTLR_EXPORTS // If you are compiling code to be used with the DLL define ANTLR_IMPORTS # ifdef ANTLR_EXPORTS # undef ANTLR_API # define ANTLR_API __declspec(dllexport) # endif # ifdef ANTLR_IMPORTS # undef ANTLR_API # define ANTLR_API __declspec(dllimport) # endif // VC6 # if ( _MSC_VER == 1200 ) # undef ANTLR_ATOI_IN_STD # endif // These should be verified for newer MSVC's // Not allowed to put 'static const int XXX=20;' in a class definition # define NO_STATIC_CONSTS // Using vector requires operator<(X,X) to be defined # define NEEDS_OPERATOR_LESS_THAN // No strcasecmp in the C library (so use stricmp instead) // - Anyone know which is in which standard? # define NO_STRCASECMP # undef ANTLR_CCTYPE_NEEDS_STD // needed for CharScannerLiteralsLess # define NO_TEMPLATE_PARTS #endif // End of Microsoft Visual C++ /*}}}*/ /******************************************************************************/ // RK: belongs to what compiler? #if defined(__ICL) # define NO_STRCASECMP #endif /*****************************************************************************/ /*{{{ SunPro Compiler (Using OBJECTSPACE STL) *****************************************************************************/ #ifdef __SUNPRO_CC # if (__SUNPRO_CC >= 0x500) # define NEEDS_OPERATOR_LESS_THAN # define NO_TEMPLATE_PARTS # else # undef namespace # define namespace # if (__SUNPRO_CC == 0x420) /* This code is specif to SunWspro Compiler 4.2, and will compile with the objectspace 2.1 toolkit for Solaris2.6 */ # define HAS_NOT_CASSERT_H # define HAS_NOT_CSTRING_H # define HAS_NOT_CCTYPE_H # define HAS_NOT_CSTDIO_H # define HAS_OSTREAM_H /* #define OS_SOLARIS_2_6 #define OS_NO_WSTRING #define OS_NO_ALLOCATORS #define OS_MULTI_THREADED #define OS_SOLARIS_NATIVE #define OS_REALTIME #define __OSVERSION__=5 #define SVR4 */ // ObjectSpace + some specific templates constructions with stl. /* #define OS_NO_ALLOCATOR */ // This great compiler does not have the namespace feature. # undef ANTLR_USE_NAMESPACE # define ANTLR_USE_NAMESPACE(_x_) # undef ANTLR_USING_NAMESPACE # define ANTLR_USING_NAMESPACE(_x_) # undef ANTLR_CXX_SUPPORTS_NAMESPACE # endif // End __SUNPRO_CC == 0x420 # undef explicit # define explicit # define exception os_exception # define bad_exception os_bad_exception // Not allowed to put 'static const int XXX=20;' in a class definition # define NO_STATIC_CONSTS // Using vector requires operator<(X,X) to be defined # define NEEDS_OPERATOR_LESS_THAN # endif # undef ANTLR_CCTYPE_NEEDS_STD #endif // end __SUNPRO_CC /*}}}*/ /*****************************************************************************/ /*{{{ Inprise C++ Builder 3.0 *****************************************************************************/ #ifdef __BCPLUSPLUS__ # define NO_TEMPLATE_PARTS # define NO_STRCASECMP # undef ANTLR_CCTYPE_NEEDS_STD #endif // End of C++ Builder 3.0 /*}}}*/ /*****************************************************************************/ /*{{{ IBM VisualAge C++ ( which includes the Dinkumware C++ Library ) *****************************************************************************/ #ifdef __IBMCPP__ // No strcasecmp in the C library (so use stricmp instead) // - Anyone know which is in which standard? # define NO_STRCASECMP # undef ANTLR_CCTYPE_NEEDS_STD #endif // end IBM VisualAge C++ /*}}}*/ /*****************************************************************************/ /*{{{ Metrowerks Codewarrior *****************************************************************************/ #ifdef __MWERKS__ # if (__MWERKS__ <= 0x2201) # define NO_TEMPLATE_PARTS # endif // CW 6.0 and 7.0 still do not have it. # define ANTLR_REALLY_NO_STRCASECMP # undef ANTLR_C_USING # define ANTLR_C_USING(_x_) using std:: ## _x_; # define ANTLR_CCTYPE_NEEDS_STD # undef ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION #endif // End of Metrowerks Codewarrior /*}}}*/ /*****************************************************************************/ /*{{{ SGI Irix 6.5.10 MIPSPro compiler *****************************************************************************/ // (contributed by Anna Winkler) // Note: you can't compile ANTLR with the MIPSPro compiler on // anything < 6.5.10 because SGI just fixed a big bug dealing with // namespaces in that release. #ifdef __sgi # define HAS_NOT_CCTYPE_H # define HAS_NOT_CSTRING_H # define HAS_NOT_CSTDIO_H # undef ANTLR_CCTYPE_NEEDS_STD #endif // End IRIX MIPSPro /*}}}*/ /*****************************************************************************/ /*{{{ G++ in various incarnations *****************************************************************************/ // With the gcc-2.95 and 3.0 being in the near future we should start handling // incompatabilities between the various libstdc++'s. #if defined(__GNUC__) || defined(__GNUG__) // gcc 2 branch.. # if (__GNUC__ == 2 ) # if (__GNUC_MINOR__ <= 8 ) # undef ANTLR_USE_NAMESPACE # define ANTLR_USE_NAMESPACE(_x_) # undef ANTLR_USING_NAMESPACE # define ANTLR_USING_NAMESPACE(_x_) # undef ANTLR_CXX_SUPPORTS_NAMESPACE # endif # if (__GNUC_MINOR__ > 8 && __GNUC_MINOR__ <= 95 ) # undef ANTLR_IOS_BASE # define ANTLR_IOS_BASE ios # undef ANTLR_CCTYPE_NEEDS_STD // compiling with -ansi ? # ifdef __STRICT_ANSI__ # undef ANTLR_REALLY_NO_STRCASECMP # define ANTLR_REALLY_NO_STRCASECMP # endif # else // experimental .96 .97 branches.. # undef ANTLR_CCTYPE_NEEDS_STD # endif # endif #endif // ! __GNUC__ /*}}}*/ /*****************************************************************************/ /*{{{ Digital CXX (Tru64) *****************************************************************************/ #ifdef __DECCXX #define __USE_STD_IOSTREAM #endif /*}}}*/ /*****************************************************************************/ // Redefine these for backwards compatability.. #undef ANTLR_BEGIN_NAMESPACE #undef ANTLR_END_NAMESPACE #if ANTLR_CXX_SUPPORTS_NAMESPACE == 1 # define ANTLR_BEGIN_NAMESPACE(_x_) namespace _x_ { # define ANTLR_END_NAMESPACE } #else # define ANTLR_BEGIN_NAMESPACE(_x_) # define ANTLR_END_NAMESPACE #endif #endif //INC_config_hpp__ gdl-0.9.9/src/antlr/dll.cpp000066400000000000000000000234021340051421000154540ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: dll.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ /* * DLL stub for MSVC++. Based upon versions of Stephen Naughton and Michael * T. Richter */ // RK: Uncommented by instruction of Alexander Lenski //#if _MSC_VER > 1000 //# pragma once //#endif // _MSC_VER > 1000 // Exclude rarely-used stuff from Windows headers #define WIN32_LEAN_AND_MEAN #include #if defined( _MSC_VER ) && ( _MSC_VER < 1300 ) # error "DLL Build not supported on old MSVC's" // Ok it seems to be possible with STLPort in stead of the vanilla MSVC STL // implementation. This needs some work though. (and don't try it if you're // not that familiar with compilers/building C++ DLL's in windows) #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif // Take care of necessary implicit instantiations of templates from STL // This should take care of MSVC 7.0 #if defined( _MSC_VER ) && ( _MSC_VER == 1300 ) // these come from AST.hpp template class ANTLR_API ASTRefCount< AST >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< RefAST >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< RefAST >; //template ANTLR_API int operator<( ASTRefCount< AST >, ASTRefCount< AST > ); // ASTFactory.hpp template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< factory_descriptor_* >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const char*, factory_type_ > >; template struct ANTLR_API ANTLR_USE_NAMESPACE(std)pair< const char*, factory_type_ >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< factory_descriptor_*, ANTLR_USE_NAMESPACE(std)allocator< factory_descriptor_* > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< factory_descriptor_* >; // BitSet.hpp template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< bool >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< bool, ANTLR_USE_NAMESPACE(std)allocator< bool > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< bool >; // CharScanner.hpp template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, int > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >, false > >::_Node >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >, false > >::_Nodeptr >; template struct ANTLR_API ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, int >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_val< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)map< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess >; // CircularQueue.hpp // RK: it might well be that a load of these ints need to be unsigned ints // (made some more stuff unsigned) template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< int >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< int, ANTLR_USE_NAMESPACE(std)allocator< int > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< int >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< int, ANTLR_USE_NAMESPACE(std)allocator< int > >; // template ANTLR_API inline int CircularQueue< int >::entries() const; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< RefToken >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< RefToken, ANTLR_USE_NAMESPACE(std)allocator< RefToken > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< RefToken >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< RefToken, ANTLR_USE_NAMESPACE(std)allocator< RefToken > >; // template ANTLR_API inline int CircularQueue< RefToken >::entries() const; // CommonAST.hpp template class ANTLR_API ASTRefCount< CommonAST >; // CommonASTWithHiddenTokenTypes.hpp template class ANTLR_API ASTRefCount< CommonASTWithHiddenTokens >; // LexerSharedInputState.hpp template class ANTLR_API RefCount< LexerInputState >; // ParserSharedInputState.hpp template class ANTLR_API RefCount< ParserInputState >; // TokenStreamSelector.hpp template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, TokenStream* > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >, false > >::_Node >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >, false > >::_Nodeptr >; template struct ANTLR_API ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, TokenStream* >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_val< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)map< ANTLR_USE_NAMESPACE(std)string, TokenStream* >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< TokenStream* >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Deque_map< TokenStream* , ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >::_Tptr >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Deque_map< TokenStream*, ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Deque_val< TokenStream*, ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)deque< TokenStream*, ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >; template class ANTLR_API ANTLR_USE_NAMESPACE(std)stack< TokenStream*, ANTLR_USE_NAMESPACE(std)deque >; // #else // Add instantiations for MSVC 7.1 here if necessary.. #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } gdl-0.9.9/src/arrayindex.cpp000066400000000000000000000333321340051421000157320ustar00rootroot00000000000000/*************************************************************************** arrayindex.cpp - array access descriptor ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "GDLInterpreter.hpp" #include "arrayindex.hpp" using namespace std; ArrayIndexScalar::ArrayIndexScalar( RefDNode& dNode) { assert( dNode->getType() == GDLTokenTypes::VAR); varIx = dNode->GetVarIx(); } ArrayIndexScalarVP::ArrayIndexScalarVP( RefDNode& dNode) { assert( dNode->getType() == GDLTokenTypes::VARPTR); varPtr = dNode->GetVar(); } // // if this is used, Init was NOT called before // // only called if !var->IsAssoc() // BaseGDL* ArrayIndexScalar::Index( BaseGDL* var, IxExprListT& ixL) // { // s = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); // // if( s >= var->N_Elements()/*var->Size()*/) // { // throw GDLException("Scalar subscript out of range [>].a"); // } // return var->NewIx( s); // } // BaseGDL* ArrayIndexScalarVP::Index( BaseGDL* var, IxExprListT& ixL) // { // s = varPtr->Data()->LoopIndex(); // // if( s >= var->N_Elements()/*var->Size()*/) // { // throw GDLException("Scalar subscript out of range [>].b"); // } // return var->NewIx( s); // } SizeT ArrayIndexScalar::NIter( SizeT varDim) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( sInit < 0) s = sInit + varDim; else s = sInit; if( s < 0) throw GDLException("Scalar subscript out of range [<].c"); if( s >= varDim && s > 0) // s == 0 is fine throw GDLException("Scalar subscript out of range [>].c"); return 1; } SizeT ArrayIndexScalarVP::NIter( SizeT varDim) { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) s = sInit + varDim; else s = sInit; if( s < 0) throw GDLException("Scalar subscript out of range [<].d"); if( s >= varDim && s > 0) // s == 0 is fine throw GDLException("Scalar subscript out of range [>].d"); return 1; } void ArrayIndexScalar::Init() { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); s = sInit; } BaseGDL* ArrayIndexScalar::OverloadIndexNew() { BaseGDL* v = GDLInterpreter::CallStackBack()->GetKW( varIx); if( v == NULL) return NULL; return v->Dup(); } // // void ArrayIndexListOneScalarT::Init( IxExprListT& ix_) // // { // // s = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); // // } // // void ArrayIndexListOneScalarVPT::Init( IxExprListT& ix_) // // { // // s = varPtr->Data()->LoopIndex(); // // } // void ArrayIndexListOneScalarT::Init() // { // // assert( 0); // // s = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); // } // void ArrayIndexListOneScalarVPT::Init() // { // // assert( 0); // // s = varPtr->Data()->LoopIndex(); // } // // vtable // ArrayIndexListOneScalarNoAssocT::~ArrayIndexListOneScalarNoAssocT() // {} // optimized for one dimensional access BaseGDL* ArrayIndexListOneScalarT::Index( BaseGDL* var, IxExprListT& ix_) { // Init() not called if( !var->IsAssoc())// && var->Type() != GDL_STRUCT) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s >= var->N_Elements()/*var->Size()*/) { throw GDLException("Scalar subscript out of range [>].e"); } if( s < 0) { throw GDLException("Scalar subscript out of range [<].e"); } return var->NewIx( s); } // normal case // Init(); SetVariable( var); return var->Index( this); } BaseGDL* ArrayIndexListOneScalarNoAssocT::Index( BaseGDL* var, IxExprListT& ix_) { // Init() not called // if( !var->IsAssoc())// && var->Type() != GDL_STRUCT) // { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s >= var->N_Elements()/*var->Size()*/) { throw GDLException("Scalar subscript out of range [>].e ("+i2s(s)+")"); } if( s < 0) { throw GDLException("Scalar subscript out of range [<].e ("+i2s(s)+")"); } return var->NewIx( s); // } // // // normal case // // Init(); // SetVariable( var); // return var->Index( this); } void ArrayIndexListOneScalarNoAssocT::InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( 0 == nParam); DLongGDL* isRange = new DLongGDL( 0); ixOut.push_back(isRange); BaseGDL* oIx = GDLInterpreter::CallStackBack()->GetKW( varIx); if( oIx != NULL) oIx = oIx->Dup(); ixOut.push_back(oIx); } void ArrayIndexListOneScalarVPNoAssocT::InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( varPtr != NULL); assert( 0 == nParam); DLongGDL* isRange = new DLongGDL( 0); ixOut.push_back(isRange); BaseGDL* oIx = varPtr->Data(); if( oIx != NULL) oIx = oIx->Dup(); ixOut.push_back(oIx); } BaseGDL* ArrayIndexListOneScalarVPT::Index( BaseGDL* var, IxExprListT& ix_) { assert( varPtr != NULL); // Init() not called if( !var->IsAssoc())// && var->Type() != GDL_STRUCT) { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s >= var->N_Elements()/*var->Size()*/) { throw GDLException("Scalar subscript out of range [>].f"); } if( s < 0) { throw GDLException("Scalar subscript out of range [<].f"); } return var->NewIx( s); } // normal case // Init(); SetVariable( var); return var->Index( this); } BaseGDL* ArrayIndexListOneScalarVPNoAssocT::Index( BaseGDL* var, IxExprListT& ix_) { // Init() not called // if( !var->IsAssoc())// && var->Type() != GDL_STRUCT) // { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s >= var->N_Elements()/*var->Size()*/) { throw GDLException("Scalar subscript out of range [>].f"); } if( s < 0) { throw GDLException("Scalar subscript out of range [<].f"); } return var->NewIx( s); // } // // // normal case // // Init(); // SetVariable( var); // return var->Index( this); } bool ArrayIndexListOneScalarT::ToAssocIndex( SizeT& lastIx) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( sInit < 0) throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context.",true,false); lastIx = sInit; return true; } void ArrayIndexListOneScalarT::SetVariable( BaseGDL* var) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( var->IsAssoc()) { s = sInit; return; } if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s < 0) throw GDLException("Scalar subscript out of range [<].h"); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException("Scalar subscript out of range [>].h"); // for assoc variables last index is the record if( s >= var->N_Elements()/*var->Size()*/) throw GDLException("Scalar subscript out of range [>].g"); } void ArrayIndexListOneScalarNoAssocT::SetVariable( BaseGDL* var) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( var->IsAssoc()) { s = sInit; return; } // if( var->IsAssoc()) return; if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s < 0) throw GDLException("Scalar subscript out of range [<].h"); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException("Scalar subscript out of range [>].h"); // for assoc variables last index is the record if( s >= var->N_Elements()/*var->Size()*/) throw GDLException("Scalar subscript out of range [>].g"); } void ArrayIndexListOneScalarT::AssignAt( BaseGDL* var, BaseGDL* right) { // Init() was already called // scalar case if( right->N_Elements() == 1 && !var->IsAssoc())// && var->Type() != GDL_STRUCT) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s < 0) throw GDLException("Scalar subscript out of range [<].h"); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException("Scalar subscript out of range [>].h"); var->AssignAtIx( s, right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } void ArrayIndexListOneScalarNoAssocT::AssignAt( BaseGDL* var, BaseGDL* right) { // Init() was already called // scalar case if( right->N_Elements() == 1)// && !var->IsAssoc())// && var->Type() != GDL_STRUCT) { sInit = GDLInterpreter::CallStackBack()->GetKW( varIx)->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; else s = sInit; if( s < 0) throw GDLException("Scalar subscript out of range [<].h"); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException("Scalar subscript out of range [>].h"); var->AssignAtIx( s, right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // vtable ArrayIndexListT::~ArrayIndexListT() {} AllIxBaseT* ArrayIndexListT::BuildIx() {return NULL;} // called from compiler after (array) structure is fixed // the ArrayIndexListT factory void MakeArrayIndex( ArrayIndexVectorT* ixList, ArrayIndexListT** arrayIndexOut, ArrayIndexListT** arrayIndexNoAssocOut) { assert( ixList->size() != 0); // must be, from compiler if( ixList->size() == 1) { if( CArrayIndexScalarID == (*ixList)[0]->Type()) { if( arrayIndexNoAssocOut != NULL) *arrayIndexNoAssocOut = new ArrayIndexListOneConstScalarNoAssocT( ixList); // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListOneConstScalarT( ixList); return; } if( ArrayIndexScalarID == (*ixList)[0]->Type()) { if( arrayIndexNoAssocOut != NULL) *arrayIndexNoAssocOut = new ArrayIndexListOneScalarNoAssocT( ixList); // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListOneScalarT( ixList); return; } if( ArrayIndexScalarVPID == (*ixList)[0]->Type()) { if( arrayIndexNoAssocOut != NULL) *arrayIndexNoAssocOut = new ArrayIndexListOneScalarVPNoAssocT( ixList); // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListOneScalarVPT( ixList); return; } if( arrayIndexNoAssocOut != NULL) *arrayIndexNoAssocOut = new ArrayIndexListOneNoAssocT( ixList); // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListOneT( ixList); return; } SizeT nScalar = 0; SizeT nIndexed = 0; for( SizeT i=0; isize(); ++i) { if( ArrayIndexScalarID == (*ixList)[i]->Type() || ArrayIndexScalarVPID == (*ixList)[i]->Type() || CArrayIndexScalarID == (*ixList)[i]->Type() ) ++nScalar; else if( ArrayIndexIndexedID == (*ixList)[i]->Type() || CArrayIndexIndexedID == (*ixList)[i]->Type()) ++nIndexed; } if( nScalar == ixList->size()) { if( arrayIndexNoAssocOut != NULL) { if( ixList->size() == 2) *arrayIndexNoAssocOut = new ArrayIndexListScalarNoAssoc2DT( ixList); else *arrayIndexNoAssocOut = new ArrayIndexListScalarNoAssocT( ixList); } // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListScalarT( ixList); return; } // Note that each index can be a assoc index anytime // filter this special case out should save complexity in // ArrayIndexListMultiT if( nIndexed == 0) { if( arrayIndexNoAssocOut != NULL) { if( ixList->size() == 2) *arrayIndexNoAssocOut = new ArrayIndexListMultiNoneIndexedNoAssoc2DT( ixList); else *arrayIndexNoAssocOut = new ArrayIndexListMultiNoneIndexedNoAssocT( ixList); } // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListMultiNoneIndexedT( ixList); return; } if( nIndexed == ixList->size()) { if( arrayIndexNoAssocOut != NULL) *arrayIndexNoAssocOut = new ArrayIndexListMultiAllIndexedNoAssocT( ixList); // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListMultiAllIndexedT( ixList); return; } if( arrayIndexNoAssocOut != NULL) *arrayIndexNoAssocOut = new ArrayIndexListMultiNoAssocT( ixList); // if( arrayIndexOut != NULL) *arrayIndexOut = new ArrayIndexListMultiT( ixList); } gdl-0.9.9/src/arrayindex.hpp000066400000000000000000000721241340051421000157410ustar00rootroot00000000000000/*************************************************************************** arrayindex.hpp - array access descriptor ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ARRAYINDEX_HPP_ #define ARRAYINDEX_HPP_ #include #include #include "datatypes.hpp" #include "real2int.hpp" // done below // #include "allix.hpp" //typedef std::valarray AllIxT; // now in typedefs.hpp //typedef std::vector IxExprListT; class IxExprListT { private: BaseGDL* eArr[3*MAXRANK]; int sz; public: IxExprListT(): sz(0) {} void push_back( BaseGDL* p) { assert( sz<3*MAXRANK); eArr[ sz++] = p;} BaseGDL* operator[]( SizeT i) const { assert( i<3*MAXRANK && i 0); return arrayIxArr[0]->GetS(); } ArrayIndexT* operator[]( SizeT ix) const { assert( ix < MAXRANK); return arrayIxArr[ ix]; } SizeT size() const { return sz;} void push_back( ArrayIndexT* aIx) { // if( sz >= MAXRANK) // debug assert( sz < MAXRANK); arrayIxArr[ sz++] = aIx; } void Clear() { for( int i=0; iClear(); } void Destruct() // only to be used from destructor (instance is not valid anymore afterwards) { for( int i=0; iData(); if( v == NULL) return NULL; return v->Dup(); } DVar* GetVarPtr() const { return varPtr;} SizeT NParam() { return 0;} // number of parameter to Init(...) RangeT GetS() { return s;} bool Scalar() const { return true;} bool Scalar( RangeT& s_) const { s_ = s; return true; } void Init() { sInit = varPtr->Data()->LoopIndex(); s = sInit; } void Clear() {} RangeT GetIx0() { return s; } ~ArrayIndexScalarVP() {} ArrayIndexScalarVP( RefDNode& dNode); // c-i ArrayIndexScalarVP( const ArrayIndexScalarVP& r): varPtr( r.varPtr), s( r.s) {} ArrayIndexT* Dup() const { return new ArrayIndexScalarVP(*this); } // if this is used, Init was NOT called before // BaseGDL* Index( BaseGDL* var, IxExprListT& ixL); // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim); }; // constant SCALAR class CArrayIndexScalar: public ArrayIndexT { private: RangeT sInit; // can be < 0 as well RangeT s; BaseGDL* rawData; // for overloaded object indexing CArrayIndexScalar( const CArrayIndexScalar& c): sInit( c.sInit), s( c.s) { assert( c.rawData != NULL); rawData = c.rawData->Dup(); } public: IndexType Type() { return CArrayIndexScalarID;} BaseGDL* OverloadIndexNew() { assert( rawData != NULL); return rawData->Dup(); } SizeT NParam() { return 0;} // number of parameter to Init(...) BaseGDL* StealRawData() { BaseGDL* r = rawData; rawData = NULL; return r;} bool Scalar() const { return true;} bool Scalar( RangeT& s_) const { s_ = s; return true; } RangeT GetIx0() { return s; } RangeT GetS() { return s;} ~CArrayIndexScalar() { delete rawData; } // grabs c CArrayIndexScalar( BaseGDL* c) : rawData(c) { // if( c->Type() == GDL_STRING) // { // DStringGDL* cString = static_cast(c); // if( (*cString)[0] == "") // { // s = 0; // } // else // { // const char* cStart=(*cString)[0].c_str(); // char* cEnd; // RangeT ix=strtol(cStart,&cEnd,10); // if( cEnd == cStart) // { // // in LoopIndex() just a warning is printed // // An exception is necessary as then ArrayIndexScalar // // is used instead (see: gdlc.tree.g: arrayindex) // throw GDLException("Type conversion error: " // "Unable to convert given STRING: '"+ // (*cString)[0]+"' to index."); // } // s = ix; // } // } // else sInit = c->LoopIndex(); // non STRING throw if not allowed s = sInit; } CArrayIndexScalar( RangeT s_): sInit( s_), s( s_), rawData(NULL) {} ArrayIndexT* Dup() const { return new CArrayIndexScalar( *this); } void Clear() {} void Init() {} // // if this is used, Init was NOT called before // BaseGDL* Index( BaseGDL* var, IxExprListT& ixL) // { // if( s >= var->N_Elements()/*var->Size()*/) // throw GDLException(-1,NULL,"Scalar subscript out of range [>].h1",true,false); // return var->NewIx( s); // } // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { if( sInit < 0) s = sInit + varDim; else s = sInit; if( s < 0) throw GDLException(-1,NULL,"Constant scalar subscript out of range [-i].",true,false); if( s >= varDim && s > 0) // varDim == 0 && s == 0 ok throw GDLException(-1,NULL,"Constant scalar out of range [i].",true,false); return 1; // if( s >= varDim && s > 0) // varDim == 0 && s == 0 ok // throw GDLException(-1,NULL,"Scalar subscript out of range [>].h2",true,false); // return 1; } }; //class CArrayIndexScalar: public ArrayIndexT // INDEXED or ONE [v] (must handle both) class ArrayIndexIndexed: public ArrayIndexT { protected: bool strictArrSubs; // for compile_opt STRICTARRSUBS RangeT sInit; // can be < 0 as well RangeT s; // SizeT maxVal; AllIxIndicesT* ix; char ixBuf[ AllIxMaxSize]; const dimension* ixDim; // keep dimension of ix // forbid c-i ArrayIndexIndexed( const ArrayIndexT& r) {} public: IndexType Type() { return ArrayIndexIndexedID;} BaseGDL* OverloadIndexNew( BaseGDL* p1) { if( p1 == NULL) return NULL; return p1->Dup(); } SizeT NParam() { return 1;} // number of parameter to Init(...) RangeT GetS() { return s;} bool Scalar() const { return (ix == NULL);} bool Scalar( RangeT& s_) const // changed from RangeT for proper overloading { if( ix == NULL) { s_ = s; return true; } s_ = (*ix)[0]; return (ix->size() == 1); } bool Indexed() { return (ix != NULL);} const dimension& GetDim() { assert(ixDim != NULL); return *ixDim;} RangeT GetIx0() { if( ix != NULL) return (*ix)[0]; // from array return s; } SizeT GetIx( SizeT i) { assert( ix != NULL); return (*ix)[ i]; } // SizeT* StealIx() { SizeT* ret = ix; ix = NULL; return ret;} //AllIxIndicesT* StealIx() { AllIxIndicesT* ret = ix; ix = NULL; return ret;} AllIxIndicesT* GetAllIx() const { return ix;} ~ArrayIndexIndexed() { // delete ix; // delete ixDim; } ArrayIndexIndexed( bool strictArrSubs_ = false): strictArrSubs( strictArrSubs_), // maxVal( 0), ix( NULL), ixDim( NULL) {} ArrayIndexT* Dup() const { ArrayIndexIndexed* d = new ArrayIndexIndexed( strictArrSubs); assert( ix == NULL); assert( ixDim == NULL); d->sInit = sInit; d->s = s; // d->maxVal = maxVal; return d; } void Clear() { // maxVal = 0; // delete ixDim; ixDim = NULL; // delete ix; ix = NULL; // marker ONE or INDEXED } void Init( BaseGDL* ix_) { if( ix_->Rank() == 0) // type ONE { ix_->Scalar2RangeT(sInit); s = sInit; // in case of assoc NIter is not called // int ret = ix_->Scalar2RangeT(s); // from GDL 0.9 on negative indices are fine // if( ret == -1) // index < 0 // { // throw // GDLException(-1,NULL, "Subscript range values of the" // " form low:high must be >= 0, < size," // " with low <= high.",true,false); // } return; } // type INDEXED DType dType = ix_->Type(); assert( dType != GDL_UNDEF); // assert( maxVal == 0); int typeCheck = DTypeOrder[ dType]; if( typeCheck >= 100) throw GDLException(-1, NULL,"Type not allowed as subscript.",true,false); //SizeT nElem = ix_->N_Elements(); // ix = new SizeT[ nElem]; // allocate array //DEBUG if( ix != NULL) assert( ix == NULL); // ix = new AllIxMultiT( nElem); if( strictArrSubs) ix = new (ixBuf) AllIxIndicesStrictT( ix_); else ix = new (ixBuf) AllIxIndicesT( ix_); ixDim = &ix_->Dim(); } // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { if( ix == NULL) // ONE { if( sInit < 0) s = sInit + varDim; else s = sInit; if( s < 0) throw GDLException(-1, NULL,"Subscript out of range [-i].",true,false); if( s >= varDim && s > 0) throw GDLException(-1, NULL,"Subscript out of range [i].",true,false); return 1; } // INDEXED ix->SetUpper( varDim-1); return ix->size(); } }; // class ArrayIndexIndexed: public ArrayIndexT // INDEXED or ONE [v] (must handle both) class CArrayIndexIndexed: public ArrayIndexT { private: bool strictArrSubs; // for compile_opt STRICTARRSUBS RangeT sInit; // can be < 0 as well RangeT s; AllIxIndicesT* ix; char ixBuf[ AllIxMaxSize]; const dimension* ixDim; // keep dimension of ix // forbid c-i CArrayIndexIndexed( const ArrayIndexT& r) { assert(false);} BaseGDL* rawData; bool isScalar; public: IndexType Type() { return CArrayIndexIndexedID;} BaseGDL* OverloadIndexNew() { assert( rawData != NULL); return rawData->Dup(); } SizeT NParam() { return 0;} // number of parameter to Init(...) RangeT GetS() { return s; } bool Scalar() const { return isScalar;} bool Scalar( RangeT& s_) const // changed from RangeT for proper overloading { if( isScalar) { s_ = s; return true; } s_ = (*ix)[0]; return (ix->size() == 1); } bool Indexed() { return !isScalar;} const dimension& GetDim() { assert(ixDim != NULL); return *ixDim;} RangeT GetIx0() { if( !isScalar) return (*ix)[0]; // from array return s; } SizeT GetIx( SizeT i) { assert( ix != NULL); return (*ix)[ i]; } // SizeT* StealIx() { SizeT* ret = ix; ix = NULL; return ret;} //AllIxIndicesT* StealIx() { AllIxIndicesT* ret = ix; ix = NULL; return ret;} AllIxIndicesT* GetAllIx() const { return ix; } ~CArrayIndexIndexed() { delete rawData; } // grabs c CArrayIndexIndexed( BaseGDL* c, bool strictArrSubs_ = false) : strictArrSubs( strictArrSubs_) , ix( NULL), ixDim( NULL) , rawData( c) { assert( rawData != NULL); if( rawData->Rank() == 0) // type ONE { rawData->Scalar2RangeT(sInit); s = sInit; // in case of assoc NIter is not called isScalar = true; return; } // type INDEXED isScalar = false;; ixDim = &rawData->Dim(); assert( rawData->Type() != GDL_UNDEF); DType dType = rawData->Type(); int typeCheck = DTypeOrder[ dType]; if( typeCheck >= 100) throw GDLException(-1, NULL,"Type not allowed as subscript.",true,false); if( strictArrSubs) ix = new (ixBuf) AllIxIndicesStrictT( rawData); else ix = new (ixBuf) AllIxIndicesT( rawData); } ArrayIndexT* Dup() const { return new CArrayIndexIndexed( rawData->Dup(), strictArrSubs); } void Clear() {} // nothing to clear void Init() {} // already initialized in constructor // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { if( isScalar) // ONE { if( sInit < 0) s = sInit + varDim; else s = sInit; if( s < 0) throw GDLException(-1, NULL,"Subscript out of range [-i].",true,false); if( s >= varDim && s > 0) throw GDLException(-1, NULL,"Subscript out of range [i].",true,false); return 1; } // INDEXED ix->SetUpper( varDim-1); return ix->size(); } }; //class CArrayIndexIndexed: public ArrayIndexIndexed // [*] class ArrayIndexAll: public ArrayIndexT { public: IndexType Type() { return ArrayIndexAllID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew() { const DLong arr[3] = {0,-1,1}; return new DLongGDL( arr, 3); } SizeT NParam() { return 0;} // number of parameter to Init(...) void Init() {}; RangeT GetIx0() { return 0;} ArrayIndexT* Dup() const { return new ArrayIndexAll(); } // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { return varDim; } }; // [s:*] class ArrayIndexORange: public ArrayIndexT { protected: RangeT sInit; RangeT s; public: IndexType Type() { return ArrayIndexORangeID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew( BaseGDL* s_) { Init( s_); DLong arr[3] = {static_cast(sInit),-1,1}; return new DLongGDL( arr, 3); } SizeT NParam() { return 1;} // number of parameter to Init(...) RangeT GetS() { return s;} RangeT GetIx0() { return s;} ArrayIndexT* Dup() const { ArrayIndexORange* d = new ArrayIndexORange(); d->sInit = sInit; d->s = s; return d; } // s is always scalar here void Init( BaseGDL* s_) { int retMsg=s_->Scalar2RangeT(sInit); if( retMsg == 0) // index empty or array { if( s_->N_Elements() == 0) throw GDLException(-1,NULL,"Internal error: Scalar2RangeT:" " 1st index empty",true,false); else throw GDLException(-1,NULL,"Expression must be a scalar" " in this context.",true,false); } // s = sInit; // for assoc // not with Scalar2RangeT(): // if( retMsg == -1) // index < 0 // { // throw // GDLException(-1,NULL,"Subscript range values of the" // " form low:high must be >= 0, < size, " // "with low <= high.",true,false); // } } SizeT NIter( SizeT varDim) { if( sInit >= varDim) // && s > 0) throw GDLException(-1,NULL,"Subscript out of range [s:*].",true,false); if( sInit < 0) { s = sInit + varDim; if( s < 0) throw GDLException(-1,NULL,"Subscript out of range [-s:*].",true,false); return (varDim - s); } s = sInit; return (varDim - s); } }; class CArrayIndexORange: public ArrayIndexORange { public: IndexType Type() { return CArrayIndexORangeID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew() { DLong arr[3] = {static_cast(sInit),-1,1}; return new DLongGDL( arr, 3); } SizeT NParam() { return 0;} // number of parameter to Init(...) CArrayIndexORange( BaseGDL* c): ArrayIndexORange() { ArrayIndexORange::Init( c); } CArrayIndexORange() {} ArrayIndexT* Dup() const { CArrayIndexORange* d = new CArrayIndexORange(); d->sInit = sInit; d->s = s; return d; } }; // [s:e] class ArrayIndexRange: public ArrayIndexT { protected: RangeT sInit,eInit; RangeT s,e; public: IndexType Type() { return ArrayIndexRangeID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew( BaseGDL* s_, BaseGDL* e_) { Init( s_, e_); DLong arr[3] = {static_cast(sInit),static_cast(eInit),1}; return new DLongGDL( arr, 3); } SizeT NParam() { return 2;} // number of parameter to Init(...) RangeT GetS() { return s;} RangeT GetIx0() { return s;} ArrayIndexT* Dup() const { ArrayIndexRange* d = new ArrayIndexRange(); d->sInit = sInit; d->eInit = eInit; d->s = s; d->e = e; return d; } void Init( BaseGDL* s_, BaseGDL* e_) { // SizeT varSize = var->N_Elements()/*var->Size()*/; int retMsg=s_->Scalar2RangeT(sInit); if( retMsg == 0) // index empty or array { if( s_->N_Elements() == 0) throw GDLException(-1,NULL,"Internal error: Scalar2RangeT: 1st index empty.",true,false); else throw GDLException(-1,NULL,"Expression must be a scalar in this context.",true,false); } // if( retMsg == -1) // index < 0 // { // throw // GDLException(-1,NULL,"Subscript range values of the form low:high " // "must be >= 0, < size, with low <= high.",true,false); // } retMsg=e_->Scalar2RangeT(eInit); if( retMsg == 0) // index empty or array { if( e_->N_Elements() == 0) throw GDLException(-1,NULL,"Internal error: Scalar2RangeT: 2nd index empty.",true,false); else throw GDLException(-1,NULL,"Expression must be a scalar in this context.",true,false); } } // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { // RangeT sl,el; if( sInit < 0) { s = sInit + varDim; if( s < 0) throw GDLException(-1,NULL,"Subscript out of range [S:e].",true,false); } else s = sInit; if( eInit < 0) { e = eInit + varDim; if( e < 0) throw GDLException(-1,NULL,"Subscript out of range [s:E].",true,false); } else e = eInit; if( s > e) throw GDLException(-1,NULL,"Subscript range values of the form low:high " "must be < size, with low <= high",true,false); if( e >= varDim) // && e > 0) throw GDLException(-1,NULL,"Subscript out of range [s:e].",true,false); return (e - s + 1); } }; class CArrayIndexRange: public ArrayIndexRange { public: IndexType Type() { return CArrayIndexRangeID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew() { DLong arr[3] = {static_cast(sInit),static_cast(eInit),1}; return new DLongGDL( arr, 3); } SizeT NParam() { return 0;} // number of parameter to Init(...) CArrayIndexRange( BaseGDL* c1, BaseGDL* c2): ArrayIndexRange() { ArrayIndexRange::Init( c1, c2); } CArrayIndexRange(){} ArrayIndexT* Dup() const { CArrayIndexRange* d = new CArrayIndexRange(); d->sInit = sInit; d->eInit = eInit; d->s = s; d->e = e; return d; } }; // [s:*:st] class ArrayIndexORangeS: public ArrayIndexT { protected: RangeT sInit; RangeT s; SizeT stride; public: IndexType Type() { return ArrayIndexORangeSID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew( BaseGDL* s_, BaseGDL* stride_) { Init( s_, stride_); DLong arr[3] = {static_cast(sInit),-1,static_cast(stride)}; return new DLongGDL( arr, 3); } SizeT NParam() { return 2;} // number of parameter to Init(...) RangeT GetS() { return s;} SizeT GetStride() { return stride;} RangeT GetIx0() { return s;} ArrayIndexT* Dup() const { ArrayIndexORangeS* d = new ArrayIndexORangeS(); d->sInit = sInit; d->s = s; d->stride = stride; return d; } void Init( BaseGDL* s_, BaseGDL* stride_) { int retMsg=s_->Scalar2RangeT( sInit); if( retMsg == 0) // index empty or array { if( s_->N_Elements() == 0) throw GDLException( "Internal error: Scalar2RangeT:" " 1st index empty",true,false); else throw GDLException( "Expression must be a scalar" " in this context.",true,false); } // if( retMsg == -1) // index < 0 // { // throw // GDLException( "Subscript range values of the" // " form low:high must be >= 0, < size, with low <= high.",true,false); // } // stride retMsg=stride_->Scalar2Index( stride); if( retMsg == 0) // index empty or array { if( stride_->N_Elements() == 0) throw GDLException( "Internal error: Scalar2Index:" " stride index empty",true,false); else throw GDLException( "Expression must be a scalar" " in this context.",true,false); } if( retMsg == -1 || stride == 0) // stride <= 0 { throw GDLException( "Range subscript stride must be >= 1.",true,false); } } // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { if( sInit < 0) { s = sInit + varDim; if( s < 0) throw GDLException(-1,NULL,"Subscript out of range [-S:*:stride].",true,false); return (varDim - s + stride - 1)/stride; } else s= sInit; if( s >= varDim) // && s > 0) throw GDLException(-1,NULL,"Subscript out of range [s:*:stride].",true,false); return (varDim - s + stride - 1)/stride; } }; class CArrayIndexORangeS: public ArrayIndexORangeS { public: IndexType Type() { return CArrayIndexORangeSID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew() { DLong arr[3] = {static_cast(sInit),-1,static_cast(stride)}; return new DLongGDL( arr, 3); } SizeT NParam() { return 0;} // number of parameter to Init(...) CArrayIndexORangeS( BaseGDL* c1, BaseGDL* c2): ArrayIndexORangeS() { ArrayIndexORangeS::Init( c1, c2); } CArrayIndexORangeS(){} ArrayIndexT* Dup() const { CArrayIndexORangeS* d = new CArrayIndexORangeS(); d->sInit = sInit; d->s = s; d->stride = stride; return d; } }; // [s:e:st] class ArrayIndexRangeS: public ArrayIndexT { protected: RangeT sInit,eInit; RangeT s,e; SizeT stride; void Init( DLong s_, DLong e_, DLong stride_) { sInit = s_; eInit = e_; if( stride_ <= 0) { throw GDLException( "Range subscript stride must be >= 1.",true,false); } stride = stride_; } public: IndexType Type() { return ArrayIndexRangeSID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew( BaseGDL* s_, BaseGDL* e_, BaseGDL* stride_) { Init( s_, e_, stride_); DLong arr[3] = {static_cast(sInit),static_cast(eInit),static_cast(stride)}; return new DLongGDL( arr, 3); } SizeT NParam() { return 3;} // number of parameter to Init(...) RangeT GetS() { return s;} SizeT GetStride() { return stride;} RangeT GetIx0() { return s;} ArrayIndexT* Dup() const { ArrayIndexRangeS* d = new ArrayIndexRangeS(); d->sInit = sInit; d->eInit = eInit; d->s = s; d->e = e; d->stride = stride; return d; } void Init( BaseGDL* s_, BaseGDL* e_, BaseGDL* stride_) { int retMsg=s_->Scalar2RangeT(sInit); if( retMsg == 0) // index empty or array { if( s_->N_Elements() == 0) throw GDLException( "Internal error: Scalar2RangeT: 1st index empty.",true,false); else throw GDLException( "Expression must be a scalar in this context.",true,false); } // if( retMsg == -1) // index < 0 // { // throw // GDLException( "Subscript range values of the form low:high " // "must be >= 0, < size, with low <= high.",true,false); // } retMsg=e_->Scalar2RangeT(eInit); if( retMsg == 0) // index empty or array { if( e_->N_Elements() == 0) throw GDLException( "Internal error: Scalar2RangeT: 2nd index empty.",true,false); else throw GDLException( "Expression must be a scalar in this context.",true,false); } // stride retMsg=stride_->Scalar2Index(stride); if( retMsg == 0) // index empty or array { if( stride_->N_Elements() == 0) throw GDLException( "Internal error: Scalar2Index:" " stride index empty",true,false); else throw GDLException( "Expression must be a scalar" " in this context.",true,false); } if( retMsg == -1 || stride == 0) // stride <= 0 { throw GDLException( "Range subscript stride must be >= 1.",true,false); } } // number of iterations // also checks/adjusts range SizeT NIter( SizeT varDim) { // RangeT sl,el; if( sInit < 0) { s = sInit + varDim; if( s < 0) throw GDLException(-1,NULL,"Subscript out of range [-S:e:stride].",true,false); } else s = sInit; if( eInit < 0) { e = eInit + varDim; if( e < 0) throw GDLException(-1,NULL,"Subscript out of range [s:-E:stride].",true,false); } else e = eInit; if( s > e) throw GDLException(-1,NULL,"Subscript range values of the form low:high " "must be < size, with low <= high",true,false); if( e >= varDim) // && e > 0) { throw GDLException(-1,NULL,"Subscript out of range [s:E:st].",true,false); } return (e - s + stride)/stride; } }; class CArrayIndexRangeS: public ArrayIndexRangeS { public: IndexType Type() { return CArrayIndexRangeSID;} bool IsRange() { return true;} BaseGDL* OverloadIndexNew() { DLong arr[3] = {static_cast(sInit),static_cast(eInit),static_cast(stride)}; return new DLongGDL( arr, 3); } SizeT NParam() { return 0;} // number of parameter to Init(...) CArrayIndexRangeS( BaseGDL* c1, BaseGDL* c2, BaseGDL* c3): ArrayIndexRangeS() { ArrayIndexRangeS::Init( c1, c2, c3); } // for internal routines to ease definition CArrayIndexRangeS( DLong s_, DLong e_, DLong stride_): ArrayIndexRangeS() { ArrayIndexRangeS::Init( s_, e_, stride_); } CArrayIndexRangeS(){} ArrayIndexT* Dup() const { CArrayIndexRangeS* d = new CArrayIndexRangeS(); d->sInit = sInit; d->eInit = eInit; d->s = s; d->e = e; d->stride = stride; return d; } }; #endif gdl-0.9.9/src/arrayindexlistnoassoct.hpp000066400000000000000000001646651340051421000204230ustar00rootroot00000000000000/*************************************************************************** arrayindexlistnoassoct.hpp - array access descriptor, optimization for non assoc index ------------------- begin : July 22 2005 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ARRAYINDEXLISTNOASSOCT_HPP_ #define ARRAYINDEXLISTNOASSOCT_HPP_ #include "arrayindex.hpp" // this is the main file for non assco arrayindices, // this classes here must only be used with non-assoc variables // the classes in arrayindexlistt.hpp can handle both, because // as ASSOC variables are connected to files, a few more checks // do not hurt, other than here: These are the core routines for indexing // only one index [ix],[s:e],... // NEVER ArrayIndexScalar types (they have their own ArrayIndexListT) class ArrayIndexListOneNoAssocT: public ArrayIndexListT { private: IxExprListT cleanupIx; ArrayIndexT* ix; SizeT nIx; // number of indexed elements AllIxBaseT* allIx; char allIxInstance[ AllIxMaxSize]; public: ~ArrayIndexListOneNoAssocT() { // delete allIx; delete ix; cleanupIx.Cleanup(); // must be explicitely cleaned up } // constructor ArrayIndexListOneNoAssocT() : cleanupIx() , ix( NULL) , allIx( NULL) { nParam = 0;} ArrayIndexListOneNoAssocT( const ArrayIndexListOneNoAssocT& cp): ArrayIndexListT( cp), cleanupIx(), ix( cp.ix->Dup()), allIx( NULL) { assert( cp.allIx == NULL); assert( cp.cleanupIx.size() == 0); } // called after structure is fixed ArrayIndexListOneNoAssocT( ArrayIndexVectorT* aIV): allIx( NULL) { ix = (*aIV)[0]->Dup(); // ArrayIndexListOneT will grab here nParam = ix->NParam(); } void Clear() { // delete allIx; allIx = NULL; // allIxMulti.Clear(); ix->Clear(); cleanupIx.Cleanup(); } ArrayIndexListT* Clone() { return new ArrayIndexListOneNoAssocT( *this);} IxExprListT* GetCleanupIx() { return &cleanupIx;} void InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( allIx == NULL); assert( ix_.size() == nParam); // if( cleanupIxIn != NULL) // cleanupIx = *cleanupIxIn; DLongGDL* isRange = new DLongGDL( dimension(1, BaseGDL::NOZERO)); ixOut.push_back(isRange); (*isRange)[ 0] = (ix->IsRange()) ? 1 : 0; if( nParam == 0) { BaseGDL* oIx = ix->OverloadIndexNew(); ixOut.push_back(oIx); return; } if( nParam == 1) { BaseGDL* oIx = ix->OverloadIndexNew( ix_[ 0]); ixOut.push_back(oIx); return; } if( nParam == 2) { BaseGDL* oIx = ix->OverloadIndexNew( ix_[ 0], ix_[ 1]); ixOut.push_back(oIx); return; } if( nParam == 3) { BaseGDL* oIx = ix->OverloadIndexNew( ix_[ 0], ix_[ 1], ix_[ 2]); ixOut.push_back(oIx); return; } } void Init( IxExprListT& ix_)//, IxExprListT* cleanupIxIn) { assert( allIx == NULL); assert( ix_.size() == nParam); // if( cleanupIxIn != NULL) // cleanupIx = *cleanupIxIn; if( nParam == 0) //return; { ix->Init(); return; } if( nParam == 1) { ix->Init( ix_[ 0]); return; } if( nParam == 2) { ix->Init( ix_[ 0], ix_[ 1]); return; } else // nParam == 3 { assert( nParam == 3); ix->Init( ix_[ 0], ix_[ 1], ix_[ 2]); return; } } void Init() {} // eg. a[*] // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty // bool ToAssocIndex( SizeT& lastIx) bool ToAssocIndex( SizeT& lastIx) { assert( 0); throw GDLException(-1,NULL,"Internal error: ArrayIndexListOneNoAssocT::ToAssocIndex(...) called.",true,false); return true; } // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // for assoc variables last index is the record // if( var->IsAssoc()) return; // ArrayIndexScalar[VP] are not initialized // they need the NIter call, but // for only one index they have their own ArrayIndexListT nIx=ix->NIter( var->N_Elements()/*var->Size()*/); } // structure of indexed expression const dimension GetDim() { if( ix->Scalar()) { return dimension(); } else if( ix->Indexed()) { return static_cast(ix)->GetDim(); // gets structure of indexing array } else { return dimension( nIx); // one dimensional if not indexed } } SizeT N_Elements() { return nIx; } // returns 1-dim index for all elements AllIxBaseT* BuildIx() { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; assert( allIx == NULL); // if( allIx != NULL) // return allIx; if( ix->Indexed()) { // allIx = static_cast< ArrayIndexIndexed*>(ix)->StealIx(); allIx = static_cast< ArrayIndexIndexed*>(ix)->GetAllIx(); return allIx; } if( nIx == 1) { allIx = new (allIxInstance) AllIxT( ix->GetS()); return allIx; } // allIx = new AllIxMulAllIxRangeStrideTtiT( nIx); SizeT s = ix->GetS(); SizeT ixStride = ix->GetStride(); if( ixStride <= 1) if( s != 0) { allIx = new (allIxInstance) AllIxRangeT( nIx, s); // for( SizeT i=0; i(allIx)->SetIx( i, i + s); // (*allIx)[i] = i + s; } else { allIx = new (allIxInstance) AllIxRange0T( nIx); // for( SizeT i=0; i(allIx)->SetIx( i, i ); // (*allIx)[i] = i; } else if( s != 0) { allIx = new (allIxInstance) AllIxRangeStrideT( nIx, s, ixStride); // for( SizeT i=0; i(allIx)->SetIx( i, i * ixStride + s); // (*allIx)[i] = i * ixStride + s; } else { allIx = new (allIxInstance) AllIxRange0StrideT( nIx, ixStride); // for( SizeT i=0; i(allIx)->SetIx( i, i * ixStride); // (*allIx)[i] = i * ixStride; } return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return ix->GetIx0(); } void AssignAt( BaseGDL* var, BaseGDL* right) { // scalar case if( right->N_Elements() == 1 && //!var->IsAssoc() && ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT) { var->AssignAtIx( ix->GetIx0(), right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_) { Init( ix_);//, NULL); if( ix->Scalar())// && ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT) // if( !var->IsAssoc() && ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT) { SizeT assertValue = ix->NIter( var->N_Elements()/*var->Size()*/); assert( assertValue == 1); return var->NewIx( ix->GetIx0()); } // normal case SetVariable( var); return var->Index( this); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { destStart = ix->GetIx0(); return dimension( destStart); } SizeT NDim() { return 1; } }; //class ArrayIndexListOneT: public ArrayIndexListT // loop index class ArrayIndexListOneScalarNoAssocT: public ArrayIndexListT { protected: SizeT varIx; RangeT sInit; RangeT s; AllIxT allIx; public: ~ArrayIndexListOneScalarNoAssocT() {} // constructor ArrayIndexListOneScalarNoAssocT() : varIx( 0) // , allIx( NULL) { nParam = 0;} ArrayIndexListOneScalarNoAssocT( const ArrayIndexListOneScalarNoAssocT& cp) : ArrayIndexListT( cp) , varIx( cp.varIx) , s( cp.s) // , allIx( NULL) { // assert( cp.allIx == NULL); } // called after structure is fixed ArrayIndexListOneScalarNoAssocT( ArrayIndexVectorT* aIV) // : allIx( NULL) { nParam = 0; varIx = static_cast((*aIV)[0])->GetVarIx(); // ArrayIndexListOneScalarT will do the cleanup // delete (*aIV)[0]; } void Clear() {} ArrayIndexListT* Clone() { return new ArrayIndexListOneScalarNoAssocT( *this);} void InitAsOverloadIndex( IxExprListT& ix_, IxExprListT& ixOut); void Init() {} // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { assert( false); return false;} // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var); // structure of indexed expression const dimension GetDim() { return dimension(); } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { allIx.Set( s); return &allIx; // if( allIx != NULL) // { // allIx->Set( s); // return allIx; // } // // allIx = new AllIxT( s); // return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return s; } void AssignAt( BaseGDL* var, BaseGDL* right); // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_); // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { destStart = s; return dimension( destStart); } SizeT NDim() { return 1; } }; // class ArrayIndexListOneScalarT: public ArrayIndexListT class ArrayIndexListOneScalarVPNoAssocT: public ArrayIndexListT { protected: DVar* varPtr; RangeT sInit; RangeT s; AllIxT allIx; // AllIxT* allIx; public: ~ArrayIndexListOneScalarVPNoAssocT() { // delete allIx; } // constructor ArrayIndexListOneScalarVPNoAssocT() : varPtr( NULL) // , allIx( NULL) { nParam = 0;} ArrayIndexListOneScalarVPNoAssocT( const ArrayIndexListOneScalarVPNoAssocT& cp) : ArrayIndexListT( cp) , varPtr( cp.varPtr) , sInit( cp.sInit) , s( cp.s) // , allIx( NULL) { // assert( cp.allIx == NULL); } // called after structure is fixed ArrayIndexListOneScalarVPNoAssocT( ArrayIndexVectorT* aIV) // : allIx( NULL) { nParam = 0; varPtr = static_cast((*aIV)[0])->GetVarPtr(); // ArrayIndexListOneScalarVPT will do the cleanup // delete (*aIV)[0]; } void Clear() {} ArrayIndexListT* Clone() { return new ArrayIndexListOneScalarVPNoAssocT( *this);} void InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut); void Init() {} // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context.",true,false); s = sInit; lastIx = s; return true; } // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var) { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements(); else s = sInit; // for assoc variables last index is the record // if( var->IsAssoc()) return; if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript too large.",true,false); if( s < 0) throw GDLException(-1,NULL,"Scalar subscript too small (<-1).",true,false); } // structure of indexed expression const dimension GetDim() { return dimension(); } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { allIx.Set( s); return &allIx; // if( allIx != NULL) // { // allIx->Set( s); // return allIx; // } // // allIx = new AllIxT( s); // return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return s; } void AssignAt( BaseGDL* var, BaseGDL* right) { // Init() was already called // scalar case if( right->N_Elements() == 1) // && !var->IsAssoc()) // && var->Type() != GDL_STRUCT) { s = varPtr->Data()->LoopIndex(); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript out of range [>].2",true,false); var->AssignAtIx( s, right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_); // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { destStart = s; return dimension( destStart); } SizeT NDim() { return 1; } }; // class ArrayIndexListOneScalarVPT: public ArrayIndexListT class ArrayIndexListOneConstScalarNoAssocT: public ArrayIndexListT { RangeT sInit; RangeT s; AllIxT allIx; BaseGDL* rawData; public: ~ArrayIndexListOneConstScalarNoAssocT() { delete rawData; } // constructor ArrayIndexListOneConstScalarNoAssocT() : rawData( NULL) // : allIx( NULL) { nParam = 0; } ArrayIndexListOneConstScalarNoAssocT( const ArrayIndexListOneConstScalarNoAssocT& cp) : ArrayIndexListT( cp) , sInit( cp.sInit) , s( cp.s) // , allIx( NULL) { assert( cp.rawData != NULL); rawData = cp.rawData->Dup(); // assert( cp.allIx == NULL); // all copying should be done before using. } // called after structure is fixed ArrayIndexListOneConstScalarNoAssocT( ArrayIndexVectorT* aIV) // : allIx( NULL) { assert( CArrayIndexScalarID == (*aIV)[0]->Type()); // see MakeArrayIndex (arrayindex.cpp) CArrayIndexScalar* arrayIndex = static_cast( (*aIV)[0]); rawData = arrayIndex->StealRawData(); sInit = arrayIndex->GetS(); if( sInit >= 0) s = sInit; nParam = 0; // ArrayIndexListOneConstScalarT will do the cleanup // delete (*aIV)[0]; } void InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( 0 == nParam); assert( rawData != NULL); DLongGDL* isRange = new DLongGDL( 0); ixOut.push_back(isRange); ixOut.push_back(rawData->Dup()); } void Clear() {} ArrayIndexListT* Clone() { return new ArrayIndexListOneConstScalarNoAssocT( *this);} void Init() {} SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { allIx.Set( s); return &allIx; // if( allIx != NULL) // return allIx; // // allIx = new AllIxT( s); // return allIx; } // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { if( sInit < 0) throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context. ("+i2s(sInit)+")",true,false); lastIx = sInit; return true; } // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var) { // if( var->IsAssoc()) return; if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; // for assoc variables last index is the record if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range [<0] ("+i2s(s)+")",true,false); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript out of range [>] ("+i2s(s)+")",true,false); } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return s; } void AssignAt( BaseGDL* var, BaseGDL* right) { // one index and assoc -> no index left -> no AssignAt // wrong! This is the entry function // assert( !var->IsAssoc()); // Init() was already called // scalar case if( right->N_Elements() == 1)// && !var->IsAssoc())// && var->Type() != GDL_STRUCT) { if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range [<0]. ("+i2s(s)+")",true,false); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript out of range [>]. ("+i2s(s)+")",true,false); var->AssignAtIx( s, right); // must use COPY_BYTE_AS_INT return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_) { // Init() not called // if( !var->IsAssoc())// && var->Type() != GDL_STRUCT) { if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range [<0]: ("+i2s(s)+")",true,false); if( s >= var->N_Elements()/*var->Size()*/) { // std::cout << s << " var->N_Elements()/*var->Size()*/:" << var->N_Elements()/*var->Size()*/ << std::endl; throw GDLException(-1,NULL,"Scalar subscript out of range [>]: ("+i2s(s)+")",true,false); } return var->NewIx( s); } // normal case //Init();// ix_); //SetVariable( var); return var->Index( this); } const dimension GetDim() { return dimension(); } const dimension GetDimIx0( SizeT& destStart) { destStart = s; return dimension( destStart); } SizeT NDim() { return 1; } }; // class ArrayIndexListOneConstScalarT: public ArrayIndexListT // all scalar elements (multi-dim) class ArrayIndexListScalarNoAssocT: public ArrayIndexListT { private: ArrayIndexVectorT ixList; // std::vector paramPresent; SizeT acRank; // rank upto which indexing is done const SizeT* varStride; // variables stride // SizeT varStride[MAXRANK+1]; // variables stride // SizeT nIx; // number of indexed elements AllIxT allIx; // AllIxT allIxInstance; // ArrayIndexT* ixListEnd; // for assoc index // constructor ArrayIndexListScalarNoAssocT(): acRank(0) { nParam = 0;} public: ~ArrayIndexListScalarNoAssocT() // cleanup done by related ArrayIndexListScalarT { // delete allIx; // ixList.Destruct(); // for( std::vector::iterator i=ixList.begin(); // i != ixList.end(); ++i) // { delete *i;} } // // constructor // ArrayIndexListScalarNoAssocT(): // acRank(0) // // allIx( NULL), // // ixListEnd( NULL) // { nParam = 0;} ArrayIndexListScalarNoAssocT( const ArrayIndexListScalarNoAssocT& cp): ArrayIndexListT( cp), // paramPresent( cp.paramPresent), acRank(cp.acRank) // allIx( NULL), // ixListEnd( NULL) { // ixList.reserve(MAXRANK); // assert( cp.allIx == NULL); // assert( cp.ixListEnd == NULL); for( SizeT i=0; iDup()); } // called once after structure is fixed ArrayIndexListScalarNoAssocT( ArrayIndexVectorT* ix): ixList( *ix) // allIx( NULL), // ixListEnd( NULL) { if( ix->size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); assert( ixList.size() > 1); // must be, from compiler // set acRank acRank = ixList.size(); nParam = 0; } void InitAsOverloadIndex( IxExprListT& ix, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( ix.size() == 0); DLongGDL* isRange = new DLongGDL( dimension(ixList.size(), BaseGDL::ZERO)); ixOut.push_back(isRange); for( SizeT i=0; iNParam() == 0); BaseGDL* oIx = ixList[ i]->OverloadIndexNew(); ixOut.push_back(oIx); } } void Clear() { } ArrayIndexListT* Clone() { return new ArrayIndexListScalarNoAssocT( *this);} void Init() {} // set the root variable which is indexed by this ArrayIndexListScalarT void SetVariable( BaseGDL* var) { // // set acRank // acRank = ixList.size(); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) for( SizeT i=0; iNIter( var->Dim(i)); // check boundary varStride = var->Dim().Stride(); } // structure of indexed expression const dimension GetDim() { return dimension(); // -> results in scalar } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { // if( allIx != NULL) // return allIx; SizeT s = ixList.FrontGetS(); //[0]->GetS(); for( SizeT l=1; l < acRank; ++l) { s += ixList[l]->GetS() * varStride[l]; } // allIx = &allIxInstance; //new AllIxT(s); // allIx->Set( s); allIx.Set( s); // allIx = new AllIxT(s); // (*allIx)[0] = s; return &allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { // if( acRank == 1) // return ixList.FrontGetS(); //ixList[0]->GetS(); SizeT dStart = ixList.FrontGetS(); //[0]->GetS(); for( SizeT i=1; i < acRank; ++i) dStart += ixList[i]->GetS() * varStride[ i]; return dStart; } void AssignAt( BaseGDL* var, BaseGDL* right) { // right, not var if( right->N_Elements() == 1)// && !var->IsAssoc()) { // SetVariable( var); // // set acRank // acRank = ixList.size(); varStride = var->Dim().Stride(); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( var->Dim(0)); // check boundary SizeT dStart = ixList.FrontGetS(); //[0]->GetS(); for( SizeT i=1; i < acRank; ++i) { ixList[i]->NIter( var->Dim(i)); // check boundary dStart += ixList[i]->GetS() * varStride[ i]; } var->AssignAtIx( dStart, right); // assigns inplace return; } // var->N_Elements() > 1 SetVariable( var); // assert( nIx == 1); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace (not only scalar) } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace (not only scalar) } } BaseGDL* Index( BaseGDL* var, IxExprListT& ix) { varStride = var->Dim().Stride(); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( var->Dim(0)); // check boundary SizeT dStart = ixList.FrontGetS(); //[0]->GetS(); for( SizeT i=1; i < acRank; ++i) { ixList[i]->NIter( var->Dim(i)); // check boundary dStart += ixList[i]->GetS() * varStride[ i]; } return var->NewIx( dStart); //this->LongIx()); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { SizeT dStart = 0; SizeT actIx[ MAXRANK]; for( SizeT i=0; i < acRank; ++i) { actIx[ i] = ixList[i]->GetS(); dStart += actIx[ i] * varStride[ i]; } destStart = dStart; return dimension( actIx, acRank); } SizeT NDim() { return acRank; } }; // class ArrayIndexListScalarT: public ArrayIndexListT // all scalar elements (multi-dim) const int acRank2D = 2; class ArrayIndexListScalarNoAssoc2DT: public ArrayIndexListT { private: ArrayIndexVectorT ixList; // std::vector paramPresent; // enum AcRankEnum { acRank = 2; }; SizeT varStride; // variables stride // SizeT varStride[MAXRANK+1]; // variables stride // SizeT nIx; // number of indexed elements AllIxT allIx; // AllIxT allIxInstance; // ArrayIndexT* ixListEnd; // for assoc index // constructor ArrayIndexListScalarNoAssoc2DT() { nParam = 0;} public: ~ArrayIndexListScalarNoAssoc2DT() // cleanup done by related ArrayIndexListScalarT { } ArrayIndexListScalarNoAssoc2DT( const ArrayIndexListScalarNoAssoc2DT& cp): ArrayIndexListT( cp) { for( SizeT i=0; iDup()); assert( ixList.size() == 2); // must be, from compiler } // called once after structure is fixed ArrayIndexListScalarNoAssoc2DT( ArrayIndexVectorT* ix): ixList( *ix) { if( ix->size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); assert( ixList.size() == 2); // must be, from compiler nParam = 0; } void InitAsOverloadIndex( IxExprListT& ix, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( ix.size() == 0); DLongGDL* isRange = new DLongGDL( dimension(ixList.size(), BaseGDL::ZERO)); ixOut.push_back(isRange); for( SizeT i=0; iNParam() == 0); BaseGDL* oIx = ixList[ i]->OverloadIndexNew(); ixOut.push_back(oIx); } } void Clear() { } ArrayIndexListT* Clone() { return new ArrayIndexListScalarNoAssoc2DT( *this);} void Init() {} // set the root variable which is indexed by this ArrayIndexListScalarT void SetVariable( BaseGDL* var) { varStride = var->Dim(0); ixList[0]->NIter( varStride); // check boundary ixList[1]->NIter( var->Dim(1)); // check boundary } // structure of indexed expression const dimension GetDim() { return dimension(); // -> results in scalar } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { SizeT s = ixList.FrontGetS() + ixList[1]->GetS() * varStride; allIx.Set( s); return &allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { SizeT s = ixList.FrontGetS() + ixList[1]->GetS() * varStride; return s; } void AssignAt( BaseGDL* var, BaseGDL* right) { // right, not var if( right->N_Elements() == 1)// && !var->IsAssoc()) { varStride = var->Dim(0); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( varStride); // check boundary ixList[1]->NIter( var->Dim(1)); // check boundary SizeT s = ixList.FrontGetS() + ixList[1]->GetS() * varStride; var->AssignAtIx( s, right); // assigns inplace return; } // right->N_Elements() > 1 SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace (not only scalar) } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace (not only scalar) } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix) { varStride = var->Dim(0); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( varStride); // check boundary ixList[1]->NIter( var->Dim(1)); // check boundary SizeT dStart = ixList.FrontGetS() + ixList[1]->GetS() * varStride; return var->NewIx( dStart); //this->LongIx()); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { SizeT actIx[ MAXRANK]; actIx[ 0] = ixList[0]->GetS(); actIx[ 1] = ixList[1]->GetS(); SizeT dStart = actIx[ 0] + actIx[ 1] * varStride; destStart = dStart; return dimension( actIx, acRank2D); } SizeT NDim() { return acRank2D; } }; // class ArrayIndexListScalar2DT: public ArrayIndexListT /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // general case (mixed, multi-dim) at least one indexed // but note: last index can be assoc index class ArrayIndexListMultiNoAssocT: public ArrayIndexListT { private: IxExprListT cleanupIx; protected: ArrayIndexVectorT ixList; enum AccessType { GDL_UNDEF=0, // for init access type INDEXED_ONE, // all indexed OR one NORMAL, // mixed ALLINDEXED, ALLONE // all ONE }; AccessType accessType; // actual access type AccessType accessTypeInit; // possible access type non assoc AccessType accessTypeAssocInit;// possible access type for assoc SizeT acRank; // rank upto which indexing is done SizeT nIterLimit[MAXRANK]; // for each dimension, how many iterations SizeT stride[MAXRANK+1]; const SizeT* varStride; // variables stride // SizeT varStride[MAXRANK+1]; // variables stride SizeT nIx; // number of indexed elements AllIxBaseT* allIx; char allIxInstance[ AllIxMaxSize]; // ArrayIndexT* ixListEnd; // for assoc index // for access with only a single variable index (column/row-extractor) SizeT nIterLimitGt1; // how many dimensions > 1 RankT gt1Rank; // which rank is the variable rank SizeT baseIx; // offset to add for all other constant dims bool indexed; // is the variable index indexed? public: ~ArrayIndexListMultiNoAssocT() { // delete allIx; // ixList.Destruct(); // done in ArrayIndexListMultiT // for( std::vector::iterator i=ixList.begin(); // i != ixList.end(); ++i) // { delete *i;} cleanupIx.Cleanup(); } // constructor ArrayIndexListMultiNoAssocT(): accessType(NORMAL), acRank(0), allIx( NULL) // ixListEnd( NULL) { nParam = 0;} ArrayIndexListMultiNoAssocT( const ArrayIndexListMultiNoAssocT& cp): ArrayIndexListT( cp), accessType(cp.accessType), accessTypeInit(cp.accessTypeInit), accessTypeAssocInit(cp.accessTypeAssocInit), acRank(cp.acRank), allIx( NULL) // ixListEnd( NULL) { assert( cp.allIx == NULL); // assert( cp.ixListEnd == NULL); assert( cp.cleanupIx.size() == 0); for( SizeT i=0; iDup()); } // called once after structure is fixed at (GDL-)compile time ArrayIndexListMultiNoAssocT( ArrayIndexVectorT* ix): ixList( *ix), allIx( NULL) // ixListEnd( NULL) { assert( ix->size() != 0); // must be, from compiler if( ixList.size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); // determine type of index SizeT nIndexed = 0; SizeT nScalar = 0; for( SizeT i=0; (i+1)Type() || ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[i]->Type() ) nScalar++; else if( ArrayIndexIndexedID == ixList[i]->Type() || CArrayIndexIndexedID == ixList[i]->Type()) nIndexed++; } if( nScalar == ixList.size()-1) accessTypeAssocInit = ALLONE; else if( nIndexed == ixList.size()-1) accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well else if( nScalar + nIndexed < ixList.size()-1) accessTypeAssocInit = NORMAL; else accessTypeAssocInit = INDEXED_ONE; // save some checking later if( ArrayIndexScalarID == ixList[ixList.size()-1]->Type() || ArrayIndexScalarVPID == ixList[ixList.size()-1]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[ixList.size()-1]->Type()) nScalar++; else if( ArrayIndexIndexedID == ixList[ixList.size()-1]->Type() || CArrayIndexIndexedID == ixList[ixList.size()-1]->Type()) nIndexed++; if( nScalar == ixList.size()) accessTypeInit = ALLONE; else if( nIndexed == ixList.size()) // actually cannot happen (ArrayIndexListMultiAllIndexedT) // but better keep it for stability accessTypeInit = ALLINDEXED; // might be ALLONE as well else if( nScalar + nIndexed < ixList.size()) accessTypeInit = NORMAL; else accessTypeInit = INDEXED_ONE; // save some checking later // std::cout << "accessTypeInit: " << accessTypeInit << std::endl; } void Clear() { // delete allIx; allIx = NULL; ixList.Clear(); // for( ArrayIndexVectorT::iterator i=ixList.begin(); i != ixList.end(); ++i) // { (*i)->Clear();} cleanupIx.Cleanup(); } IxExprListT* GetCleanupIx() { return &cleanupIx;} ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoAssocT( *this);} void InitAsOverloadIndex( IxExprListT& ix, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut) { assert( allIx == NULL); assert( ix.size() == nParam); // if( cleanupIxIn != NULL) // cleanupIx = *cleanupIxIn; DLongGDL* isRange = new DLongGDL( dimension(ixList.size(), BaseGDL::NOZERO)); ixOut.push_back(isRange); SizeT pIX = 0; for( SizeT i=0; iNParam(); (*isRange)[ i] = (ixList[ i]->IsRange()) ? 1 : 0; if( ixNParam == 0) { BaseGDL* oIx = ixList[ i]->OverloadIndexNew(); ixOut.push_back(oIx); continue; } if( ixNParam == 1) { BaseGDL* oIx = ixList[ i]->OverloadIndexNew( ix[ pIX]); ixOut.push_back(oIx); pIX += 1; continue; } if( ixNParam == 2) { BaseGDL* oIx = ixList[ i]->OverloadIndexNew( ix[ pIX], ix[ pIX+1]); ixOut.push_back(oIx); pIX += 2; continue; } if( ixNParam == 3) { BaseGDL* oIx = ixList[ i]->OverloadIndexNew( ix[ pIX], ix[ pIX+1], ix[ pIX+2]); ixOut.push_back(oIx); pIX += 3; continue; } } } void Init( IxExprListT& ix)//, IxExprListT* cleanupIxIn) { assert( allIx == NULL); assert( ix.size() == nParam); // if( cleanupIxIn != NULL) // cleanupIx = *cleanupIxIn; SizeT pIX = 0; for( SizeT i=0; iNParam(); if( ixNParam == 0) { ixList[ i]->Init(); continue; } if( ixNParam == 1) { // BaseGDL* debugP = ix[ pIX]; // ixList[ i]->Init( debugP); ixList[ i]->Init( ix[ pIX]); pIX += 1; continue; } if( ixNParam == 2) { ixList[ i]->Init( ix[ pIX], ix[ pIX+1]); pIX += 2; continue; } if( ixNParam == 3) { ixList[ i]->Init( ix[ pIX], ix[ pIX+1], ix[ pIX+2]); pIX += 3; continue; } } } // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { assert( false); return FALSE; } // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record // if( var->IsAssoc()) // { // acRank--; // accessType = accessTypeAssocInit; // } // else accessType = accessTypeInit; // can happen due to assoc variables if( accessType == ALLONE) // implied none INDEXED { const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0NIter( (iGetS() * varStride[i]; // GetS() ok because of none INDEXED } nIx = 1; return; // varStride = var->Dim().Stride(); // // check boundary // const dimension& varDim = var->Dim(); // SizeT varRank = varDim.Rank(); // for(SizeT i=0; iNIter( (iScalar()) break; if( i == acRank) // counted up to acRank -> all scalar { accessType = ALLONE; // needed for GetDim() const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0GetIx0(); // * varStride[0]; // GetS() not ok because INDEXED // check boundary for(SizeT i=1; iNIter( (iGetIx0() * varStride[i]; // GetS() not ok because INDEXED } nIx = 1; return; // accessType = ALLONE; // varStride = var->Dim().Stride(); // // check boundary // const dimension& varDim = var->Dim(); // SizeT varRank = varDim.Rank(); // for(SizeT i=0; iNIter( (i 0 || accessType == INDEXED_ONE) { accessType = NORMAL; // there was a scalar (and break because of non-scalar) } else // i == 0 -> first was (because of ALLINDEXED) indexed { ++i; // first was already non-scalar -> indexed for(; iIndexed()) { accessType = NORMAL; break; } // else // accessType = ALLINDEXED; // is already } } // accessType can be at this point: // NORMAL // ALLINDEXED // both are the definite types here assert( accessType == NORMAL || accessType == ALLINDEXED); // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = var->Dim().Stride(); if( accessType == ALLINDEXED) { baseIx = 0; nIx=ixList[0]->NIter( (0 1); for( SizeT i=1; iNIter( (iNIter( (0 1) { nIterLimitGt1 = 1; // important for BuildIx gt1Rank = 0; if( ixList[0]->Indexed()) { baseIx = 0; indexed = true; } else { baseIx = ixList[0]->GetS();// * varStride[0]; indexed = false; } } else { nIterLimitGt1 = 0; // important for BuildIx if( ixList[0]->Indexed()) { baseIx = static_cast< ArrayIndexIndexed*>( ixList[0])->GetIx0();// * varStride[0]; } else { baseIx = ixList[0]->GetS();// * varStride[0]; } } for( SizeT i=1; iNIter( (i 1) { ++nIterLimitGt1; gt1Rank = i; if( ixList[i]->Indexed()) { indexed = true; } else { baseIx += ixList[i]->GetS() * varStride[i]; indexed = false; } } else { if( ixList[i]->Indexed()) { baseIx += static_cast< ArrayIndexIndexed*>( ixList[i])->GetIx0() * varStride[i]; } else { baseIx += ixList[i]->GetS() * varStride[i]; } } } stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride nIx = stride[acRank]; } // structure of indexed expression const dimension GetDim() { // should be changed to ALLINDEXED or ALLONE by now assert( accessType != INDEXED_ONE); if( accessType == ALLONE) return dimension(); // -> results in scalar if( accessType == ALLINDEXED) { // always indexed return static_cast(ixList[0])->GetDim(); } // accessType == NORMAL -> structure from indices return dimension( nIterLimit, acRank); } SizeT N_Elements() { return nIx; } // returns 1-dim index for all elements AllIxBaseT* BuildIx() // ArrayIndexListMultiT { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; assert( allIx == NULL); if( accessType == ALLINDEXED) // nIterLimitGt1 is not properly set { // note that this indexer cannot live without this ArrayIndexListMultiT allIx = new (allIxInstance) AllIxAllIndexedT( &ixList, acRank, nIx, varStride); return allIx; } // can happen // this must be done only here as oterwise nIterLimitGt1 is not properly set if( nIterLimitGt1 == 0) // only one single index { allIx = new (allIxInstance) AllIxT( baseIx); return allIx; } assert( acRank > 1); // NORMAL // loop only over specified indices // higher indices of variable are implicitely zero, // therefore they are not checked in 'SetRoot' if( nIterLimitGt1 == 1) // only one variable dimension { if( indexed) allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexIndexedT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride); else allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } if( acRank == 2) { allIx = new (allIxInstance) AllIxNewMulti2DT( &ixList, nIx, varStride, nIterLimit, stride); return allIx; } allIx = new (allIxInstance) AllIxNewMultiT( &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt and Index functions SizeT LongIx() const { SizeT dStart = ixList[0]->GetIx0(); for( SizeT i=1; i < acRank; ++i) dStart += ixList[i]->GetIx0() * varStride[ i]; return dStart; } void AssignAt( BaseGDL* var, BaseGDL* right) { SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix) { // normal case Init( ix);//, NULL); SetVariable( var); if( nIx == 1 && accessType != ALLINDEXED)// && !var->IsAssoc()) { BaseGDL* res = var->NewIx( baseIx); if( accessType != ALLONE) res->MakeArrayFromScalar(); return res; } return var->Index( this); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { SizeT dStart = 0; SizeT actIx[ MAXRANK]; for( SizeT i=0; i < acRank; ++i) { actIx[ i] = ixList[i]->GetIx0(); dStart += actIx[ i] * varStride[ i]; } destStart = dStart; return dimension( actIx, acRank); } SizeT NDim() { return acRank;} }; //class ArrayIndexListMultiT: public ArrayIndexListT // some checks are not needed here class ArrayIndexListMultiNoneIndexedNoAssocT: public ArrayIndexListMultiNoAssocT { public: // constructor // ArrayIndexListMultiNoneIndexedT // : ArrayIndexListMultiT() // {} // ArrayIndexListMultiNoneIndexedT( const ArrayIndexListMultiNoneIndexedT& cp): // ArrayIndexListMultiT( cp) // {} // called after structure is fixed ArrayIndexListMultiNoneIndexedNoAssocT( ArrayIndexVectorT* ix) // : ixList( *ix), // allIx( NULL), // ixListEnd( NULL) { ixList = *ix; allIx = NULL; // ixListEnd = NULL; assert( ix->size() != 0); // must be, from compiler if( ixList.size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); // determine type of index // SizeT nIndexed = 0; SizeT nScalar = 0; for( SizeT i=0; (i+1)Type() || ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[i]->Type() ) nScalar++; // else if( ArrayIndexIndexedID == ixList[i]->Type() || // CArrayIndexIndexedID == ixList[i]->Type()) nIndexed++; } if( nScalar == ixList.size()-1) accessTypeAssocInit = ALLONE; // else if( nIndexed == ixList.size()-1) // accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well // else if( nScalar + nIndexed < ixList.size()-1) else accessTypeAssocInit = NORMAL; // else // accessTypeAssocInit = INDEXED_ONE; if( ArrayIndexScalarID == ixList[ixList.size()-1]->Type() || ArrayIndexScalarVPID == ixList[ixList.size()-1]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[ixList.size()-1]->Type()) nScalar++; // else if( ArrayIndexIndexedID == ixList[ixList.size()-1]->Type() || // CArrayIndexIndexedID == ixList[ixList.size()-1]->Type()) nIndexed++; /* if( dynamic_cast< ArrayIndexScalar*>(ixList[ixList.size()-1]) || dynamic_cast< CArrayIndexScalar*>(ixList[ixList.size()-1])) nScalar++; if( dynamic_cast(ixList[ixList.size()-1]) || dynamic_cast(ixList[ixList.size()-1]) ) nIndexed++;*/ assert( nScalar <= ixList.size()); // from MakeArrayIndex // if( nScalar == ixList.size()) // accessTypeInit = ALLONE; // // else if( nIndexed == ixList.size()) // // accessTypeInit = ALLINDEXED; // might be ALLONE as well // // else if( nScalar + nIndexed < ixList.size()) // else accessTypeInit = NORMAL; // std::cout << "accessTypeInit: " << accessTypeInit << std::endl; } ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoneIndexedNoAssocT( *this);} // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record // if( var->IsAssoc()) // { // acRank--; // accessType = accessTypeAssocInit; // } // else accessType = accessTypeInit; // can happen due to assoc variables if( accessType == ALLONE) { const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0NIter( (iGetS() * varStride[i]; } nIx = 1; return; } // accessType can be at this point: // NORMAL // now the definite types here assert( accessType == NORMAL); // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); // varDim.Stride( varStride,acRank); // copy variables stride into varStride nIterLimit[0]=ixList[0]->NIter( (0 1)? 1 : 0; gt1Rank = 0; assert( varStride[0] == 1); baseIx = ixList[0]->GetS(); // * varStride[0]; for( SizeT i=1; iNIter( (i 1) { ++nIterLimitGt1; gt1Rank = i; } baseIx += ixList[i]->GetS() * varStride[i]; } stride[acRank]= stride[acRank-1]*nIterLimit[acRank-1]; // index stride nIx = stride[acRank]; } // returns 1-dim index for all elements AllIxBaseT* BuildIx() { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; assert( allIx == NULL); // if( allIx != NULL) // return allIx; // if( accessType == ALLONE) // { // SizeT s = ixList.FrontGetS(); //ixList[0]->GetS(); // for( SizeT l=1; l < acRank; ++l) // { // s += ixList[l]->GetS() * varStride[l]; // } // allIx = new (allIxInstance) AllIxT(s); // return allIx; // } // ALLONE or all nIterLimit == 1 if( nIterLimitGt1 == 0) // only one single index { allIx = new (allIxInstance) AllIxT( baseIx); return allIx; } assert( acRank > 1); // NORMAL // loop only over specified indices // higher indices of variable are implicitely zero, // therefore they are not checked in 'SetRoot' if( nIterLimitGt1 == 1) // only one variable dimension { allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } if( acRank == 2) // assoc already recognized { allIx = new (allIxInstance) AllIxNewMultiNoneIndexed2DT( &ixList, nIx, varStride, nIterLimit, stride); return allIx; } allIx = new (allIxInstance) AllIxNewMultiNoneIndexedT( &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } }; // ArrayIndexListMultiNoneIndexedT class ArrayIndexListMultiNoneIndexedNoAssoc2DT: public ArrayIndexListMultiNoAssocT { public: // called after structure is fixed ArrayIndexListMultiNoneIndexedNoAssoc2DT( ArrayIndexVectorT* ix) { ixList = *ix; allIx = NULL; assert( ix->size() == 2); // must be, from compiler assert( ixList.size() == 2); acRank = acRank2D; nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); // determine type of index // SizeT nIndexed = 0; SizeT nScalar = 0; for( SizeT i=0; iType() || ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[i]->Type() ) nScalar++; } assert( nScalar < ixList.size()); // from MakeArrayIndex accessTypeInit = NORMAL; } ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoneIndexedNoAssoc2DT( *this);} // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { // accessType must be at this point: // NORMAL // now the definite types here // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); // varDim.Stride( varStride,acRank); // copy variables stride into varStride nIterLimit[0]=ixList[0]->NIter( (0 1)? 1 : 0; gt1Rank = 0; assert( varStride[0] == 1); nIterLimit[1]=ixList[1]->NIter( (1 1) { ++nIterLimitGt1; gt1Rank = 1; } baseIx = ixList[0]->GetS() + ixList[1]->GetS() * varStride[1]; stride[2]=nIx; // index stride } // returns 1-dim index for all elements AllIxBaseT* BuildIx() { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; assert( allIx == NULL); // all nIterLimit == 1 if( nIterLimitGt1 == 0) // only one single index { allIx = new (allIxInstance) AllIxT( baseIx); return allIx; } // NORMAL // loop only over specified indices // higher indices of variable are implicitely zero, // therefore they are not checked in 'SetRoot' if( nIterLimitGt1 == 1) // only one variable dimension { allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank2D, nIx, varStride, nIterLimit, stride); return allIx; } allIx = new (allIxInstance) AllIxNewMultiNoneIndexed2DT( &ixList, nIx, varStride, nIterLimit, stride); return allIx; } }; // ArrayIndexListMultiNoneIndexed2DT class ArrayIndexListMultiAllIndexedNoAssocT: public ArrayIndexListMultiNoAssocT { public: // called once after structure is fixed at (GDL-)compile time ArrayIndexListMultiAllIndexedNoAssocT( ArrayIndexVectorT* ix) // : ixList( *ix), // allIx( NULL), // ixListEnd( NULL) { ixList = *ix; allIx = NULL; // ixListEnd = NULL; assert( ix->size() != 0); // must be, from compiler if( ixList.size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); accessTypeInit = ALLINDEXED; // might be ALLONE as well } ArrayIndexListT* Clone() { return new ArrayIndexListMultiAllIndexedNoAssocT( *this);} // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record // if( var->IsAssoc()) // { // acRank--; // accessType = accessTypeAssocInit; // } // else accessType = accessTypeInit; SizeT i=0; for(; iScalar()) break; if( i == acRank) // counted up to acRank -> all scalar { accessType = ALLONE; // needed for GetDim() and Index (to return scalar instead of array) const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0GetIx0(); // * varStride[0]; // GetS() not ok because INDEXED // check boundary for(SizeT i=1; iNIter( (iGetIx0() * varStride[i]; // GetS() not ok because INDEXED } nIx = 1; return; } if( i > 0) { accessType = NORMAL; // there was a scalar (and break because of non-scalar) } else // i == 0 -> first was (because of ALLINDEXED) indexed { ++i; // first was already non-scalar -> indexed for(; iIndexed()) { accessType = NORMAL; break; } } // accessType can be at this point: // NORMAL // ALLINDEXED // both are the definite types here assert( accessType == NORMAL || accessType == ALLINDEXED); // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); if( accessType == ALLINDEXED) { nIx=ixList[0]->NIter( (0NIter( (iDim().Stride(); return; } // NORMAL varStride = var->Dim().Stride(); assert( varStride[0] == 1); nIterLimit[0]=ixList[0]->NIter( (0 1) { nIterLimitGt1 = 1; // important for BuildIx gt1Rank = 0; if( ixList[0]->Indexed()) { baseIx = 0; indexed = true; } else { baseIx = ixList[0]->GetS();// * varStride[0]; indexed = false; } } else { nIterLimitGt1 = 0; // important for BuildIx if( ixList[0]->Indexed()) { baseIx = static_cast< ArrayIndexIndexed*>( ixList[0])->GetIx0();// * varStride[0]; } else { baseIx = ixList[0]->GetS();// * varStride[0]; } } for( SizeT i=1; iNIter( (i 1) { ++nIterLimitGt1; gt1Rank = i; if( ixList[i]->Indexed()) { indexed = true; } else { baseIx += ixList[i]->GetS() * varStride[i]; indexed = false; } } else { if( ixList[i]->Indexed()) { baseIx += static_cast< ArrayIndexIndexed*>( ixList[i])->GetIx0() * varStride[i]; } else { baseIx += ixList[i]->GetS() * varStride[i]; } } } stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride } }; //class ArrayIndexListMultiAllIndexedT: public ArrayIndexListMultiT #endif gdl-0.9.9/src/arrayindexlistt.hpp000066400000000000000000001531541340051421000170240ustar00rootroot00000000000000/*************************************************************************** arrayindexlistt.hpp - array access descriptor ------------------- begin : July 22 2005 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ARRAYINDEXLISTT_HPP_ #define ARRAYINDEXLISTT_HPP_ #include "arrayindex.hpp" class ArrayIndexListT { protected: SizeT nParam; // number of (BaseGDL*) parameters public: SizeT NParam() { return nParam;} virtual ~ArrayIndexListT(); // constructor ArrayIndexListT() {} ArrayIndexListT( const ArrayIndexListT& cp): nParam( cp.nParam) {} virtual void Clear() {} virtual ArrayIndexListT* Clone() { assert( 0); return NULL;} virtual void InitAsOverloadIndex( IxExprListT& ixIn, /*IxExprListT* cleanupIx,*/ IxExprListT& ixOut) { throw GDLException( -1, NULL,"Internal error: ArrayIndexListT::InitAsOverladIndex( IxExprListT& ixInOut) called.",true,false); } virtual void Init( IxExprListT& ix)//, IxExprListT* cleanupIx) { assert( 0); throw GDLException( -1, NULL,"Internal error: ArrayIndexListT::Init( IxExprListT& ix, IxExprListT* cleanupIx) called.",true,false); } virtual IxExprListT* GetCleanupIx() { assert( 0); throw GDLException( -1, NULL,"Internal error: ArrayIndexListT::GetCleanupIx() called.",true,false); } virtual void Init() {} virtual bool ToAssocIndex( SizeT& lastIx) { assert( 0); throw GDLException( -1, NULL,"Internal error: ArrayIndexListT::ToAssocIndex( SizeT& lastIx) called.",true,false); } // virtual bool ToAssocIndex( RangeT& lastIx) = 0; // set the root variable which is indexed by this ArrayIndexListT virtual void SetVariable( BaseGDL* var) {} // structure of indexed expression virtual const dimension GetDim() = 0; virtual SizeT N_Elements() = 0; // returns 1-dim index for all elements virtual AllIxBaseT* BuildIx(); // returns one dim long ix in case of one element array index // used by AssignAt functions virtual SizeT LongIx() const = 0; virtual void AssignAt( BaseGDL* var, BaseGDL* right) {} // optimized for one dimensional access // this is called from the interpreter and ARRAYEXPRNode::Eval() virtual BaseGDL* Index( BaseGDL* var, IxExprListT& ix) = 0; // returns multi-dim index for 1st element // used by InsAt functions virtual const dimension GetDimIx0( SizeT& destStart) = 0; virtual SizeT NDim() = 0; }; #include "arrayindexlistnoassoct.hpp" // only one index [ix],[s:e],... // NEVER ArrayIndexScalar types (they have their own ArrayIndexListT) class ArrayIndexListOneT: public ArrayIndexListT { private: IxExprListT cleanupIx; ArrayIndexT* ix; SizeT nIx; // number of indexed elements AllIxBaseT* allIx; char allIxInstance[ AllIxMaxSize]; public: IxExprListT* GetCleanupIx() { return &cleanupIx;} ~ArrayIndexListOneT() { // delete allIx; delete ix; cleanupIx.Cleanup(); // must be explicitely cleaned up } // constructor ArrayIndexListOneT() : cleanupIx() , ix( NULL) , allIx( NULL) { nParam = 0;} ArrayIndexListOneT( const ArrayIndexListOneT& cp): ArrayIndexListT( cp), cleanupIx(), ix( cp.ix->Dup()), allIx( NULL) { assert( cp.allIx == NULL); assert( cp.cleanupIx.size() == 0); } // called after structure is fixed ArrayIndexListOneT( ArrayIndexVectorT* aIV): allIx( NULL) { ix = (*aIV)[0]; nParam = ix->NParam(); } void Clear() { // delete allIx; allIx = NULL; // allIxMulti.Clear(); ix->Clear(); cleanupIx.Cleanup(); } ArrayIndexListT* Clone() { return new ArrayIndexListOneT( *this);} void Init( IxExprListT& ix_)//, IxExprListT* cleanupIxIn) { assert( allIx == NULL); assert( ix_.size() == nParam); // if( cleanupIxIn != NULL) // cleanupIx = *cleanupIxIn; if( nParam == 0) return; if( nParam == 1) { ix->Init( ix_[ 0]); } else if( nParam == 2) { ix->Init( ix_[ 0], ix_[ 1]); return; } else // nParam == 3 { ix->Init( ix_[ 0], ix_[ 1], ix_[ 2]); return; } } void Init() {} // eg. a[*] // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { // cannot be ArrayIndexScalar[VP] ix->Init(); RangeT lastValIx; if( !ix->Scalar( lastValIx)) throw GDLException( -1, NULL,"Record number must be a scalar in this context.",true,false); if( lastValIx < 0) throw GDLException( -1, NULL,"Record number must be a scalar > 0 in this context.",true,false); lastIx = lastValIx; return true; } // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // for assoc variables last index is the record if( var->IsAssoc()) { // note: s is copied from sIter in ArrayIndex::Init return; } // ArrayIndexScalar[VP] are not initialized // they need the NIter call, but // for only one index they have their own ArrayIndexListT nIx=ix->NIter( var->N_Elements()/*var->Size()*/); } // structure of indexed expression const dimension GetDim() { if( ix->Scalar()) { return dimension(); } else if( ix->Indexed()) { return static_cast(ix)->GetDim(); // gets structure of indexing array } else { return dimension( nIx); // one dimensional if not indexed } } SizeT N_Elements() { return nIx; } // returns 1-dim index for all elements AllIxBaseT* BuildIx() { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; if( ix->Indexed()) { // allIx = static_cast< ArrayIndexIndexed*>(ix)->StealIx(); allIx = static_cast< ArrayIndexIndexed*>(ix)->GetAllIx(); return allIx; } if( nIx == 1) { allIx = new (allIxInstance) AllIxT( ix->GetS()); return allIx; } // allIx = new AllIxMulAllIxRangeStrideTtiT( nIx); SizeT s = ix->GetS(); SizeT ixStride = ix->GetStride(); if( ixStride <= 1) if( s != 0) { allIx = new (allIxInstance) AllIxRangeT( nIx, s); // for( SizeT i=0; i(allIx)->SetIx( i, i + s); // (*allIx)[i] = i + s; } else { allIx = new (allIxInstance) AllIxRange0T( nIx); // for( SizeT i=0; i(allIx)->SetIx( i, i ); // (*allIx)[i] = i; } else if( s != 0) { allIx = new (allIxInstance) AllIxRangeStrideT( nIx, s, ixStride); // for( SizeT i=0; i(allIx)->SetIx( i, i * ixStride + s); // (*allIx)[i] = i * ixStride + s; } else { allIx = new (allIxInstance) AllIxRange0StrideT( nIx, ixStride); // for( SizeT i=0; i(allIx)->SetIx( i, i * ixStride); // (*allIx)[i] = i * ixStride; } return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return ix->GetIx0(); } void AssignAt( BaseGDL* var, BaseGDL* right) { // scalar case if( right->N_Elements() == 1 && !var->IsAssoc() && ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT) { var->AssignAtIx( ix->GetIx0(), right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_) { Init( ix_);//, NULL); if( var->IsAssoc()) // deault case return var->Index( this); if( /*!var->IsAssoc() &&*/ ix->Scalar()) //ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT) { SizeT assertValue = ix->NIter( var->N_Elements()/*var->Size()*/); assert( assertValue == 1); return var->NewIx( ix->GetIx0()); } // normal case, no assoc SetVariable( var); return var->Index( this); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { destStart = ix->GetIx0(); return dimension( destStart); } SizeT NDim() { return 1; } }; //class ArrayIndexListOneT: public ArrayIndexListT // loop index class ArrayIndexListOneScalarT: public ArrayIndexListT { protected: SizeT varIx; RangeT sInit; RangeT s; AllIxT allIx; public: ~ArrayIndexListOneScalarT() { // delete allIx; } // constructor ArrayIndexListOneScalarT() : varIx( 0) // , allIx( NULL) { nParam = 0;} ArrayIndexListOneScalarT( const ArrayIndexListOneScalarT& cp) : ArrayIndexListT( cp) , varIx( cp.varIx) , s( cp.s) // , allIx( NULL) { // assert( cp.allIx == NULL); } // called after structure is fixed ArrayIndexListOneScalarT( ArrayIndexVectorT* aIV) // : allIx( NULL) { nParam = 0; varIx = static_cast((*aIV)[0])->GetVarIx(); delete (*aIV)[0]; } void Clear() {} ArrayIndexListT* Clone() { return new ArrayIndexListOneScalarT( *this);} void Init() {} // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx); // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var); // structure of indexed expression const dimension GetDim() { return dimension(); } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { allIx.Set( s); return &allIx; // if( allIx != NULL) // { // allIx->Set( s); // return allIx; // } // // allIx = new AllIxT( s); // return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return s; } void AssignAt( BaseGDL* var, BaseGDL* right); // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_); // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { destStart = s; return dimension( destStart); } SizeT NDim() { return 1; } }; // class ArrayIndexListOneScalarT: public ArrayIndexListT class ArrayIndexListOneScalarVPT: public ArrayIndexListT { protected: DVar* varPtr; RangeT sInit; RangeT s; AllIxT allIx; // AllIxT* allIx; public: ~ArrayIndexListOneScalarVPT() { // delete allIx; } // constructor ArrayIndexListOneScalarVPT() : varPtr( NULL) // , allIx( NULL) { nParam = 0;} ArrayIndexListOneScalarVPT( const ArrayIndexListOneScalarVPT& cp) : ArrayIndexListT( cp) , varPtr( cp.varPtr) , sInit( cp.sInit) , s( cp.s) // , allIx( NULL) { // assert( cp.allIx == NULL); } // called after structure is fixed ArrayIndexListOneScalarVPT( ArrayIndexVectorT* aIV) // : allIx( NULL) { nParam = 0; varPtr = static_cast((*aIV)[0])->GetVarPtr(); delete (*aIV)[0]; } void Clear() {} ArrayIndexListT* Clone() { return new ArrayIndexListOneScalarVPT( *this);} void Init() {} // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) throw GDLException( -1, NULL,"Record number must be a scalar > 0 in this context.",true,false); s = sInit; lastIx = s; return true; } // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var) { sInit = varPtr->Data()->LoopIndex(); if( sInit < 0) s = sInit + var->N_Elements(); else s = sInit; // for assoc variables last index is the record if( var->IsAssoc()) return; if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1, NULL,"Scalar subscript out of range (>).",true,false); if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range (<-1).",true,false); } // structure of indexed expression const dimension GetDim() { return dimension(); } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { allIx.Set( s); return &allIx; // if( allIx != NULL) // { // allIx->Set( s); // return allIx; // } // // allIx = new AllIxT( s); // return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return s; } void AssignAt( BaseGDL* var, BaseGDL* right) { // Init() was already called // scalar case if( right->N_Elements() == 1 && !var->IsAssoc()) // && var->Type() != GDL_STRUCT) { s = varPtr->Data()->LoopIndex(); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript out of range [>].2",true,false); var->AssignAtIx( s, right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_); // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { destStart = s; return dimension( destStart); } SizeT NDim() { return 1; } }; // class ArrayIndexListOneScalarVPT: public ArrayIndexListT class ArrayIndexListOneConstScalarT: public ArrayIndexListT { RangeT sInit; RangeT s; AllIxT allIx; // AllIxT* allIx; public: ~ArrayIndexListOneConstScalarT() { // delete allIx; } // constructor ArrayIndexListOneConstScalarT() // : allIx( NULL) { nParam = 0; } ArrayIndexListOneConstScalarT( const ArrayIndexListOneConstScalarT& cp) : ArrayIndexListT( cp) , sInit( cp.sInit) , s( cp.s) // , allIx( NULL) { // assert( cp.allIx == NULL); // all copying should be done before using. } // called after structure is fixed ArrayIndexListOneConstScalarT( ArrayIndexVectorT* aIV) // : allIx( NULL) { sInit = (*aIV)[0]->GetS(); if( sInit >= 0) s = sInit; nParam = 0; delete (*aIV)[0]; } void Clear() {} ArrayIndexListT* Clone() { return new ArrayIndexListOneConstScalarT( *this);} void Init() {} SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { allIx.Set( s); return &allIx; // if( allIx != NULL) // return allIx; // // allIx = new AllIxT( s); // return allIx; } // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { if( sInit < 0) throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context.",true,false); lastIx = sInit; return true; } // set the root variable which is indexed by this ArrayIndexListT void SetVariable( BaseGDL* var) { if( var->IsAssoc()) return; if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; // for assoc variables last index is the record if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range [<].1",true,false); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript out of range [>].1",true,false); } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { return s; } void AssignAt( BaseGDL* var, BaseGDL* right) { // one index and assoc -> no index left -> no AssignAt // wrong! This is the entry function // assert( !var->IsAssoc()); // Init() was already called // scalar case if( right->N_Elements() == 1 && !var->IsAssoc())// && var->Type() != GDL_STRUCT) { if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range [<].2",true,false); if( s >= var->N_Elements()/*var->Size()*/) throw GDLException(-1,NULL,"Scalar subscript out of range [>].2",true,false); var->AssignAtIx( s, right); return; } SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix_) { // Init() not called if( !var->IsAssoc())// && var->Type() != GDL_STRUCT) { if( sInit < 0) s = sInit + var->N_Elements()/*var->Size()*/; if( s < 0) throw GDLException(-1,NULL,"Scalar subscript out of range [<].3",true,false); if( s >= var->N_Elements()/*var->Size()*/) { // std::cout << s << " var->N_Elements()/*var->Size()*/:" << var->N_Elements()/*var->Size()*/ << std::endl; throw GDLException(-1,NULL,"Scalar subscript out of range [>].3",true,false); } return var->NewIx( s); } // normal case //Init();// ix_); //SetVariable( var); return var->Index( this); } const dimension GetDim() { return dimension(); } const dimension GetDimIx0( SizeT& destStart) { destStart = s; return dimension( destStart); } SizeT NDim() { return 1; } }; // class ArrayIndexListOneConstScalarT: public ArrayIndexListT // all scalar elements (multi-dim) class ArrayIndexListScalarT: public ArrayIndexListT { private: ArrayIndexVectorT ixList; // std::vector paramPresent; SizeT acRank; // rank upto which indexing is done const SizeT* varStride; // variables stride // SizeT varStride[MAXRANK+1]; // variables stride SizeT nIx; // number of indexed elements AllIxT allIx; // AllIxT allIxInstance; ArrayIndexT* ixListEnd; // for assoc index public: ~ArrayIndexListScalarT() { // delete allIx; ixList.Destruct(); // for( std::vector::iterator i=ixList.begin(); // i != ixList.end(); ++i) // { delete *i;} } // constructor ArrayIndexListScalarT(): acRank(0), // allIx( NULL), ixListEnd( NULL) { nParam = 0;} ArrayIndexListScalarT( const ArrayIndexListScalarT& cp): ArrayIndexListT( cp), // paramPresent( cp.paramPresent), acRank(cp.acRank), // allIx( NULL), ixListEnd( NULL) { // ixList.reserve(MAXRANK); // assert( cp.allIx == NULL); assert( cp.ixListEnd == NULL); for( SizeT i=0; iDup()); } // called after structure is fixed ArrayIndexListScalarT( ArrayIndexVectorT* ix): ixList( *ix), // allIx( NULL), ixListEnd( NULL) { assert( ixList.size() > 1); // must be, from compiler if( ix->size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; iNParam(); if( actNParam == 1) { // paramPresent.push_back( i); nParam++; } } } void Clear() { // delete allIx; // allIx = NULL; if( ixListEnd != NULL) // revert assoc indexing { ixList.push_back( ixListEnd); ixListEnd = NULL; } // // no clearing of scalar indices // for( std::vector::iterator i=ixList.begin(); // i != ixList.end(); ++i) // { (*i)->Clear();} } // void Init( IxExprListT& ix) // { // assert( allIx == NULL); // assert( ix.size() == nParam); // for( SizeT i=0; iInit( ix[ i]); // } // } ArrayIndexListT* Clone() { return new ArrayIndexListScalarT( *this);} void Init() {} // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true if the list is empty bool ToAssocIndex( SizeT& lastIx) { assert( ixListEnd == NULL); ixListEnd = ixList.pop_back_get(); // init in case of ixListEnd->NParam == 0 ixListEnd->Init(); RangeT lastIxVal; ixListEnd->Scalar( lastIxVal); // always scalar if( lastIxVal < 0) throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context.",true,false); lastIx = lastIxVal; return false; // multi dim } // set the root variable which is indexed by this ArrayIndexListScalarT void SetVariable( BaseGDL* var) { // assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record if( var->IsAssoc()) { acRank--; // if( acRank == 0) return; // multi dim } // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) for( SizeT i=0; iNIter( var->Dim(i)); // check boundary varStride = var->Dim().Stride(); // var->Dim().Stride( varStride, acRank); // copy variables stride into varStride nIx = 1; } // structure of indexed expression const dimension GetDim() { return dimension(); // -> results in scalar } SizeT N_Elements() { return 1; } // returns 1-dim index for all elements AllIxT* BuildIx() { // if( allIx != NULL) // return allIx; SizeT s = ixList.FrontGetS(); //[0]->GetS(); for( SizeT l=1; l < acRank; ++l) { s += ixList[l]->GetS() * varStride[l]; } // allIx = &allIxInstance; //new AllIxT(s); // allIx->Set( s); allIx.Set( s); // allIx = new AllIxT(s); // (*allIx)[0] = s; return &allIx; } // returns one dim long ix in case of one element array index // used by AssignAt functions SizeT LongIx() const { // if( acRank == 1) // return ixList.FrontGetS(); //ixList[0]->GetS(); SizeT dStart = ixList.FrontGetS(); //[0]->GetS(); for( SizeT i=1; i < acRank; ++i) dStart += ixList[i]->GetS() * varStride[ i]; return dStart; } void AssignAt( BaseGDL* var, BaseGDL* right) { if( var->N_Elements() == 1 && !var->IsAssoc()) { // SetVariable( var); // set acRank acRank = ixList.size(); varStride = var->Dim().Stride(); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( var->Dim(0)); // check boundary SizeT dStart = ixList.FrontGetS(); //[0]->GetS(); for( SizeT i=1; i < acRank; ++i) { ixList[i]->NIter( var->Dim(i)); // check boundary dStart += ixList[i]->GetS() * varStride[ i]; } var->AssignAtIx( dStart, right); // assigns inplace return; } // var->N_Elements() > 1 SetVariable( var); assert( nIx == 1); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace (not only scalar) } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace (not only scalar) } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix) { // Init(); // SetVariable( var); // set acRank acRank = ixList.size(); // for assoc variables last index is the record if( var->IsAssoc()) { acRank--; varStride = var->Dim().Stride(); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( var->Dim(0)); // check boundary for( SizeT i=1; i < acRank; ++i) { ixList[i]->NIter( var->Dim(i)); // check boundary } // return dStart; // for( SizeT i=0; iNIter( var->Dim(i)); // check boundary // return var->NewIx( dStart); //this->LongIx()); return var->Index( this); } varStride = var->Dim().Stride(); // ArrayIndexScalar[VP] need this call to read their actual data // as their are not initalized (nParam == 0) ixList[0]->NIter( var->Dim(0)); // check boundary SizeT dStart = ixList.FrontGetS(); //[0]->GetS(); for( SizeT i=1; i < acRank; ++i) { ixList[i]->NIter( var->Dim(i)); // check boundary dStart += ixList[i]->GetS() * varStride[ i]; } // return dStart; // for( SizeT i=0; iNIter( var->Dim(i)); // check boundary return var->NewIx( dStart); //this->LongIx()); // return var->Index( this); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { SizeT dStart = 0; SizeT actIx[ MAXRANK]; for( SizeT i=0; i < acRank; ++i) { actIx[ i] = ixList[i]->GetS(); dStart += actIx[ i] * varStride[ i]; } destStart = dStart; return dimension( actIx, acRank); } SizeT NDim() { return acRank; } }; // class ArrayIndexListScalarT: public ArrayIndexListT /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // general case (mixed, multi-dim) at least one indexed // but note: last index can be assoc index class ArrayIndexListMultiT: public ArrayIndexListT { private: IxExprListT cleanupIx; protected: ArrayIndexVectorT ixList; enum AccessType { GDL_UNDEF=0, // for init access type INDEXED_ONE, // all indexed OR one NORMAL, // mixed ALLINDEXED, ALLONE // all ONE }; AccessType accessType; // actual access type AccessType accessTypeInit; // possible access type non assoc AccessType accessTypeAssocInit;// possible access type for assoc SizeT acRank; // rank upto which indexing is done SizeT nIterLimit[MAXRANK]; // for each dimension, how many iterations SizeT stride[MAXRANK+1]; const SizeT* varStride; // variables stride // SizeT varStride[MAXRANK+1]; // variables stride SizeT nIx; // number of indexed elements AllIxBaseT* allIx; char allIxInstance[ AllIxMaxSize]; ArrayIndexT* ixListEnd; // for assoc index // for access with only a single variable index (column/row-extractor) SizeT nIterLimitGt1; // how many dimensions > 1 RankT gt1Rank; // which rank is the variable rank SizeT baseIx; // offset to add for all other constant dims bool indexed; // is the variable index indexed? public: IxExprListT* GetCleanupIx() { return &cleanupIx;} ~ArrayIndexListMultiT() { // delete allIx; ixList.Destruct(); // for( std::vector::iterator i=ixList.begin(); // i != ixList.end(); ++i) // { delete *i;} cleanupIx.Cleanup(); } // constructor ArrayIndexListMultiT(): accessType(NORMAL), acRank(0), allIx( NULL), ixListEnd( NULL) { nParam = 0;} ArrayIndexListMultiT( const ArrayIndexListMultiT& cp): ArrayIndexListT( cp), accessType(cp.accessType), accessTypeInit(cp.accessTypeInit), accessTypeAssocInit(cp.accessTypeAssocInit), acRank(cp.acRank), allIx( NULL), ixListEnd( NULL) { assert( cp.allIx == NULL); assert( cp.ixListEnd == NULL); assert( cp.cleanupIx.size() == 0); for( SizeT i=0; iDup()); } // called once after structure is fixed at (GDL-)compile time ArrayIndexListMultiT( ArrayIndexVectorT* ix): ixList( *ix), allIx( NULL), ixListEnd( NULL) { assert( ix->size() != 0); // must be, from compiler if( ixList.size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); // determine type of index SizeT nIndexed = 0; SizeT nScalar = 0; for( SizeT i=0; (i+1)Type() || ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[i]->Type() ) nScalar++; else if( ArrayIndexIndexedID == ixList[i]->Type() || CArrayIndexIndexedID == ixList[i]->Type()) nIndexed++; } if( nScalar == ixList.size()-1) accessTypeAssocInit = ALLONE; else if( nIndexed == ixList.size()-1) accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well else if( nScalar + nIndexed < ixList.size()-1) accessTypeAssocInit = NORMAL; else accessTypeAssocInit = INDEXED_ONE; // save some checking later if( ArrayIndexScalarID == ixList[ixList.size()-1]->Type() || ArrayIndexScalarVPID == ixList[ixList.size()-1]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[ixList.size()-1]->Type()) nScalar++; else if( ArrayIndexIndexedID == ixList[ixList.size()-1]->Type() || CArrayIndexIndexedID == ixList[ixList.size()-1]->Type()) nIndexed++; if( nScalar == ixList.size()) accessTypeInit = ALLONE; else if( nIndexed == ixList.size()) // actually cannot happen (ArrayIndexListMultiAllIndexedT) // but better keep it for stability accessTypeInit = ALLINDEXED; // might be ALLONE as well else if( nScalar + nIndexed < ixList.size()) accessTypeInit = NORMAL; else accessTypeInit = INDEXED_ONE; // save some checking later // std::cout << "accessTypeInit: " << accessTypeInit << std::endl; } void Clear() { // delete allIx; allIx = NULL; if( ixListEnd != NULL) // revert assoc indexing { ixList.push_back( ixListEnd); ixListEnd = NULL; } ixList.Clear(); // for( ArrayIndexVectorT::iterator i=ixList.begin(); i != ixList.end(); ++i) // { (*i)->Clear();} cleanupIx.Cleanup(); } ArrayIndexListT* Clone() { return new ArrayIndexListMultiT( *this);} void Init( IxExprListT& ix)//, IxExprListT* cleanupIxIn) { assert( allIx == NULL); assert( ix.size() == nParam); // if( cleanupIxIn != NULL) // cleanupIx = *cleanupIxIn; SizeT pIX = 0; for( SizeT i=0; iNParam(); if( ixNParam == 0) { ixList[ i]->Init(); continue; } if( ixNParam == 1) { ixList[ i]->Init( ix[ pIX]); pIX += 1; continue; } if( ixNParam == 2) { ixList[ i]->Init( ix[ pIX], ix[ pIX+1]); pIX += 2; continue; } if( ixNParam == 3) { ixList[ i]->Init( ix[ pIX], ix[ pIX+1], ix[ pIX+2]); pIX += 3; continue; } } } // requires special handling // used by Assoc_<> returns last index in lastIx, removes it // and returns true is the list is empty bool ToAssocIndex( SizeT& lastIx) { assert( ixListEnd == NULL); ArrayIndexT* ixListEndTmp = ixList.back(); ixListEndTmp->Init(); RangeT lastValIx; if( !ixListEndTmp->Scalar( lastValIx)) throw GDLException(-1, NULL ,"Record number must be a scalar in this context.",true,false); if( lastValIx < 0) throw GDLException(-1, NULL,"Record number must be a scalar > 0 in this context.",true,false); lastIx = lastValIx; ixListEnd = ixListEndTmp; ixList.pop_back(); return false; // multi dim ixList.empty(); } // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record if( var->IsAssoc()) { acRank--; accessType = accessTypeAssocInit; } else accessType = accessTypeInit; // can happen due to assoc variables if( accessType == ALLONE) // implied none INDEXED { const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0NIter( (iGetS() * varStride[i]; // GetS() ok because of none INDEXED } nIx = 1; return; // varStride = var->Dim().Stride(); // // check boundary // const dimension& varDim = var->Dim(); // SizeT varRank = varDim.Rank(); // for(SizeT i=0; iNIter( (iScalar()) break; if( i == acRank) // counted up to acRank -> all scalar { accessType = ALLONE; // needed for GetDim() const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0GetIx0(); // * varStride[0]; // GetS() not ok because INDEXED // check boundary for(SizeT i=1; iNIter( (iGetIx0() * varStride[i]; // GetS() not ok because INDEXED } nIx = 1; return; // accessType = ALLONE; // varStride = var->Dim().Stride(); // // check boundary // const dimension& varDim = var->Dim(); // SizeT varRank = varDim.Rank(); // for(SizeT i=0; iNIter( (i 0 || accessType == INDEXED_ONE) { accessType = NORMAL; // there was a scalar (and break because of non-scalar) } else // i == 0 -> first was (because of ALLINDEXED) indexed { ++i; // first was already non-scalar -> indexed for(; iIndexed()) { accessType = NORMAL; break; } // else // accessType = ALLINDEXED; // is already } } // accessType can be at this point: // NORMAL // ALLINDEXED // both are the definite types here assert( accessType == NORMAL || accessType == ALLINDEXED); // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); if( accessType == ALLINDEXED) { nIx=ixList[0]->NIter( (0 1); for( SizeT i=1; iNIter( (iDim().Stride(); // varDim.Stride( varStride,acRank); // copy variables stride into varStride return; } // NORMAL varStride = var->Dim().Stride(); // varDim.Stride( varStride,acRank); // copy variables stride into varStride assert( varStride[0] == 1); nIterLimit[0]=ixList[0]->NIter( (0 1) { nIterLimitGt1 = 1; // important for BuildIx gt1Rank = 0; if( ixList[0]->Indexed()) { baseIx = 0; indexed = true; } else { baseIx = ixList[0]->GetS();// * varStride[0]; indexed = false; } } else { nIterLimitGt1 = 0; // important for BuildIx if( ixList[0]->Indexed()) { baseIx = static_cast< ArrayIndexIndexed*>( ixList[0])->GetIx0();// * varStride[0]; } else { baseIx = ixList[0]->GetS();// * varStride[0]; } } for( SizeT i=1; iNIter( (i 1) { ++nIterLimitGt1; gt1Rank = i; if( ixList[i]->Indexed()) { indexed = true; } else { baseIx += ixList[i]->GetS() * varStride[i]; indexed = false; } } else { if( ixList[i]->Indexed()) { baseIx += static_cast< ArrayIndexIndexed*>( ixList[i])->GetIx0() * varStride[i]; } else { baseIx += ixList[i]->GetS() * varStride[i]; } } } stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride } // structure of indexed expression const dimension GetDim() { // should be changed to ALLINDEXED or ALLONE by now assert( accessType != INDEXED_ONE); if( accessType == ALLONE) return dimension(); // -> results in scalar if( accessType == ALLINDEXED) { // always indexed return static_cast(ixList[0])->GetDim(); } // accessType == NORMAL -> structure from indices return dimension( nIterLimit, acRank); } SizeT N_Elements() { return nIx; } // returns 1-dim index for all elements AllIxBaseT* BuildIx() // ArrayIndexListMultiT { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; assert( allIx == NULL); if( accessType == ALLINDEXED) // nIterLimitGt1 is not properly set { // note that this indexer cannot live without this ArrayIndexListMultiT allIx = new (allIxInstance) AllIxAllIndexedT( &ixList, acRank, nIx, varStride); return allIx; } // can happen // this must be done only here as oterwise nIterLimitGt1 is not properly set if( nIterLimitGt1 == 0) // only one single index { allIx = new (allIxInstance) AllIxT( baseIx); return allIx; } if( acRank == 1) // assoc already recognized { ArrayIndexT* ix = ixList[0]; if( ix->Indexed()) { allIx = static_cast< ArrayIndexIndexed*>(ix)->GetAllIx(); return allIx; } if( nIx == 1) { allIx = new (allIxInstance) AllIxT( ix->GetS()); return allIx; } SizeT s = ix->GetS(); SizeT ixStride = ix->GetStride(); if( ixStride <= 1) if( s != 0) { allIx = new (allIxInstance) AllIxRangeT( nIx, s); } else { allIx = new (allIxInstance) AllIxRange0T( nIx); } else if( s != 0) { allIx = new (allIxInstance) AllIxRangeStrideT( nIx, s, ixStride); } else { allIx = new (allIxInstance) AllIxRange0StrideT( nIx, ixStride); } return allIx; } // NORMAL // loop only over specified indices // higher indices of variable are implicitely zero, // therefore they are not checked in 'SetRoot' if( nIterLimitGt1 == 1) // only one variable dimension { if( indexed) allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexIndexedT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride); else allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } if( acRank == 2) { allIx = new (allIxInstance) AllIxNewMulti2DT( &ixList, nIx, varStride, nIterLimit, stride); return allIx; } allIx = new (allIxInstance) AllIxNewMultiT( &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } // returns one dim long ix in case of one element array index // used by AssignAt and Index functions SizeT LongIx() const { SizeT dStart = ixList[0]->GetIx0(); for( SizeT i=1; i < acRank; ++i) dStart += ixList[i]->GetIx0() * varStride[ i]; return dStart; } void AssignAt( BaseGDL* var, BaseGDL* right) { SetVariable( var); if( var->EqType( right)) { var->AssignAt( right, this); // assigns inplace } else { BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY); Guard conv_guard( rConv); var->AssignAt( rConv, this); // assigns inplace } } // optimized for one dimensional access BaseGDL* Index( BaseGDL* var, IxExprListT& ix) { // normal case Init( ix);//, NULL); SetVariable( var); if( nIx == 1 && !var->IsAssoc()) { BaseGDL* res = var->NewIx( baseIx); res->MakeArrayFromScalar(); return res; } return var->Index( this); } // returns multi-dim index for 1st element // used by InsAt functions const dimension GetDimIx0( SizeT& destStart) { SizeT dStart = 0; SizeT actIx[ MAXRANK]; for( SizeT i=0; i < acRank; ++i) { actIx[ i] = ixList[i]->GetIx0(); dStart += actIx[ i] * varStride[ i]; } destStart = dStart; return dimension( actIx, acRank); } SizeT NDim() { return acRank;} }; //class ArrayIndexListMultiT: public ArrayIndexListT // some checks are not needed here class ArrayIndexListMultiNoneIndexedT: public ArrayIndexListMultiT { public: // constructor // ArrayIndexListMultiNoneIndexedT // : ArrayIndexListMultiT() // {} // ArrayIndexListMultiNoneIndexedT( const ArrayIndexListMultiNoneIndexedT& cp): // ArrayIndexListMultiT( cp) // {} // called after structure is fixed ArrayIndexListMultiNoneIndexedT( ArrayIndexVectorT* ix) // : ixList( *ix), // allIx( NULL), // ixListEnd( NULL) { ixList = *ix; allIx = NULL; ixListEnd = NULL; assert( ix->size() != 0); // must be, from compiler if( ixList.size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); // determine type of index // SizeT nIndexed = 0; SizeT nScalar = 0; for( SizeT i=0; (i+1)Type() || ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[i]->Type() ) nScalar++; // else if( ArrayIndexIndexedID == ixList[i]->Type() || // CArrayIndexIndexedID == ixList[i]->Type()) nIndexed++; } if( nScalar == ixList.size()-1) accessTypeAssocInit = ALLONE; // else if( nIndexed == ixList.size()-1) // accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well // else if( nScalar + nIndexed < ixList.size()-1) else accessTypeAssocInit = NORMAL; // else // accessTypeAssocInit = INDEXED_ONE; if( ArrayIndexScalarID == ixList[ixList.size()-1]->Type() || ArrayIndexScalarVPID == ixList[ixList.size()-1]->Type() || // ? (from MakeArrayIndex) CArrayIndexScalarID == ixList[ixList.size()-1]->Type()) nScalar++; // else if( ArrayIndexIndexedID == ixList[ixList.size()-1]->Type() || // CArrayIndexIndexedID == ixList[ixList.size()-1]->Type()) nIndexed++; /* if( dynamic_cast< ArrayIndexScalar*>(ixList[ixList.size()-1]) || dynamic_cast< CArrayIndexScalar*>(ixList[ixList.size()-1])) nScalar++; if( dynamic_cast(ixList[ixList.size()-1]) || dynamic_cast(ixList[ixList.size()-1]) ) nIndexed++;*/ assert( nScalar <= ixList.size()); // from MakeArrayIndex // if( nScalar == ixList.size()) // accessTypeInit = ALLONE; // // else if( nIndexed == ixList.size()) // // accessTypeInit = ALLINDEXED; // might be ALLONE as well // // else if( nScalar + nIndexed < ixList.size()) // else accessTypeInit = NORMAL; // std::cout << "accessTypeInit: " << accessTypeInit << std::endl; } ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoneIndexedT( *this);} // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record if( var->IsAssoc()) { acRank--; accessType = accessTypeAssocInit; } else accessType = accessTypeInit; // can happen due to assoc variables if( accessType == ALLONE) { const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0NIter( (iGetS() * varStride[i]; } nIx = 1; return; } // accessType can be at this point: // NORMAL // now the definite types here assert( accessType == NORMAL); // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); // varDim.Stride( varStride,acRank); // copy variables stride into varStride nIterLimit[0]=ixList[0]->NIter( (0 1)? 1 : 0; gt1Rank = 0; assert( varStride[0] == 1); baseIx = ixList[0]->GetS(); // * varStride[0]; for( SizeT i=1; iNIter( (i 1) { ++nIterLimitGt1; gt1Rank = i; } baseIx += ixList[i]->GetS() * varStride[i]; } stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride } // returns 1-dim index for all elements AllIxBaseT* BuildIx() { if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign() return allIx; assert( allIx == NULL); // if( allIx != NULL) // return allIx; // if( accessType == ALLONE) // { // SizeT s = ixList.FrontGetS(); //ixList[0]->GetS(); // for( SizeT l=1; l < acRank; ++l) // { // s += ixList[l]->GetS() * varStride[l]; // } // allIx = new (allIxInstance) AllIxT(s); // return allIx; // } // ALLONE or all nIterLimit == 1 if( nIterLimitGt1 == 0) // only one single index { allIx = new (allIxInstance) AllIxT( baseIx); return allIx; } if( acRank == 1) // assoc already recognized { ArrayIndexT* ix = ixList[0]; if( nIx == 1) { allIx = new (allIxInstance) AllIxT( ix->GetS()); return allIx; } SizeT s = ix->GetS(); SizeT ixStride = ix->GetStride(); if( ixStride <= 1) if( s != 0) { allIx = new (allIxInstance) AllIxRangeT( nIx, s); } else { allIx = new (allIxInstance) AllIxRange0T( nIx); } else if( s != 0) { allIx = new (allIxInstance) AllIxRangeStrideT( nIx, s, ixStride); } else { allIx = new (allIxInstance) AllIxRange0StrideT( nIx, ixStride); } return allIx; } // NORMAL // loop only over specified indices // higher indices of variable are implicitely zero, // therefore they are not checked in 'SetRoot' if( nIterLimitGt1 == 1) // only one variable dimension { allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } if( acRank == 2) // assoc already recognized { allIx = new (allIxInstance) AllIxNewMultiNoneIndexed2DT( &ixList, nIx, varStride, nIterLimit, stride); return allIx; } allIx = new (allIxInstance) AllIxNewMultiNoneIndexedT( &ixList, acRank, nIx, varStride, nIterLimit, stride); return allIx; } }; // ArrayIndexListMultiNoneIndexedT class ArrayIndexListMultiAllIndexedT: public ArrayIndexListMultiT { public: // called once after structure is fixed at (GDL-)compile time ArrayIndexListMultiAllIndexedT( ArrayIndexVectorT* ix) // : ixList( *ix), // allIx( NULL), // ixListEnd( NULL) { ixList = *ix; allIx = NULL; ixListEnd = NULL; assert( ix->size() != 0); // must be, from compiler if( ixList.size() > MAXRANK) throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false); nParam = 0; for( SizeT i=0; isize(); ++i) nParam += (*ix)[i]->NParam(); accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well accessTypeInit = ALLINDEXED; // might be ALLONE as well } ArrayIndexListT* Clone() { return new ArrayIndexListMultiAllIndexedT( *this);} // set the root variable which is indexed by this ArrayIndexListMultiT void SetVariable( BaseGDL* var) { assert( allIx == NULL); // set acRank acRank = ixList.size(); // for assoc variables last index is the record if( var->IsAssoc()) { acRank--; accessType = accessTypeAssocInit; } else accessType = accessTypeInit; SizeT i=0; for(; iScalar()) break; if( i == acRank) // counted up to acRank -> all scalar { accessType = ALLONE; // needed for GetDim() const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); varStride = varDim.Stride(); nIterLimitGt1 = 0; // marker for BuildIx ixList[0]->NIter( (0GetIx0(); // * varStride[0]; // GetS() not ok because INDEXED // check boundary for(SizeT i=1; iNIter( (iGetIx0() * varStride[i]; // GetS() not ok because INDEXED } nIx = 1; return; } if( i > 0) { accessType = NORMAL; // there was a scalar (and break because of non-scalar) } else // i == 0 -> first was (because of ALLINDEXED) indexed { ++i; // first was already non-scalar -> indexed for(; iIndexed()) { accessType = NORMAL; break; } } // accessType can be at this point: // NORMAL // ALLINDEXED // both are the definite types here assert( accessType == NORMAL || accessType == ALLINDEXED); // set varDim from variable const dimension& varDim = var->Dim(); SizeT varRank = varDim.Rank(); if( accessType == ALLINDEXED) { nIx=ixList[0]->NIter( (0NIter( (iDim().Stride(); return; } // NORMAL varStride = var->Dim().Stride(); assert( varStride[0] == 1); nIterLimit[0]=ixList[0]->NIter( (0 1) { nIterLimitGt1 = 1; // important for BuildIx gt1Rank = 0; if( ixList[0]->Indexed()) { baseIx = 0; indexed = true; } else { baseIx = ixList[0]->GetS();// * varStride[0]; indexed = false; } } else { nIterLimitGt1 = 0; // important for BuildIx if( ixList[0]->Indexed()) { baseIx = static_cast< ArrayIndexIndexed*>( ixList[0])->GetIx0();// * varStride[0]; } else { baseIx = ixList[0]->GetS();// * varStride[0]; } } for( SizeT i=1; iNIter( (i 1) { ++nIterLimitGt1; gt1Rank = i; if( ixList[i]->Indexed()) { indexed = true; } else { baseIx += ixList[i]->GetS() * varStride[i]; indexed = false; } } else { if( ixList[i]->Indexed()) { baseIx += static_cast< ArrayIndexIndexed*>( ixList[i])->GetIx0() * varStride[i]; } else { baseIx += ixList[i]->GetS() * varStride[i]; } } } stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride } }; //class ArrayIndexListMultiAllIndexedT: public ArrayIndexListMultiT class ArrayIndexListGuard { private: ArrayIndexListT* aL; public: ArrayIndexListGuard(): aL( NULL) {} ArrayIndexListGuard(ArrayIndexListT* aLToGuard): aL( aLToGuard) {} ~ArrayIndexListGuard() { if( aL != NULL) aL->Clear(); } void reset( ArrayIndexListT* aL_) { aL = aL_;} ArrayIndexListT* release() { ArrayIndexListT* res = aL; aL = NULL; return res;} void Release() { aL = NULL;} }; // called after structure is fixed (code in arrayindex.cpp) //ArrayIndexListT* MakeArrayIndex( ArrayIndexVectorT* ixList); void MakeArrayIndex( ArrayIndexVectorT* ixList, ArrayIndexListT** arrayIndexOut, ArrayIndexListT** arrayIndexNoAssocOut = NULL); #endif gdl-0.9.9/src/assocdata.cpp000066400000000000000000000234551340051421000155330ustar00rootroot00000000000000/*************************************************************************** assocdata.cpp - GDL ASSOC datatype ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "assocdata.hpp" #include "arrayindexlistt.hpp" #include "objects.hpp" #include "io.hpp" using namespace std; template< class Parent_> vector< void*> Assoc_< Parent_>::freeList; template< class Parent_> void* Assoc_< Parent_>::operator new( size_t bytes) { assert( bytes == sizeof( Assoc_< Parent_> )); if( freeList.size() > 0) { void* res = freeList.back(); freeList.pop_back(); return res; } const size_t newSize = multiAlloc - 1; static long callCount = 0; ++callCount; // reserve space for all instances freeList.reserve( callCount*multiAlloc); // resize to what is needed now freeList.resize( newSize); #ifdef USE_EIGEN // we need this allocation here as well (as in typedefs.hpp), because GDLArray needs to be aligned const int alignmentInBytes = 16; // set to multiple of 16 >= sizeof( char*) const size_t realSizeOfType = sizeof( Assoc_< Parent_>); const SizeT exceed = realSizeOfType % alignmentInBytes; const size_t sizeOfType = realSizeOfType + (alignmentInBytes - exceed); char* res = static_cast< char*>( Eigen::internal::aligned_malloc( sizeOfType * multiAlloc)); // one more than newSize #else const size_t sizeOfType = sizeof( Assoc_< Parent_>); char* res = static_cast< char*>( malloc( sizeOfType * multiAlloc)); // one more than newSize #endif for( size_t i=0; i void Assoc_< Parent_>::operator delete( void *ptr) { freeList.push_back( ptr); } template< class Parent_> Assoc_< Parent_>::Assoc_( int lun_, Parent_* assoc_, SizeT fileOffset_): Parent_( assoc_->Dim(), BaseGDL::NOZERO), lun( lun_-1), fileOffset( fileOffset_), sliceSize( assoc_->NBytes()) { if( assoc_->Type() == GDL_STRING) throw GDLException( "Expression containing string data not allowed in this context."); if( assoc_->Type() == GDL_PTR) throw GDLException( "Expression containing pointers not allowed in this context."); if( assoc_->Type() == GDL_OBJ) throw GDLException( "Expression containing object references not allowed in this context."); } template<> Assoc_< DStructGDL>::Assoc_( int lun_, DStructGDL* assoc_, SizeT fileOffset_): DStructGDL( assoc_->Desc(), assoc_->Dim()), // BaseGDL::NOZERO), // an instance is needed (for storing the data slice) lun( lun_-1), fileOffset( fileOffset_), sliceSize( assoc_->NBytes()) { MakeOwnDesc(); } // called from help_item template std::ostream& Assoc_::ToStream(std::ostream& o, SizeT width, SizeT* actPosPtr) { o << "File<" << fileUnits[ lun].Name() << "> "; return o; // throw GDLException("File expression not allowed in this context."); } // writing 1 // assigns srcIn to this at ixList, if ixList is NULL does linear copy // assumes: ixList has this already set as variable // ("offset" is offset into srcIn) template void Assoc_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { assert( offset == 0); SizeT recordNum; bool ixEmpty = ixList->ToAssocIndex( recordNum); if( !ixEmpty) { // throw GDLException("File expression cannot be subindexed for output."); SizeT seekPos = fileOffset + recordNum * sliceSize; if( fileUnits[ lun].Size() > seekPos) { fileUnits[ lun].Seek( seekPos); Parent_::Read( (fileUnits[lun].Compress()?static_cast(fileUnits[lun].IgzStream()):static_cast(fileUnits[lun].IStream())), fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); } else { Parent_::Clear(); // zero fields } Parent_::AssignAt( srcIn, ixList, offset); fstream& fs = fileUnits[ lun].OStream(); fileUnits[ lun].SeekPad( seekPos); Parent_::Write( fs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); } else { // ix empty -> write direct fstream& ofs = fileUnits[ lun].OStream(); fileUnits[ lun].SeekPad( fileOffset + recordNum * sliceSize); srcIn->Write( ofs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); } } template void Assoc_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { SizeT recordNum; bool ixEmpty = ixList->ToAssocIndex( recordNum); if( !ixEmpty) { // throw GDLException("File expression cannot be subindexed for output."); SizeT seekPos = fileOffset + recordNum * sliceSize; if( fileUnits[ lun].Size() > seekPos) { // fstream& fs = fileUnits[ lun].IStream(); fileUnits[ lun].Seek( seekPos); Parent_::Read( (fileUnits[lun].Compress()?static_cast(fileUnits[lun].IgzStream()):static_cast(fileUnits[lun].IStream())), fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); } else { Parent_::Clear(); // zero fields } Parent_::AssignAt( srcIn, ixList); fstream& fs = fileUnits[ lun].OStream(); fileUnits[ lun].SeekPad( seekPos); // Parent_::Write( fs, fileUnits[ lun].SwapEndian()); Parent_::Write( fs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); } else { // ix empty -> write direct fstream& ofs = fileUnits[ lun].OStream(); fileUnits[ lun].SeekPad( fileOffset + recordNum * sliceSize); srcIn->Write( ofs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); /* Parent_::Write( ofs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Xdr());*/ } } template void Assoc_::AssignAt( BaseGDL* srcIn) { SizeT recordNum = 0; // ix empty -> write direct fstream& ofs = fileUnits[ lun].OStream(); fileUnits[ lun].SeekPad( fileOffset + recordNum * sliceSize); srcIn->Write( ofs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); /* Parent_::Write( ofs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Xdr());*/ } // (writing 2) // should not be called at all // only from AccessdescT::Resolve() // and this only for dot expressions (which are not allowed for assoc vars) template void Assoc_::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { throw GDLException("Internal error: Assoc::InsertAt: called."); SizeT recordNum; bool ixEmpty = ixList->ToAssocIndex( recordNum); if( ixEmpty) { // potential problem if offset != 0 Parent_::InsertAt( offset, srcIn, NULL); fstream& ofs = fileUnits[ lun].OStream(); fileUnits[ lun].SeekPad( fileOffset + recordNum * sliceSize); // Parent_::Write( ofs, fileUnits[ lun].SwapEndian()); Parent_::Write( ofs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); } else { // throw GDLException("File expression cannot be subindexed for output."); fstream& fs = fileUnits[ lun].IStream(); fileUnits[ lun].Seek( fileOffset + recordNum * sliceSize); Parent_::Read( fs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); Parent_::InsertAt( offset, srcIn, ixList); fileUnits[ lun].SeekPad( fileOffset + recordNum * sliceSize); // Parent_::Write( fs, fileUnits[ lun].SwapEndian()); Parent_::Write( fs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); return; } } // reading OK // returns (*this)[ ixList] template Parent_* Assoc_::Index( ArrayIndexListT* ixList) { SizeT recordNum; bool ixEmpty = ixList->ToAssocIndex( recordNum); istream& fs = fileUnits[lun].Compress()?static_cast(fileUnits[lun].IgzStream()):static_cast(fileUnits[lun].IStream()); fileUnits[ lun].Seek( fileOffset + recordNum * sliceSize); Parent_::Read( fs, fileUnits[ lun].SwapEndian(), fileUnits[ lun].Compress(), fileUnits[ lun].Xdr()); if( ixEmpty) { return static_cast(Parent_::Dup()); } else { return Parent_::Index( ixList); } } // explicit instantiation requests template class Assoc_< DByteGDL>; template class Assoc_< DIntGDL>; template class Assoc_< DUIntGDL>; template class Assoc_< DLongGDL>; template class Assoc_< DULongGDL>; template class Assoc_< DLong64GDL>; template class Assoc_< DULong64GDL>; template class Assoc_< DPtrGDL>; template class Assoc_< DStructGDL>; template class Assoc_< DFloatGDL>; template class Assoc_< DDoubleGDL>; template class Assoc_< DStringGDL>; template class Assoc_< DObjGDL>; template class Assoc_< DComplexGDL>; template class Assoc_< DComplexDblGDL>; gdl-0.9.9/src/assocdata.hpp000066400000000000000000000267541340051421000155450ustar00rootroot00000000000000/*************************************************************************** assocdata.hpp - GDL assoc variables ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ASSOCDATA_HPP_ #define ASSOCDATA_HPP_ #include "typetraits.hpp" #include "datatypes.hpp" #include "dstructgdl.hpp" template class Assoc_: public Parent_ { int lun; // internal lun (0..127) SizeT fileOffset; SizeT sliceSize; // size of one slice public: // memory management optimization static std::vector< void*> freeList; // operator new and delete static void* operator new( size_t bytes); static void operator delete( void *ptr); // external lun (1..128) Assoc_( int lun_, Parent_* assoc_, SizeT fileOffset_); ~Assoc_() {} // c-i Assoc_( const Assoc_& cp): Parent_(cp), lun(cp.lun), fileOffset( cp.fileOffset), sliceSize( cp.sliceSize) {} Assoc_* Dup() const { return new Assoc_(*this);} void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset); void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList); void AssignAt( BaseGDL* srcIn); // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset void InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList); // returns (*this)[ ixList] Parent_* Index( ArrayIndexListT* ixList); SizeT N_Elements() const { return this->Parent_::N_Elements(); return 1; } bool IsAssoc() const { return true;} // ****************************************** // all the following operations are illegal with file types // one dim array access (unchecked) typename Parent_::Ty& operator[] (const SizeT d1) { throw GDLException("Assoc_::Operator[](...) called."); } SizeT NBytes() const { return this->Parent_::NBytes(); throw GDLException("Assoc_::NBytes() called."); } std::ostream& Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs) { throw GDLException("Assoc_::Write(...) called."); } std::istream& Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs) { throw GDLException("Assoc_::Read(...) called."); } // std::ostream& ToStream(std::ostream& o) std::ostream& ToStream(std::ostream& o, SizeT width = 0, SizeT* actPosPtr = NULL); // { // // os << "File<"+/dev/zero+"> "; // return Parent_::ToStream( o, width, actPosPtr); // // throw GDLException("File expression not allowed in this context."); // } std::istream& FromStream(std::istream& i) { throw GDLException("File expression not allowed in this context."); } bool Scalar() const { return false;} // const DType Type() const; // const string& TypeStr() const; //Don't overwrite New method Parent_* New( const dimension& dim_, BaseGDL::InitType noZero=BaseGDL::ZERO) const { throw GDLException("Assoc_::New(...) called."); } Parent_* NewResult() const { throw GDLException("Assoc_::NewResult() called."); } // cannot convert Assoc_ data // Parent_::CatArray throws because of Parent_::Convert2(...) // if type is Assoc_<> Parent_* Convert2( DType destTy, BaseGDL::Convert2Mode=BaseGDL::CONVERT) { throw GDLException("File expression not allowed in this context."); } // DStructDesc::AddTag() (which uses GetTag()) must refuse Assoc_ Parent_* GetTag() const { throw GDLException("File expression not allowed in this context."); } // because of AddTag(), this function should never be called Parent_* GetInstance() const { throw GDLException("Assoc_::GetInstance(...) called."); } int Scalar2Index(SizeT& ret) const { throw GDLException("File expression not allowed in this context."); } bool True() { throw GDLException("File expression not allowed in this context."); } bool LogTrue() { throw GDLException("File expression not allowed in this context."); } bool LogTrue( SizeT ix) { throw GDLException("File expression not allowed in this context."); } Data_* LogNeg() { throw GDLException("File expression not allowed in this context."); } bool False() { throw GDLException("File expression not allowed in this context."); } int Sgn() // -1,0,1 { throw GDLException("File expression not allowed in this context."); } bool Equal( BaseGDL*) const { throw GDLException("File expression not allowed in this context."); } bool EqualNoDelete( const BaseGDL*) const { throw GDLException("File expression not allowed in this context."); } void ForCheck( BaseGDL**, BaseGDL** = NULL) { throw GDLException("File expression not allowed in this context."); } bool ForAddCondUp( BaseGDL* loopInfo) // bool ForAddCondUp( ForLoopInfoT& loopInfo) { throw GDLException("File expression not allowed in this context."); } bool ForCondUp( BaseGDL*) { throw GDLException("File expression not allowed in this context."); } bool ForCondDown( BaseGDL*) { throw GDLException("File expression not allowed in this context."); } void ForAdd( BaseGDL* add=NULL) { throw GDLException("File expression not allowed in this context."); } Parent_* CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank) { throw GDLException("File expression not allowed in this context."); } // used in r_expr BaseGDL* UMinus() { throw GDLException("File expression not allowed in this context."); } Parent_* NotOp() { throw GDLException("File expression not allowed in this context."); } Parent_* AndOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* AndOpInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* OrOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* OrOpInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* XorOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } BaseGDL* EqOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } BaseGDL* NeOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } BaseGDL* LeOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } BaseGDL* GeOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } BaseGDL* LtOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } BaseGDL* GtOp( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* Add( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* AddInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* Sub( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* SubInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* LtMark( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* GtMark( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* Mult( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* Div( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* DivInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* Mod( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* ModInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* Pow( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* PowInv( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* PowInt( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* PowIntNew( BaseGDL* r) { throw GDLException("File expression not allowed in this context."); } Parent_* MatrixOp( BaseGDL* r, bool, bool) { throw GDLException("File expression not allowed in this context."); } void DecAt( ArrayIndexListT* ixList) { throw GDLException("File expression not allowed in this context."); } void IncAt( ArrayIndexListT* ixList) { throw GDLException("File expression not allowed in this context."); } void Dec() { throw GDLException("File expression not allowed in this context."); } void Inc() { throw GDLException("File expression not allowed in this context."); } SizeT OFmtA( std::ostream* os, SizeT offset, SizeT num, int width) { throw GDLException("File expression not allowed in this context."); } SizeT OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code, const BaseGDL::IOMode oM = BaseGDL::FIXED) { throw GDLException("File expression not allowed in this context."); } SizeT OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code, BaseGDL::IOMode oM = BaseGDL::DEC) { throw GDLException("File expression not allowed in this context."); } SizeT OFmtCal( std::ostream* os, SizeT offs, SizeT num, int width, int minN, char *f, int code, BaseGDL::Cal_IOMode oM = BaseGDL::DEFAULT) { throw GDLException("File expression not allowed in this context."); } SizeT IFmtA( std::istream* os, SizeT offset, SizeT num, int width) { throw GDLException("File expression not allowed in this context."); } SizeT IFmtF( std::istream* os, SizeT offs, SizeT num, int width) { throw GDLException("File expression not allowed in this context."); } SizeT IFmtI( std::istream* os, SizeT offs, SizeT num, int width, BaseGDL::IOMode oM = BaseGDL::DEC) { throw GDLException("File expression not allowed in this context."); } SizeT IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode) { throw GDLException("File expression not allowed in this context."); } Parent_* AssocVar( int, SizeT) { throw GDLException("File expression not allowed in this context."); } }; template<> Assoc_< DStructGDL>::Assoc_( int lun_, DStructGDL* assoc_, SizeT fileOffset_); #endif gdl-0.9.9/src/base64.hpp000066400000000000000000000153001340051421000146500ustar00rootroot00000000000000#ifndef INCLUDED_Base64_H # define INCLUDED_Base64_H // SA: based on: // ---------------------------------------------------------------- // http://cvs.tekkotsu.org/viewvc/Tekkotsu/Shared/Base64.cc?view=co // http://cvs.tekkotsu.org/viewvc/Tekkotsu/Shared/Base64.h?view=co // ---------------------------------------------------------------- /* ... * Copyright (c) 1999, Bob Withers - bwit@pobox.com * * This code may be freely used for any purpose, either personal * or commercial, provided the authors copyright notice remains * intact. * * Enhancements by Stanley Yamane: * - reverse lookup table for the decode function * - reserve string buffer space in advance * * Modified by Ethan Tira-Thompson: * - changed Base64 class to base64 namespace * - modified functions to work on char[] instead of strings * - added doxygen commenting * * author: Bob Withers - bwit@pobox.com (Creator) */ using namespace std; namespace base64 { static const char fillchar = '='; //!< used to mark partial words at the end static const string::size_type np = string::npos; //!< shorthand for the "no position" return code from string //! this lookup table defines the base64 encoding const string Base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); //! Decode Table gives the index of any valid base64 character in the Base64 table] /*! 65 == A, 97 == a, 48 == 0, 43 == +, 47 == / */ const string::size_type DecodeTable[] = { np,np,np,np,np,np,np,np,np,np, // 0 - 9 np,np,np,np,np,np,np,np,np,np, //10 -19 np,np,np,np,np,np,np,np,np,np, //20 -29 np,np,np,np,np,np,np,np,np,np, //30 -39 np,np,np,62,np,np,np,63,52,53, //40 -49 54,55,56,57,58,59,60,61,np,np, //50 -59 np,np,np,np,np, 0, 1, 2, 3, 4, //60 -69 5, 6, 7, 8, 9,10,11,12,13,14, //70 -79 15,16,17,18,19,20,21,22,23,24, //80 -89 25,np,np,np,np,np,np,26,27,28, //90 -99 29,30,31,32,33,34,35,36,37,38, //100 -109 39,40,41,42,43,44,45,46,47,48, //110 -119 49,50,51,np,np,np,np,np,np,np, //120 -129 np,np,np,np,np,np,np,np,np,np, //130 -139 np,np,np,np,np,np,np,np,np,np, //140 -149 np,np,np,np,np,np,np,np,np,np, //150 -159 np,np,np,np,np,np,np,np,np,np, //160 -169 np,np,np,np,np,np,np,np,np,np, //170 -179 np,np,np,np,np,np,np,np,np,np, //180 -189 np,np,np,np,np,np,np,np,np,np, //190 -199 np,np,np,np,np,np,np,np,np,np, //200 -209 np,np,np,np,np,np,np,np,np,np, //210 -219 np,np,np,np,np,np,np,np,np,np, //220 -229 np,np,np,np,np,np,np,np,np,np, //230 -239 np,np,np,np,np,np,np,np,np,np, //240 -249 np,np,np,np,np,np //250 -256 }; string encode(char buf[], unsigned int len) { string ret; if(len==0) return ""; ret.reserve((len-1)/3*4 + 4 + 1); for (string::size_type i = 0; i < len; ++i) { char c; c = (buf[i] >> 2) & 0x3f; ret.append(1, Base64Table[c]); c = (buf[i] << 4) & 0x3f; if (++i < len) c |= (buf[i] >> 4) & 0x0f; ret.append(1, Base64Table[c]); if (i < len) { c = (buf[i] << 2) & 0x3f; if (++i < len) c |= (buf[i] >> 6) & 0x03; ret.append(1, Base64Table[c]); } else { ++i; ret.append(1, fillchar); } if (i < len) { c = buf[i] & 0x3f; ret.append(1, Base64Table[c]); } else { ret.append(1, fillchar); } } return(ret); } unsigned int decodeSize(const std::string& data) { unsigned int fills=0; unsigned int size=data.size(); //skip any extra characters at the end (e.g. newlines or spaces) while(size>0 && DecodeTable[(unsigned char)data[size-1]]==np && data[size-1]!=fillchar) size--; if((size/4) * 4 != size) { Warning("base 64 decodeSize error: data size is not multiple of 4"); return size/4*3 + 3; } //count fill characters ('=') while(fills2) { Warning("base 64 decodeSize error: too many fill characters"); size-=(fills/3) * 3; fills=fills%3; } //cout << "Size is " << size/4*3-fills << " with " << fills << " fills and " << data.size()-size << " extra" << endl; return size/4*3-fills; } bool decode(const std::string& data, char buf[], unsigned int len) { const string::size_type size = data.length(); string::size_type i = 0, p=0; while(true) { bool retry=false; string::size_type d=np; do { d=DecodeTable[(unsigned char)data[i++]]; retry=false; if(d==np) { if(fillchar == data[i-1]) { Warning("base64 decode error: unexpected fill char -- offset read?"); return false; } if(!(std::isspace(data[i-1]))) { //cerr << "base 64 decode error: illegal character '" << data[i-1] << "' (0x" << std::hex << (int)data[i-1] << std::dec << ")" << endl; Warning("base 64 decode error: illegal character"); return false; } retry=true; } } while(retry); char c = (char) d; do { d=DecodeTable[(unsigned char)data[i++]]; retry=false; if(d==np) { if(fillchar == data[i-1]) { Warning("base64 decode error: unexpected fill char -- offset read?"); return false; } if(!(std::isspace(data[i-1]))) { //cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl; Warning("base 64 decode error: illegal character"); return false; } retry=true; } } while(retry); if(p>=len) return false; char c1 = (char) d; c = (c << 2) | ((c1 >> 4) & 0x3); buf[p++]=c; if(i>=size) { Warning("base64 decode error: Truncated data"); return false; } do { d=DecodeTable[(unsigned char)data[i++]]; retry=false; if(d==np) { if(fillchar == data[i-1]) { return true; } if((!std::isspace(data[i-1]))) { //cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl; Warning("base 64 decode error: illegal character"); return false; } retry=true; } } while(retry); if(p>=len) return false; c = (char) d; c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); buf[p++]=c1; if(i>=size) { Warning("base64 decode error: Truncated data"); return false; } do { d=DecodeTable[(unsigned char)data[i++]]; retry=false; if(d==np) { if(fillchar == data[i-1]) { return true; } if(!(std::isspace(data[i-1]))) { //cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl; Warning("base 64 decode error: illegal character"); return false; } retry=true; } } while(retry); if(p>=len) return false; c1 = (char) d; c = ((c << 6) & 0xc0) | c1; buf[p++]=c; if(i==size) return true; } //Warning("base64 decode error: unexpected break"); //return false; } } #endif gdl-0.9.9/src/basegdl.cpp000066400000000000000000000554151340051421000151730ustar00rootroot00000000000000/*************************************************************************** basegdl.cpp - base class for GDL datatypes ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "basegdl.hpp" #include "nullgdl.hpp" using namespace std; DInterpreter* BaseGDL::interpreter = NULL; // get the vtable for BaseGDL BaseGDL::~BaseGDL() {} BaseGDL::BaseGDL(): dim() {} BaseGDL::BaseGDL(const dimension& dim_): dim(dim_) {} bool BaseGDL::IsAssoc() const { return false;} BaseGDL* BaseGDL::AssocVar( int, SizeT) { throw GDLException("BaseGDL::AssocVar(...) called."); } SizeT BaseGDL::N_Elements() const { return dim.NDimElementsConst(); } SizeT BaseGDL::Size() const { return 0;} SizeT BaseGDL::ToTransfer() const { return 0;} SizeT BaseGDL::Sizeof() const { return 0;} SizeT BaseGDL::NBytes() const { return 0;} // for assoc function BaseGDL& BaseGDL::operator=(const BaseGDL& right) { if( &right == this) return *this; this->dim = right.dim; return *this; } void BaseGDL::InitFrom(const BaseGDL& right) { throw GDLException("BaseGDL::InitFrom(const BaseGDL& right) called."); } // BaseGDL* BaseGDL::Abs() const // { // throw GDLException("BaseGDL::Abs() called."); // } int BaseGDL::HashCompare( BaseGDL*) const { throw GDLException("BaseGDL::HashCompare( BaseGDL*) called."); } bool BaseGDL::Greater(SizeT i1, SizeT i2) const { throw GDLException("BaseGDL::Greater(SizeT,SizeT) called."); } bool BaseGDL::Equal(SizeT i1, SizeT i2) const { throw GDLException("BaseGDL::Equal(SizeT,SizeT) called."); } BaseGDL* BaseGDL::CShift( DLong d) const { throw GDLException("BaseGDL::CShift(...) called."); } BaseGDL* BaseGDL::CShift( DLong d[MAXRANK]) const { throw GDLException("BaseGDL::CShift( DLong d[MAXRANK]) called."); } BaseGDL* BaseGDL::Transpose( DUInt* perm) { throw GDLException("BaseGDL::Transpose(...) called."); } void BaseGDL::MinMax(DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { throw GDLException("BaseGDL::MinMax(...) called."); } void BaseGDL::Clear() { throw GDLException("BaseGDL::Clear() called."); } void BaseGDL::Construct() { throw GDLException("BaseGDL::Construct() called."); } void BaseGDL::ConstructTo0() { throw GDLException("BaseGDL::ConstructTo0() called."); } void BaseGDL::Destruct() { throw GDLException("BaseGDL::Destruct() called."); } void BaseGDL::Assign( BaseGDL* src, SizeT nEl) { throw GDLException("BaseGDL::Assign(...) called."); } std::ostream& BaseGDL::Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs) { throw GDLException("BaseGDL::Write(...) called."); } std::istream& BaseGDL::Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs) { throw GDLException("BaseGDL::Read(...) called."); } std::ostream& BaseGDL::ToStream(std::ostream& o, SizeT width, SizeT* actPosPtr ) { throw GDLException("BaseGDL::ToStream(...) called."); } std::istream& BaseGDL::FromStream(std::istream& i) { i >> *this; return i; } bool BaseGDL::OutOfRangeOfInt() const { return false;} bool BaseGDL::Scalar() const { return false;} bool BaseGDL::StrictScalar() const { return false;} DType BaseGDL::Type() const { return GDL_UNDEF;} const std::string& BaseGDL::TypeStr() const { static const std::string s("UNDEFINED"); return s;} bool BaseGDL::EqType( const BaseGDL*) const { throw GDLException("BaseGDL::EqType(...) called."); } void* BaseGDL::DataAddr()// SizeT elem) { throw GDLException("BaseGDL::DataAddr(...) called."); } // make same type on the heap BaseGDL* BaseGDL::New( const dimension& dim_, InitType noZero) const { throw GDLException("BaseGDL::New(...) called."); } BaseGDL* BaseGDL::NewResult() const { throw GDLException("BaseGDL::NewResult() called."); } BaseGDL* BaseGDL::Dup() const { throw GDLException("BaseGDL::Dup() called."); } // BaseGDL* BaseGDL::Dup( void*) const // { // throw GDLException("BaseGDL::Dup(...) called."); // } BaseGDL* BaseGDL::Convert2( DType destTy, Convert2Mode mode) { throw GDLException("BaseGDL::Convert2(...) called."); } BaseGDL* BaseGDL::GetTag() const { throw GDLException("BaseGDL::GetTag(...) called."); } BaseGDL* BaseGDL::GetInstance() const { throw GDLException("BaseGDL::GetInstance(...) called."); } BaseGDL* BaseGDL::GetEmptyInstance() const { throw GDLException("BaseGDL::GetEmptyInstance(...) called."); } BaseGDL* BaseGDL::SetBuffer( const void* b) { throw GDLException("BaseGDL::SetBuffer called."); } void BaseGDL::SetBufferSize( SizeT s) { throw GDLException("BaseGDL::SetBufferSize called."); } int BaseGDL::Scalar2Index(SizeT& ret) const { throw GDLException("Operation not defined for UNDEF 1."); } int BaseGDL::Scalar2RangeT(RangeT& ret) const { throw GDLException("Operation not defined for UNDEF 1a."); } SizeT BaseGDL::GetAsIndex( SizeT i) const { throw GDLException("BaseGDL::GetAsIndex called."); } SizeT BaseGDL::GetAsIndexStrict( SizeT i) const { throw GDLException("BaseGDL::GetAsIndexStrict called."); } #ifdef _MSC_VER bool BaseGDL::True() #else bool BaseGDL::BaseGDL::True() #endif { throw GDLException("Operation not defined for UNDEF 3."); } #ifdef _MSC_VER bool BaseGDL::False() #else bool BaseGDL::BaseGDL::False() #endif { throw GDLException("Operation not defined for UNDEF 4."); } bool BaseGDL::LogTrue() { throw GDLException("Operation not defined for UNDEF 4a."); } bool BaseGDL::LogTrue( SizeT ix) { throw GDLException("Operation not defined for UNDEF 4b."); } void BaseGDL::Where(DLong* &ret, SizeT &passed_count, bool comp, DLong* &comp_ret) { throw GDLException("Operation not defined for UNDEF 4b."); } void BaseGDL::Where(DLong64* &ret, SizeT &passed_count, bool comp, DLong64* &comp_ret) { throw GDLException("Operation not defined for UNDEF 4b."); } BaseGDL* BaseGDL::LogNeg() { throw GDLException("Operation not defined for UNDEF 4c."); } int BaseGDL::Sgn() // -1,0,1 { throw GDLException("Operation not defined for UNDEF 5."); } bool BaseGDL::Equal( BaseGDL*) const { throw GDLException("Operation not defined for UNDEF 6."); } bool BaseGDL::EqualNoDelete( const BaseGDL*) const { throw GDLException("Operation not defined for UNDEF 6a."); } bool BaseGDL::ArrayEqual( BaseGDL*) { throw GDLException("Operation not defined for UNDEF 6b."); } bool BaseGDL::ArrayNeverEqual( BaseGDL*) { throw GDLException("Operation not defined for UNDEF 6b."); } // for statement compliance (int types , float types scalar only) void BaseGDL::ForCheck( BaseGDL**, BaseGDL**) { throw GDLException("Operation not defined for UNDEF 7."); } bool BaseGDL::ForCondUp( BaseGDL*) { throw GDLException("Operation not defined for UNDEF 8."); } bool BaseGDL::ForAddCondUp( BaseGDL* loopInfo) // bool BaseGDL::ForAddCondUp( ForLoopInfoT& loopInfo) { throw GDLException("Operation not defined for UNDEF 8a."); } bool BaseGDL::ForCondDown( BaseGDL*) { throw GDLException("Operation not defined for UNDEF 9."); } // bool BaseGDL::ForCondUpDown( BaseGDL*) // { // throw GDLException("Operation not defined for UNDEF 9a."); // } void BaseGDL::ForAdd( BaseGDL* add) { throw GDLException("Operation not defined for UNDEF 10."); } BaseGDL* BaseGDL::CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank) { throw GDLException("BaseGDL::CatArray(...) called."); } BaseGDL* BaseGDL::Index( ArrayIndexListT* ixList) { throw GDLException("BaseGDL::Index(...) called."); } // used in r_expr BaseGDL* BaseGDL::UMinus() { throw GDLException("Operation not defined for UNDEF 11."); } BaseGDL* BaseGDL::NotOp() { throw GDLException("Operation not defined for UNDEF 12."); } BaseGDL* BaseGDL::AndOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::AndOpInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 14."); } BaseGDL* BaseGDL::OrOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::OrOpInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 14."); } BaseGDL* BaseGDL::XorOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::XorOpS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13a."); } BaseGDL* BaseGDL::EqOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::NeOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::LeOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::GeOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::LtOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::GtOp( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::Add( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 15."); } BaseGDL* BaseGDL::AddInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 15."); } BaseGDL* BaseGDL::Sub( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::SubInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::LtMark( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 18."); } BaseGDL* BaseGDL::GtMark( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 19."); } BaseGDL* BaseGDL::Mult( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 19a."); } BaseGDL* BaseGDL::Div( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::DivInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::Mod( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::ModInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::Pow( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::PowInv( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::PowInt( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 170."); } BaseGDL* BaseGDL::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { throw GDLException("Operation not defined for UNDEF 18."); } void BaseGDL::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { throw GDLException("BaseGDL::AssignAt(...) called."); } void BaseGDL::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { throw GDLException("BaseGDL::AssignAt(..) called."); } void BaseGDL::AssignAt( BaseGDL* srcIn) { throw GDLException("BaseGDL::AssignAt(.) called."); } void BaseGDL::DecAt( ArrayIndexListT* ixList) { throw GDLException("BaseGDL::DecAt(...) called."); } void BaseGDL::IncAt( ArrayIndexListT* ixList) { throw GDLException("BaseGDL::IncAt(...) called."); } void BaseGDL::Dec() { throw GDLException("BaseGDL::Dec(...) called."); } void BaseGDL::Inc() { throw GDLException("BaseGDL::Inc(...) called."); } void BaseGDL::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { throw GDLException("BaseGDL::InsertAt( SizeT, ...) called."); } // formatting output functions SizeT BaseGDL::OFmtA( std::ostream* os, SizeT offset, SizeT num, int width, int code) {throw GDLException("BaseGDL::OFmtA(...) called.");} SizeT BaseGDL::OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code, const BaseGDL::IOMode oM) {throw GDLException("BaseGDL::OFmtF(...) called.");} SizeT BaseGDL::OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code, BaseGDL::IOMode oM) {throw GDLException("BaseGDL::OFmtI(...) called.");} SizeT BaseGDL::IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode) {throw GDLException("BaseGDL::IFmtCal(...) called.");} SizeT BaseGDL::OFmtCal( std::ostream* os, SizeT offs, SizeT num, int width, int minN, char *f, int code, BaseGDL::Cal_IOMode oM) {throw GDLException("BaseGDL::OFmtCal(...) called.");} SizeT BaseGDL::IFmtA( std::istream* is, SizeT offset, SizeT num, int width) {throw GDLException("BaseGDL::IFmtA(...) called.");} SizeT BaseGDL::IFmtF( std::istream* is, SizeT offs, SizeT num, int width) {throw GDLException("BaseGDL::IFmtF(...) called.");} SizeT BaseGDL::IFmtI( std::istream* is, SizeT offs, SizeT num, int width, BaseGDL::IOMode oM) {throw GDLException("BaseGDL::IFmtI(...) called.");} BaseGDL* BaseGDL::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { throw GDLException("BaseGDL::Convol(...) called."); } BaseGDL* BaseGDL::Smooth( DLong* width, int edgeMode, bool doNan, BaseGDL* missing) { throw GDLException("BaseGDL::Smooth(...) called."); } BaseGDL* BaseGDL::Rebin( const dimension& newDim, bool sample) { throw GDLException("BaseGDL::Rebin(...) called."); } #ifdef USE_PYTHON PyObject* BaseGDL::ToPython() {throw GDLException("BaseGDL::ToPython(...) called.");} #endif BaseGDL* BaseGDL::AndOpS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::AndOpInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 14."); } BaseGDL* BaseGDL::OrOpS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 13."); } BaseGDL* BaseGDL::OrOpInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 14."); } BaseGDL* BaseGDL::AddS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 15."); } BaseGDL* BaseGDL::AddInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 15."); } BaseGDL* BaseGDL::SubS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::SubInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::LtMarkS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 18."); } BaseGDL* BaseGDL::GtMarkS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 19."); } BaseGDL* BaseGDL::MultS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 19a."); } BaseGDL* BaseGDL::DivS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::DivInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::ModS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::ModInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::PowS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 16."); } BaseGDL* BaseGDL::PowInvS( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 17."); } BaseGDL* BaseGDL::NewIx( SizeT ix) { throw GDLException("Operation not defined for UNDEF 20."); } BaseGDL* BaseGDL::NewIx( BaseGDL* ix, bool strict) { throw GDLException("Operation not defined for UNDEF 21."); } BaseGDL* BaseGDL::NewIx( AllIxBaseT* ix, const dimension* dIn) { throw GDLException("Operation not defined for UNDEF 22."); } BaseGDL* BaseGDL::NewIxFrom( SizeT s) { throw GDLException("Operation not defined for UNDEF 23."); } BaseGDL* BaseGDL::NewIxFrom( SizeT s, SizeT e) { throw GDLException("Operation not defined for UNDEF 24."); } BaseGDL* BaseGDL::NewIxFromStride( SizeT s, SizeT stride) { throw GDLException("Operation not defined for UNDEF 25."); } BaseGDL* BaseGDL::NewIxFromStride( SizeT s, SizeT e, SizeT stride) { throw GDLException("Operation not defined for UNDEF 26."); } BaseGDL* BaseGDL::Log() { throw GDLException("Operation not defined for UNDEF 27a."); } BaseGDL* BaseGDL::LogThis() { throw GDLException("Operation not defined for UNDEF 27b."); } BaseGDL* BaseGDL::Log10() { throw GDLException("Operation not defined for UNDEF 27c."); } BaseGDL* BaseGDL::Log10This() { throw GDLException("Operation not defined for UNDEF 27d."); } void BaseGDL::AssignAtIx( RangeT ix, BaseGDL* srcIn) { throw GDLException("Operation not defined for UNDEF 28."); } RangeT BaseGDL::LoopIndex() const { throw GDLException("Operation not defined for UNDEF 29."); } DDouble BaseGDL::HashValue() const { throw GDLException("Operation not defined for UNDEF 29a."); } BaseGDL* BaseGDL::Rotate( DLong dir) { throw GDLException("Operation not defined for UNDEF 30."); } void BaseGDL::Reverse( DLong dim) { throw GDLException("Operation not defined for UNDEF 31."); } BaseGDL* BaseGDL::DupReverse( DLong dim) { throw GDLException("Operation not defined for UNDEF 32."); } BaseGDL* BaseGDL::AndOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 40.");} BaseGDL* BaseGDL::AndOpInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 41.");} BaseGDL* BaseGDL::OrOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 42.");} BaseGDL* BaseGDL::OrOpInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 43.");} BaseGDL* BaseGDL::XorOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 44.");} // BaseGDL* BaseGDL::EqOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 45.");} // BaseGDL* BaseGDL::NeOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 46.");} // BaseGDL* BaseGDL::LeOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 47.");} // BaseGDL* BaseGDL::GeOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 48.");} // BaseGDL* BaseGDL::LtOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 49.");} // BaseGDL* BaseGDL::GtOpNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 50.");} BaseGDL* BaseGDL::AddNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 51.");} // implemented BaseGDL* BaseGDL::AddInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 52.");} // implemented BaseGDL* BaseGDL::SubNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 53.");} BaseGDL* BaseGDL::SubInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 54.");} BaseGDL* BaseGDL::LtMarkNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 55.");} BaseGDL* BaseGDL::GtMarkNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 56.");} BaseGDL* BaseGDL::MultNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 57.");} // implemented BaseGDL* BaseGDL::DivNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 58.");} BaseGDL* BaseGDL::DivInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 59.");} BaseGDL* BaseGDL::ModNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 60.");} BaseGDL* BaseGDL::ModInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 61.");} BaseGDL* BaseGDL::PowNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 62.");} BaseGDL* BaseGDL::PowInvNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 63.");} BaseGDL* BaseGDL::PowIntNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 64.");} // implemented BaseGDL* BaseGDL::AndOpSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 65.");} BaseGDL* BaseGDL::AndOpInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 66.");} BaseGDL* BaseGDL::OrOpSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 67.");} BaseGDL* BaseGDL::OrOpInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 68.");} BaseGDL* BaseGDL::XorOpSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 69.");} BaseGDL* BaseGDL::AddSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 70.");} // implemented BaseGDL* BaseGDL::AddInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 71.");} // implemented BaseGDL* BaseGDL::SubSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 73.");} BaseGDL* BaseGDL::SubInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 74.");} BaseGDL* BaseGDL::LtMarkSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 75.");} BaseGDL* BaseGDL::GtMarkSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 76.");} BaseGDL* BaseGDL::MultSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 77.");} // implemented BaseGDL* BaseGDL::DivSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 78.");} BaseGDL* BaseGDL::DivInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 79.");} BaseGDL* BaseGDL::ModSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 80.");} BaseGDL* BaseGDL::ModInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 81.");} BaseGDL* BaseGDL::PowSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 82.");} BaseGDL* BaseGDL::PowInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for UNDEF 83.");} // --- SA: MemStats stuff SizeT MemStats::NumAlloc = 0; SizeT MemStats::NumFree = 0; SizeT MemStats::HighWater = 0; SizeT MemStats::Current = 0; #if !defined(HAVE_MALLINFO) # if (!defined(HAVE_MALLOC_ZONE_STATISTICS) || !defined(HAVE_MALLOC_MALLOC_H)) # if defined(HAVE_SBRK) char* MemStats::StartOfMemory = reinterpret_cast(::sbrk(0)); # endif # endif #endif // --- void GDLDelete( BaseGDL* toDelete) { if( toDelete != NullGDL::GetSingleInstance()) delete toDelete; } gdl-0.9.9/src/basegdl.hpp000066400000000000000000000607301340051421000151740ustar00rootroot00000000000000/*************************************************************************** basegdl.hpp - base class for all data types ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASEGDL_HPP_ #define BASEGDL_HPP_ #include "includefirst.hpp" //#include #if defined(__CYGWIN__) || defined(_WIN32) # include #else # include #endif #include #include "dimension.hpp" #include "gdlexception.hpp" #ifdef HAVE_MALLOC_H # include #endif #ifdef HAVE_MALLOC_MALLOC_H # include #endif #if !defined(HAVE_MALLINFO) # if (!defined(HAVE_MALLOC_ZONE_STATISTICS) || !defined(HAVE_MALLOC_MALLOC_H)) # if defined(HAVE_SBRK) # include # endif # endif #endif // GDL typecodes enum DType { // Object types (IDL type numbers) GDL_UNDEF=0, // 0 Undefined value, the default for new symbols GDL_BYTE=1, // 1 byte GDL_INT, // 2 Integer scalar GDL_LONG, // 3 long Integer scalar GDL_FLOAT, // 4 Real scalar GDL_DOUBLE, // 5 Double scalar GDL_COMPLEX, // 6 Complex scalar GDL_STRING, // 7 String GDL_STRUCT, // 8 Struct GDL_COMPLEXDBL, // 9 Complex double GDL_PTR, // 10 Pointer GDL_OBJ, // 11 Object reference GDL_UINT, // 12 unsigned int GDL_ULONG, // 13 unsigned long int GDL_LONG64, // 14 64 bit integer GDL_ULONG64 // 15 unsigned 64 bit integer // not yet implemented // , GDL_LONG128 // 128 bit integer // , GDL_ULONG128 // unsigned 128 bit integer // , GDL_LONGABI // arbitrary length int //, GDL_ULONGABI // arbitrary length unsigned int (pointless) // , GDL_LDOUBLE // long double precision float (80 or 128bit) // , GDL_COMPLEXLDBL // Complex long double // // , GDL_ARBITRARY // arbitrary precision float // , GDL_COMPLEXABI // Complex arbitrary // // , GDL_RATIONAL // arbitrary length rational // , GDL_COMPLEXRAT // Complex arbitrary length rational }; // order of conversion precedence if two types are the same, // the first type is used // used also by ArrayIndexT const int DTypeOrder[]={ -1, //GDL_UNDEF 2, //GDL_BYTE 3, //GDL_INT 4, //GDL_LONG, 8, //GDL_FLOAT, 9, //GDL_DOUBLE, 20, //GDL_COMPLEX, 1, //GDL_STRING, 101, //GDL_STRUCT, 21, //GDL_COMPLEXDBL, 102, //GDL_PTR, 103, //GDL_OBJ, // must be highest number (see AdjustTypes... functions) 3, //GDL_UINT, 4, //GDL_ULONG, 5, //GDL_LONG64, 5 //GDL_ULONG64 // not yet implemented ,6 // , GDL_LONG128 // 128 bit integer ,6 // , GDL_ULONG128 // unsigned 128 bit integer // ,7 // , GDL_LONGAB // arbitrary length int // ,7 // , GDL_ULONGAR // arbitrary length unsigned int (pointless) // ,10 // , GDL_LDOUBLE // quad precision float (80 or 128bit) ,22 // , GDL_COMPLEXLDBL // Complex quad // ,11 // , GDL_ARBITRARY // arbitrary precision float ,23 // , GDL_COMPLEXAR // Complex arbitrary // ,12 // , GDL_RATIONAL // arbitrary length rational ,24 // , GDL_COMPLEXRAT // Complex arbitrary length rational }; inline DType PromoteMatrixOperands( DType aTy, DType bTy) { DType maxTy=(DTypeOrder[aTy] >= DTypeOrder[bTy])? aTy: bTy; if( maxTy == GDL_BYTE || maxTy == GDL_INT) return GDL_LONG; else if( maxTy == GDL_UINT) return GDL_ULONG; return maxTy; } inline DType PromoteComplexOperand( DType aTy, DType bTy) { if((aTy == GDL_COMPLEX && bTy == GDL_DOUBLE) || (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE) ) return GDL_COMPLEXDBL; return GDL_UNDEF; } namespace gdl_type_lookup { const bool IsConvertableType[]={ false, //GDL_UNDEF true, //GDL_BYTE true, //GDL_INT true, //GDL_LONG, true, //GDL_FLOAT, true, //GDL_DOUBLE, true, //GDL_COMPLEX, true, //GDL_STRING, false, //GDL_STRUCT, true, //GDL_COMPLEXDBL, false, //GDL_PTR, false, //GDL_OBJ, true, //GDL_UINT, true, //GDL_ULONG, true, //GDL_LONG64, true //GDL_ULONG64 }; const bool IsNumericType[]={ false, //GDL_UNDEF true, //GDL_BYTE true, //GDL_INT true, //GDL_LONG, true, //GDL_FLOAT, true, //GDL_DOUBLE, true, //GDL_COMPLEX, false, //GDL_STRING, false, //GDL_STRUCT, true, //GDL_COMPLEXDBL, false, //GDL_PTR, false, //GDL_OBJ, true, //GDL_UINT, true, //GDL_ULONG, true, //GDL_LONG64, true //GDL_ULONG64 }; const bool IsIntType[]={ false, //GDL_UNDEF true, //GDL_BYTE true, //GDL_INT true, //GDL_LONG, false, //GDL_FLOAT, false, //GDL_DOUBLE, false, //GDL_COMPLEX, false, //GDL_STRING, false, //GDL_STRUCT, false, //GDL_COMPLEXDBL, false, //GDL_PTR, false, //GDL_OBJ, true, //GDL_UINT, true, //GDL_ULONG, true, //GDL_LONG64, true //GDL_ULONG64 }; const bool IsRealType[]={ false, //GDL_UNDEF true, //GDL_BYTE true, //GDL_INT true, //GDL_LONG, true, //GDL_FLOAT, true, //GDL_DOUBLE, false, //GDL_COMPLEX, false, //GDL_STRING, false, //GDL_STRUCT, false, //GDL_COMPLEXDBL, false, //GDL_PTR, false, //GDL_OBJ, true, //GDL_UINT, true, //GDL_ULONG, true, //GDL_LONG64, true //GDL_ULONG64 }; const bool IsNonPODType[]={ false, //GDL_UNDEF false, //GDL_BYTE false, //GDL_INT false, //GDL_LONG, false, //GDL_FLOAT, false, //GDL_DOUBLE, true, //GDL_COMPLEX, true, //GDL_STRING, true, //GDL_STRUCT, true, //GDL_COMPLEXDBL, true, //GDL_PTR, nonPOD due to reference counting true, //GDL_OBJ, nonPOD due to reference counting false, //GDL_UINT, false, //GDL_ULONG, false, //GDL_LONG64, false //GDL_ULONG64 }; } //namespace gdl_type_lookup inline bool NonPODType( DType t) { return gdl_type_lookup::IsNonPODType[ t]; // return (t == GDL_COMPLEX) || (t == GDL_COMPLEXDBL) || (t == GDL_STRING) || (t == GDL_STRUCT); } inline bool IntType( DType t) { return gdl_type_lookup::IsIntType[ t]; // int o = DTypeOrder[ t]; // return (o >= 2 && o <= 5); } inline bool FloatType( DType t) { return (t == GDL_FLOAT || t == GDL_DOUBLE); } inline bool RealType( DType t) // Float or Int { return gdl_type_lookup::IsRealType[ t]; // int o = DTypeOrder[ t]; // return (o >= 2 && o <= 9); } inline bool ComplexType( DType t) { return (t == GDL_COMPLEX || t == GDL_COMPLEXDBL); } inline bool NumericType( DType t) // Float or Int or Complex { return gdl_type_lookup::IsNumericType[ t]; // int o = DTypeOrder[ t]; // return (o >= 2 && o <= 11); } inline bool ConvertableType( DType t) // everything except Struct, Ptr, Obj { return gdl_type_lookup::IsConvertableType[ t]; // int o = DTypeOrder[ t]; // return (o >= 1 && o <= 11); } class BaseGDL; class ArrayIndexListT; //class ExprListT; struct SpDULong; template class Data_; struct ForLoopInfoT; void breakpoint(); // --- SA: MemStats stuff class MemStats { private: // SizeT has architecture-dependant size (32/64 bit) static SizeT NumAlloc, NumFree, HighWater, Current; #if !defined(HAVE_MALLINFO) # if (!defined(HAVE_MALLOC_ZONE_STATISTICS) || !defined(HAVE_MALLOC_MALLOC_H)) # if defined(HAVE_SBRK) static char* StartOfMemory; # endif # endif #endif public: ~MemStats() { NumFree++; #if defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) // - the sbrk(0) does not give any meaningfull info for HIGHWATER // - using mallinfo() frequently gives a large performace loss UpdateCurrent(); // updates the highwater mark #endif } MemStats() { NumAlloc++; } static SizeT GetNumAlloc() { return NumAlloc; } static SizeT GetNumFree() { return NumFree; } static SizeT GetCurrent() { UpdateCurrent(); // updates the highwater mark return Current; } // returns and resets the highwater mark (called from HELP and MEMORY()) static SizeT GetHighWater() { // Current can be safely used as a temporary variable here Current = HighWater; HighWater = 0; return Current; } // returns current memory usage and updates the highwater mark static void UpdateCurrent() { // --------------------------------------------------------------------- // based on the codes from: // - the LLVM project (lib/System/Unix/Process.inc) see http://llvm.org/ // - the Squid cache project (src/tools.cc) see http://squid-cache.org/ // TODO (TOCHECK): Squid considers also gnumalloc.h - ? #if defined(HAVE_MALLINFO) // Linux case for example static struct mallinfo mi; mi = mallinfo(); // printf("Total non-mmapped bytes (arena): %d\n", mi.arena); // printf("# of free chunks (ordblks): %d\n", mi.ordblks); // printf("# of free fastbin blocks (smblks): %d\n", mi.smblks); // printf("# of mapped regions (hblks): %d\n", mi.hblks); // printf("Bytes in mapped regions (hblkhd): %d\n", mi.hblkhd); // printf("Max. total allocated space (usmblks): %d\n", mi.usmblks); // printf("Free bytes held in fastbins (fsmblks): %d\n", mi.fsmblks); // printf("Total allocated space (uordblks): %d\n", mi.uordblks); // printf("Total free space (fordblks): %d\n", mi.fordblks); // printf("Topmost releasable block (keepcost): %d\n", mi.keepcost); Current = mi.arena+mi.hblkhd; //was mi.uordblks; #elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) // Mac OS X case for example static malloc_statistics_t stats; malloc_zone_statistics(malloc_default_zone(), &stats); Current = stats.size_in_use; #elif defined(HAVE_SBRK) // Open Solaris case for example static char* EndOfMemory; EndOfMemory = (char*)sbrk(0); Current = EndOfMemory - StartOfMemory; #else /* * // a draft of Windows version (for neccesarry includes consult the LLVM source): * _HEAPINFO hinfo; * hinfo._pentry = NULL; * Current = 0; * while (_heapwalk(&hinfo) == _HEAPOK) Current += hinfo._size; */ // Warning("Cannot get dynamic memory information on this platform (FIXME)"); #endif HighWater = std::max(HighWater, Current); } }; // --- class AllIxBaseT; class BaseGDL: private MemStats { public: static DInterpreter* interpreter; protected: dimension dim; public: // type of initalization enum InitType { ZERO=0, NOZERO, INDGEN, INIT, NOALLOC }; enum Convert2Mode { CONVERT=1, COPY=2, COPY_BYTE_AS_INT=(4|2), // for GDL_STRING function THROWIOERROR=8, // for DStringGDL::Convert2() COPY_THROWIOERROR=(8|2), // for DStringGDL::Convert2() CONVERT_THROWIOERROR=(8|1) // for DStringGDL::Convert2() (SA: used in NEWTON()) }; enum IOMode { FIXED=0, SCIENTIFIC, BIN=2, OCT=8, DEC=10, HEX=16, HEXL, // lower case characters AUTO }; enum Cal_IOMode { WRITE=-2, COMPUTE=-1, DEFAULT=0, CMOA, CMoA, CmoA, CMOI, CDI, CYI, CHI, ChI, CMI, CSI, CSF, CDWA, CDwA, CdwA, CAPA, CApA, CapA, STRING }; // FIRST VIRTUAL FUNCTION'S GDL_OBJ FILE CONTAINS ALSO THE VTABLE // therefore it must be defined non-inline (g++) virtual ~BaseGDL(); // defined in basegdl.cpp BaseGDL();//: dim() {} explicit BaseGDL(const dimension& dim_);//: dim(dim_) {} // provide access to dim member inline const dimension& Dim() const { return dim;} inline SizeT Dim(SizeT d) const { return dim[d];} // inline SizeT* Dim0Address() { return dim.Dim0Address();} inline SizeT Stride(SizeT d) const { return dim.Stride(d);} inline void Purge() { dim.Purge();} inline SizeT Rank() const { return dim.Rank();} inline SizeT EquivalentRank() const { return dim.EquivalentRank();} inline void SetDim(const dimension& d) { dim=d;} inline void MakeArrayFromScalar() { dim.MakeArrayFromScalar();} friend std::istream& operator>>(std::istream& i, BaseGDL& data_) { throw GDLException("Variable is of type UNDEF."); return i; } // private: virtual BaseGDL& operator=(const BaseGDL& right); // public: virtual void InitFrom(const BaseGDL& right); // for structs // virtual functions virtual bool IsAssoc() const; virtual BaseGDL* AssocVar( int, SizeT); virtual SizeT N_Elements() const; // number of elements virtual SizeT Size() const; // size (= N_Elements, but 0 for BaseGDL) virtual SizeT NBytes() const; // total bytes of data virtual SizeT ToTransfer() const; // elements to transfer virtual SizeT Sizeof() const; // size of scalar data virtual int HashCompare( BaseGDL* p2) const; virtual BaseGDL* Transpose( DUInt* perm); virtual BaseGDL* Rotate( DLong dir); virtual void Reverse( DLong dim); virtual BaseGDL* DupReverse( DLong dim); virtual void MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start = 0, SizeT stop = 0, SizeT step = 1, DLong valIx = -1, bool useAbs = false); virtual void Clear(); virtual void Construct(); virtual void ConstructTo0(); virtual void Destruct(); virtual std::ostream& Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs); virtual std::istream& Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs); virtual std::ostream& ToStream(std::ostream& o, SizeT width = 0, SizeT* actPosPtr = NULL); virtual std::istream& FromStream(std::istream& i); virtual bool Greater(SizeT i1, SizeT i2) const; // comp 2 elements virtual bool Equal(SizeT i1, SizeT i2) const; // comp 2 elements virtual BaseGDL* CShift( DLong d) const; // circular shift virtual BaseGDL* CShift( DLong d[MAXRANK]) const; // circular shift multi dim virtual bool OutOfRangeOfInt() const; virtual bool Scalar() const; virtual bool StrictScalar() const; virtual DType Type() const; virtual const std::string& TypeStr() const; virtual bool EqType( const BaseGDL*) const; virtual void* DataAddr();// SizeT elem=0); virtual BaseGDL* New( const dimension& dim_, InitType noZero=ZERO) const; virtual BaseGDL* NewResult() const; virtual BaseGDL* Dup() const; // virtual BaseGDL* Dup( char*) const; virtual BaseGDL* Convert2( DType destTy, Convert2Mode mode=CONVERT); virtual BaseGDL* GetTag() const; virtual BaseGDL* GetInstance() const; virtual BaseGDL* GetEmptyInstance() const; virtual BaseGDL* SetBuffer( const void* b); virtual void SetBufferSize( SizeT s); virtual int Scalar2Index(SizeT& ret) const; virtual int Scalar2RangeT(RangeT& ret) const; virtual SizeT GetAsIndex( SizeT i) const; virtual SizeT GetAsIndexStrict( SizeT i) const; virtual RangeT LoopIndex() const; virtual DDouble HashValue() const; virtual bool True(); virtual bool False(); virtual bool LogTrue(); virtual bool LogTrue( SizeT ix); virtual void Where(DLong* &ret, SizeT &passed_count, bool comp, DLong* &comp_ret) ; virtual void Where(DLong64* &ret, SizeT &passed_count, bool comp, DLong64* &comp_ret) ; virtual BaseGDL* LogNeg(); virtual int Sgn(); // -1,0,1 virtual bool Equal( BaseGDL*) const; virtual bool EqualNoDelete( const BaseGDL*) const; virtual bool ArrayEqual( BaseGDL*); virtual bool ArrayNeverEqual( BaseGDL*); // for statement compliance (int types , float types scalar only) virtual void ForCheck( BaseGDL**, BaseGDL** = NULL); virtual bool ForCondUp( BaseGDL*); virtual bool ForCondDown( BaseGDL*); virtual bool ForAddCondUp( BaseGDL* loopInfo); // virtual bool ForAddCondUp( ForLoopInfoT& loopInfo); // virtual bool ForAddCondDown( ForLoopInfoT& loopInfo); // virtual bool ForCondUpDown( BaseGDL*); virtual void ForAdd( BaseGDL* add=NULL); virtual BaseGDL* CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank); virtual BaseGDL* Index( ArrayIndexListT* ixList); // virtual BaseGDL* Abs() const; // return a new type of itself virtual BaseGDL* NewIx( SizeT ix); virtual BaseGDL* NewIx( BaseGDL* ix, bool strict); virtual BaseGDL* NewIx( AllIxBaseT* ix, const dimension* dIn); virtual BaseGDL* NewIxFrom( SizeT s); virtual BaseGDL* NewIxFrom( SizeT s, SizeT e); virtual BaseGDL* NewIxFromStride( SizeT s, SizeT stride); virtual BaseGDL* NewIxFromStride( SizeT s, SizeT e, SizeT stride); // library functions virtual BaseGDL* Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid); virtual BaseGDL* Smooth( DLong* width, int edgeMode, bool doNan, BaseGDL* missing); virtual BaseGDL* Rebin( const dimension& newDim, bool sample); // for STRUCT_ASSIGN virtual void Assign( BaseGDL* src, SizeT nEl); virtual BaseGDL* Log(); virtual BaseGDL* LogThis(); virtual BaseGDL* Log10(); virtual BaseGDL* Log10This(); // defined in basic_op.cpp // used in r_expr virtual BaseGDL* UMinus(); virtual BaseGDL* NotOp(); virtual BaseGDL* AndOp( BaseGDL* r); virtual BaseGDL* AndOpInv( BaseGDL* r); virtual BaseGDL* OrOp( BaseGDL* r); virtual BaseGDL* OrOpInv( BaseGDL* r); virtual BaseGDL* XorOp( BaseGDL* r); virtual BaseGDL* EqOp( BaseGDL* r); virtual BaseGDL* NeOp( BaseGDL* r); virtual BaseGDL* LeOp( BaseGDL* r); virtual BaseGDL* GeOp( BaseGDL* r); virtual BaseGDL* LtOp( BaseGDL* r); virtual BaseGDL* GtOp( BaseGDL* r); virtual BaseGDL* Add( BaseGDL* r); virtual BaseGDL* AddInv( BaseGDL* r); virtual BaseGDL* Sub( BaseGDL* r); virtual BaseGDL* SubInv( BaseGDL* r); virtual BaseGDL* LtMark( BaseGDL* r); virtual BaseGDL* GtMark( BaseGDL* r); virtual BaseGDL* Mult( BaseGDL* r); virtual BaseGDL* Div( BaseGDL* r); virtual BaseGDL* DivInv( BaseGDL* r); virtual BaseGDL* Mod( BaseGDL* r); virtual BaseGDL* ModInv( BaseGDL* r); virtual BaseGDL* Pow( BaseGDL* r); virtual BaseGDL* PowInv( BaseGDL* r); virtual BaseGDL* PowInt( BaseGDL* r); virtual BaseGDL* AndOpS( BaseGDL* r); virtual BaseGDL* AndOpInvS( BaseGDL* r); virtual BaseGDL* OrOpS( BaseGDL* r); virtual BaseGDL* OrOpInvS( BaseGDL* r); virtual BaseGDL* XorOpS( BaseGDL* r); virtual BaseGDL* AddS( BaseGDL* r); virtual BaseGDL* AddInvS( BaseGDL* r); virtual BaseGDL* SubS( BaseGDL* r); virtual BaseGDL* SubInvS( BaseGDL* r); virtual BaseGDL* LtMarkS( BaseGDL* r); virtual BaseGDL* GtMarkS( BaseGDL* r); virtual BaseGDL* MultS( BaseGDL* r); virtual BaseGDL* DivS( BaseGDL* r); virtual BaseGDL* DivInvS( BaseGDL* r); virtual BaseGDL* ModS( BaseGDL* r); virtual BaseGDL* ModInvS( BaseGDL* r); virtual BaseGDL* PowS( BaseGDL* r); virtual BaseGDL* PowInvS( BaseGDL* r); // the New functions // defined in basic_op_new.cpp // results go into a new DataT virtual BaseGDL* AndOpNew( BaseGDL* r); virtual BaseGDL* AndOpInvNew( BaseGDL* r); virtual BaseGDL* OrOpNew( BaseGDL* r); virtual BaseGDL* OrOpInvNew( BaseGDL* r); virtual BaseGDL* XorOpNew( BaseGDL* r); // virtual BaseGDL* EqOpNew( BaseGDL* r); // virtual BaseGDL* NeOpNew( BaseGDL* r); // virtual BaseGDL* LeOpNew( BaseGDL* r); // virtual BaseGDL* GeOpNew( BaseGDL* r); // virtual BaseGDL* LtOpNew( BaseGDL* r); // virtual BaseGDL* GtOpNew( BaseGDL* r); virtual BaseGDL* AddNew( BaseGDL* r); // implemented virtual BaseGDL* AddInvNew( BaseGDL* r); // implemented virtual BaseGDL* SubNew( BaseGDL* r); virtual BaseGDL* SubInvNew( BaseGDL* r); virtual BaseGDL* LtMarkNew( BaseGDL* r); virtual BaseGDL* GtMarkNew( BaseGDL* r); virtual BaseGDL* MultNew( BaseGDL* r); // implemented virtual BaseGDL* DivNew( BaseGDL* r); virtual BaseGDL* DivInvNew( BaseGDL* r); virtual BaseGDL* ModNew( BaseGDL* r); virtual BaseGDL* ModInvNew( BaseGDL* r); virtual BaseGDL* PowNew( BaseGDL* r); virtual BaseGDL* PowInvNew( BaseGDL* r); virtual BaseGDL* PowIntNew( BaseGDL* r); // implemented virtual BaseGDL* AndOpSNew( BaseGDL* r); virtual BaseGDL* AndOpInvSNew( BaseGDL* r); virtual BaseGDL* OrOpSNew( BaseGDL* r); virtual BaseGDL* OrOpInvSNew( BaseGDL* r); virtual BaseGDL* XorOpSNew( BaseGDL* r); virtual BaseGDL* AddSNew( BaseGDL* r); // implemented virtual BaseGDL* AddInvSNew( BaseGDL* r); // implemented virtual BaseGDL* SubSNew( BaseGDL* r); virtual BaseGDL* SubInvSNew( BaseGDL* r); virtual BaseGDL* LtMarkSNew( BaseGDL* r); virtual BaseGDL* GtMarkSNew( BaseGDL* r); virtual BaseGDL* MultSNew( BaseGDL* r); // implemented virtual BaseGDL* DivSNew( BaseGDL* r); virtual BaseGDL* DivInvSNew( BaseGDL* r); virtual BaseGDL* ModSNew( BaseGDL* r); virtual BaseGDL* ModInvSNew( BaseGDL* r); virtual BaseGDL* PowSNew( BaseGDL* r); virtual BaseGDL* PowInvSNew( BaseGDL* r); // virtual BaseGDL* PowInvNew( BaseGDL* r); virtual BaseGDL* MatrixOp( BaseGDL* r, bool atranspose=false, bool btranspose=false); virtual void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset); virtual void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList); virtual void AssignAt( BaseGDL* srcIn); virtual void AssignAtIx( RangeT ix, BaseGDL* srcIn); virtual void DecAt( ArrayIndexListT* ixList); virtual void IncAt( ArrayIndexListT* ixList); virtual void Dec(); virtual void Inc(); virtual void InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList); // virtual formatting output functions virtual SizeT OFmtA( std::ostream* os, SizeT offset, SizeT num, int width, int code); virtual SizeT OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code=0, const BaseGDL::IOMode oM = FIXED); virtual SizeT OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code=0, BaseGDL::IOMode oM = DEC); virtual SizeT OFmtCal( std::ostream* os, SizeT offs, SizeT num, int width, int minN, char *fill, int code=0, BaseGDL::Cal_IOMode oM = DEFAULT); virtual SizeT IFmtA( std::istream* is, SizeT offset, SizeT num, int width); virtual SizeT IFmtF( std::istream* is, SizeT offs, SizeT num, int width); virtual SizeT IFmtI( std::istream* is, SizeT offs, SizeT num, int width, BaseGDL::IOMode oM = DEC); virtual SizeT IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode); #if defined(USE_PYTHON) || defined(PYTHON_MODULE) virtual PyObject* ToPython(); #endif virtual bool Test2() {return false;} }; // ExprListT deletes all members upon own destruction // old slow version (up to GDL 0.9.1): // class ExprListT: public std::vector // { // public: // ExprListT() // { // this->reserve(ExprListDefaultLength); // } // ~ExprListT() // { // for( ExprListT::iterator i=this->begin(); i!=this->end(); ++i) // delete *i; // } // }; struct ForLoopInfoT { BaseGDL* endLoopVar; // the source for foreach as well BaseGDL* loopStepVar; DLong foreachIx; // bool isHash; // only used in FOREACH_INDEXNode::Run() and FOREACH_INDEX_LOOPNode::Run() ForLoopInfoT() : endLoopVar(NULL) , loopStepVar(NULL) , foreachIx(-1) {} ~ForLoopInfoT() { delete endLoopVar; delete loopStepVar; } void Init() { endLoopVar = NULL; loopStepVar = NULL; foreachIx = -1; } void Clear() { delete endLoopVar; delete loopStepVar; } void ClearInit() { delete endLoopVar; endLoopVar = NULL; delete loopStepVar; loopStepVar = NULL; } }; // before NullGDL instance must not be deleted, now this is fine (overloaded operators new and delete) // inline void GDLDelete( BaseGDL* toDelete) { delete toDelete;} void GDLDelete( BaseGDL* toDelete); #endif gdl-0.9.9/src/basic_fun.cpp000066400000000000000000010564601340051421000155250ustar00rootroot00000000000000/*************************************************************************** basic_fun.cpp - basic GDL library function ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens (exceptions see below) email : m_schellens@users.sf.net strtok_fun, getenv_fun, tag_names_fun, stregex_fun: (C) 2004 by Peter Messmer 20150506 Jacco A. de Zwart, National Institutes of Health, Bethesda, MD, USA Changed behavior of COMPLEX() and DCOMPLEX() called with three arguments, aka where type casting is the expected behavoir. 2017 September Greg Jung mods to unbug pointer, object treatments. Also: Updated with new Where(), cosmetics #ifndef _WIN32 replaces #if !defined(_WIN32) || defined(__CYGWIN__) Mods to array_equal() and array_never_equal (new) routine_filepath moved to here. command_line_args uses strings instead of char* 2017 July gilles-duvert New version of Where() twice as fast as previous ***************************************************************************/ // AC 2018-feb /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" // get_kbrd patch // http://sourceforge.net/forum/forum.php?thread_id=3292183&forum_id=338691 #ifndef _WIN32 #include #include #endif // used to defined GDL_TMPDIR: may have trouble on MSwin, help welcome #ifndef _WIN32 #include #endif #include #include #include //#include #include // stregex #ifdef __APPLE__ # include # define environ (*_NSGetEnviron()) #endif #if defined(__FreeBSD__) || defined(__sun__) || defined(__OpenBSD__) extern "C" char **environ; #endif #include "nullgdl.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" #include "basic_pro.hpp" #include "terminfo.hpp" #include "typedefs.hpp" #include "base64.hpp" #include "objects.hpp" #ifdef HAVE_LOCALE_H # include #endif /* max regexp error message length */ #define MAX_REGEXPERR_LENGTH 80 #ifdef _MSC_VER #if _MSC_VER < 1800 #define std::isfinite _finite #define isnan _isnan #define round(f) floor(f+0.5) #endif #define std::isfinite(x) std::isfinite((double) x) int strncasecmp(const char *s1, const char *s2, size_t n) { if (n == 0) return 0; while (n-- != 0 && tolower(*s1) == tolower(*s2)) { if (n == 0 || *s1 == '\0' || *s2 == '\0') break; s1++; s2++; } return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); } #endif #ifndef _WIN32 #include #endif static DStructGDL* GetObjStruct( BaseGDL* Objptr, EnvT* e) { if( Objptr == 0 || Objptr->Type() != GDL_OBJ) e->Throw( "Objptr not of type OBJECT. Please report."); if( !Objptr->Scalar()) e->Throw( "Objptr must be a scalar. Please report."); DObjGDL* Object = static_cast( Objptr); DObj ID = (*Object)[0]; try { return BaseGDL::interpreter->GetObjHeap( ID); } catch( GDLInterpreter::HeapException& hEx) { e->Throw( "Object ID <"+i2s(ID)+"> not found."); } } static bool trace_me(false); namespace lib { bool trace_arg(); bool gdlarg_present(const char* s); SizeT HASH_count( DStructGDL* oStructGDL); SizeT LIST_count( DStructGDL* oStructGDL); // for use in COMMAND_LINE_ARGS() std::vector command_line_args; // using namespace std; using std::isinf; using std::isnan; using namespace antlr; DULong SHA256Constants[] = { 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 ,0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 ,0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da ,0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 ,0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 ,0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070 ,0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 ,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}; DULong SHAH0[] = { 0x6a09e667 // H0_0 ,0xbb67ae85 ,0x3c6ef372 ,0xa54ff53a ,0x510e527f ,0x9b05688c ,0x1f83d9ab ,0x5be0cd19 // H0_7 }; // assumes all parameters from pOffs till end are dim void arr( EnvT* e, dimension& dim, SizeT pOffs=0) { int nParam=e->NParam()-pOffs; if( nParam <= 0) e->Throw( "Incorrect number of arguments."); const string BadDims="Array dimensions must be greater than 0."; if( nParam == 1 ) { BaseGDL* par = e->GetParDefined( pOffs); SizeT newDim; int ret = par->Scalar2Index( newDim); if (ret < 0) throw GDLException(BadDims); if( ret > 0) { // single argument if (newDim < 1) throw GDLException(BadDims); dim << newDim; return; } if( ret == 0) { // array argument DLongGDL* ind = static_cast(par->Convert2(GDL_LONG, BaseGDL::COPY)); Guard ind_guard( ind); //e->Guard( ind); for(SizeT i =0; i < par->N_Elements(); ++i){ if ((*ind)[i] < 1) throw GDLException(BadDims); dim << (*ind)[i]; } return; } e->Throw( "arr: should never arrive here."); return; } // max number checked in interpreter SizeT endIx=nParam+pOffs; for( SizeT i=pOffs; iGetParDefined( i); SizeT newDim; int ret=par->Scalar2Index( newDim); if( ret < 1 || newDim == 0) throw GDLException(BadDims); dim << newDim; } } BaseGDL* bytarr( EnvT* e) { dimension dim; arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DByteGDL(dim, BaseGDL::NOZERO); return new DByteGDL(dim); } BaseGDL* intarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DIntGDL(dim, BaseGDL::NOZERO); return new DIntGDL(dim); // } // catch( GDLException& ex) // { // e->Throw( "INTARR: "+ex.getMessage()); // } } BaseGDL* uintarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DUIntGDL(dim, BaseGDL::NOZERO); return new DUIntGDL(dim); // } // catch( GDLException& ex) // { // e->Throw( "UINTARR: "+ex.getMessage()); // } } BaseGDL* lonarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DLongGDL(dim, BaseGDL::NOZERO); return new DLongGDL(dim); /* } catch( GDLException& ex) { e->Throw( "LONARR: "+ex.getMessage()); }*/ } BaseGDL* ulonarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DULongGDL(dim, BaseGDL::NOZERO); return new DULongGDL(dim); /* } catch( GDLException& ex) { e->Throw( "ULONARR: "+ex.getMessage()); } */ } BaseGDL* lon64arr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DLong64GDL(dim, BaseGDL::NOZERO); return new DLong64GDL(dim); /* } catch( GDLException& ex) { e->Throw( "LON64ARR: "+ex.getMessage()); }*/ } BaseGDL* ulon64arr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DULong64GDL(dim, BaseGDL::NOZERO); return new DULong64GDL(dim); /* } catch( GDLException& ex) { e->Throw( "ULON64ARR: "+ex.getMessage()); }*/ } BaseGDL* fltarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DFloatGDL(dim, BaseGDL::NOZERO); return new DFloatGDL(dim); /* } catch( GDLException& ex) { e->Throw( "FLTARR: "+ex.getMessage()); } */} BaseGDL* dblarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DDoubleGDL(dim, BaseGDL::NOZERO); return new DDoubleGDL(dim); /* } catch( GDLException& ex) { e->Throw( "DBLARR: "+ex.getMessage()); }*/ } BaseGDL* strarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) e->Throw( "Keyword parameters not allowed in call."); return new DStringGDL(dim); /* } catch( GDLException& ex) { e->Throw( "STRARR: "+ex.getMessage()); } */ } BaseGDL* complexarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); if( e->KeywordSet(0)) return new DComplexGDL(dim, BaseGDL::NOZERO); return new DComplexGDL(dim); /*} catch( GDLException& ex) { e->Throw( "COMPLEXARR: "+ex.getMessage()); } */ } BaseGDL* dcomplexarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) if( e->KeywordSet(0)) return new DComplexDblGDL(dim, BaseGDL::NOZERO); return new DComplexDblGDL(dim); /* } catch( GDLException& ex) { e->Throw( "DCOMPLEXARR: "+ex.getMessage()); } */ } BaseGDL* ptrarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); DPtrGDL* ret; // if( e->KeywordSet(0)) // ret= new DPtrGDL(dim);//, BaseGDL::NOZERO); // else // if( e->KeywordSet(1)) // ret= new DPtrGDL(dim, BaseGDL::NOZERO); // else // return new DPtrGDL(dim); if( !e->KeywordSet(1)) return new DPtrGDL(dim); ret= new DPtrGDL(dim, BaseGDL::NOZERO); SizeT nEl=ret->N_Elements(); SizeT sIx=e->NewHeap(nEl); // not a thread pool function #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; iThrow( "PTRARR: "+ex.getMessage()); }*/ } BaseGDL* objarr( EnvT* e) { dimension dim; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); // reference counting if( e->KeywordSet(0)) return new DObjGDL(dim, BaseGDL::NOZERO); return new DObjGDL(dim); /* } catch( GDLException& ex) { e->Throw( "OBJARR: "+ex.getMessage()); } */ } BaseGDL* ptr_new( EnvT* e) { int nParam=e->NParam(); if( nParam > 0) { BaseGDL* p= e->GetPar( 0); // new ptr from undefined variable is allowed as well // this case was discovered by chance by Leva, July 16, 2014 // p=ptr_new(), p=ptr_new(!null), p=ptr_new(undef_var) should work if ((p == NULL) || (p->Type() == GDL_UNDEF)) { DPtr heapID= e->NewHeap(); return new DPtrGDL( heapID); } static int no_copyIx=e->KeywordIx("NO_COPY"); if (e->KeywordSet(no_copyIx)) // NO_COPY { BaseGDL** p= &e->GetPar( 0); // if( *p == NULL) // e->Throw( "Parameter undefined: "+ // e->GetParString(0)); DPtr heapID= e->NewHeap( 1, *p); *p=NULL; return new DPtrGDL( heapID); } else { BaseGDL* p= e->GetParDefined( 0); DPtr heapID= e->NewHeap( 1, p->Dup()); return new DPtrGDL( heapID); } } else { if( e->KeywordSet(1)) // ALLOCATE_HEAP { DPtr heapID= e->NewHeap(); return new DPtrGDL( heapID); } else { return new DPtrGDL( 0); // null ptr } } } BaseGDL* ptr_valid( EnvT* e) { int nParam=e->NParam(); static int CASTIx = e->KeywordIx("CAST"); static int COUNTIx = e->KeywordIx("COUNT"); static int GET_HEAP_IDENTIFIERIx = e->KeywordIx("GET_HEAP_IDENTIFIER"); if( e->KeywordPresent( COUNTIx)) { e->SetKW( COUNTIx, new DLongGDL( e->Interpreter()->HeapSize())); } if( nParam == 0) { return e->Interpreter()->GetAllHeap(); } BaseGDL* p = e->GetPar( 0); if( p == NULL) { return new DByteGDL( 0); } DType pType = p->Type(); bool isscalar = p->StrictScalar(); DLongGDL* pL; Guard pL_guard; GDLInterpreter* interpreter = e->Interpreter(); if( pType == GDL_PTR){ DPtrGDL* pPtr = static_cast( p); pL = new DLongGDL( p->Dim()); for( SizeT i=0; i < pL->N_Elements(); ++i) (*pL) [i] = (*pPtr)[i]; if( e->KeywordSet( GET_HEAP_IDENTIFIERIx)) { if(isscalar) return new DLongGDL( (*pL)[0] ); else return pL; } pL_guard.Init( pL); } else { // pType==GDL_PTR pL = static_cast(p->Convert2(GDL_LONG,BaseGDL::COPY)); pL_guard.Init( pL); if( e->KeywordSet( CASTIx)) { if(isscalar) { DLong p0 = (*pL)[0]; if( interpreter->PtrValid( p0 )) { interpreter->IncRef( p0); return new DPtrGDL( p0); } else return new DPtrGDL( 0); } DPtrGDL* ret = new DPtrGDL( pL->Dim()); for( SizeT i=0; i < pL->N_Elements(); ++i) if( interpreter->PtrValid( (*pL)[ i])) { interpreter->IncRef((*pL)[ i]); (*ret)[ i] = (*pL)[ i]; } return ret; } } DByteGDL* ret = new DByteGDL( pL->Dim()); for( SizeT i=0; i < pL->N_Elements(); ++i) { if( interpreter->PtrValid( (*pL)[ i])) (*ret)[ i] = 1; } if(isscalar) return new DByteGDL( (*ret)[0] ); else return ret; } // // 2018 May 29 G. Jung: Note there is an inordinate separation of scalar and non-scalar treament. // This was my last line of attempt to quash an error, due to an assert // in gdlarray.cpp (line 210) which obj_valid() triggered in Travis tests. // I am now convinced that this error is due to the incorrect hack in GDL // that, for "SizeT nEl = p->N_Elements();" returns instead the count() of the list // so in fact, a list is not a true object. // Merge "legacy_list" branch to remedy this. // BaseGDL* obj_valid( EnvT* e) { int nParam=e->NParam(); static int CASTIx = e->KeywordIx("CAST"); static int COUNTIx = e->KeywordIx("COUNT"); static int GET_HEAP_IDENTIFIERIx = e->KeywordIx("GET_HEAP_IDENTIFIER"); if( e->KeywordPresent( COUNTIx)) // COUNT { e->SetKW( COUNTIx, new DLongGDL( e->Interpreter()->ObjHeapSize())); } if( nParam == 0) { return e->Interpreter()->GetAllObjHeap(); } BaseGDL* p = e->GetPar( 0); if( p == NULL) { return new DByteGDL( 0); } DType pType = p->Type(); bool isscalar = p->StrictScalar(); DLongGDL* pL; Guard pL_guard; GDLInterpreter* interpreter = e->Interpreter(); if( pType == GDL_OBJ) { DObjGDL* pObj = static_cast( p); pL = new DLongGDL( p->Dim()); for( SizeT i=0; i < pL->N_Elements(); ++i) (*pL) [i] = (*pObj)[i]; if( e->KeywordSet( GET_HEAP_IDENTIFIERIx)) { if(isscalar) return new DLongGDL( (*pL)[0] ); else return pL; } } else { // pType == GDL_OBJ pL = static_cast(p->Convert2(GDL_LONG,BaseGDL::COPY)); pL_guard.Init( pL); if( e->KeywordSet( CASTIx)) { if(isscalar) { DLong p0 = (*pL)[0]; if( interpreter->ObjValid( p0 )) { interpreter->IncRefObj( p0); return new DObjGDL( p0); } else return new DObjGDL( 0); } DObjGDL* ret = new DObjGDL( pL->Dim()); for( SizeT i=0; i < pL->N_Elements(); ++i) if( interpreter->ObjValid( (*pL)[ i])) { interpreter->IncRefObj((*pL)[ i]); (*ret)[ i] = (*pL)[ i]; } return ret; } } DByteGDL* ret = new DByteGDL( pL->Dim()); // zero for( SizeT i=0; iN_Elements(); ++i) { if( interpreter->ObjValid( (*pL)[ i])) (*ret)[ i] = 1; } if(isscalar) return new DByteGDL( (*ret)[0] ); else return ret; } BaseGDL* obj_new( EnvT* e) { // StackGuard guard( e->Interpreter()->CallStack()); int nParam=e->NParam(); if( nParam == 0) { return new DObjGDL( 0); } DString objName; e->AssureScalarPar( 0, objName); // this is a struct name -> convert to UPPERCASE objName=StrUpCase(objName); if( objName == "IDL_OBJECT") objName = GDL_OBJECT_NAME; // replacement also done in GDLParser else if( objName == "IDL_CONTAINER" ) objName = GDL_CONTAINER_NAME; DStructDesc* objDesc=e->Interpreter()->GetStruct( objName, e->CallingNode()); DStructGDL* objStruct= new DStructGDL( objDesc, dimension()); DObj objID= e->NewObjHeap( 1, objStruct); // owns objStruct DObjGDL* newObj = new DObjGDL( objID); // the object try { // call INIT function DFun* objINIT= objDesc->GetFun( "INIT"); if( objINIT != NULL) { StackGuard guard( e->Interpreter()->CallStack()); // morph to obj environment and push it onto the stack again e->PushNewEnvUD( objINIT, 1, &newObj); BaseGDL* res=e->Interpreter()->call_fun( objINIT->GetTree()); if( res == NULL || (!res->Scalar()) || res->False()) { GDLDelete(res); return new DObjGDL( 0); } GDLDelete(res); } } catch(...) { e->FreeObjHeap( objID); // newObj might be changed GDLDelete(newObj); throw; } return newObj; } BaseGDL* heap_refcount( EnvT* e) { static int DISABLEIx = e->KeywordIx("DISABLE"); static int ENABLEIx = e->KeywordIx("ENABLE"); static int IS_ENABLEDIx = e->KeywordIx("IS_ENABLED"); // trace_me = trace_arg(); int nParam=e->NParam(); GDLInterpreter* interpreter = e->Interpreter(); if( nParam == 0) { if( e->KeywordSet(DISABLEIx)) { EnableGC(false); } else if( e->KeywordSet(ENABLEIx)) { EnableGC(true); interpreter->EnableAllGC(); } if(e->KeywordPresent(IS_ENABLEDIx)) e->SetKW( IS_ENABLEDIx, new DByteGDL( IsEnabledGC()) ); return new DIntGDL( 0); } BaseGDL* p = e->GetPar( 0); if( p == NULL) { return new DIntGDL( 0); } DIntGDL* ret = new DIntGDL(p->Dim()); Guard ret_guard(ret); DType pType = p->Type(); SizeT nEl = p->N_Elements(); if(pType == GDL_OBJ) { DObjGDL* pObj = static_cast( p); for( SizeT i=0; iRefCountHeapObj( (*pObj)[ i]); if( e->KeywordSet(DISABLEIx) or e->KeywordSet(ENABLEIx) ) { bool set = e->KeywordSet(ENABLEIx) ? true: false; interpreter->EnableGCObj( pObj, set); } } else { if( pType == GDL_PTR) { DPtrGDL* pPtr = static_cast( p); for( SizeT i=0; iRefCountHeap( (*pPtr)[ i]); if( e->KeywordSet(DISABLEIx) or e->KeywordSet(ENABLEIx) ) { bool set = e->KeywordSet(ENABLEIx) ? true: false; // if(trace_me) cout <<" GC set? "<EnableGC( pPtr, set); } } else { DLongGDL* pL; Guard pL_guard(pL); if( pType != GDL_LONG) { pL = static_cast(p->Convert2(GDL_LONG,BaseGDL::COPY)); pL_guard.Init( pL); } else { pL = static_cast(p); } for( SizeT i=0; iRefCountHeap( (*pL)[ i]); } } // #if 1 if(e->KeywordPresent(IS_ENABLEDIx)) { DByteGDL* enabled; // if(trace_me) // cout << " heap_refcount( prm, KeywordPresent(IS_ENABLEDIx)) "<< endl; if(pType == GDL_OBJ) { enabled = interpreter->IsEnabledGCObj(static_cast( p)); } else { if( pType == GDL_PTR) { enabled = interpreter->IsEnabledGC(static_cast( p)); } else { // if(trace_me) // cout << " heap_refcount(prm=lonarr, KeywordPresent(IS_ENABLEDIx) "<< endl; DLongGDL* pL; Guard pL_guard(pL); if( pType != GDL_LONG) { pL = static_cast(p->Convert2(GDL_LONG,BaseGDL::COPY)); pL_guard.Init( pL); } else { pL = static_cast(p); } DPtrGDL* ptr = new DPtrGDL( p->Dim()); Guard ptr_guard(ptr); for( SizeT i=0; iIsEnabledGC(ptr); } } e->SetKW( IS_ENABLEDIx, enabled); } // #endif return ret_guard.release(); } BaseGDL* bindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DByteGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "BINDGEN: "+ex.getMessage()); } */ } BaseGDL* indgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; DType type = GDL_INT; static int kwIx1 = e->KeywordIx("BYTE"); if (e->KeywordSet(kwIx1)){ type = GDL_BYTE; } static int kwIx2 = e->KeywordIx("COMPLEX"); if (e->KeywordSet(kwIx2)){ type = GDL_COMPLEX; } static int kwIx3 = e->KeywordIx("DCOMPLEX"); if (e->KeywordSet(kwIx3)){ type = GDL_COMPLEXDBL; } static int kwIx4 = e->KeywordIx("DOUBLE"); if (e->KeywordSet(kwIx4)){ type = GDL_DOUBLE; } static int kwIx5 = e->KeywordIx("FLOAT"); if (e->KeywordSet(kwIx5)){ type = GDL_FLOAT; } static int kwIx6 = e->KeywordIx("L64"); if (e->KeywordSet(kwIx6)){ type = GDL_LONG64; } static int kwIx7 = e->KeywordIx("LONG"); if (e->KeywordSet(kwIx7)){ type = GDL_LONG; } static int kwIx8 = e->KeywordIx("STRING"); if (e->KeywordSet(kwIx8)){ type = GDL_STRING; } static int kwIx9 = e->KeywordIx("UINT"); if (e->KeywordSet(kwIx9)){ type = GDL_UINT; } static int kwIx10 = e->KeywordIx("UL64"); if (e->KeywordSet(kwIx10)){ type = GDL_ULONG64; } static int kwIx11 = e->KeywordIx("ULONG"); if (e->KeywordSet(kwIx11)){ type = GDL_ULONG; } /*try {*/ // Seeing if the user passed in a TYPE code static int kwIx12 = e->KeywordIx("TYPE"); if ( e->KeywordPresent(kwIx12)){ DLong temp_long; e->AssureLongScalarKW(kwIx12, temp_long); type = static_cast(temp_long); } arr(e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); switch(type) { case GDL_INT: return new DIntGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_BYTE: return new DByteGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_COMPLEX: return new DComplexGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_COMPLEXDBL: return new DComplexDblGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_DOUBLE: return new DDoubleGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_FLOAT: return new DFloatGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_LONG64: return new DLong64GDL(dim, BaseGDL::INDGEN, off, inc); case GDL_LONG: return new DLongGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_STRING: { DULongGDL* iGen = new DULongGDL(dim, BaseGDL::INDGEN, off, inc); return iGen->Convert2(GDL_STRING); } case GDL_UINT: return new DUIntGDL(dim, BaseGDL::INDGEN, off, inc); case GDL_ULONG64: return new DULong64GDL(dim, BaseGDL::INDGEN, off, inc); case GDL_ULONG: return new DULongGDL(dim, BaseGDL::INDGEN, off, inc); default: e->Throw( "Invalid type code specified."); break; } /* } catch( GDLException& ex) { e->Throw( ex.getMessage()); }*/ assert(false); return NULL; } BaseGDL* uindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DUIntGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "UINDGEN: "+ex.getMessage()); } */ } BaseGDL* sindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); DULongGDL* iGen = new DULongGDL(dim, BaseGDL::INDGEN, off, inc); return iGen->Convert2( GDL_STRING); /* } catch( GDLException& ex) { e->Throw( "SINDGEN: "+ex.getMessage()); }*/ } BaseGDL* lindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DLongGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "LINDGEN: "+ex.getMessage()); }*/ } BaseGDL* ulindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DULongGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "ULINDGEN: "+ex.getMessage()); }*/ } BaseGDL* l64indgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DLong64GDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "L64INDGEN: "+ex.getMessage()); }*/ } BaseGDL* ul64indgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DULong64GDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "UL64INDGEN: "+ex.getMessage()); } */ } BaseGDL* findgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DFloatGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "FINDGEN: "+ex.getMessage()); }*/ } BaseGDL* dindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DDoubleGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "DINDGEN: "+ex.getMessage()); }*/ } BaseGDL* cindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DComplexGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "CINDGEN: "+ex.getMessage()); }*/ } BaseGDL* dcindgen( EnvT* e) { dimension dim; DDouble off = 0, inc = 1; // try{ arr( e, dim); if (dim[0] == 0) throw GDLException( "Array dimensions must be greater than 0"); e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); return new DComplexDblGDL(dim, BaseGDL::INDGEN, off, inc); /* } catch( GDLException& ex) { e->Throw( "DCINDGEN: "+ex.getMessage()); } */ } // only called from CALL_FUNCTION // otherwise done directly in FCALL_LIB_N_ELEMENTSNode::Eval(); // (but must be defined anyway for LibInit() for correct parametrization) // N_ELEMENTS is special because on error it just returns 0L // (the error is just caught and dropped) BaseGDL* n_elements( EnvT* e) { SizeT nParam=e->NParam(1); BaseGDL* p0=e->GetPar( 0); if( p0 == NULL) return new DLongGDL( 0); if( p0->IsAssoc()) return new DLongGDL( 1); if(p0->Type() == GDL_OBJ) { DStructGDL* s = GetObjStruct(p0, e); if( s->Desc()->IsParent("LIST")) return new DLongGDL( LIST_count(s)); else if( s->Desc()->IsParent("HASH")) return new DLongGDL( HASH_count(s)); } if (p0->N_Elements() > 2147483647UL) return new DLong64GDL( p0->N_Elements()); else return new DLongGDL( p0->N_Elements()); } // JAdZ 20150506: This is now only for nParam=2, complex_fun_template redefined several lines below instead template< typename ComplexGDL, typename Complex, typename Float> BaseGDL* complex_fun_template_twopar( EnvT* e) { SizeT nParam=e->NParam( 1); // JAdZ 20150506: This should now only be called when nParam=2, see below if( nParam != 2) { e->Throw( "Exception: You should never have been able to get here! Please report this."); } BaseGDL* p0=e->GetParDefined( 0); BaseGDL* p1=e->GetParDefined( 1); Float* p0Float = static_cast (p0->Convert2( Float::t,BaseGDL::COPY)); Guard p0FloatGuard(p0Float); Float* p1Float = static_cast (p1->Convert2( Float::t,BaseGDL::COPY)); Guard p1FloatGuard(p1Float); if( p0Float->Rank() == 0) { ComplexGDL* res = new ComplexGDL( p1Float->Dim(), BaseGDL::NOZERO); SizeT nE=p1Float->N_Elements(); // #pragma omp parallel if (nE >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nE)) { // #pragma omp for for( SizeT i=0; iRank() == 0) { ComplexGDL* res = new ComplexGDL( p0Float->Dim(), BaseGDL::NOZERO); SizeT nE=p0Float->N_Elements(); // #pragma omp parallel if (nE >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nE)) { // #pragma omp for for( SizeT i=0; iN_Elements() >= p1Float->N_Elements()) { ComplexGDL* res = new ComplexGDL( p1Float->Dim(), BaseGDL::NOZERO); SizeT nE=p1Float->N_Elements(); // #pragma omp parallel if (nE >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nE)) { // #pragma omp for for( SizeT i=0; iDim(), BaseGDL::NOZERO); SizeT nE=p0Float->N_Elements(); // #pragma omp parallel if (nE >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nE)) { // #pragma omp for for( SizeT i=0; iKeywordSet("DOUBLE")) { return complex_fun_template< DComplexDblGDL, DComplexDbl, DDoubleGDL>( e); } else { return complex_fun_template< DComplexGDL, DComplex, DFloatGDL>( e); } } BaseGDL* dcomplex_fun( EnvT* e) { return complex_fun_template< DComplexDblGDL, DComplexDbl, DDoubleGDL>( e); } */ // END JAdZ 20150506 template< class TargetClass> BaseGDL* type_fun( EnvT* e) { SizeT nParam=e->NParam(1); if( nParam == 1) { BaseGDL* p0=e->GetParDefined( 0); assert( dynamic_cast< EnvUDT*>( e->Caller()) != NULL); // type_fun( expr) just convert if( static_cast< EnvUDT*>( e->Caller())->GetIOError() != NULL) return p0->Convert2( TargetClass::t, BaseGDL::COPY_THROWIOERROR); // SA: see tracker item no. 3151760 else if (TargetClass::t == p0->Type() && e->GlobalPar(0)) // HERE THE INPUT VARIABLE IS RETURNED { e->SetPtrToReturnValue( &e->GetPar(0)); return p0; } else return p0->Convert2( TargetClass::t, BaseGDL::COPY); } BaseGDL* p0=e->GetNumericParDefined( 0); // GDL_BYTE( expr, offs, dim1,..,dim8) DLong offs; e->AssureLongScalarPar( 1, offs); dimension dim; if( nParam > 2) arr( e, dim, 2); TargetClass* res=new TargetClass( dim, BaseGDL::NOZERO); SizeT nByteCreate=res->NBytes(); // net size of new data SizeT nByteSource=p0->NBytes(); // net size of src if( offs < 0 || (offs+nByteCreate) > nByteSource) { GDLDelete(res); e->Throw( "Specified offset to" " expression is out of range: "+e->GetParString(0)); } //*** POSSIBLE ERROR because of alignment here void* srcAddr = static_cast( static_cast(p0->DataAddr()) + offs); void* dstAddr = static_cast(&(*res)[0]); memcpy( dstAddr, srcAddr, nByteCreate); // char* srcAddr = reinterpret_cast(p0->DataAddr()); // char* dstAddr = reinterpret_cast(&(*res)[0]); // copy( srcAddr, srcAddr+nByteCreate, dstAddr); return res; } BaseGDL* byte_fun( EnvT* e) { return type_fun( e); } BaseGDL* uint_fun( EnvT* e) { return type_fun( e); } BaseGDL* long_fun( EnvT* e) { return type_fun( e); } BaseGDL* ulong_fun( EnvT* e) { return type_fun( e); } BaseGDL* long64_fun( EnvT* e) { return type_fun( e); } BaseGDL* ulong64_fun( EnvT* e) { return type_fun( e); } BaseGDL* float_fun( EnvT* e) { return type_fun( e); } BaseGDL* double_fun( EnvT* e) { return type_fun( e); } // JAdZ 20150506: I defined complex_fun and dcomplex_fun here instead, based on // complex_fun_template_twopar when nParam=2 BaseGDL* complex_fun( EnvT* e) { SizeT nParam=e->NParam( 1); if( nParam == 2) { static int doubleIx=e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx)) { return complex_fun_template_twopar< DComplexDblGDL, DComplexDbl, DDoubleGDL>( e); } else { return complex_fun_template_twopar< DComplexGDL, DComplex, DFloatGDL>( e); } } else { return type_fun( e); } } BaseGDL* dcomplex_fun( EnvT* e) { SizeT nParam=e->NParam( 1); if( nParam == 2) { return complex_fun_template_twopar< DComplexDblGDL, DComplexDbl, DDoubleGDL>( e); } else { return type_fun( e); } } // END JAdZ 20150506 // STRING function behaves different BaseGDL* string_fun( EnvT* e) { SizeT nParam=e->NParam(); if( nParam == 0) e->Throw( "Incorrect number of arguments."); // AC 2016/02/12 we check now here if params are defined to avoid future problems // print, string(kk, 12, ee) said "ee" undefined because of VMS hack (should say kk undefined before !) // print, string(kk, 12, ee, format='()') did not complains // for (SizeT i=0; iGetParDefined( i); static int printKeyIx=e->KeywordIx("PRINT"); bool printKey = e->KeywordSet(printKeyIx); int parOffset = 0; // SA: handling special VMS-compatibility syntax, e.g.: string(1,'$(F)') // (if nor FORMAT neither PRINT defined, >1 parameter, last param is scalar string // which begins with "$(" or "(" but is not "()" then last param [minus "$"] is treated as FORMAT) bool vmshack = false; if (!printKey && (e->GetKW(0) == NULL) && nParam > 1) { vmshack = true; BaseGDL* par = e->GetParDefined(nParam - 1); if (par->Type() == GDL_STRING && par->Scalar()) { int dollar = (*static_cast(par))[0].compare(0,2,"$("); if (dollar == 0 || ((*static_cast(par))[0].compare(0,1,"(") == 0 && (*static_cast(par))[0] != "()")) { e->SetKeyword("FORMAT", new DStringGDL( (*static_cast(par))[0].c_str() + (dollar == 0 ? 1 : 0) )); } } } static int formatIx=e->KeywordIx ("FORMAT"); BaseGDL* format_kw = e->GetKW(formatIx); bool formatKey = format_kw != NULL; if (formatKey && format_kw->Type() == GDL_STRING && (*static_cast(format_kw))[0] == "") formatKey = false; if( printKey || formatKey) // PRINT or FORMAT { stringstream os; SizeT width = 0; if( printKey) // otherwise: FORMAT -> width is ignored { // for /PRINT always a terminal width of 80 is assumed width = 80;//TermWidth(); } if (vmshack) { parOffset = 1; e->ShiftParNumbering(1); } print_os( &os, e, parOffset, width); if (vmshack) { e->ShiftParNumbering(-1); } vector buf; while( os.good()) { string line; getline( os, line); if(!line.empty()) buf.push_back( line); //should save the day for the formats with '$' at end. } SizeT bufSize = buf.size(); if( bufSize == 0) e->Throw( "Internal error: print buffer empty."); if( bufSize > 1) { DStringGDL* retVal = new DStringGDL( dimension( bufSize), BaseGDL::NOZERO); for( SizeT i=0; i conversion { BaseGDL* p0 = e->GetParDefined( 0); // SA: see tracker item no. 3151760 // HERE INPUT VARIABLE IS RETURNED if (p0->Type() == GDL_STRING && e->GlobalPar(0)) { e->SetPtrToReturnValue( &e->GetPar(0)); return p0; } return p0->Convert2( GDL_STRING, BaseGDL::COPY); } else // concatenation { DString s; for( SizeT i=0; iGetParDefined( i); DStringGDL* sP = static_cast ( p->Convert2(GDL_STRING, BaseGDL::COPY_BYTE_AS_INT)); SizeT nEl = sP->N_Elements(); for( SizeT e=0; eIfDefGetKWAs( 0); if (type != NULL) { int typ = (*type)[0]; if (typ == GDL_BYTE) { // SA: slow yet simple solution using GDL_BYTE->GDL_INT->GDL_BYTE conversion return (e->KeywordSet(1) && e->GetPar(0)->Type() == GDL_STRING) ? type_fun( e)->Convert2(GDL_BYTE, BaseGDL::CONVERT) : type_fun( e); } if (typ == 0 || typ == GDL_INT) return type_fun( e); if (typ == GDL_UINT) return type_fun( e); if (typ == GDL_LONG) return type_fun( e); if (typ == GDL_ULONG) return type_fun( e); if (typ == GDL_LONG64) return type_fun( e); if (typ == GDL_ULONG64) return type_fun( e); if (typ == GDL_FLOAT) return type_fun( e); if (typ == GDL_DOUBLE) return type_fun( e); if (typ == GDL_COMPLEX) return type_fun( e); if (typ == GDL_COMPLEXDBL) return type_fun( e); if (typ == GDL_STRING) { // SA: calling GDL_STRING() with correct parameters static int stringIx = LibFunIx("STRING"); assert( stringIx >= 0); EnvT* newEnv= new EnvT(e, libFunList[stringIx], NULL); Guard guard( newEnv); newEnv->SetNextPar(&e->GetPar(0)); // pass as global if (e->KeywordSet(1) && e->GetPar(0)->Type() == GDL_BYTE) newEnv->SetKeyword("PRINT", new DIntGDL(1)); // e->Interpreter()->CallStack().push_back( newEnv); return static_cast(newEnv->GetPro())->Fun()(newEnv); } e->Throw( "Improper TYPE value."); } return type_fun( e); } BaseGDL* call_function( EnvT* e) { int nParam=e->NParam(); if( nParam == 0) e->Throw( "No function specified."); DString callF; e->AssureScalarPar( 0, callF); // this is a function name -> convert to UPPERCASE callF = StrUpCase( callF); // first search library funcedures int funIx=LibFunIx( callF); if( funIx != -1) { // e->PushNewEnv( libFunList[ funIx], 1); // make the call // EnvT* newEnv = static_cast(e->Interpreter()->CallStack().back()); // handle direct call functions if( libFunList[ funIx]->DirectCall()) { BaseGDL* directCallParameter = e->GetParDefined(1); BaseGDL* res = static_cast(libFunList[ funIx])->FunDirect()(directCallParameter, true /*isReference*/); return res; } else { EnvT* newEnv = e->NewEnv( libFunList[ funIx], 1); Guard guard( newEnv); BaseGDL* res = static_cast(newEnv->GetPro())->Fun()(newEnv); e->SetPtrToReturnValue( newEnv->GetPtrToReturnValue()); return res; } } else { // no direct call here funIx = GDLInterpreter::GetFunIx( callF); StackGuard guard( e->Interpreter()->CallStack()); EnvUDT* newEnv = e->PushNewEnvUD( funList[ funIx], 1); // make the call // EnvUDT* newEnv = static_cast(e->Interpreter()->CallStack().back()); //GD: changed LRFUNCTION to RFUNCTION and removed e->SetPtrToReturnValue() below. //this solved bug #706 newEnv->SetCallContext( EnvUDT::RFUNCTION); BaseGDL* res = e->Interpreter()->call_fun(static_cast(newEnv->GetPro())->GetTree()); //GD: removed e->SetPtrToReturnValue( newEnv->GetPtrToReturnValue()); // BaseGDL* ppp = res->Dup(); // cout << " res = " << res << " p to res = " << newEnv->GetPtrToReturnValue() << endl; return res; } } BaseGDL* call_method_function( EnvT* e) { int nParam=e->NParam(); if( nParam < 2) e->Throw( "Name and object reference must be specified."); DString callP; e->AssureScalarPar( 0, callP); // this is a procedure name -> convert to UPPERCASE callP = StrUpCase( callP); DStructGDL* oStruct = e->GetObjectPar( 1); DFun* method= oStruct->Desc()->GetFun( callP); if( method == NULL) e->Throw( "Method not found: "+callP); StackGuard guard( e->Interpreter()->CallStack()); EnvUDT* newEnv = e->PushNewEnvUD( method, 2, (DObjGDL**) &e->GetPar( 1)); // make the call // return e->Interpreter()->call_fun( method->GetTree()); newEnv->SetCallContext( EnvUDT::LRFUNCTION); BaseGDL* res = e->Interpreter()->call_fun( method->GetTree()); e->SetPtrToReturnValue( newEnv->GetPtrToReturnValue()); return res; } BaseGDL* execute_fun( EnvT* e) { int nParam=e->NParam( 1); bool compileFlags = false; if( nParam >= 2) { BaseGDL* p1 = e->GetParDefined( 1); if( !p1->Scalar()) e->Throw( "Expression must be scalar in this context: "+ e->GetParString(1)); // we do not enforce the case of Implied Print, then only 2 states compileFlags = p1->LogTrue(); } bool quietExecution = false; if( nParam == 3) { BaseGDL* p2 = e->GetParDefined( 2); if( !p2->Scalar()) e->Throw( "Expression must be scalar in this context: "+ e->GetParString(2)); quietExecution = p2->LogTrue(); Warning("This third argument is not enforce now !"); } if (e->GetParDefined(0)->Rank() != 0) e->Throw("Expression must be scalar in this context: "+e->GetParString(0)); DString line; e->AssureScalarPar( 0, line); // remove current environment (own one) assert( dynamic_cast(e->Caller()) != NULL); EnvUDT* caller = static_cast(e->Caller()); // e->Interpreter()->CallStack().pop_back(); // wrong: e is guarded, do not delete it here // delete e; istringstream istr(line+"\n"); RefDNode theAST; try { GDLLexer lexer(istr, "", caller->CompileOpt()); GDLParser& parser=lexer.Parser(); parser.interactive(); theAST=parser.getAST(); } catch( GDLException& ex) { if( !compileFlags) GDLInterpreter::ReportCompileError( ex); return new DIntGDL( 0); } catch( ANTLRException& ex) { if( !compileFlags) cerr << "EXECUTE: Lexer/Parser exception: " << ex.getMessage() << endl; return new DIntGDL( 0); } if( theAST == NULL) return new DIntGDL( 1); RefDNode trAST; try { GDLTreeParser treeParser( caller); treeParser.interactive(theAST); trAST=treeParser.getAST(); } catch( GDLException& ex) { if( !compileFlags) GDLInterpreter::ReportCompileError( ex); return new DIntGDL( 0); } catch( ANTLRException& ex) { if( !compileFlags) cerr << "EXECUTE: Compiler exception: " << ex.getMessage() << endl; return new DIntGDL( 0); } if( trAST == NULL) return new DIntGDL( 1); int nForLoopsIn = caller->NForLoops(); try { ProgNodeP progAST = ProgNode::NewProgNode( trAST); Guard< ProgNode> progAST_guard( progAST); int nForLoops = ProgNode::NumberForLoops( progAST, nForLoopsIn); caller->ResizeForLoops( nForLoops); progAST->setLine( e->GetLineNumber()); // AC 2016-02-26 : bug report #692 always verbose in EXECUTE() // Do we have a way not to *always* issue a message here // in case of problem ??? RetCode retCode = caller->Interpreter()->execute( progAST, true); //throwImmediately=true as we must avoid "implied print" infinite loop. caller->ResizeForLoops( nForLoopsIn); if( retCode == RC_OK) return new DIntGDL( 1); else return new DIntGDL( 0); } catch( GDLException& ex) { caller->ResizeForLoops( nForLoopsIn); // are we throwing to target environment? // if( ex.GetTargetEnv() == NULL) if( !compileFlags) cerr << "EXECUTE: " << ex.getMessage() << endl; return new DIntGDL( 0); } catch( ANTLRException& ex) { caller->ResizeForLoops( nForLoopsIn); if( !compileFlags) cerr << "EXECUTE: Interpreter exception: " << ex.getMessage() << endl; return new DIntGDL( 0); } return new DIntGDL( 0); // control flow cannot reach here - compiler shut up } BaseGDL* assoc( EnvT* e) { SizeT nParam=e->NParam( 2); DLong lun; e->AssureLongScalarPar( 0, lun); bool stdLun = check_lun( e, lun); if( stdLun) e->Throw( "File unit does not allow" " this operation. Unit: "+i2s( lun)); DLong offset = 0; if( nParam >= 3) e->AssureLongScalarPar( 2, offset); BaseGDL* arr = e->GetParDefined( 1); if( arr->StrictScalar()) e->Throw( "Scalar variable not allowed in this" " context: "+e->GetParString(1)); return arr->AssocVar( lun, offset); } // gdl_ naming because of weired namespace problem in MSVC BaseGDL* gdl_logical_and( EnvT* e) { SizeT nParam=e->NParam(); if( nParam != 2) e->Throw( "Incorrect number of arguments."); BaseGDL* e1=e->GetParDefined( 0);//, "LOGICAL_AND"); BaseGDL* e2=e->GetParDefined( 1);//, "LOGICAL_AND"); ULong nEl1 = e1->N_Elements(); ULong nEl2 = e2->N_Elements(); Data_* res; if( e1->Scalar()) { if( e1->LogTrue(0)) { res= new Data_( e2->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl2 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl2)) { // #pragma omp for for( SizeT i=0; i < nEl2; i++) (*res)[i] = e2->LogTrue( i) ? 1 : 0; } } else { return new Data_( e2->Dim()); } } else if( e2->Scalar()) { if( e2->LogTrue(0)) { res= new Data_( e1->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl1 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl1)) { // #pragma omp for for( SizeT i=0; i < nEl1; i++) (*res)[i] = e1->LogTrue( i) ? 1 : 0; } } else { return new Data_( e1->Dim()); } } else if( nEl2 < nEl1) { res= new Data_( e2->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl2 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl2)) { // #pragma omp for for( SizeT i=0; i < nEl2; i++) (*res)[i] = (e1->LogTrue( i) && e2->LogTrue( i)) ? 1 : 0; } } else // ( nEl2 >= nEl1) { res= new Data_( e1->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl1 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl1)) { // #pragma omp for for( SizeT i=0; i < nEl1; i++) (*res)[i] = (e1->LogTrue( i) && e2->LogTrue( i)) ? 1 : 0; } } return res; } // gdl_ naming because of weired namespace problem in MSVC BaseGDL* gdl_logical_or( EnvT* e) { SizeT nParam=e->NParam(); if( nParam != 2) e->Throw( "Incorrect number of arguments."); BaseGDL* e1=e->GetParDefined( 0);//, "LOGICAL_OR"); BaseGDL* e2=e->GetParDefined( 1);//, "LOGICAL_OR"); ULong nEl1 = e1->N_Elements(); ULong nEl2 = e2->N_Elements(); Data_* res; if( e1->Scalar()) { if( e1->LogTrue(0)) { res= new Data_( e2->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl2 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl2)) { // #pragma omp for for( SizeT i=0; i < nEl2; i++) (*res)[i] = 1; } } else { res= new Data_( e2->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl2 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl2)) { // #pragma omp for for( SizeT i=0; i < nEl2; i++) (*res)[i] = e2->LogTrue( i) ? 1 : 0; } } } else if( e2->Scalar()) { if( e2->LogTrue(0)) { res= new Data_( e1->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl1 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl1)) { // #pragma omp for for( SizeT i=0; i < nEl1; i++) (*res)[i] = 1; } } else { res= new Data_( e1->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl1 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl1)) { // #pragma omp for for( SizeT i=0; i < nEl1; i++) (*res)[i] = e1->LogTrue( i) ? 1 : 0; } } } else if( nEl2 < nEl1) { res= new Data_( e2->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl2 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl2)) { // #pragma omp for for( SizeT i=0; i < nEl2; i++) (*res)[i] = (e1->LogTrue( i) || e2->LogTrue( i)) ? 1 : 0; } } else // ( nEl2 >= nEl1) { res= new Data_( e1->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl1 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl1)) { // #pragma omp for for( SizeT i=0; i < nEl1; i++) (*res)[i] = (e1->LogTrue( i) || e2->LogTrue( i)) ? 1 : 0; } } return res; } BaseGDL* logical_true( BaseGDL* e1, bool isReference)//( EnvT* e); { assert( e1 != NULL); assert( e1->N_Elements() > 0); // SizeT nParam=e->NParam(); // if( nParam != 1) // e->Throw( // "Incorrect number of arguments."); // // BaseGDL* e1=e->GetParDefined( 0);//, "LOGICAL_TRUE"); // ULong nEl1 = e1->N_Elements(); Data_* res = new Data_( e1->Dim(), BaseGDL::NOZERO); // #pragma omp parallel if (nEl1 >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl1)) { // #pragma omp for for( SizeT i=0; i < nEl1; i++) (*res)[i] = e1->LogTrue( i) ? 1 : 0; } return res; } BaseGDL* replicate( EnvT* e) { SizeT nParam=e->NParam(); if( nParam < 2) e->Throw( "Incorrect number of arguments."); dimension dim; arr( e, dim, 1); BaseGDL* p0=e->GetParDefined( 0);//, "REPLICATE"); if( !p0->Scalar()) e->Throw( "Expression must be a scalar in this context: "+ e->GetParString(0)); return p0->New( dim, BaseGDL::INIT); } BaseGDL* strtrim( EnvT* e) { SizeT nParam = e->NParam( 1);//, "STRTRIM"); BaseGDL* p0 = e->GetPar( 0); if( p0 == NULL) e->Throw("Variable is undefined: " + e->GetParString(0)); DStringGDL* p0S = static_cast(p0->Convert2(GDL_STRING,BaseGDL::COPY)); DLong mode = 0; if( nParam == 2) { BaseGDL* p1 = e->GetPar( 1); if( p1 == NULL) e->Throw("Variable is undefined: "+e->GetParString(1)); if( !p1->Scalar()) e->Throw("Expression must be a scalar in this context: "+ e->GetParString(1)); DLongGDL* p1L = static_cast (p1->Convert2(GDL_LONG,BaseGDL::COPY)); mode = (*p1L)[ 0]; GDLDelete(p1L); if( mode < 0 || mode > 2) { ostringstream os; p1->ToStream( os); e->Throw( "Value of <"+ p1->TypeStr() + " ("+ os.str() + ")> is out of allowed range."); } } SizeT nEl = p0S->N_Elements(); if( mode == 2) // both { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nEl*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; i= (*p0S)[i].length()) { (*p0S)[ i] = ""; } else { unsigned long last = (*p0S)[ i].find_last_not_of(" \t"); (*p0S)[ i] = (*p0S)[ i].substr(first,last-first+1); } } } } else if( mode == 1) // leading { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nEl*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; i= (*p0S)[i].length()) { (*p0S)[ i] = ""; } else { (*p0S)[ i] = (*p0S)[ i].substr(first); } } } } else // trailing { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nEl*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; i= (*p0S)[i].length()) { (*p0S)[ i] = ""; } else { (*p0S)[ i] = (*p0S)[ i].substr(0,last+1); } } } } return p0S; } BaseGDL* strcompress( EnvT* e) { e->NParam( 1); DStringGDL* p0S = e->GetParAs( 0); bool removeAll = e->KeywordSet(0); DStringGDL* res = new DStringGDL( p0S->Dim(), BaseGDL::NOZERO); SizeT nEl = p0S->N_Elements(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nEl*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; iNParam( 2);//, "STRPOS"); bool reverseOffset = e->KeywordSet(0); // REVERSE_OFFSET bool reverseSearch = e->KeywordSet(1); // REVERSE_SEARCH DStringGDL* p0S = e->GetParAs( 0); DString searchString; // e->AssureScalarPar( 1, searchString); DStringGDL* sStr = e->GetParAs( 1); if( !sStr->Scalar( searchString)) e->Throw( "Search string must be a scalar or one element array: "+ e->GetParString( 1)); unsigned long pos = string::npos; if( nParam > 2) { BaseGDL* p2 = e->GetParDefined(2); // if( p2 != NULL) //e->AssureLongScalarPar( 2,posDLong); // { const SizeT pIx = 2; BaseGDL* p = e->GetParDefined( pIx); DLongGDL* lp = static_cast(p->Convert2( GDL_LONG, BaseGDL::COPY)); Guard guard_lp( lp); DLong scalar; if( !lp->Scalar( scalar)) throw GDLException("Parameter must be a scalar in this context: "+ e->GetParString(pIx)); pos = scalar; } DLongGDL* res = new DLongGDL( p0S->Dim(), BaseGDL::NOZERO); SizeT nSrcStr = p0S->N_Elements(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nSrcStr*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nSrcStr*10))) { #pragma omp for for( OMPInt i=0; iNParam( 2);//, "STRMID"); bool reverse = e->KeywordSet(0); DStringGDL* p0S = e->GetParAs( 0); DLongGDL* p1L = e->GetParAs( 1); // BaseGDL* p2 = e->GetPar( 2); DLongGDL* p2L = NULL; if( nParam > 2) p2L = e->GetParAs( 2); DLong scVal1; bool sc1 = p1L->Scalar( scVal1); DLong scVal2 = numeric_limits::max(); bool sc2 = true; if( p2L != NULL) { DLong scalar; sc2 = p2L->Scalar( scalar); scVal2 = scalar; } DLong stride; if( !sc1 && !sc2) { stride = p1L->Dim( 0); if( stride != p2L->Dim( 0)) e->Throw( "Starting offset and length arguments " "have incompatible first dimension."); } else { // at least one scalar, p2L possibly NULL if( p2L == NULL) stride = p1L->Dim( 0); else stride = max( p1L->Dim( 0), p2L->Dim( 0)); stride = (stride > 0)? stride : 1; } dimension resDim( p0S->Dim()); if( stride > 1) resDim >> stride; DStringGDL* res = new DStringGDL( resDim, BaseGDL::NOZERO); SizeT nEl1 = p1L->N_Elements(); SizeT nEl2 = (sc2)? 1 : p2L->N_Elements(); SizeT nSrcStr = p0S->N_Elements(); if( nSrcStr == 1) { // possibly this optimization is not worth the longer code (as the gain can only be a small fraction // of the overall time), but then this is a very common use for( long ii=0; ii= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nSrcStr*10))) default( shared) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1);//, "STRLOWCASE"); // DStringGDL* p0S = e->GetParAs( 0); DStringGDL* p0S; DStringGDL* res; // Guard guard; if( p0->Type() == GDL_STRING) { p0S = static_cast( p0); if( !isReference) res = p0S; else res = new DStringGDL( p0S->Dim(), BaseGDL::NOZERO); } else { p0S = static_cast( p0->Convert2( GDL_STRING, BaseGDL::COPY)); res = p0S; // guard.Reset( p0S); } // DStringGDL* res = new DStringGDL( p0S->Dim(), BaseGDL::NOZERO); SizeT nEl = p0S->N_Elements(); if( res == p0S) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nEl*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1);//, "STRLOWCASE"); // DStringGDL* p0S = e->GetParAs( 0); DStringGDL* p0S; DStringGDL* res; // Guard guard; if( p0->Type() == GDL_STRING) { p0S = static_cast( p0); if( !isReference) res = p0S; else res = new DStringGDL( p0S->Dim(), BaseGDL::NOZERO); } else { p0S = static_cast( p0->Convert2( GDL_STRING, BaseGDL::COPY)); res = p0S; // guard.Reset( p0S); } // DStringGDL* res = new DStringGDL( p0S->Dim(), BaseGDL::NOZERO); SizeT nEl = p0S->N_Elements(); if( res == p0S) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if ((nEl*10) >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl*10))) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1);//, "STRLEN"); DStringGDL* p0S; Guard guard; if( p0->Type() == GDL_STRING) p0S = static_cast( p0); else { p0S = static_cast( p0->Convert2( GDL_STRING, BaseGDL::COPY)); guard.Reset( p0S); } DLongGDL* res = new DLongGDL( p0S->Dim(), BaseGDL::NOZERO); SizeT nEl = p0S->N_Elements(); // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; iNParam( 1); DStringGDL* p0S = e->GetParAs( 0); SizeT nEl = p0S->N_Elements(); DString delim = ""; if( nParam > 1) e->AssureStringScalarPar( 1, delim); bool single = e->KeywordSet( 0); // SINGLE if( single) { DStringGDL* res = new DStringGDL( (*p0S)[0]); DString& scl = (*res)[0]; for( SizeT i=1; iDim()); resDim.Purge(); SizeT stride = resDim.Stride( 1); resDim.Remove( 0); DStringGDL* res = new DStringGDL( resDim, BaseGDL::NOZERO); for( SizeT src=0, dst=0; src(e->Caller()); if( caller == NULL) return new DLongGDL( 0); DLong nP = caller->NParam(); if( caller->IsObject()) return new DLongGDL( nP-1); // "self" is not counted return new DLongGDL( nP); } BaseGDL* keyword_set( EnvT* e) { e->NParam( 1);//, "KEYWORD_SET"); BaseGDL* p0 = e->GetPar( 0); if( p0 == NULL) return new DIntGDL( 0); if( p0->Type() == GDL_UNDEF) return new DIntGDL( 0); if( !p0->Scalar()) return new DIntGDL( 1); if( p0->Type() == GDL_STRUCT) return new DIntGDL( 1); if( p0->LogTrue()) return new DIntGDL( 1); return new DIntGDL( 0); } // passing 2nd argument by value is slightly better for float and double, // but incur some overhead for the complex class. template inline void AddOmitNaN(T& dest, T value) { if (std::isfinite(value)) { // #pragma omp atomic dest += value; } } template inline void AddOmitNaNCpx(T& dest, T value) { // #pragma omp atomic dest += T(std::isfinite(value.real())? value.real() : 0, std::isfinite(value.imag())? value.imag() : 0); } template<> inline void AddOmitNaN(DComplex& dest, DComplex value) { AddOmitNaNCpx(dest, value); } template<> inline void AddOmitNaN(DComplexDbl& dest, DComplexDbl value) { AddOmitNaNCpx(dest, value); } template inline void NaN2Zero(T& value) { if (!std::isfinite(value)) value = 0; } template inline void NaN2ZeroCpx(T& value) { value = T(std::isfinite(value.real())? value.real() : 0, std::isfinite(value.imag())? value.imag() : 0); } template<> inline void NaN2Zero(DComplex& value) { NaN2ZeroCpx< DComplex>(value); } template<> inline void NaN2Zero(DComplexDbl& value) { NaN2ZeroCpx< DComplexDbl>(value); } // total over all elements template BaseGDL* total_template( T* src, bool omitNaN) { if (!omitNaN) return new T(src->Sum()); typename T::Ty sum = 0; SizeT nEl = src->N_Elements(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared(sum) { #pragma omp for for ( OMPInt i=0; i BaseGDL* total_cu_template( T* res, bool omitNaN) { SizeT nEl = res->N_Elements(); if (omitNaN) { // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for (SizeT i = 0; i < nEl; ++i) NaN2Zero((*res)[i]); } } for (SizeT i = 1, ii = 0; i < nEl; ++i, ++ii) (*res)[i] += (*res)[ii]; return res; } // total over one dim template< typename T> BaseGDL* total_over_dim_template( T* src, const dimension& srcDim, SizeT sumDimIx, bool omitNaN) { SizeT nEl = src->N_Elements(); // get dest dim and number of summations dimension destDim = srcDim; SizeT nSum = destDim.Remove(sumDimIx); T* res = new T(destDim); // zero fields // sumStride is also the number of linear src indexing SizeT sumStride = srcDim.Stride(sumDimIx); SizeT outerStride = srcDim.Stride(sumDimIx + 1); SizeT sumLimit = nSum * sumStride; if (omitNaN) { #pragma omp parallel if ((nEl/outerStride)*sumStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*sumStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { SizeT rIx = (o / outerStride) * sumStride; for (SizeT i = 0; i < sumStride; ++i) { SizeT oi = o + i; SizeT oiLimit = sumLimit + oi; for (SizeT s = oi; s < oiLimit; s += sumStride) AddOmitNaN((*res)[ rIx], (*src)[ s]); ++rIx; } } } } else { #pragma omp parallel if ((nEl/outerStride)*sumStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*sumStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { SizeT rIx = (o / outerStride) * sumStride; for (SizeT i = 0; i < sumStride; ++i) { SizeT oi = o + i; SizeT oiLimit = sumLimit + oi; for (SizeT s = oi; s < oiLimit; s += sumStride) (*res)[ rIx] += (*src)[ s]; ++rIx; } } } } return res; } // cumulative over one dim template< typename T> BaseGDL* total_over_dim_cu_template( T* res, SizeT sumDimIx, bool omitNaN) { SizeT nEl = res->N_Elements(); const dimension& resDim = res->Dim(); if (omitNaN) { for (SizeT i = 0; i < nEl; ++i) NaN2Zero((*res)[i]); } SizeT cumStride = resDim.Stride(sumDimIx); SizeT outerStride = resDim.Stride(sumDimIx + 1); for (SizeT o = 0; o < nEl; o += outerStride) { SizeT cumLimit = o + outerStride; for (SizeT i = o + cumStride, ii = o; i < cumLimit; ++i, ++ii) (*res)[ i] += (*res)[ ii]; } return res; } BaseGDL* total_fun( EnvT* e) { SizeT nParam = e->NParam(1); //, "TOTAL"); BaseGDL* p0 = e->GetParDefined(0); //, "TOTAL"); SizeT nEl = p0->N_Elements(); if (nEl == 0) e->Throw("Variable is undefined: " + e->GetParString(0)); if (p0->Type() == GDL_STRING) e->Throw("String expression not allowed " "in this context: " + e->GetParString(0)); static int cumIx = e->KeywordIx("CUMULATIVE"); static int intIx = e->KeywordIx("INTEGER"); static int doubleIx = e->KeywordIx("DOUBLE"); static int nanIx = e->KeywordIx("NAN"); static int preserveIx = e->KeywordIx("PRESERVE_TYPE"); bool cumulative = e->KeywordSet(cumIx); bool intRes = e->KeywordSet(intIx); bool doubleRes = e->KeywordSet(doubleIx); bool nan = e->KeywordSet(nanIx); bool preserve = e->KeywordSet(preserveIx); DLong sumDim = 0; if (nParam == 2) e->AssureLongScalarPar(1, sumDim); if (sumDim == 0) { if (!cumulative) { if (preserve) { switch (p0->Type()) { case GDL_BYTE: return total_template(static_cast (p0), false); case GDL_INT: return total_template(static_cast (p0), false); case GDL_UINT: return total_template(static_cast (p0), false); case GDL_LONG: return total_template(static_cast (p0), false); case GDL_ULONG: return total_template(static_cast (p0), false); case GDL_LONG64: return total_template(static_cast (p0), false); case GDL_ULONG64: return total_template(static_cast (p0), false); case GDL_FLOAT: return total_template(static_cast (p0), nan); case GDL_DOUBLE: return total_template(static_cast (p0), nan); case GDL_COMPLEX: return total_template(static_cast (p0), nan); case GDL_COMPLEXDBL: return total_template(static_cast (p0), nan); default: assert(false); } } // Integer parts by Erin Sheldon // In IDL total(), the INTEGER keyword takes precedence if (intRes) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if (p0->Type() == GDL_LONG64) { return total_template (static_cast (p0), nan); } if (p0->Type() == GDL_ULONG64) { return total_template (static_cast (p0), nan); } // Conver to Long64 DLong64GDL* p0L64 = static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)); Guard guard(p0L64); return total_template(p0L64, nan); } // integer results if (p0->Type() == GDL_DOUBLE) { return total_template (static_cast (p0), nan); } if (p0->Type() == GDL_COMPLEXDBL) { return total_template (static_cast (p0), nan); } // AC 2018-feb doc. said Long64 & ULong64 too, but when ?! TBC ! if (!doubleRes) { if (p0->Type() == GDL_FLOAT) { return total_template (static_cast (p0), nan); } if (p0->Type() == GDL_COMPLEX) { return total_template (static_cast (p0), nan); } // AC 2018-feb // cout << "hello default general case" << endl; // the ulong64 is missing if (p0->Type() == GDL_BYTE || p0->Type() == GDL_INT || p0->Type() == GDL_LONG || p0->Type() == GDL_LONG64) { // Conver to Long64 DLong64GDL* p0L64 = static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)); Guard guard(p0L64); BaseGDL* tmp; tmp= total_template(p0L64, nan); if (p0->Type() == GDL_LONG64) return tmp->Convert2(GDL_DOUBLE, BaseGDL::COPY); return tmp->Convert2(GDL_FLOAT, BaseGDL::COPY); } if (p0->Type() == GDL_ULONG || p0->Type() == GDL_ULONG64) { // Conver to ULong64 DULong64GDL* p0UL64 = static_cast (p0->Convert2(GDL_ULONG64, BaseGDL::COPY)); Guard guard(p0UL64); BaseGDL* tmp; tmp= total_template(p0UL64, nan); if (p0->Type() == GDL_ULONG64) return tmp->Convert2(GDL_DOUBLE, BaseGDL::COPY); return tmp->Convert2(GDL_FLOAT, BaseGDL::COPY); } DFloatGDL* p0F = static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); Guard guard(p0F); return total_template(p0F, false); } if (p0->Type() == GDL_COMPLEX) { DComplexDblGDL* p0D = static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); Guard p0D_guard(p0D); return total_template(p0D, nan); } DDoubleGDL* p0D = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); Guard p0D_guard(p0D); return total_template(p0D, nan); } else // cumulative { if (preserve) { switch (p0->Type()) { case GDL_BYTE: return total_cu_template(static_cast (p0->Dup()), false); case GDL_INT: return total_cu_template(static_cast (p0->Dup()), false); case GDL_UINT: return total_cu_template(static_cast (p0->Dup()), false); case GDL_LONG: return total_cu_template(static_cast (p0->Dup()), false); case GDL_ULONG: return total_cu_template(static_cast (p0->Dup()), false); case GDL_LONG64: return total_cu_template(static_cast (p0->Dup()), false); case GDL_ULONG64: return total_cu_template(static_cast (p0->Dup()), false); case GDL_FLOAT: return total_cu_template(static_cast (p0->Dup()), nan); case GDL_DOUBLE: return total_cu_template(static_cast (p0->Dup()), nan); case GDL_COMPLEX: return total_cu_template(static_cast (p0->Dup()), nan); case GDL_COMPLEXDBL: return total_cu_template(static_cast (p0->Dup()), nan); default: assert(false); } } // INTEGER keyword takes precedence if (intRes) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if (p0->Type() == GDL_LONG64) { return total_cu_template (static_cast (p0->Dup()), nan); } if (p0->Type() == GDL_ULONG64) { return total_cu_template (static_cast (p0->Dup()), nan); } // Convert to Long64 return total_cu_template (static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)), nan); } // integer results // special case as GDL_DOUBLE type overrides /GDL_DOUBLE if (p0->Type() == GDL_DOUBLE) { return total_cu_template< DDoubleGDL> (static_cast (p0->Dup()), nan); } if (p0->Type() == GDL_COMPLEXDBL) { return total_cu_template< DComplexDblGDL> (static_cast (p0->Dup()), nan); } if (!doubleRes && p0->Type() != GDL_LONG64 && p0->Type() != GDL_ULONG64) { // special case for GDL_FLOAT has no advantage here if (p0->Type() == GDL_COMPLEX) { return total_cu_template< DComplexGDL> (static_cast (p0->Dup()), nan); } return total_cu_template< DFloatGDL> (static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)), nan); } if (p0->Type() == GDL_COMPLEX) { return total_cu_template< DComplexDblGDL> (static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)), nan); } return total_cu_template< DDoubleGDL> (static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)), nan); } } // total over sumDim dimension srcDim = p0->Dim(); SizeT srcRank = srcDim.Rank(); if (sumDim < 1 || sumDim > srcRank) e->Throw( "Array must have " + i2s(sumDim) + " dimensions: " + e->GetParString(0)); if (!cumulative) { if (preserve) { switch (p0->Type()) { case GDL_BYTE: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_INT: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_UINT: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_LONG: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_ULONG: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_LONG64: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_ULONG64: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, false); case GDL_FLOAT: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nan); case GDL_DOUBLE: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nan); case GDL_COMPLEX: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nan); case GDL_COMPLEXDBL: return total_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nan); default: assert(false); } } // INTEGER keyword takes precedence if (intRes) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if (p0->Type() == GDL_LONG64) { return total_over_dim_template (static_cast (p0), srcDim, sumDim - 1, nan); } if (p0->Type() == GDL_ULONG64) { return total_over_dim_template (static_cast (p0), srcDim, sumDim - 1, nan); } // Conver to Long64 DLong64GDL* p0L64 = static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)); Guard p0L64_guard(p0L64); return total_over_dim_template (p0L64, srcDim, sumDim - 1, nan); } // integer results if (p0->Type() == GDL_DOUBLE) { return total_over_dim_template< DDoubleGDL> (static_cast (p0), srcDim, sumDim - 1, nan); } if (p0->Type() == GDL_COMPLEXDBL) { return total_over_dim_template< DComplexDblGDL> (static_cast (p0), srcDim, sumDim - 1, nan); } if (!doubleRes) { if (p0->Type() == GDL_FLOAT) { return total_over_dim_template< DFloatGDL> (static_cast (p0), srcDim, sumDim - 1, nan); } if (p0->Type() == GDL_COMPLEX) { return total_over_dim_template< DComplexGDL> (static_cast (p0), srcDim, sumDim - 1, nan); } // default for NOT /GDL_DOUBLE DFloatGDL* p0F = static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); Guard p0F_guard(p0F); // p0F_guard.Reset( p0F); return total_over_dim_template< DFloatGDL> (p0F, srcDim, sumDim - 1, false); } if (p0->Type() == GDL_COMPLEX) { DComplexDblGDL* p0D = static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); Guard p0D_guard(p0D); // p0D_guard.Reset( p0D); return total_over_dim_template< DComplexDblGDL> (p0D, srcDim, sumDim - 1, nan); } // default for /GDL_DOUBLE DDoubleGDL* p0D = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); Guard p0D_guard(p0D); //p0D_guard.Reset( p0D); return total_over_dim_template< DDoubleGDL>(p0D, srcDim, sumDim - 1, nan); } else // cumulative { if (preserve) { switch (p0->Type()) { case GDL_BYTE: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_INT: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_UINT: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_LONG: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_ULONG: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_LONG64: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_ULONG64: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, false); case GDL_FLOAT: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nan); case GDL_DOUBLE: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nan); case GDL_COMPLEX: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nan); case GDL_COMPLEXDBL: return total_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nan); default: assert(false); } } // INTEGER keyword takes precedence if (intRes) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if (p0->Type() == GDL_LONG64) { return total_over_dim_cu_template (static_cast (p0->Dup()), sumDim - 1, nan); } if (p0->Type() == GDL_ULONG64) { return total_over_dim_cu_template (static_cast (p0->Dup()), sumDim - 1, nan); } // Convert to Long64 return total_over_dim_cu_template (static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)), sumDim - 1, nan); } // integer results if (p0->Type() == GDL_DOUBLE) { return total_over_dim_cu_template< DDoubleGDL> (static_cast (p0->Dup()), sumDim - 1, nan); } if (p0->Type() == GDL_COMPLEXDBL) { return total_over_dim_cu_template< DComplexDblGDL> (static_cast (p0->Dup()), sumDim - 1, nan); } if (!doubleRes) { // special case for GDL_FLOAT has no advantage here if (p0->Type() == GDL_COMPLEX) { return total_over_dim_cu_template< DComplexGDL> (static_cast (p0->Dup()), sumDim - 1, nan); } // default for NOT /GDL_DOUBLE return total_over_dim_cu_template< DFloatGDL> (static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)), sumDim - 1, nan); } if (p0->Type() == GDL_COMPLEX) { return total_over_dim_cu_template< DComplexDblGDL> (static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)), sumDim - 1, nan); } // default for /GDL_DOUBLE return total_over_dim_cu_template< DDoubleGDL> (static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)), sumDim - 1, nan); } } // passing 2nd argument by value is slightly better for float and double, // but incur some overhead for the complex class. template inline void MultOmitNaN(T& dest, T value) { if (std::isfinite(value)) { // #pragma omp atomic dest *= value; } } template inline void MultOmitNaNCpx(T& dest, T value) { dest *= T(std::isfinite(value.real())? value.real() : 1, std::isfinite(value.imag())? value.imag() : 1); } template<> inline void MultOmitNaN(DComplex& dest, DComplex value) { MultOmitNaNCpx(dest, value); } template<> inline void MultOmitNaN(DComplexDbl& dest, DComplexDbl value) { MultOmitNaNCpx(dest, value); } template inline void Nan2One(T& value) { if (!std::isfinite(value)) value = 1; } template inline void Nan2OneCpx(T& value) { value = T(std::isfinite(value.real())? value.real() : 1, std::isfinite(value.imag())? value.imag() : 1); } template<> inline void Nan2One(DComplex& value) { Nan2OneCpx< DComplex>(value); } template<> inline void Nan2One(DComplexDbl& value) { Nan2OneCpx< DComplexDbl>(value); } // product over all elements template BaseGDL* product_template( T* src, bool omitNaN) { typename T::Ty prod = 1; SizeT nEl = src->N_Elements(); if (!omitNaN) { TRACEOMP(__FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared(prod) { #pragma omp for reduction(*:prod) for (OMPInt i = 0; i < nEl; ++i) { prod *= (*src)[ i]; } } } else { TRACEOMP(__FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared(prod) { #pragma omp for reduction(*:prod) for (OMPInt i = 0; i < nEl; ++i) { MultOmitNaN(prod, (*src)[ i]); } } } return new T(prod); } template<> BaseGDL* product_template( DComplexGDL* src, bool omitNaN) { DComplexGDL::Ty prod = 1; SizeT nEl = src->N_Elements(); if (!omitNaN) { for (SizeT i = 0; i < nEl; ++i) { prod *= (*src)[ i]; } } else { for (SizeT i = 0; i < nEl; ++i) { MultOmitNaN(prod, (*src)[ i]); } } return new DComplexGDL(prod); } template<> BaseGDL* product_template( DComplexDblGDL* src, bool omitNaN) { DComplexDblGDL::Ty prod = 1; SizeT nEl = src->N_Elements(); if (!omitNaN) { for (SizeT i = 0; i < nEl; ++i) { prod *= (*src)[ i]; } } else { for (SizeT i = 0; i < nEl; ++i) { MultOmitNaN(prod, (*src)[ i]); } } return new DComplexDblGDL(prod); } // cumulative over all dims template BaseGDL* product_cu_template( T* res, bool omitNaN) { SizeT nEl = res->N_Elements(); if (omitNaN) { for (SizeT i = 0; i < nEl; ++i) Nan2One((*res)[i]); } for (SizeT i = 1, ii = 0; i < nEl; ++i, ++ii) (*res)[i] *= (*res)[ii]; return res; } // product over one dim template< typename T> BaseGDL* product_over_dim_template( T* src, const dimension& srcDim, SizeT prodDimIx, bool omitNaN) { SizeT nEl = src->N_Elements(); // get dest dim and number of products dimension destDim = srcDim; SizeT nProd = destDim.Remove(prodDimIx); T* res = new T(destDim, BaseGDL::NOZERO); // prodStride is also the number of linear src indexing SizeT prodStride = srcDim.Stride(prodDimIx); SizeT outerStride = srcDim.Stride(prodDimIx + 1); SizeT prodLimit = nProd * prodStride; if (omitNaN) { #pragma omp parallel if ((nEl/outerStride)*prodStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*prodStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { SizeT rIx = (o / outerStride) * prodStride; for (SizeT i = 0; i < prodStride; ++i) { (*res)[ rIx] = 1; SizeT oi = o + i; SizeT oiLimit = prodLimit + oi; for (SizeT s = oi; s < oiLimit; s += prodStride) MultOmitNaN((*res)[ rIx], (*src)[ s]); ++rIx; } } } } else { #pragma omp parallel if ((nEl/outerStride)*prodStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*prodStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { SizeT rIx = (o / outerStride) * prodStride; for (SizeT i = 0; i < prodStride; ++i) { (*res)[ rIx] = 1; SizeT oi = o + i; SizeT oiLimit = prodLimit + oi; for (SizeT s = oi; s < oiLimit; s += prodStride) (*res)[ rIx] *= (*src)[ s]; ++rIx; } } } } return res; } // cumulative over one dim template< typename T> BaseGDL* product_over_dim_cu_template( T* res, SizeT sumDimIx, bool omitNaN) { SizeT nEl = res->N_Elements(); const dimension& resDim = res->Dim(); if (omitNaN) { for (SizeT i = 0; i < nEl; ++i) Nan2One((*res)[i]); } SizeT cumStride = resDim.Stride(sumDimIx); SizeT outerStride = resDim.Stride(sumDimIx + 1); for (SizeT o = 0; o < nEl; o += outerStride) { SizeT cumLimit = o + outerStride; for (SizeT i = o + cumStride, ii = o; i < cumLimit; ++i, ++ii) (*res)[ i] *= (*res)[ ii]; } return res; } BaseGDL* product_fun( EnvT* e) { SizeT nParam = e->NParam(1); BaseGDL* p0 = e->GetParDefined(0); SizeT nEl = p0->N_Elements(); if (nEl == 0) e->Throw("Variable is undefined: " + e->GetParString(0)); if (p0->Type() == GDL_STRING) e->Throw("String expression not allowed " "in this context: " + e->GetParString(0)); static int cumIx = e->KeywordIx("CUMULATIVE"); static int nanIx = e->KeywordIx("NAN"); static int intIx = e->KeywordIx("INTEGER"); static int preIx = e->KeywordIx("PRESERVE_TYPE"); bool KwCumul = e->KeywordSet(cumIx); bool KwNaN = e->KeywordSet(nanIx); bool KwInt = e->KeywordSet(intIx); bool KwPre = e->KeywordSet(preIx); bool nanInt = false; DLong sumDim = 0; if (nParam == 2) e->AssureLongScalarPar(1, sumDim); if (sumDim == 0) { if (!KwCumul) { if (KwPre) { switch (p0->Type()) { case GDL_BYTE: return product_template(static_cast (p0), nanInt); case GDL_INT: return product_template(static_cast (p0), nanInt); case GDL_UINT: return product_template(static_cast (p0), nanInt); case GDL_LONG: return product_template(static_cast (p0), nanInt); case GDL_ULONG: return product_template(static_cast (p0), nanInt); case GDL_LONG64: return product_template(static_cast (p0), nanInt); case GDL_ULONG64: return product_template(static_cast (p0), nanInt); case GDL_FLOAT: return product_template(static_cast (p0), KwNaN); case GDL_DOUBLE: return product_template(static_cast (p0), KwNaN); case GDL_COMPLEX: return product_template(static_cast (p0), KwNaN); case GDL_COMPLEXDBL: return product_template(static_cast (p0), KwNaN); default: assert(false); } } // Integer parts derivated from Total code by Erin Sheldon // In IDL PRODUCT(), the INTEGER keyword takes precedence if (KwInt) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if ((p0->Type() == GDL_LONG64) && (!KwNaN)) { return product_template (static_cast (p0), nanInt); } if ((p0->Type() == GDL_ULONG64) && (!KwNaN)) { return product_template (static_cast (p0), nanInt); } // Convert to Long64 DLong64GDL* p0L64 = static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)); Guard guard(p0L64); if (KwNaN) { DFloatGDL* p0f = static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); Guard guard(p0f); for (SizeT i = 0; i < nEl; ++i) { if (!std::isfinite((*p0f)[i])) (*p0L64)[i] = 1; } } return product_template(p0L64, nanInt); } // integer results if (p0->Type() == GDL_DOUBLE) { return product_template (static_cast (p0), KwNaN); } if (p0->Type() == GDL_COMPLEXDBL) { return product_template (static_cast (p0), KwNaN); } if (p0->Type() == GDL_COMPLEX) { DComplexDblGDL* p0D = static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); Guard p0D_guard(p0D); //p0D_guard.Reset( p0D); return product_template(p0D, KwNaN); } DDoubleGDL* p0D = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); Guard p0D_guard(p0D); // p0D_guard.Reset( p0D); return product_template(p0D, KwNaN); } else { // KwCumul if (KwPre) { switch (p0->Type()) { case GDL_BYTE: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_INT: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_UINT: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_LONG: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_ULONG: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_LONG64: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_ULONG64: return product_cu_template(static_cast (p0->Dup()), nanInt); case GDL_FLOAT: return product_cu_template(static_cast (p0->Dup()), KwNaN); case GDL_DOUBLE: return product_cu_template(static_cast (p0->Dup()), KwNaN); case GDL_COMPLEX: return product_cu_template(static_cast (p0->Dup()), KwNaN); case GDL_COMPLEXDBL: return product_cu_template(static_cast (p0->Dup()), KwNaN); default: assert(false); } } // Integer parts derivated from Total code by Erin Sheldon // In IDL PRODUCT(), the INTEGER keyword takes precedence if (KwInt) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if ((p0->Type() == GDL_LONG64) && (!KwNaN)) { return product_cu_template (static_cast (p0->Dup()), nanInt); } if ((p0->Type() == GDL_ULONG64) && (!KwNaN)) { return product_cu_template (static_cast (p0->Dup()), nanInt); } // Convert to Long64 DLong64GDL* p0L64 = static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)); Guard guard(p0L64); if (KwNaN) { DFloatGDL* p0f = static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); Guard guard(p0f); for (SizeT i = 0; i < nEl; ++i) { if (!std::isfinite((*p0f)[i])) (*p0L64)[i] = 1; } } return product_cu_template (static_cast (p0L64->Dup()), nanInt); } // integer results // special case as GDL_DOUBLE type overrides /GDL_DOUBLE if (p0->Type() == GDL_DOUBLE) { return product_cu_template< DDoubleGDL> (static_cast (p0->Dup()), KwNaN); } if (p0->Type() == GDL_COMPLEXDBL) { return product_cu_template< DComplexDblGDL> (static_cast (p0->Dup()), KwNaN); } if (p0->Type() == GDL_COMPLEX) { return product_cu_template< DComplexDblGDL> (static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)), KwNaN); } return product_cu_template< DDoubleGDL> (static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)), KwNaN); } } // product over sumDim dimension srcDim = p0->Dim(); SizeT srcRank = srcDim.Rank(); if (sumDim < 1 || sumDim > srcRank) e->Throw("Array must have " + i2s(sumDim) + " dimensions: " + e->GetParString(0)); if (!KwCumul) { if (KwPre) { switch (p0->Type()) { case GDL_BYTE: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_INT: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_UINT: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_LONG: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_ULONG: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_LONG64: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_ULONG64: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, nanInt); case GDL_FLOAT: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, KwNaN); case GDL_DOUBLE: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, KwNaN); case GDL_COMPLEX: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, KwNaN); case GDL_COMPLEXDBL: return product_over_dim_template(static_cast (p0), srcDim, sumDim - 1, KwNaN); default: assert(false); } } // Integer parts derivated from Total code by Erin Sheldon // In IDL PRODUCT(), the INTEGER keyword takes precedence if (KwInt) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if ((p0->Type() == GDL_LONG64) && (!KwNaN)) { return product_over_dim_template (static_cast (p0), srcDim, sumDim - 1, nanInt); } if ((p0->Type() == GDL_ULONG64) && (!KwNaN)) { return product_over_dim_template (static_cast (p0), srcDim, sumDim - 1, nanInt); } // Conver to Long64 DLong64GDL* p0L64 = static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)); Guard guard(p0L64); if (KwNaN) { DFloatGDL* p0f = static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); Guard guard(p0f); for (SizeT i = 0; i < nEl; ++i) { if (!std::isfinite((*p0f)[i])) (*p0L64)[i] = 1; } } return product_over_dim_template (p0L64, srcDim, sumDim - 1, nanInt); } // integer results if (p0->Type() == GDL_DOUBLE) { return product_over_dim_template< DDoubleGDL> (static_cast (p0), srcDim, sumDim - 1, KwNaN); } if (p0->Type() == GDL_COMPLEXDBL) { return product_over_dim_template< DComplexDblGDL> (static_cast (p0), srcDim, sumDim - 1, KwNaN); } if (p0->Type() == GDL_COMPLEX) { DComplexDblGDL* p0D = static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); Guard p0D_guard(p0D); // p0D_guard.Reset( p0D); return product_over_dim_template< DComplexDblGDL> (p0D, srcDim, sumDim - 1, KwNaN); } DDoubleGDL* p0D = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); Guard p0D_guard(p0D); //p0D_guard.Reset( p0D); return product_over_dim_template< DDoubleGDL> (p0D, srcDim, sumDim - 1, KwNaN); } else { // KwCumul if (KwPre) { switch (p0->Type()) { case GDL_BYTE: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_INT: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_UINT: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_LONG: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_ULONG: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_LONG64: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_ULONG64: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, nanInt); case GDL_FLOAT: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, KwNaN); case GDL_DOUBLE: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, KwNaN); case GDL_COMPLEX: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, KwNaN); case GDL_COMPLEXDBL: return product_over_dim_cu_template(static_cast (p0->Dup()), sumDim - 1, KwNaN); default: assert(false); } } // Integer parts derivated from Total code by Erin Sheldon // In IDL PRODUCT(), the INTEGER keyword takes precedence if (KwInt) { // We use GDL_LONG64 unless the input is GDL_ULONG64 if ((p0->Type() == GDL_LONG64) && (!KwNaN)) { return product_over_dim_cu_template (static_cast (p0->Dup()), sumDim - 1, nanInt); } if ((p0->Type() == GDL_ULONG64) && (!KwNaN)) { return product_over_dim_cu_template (static_cast (p0->Dup()), sumDim - 1, nanInt); } // Convert to Long64 if (KwNaN) { DFloatGDL* p0f = static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); Guard guard(p0f); for (SizeT i = 0; i < nEl; ++i) { if (!std::isfinite((*p0f)[i])) (*p0f)[i] = 1; } return product_over_dim_cu_template (static_cast (p0f->Convert2(GDL_LONG64, BaseGDL::COPY)), sumDim - 1, nanInt); } else { return product_over_dim_cu_template (static_cast (p0->Convert2(GDL_LONG64, BaseGDL::COPY)), sumDim - 1, nanInt); } } // integer results if (p0->Type() == GDL_DOUBLE) { return product_over_dim_cu_template< DDoubleGDL> (static_cast (p0->Dup()), sumDim - 1, KwNaN); } if (p0->Type() == GDL_COMPLEXDBL) { return product_over_dim_cu_template< DComplexDblGDL> (static_cast (p0->Dup()), sumDim - 1, KwNaN); } if (p0->Type() == GDL_COMPLEX) { return product_over_dim_cu_template< DComplexDblGDL> (static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)), sumDim - 1, KwNaN); } return product_over_dim_cu_template< DDoubleGDL> (static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)), sumDim - 1, KwNaN); } } // servicing array_equal and also gdl_container::equals bool array_equal_bool( BaseGDL* p0, BaseGDL* p1, bool notypeconv=false, bool not_equal=false, bool quiet=true) { if( p0 == p1) return true; if( p0==0 or p1==0) return false; SizeT nEl0 = p0->N_Elements(); SizeT nEl1 = p1->N_Elements(); // first case : arrays with differents size (>1) if (nEl0 != nEl1 && nEl0 != 1 && nEl1 != 1) return false; // if one of input has only one element, it should NOt be an array // ARRAY_EQUAL(1,[1,1]) True, ARRAY_EQUAL([1],[1,1]) False !! if (nEl0 != nEl1) { if (nEl0 == 1 && nEl1 != 1) { if (!p0->StrictScalar()) return false; } if (nEl0 != 1 && nEl1 == 1) { if (!p1->StrictScalar()) return false; } } //cout << "pO "<< p0->Dim() << " p1 "<< p1->Dim() << endl; //cout << "pO "<< p0->StrictScalar() << " p1 "<< p1->StrictScalar() << endl; DType aTy=p0->Type(); DType bTy=p1->Type(); if( aTy==GDL_STRUCT or bTy==GDL_STRUCT) { if(quiet) return false; throw GDLException("array_equal: inconvertable GDL_STRUCT"); } Guard p0_guard; Guard p1_guard; if( ( aTy==GDL_PTR and bTy==GDL_PTR) or ( aTy==GDL_OBJ and bTy==GDL_OBJ) ) { Data_* p0t = static_cast* >( p0); if( not_equal) return p0t->ArrayNeverEqual( p1); else return p0t->ArrayEqual( p1); } else if( aTy==GDL_PTR or bTy==GDL_PTR) { if(quiet) return false; throw GDLException("array_equal: GDL_PTR only with PTR"); } else if( aTy==GDL_OBJ or bTy==GDL_OBJ) { if(quiet) return false; throw GDLException("array_equal: GDL_OBJ only with OBJ"); } else if( aTy != bTy) { if( notypeconv) // NO_TYPECONV return false; else { if( !ConvertableType( aTy) or !ConvertableType( bTy)) { if(quiet) return false; throw GDLException("array_equal: inconvertable type"); } else if( DTypeOrder[aTy] >= DTypeOrder[bTy]) { p1 = p1->Convert2(aTy, BaseGDL::COPY); p1_guard.Reset(p1); } else { p0 = p0->Convert2(bTy, BaseGDL::COPY); p0_guard.Reset(p0); } } } if( not_equal) return p0->ArrayNeverEqual( p1); else return p0->ArrayEqual( p1); } BaseGDL* array_equal( EnvT* e) { e->NParam( 2); // trace_me = trace_arg(); static int notypeconvIx = e->KeywordIx("NO_TYPECONV"); static int notequalIx = e->KeywordIx("NOT_EQUAL"); static int quietIx = e->KeywordIx("QUIET"); // if(trace_me) cout << " array=? "; BaseGDL* p0 = e->GetParDefined( 0); BaseGDL* p1 = e->GetParDefined( 1); bool result = array_equal_bool(p0, p1, e->KeywordSet( notypeconvIx), e->KeywordSet( notequalIx), e->KeywordSet( quietIx)); // if(trace_me) cout << result<< endl; return new DByteGDL( result ? 1 : 0 ); } BaseGDL* min_fun( EnvT* e) { SizeT nParam = e->NParam(1); BaseGDL* searchArr = e->GetParDefined(0); static int omitNaNIx = e->KeywordIx("NAN"); bool omitNaN = e->KeywordSet(omitNaNIx); static int subIx = e->KeywordIx("SUBSCRIPT_MAX"); bool subMax = e->KeywordPresent(subIx); static int dimIx = e->KeywordIx("DIMENSION"); bool dimSet = e->KeywordSet(dimIx); static int maxIx = e->KeywordIx("MAX"); bool maxSet = e->KeywordPresent(maxIx); static int absIx= e->KeywordIx("ABSOLUTE"); bool absSet = e->KeywordSet(absIx); // not KeywordPresent as it should be ignored if not set. DLong searchDim; if (dimSet) { e->AssureLongScalarKW(dimIx, searchDim); if (searchDim < 0 || searchDim > searchArr->Rank()) e->Throw("Illegal keyword value for DIMENSION"); } if (dimSet && searchArr->Rank() > 1) { searchDim -= 1; // user-supplied dimensions start with 1! // here destDim is in fact the srcDim... dimension destDim = searchArr->Dim(); SizeT searchStride = destDim.Stride(searchDim); SizeT outerStride = destDim.Stride(searchDim + 1); // ... and now becomes the destDim SizeT nSearch = destDim.Remove(searchDim); SizeT searchLimit = nSearch * searchStride; SizeT nEl = searchArr->N_Elements(); // memory allocation BaseGDL *maxVal, *resArr = searchArr->New(destDim, BaseGDL::NOZERO); DLongGDL *minElArr, *maxElArr; if (maxSet) { e->AssureGlobalKW(maxIx); // instead of using a guard pointer maxVal = searchArr->New(destDim, BaseGDL::NOZERO); } if (subMax) { e->AssureGlobalKW(subIx); // instead of using a guard pointer maxElArr = new DLongGDL(destDim); } if (nParam == 2) { e->AssureGlobalPar(1); // instead of using a guard pointer minElArr = new DLongGDL(destDim); } SizeT rIx = 0; #pragma omp parallel if ((nEl/outerStride)*searchStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*searchStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { SizeT rIx = (o / outerStride) * searchStride; for (SizeT i = 0; i < searchStride; ++i) { searchArr->MinMax( (nParam == 2 ? &((*minElArr)[rIx]) : NULL), (subMax ? &((*maxElArr)[rIx]) : NULL), &resArr, (maxSet ? &maxVal : NULL), omitNaN, o + i, searchLimit + o + i, searchStride, rIx, absSet ); rIx++; } } } if (nParam == 2) e->SetPar(1, minElArr); if (subMax) e->SetKW(subIx, maxElArr); if (maxSet) e->SetKW(maxIx, maxVal); return resArr; } else { DLong minEl; BaseGDL* res; if (maxSet) // MAX keyword given { e->AssureGlobalKW(0); GDLDelete(e->GetKW(0)); DLong maxEl; searchArr->MinMax(&minEl, &maxEl, &res, &e->GetKW(0), omitNaN, 0, 0, 1, -1, absSet); if (subMax) e->SetKW(subIx, new DLongGDL(maxEl)); } else // no MAX keyword { if (subMax) { DLong maxEl; searchArr->MinMax(&minEl, &maxEl, &res, NULL, omitNaN, 0, 0, 1, -1, absSet); e->SetKW(subIx, new DLongGDL(maxEl)); } else searchArr->MinMax(&minEl, NULL, &res, NULL, omitNaN, 0, 0, 1, -1, absSet); } // handle index if (nParam == 2) e->SetPar(1, new DLongGDL(minEl)); else SysVar::SetC(minEl); return res; } } BaseGDL* max_fun( EnvT* e) { SizeT nParam = e->NParam(1); BaseGDL* searchArr = e->GetParDefined(0); static int omitNaNIx = e->KeywordIx("NAN"); bool omitNaN = e->KeywordSet(omitNaNIx); static int subIx = e->KeywordIx("SUBSCRIPT_MIN"); bool subMin = e->KeywordPresent(subIx); static int dimIx = e->KeywordIx("DIMENSION"); bool dimSet = e->KeywordSet(dimIx); static int minIx = e->KeywordIx("MIN"); bool minSet = e->KeywordPresent(minIx); static int absIx= e->KeywordIx("ABSOLUTE"); bool absSet = e->KeywordSet(absIx); // not KeywordPresent as it should be ignored if not set. DLong searchDim; if (dimSet) { e->AssureLongScalarKW(dimIx, searchDim); if (searchDim < 0 || searchDim > searchArr->Rank()) e->Throw("Illegal keyword value for DIMENSION"); } if (dimSet && searchArr->Rank() > 1) { searchDim -= 1; // user-supplied dimensions start with 1! // here destDim is in fact the srcDim... dimension destDim = searchArr->Dim(); SizeT searchStride = destDim.Stride(searchDim); SizeT outerStride = destDim.Stride(searchDim + 1); // ... and now becomes the destDim SizeT nSearch = destDim.Remove(searchDim); SizeT searchLimit = nSearch * searchStride; SizeT nEl = searchArr->N_Elements(); // memory allocation BaseGDL *minVal, *resArr = searchArr->New(destDim, BaseGDL::NOZERO); DLongGDL *minElArr, *maxElArr; if (minSet) { e->AssureGlobalKW(minIx); // instead of using a guard pointer minVal = searchArr->New(destDim, BaseGDL::NOZERO); } if (subMin) { e->AssureGlobalKW(subIx); // instead of using a guard pointer minElArr = new DLongGDL(destDim); } if (nParam == 2) { e->AssureGlobalPar(1); // instead of using a guard pointer maxElArr = new DLongGDL(destDim); } #pragma omp parallel if ((nEl/outerStride)*searchStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*searchStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { SizeT rIx = (o/outerStride)*searchStride; for (SizeT i = 0; i < searchStride; ++i) { searchArr->MinMax( (subMin ? &((*minElArr)[rIx]) : NULL), (nParam == 2 ? &((*maxElArr)[rIx]) : NULL), (minSet ? &minVal : NULL), &resArr, omitNaN, o + i, searchLimit + o + i, searchStride, rIx, absSet ); rIx++; } } } if (nParam == 2) e->SetPar(1, maxElArr); if (subMin) e->SetKW(subIx, minElArr); if (minSet) e->SetKW(minIx, minVal); return resArr; } else { DLong maxEl; BaseGDL* res; if (minSet) // MIN keyword given { e->AssureGlobalKW(0); GDLDelete(e->GetKW(0)); DLong minEl; searchArr->MinMax(&minEl, &maxEl, &e->GetKW(0), &res, omitNaN, 0, 0, 1, -1, absSet); if (subMin) e->SetKW(subIx, new DLongGDL(minEl)); } else // no MIN keyword { if (subMin) { DLong minEl; searchArr->MinMax(&minEl, &maxEl, NULL, &res, omitNaN, 0, 0, 1, -1, absSet); e->SetKW(subIx, new DLongGDL(minEl)); } else searchArr->MinMax(NULL, &maxEl, NULL, &res, omitNaN, 0, 0, 1, -1, absSet); } // handle index if (nParam == 2) e->SetPar(1, new DLongGDL(maxEl)); else SysVar::SetC(maxEl); return res; } } BaseGDL* transpose( EnvT* e) { SizeT nParam=e->NParam( 1); BaseGDL* p0 = e->GetParDefined( 0); if( p0->Type() == GDL_STRUCT) e->Throw("Struct expression not allowed in this context: "+ e->GetParString(0)); SizeT rank = p0->Rank(); if( rank == 0) e->Throw( "Expression must be an array " "in this context: "+ e->GetParString(0)); if( nParam == 2) { BaseGDL* p1 = e->GetParDefined( 1); if( p1->N_Elements() != rank) e->Throw("Incorrect number of elements in permutation."); DUInt* perm = new DUInt[rank]; ArrayGuard perm_guard( perm); DUIntGDL* p1L = static_cast (p1->Convert2( GDL_UINT, BaseGDL::COPY)); for( SizeT i=0; iThrow( "Incorrect permutation vector."); } return p0->Transpose( perm); } return p0->Transpose( NULL); } // BaseGDL* matrix_multiply( EnvT* e) // { // SizeT nParam=e->NParam( 2); // // BaseGDL* a = e->GetNumericArrayParDefined( 0); // BaseGDL* b = e->GetNumericArrayParDefined( 1); // // static int aTIx = e->KeywordIx("ATRANSPOSE"); // bool aT = e->KeywordPresent(aTIx); // static int bTIx = e->KeywordIx("BTRANSPOSE"); // bool bT = e->KeywordPresent(bTIx); // // static int strassenIx = e->KeywordIx("STRASSEN_ALGORITHM"); // bool strassen = e->KeywordPresent(strassenIx); // // // if( p1->N_Elements() != rank) // e->Throw("Incorrect number of elements in permutation."); // // DUInt* perm = new DUInt[rank]; // Guard perm_guard( perm); // // DUIntGDL* p1L = static_cast // (p1->Convert2( GDL_UINT, BaseGDL::COPY)); // for( SizeT i=0; iThrow( "Incorrect permutation vector."); // } // return p0->Transpose( perm); // } // // return a->Transpose( NULL); // } // helper function for sort_fun, recursive // optimized version template< typename IndexT> void MergeSortOpt( BaseGDL* p0, IndexT* hhS, IndexT* h1, IndexT* h2, SizeT len) { if( len <= 1) return; SizeT h1N = len / 2; SizeT h2N = len - h1N; // 1st half MergeSortOpt(p0, hhS, h1, h2, h1N); // 2nd half IndexT* hhM = &hhS[h1N]; MergeSortOpt(p0, hhM, h1, h2, h2N); SizeT i; for(i=0; iGreater( h1[h1Ix], h2[h2Ix])) hhS[ i] = h2[ h2Ix++]; else hhS[ i] = h1[ h1Ix++]; } for(; h1Ix < h1N; ++i) hhS[ i] = h1[ h1Ix++]; for(; h2Ix < h2N; ++i) hhS[ i] = h2[ h2Ix++]; } // helper function for sort_fun, recursive void MergeSort( BaseGDL* p0, SizeT* hh, SizeT* h1, SizeT* h2, SizeT start, SizeT end) { if( start+1 >= end) return; SizeT middle = (start+end) / 2; MergeSort(p0, hh, h1, h2, start, middle); MergeSort(p0, hh, h1, h2, middle, end); SizeT h1N = middle - start; SizeT h2N = end - middle; SizeT* hhS = &hh[start]; SizeT i; for(i=0; iGreater( h1[h1Ix], h2[h2Ix])) hhS[ i] = h2[ h2Ix++]; else hhS[ i] = h1[ h1Ix++]; } for(; h1Ix < h1N; ++i) hhS[ i] = h1[ h1Ix++]; for(; h2Ix < h2N; ++i) hhS[ i] = h2[ h2Ix++]; } // sort function uses MergeSort BaseGDL* sort_fun( EnvT* e) { e->NParam( 1); BaseGDL* p0 = e->GetParDefined( 0); if( p0->Type() == GDL_STRUCT) e->Throw( "Struct expression not allowed in this context: "+ e->GetParString(0)); static int l64Ix = e->KeywordIx( "L64"); bool l64 = e->KeywordSet( l64Ix); SizeT nEl = p0->N_Elements(); // helper arrays DLongGDL* res = new DLongGDL( dimension( nEl), BaseGDL::INDGEN); DLong nanIx = nEl; if( p0->Type() == GDL_FLOAT) { DFloatGDL* p0F = static_cast(p0); for( DLong i=nEl-1; i >= 0; --i) { if( isnan((*p0F)[ i]) )//|| !std::isfinite((*p0F)[ i])) { --nanIx; (*res)[i] = (*res)[nanIx]; (*res)[ nanIx] = i; // cout << "swap " << i << " with " << nanIx << endl; // cout << "now: "; // for( DLong ii=0; ii < nEl; ++ii) // { // cout << (*res)[ii] << " "; // } // cout << endl; } } } else if( p0->Type() == GDL_DOUBLE) { DDoubleGDL* p0F = static_cast(p0); for( DLong i=nEl-1; i >= 0; --i) { if( isnan((*p0F)[ i]))// || !std::isfinite((*p0F)[ i])) { --nanIx; (*res)[i] = (*res)[nanIx]; (*res)[ nanIx] = i; } } } else if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0F = static_cast(p0); for( DLong i=nEl-1; i >= 0; --i) { if( isnan((*p0F)[ i].real()) || //!std::isfinite((*p0F)[ i].real()) || isnan((*p0F)[ i].imag()))// || !std::isfinite((*p0F)[ i].imag()) ) { --nanIx; (*res)[i] = (*res)[nanIx]; (*res)[ nanIx] = i; } } } else if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* p0F = static_cast(p0); for( DLong i=nEl-1; i >= 0; --i) { if( isnan((*p0F)[ i].real()) || //!std::isfinite((*p0F)[ i].real()) || isnan((*p0F)[ i].imag()))// || !std::isfinite((*p0F)[ i].imag()) ) { --nanIx; (*res)[i] = (*res)[nanIx]; (*res)[ nanIx] = i; } } } // cout << "nEl " << nEl << " nanIx " << nanIx << endl; nEl = nanIx; // cout << "sorting: "; // for( DLong ii=0; ii < nEl; ++ii) // { // cout << (*res)[ii] << " "; // } // cout << endl; DLong *hh = static_cast(res->DataAddr()); DLong* h1 = new DLong[ nEl/2]; DLong* h2 = new DLong[ (nEl+1)/2]; // call the sort routine MergeSortOpt( p0, hh, h1, h2, nEl); delete[] h1; delete[] h2; if( l64) { // leave it this way, as sorting of more than 2^31 // items seems not feasible in the future we might // use MergeSortOpt(...) for this return res->Convert2( GDL_LONG64); } return res; } // start of highly-optimized median code. 1D and 2D fast medians are in medianfilter.cpp, gathered from // recent sources. see tjis file for explanations & copyrights. #include "medianfilter.cpp" /* * Following routines are variants of the algorithm described in * "Numerical recipes in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 * Original code by Nicolas Devillard - 1998. Public domain. * Modified by G. Duvert, 2017, for NaN/INF handling and correction of Nicolas's code * which gave erroneous results when two or more elements were identical. */ #define ELEM_SWAP(a,b) { DDouble t=(a);(a)=(b);(b)=t; } DDouble quick_select_d(DDouble array[], SizeT arraySize, int even) { if (arraySize==1) return array[0]; SizeT high, low, middle; SizeT median=(arraySize)/2; SizeT ll, hh; DDouble pivot; low = 0; high = arraySize-1; for (;;) { if (high <= low + 1) { if (high == low + 1 && array[high] < array[low]) { ELEM_SWAP(array[low], array[high]) } if (even) return 0.5*(array[median]+array[median-1]); else return array[median]; } else { middle = (low + high) /2 ; ELEM_SWAP(array[middle], array[low + 1]) if (array[low] > array[high]) { ELEM_SWAP(array[low], array[high]) } if (array[low + 1] > array[high]) { ELEM_SWAP(array[low + 1], array[high]) } if (array[low] > array[low + 1]) { ELEM_SWAP(array[low], array[low + 1]) } ll = low + 1; hh = high; pivot = array[low + 1]; for (;;) { do ll++; while (array[ll] < pivot); do hh--; while (array[hh] > pivot); if (hh < ll) break; ELEM_SWAP(array[ll], array[hh]) } array[low + 1] = array[hh]; array[hh] = pivot; if (hh >= median) high = hh - 1; if (hh <= median) low = ll; } } } #undef ELEM_SWAP #define ELEM_SWAP(a,b) { DFloat t=(a);(a)=(b);(b)=t; } DFloat quick_select_f(DFloat array[], SizeT arraySize, int even) { if (arraySize==1) return array[0]; SizeT high, low, middle; SizeT median=(arraySize)/2; SizeT ll, hh; DFloat pivot; low = 0; high = arraySize-1; for (;;) { if (high <= low + 1) { if (high == low + 1 && array[high] < array[low]) { ELEM_SWAP(array[low], array[high]) } if (even) return 0.5*(array[median]+array[median-1]); else return array[median]; } else { middle = (low + high) /2 ; ELEM_SWAP(array[middle], array[low + 1]) if (array[low] > array[high]) { ELEM_SWAP(array[low], array[high]) } if (array[low + 1] > array[high]) { ELEM_SWAP(array[low + 1], array[high]) } if (array[low] > array[low + 1]) { ELEM_SWAP(array[low], array[low + 1]) } ll = low + 1; hh = high; pivot = array[low + 1]; for (;;) { do ll++; while (array[ll] < pivot); do hh--; while (array[hh] > pivot); if (hh < ll) break; ELEM_SWAP(array[ll], array[hh]) } array[low + 1] = array[hh]; array[hh] = pivot; if (hh >= median) high = hh - 1; if (hh <= median) low = ll; } } } #undef ELEM_SWAP //input-protected versions of above DFloat quick_select_f_protect_input(const DFloat data[], SizeT arraySize, int even) { DFloat * array=(DFloat*)malloc(arraySize*sizeof(DFloat)); for (SizeT i = 0; i < arraySize; ++i) array[i]=data[i]; DFloat res=quick_select_f(array, arraySize, even); free(array); return res; } DDouble quick_select_d_protect_input(const DDouble data[], SizeT arraySize, int even) { DDouble * array=(DDouble*)malloc(arraySize*sizeof(DDouble)); for (SizeT i = 0; i < arraySize; ++i) array[i]=data[i]; DDouble res=quick_select_d(array, arraySize, even); free(array); return res; } //simple median for double arrays with no NaNs. inline BaseGDL* mymedian_d(EnvT* e) { DDoubleGDL* array = e->GetParAs(0)->Dup(); //original array is protected SizeT nEl = array->N_Elements(); static int evenIx = e->KeywordIx("EVEN"); int iseven = ((nEl % 2) == 0 && e->KeywordSet(evenIx)); BaseGDL *res = new DDoubleGDL(quick_select_d((DDouble*) array->DataAddr(), nEl, iseven)); delete array; return res; } //simple median for double arrays whith NaNs. Remove the Nans before doing the median. inline BaseGDL* mymedian_d_nan(EnvT* e) { DDoubleGDL* data = e->GetParAs(0); //original array is protected SizeT nEl = data->N_Elements(); DLong iEl = 0; DDouble * array=(DDouble*)malloc(nEl*sizeof(DDouble)); for (SizeT i = 0; i < data->N_Elements(); ++i) { if(!isnan( (*data)[i]) ) { array[iEl] = (*data)[i]; iEl++; } } if (iEl == 0) { free(array); return new DDoubleGDL(std::numeric_limits::quiet_NaN()); } static int evenIx = e->KeywordIx("EVEN"); int iseven = (((iEl + 1) % 2) == 0 && e->KeywordSet(evenIx)); BaseGDL *res = new DDoubleGDL(quick_select_d(array, iEl, iseven)); free(array); return res; } //simple median for double arrays whith NaNs. Remove the Nans before doing the median. inline DDouble quick_select_d_filter_nan( const DDouble* arr, SizeT nEl, int even) { DLong iEl = 0; DDouble* array=(DDouble*)malloc(nEl*sizeof(DDouble)); for (SizeT i = 0; i < nEl; ++i) { if (!isnan( arr[i]) ) { array[iEl] = arr[i]; iEl++; } } if (iEl == 0) { free(array); return std::numeric_limits::quiet_NaN(); } DDouble res=quick_select_d(array, iEl, even); free(array); return res; } inline bool hasnan_d( DDouble* arr, SizeT nEl) { for (SizeT i=0; i< nEl; ++i) if (isnan( arr[i])) return true; return false; } inline BaseGDL* mymedian_f(EnvT* e) { DFloatGDL* array = e->GetParAs(0)->Dup(); //original array is protected SizeT nEl = array->N_Elements(); static int evenIx = e->KeywordIx("EVEN"); int iseven=((nEl % 2) == 0 && e->KeywordSet(evenIx)); BaseGDL *res = new DFloatGDL(quick_select_f((DFloat*) array->DataAddr(), nEl, iseven)); delete array; return res; } inline BaseGDL* mymedian_f_nan(EnvT* e) { DFloatGDL* data = e->GetParAs(0); //original array is protected SizeT nEl = data->N_Elements(); DLong iEl = 0; DFloat * array=(DFloat*)malloc(nEl*sizeof(DFloat)); for (SizeT i = 0; i < data->N_Elements(); ++i) { if (!isnan( (*data)[i]) ) { array[iEl] = (*data)[i]; iEl++; } } if (iEl == 0) { free(array); return new DFloatGDL(std::numeric_limits::quiet_NaN()); } static int evenIx = e->KeywordIx("EVEN"); int iseven = (((iEl + 1) % 2) == 0 && e->KeywordSet(evenIx)); BaseGDL *res = new DFloatGDL(quick_select_f(array, iEl, iseven)); free(array); return res; } inline DFloat quick_select_f_filter_nan(const DFloat* arr, SizeT nEl, int even){ DLong iEl = 0; DFloat * array=(DFloat*)malloc(nEl*sizeof(DFloat)); for (SizeT i = 0; i < nEl; ++i) { if (!isnan( arr[i]) ) { array[iEl] = arr[i]; iEl++; } } if (iEl == 0) { free(array); return std::numeric_limits::quiet_NaN(); } DFloat res = quick_select_f(array, iEl, even); free(array); return res; } inline bool hasnan_f(DFloat* arr, SizeT nEl) { for (SizeT i = 0; i < nEl; ++i) if (isnan(arr[i])) return true; return false; } BaseGDL* SlowReliableMedian(EnvT* e); //see below. BaseGDL* median(EnvT* e) { BaseGDL* p0 = e->GetParDefined(0); SizeT nParam = e->NParam(1); //get number of parameters, must be >=1. if (p0->Rank() == 0) e->Throw("Expression must be an array in this context: " + e->GetParString(0)); if (p0->Type() == GDL_PTR) e->Throw("Pointer expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_OBJ) e->Throw("Object expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("Struct expression not allowed in this context: " + e->GetParString(0)); static int doubleIx = e->KeywordIx("DOUBLE"); bool dbl = (p0->Type() == GDL_DOUBLE || p0->Type() == GDL_COMPLEXDBL || e->KeywordSet(doubleIx)); //contrary to doc (?) EVEN is useable everywhere, 1D or 2D. static int evenIx = e->KeywordIx("EVEN"); if (nParam == 1) { // Check conversion to real or double: // Check possibility of Nan (not useful to speed down medians on integer data which // will never produce NaNs). bool possibleNaN = (p0->Type() == GDL_DOUBLE || p0->Type() == GDL_FLOAT || p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL); //DIMENSION Kw static int dimIx = e->KeywordIx("DIMENSION"); bool dimSet = e->KeywordSet(dimIx); DLong medianDim; if (dimSet) { e->AssureLongScalarKW(dimIx, medianDim); if (medianDim < 0 || medianDim > p0->Rank()) e->Throw("Illegal keyword value for DIMENSION"); } if (dimSet && p0->Rank() > 1) { medianDim -= 1; // user-supplied dimensions start with 1! // input/output dimensions: copy srcDim to destDim dimension destDim = p0->Dim(); // make array of dims for transpose DUInt* perm = new DUInt[p0->Rank()]; ArrayGuard perm_guard(perm); //useful to reorder dims for transpose to order data in continuous 'medianing' order. DUInt i = 0, j = 0; for (i = 0; i < p0->Rank(); ++i) if (i != medianDim) { perm[j + 1] = i; j++; } perm[0] = medianDim; // resize destDim destDim.Remove(medianDim); //compute stride and number of elements of result: SizeT stride = p0->Dim(medianDim); int iseven = ((stride % 2) == 0 && e->KeywordSet(evenIx)); SizeT nEl = destDim.NDimElementsConst(); //transpose p0 to arrange dimensions if medianDim is > 0. Do not forget to remove transposed array. bool clean_array = false; if (possibleNaN) { bool hasnan = false; if (dbl) { DDoubleGDL* input = e->GetParAs(0); if (medianDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DDoubleGDL* res = new DDoubleGDL(destDim, BaseGDL::NOZERO); //probably overkill to start multithreading in some easy cases. TBD. #pragma omp for private(i,hasnan) for (SizeT i = 0; i < nEl; ++i) { if (hasnan_d(&(*input)[i * stride], stride)) (*res)[i] = quick_select_d_filter_nan(&(*input)[i * stride], stride, iseven); //special if nan. else (*res)[i] = quick_select_d_protect_input(&(*input)[i * stride], stride, iseven); } if (clean_array) delete input; return res; } else { DFloatGDL* input = e->GetParAs(0); if (medianDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DFloatGDL* res = new DFloatGDL(destDim, BaseGDL::NOZERO); //probably overkill to start multithreading in some easy cases. TBD. #pragma omp for private(i) for (SizeT i = 0; i < nEl; ++i) { if (hasnan_f(&(*input)[i * stride], stride)) (*res)[i] = quick_select_f_filter_nan(&(*input)[i * stride], stride, iseven); //special if nan. else (*res)[i] = quick_select_f_protect_input(&(*input)[i * stride], stride, iseven); } if (clean_array) delete input; return res; } } else { //faster since no NaN handling needed. if (dbl) { DDoubleGDL* input = e->GetParAs(0); if (medianDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DDoubleGDL* res = new DDoubleGDL(destDim, BaseGDL::NOZERO); #pragma omp for private(i) for (SizeT i = 0; i < nEl; ++i) (*res)[i] = quick_select_d_protect_input(&(*input)[i * stride], stride, iseven); if (clean_array) delete input; return res; } else { DFloatGDL* input = e->GetParAs(0); if (medianDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DFloatGDL* res = new DFloatGDL(destDim, BaseGDL::NOZERO); #pragma omp for private(i) for (SizeT i = 0; i < nEl; ++i) (*res)[i] = quick_select_f_protect_input(&(*input)[i * stride], stride, iseven); if (clean_array) delete input; return res; } } } else { if (possibleNaN) { if (dbl) { return mymedian_d_nan(e); } else { return mymedian_f_nan(e); } } else { if (dbl) return mymedian_d(e); else return mymedian_f(e); } } } else if (nParam == 2) { if (p0->Rank() > 2) e->Throw("Only 1 or 2 dimensions allowed: " + e->GetParString(0)); //rank is important as fast algos are different! bool twoD = (p0->Rank() == 2); // basic checks on "width" input DDoubleGDL* p1d = e->GetParAs(1); if (p1d->N_Elements() > 1 || (*p1d)[0] <= 0) e->Throw("Width must be a positive scalar or 1 (positive) element array in this context: " + e->GetParString(0)); DLong MaxAllowedWidth = 0; if (twoD) { MaxAllowedWidth = p0->Dim(0); if (p0->Dim(1) < MaxAllowedWidth) MaxAllowedWidth = p0->Dim(1); } else MaxAllowedWidth = p0->N_Elements(); if (!std::isfinite((*p1d)[0])) e->Throw("Width must be > 1, and < dimension of array (NaN or Inf)"); if ((*p1d)[0] < 2 || (*p1d)[0] > MaxAllowedWidth) e->Throw("Width must be > 1, and < dimensions: ."); DIntGDL* p1 = e->GetParAs(1); int width = p0->Dim(0); int height = twoD ? p0->Dim(1) : 1; int size = (*p1)[0]; int radius = (size-1) / 2; bool oddsize = (size % 2 == 1); bool iseven = ((size % 2) == 0 && e->KeywordSet(evenIx)); if (p0->Type() == GDL_BYTE && twoD && oddsize) { // for this special case we apply the constant-time algorithm described in Perreault et al, // Published in the September 2007 issue of IEEE Transactions on Image Processing. DOI: 10.1109/TIP.2007.902329 DByteGDL* data = e->GetParAs(0); BaseGDL* res = new DByteGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::ctmf( (unsigned char*) data->DataAddr(), (unsigned char*) res->DataAddr(), width, height, width, width, radius, 1, 32 * 1024); //for a 32K cache. FIXME-> get cache size value!!! return res; } else { //here we adapt according to problem using various solutions found in the literature. if (dbl) { DDoubleGDL* data = e->GetParAs(0); if (twoD) { if (oddsize) { //2D fast routines are programmed with odd sizes (2*radius+1) BaseGDL* res = new DDoubleGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::median_filter_2d(width, height, radius, radius, 0, (DDouble*) data->DataAddr(), (DDouble*) res->DataAddr()); return res; } else { //for quite a large number of pixels (100=10^2), use the next ODD value. Results are compatible within 1% for random values. //to be tested, but should be better for natural values. if (size > 10) { radius=size/2; //1 more BaseGDL* res = new DDoubleGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::median_filter_2d(width, height, radius, radius, 0, (DDouble*) data->DataAddr(), (DDouble*) res->DataAddr()); if (p0->Type() == GDL_BYTE) return res->Convert2(GDL_BYTE, BaseGDL::CONVERT); else return res; } else return SlowReliableMedian(e); //until we rewrite a fast non-odd 2 d filter. } } else { if (oddsize) { BaseGDL* res = new DDoubleGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::median_filter_1d(width, radius, 0, (DDouble*) data->DataAddr(), (DDouble*) res->DataAddr()); return res; } else { //this oneD fast routine accepts odd and even sizes, but is slower than Jukka's BaseGDL* res = data->Dup(); fastmedian::filter((DDouble*) res->DataAddr(), width, size, iseven); return res; } } } else { DFloatGDL* data = e->GetParAs(0); if (twoD) { if (oddsize) { //2D fast routines are programmed with odd sizes (2*radius+1). BaseGDL* res = new DFloatGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::median_filter_2d(width, height, radius, radius, 0, (DFloat*) data->DataAddr(), (DFloat*) res->DataAddr()); return res; } else { //for quite a large number of pixels (100=10^2), use the next ODD value. Results are compatible within 1% for random values. //to be tested, but should be better for natural values. if (size > 10) { radius=size/2; //1 more BaseGDL* res = new DFloatGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::median_filter_2d(width, height, radius, radius, 0, (DFloat*) data->DataAddr(), (DFloat*) res->DataAddr()); if (p0->Type() == GDL_BYTE) return res->Convert2(GDL_BYTE, BaseGDL::CONVERT); else return res; } else return SlowReliableMedian(e); //until we rewrite a fast non-odd 2 d filter. } } else { if (oddsize) { //Jukka's version is faster. BaseGDL* res = new DFloatGDL(data->Dim(), BaseGDL::NOZERO); fastmedian::median_filter_1d(width, radius, 0, (DFloat*) data->DataAddr(), (DFloat*) res->DataAddr()); return res; } else { //this oneD fast routine accepts odd an even sizes. BaseGDL* res = data->Dup(); fastmedian::filter((DFloat*) res->DataAddr(), width, size, iseven); if (p0->Type() == GDL_BYTE) return res->Convert2(GDL_BYTE, BaseGDL::CONVERT); else return res; } } } } } return NULL; //pacifies dumm compilers. } // uses MergeSort // 2 parts in the code: without "width" or with "width" (limited to 1D and 2D) BaseGDL* SlowReliableMedian(EnvT* e) { BaseGDL* p0 = e->GetParDefined(0); if (p0->Type() == GDL_PTR) e->Throw("Pointer expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_OBJ) e->Throw("Object expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("Struct expression not allowed in this context: " + e->GetParString(0)); if (p0->Rank() == 0) e->Throw("Expression must be an array in this context: " + e->GetParString(0)); SizeT nParam = e->NParam(1); SizeT nEl = p0->N_Elements(); // "f_nan" and "d_nan" used by both parts ... DStructGDL *Values = SysVar::Values(); //MUST NOT BE STATIC, due to .reset DFloat f_nan = (*static_cast (Values->GetTag(Values->Desc()->TagIndex("F_NAN"), 0)))[0]; DDouble d_nan = (*static_cast (Values->GetTag(Values->Desc()->TagIndex("D_NAN"), 0)))[0]; // -------------------------------------------------------- // begin of the part 1: without "width" param if (nParam == 1) { static int evenIx = e->KeywordIx("EVEN"); // TYPE static int doubleIx = e->KeywordIx("DOUBLE"); bool dbl = p0->Type() == GDL_DOUBLE || p0->Type() == GDL_COMPLEXDBL || e->KeywordSet(doubleIx); DType type = dbl ? GDL_DOUBLE : GDL_FLOAT; bool noconv = (dbl && p0->Type() == GDL_DOUBLE) || (!dbl && p0->Type() == GDL_FLOAT); // DIMENSION keyword DLong dim = 0; DLong nmed = 1; BaseGDL *res; static int dimensionIx = e->KeywordIx("DIMENSION"); e->AssureLongScalarKWIfPresent(dimensionIx, dim); // cout << "dim : "<< dim << endl; if (dim > p0->Rank()) e->Throw("Illegal keyword value for DIMENSION."); if (dim > 0) { DLong dims[8]; DLong k = 0; for (SizeT i = 0; i < p0->Rank(); ++i) if (i != (dim - 1)) { nmed *= p0->Dim(i); dims[k++] = p0->Dim(i); } dimension dimRes((DLong *) dims, p0->Rank() - 1); res = dbl ? static_cast (new DDoubleGDL(dimRes, BaseGDL::NOZERO)) : static_cast (new DFloatGDL(dimRes, BaseGDL::NOZERO)); } else { res = dbl ? static_cast (new DDoubleGDL(1)) : static_cast (new DFloatGDL(1)); } // conversion of Complex types if (p0->Type() == GDL_COMPLEX) p0 = p0->Convert2(GDL_FLOAT, BaseGDL::COPY); if (p0->Type() == GDL_COMPLEXDBL) p0 = p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); // helper arrays if (nmed > 1) nEl = p0->N_Elements() / nmed; // cout << "hello2" << endl; DLong *hh = new DLong[ nEl]; DLong* h1 = new DLong[ nEl / 2]; DLong* h2 = new DLong[ (nEl + 1) / 2]; DLong accumStride = 1; if (nmed > 1) for (DLong i = 0; i < dim - 1; ++i) accumStride *= p0->Dim(i); BaseGDL *op1, *op2, *op3; if (dbl) op3 = new DDoubleGDL(2); else op3 = new DFloatGDL(2); // nEl_extern is used to store "nEl" initial value DLong nanIx, nEl_extern; nEl_extern = nEl; // if (nmed > 1) nEl_extern = p0->N_Elements() / nmed; //else nEl_extern = p0->N_Elements(); // cout << "hello type" << p0->Type() << endl; // Loop over all subarray medians for (SizeT k = 0; k < nmed; ++k) { // nEl=nEl_extern; if (nmed == 1) { //cout << "hello inside 1D" << endl; for (DLong i = 0; i < nEl; ++i) hh[i] = i; nanIx = nEl; if (p0->Type() == GDL_DOUBLE) { DDoubleGDL* p0F = static_cast (p0); for (DLong i = nEl - 1; i >= 0; --i) { if (isnan((*p0F)[i])) { --nanIx; hh[i] = hh[nanIx]; hh[ nanIx] = i; } } } if (p0->Type() == GDL_FLOAT) { DFloatGDL* p0F = static_cast (p0); for (DLong i = nEl - 1; i >= 0; --i) { if (isnan((*p0F)[i])) { --nanIx; hh[i] = hh[nanIx]; hh[ nanIx] = i; } } } //cout << "nEl " << nEl << " nanIx " << nanIx << endl; nEl = nanIx; } else { nanIx = nEl; nEl = nEl_extern; // DLong nanIx = nEl; // Starting Element DLong start = accumStride * p0->Dim(dim - 1) * (k / accumStride) + (k % accumStride); for (DLong i = 0; i < nEl; ++i) hh[i] = start + i * accumStride; DLong jj; nanIx = nEl; if (p0->Type() == GDL_FLOAT) { DFloatGDL* p0F = static_cast (p0); for (DLong i = nEl - 1; i >= 0; --i) { jj = start + i * accumStride; if (isnan((*p0F)[ jj])) { --nanIx; hh[i] = hh[nanIx]; hh[ nanIx] = i; } } nEl = nanIx; } if (p0->Type() == GDL_DOUBLE) { DDoubleGDL* p0F = static_cast (p0); for (DLong i = nEl - 1; i >= 0; --i) { jj = start + i * accumStride; if (isnan((*p0F)[ jj])) { --nanIx; hh[i] = hh[nanIx]; hh[ nanIx] = i; } } //cout << "nanIx :" << nanIx << "nEl :" << nEl << endl; nEl = nanIx; } } DLong medEl, medEl_1; // call the sort routine if (nEl > 1) { MergeSortOpt(p0, hh, h1, h2, nEl); medEl = hh[ nEl / 2]; medEl_1 = hh[ nEl / 2 - 1]; } else { if (nEl == 1) { medEl = hh[0]; medEl_1 = hh[0]; } else { // normal case, more than one element, nothing to do //cout << "gasp : no result ! " << endl; } } if (nEl <= 0) { // we have a NaN if (dbl) (*static_cast (res))[k] = d_nan; else (*static_cast (res))[k] = f_nan; } else { //cout << k << "" << (*static_cast(p0))[medEl] << " " // << (*static_cast(p0))[medEl_1] << endl; //cout << "k :" << k << endl; if ((nEl % 2) == 1 || !e->KeywordSet(evenIx)) { if (nmed == 1) res = p0->NewIx(medEl)->Convert2(type, BaseGDL::CONVERT); else { if (noconv) { if (dbl) (*static_cast (res))[k] = (*static_cast (p0))[medEl]; else (*static_cast (res))[k] = (*static_cast (p0))[medEl]; } else { op1 = p0->NewIx(medEl)->Convert2(type, BaseGDL::CONVERT); if (dbl) (*static_cast (res))[k] = (*static_cast (op1))[0]; else (*static_cast (res))[k] = (*static_cast (op1))[0]; delete(op1); } } } else { if (noconv) { if (dbl) (*static_cast (res))[k] = .5 * ( (*static_cast (p0))[medEl] + (*static_cast (p0))[medEl_1] ); else (*static_cast (res))[k] = .5 * ( (*static_cast (p0))[medEl] + (*static_cast (p0))[medEl_1] ); } else { op1 = p0->NewIx(medEl)->Convert2(type, BaseGDL::CONVERT); op2 = p0->NewIx(medEl_1)->Convert2(type, BaseGDL::CONVERT); if (nmed == 1) res = op2->Add(op1)->Div(op3); // TODO: leak with res? else { if (dbl) (*static_cast (res))[k] = (*static_cast ((op2->Add(op1)->Div(op3))))[0]; else (*static_cast (res))[k] = (*static_cast ((op2->Add(op1)->Div(op3))))[0]; delete(op2); } delete(op1); } } } } delete(op3); delete[] h1; delete[] h2; delete[] hh; return res; } // begin of the part 2: with "width" param if (nParam == 2) { // with parameter Width : median filtering with no optimisation, // such as histogram algorithms. // Copyright: (C) 2008 by Nicolas Galmiche // basic checks on "vector/array" input DDoubleGDL* p0 = e->GetParAs(0); if (p0->Rank() > 2) e->Throw("Only 1 or 2 dimensions allowed: " + e->GetParString(0)); // basic checks on "width" input DDoubleGDL* p1d = e->GetParAs(1); if (p1d->N_Elements() > 1 || (*p1d)[0] <= 0) e->Throw("Width must be a positive scalar or 1 (positive) element array in this context: " + e->GetParString(0)); DLong MaxAllowedWidth = 0; if (p0->Rank() == 1) MaxAllowedWidth = p0->N_Elements(); if (p0->Rank() == 2) { MaxAllowedWidth = p0->Dim(0); if (p0->Dim(1) < MaxAllowedWidth) MaxAllowedWidth = p0->Dim(1); } const int debug = 0; if (debug == 1) { cout << "X dim " << p0->Dim(0) << endl; cout << "y dim " << p0->Dim(1) << endl; cout << "MaxAllowedWidth " << MaxAllowedWidth << endl; } if (!std::isfinite((*p1d)[0])) e->Throw("Width must be > 1, and < dimension of array (NaN or Inf)"); DLongGDL* p1 = e->GetParAs(1); DDoubleGDL *tamp = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); DDouble min = ((*p0)[0]); DDouble max = min; for (SizeT ii = 0; ii < p0->N_Elements(); ++ii) { (*tamp)[ii] = (*p0)[ii]; if ((*p0)[ii] < min) min = ((*p0)[ii]); if ((*p0)[ii] > max) max = ((*p0)[ii]); } //---------------------------- END d'acquisistion des parametres ------------------------------------- static int evenIx = e->KeywordIx("EVEN"); static int doubleIx = e->KeywordIx("DOUBLE"); DStructGDL *Values = SysVar::Values(); //MUST NOT BE STATIC, due to .reset DDouble d_nan = (*static_cast (Values->GetTag(Values->Desc()->TagIndex("D_NAN"), 0)))[0]; DDouble d_infinity = (*static_cast (Values->GetTag(Values->Desc()->TagIndex("D_INFINITY"), 0)))[0]; //------------------------------ Init variables and allocation --------------------------------------- SizeT width = (*p1)[0]; SizeT N_MaskElem = width*width; SizeT larg = p0->Stride(1); SizeT haut = p0->Stride(2) / larg; SizeT lim = static_cast (round(width / 2)); SizeT init = (lim * larg + lim); // we don't go further if dimension(s) versus not width OK if (debug == 1) { cout << "ici" << endl; } if (p0->Rank() == 1) { if (larg < width || width == 1) e->Throw("Width must be > 1, and < width of vector"); } if (p0->Rank() == 2) { if (larg < width || haut < width || width == 1) e->Throw("Width must be > 1, and < dimension of array"); } // for 2D arrays, we use the algorithm described in paper // from T. Huang, G. Yang, and G. Tang, Fast Two-Dimensional Median Filtering Algorithm, // IEEE Trans. Acoust., Speech, Signal Processing, // vol. 27, no. 1, pp. 13--18, 1979. if ((e->GetParDefined(0)->Type() == GDL_BYTE || e->GetParDefined(0)->Type() == GDL_INT || e->GetParDefined(0)->Type() == GDL_UINT || e->GetParDefined(0)->Type() == GDL_LONG || e->GetParDefined(0)->Type() == GDL_ULONG || e->GetParDefined(0)->Type() == GDL_LONG64 || e->GetParDefined(0)->Type() == GDL_ULONG64) && (haut > 1)) { SizeT taille = static_cast (abs(max) - min + 1); DDoubleGDL* Histo = new DDoubleGDL(taille, BaseGDL::NOZERO); if (width % 2 == 0) { for (SizeT i = 0; i < haut - 2 * lim; ++i) { SizeT ltmed = 0; SizeT med = 0; SizeT initial = init + i * larg - lim * larg - lim; for (SizeT pp = 0; pp < taille; ++pp)(*Histo)[pp] = 0; for (SizeT ii = initial; ii < initial + width; ++ii) { for (SizeT yy = 0; yy < width; yy++) (*Histo)[static_cast ((*p0)[ii + yy * larg] - min)]++; } while (ltmed + (*Histo)[med] <= (N_MaskElem / 2)) { ltmed += static_cast ((*Histo)[med]); ++med; } if (e->KeywordSet(evenIx)) { SizeT EvenMed = med; //if ((*Histo)[EvenMed]==1 || (ltmed!=0 && ltmed !=(N_MaskElem /2) -1)) if ((*Histo)[EvenMed] == 1 || (ltmed != 0 && N_MaskElem / 2 - ltmed != 1)) { while ((*Histo)[EvenMed - 1] == 0) { EvenMed--; } (*tamp)[init + i * larg] = ((med + min)+(EvenMed - 1 + min)) / 2; } else (*tamp)[init + i * larg] = med + min; } else { (*tamp)[init + i * larg] = med + min; } for (SizeT j = init + i * larg + 1; j < init + (i + 1) * larg - 2 * lim; ++j) { SizeT initMask = j - lim * larg - lim; for (SizeT k = 0; k < 2 * lim; ++k) { (*Histo)[static_cast ((*p0)[initMask - 1 + k * larg] - min)]--; if ((*p0)[initMask - 1 + k * larg] - min < med)ltmed--; (*Histo)[static_cast ((*p0)[initMask + k * larg + 2 * lim - 1] - min)]++; if ((*p0)[initMask + k * larg + 2 * lim - 1] - min < med)ltmed++; } if (ltmed > N_MaskElem / 2) { while (ltmed > N_MaskElem / 2) { --med; ltmed -= static_cast ((*Histo)[med]); } } else { while (ltmed + (*Histo)[med] <= (N_MaskElem / 2)) { ltmed += static_cast ((*Histo)[med]); ++med; } } if (e->KeywordSet(evenIx)) { SizeT EvenMed = med; if ((*Histo)[EvenMed] == 1 || (ltmed != 0 && N_MaskElem / 2 - ltmed != 1)) { while ((*Histo)[EvenMed - 1] == 0) { EvenMed--; } (*tamp)[j] = ((med + min)+(EvenMed - 1 + min)) / 2; } else { (*tamp)[j] = med + min; } } else { (*tamp)[j] = med + min; } } } } else { for (SizeT i = 0; i < haut - 2 * lim; ++i) { SizeT ltmed = 0; SizeT med = 0; SizeT initial = init + i * larg - lim * larg - lim; for (SizeT pp = 0; pp < taille; ++pp)(*Histo)[pp] = 0; for (SizeT ii = initial; ii < initial + width; ++ii) { for (SizeT yy = 0; yy < width; yy++) (*Histo)[static_cast ((*p0)[ii + yy * larg] - min)]++; } while (ltmed + (*Histo)[med] <= (N_MaskElem / 2)) { ltmed += static_cast ((*Histo)[med]); ++med; } (*tamp)[init + i * larg] = med + min; for (SizeT j = init + i * larg + 1; j < init + (i + 1) * larg - 2 * lim; ++j) { SizeT initMask = j - lim * larg - lim; for (SizeT k = 0; k <= 2 * lim; ++k) { (*Histo)[static_cast ((*p0)[initMask - 1 + k * larg] - min)]--; if ((*p0)[initMask - 1 + k * larg] - min < med)ltmed--; (*Histo)[static_cast ((*p0)[initMask + k * larg + 2 * lim] - min)]++; if ((*p0)[initMask + k * larg + 2 * lim] - min < med)ltmed++; } if (ltmed > N_MaskElem / 2) { while (ltmed > N_MaskElem / 2) { --med; ltmed -= static_cast ((*Histo)[med]); } } else { while (ltmed + (*Histo)[med] <= (N_MaskElem / 2)) { ltmed += static_cast ((*Histo)[med]); ++med; } } (*tamp)[j] = med + min; } } } } else { DLong* hh; DLong* h1; DLong* h2; DDoubleGDL* Mask, *Mask1D; if (p0->Rank() != 1) { hh = new DLong[ N_MaskElem]; h1 = new DLong[ N_MaskElem / 2]; h2 = new DLong[ (N_MaskElem + 1) / 2]; Mask = new DDoubleGDL(N_MaskElem, BaseGDL::NOZERO); for (DLong i = 0; i < N_MaskElem; ++i) hh[i] = i; } else { hh = new DLong[ width]; h1 = new DLong[ width / 2]; h2 = new DLong[(width + 1) / 2]; Mask1D = new DDoubleGDL(width, BaseGDL::NOZERO); for (DLong i = 0; i < width; ++i) hh[i] = i; } //-------------------------------- END OF VARIABLES INIT --------------------------------------------- //------------------------------ Median Filter Algorithms --------------------------------------- if (width % 2 == 0) { if (p0->Rank() == 1)//------------------------ For a vector with even width ------------------- { for (SizeT col = lim; col < larg - lim; ++col) { SizeT ctl_NaN = 0; SizeT kk = 0; for (SizeT ind = col - lim; ind < col + lim; ++ind) { if ((*p0)[ind] != d_infinity && (*p0)[ind] != -d_infinity && std::isfinite((*p0)[ind]) == 0) ctl_NaN++; else { (*Mask1D)[kk] = (*p0)[ind]; kk++; } } if (ctl_NaN != 0) { if (ctl_NaN == width)(*tamp)[col] = d_nan; else { DLong* hhbis = new DLong[ width - ctl_NaN]; DLong* h1bis = new DLong[ width - ctl_NaN / 2]; DLong* h2bis = new DLong[(width - ctl_NaN + 1) / 2]; DDoubleGDL *Mask1Dbis = new DDoubleGDL(width - ctl_NaN, BaseGDL::NOZERO); for (DLong t = 0; t < width - ctl_NaN; ++t) hhbis[t] = t; for (DLong ii = 0; ii < width - ctl_NaN; ++ii)(*Mask1Dbis)[ii] = (*Mask1D)[ii]; BaseGDL* besort = static_cast (Mask1Dbis); MergeSortOpt(besort, hhbis, h1bis, h2bis, (width - ctl_NaN)); if (e->KeywordSet(evenIx)&& (width - ctl_NaN) % 2 == 0) (*tamp)[col] = ((*Mask1Dbis)[hhbis[ (width - ctl_NaN) / 2]]+(*Mask1Dbis )[hhbis [ (width - ctl_NaN - 1) / 2]]) / 2; else (*tamp)[col] = (*Mask1Dbis)[hhbis[ (width - ctl_NaN) / 2]]; delete[]hhbis; delete[]h2bis; delete[]h1bis; } } else { BaseGDL* besort = static_cast (Mask1D); MergeSortOpt(besort, hh, h1, h2, width); // call the sort routine if (e->KeywordSet(evenIx)) (*tamp)[col] = ((*Mask1D)[hh[ width / 2]]+(*Mask1D)[hh[ (width - 1) / 2]]) / 2; else (*tamp)[col] = (*Mask1D)[hh[ width / 2]]; // replace value by Mask median } } } else//------------------------ For an array with even width ------------------- { SizeT jj; for (SizeT i = 0; i < haut - 2 * lim; ++i) // lines to replace { for (SizeT j = init + i * larg; j < init + (i + 1) * larg - 2 * lim; ++j)// elements to replace { SizeT initMask = j - lim * larg - lim; // left corner of mask SizeT kk = 0; SizeT ctl_NaN = 0; for (SizeT k = 0; k < 2 * lim; ++k) // lines of mask { for (jj = initMask + k * larg; jj < (initMask + k * larg) + 2 * lim; ++jj) // elements of mask { if ((*p0)[jj] != d_infinity && (*p0)[jj] != -d_infinity && std::isfinite((*p0)[jj]) == 0) ctl_NaN++; else { (*Mask)[kk] = (*p0)[jj]; kk++; } } } if (ctl_NaN != 0) { if (ctl_NaN == N_MaskElem)(*tamp)[j] = d_nan; else { DLong* hhb = new DLong[ N_MaskElem - ctl_NaN]; DLong* h1b = new DLong[ (N_MaskElem - ctl_NaN) / 2]; DLong* h2b = new DLong[(N_MaskElem - ctl_NaN + 1) / 2]; DDoubleGDL *Maskb = new DDoubleGDL(N_MaskElem - ctl_NaN, BaseGDL::NOZERO); for (DLong t = 0; t < N_MaskElem - ctl_NaN; ++t) hhb[t] = t; for (DLong ii = 0; ii < N_MaskElem - ctl_NaN; ++ii)(*Maskb)[ii] = (*Mask)[ii]; BaseGDL* besort = static_cast (Maskb); MergeSortOpt(besort, hhb, h1b, h2b, (N_MaskElem - ctl_NaN)); if ((N_MaskElem - ctl_NaN) % 2 == 0 && e->KeywordSet(evenIx)) (*tamp)[j] = ((*Maskb)[hhb[ (N_MaskElem - ctl_NaN) / 2]]+(*Maskb)[hhb [ (N_MaskElem - ctl_NaN - 1) / 2]]) / 2; else (*tamp)[j] = (*Maskb)[hhb[ (N_MaskElem - ctl_NaN) / 2]]; delete[]hhb; delete[]h2b; delete[]h1b; } } else { BaseGDL* besort = static_cast (Mask); MergeSortOpt(besort, hh, h1, h2, N_MaskElem); // call the sort routine if (e->KeywordSet(evenIx)) (*tamp)[j] = ((*Mask)[hh[ N_MaskElem / 2]]+(*Mask)[hh[ (N_MaskElem - 1) / 2]]) / 2; else (*tamp)[j] = (*Mask)[hh[ N_MaskElem / 2]]; // replace value by median Mask one } } } } } else { if (p0->Rank() == 1)//------------------------ For a vector with odd width ------------------- { for (SizeT col = lim; col < larg - lim; ++col) { SizeT kk = 0; SizeT ctl_NaN = 0; for (SizeT ind = col - lim; ind <= col + lim; ++ind) { if ((*p0)[ind] != d_infinity && (*p0)[ind] != -d_infinity && std::isfinite((*p0)[ind]) == 0) ctl_NaN++; else { (*Mask1D)[kk] = (*p0)[ind]; kk++; } } if (ctl_NaN != 0) { if (ctl_NaN == width)(*tamp)[col] = d_nan; else { DLong* hhbis = new DLong[ width - ctl_NaN]; DLong* h1bis = new DLong[ width - ctl_NaN / 2]; DLong* h2bis = new DLong[(width - ctl_NaN + 1) / 2]; DDoubleGDL *Mask1Dbis = new DDoubleGDL(width - ctl_NaN, BaseGDL::NOZERO); for (DLong t = 0; t < width - ctl_NaN; ++t) hhbis[t] = t; for (DLong ii = 0; ii < width - ctl_NaN; ++ii)(*Mask1Dbis)[ii] = (*Mask1D)[ii]; BaseGDL* besort = static_cast (Mask1Dbis); MergeSortOpt(besort, hhbis, h1bis, h2bis, (width - ctl_NaN)); if (e->KeywordSet(evenIx)&& (width - ctl_NaN) % 2 == 0) (*tamp)[col] = ((*Mask1Dbis)[hhbis[ (width - ctl_NaN) / 2]]+(*Mask1Dbis )[hhbis [ (width - ctl_NaN - 1) / 2]]) / 2; else(*tamp)[col] = (*Mask1Dbis)[hhbis[ (width - ctl_NaN) / 2]]; delete[]hhbis; delete[]h2bis; delete[]h1bis; } } else { BaseGDL* besort = static_cast (Mask1D); MergeSortOpt(besort, hh, h1, h2, width); // call the sort routine (*tamp)[col] = (*Mask1D)[hh[ (width) / 2]]; // replace value by Mask median } } } else //----------------------------- For an array with odd width --------------------------------- { SizeT jj; for (SizeT i = 0; i < haut - 2 * lim; ++i) // lines to replace { SizeT initial = init + i * larg - lim * larg - lim; SizeT dd = 0; SizeT ctl_NaN_init = 0; for (SizeT yy = 0; yy < width; yy++) { for (SizeT ii = initial + yy * larg; ii < initial + yy * larg + width; ++ii) { if ((*p0)[ii] != d_infinity && (*p0)[ii] != -d_infinity && std::isfinite((*p0)[ii]) == 0) ctl_NaN_init++; else (*Mask)[dd] = (*p0)[ii]; dd++; } } SizeT kk = 0; for (SizeT j = init + i * larg; j < init + (i + 1) * larg - 2 * lim; ++j)// elements to replace { SizeT initMask = j - lim * larg - lim; // left corner of mask SizeT kk = 0; SizeT ctl_NaN = 0; for (SizeT k = 0; k <= 2 * lim; ++k) // lines of mask { for (jj = initMask + k * larg; jj <= (initMask + k * larg) + 2 * lim; ++jj) // elements of mask { if ((*p0)[jj] != d_infinity && (*p0)[jj] != -d_infinity && std::isfinite((*p0)[jj]) == 0) ctl_NaN++; else { (*Mask)[kk] = (*p0)[jj]; kk++; } } } if (ctl_NaN != 0) { if (ctl_NaN == N_MaskElem) (*tamp)[j] = d_nan; else { DLong* hhb = new DLong[ N_MaskElem - ctl_NaN]; DLong* h1b = new DLong[ (N_MaskElem - ctl_NaN) / 2]; DLong* h2b = new DLong[(N_MaskElem - ctl_NaN + 1) / 2]; DDoubleGDL*Maskb = new DDoubleGDL(N_MaskElem - ctl_NaN, BaseGDL::NOZERO); for (DLong t = 0; t < N_MaskElem - ctl_NaN; ++t) hhb[t] = t; for (DLong ii = 0; ii < N_MaskElem - ctl_NaN; ++ii)(*Maskb)[ii] = (*Mask)[ii]; BaseGDL* besort = static_cast (Maskb); MergeSortOpt(besort, hhb, h1b, h2b, (N_MaskElem - ctl_NaN)); if ((N_MaskElem - ctl_NaN) % 2 == 0 && e->KeywordSet(evenIx)) (*tamp)[j] = ((*Maskb)[hhb[ (N_MaskElem - ctl_NaN) / 2]]+(*Maskb)[hhb [ (N_MaskElem - ctl_NaN - 1) / 2]]) / 2; else(*tamp)[j] = (*Maskb)[hhb[(N_MaskElem - ctl_NaN) / 2]]; delete[]hhb; delete[]h2b; delete[]h1b; } } else { BaseGDL* besort = static_cast (Mask); MergeSortOpt(besort, hh, h1, h2, N_MaskElem); // call the sort routine (*tamp)[j] = (*Mask)[hh[ (N_MaskElem) / 2]]; // replace value by Mask median } } } } } //--------------------------- END OF MEDIAN FILTER ALOGORITHMS ----------------------------------- delete[] h1; delete[] h2; delete[] hh; } if (e->GetParDefined(0)->Type() == GDL_DOUBLE || p0->Type() == GDL_COMPLEXDBL || e->KeywordSet(doubleIx)) return tamp; else if (e->GetParDefined(0)->Type() == GDL_BYTE) return tamp->Convert2(GDL_BYTE, BaseGDL::CONVERT); return tamp->Convert2(GDL_FLOAT, BaseGDL::CONVERT); }// end if e->Throw("More than 2 parameters not handled."); return NULL; }// end of median //template static inline Ty do_max(const Ty* data, const SizeT sz) { // Ty maxval = data[0]; // //#if OMP_HAS_MAX //#pragma omp parallel // { //#pragma omp for reduction(max:maxval) //#endif // for (SizeT i = 1; i < sz; ++i) maxval = max(maxval,data[i]); //#if OMP_HAS_MAX // } //#endif // return maxval; // } //template static inline Ty do_max_nan(const Ty* data, const SizeT sz) { // Ty maxval = data[0]; //#if OMP_HAS_MAX //#pragma omp parallel // { //#pragma omp for reduction(max:maxval) //#endif // for (SizeT i = 1; i < sz; ++i) maxval = max(maxval,data[i]); //#if OMP_HAS_MAX // } //#endif // return maxval; // } template static inline Ty do_mean(const Ty* data, const SizeT sz) { Ty mean = 0; #pragma omp parallel { #pragma omp for reduction(+:mean) for (SizeT i = 0; i < sz; ++i) mean += data[i]; } return mean/sz; } template static inline Ty do_mean_cpx(const Ty* data, const SizeT sz) { T2 meanr = 0; T2 meani = 0; #pragma omp parallel { #pragma omp for reduction(+:meanr) for (SizeT i = 0; i < sz; ++i) meanr += data[i].real(); #pragma omp for reduction(+:meani) for (SizeT i = 0; i < sz; ++i) meani += data[i].imag(); } return std::complex(meanr/sz,meani/sz); } template static inline Ty do_mean_nan(const Ty* data, const SizeT sz) { Ty mean = 0; SizeT n = 0; #pragma omp parallel //if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:mean,n) for (SizeT i = 0; i < sz; ++i) { Ty v = data[i]; if (std::isfinite(v)) { n++, mean += v; } } } return mean/n; } template static inline Ty do_mean_cpx_nan(const Ty* data, const SizeT sz) { T2 meanr = 0; T2 meani = 0; SizeT nr = 0; SizeT ni = 0; #pragma omp parallel //if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:meanr,nr) for (SizeT i = 0; i < sz; ++i) { T2 v = data[i].real(); if (std::isfinite(v)) { nr++, meanr += v; } } #pragma omp for reduction(+:meani,ni) for (SizeT i = 0; i < sz; ++i) { T2 v = data[i].imag(); if (std::isfinite(v)) { ni++, meani += v; } } } return std::complex(meanr/nr,meani/ni); } BaseGDL* mean_fun(EnvT* e) { BaseGDL* p0 = e->GetParDefined(0); if (p0->Type() == GDL_PTR) e->Throw("Pointer expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_OBJ) e->Throw("Object expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("Struct expression not allowed in this context: " + e->GetParString(0)); static int doubleIx = e->KeywordIx("DOUBLE"); bool dbl = (p0->Type() == GDL_DOUBLE || p0->Type() == GDL_COMPLEXDBL || e->KeywordSet(doubleIx)); static int nanIx = e->KeywordIx("NAN"); // Check possibility of Nan (not useful to speed down mean on integer data which // will never produce NaNs). bool possibleNaN = (p0->Type() == GDL_DOUBLE || p0->Type() == GDL_FLOAT || p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL); bool omitNaN = (e->KeywordPresent(nanIx) && possibleNaN); //DIMENSION Kw static int dimIx = e->KeywordIx("DIMENSION"); bool dimSet = e->KeywordSet(dimIx); DLong meanDim; if (dimSet) { e->AssureLongScalarKW(dimIx, meanDim); if (meanDim < 0 || meanDim > p0->Rank()) e->Throw("Illegal keyword value for DIMENSION"); } if (dimSet && p0->Rank() > 1) { meanDim -= 1; // user-supplied dimensions start with 1! // output dimension: copy srcDim to destDim dimension destDim = p0->Dim(); // make array of dims for transpose DUInt* perm = new DUInt[p0->Rank()]; ArrayGuard perm_guard(perm); //useful to reorder dims for transpose to order data in continuous order. DUInt i = 0, j = 0; for (i = 0; i < p0->Rank(); ++i) if (i != meanDim) { perm[j + 1] = i; j++; } perm[0] = meanDim; // resize destDim destDim.Remove(meanDim); //will be one dimension less //compute stride and number of elements of result: SizeT stride = p0->Dim(meanDim); SizeT nEl = destDim.NDimElementsConst(); //transpose p0 to arrange dimensions if meanDim is > 0. Do not forget to remove transposed array. bool clean_array = false; if (p0->Type() == GDL_COMPLEXDBL || (p0->Type() == GDL_COMPLEX && dbl)) { DComplexDblGDL* input = e->GetParAs(0); if (meanDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DComplexDblGDL* res = new DComplexDblGDL(destDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean_cpx_nan(&(*input)[i * stride], stride); } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean_cpx(&(*input)[i * stride], stride); } } if (clean_array) delete input; return res; } else if (p0->Type() == GDL_COMPLEX) { DComplexGDL* input = e->GetParAs(0); if (meanDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DComplexGDL* res = new DComplexGDL(destDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean_cpx_nan(&(*input)[i * stride], stride); } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean_cpx(&(*input)[i * stride], stride); } } if (clean_array) delete input; return res; } else { if (dbl) { DDoubleGDL* input = e->GetParAs(0); if (meanDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DDoubleGDL* res = new DDoubleGDL(destDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean_nan(&(*input)[i * stride], stride); } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean(&(*input)[i * stride], stride); } } if (clean_array) delete input; return res; } else { DFloatGDL* input = e->GetParAs(0); if (meanDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DFloatGDL* res = new DFloatGDL(destDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean_nan(&(*input)[i * stride], stride); } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) (*res)[i] = do_mean(&(*input)[i * stride], stride); } } if (clean_array) delete input; return res; } } } else { if (p0->Type() == GDL_COMPLEXDBL || (p0->Type() == GDL_COMPLEX && dbl)) { DComplexDblGDL* input = e->GetParAs(0); if (omitNaN) return new DComplexDblGDL(do_mean_cpx_nan(&(*input)[0], input->N_Elements())); else return new DComplexDblGDL(do_mean_cpx(&(*input)[0], input->N_Elements())); } else if (p0->Type() == GDL_COMPLEX) { DComplexGDL* input = e->GetParAs(0); if (omitNaN) return new DComplexGDL(do_mean_cpx_nan(&(*input)[0], input->N_Elements())); else return new DComplexGDL(do_mean_cpx(&(*input)[0], input->N_Elements())); } else { if (dbl) { DDoubleGDL* input = e->GetParAs(0); if (omitNaN) return new DDoubleGDL(do_mean_nan(&(*input)[0], input->N_Elements())); else return new DDoubleGDL(do_mean(&(*input)[0], input->N_Elements())); } else { DFloatGDL* input = e->GetParAs(0); if (omitNaN) return new DFloatGDL(do_mean_nan(&(*input)[0], input->N_Elements())); else return new DFloatGDL(do_mean(&(*input)[0], input->N_Elements())); } } } } template static inline void do_moment(const Ty* data, const SizeT sz, Ty &mean, Ty &variance, Ty &skewness, Ty &kurtosis, Ty &mdev, Ty &sdev, const int maxmoment){ Ty meanl=do_mean(data,sz); mean=meanl; if (maxmoment==1) { variance=skewness=kurtosis=mdev=sdev=std::numeric_limits::quiet_NaN(); return; } Ty var=0; Ty md=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:var,md) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; var += cdata*cdata; md+=fabs(cdata);} } var/=(sz-1); variance=var; sdev=sqrt(var); mdev=md/sz; if (maxmoment==2 || var==0 ) { skewness=kurtosis=std::numeric_limits::quiet_NaN(); return; } Ty skew=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:skew) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; skew += (cdata*cdata*cdata)/(var*sdev); } } skewness=skew/sz; if (maxmoment==3) { kurtosis=std::numeric_limits::quiet_NaN(); return; } Ty kurt=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:kurt) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; kurt += (cdata*cdata*cdata*cdata)/(var*var);} } kurtosis=(kurt/sz)-3; } template static inline void do_moment_cpx(const Ty* data, const SizeT sz, Ty &mean, Ty &variance, Ty &skewness, Ty &kurtosis, T2 &mdev, Ty &sdev, const int maxmoment){ Ty meanl=do_mean_cpx(data,sz); mean=meanl; if (maxmoment == 1) { variance = skewness = kurtosis = sdev = std::complex(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); mdev = std::numeric_limits::quiet_NaN(); return; } T2 mdr=0; T2 varr=0; T2 vari=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:varr,vari,mdr) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; T2 cdatar=cdata.real(); T2 cdatai=cdata.imag(); varr += (cdatar*cdatar)-(cdatai*cdatai); vari += 2*cdatar*cdatai; mdr += sqrt(cdatar*cdatar+cdatai*cdatai); } } varr/=(sz-1); vari/=(sz-1); mdr/=sz; variance=std::complex(varr,vari); sdev=sqrt(variance); mdev=mdr; if (maxmoment==2) { skewness=kurtosis= std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); return; } T2 skewr=0; T2 skewi=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:skewr,skewi) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; T2 cdatar=cdata.real(); T2 cdatai=cdata.imag(); skewr += (cdatar*cdatar*cdatar-3.0*cdatar*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))* cos(0.15E1*atan2(vari,varr))+(3.0*cdatar*cdatar*cdatai-cdatai*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))*sin(1.5*atan2(vari,varr)); skewi += (3.0*cdatar*cdatar*cdatai-cdatai*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))*cos(1.5*atan2(vari,varr))- (cdatar*cdatar*cdatar-3.0*cdatar*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))*sin(1.5*atan2(vari,varr)); } } skewness=std::complex(skewr/sz,skewi/sz); if (maxmoment==3) { kurtosis=std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); return; } T2 kurtr=0; T2 kurti=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:kurtr,kurti) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; T2 cdatar=cdata.real(); T2 cdatai=cdata.imag(); kurtr += (cdatar*cdatar*cdatar*cdatar-6.0*cdatar*cdatar*cdatai*cdatai+cdatai* cdatai*cdatai*cdatai)*(varr*varr-vari*vari)/(pow(varr*varr-vari*vari,2.0)+ 4.0*varr*varr*vari*vari)+2.0*(4.0*cdatar*cdatar*cdatar*cdatai- 4.0*cdatar*cdatai*cdatai*cdatai)*varr*vari/ (pow(varr*varr-vari*vari,2.0)+ 4.0*varr*varr*vari*vari); kurti += (4.0*cdatar*cdatar*cdatar*cdatai-4.0*cdatar*cdatai*cdatai*cdatai)* (varr*varr-vari*vari)/(pow(varr*varr-vari*vari,2.0)+4.0*varr*varr*vari*vari)- 2.0*(cdatar*cdatar*cdatar*cdatar- 6.0*cdatar*cdatar*cdatai*cdatai+cdatai*cdatai*cdatai*cdatai)*varr*vari/ (pow(varr*varr-vari*vari,2.0)+ 4.0*varr*varr*vari*vari); } } kurtosis=std::complex((kurtr/sz)-3,(kurti/sz)-3); } template static inline void do_moment_nan(const Ty* data, const SizeT sz, Ty &mean, Ty &variance, Ty &skewness, Ty &kurtosis, Ty &mdev, Ty &sdev, const int maxmoment){ Ty meanl=do_mean_nan(data,sz); mean=meanl; if (maxmoment==1 || !std::isfinite(mean)) { variance=skewness=kurtosis=mdev=sdev=std::numeric_limits::quiet_NaN(); return; } Ty var=0; Ty md=0; SizeT k=0; #pragma omp parallel //if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:var,md,k) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; if (std::isfinite(cdata)) {var += cdata*cdata; md+=fabs(cdata); k+=1;} } } if (k>1) var/=(k-1); else { variance=skewness=kurtosis=mdev=sdev=std::numeric_limits::quiet_NaN(); return; } variance=var; sdev=sqrt(var); mdev=md/k; if (maxmoment==2 || var==0 ) { skewness=kurtosis=std::numeric_limits::quiet_NaN(); return; } Ty skew=0; #pragma omp parallel //if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:skew) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; if (std::isfinite(cdata)) skew += (cdata*cdata*cdata)/(var*sdev); } } skewness=skew/k; if (maxmoment==3) { kurtosis=std::numeric_limits::quiet_NaN(); return; } Ty kurt=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:kurt) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; if (std::isfinite(cdata)) kurt += (cdata*cdata*cdata*cdata)/(var*var);} } kurtosis=(kurt/k)-3; } template static inline void do_moment_cpx_nan(const Ty* data, const SizeT sz, Ty &mean, Ty &variance, Ty &skewness, Ty &kurtosis, T2 &mdev, Ty &sdev, const int maxmoment){ Ty meanl=do_mean_cpx_nan(data,sz); mean=meanl; if (maxmoment==1) { variance=skewness=kurtosis=sdev= std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); mdev=std::numeric_limits::quiet_NaN(); return; } SizeT kr=0; SizeT ki=0; T2 mdr=0; T2 varr=0; T2 vari=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:varr,vari,mdr,kr,ki) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; T2 cdatar=cdata.real(); T2 cdatai=cdata.imag(); if (std::isfinite(cdatar)) {varr += cdatar*cdatar; kr++;} if (std::isfinite(cdatai)) {vari += cdatai*cdatai; ki++;} if (std::isfinite(cdatar)) mdr += sqrt(cdatar*cdatar+cdatai*cdatai); } } varr/=(kr-1); vari/=(ki-1); mdr/=kr; variance=std::complex(varr,vari); sdev=sqrt(variance); mdev=mdr; if (maxmoment==2) { skewness=kurtosis= std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); return; } T2 skewr=0; T2 skewi=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:skewr,skewi) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; T2 cdatar=cdata.real(); T2 cdatai=cdata.imag(); if (std::isfinite(cdatar)) skewr += (cdatar*cdatar*cdatar-3.0*cdatar*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))* cos(0.15E1*atan2(vari,varr))+(3.0*cdatar*cdatar*cdatai-cdatai*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))*sin(1.5*atan2(vari,varr)); if (std::isfinite(cdatai)) skewi += (3.0*cdatar*cdatar*cdatai-cdatai*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))*cos(1.5*atan2(vari,varr))- (cdatar*cdatar*cdatar-3.0*cdatar*cdatai*cdatai)* exp(-0.75*log(varr*varr+vari*vari))*sin(1.5*atan2(vari,varr)); } } skewness=std::complex(skewr/kr,skewi/ki); if (maxmoment==3) { kurtosis=std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); return; } T2 kurtr=0; T2 kurti=0; #pragma omp parallel // if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for reduction(+:kurtr,kurti) for (SizeT i = 0; i < sz; ++i) { Ty cdata=data[i]-meanl; T2 cdatar=cdata.real(); T2 cdatai=cdata.imag(); if (std::isfinite(cdatar)) kurtr += (cdatar*cdatar*cdatar*cdatar-6.0*cdatar*cdatar*cdatai*cdatai+cdatai* cdatai*cdatai*cdatai)*(varr*varr-vari*vari)/(pow(varr*varr-vari*vari,2.0)+ 4.0*varr*varr*vari*vari)+2.0*(4.0*cdatar*cdatar*cdatar*cdatai- 4.0*cdatar*cdatai*cdatai*cdatai)*varr*vari/ (pow(varr*varr-vari*vari,2.0)+ 4.0*varr*varr*vari*vari); if (std::isfinite(cdatai)) kurti += (4.0*cdatar*cdatar*cdatar*cdatai-4.0*cdatar*cdatai*cdatai*cdatai)* (varr*varr-vari*vari)/(pow(varr*varr-vari*vari,2.0)+4.0*varr*varr*vari*vari)- 2.0*(cdatar*cdatar*cdatar*cdatar- 6.0*cdatar*cdatar*cdatai*cdatai+cdatai*cdatai*cdatai*cdatai)*varr*vari/ (pow(varr*varr-vari*vari,2.0)+ 4.0*varr*varr*vari*vari); } } kurtosis=std::complex((kurtr/kr)-3,(kurti/kr)-3); } BaseGDL* moment_fun(EnvT* e) { BaseGDL* p0 = e->GetParDefined(0); if (p0->Type() == GDL_PTR) e->Throw("Pointer expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_OBJ) e->Throw("Object expression not allowed in this context: " + e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("Struct expression not allowed in this context: " + e->GetParString(0)); static int doubleIx = e->KeywordIx("DOUBLE"); bool dbl = (p0->Type() == GDL_DOUBLE || p0->Type() == GDL_COMPLEXDBL || e->KeywordSet(doubleIx)); static int nanIx = e->KeywordIx("NAN"); // Check possibility of Nan (not useful to speed down moment on integer data which // will never produce NaNs). bool possibleNaN = (p0->Type() == GDL_DOUBLE || p0->Type() == GDL_FLOAT || p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL); bool omitNaN = (e->KeywordPresent(nanIx) && possibleNaN); //DIMENSION Kw static int dimIx = e->KeywordIx("DIMENSION"); bool dimSet = e->KeywordSet(dimIx); //MAXMOMENT Kw. It limits the computation, even if a modifying kw of higher moment, such as "kurtosis" is present static int maxmIx = e->KeywordIx("MAXMOMENT"); DLong maxmoment = 4; if (e->KeywordPresent(maxmIx)) e->AssureLongScalarKW(maxmIx, maxmoment); if (maxmoment > 4) maxmoment=4; if (maxmoment < 1) maxmoment=4; //MEAN Kw static int meanIx = e->KeywordIx("MEAN"); int domean = e->KeywordPresent(meanIx); //KURTOSIS Kw static int kurtIx = e->KeywordIx("KURTOSIS"); int dokurt = e->KeywordPresent(kurtIx); //SDEV Kw static int sdevIx = e->KeywordIx("SDEV"); int dosdev = e->KeywordPresent(sdevIx); //MDEV Kw static int mdevIx = e->KeywordIx("MDEV"); int domdev = e->KeywordPresent(mdevIx); //VARIANCE Kw static int varIx = e->KeywordIx("VARIANCE"); int dovar = e->KeywordPresent(varIx); //SKEWNESS Kw static int skewIx = e->KeywordIx("SKEWNESS"); int doskew = e->KeywordPresent(skewIx); DLong momentDim; if (dimSet) { e->AssureLongScalarKW(dimIx, momentDim); if (momentDim < 0 || momentDim > p0->Rank()) e->Throw("Illegal keyword value for DIMENSION"); } if (dimSet && p0->Rank() > 1) { momentDim -= 1; // user-supplied dimensions start with 1! // output dimension: copy srcDim to destDim dimension destDim = p0->Dim(); dimension auxiliaryDim; // make array of dims for transpose DUInt* perm = new DUInt[p0->Rank()]; ArrayGuard perm_guard(perm); //useful to reorder dims for transpose to order data in continuous order. DUInt i = 0, j = 0; for (i = 0; i < p0->Rank(); ++i) if (i != momentDim) { perm[j + 1] = i; j++; } perm[0] = momentDim; // resize destDim destDim.Remove(momentDim); //will be one dimension less SizeT nEl = destDim.NDimElementsConst(); //need to compute that here, before adding last dim. auxiliaryDim=destDim; destDim<<4; //add 4 as last dim //compute stride and number of elements of result: SizeT stride = p0->Dim(momentDim); //transpose p0 to arrange dimensions if momentDim is > 0. Do not forget to remove transposed array. bool clean_array = false; if (p0->Type() == GDL_COMPLEXDBL || (p0->Type() == GDL_COMPLEX && dbl)) { DComplexDblGDL* input = e->GetParAs(0); if (momentDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DComplexDblGDL* res = new DComplexDblGDL(destDim, BaseGDL::NOZERO); DComplexDblGDL* mean; DComplexDblGDL* var; DComplexDblGDL* skew; DComplexDblGDL* kurt; DComplexDblGDL* sdev; DDoubleGDL* mdev; if (domean) mean = new DComplexDblGDL(auxiliaryDim, BaseGDL::NOZERO); if (dovar) var = new DComplexDblGDL(auxiliaryDim, BaseGDL::NOZERO); if (doskew) skew = new DComplexDblGDL(auxiliaryDim, BaseGDL::NOZERO); if (dokurt) kurt = new DComplexDblGDL(auxiliaryDim, BaseGDL::NOZERO); if (dosdev) sdev = new DComplexDblGDL(auxiliaryDim, BaseGDL::NOZERO); if (domdev) mdev = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DDouble mdevl; DComplexDbl sdevl; do_moment_cpx_nan(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DDouble mdevl; DComplexDbl sdevl; do_moment_cpx(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } if (clean_array) delete input; if (domean) e->SetKW( meanIx, mean ); if (dovar ) e->SetKW( varIx, var ); if (doskew) e->SetKW( skewIx, skew ); if (dokurt) e->SetKW( kurtIx, kurt ); if (dosdev) e->SetKW( sdevIx, sdev ); if (domdev) e->SetKW( mdevIx, mdev ); return res; } else if (p0->Type() == GDL_COMPLEX) { DComplexGDL* input = e->GetParAs(0); if (momentDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DComplexGDL* res = new DComplexGDL(destDim, BaseGDL::NOZERO); DComplexGDL* mean; DComplexGDL* var; DComplexGDL* skew; DComplexGDL* kurt; DComplexGDL* sdev; DFloatGDL* mdev; if (domean) mean = new DComplexGDL(auxiliaryDim, BaseGDL::NOZERO); if (dovar) var = new DComplexGDL(auxiliaryDim, BaseGDL::NOZERO); if (doskew) skew = new DComplexGDL(auxiliaryDim, BaseGDL::NOZERO); if (dokurt) kurt = new DComplexGDL(auxiliaryDim, BaseGDL::NOZERO); if (dosdev) sdev = new DComplexGDL(auxiliaryDim, BaseGDL::NOZERO); if (domdev) mdev = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DFloat mdevl; DComplex sdevl; do_moment_cpx_nan(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DFloat mdevl; DComplex sdevl; do_moment_cpx(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } if (clean_array) delete input; if (domean) e->SetKW( meanIx, mean ); if (dovar ) e->SetKW( varIx, var ); if (doskew) e->SetKW( skewIx, skew ); if (dokurt) e->SetKW( kurtIx, kurt ); if (dosdev) e->SetKW( sdevIx, sdev ); if (domdev) e->SetKW( mdevIx, mdev ); return res; } else { if (dbl) { DDoubleGDL* input = e->GetParAs(0); if (momentDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DDoubleGDL* res = new DDoubleGDL(destDim, BaseGDL::NOZERO); DDoubleGDL* mean; DDoubleGDL* var; DDoubleGDL* skew; DDoubleGDL* kurt; DDoubleGDL* sdev; DDoubleGDL* mdev; if (domean) mean = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (dovar) var = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (doskew) skew = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (dokurt) kurt = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (dosdev) sdev = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (domdev) mdev = new DDoubleGDL(auxiliaryDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DDouble mdevl; DDouble sdevl; do_moment_nan(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DDouble mdevl; DDouble sdevl; do_moment(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } if (clean_array) delete input; if (domean) e->SetKW( meanIx, mean ); if (dovar ) e->SetKW( varIx, var ); if (doskew) e->SetKW( skewIx, skew ); if (dokurt) e->SetKW( kurtIx, kurt ); if (dosdev) e->SetKW( sdevIx, sdev ); if (domdev) e->SetKW( mdevIx, mdev ); return res; } else { DFloatGDL* input = e->GetParAs(0); if (momentDim != 0) { input = static_cast (static_cast (input)->Transpose(perm)); clean_array = true; } DFloatGDL* res = new DFloatGDL(destDim, BaseGDL::NOZERO); DFloatGDL* mean; DFloatGDL* var; DFloatGDL* skew; DFloatGDL* kurt; DFloatGDL* sdev; DFloatGDL* mdev; if (domean) mean = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (dovar) var = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (doskew) skew = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (dokurt) kurt = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (dosdev) sdev = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (domdev) mdev = new DFloatGDL(auxiliaryDim, BaseGDL::NOZERO); if (omitNaN) { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DFloat mdevl; DFloat sdevl; do_moment_nan(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } else { #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (SizeT i = 0; i < nEl; ++i) { DFloat mdevl; DFloat sdevl; do_moment(&(*input)[i * stride], stride, (*res)[i], (*res)[i+nEl], (*res)[i+2*nEl], (*res)[i+3*nEl], mdevl, sdevl, maxmoment); if (domean) (*mean)[i]=(*res)[i]; if (dovar ) (*var )[i]=(*res)[i+nEl]; if (doskew) (*skew)[i]=(*res)[i+2*nEl]; if (dokurt) (*kurt)[i]=(*res)[i+3*nEl]; if (dosdev) (*sdev)[i]=sdevl; if (domdev) (*mdev)[i]=mdevl; } } } if (clean_array) delete input; if (domean) e->SetKW( meanIx, mean ); if (dovar ) e->SetKW( varIx, var ); if (doskew) e->SetKW( skewIx, skew ); if (dokurt) e->SetKW( kurtIx, kurt ); if (dosdev) e->SetKW( sdevIx, sdev ); if (domdev) e->SetKW( mdevIx, mdev ); return res; } } } else { if (p0->Type() == GDL_COMPLEXDBL || (p0->Type() == GDL_COMPLEX && dbl)) { DComplexDblGDL* input = e->GetParAs(0); DComplexDbl mean; DComplexDbl var; DComplexDbl skew; DComplexDbl kurt; DComplexDbl sdev; DDouble mdev; if (omitNaN) do_moment_cpx_nan(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); else do_moment_cpx(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); if (domean) e->SetKW( meanIx,new DComplexDblGDL( mean) ); if (dovar ) e->SetKW( varIx, new DComplexDblGDL( var ) ); if (doskew) e->SetKW( skewIx,new DComplexDblGDL( skew) ); if (dokurt) e->SetKW( kurtIx,new DComplexDblGDL( kurt) ); if (dosdev) e->SetKW( sdevIx,new DComplexDblGDL( sdev) ); if (domdev) e->SetKW( mdevIx,new DDoubleGDL( mdev) ); DComplexDblGDL* res = new DComplexDblGDL(4, BaseGDL::NOZERO); (*res)[0]=mean; (*res)[1]=var; (*res)[2]=skew; (*res)[3]=kurt; return res; } else if (p0->Type() == GDL_COMPLEX) { DComplexGDL* input = e->GetParAs(0); DComplex mean; DComplex var; DComplex skew; DComplex kurt; DComplex sdev; DFloat mdev; if (omitNaN) do_moment_cpx_nan(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); else do_moment_cpx(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); if (domean) e->SetKW( meanIx,new DComplexGDL( mean) ); if (dovar ) e->SetKW( varIx, new DComplexGDL( var ) ); if (doskew) e->SetKW( skewIx,new DComplexGDL( skew) ); if (dokurt) e->SetKW( kurtIx,new DComplexGDL( kurt) ); if (dosdev) e->SetKW( sdevIx,new DComplexGDL( sdev) ); if (domdev) e->SetKW( mdevIx,new DFloatGDL( mdev) ); DComplexGDL* res = new DComplexGDL(4, BaseGDL::NOZERO); (*res)[0]=mean; (*res)[1]=var; (*res)[2]=skew; (*res)[3]=kurt; return res; } else { if (dbl) { DDoubleGDL* input = e->GetParAs(0); DDouble mean; DDouble var; DDouble skew; DDouble kurt; DDouble sdev; DDouble mdev; if (omitNaN) do_moment_nan(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); else do_moment(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); if (domean) e->SetKW( meanIx,new DDoubleGDL( mean) ); if (dovar ) e->SetKW( varIx, new DDoubleGDL( var ) ); if (doskew) e->SetKW( skewIx,new DDoubleGDL( skew) ); if (dokurt) e->SetKW( kurtIx,new DDoubleGDL( kurt) ); if (dosdev) e->SetKW( sdevIx,new DDoubleGDL( sdev) ); if (domdev) e->SetKW( mdevIx,new DDoubleGDL( mdev) ); DDoubleGDL* res = new DDoubleGDL(4, BaseGDL::NOZERO); (*res)[0]=mean; (*res)[1]=var; (*res)[2]=skew; (*res)[3]=kurt; return res; } else { DFloatGDL* input = e->GetParAs(0); DFloat mean; DFloat var; DFloat skew; DFloat kurt; DFloat sdev; DFloat mdev; if (omitNaN) do_moment_nan(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); else do_moment(&(*input)[0], input->N_Elements(), mean, var, skew, kurt, mdev, sdev, maxmoment); if (domean) e->SetKW( meanIx,new DFloatGDL( mean) ); if (dovar ) e->SetKW( varIx, new DFloatGDL( var ) ); if (doskew) e->SetKW( skewIx,new DFloatGDL( skew) ); if (dokurt) e->SetKW( kurtIx,new DFloatGDL( kurt) ); if (dosdev) e->SetKW( sdevIx,new DFloatGDL( sdev) ); if (domdev) e->SetKW( mdevIx,new DFloatGDL( mdev) ); DFloatGDL* res = new DFloatGDL(4, BaseGDL::NOZERO); (*res)[0]=mean; (*res)[1]=var; (*res)[2]=skew; (*res)[3]=kurt; return res; } } } } BaseGDL* ishft_fun(EnvT* e) { Guardga; Guardgb; DType typ = (e->GetParDefined(0))->Type(); //types are norally correct, so do not loose time looking for wrong types if ((typ == GDL_BYTE) || (typ == GDL_UINT) || (typ == GDL_INT) || (typ == GDL_LONG) || (typ == GDL_ULONG) || (typ == GDL_LONG64) || (typ == GDL_ULONG64)) { dimension finalDim; //behaviour: minimum set of dimensions of arrays. singletons expanded to dimension, //keep array trace. SizeT nEl, maxEl = 1, minEl, finalN = 1; for (int i = 0; i < 2; ++i) { nEl = e->GetPar(i)->N_Elements(); if ((nEl > 1) && (nEl > maxEl)) { maxEl = nEl; finalN = maxEl; finalDim = e->GetPar(i)->Dim(); } } //first max - but we need first min: minEl = maxEl; for (int i = 0; i < 2; ++i) { nEl = e->GetPar(i)->N_Elements(); if ((nEl > 1) && (nEl < minEl)) { minEl = nEl; finalN = minEl; finalDim = e->GetPar(i)->Dim(); } } //now get pointers to a and b, and increment (0 if b is singleton) switch (typ) { case GDL_BYTE: { DByteGDL* ret = new DByteGDL(finalDim, BaseGDL::NOZERO); DByteGDL* a=e->GetParAs(0); DByteGDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; case GDL_UINT: { DUIntGDL* ret = new DUIntGDL(finalDim, BaseGDL::NOZERO); DUIntGDL* a=e->GetParAs(0); DIntGDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; case GDL_INT: { DIntGDL* ret = new DIntGDL(finalDim, BaseGDL::NOZERO); DIntGDL* a=e->GetParAs(0); DIntGDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; case GDL_LONG: { DLongGDL* ret = new DLongGDL(finalDim, BaseGDL::NOZERO); DLongGDL* a=e->GetParAs(0); DLongGDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; case GDL_ULONG: { DULongGDL* ret = new DULongGDL(finalDim, BaseGDL::NOZERO); DULongGDL* a=e->GetParAs(0); DLongGDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; case GDL_LONG64: { DLong64GDL* ret = new DLong64GDL(finalDim, BaseGDL::NOZERO); DLong64GDL* a=e->GetParAs(0); DLong64GDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; case GDL_ULONG64: { DULong64GDL* ret = new DULong64GDL(finalDim, BaseGDL::NOZERO); DULong64GDL* a=e->GetParAs(0); DLong64GDL* b=e->GetParAs(1); if (a->Scalar()) {a=a->New( finalN, BaseGDL::INIT); ga.Reset(a);} //expand to return element size, for parallel processing if (b->Scalar()) {b=b->New( finalN, BaseGDL::INIT); gb.Reset(b);}//expand to return element size, for parallel processing #pragma omp parallel if (finalN >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= finalN)) { #pragma omp for for (SizeT i=0 ; i < finalN; ++i) (*ret)[i] = ((*b)[i]>=0)? (*a)[i] << (*b)[i]: (*a)[i] >> -(*b)[i]; } return ret; } break; default: cerr<<"Internal Error, please report"<Throw("Operand must be integer:" + e->GetParString(0)); return NULL; //pacify dumb compilers. } BaseGDL* shift_fun( EnvT* e) { SizeT nParam = e->NParam(2); BaseGDL* p0 = e->GetParDefined(0); SizeT nShift = nParam - 1; DLong sIx[ MAXRANK]; // in fact, the second param can be a singleton or an array ... if (nShift == 1) { DLongGDL* s1v = e->GetParAs(1); if (s1v->N_Elements() == 1) { DLong s1; e->AssureLongScalarPar(1, s1); // IncRef[Obj] done for GDL_PTR and GDL_OBJ return p0->CShift(s1); } if (p0->Rank() != s1v->N_Elements()) e->Throw("Incorrect number of arguments."); for (SizeT i = 0; i < s1v->N_Elements(); i++) sIx[ i] = (*s1v)[i]; } else { if (p0->Rank() != nShift) e->Throw("Incorrect number of arguments."); // DLong sIx[ MAXRANK]; for (SizeT i = 0; i < nShift; i++) e->AssureLongScalarPar(i + 1, sIx[ i]); if (p0->Type() == GDL_OBJ) GDLInterpreter::IncRefObj(static_cast (p0)); else if (p0->Type() == GDL_PTR) GDLInterpreter::IncRef(static_cast (p0)); } return p0->CShift(sIx); } BaseGDL* arg_present( EnvT* e) { e->NParam( 1); if( !e->GlobalPar( 0)) return new DIntGDL( 0); EnvBaseT* caller = e->Caller(); if( caller == NULL) return new DIntGDL( 0); BaseGDL** pp0 = &e->GetPar( 0); int ix = caller->FindGlobalKW( pp0); if( ix == -1) return new DIntGDL( 0); return new DIntGDL( 1); } BaseGDL* eof_fun( EnvT* e) { e->NParam( 1); DLong lun; e->AssureLongScalarPar( 0, lun); bool stdLun = check_lun( e, lun); if( stdLun) return new DIntGDL( 0); // nicer error message (Disregard if socket) if ( fileUnits[ lun-1].SockNum() == -1) { if( !fileUnits[ lun-1].IsOpen()) throw GDLIOException( e->CallingNode(), "File unit is not open: "+i2s( lun)+"."); if( fileUnits[ lun-1].Eof()) return new DIntGDL( 1); } else { // Socket string *recvBuf = &fileUnits[ lun-1].RecvBuf(); if (recvBuf->size() == 0) return new DIntGDL( 1); } return new DIntGDL( 0); } BaseGDL* rebin_fun( EnvT* e) { SizeT nParam = e->NParam( 2); BaseGDL* p0 = e->GetNumericParDefined( 0); SizeT rank = p0->Rank(); if( rank == 0) e->Throw( "Expression must be an array in this context: "+ e->GetParString(0)); SizeT resDimInit[ MAXRANK]; DLongGDL* p1 = e->GetParAs(1); if (p1->Rank() > 0 && nParam > 2) e->Throw("The new dimensions must either be specified as an array or as a set of scalars."); SizeT np = p1->Rank() == 0 ? nParam : p1->N_Elements() + 1; for( SizeT p=1; pRank() == 0) e->AssureLongScalarPar( p, newDim); else newDim = (*p1)[p - 1]; if( newDim <= 0) e->Throw( "Array dimensions must be greater than 0."); if( rank >= p) { SizeT oldDim = p0->Dim( p-1); if( newDim > oldDim) { if( (newDim % oldDim) != 0) e->Throw( "Result dimensions must be integer factor " "of original dimensions."); } else { if( (oldDim % newDim) != 0) e->Throw( "Result dimensions must be integer factor " "of original dimensions."); } } resDimInit[ p-1] = newDim; } dimension resDim( resDimInit, np-1); static int sampleIx = e->KeywordIx( "SAMPLE"); bool sample = e->KeywordSet( sampleIx); return p0->Rebin( resDim, sample); } BaseGDL* obj_class( EnvT* e) { SizeT nParam = e->NParam(); static int countIx = e->KeywordIx( "COUNT"); static int superIx = e->KeywordIx( "SUPERCLASS"); bool super = e->KeywordSet( superIx); bool count = e->KeywordPresent( countIx); if( count) e->AssureGlobalKW( countIx); if( nParam > 0) { BaseGDL* p0 = e->GetParDefined( 0); if( p0->Type() != GDL_STRING && p0->Type() != GDL_OBJ) e->Throw( "Argument must be a scalar object reference or string: "+ e->GetParString(0)); if( !p0->Scalar()) e->Throw( "Expression must be a scalar or 1 element " "array in this context: "+e->GetParString(0)); DStructDesc* objDesc; if( p0->Type() == GDL_STRING) { DString objName; e->AssureScalarPar( 0, objName); objName = StrUpCase( objName); objDesc = FindInStructList( structList, objName); if( objDesc == NULL) { if( count) e->SetKW( countIx, new DLongGDL( 0)); return new DStringGDL( ""); } } else // GDL_OBJ { DObj objRef; e->AssureScalarPar( 0, objRef); if( objRef == 0) { if( count) e->SetKW( countIx, new DLongGDL( 0)); return new DStringGDL( ""); } DStructGDL* oStruct; try { oStruct = e->GetObjHeap( objRef); } catch ( GDLInterpreter::HeapException& ) { // non valid object if( count) e->SetKW( countIx, new DLongGDL( 0)); return new DStringGDL( ""); } objDesc = oStruct->Desc(); // cannot be NULL } if( !super) { if( count) e->SetKW( countIx, new DLongGDL( 1)); return new DStringGDL( objDesc->Name()); } vector< string> pNames; objDesc->GetParentNames( pNames); SizeT nNames = pNames.size(); if( count) e->SetKW( countIx, new DLongGDL( nNames)); if( nNames == 0) { return new DStringGDL( ""); } DStringGDL* res = new DStringGDL( dimension( nNames), BaseGDL::NOZERO); for( SizeT i=0; iThrow( "Conflicting keywords."); SizeT nObj = structList.size(); DStringGDL* res = new DStringGDL( dimension( nObj), BaseGDL::NOZERO); for( SizeT i=0; iName(); } return res; } BaseGDL* obj_hasmethod( EnvT* e) { SizeT nParam = e->NParam( 2); //trace_me = trace_arg(); BaseGDL*& p0 = e->GetPar( 0); if( p0 == NULL || p0->Type() != GDL_OBJ) e->Throw( "Object reference type required in this context: "+ e->GetParString(0)); BaseGDL* p1 = e->GetParDefined( 1); if( p1->Type() != GDL_STRING) e->Throw( "Methods can be referenced only with names (strings)"); DStringGDL* p1S = static_cast( p1); DObjGDL* pObj = static_cast( p0); SizeT nObj = p0->StrictScalar() ? 1 : p0->N_Elements(); DByteGDL* res = new DByteGDL( dimension(nObj)); Guard res_guard(res); DByteGDL* altres = new DByteGDL( dimension(nObj)); Guard altres_guard(altres); GDLInterpreter* interpreter = e->Interpreter(); for( SizeT iobj=0; iobj( p0))[iobj]; if( s != 0) { // DStructGDL* oStruct = e->GetObjHeap( (*pObj)[iobj]); DStructGDL* oStruct = e->GetObjHeap( s); //if(trace_me) std::cout << " oStruct"; DStructDesc* odesc = oStruct->Desc(); int passed = 1; for( SizeT m=0; mN_Elements(); m++) { DString method = StrUpCase((*p1S)[m]); // if(trace_me) std::cout << method; if( odesc->GetFun( method) != NULL) continue; if( odesc->GetPro( method) != NULL) continue; passed = 0; break; } (*res)[iobj] = passed; for( SizeT i=iobj+1; iObjValid( (*pObj)[ i])) if( e->GetObjHeap( (*pObj)[i])->Desc() == odesc) { (*res)[i] = passed; (*altres)[i] = 1-passed; } } } // else if(trace_me) std::cout << " 0 "; } if( p0->StrictScalar()) return new DByteGDL((*res)[0]); else return res_guard.release(); } BaseGDL* obj_isa(EnvT* e) { DString className; e->AssureScalarPar(1, className); className = StrUpCase(className); if( className == "IDL_OBJECT") className = GDL_OBJECT_NAME; else if( className == "IDL_CONTAINER" ) className = GDL_CONTAINER_NAME; BaseGDL* p0 = e->GetPar(0); //nObjects is the number of objects or strings passed in array format. SizeT nElem = p0->N_Elements(); DByteGDL* res = new DByteGDL(p0->Dim()); // zero if (p0->Type() == GDL_OBJ) { DObjGDL* pObj = static_cast (p0); if (pObj) { //pObj protection probably overkill. for (SizeT i = 0; i < nElem; ++i) { if (e->Interpreter()->ObjValid((*pObj)[ i])) { DStructGDL* oStruct = e->GetObjHeap((*pObj)[i]); if (oStruct->Desc()->IsParent(className)) (*res)[i] = 1; } } return res; } } else if (p0->Type() == GDL_STRING) { std::cerr << "OBJ_ISA: not implemented for strings, only objects (FIXME)." << endl; for (SizeT i = 0; i < nElem; ++i) { (*res)[i] = 0; } return res; } else e->Throw("Object reference type required in this context: " + e->GetParString(0)); return NULL; } BaseGDL* n_tags( EnvT* e) { e->NParam( 1); BaseGDL* p0 = e->GetPar( 0); if( p0 == NULL) return new DLongGDL( 0); if( p0->Type() != GDL_STRUCT) return new DLongGDL( 0); DStructGDL* s = static_cast( p0); //static int lengthIx = e->KeywordIx( "DATA_LENGTH"); //bool length = e->KeywordSet( lengthIx); // we don't know now how to distinguish the 2 following cases static int datalengthIx=e->KeywordIx("DATA_LENGTH"); static int lengthIx=e->KeywordIx("LENGTH"); if(e->KeywordSet(datalengthIx)) return new DLongGDL( s->SizeofTags()); if(e->KeywordSet(lengthIx)) return new DLongGDL( s->Sizeof()); return new DLongGDL( s->Desc()->NTags()); } BaseGDL* bytscl(EnvT* e) { SizeT nParam = e->NParam(1); BaseGDL* p0 = e->GetNumericParDefined(0); static int minIx = e->KeywordIx("MIN"); static int maxIx = e->KeywordIx("MAX"); static int topIx = e->KeywordIx("TOP"); static int nanIx = e->KeywordIx("NAN"); bool omitNaN = e->KeywordPresent(nanIx); //the following is going to be wrong in cases where TOP is so negative that a Long does not suffice. //Besides, a template version for each different tyep would be faster and probably the only solution to get the //correct behavior in all cases. DLong topL = 255; if (e->GetKW(topIx) != NULL) e->AssureLongScalarKW(topIx, topL); if (topL > 255) topL = 255; // Bug corrected: Topl cannot be > 255. DDouble dTop = static_cast (topL); //Topl can be extremely negative. DDouble min; bool minSet = false; // SA: handling 3 parameters to emulate undocumented IDL behaviour // of translating second and third arguments to MIN and MAX, respectively // (parameters have precedence over keywords) if (nParam >= 2) { e->AssureDoubleScalarPar(1, min); minSet = true; } else if (e->GetKW(minIx) != NULL) { e->AssureDoubleScalarKW(minIx, min); minSet = true; } DDouble max; bool maxSet = false; if (nParam == 3) { e->AssureDoubleScalarPar(2, max); maxSet = true; } else if (e->GetKW(maxIx) != NULL) { e->AssureDoubleScalarKW(maxIx, max); maxSet = true; } DDoubleGDL* dRes = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); DLong maxEl, minEl; if (!maxSet || !minSet) dRes->MinMax(&minEl, &maxEl, NULL, NULL, omitNaN); if (!minSet) min = (*dRes)[ minEl]; if (!maxSet) max = (*dRes)[ maxEl]; // cout << "Min/max :" << min << " " << max << endl; SizeT nEl = dRes->N_Elements(); if (IntType(p0->Type())) { //Is a thread pool function #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for (SizeT i = 0; i < nEl; ++i) { DDouble& d = (*dRes)[ i]; if (omitNaN && (isnan(d) || isinf(d))) (*dRes)[ i] = 0; else if (d <= min) (*dRes)[ i] = 0; else if (d >= max) (*dRes)[ i] = dTop; else { // SA: floor is used for integer types to simulate manipulation on input data types (*dRes)[ i] = floor(((dTop + 1.)*(d - min) - 1.) / (max - min)); } } } else { #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for (SizeT i = 0; i < nEl; ++i) { DDouble& d = (*dRes)[ i]; if (omitNaN && (isnan(d) || isinf(d))) (*dRes)[ i] = 0; else if (d <= min) (*dRes)[ i] = 0; else if (d >= max) (*dRes)[ i] = dTop; else { // SA (?): here floor is used (instead of round) to simulate IDL behaviour (*dRes)[ i] = floor(((dTop + .9999)*(d - min)) / (max - min) ); } } } return dRes->Convert2(GDL_BYTE); } BaseGDL* strtok_fun(EnvT* e) { SizeT nParam = e->NParam(1); DString stringIn; e->AssureStringScalarPar(0, stringIn); DString pattern = " \t"; if (nParam > 1) { e->AssureStringScalarPar(1, pattern); } static int extractIx = e->KeywordIx( "EXTRACT"); bool extract = e->KeywordSet( extractIx); static int countIx = e->KeywordIx( "COUNT"); bool countPresent = e->KeywordPresent( countIx); static int lengthIx = e->KeywordIx( "LENGTH"); bool lengthPresent = e->KeywordPresent( lengthIx); static int pre0Ix = e->KeywordIx("PRESERVE_NULL"); bool pre0 = e->KeywordSet(pre0Ix); static int regexIx = e->KeywordIx("REGEX"); bool regex = e->KeywordSet(regexIx); char err_msg[MAX_REGEXPERR_LENGTH]; regex_t regexp; static int foldCaseIx = e->KeywordIx( "FOLD_CASE" ); bool foldCaseKW = e->KeywordSet( foldCaseIx ); //FOLD_CASE can only be specified if the REGEX keyword is set if (!regex && foldCaseKW) e->Throw("Conflicting keywords."); vector tokenStart; vector tokenLen; int strLen = stringIn.length(); DString escape = ""; static int ESCAPEIx=e->KeywordIx("ESCAPE"); //ESCAPE cannot be specified with the FOLD_CASE or REGEX keywords. if (regex && e->KeywordPresent(ESCAPEIx)) e->Throw("Conflicting keywords."); if (foldCaseKW && e->KeywordPresent(ESCAPEIx)) e->Throw("Conflicting keywords."); e->AssureStringScalarKWIfPresent(ESCAPEIx, escape); vector escList; long pos = 0; while (pos != string::npos) { pos = stringIn.find_first_of(escape, pos); if (pos != string::npos) { escList.push_back(pos + 1); // remember escaped char pos += 2; // skip escaped char } } vector::iterator escBeg = escList.begin(); vector::iterator escEnd = escList.end(); long tokB = 0; long tokE; long nextE = 0; long actLen; //special case: pattern void string if (pattern.size()==0) { if (lengthPresent) { e->AssureGlobalKW(lengthIx); e->SetKW(lengthIx, new DLongGDL(0)); } if (countPresent) { e->AssureGlobalKW(countIx); e->SetKW(countIx, new DLongGDL(0)); } if (!extract) return new DLongGDL(0); else return new DStringGDL(""); } // If regex then compile regex. // set the compile flags to use the REG_ICASE facility in case /FOLD_CASE is given. int cflags = REG_EXTENDED; if (foldCaseKW) cflags |= REG_ICASE; if (regex) { if (pattern == " \t") pattern = " "; // regcomp doesn't like "\t" JMG int compRes = regcomp(®exp, pattern.c_str(), cflags); if (compRes) { regerror(compRes, ®exp, err_msg, MAX_REGEXPERR_LENGTH); e->Throw("Error processing regular expression: " + pattern + "\n " + string(err_msg) + "."); } } if (foldCaseKW && !regex) { //duplicate pattern with ascii chars upcased pattern=pattern+StrUpCase(pattern); } for (;;) { regmatch_t pmatch[1]; if (regex) { int matchres = regexec(®exp, stringIn.c_str() + nextE, 1, pmatch, 0); tokE = matchres ? -1 : pmatch[0].rm_so; } else { tokE = stringIn.find_first_of(pattern, nextE); } if (tokE == string::npos) { actLen = strLen - tokB; if (actLen > 0 || pre0) { tokenStart.push_back(tokB); tokenLen.push_back(actLen); } break; } if (find(escBeg, escEnd, tokE) == escEnd) { if (regex) actLen = tokE; else actLen = tokE - tokB; if (actLen > 0 || pre0) { tokenStart.push_back(tokB); tokenLen.push_back(actLen); } if (regex) tokB += pmatch[0].rm_eo; else tokB = tokE + 1; } if (regex) nextE += pmatch[0].rm_eo; else nextE = tokE + 1; } // for(;;) if (regex) regfree(®exp); SizeT nTok = tokenStart.size(); if (countPresent) { e->AssureGlobalKW(countIx); if (nTok > 0) { DLongGDL* count = new DLongGDL(nTok); e->SetKW(countIx, count); } else { e->SetKW(countIx, new DLongGDL(0)); } } if (lengthPresent) { e->AssureGlobalKW(lengthIx); if (nTok > 0) { dimension dim(nTok); DLongGDL* len = new DLongGDL(dim); for (int i = 0; i < nTok; i++) (*len)[i] = tokenLen[i]; e->SetKW(lengthIx, len); } else { e->SetKW(lengthIx, new DLongGDL(0)); } } if (!extract) { if (nTok == 0) return new DLongGDL(0); dimension dim(nTok); DLongGDL* d = new DLongGDL(dim); for (int i = 0; i < nTok; i++) (*d)[i] = tokenStart[i]; return d; } else { // EXTRACT if (nTok == 0) return new DStringGDL(""); dimension dim(nTok); DStringGDL *d = new DStringGDL(dim); for (int i = 0; i < nTok; i++) { (*d)[i] = stringIn.substr(tokenStart[i], tokenLen[i]); // remove escape DString& act = (*d)[i]; long escPos = act.find_first_of(escape, 0); while (escPos != string::npos) { act = act.substr(0, escPos) + act.substr(escPos + 1); escPos = act.find_first_of(escape, escPos + 1); } } return d; } } BaseGDL* getenv_fun( EnvT* e) { SizeT nParam=e->NParam(); static int environmentIx = e->KeywordIx( "ENVIRONMENT" ); bool environment = e->KeywordSet( environmentIx ); SizeT nEnv; DStringGDL* env; if( environment) { if(nParam != 0) e->Throw( "Incorrect number of arguments."); // determine number of environment entries for(nEnv = 0; environ[nEnv] != NULL ; ++nEnv); dimension dim( nEnv ); env = new DStringGDL(dim); // copy stuff into local string array for(SizeT i=0; i < nEnv ; ++i) (*env)[i] = environ[i]; } else { if(nParam != 1) e->Throw( "Incorrect number of arguments."); DStringGDL* name = e->GetParAs(0); nEnv = name->N_Elements(); env = new DStringGDL( name->Dim()); // copy the stuff into local string only if param found char *resPtr; for(SizeT i=0; i < nEnv ; ++i) { // handle special environment variables // GDL_TMPDIR, IDL_TMPDIR if( (*name)[i] == "GDL_TMPDIR" || (*name)[i] == "IDL_TMPDIR") { resPtr = getenv((*name)[i].c_str()); if (resPtr != NULL) { (*env)[i] = resPtr; } else { // (*env)[i] = SysVar::Dir(); #ifdef _WIN32 WCHAR tmpBuf[MAX_PATH]; GetTempPathW(MAX_PATH, tmpBuf); char c_tmpBuf[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, tmpBuf, MAX_PATH, c_tmpBuf, MAX_PATH, NULL, NULL); (*env)[i] = c_tmpBuf; #else // AC 2017/10/19 : why _PATH_VARTMP_, not just _PATH_TMP_ (*env)[i] = _PATH_TMP ; #endif } AppendIfNeeded( (*env)[i], "/"); } else // normal environment variables if( (resPtr = getenv((*name)[i].c_str())) ) (*env)[i] = resPtr; } } return env; } BaseGDL* tag_names_fun( EnvT* e) { SizeT nParam=e->NParam(); DStructGDL* struc= e->GetParAs(0); static int structureNameIx = e->KeywordIx( "STRUCTURE_NAME" ); bool structureName = e->KeywordSet( structureNameIx ); DStringGDL* tagNames; if(structureName){ if ((*struc).Desc()->Name() != "$truct") tagNames = new DStringGDL((*struc).Desc()->Name()); else tagNames = new DStringGDL(""); } else { SizeT nTags = (*struc).Desc()->NTags(); tagNames = new DStringGDL(dimension(nTags)); for(int i=0; i < nTags; ++i) (*tagNames)[i] = (*struc).Desc()->TagName(i); } return tagNames; } // AC 12-Oc-2011: better version for: len=len, /Extract and /Sub // but it is still not perfect BaseGDL* stregex_fun( EnvT* e) { SizeT nParam=e->NParam( 2); DStringGDL* stringExpr= e->GetParAs(0); dimension dim = stringExpr->Dim(); DString pattern; e->AssureStringScalarPar(1, pattern); if (pattern.size() <= 0) { e->Throw( "Error processing regular expression: "+pattern+ "\n empty (sub)expression"); } static int booleanIx = e->KeywordIx( "BOOLEAN" ); bool booleanKW = e->KeywordSet( booleanIx ); static int extractIx = e->KeywordIx( "EXTRACT" ); bool extractKW = e->KeywordSet( extractIx ); static int foldCaseIx = e->KeywordIx( "FOLD_CASE" ); bool foldCaseKW = e->KeywordSet( foldCaseIx ); //XXXpch: this is wrong, should check arg_present static int lengthIx = e->KeywordIx( "LENGTH" ); bool lengthKW = e->KeywordPresent( lengthIx ); static int subexprIx = e->KeywordIx( "SUBEXPR" ); bool subexprKW = e->KeywordSet( subexprIx ); if( booleanKW && (subexprKW || extractKW || lengthKW)) e->Throw( "Conflicting keywords."); char err_msg[MAX_REGEXPERR_LENGTH]; // set the compile flags int cflags = REG_EXTENDED; if (foldCaseKW) cflags |= REG_ICASE; if (booleanKW) cflags |= REG_NOSUB; // compile the regular expression regex_t regexp; int compRes = regcomp( ®exp, pattern.c_str(), cflags); SizeT nSubExpr = regexp.re_nsub + 1; // cout << regexp.re_nsub << endl; if (compRes) { regerror(compRes, ®exp, err_msg, MAX_REGEXPERR_LENGTH); e->Throw( "Error processing regular expression: "+ pattern+"\n "+string(err_msg)+"."); } BaseGDL* result; if( booleanKW) result = new DByteGDL(dim); else if( extractKW && !subexprKW) { // cout << "my pb ! ? dim= " << dim << endl; result = new DStringGDL(dim); } else if( subexprKW) { // cout << "my pb 2 ? dim= " << dim << endl; dimension subExprDim = dim; subExprDim >> nSubExpr; // m_schellens: commented in, needed if( extractKW) result = new DStringGDL(subExprDim); else result = new DLongGDL(subExprDim); } else result = new DLongGDL(dim); DLongGDL* len = NULL; if( lengthKW) { e->AssureGlobalKW( lengthIx); if( subexprKW) { dimension subExprDim = dim; subExprDim >> nSubExpr; // m_schellens: commented in, needed len = new DLongGDL(subExprDim); } else { len = new DLongGDL(dim); } for( SizeT i=0; iN_Elements(); ++i) (*len)[i]= -1; } int nmatch = 1; if( subexprKW) nmatch = nSubExpr; regmatch_t* pmatch = new regmatch_t[nSubExpr]; ArrayGuard pmatchGuard( pmatch); // cout << "dim " << dim.NDimElements() << endl; for( SizeT s=0; s(result))[i+s*nSubExpr] = (*stringExpr)[s].substr( pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so); // (*stringExpr)[i+s*nSubExpr].substr( pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so); if( lengthKW) (*len)[i+s*nSubExpr] = pmatch[i].rm_so != -1 ? pmatch[i].rm_eo - pmatch[i].rm_so : -1; // (*len)[i+s*nSubExpr] = pmatch[i].rm_eo - pmatch[i].rm_so; } } else if ( subexprKW) { // cout << "je ne comprends pas v2: "<< nSubExpr << endl; // Loop through subexpressions & fill output array for( SizeT i = 0; i(result))[i+s*nSubExpr] = pmatch[i].rm_so; if( lengthKW) (*len)[i+s*nSubExpr] = pmatch[i].rm_so != -1 ? pmatch[i].rm_eo - pmatch[i].rm_so : -1; } } else { if( booleanKW) (* static_cast(result))[s] = (matchres == 0); else if ( extractKW) // !subExprKW { if( matchres == 0) (* static_cast(result))[s] = (*stringExpr)[s].substr( pmatch[0].rm_so, pmatch[0].rm_eo - pmatch[0].rm_so); } else (*static_cast(result))[s] = matchres ? -1 : pmatch[0].rm_so; } if( lengthKW && !subexprKW) //(*len)[s] = pmatch[0].rm_eo - pmatch[0].rm_so; (*len)[s] = pmatch[0].rm_so != -1 ? pmatch[0].rm_eo - pmatch[0].rm_so : -1; } regfree( ®exp); if( lengthKW) e->SetKW( lengthIx, len); return result; } BaseGDL* routine_filepath( EnvT* e) { SizeT nParam=e->NParam(); DStringGDL* p0S; Guard p0S_guard; if (nParam > 1) e->Throw("Incorrect number of arguments."); if( nParam > 0) { BaseGDL* p0 = e->GetParDefined( 0); if( p0->Type() != GDL_STRING) e->Throw("String expression required in this context: " + e->GetParString(0)); p0S = static_cast( p0); } else { // routine_filepath() p0S = new DStringGDL( dynamic_cast((e->Caller())->GetPro())->Name()); p0S_guard.Init(p0S); } static int is_functionIx = e->KeywordIx( "IS_FUNCTION" ); bool is_functionKW = e->KeywordSet( is_functionIx ); static int eitherIx = e->KeywordIx( "EITHER" ); bool eitherKW = e->KeywordSet( eitherIx ); SizeT nPath = p0S->N_Elements(); DStringGDL* res = new DStringGDL(p0S->Dim(), BaseGDL::NOZERO); Guard res_guard(res); DString name; string FullFileName; for(int i = 0; i < nPath; i ++) { name = StrUpCase((*p0S)[i]); bool found=false; FullFileName = ""; if( eitherKW || !is_functionKW) { for(ProListT::iterator i=proList.begin(); i != proList.end(); ++i) if ((*i)->ObjectName() == name) { found=true; FullFileName=(*i)->GetFilename(); break; } } if (!found && (is_functionKW || eitherKW)) { for(FunListT::iterator i=funList.begin(); i != funList.end(); ++i) if ((*i)->ObjectName() == name) { found=true; FullFileName=(*i)->GetFilename(); break; } } (*res)[i] = FullFileName; } // if(nParam == 0) return new DStringGDL(FullFileName); return res_guard.release(); } BaseGDL* routine_info( EnvT* e) { SizeT nParam=e->NParam(); if (nParam > 1) e->Throw("Incorrect number of arguments."); static int functionsIx = e->KeywordIx( "FUNCTIONS" ); bool functionsKW = e->KeywordSet( functionsIx ); static int systemIx = e->KeywordIx( "SYSTEM" ); bool systemKW = e->KeywordSet( systemIx ); static int disabledIx = e->KeywordIx( "DISABLED" ); bool disabledKW = e->KeywordSet( disabledIx ); static int parametersIx = e->KeywordIx( "PARAMETERS" ); bool parametersKW = e->KeywordSet( parametersIx ); static int sourceIx = e->KeywordIx( "SOURCE" ); bool sourceKW = e->KeywordSet(sourceIx ); if ( sourceKW ) { // sanity checks if ( systemKW ) e->Throw( "Conflicting keywords." ); DString raw_name, name; string FullFileName; bool found = FALSE; DStructGDL* stru; DStructDesc* stru_desc; if ( nParam == 1 ) { // getting the routine name from the first parameter (must be a singleton) e->AssureScalarPar(0, raw_name); name = StrUpCase( raw_name ); if ( functionsKW ) { for ( FunListT::iterator i = funList.begin( ); i != funList.end( ); ++i ) { if ( (*i)->ObjectName( ) == name ) { found = true; FullFileName = (*i)->GetFilename( ); break; } } if ( !found ) e->Throw( "% Attempt to call undefined/not compiled function: '" + raw_name + "'" ); } else { for ( ProListT::iterator i = proList.begin( ); i != proList.end( ); ++i ) { if ( (*i)->ObjectName( ) == name ) { found = true; FullFileName = (*i)->GetFilename( ); break; } } if ( !found ) e->Throw( "% Attempt to call undefined/not compiled procedure: '" + raw_name + "'" ); } // creating the output anonymous structure stru_desc = new DStructDesc( "$truct" ); SpDString aString; stru_desc->AddTag( "NAME", &aString ); stru_desc->AddTag( "PATH", &aString ); stru = new DStructGDL( stru_desc, dimension( ) ); // filling the structure with information about the routine stru->InitTag( "NAME", DStringGDL( name ) ); stru->InitTag( "PATH", DStringGDL( FullFileName ) ); return stru; } else { // creating the output anonymous structure stru_desc = new DStructDesc( "$truct" ); SpDString aString; stru_desc->AddTag( "NAME", &aString ); stru_desc->AddTag( "PATH", &aString ); //always starts with $MAIN$ SizeT N=(functionsKW)?funList.size()+1:proList.size()+1; stru = new DStructGDL( stru_desc, dimension(N) ); (*static_cast(stru->GetTag((SizeT)0, 0)))[0]="$MAIN$"; if ( functionsKW ) { SizeT ii=1; for ( FunListT::iterator i = funList.begin( ); i != funList.end( ); ++i ) { (*static_cast(stru->GetTag((SizeT)0, ii)))[0]=(*i)->ObjectName( ); (*static_cast(stru->GetTag((SizeT)1, ii)))[0]=(*i)->GetFilename( ); ii++; } } else { SizeT ii=1; for ( ProListT::iterator i = proList.begin( ); i != proList.end( ); ++i ) { (*static_cast(stru->GetTag((SizeT)0, ii)))[0]=(*i)->ObjectName( ); (*static_cast(stru->GetTag((SizeT)1, ii)))[0]=(*i)->GetFilename( ); ii++; } } return stru; } } if (parametersKW) { // sanity checks if (systemKW || disabledKW) e->Throw("Conflicting keywords."); // getting the routine name from the first parameter DString name; e->AssureScalarPar(0, name); name = StrUpCase(name); DSubUD* routine = functionsKW ? static_cast(funList[GDLInterpreter::GetFunIx(name)]) : static_cast(proList[GDLInterpreter::GetProIx(name)]); SizeT np = routine->NPar(), nk = routine->NKey(); // creating the output anonymous structure DStructDesc* stru_desc = new DStructDesc("$truct"); SpDLong aLong; stru_desc->AddTag("NUM_ARGS", &aLong); stru_desc->AddTag("NUM_KW_ARGS", &aLong); if (np > 0) { SpDString aStringArr(dimension((int)np)); stru_desc->AddTag("ARGS", &aStringArr); } if (nk > 0) { SpDString aStringArr(dimension((int)nk)); stru_desc->AddTag("KW_ARGS", &aStringArr); } DStructGDL* stru = new DStructGDL(stru_desc, dimension()); // filling the structure with information about the routine stru->InitTag("NUM_ARGS", DLongGDL(np)); stru->InitTag("NUM_KW_ARGS", DLongGDL(nk)); if (np > 0) { DStringGDL *pnames = new DStringGDL(dimension(np)); for (SizeT p = 0; p < np; ++p) (*pnames)[p] = routine->GetVarName(nk + p); stru->InitTag("ARGS", *pnames); GDLDelete(pnames); } if (nk > 0) { DStringGDL *knames = new DStringGDL(dimension(nk)); for (SizeT k = 0; k < nk; ++k) (*knames)[k] = routine->GetKWName(k); stru->InitTag("KW_ARGS", *knames); GDLDelete(knames); } // returning return stru; } // GDL does not have disabled routines if( disabledKW) return new DStringGDL(""); // if( functionsKW || systemKW || nParam == 0) // { vector subList; if( functionsKW) { if( systemKW) { SizeT n = libFunList.size(); if( n == 0) return new DStringGDL(""); DStringGDL* res = new DStringGDL( dimension( n), BaseGDL::NOZERO); for( SizeT i = 0; iObjectName(); return res; } else { SizeT n = funList.size(); if( n == 0) { Message("No FUNCTIONS compiled yet !"); return new DStringGDL(""); } for( SizeT i = 0; iObjectName()); } } else { if( systemKW) { SizeT n = libProList.size(); if( n == 0) return new DStringGDL(""); DStringGDL* res = new DStringGDL( dimension( n), BaseGDL::NOZERO); for( SizeT i = 0; iObjectName(); return res; } else { SizeT n = proList.size(); if( n == 0) { Message("No PROCEDURES compiled yet !"); DStringGDL* res = new DStringGDL(1, BaseGDL::NOZERO); (*res)[0]="$MAIN$"; return res; } subList.push_back("$MAIN$"); for( SizeT i = 0; iObjectName()); } } sort( subList.begin(), subList.end()); SizeT nS = subList.size(); DStringGDL* res = new DStringGDL( dimension( nS), BaseGDL::NOZERO); for( SizeT s=0; s rl_prep_terminal (0); #endif #if defined(HAVE_EDITLINE) #include rl_prep_terminal (0); #endif SizeT nParam=e->NParam(); bool doWait = true; if( nParam > 0) { doWait = false; DLong waitArg = 0; e->AssureLongScalarPar( 0, waitArg); if( waitArg != 0) { doWait = true; } } // https://sourceforge.net/forum/forum.php?thread_id=3292183&forum_id=338691 // DONE: Implement proper SCALAR parameter handling (doWait variable) // which is/was not blocking in the original program. // note: multi-byte input is not supported here. char c='\0'; //initialize is never a bad idea... int fd=fileno(stdin); #ifndef _WIN32 struct termios orig, get; #endif // Get terminal setup to revert to it at end. #ifndef _WIN32 (void)tcgetattr(fd, &orig); // New terminal setup, non-canonical. get.c_lflag = ISIG; #endif if (doWait) { // will wait for a character #ifndef _WIN32 get.c_cc[VTIME]=0; get.c_cc[VMIN]=1; (void)tcsetattr(fd, TCSANOW, &get); #endif cin.get(c); } else { // will not wait, but return EOF or next character in terminal buffer if present #ifndef _WIN32 get.c_cc[VTIME]=0; get.c_cc[VMIN]=0; (void)tcsetattr(fd, TCSANOW, &get); #endif //the trick is *not to use C++ functions here. cin.get would wait.* c=std::fgetc(stdin); //and to convert EOF to null (otherwise GDL may exit if not compiled with //[lib][n]curses) if(c==EOF) c='\0'; } // Restore original terminal settings. #ifndef _WIN32 (void)tcsetattr(fd, TCSANOW, &orig); #endif #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) rl_deprep_terminal (); #endif DStringGDL* res = new DStringGDL( DString( i2s( c))); return res; } BaseGDL* temporary( EnvT* e) { SizeT nParam=e->NParam(1); BaseGDL** p0 = &e->GetParDefined( 0); BaseGDL* ret = *p0; *p0 = NULL; // make parameter undefined return ret; } BaseGDL* memory( EnvT* e) { SizeT nParam=e->NParam( 0); BaseGDL* ret; static int kw_l64_Ix = e->KeywordIx("L64"); bool kw_l64 = e->KeywordSet(kw_l64_Ix); // TODO: IDL-doc mentions about automatically switching to L64 if needed static int structureIx=e->KeywordIx("STRUCTURE"); if (e->KeywordSet(structureIx)) { // returning structure if (kw_l64) { ret = new DStructGDL("IDL_MEMORY64"); DStructGDL* retStru = static_cast(ret); (retStru->GetTag(retStru->Desc()->TagIndex("CURRENT")))->InitFrom( DLong64GDL(MemStats::GetCurrent())); (retStru->GetTag(retStru->Desc()->TagIndex("NUM_ALLOC")))->InitFrom( DLong64GDL(MemStats::GetNumAlloc())); (retStru->GetTag(retStru->Desc()->TagIndex("NUM_FREE")))->InitFrom( DLong64GDL(MemStats::GetNumFree())); (retStru->GetTag(retStru->Desc()->TagIndex("HIGHWATER")))->InitFrom( DLong64GDL(MemStats::GetHighWater())); } else { ret = new DStructGDL("IDL_MEMORY"); DStructGDL* retStru = static_cast(ret); (retStru->GetTag(retStru->Desc()->TagIndex("CURRENT")))->InitFrom( DLongGDL(MemStats::GetCurrent())); (retStru->GetTag(retStru->Desc()->TagIndex("NUM_ALLOC")))->InitFrom( DLongGDL(MemStats::GetNumAlloc())); (retStru->GetTag(retStru->Desc()->TagIndex("NUM_FREE")))->InitFrom( DLongGDL(MemStats::GetNumFree())); (retStru->GetTag(retStru->Desc()->TagIndex("HIGHWATER")))->InitFrom( DLongGDL(MemStats::GetHighWater())); } } else { static int Ix_kw_current = e->KeywordIx("CURRENT"); static int Ix_kw_num_alloc = e->KeywordIx("NUM_ALLOC"); static int Ix_kw_num_free = e->KeywordIx("NUM_FREE"); static int Ix_kw_highwater = e->KeywordIx("HIGHWATER"); bool kw_current = e->KeywordSet( Ix_kw_current ); bool kw_num_alloc = e->KeywordSet( Ix_kw_num_alloc); bool kw_num_free = e->KeywordSet( Ix_kw_num_free ); bool kw_highwater = e->KeywordSet( Ix_kw_highwater); // Following the IDL documentation: mutually exclusive keywords // IDL behaves different, incl. segfaults with selected kw combinations if (kw_current + kw_num_alloc + kw_num_free + kw_highwater > 1) e->Throw("CURRENT, NUM_ALLOC, NUM_FREE & HIGHWATER keywords" " are mutually exclusive"); if (kw_current) { if (kw_l64) ret = new DLong64GDL(MemStats::GetCurrent()); else ret = new DLongGDL(MemStats::GetCurrent()); } else if (kw_num_alloc) { if (kw_l64) ret = new DLong64GDL(MemStats::GetNumAlloc()); else ret = new DLongGDL(MemStats::GetNumAlloc()); } else if (kw_num_free) { if (kw_l64) ret = new DLong64GDL(MemStats::GetNumFree()); else ret = new DLongGDL(MemStats::GetNumFree()); } else if (kw_highwater) { if (kw_l64) ret = new DLong64GDL(MemStats::GetHighWater()); else ret = new DLongGDL(MemStats::GetHighWater()); } else { // returning 4-element array if (kw_l64) { ret = new DLong64GDL(dimension(4)); (*static_cast(ret))[0] = MemStats::GetCurrent(); (*static_cast(ret))[1] = MemStats::GetNumAlloc(); (*static_cast(ret))[2] = MemStats::GetNumFree(); (*static_cast(ret))[3] = MemStats::GetHighWater(); } else { ret = new DLongGDL(dimension(4)); (*static_cast(ret))[0] = MemStats::GetCurrent(); (*static_cast(ret))[1] = MemStats::GetNumAlloc(); (*static_cast(ret))[2] = MemStats::GetNumFree(); (*static_cast(ret))[3] = MemStats::GetHighWater(); } } } return ret; } inline DByte StrCmp( const string& s1, const string& s2, DLong n) { if( n <= 0) return 1; if( s1.substr(0,n) == s2.substr(0,n)) return 1; return 0; } inline DByte StrCmp( const string& s1, const string& s2) { if( s1 == s2) return 1; return 0; } inline DByte StrCmpFold( const string& s1, const string& s2, DLong n) { if( n <= 0) return 1; if( StrUpCase( s1.substr(0,n)) == StrUpCase(s2.substr(0,n))) return 1; return 0; } inline DByte StrCmpFold( const string& s1, const string& s2) { if( StrUpCase( s1) == StrUpCase(s2)) return 1; return 0; } BaseGDL* strcmp_fun( EnvT* e) { SizeT nParam=e->NParam(2); DStringGDL* s0 = static_cast( e->GetParAs< DStringGDL>( 0)); DStringGDL* s1 = static_cast( e->GetParAs< DStringGDL>( 1)); DLongGDL* l2 = NULL; if( nParam > 2) { l2 = static_cast( e->GetParAs< DLongGDL>( 2)); } static int foldIx = e->KeywordIx( "FOLD_CASE"); bool fold = e->KeywordSet( foldIx ); if( s0->Scalar() && s1->Scalar()) { if( l2 == NULL) { if( fold) return new DByteGDL( StrCmpFold( (*s0)[0], (*s1)[0])); else return new DByteGDL( StrCmp( (*s0)[0], (*s1)[0])); } else { DByteGDL* res = new DByteGDL( l2->Dim(), BaseGDL::NOZERO); SizeT nEl = l2->N_Elements(); if( fold) for( SizeT i=0; iScalar()) { DByteGDL* res = new DByteGDL( s1->Dim(), BaseGDL::NOZERO); SizeT nEl = s1->N_Elements(); if( fold) for( SizeT i=0; iScalar()) { DByteGDL* res = new DByteGDL( s0->Dim(), BaseGDL::NOZERO); SizeT nEl = s0->N_Elements(); if( fold) for( SizeT i=0; iN_Elements() <= s1->N_Elements()) { res = new DByteGDL( s0->Dim(), BaseGDL::NOZERO); nEl = s0->N_Elements(); } else { res = new DByteGDL( s1->Dim(), BaseGDL::NOZERO); nEl = s1->N_Elements(); } if( fold) for( SizeT i=0; iScalar(); if( s0->Scalar()) { if( l2Scalar || s1->N_Elements() <= l2->N_Elements()) { res = new DByteGDL( s1->Dim(), BaseGDL::NOZERO); nEl = s1->N_Elements(); } else { res = new DByteGDL( l2->Dim(), BaseGDL::NOZERO); nEl = l2->N_Elements(); } if( fold) for( SizeT i=0; iScalar()) { if( l2Scalar || s0->N_Elements() <= l2->N_Elements()) { res = new DByteGDL( s0->Dim(), BaseGDL::NOZERO); nEl = s0->N_Elements(); } else { res = new DByteGDL( l2->Dim(), BaseGDL::NOZERO); nEl = l2->N_Elements(); } if( fold) for( SizeT i=0; iN_Elements() <= s1->N_Elements()) { res = new DByteGDL( s0->Dim(), BaseGDL::NOZERO); nEl = s0->N_Elements(); } else { res = new DByteGDL( s1->Dim(), BaseGDL::NOZERO); nEl = s1->N_Elements(); } else { if( s0->N_Elements() <= s1->N_Elements()) if( s0->N_Elements() <= l2->N_Elements()) { res = new DByteGDL( s0->Dim(), BaseGDL::NOZERO); nEl = s0->N_Elements(); } else { res = new DByteGDL( l2->Dim(), BaseGDL::NOZERO); nEl = l2->N_Elements(); } else if( s1->N_Elements() <= l2->N_Elements()) { res = new DByteGDL( s1->Dim(), BaseGDL::NOZERO); nEl = s1->N_Elements(); } else { res = new DByteGDL( l2->Dim(), BaseGDL::NOZERO); nEl = l2->N_Elements(); } } if( fold) for( SizeT i=0; i 'Z')) e->Throw( "Illegal tag name: "+name+"."); for( SizeT i=1; i 'Z') && (n[i] < '0' || n[i] > '9')) e->Throw( "Illegal tag name: "+name+"."); } return n; } BaseGDL* create_struct( EnvT* e) { static int nameIx = e->KeywordIx( "NAME" ); DString name = "$truct"; if( e->KeywordPresent( nameIx)) { // Check if name exists, if not then treat as unnamed if (e->GetKW( nameIx) != NULL) e->AssureStringScalarKW( nameIx, name); } if( name != "$truct") // named struct { name = StrUpCase( name); SizeT nParam=e->NParam(); if( nParam == 0) { DStructDesc* desc = e->Interpreter()->GetStruct( name, e->CallingNode()); dimension dim( 1); return new DStructGDL( desc, dim); } DStructDesc* nStructDesc; Guard nStructDescGuard; DStructDesc* oStructDesc= FindInStructList( structList, name); if( oStructDesc == NULL || oStructDesc->NTags() > 0) { // not defined at all yet (-> define now) // or completely defined (-> define now and check equality) nStructDesc= new DStructDesc( name); // guard it nStructDescGuard.Reset( nStructDesc); } else { // NTags() == 0 // not completely defined (only name in list) nStructDesc= oStructDesc; } // the instance variable // dimension dim( 1); // DStructGDL* instance = new DStructGDL( nStructDesc, dim); DStructGDL* instance = new DStructGDL( nStructDesc); Guard instance_guard(instance); for( SizeT p=0; pGetParDefined( p); if( par->Type() == GDL_STRUCT) { DStructGDL* parStruct = static_cast( par); // add struct if( !parStruct->Scalar()) e->Throw("Expression must be a scalar in this context: "+ e->GetParString( p)); DStructDesc* desc = parStruct->Desc(); for( SizeT t=0; t< desc->NTags(); ++t) { instance->NewTag( desc->TagName( t), parStruct->GetTag( t)->Dup()); } } else { // add tag value pair DStringGDL* tagNames = e->GetParAs( p); SizeT nTags = tagNames->N_Elements(); SizeT tagStart = p+1; SizeT tagEnd = p+nTags; if( tagEnd >= nParam) e->Throw( "Incorrect number of arguments."); do{ ++p; BaseGDL* value = e->GetParDefined( p); // add instance->NewTag( TagName( e, (*tagNames)[ p-tagStart]), value->Dup()); } while( pAssureIdentical(nStructDesc); instance->DStructGDL::SetDesc(oStructDesc); //delete nStructDesc; // auto_ptr } } else { // release from guard (if not NULL) nStructDescGuard.release(); // insert into struct list structList.push_back(nStructDesc); } instance_guard.release(); return instance; } else { // unnamed struc // Handle case of single structure parameter SizeT nParam; nParam = e->NParam(1); BaseGDL* par = e->GetParDefined( 0); // DStructGDL* parStruct = dynamic_cast( par); if (nParam != 1 || par->Type() != GDL_STRUCT)// == NULL) nParam=e->NParam(2); DStructDesc* nStructDesc = new DStructDesc( "$truct"); // instance takes care of nStructDesc since it is unnamed // dimension dim( 1); // DStructGDL* instance = new DStructGDL( nStructDesc, dim); DStructGDL* instance = new DStructGDL( nStructDesc); Guard instance_guard(instance); for( SizeT p=0; pGetParDefined( p); // DStructGDL* parStruct = dynamic_cast( par); // if( parStruct != NULL) if( par->Type() == GDL_STRUCT) { // add struct DStructGDL* parStruct = static_cast( par); if( !parStruct->Scalar()) e->Throw("Expression must be a scalar in this context: "+ e->GetParString( p)); DStructDesc* desc = parStruct->Desc(); for( SizeT t=0; t< desc->NTags(); ++t) { instance->NewTag( desc->TagName( t), parStruct->GetTag( t)->Dup()); } ++p; } else { // add tag value pair DStringGDL* tagNames = e->GetParAs( p); SizeT nTags = tagNames->N_Elements(); SizeT tagStart = p+1; SizeT tagEnd = p+nTags; if( tagEnd >= nParam) e->Throw( "Incorrect number of arguments."); for(++p; p<=tagEnd; ++p) { BaseGDL* value = e->GetParDefined( p); // add instance->NewTag( TagName( e, (*tagNames)[ p-tagStart]), value->Dup()); } } } instance_guard.release(); return instance; } } BaseGDL* rotate(EnvT* e) { e->NParam(2); BaseGDL* p0 = e->GetParDefined(0); if (p0->Rank() == 0) e->Throw("Expression must be an array in this context: " + e->GetParString(0)); if (p0->Rank() != 1 && p0->Rank() != 2) e->Throw("Only 1 or 2 dimensions allowed: " + e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("STRUCT expression not allowed in this context: " + e->GetParString(0)); DLong dir; e->AssureLongScalarPar(1, dir); return p0->Rotate(dir); } // SA: based on the code of rotate() (above) BaseGDL* reverse(EnvT* e) { e->NParam(1); BaseGDL* p0 = e->GetParDefined(0); if (p0->Rank() == 0) return p0->Dup(); DLong dim = 1; if (e->GetPar(1) != NULL) e->AssureLongScalarPar(1, dim); if (p0->Rank() != 0 && (dim > p0->Rank() || dim < 1)) e->Throw("Subscript_index must be positive and less than or equal to number of dimensions."); BaseGDL* ret; // IDL doc states that OVERWRITE is ignored for one- or two-dim. arrays // but it seems to behave differently // if (p0->Rank() > 2 && e->KeywordSet("OVERWRITE") && e->GlobalPar(0)) static int overwriteIx = e->KeywordIx("OVERWRITE"); if (e->KeywordSet(overwriteIx)) { p0->Reverse(dim - 1); bool stolen = e->StealLocalPar(0); // if( !stolen) // e->GetPar(0) = NULL; if (!stolen) e->SetPtrToReturnValue(&e->GetPar(0)); return p0; } else ret = p0->DupReverse(dim - 1); return ret; } // PARSE_URL based on the IDL parse_url function behaviour and documentation BaseGDL* parse_url( EnvT* env) { // sanity check for number of parameters SizeT nParam = env->NParam(); // 1-nd argument : the url string DString url; env->AssureScalarPar(0, url); // creating the output anonymous structure DStructDesc* urlstru_desc = new DStructDesc("$truct"); SpDString aString; urlstru_desc->AddTag("SCHEME", &aString); urlstru_desc->AddTag("USERNAME", &aString); urlstru_desc->AddTag("PASSWORD", &aString); urlstru_desc->AddTag("HOST", &aString); urlstru_desc->AddTag("PORT", &aString); urlstru_desc->AddTag("PATH", &aString); urlstru_desc->AddTag("QUERY", &aString); DStructGDL* urlstru = new DStructGDL(urlstru_desc, dimension()); Guard urlstru_guard(urlstru); char const *str = url.c_str(); size_t length = url.length(); char const*pStart, *pMid, *pEnd; // initialise PORT at 80 urlstru->InitTag("PORT", DStringGDL("80")); //searching for the scheme and exciting if not found pStart = str; if (!(pEnd = std::strstr(str, "://"))){ urlstru_guard.release(); return (urlstru); } urlstru->InitTag("SCHEME", DStringGDL(pStart < pEnd ? string(pStart, pEnd - pStart) : "")); // setting pStart after "://" pEnd += 3; pStart = pEnd; //searching for the username and password (':' & '@') if (std::strchr(pStart, '@')){ pEnd = std::strchr(pStart, '@'); if (!(pMid = std::strchr(pStart, ':'))) pMid = pEnd; if (pMid && pMid < pEnd) urlstru->InitTag("PASSWORD", DStringGDL(pMid + 1 < pEnd ? string(pMid + 1, pEnd - (pMid + 1)) : "")); urlstru->InitTag("USERNAME", DStringGDL(pStart < pMid ? string(pStart, pMid - pStart) : "")); pStart = pEnd + 1; } // setting pEnd at the first '/' found or at the end if not found if (std::strchr(pStart, '/')){ pEnd = std::strchr(pStart, '/'); } else { pEnd = pStart + std::strlen(pStart); } // setting pMid at the first ':' found or at the end if not found // if found : InitTag "PORT" from pMid + 1 (after ':') to pEnd ('/' or END) if (std::strchr(pStart, ':')){ pMid = std::strchr(pStart, ':'); urlstru->InitTag("PORT", DStringGDL(pMid + 1 < pEnd ? string(pMid + 1, pEnd - (pMid + 1)) : "")); } else { pMid = pEnd; } // InitTag "PORT" from pStart(after "://" or '@') to pMid (':' or '/' or END) urlstru->InitTag("HOST", DStringGDL(pStart < pMid ? string(pStart, pMid - pStart) : "")); pStart = pEnd + 1; // Searching for a query ('?') // if found : InitTag "QUERY" from pEnd + 1 (after '?') to the end if ((pEnd = strchr(pMid, '?'))){ urlstru->InitTag("QUERY", DStringGDL(std::strlen(pEnd + 1) > 0 ? string(pEnd + 1, std::strlen(pEnd + 1)) : "")); } else { pEnd = pMid + std::strlen(pMid); } // InitTag "PATH" from pStart (after '/') to the end urlstru->InitTag("PATH", DStringGDL(pStart < pEnd ? string(pStart, pEnd - pStart) : "")); urlstru_guard.release(); return urlstru; } BaseGDL* locale_get(EnvT* e) { #ifdef HAVE_LOCALE_H // make GDL inherit the calling process locale setlocale(LC_ALL, ""); // note doen the inherited locale DStringGDL *locale = new DStringGDL(setlocale(LC_CTYPE, NULL)); // return to the C locale setlocale(LC_ALL, "C"); return locale; #else e->Throw("OS does not provide locale information"); #endif } // SA: relies on the contents of the lib::command_line_args vector // defined and filled with data (pointers) in gdl.cpp BaseGDL* command_line_args_fun(EnvT* e) { static int countIx = e->KeywordIx("COUNT"); static int resetIx = e->KeywordIx("RESET"); static int setIx = e->KeywordIx("SET"); // resetting the command_line_args if( e->KeywordSet(resetIx) ) command_line_args.clear(); BaseGDL* setKW = e->GetKW(setIx); if( setKW != NULL) { if(setKW->Type() != GDL_STRING) e->Throw(" SET string values only allowed "); DString setp; for(SizeT i = 0; i < setKW->N_Elements(); i++) { setp = (*static_cast(setKW))[i] ; command_line_args.push_back( setp); } // printf(" SET: %s \n", (*static_cast(setKW))[i] ) // command_line_args.push_back( ( (*static_cast(setKW))[i] ); } // setting the COUNT keyword value if (e->KeywordPresent(countIx)) { e->AssureGlobalKW(countIx); e->SetKW(countIx, new DLongGDL(command_line_args.size())); } // returning empty string or an array of arguments if (command_line_args.empty()) return new DStringGDL(""); else { BaseGDL* ret = new DStringGDL(dimension(command_line_args.size())); for (size_t i = 0; i < command_line_args.size(); i++) (*static_cast(ret))[i] = command_line_args[i]; return ret; } } // SA: relies in the uname() from libc (must be there if POSIX) BaseGDL* get_login_info( EnvT* e) { // getting the info #ifdef _WIN32 #define MAX_WCHAR_BUF 256 char login[MAX_WCHAR_BUF]; char info[MAX_WCHAR_BUF]; DWORD N_WCHAR = MAX_WCHAR_BUF; WCHAR w_buf[MAX_WCHAR_BUF]; GetUserNameW(w_buf, &N_WCHAR); WideCharToMultiByte(CP_ACP, 0, w_buf, N_WCHAR, login, N_WCHAR, NULL, NULL); GetComputerNameW(w_buf, &N_WCHAR); WideCharToMultiByte(CP_ACP, 0, w_buf, N_WCHAR, info, N_WCHAR, NULL, NULL); #else char* login = getlogin(); if (login == NULL) e->Throw("Failed to get user name from the OS"); struct utsname info; if (0 != uname(&info)) e->Throw("Failed to get machine name from the OS"); #endif // creating the output anonymous structure DStructDesc* stru_desc = new DStructDesc("$truct"); SpDString aString; stru_desc->AddTag("MACHINE_NAME", &aString); stru_desc->AddTag("USER_NAME", &aString); DStructGDL* stru = new DStructGDL(stru_desc, dimension()); // returning the info stru->InitTag("USER_NAME", DStringGDL(login)); #ifdef _WIN32 stru->InitTag("MACHINE_NAME", DStringGDL(info)); #else stru->InitTag("MACHINE_NAME", DStringGDL(info.nodename)); #endif return stru; } // SA: base64 logic in base64.hpp, based on code by Bob Withers (consult base64.hpp) BaseGDL* idl_base64(EnvT* e) { BaseGDL* p0 = e->GetPar(0); if (p0 != NULL) { if (p0->Rank() == 0 && p0->Type() == GDL_STRING) { // decoding string* str = &((*static_cast(p0))[0]); if (str->length() == 0) return new DByteGDL(0); if (str->length() % 4 != 0) e->Throw("Input string length must be a multiple of 4"); unsigned int retlen = base64::decodeSize(*str); if (retlen == 0 || retlen > str->length()) e->Throw("No data in the input string"); DByteGDL* ret = new DByteGDL(dimension(retlen)); if (!base64::decode(*str, (char*)&((*ret)[0]), ret->N_Elements())) { delete ret; e->Throw("Base64 decoder failed"); return NULL; } return ret; } if (p0->Rank() >= 1 && p0->Type() == GDL_BYTE) { // encoding return new DStringGDL( base64::encode((char*)&(*static_cast(p0))[0], p0->N_Elements()) ); } } e->Throw("Expecting string or byte array as a first parameter"); return NULL; //pacify dumb compilers } BaseGDL* get_drive_list(EnvT* e) { if (e->KeywordPresent(0)) e->SetKW(0, new DLongGDL(0)); return new DStringGDL(""); } BaseGDL* scope_level( EnvT* e) { SizeT nParam=e->NParam(); if ( nParam > 0 ) e->Throw("Incorrect number of arguments."); EnvStackT& callStack = e->Interpreter()->CallStack(); return new DLongGDL(callStack.size()); } // based on void SimpleDumpStack(EnvT* e) used in "basic_pro.cpp" BaseGDL* scope_traceback( EnvT* e) { static int structureIx = e->KeywordIx("STRUCTURE"); bool structureKW = e->KeywordSet(structureIx); static int systemIx = e->KeywordIx("SYSTEM"); bool systemKW = e->KeywordSet(systemIx); if (systemKW) { Warning("keyword SYSTEM is not ready here, please contribute !"); } int debug=0; EnvStackT& callStack = e->Interpreter()->CallStack(); long actIx = callStack.size(); if (debug) cout << "actIx : " << actIx << endl; string tmp, filename; int lineNumber; if (!structureKW) { DStringGDL* res; res = new DStringGDL(dimension(actIx) , BaseGDL::NOZERO); for( SizeT i=0; iGetProName(); filename=upEnv->GetFilename(); if( filename != "") { lineNumber = upEnv->GetLineNumber(); if( lineNumber != 0) { tmp=tmp+" <"+filename+"("+i2s(lineNumber)+")>"; } } if (debug) cout << tmp << endl; (*res)[i]=tmp; } return res; } if (structureKW) { DStructGDL* res = new DStructGDL( FindInStructList(structList, "IDL_TRACEBACK"), dimension(actIx)); int tRoutine, tFilename, tLine, tLevel, tFunction; int tMethod=0, tRestored=0, tSystem=0; for( SizeT i=0; iGetProName(); filename=upEnv->GetFilename(); if (filename.length() == 0) filename=" "; lineNumber = upEnv->GetLineNumber(); tRoutine = res->Desc()->TagIndex("ROUTINE"); tFilename= res->Desc()->TagIndex("FILENAME"); tLine= res->Desc()->TagIndex("LINE"); tLevel= res->Desc()->TagIndex("LEVEL"); tFunction= res->Desc()->TagIndex("IS_FUNCTION"); tMethod= res->Desc()->TagIndex("METHOD"); tRestored= res->Desc()->TagIndex("RESTORED"); tSystem= res->Desc()->TagIndex("SYSTEM"); *(res->GetTag(tRoutine, i)) = DStringGDL(tmp); *(res->GetTag(tFilename, i)) = DStringGDL(filename); *(res->GetTag(tLine, i)) = DLongGDL(lineNumber); *(res->GetTag(tLevel, i)) = DLongGDL(i); // AC 2015/03/03 : HELP WELCOME // I don't know how to know if we use Pro or Func // we do have a long way in "dinterpreter.cpp" with // if( firstChar == "#") bool isFunc = false; for (FunListT::iterator ifunc = funList.begin(); ifunc != funList.end(); ++ifunc) { if (StrUpCase(tmp).find((*ifunc)->ObjectName()) != std::string::npos) { isFunc = true; break; } } *(res->GetTag(tFunction, i)) = (isFunc)?DByteGDL(1):DByteGDL(0); //all others 0 for the time being *(res->GetTag(tMethod, i)) = DByteGDL(0); *(res->GetTag(tRestored, i)) = DByteGDL(0); *(res->GetTag(tSystem, i)) = DByteGDL(0); } return res; } return NULL; //pacify, etc. } // note: changes here MUST be reflected in scope_varfetch_reference() as well // because DLibFun of this function is used for scope_varfetch_reference() the keyword // indices must match BaseGDL* scope_varfetch_value(EnvT* e) { SizeT nParam = e->NParam(); EnvStackT& callStack = e->Interpreter()->CallStack(); // DLong curlevnum = callStack.size()-1; // 'e' is not on the stack DLong curlevnum = callStack.size(); // static int variablesIx = e->KeywordIx( "VARIABLES" ); static int levelIx = e->KeywordIx("LEVEL"); static int enterIx = e->KeywordIx("ENTER"); bool acceptNew = e->KeywordSet(enterIx); DLongGDL* level = e->IfDefGetKWAs(levelIx); DLong desiredlevnum = 0; if (level != NULL) desiredlevnum = (*level)[0]; if (desiredlevnum <= 0) desiredlevnum += curlevnum; if (desiredlevnum < 1) desiredlevnum = 1; else if (desiredlevnum > curlevnum) desiredlevnum = curlevnum; DSubUD* pro = static_cast (callStack[desiredlevnum - 1]->GetPro()); SizeT nVar = pro->Size(); // # var in GDL for desired level int nKey = pro->NKey(); DString varName; e->AssureScalarPar(0, varName); varName = StrUpCase(varName); int xI = pro->FindVar(varName); if (xI != -1) { // BaseGDL*& par = ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( xI); BaseGDL*& par = callStack[desiredlevnum - 1]->GetKW(xI); if (par == NULL) e->Throw("Variable is undefined: " + varName); return par->Dup(); } else if (acceptNew) { SizeT u = pro->AddVar(varName); SizeT s = callStack[desiredlevnum - 1]->AddEnv(); BaseGDL*& par = ((EnvT*) (callStack[desiredlevnum - 1]))->GetPar(s - nKey); return par->Dup(); } e->Throw("Variable not found: " + varName); return new DLongGDL(0); // compiler shut-up } // this routine is special, only called as an l-function (from FCALL_LIB::LEval()) // it MUST use an EnvT set up for scope_varfetch_value BaseGDL** scope_varfetch_reference(EnvT* e) { SizeT nParam = e->NParam(); EnvStackT& callStack = e->Interpreter()->CallStack(); // DLong curlevnum = callStack.size()-1; // 'e' is not on the stack DLong curlevnum = callStack.size(); // static int variablesIx = e->KeywordIx( "VARIABLES" ); static int levelIx = e->KeywordIx("LEVEL"); static int enterIx = e->KeywordIx("ENTER"); bool acceptNew = e->KeywordSet(enterIx); DLongGDL* level = e->IfDefGetKWAs(levelIx); DLong desiredlevnum = 0; if (level != NULL) desiredlevnum = (*level)[0]; if (desiredlevnum <= 0) desiredlevnum += curlevnum; if (desiredlevnum < 1) desiredlevnum = 1; else if (desiredlevnum > curlevnum) desiredlevnum = curlevnum; DSubUD* pro = static_cast (callStack[desiredlevnum - 1]->GetPro()); SizeT nVar = pro->Size(); // # var in GDL for desired level int nKey = pro->NKey(); DString varName; e->AssureScalarPar(0, varName); varName = StrUpCase(varName); int xI = pro->FindVar(varName); if (xI != -1) { // BaseGDL*& par = ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( xI); BaseGDL*& par = callStack[desiredlevnum - 1]->GetKW(xI); // if( par == NULL) // e->Throw( "Variable is undefined: " + varName); return ∥ } else if (acceptNew) { SizeT u = pro->AddVar(varName); SizeT s = callStack[desiredlevnum - 1]->AddEnv(); BaseGDL*& par = ((EnvT*) (callStack[desiredlevnum - 1]))->GetPar(s - nKey); return ∥ } e->Throw("LVariable not found: " + varName); return NULL; // compiler shut-up } } // namespace gdl-0.9.9/src/basic_fun.hpp000066400000000000000000000122371340051421000155230ustar00rootroot00000000000000/*************************************************************************** basic_fun.hpp - basic GDL library functions ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASIC_FUN_HPP_ #define BASIC_FUN_HPP_ namespace lib { // also used from basic_fun_jmg.cpp void arr( EnvT* e, dimension& dim, SizeT pOffs=0); SizeT HASH_count( DStructGDL* oStructGDL); SizeT LIST_count( DStructGDL* oStructGDL); BaseGDL* get_kbrd( EnvT* e); BaseGDL* bytarr( EnvT* e); BaseGDL* intarr( EnvT* e); BaseGDL* uintarr( EnvT* e); BaseGDL* lonarr( EnvT* e); BaseGDL* ulonarr( EnvT* e); BaseGDL* lon64arr( EnvT* e); BaseGDL* ulon64arr( EnvT* e); BaseGDL* fltarr( EnvT* e); BaseGDL* dblarr( EnvT* e); BaseGDL* strarr( EnvT* e); BaseGDL* complexarr( EnvT* e); BaseGDL* dcomplexarr( EnvT* e); BaseGDL* ptrarr( EnvT* e); BaseGDL* objarr( EnvT* e); BaseGDL* ptr_valid( EnvT* e); BaseGDL* obj_valid( EnvT* e); BaseGDL* ptr_new( EnvT* e); BaseGDL* obj_new( EnvT* e); BaseGDL* heap_refcount( EnvT* e); BaseGDL* call_function( EnvT* e); BaseGDL* call_method_function( EnvT* e); BaseGDL* bindgen( EnvT* e); BaseGDL* indgen( EnvT* e); BaseGDL* uindgen( EnvT* e); BaseGDL* sindgen( EnvT* e); BaseGDL* lindgen( EnvT* e); BaseGDL* ulindgen( EnvT* e); BaseGDL* l64indgen( EnvT* e); BaseGDL* ul64indgen( EnvT* e); BaseGDL* findgen( EnvT* e); BaseGDL* dindgen( EnvT* e); BaseGDL* cindgen( EnvT* e); BaseGDL* dcindgen( EnvT* e); BaseGDL* n_elements( EnvT* e); BaseGDL* execute_fun( EnvT* e); BaseGDL* assoc( EnvT* e); BaseGDL* byte_fun( EnvT* e); BaseGDL* fix_fun( EnvT* e); BaseGDL* uint_fun( EnvT* e); BaseGDL* long_fun( EnvT* e); BaseGDL* ulong_fun( EnvT* e); BaseGDL* long64_fun( EnvT* e); BaseGDL* ulong64_fun( EnvT* e); BaseGDL* float_fun( EnvT* e); BaseGDL* double_fun( EnvT* e); BaseGDL* string_fun( EnvT* e); BaseGDL* complex_fun( EnvT* e); BaseGDL* dcomplex_fun( EnvT* e); BaseGDL* gdl_logical_and( EnvT* e); BaseGDL* gdl_logical_or( EnvT* e); BaseGDL* logical_true( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* replicate( EnvT* e); BaseGDL* strcompress( EnvT* e); BaseGDL* strlowcase( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* strupcase( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* strlen( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* strmid( EnvT* e); BaseGDL* strpos( EnvT* e); BaseGDL* strtrim( EnvT* e); BaseGDL* total_fun( EnvT* e); BaseGDL* product_fun( EnvT* e); BaseGDL* n_params( EnvT* e); BaseGDL* keyword_set( EnvT* e); bool array_equal_bool( BaseGDL* p0, BaseGDL* p1, bool notypeconv=false, bool not_equal=false, bool quiet=true); BaseGDL* array_equal( EnvT* e); BaseGDL* min_fun( EnvT* e); BaseGDL* max_fun( EnvT* e); BaseGDL* transpose( EnvT* e); BaseGDL* sort_fun( EnvT* e); BaseGDL* SlowReliableMedian( EnvT* e); BaseGDL* median( EnvT* e); BaseGDL* shift_fun( EnvT* e); BaseGDL* ishft_fun( EnvT* e); BaseGDL* arg_present( EnvT* e); BaseGDL* eof_fun( EnvT* e); BaseGDL* strjoin( EnvT* e); BaseGDL* rebin_fun( EnvT* e); BaseGDL* obj_class( EnvT* e); BaseGDL* obj_hasmethod( EnvT* e); BaseGDL* obj_isa( EnvT* e); BaseGDL* n_tags( EnvT* e); BaseGDL* bytscl( EnvT* e); BaseGDL* routine_info( EnvT* e); BaseGDL* temporary( EnvT* e); BaseGDL* memory(EnvT* e); // the following by Peter Messmer // (messmer@users.sourceforge.net) BaseGDL* strtok_fun( EnvT* e); // strsplit BaseGDL* getenv_fun( EnvT* e); BaseGDL* tag_names_fun( EnvT* e); BaseGDL* stregex_fun( EnvT* e); BaseGDL* strcmp_fun( EnvT* e); BaseGDL* create_struct( EnvT* e); BaseGDL* rotate( EnvT* e); BaseGDL* routine_filepath( EnvT* e); // the following by Sylwester Arabas // (slayoo@users.sourceforge.net) BaseGDL* reverse( EnvT* e); BaseGDL* parse_url( EnvT* e); BaseGDL* locale_get( EnvT* e); BaseGDL* get_login_info( EnvT* e); BaseGDL* command_line_args_fun(EnvT* e); BaseGDL* idl_base64(EnvT* e); BaseGDL* get_drive_list(EnvT* e); BaseGDL* scope_level( EnvT* e); BaseGDL* scope_traceback( EnvT* e); BaseGDL* scope_varfetch_value( EnvT* e); // regular library function BaseGDL** scope_varfetch_reference( EnvT* e); // special version for LEval() BaseGDL* mean_fun(EnvT* e); BaseGDL* moment_fun(EnvT* e); } // namespace #endif gdl-0.9.9/src/basic_fun_cl.cpp000066400000000000000000000341261340051421000161750ustar00rootroot00000000000000/*************************************************************************** basic_fun.cpp - basic GDL library function ------------------- begin : March 14 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 // default: assume we have ImageMagick #define USE_MAGICK 1 #endif #include "includefirst.hpp" #include #include #include #include #include #include #include #include #include "initsysvar.hpp" #include "datatypes.hpp" #include "envt.hpp" //#include "dpro.hpp" //#include "dinterpreter.hpp" #include "basic_fun_cl.hpp" //#include "terminfo.hpp" #define MAX_DATE_STRING_LENGTH 80 #ifdef _MSC_VER #include "gtdhelper.hpp" #else #include #endif namespace lib { using namespace std; using namespace antlr; BaseGDL* systime(EnvT* e) { struct timeval tval; struct timezone tzone; /*get the time before doing anything else, this hopefully gives a more meaningful "time" than if the t=time(0) call came after an arbitary number of conditional statements.*/ // cout << "lib::systime: " << t << endl; gettimeofday(&tval,&tzone); double tt = tval.tv_sec+tval.tv_usec/1e+6; // time in UTC seconds SizeT nParam=e->NParam(0); //,"SYSTIME"); bool ret_seconds=false; Guard v_guard; Guard v1_guard; if (nParam == 1) { //1 parameter, // 1->current UTC time seconds // default DLong v=0; e->AssureLongScalarPar(0,v); // DIntGDL* v = static_cast(e->GetParDefined(0)->Convert2(GDL_INT,BaseGDL::COPY)); //v_guard.Reset( v); // e->Guard(v); //if ( (*v)[0] == 1) //->EqualNoDelete( static_cDIntGDL(1))) // AC 15/05/14 : in fact, the range goes in ]-1,1[ if ((v <= -1) || (v >= 1)) ret_seconds=true; } static int julianIx=e->KeywordIx("JULIAN"); bool isjulian=e->KeywordSet(julianIx); static int secondsIx=e->KeywordIx("SECONDS"); static int utcIx=e->KeywordIx("UTC"); bool isutc=e->KeywordSet(utcIx); if (nParam == 2) { if (isjulian) e->Throw("Conflicting keywords."); //2 parameters //if the first param is 0, return the date of the second arg //if the first param is 1, return the 'double' of the second arg DLong v1=0; e->AssureLongScalarPar(0,v1); DDouble v2=0.0; e->AssureDoubleScalarPar(1,v2); // DIntGDL* v1 = static_cast(e->GetParDefined(0)->Convert2(GDL_INT,BaseGDL::COPY)); //v_guard.Reset( v1); // e->Guard(v1); //DDoubleGDL* v2 = static_cast(e->GetParDefined(1)->Convert2(GDL_DOUBLE,BaseGDL::COPY)); if (v1 == 0) { //v1->EqualNoDelete( DIntGDL(0))) { //0, read the second argument as time_t; tval.tv_sec = static_cast(v2); tval.tv_usec = static_cast((v2-tval.tv_sec)*1e+6); //delete v2; // we delete v2 here as it is not guarded. Avoids a "new" in the following "else" } else { //1 return new DDoubleGDL(v2); } } //return the variable in seconds, either JULIAN, JULIAN+UTC, //or no other keywords struct tm *tstruct; if( ret_seconds || e->KeywordSet(secondsIx) ) { if( isjulian ) { time_t ttime = tval.tv_sec; if( isutc ) tstruct=gmtime(&ttime); else tstruct=localtime(&ttime); return new DDoubleGDL(Gregorian2Julian(tstruct)); } else { // does not (necessaryly) work: time might count backwards //double tickTime = static_cast(t) + tt - floor( tt); return new DDoubleGDL(static_cast(tt)); } } //return a string of the time, either UTC or local (default) time_t ttime = tval.tv_sec; if(isutc) tstruct= gmtime(&ttime); else tstruct= localtime(&ttime); //Convert the time to JULIAN or NOT if(isjulian) return new DDoubleGDL(Gregorian2Julian(tstruct)); else { char st[MAX_DATE_STRING_LENGTH]; // char *st=new char[MAX_DATE_STRING_LENGTH]; // ArrayGuard stGuard( st); const char *format="%a %h %d %T %Y";//my IDL date format. DStringGDL *S; #ifdef _WIN32 S = new DStringGDL(asctime(tstruct)); #else SizeT res=strftime(st,MAX_DATE_STRING_LENGTH,format,tstruct); if(res != 0) S=new DStringGDL(st); else S=new DStringGDL(""); #endif return S; } } BaseGDL* legendre(EnvT* e) { Guard x_guard; Guard l_guard; Guard m_guard; SizeT nParam=e->NParam(2); //, "LEGENDRE"); Guard guard; int count; BaseGDL* xvals,* lvals,* mvals; xvals= e->GetParDefined(0); //,"LEGENDRE"); SizeT nEx,nEl, nEm,nmin; nEl=0; nEm=0; nEx=xvals->N_Elements(); if(nEx == 0) e->Throw( "Variable is undefined: " +e->GetParString(0)); lvals=e->GetParDefined(1); //,"LEGENDRE"); nEl=lvals->N_Elements(); if(nEl == 0) e->Throw( "Variable is undefined: " +e->GetParString(1)); if(nParam > 2) { mvals=e->GetParDefined(2); //,"LEGENDRE"); nEm=mvals->N_Elements(); } else { mvals=new DIntGDL(0); nEm=1; guard.Reset(mvals); } if(nEm == 0) e->Throw( "Variable is undefined: " +e->GetParString(2)); nmin=nEx; if(nEl < nmin && nEl > 1) nmin=nEl; if(nEm < nmin && nEm > 1) nmin=nEm; if (xvals->Type() == GDL_STRING) { e->Throw( "String expression not allowed in this context: " +e->GetParString(0)); } else if (xvals->Type() == GDL_PTR) { e->Throw( "Pointer expression not allowed in this context: " +e->GetParString(0)); } else if (xvals->Type() == GDL_OBJ) { e->Throw( "Object expression not allowed in this context: " +e->GetParString(0)); } else if (xvals->Type() == GDL_STRUCT) { e->Throw( "Struct expression not allowed in this context: " +e->GetParString(0)); } else if(xvals->Type() == GDL_COMPLEX || xvals->Type() == GDL_COMPLEXDBL) { e->Throw( "Complex Legendre not implemented: "); } else { //byte, int, long float, double, uint, ulong, int64, uint64 DDoubleGDL* res; DDoubleGDL* x_cast; DIntGDL* l_cast,*m_cast; if(xvals->Type() == GDL_DOUBLE) x_cast= static_cast(xvals); else { x_cast= static_cast(xvals->Convert2(GDL_DOUBLE,BaseGDL::COPY)); x_guard.Reset(x_cast);//e->Guard( x_cast); } //lval check if (lvals->Type() == GDL_STRING) e->Throw( "String expression not allowed in this context: " +e->GetParString(1)); else if (lvals->Type() == GDL_PTR) e->Throw( "Pointer expression not allowed in this context: " +e->GetParString(1)); else if (lvals->Type() == GDL_OBJ) e->Throw( "Object expression not allowed in this context: " +e->GetParString(1)); else if (lvals->Type() == GDL_STRUCT) e->Throw( "Struct expression not allowed in this context: " +e->GetParString(1)); else if(lvals->Type() == GDL_COMPLEX || lvals->Type() == GDL_COMPLEXDBL) e->Throw( "Complex Legendre not implemented: "); else if(lvals->Type() == GDL_INT) l_cast=static_cast(lvals); else { l_cast=static_cast(lvals->Convert2(GDL_INT,BaseGDL::COPY)); l_guard.Reset(l_cast);//e->Guard( l_cast); } //mval check if (mvals->Type() == GDL_STRING) e->Throw( "String expression not allowed in this context: " +e->GetParString(2)); else if (mvals->Type() == GDL_PTR) e->Throw( "Pointer expression not allowed in this context: " +e->GetParString(2)); else if (mvals->Type() == GDL_OBJ) e->Throw( "Object expression not allowed in this context: " +e->GetParString(2)); else if (mvals->Type() == GDL_STRUCT) e->Throw( "Struct expression not allowed in this context: " +e->GetParString(2)); else if(mvals->Type() == GDL_COMPLEX || mvals->Type() == GDL_COMPLEXDBL) e->Throw( "Complex Legendre not implemented: "); else if(mvals->Type() == GDL_INT) m_cast=static_cast(mvals); else { m_cast=static_cast(mvals->Convert2(GDL_INT,BaseGDL::COPY)); //e->Guard( m_cast); m_guard.Reset(m_cast); } //x,m,l are converted to the correct format (double, int, int) here //make the result array have the same size as the smallest x,m,l array if(nmin == nEx) res=new DDoubleGDL(xvals->Dim(),BaseGDL::NOZERO); else if(nmin == nEl) res=new DDoubleGDL(lvals->Dim(),BaseGDL::NOZERO); else if(nmin == nEm) res=new DDoubleGDL(mvals->Dim(),BaseGDL::NOZERO); for (count=0;count nEx?0:count]; DInt lNow = (*l_cast)[nmin > nEl?0:count]; DInt mNow = (*m_cast)[nmin > nEm?0:count]; if( xNow < -1.0 || xNow > 1.0) e->Throw( "Argument X must be in the range [-1.0, 1.0]"); if( lNow < 0) e->Throw( "Argument L must be greater than or equal to zero."); if( mNow < -lNow || mNow > lNow) e->Throw( "Argument M must be in the range [-L, L]."); if( mNow >= 0) (*res)[count]= gsl_sf_legendre_Plm( lNow, mNow, xNow); else { mNow = -mNow; int addIx = lNow+mNow; DDouble mul = 1.0; DDouble dD = static_cast( lNow-mNow+1); for( int d=lNow-mNow+1; d<=addIx; ++d) { mul *= dD; dD += 1.0; } DDouble Pm = gsl_sf_legendre_Plm( lNow, mNow, xNow); if( mNow % 2 == 1) Pm = -Pm; (*res)[count] = Pm / mul; } } //convert things back static int doubleIx=e->KeywordIx("DOUBLE"); if(xvals->Type() != GDL_DOUBLE && !e->KeywordSet(doubleIx)) { return res->Convert2(GDL_FLOAT,BaseGDL::CONVERT); } else { return res; } } return new DByteGDL(0); } // Gamma, LnGamma, IGamma and Beta are now in math_fun_gm.cpp // I rewrite them because they had many bugs (gregory.marchal_at_obspm.fr) BaseGDL* gsl_exp(EnvT* e) { Guard cdr_guard; Guard cd_guard; Guard d_guard; Guard fr_guard; SizeT nParam = e->NParam(1); BaseGDL* v=e->GetParDefined(0); size_t nEl = v->N_Elements(); size_t i; if (v->Type() == GDL_STRING) { e->Throw( "String expression not allowed in this context: " +e->GetParString(0)); } else if (v->Type() == GDL_PTR) { e->Throw( "Pointer expression not allowed in this context: " +e->GetParString(0)); } else if (v->Type() == GDL_OBJ) { e->Throw( "Object expression not allowed in this context: " +e->GetParString(0)); } else if (v->Type() == GDL_STRUCT) { e->Throw( "Struct expression not allowed in this context: " +e->GetParString(0)); } else { // DDoubleGDL* d; DDoubleGDL* dr = new DDoubleGDL(v->Dim(), BaseGDL::NOZERO); // e->Guard( dr); if(v->Type() == GDL_COMPLEX) { DComplexDblGDL* cd= static_cast(v->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); cd_guard.Reset(cd);//e->Guard( cd); DComplexDblGDL* cdr = new DComplexDblGDL(v->Dim(), BaseGDL::NOZERO); cdr_guard.Reset(cdr);//e->Guard( cdr); if(nEl == 1) (*cdr)[0]= DComplex((gsl_sf_exp((*cd)[0].real())*cos((*cd)[0].imag())), (gsl_sf_exp((*cd)[0].real())*sin((*cd)[0].imag()))); else for(i=0;i(cdr->Convert2(GDL_COMPLEX,BaseGDL::COPY)); } else if(v->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* cd= static_cast(v->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); cd_guard.Reset(cd);//e->Guard( cd); DComplexDblGDL* cdr = new DComplexDblGDL(v->Dim(), BaseGDL::NOZERO); if(nEl == 1) (*cdr)[0]= DComplex((gsl_sf_exp((*cd)[0].real())*cos((*cd)[0].imag())), (gsl_sf_exp((*cd)[0].real())*sin((*cd)[0].imag()))); else for(i=0;iType() == GDL_DOUBLE) { DDoubleGDL* d=static_cast(v->Convert2(GDL_DOUBLE, BaseGDL::COPY)); d_guard.Reset(d);//e->Guard( d); if(nEl == 1) (*dr)[0]=gsl_sf_exp((*d)[0]); else for (i=0;iType() == GDL_FLOAT || v->Type() == GDL_INT || v->Type() == GDL_LONG) { DFloatGDL *fr=new DFloatGDL(v->Dim(), BaseGDL::NOZERO); fr_guard.Reset(fr);//e->Guard( fr); DDoubleGDL* d=static_cast(v->Convert2(GDL_DOUBLE, BaseGDL::COPY)); d_guard.Reset(d);//e->Guard( d); if(nEl == 1) (*dr)[0]=gsl_sf_exp((*d)[0]); else for (i=0;i(dr->Convert2(GDL_FLOAT,BaseGDL::COPY)); } } assert(false); return NULL; } } // namespace gdl-0.9.9/src/basic_fun_cl.hpp000066400000000000000000000024141340051421000161750ustar00rootroot00000000000000/*************************************************************************** basic_fun.hpp - basic GDL library functions ------------------- begin : March 14 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASIC_FUN_HPP_CL #define BASIC_FUN_HPP_CL namespace lib { double Gregorian2Julian(struct tm ts); BaseGDL* systime(EnvT* e); BaseGDL* legendre(EnvT* e); BaseGDL* interpol(EnvT* e); BaseGDL* gsl_exp(EnvT* e); } // namespace #endif gdl-0.9.9/src/basic_fun_jmg.cpp000066400000000000000000001255061340051421000163570ustar00rootroot00000000000000/*************************************************************************** basic_fun_jmg.cpp - basic GDL library function ------------------- begin : 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "io.hpp" #include "dinterpreter.hpp" #include "objects.hpp" #include "basic_fun_jmg.hpp" #include "nullgdl.hpp" //#define GDL_DEBUG #undef GDL_DEBUG namespace lib { using namespace std; using namespace antlr; SizeT HASH_count( DStructGDL* oStructGDL); SizeT LIST_count( DStructGDL* oStructGDL); BaseGDL* isa_fun( EnvT* e) { if (e->NParam() == 0) e->Throw("Requires at least one argument !"); DString type; BaseGDL *p0; BaseGDL *p1; DStringGDL *p1Str; DString p1S = ""; int nb_kw=0; bool secPar = false; SizeT n_elem; SizeT rank; int debug=0; string structName; string objectName; bool ARRAY_KW_B = false; bool NULL_KW_B = false; bool NUMBER_KW_B = false; bool SCALAR_KW_B = false; bool isARRAY = false; bool isFILE = false; bool isNULL = false; bool isSCALAR = false; static int array_kw = e->KeywordIx("ARRAY"); static int null_kw = e->KeywordIx("NULL"); static int number_kw = e->KeywordIx("NUMBER"); static int scalar_kw = e->KeywordIx("SCALAR"); if (e->KeywordSet(array_kw)) { ARRAY_KW_B = true;} if (e->KeywordSet(null_kw)) { NULL_KW_B = true;} if (e->KeywordSet(number_kw)) { NUMBER_KW_B = true;} if (e->KeywordSet(scalar_kw)) { SCALAR_KW_B = true; } // new since 8.4 bool isBOOLEAN = false; bool isINTEGER = false; bool isFLOAT = false; bool isCOMPLEX = false; bool isSTRING = false; bool BOOLEAN_KW_B = false; bool INTEGER_KW_B = false; bool FLOAT_KW_B = false; bool COMPLEX_KW_B = false; bool STRING_KW_B = false; static int boolean_kw = e->KeywordIx("BOOLEAN"); static int integer_kw = e->KeywordIx("INTEGER"); static int float_kw = e->KeywordIx("FLOAT"); static int complex_kw = e->KeywordIx("COMPLEX"); static int string_kw = e->KeywordIx("STRING"); if (e->KeywordSet(boolean_kw)) { BOOLEAN_KW_B = true;} if (e->KeywordSet(integer_kw)) { INTEGER_KW_B = true;} if (e->KeywordSet(float_kw)) { FLOAT_KW_B = true;} if (e->KeywordSet(complex_kw)) { COMPLEX_KW_B = true; } if (e->KeywordSet(string_kw)) { STRING_KW_B = true; } // /FILE keyword not ready bool FILE_KW_B = false; static int file_kw = e->KeywordIx("FILE"); if (e->KeywordSet(file_kw)) { FILE_KW_B = true;} if (FILE_KW_B) { string txt="(file keyword - ISA() not ready ! Please contribute !!"; e->Throw(txt); } if (SCALAR_KW_B && ARRAY_KW_B) { e->Throw("Keywords ARRAY and SCALAR are mutually exclusive."); } if (NULL_KW_B) { string txt="Keywords NULL and "; if (ARRAY_KW_B) e->Throw(txt+"ARRAY are mutually exclusive."); if (FILE_KW_B) e->Throw(txt+"FILE are mutually exclusive."); if (SCALAR_KW_B) e->Throw(txt+"SCALAR are mutually exclusive."); if (NUMBER_KW_B) e->Throw(txt+"NUMBER are mutually exclusive."); if (BOOLEAN_KW_B) e->Throw(txt+"BOOLEAN are mutually exclusive."); if (INTEGER_KW_B) e->Throw(txt+"INTEGER are mutually exclusive."); if (FLOAT_KW_B) e->Throw(txt+"FLOAT are mutually exclusive."); if (COMPLEX_KW_B) e->Throw(txt+"COMPLEX are mutually exclusive."); if (STRING_KW_B) e->Throw(txt+"STRING are mutually exclusive."); } if (BOOLEAN_KW_B) { string txt="Keywords BOOLEAN and "; if (INTEGER_KW_B) e->Throw(txt+"INTEGER are mutually exclusive."); if (FLOAT_KW_B) e->Throw(txt+"FLOAT are mutually exclusive."); if (COMPLEX_KW_B) e->Throw(txt+"COMPLEX are mutually exclusive."); if (STRING_KW_B) e->Throw(txt+"STRING are mutually exclusive."); } if (INTEGER_KW_B) { string txt="Keywords INTEGER and "; if (FLOAT_KW_B) e->Throw(txt+"FLOAT are mutually exclusive."); if (COMPLEX_KW_B) e->Throw(txt+"COMPLEX are mutually exclusive."); if (STRING_KW_B) e->Throw(txt+"STRING are mutually exclusive."); } if (FLOAT_KW_B) { string txt="Keywords FLOAT and "; if (COMPLEX_KW_B) e->Throw(txt+"COMPLEX are mutually exclusive."); if (STRING_KW_B) e->Throw(txt+"STRING are mutually exclusive."); } if (COMPLEX_KW_B) { string txt="Keywords COMPLEX and "; if (STRING_KW_B) e->Throw(txt+"STRING are mutually exclusive."); } //first par. p0 = e->GetPar(0); bool isNUMBER = true; bool res = true; // (1: boolean, 2: all integer like, 3 : float, 4 : complex, 5: string) int sub_type=0; if (p0 == NULL) { type="UNDEFINED"; res = false; isNUMBER=false; } else { n_elem = p0->N_Elements(); rank = p0->Rank(); if (debug) cout << "type : "<< p0->Type() << ", Rank : "<< rank << endl; switch (p0->Type()) { case GDL_UNDEF: type="UNDEFINED"; isNUMBER=false; res=false; break; case GDL_BYTE: type="BYTE"; sub_type=1; break; case GDL_INT: type="INT"; sub_type=2; break; case GDL_LONG: type="LONG"; sub_type=2; break; case GDL_FLOAT: type="FLOAT"; sub_type=3; break; case GDL_DOUBLE: type="DOUBLE"; sub_type=3; break; case GDL_COMPLEX: type="COMPLEX"; sub_type=4; break; case GDL_STRING: type="STRING"; sub_type=5; isNUMBER=false; break; case GDL_STRUCT: type="STRUCT"; isNUMBER=false; break; case GDL_COMPLEXDBL: type="DCOMPLEX"; sub_type=4; break; case GDL_PTR: type="POINTER"; isNUMBER=false; break; case GDL_OBJ: type="OBJREF"; isNUMBER=false; break; case GDL_UINT: type="UINT"; sub_type=2; break; case GDL_ULONG: type="ULONG"; sub_type=2; break; case GDL_LONG64: type="LONG64"; sub_type=2; break; case GDL_ULONG64: type="ULONG64"; sub_type=2; break; default: e->Throw("This should never happen, please report"); } } if(type == "POINTER"){ DPtrGDL* ptr = static_cast(p0); DPtr ptrID = (*ptr)[0]; if(ptrID == 0) res=false; else res=true; } if(type == "STRUCT"){ //cout << "struct" << endl; rank=1; // alway array following ISA() doc. DStructGDL* str = static_cast(p0); if(str->Desc()->IsUnnamed()) structName="ANONYMOUS"; else structName = str->Desc()->Name(); } if(type == "OBJREF"){ rank=1; // alway array following ISA() doc. //cout << "OBJREF" << endl; DObjGDL* obj = static_cast(p0); DObj objID = (*obj)[0]; if(objID == 0) res = false; else res = true; DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow(objID); if( oStructGDL != NULL) { BaseGDL* objRef = DInterpreter::GetObjHeap(objID); DStructGDL* str = static_cast(objRef); if(str->Desc()->IsUnnamed()) { objectName="Anonymous"; } else { objectName = str->Desc()->Name(); } // cout << objectName << endl; } } //second par. p1 = e->GetPar(1); if (p1 != NULL){ if (p1->Type() != GDL_STRING) e->Throw("String expression required in this context:"+e->GetParString(1)); if (p1->N_Elements() > 1) e->Throw("Expression must be a scalar or 1 element array in this context"+e->GetParString(1)); p1Str = static_cast(p1->Convert2(GDL_STRING,BaseGDL::COPY)); transform((*p1Str)[0].begin(), (*p1Str)[0].end(),(*p1Str)[0].begin(), ::toupper); if (type == (*p1Str)[0]) res = true; else res = false; debug=0; if (debug) cout << type << " " << (*p1Str)[0] << " " << res << endl; if(type == "STRUCT"){ if(structName == (*p1Str)[0]) res = true;} if(type == "OBJREF"){ if(objectName == (*p1Str)[0]) res = true;} } if(type != "UNDEFINED"){ if (sub_type == 1) isBOOLEAN = true; if (sub_type == 2) isINTEGER = true; if (sub_type == 3) isFLOAT = true; if (sub_type == 4) isCOMPLEX = true; if (sub_type == 5) isSTRING = true; if(BOOLEAN_KW_B && res) { res = res && isBOOLEAN ;} if(INTEGER_KW_B && res) { res = res && isINTEGER ;} if(FLOAT_KW_B && res) { res = res && isFLOAT ;} if(COMPLEX_KW_B && res) { res = res && isCOMPLEX ;} if(STRING_KW_B && res) { res = res && isSTRING ;} if(NULL_KW_B && res){ res = false; } if(SCALAR_KW_B && res){ if (rank == 0) isSCALAR=true; else isSCALAR=false; res = res && isSCALAR; } if(NUMBER_KW_B && res){ //cout<<"Number"< 0) isARRAY = true; else isARRAY = false; res = res && isARRAY; } if(NULL_KW_B && res){ res = false; } } else { // we have two cases : undefined variable OR variable set to !null if (NULL_KW_B){ if (p0 == NULL) res = false; else { res = true; res = res && (!ARRAY_KW_B) && (!SCALAR_KW_B) && (!NUMBER_KW_B); } } else { res = res && (!ARRAY_KW_B) && (!SCALAR_KW_B) && (!NUMBER_KW_B); } } if (res) return new DByteGDL(1); return new DByteGDL(0); } BaseGDL* typename_fun( EnvT* e) { DString type=""; BaseGDL* p0 = e->GetPar(0); // we manage Undefined here, !null is managed below if (p0 == NULL) return new DStringGDL("UNDEFINED"); int redo=0; switch (p0->Type()) { // this is different that (p0 == NULL), here input is set to !null case GDL_UNDEF: type="UNDEFINED"; break; case GDL_BYTE: type="BYTE"; break; case GDL_INT: type="INT"; break; case GDL_LONG: type="LONG"; break; case GDL_FLOAT: type="FLOAT"; break; case GDL_DOUBLE: type="DOUBLE"; break; case GDL_COMPLEX: type="COMPLEX"; break; case GDL_STRING: type="STRING"; break; case GDL_STRUCT: redo=1; break; case GDL_COMPLEXDBL: type="DCOMPLEX"; break; case GDL_PTR: type="POINTER"; break; case GDL_OBJ:redo=1; break; case GDL_UINT: type="UINT"; break; case GDL_ULONG: type="ULONG"; break; case GDL_LONG64: type="LONG64"; break; case GDL_ULONG64: type="ULONG64"; break; default: e->Throw("This should never happen, please report"); } if (redo) { //cout << "here we are " <Type() << endl; if (p0->Type() == GDL_STRUCT) { DStructGDL* s = static_cast (p0); // AC 2018-Feb-02 : order is : Array (struct), name, anon bool debug=false; if (debug) { cout << "Rank :" << p0->Rank() << endl; cout << "Dim :" << p0->Dim() << endl; cout << "Size :" << p0->Size() << endl; cout << "StrictScalar :" << p0->StrictScalar() << endl; } if (p0->Dim(0) > 1) { type = "STRUCT"; } else { if (s->Desc()->IsUnnamed()) { type = "ANONYMOUS"; } else { type = s->Desc()->Name(); } } } // here we manage : {Objects, LIST, HASH} if (p0->Type() == GDL_OBJ) { // see case in "basic_pro.cpp", in help_item() if (!p0->StrictScalar()) { type = "OBJREF"; } else { DObj s = (*static_cast (p0))[0]; // is StrictScalar() if (s != 0) // no overloads for null object { DStructGDL* oStructGDL = GDLInterpreter::GetObjHeapNoThrow(s); if (oStructGDL->Desc()->IsUnnamed()) e->Throw("We don't know how to be here (unnamed Obj/List/Hash), please provide exemple !"); type = oStructGDL->Desc()->Name(); } else { type = "UNDEFINED"; } } } } return new DStringGDL(type); } BaseGDL* size_fun( EnvT* e) { static int L64Ix = e->KeywordIx( "L64"); static int dimIx = e->KeywordIx( "DIMENSIONS"); static int FILE_LUNIx = e->KeywordIx( "FILE_LUN"); static int FILE_OFFSETIx = e->KeywordIx( "FILE_OFFSET"); static int N_DIMENSIONSIx = e->KeywordIx( "N_DIMENSIONS"); static int N_ELEMENTSIx = e->KeywordIx( "N_ELEMENTS"); static int STRUCTUREIx = e->KeywordIx( "STRUCTURE"); static int SNAMEIx = e->KeywordIx( "SNAME"); static int TNAMEIx = e->KeywordIx( "TNAME"); static int TYPEIx = e->KeywordIx( "TYPE"); e->NParam( 1); // might be GDL_UNDEF, but must be given // BaseGDL* p0 = e->GetParDefined( 0); //, "SIZE"); BaseGDL* p0 = e->GetPar( 0); //, "SIZE"); // managing exclusive keywords (all but L64) int nb_keywords_set=0; if (e->KeywordSet(dimIx)) nb_keywords_set++; if (e->KeywordSet(FILE_LUNIx)) nb_keywords_set++; if (e->KeywordSet(FILE_OFFSETIx)) nb_keywords_set++; if (e->KeywordSet(N_DIMENSIONSIx)) nb_keywords_set++; if (e->KeywordSet(N_ELEMENTSIx)) nb_keywords_set++; if (e->KeywordSet(STRUCTUREIx)) nb_keywords_set++; if (e->KeywordSet(SNAMEIx)) nb_keywords_set++; if (e->KeywordSet(TNAMEIx)) nb_keywords_set++; if (e->KeywordSet(TYPEIx)) nb_keywords_set++; if (nb_keywords_set > 1) e->Throw("Conflicting keywords."); SizeT nEl = 0; SizeT Rank = 0; SizeT LogicalRank = 0; SizeT vType = GDL_UNDEF; if (p0 != NULL) { nEl = p0->N_Elements(); Rank = p0->Rank(); LogicalRank = p0->Rank(); vType = p0->Type(); } bool forceL64=false; if (nEl > 2147483647UL) forceL64=true; bool isObjectContainer = false; if( vType == GDL_OBJ) { DObjGDL* p0Obj = static_cast(p0); if( p0Obj->StrictScalar()) { DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( (*p0Obj)[0]); if( oStructGDL != NULL) // if object not valid -> default behaviour { DStructDesc* desc = oStructGDL->Desc(); if( desc->IsParent("LIST")) { isObjectContainer = true; nEl = LIST_count(oStructGDL); } if( desc->IsParent("HASH")) { isObjectContainer = true; nEl = HASH_count(oStructGDL); } } } } if( isObjectContainer) { LogicalRank = 1; } // DIMENSIONS if( e->KeywordSet( dimIx)) { if( LogicalRank == 0) { if( e->KeywordSet(L64Ix) || forceL64) return new DLong64GDL( 0); else return new DLongGDL( 0); } dimension dim( LogicalRank); if( e->KeywordSet(L64Ix) || forceL64) { // L64 DLong64GDL* res = new DLong64GDL( dim, BaseGDL::NOZERO); (*res)[0] = 0; for( SizeT i=0; iDim(i); if( isObjectContainer) (*res)[ 0] = nEl; return res; } else { DLongGDL* res = new DLongGDL( dim, BaseGDL::NOZERO); (*res)[0] = 0; for( SizeT i=0; iDim(i); if( isObjectContainer) (*res)[ 0] = nEl; return res; } } // FILE_LUN string txt="Sorry, keyword "; if( e->KeywordSet(FILE_LUNIx)) { e->Throw(txt+"/FILE_LUN not supported yet, please contribute."); } if( e->KeywordSet(FILE_OFFSETIx)) { e->Throw(txt+"/FILE_OFFSET not supported yet, please contribute."); } // N_DIMENSIONS if( e->KeywordSet(N_DIMENSIONSIx)) { return new DLongGDL( LogicalRank); } //N_ELEMENTS if( e->KeywordSet(N_ELEMENTSIx)) { if( e->KeywordSet(L64Ix) || forceL64) return new DLong64GDL(nEl); else return new DLongGDL( nEl); } // STRUCTURE if( e->KeywordSet(STRUCTUREIx)) { DStructGDL* res; if (e->KeywordSet(L64Ix) || forceL64 ) { res = new DStructGDL( "IDL_SIZE64"); } else { res = new DStructGDL( "IDL_SIZE"); } if ( p0 == NULL) { res->InitTag("TYPE_NAME", DStringGDL("UNDEFINED")); return res; } DString tname; DString sname; if (vType == GDL_STRUCT) { tname = "STRUCT"; DStructGDL* s = static_cast( p0); if (s->Desc()->IsUnnamed()) sname = ""; else sname = s->Desc()->Name(); } else { tname = p0->TypeStr(); sname = ""; } res->InitTag("TYPE_NAME", DStringGDL(tname)); res->InitTag("STRUCTURE_NAME", DStringGDL(sname)); res->InitTag("TYPE", DIntGDL(vType)); res->InitTag("FILE_LUN", DIntGDL(0)); if (e->KeywordSet(L64Ix) || forceL64) { res->InitTag("FILE_OFFSET", DLong64GDL(0)); res->InitTag("N_ELEMENTS", DLong64GDL(nEl)); } else { res->InitTag("FILE_OFFSET", DLongGDL(0)); res->InitTag("N_ELEMENTS", DLongGDL(nEl)); } res->InitTag("N_DIMENSIONS", DLongGDL(Rank)); // Initialize dimension values to 0 if (e->KeywordSet(L64Ix) || forceL64 ) { DLong64GDL *dims_res = new DLong64GDL(dimension(MAXRANK), BaseGDL::ZERO); for( SizeT i=Rank; iDim(i); res->InitTag("DIMENSIONS", *dims_res); } else { DLongGDL *dims_res = new DLongGDL(dimension(MAXRANK), BaseGDL::ZERO); for( SizeT i=Rank; iDim(i); res->InitTag("DIMENSIONS", *dims_res); } return res; //e->Throw( "STRUCTURE not supported yet."); } // SNAME if( e->KeywordSet(SNAMEIx)) { DString sname=""; if (vType == GDL_STRUCT) { DStructGDL* s = static_cast( p0); if (!s->Desc()->IsUnnamed()) sname = s->Desc()->Name(); } return new DStringGDL(sname); } // TNAME if( e->KeywordSet(TNAMEIx)) { if( p0 == NULL) return new DStringGDL( "UNDEFINED"); return new DStringGDL( p0->TypeStr()); } // TYPE if( e->KeywordSet(TYPEIx)) { return new DLongGDL( vType ); } // the general case without keyword ... dimension dim( 3 + LogicalRank); if( e->KeywordSet(L64Ix) || forceL64 ) { DLong64GDL* res = new DLong64GDL( dim, BaseGDL::NOZERO); (*res)[ 0] = LogicalRank; for( SizeT i=0; iDim(i); if( isObjectContainer) (*res)[ 0+1] = nEl; (*res) [ LogicalRank+1] = vType; (*res) [ LogicalRank+2] = nEl; return res; } else { DLongGDL* res = new DLongGDL( dim, BaseGDL::NOZERO); (*res)[ 0] = LogicalRank; for( SizeT i=0; iDim(i); if( isObjectContainer) (*res)[ 0+1] = nEl; (*res) [ LogicalRank+1] = vType; (*res) [ LogicalRank+2] = nEl; return res; } return new DIntGDL( 0); // default for not supported } BaseGDL* fstat_fun( EnvT* e) { e->NParam( 1);//, "FSTAT"); DLong lun; e->AssureLongScalarPar( 0, lun); if( lun < -2 || lun > maxLun) throw GDLException( e->CallingNode(), " File unit is not within allowed range."); SizeT size; bool big = false; if (lun > 0) { if (fileUnits[ lun - 1].IsOpen() && !fileUnits[ lun - 1].Compress() ) //due to bug in gzTell, we DO NOT WANT to get the size here. { size = fileUnits[ lun - 1].Size(); big = (DLong(size) != size); } } DStructGDL* fstat; if (big) fstat = new DStructGDL( "FSTAT64"); else fstat = new DStructGDL( "FSTAT"); fstat->InitTag("UNIT", DLongGDL( lun)); if( lun == -2) { fstat->InitTag("NAME", DStringGDL( "")); // fstat->InitTag("SIZE", DLongGDL( 0)); fstat->InitTag("OPEN", DByteGDL( 1)); fstat->InitTag("ISATTY", DByteGDL( 1)); // fstat->InitTag("ISAGUI", DByteGDL( 0)); fstat->InitTag("INTERACTIVE", DByteGDL( 1)); // fstat->InitTag("XDR", DByteGDL( 0)); // fstat->InitTag("COMPRESS", DByteGDL( 0)); // fstat->InitTag("READ", DByteGDL( 0)); fstat->InitTag("WRITE", DByteGDL( 1)); } else if( lun == -1) { fstat->InitTag("NAME", DStringGDL( "")); // fstat->InitTag("SIZE", DLongGDL( 0)); fstat->InitTag("OPEN", DByteGDL( 1)); fstat->InitTag("ISATTY", DByteGDL( 1)); // fstat->InitTag("ISAGUI", DByteGDL( 0)); fstat->InitTag("INTERACTIVE", DByteGDL( 1)); // fstat->InitTag("XDR", DByteGDL( 0)); // fstat->InitTag("COMPRESS", DByteGDL( 0)); // fstat->InitTag("READ", DByteGDL( 0)); fstat->InitTag("WRITE", DByteGDL( 1)); } else if( lun == 0) { fstat->InitTag("NAME", DStringGDL( "")); // fstat->InitTag("SIZE", DLongGDL( 0)); fstat->InitTag("OPEN", DByteGDL( 1)); fstat->InitTag("ISATTY", DByteGDL( 1)); // fstat->InitTag("ISAGUI", DByteGDL( 0)); fstat->InitTag("INTERACTIVE", DByteGDL( 1)); // fstat->InitTag("XDR", DByteGDL( 0)); // fstat->InitTag("COMPRESS", DByteGDL( 0)); fstat->InitTag("READ", DByteGDL( 1)); // fstat->InitTag("WRITE", DByteGDL( 0)); } else { // normal file GDLStream& actUnit = fileUnits[ lun-1]; if( !actUnit.IsOpen()) return fstat; // OPEN tag is init to zero (SpDByte::GetInstance()) struct stat buffer; int status = stat(actUnit.Name().c_str(), &buffer); fstat->InitTag("NAME", DStringGDL( actUnit.Name())); if (big) fstat->InitTag("SIZE", DLong64GDL( buffer.st_size));//size)); else fstat->InitTag("SIZE", DLongGDL( buffer.st_size));//size)); fstat->InitTag("OPEN", DByteGDL( 1)); // fstat->InitTag("ISATTY", DByteGDL( 0)); // fstat->InitTag("ISAGUI", DByteGDL( 0)); // fstat->InitTag("INTERACTIVE", DByteGDL( 0)); // fstat->InitTag("COMPRESS", DByteGDL( 0)); fstat->InitTag("COMPRESS",DByteGDL( actUnit.Compress())); fstat->InitTag("READ", DByteGDL( actUnit.IsReadable()?1:0)); fstat->InitTag("WRITE", DByteGDL( actUnit.IsWriteable()?1:0)); fstat->InitTag("ATIME", DLong64GDL( buffer.st_atime)); fstat->InitTag("CTIME", DLong64GDL( buffer.st_ctime)); fstat->InitTag("MTIME", DLong64GDL( buffer.st_mtime)); if (big) fstat->InitTag("CUR_PTR", DLong64GDL( actUnit.Tell())); else fstat->InitTag("CUR_PTR", DLongGDL( actUnit.Tell())); } return fstat; } template BaseGDL* make_array_template(EnvT* e, DLongGDL* dimKey, BaseGDL* value, DDouble off, DDouble inc) { try { dimension dim; if(!dimKey) arr(e, dim); else dim = dimension(&(*dimKey)[0], dimKey->N_Elements()); if(value) return static_cast(value)-> New(dim, BaseGDL::INIT)-> Convert2(T::Traits::t); if(e->KeywordSet("NOZERO")) return new T(dim, BaseGDL::NOZERO); if(e->KeywordSet("INDEX")) return new T(dim, BaseGDL::INDGEN, off, inc); return new T(dim); } catch(GDLException& ex) { e->Throw(ex.getMessage()); } assert(false); return NULL; } BaseGDL* make_array(EnvT* e) { DDouble off = 0, inc = 1; DType type = GDL_UNDEF; e->AssureDoubleScalarKWIfPresent("START", off); e->AssureDoubleScalarKWIfPresent("INCREMENT", inc); DLongGDL* dimKey = NULL; Guard dimKey_guard; static int sizeix = e->KeywordIx("SIZE"); static int dimensionix = e->KeywordIx("DIMENSION"); BaseGDL* size = e->GetKW(sizeix); BaseGDL* b_dimension = e->GetKW(dimensionix); if(b_dimension) { DLongGDL* l_dimension = e->GetKWAs(dimensionix); for(int i = 0; i < l_dimension->N_Elements(); ++i) if((*l_dimension)[i] < 1) e->Throw("Array dimensions must be greater than 0."); if(e->NParam() == 0 && size == NULL) { dimension dim(l_dimension->N_Elements(), 1); dimKey = new DLongGDL(dim, BaseGDL::NOZERO); dimKey_guard.Reset(dimKey); for(int i = 0; i < l_dimension->N_Elements(); ++i) (*dimKey)[i] = (*l_dimension)[i]; } } else if(size) { DLongGDL* l_size = e->GetKWAs(sizeix); if(l_size->N_Elements() < 4 || l_size->N_Elements() > 11) e->Throw("Keyword array parameter SIZE must have from 4 to 11 elements."); DLong expectedDim = l_size->N_Elements()-3; type = static_cast((*l_size)[expectedDim + 1]); if(e->NParam() == 0) { dimension dim(expectedDim, 1); dimKey = new DLongGDL(dim, BaseGDL::NOZERO); dimKey_guard.Reset(dimKey); for(int i = 1; i <= expectedDim; ++i) { if((*l_size)[i] < 1) e->Throw("Array dimensions must be greater than 0."); (*dimKey)[i - 1] = (*l_size)[i]; } } } static int indexIx = e->KeywordIx("INDEX"); static int valueIx = e->KeywordIx("VALUE"); BaseGDL* value = e->GetKW(valueIx); if(value && !value->Scalar()) e->Throw("Expression must be a scalar in this context: " + e->GetString(valueIx)); static int typeIx = e->KeywordIx("TYPE"); if(e->KeywordPresent(typeIx)) { DLong temp; e->AssureLongScalarKW(typeIx, temp); type = static_cast(temp); } else if(e->KeywordSet("BOOLEAN")) { if(e->KeywordSet(indexIx)) e->Throw("Keyword INDEX is not allowed with BOOLEAN."); // TODO: Add support for BOOLEAN type introduced in IDL 8.4 e->Throw("MAKE_ARRAY of BOOLEAN types not yet implemented."); } else if(e->KeywordSet("BYTE")) type = GDL_BYTE; else if(e->KeywordSet("COMPLEX")) type = GDL_COMPLEX; else if(e->KeywordSet("DCOMPLEX")) type = GDL_COMPLEXDBL; else if(e->KeywordSet("DOUBLE")) type = GDL_DOUBLE; else if(e->KeywordSet("FLOAT")) type = GDL_FLOAT; else if(e->KeywordSet("INTEGER")) type = GDL_INT; else if(e->KeywordSet("L64")) type = GDL_LONG64; else if(e->KeywordSet("LONG")) type = GDL_LONG; else if(e->KeywordSet("OBJ")) type = GDL_OBJ; else if(e->KeywordSet("PTR")) type = GDL_PTR; else if(e->KeywordSet("STRING")) type = GDL_STRING; else if(e->KeywordSet("UINT")) type = GDL_UINT; else if(e->KeywordSet("UL64")) type = GDL_ULONG64; else if(e->KeywordSet("ULONG")) type = GDL_ULONG; else if(value) type = value->Type(); switch(type) { case GDL_BYTE: return make_array_template(e, dimKey, value, off, inc); case GDL_COMPLEX: return make_array_template(e, dimKey, value, off, inc); case GDL_COMPLEXDBL: return make_array_template(e, dimKey, value, off, inc); case GDL_DOUBLE: return make_array_template(e, dimKey, value, off, inc); case GDL_FLOAT: return make_array_template(e, dimKey, value, off, inc); case GDL_INT: return make_array_template(e, dimKey, value, off, inc); case GDL_LONG64: return make_array_template(e, dimKey, value, off, inc); case GDL_LONG: return make_array_template(e, dimKey, value, off, inc); case GDL_UINT: return make_array_template(e, dimKey, value, off, inc); case GDL_ULONG64: return make_array_template(e, dimKey, value, off, inc); case GDL_ULONG: return make_array_template(e, dimKey, value, off, inc); case GDL_OBJ: if(e->KeywordSet(indexIx)) e->Throw("Index initialization of object reference array is invalid."); return make_array_template(e, dimKey, value, off, inc); case GDL_PTR: if(e->KeywordSet(indexIx)) e->Throw("Index initialization of pointer array is invalid."); return make_array_template(e, dimKey, value, off, inc); case GDL_STRING: if(!e->KeywordSet(indexIx)) return make_array_template(e, dimKey, value, off, inc); else return make_array_template(e, dimKey, value, off, inc)->Convert2(GDL_STRING); case GDL_STRUCT: e->Throw("Invalid type specified for result."); default:; // Default to FLOAT to emulate IDL } return make_array_template(e, dimKey, value, off, inc); } BaseGDL* reform( EnvT* e) { SizeT nParam=e->NParam(1); BaseGDL** p0P = &e->GetParDefined( 0); BaseGDL* p0 = *p0P; SizeT nEl = p0->N_Elements(); // SizeT Rank = p0->Rank(); // if( Rank == 0) // e->Throw( "Parameter must be an array in this context: " // + e->GetParString( 0)); // SizeT Type = p0->Type(); dimension dim; if (nParam == 1) { // SizeT j=1; for( SizeT i=0; iRank(); ++i) { // if (p0->Dim(i) == 0) break; if (p0->Dim(i) > 1) { dim << p0->Dim( i); // j *= p0->Dim(i); // cout << j << p0->Dim(i) << endl; // dim.Set(j,p0->Dim(i)); //j++; } } if( dim.Rank() == 0) dim << 1; // dim.Set(0, j); } else arr( e, dim, 1); if (dim.NDimElements() != nEl) e->Throw( "New subscripts must not change the number of elements in " + e->GetParString( 0)); // make a copy if p0 is not global // if( !e->GlobalPar( 0)) // p0 = p0->Dup(); // better: steal p0 if( !e->GlobalPar( 0)) { bool success = e->StealLocalPar( 0); //*p0P = NULL; //*p0P = NULL; // prevent local parameter form deletion assert( success); p0->SetDim(dim); return p0; } static int overwriteIx = e->KeywordIx("OVERWRITE"); if (e->KeywordSet( overwriteIx)) { p0->SetDim(dim); e->SetPtrToReturnValue( p0P); return p0; } // global paramter - make a copy BaseGDL* res = p0->Dup(); res->SetDim(dim); return res; } // note: changes here MUST be reflected in routine_names_reference() as well // because DLibFun of this function is used for routine_names_reference() the keyword // indices must match BaseGDL* routine_names_value(EnvT* e) { SizeT nParam = e->NParam(); EnvStackT& callStack = e->Interpreter()->CallStack(); // DLong curlevnum = callStack.size()-1; // 'e' is not on the stack DLong curlevnum = callStack.size(); static int sfunctionsIx=e->KeywordIx("S_FUNCTIONS"); static int sproceduresIx=e->KeywordIx("S_PROCEDURES"); static int levelIx=e->KeywordIx("LEVEL"); if (e->KeywordSet(sfunctionsIx)) { vector subList; SizeT nFun = libFunList.size(); for (SizeT i = 0; i < nFun; ++i) { DString s = libFunList[ i]->ToString(); s = s.substr(4); // Remove "res=" size_t left_paren = s.find_first_of("("); subList.push_back(s.substr(0, left_paren)); } sort(subList.begin(), subList.end()); DStringGDL* res = new DStringGDL(dimension(nFun), BaseGDL::NOZERO); for (SizeT i = 0; i < nFun; ++i) { (*res)[i] = subList[ i]; } return res; } if (e->KeywordSet(sproceduresIx)) { vector subList; SizeT nPro = libProList.size(); for (SizeT i = 0; i < nPro; ++i) { DString s = libProList[ i]->ToString(); size_t comma_brac = s.find_first_of(",["); subList.push_back(s.substr(0, comma_brac)); } sort(subList.begin(), subList.end()); DStringGDL* res = new DStringGDL(dimension(nPro), BaseGDL::NOZERO); for (SizeT i = 0; i < nPro; ++i) { (*res)[i] = subList[ i]; } return res; } if (e->KeywordSet(levelIx)) { return new DLongGDL(curlevnum); } static int variablesIx = e->KeywordIx("VARIABLES"); static int fetchIx = e->KeywordIx("FETCH"); static int arg_namesIx = e->KeywordIx("ARG_NAME"); static int storeIx = e->KeywordIx("STORE"); bool var = false, fetch = false, arg = false, store = false; DLongGDL* level; level = e->IfDefGetKWAs(variablesIx); if (level != NULL) { var = true; } else { level = e->IfDefGetKWAs(fetchIx); if (level != NULL) { fetch = true; } else { level = e->IfDefGetKWAs(arg_namesIx); if (level != NULL) { arg = true; } else { level = e->IfDefGetKWAs(storeIx); if (level != NULL) { store = true; } } } } DString varName; if (level != NULL) { DLong desiredlevnum = (*level)[0]; if (desiredlevnum <= 0) desiredlevnum += curlevnum; if (desiredlevnum < 1) return new DStringGDL(""); if (desiredlevnum > curlevnum) desiredlevnum = curlevnum; DSubUD* pro = static_cast (callStack[desiredlevnum - 1]->GetPro()); SizeT nVar = pro->Size(); // # var in GDL for desired level SizeT nComm = pro->CommonsSize(); // # has commons? //cerr<<"nComm= "<NumberOfCommons()<<" commons"<NKey(); //cout << "nKey:" << nKey << endl; //cout << "nVar:" << nVar << endl; //cout << pro->Name() << endl; if (var) { if (nTotVar == 0) return new DStringGDL(""); DStringGDL* res = new DStringGDL(dimension(nTotVar), BaseGDL::NOZERO); set sortedList; // "Sorted List" if (nVar > 0) { for (SizeT i = 0; i < nVar; ++i) { string vname = pro->GetVarName(i); sortedList.insert(vname); } } if (nComm > 0) { DStringGDL* list=static_cast(pro->GetCommonVarNameList()); for (SizeT i = 0; i < list->N_Elements(); ++i) { sortedList.insert((*list)[i]); } } SizeT ivar=0; set::iterator it = sortedList.begin(); while (it != sortedList.end()) (*res)[ivar++] = *it++; return res; } else if (fetch) { // FETCH e->AssureScalarPar(0, varName); varName = StrUpCase(varName); int xI = pro->Find(varName); //cout << xI << " " << varName << " " << pro->Size() << endl; if (xI != -1) { // BaseGDL* par = ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( xI-nKey); // Keywords are already counted (in FindVar) // BaseGDL*& par = ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( xI-nKey); if (((EnvT*)(callStack[desiredlevnum - 1]))->NParam() < 1) return NULL; //meaning this fetch level is not initialized. Avoids throwing an #assert in debug mode BaseGDL*& par = ((EnvT*) (callStack[desiredlevnum - 1]))->GetKW(xI); // not IDL behaviour if (par == NULL) e->Throw("Variable is undefined: " + varName); if (par == NULL) return NULL; // char* addr = static_cast(par->DataAddr()); // no retnew function BUT: ret value is not from current environment // which is ok with the new ref return value handling introdcuced with 0.9.4 // note that the _reference version does not need par to be defined and is hence still necessary e->SetPtrToReturnValue(&par); // <- HERE IS THE DIFFERENCE return par; // <- HERE IS THE DIFFERENCE // return par->Dup(); // <- HERE IS THE DIFFERENCE // no retnew function BUT: ret value is not from current environment } else { BaseGDL** par = pro->GetCommonVarPtr(varName); // not IDL behaviour if (par == NULL) e->Throw("Variable is undefined: " + varName); if (par == NULL) return NULL; return *par; // <- HERE IS THE DIFFERENCE } if (e->Interpreter()->InterruptEnable()) Message("Variable not found: " + varName); return NULL; } else if (arg) { // ARG_NAME if (nParam == 0) return new DStringGDL(""); DStringGDL* res = new DStringGDL(dimension(nParam), BaseGDL::NOZERO); // cout << "nVar:" << nVar << endl; EnvBaseT* desiredCallStack; if (desiredlevnum >= callStack.size()) desiredCallStack = e; else desiredCallStack = callStack[ desiredlevnum]; SizeT nCall = desiredCallStack->NParam(); // cout << "nCall:" << nCall << "curlevnum:" << curlevnum << endl; // search for all given parameters of this call for (SizeT i = 0; i < nParam; ++i) { // search all parameters of target environment for (SizeT j = 0; j < nCall; ++j) { if (e->GetParString(i) == desiredCallStack->GetParString(j)) { // cout << "Calling param: " << j+1 << endl; BaseGDL*& p = e->GetPar(i); if (p == NULL) { (*res)[i] = "UNDEFINED"; // break; } // cout << "p:" << p << endl; SizeT xI = 0; for (; xI < nVar; ++xI) { string vname = pro->GetVarName(xI); BaseGDL*& par = ((EnvT*) (callStack[desiredlevnum - 1]))->GetPar(xI - nKey); // cout << "xI:" << xI << " " << vname.c_str() << endl; // cout << "par:" << par << endl; if (&par == &p) { (*res)[i] = vname; break; } } // xI loop if (xI == nVar) // not found -> search common { string vname; bool success = pro->GetCommonVarName(p, vname); if (success) (*res)[i] = vname; } break; } } // j loop } // i loop return res; } else { // STORE if (nParam != 2) throw GDLException(e->CallingNode(), "ROUTINE_NAMES: Incorrect number of arguments."); // "res" points to variables to be restored BaseGDL* res = e->GetParDefined(1); SizeT s; e->AssureScalarPar(0, varName); varName=StrUpCase(varName); int xI = pro->FindVar(varName); // cout << "varName: " << varName << " xI: " << xI << endl; if (xI != -1) { s = xI; // cout << "FindVar s: " << s << endl; } else { BaseGDL** varPtr = pro->GetCommonVarPtr(varName); // cout << "FindCommonVar s: " << varPtr << endl; if (varPtr) { if (pro->ReplaceExistingCommonVar(varName, res->Dup())) return new DIntGDL(1); else return new DIntGDL(0); } else { SizeT u = pro->AddVar(varName); s = callStack[desiredlevnum - 1]->AddEnv(); // cout << "AddVar u: " << u << endl; // cout << "AddEnv s: " << s << endl; } } // BaseGDL*& par = ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( s-nKey); // ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( s-nKey) = res->Dup(); ((EnvT*) (callStack[desiredlevnum - 1]))->GetKW(s) = res->Dup(); // cout << "par: " << &par << endl << endl; // memcpy(&par, &res, sizeof(par)); return new DIntGDL(1); } } else { // Get Compiled Procedures & Functions DLong n = proList.size() + funList.size() + 1; // Add $MAIN$ to list vector pfList; pfList.push_back("$MAIN$"); // Procedures for (ProListT::iterator i = proList.begin(); i != proList.end(); ++i) { pfList.push_back((*i)->ObjectName()); } // Functions for (FunListT::iterator i = funList.begin(); i != funList.end(); ++i) { pfList.push_back((*i)->ObjectName()); } // Sort sort(pfList.begin(), pfList.end()); // Fill return variable dimension dim(&n, (size_t) 1); DStringGDL* res = new DStringGDL(dim, BaseGDL::NOZERO); for (SizeT i = 0; i < n; ++i) { (*res)[i] = pfList[ i]; } return res; } } // this version does not need the return value pointing to a defined value and is hence necessary BaseGDL** routine_names_reference(EnvT* e) { SizeT nParam = e->NParam(); EnvStackT& callStack = e->Interpreter()->CallStack(); DLong curlevnum = callStack.size(); static int sfunctionsIx=e->KeywordIx("S_FUNCTIONS"); static int sproceduresIx=e->KeywordIx("S_PROCEDURES"); static int levelIx=e->KeywordIx("LEVEL"); if (e->KeywordSet(sfunctionsIx)) { return NULL; } if (e->KeywordSet(sproceduresIx)) { return NULL; } if (e->KeywordSet(levelIx)) { return NULL; } static int variablesIx = e->KeywordIx("VARIABLES"); static int fetchIx = e->KeywordIx("FETCH"); static int arg_namesIx = e->KeywordIx("ARG_NAME"); static int storeIx = e->KeywordIx("STORE"); bool var = false, fetch = false, arg = false, store = false; var=e->KeywordPresent(variablesIx); arg=e->KeywordPresent(arg_namesIx); store=e->KeywordPresent(storeIx); fetch=e->KeywordPresent(fetchIx); if (fetch && nParam < 1) e->Throw("Incorrect number of arguments."); if ( var + fetch + store + arg > 1 ) e->Throw("Incorrect number of arguments."); DLongGDL* level; level = e->IfDefGetKWAs(variablesIx); if (level != NULL) { var = true; } else { level = e->IfDefGetKWAs(fetchIx); if (level != NULL) { fetch = true; } else { level = e->IfDefGetKWAs(arg_namesIx); if (level != NULL) { arg = true; } else { level = e->IfDefGetKWAs(storeIx); if (level != NULL) { store = true; } } } } DString varName; if (level != NULL) { DLong desiredlevnum = (*level)[0]; if (desiredlevnum <= 0) desiredlevnum += curlevnum; if (desiredlevnum < 1) return NULL; if (desiredlevnum > curlevnum) desiredlevnum = curlevnum; DSubUD* pro = static_cast (callStack[desiredlevnum - 1]->GetPro()); SizeT nVar = pro->Size(); // # var in GDL for desired level SizeT nComm = pro->CommonsSize(); // # has commons? SizeT nTotVar = nVar + nComm; //All the variables availables at that lev. int nKey = pro->NKey(); //cout << "nKey:" << nKey << endl; //cout << "nVar:" << nVar << endl; //cout << pro->Name() << endl; if (fetch) { // FETCH e->AssureScalarPar(0, varName); varName = StrUpCase(varName); int xI = pro->FindVar(varName); // cout << xI << endl; if (xI != -1) { // BaseGDL*& par = ((EnvT*)(callStack[desiredlevnum-1]))->GetPar( xI-nKey); BaseGDL*& par = ((EnvT*) (callStack[desiredlevnum - 1]))->GetKW(xI); if (par == NULL) return NULL; return ∥ // <- HERE IS THE DIFFERENCE } else { BaseGDL** par = pro->GetCommonVarPtr(varName); // not IDL behaviour if (par == NULL) e->Throw("Variable is undefined: " + varName); if (par == NULL) return NULL; return par; // <- HERE IS THE DIFFERENCE } e->Throw("Variable not found: " + varName); return NULL; } else if (var) { // ARG_NAME return NULL; } else if (arg) { // ARG_NAME return NULL; } else { // STORE return NULL; } } else { // Get Compiled Procedures & Functions return NULL; } } } // namespace gdl-0.9.9/src/basic_fun_jmg.hpp000066400000000000000000000026061340051421000163570ustar00rootroot00000000000000/*************************************************************************** basic_fun_jmg.hpp - basic GDL library functions ------------------- begin : 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASIC_FUN_JMG_HPP_ #define BASIC_FUN_JMG_HPP_ namespace lib { BaseGDL* isa_fun( EnvT* e); BaseGDL* typename_fun( EnvT* e); BaseGDL* size_fun( EnvT* e); BaseGDL* fstat_fun( EnvT* e); BaseGDL* make_array( EnvT* e); BaseGDL* reform( EnvT* e); BaseGDL* routine_names_value( EnvT* e); BaseGDL** routine_names_reference( EnvT* e); } // namespace #endif gdl-0.9.9/src/basic_op.cpp000066400000000000000000003701731340051421000153520ustar00rootroot00000000000000/*************************************************************************** basic_op.cpp - GDL operators ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_BASIC_OP_CPP // header in datatypes.hpp //#include "datatypes.hpp" //#include "dstructgdl.hpp" //#include "arrayindex.hpp" //#include #include "sigfpehandler.hpp" #ifdef _OPENMP #include #endif // #include "strassenmatrix.hpp" #include "typetraits.hpp" using namespace std; #if defined(USE_EIGEN) using namespace Eigen; #endif #include "basic_op_add.cpp" #include "basic_op_sub.cpp" #include "basic_op_mult.cpp" #include "basic_op_div.cpp" // Not operation // for integers template Data_* Data_::NotOp() { ULong nEl=N_Elements(); assert( nEl != 0); if( nEl == 1) { (*this)[0] = ~(*this)[0]; return this; } // if( !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = ~(*this)[i]; } return this; } // others template<> Data_* Data_::NotOp() { ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] = ((*this)[0] == 0.0f)? 1.0f : 0.0f; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = ((*this)[i] == 0.0f)? 1.0f : 0.0f; } return this; } template<> Data_* Data_::NotOp() { ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] = ((*this)[0] == 0.0)? 1.0 : 0.0; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = ((*this)[i] == 0.0)? 1.0 : 0.0; } return this; } template<> Data_* Data_::NotOp() { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::NotOp() { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::NotOp() { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::NotOp() { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::NotOp() { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } // UMinus unary minus // for numbers template BaseGDL* Data_::UMinus() { // dd = -dd; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] = -(*this)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = -(*this)[i]; } return this; } template<> BaseGDL* Data_::UMinus() { ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); Data_* newThis=static_cast*>(this->Convert2( GDL_FLOAT)); // this is deleted by convert2!!! return static_cast( newThis->UMinus()); } template<> BaseGDL* Data_::UMinus() { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> BaseGDL* Data_::UMinus() { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // logical negation // integers, also ptr and object template Data_* Data_::LogNeg() { SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] == 0)? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == 0)? 1 : 0; } return res; } template<> Data_* Data_::LogNeg() { if( this->Scalar()) { DSubUD* isTrueOverload = static_cast(GDLInterpreter::GetObjHeapOperator( dd[0], OOIsTrue)); if( isTrueOverload != NULL) { if( this->LogTrue()) return new Data_( 0); else return new Data_( 1); } } SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] == 0)? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == 0)? 1 : 0; } return res; } template<> Data_* Data_::LogNeg() { SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] == 0.0f)? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == 0.0f)? 1 : 0; } return res; } template<> Data_* Data_::LogNeg() { SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] == 0.0)? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == 0.0)? 1 : 0; } return res; } template<> Data_* Data_::LogNeg() { SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] == "")? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == "")? 1 : 0; } return res; } template<> Data_* Data_::LogNeg() { SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0].real() == 0.0 && (*this)[0].imag() == 0.0)? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i].real() == 0.0 && (*this)[i].imag() == 0.0)? 1 : 0; } return res; } template<> Data_* Data_::LogNeg() { SizeT nEl = dd.size(); assert( nEl); // if( nEl == 0) throw GDLException("Variable is undefined."); DByteGDL* res = new Data_( dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0].real() == 0.0 && (*this)[0].imag() == 0.0)? 1 : 0; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i].real() == 0.0 && (*this)[i].imag() == 0.0)? 1 : 0; } return res; } // increment decrement operators // integers template void Data_::Dec() { ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0]--; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i]--; }} template void Data_::Inc() { ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0]++; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i]++; }} // float template<> void Data_::Dec() { // dd -= 1.0f; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] -= 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] -= 1.0; }} template<> void Data_::Inc() { // dd += 1.0f; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] += 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += 1.0; }} // double template<> void Data_::Dec() { // dd -= 1.0; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] -= 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] -= 1.0; }} template<> void Data_::Inc() { // dd += 1.0; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] += 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += 1.0; }} // complex template<> void Data_::Dec() { // dd -= 1.0f; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] -= 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] -= 1.0; }} template<> void Data_::Inc() { // dd += 1.0f; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] += 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += 1.0; }} template<> void Data_::Dec() { // dd -= 1.0; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] -= 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] -= 1.0; }} template<> void Data_::Inc() { // dd += 1.0; ULong nEl=N_Elements(); assert( nEl != 0); // if( !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] += 1.0; return; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += 1.0; }} // forbidden types template<> void Data_::Dec() { throw GDLException("String expression not allowed in this context.",true,false); } template<> void Data_::Dec() { throw GDLException("Pointer expression not allowed in this context.",true,false); } template<> void Data_::Dec() { throw GDLException("Object expression not allowed in this context.",true,false); } template<> void Data_::Inc() { throw GDLException("String expression not allowed in this context.",true,false); } template<> void Data_::Inc() { throw GDLException("Pointer expression not allowed in this context.",true,false); } template<> void Data_::Inc() { throw GDLException("Object expression not allowed in this context.",true,false); } // binary operators // 1. operators that always return a new result // EqOp // returns *this eq *r template BaseGDL* Data_::EqOp( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // if( nEl == 0) // nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = (s == (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] == s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] == s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] == (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] == (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] == (*this)[i]); } } //C delete right; //C delete this; return res; } // must handle overloads template<> BaseGDL* Data_::EqOp( BaseGDL* r) { if( Scalar()) // if( StrictScalar()) { // DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( (*this)[0]); // if( oStructGDL != NULL) // object not valid -> default behaviour // { // DStructDesc* desc = oStructGDL->Desc(); // // DFun* EQOverload = static_cast(desc->GetOperator( OOEQ)); // DSubUD* EQOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*this)[0], OOEQ)); if( EQOverload == NULL) { if( r == NullGDL::GetSingleInstance()) { Data_* res= new Data_( this->dim, BaseGDL::NOZERO); (*res)[0] = (0 == (*this)[0]); return res; } } else //( EQOverload != NULL) { ProgNodeP callingNode = interpreter->GetRetTree(); // hidden SELF is counted as well int nParSub = EQOverload->NPar(); assert( nParSub >= 1); // SELF if( nParSub < 3) // (SELF), LEFT, RIGHT { throw GDLException( callingNode, EQOverload->ObjectName() + ": Incorrect number of arguments.", false, false); } EnvUDT* newEnv; DObjGDL* self; Guard selfGuard; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = EQOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { self = this; newEnv= new EnvUDT( callingNode, EQOverload, &self); newEnv->SetNextParUnchecked( (BaseGDL**) &self); // LEFT parameter newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv } else { self = this->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, EQOverload, &self); newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value } // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + EQOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( static_cast(self) != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } return res; } // } } // if( StrictScalar()) // handle type conversion first // here r can be of any GDL type (due to operator overloading) if( r->Type() != GDL_OBJ) { if( r == NullGDL::GetSingleInstance()) // "this" is not scalar here -> return always false { Data_* res= new Data_(0); // (*res)[0] = 0; return res; } throw GDLException("Unable to convert variable to type object reference.",true,false); } // same code as for other types from here Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // if( nEl == 0) // nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = (s == (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] == s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] == s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] == s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] == (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] == (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] == (*this)[i]); } } //C delete right; //C delete this; return res; } // invalid types // template<> // Data_* Data_::EqOp( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype PTR.",true,false); // return NULL; // } // template<> // Data_* Data_::EqOp( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); // return NULL; // } // NeOp // returns *this ne *r, //C deletes itself and right template BaseGDL* Data_::NeOp( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = (s != (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] != s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] != s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] != s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] != (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] != (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] != (*this)[i]); } } //C delete right; //C delete this; return res; } // must handle overloads template<> BaseGDL* Data_::NeOp( BaseGDL* r) { if( Scalar()) // if( StrictScalar()) { // DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( (*this)[0]); // if( oStructGDL != NULL) // object not valid -> default behaviour // { // DStructDesc* desc = oStructGDL->Desc(); // // DFun* NEOverload = static_cast(desc->GetOperator( OONE)); // DSubUD* NEOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*this)[0], OONE)); if( NEOverload == NULL) { if( r == NullGDL::GetSingleInstance()) { Data_* res= new Data_( this->dim, BaseGDL::NOZERO); (*res)[0] = (0 != (*this)[0]); return res; } } else // if( NEOverload != NULL) { ProgNodeP callingNode = interpreter->GetRetTree(); // hidden SELF is counted as well int nParSub = NEOverload->NPar(); assert( nParSub >= 1); // SELF if( nParSub < 3) // (SELF), LEFT, RIGHT { throw GDLException( callingNode, NEOverload->ObjectName() + ": Incorrect number of arguments.", false, false); } EnvUDT* newEnv; DObjGDL* self; Guard selfGuard; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = NEOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { self = this; newEnv= new EnvUDT( callingNode, NEOverload, &self); newEnv->SetNextParUnchecked( (BaseGDL**)&self); // LEFT parameter newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv } else { self = this->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, NEOverload, &self); newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value } // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + NEOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( static_cast( self) != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } return res; } // } } // if( StrictScalar()) // handle type conversion first // here r can be of any GDL type (due to operator overloading) if( r->Type() != GDL_OBJ) { if( r == NullGDL::GetSingleInstance()) // "this" is not scalar here -> return always true { Data_* res= new Data_(1); // (*res)[0] = 0; return res; } throw GDLException("Unable to convert variable to type object reference.",true,false); } // same code as for other types from here Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = (s != (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] != s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] != s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] != s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] != (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] != (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] != (*this)[i]); } } //C delete right; //C delete this; return res; } // invalid types // template<> // Data_* Data_::NeOp( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype PTR.",true,false); // return NULL; // } // template<> // Data_* Data_::NeOp( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); // return NULL; // } // LeOp // returns *this le *r, //C deletes itself and right template BaseGDL* Data_::LeOp( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] <= s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] <= s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] >= s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] >= s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] >= (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] >= (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] >= (*this)[i]); } } //C delete right; //C delete this; return res; } // invalid types template<> BaseGDL* Data_::LeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::LeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> BaseGDL* Data_::LeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> BaseGDL* Data_::LeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } // LtOp // returns *this lt *r, //C deletes itself and right template BaseGDL* Data_::LtOp( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] < s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] < s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] > s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] > s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] > (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] > (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] > (*this)[i]); } } //C delete right; //C delete this; return res; } // invalid types template<> BaseGDL* Data_::LtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::LtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> BaseGDL* Data_::LtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> BaseGDL* Data_::LtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } // GeOp // returns *this ge *r, //C deletes itself and right template BaseGDL* Data_::GeOp( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] >= s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] >= s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] <= s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] <= s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] <= (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] <= (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] <= (*this)[i]); } } //C delete right; //C delete this; return res; } // invalid types template<> BaseGDL* Data_::GeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::GeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> BaseGDL* Data_::GeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> BaseGDL* Data_::GeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } // GtOp // returns *this gt *r, //C deletes itself and right template BaseGDL* Data_::GtOp( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; Ty s; if( right->StrictScalar(s)) { res= new Data_( this->dim, BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = ((*this)[0] > s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*this)[i] > s); } } else if( StrictScalar(s)) { res= new Data_( right->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] < s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] < s); } } else if( rEl < nEl) { res= new Data_( right->dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] < (*this)[i]); } } else // ( rEl >= nEl) { res= new Data_( this->dim, BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] < (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] < (*this)[i]); } } //C delete right; //C delete this; return res; } // invalid types template<> BaseGDL* Data_::GtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::GtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> BaseGDL* Data_::GtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> BaseGDL* Data_::GtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } //#undef USE_EIGEN // MatrixOp // returns *this # *r, //C does not delete itself and right template Data_* Data_::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { bool at = atranspose; bool bt = btranspose; Data_* par1 = static_cast(r); long NbCol0, NbRow0, NbCol1, NbRow1;//, NbCol2, NbRow2; SizeT rank0 = this->Rank(); if (rank0 > 2) throw GDLException("Array must have 1 or 2 dimensions",true,false); SizeT rank1 = par1->Rank(); if (rank1 > 2) throw GDLException("Array must have 1 or 2 dimensions",true,false); NbCol0 = this->Dim(0); if( NbCol0 == 0) NbCol0 = 1; NbRow0 = (rank0 == 2) ? this->Dim(1): 1; NbCol1 = par1->Dim(0); if( NbCol1 == 0) NbCol1 = 1; NbRow1 = (rank1 == 2) ? par1->Dim(1): 1; // NbCol0, NbRow0, NbCol1, NbRow1 are properly set now // vector cases (possible degeneration) if( rank0 <= 1 || rank1 <=1) { if( rank0 <= 1 && rank1 <=1) { // [NbCol0,1]#[NbCol1,1] -> just transpose b (if a is not transposed) if( !at) // && !bt bt = true; } else if( rank0 <= 1) // rank1 == 2 { // [NbCol0,1]#[NbCol1,NbRow1] if( !at && ((!bt && NbCol1 != 1) || (bt && NbRow1 != 1))) at = true; } else // if( rank1 <= 1) // rank0 == 2 { // [NbCol0,NbRow0]#[NbCol1,1] if( !bt && ((!at && NbRow0 == 1) || (at && NbCol0 == 1))) bt = true; } } #ifdef USE_EIGEN Map,Aligned> m0(&(*this)[0], NbCol0, NbRow0); Map,Aligned> m1(&(*par1)[0], NbCol1, NbRow1); if (at && bt) { if( /*(at && bt) &&*/ (NbCol0 != NbRow1)) { throw GDLException("Operands of matrix multiply have incompatible dimensions.atbt",true,false); // e->Throw("Operands of matrix multiply have incompatible dimensions: " + e->GetParString(0) + ", " + e->GetParString(1) + "."); } long& NbCol2 = NbRow0 ; long& NbRow2 = NbCol1 ; dimension dim(NbCol2, NbRow2); Data_* res = new Data_(dim, BaseGDL::NOZERO); // no guarding necessary: eigen only throws on memory allocation Map,Aligned> m2(&(*res)[0], NbCol2, NbRow2); m2.noalias() = m0.transpose() * m1.transpose(); return res; } else if (bt) { if( /*(!at && bt) &&*/ (NbRow0 != NbRow1)) { throw GDLException("Operands of matrix multiply have incompatible dimensions.bt",true,false); // e->Throw("Operands of matrix multiply have incompatible dimensions: " + e->GetParString(0) + ", " + e->GetParString(1) + "."); } long& NbCol2 = NbCol0; long& NbRow2 = NbCol1; dimension dim(NbCol2, NbRow2); Data_* res = new Data_(dim, BaseGDL::NOZERO); Map,Aligned> m2(&(*res)[0], NbCol2, NbRow2); m2.noalias() = m0 * m1.transpose(); return res; } else if (at) { if( /*(at && !bt) &&*/ (NbCol0 != NbCol1)) { throw GDLException("Operands of matrix multiply have incompatible dimensions.at",true,false); // e->Throw("Operands of matrix multiply have incompatible dimensions: " + e->GetParString(0) + ", " + e->GetParString(1) + "."); } long& NbCol2 = NbRow0; long& NbRow2 = NbRow1; dimension dim(NbCol2, NbRow2); Data_* res = new Data_(dim, BaseGDL::NOZERO); Map,Aligned> m2(&(*res)[0], NbCol2, NbRow2); m2.noalias() = m0.transpose() * m1; return res; } else { if( /*(!at && !bt) &&*/ (NbRow0 != NbCol1)) { throw GDLException("Operands of matrix multiply have incompatible dimensions._",true,false); // e->Throw("Operands of matrix multiply have incompatible dimensions: " + e->GetParString(0) + ", " + e->GetParString(1) + "."); } long& NbCol2 = NbCol0; long& NbRow2 = NbRow1; dimension dim(NbCol2, NbRow2); Data_* res = new Data_(dim, BaseGDL::NOZERO); Map,Aligned> m2(&(*res)[0], NbCol2, NbRow2); m2.noalias() = m0*m1; return res; } #else Data_* right=static_cast(r); Data_* res; // right op 1st SizeT nRow, nRowEl; if(bt) { nRow = NbCol1; nRowEl = NbRow1; } else { nRow = NbRow1; nRowEl = NbCol1; } SizeT nCol, nColEl; if(at) { nCol = NbRow0; nColEl = NbCol0; } else { nCol = NbCol0; nColEl = NbRow0; } if( nColEl != nRowEl) throw GDLException("Operands of matrix multiply have" " incompatible dimensions.",true,false); if( nRow > 1) res=New(dimension(nCol,nRow), BaseGDL::NOZERO); else res=New(dimension(nCol), BaseGDL::NOZERO); /* if( rank0 <= 1 && rank1 <= 1) { #ifdef _OPENMP SizeT nOp = nRow * nCol; #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nOp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nOp)) default(shared) { #pragma omp for for( OMPInt colA=0; colA < nCol; colA++) // res dim 0 for( OMPInt rowB=0; rowB < nRow; rowB++) // res dim 1 (*res)[ rowB * nCol + colA] += (*this)[colA] * (*right)[rowB]; } return res; } */ SizeT rIxEnd = nRow * nColEl; //#ifdef _OPENMP SizeT nOp = rIxEnd * nCol; #ifdef USE_STRASSEN_MATRIXMULTIPLICATION if( !bt && !at && strassen) //if( nOp > 1000000) { SizeT maxDim; if( nCol >= nColEl && nCol >= nRow) maxDim = nCol; else if( nColEl >= nRow) maxDim = nColEl; else maxDim = nRow; SizeT sOp = maxDim * maxDim * maxDim; //if( (sOp / nOp) < 8) { SizeT mSz = 2; while (mSz < maxDim) mSz <<= 1; SM1( mSz, nCol, nColEl, nRow, static_cast(right->DataAddr()), static_cast(this->DataAddr()), static_cast(res->DataAddr())); // delete[] buf; return res; } } #endif if( !at) // normal { if( !bt) // normal { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nOp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nOp)) default(shared) { #pragma omp for for( OMPInt colA=0; colA < nCol; ++colA) // res dim 0 for( OMPInt rIx=0, rowBnCol=0; rIx < rIxEnd; rIx += nColEl, rowBnCol += nCol) // res dim 1 { Ty& resEl = (*res)[ rowBnCol + colA]; resEl = 0;//(*this)[ colA] * (*right)[ rIx]; // initialization for( OMPInt i=0; i < nColEl; ++i) resEl += (*this)[ i*nCol+colA] * (*right)[ rIx+i]; } } } else // transpose r { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nOp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nOp)) default(shared) { #pragma omp for for( OMPInt colA=0; colA < nCol; ++colA) // res dim 0 for( OMPInt rIx=0, rowBnCol=0; rIx < nRow; ++rIx, rowBnCol += nCol) // res dim 1 { Ty& resEl = (*res)[ rowBnCol + colA]; resEl = 0;//(*this)[ colA] * (*right)[ rIx]; // initialization for( OMPInt i=0; i < nColEl; ++i) resEl += (*this)[ i*nCol+colA] * (*right)[ rIx + i * nRow]; } } } } else // atranspose { if( !bt) // normal { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nOp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nOp)) default(shared) { #pragma omp for for( OMPInt colA=0; colA < nCol; ++colA) // res dim 0 for( OMPInt rIx=0, rowBnCol=0; rIx < rIxEnd; rIx += nColEl, ++rowBnCol) // res dim 1 { Ty& resEl = (*res)[ rowBnCol * nCol + colA]; // Ty& resEl = (*res)[ rowBnCol + colA * nRow]; resEl = 0;//(*this)[ colA] * (*right)[ rIx]; // initialization for( OMPInt i=0; i < nColEl; ++i) resEl += (*this)[ i+colA*nColEl] * (*right)[ rIx+i]; // resEl += (*this)[ i*nCol+colA] * (*right)[ rIx+i]; } } } else // transpose r { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nOp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nOp)) default(shared) { #pragma omp for for( OMPInt colA=0; colA < nCol; ++colA) // res dim 0 for( OMPInt rIx=0; rIx < nRow; ++rIx) // res dim 1 { Ty& resEl = (*res)[ rIx *nCol + colA]; // Ty& resEl = (*res)[ rIx + colA * nRow]; resEl = 0;//(*this)[ colA] * (*right)[ rIx]; // initialization for( OMPInt i=0; i < nColEl; ++i) resEl += (*this)[ i+colA*nColEl] * (*right)[ rIx + i * nRow]; // resEl += (*this)[ i*nCol+colA] * (*right)[ rIx + i * nRow]; } } } } return res; #endif // #elseif USE_EIGEN } // invalid types template<> Data_* Data_::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // 2. operators which operate on 'this' // AndOp // Ands right to itself, //C deletes right // right must always have more or same number of elements // for integers template Data_* Data_::AndOp( BaseGDL* r) // GDL_DEFINE_INTEGER_FUNCTION( Data_*) AndOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { (*this)[0] = (*this)[0] & (*right)[0]; // & Ty(1); return this; } // note: we can't use valarray operation here as right->dd // might be larger than this->dd TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = (*this)[i] & (*right)[i]; // & Ty(1); } //C delete right; return this; } // different for floats template Data_* Data_::AndOpInv( BaseGDL* right) { return AndOp( right); } // for floats template<> Data_* Data_::AndOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { if( (*right)[0] == zero) (*this)[0]=zero; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*right)[i] == zero) (*this)[i]=zero; // if( (*this)[i] == zero || (*right)[i] == zero) (*this)[i]=zero; } //C delete right; return this; } template<> Data_* Data_::AndOpInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { if( (*this)[0] != zero) (*this)[0] = (*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*this)[i] = (*right)[i]; } //C delete right; return this; } // // for doubles template<> Data_* Data_::AndOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { if( (*right)[0] == zero) (*this)[0]=zero; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*right)[i] == zero) (*this)[i]=zero; // if( (*this)[i] == zero || (*right)[i] == zero) (*this)[i]=zero; } //C delete right; return this; } template<> Data_* Data_::AndOpInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { if( (*this)[0] != zero) (*this)[0] = (*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*this)[i] = (*right)[i]; } //C delete right; return this; } // invalid types // GDL_DEFINE_COMPLEX_FUNCTION( Data_*) AndOp( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype "+Sp::str+".",true,false); // return this; // } template<> Data_* Data_::AndOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::AndOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } // GDL_DEFINE_OTHER_FUNCTION( Data_*) AndOp( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype "+Sp::str+".",true,false); // return this; // } template<> Data_* Data_::AndOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } // template<> // Data_* Data_::AndOpInv( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype STRING.",true,false); // return this; // } template<> Data_* Data_::AndOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } // template<> // Data_* Data_::AndOpInv( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype PTR.",true,false); // return this; // } template<> Data_* Data_::AndOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // template<> // Data_* Data_::AndOpInv( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); // return this; // } template Data_* Data_::AndOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); // s &= Ty(1); // dd &= s; if( nEl == 1) { (*this)[0] &= s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared(s) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] &= s; } return this; } // different for floats template Data_* Data_::AndOpInvS( BaseGDL* right) { return AndOpS( right); } // for floats template<> Data_* Data_::AndOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); if( s == zero) // dd = zero; { // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*this)[i] = zero; }} return this; } template<> Data_* Data_::AndOpInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); if( s == zero) // dd = zero; { // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*this)[i] = zero; }} else { if( nEl == 1) { if( (*this)[0] != zero) (*this)[0] = s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*this)[i] = s; }} return this; } // for doubles template<> Data_* Data_::AndOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); if( s == zero) // dd = zero; // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*this)[i] = zero; } return this; } template<> Data_* Data_::AndOpInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); if( s == zero) // dd = zero; { // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*this)[i] = zero; }} else { if( nEl == 1) { if( (*this)[0] != zero) (*this)[0] = s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*this)[i] = s; }} return this; } // invalid types template<> Data_* Data_::AndOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::AndOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::AndOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } // template<> // Data_* Data_::AndOpInvS( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype STRING.",true,false); // return this; // } template<> Data_* Data_::AndOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::AndOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // OrOp // Ors right to itself, //C deletes right // right must always have more or same number of elements // for integers template Data_* Data_::OrOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); //if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] = (*this)[0] | (*right)[0]; // | Ty(1); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = (*this)[i] | (*right)[i]; // | Ty(1); } //C delete right; return this; } // different for floats template Data_* Data_::OrOpInv( BaseGDL* right) { return OrOp( right); } // for floats template<> Data_* Data_::OrOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] == zero) (*this)[0]=(*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*this)[i]=(*right)[i]; } //C delete right; return this; } template<> Data_* Data_::OrOpInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*right)[0] != zero) (*this)[0] = (*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*right)[i] != zero) (*this)[i] = (*right)[i]; } //C delete right; return this; } // for doubles template<> Data_* Data_::OrOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] == zero) (*this)[0]= (*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*this)[i]= (*right)[i]; } //C delete right; return this; } template<> Data_* Data_::OrOpInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*right)[0] != zero) (*this)[0] = (*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*right)[i] != zero) (*this)[i] = (*right)[i]; } //C delete right; return this; } // invalid types template<> Data_* Data_::OrOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::OrOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::OrOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::OrOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::OrOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // OrOp // Ors right to itself, //C deletes right // right must always have more or same number of elements // for integers template Data_* Data_::OrOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); //s &= Ty(1); // dd |= s; if( nEl == 1) { (*this)[0] = (*this)[0] | s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = (*this)[i] | s; } //C delete right; return this; } // different for floats template Data_* Data_::OrOpInvS( BaseGDL* right) { return OrOpS( right); } // for floats template<> Data_* Data_::OrOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); if( s != zero) { if( nEl == 1) { if( (*this)[0] == zero) (*this)[0] = s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*this)[i] = s; }} //C delete right; return this; } template<> Data_* Data_::OrOpInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); if( s != zero) // dd = s; { // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*this)[i] = s; return this; }} else { if( nEl == 1) { if( (*this)[0] != zero) (*this)[0] = s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*this)[i] = s; }} //C delete right; return this; } // for doubles template<> Data_* Data_::OrOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); if( s != zero) { if( nEl == 1) { if( (*this)[0] == zero) (*this)[0] = s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*this)[i] = s; }} //C delete right; return this; } template<> Data_* Data_::OrOpInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); if( s != zero) // dd = s; { // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*this)[i] = s; }} else { if( nEl == 1) { if( (*this)[0] != zero) (*this)[0] = s; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*this)[i] = s; }} //C delete right; return this; } // invalid types template<> Data_* Data_::OrOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::OrOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::OrOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::OrOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::OrOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // XorOp // Xors right to itself, //C deletes right // right must always have more or same number of elements // for integers template Data_* Data_::XorOp( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] ^= (*right)[0]; return this; } Ty s = (*right)[0]; if( right->StrictScalar(s)) { if( s != Sp::zero) // dd ^= s; { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] ^= s; }} } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] ^= (*right)[i]; } } //C delete right; return this; } // invalid types template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype FLOAT.",true,false); return this; } template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype DOUBLE.",true,false); return this; } template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::XorOpS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { (*this)[0] ^= /*(*this)[0] ^*/ (*right)[0]; return this; } Ty s = (*right)[0]; // dd ^= s; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] ^= s; // (*this)[i] = (*this)[i] ^ s; } //C delete right; return this; } // different for floats // for floats template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype FLOAT.",true,false); return this; } // for doubles template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype DOUBLE.",true,false); return this; } // invalid types template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // LtMark // LtMarks right to itself, //C deletes right // right must always have more or same number of elements template Data_* Data_::LtMark( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] > (*right)[0]) (*this)[0]=(*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] > (*right)[i]) (*this)[i]=(*right)[i]; } //C delete right; return this; } // invalid types template<> Data_* Data_::LtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::LtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::LtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::LtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::LtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::LtMarkS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { if( (*this)[0] > (*right)[0]) (*this)[0]=(*right)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] > s) (*this)[i]=s; } //C delete right; return this; } // invalid types template<> Data_* Data_::LtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::LtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::LtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::LtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::LtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // GtMark // GtMarks right to itself, //C deletes right // right must always have more or same number of elements template Data_* Data_::GtMark( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] < (*right)[0]) (*this)[0]=(*right)[0]; return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] < (*right)[i]) (*this)[i]=(*right)[i]; } //C delete right; return this; } // invalid types template<> Data_* Data_::GtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::GtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::GtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::GtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::GtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::GtMarkS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { if( (*this)[0] < (*right)[0]) (*this)[0]=(*right)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] < s) (*this)[i]=s; } //C delete right; return this; } // invalid types template<> Data_* Data_::GtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::GtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::GtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::GtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::GtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // Mod // modulo division: left=left % right template Data_* Data_::Mod( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); SizeT i=0; // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] %= (*right)[i]; //C delete right; return this; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // bool zeroEncountered = false; #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) /* if( !zeroEncountered) { if( (*right)[i] == this->zero) { zeroEncountered = true; (*this)[i] = this->zero; } } else*/ if( (*right)[ix] != this->zero) (*this)[ix] %= (*right)[ix]; else (*this)[ix] = this->zero; } //C delete right; return this; } } // inverse modulo division: left=right % left template Data_* Data_::ModInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] = (*right)[i] % (*this)[i]; //C delete right; return this; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // bool zeroEncountered = false; #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) /* if( !zeroEncountered) { if( (*this)[ix] == this->zero) { zeroEncountered = true; (*this)[ ix] = this->zero; } } else*/ if( (*this)[ix] != this->zero) (*this)[ix] = (*right)[ix] % (*this)[ix]; else (*this)[ix] = this->zero; } //C delete right; return this; } } // float modulo division: left=left % right inline DFloat Modulo( const DFloat& l, const DFloat& r) { // float t=abs(l/r); // if( l < 0.0) return t=(floor(t)-t)*abs(r); // return (t-floor(t))*abs(r); return fmod(l,r); } template<> Data_* Data_::Mod( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = Modulo((*this)[i],(*right)[i]); } //C delete right; return this; } // float inverse modulo division: left=right % left template<> Data_* Data_::ModInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = Modulo((*right)[i],(*this)[i]); } //C delete right; return this; } // in basic_op.cpp // double modulo division: left=left % right inline DDouble DModulo( const DDouble& l, const DDouble& r) { // DDouble t=abs(l/r); // if( l < 0.0) return t=(floor(t)-t)*abs(r); // return (t-floor(t))*abs(r); return fmod(l,r); } template<> Data_* Data_::Mod( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = DModulo((*this)[i],(*right)[i]); } //C delete right; return this; } // double inverse modulo division: left=right % left template<> Data_* Data_::ModInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = DModulo((*right)[i],(*this)[i]); } //C delete right; return this; } // invalid types template<> Data_* Data_::Mod( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::ModInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::Mod( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::Mod( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::ModInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::ModInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::Mod( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::ModInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::Mod( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::ModInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::ModS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; SizeT i=0; // remember: this is a template (must work for several types) // due to error handling the actual devision by 0 // has to be done // but if not 0, we save the expensive error handling if( s != this->zero) { // right->Scalar(s); // dd %= s; for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] %= s; //C delete right; return this; } if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { // right->Scalar(s); // dd %= s; for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] %= s; //C delete right; return this; } else { // bool zeroEncountered = false; // until zero operation is already done. // right->Scalar(s); assert( s == this->zero); // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS)// && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT ix=i; ix < nEl; ++ix) (*this)[ix] = 0; } //C delete right; return this; } } // inverse modulo division: left=right % left template Data_* Data_::ModInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // remember: this is a template (must work for several types) // due to error handling the actual devision by 0 // has to be done // but if not 0, we save the expensive error handling if( nEl == 1 && (*this)[0] != this->zero) { (*this)[0] = (*right)[0] % (*this)[0]; return this; } Ty s = (*right)[0]; SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { // right->Scalar(s); for( /*SizeT i=0*/; i < nEl; ++i) { (*this)[i] = s % (*this)[i]; } //C delete right; return this; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for // bool zeroEncountered = false; // right->Scalar(s); for( OMPInt ix=i; ix < nEl; ++ix) /* if( !zeroEncountered) { if( (*this)[ix] == this->zero) { zeroEncountered = true; (*this)[ix] = this->zero; } } else*/ if( (*this)[ix] != this->zero) (*this)[ix] = s % (*this)[ix]; else (*this)[ix] = this->zero; } //C delete right; return this; } } template<> Data_* Data_::ModS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = Modulo((*this)[i],s); } //C delete right; return this; } // float inverse modulo division: left=right % left template<> Data_* Data_::ModInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = Modulo(s,(*this)[i]); } //C delete right; return this; } template<> Data_* Data_::ModS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = DModulo((*this)[i],s); } //C delete right; return this; } // double inverse modulo division: left=right % left template<> Data_* Data_::ModInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = DModulo(s,(*this)[i]); } //C delete right; return this; } // invalid types template<> Data_* Data_::ModS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::ModInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::ModS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::ModS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::ModInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::ModInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } template<> Data_* Data_::ModS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::ModInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::ModS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::ModInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } // Pow // C++ defines pow only for floats and doubles //template T pow( const T r, const TT l) template T pow( const T r, const T l) { typedef T TT; if( l == 0) return 1; if( l < 0) return 0; const int nBits = sizeof(TT) * 8; T arr = r; T res = 1; TT mask = 1; for( SizeT i=0; i Data_* Data_::Pow( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); // valarray } //C delete right; return this; } // inverse power of value: left=right ^ left template Data_* Data_::PowInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // right->dd.resize(nEl); // dd = pow( right->Resize(nEl), dd); // valarray TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*right)[i], (*this)[i]); } //C delete right; return this; } // floats power of value: left=left ^ right template<> Data_* Data_::Pow( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); /* if( rEl == nEl) { for( SizeT i=0; i < nEl; ++i) dd[ i] = pow( dd[ i], right->dd[ i]); // valarray } else*/ { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); } } return this; } // PowInt and PowIntNew can only be called for GDL_FLOAT and GDL_DOUBLE template Data_* Data_::PowInt( BaseGDL* r) { assert( 0); return this; } // floats power of value with GDL_LONG: left=left ^ right template<> Data_* Data_::PowInt( BaseGDL* r) { DLongGDL* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); if( r->StrictScalar()) { DLong r0 = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], r0); } return this; } if( StrictScalar()) { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); Ty s0 = (*this)[ 0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[ i] = pow( s0, (*right)[ i]); } return res; } if( nEl <= rEl) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); } return this; } else { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } } template<> Data_* Data_::PowInt( BaseGDL* r) { DLongGDL* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); if( r->StrictScalar()) { DLong r0 = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], r0); } return this; } if( StrictScalar()) { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); Ty s0 = (*this)[ 0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[ i] = pow( s0, (*right)[ i]); } return res; } if( nEl <= rEl) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); } return this; } else { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } } // floats inverse power of value: left=right ^ left template<> Data_* Data_::PowInv( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // right->dd.resize(nEl); /* if( rEl == nEl) dd = pow( right->dd, dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*right)[i], (*this)[i]); } //C delete right; return this; } // doubles power of value: left=left ^ right template<> Data_* Data_::Pow( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // right->dd.resize(nEl); // dd = pow( dd, right->Resize(nEl)); // valarray /* if( rEl == nEl) dd = pow( dd, right->dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); } //C delete right; return this; } // doubles inverse power of value: left=right ^ left template<> Data_* Data_::PowInv( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // right->dd.resize(nEl); // dd = pow( right->Resize(nEl), dd); // valarray /* if( rEl == nEl) dd = pow( right->dd, dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*right)[i], (*this)[i]); } //C delete right; return this; } // complex power of value: left=left ^ right // complex is special here template<> Data_* Data_::Pow( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); assert( r->N_Elements() > 0); if( r->Type() == GDL_FLOAT) { Data_* right=static_cast* >(r); DFloat s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); // ULong rEl=right->N_Elements(); // ULong nEl=N_Elements(); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // right->dd.resize(nEl); // dd = pow( dd, right->dd); // valarray #if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) for( SizeT i=0; iResize(nEl)); // valarray /* if( r->N_Elements() == nEl) dd = pow( dd, right->dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); } #endif //C delete right; return this; } // complex inverse power of value: left=right ^ left template<> Data_* Data_::PowInv( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); #if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) for( SizeT i=0; idd.resize(nEl); // dd = pow( right->Resize(nEl), dd); // valarray /* if( rEl == nEl) dd = pow( right->dd, dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*right)[i], (*this)[i]); #endif } //C delete right; return this; } // double complex power of value: left=left ^ right template<> Data_* Data_::Pow( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); if( r->Type() == GDL_DOUBLE) { Data_* right=static_cast* >(r); assert( right->N_Elements() > 0); DDouble s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); assert( right->N_Elements() > 0); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); // ULong rEl=right->N_Elements(); // ULong nEl=N_Elements(); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // right->dd.resize(nEl); // dd = pow( dd, right->dd); // valarray #if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) for( SizeT i=0; iResize(nEl)); // valarray /* if( r->N_Elements() == nEl) dd = pow( dd, right->dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], (*right)[i]); } #endif //C delete right; return this; } // double complex inverse power of value: left=right ^ left template<> Data_* Data_::PowInv( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); #if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) for( SizeT i=0; idd.resize(nEl); // dd = pow( right->Resize(nEl), dd); // valarray /* if( rEl == nEl) dd = pow( right->dd, dd); // valarray else*/ TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*right)[i], (*this)[i]); } #endif //C delete right; return this; } // invalid types template<> Data_* Data_::Pow( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::PowInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::Pow( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::PowInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::Pow( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::PowInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::PowS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( (*this)[i], s); } //C delete right; return this; } // inverse power of value: left=right ^ left template Data_* Data_::PowInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); // dd = pow( s, d); // valarray TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = pow( s, (*this)[i]); } //C delete right; return this; } // floats power of value: left=left ^ right template<> Data_* Data_::PowS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowS( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); assert( r->N_Elements() > 0); if( r->Type() == GDL_FLOAT) { Data_* right=static_cast* >(r); DFloat s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); // ULong rEl=right->N_Elements(); // ULong nEl=N_Elements(); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); //#if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); //#if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowS( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); if( r->Type() == GDL_DOUBLE) { Data_* right=static_cast* >(r); assert( right->N_Elements() > 0); DDouble s; // note: changes here have to be reflected in POWNCNode::Eval() (prognodeexpr.cpp) // (concerning when a new variable is created vs. using this) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); assert( right->N_Elements() > 0); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) if( right->StrictScalar(s)) { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); // ULong rEl=right->N_Elements(); // ULong nEl=N_Elements(); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); //#if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s = (*right)[0]; // right->Scalar(s); //#if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::PowInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::PowS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::PowInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::PowS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::PowInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } //#include "instantiate_templates.hpp" #endif gdl-0.9.9/src/basic_op_add.cpp000066400000000000000000000273351340051421000161610ustar00rootroot00000000000000/*************************************************************************** basic_op_add.cpp - GDL add (+) operators ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_BASIC_OP_CPP // // header in datatypes.hpp // // //#include "datatypes.hpp" // //#include "dstructgdl.hpp" // //#include "arrayindex.hpp" // // //#include // #include "sigfpehandler.hpp" // // #ifdef _OPENMP // #include // #endif // // #include "typetraits.hpp" // // using namespace std; // ************************ // Add // ************************ // also see Add...New operators (in basic_op_new.cpp) // Adds right to itself, //C deletes right // right must always have more or same number of elements template BaseGDL* Data_::Add( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { (*this)[0] += (*right)[0]; return this; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); mThis += mRight; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += (*right)[i]; } //C delete right; return this; #endif } template BaseGDL* Data_::AddInv( BaseGDL* r) { assert( this->Type() != GDL_OBJ); // should never be called via this return Add( r); // this needs to be modified } template<> BaseGDL* Data_::AddInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); if( nEl == 1) { (*this)[0] = (*right)[0] + (*this)[0]; return this; } // if( !rEl || !nEl) throw GDLException("Variable is undefined."); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = (*right)[i] + (*this)[i]; } //C delete right; return this; } // invalid types template<> BaseGDL* Data_::Add( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> BaseGDL* Data_::Add( BaseGDL* r) { // overload here Data_* self; DSubUD* plusOverload; ProgNodeP callingNode = interpreter->GetRetTree(); if( !Scalar()) { if( r->Type() == GDL_OBJ && r->Scalar()) { self = static_cast( r); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOPlus)); if( plusOverload == NULL) { throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false); } } else { throw GDLException( callingNode, "Cannot apply operation to non-scalar datatype OBJECT.", true, false); } } else { // Scalar() self = static_cast( this); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOPlus)); if( plusOverload == NULL) { if( r->Type() == GDL_OBJ && r->Scalar()) { self = static_cast( r); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOPlus)); if( plusOverload == NULL) { throw GDLException(callingNode,"Cannot apply not overloaded operator to datatype OBJECT.",true, false); } } else { throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false); } } } assert( self->Scalar()); assert( plusOverload != NULL); // hidden SELF is counted as well int nParSub = plusOverload->NPar(); assert( nParSub >= 1); // SELF if( nParSub < 3) // (SELF), LEFT, RIGHT { throw GDLException( callingNode, plusOverload->ObjectName() + ": Incorrect number of arguments.", false, false); } EnvUDT* newEnv; Guard selfGuard; BaseGDL* thisP; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = plusOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { thisP = this; newEnv= new EnvUDT( callingNode, plusOverload, &self); newEnv->SetNextParUnchecked( &thisP); // LEFT parameter, as reference to prevent cleanup in newEnv newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv } else { self = self->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, plusOverload, &self); newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value } // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + plusOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( static_cast(self) != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } return res; } // difference from above: Order of parameters in call template<> BaseGDL* Data_::AddInv( BaseGDL* r) { if( r->Type() == GDL_OBJ && r->Scalar()) { return r->Add( this); // for right order of parameters } // overload here Data_* self; DSubUD* plusOverload; ProgNodeP callingNode = interpreter->GetRetTree(); if( !Scalar()) { throw GDLException( callingNode, "Cannot apply operation to non-scalar datatype OBJECT.", true, false); } else { // Scalar() self = static_cast( this); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOPlus)); if( plusOverload == NULL) { throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false); } } assert( self->Scalar()); assert( plusOverload != NULL); // hidden SELF is counted as well int nParSub = plusOverload->NPar(); assert( nParSub >= 1); // SELF if( nParSub < 3) // (SELF), LEFT, RIGHT { throw GDLException( callingNode, plusOverload->ObjectName() + ": Incorrect number of arguments.", false, false); } EnvUDT* newEnv; Guard selfGuard; BaseGDL* thisP; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = plusOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { thisP = this; newEnv= new EnvUDT( callingNode, plusOverload, &self); // order different to Add newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv newEnv->SetNextParUnchecked( &thisP); // LEFT parameter, as reference to prevent cleanup in newEnv } else { self = self->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, plusOverload, &self); // order different to Add newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value } // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + plusOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( static_cast(self) != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } return res; } template BaseGDL* Data_::AddS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] += (*right)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); // dd += s; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); mThis += s; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += s; } //C delete right; return this; #endif } template<> BaseGDL* Data_::AddS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] += (*right)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); // dd += s; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] += s; } //C delete right; return this; } template BaseGDL* Data_::AddInvS( BaseGDL* r) { return AddS( r); } template<> BaseGDL* Data_::AddInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] = (*right)[0] + (*this)[0] ; return this; } Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = s + (*this)[i]; } //C delete right; return this; } // invalid types template<> BaseGDL* Data_::AddS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> BaseGDL* Data_::AddS( BaseGDL* r) { return Add( r); } template<> BaseGDL* Data_::AddInvS( BaseGDL* r) { return AddInv( r); } //#include "instantiate_templates.hpp" #endif gdl-0.9.9/src/basic_op_div.cpp000066400000000000000000000170021340051421000162010ustar00rootroot00000000000000/*************************************************************************** basic_op_div.cpp - GDL div (/) operators ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_BASIC_OP_CPP // // header in datatypes.hpp // // //#include "datatypes.hpp" // //#include "dstructgdl.hpp" // //#include "arrayindex.hpp" // // //#include // #include "sigfpehandler.hpp" // // #ifdef _OPENMP // #include // #endif // // #include "typetraits.hpp" // // using namespace std; // Div // division: left=left/right template Data_* Data_::Div( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); SizeT i = 0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { // TODO: Check if we can use OpenMP here (is longjmp allowed?) // if yes: need to run the full loop after the longjmp for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] /= (*right)[i]; //C delete right; return this; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // bool zeroEncountered = false; // until zero operation is already done. #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) /* if( !zeroEncountered) { if( (*right)[ix] == this->zero) zeroEncountered = true; } else*/ if( (*right)[ix] != this->zero) (*this)[ix] /= (*right)[ix]; } //C delete right; return this; } } // inverse division: left=right/left template Data_* Data_::DivInv( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); SizeT i = 0; // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] = (*right)[i] / (*this)[i]; //C delete right; return this; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // bool zeroEncountered = false; // until zero operation is already done. #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) /* if( !zeroEncountered) { if( (*this)[ix] == this->zero) { zeroEncountered = true; (*this)[ ix] = (*right)[i]; } } else*/ if( (*this)[ix] != this->zero) (*this)[ix] = (*right)[ix] / (*this)[ix]; else (*this)[ix] = (*right)[ix]; } //C delete right; return this; } } // invalid types template<> Data_* Data_::Div( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::DivInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::Div( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::DivInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::Div( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::DivInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::DivS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; // remember: this is a template (must work for several types) // due to error handling the actual devision by 0 // has to be done // but if not 0, we save the expensive error handling if( s != this->zero) { for(SizeT i=0; i < nEl; ++i) { (*this)[i] /= s; } return this; } if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for(SizeT i=0; i < nEl; ++i) { (*this)[i] /= s; } return this; } return this; } // inverse division: left=right/left template Data_* Data_::DivInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); // remember: this is a template (must work for several types) // due to error handling the actual devision by 0 // has to be done // but if not 0, we save the expensive error handling if( nEl == 1 && (*this)[0] != this->zero) { (*this)[0] = (*right)[0] / (*this)[0]; return this; } Ty s = (*right)[0]; SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { // right->Scalar(s); for( /*SizeT i=0*/; i < nEl; ++i) (*this)[i] = s / (*this)[i]; //C delete right; return this; } else { // TRACEOMP( __FILE__, __LINE__) // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // // bool zeroEncountered = false; // #pragma omp for // right->Scalar(s); for( SizeT ix=i; ix < nEl; ++ix) /* if( !zeroEncountered) { if( (*this)[ix] == this->zero) { zeroEncountered = true; (*this)[ix] = s; } } else*/ if( (*this)[ix] != this->zero) (*this)[ix] = s / (*this)[ix]; else (*this)[ix] = s; // } //C delete right; return this; } } // invalid types template<> Data_* Data_::DivS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::DivInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::DivS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::DivInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::DivS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::DivInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } #endif gdl-0.9.9/src/basic_op_mult.cpp000066400000000000000000000077621340051421000164140ustar00rootroot00000000000000/*************************************************************************** basic_op_mult.cpp - GDL mult (*) operators ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_BASIC_OP_CPP // // header in datatypes.hpp // // //#include "datatypes.hpp" // //#include "dstructgdl.hpp" // //#include "arrayindex.hpp" // // //#include // #include "sigfpehandler.hpp" // // #ifdef _OPENMP // #include // #endif // // #include "typetraits.hpp" // // using namespace std; // Mult // Mults right to itself, //C deletes right // right must always have more or same number of elements template Data_* Data_::Mult( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] *= (*right)[0]; return this; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); mThis *= mRight; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] *= (*right)[i]; } //C delete right; return this; #endif } // invalid types template<> Data_* Data_::Mult( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::Mult( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::Mult( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template Data_* Data_::MultS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { (*this)[0] *= (*right)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); // dd *= s; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); mThis *= s; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] *= s; } //C delete right; return this; #endif } // invalid types template<> Data_* Data_::MultS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::MultS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::MultS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } #endif gdl-0.9.9/src/basic_op_new.cpp000066400000000000000000002627321340051421000162240ustar00rootroot00000000000000/*************************************************************************** basic_op_new.cpp - GDL operators ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp // after basic_op.cpp #ifdef INCLUDE_BASIC_OP_CPP using namespace std; // binary operators // in basic_op.cpp: // 1. operators that always return a new result (basic_op.cpp) // 2. operators which operate on 'this' (basic_op.cpp) // here: // 3. same operators as under 2. that always return a new result // AndOp &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // Ands right and itself into a new DataT_ // right must always have more or same number of elements // for integers template Data_* Data_::AndOpNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); assert(right->N_Elements()); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*this)[0] & (*right)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] & (*right)[i]; // & Ty(1); } return res; } // different for floats template Data_* Data_::AndOpInvNew( BaseGDL* right) { return AndOpNew( right); } // for floats template<> Data_* Data_::AndOpNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); if( nEl == 1) { if ( (*right)[0] == zero ) (*res)[0] = zero; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for ( OMPInt i=0; i < nEl; ++i ) if ( (*right)[i] == zero ) (*res)[i] = zero; else (*res)[i] = (*this)[i]; } return res; } template<> Data_* Data_::AndOpInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); assert( right->N_Elements()); Data_* res = NewResult(); if( nEl == 1) { if( (*this)[0] != zero) (*res)[0] = (*right)[0]; else (*res)[0] = zero; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*res)[i] = (*right)[i]; else (*res)[i] = zero; } return res; } // for doubles template<> Data_* Data_::AndOpNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); assert( right->N_Elements()); Data_* res = NewResult(); if( nEl == 1) { if ( (*right)[0] == zero ) (*res)[0] = zero; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if ( (*right)[i] == zero ) (*res)[i] = zero; else (*res)[i] = (*this)[i]; } return res; } template<> Data_* Data_::AndOpInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); assert( right->N_Elements()); Data_* res = NewResult(); if( nEl == 1) { if( (*this)[0] != zero) (*res)[0] = (*right)[0]; else (*res)[0] = zero; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*res)[i] = (*right)[i]; else (*res)[i] = zero; } return res; } // invalid types template<> Data_* Data_::AndOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::AndOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::AndOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } // template<> // Data_* Data_::AndOpInvNew( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype STRING.",true,false); // return res; // } template<> Data_* Data_::AndOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } // template<> // Data_* Data_::AndOpInvNew( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype PTR.",true,false); // return res; // } template<> Data_* Data_::AndOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // template<> // Data_* Data_::AndOpInvNew( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype PTR.",true,false); // return res; // } // scalar versions template Data_* Data_::AndOpSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*this)[0] & s; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared(s) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] & s; } return res; } // different for floats template Data_* Data_::AndOpInvSNew( BaseGDL* right) { return AndOpSNew( right); } // for floats template<> Data_* Data_::AndOpSNew( BaseGDL* r) { Data_* right=static_cast(r); if( (*right)[0] == zero) { return New( this->dim, BaseGDL::ZERO); } return this->Dup(); } template<> Data_* Data_::AndOpInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; if( s == zero) { return New( this->dim, BaseGDL::ZERO); } else { Data_* res = NewResult(); if( nEl == 1) { if( (*this)[0] != zero) (*res)[0] = s; else (*res)[0] = zero; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*res)[i] = s; else (*res)[i] = zero; } return res; } } // for doubles template<> Data_* Data_::AndOpSNew( BaseGDL* r) { Data_* right=static_cast(r); if( (*right)[0] == zero) { return New( this->dim, BaseGDL::ZERO); } return this->Dup(); } template<> Data_* Data_::AndOpInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; if( s == zero) { return New( this->dim, BaseGDL::ZERO); } else { Data_* res = NewResult(); if( nEl == 1) { if( (*this)[0] != zero) (*res)[0] = s; else (*res)[0] = zero; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*res)[i] = s; else (*res)[i] = zero; } return res; } } // invalid types template<> Data_* Data_::AndOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::AndOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::AndOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } // template<> // Data_* Data_::AndOpInvSNew( BaseGDL* r) // { // throw GDLException("Cannot apply operation to datatype STRING.",true,false); // return res; // } template<> Data_* Data_::AndOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::AndOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // OrOp |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| // Ors right to itself returns new result // right must always have more or same number of elements // for integers template Data_* Data_::OrOpNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); //if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*res)[0] = (*this)[0] | (*right)[0]; // | Ty(1); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] | (*right)[i]; // | Ty(1); } //C delete right; return res; } // different for floats template Data_* Data_::OrOpInvNew( BaseGDL* right) { return OrOpNew( right); } // for floats template<> Data_* Data_::OrOpNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] == zero) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*res)[i] = (*right)[i]; else (*res)[i] = (*this)[i]; } //C delete right; return res; } template<> Data_* Data_::OrOpInvNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*right)[0] != zero) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*right)[i] != zero) (*res)[i] = (*right)[i]; else (*res)[i] = (*this)[i]; } //C delete right; return res; } // for doubles template<> Data_* Data_::OrOpNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] == zero) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*res)[i] = (*right)[i]; else (*res)[i] = (*this)[i]; } //C delete right; return res; } template<> Data_* Data_::OrOpInvNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*right)[0] != zero) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*right)[i] != zero) (*res)[i] = (*right)[i]; else (*res)[i] = (*this)[i]; } //C delete right; return res; } // invalid types template<> Data_* Data_::OrOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::OrOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::OrOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::OrOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::OrOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // OrOpS // for integers template Data_* Data_::OrOpSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); //s &= Ty(1); // dd |= s; if( nEl == 1) { (*res)[0] = (*this)[0] | s; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] | s; } //C delete right; return res; } // different for floats template Data_* Data_::OrOpInvSNew( BaseGDL* right) { return OrOpSNew( right); } // for floats template<> Data_* Data_::OrOpSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; if( s != zero) { Data_* res = NewResult(); if( nEl == 1) { if( (*this)[0] == zero) (*res)[0] = s; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*res)[i] = s; else (*res)[i] = (*this)[i]; } return res; } else // s == zero { return this->Dup(); } } template<> Data_* Data_::OrOpInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); Ty s = (*right)[0]; if( s != zero) { for( SizeT i=0; i < nEl; ++i) (*res)[i] = s; return res; } else { if( nEl == 1) { if( (*this)[0] != zero) (*res)[0] = s; else (*res)[0] = zero; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*res)[i] = s; else (*res)[i] = zero; } return res; } } // for doubles template<> Data_* Data_::OrOpSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); Ty s = (*right)[0]; // right->Scalar(s); if( s != zero) { if( nEl == 1) { if( (*this)[0] == zero) (*res)[0] = s; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] == zero) (*res)[i] = s; else (*res)[i] = (*this)[i]; } return res; } // s == zero return this->Dup(); } template<> Data_* Data_::OrOpInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); Ty s = (*right)[0]; if( s != zero) { for( SizeT i=0; i < nEl; ++i) (*res)[i] = s; return res; } else { if( nEl == 1) { if( (*this)[0] != zero) (*res)[0] = s; else (*res)[0] = zero; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] != zero) (*res)[i] = s; else (*res)[i] = zero; } return res; } } // invalid types template<> Data_* Data_::OrOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::OrOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::OrOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::OrOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::OrOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // XorOp ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // Xors right to itself, //C deletes right // right must always have more or same number of elements // for integers template Data_* Data_::XorOpNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { Data_* res = NewResult(); (*res)[0] = (*this)[0] ^ (*right)[0]; return res; } Ty s; if( right->StrictScalar(s)) { if( s == Sp::zero) return this->Dup(); Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] ^ s; } return res; } else { Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] ^ (*right)[i]; } return res; } } // invalid types template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype FLOAT.",true,false); return NULL; } template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype DOUBLE.",true,false); return NULL; } template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template Data_* Data_::XorOpSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { Data_* res = NewResult(); (*res)[0] = (*this)[0] ^ (*right)[0]; return res; } Ty s = (*right)[0]; if( s == this->zero) return this->Dup(); Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] ^ s; } return res; } // different for floats // for floats template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype FLOAT.",true,false); return NULL; } // for doubles template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype DOUBLE.",true,false); return NULL; } // invalid types template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // Add ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Adds right to itself returns new result // right must always have more or same number of elements template BaseGDL* Data_::AddNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( nEl); assert( right->N_Elements()); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*this)[0] + (*right)[0]; return res; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis + mRight; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] + (*right)[i]; } //C delete right; return res; #endif } template BaseGDL* Data_::AddInvNew( BaseGDL* r) { return AddNew( r); } template<> BaseGDL* Data_::AddInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*right)[0] + (*this)[0] ; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*right)[i] + (*this)[i]; } //C delete right; return res; } // invalid types template<> BaseGDL* Data_::AddNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::AddNew( BaseGDL* r) { return Add( r); } template<> BaseGDL* Data_::AddInvNew( BaseGDL* r) { return AddInv( r); } // scalar versions template BaseGDL* Data_::AddSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*this)[0] + (*right)[0]; return res; } Ty s = (*right)[0]; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis + s; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] + s; } //C delete right; return res; #endif } template BaseGDL* Data_::AddInvSNew( BaseGDL* r) { return AddSNew( r); } template<> BaseGDL* Data_::AddInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { (*res)[0] = (*right)[0] + (*this)[0]; return res; } Ty s = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = s + (*this)[i]; } //C delete right; return res; } // invalid types template<> BaseGDL* Data_::AddSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::AddSNew( BaseGDL* r) { return Add( r); } template<> BaseGDL* Data_::AddInvSNew( BaseGDL* r) { return AddInv( r); } // Sub ---------------------------------------------------------------------- // substraction: res=left-right template BaseGDL* Data_::SubNew( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); Data_* res = NewResult(); if( nEl == 1)// && rEl == 1) { (*res)[0] = (*this)[0] - (*right)[0]; return res; } Ty s; if( right->StrictScalar(s)) { #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis - s; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] - s; } return res; #endif } else { #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis - mRight; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] - (*right)[i]; } return res; #endif } } // inverse substraction: left=right-left template BaseGDL* Data_::SubInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*right)[0] - (*this)[0]; return res; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mRight - mThis; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*right)[i] - (*this)[i]; } return res; #endif } // invalid types template<> BaseGDL* Data_::SubNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> BaseGDL* Data_::SubInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> BaseGDL* Data_::SubNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::SubInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::SubNew( BaseGDL* r) { return Sub( r); } template<> BaseGDL* Data_::SubInvNew( BaseGDL* r) { return SubInv( r); } // scalar versions template BaseGDL* Data_::SubSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*this)[0] - (*right)[0]; return res; } Ty s = (*right)[0]; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis - s; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] - s; } return res; #endif } // inverse substraction: left=right-left template BaseGDL* Data_::SubInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = (*right)[0] - (*this)[0]; return res; } Ty s = (*right)[0]; // right->Scalar(s); // dd = s - dd; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = s - mThis; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = s - (*this)[i]; } return res; #endif } // invalid types template<> BaseGDL* Data_::SubSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> BaseGDL* Data_::SubInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> BaseGDL* Data_::SubSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::SubInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> BaseGDL* Data_::SubSNew( BaseGDL* r) { return Sub( r); } template<> BaseGDL* Data_::SubInvSNew( BaseGDL* r) { return SubInv( r); } // LtMark <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // LtMarks right to itself, //C deletes right // right must always have more or same number of elements template Data_* Data_::LtMarkNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] > (*right)[0]) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] > (*right)[i]) (*res)[i] = (*right)[i]; else (*res)[i] = (*this)[i]; } //C delete right; return res; } // invalid types template<> Data_* Data_::LtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::LtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::LtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::LtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::LtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // scalar versions template Data_* Data_::LtMarkSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { if( (*this)[0] > (*right)[0]) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] > s) (*res)[i] = s; else (*res)[i] = (*this)[i]; } //C delete right; return res; } // invalid types template<> Data_* Data_::LtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::LtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::LtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::LtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::LtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // GtMark >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // GtMarks right to itself returns new result // right must always have more or same number of elements template Data_* Data_::GtMarkNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { if( (*this)[0] < (*right)[0]) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] < (*right)[i]) (*res)[i] = (*right)[i]; else (*res)[i] = (*this)[i]; } //C delete right; return res; } // invalid types template<> Data_* Data_::GtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::GtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::GtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::GtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::GtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // scalar versions template Data_* Data_::GtMarkSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { if( (*this)[0] < (*right)[0]) (*res)[0] = (*right)[0]; else (*res)[0] = (*this)[0]; return res; } Ty s = (*right)[0]; // right->Scalar(s); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) if( (*this)[i] < s) (*res)[i] = s; else (*res)[i] = (*this)[i]; } ; return res; } // invalid types template<> Data_* Data_::GtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::GtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::GtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::GtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::GtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // Mult ********************************************************************* // Mults right to itself, //C deletes right // right must always have more or same number of elements template Data_* Data_::MultNew( BaseGDL* r) { Data_* right=static_cast(r); Data_* res=NewResult(); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); // assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*res)[0] = (*this)[0] * (*right)[0]; return res; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis * mRight; return res; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = (*this)[i] * (*right)[i]; } //C delete right; return res; #endif } // invalid types template<> Data_* Data_::MultNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::MultNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::MultNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // scalar versions template Data_* Data_::MultSNew( BaseGDL* r ) { Data_* right=static_cast ( r ); ULong nEl=N_Elements(); assert ( nEl ); Data_* res = NewResult(); if ( nEl == 1 ) { ( *res )[0] = ( *this )[0] * ( *right )[0]; return res; } Ty s = ( *right ) [0]; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); mRes = mThis * s; return res; #else TRACEOMP ( __FILE__, __LINE__ ) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for ( OMPInt i=0; i < nEl; ++i ) (*res ) [i] = (*this )[i] * s; } return res; #endif } // invalid types template<> Data_* Data_::MultSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::MultSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::MultSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // Div ////////////////////////////////////////////////////////////////////// // division: left=left/right template Data_* Data_::DivNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); SizeT i = 0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { // TODO: Check if we can use OpenMP here (is longjmp allowed?) // if yes: need to run the full loop after the longjmp for( ; i < nEl; ++i) (*res)[i] = (*this)[i] / (*right)[i]; return res; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) if( (*right)[ix] != this->zero) (*res)[ix] = (*this)[ix] / (*right)[ix]; else (*res)[ix] = (*this)[ix]; } return res; } } // inverse division: left=right/left template Data_* Data_::DivInvNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); SizeT i = 0; // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( /*SizeT i=0*/; i < nEl; ++i) (*res)[i] = (*right)[i] / (*this)[i]; return res; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) if( (*this)[ix] != this->zero) (*res)[ix] = (*right)[ix] / (*this)[ix]; else (*res)[ix] = (*right)[ix]; } //C delete right; return res; } } // invalid types template<> Data_* Data_::DivNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::DivInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::DivNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::DivInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::DivNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> Data_* Data_::DivInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // scalar versions template Data_* Data_::DivSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; SizeT i=0; Data_* res = NewResult(); if( s != this->zero) { for( SizeT i=0; i < nEl; ++i) (*res)[i] = (*this)[i] / s; return res; } if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( SizeT i=0; i < nEl; ++i) (*res)[i] = (*this)[i] / s; } else { for( SizeT i=0; i < nEl; ++i) (*res)[i] = (*this)[i]; // } } return res; } // inverse division: left=right/left template Data_* Data_::DivInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1 && (*this)[0] != this->zero) { (*res)[0] = (*right)[0] / (*this)[0]; return res; } Ty s = (*right)[0]; SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( ; i < nEl; ++i) (*res)[i] = s / (*this)[i]; return res; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) if( (*this)[ix] != this->zero) (*res)[ix] = s / (*this)[ix]; else (*res)[ix] = s; } return res; } } // invalid types template<> Data_* Data_::DivSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::DivInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::DivSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::DivInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::DivSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> Data_* Data_::DivInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // Mod %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // modulo division: left=left % right template Data_* Data_::ModNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); // assert( rEl); assert( nEl); SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( ; i < nEl; ++i) (*res)[i] = (*this)[i] % (*right)[i]; return res; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) if( (*right)[ix] != this->zero) (*res)[ix] = (*this)[ix] % (*right)[ix]; else (*res)[ix] = this->zero; } return res; } } // inverse modulo division: left=right % left template Data_* Data_::ModInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( ; i < nEl; ++i) (*res)[i] = (*right)[i] % (*this)[i]; return res; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) if( (*this)[ix] != this->zero) (*res)[ix] = (*right)[ix] % (*this)[ix]; else (*res)[ix] = this->zero; } return res; } } // in basic_op.cpp // float modulo division: left=left % right template<> Data_* Data_::ModNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { (*res)[0] = Modulo((*this)[0],(*right)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = Modulo((*this)[i],(*right)[i]); } return res; } // float inverse modulo division: left=right % left template<> Data_* Data_::ModInvNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { (*res)[0] = Modulo((*right)[0],(*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = Modulo((*right)[i],(*this)[i]); } return res; } // double modulo division: left=left % right template<> Data_* Data_::ModNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = DModulo((*this)[0],(*right)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = DModulo((*this)[i],(*right)[i]); } return res; } // double inverse modulo division: left=right % left template<> Data_* Data_::ModInvNew( BaseGDL* r) { Data_* right=static_cast(r); // ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { (*res)[0] = DModulo((*right)[0],(*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = DModulo((*right)[i],(*this)[i]); } return res; } // invalid types template<> Data_* Data_::ModNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::ModInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::ModNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::ModInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::ModNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> Data_* Data_::ModInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // scalar versions template Data_* Data_::ModSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; Data_* res = NewResult(); if( s != this->zero) { for( SizeT i=0; i < nEl; ++i) (*res)[i] = (*this)[i] % s; return res; } if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( SizeT i=0; i < nEl; ++i) (*res)[i] = (*this)[i] % s; return res; } else { assert( s == this->zero); for( SizeT i=0; i < nEl; ++i) (*res)[i] = this->zero; return res; } } // inverse modulo division: left=right % left template Data_* Data_::ModInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1 && (*this)[0] != this->zero) { (*res)[0] = (*right)[0] % (*this)[0]; return res; } Ty s = (*right)[0]; SizeT i=0; if( sigsetjmp( sigFPEJmpBuf, 1) == 0) { for( /*SizeT i=0*/; i < nEl; ++i) { (*res)[i] = s % (*this)[i]; } return res; } else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt ix=i; ix < nEl; ++ix) if( (*this)[ix] != this->zero) (*res)[ix] = s % (*this)[ix]; else (*res)[ix] = this->zero; } return res; } } template<> Data_* Data_::ModSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = Modulo((*this)[0],(*right)[0]); return res; } Ty s = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = Modulo((*this)[i],s); } return res; } // float inverse modulo division: left=right % left template<> Data_* Data_::ModInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = Modulo((*right)[0],(*this)[0]); return res; } Ty s = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = Modulo(s,(*this)[i]); } return res; } template<> Data_* Data_::ModSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = DModulo((*this)[0],(*right)[0]); return res; } Ty s = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = DModulo((*this)[i],s); } return res; } // double inverse modulo division: left=right % left template<> Data_* Data_::ModInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = DModulo((*right)[0],(*this)[0]); return res; } Ty s = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = DModulo(s,(*this)[i]); } return res; } // invalid types template<> Data_* Data_::ModSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::ModInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::ModSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return NULL; } template<> Data_* Data_::ModSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::ModInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::ModSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> Data_* Data_::ModInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // Pow pow pow pow pow pow pow pow pow pow pow pow pow pow pow pow pow pow // C++ defines pow only for floats and doubles // in basic_op.cpp: // template T pow( const T r, const T l) // { // typedef T TT; // // if( l == 0) return 1; // if( l < 0) return 0; // // const int nBits = sizeof(TT) * 8; // // T arr = r; // T res = 1; // TT mask = 1; // for( SizeT i=0; i Data_* Data_::PowNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { (*res)[0] = pow( (*this)[0], (*right)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); // valarray } //C delete right; return res; } // inverse power of value: left=right ^ left template Data_* Data_::PowInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = pow( (*right)[0], (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*right)[i], (*this)[i]); } return res; } // PowInt and PowIntNew can only be called for GDL_FLOAT and GDL_DOUBLE template Data_* Data_::PowIntNew( BaseGDL* r) { assert( 0); throw GDLException("Internal error: Data_::PowIntNew called.",true,false); return NULL; } // floats power of value with GDL_LONG: left=left ^ right template<> Data_* Data_::PowIntNew( BaseGDL* r) { DLongGDL* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); if( r->StrictScalar()) { Data_* res = new Data_( Dim(), BaseGDL::NOZERO); DLong r0 = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], r0); } return res; } if( StrictScalar()) { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); Ty s0 = (*this)[ 0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[ i] = pow( s0, (*right)[ i]); } return res; } if( nEl <= rEl) { Data_* res = new Data_( Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } else { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } } template<> Data_* Data_::PowIntNew( BaseGDL* r) { DLongGDL* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); if( r->StrictScalar()) { Data_* res = new Data_( Dim(), BaseGDL::NOZERO); DLong r0 = (*right)[0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], r0); } return res; } if( StrictScalar()) { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); Ty s0 = (*this)[ 0]; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[ i] = pow( s0, (*right)[ i]); } return res; } if( nEl <= rEl) { Data_* res = new Data_( Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } else { Data_* res = new Data_( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } } // floats power of value: left=left ^ right template<> Data_* Data_::PowNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = pow( (*this)[0], (*right)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } // floats inverse power of value: left=right ^ left template<> Data_* Data_::PowInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = pow( (*right)[0], (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*right)[i], (*this)[i]); } //C delete right; return res; } // doubles power of value: left=left ^ right template<> Data_* Data_::PowNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = pow( (*this)[0], (*right)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } // doubles inverse power of value: left=right ^ left template<> Data_* Data_::PowInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); if( nEl == 1) { (*res)[0] = pow( (*right)[0], (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*right)[i], (*this)[i]); } //C delete right; return res; } // complex power of value: left=left ^ right // complex is special here template<> Data_* Data_::PowNew( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); assert( r->N_Elements() > 0); if( r->Type() == GDL_FLOAT) { Data_* right=static_cast* >(r); DFloat s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( this->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( this->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); // ULong rEl=right->N_Elements(); // ULong nEl=N_Elements(); Data_* res = NewResult(); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Ty s; if( right->StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( this->Dim(), BaseGDL::NOZERO); //#if (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2) TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } } // complex inverse power of value: left=right ^ left template<> Data_* Data_::PowInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*right)[i], (*this)[i]); } return res; } // double complex power of value: left=left ^ right template<> Data_* Data_::PowNew( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); assert( r->N_Elements() > 0); if( r->Type() == GDL_DOUBLE) { Data_* right=static_cast* >(r); DDouble s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( this->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( this->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); Ty s; if( right->StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( this->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], (*right)[i]); } return res; } } // double complex inverse power of value: left=right ^ left template<> Data_* Data_::PowInvNew( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*right)[i], (*this)[i]); } return res; } // invalid types template<> Data_* Data_::PowNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::PowInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::PowNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::PowInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::PowNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> Data_* Data_::PowInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } // scalar versions template Data_* Data_::PowSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); Data_* res = NewResult(); assert( nEl); Ty s = (*right)[0]; if( nEl == 1) { (*res)[0] = pow( (*this)[0], s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( (*this)[i], s); } //C delete right; return res; } // inverse power of value: left=right ^ left template Data_* Data_::PowInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = pow( s, (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = pow( s, (*this)[i]); } //C delete right; return res; } // complex power of value: left=left ^ right // complex is special here template<> Data_* Data_::PowSNew( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); assert( r->N_Elements() > 0); if( r->Type() == GDL_FLOAT) { Data_* right=static_cast* >(r); DFloat s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) // (must also be consistent with ComplexDbl) if( right->StrictScalar(s)) { Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplex s; if( StrictScalar(s)) { DComplexGDL* res = new DComplexGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEX Data_* right=static_cast(r); Ty s = (*right)[0]; Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); assert( right->N_Elements()); Ty s = (*right)[0]; Data_* res = NewResult(); if( nEl == 1) { (*res)[0] = pow( s, (*this)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowSNew( BaseGDL* r) { SizeT nEl = N_Elements(); assert( nEl > 0); if( r->Type() == GDL_DOUBLE) { Data_* right=static_cast* >(r); assert( right->N_Elements() > 0); DDouble s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) if( right->StrictScalar(s)) { Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_LONG) { Data_* right=static_cast* >(r); assert( right->N_Elements() > 0); DLong s; // note: changes here have to be reflected in POWNCNode::Eval() (dnode.cpp) // (concerning when a new variable is created vs. using this) if( right->StrictScalar(s)) { Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements(); if( nEl < rEl) { DComplexDbl s; if( StrictScalar(s)) { DComplexDblGDL* res = new DComplexDblGDL( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i(r); const Ty s = (*right)[0]; Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowInvSNew( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); Ty s = (*right)[0]; Data_* res = NewResult(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i Data_* Data_::PowSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::PowInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return NULL; } template<> Data_* Data_::PowSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::PowInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return NULL; } template<> Data_* Data_::PowSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } template<> Data_* Data_::PowInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return NULL; } //#include "instantiate_templates.hpp" #endif gdl-0.9.9/src/basic_op_sub.cpp000066400000000000000000000303521340051421000162130ustar00rootroot00000000000000/*************************************************************************** basic_op_sub.cpp - GDL sub (-) operators ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_BASIC_OP_CPP // // header in datatypes.hpp // // //#include "datatypes.hpp" // //#include "dstructgdl.hpp" // //#include "arrayindex.hpp" // // //#include // #include "sigfpehandler.hpp" // // #ifdef _OPENMP // #include // #endif // // #include "typetraits.hpp" // // using namespace std; // Sub // substraction: left=left-right template BaseGDL* Data_::Sub( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); if( nEl == 1) { (*this)[0] -= (*right)[0]; return this; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); mThis -= mRight; return this; #else if( nEl == rEl) dd -= right->dd; else { TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] -= (*right)[i]; }} //C delete right; return this; #endif } // inverse substraction: left=right-left template BaseGDL* Data_::SubInv( BaseGDL* r) { Data_* right=static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); /* if( nEl == rEl) dd = right->dd - dd; else*/ if( nEl == 1) { (*this)[0] = (*right)[0] - (*this)[0]; return this; } #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); Eigen::Map ,Eigen::Aligned> mRight(&(*right)[0], nEl); mThis = mRight - mThis; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = (*right)[i] - (*this)[i]; } //C delete right; return this; #endif } // invalid types template<> BaseGDL* Data_::Sub( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> BaseGDL* Data_::SubInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> BaseGDL* Data_::Sub( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> BaseGDL* Data_::SubInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> BaseGDL* Data_::Sub( BaseGDL* r) { // overload here Data_* self; DSubUD* plusOverload; ProgNodeP callingNode = interpreter->GetRetTree(); if( !Scalar()) { if( r->Type() == GDL_OBJ && r->Scalar()) { self = static_cast( r); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus)); if( plusOverload == NULL) { throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false); } } else { throw GDLException( callingNode, "Cannot apply operation to non-scalar datatype OBJECT.", true, false); } } else { // Scalar() self = static_cast( this); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus)); if( plusOverload == NULL) { if( r->Type() == GDL_OBJ && r->Scalar()) { self = static_cast( r); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus)); if( plusOverload == NULL) { throw GDLException(callingNode,"Cannot apply not overloaded operator to datatype OBJECT.",true, false); } } else { throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false); } } } assert( self->Scalar()); assert( plusOverload != NULL); // hidden SELF is counted as well int nParSub = plusOverload->NPar(); assert( nParSub >= 1); // SELF if( nParSub < 3) // (SELF), LEFT, RIGHT { throw GDLException( callingNode, plusOverload->ObjectName() + ": Incorrect number of arguments.", false, false); } EnvUDT* newEnv; Guard selfGuard; BaseGDL* thisP; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = plusOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { thisP = this; newEnv= new EnvUDT( callingNode, plusOverload, &self); newEnv->SetNextParUnchecked( &thisP); // LEFT parameter, as reference to prevent cleanup in newEnv newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv } else { self = self->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, plusOverload, &self); newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value } // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + plusOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( static_cast(self) != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } return res; } template<> BaseGDL* Data_::SubInv( BaseGDL* r) { if( r->Type() == GDL_OBJ && r->Scalar()) { return r->Sub( this); // for right order of parameters } // overload here Data_* self; DSubUD* plusOverload; ProgNodeP callingNode = interpreter->GetRetTree(); if( !Scalar()) { throw GDLException( callingNode, "Cannot apply operation to non-scalar datatype OBJECT.", true, false); } else { // Scalar() self = static_cast( this); plusOverload = static_cast(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus)); if( plusOverload == NULL) { throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false); } } assert( self->Scalar()); assert( plusOverload != NULL); // hidden SELF is counted as well int nParSub = plusOverload->NPar(); assert( nParSub >= 1); // SELF if( nParSub < 3) // (SELF), LEFT, RIGHT { throw GDLException( callingNode, plusOverload->ObjectName() + ": Incorrect number of arguments.", false, false); } EnvUDT* newEnv; Guard selfGuard; BaseGDL* thisP; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = plusOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { thisP = this; newEnv= new EnvUDT( callingNode, plusOverload, &self); // order different to Add newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv newEnv->SetNextParUnchecked( &thisP); // LEFT parameter, as reference to prevent cleanup in newEnv } else { self = self->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, plusOverload, &self); // order different to Add newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value } // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + plusOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( static_cast(self) != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } return res; } template Data_* Data_::SubS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { (*this)[0] -= (*right)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); // dd -= s; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); mThis -= s; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] -= s; } //C delete right; return this; #endif } // inverse substraction: left=right-left template Data_* Data_::SubInvS( BaseGDL* r) { Data_* right=static_cast(r); ULong nEl=N_Elements(); assert( nEl); if( nEl == 1) { (*this)[0] = (*right)[0] - (*this)[0]; return this; } Ty s = (*right)[0]; // right->Scalar(s); // dd = s - dd; #ifdef USE_EIGEN Eigen::Map ,Eigen::Aligned> mThis(&(*this)[0], nEl); mThis = s - mThis; return this; #else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*this)[i] = s - (*this)[i]; } //C delete right; return this; #endif } // invalid types template<> Data_* Data_::SubS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::SubInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRING.",true,false); return this; } template<> Data_* Data_::SubS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::SubInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype PTR.",true,false); return this; } template<> Data_* Data_::SubS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } template<> Data_* Data_::SubInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype OBJECT.",true,false); return this; } #endif gdl-0.9.9/src/basic_pro.cpp000066400000000000000000002423551340051421000155340ustar00rootroot00000000000000/*************************************************************************** basic_pro.cpp - basic GDL library procedures ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net - UNIT keyword for SPAWN by Greg Huey ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include #include #include #include #ifndef _WIN32 //#include // stregex #include #include #else #include #endif #ifdef _OPENMP #include #endif #include "dinterpreter.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "io.hpp" #include "basic_pro.hpp" #include "semshm.hpp" #include "graphicsdevice.hpp" #ifdef HAVE_EXT_STDIO_FILEBUF_H #include // TODO: is it portable across compilers? #endif #include static bool trace_me(false); namespace lib { using namespace std; DString GetCWD(); // From file.cpp // control !CPU settings void cpu(EnvT* e) { static int resetIx = e->KeywordIx("RESET"); static int restoreIx = e->KeywordIx("RESTORE"); static int max_eltsIx = e->KeywordIx("TPOOL_MAX_ELTS"); static int min_eltsIx = e->KeywordIx("TPOOL_MIN_ELTS"); static int nThreadsIx = e->KeywordIx("TPOOL_NTHREADS"); static int vectorEableIx = e->KeywordIx("VECTOR_ENABLE"); bool reset = e->KeywordSet(resetIx); bool restore = e->KeywordSet(restoreIx); if ((reset) && (restore)) e->Throw("Conflicting keywords (/reset and /restore)."); bool vectorEnable = e->KeywordSet(vectorEableIx); DLong NbCOREs = 1; #ifdef _OPENMP NbCOREs = omp_get_num_procs(); #endif DLong locCpuTPOOL_NTHREADS = CpuTPOOL_NTHREADS; DLong64 locCpuTPOOL_MIN_ELTS = CpuTPOOL_MIN_ELTS; DLong64 locCpuTPOOL_MAX_ELTS = CpuTPOOL_MAX_ELTS; // reading the Tag Index of the variable parts in !CPU DStructGDL* cpu = SysVar::Cpu(); static unsigned NTHREADSTag = cpu->Desc()->TagIndex("TPOOL_NTHREADS"); static unsigned TPOOL_MIN_ELTSTag = cpu->Desc()->TagIndex("TPOOL_MIN_ELTS"); static unsigned TPOOL_MAX_ELTSTag = cpu->Desc()->TagIndex("TPOOL_MAX_ELTS"); if (reset) { locCpuTPOOL_NTHREADS = NbCOREs; locCpuTPOOL_MIN_ELTS = DefaultTPOOL_MIN_ELTS; locCpuTPOOL_MAX_ELTS = DefaultTPOOL_MAX_ELTS; } else if (e->KeywordPresent(restoreIx)) { DStructGDL* restoreCpu = e->GetKWAs(restoreIx); if (restoreCpu->Desc() != cpu->Desc()) e->Throw("RESTORE must be set to an instance with the same struct layout as {!CPU}"); locCpuTPOOL_NTHREADS = (*(static_cast (restoreCpu->GetTag(NTHREADSTag, 0))))[0]; locCpuTPOOL_MIN_ELTS = (*(static_cast (restoreCpu->GetTag(TPOOL_MIN_ELTSTag, 0))))[0]; locCpuTPOOL_MAX_ELTS = (*(static_cast (restoreCpu->GetTag(TPOOL_MAX_ELTSTag, 0))))[0]; } else { if (e->KeywordPresent(nThreadsIx)) { e->AssureLongScalarKW(nThreadsIx, locCpuTPOOL_NTHREADS); } if (e->KeywordPresent(min_eltsIx)) { e->AssureLongScalarKW(min_eltsIx, locCpuTPOOL_MIN_ELTS); } if (e->KeywordPresent(max_eltsIx)) { e->AssureLongScalarKW(max_eltsIx, locCpuTPOOL_MAX_ELTS); } } // update here all together in case of error #ifdef _OPENMP //cout < 0) { CpuTPOOL_NTHREADS = locCpuTPOOL_NTHREADS; } else { CpuTPOOL_NTHREADS = NbCOREs; } if (CpuTPOOL_NTHREADS > NbCOREs) Warning("CPU : Warning: Using more threads (" + i2s(CpuTPOOL_NTHREADS) + ") than the number of CPUs in the system (" + i2s(NbCOREs) + ") will degrade performance."); #else CpuTPOOL_NTHREADS = 1; #endif if (locCpuTPOOL_MIN_ELTS >= 0) CpuTPOOL_MIN_ELTS = locCpuTPOOL_MIN_ELTS; if (locCpuTPOOL_MAX_ELTS >= 0) CpuTPOOL_MAX_ELTS = locCpuTPOOL_MAX_ELTS; // update !CPU system variable (*static_cast (cpu->GetTag(NTHREADSTag, 0)))[0] = CpuTPOOL_NTHREADS; (*static_cast (cpu->GetTag(TPOOL_MIN_ELTSTag, 0)))[0] = CpuTPOOL_MIN_ELTS; (*static_cast (cpu->GetTag(TPOOL_MAX_ELTSTag, 0)))[0] = CpuTPOOL_MAX_ELTS; #ifdef _OPENMP omp_set_num_threads(CpuTPOOL_NTHREADS); #endif } void exitgdl(EnvT* e) { #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) // we manage the ASCII "history" file (located in ~/.gdl/) // we do not manage NOW the number of lines we save, // this should be limited by "history/readline" itself if (historyIntialized) { // Create eventually the ".gdl" path in user $HOME int result, debug = 0; char *homeDir = getenv("HOME"); if( homeDir == NULL) homeDir = getenv("HOMEPATH"); if (homeDir != NULL) { string pathToGDL_history = homeDir; AppendIfNeeded(pathToGDL_history, "/"); pathToGDL_history += ".gdl"; // Create eventially the ".gdl" path in Home #ifdef _WIN32 result = mkdir(pathToGDL_history.c_str()); #else result = mkdir(pathToGDL_history.c_str(), 0700); #endif if (debug) { if (result == 0) cout << "Creation of ~/.gdl PATH " << endl; else cout << "~/.gdl PATH was still here " << endl; } // (over)write the history file in ~/.gdl PATH AppendIfNeeded(pathToGDL_history, "/"); string history_filename = pathToGDL_history + "history"; if (debug) cout << "History file name: " << history_filename << endl; result = write_history(history_filename.c_str()); if (debug) { if (result == 0) cout << "Successfull writing of ~/.gdl/history" << endl; else cout << "Fail to write ~/.gdl/history" << endl; } } } #endif sem_onexit(); BaseGDL* status = e->GetKW(1); if (status == NULL) exit(EXIT_SUCCESS); if (!status->Scalar()) e->Throw("Expression must be a scalar in this context: " + e->GetString(status)); DLongGDL* statusL = static_cast (status->Convert2(GDL_LONG, BaseGDL::COPY)); DLong exit_status; statusL->Scalar(exit_status); exit(exit_status); } void heap_gc(EnvT* e) { static int objIx = e->KeywordIx("OBJ"); static int ptrIx = e->KeywordIx("PTR"); static int verboseIx = e->KeywordIx("VERBOSE"); bool doObj = e->KeywordSet(objIx); bool doPtr = e->KeywordSet(ptrIx); bool verbose = e->KeywordSet(verboseIx); if (!doObj && !doPtr) doObj = doPtr = true; e->HeapGC(doPtr, doObj, verbose); if( GDLInterpreter::HeapSize() == 0 and (GDLInterpreter::ObjHeapSize() == 0) ) GDLInterpreter::ResetHeap(); } void HeapFreeObj(EnvT* env, BaseGDL* var, bool verbose) { if (var == NULL) return; if (var->Type() == GDL_STRUCT) { DStructGDL* varStruct = static_cast (var); DStructDesc* desc = varStruct->Desc(); for (SizeT e = 0; e < varStruct->N_Elements(); ++e) for (SizeT t = 0; t < desc->NTags(); ++t) { BaseGDL* actElementTag = varStruct->GetTag(t, e); HeapFreeObj(env, actElementTag, verbose); } } else if (var->Type() == GDL_PTR) { // descent into pointer DPtrGDL* varPtr = static_cast (var); for (SizeT e = 0; e < varPtr->N_Elements(); ++e) { DPtr actPtrID = (*varPtr)[e]; if( !DInterpreter::PtrValid(actPtrID)) continue; BaseGDL* derefPtr = DInterpreter::GetHeap(actPtrID); HeapFreeObj(env, derefPtr, verbose); } } else if (var->Type() == GDL_OBJ) { DObjGDL* varObj = static_cast (var); for (SizeT e = 0; e < varObj->N_Elements(); ++e) { DObj actID = (*varObj)[e]; if (actID == 0) continue; if (verbose) { BaseGDL* derefObj = DInterpreter::GetObjHeap(actID); help_item(cout, derefObj, DString("", false); } // 2. free object env->ObjCleanup(actID); } } } void HeapFreePtr(BaseGDL* var, bool verbose) { if (var == NULL) return; if (var->Type() == GDL_STRUCT) { DStructGDL* varStruct = static_cast (var); DStructDesc* desc = varStruct->Desc(); for (SizeT e = 0; e < varStruct->N_Elements(); ++e) for (SizeT t = 0; t < desc->NTags(); ++t) { BaseGDL* actElementTag = varStruct->GetTag(t, e); HeapFreePtr(actElementTag, verbose); // recursive call } } else if (var->Type() == GDL_PTR) { // 1. descent into pointer DPtrGDL* varPtr = static_cast (var); for (SizeT e = 0; e < varPtr->N_Elements(); ++e) { DPtr actPtrID = (*varPtr)[e]; //GJ 2016.05.12 Replaced "if (actPtrID == 0)" for a more restrictive condition: if( !DInterpreter::PtrValid(actPtrID)) continue; BaseGDL* derefPtr = DInterpreter::GetHeap(actPtrID); if (verbose) { help_item(cout, derefPtr, DString("", false); } if (derefPtr == NULL) continue; HeapFreePtr(derefPtr, verbose); // recursive call // 2. free pointer DInterpreter::FreeHeap(varPtr); } } } void heap_free(EnvT* e) { static int objIx = e->KeywordIx("OBJ"); static int ptrIx = e->KeywordIx("PTR"); static int verboseIx = e->KeywordIx("VERBOSE"); bool doObj = e->KeywordSet(objIx); bool doPtr = e->KeywordSet(ptrIx); bool verbose = e->KeywordSet(verboseIx); if (!doObj && !doPtr) doObj = doPtr = true; e->NParam(1); BaseGDL* p0 = e->GetParDefined(0); if (doObj) // do first objects as they may in turn free some pointers HeapFreeObj(e, p0, verbose); if (doPtr) HeapFreePtr(p0, verbose); } void ptr_free(EnvT* e) { SizeT nParam = e->NParam(); for (SizeT i = 0; i < nParam; i++) { BaseGDL* p = e->GetPar(i); if (p == NULL) { e->Throw("Pointer type required" " in this context: " + e->GetParString(i)); } if (p->Type() != GDL_PTR) { e->Throw("Pointer type required" " in this context: " + e->GetParString(i)); } DPtrGDL* par = static_cast (e->GetPar(i)); e->FreeHeap(par); } } void obj_destroy(EnvT* e) { StackGuard guard(e->Interpreter()->CallStack()); int n_Param=e->NParam(); if( n_Param == 0) return; BaseGDL*& par=e->GetPar( 0); if( par == NULL or par->Type() != GDL_OBJ) return; DObjGDL* op= static_cast(par); SizeT nEl = op->N_Elements(); for( SizeT i=0; iObjCleanup( (*op)[i]); } void call_procedure(EnvT* e) { int nParam = e->NParam(); if (nParam == 0) e->Throw("No procedure specified."); DString callP; e->AssureScalarPar(0, callP); // this is a procedure name -> convert to UPPERCASE callP = StrUpCase(callP); // first search library procedures int proIx = LibProIx(callP); if (proIx != -1) { // e->PushNewEnv( libProList[ proIx], 1); // make the call // EnvT* newEnv = static_cast(e->Interpreter()->CallStack().back()); EnvT* newEnv = e->NewEnv(libProList[proIx], 1); Guard guard(newEnv); static_cast (newEnv->GetPro())->Pro()(newEnv); } else { proIx = DInterpreter::GetProIx(callP); StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnv = e->PushNewEnvUD(proList[proIx], 1); // make the call // EnvUDT* newEnv = static_cast(e->Interpreter()->CallStack().back()); e->Interpreter()->call_pro(static_cast (newEnv->GetPro())->GetTree()); } } void call_method_procedure(EnvT* e) { int nParam = e->NParam(); if (nParam < 2) e->Throw("Name and object reference must be specified."); DString callP; e->AssureScalarPar(0, callP); // this is a procedure name -> convert to UPPERCASE callP = StrUpCase(callP); DStructGDL* oStruct = e->GetObjectPar(1); DPro* method = oStruct->Desc()->GetPro(callP); if (method == NULL) e->Throw("Method not found: " + callP); StackGuard guard(e->Interpreter()->CallStack()); e->PushNewEnvUD(method, 2, (DObjGDL**) & e->GetPar(1)); // the call e->Interpreter()->call_pro(method->GetTree()); } void get_lun(EnvT* e) { int nParam = e->NParam(1); // not using SetPar later gives a better error message e->AssureGlobalPar(0); // here lun is the GDL lun, not the internal one DLong lun = GetLUN(); if (lun == 0) e->Throw("All available logical units are currently in use."); BaseGDL** retLun = &e->GetPar(0); GDLDelete((*retLun)); // if( *retLun != e->Caller()->Object()) delete (*retLun); *retLun = new DLongGDL(lun); return; } // returns true if lun points to special unit // lun is GDL lun (-2..128) bool check_lun(EnvT* e, DLong lun) { if (lun < -2 || lun > maxLun) e->Throw("File unit is not within allowed range: " + i2s(lun) + "."); return (lun <= 0); } // TODO: handle ON_ERROR, ON_IOERROR, !ERROR_STATE.MSG void open_lun(EnvT* e, fstream::openmode mode) { int nParam = e->NParam(2); DLong lun; static int getlunIx=e->KeywordIx("GET_LUN"); //works because index of GET_LUN is same for all 3 functions using it. bool getlunIsSet=e->KeywordSet(getlunIx); if (getlunIsSet) { // get_lun( e); // not using SetPar later gives a better error message e->AssureGlobalPar(0); // here lun is the GDL lun, not the internal one lun = GetLUN(); if (lun == 0) e->Throw("All available logical units are currently in use."); } else { e->AssureLongScalarPar(0, lun); } bool stdLun = check_lun(e, lun); if (stdLun) e->Throw("Unit already open. Unit: " + i2s(lun)); DString name; // IDL allows here also arrays of length 1 e->AssureScalarPar(1, name); // Change leading "~" to home directory // if (name.substr(0,2) == "~/") // name = getenv("HOME") + name.substr(1,name.size()-1); // AC 2018-mars-22 : at the end, correcting bug 720 WordExp(name); // endian bool swapEndian = false; static int swapIx = e->KeywordIx("SWAP_ENDIAN"); static int swapIfBigIx = e->KeywordIx("SWAP_IF_BIG_ENDIAN"); static int swapIfLittleIx = e->KeywordIx("SWAP_IF_LITTLE_ENDIAN"); if (e->KeywordSet(swapIx)) swapEndian = true; else if (BigEndian()) swapEndian = e->KeywordSet(swapIfBigIx); else swapEndian = e->KeywordSet(swapIfLittleIx); // compress bool compress = false; static int compressIx = e->KeywordIx("COMPRESS"); if (e->KeywordSet(compressIx)) compress = true; // xdr static int xdrIx = e->KeywordIx("XDR"); bool xdr = e->KeywordSet(xdrIx); static int appendIx = e->KeywordIx("APPEND"); // if( e->KeywordSet( appendIx)) mode |= fstream::ate;// fstream::app; // SA: trunc flag for non-existent file is needed in order to comply with // IDL behaviour (creating a file even if /APPEND flag is set) (tracker bug 2103871) if (e->KeywordSet(appendIx)) { if (compress) e->Throw("Keywords APPEND and COMPRESS exclude each other."); // // SA: The manual says that access() "is a potential security hole and should never be used" // but I didn't find any better way to do it. A problem might happen when the following sequence occurs: // * openu/openw is called with the /append flag and the target file does not exist // * access() informs about non-existence -> "trunc" flag is set to be used instead of "ate" // * in the meantime the file is created by some other process // * opening the file truncates it but it shouldn't as the /append flag was used // However, apparently only when "trunc" is set, a previously-non-existent file gets created. // Therefore it seems necessary to check for file existence before, in order to choose // between "ate" and "trunc" flags. // // ensuring trunc when a non-existent file requested (the OPENU,/APPEND case) if (-1 == access(name.c_str(), F_OK)) mode |= fstream::trunc; else { // ensuring no trunc when an existent file requested (the OPENW,/APPEND case) mode &= ~fstream::trunc; // handling /APPEND (both for OPENW,/APPEND and OPENU,/APPEND) mode |= fstream::ate; } } #ifdef _WIN32 mode |= ios::binary; #endif static int f77Ix = e->KeywordIx("F77_UNFORMATTED"); bool f77 = e->KeywordSet(f77Ix); static int delIx = e->KeywordIx("DELETE"); bool deleteKey = e->KeywordSet(delIx); static int errorIx = e->KeywordIx("ERROR"); bool errorKeyword = e->KeywordPresent(errorIx); if (errorKeyword) e->AssureGlobalKW(errorIx); DLong width = defaultStreamWidth; static int widthIx = e->KeywordIx("WIDTH"); BaseGDL* widthKeyword = e->GetKW(widthIx); if (widthKeyword != NULL) { e->AssureLongScalarKW(widthIx, width); } // Assume variable-length VMS file initially // fileUnits[ lun-1].PutVarLenVMS( true); // m_schellens: this is no good. It fails for regular files which by accident fit the // variable-length VMS file criteria (see bug tracker ID: 3028279) // we need something more sophisticated here fileUnits[lun - 1].PutVarLenVMS(false); try { fileUnits[lun - 1].Open(name, mode, swapEndian, deleteKey, xdr, width, f77, compress); if (getlunIsSet) { BaseGDL** retLun = &e->GetPar(0); GDLDelete((*retLun)); *retLun = new DLongGDL(lun); // par 0 contains now the LUN } } //GD: If GDLIOException is not catched here BEFORE GDLException, catch (GDLIOException& ex) { if (getlunIsSet) { fileUnits[lun - 1].Free(); } DString errorMsg = ex.getMessage() + // getMessage gets the non-decorated error message " Unit: " + i2s(lun) + ", File: " + name; //+ fileUnits[lun - 1].Name(); if (!errorKeyword) { throw GDLIOException(ex.ErrorCode(), e->CallingNode(), errorMsg); //go above and be catched } BaseGDL** err = &e->GetKW(errorIx); GDLDelete(*err); // if( *err != e->Caller()->Object()) delete (*err); *err = new DLongGDL(ex.ErrorCode()); return; } catch (GDLException& ex) { if (getlunIsSet) { fileUnits[lun - 1].Free(); } DString errorMsg = ex.getMessage() + // getMessage gets the non-decorated error message " Unit: " + i2s(lun) + ", File: " + name; // + fileUnits[lun - 1].Name(); if (!errorKeyword) e->Throw(errorMsg); // throw GDLIOException(ex.ErrorCode(), e->CallingNode(), errorMsg); BaseGDL** err = &e->GetKW(errorIx); GDLDelete(*err); // if( *err != e->Caller()->Object()) delete (*err); *err = new DLongGDL(ex.ErrorCode()); return; } if (errorKeyword) { BaseGDL** err = &e->GetKW(errorIx); // if( *err != e->Caller()->Object()) delete (*err); GDLDelete((*err)); *err = new DLongGDL(0); } } void openr(EnvT* e) { open_lun(e, fstream::in); } void openw(EnvT* e) { open_lun(e, fstream::in | fstream::out | fstream::trunc); } void openu(EnvT* e) { open_lun(e, fstream::in | fstream::out); } void socket(EnvT* e) { int nParam = e->NParam(3); static int getlunIx=e->KeywordIx("GET_LUN"); bool getlunIsSet=e->KeywordSet(getlunIx); if (getlunIsSet) get_lun(e); // par 0 contains now the LUN DLong lun; e->AssureLongScalarPar(0, lun); bool stdLun = check_lun(e, lun); if (stdLun) e->Throw("Unit already open. Unit: " + i2s(lun)); DString host; // IDL allows here also arrays of length 1 e->AssureScalarPar(1, host); DUInt port; BaseGDL* p2 = e->GetParDefined(2); if (p2->Type() == GDL_STRING) { // look up /etc/services } else if (p2->Type() == GDL_UINT) { e->AssureScalarPar(2, port); } else if (p2->Type() == GDL_INT) { DInt p; e->AssureScalarPar(2, p); port = p; } else if (p2->Type() == GDL_LONG) { DLong p; e->AssureScalarPar(2, p); port = p; } else if (p2->Type() == GDL_ULONG) { DULong p; e->AssureScalarPar(2, p); port = p; } // endian bool swapEndian = false; static int swapIx = e->KeywordIx("SWAP_ENDIAN"); static int swapIfBigIx = e->KeywordIx("SWAP_IF_BIG_ENDIAN"); static int swapIfLittleIx = e->KeywordIx("SWAP_IF_LITTLE_ENDIAN"); if (e->KeywordSet(swapIx)) swapEndian = true; else if (BigEndian()) swapEndian = e->KeywordSet(swapIfBigIx); else swapEndian = e->KeywordSet(swapIfLittleIx); static int connect_timeoutIx = e->KeywordIx("CONNECT_TIMEOUT"); DDouble c_timeout = 0.0; e->AssureDoubleScalarKWIfPresent(connect_timeoutIx, c_timeout); static int read_timeoutIx = e->KeywordIx("READ_TIMEOUT"); DDouble r_timeout = 0.0; e->AssureDoubleScalarKWIfPresent(read_timeoutIx, r_timeout); static int write_timeoutIx = e->KeywordIx("WRITE_TIMEOUT"); DDouble w_timeout = 0.0; e->AssureDoubleScalarKWIfPresent(write_timeoutIx, w_timeout); static int errorIx = e->KeywordIx("ERROR"); bool errorKeyword = e->KeywordPresent(errorIx); if (errorKeyword) e->AssureGlobalKW(errorIx); DLong width = defaultStreamWidth; static int widthIx = e->KeywordIx("WIDTH"); BaseGDL* widthKeyword = e->GetKW(widthIx); if (widthKeyword != NULL) { e->AssureLongScalarKW(widthIx, width); } try { fileUnits[lun - 1].Socket(host, port, swapEndian, c_timeout, r_timeout, c_timeout); } catch (GDLException& ex) { DString errorMsg = ex.toString() + " Unit: " + i2s(lun) + ", File: " + fileUnits[lun - 1].Name(); if (!errorKeyword) e->Throw(errorMsg); BaseGDL** err = &e->GetKW(errorIx); GDLDelete((*err)); // if( *err != e->Caller()->Object()) delete (*err); *err = new DLongGDL(1); return; } if (errorKeyword) { BaseGDL** err = &e->GetKW(errorIx); // if( *err != e->Caller()->Object()) delete (*err); GDLDelete((*err)); *err = new DLongGDL(0); } } // FLUSH based on a patch from Orion Poplawski void flush_lun(EnvT* e) { // within GDL, always lun+1 is used int nParam = e->NParam(); for (int p = 0; p < nParam; p++) { DLong lun; e->AssureLongScalarPar(p, lun); if (lun > maxLun) e->Throw("File unit is not within allowed range: " + i2s(lun) + "."); else if (lun == -2) cerr << flush; else if (lun == -1) cout << flush; else if (lun == 0) ; // do nothing? else fileUnits[lun - 1].Flush(); } } // void close_free_lun(EnvT* e, bool freeLun) { // DLong journalLUN = SysVar::JournalLUN(); // // // within GDL, always lun+1 is used // if (e->KeywordSet("ALL")) //necessary: ALL is not part of free_lun list. // for (int p = maxUserLun; p < maxLun; ++p) { // if ((journalLUN - 1) != p) { // fileUnits[p].Close(); // // if( freeLun) // fileUnits[p].Free(); // } // } // // if (e->KeywordSet("FILE") || e->KeywordSet("ALL")) //necessary, not parts of free_lun list. // for (int p = 0; p < maxUserLun; ++p) { // fileUnits[p].Close(); // // freeing not necessary as get_lun does not use them // //if( freeLun) fileUnits[ p].Free(); // } // // int nParam = e->NParam(); // for (int p = 0; p < nParam; p++) { // DLong lun; // e->AssureLongScalarPar(p, lun); // if (lun > maxLun) // e->Throw("File unit is not within allowed range: " + // i2s(lun) + "."); // if (lun < 1) // e->Throw("File unit does not allow this operation." // " Unit: " + i2s(lun) + "."); // // if (lun == journalLUN) // e->Throw("Reserved file cannot be closed in this manner. Unit: " + // i2s(lun)); // // fileUnits[lun - 1].Close(); // if (freeLun) fileUnits[lun - 1].Free(); // } // } void close_lun(EnvT* e) { DLong journalLUN = SysVar::JournalLUN(); static int ALLIx=e->KeywordIx("ALL"); static int FILEIx=e->KeywordIx("FILE"); // within GDL, always lun+1 is used if (e->KeywordSet(ALLIx)) { for (int p = maxUserLun; p < maxLun; ++p) { if ((journalLUN - 1) != p) { fileUnits[p].Close(); fileUnits[p].Free(); } } } if (e->KeywordSet(FILEIx) || e->KeywordSet(ALLIx)) { for (int p = 0; p < maxUserLun; ++p) { fileUnits[p].Close(); // freeing not necessary as get_lun does not use them //if( freeLun) fileUnits[ p].Free(); } } int nParam = e->NParam(); for (int p = 0; p < nParam; p++) { DLong lun; e->AssureLongScalarPar(p, lun); if (lun > maxLun) e->Throw("File unit is not within allowed range: " + i2s(lun) + "."); if (lun < 1) e->Throw("File unit does not allow this operation." " Unit: " + i2s(lun) + "."); if (lun == journalLUN) e->Throw("Reserved file cannot be closed in this manner. Unit: " + i2s(lun)); fileUnits[lun - 1].Close(); } } void free_lun(EnvT* e) { DLong journalLUN = SysVar::JournalLUN(); // within GDL, always lun+1 is used int nParam = e->NParam(); for (int p = 0; p < nParam; p++) { DLong lun; e->AssureLongScalarPar(p, lun); if (lun > maxLun) e->Throw("File unit is not within allowed range: " + i2s(lun) + "."); if (lun < 1) e->Throw("File unit does not allow this operation." " Unit: " + i2s(lun) + "."); if (lun == journalLUN) e->Throw("Reserved file cannot be closed in this manner. Unit: " + i2s(lun)); fileUnits[lun - 1].Close(); fileUnits[lun - 1].Free(); } } void writeu(EnvT* e) { SizeT nParam = e->NParam(1); DLong lun; e->AssureLongScalarPar(0, lun); ostream* os = NULL; ogzstream* ogzs = NULL; bool f77 = false; bool swapEndian = false; bool compress = false; XDR *xdrs = NULL; bool stdLun = check_lun(e, lun); if (stdLun) { if (lun == 0) e->Throw("Cannot write to stdin. Unit: " + i2s(lun)); os = (lun == -1) ? &cout : &cerr; } else { if (!fileUnits[lun - 1].IsOpen()) e->Throw("File unit is not open: " + i2s(lun)); compress = fileUnits[lun - 1].Compress(); if (!compress) os = &fileUnits[lun - 1].OStream(); else ogzs = &fileUnits[lun - 1].OgzStream(); f77 = fileUnits[lun - 1].F77(); swapEndian = fileUnits[lun - 1].SwapEndian(); xdrs = fileUnits[lun - 1].Xdr(); } if (f77) { if (compress) e->Throw("COMPRESS not supported for F77."); // count record length SizeT nBytesAll = 0; for (SizeT i = 1; i < nParam; i++) { BaseGDL* p = e->GetParDefined(i); if (p->Type() == GDL_STRUCT) nBytesAll += static_cast (p)->NBytesToTransfer(); else nBytesAll += p->NBytes(); } // write record length fileUnits[lun - 1].F77Write(nBytesAll); // write data for (SizeT i = 1; i < nParam; i++) { BaseGDL* p = e->GetPar(i); // defined already checkede p->Write(*os, swapEndian, compress, xdrs); } // write record length fileUnits[lun - 1].F77Write(nBytesAll); } else if (compress) { for (SizeT i = 1; i < nParam; i++) { BaseGDL* p = e->GetParDefined(i); p->Write(*ogzs, swapEndian, compress, xdrs); } } else { for (SizeT i = 1; i < nParam; i++) { BaseGDL* p = e->GetParDefined(i); p->Write(*os, swapEndian, compress, xdrs); } } BaseGDL* p = e->GetParDefined(nParam - 1); SizeT cc = p->Dim(0); BaseGDL** tcKW = NULL; static int tcIx = e->KeywordIx("TRANSFER_COUNT"); if (e->KeywordPresent(tcIx)) { BaseGDL* p = e->GetParDefined(nParam - 1); tcKW = &e->GetKW(tcIx); GDLDelete((*tcKW)); *tcKW = new DLongGDL(p->N_Elements()); } } void readu(EnvT* e) { SizeT nParam = e->NParam(1); DLong lun; e->AssureLongScalarPar(0, lun); istream* is = NULL; igzstream* igzs = NULL; bool f77 = false; bool varlenVMS = false; bool swapEndian = false; bool compress = false; XDR *xdrs = NULL; int sockNum = fileUnits[lun - 1].SockNum(); bool stdLun = check_lun(e, lun); if (stdLun) { if (lun != 0) e->Throw("Cannot read from stdout and stderr." " Unit: " + i2s(lun)); is = &cin; } else if (sockNum != -1) { // Socket Read swapEndian = fileUnits[lun - 1].SwapEndian(); compress = fileUnits[lun - 1].Compress(); string *recvBuf = &fileUnits[lun - 1].RecvBuf(); // Setup recv buffer & string const int MAXRECV = 2048 * 8; char buf[MAXRECV + 1]; // Read socket until finished & store in recv string while (1) { memset(buf, 0, MAXRECV + 1); int status = recv(sockNum, buf, MAXRECV, 0); // cout << "Bytes received: " << status << endl; if (status == 0) break; for (SizeT i = 0; i < status; i++) recvBuf->push_back(buf[i]); } // Get istringstream, write recv string, & assign to istream istringstream *iss = &fileUnits[lun - 1].ISocketStream(); iss->str(*recvBuf); is = iss; } else { compress = fileUnits[lun - 1].Compress(); if (!compress) is = &fileUnits[lun - 1].IStream(); else igzs = &fileUnits[lun - 1].IgzStream(); f77 = fileUnits[lun - 1].F77(); varlenVMS = fileUnits[lun - 1].VarLenVMS(); swapEndian = fileUnits[lun - 1].SwapEndian(); xdrs = fileUnits[lun - 1].Xdr(); } if (f77) { SizeT recordLength = fileUnits[lun - 1].F77ReadStart(); SizeT relPos = 0; for (SizeT i = 1; i < nParam; i++) { BaseGDL* p = e->GetPar(i); if (p == NULL) { e->AssureGlobalPar(i); p = new DFloatGDL(0.0); e->SetPar(i, p); } SizeT nBytes; if (p->Type() == GDL_STRUCT) nBytes = static_cast (p)->NBytesToTransfer(); //p->NBytes does not give sum of length of struct elements, due to alignment.We decompose. else nBytes = p->NBytes(); if ((relPos + nBytes) > recordLength) e->Throw("Attempt to read past end of F77_UNFORMATTED " "file record."); p->Read(*is, swapEndian, compress, xdrs); relPos += nBytes; } // forward to next record if necessary fileUnits[lun - 1].F77ReadEnd(); } else for (SizeT i = 1; i < nParam; i++) { BaseGDL* p = e->GetPar(i); // cout << p->Rank() << endl; // JMG if (p == NULL) { e->AssureGlobalPar(i); p = new DFloatGDL(0.0); e->SetPar(i, p); } if (compress) { p->Read(*igzs, swapEndian, compress, xdrs); } else if (varlenVMS && i == 1) { // Check if VMS variable-length file char hdr[4], tmp; // Read possible record header is->read(hdr, 4); DLong nRec1; memcpy(&nRec1, hdr, 4); // switch endian tmp = hdr[3]; hdr[3] = hdr[0]; hdr[0] = tmp; tmp = hdr[2]; hdr[2] = hdr[1]; hdr[1] = tmp; DLong nRec2; memcpy(&nRec2, hdr, 4); // 2018 April 14 // G.Jung I don't think this works right for stuctures. // I have a method (RealBytes) that computes the actual byte count, // it needs entries across several different files. SizeT nBytes = p->NBytes(); // In variable length VMS files, each record is prefixed // with a count byte that contains the number of bytes // in the record. This step checks whether the length // of the possible header record actually corresponds // to the total length of the desired fields in the // call to READU. // if not VMS v.l.f then backup 4 bytes and tag files // as not variable-length if (nRec1 != nBytes && nRec2 != nBytes) { is->seekg(-4, ios::cur); fileUnits[lun - 1].PutVarLenVMS(false); } p->Read(*is, swapEndian, compress, xdrs); } else p->Read(*is, swapEndian, compress, xdrs); // Socket Read if (sockNum != -1) { int pos = is->tellg(); string *recvBuf = &fileUnits[lun - 1].RecvBuf(); // cout << "pos: " << pos << endl; recvBuf->erase(0, pos); } } BaseGDL* p = e->GetParDefined(nParam - 1); SizeT cc = p->Dim(0); BaseGDL** tcKW = NULL; static int tcIx = e->KeywordIx("TRANSFER_COUNT"); if (e->KeywordPresent(tcIx)) { BaseGDL* p = e->GetParDefined(nParam - 1); tcKW = &e->GetKW(tcIx); GDLDelete((*tcKW)); *tcKW = new DLongGDL(p->N_Elements()); } } void on_error(EnvT* e) { e->OnError(); } void catch_pro(EnvT* e) { // static bool warned = false; // if (!warned) { // Warning("CATCH: feature not implemented yet (FIXME!)."); // warned = true; // } e->Catch(); } void strput(EnvT* e) { SizeT nParam = e->NParam(2); BaseGDL* p0 = e->GetParGlobal(0); if (p0->Type() != GDL_STRING) e->Throw("String expression required in this context: " + e->GetParString(0)); DStringGDL* dest = static_cast (p0); DString source; e->AssureStringScalarPar(1, source); DLong pos = 0; if (nParam == 3) { e->AssureLongScalarPar(2, pos); if (pos < 0) pos = 0; } SizeT nEl = dest->N_Elements(); TRACEOMP(__FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (OMPInt i = 0; i < nEl; ++i) StrPut((*dest)[i], source, pos); } } void retall(EnvT* e) { e->Interpreter()->RetAll(); } void stop(EnvT* e) { if (e->NParam() > 0) print(e); debugMode = DEBUG_STOP; } void defsysv(EnvT* e) { SizeT nParam = e->NParam(1); DString sysVarNameFull; e->AssureStringScalarPar(0, sysVarNameFull); static int existIx = e->KeywordIx("EXIST"); if (e->KeywordPresent(existIx)) { if (sysVarNameFull.length() < 2 || sysVarNameFull[0] != '!') { e->SetKW(existIx, new DLongGDL(0)); } DVar* sysVar = FindInVarList(sysVarList, StrUpCase(sysVarNameFull.substr(1))); if (sysVar == NULL) e->SetKW(existIx, new DLongGDL(0)); else e->SetKW(existIx, new DLongGDL(1)); return; } else if (nParam < 2) e->Throw("Incorrect number of arguments."); // here: nParam >= 2 DLong rdOnly = 0; if (nParam >= 3) e->AssureLongScalarPar(2, rdOnly); if (sysVarNameFull.length() < 2 || sysVarNameFull[0] != '!') e->Throw("Illegal system variable name: " + sysVarNameFull + "."); // strip "!", uppercase DString sysVarName = StrUpCase(sysVarNameFull.substr(1)); DVar* sysVar = FindInVarList(sysVarList, sysVarName); // check if the variable is defined BaseGDL* p1 = e->GetParDefined(1); if (sysVar == NULL) { // define new DVar *newSysVar = new DVar(sysVarName, p1->Dup()); sysVarList.push_back(newSysVar); // rdOnly is only set at the first definition if (rdOnly != 0) sysVarRdOnlyList.push_back(newSysVar); return; } // re-set // make sure type and size are kept BaseGDL* oldVar = sysVar->Data(); BaseGDL* newVar = p1; if (oldVar->Type() != newVar->Type() || oldVar->N_Elements() != newVar->N_Elements()) e->Throw("Conflicting definition for " + sysVarNameFull + "."); // if struct -> assure equal descriptors if (oldVar->Type() == GDL_STRUCT) { DStructGDL *oldStruct = static_cast (oldVar); // types are same -> static cast DStructGDL *newStruct = static_cast (newVar); // note that IDL handles different structs more relaxed // ie. just the structure pattern is compared. if (*oldStruct->Desc() != *newStruct->Desc()) e->Throw("Conflicting definition for " + sysVarNameFull + "."); } DVar* sysVarRdOnly = FindInVarList(sysVarRdOnlyList, sysVarName); if (sysVarRdOnly != NULL) { // rdOnly set and is already rdOnly: do nothing if (rdOnly != 0) return; // else complain e->Throw("Attempt to write to a readonly variable: " + sysVarNameFull + "."); } else { // not read only GDLDelete(oldVar); sysVar->Data() = newVar->Dup(); // only on first definition // if( rdOnly != 0) // sysVarRdOnlyList.push_back( sysVar); } } // note: this implemetation does not honor all keywords void message_pro(EnvT* e) { DStructGDL* errorState = SysVar::Error_State(); static unsigned nameTag = errorState->Desc()->TagIndex("NAME"); static unsigned blockTag = errorState->Desc()->TagIndex("BLOCK"); static unsigned codeTag = errorState->Desc()->TagIndex("CODE"); static unsigned sys_codeTag = errorState->Desc()->TagIndex("SYS_CODE"); static unsigned sys_code_typeTag = errorState->Desc()->TagIndex("SYS_CODE_TYPE"); static unsigned msgTag = errorState->Desc()->TagIndex("MSG"); static unsigned sys_msgTag = errorState->Desc()->TagIndex("SYS_MSG"); static unsigned msg_prefixTag = errorState->Desc()->TagIndex("MSG_PREFIX"); SizeT nParam = e->NParam(); static int continueIx = e->KeywordIx("CONTINUE"); static int infoIx = e->KeywordIx("INFORMATIONAL"); static int ioerrorIx = e->KeywordIx("IOERROR"); static int nonameIx = e->KeywordIx("NONAME"); static int noprefixIx = e->KeywordIx("NOPREFIX"); static int noprintIx = e->KeywordIx("NOPRINT"); static int resetIx = e->KeywordIx("RESET"); static int reissueIx = e->KeywordIx("REISSUE_LAST"); bool continueKW = e->KeywordSet(continueIx); bool info = e->KeywordSet(infoIx); bool ioerror = e->KeywordSet(ioerrorIx); bool noname = e->KeywordSet(nonameIx); bool noprefix = e->KeywordSet(noprefixIx); bool noprint = e->KeywordSet(noprintIx); bool reset = e->KeywordSet(resetIx); bool reissue = e->KeywordSet(reissueIx); if (reset) { (*static_cast (errorState->GetTag(nameTag)))[0] = "IDL_M_SUCCESS"; (*static_cast (errorState->GetTag(blockTag)))[0] = "IDL_MBLK_CORE"; (*static_cast (errorState->GetTag(sys_codeTag)))[0] = 0; (*static_cast (errorState->GetTag(sys_codeTag)))[1] = 0; (*static_cast (errorState->GetTag(sys_code_typeTag)))[0] = ""; (*static_cast (errorState->GetTag(msgTag)))[0] = ""; (*static_cast (errorState->GetTag(sys_msgTag)))[0] = ""; (*static_cast (errorState->GetTag(msg_prefixTag)))[0] = "% "; SysVar::SetErr_String(""); SysVar::SetErrError(0); } if (reissue) { DStructGDL* errorState = SysVar::Error_State(); static unsigned msgTag = errorState->Desc()->TagIndex("MSG"); if (!info || (SysVar::Quiet() == 0)) cout << (*static_cast (errorState->GetTag(msgTag)))[0] << endl; return; } if (nParam == 0) return; DString msg; e->AssureScalarPar(0, msg); if (!noname) { static int levelIx = e->KeywordIx("LEVEL"); if (!e->KeywordPresent(levelIx)) { msg = e->Caller()->GetProName() + ": " + msg; } else { DLong level; e->AssureLongScalarKW(levelIx, level); if (level == 0) { msg = e->Caller()->GetProName() + ": " + msg; } else { // this is a code derived from SimpleDumpStack() above EnvStackT& callStack = e->Interpreter()->CallStack(); long actIx = callStack.size() - 1; if (level > 0) { if (level > actIx) level = actIx; if (level == 0) level++; EnvStackT::pointer_type upEnv = callStack[level - 1]; DString actString = upEnv->GetProName(); msg = actString + ": " + msg; } if (level < 0) { DLong value = actIx + level; if (value < 0) value = 0; EnvStackT::pointer_type upEnv = callStack[value]; DString actString = upEnv->GetProName(); msg = actString + ": " + msg; } } } } if (!info) { (*static_cast (errorState->GetTag(nameTag)))[0] = "IDL_M_USER_ERR"; //unfortunately will be erased by gdlexception below... (*static_cast (errorState->GetTag(codeTag)))[0] = -5; (*static_cast (errorState->GetTag(msgTag)))[0] = msg; SysVar::SetErr_String(msg); SysVar::SetErrError(-5); //IDL_M_USER_ERR is -5 } if (noprint) msg = ""; if (!continueKW && !info) throw GDLException(-5, msg, !noprefix, false); if (!noprint && !noprefix) msg = SysVar::MsgPrefix() + msg; if (!info || (SysVar::Quiet() == 0)) cout << msg << endl; } void byteorderDo(EnvT* e, BaseGDL* pIn, SizeT swapSz, DLong p) { if (pIn->Type() == GDL_STRUCT) { DStructGDL* dS = static_cast (pIn); if (dS->Desc()->ContainsStringPtrObject()) e->Throw("Structs must not contain PTR, OBJECT or STRING tags: " + e->GetParString(p)); for (SizeT t = 0; t < dS->NTags(); ++t) { BaseGDL* par = dS->GetTag(t); if (par->Type() == GDL_STRUCT && par->N_Elements() == 1) { // do tag by tag for scalar struct as memory might not be contigous ( byteorderDo(e, par, swapSz, p); } else { SizeT nBytes = par->NBytes(); if (nBytes % swapSz != 0) e->Throw("Operand's size must be a multiple of swap " "datum size: " + e->GetParString(p)); SizeT nSwap = nBytes / swapSz; char* addr = static_cast (par->DataAddr()); for (SizeT i = 0; i < nSwap; ++i) { for (SizeT s = 0; s < (swapSz / 2); ++s) { char tmp = *(addr + i * swapSz + s); *(addr + i * swapSz + s) = *(addr + i * swapSz + swapSz - 1 - s); *(addr + i * swapSz + swapSz - 1 - s) = tmp; } } } } } else { if (pIn->Type() == GDL_STRING) e->Throw("STRING type not allowed in this context: " + e->GetParString(p)); if (pIn->Type() == GDL_OBJ) e->Throw("Object type not allowed in this context: " + e->GetParString(p)); if (pIn->Type() == GDL_PTR) e->Throw("PTR type not allowed in this context: " + e->GetParString(p)); BaseGDL*& par = pIn; SizeT nBytes = par->NBytes(); if (nBytes % swapSz != 0) e->Throw("Operand's size must be a multiple of swap " "datum size: " + e->GetParString(p)); SizeT nSwap = nBytes / swapSz; char* addr = static_cast (par->DataAddr()); for (SizeT i = 0; i < nSwap; ++i) { for (SizeT s = 0; s < (swapSz / 2); ++s) { char tmp = *(addr + i * swapSz + s); *(addr + i * swapSz + s) = *(addr + i * swapSz + swapSz - 1 - s); *(addr + i * swapSz + swapSz - 1 - s) = tmp; } } } } void byteorder(EnvT* e) { SizeT nParam = e->NParam(1); // static int sswapIx = e->KeywordIx( "SSWAP"); static int lswapIx = e->KeywordIx("LSWAP"); static int l64swapIx = e->KeywordIx("L64SWAP"); static int ifBigIx = e->KeywordIx("SWAP_IF_BIG_ENDIAN"); static int ifLittleIx = e->KeywordIx("SWAP_IF_LITTLE_ENDIAN"); static int ntohlIx = e->KeywordIx("NTOHL"); static int ntohsIx = e->KeywordIx("NTOHS"); static int htonlIx = e->KeywordIx("HTONL"); static int htonsIx = e->KeywordIx("HTONS"); static int ftoxdrIx = e->KeywordIx("FTOXDR"); static int dtoxdrIx = e->KeywordIx("DTOXDR"); static int xdrtofIx = e->KeywordIx("XDRTOF"); static int xdrtodIx = e->KeywordIx("XDRTOD"); bool lswap = e->KeywordSet(lswapIx); bool l64swap = e->KeywordSet(l64swapIx); bool ifBig = e->KeywordSet(ifBigIx); bool ifLittle = e->KeywordSet(ifLittleIx); // to-from network conversion (big-endian) bool ntohl = e->KeywordSet(ntohlIx); bool ntohs = e->KeywordSet(ntohsIx); bool htonl = e->KeywordSet(htonlIx); bool htons = e->KeywordSet(htonsIx); // XDR to-from conversion bool ftoxdr = e->KeywordSet(ftoxdrIx); bool dtoxdr = e->KeywordSet(dtoxdrIx); bool xdrtof = e->KeywordSet(xdrtofIx); bool xdrtod = e->KeywordSet(xdrtodIx); if (ifBig && !BigEndian()) return; if (ifLittle && BigEndian()) return; if (BigEndian() && (ntohl || ntohs || htonl || htons)) return; for (DLong p = nParam - 1; p >= 0; --p) { BaseGDL* par = e->GetParDefined(p); if (!e->GlobalPar(p)) e->Throw("Expression must be named variable in this context: " + e->GetParString(p)); SizeT swapSz = 2; if (l64swap || dtoxdr || xdrtod) swapSz = 8; else if (lswap || ntohl || htonl || ftoxdr || xdrtof) swapSz = 4; byteorderDo(e, par, swapSz, p); } } void setenv_pro(EnvT* e) { SizeT nParam = e->NParam(); DStringGDL* name = e->GetParAs(0); SizeT nEnv = name->N_Elements(); for (SizeT i = 0; i < nEnv; ++i) { DString strEnv = (*name)[i]; long len = strEnv.length(); long pos = strEnv.find_first_of("=", 0); if (pos == string::npos) continue; DString strArg = strEnv.substr(pos + 1, len - pos - 1); strEnv = strEnv.substr(0, pos); // putenv() is POSIX unlike setenv() #if defined(__hpux__) || defined(_WIN32) int ret = putenv((strEnv + "=" + strArg).c_str()); #else int ret = setenv(strEnv.c_str(), strArg.c_str(), 1); #endif } } void struct_assign_pro(EnvT* e) { SizeT nParam = e->NParam(2); DStructGDL* source = e->GetParAs(0); DStructGDL* dest = e->GetParAs(1); static int nozeroIx = e->KeywordIx("NOZERO"); bool nozero = e->KeywordSet(nozeroIx); static int verboseIx = e->KeywordIx("VERBOSE"); bool verbose = e->KeywordSet(verboseIx); string sourceName = (*source).Desc()->Name(); SizeT nTags = 0; // array of struct SizeT nElements = source->N_Elements(); SizeT nDestElements = dest->N_Elements(); if (nElements > nDestElements) nElements = nDestElements; // zero out the destination if (!nozero) (*dest).Clear(); nTags = (*source).Desc()->NTags(); // copy the stuff for (int t = 0; t < nTags; ++t) { string sourceTagName = (*source).Desc()->TagName(t); int ix = (*dest).Desc()->TagIndex(sourceTagName); if (ix >= 0) { SizeT nTagElements = source->GetTag(t)->N_Elements(); SizeT nTagDestElements = dest->GetTag(ix)->N_Elements(); if (verbose) { if (nTagElements > nTagDestElements) Warning("STRUCT_ASSIGN: " + sourceName + " tag " + sourceTagName + " is longer than destination. " "The end will be clipped."); else if (nTagElements < nTagDestElements) Warning("STRUCT_ASSIGN: " + sourceName + " tag " + sourceTagName + " is shorter than destination. " "The end will be zero filled."); } if (nTagElements > nTagDestElements) nTagElements = nTagDestElements; for (SizeT a = 0; a < nElements; ++a) dest->GetTag(ix, a)->Assign(source->GetTag(t, a), nTagElements); } else if (verbose) Warning("STRUCT_ASSIGN: Destination lacks " + sourceName + " tag " + sourceTagName + ". Not copied."); } } #ifdef _WIN32 #define BUFSIZE 1024 void ReadPipeToDString(HANDLE g_Rd, char *buf, int *pos, vector *s_str) { CHAR chbuf[BUFSIZE]; CHAR a_chr; DWORD dwRead; BOOL bSuccess = FALSE; int len = 0; int nlines = 0; int debug = 0; int ptr = *pos; if (debug) std::printf(" RPTD: for(;;) { "); for (;;) { if (debug) std::printf(" ReadFile .. "); bSuccess = ReadFile(g_Rd, chbuf, BUFSIZE, &dwRead, NULL); if (!bSuccess || dwRead == 0) break; if (debug) std::printf(" dwRead, pos= %d %d ", dwRead, ptr); len = 0; while (dwRead > 0) { a_chr = chbuf[len++]; dwRead--; if (a_chr == '\r') a_chr = '\0'; if (a_chr == '\n') { buf[ptr] = 0; ptr = 0; nlines++; // if(debug) std::printf(" %d:%s",dwRead,buf); s_str->push_back(DString(buf)); } else buf[ptr++] = a_chr; if (ptr >= BUFSIZE - 1) { buf[BUFSIZE - 1] = 0; ptr = 0; s_str->push_back(DString(buf)); } } } if (debug) { if (bSuccess) std::printf(" bSuccess=T #lines: %d ", nlines); else std::printf(" bSuccess=F #lines: %d ", nlines); std::printf(" pos= %d }\n", ptr); } *pos = ptr; } static DWORD launch_cmd(BOOL hide, BOOL nowait, const char * cmd, const char * title = NULL, DWORD *pid = NULL, vector *ds_outs = NULL, vector *ds_errs = NULL) { DWORD status; CHAR outbuf[BUFSIZE]; CHAR errbuf[BUFSIZE]; STARTUPINFOW si = {0,}; PROCESS_INFORMATION pi = {0,}; WCHAR w_cmd[1000]; MultiByteToWideChar(CP_UTF8, 0, cmd, -1, w_cmd, 1000); WCHAR w_title[100]; if( title != NULL) MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, 100); WCHAR w_cwd[MAX_PATH]; DString cwd = lib::GetCWD(); MultiByteToWideChar(CP_UTF8, 0, cwd.c_str(), -1, w_cwd, MAX_PATH); SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; HANDLE g_hChildStd_OUT_Rd = NULL; HANDLE g_hChildStd_OUT_Wr = NULL; HANDLE g_hChildStd_ERR_Rd = NULL; HANDLE g_hChildStd_ERR_Wr = NULL; si.cb = sizeof (si); if (title == NULL) si.lpTitle = (wchar_t *) L"GDL spawned process"; else si.lpTitle = w_title; int debug = 0; if (hide) { si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWMINNOACTIVE; } if (ds_outs != NULL) { if (debug) std::printf(" CreatePipe stdout: "); CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0); si.hStdOutput = g_hChildStd_OUT_Wr; // Ensure the read handle to the pipe for STDOUT is not inherited. SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0); if (ds_errs != NULL) { if (debug) std::printf(" CreatePipe stderr: "); CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0); si.hStdError = g_hChildStd_ERR_Wr; SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0); } si.dwFlags |= STARTF_USESTDHANDLES; if (debug) std::printf(" CreateProcess: "); CreateProcessW(NULL, w_cmd, NULL, NULL, TRUE, 0, NULL, w_cwd, // start from wherever we happen to be &si, &pi); if (pid != NULL) *pid = pi.dwProcessId; DWORD progress; int poserr = 0; int posout = 0; if (ds_errs != NULL) CloseHandle(g_hChildStd_ERR_Wr); CloseHandle(g_hChildStd_OUT_Wr); do { Sleep(10); // if (ds_errs != NULL) ReadPipeToDString(g_hChildStd_ERR_Rd,errbuf,&poserr,ds_errs); if (ds_outs != NULL) ReadPipeToDString(g_hChildStd_OUT_Rd, outbuf, &posout, ds_outs); if (debug) std::printf(" Wait 1 sec: "); if (debug) Sleep(1000); progress = WaitForSingleObject(pi.hProcess, 0); } while (progress == WAIT_TIMEOUT); GetExitCodeProcess(pi.hProcess, &status); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (progress == WAIT_OBJECT_0) { ReadPipeToDString(g_hChildStd_OUT_Rd, outbuf, &posout, ds_outs); if (posout > 0) { outbuf[BUFSIZE - 1] = 0; posout++; if (posout < BUFSIZE) outbuf[posout] = 0; ds_outs->push_back(DString(outbuf)); } CloseHandle(g_hChildStd_OUT_Rd); if (ds_errs != NULL) { ReadPipeToDString(g_hChildStd_ERR_Rd, errbuf, &poserr, ds_errs); if (poserr > 0) { errbuf[BUFSIZE - 1] = 0; poserr++; if (poserr < BUFSIZE) errbuf[poserr] = 0; ds_errs->push_back(DString(errbuf)); } CloseHandle(g_hChildStd_ERR_Rd); } } else std::printf(" error from CreateProcess: progress = 0x%x \n", progress); } else { CreateProcessW(NULL, w_cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, w_cwd, // start from wherever we happen to be &si, &pi); if (pid != NULL) *pid = pi.dwProcessId; if (!nowait) WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &status); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } return status; } void spawn_pro(EnvT* e) { SizeT nParam = e->NParam(); static int countIx = e->KeywordIx("COUNT"); bool countKeyword = e->KeywordPresent(countIx); if (countKeyword) e->AssureGlobalKW(countIx); static int pidIx = e->KeywordIx("PID"); bool pidKeyword = e->KeywordPresent(pidIx); if (pidKeyword) e->AssureGlobalKW(pidIx); static int waitIx = e->KeywordIx("NOWAIT"); bool nowaitKeyword = e->KeywordPresent(waitIx); static int exit_statusIx = e->KeywordIx("EXIT_STATUS"); bool exit_statusKeyword = e->KeywordPresent(exit_statusIx); if (exit_statusKeyword) e->AssureGlobalKW(exit_statusIx); static int noshellIx = e->KeywordIx("NOSHELL"); bool noshellKeyword = e->KeywordSet(noshellIx); static int hideIx = e->KeywordIx("HIDE"); bool hideKeyword = e->KeywordSet(hideIx); static int unitIx = e->KeywordIx("UNIT"); bool unitKeyword = e->KeywordPresent(unitIx); if (unitKeyword) e->AssureGlobalKW(unitIx); if (unitKeyword) { e->Throw("UNIT keyword is not implemented yet!"); /* if (exit_statusKeyword) { Warning("SPAWN: specifying EXIT_STATUS with UNIT keyword has no meaning (assigning zero)"); e->SetKW(exit_statusIx, new DLongGDL(0)); } if (countKeyword) { Warning("SPAWN: specifying COUNT with UNIT keyword has no meaning (assigning zero)"); e->SetKW(countIx, new DLongGDL(0)); } if (nParam != 1) e->Throw("Invalid use of the UNIT keyword (only one argument allowed when using UNIT)."); */ } if (nParam == 0) { DWORD status = launch_cmd(hideKeyword, nowaitKeyword, "cmd", " (GDL-Spawned) Command Prompt"); if (countKeyword) e->SetKW(countIx, new DLongGDL(0)); if (exit_statusKeyword) e->SetKW(exit_statusIx, new DLongGDL(status)); return; } DStringGDL* command = e->GetParAs(0); DString cmd = (*command)[0]; const int bufSize = 1024; char buf[bufSize]; if (nParam > 1) e->AssureGlobalPar(1); if (nParam > 2) e->AssureGlobalPar(2); DString ds_cmd; if (noshellKeyword) ds_cmd = cmd; else ds_cmd = "cmd /c " + cmd; vector ds_outs; vector ds_errs; int status; DWORD pid; if (nParam == 1) status = launch_cmd(hideKeyword, nowaitKeyword, ds_cmd.c_str(), NULL, &pid); else if (nParam == 2) { status = launch_cmd(hideKeyword, nowaitKeyword, ds_cmd.c_str(), NULL, &pid, &ds_outs); } else if (nParam == 3) { status = launch_cmd(hideKeyword, nowaitKeyword, ds_cmd.c_str(), NULL, &pid, &ds_outs, &ds_errs); } if (pidKeyword) e->SetKW(pidIx, new DLongGDL(pid)); if (exit_statusKeyword) e->SetKW(exit_statusIx, new DLongGDL(status)); SizeT nLines = 0; if (nParam > 1) { DStringGDL* result; nLines = ds_outs.size(); if (nLines == 0) result = new DStringGDL(""); else { result = new DStringGDL(dimension(nLines), BaseGDL::NOZERO); for (SizeT l = 0; l < nLines; ++l) (*result)[l] = ds_outs[l]; } e->SetPar(1, result); } if (countKeyword) e->SetKW(countIx, new DLongGDL(nLines)); if (nParam > 2) { DStringGDL* errResult; SizeT nErrLines = ds_errs.size(); if (nErrLines == 0) errResult = new DStringGDL(""); else { errResult = new DStringGDL(dimension(nErrLines), BaseGDL::NOZERO); for (SizeT l = 0; l < nErrLines; ++l) (*errResult)[l] = ds_errs[l]; } e->SetPar(2, errResult); } } #else // helper function for spawn_pro static void child_sighandler(int x) { pid_t pid; while ((pid = waitpid(-1, NULL, WNOHANG)) > 0); } void spawn_pro(EnvT* e) { SizeT nParam = e->NParam(); static int countIx = e->KeywordIx("COUNT"); bool countKeyword = e->KeywordPresent(countIx); if (countKeyword) e->AssureGlobalKW(countIx); static int pidIx = e->KeywordIx("PID"); bool pidKeyword = e->KeywordPresent(pidIx); if (pidKeyword) e->AssureGlobalKW(pidIx); static int exit_statusIx = e->KeywordIx("EXIT_STATUS"); bool exit_statusKeyword = e->KeywordPresent(exit_statusIx); if (exit_statusKeyword) e->AssureGlobalKW(exit_statusIx); static int shIx = e->KeywordIx("SH"); bool shKeyword = e->KeywordSet(shIx); static int noshellIx = e->KeywordIx("NOSHELL"); bool noshellKeyword = e->KeywordSet(noshellIx); static int unitIx = e->KeywordIx("UNIT"); bool unitKeyword = e->KeywordPresent(unitIx); if (unitKeyword) e->AssureGlobalKW(unitIx); if (unitKeyword) { if (exit_statusKeyword) { Warning("SPAWN: specifying EXIT_STATUS with UNIT keyword has no meaning (assigning zero)"); e->SetKW(exit_statusIx, new DLongGDL(0)); } if (countKeyword) { Warning("SPAWN: specifying COUNT with UNIT keyword has no meaning (assigning zero)"); e->SetKW(countIx, new DLongGDL(0)); } if (nParam != 1) e->Throw("Invalid use of the UNIT keyword (only one argument allowed when using UNIT)."); } string shellCmd = "/bin/sh"; // must be there if POSIX if (!shKeyword) { char* shellEnv = getenv("SHELL"); if (shellEnv == NULL) shellEnv = getenv("COMSPEC"); if (shellEnv == NULL) e->Throw("Error spawning child process: \n" "Environment variable SHELL | COMSPEC not set."); shellCmd = shellEnv; } if (nParam == 0) { int status = system(shellCmd.c_str()); status >>= 8; if (countKeyword) e->SetKW(countIx, new DLongGDL(0)); if (exit_statusKeyword) e->SetKW(exit_statusIx, new DLongGDL(status)); return; } // added on occasion of the UNIT kw patch if (unitKeyword) signal(SIGCHLD, child_sighandler); DStringGDL* command = e->GetParAs(0); DString cmd = (*command)[0]; const int bufSize = 1024; char buf[bufSize]; if (nParam > 1) e->AssureGlobalPar(1); if (nParam > 2) e->AssureGlobalPar(2); int coutP[2]; if (nParam > 1 || unitKeyword) { if (pipe(coutP)) return; } int cerrP[2]; if (nParam > 2 && !unitKeyword && pipe(cerrP)) return; pid_t pid = fork(); // *** fork if (pid == -1) // error in fork { close(coutP[0]); close(coutP[1]); if (nParam > 2 && !unitKeyword) { close(cerrP[0]); close(cerrP[1]); } return; } if (pid == 0) // we are child { if (unitKeyword) { dup2(coutP[1], 1); // cout dup2(coutP[1], 2); // cout close(coutP[0]); close(coutP[1]); } else { if (nParam > 1) dup2(coutP[1], 1); // cout if (nParam > 2) dup2(cerrP[1], 2); // cerr if (nParam > 1) { close(coutP[0]); close(coutP[1]); } if (nParam > 2) { close(cerrP[0]); close(cerrP[1]); } } if (noshellKeyword) { SizeT nArg = command->N_Elements(); char** argv = new char*[nArg + 1]; argv[nArg] = NULL; for (SizeT i = 0; i < nArg; ++i) argv[i] = const_cast ((*command)[i].c_str()); execvp(cmd.c_str(), argv); delete[] argv; // only executes if exec fails } else execl(shellCmd.c_str(), shellCmd.c_str(), "-c", cmd.c_str(), (char *) NULL); Warning("SPAWN: Error managing child process."); _exit(1); // error in exec } else // we are parent { if (pidKeyword) e->SetKW(pidIx, new DLongGDL(pid)); if (nParam > 1 || unitKeyword) close(coutP[1]); if (nParam > 2 && !unitKeyword) close(cerrP[1]); if (unitKeyword) { #ifdef HAVE_EXT_STDIO_FILEBUF_H // UNIT kw code based on the patch by Greg Huey: Warning("Warning: UNIT keyword to SPAWN may not yet be fully implemented (proceeding)"); // This is just code stolen from void get_lun( EnvT* e) // here lun is the GDL lun, not the internal one DLong unit_lun = GetLUN(); if (unit_lun == 0) e->Throw("SPAWN: Failed to get new LUN: GetLUN says: All available logical units are currently in use."); FILE *coutF; coutF = fdopen(coutP[0], "r"); if (coutF == NULL) close(coutP[0]); e->SetKW(unitIx, new DLongGDL(unit_lun)); bool stdLun = check_lun(e, unit_lun); if (stdLun) e->Throw("SPAWN: Failed to open new LUN: Unit already open. Unit: " + i2s(unit_lun)); fileUnits[unit_lun - 1].PutVarLenVMS(false); // Here we invoke the black arts of converting from a C FILE*fd to an fstream object __gnu_cxx::stdio_filebuf *frb_p; frb_p = new __gnu_cxx::stdio_filebuf(coutF, std::ios_base::in); fileUnits[unit_lun - 1].Close(); fileUnits[unit_lun - 1].Open("/dev/zero", std::ios_base::in, 0, 0, 0, 0, 0, 0); basic_streambuf *bsrb_old_p; bsrb_old_p = fileUnits[unit_lun - 1].get_stream_readbuf_bsrb(); fileUnits[unit_lun - 1].set_stream_readbuf_bsrb_from_frb(frb_p); fileUnits[unit_lun - 1].set_readbuf_frb_destroy_on_close(frb_p); fileUnits[unit_lun - 1].set_readbuf_bsrb_destroy_on_close(bsrb_old_p); fileUnits[unit_lun - 1].set_fd_close_on_close(coutP[0]); #else e->Throw("UNIT kw. relies on GNU extensions to the std C++ library (that were not availble during compilation?)"); #endif } else { FILE *coutF, *cerrF; if (nParam > 1) { coutF = fdopen(coutP[0], "r"); if (coutF == NULL) close(coutP[0]); } if (nParam > 2) { cerrF = fdopen(cerrP[0], "r"); if (cerrF == NULL) close(cerrP[0]); } vector outStr; vector errStr; // read cout if (nParam > 1 && coutF != NULL) { while (fgets(buf, bufSize, coutF) != NULL) { SizeT len = strlen(buf); if (len != 0 && buf[len - 1] == '\n') buf[len - 1] = 0; outStr.push_back(DString(buf)); } fclose(coutF); } // read cerr if (nParam > 2 && cerrF != NULL) { while (fgets(buf, bufSize, cerrF) != NULL) { SizeT len = strlen(buf); if (len != 0 && buf[len - 1] == '\n') buf[len - 1] = 0; errStr.push_back(DString(buf)); } fclose(cerrF); } // wait until child terminates int status; pid_t wpid = wait(&status); if (exit_statusKeyword) e->SetKW(exit_statusIx, new DLongGDL(status >> 8)); SizeT nLines = 0; if (nParam > 1) { DStringGDL* result; nLines = outStr.size(); if (nLines == 0) result = new DStringGDL(""); else { result = new DStringGDL(dimension(nLines), BaseGDL::NOZERO); for (SizeT l = 0; l < nLines; ++l) (*result)[l] = outStr[l]; } e->SetPar(1, result); } if (countKeyword) e->SetKW(countIx, new DLongGDL(nLines)); if (nParam > 2) { DStringGDL* errResult; SizeT nErrLines = errStr.size(); if (nErrLines == 0) errResult = new DStringGDL(""); else { errResult = new DStringGDL(dimension(nErrLines), BaseGDL::NOZERO); for (SizeT l = 0; l < nErrLines; ++l) (*errResult)[l] = errStr[l]; } e->SetPar(2, errResult); } } } } #endif void replicate_inplace_pro(EnvT* e) { SizeT nParam = e->NParam(2); if (nParam % 2) e->Throw("Incorrect number of arguments."); BaseGDL* p0 = e->GetParDefined(0); if (!e->GlobalPar(0)) e->Throw("Expression must be named variable in this context: " + e->GetParString(0)); BaseGDL* p1 = e->GetParDefined(1); if (!p1->Scalar()) e->Throw("Expression must be a scalar in this context: " + e->GetParString(1)); p1 = p1->Convert2(p0->Type(), BaseGDL::COPY); if (nParam == 2) { p0->AssignAt(p1); return; } else { BaseGDL* p2 = e->GetNumericParDefined(2); if (!p2->StrictScalar()) e->Throw("Expression must be a scalar in this context: " + e->GetParString(2)); SizeT d1; int ret = p2->Scalar2Index(d1); if (d1 < 1 || d1 > p0->Rank()) e->Throw("D1 (3rd) argument is out of range: " + e->GetParString(2)); // BaseGDL* p3 = e->GetNumericParDefined( 3); DLongGDL* p3 = e->GetParAs< DLongGDL>(3); if (p3->N_Elements() != p0->Rank()) e->Throw("Loc1 (4th) argument must have the same number of " "elements as the dimensions of the X (1st) argument: " + e->GetParString(3)); SizeT d2 = 0; BaseGDL* p4; BaseGDL* p5; if (nParam > 4) { p4 = e->GetNumericParDefined(4); if (!p4->StrictScalar()) e->Throw("Expression must be a scalar in this context: " + e->GetParString(4)); ret = p4->Scalar2Index(d2); if (d2 < 1 || d2 > p0->Rank()) e->Throw("D5 (5th) argument is out of range: " + e->GetParString(4)); p5 = e->GetNumericParDefined(5); } // ArrayIndexVectorT* ixList = new ArrayIndexVectorT(); // Guard< ArrayIndexVectorT> ixList_guard( ixList); ArrayIndexVectorT ixList; // BaseGDL* loc1 = p3->Dup(); // loc1->SetDim (dimension( loc1->N_Elements())); // ixList->reserve( p3->N_Elements()); for (size_t i = 0; i < p3->N_Elements(); i++) if ((i + 1) == d1) ixList.push_back(new ArrayIndexAll()); else if ((i + 1) == d2) ixList.push_back(new CArrayIndexIndexed(p5, true)); else ixList.push_back(new CArrayIndexScalar((*p3)[i])); //p3->NewIx(i))); ArrayIndexListT* ixL; MakeArrayIndex(&ixList, &ixL); Guard< ArrayIndexListT> ixL_guard(ixL); ixL->AssignAt(p0, p1); return; } } void resolve_routine(EnvT* e) { // AC 11 Sept. 2014 //Warning("This code is not doing what it should."); //Warning("and keywords are not managed ..."); //Warning("If you need this code, please ask or contribute !"); static int eitherIx = e->KeywordIx("EITHER"); bool eitherKeyword = e->KeywordSet(eitherIx); static int is_functionIx = e->KeywordIx("IS_FUNCTION"); bool isfunctionKeyword = e->KeywordSet(is_functionIx); static int no_recompileIx = e->KeywordIx("NO_RECOMPILE"); bool norecompileKeyword = e->KeywordSet(no_recompileIx); static int quietIx = e->KeywordIx("QUIET"); bool quiet = e->KeywordSet(quietIx); static int cffIx = e->KeywordIx("COMPILE_FULL_FILE"); bool cff = e->KeywordSet(cffIx); BaseGDL* p0 = e->GetParDefined(0); if (p0->Type() != GDL_STRING) e->Throw("Expression must be a string in this context: " + e->GetParString(0)); DStringGDL* p0S = static_cast (p0); static StrArr openFiles; SizeT nEl = p0S->N_Elements(); for (int i = 0; i < nEl; ++i) { DString pro = (*p0S)[i]; string proFile = StrLowCase(pro); AppendIfNeeded(proFile, ".pro"); bool found = CompleteFileName(proFile); if (!found ) { if (!quiet) e->Throw("Not found: " + proFile); else return; } // file already opened? bool open = false; for (StrArr::iterator j = openFiles.begin(); j != openFiles.end(); ++j) { if (proFile == *j) { open = true; break; } } if (open) continue; //routine already compiled? NATCHKEBIA Ilia 24.06.2015 bool exists = false; for (ProListT::iterator i = proList.begin(); i != proList.end(); ++i) { if (StrUpCase(proFile).find((*i)->ObjectName()) != std::string::npos) { //cout << "Routine is compiled,so won't recompile " << (*i)->ObjectName() < guard(openFiles); // append file to list openFiles.push_back(proFile); bool success = GDLInterpreter::CompileFile(proFile,cff?StrUpCase(pro):""); // this might trigger recursion //is func NATCHKEBIA Ilia 25.06.2015 bool isFunc = false; for (FunListT::iterator i = funList.begin(); i != funList.end(); ++i) { if (StrUpCase(proFile).find((*i)->ObjectName()) != std::string::npos) { //cout << "exists function " << (*i)->ObjectName() <Throw("Attempt to call undefined : " + proFile); if (success) { // Message("RESOLVE_ROUTINE: Compiled file: " + proFile); } else if (!quiet) e->Throw("Failed to compiled file: " + proFile); //please check this is the good behaviour } } void caldat(EnvT* e) { /* * SA: based on the following codes: * - cal_date() function from the NOVAS-C library (novas.c) * (U.S. Naval Observatory Vector Astrometry Subroutines) * http://aa.usno.navy.mil/software/novas/novas_c/novasc_info.php * - ln_get_date() function from the libnova library (src/julian_day.c) * (by Liam Girdwood and Petr Kubanek) http://libnova.sourceforge.net/ */ // checking input; exiting if nothing to do SizeT nParam = e->NParam(1); if (nParam == 1) return; DDoubleGDL* p0 = e->GetParAs(0); // checking output (if present and global); exiting if nothing to do bool global[6]; { short int sum = 0; for (SizeT i = 0; i < 6; i++) sum += global[i] = e->GlobalPar(i + 1); if (sum == 0) return; } // checking if all Julian values fall within the accepted range SizeT nEl = p0->N_Elements(); for (SizeT i = 0; i < nEl; i++) if ((*p0)[i] < -1095 || (*p0)[i] > 1827933925) e->Throw("Value of Julian date (" + i2s((*p0)[i]) + ") is out of allowed range."); // preparing output (loop order important when all parameters point the same variable) //BaseGDL** ret[nParam - 1]; BaseGDL*** ret; ret = (BaseGDL***) malloc((nParam - 1) * sizeof (BaseGDL**)); GDLGuard retGuard(ret, free); for (int i = nParam - 2; i >= 0; i--) { if (global[i]) { ret[i] = &e->GetPar(i + 1); // global parameter: undefined or different type/size -> creating if (*ret[i] == NULL || (*ret[i])->Type() != (i < 5 ? GDL_LONG : GDL_DOUBLE) || (*ret[i])->N_Elements() != nEl) { // gratutitous braces // not catching exceptions from SetPar as globality was ensured before if (i < 5) { // handling repeated parameters case if (nParam == 7 && *ret[i] == *ret[5]) global[i] = false; else e->SetPar(i + 1, new DLongGDL(p0->Dim())); } else e->SetPar(i + 1, new DDoubleGDL(p0->Dim())); } // global parameter that has correct size but different shape -> reforming else if ((*ret[i])->Rank() != p0->Rank()) (*ret[i])->SetDim(p0->Dim()); } } // loop over input elements for (SizeT i = 0; i < nEl; i++) { DLong iMonth, iDay, iYear, iHour, iMinute, dow, icap; DDouble Second; if (!j2ymdhms( (*p0)[i], iMonth, iDay, iYear, iHour, iMinute, Second, dow, icap )) throw GDLException("Value of Julian date is out of allowed range."); if (global[1 - 1]) (*static_cast (*ret[1 - 1]))[i] = iMonth+1; // days if (global[2 - 1]) (*static_cast (*ret[2 - 1]))[i] = iDay; // years if (global[3 - 1]) (*static_cast (*ret[3 - 1]))[i] = iYear; if (!(global[4 - 1] || global[5 - 1] || global[6 - 1])) continue; // hours if (global[4 - 1]) (*static_cast (*ret[4 - 1]))[i] = iHour; // minutes if (global[5 - 1]) (*static_cast (*ret[5 - 1]))[i] = iMinute; // seconds if (global[6 - 1]) (*static_cast (*ret[6 - 1]))[i] = Second; } // now guarded. s. a. // free((void *)ret); } BaseGDL* julday(EnvT* e) { if ((e->NParam() < 3 || e->NParam() > 6)) { e->Throw("Incorrect number of arguments."); } DLongGDL *Month, *Day, *Year, *Hour, *Minute; DDoubleGDL* Second; DDouble jd; DLong h = 12; DLong m = 0; DDouble s = 0.0; SizeT nM, nD, nY, nH, nMi, nS, finalN = 1; dimension finalDim; //behaviour: minimum set of dimensions of arrays. singletons expanded to dimension, //keep array trace. SizeT nEl, maxEl = 1, minEl; for (int i = 0; i < e->NParam(); ++i) { nEl = e->GetPar(i)->N_Elements(); if ((nEl > 1) && (nEl > maxEl)) { maxEl = nEl; finalN = maxEl; finalDim = e->GetPar(i)->Dim(); } } //first max - but we need first min: minEl = maxEl; for (int i = 0; i < e->NParam(); ++i) { nEl = e->GetPar(i)->N_Elements(); if ((nEl > 1) && (nEl < minEl)) { minEl = nEl; finalN = minEl; finalDim = e->GetPar(i)->Dim(); } } //min not singleton Month = e->GetParAs(0); nM = Month->N_Elements(); Day = e->GetParAs(1); nD = Day->N_Elements(); Year = e->GetParAs(2); nY = Year->N_Elements(); if (e->NParam() == 3) { DLongGDL *ret = new DLongGDL(finalDim, BaseGDL::NOZERO); for (SizeT i = 0; i < finalN; ++i) { if (dateToJD(jd, (*Day)[i % nD], (*Month)[i % nM], (*Year)[i % nY], h, m, s)) { (*ret)[i] = (long) jd; } else e->Throw("Invalid Calendar Date input."); } return ret; } DDoubleGDL *ret = new DDoubleGDL(finalDim, BaseGDL::NOZERO); if (e->NParam() >= 4) { Hour = e->GetParAs(3); nH = Hour->N_Elements(); } if (e->NParam() == 4) { for (SizeT i = 0; i < finalN; ++i) { if (dateToJD(jd, (*Day)[i % nD], (*Month)[i % nM], (*Year)[i % nY], (*Hour)[i % nH], m, s)) { (*ret)[i] = jd; } else e->Throw("Invalid Calendar Date input."); } return ret; } if (e->NParam() >= 5) { Minute = e->GetParAs(4); nMi = Minute->N_Elements(); } if (e->NParam() == 5) { for (SizeT i = 0; i < finalN; ++i) { if (dateToJD(jd, (*Day)[i % nD], (*Month)[i % nM], (*Year)[i % nY], (*Hour)[i % nH], (*Minute)[i % nMi], s)) { (*ret)[i] = jd; } else e->Throw("Invalid Calendar Date input."); } return ret; } if (e->NParam() == 6) { Second = e->GetParAs(5); nS = Second->N_Elements(); for (SizeT i = 0; i < finalN; ++i) { if (dateToJD(jd, (*Day)[i % nD], (*Month)[i % nM], (*Year)[i % nY], (*Hour)[i % nH], (*Minute)[i % nMi], (*Second)[i % nS])) { (*ret)[i] = jd; } else e->Throw("Invalid Calendar Date input."); } return ret; } assert(false); return NULL; } //dummy stub preventing !err and other !errore_state to be set! void pref_set_pro(EnvT* e) { SizeT nParam = e->NParam(1); if (nParam == 0) return; DStringGDL* p0 = e->GetParAs(0); cerr << "% PREF_SET: Unknown preference: " + (*p0)[0] << endl; } // delvar_pro used to live in gdlhelp.cpp void delvar_pro( EnvT* e) { StackGuard guard( e->Interpreter()->CallStack()); static volatile bool debug(false); static bool message_needed(false); static volatile SizeT numEnv; std::vector delvar, delcommon; // trace_me = trace_arg(); SizeT n_Param = e->NParam(); set showStr; // "Sorted List" // 2016.05.16: message is taken down since errors have been attributed to // other aspects, not delvar specifically. if(message_needed) { std::cout << " ** DELVAR - Warning -- experimental routine !! " << std::endl << " o- Not 100 % robust: should NOT be used for objects" << std::endl; message_needed = false; } EnvBaseT* caller = e->Caller(); if(caller->CallingNode() != 0) return; // e->Throw(" DELVAR may only be called from $MAIN$"); SizeT pIndex; int todel[33]; static int itest,ndel; ndel=0; delvar.clear(); delcommon.clear(); for( SizeT ip=0; ipGetPar( ip); if(par == 0) continue; DString parString = caller->GetString( par,true); itest= caller->findvar(parString); if ( itest < 0) {delcommon.push_back(ip); continue;} if( par->Type() == GDL_OBJ) { /* if(trace_me) // deliberately skpping code unless in debug mode. std::cout << " ** delvar on object "<< parString<< std::endl; else { */ std::cout << " ** DELVAR - object " + parString + " skipped !! use obj_destroy " << std::endl; continue; } /* GDLDelete may not be adequate for cleanup. Problems calling this way. // ObjCleanup wants to reference _EXTRA keyword but DELVAR does not support that. DObjGDL* op= static_cast(par); SizeT nEl=op->N_Elements(); for( SizeT i=0; iObjCleanup( (*op)[i]); }*/ delvar.push_back(itest); ndel++; if (ndel == 32) break; pIndex = caller->findvar(par); if(debug) cout << " delvar_pro: "+parString+" pro.var, .env= " <::iterator ix=delvar.begin(); ix< delvar.end(); ix++) todel[ndel++] = (*ix); if(trace_me) std::cout << " ** delvar x-"<< ndel; todel[ndel] = -1; caller->Remove(todel); if(trace_me) std::cout << std::endl; } if(delcommon.empty()) return; int cIx; int ncmnfound=0; std::vector c; DSubUD* proUD = dynamic_cast(caller->GetPro()); proUD->commonPtrs(c); for (std::vector::iterator ix=delcommon.begin(); ix< delcommon.end(); ix++) { int i; BaseGDL*& par=e->GetPar(*ix); for( i=0; i < c.size(); i++) { cIx = c[i]->Find(par); if(cIx >= 0) break; } if(cIx >= 0) { DString parString = c[i]->VarName( cIx) +" ("+c[i]->Name()+')'; help_item( cout , par, parString, false); c[i]->Var(cIx)->Delete(); // this would delete the variable. ncmnfound++; // but } else { cout << " lost variable" << endl; } } // if(ncmnfound > 0) // cout << "( delvar will not handle common-block variables)"<< endl; if(ncmnfound != delcommon.size()) cout << "( delvar did not find common block variables that it should have!"<NParam(); //bool isKWSetStructures = e->KeywordSet( "STRUCTURES"); bool isKWSetStructures = (n_Param == 0); static EnvBaseT* caller = e->Caller(); bool foundit=false; int sIndex,pIndex; for( SizeT i=0; iGetPar( i); DString parString = caller->GetString( par,true); if(debug) { help_item(cout, par, parString, false); } sIndex = caller->findvar(parString); pIndex = caller->findvar(par); cout << " findvar: "+parString+" pro.var, .env= " <= 0); // if(foundit) continue; } if(!isKWSetStructures) return; std::string name; bool started = false; for(StructListT::iterator is = structList.begin(); is != structList.end(); is++) { name = (*is)->Name(); if(started) { if((*is)->IsUnnamed()) name ="Anonymous"; cout << "{"+name+"} (" << (*is)->NTags() <<" tags) " ; } else started = (name.compare("!DEVICE") == 0); } cout << endl; } #endif } // namespace gdl-0.9.9/src/basic_pro.hpp000066400000000000000000000057141340051421000155350ustar00rootroot00000000000000/*************************************************************************** basic_pro.hpp - basic GDL library procedures ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASIC_PRO_HPP_ #define BASIC_PRO_HPP_ namespace lib { // control !CPU settings void cpu(EnvT* e); // helper function bool check_lun(EnvT* e, DLong lun); void ptr_free(EnvT* e); void obj_destroy(EnvT* e); void call_procedure(EnvT* e); void call_method_procedure(EnvT* e); void get_lun(EnvT* e); void openr(EnvT* e); void openw(EnvT* e); void openu(EnvT* e); void socket(EnvT* e); void flush_lun(EnvT* e); void close_lun(EnvT* e); void free_lun(EnvT* e); void writeu(EnvT* e); void readu(EnvT* e); // help_item is used by EnvT::HeapGC void help_item(std::ostream& os, BaseGDL* par, DString parString, bool doIndentation); void help_struct( std::ostream& os, BaseGDL* par, int indent , bool debug ); void exitgdl(EnvT* e); // in print.cpp void print(EnvT* e); void printf(EnvT* e); void print_os(std::ostream* os, EnvT* e, int parOffset, SizeT width); // in read.cpp void read(EnvT* e); void readf(EnvT* e); void reads(EnvT* e); void read_is(std::istream* is, EnvT* e, int parOffset); void on_error(EnvT* e); void catch_pro(EnvT* e); void strput(EnvT* e); void retall(EnvT* e); void stop(EnvT* e); void heap_gc(EnvT* e); void heap_free(EnvT* e); void defsysv(EnvT* e); void message_pro(EnvT* e); void byteorder(EnvT* e); void spawn_pro(EnvT* e); // the following by Peter Messmer // (messmer@users.sourceforge.net) void setenv_pro(EnvT* e); void struct_assign_pro(EnvT* e); // the following by Sergio Gelato // (Sergio.Gelato@astro.su.se) void replicate_inplace_pro(EnvT* e); // the following by Alain Coulais // (alaingdl @@ users.sourceforge.net) void resolve_routine(EnvT* e); // the following by Sylwester Arabas // (slayoo@igf.fuw.edu.pl) void caldat(EnvT* e); BaseGDL* julday(EnvT* e); void pm(EnvT* e); //dummy stub preventing !err and other !error_state to be set! void pref_set_pro(EnvT* e); void delvar_pro( EnvT* e); void findvar_pro( EnvT* e); } // namespace #endif gdl-0.9.9/src/basic_pro_jmg.cpp000066400000000000000000000576341340051421000163750ustar00rootroot00000000000000/*************************************************************************** basic_fun_jmg.cpp - basic GDL library function ------------------- begin : 2004 copyright : (C) 2004 by Joel Gales : (C) 2010 by Christoph Fuchs (CALL_EXTERNAL) email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include "envt.hpp" #include "dinterpreter.hpp" #include "prognode.hpp" #include "basic_pro_jmg.hpp" #define MAXNDLL 40 //#define GDL_DEBUG #undef GDL_DEBUG #if defined (_WIN32) && !defined(__CYGWIN__) #include "gtdhelper.hpp" // just a workaround, using QueryPerformanceCounter is better #endif namespace lib { using namespace std; LibPro dynPro[MAXNDLL/2]; LibFun dynFun[MAXNDLL/2]; void point_lun( EnvT* e) { e->NParam( 1);//, "POINT_LUN"); DLong lun; e->AssureLongScalarPar( 0, lun); if( lun == 0 || abs(lun) > maxLun) throw GDLException( e->CallingNode(), "POINT_LUN: File unit is not within allowed range."); GDLStream& actUnit = fileUnits[ abs(lun)-1]; if( !actUnit.IsOpen()) throw GDLException( e->CallingNode(), "POINT_LUN: File unit is not open: " +i2s(abs(lun))); if (lun < 0) { BaseGDL** retPos = &e->GetPar( 1); GDLDelete(*retPos); // see https://github.com/gnudatalanguage/gdl/issues/441 DLong64 pos = actUnit.Tell(); if (pos > std::numeric_limits::max()) { *retPos = new DLong64GDL( pos); } else { *retPos = new DLongGDL( pos); } return; } else { DLong64 pos; e->AssureLongScalarPar( 1, pos); actUnit.Seek( pos); } } void linkimage( EnvT* e) { #if defined(_WIN32) && !defined(__CYGWIN__) HMODULE module[MAXNDLL]; #else const char *error; void *module[MAXNDLL]; #endif static int count_pro=0; static int count_fun=0; int count; if (count_pro == MAXNDLL/2) { printf("Maximum number of dynamic procedures reached: %d\n", MAXNDLL/2); return; } if (count_fun == MAXNDLL/2) { printf("Maximum number of dynamic functions reached: %d\n", MAXNDLL/2); return; } count = count_pro + count_fun; SizeT nParam=e->NParam(); DString funcName; e->AssureScalarPar( 0, funcName); DString upCasefuncName = StrUpCase( funcName); DString shrdimgName; e->AssureScalarPar( 1, shrdimgName); DLong funcType; e->AssureLongScalarPar( 2, funcType); DString entryName; e->AssureScalarPar( 3, entryName); /* Load dynamically loaded library */ #if defined(_WIN32) && !defined(__CYGWIN__) WCHAR u_shrdimgName[255]; MultiByteToWideChar(CP_ACP, 0, shrdimgName.c_str(), shrdimgName.length(), u_shrdimgName, 255); module[count] = LoadLibraryW(u_shrdimgName); if (!module[count]) { fprintf(stderr, "Couldn't open %s\n", shrdimgName.c_str()); return; } #else module[count] = dlopen(shrdimgName.c_str(), RTLD_LAZY); if (!module[count]) { fprintf(stderr, "Couldn't open %s: %s\n", shrdimgName.c_str(), dlerror()); return; } /* Get symbol */ dlerror(); #endif #if defined(_WIN32) && !defined(__CYGWIN__) if (funcType == 0) { dynPro[count_pro] = (LibPro) GetProcAddress(module[count], entryName.c_str()); } else if (funcType == 1) { dynFun[count_fun] = (LibFun) GetProcAddress(module[count], entryName.c_str()); } else { printf("Improper function type: %d\n", funcType); FreeLibrary(module[count]); return; } #else if (funcType == 0) { dynPro[count_pro] = (LibPro) dlsym(module[count], entryName.c_str()); } else if (funcType == 1) { dynFun[count_fun] = (LibFun) dlsym(module[count], entryName.c_str()); } else { printf("Improper function type: %d\n", funcType); dlclose(module[count]); return; } if ((error = dlerror())) { fprintf(stderr, "Couldn't find %s: %s\n", entryName.c_str(), error); return; } #endif if (funcType == 0){ new DLibPro(lib::dynPro[count_pro], upCasefuncName.c_str(), 16); count_pro++; } else if (funcType == 1) { new DLibFun(lib::dynFun[count_fun], upCasefuncName.c_str(), 16); count_fun++; } } void wait_pro( EnvT* e) { e->NParam( 1);//, "WAIT"); DDouble waittime; e->AssureDoubleScalarPar( 0, waittime); if( waittime < 0) throw GDLException( e->CallingNode(), "WAIT: Argument must be non-negative" +e->GetParString( 0)); #ifdef _WIN32 LARGE_INTEGER Frequency; LARGE_INTEGER BeginTime; LARGE_INTEGER Endtime; LARGE_INTEGER elapsed; LARGE_INTEGER waittime_us; waittime_us.QuadPart = waittime * 1e6; QueryPerformanceFrequency(&Frequency); QueryPerformanceCounter(&BeginTime); while (1) { QueryPerformanceCounter(&Endtime); elapsed.QuadPart = (Endtime.QuadPart - BeginTime.QuadPart)/(Frequency.QuadPart/1000000); if (elapsed.QuadPart >= waittime_us.QuadPart) break; else if (elapsed.QuadPart > 100) Sleep(80); } #else int old_version=0; if (waittime <= 0.005) old_version=1; // AC 2010-09-16 // this version is OK and very accurate for small durations // but used 100% of one CPU :(( if (old_version == 1) { struct timeval tval; struct timezone tzone; // derivated from the current version of SYSTIME() gettimeofday(&tval,&tzone); double t_start = tval.tv_sec+tval.tv_usec/1e+6; // time in UTC seconds double t_current=0.0; double diff = 0.0; while (diff < waittime ) { gettimeofday(&tval,&tzone); t_current= tval.tv_sec+tval.tv_usec/1e+6; diff=t_current - t_start; } } // AC 2010-09-16 this version should used much less CPU ! if (old_version == 0) { //cout << floor(waittime) << " " << waittime-floor(waittime) << endl; struct timespec tv; tv.tv_sec = floor(waittime); tv.tv_nsec = (waittime-floor(waittime))*1e9; int retval; retval=nanosleep(&tv,NULL); } #endif } // void kwtest( EnvT* e) // { // StackGuard guard( e->Interpreter()->CallStack()); // // // here first parameter is the function name // // set callF to the function you want to call // int nParam=e->NParam(); // if( nParam == 0) // e->Throw( "No function specified."); // DString callF; // e->AssureScalarPar( 0, callF); // // // this is a function name -> convert to UPPERCASE // callF = StrUpCase( callF); // // SizeT funIx = GDLInterpreter::GetFunIx( callF); // // EnvUDT* newEnv= new EnvUDT( e->CallingNode(), funList[ funIx], (BaseGDL**)NULL); // // // add parameter // SizeT widgetID = 999; // // newEnv->SetNextPar( new DLongGDL(widgetID)); // pass as local // // e->Interpreter()->CallStack().push_back( newEnv); // // // make the call // BaseGDL* res = e->Interpreter()-> // call_fun(static_cast(newEnv->GetPro())->GetTree()); // // // set the keyword to the function's return value // static int testIx = e->KeywordIx( "TEST"); // e->SetKW( testIx, res); // } // CALL_EXTERNAL by Christoph Fuchs //AC #ifdef USE_EIGEN //AC SizeT defaultAlign = 16; //AC #else typedef struct { char c; long long l; } testAlign; SizeT defaultAlign = (SizeT)( sizeof(testAlign)-sizeof(long long) ); //AC #endif BaseGDL* call_external( EnvT* e) { DString image, entry; static std::string s; SizeT myAlign = defaultAlign; DType myReturnType = GDL_UNDEF; SizeT nParam=e->NParam(2); // Interpret keywords // Return-Type static int kwIxReturnType = e->KeywordIx("RETURN_TYPE"); DIntGDL* KWReturnType = e->IfDefGetKWAs(kwIxReturnType); if (KWReturnType != NULL && (*KWReturnType)[0] != 0) { myReturnType = (DType) (*KWReturnType)[0]; } static int B_VALUEIx = e->KeywordIx("B_VALUE"); static int I_VALUEIx = e->KeywordIx("I_VALUE"); static int L_VALUEIx = e->KeywordIx("L_VALUE"); static int F_VALUEIx = e->KeywordIx("F_VALUE"); static int D_VALUEIx = e->KeywordIx("D_VALUE"); static int S_VALUEIx = e->KeywordIx("S_VALUE"); static int UI_VALUEIx = e->KeywordIx("UI_VALUE"); static int UL_VALUEIx = e->KeywordIx("UL_VALUE"); static int L64_VALUEIx = e->KeywordIx("L64_VALUE"); static int UL64_VALUEIx = e->KeywordIx("UL64_VALUE"); static string TypeKW[16] = { "", "B_VALUE", "I_VALUE", "L_VALUE", "F_VALUE", "D_VALUE", "", "S_VALUE", "", "", "", "", "UI_VALUE", "UL_VALUE", "L64_VALUE", "UL64_VALUE" }; static int TypeKWIx[16] = { -1, B_VALUEIx, I_VALUEIx, L_VALUEIx, F_VALUEIx, D_VALUEIx, -1, S_VALUEIx, -1 , -1, -1, -1, UI_VALUEIx, UL_VALUEIx, L64_VALUEIx, UL64_VALUEIx }; for (int i=0; i<16; i++) { // if (strcmp(TypeKW[i].c_str(), "") == 0) {continue;} if (TypeKWIx[i] == -1) {continue;} // int kwIxType = e->KeywordIx(TypeKW[i]); //should be made static to speed up // if (e->KeywordSet(kwIxType)) { if (e->KeywordSet(TypeKWIx[i])) { if (myReturnType != GDL_UNDEF) { e->Throw("Multiple requests of return type not allowed: " + TypeKW[i] ); } myReturnType = (DType)i; } } if (myReturnType == GDL_UNDEF) { myReturnType = GDL_LONG; } // STRUCT_ALIGN_BYTES static int kwIxStructAlign = e->KeywordIx("STRUCT_ALIGN_BYTES"); DIntGDL* KWStructAlign = e->IfDefGetKWAs(kwIxStructAlign); if (KWStructAlign != NULL && (*KWStructAlign)[0] != 0) { myAlign = (SizeT) (*KWStructAlign)[0]; } // UNLOAD static int kwIxUnload = e->KeywordIx("UNLOAD"); bool flagUnload = e->KeywordSet(kwIxUnload); // parameters by value/reference/GDL reference static int kwIxAllValue = e->KeywordIx("ALL_VALUE"); bool flagAllValue = e->KeywordSet(kwIxAllValue); static int kwIxAllGdl = e->KeywordIx("ALL_GDL"); bool flagAllGdl = e->KeywordSet(kwIxAllGdl); if (flagAllValue && flagAllGdl) { e->Throw("Conflicting keywords ALL_VALUE and ALL_GDL"); } vector byValue(nParam-2,0); for (SizeT i=0; iKeywordIx("VALUE"); DIntGDL* KWValue = e->IfDefGetKWAs(kwIxValue); if (KWValue != NULL) { if (flagAllValue || flagAllGdl) { e->Throw("Only one of VALUE, ALL_VALUE, or ALL_GDL allowed"); } if (KWValue->N_Elements() < nParam - 2) { e->Throw("VALUE must have an entry for every parameter"); } for (SizeT i=0; iAssureStringScalarPar( (SizeT)0, image); e->AssureStringScalarPar( (SizeT)1, entry); int argc = nParam-2; // must be void** for dl... stuff void **argv = (void**)malloc((nParam-2) * sizeof(void*) ); if (argv == NULL) { e->Throw("Internal error allocating memory for argv"); } GDLGuard argvGuard(argv, free); // test if we pass sufficently wide values in case some INT values are shorter than this machine's C "int". bool upgrade[nParam-2]; bool small_int= (sizeof(DInt) < sizeof(int)); bool small_uint= (sizeof(DUInt) < sizeof(int)); //expendable, UInt and Int have same size! for(SizeT i =2; i < nParam; i++){ BaseGDL* par = e->GetParDefined(i); DType pType = par->Type(); upgrade[i-2]=false; if ( pType==GDL_INT && small_int) upgrade[i-2]=true; //Warning(e->GetParString(i)+" is of type INT, too short to be passed to the called function, use LONG");} if ( pType==GDL_UINT && small_uint) upgrade[i-2]=true; //Warning(e->GetParString(i)+" is of type UINT, too short to be passed to the called function, use ULONG");} } // Fill argv with the parameters for(SizeT i =2; i < nParam; i++){ BaseGDL* par = e->GetParDefined(i); DType pType = par->Type(); if (byValue[i-2] > 0 ) { // By Value if (! par->StrictScalar() ) { e->Throw("Must be a scalar here: " + e->GetParString(i) ); } if (NumericType(pType)) { //contains INT and UINT if (par->Sizeof() > sizeof(void*)) { e->Throw("Parameter is larger than pointer: " + e->GetParString(i) ); } if (upgrade[i-2]) { DLong intpar=0; e->AssureLongScalarPar(i,intpar); //normally should be specialzed for UInts. memcpy(&argv[i-2], (void*) &intpar, sizeof(DLong)); } else memcpy(&argv[i-2], (void*) par->DataAddr(), par->Sizeof()); } else if (pType == GDL_STRING) { argv[i-2] = (void*) (*(DStringGDL*)(par))[0].c_str(); } else { e->Throw("Unsupported type for call by value: " + e->GetParString(i) ); } } else if (byValue[i-2] < 0) { // by GDL pointer argv[i-2] = (void*) par; } else { // By reference (default) if (NumericType(pType) || pType == GDL_PTR || pType == GDL_OBJ) { argv[i - 2] = (void*) par->DataAddr(); } else if (pType == GDL_STRING) { argv[i-2] = (void*) ce_StringGDLtoIDL(e, par); } else if (pType == GDL_STRUCT) { argv[i-2] = ce_StructGDLtoIDL(e, par, NULL, myAlign); } else { e->Throw("Objects and Pointers not yet supported"); } } } // Load shared object, call function #if defined(_WIN32) && !defined(__CYGWIN__) LPWSTR wchr = new WCHAR[image.size() + 1]; wchr[image.size()] = 0; std::copy(image.begin(), image.end(), wchr); HMODULE handle = LoadLibraryW(wchr); delete(wchr); #else // note following code line is correct for gcc and linux. // in case of trouble on some architecture, find the correct option and make an #ifdef. // Do *not* modify the following line. GD. void* handle = dlopen(image.c_str(), RTLD_NOW | RTLD_GLOBAL); #endif if (handle == NULL) { #if !defined(_WIN32) || defined(__CYGWIN__) cout << dlerror() << endl; #endif e->Throw("Error opening shared object: " + image); } #if defined(_WIN32) && !defined(__CYGWIN__) void* func = (void *)GetProcAddress(handle,entry.c_str()); #else void* func = dlsym(handle,entry.c_str()); #endif if (func == NULL) { e->Throw("Entry not found: " + entry); } union { DByte d_byte; DInt d_int; DLong d_long; DFloat d_float; DDouble d_double; DUInt d_uint; DULong d_ulong; DLong64 d_long64; DULong64 d_ulong64; char* d_string; } ret; switch (myReturnType) { case GDL_BYTE: ret.d_byte = ((DByte(*) (int, void**))func)(argc, argv); break; case GDL_INT: ret.d_int = ((DInt(*) (int, void**))func)(argc, argv); break; case GDL_LONG: ret.d_long = ((DLong(*) (int, void**))func)(argc, argv); break; case GDL_FLOAT: ret.d_float = ((DFloat(*) (int, void**))func)(argc, argv); break; case GDL_DOUBLE: ret.d_double = ((DDouble(*) (int, void**))func)(argc, argv); break; case GDL_UINT: ret.d_uint = ((DUInt(*) (int, void**))func)(argc, argv); break; case GDL_ULONG: ret.d_ulong = ((DULong(*) (int, void**))func)(argc, argv); break; case GDL_LONG64: ret.d_long64 = ((DLong64(*) (int, void**))func)(argc, argv); break; case GDL_ULONG64: ret.d_ulong64 = ((DULong64(*)(int, void**))func)(argc, argv); break; case GDL_STRING: ret.d_string = ((char*(*) (int, void**))func)(argc, argv); break; default: e->Throw("Return type not supported: " + i2s(myReturnType) ); break; } if (flagUnload) { #if defined(_WIN32) && !defined(__CYGWIN__) while (! FreeLibrary(handle) ) {} #else while (! dlclose(handle) ) {} #endif } // necessary since struct is freed below, i do not see how??? (FIXME) if (myReturnType == GDL_STRING) {s=ret.d_string;} // Copy strings and structures back to GDL, free memory for (SizeT i = nParam - 1; i >= 2; i--) { if (byValue[i-2] != 0) {continue;} BaseGDL* par = e->GetParDefined(i); SizeT pType = par->Type(); if (pType == GDL_STRING) { ce_StringIDLtoGDL((EXTERN_STRING*) argv[i - 2], par, 1); } else if (pType == GDL_STRUCT) { ce_StructIDLtoGDL(e, argv[i - 2], par, 1, myAlign); } } // Return the return value switch (myReturnType) { case GDL_BYTE: return new DByteGDL(ret.d_byte); break; case GDL_INT: if (small_int) return new DIntGDL(ret.d_int); break; case GDL_LONG: return new DLongGDL(ret.d_long); break; case GDL_FLOAT: return new DFloatGDL(ret.d_float); break; case GDL_DOUBLE: return new DDoubleGDL(ret.d_double); break; case GDL_UINT: if (small_uint) return new DUIntGDL(ret.d_uint); break; case GDL_ULONG: return new DULongGDL(ret.d_ulong); break; case GDL_LONG64: return new DLong64GDL(ret.d_long64); break; case GDL_ULONG64: return new DULong64GDL(ret.d_ulong64); break; case GDL_STRING: return new DStringGDL(s); break; default: break; //already exited due to throw above. } assert( false); return NULL; //no -Wreturn-type warnings. } // ce_StringGDLtoIDL: Convert a GDL string (array) to the IDL string structure // used for call_external // Allocates memory, which should be freed later with // ce_StringIDLtoGDL EXTERN_STRING* ce_StringGDLtoIDL(EnvT* e, const BaseGDL* par) { SizeT NEl = par->N_Elements(); EXTERN_STRING* extstring = (EXTERN_STRING*) malloc(NEl * sizeof(EXTERN_STRING)); if (extstring == NULL) { e->Throw("Internal error allocating memory for extstring"); } for (SizeT iEl=0; iEl < NEl; iEl++) { // DString parstring = (*static_cast(par))[iEl]; DString parstring = (*(DStringGDL*)(par))[iEl]; extstring[iEl].slen = parstring.length(); extstring[iEl].s = (char*) malloc( (extstring[iEl].slen+1) * sizeof(char) ); if (extstring[iEl].s == NULL) { e->Throw("Internal error allocating memory for extstring[iEl].s"); } strcpy(extstring[iEl].s, parstring.c_str()); } return extstring; } // ce_StringIDLtoGDL: copy any changes made in the IDL string stucture // back to an GDL string // possibly free any memory allocated by ce_StringGDLtoIDL void ce_StringIDLtoGDL( EXTERN_STRING* extstring, BaseGDL* par, int freeMemory) { SizeT NEl = par->N_Elements(); for (SizeT iEl=0; iEl < NEl; iEl++) { DString parstring = (*static_cast(par))[iEl]; if (strcmp( extstring[iEl].s, parstring.c_str()) ) { ((*static_cast(par))[iEl]).assign(extstring[iEl].s); } if (freeMemory) {free(extstring[iEl].s); } } if (freeMemory) {free(extstring); } } // ce_StructGDLtoIDL: Convert a GDL structure (array) to the IDL (C) structure // used for call_external // Allocates memory, which should be freed later with // ce_StructIDLtoGDL void* ce_StructGDLtoIDL( EnvT* e, const BaseGDL* par, SizeT* length, SizeT myAlign) { SizeT totalSize = ce_LengthOfIDLStruct( e, par, myAlign); if (length != NULL) {*length = totalSize;} SizeT nEl = par->N_Elements(); void* IDLStruct = malloc(nEl * totalSize); if (IDLStruct == NULL) { e->Throw("Internal error allocating memory for IDLStruct"); } DStructGDL* s = (DStructGDL*) par; SizeT nTags = s->Desc()->NTags(); for (SizeT iEl=0; iEl < nEl; iEl++) { char* p = (char*) IDLStruct + iEl*totalSize; for (SizeT iTag=0; iTag < nTags; iTag++) { BaseGDL* member = s->GetTag(iTag, iEl); DType pType = member->Type(); SizeT length; SizeT sizeOf; void* source; int doFree = 0; if (NumericType(pType) || pType == GDL_PTR || pType == GDL_OBJ) { source = (void*) member->DataAddr(); length = member->NBytes(); sizeOf = member->Sizeof(); } else if (pType == GDL_STRING) { source = (void*) ce_StringGDLtoIDL(e, member); length = member->N_Elements() * sizeof(EXTERN_STRING); sizeOf = 8; doFree = 1; } else if (pType == GDL_STRUCT) { source = ce_StructGDLtoIDL( e, member, &length, myAlign ); length *= member->N_Elements(); sizeOf = 8; } else { e->Throw("Unsupported type in structure: " + i2s(pType) ); } SizeT align = sizeOf < myAlign ? sizeOf : myAlign; if ((SizeT)p % align) { SizeT space = align - (SizeT)p % align; p += space; } memcpy(p, source, length); p+=length; if (doFree) {free(source);} } } return IDLStruct; } // ce_StructIDLtoGDL: copy any changes made in the IDL stucture // back to an GDL structure // possibly free any memory allocated bi ce_StructGDLtoIDL void ce_StructIDLtoGDL( EnvT* e, void* IDLStruct, BaseGDL* par, int freeMemory, SizeT myAlign) { SizeT nEl = par->N_Elements(); DStructGDL* s = (DStructGDL*) par; SizeT nTags = s->Desc()->NTags(); char* p = (char*) IDLStruct; for (SizeT iEl=0; iEl < nEl; iEl++) { for (SizeT iTag=0; iTag < nTags; iTag++) { BaseGDL* member = s->GetTag(iTag, iEl); DType pType = member->Type(); SizeT length; SizeT sizeOf; void* dest; if (NumericType(pType)) { sizeOf = member->Sizeof(); } else { sizeOf = 8; } SizeT align = sizeOf < myAlign ? sizeOf : myAlign; if ((SizeT)p % align) { SizeT space = align - (SizeT)p % align; p += space; } if (NumericType(pType) || pType == GDL_PTR || pType == GDL_OBJ) { length = member->NBytes(); dest = (void*) member->DataAddr(); memcpy(dest, p, length); } else if (pType == GDL_STRING) { ce_StringIDLtoGDL((EXTERN_STRING*) p, member, 0); length = member->N_Elements() * sizeof(EXTERN_STRING); } else if (pType == GDL_STRUCT) { ce_StructIDLtoGDL( e, (void*)p, member, 0, myAlign ); length = member->N_Elements() * ce_LengthOfIDLStruct(e, member, myAlign); } else { e->Throw("Unsupported type"); } p += length; } if ((SizeT)p%myAlign) { p+= (myAlign - (SizeT)p%myAlign); } } if (freeMemory) { free(IDLStruct); } } SizeT ce_LengthOfIDLStruct( EnvT* e, const BaseGDL* par, SizeT myAlign) { DStructGDL* s = (DStructGDL*) par; SizeT nTags = s->Desc()->NTags(); SizeT totalSize = 0; SizeT sizeOf; for (SizeT iTag=0; iTag < nTags; iTag++) { BaseGDL* member = s->GetTag(iTag); DType pType = member->Type(); // there is probably no point transfering PTR and OBJ // but if it fits why restrict it? They should never be used though if (NumericType(pType) || pType == GDL_PTR || pType == GDL_OBJ) { totalSize += member->NBytes(); sizeOf = member->Sizeof(); } else if (pType == GDL_STRING) { totalSize += member->N_Elements() * sizeof(EXTERN_STRING); sizeOf = 8; } else if (pType == GDL_STRUCT) { totalSize += member->N_Elements() * ce_LengthOfIDLStruct( e, member, myAlign); sizeOf = 8; } else { e->Throw("Unsupported type"); } SizeT align = sizeOf < myAlign ? sizeOf : myAlign; if (totalSize%align) { totalSize+= (align - totalSize%align); } } if (totalSize%myAlign) { totalSize+= (myAlign - totalSize%myAlign); } return totalSize; } } // namespace gdl-0.9.9/src/basic_pro_jmg.hpp000066400000000000000000000036621340051421000163720ustar00rootroot00000000000000/*************************************************************************** basic_fun.hpp - basic GDL library functions ------------------- begin : 2004 copyright : (C) 2004 by Joel Gales : (C) 2010 by Christoph Fuchs (CALL_EXTERNAL) email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASIC_PRO_JMG_HPP_ #define BASIC_PRO_JMG_HPP_ #if !defined(_WIN32) || defined(__CYGWIN__) #include #endif #include namespace lib { void point_lun( EnvT* e); void linkimage( EnvT* e); void wait_pro( EnvT* e); void kwtest( EnvT* e); // CALL_EXTERNAL by Christoph Fuchs typedef struct { int slen; short stype; char *s; } EXTERN_STRING; BaseGDL* call_external( EnvT* e); EXTERN_STRING* ce_StringGDLtoIDL( EnvT* e, const BaseGDL* par); void ce_StringIDLtoGDL( EXTERN_STRING* extstring, BaseGDL* par, int freeMemory); void* ce_StructGDLtoIDL( EnvT* e, const BaseGDL* par, SizeT* length, SizeT myAlign); void ce_StructIDLtoGDL( EnvT* e, void* IDLStruct, BaseGDL* par, int freeMemory, SizeT myAlign); SizeT ce_LengthOfIDLStruct( EnvT* e, const BaseGDL* par, SizeT myAlign); } // namespace #endif gdl-0.9.9/src/brent.cpp000066400000000000000000001605461340051421000147060ustar00rootroot00000000000000/*************************************************************************** brent.cpp - GDL library function ------------------- begin : Jul 12 2017 copyright : (C) 2017 by Gilles Duvert using J.B.'s praxis implementation of R. Brent minimisation code. See Copyright and License below. ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ # include # include # include # include # include # include using namespace std; double flin ( int n, int j, double l, double f ( double x[], int n ), double x[], int &nf, double v[], double q0[], double q1[], double &qd0, double &qd1, double &qa, double &qb, double &qc ); void minfit ( int n, double tol, double a[], double q[] ); void minny ( int n, int j, int nits, double &d2, double &x1, double &f1, bool fk, double f ( double x[], int n ), double x[], double t, double h, double v[], double q0[], double q1[], int &nl, int &nf, double dmin, double ldt, double &fx, double &qa, double &qb, double &qc, double &qd0, double &qd1 ); double praxis ( double t0, double h0, int n, int prin, double x[], double f ( double x[], int n ) ); void print2 ( int n, double x[], int prin, double fx, int nf, int nl ); void quad ( int n, double f ( double x[], int n ), double x[], double t, double h, double v[], double q0[], double q1[], int &nl, int &nf, double dmin, double ldt, double &fx, double &qf1, double &qa, double &qb, double &qc, double &qd0, double &qd1 ); double r8_epsilon ( ); double r8_hypot ( double x, double y ); double r8_max ( double x, double y ); double r8_min ( double x, double y ); double r8_uniform_01 ( int &seed ); void r8mat_print ( int m, int n, double a[], string title ); void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, string title ); void r8mat_transpose_in_place ( int n, double a[] ); void r8vec_copy ( int n, double a1[], double a2[] ); double r8vec_max ( int n, double r8vec[] ); double r8vec_min ( int n, double r8vec[] ); double r8vec_norm ( int n, double a[] ); void r8vec_print ( int n, double a[], string title ); void svsort ( int n, double d[], double v[] ) ; //****************************************************************************80 double flin ( int n, int jsearch, double l, double f ( double x[], int n ), double x[], int &nf, double v[], double q0[], double q1[], double &qd0, double &qd1, double &qa, double &qb, double &qc ) //****************************************************************************80 // // Purpose: // // FLIN is the function of one variable to be minimized by MINNY. // // Discussion: // // F(X) is a scalar function of a vector argument X. // // A minimizer of F(X) is sought along a line or parabola. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // Parameters: // // Input, int N, the number of variables. // // Input, int JSEARCH, indicates the kind of search. // If JSEARCH is a legal column index, linear search along V(*,JSEARCH). // If JSEARCH is -1, then the search is parabolic, based on X, Q0 and Q1. // // Input, double L, is the parameter determining the particular // point at which F is to be evaluated. // For a linear search, L is the step size. // For a quadratic search, L is a parameter which specifies // a point in the plane of X, Q0 and Q1. // // Input, double F ( double X[], int N ), the function to be minimized. // // Input, double X[N], the base point of the search. // // Input/output, int &NF, the function evaluation counter. // // Input, double V[N,N], a matrix whose columns constitute // search directions. // // Input, double Q0[N], Q1[N], two auxiliary points used to // determine the plane when a quadratic search is performed. // // Input, double &QD0, &QD1, values needed to compute the // coefficients QA, QB, QC. // // Output, double &QA, &QB, &QC, coefficients used to combine // Q0, X, and A1 if a quadratic search is used. // // Output, double FLIN, the value of the function at the // minimizing point. // { int i; double *t; double value; t = new double[n]; // // The search is linear. // if ( 0 <= jsearch ) { for ( i = 0; i < n; i++ ) { t[i] = x[i] + l * v[i+jsearch*n]; } } // // The search is along a parabolic space curve. // else { qa = l * ( l - qd1 ) / ( qd0 + qd1 ) / qd0; qb = - ( l + qd0 ) * ( l - qd1 ) / qd1 / qd0; qc = ( l + qd0 ) * l / qd1 / ( qd0 + qd1 ); for ( i = 0; i < n; i++ ) { t[i] = qa * q0[i] + qb * x[i] + qc * q1[i]; } } // // The function evaluation counter NF is incremented. // nf = nf + 1; // // Evaluate the function. // value = f ( t, n ); delete [] t; return value; } //****************************************************************************80 void minfit ( int n, double tol, double a[], double q[] ) //****************************************************************************80 // // Purpose: // // MINFIT computes the singular value decomposition of an N by N array. // // Discussion: // // This is an improved version of the EISPACK routine MINFIT // restricted to the case M = N and P = 0. // // The singular values of the array A are returned in Q. A is // overwritten with the orthogonal matrix V such that U * diag(Q) = A * V, // where U is another orthogonal matrix. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // James Wilkinson, Christian Reinsch, // Handbook for Automatic Computation, // Volume II, Linear Algebra, Part 2, // Springer Verlag, 1971. // // Brian Smith, James Boyle, Jack Dongarra, Burton Garbow, Yasuhiko Ikebe, // Virginia Klema, Cleve Moler, // Matrix Eigensystem Routines, EISPACK Guide, // Lecture Notes in Computer Science, Volume 6, // Springer Verlag, 1976, // ISBN13: 978-3540075462, // LC: QA193.M37. // // Parameters: // // Input, int N, the order of the matrix A. // // Input, double TOL, a tolerance which determines when a vector // (a column or part of a column of the matrix) may be considered // "essentially" equal to zero. // // Input/output, double A[N,N]. On input, an N by N array whose // singular value decomposition is desired. On output, the // SVD orthogonal matrix factor V. // // Input/output, double Q[N], the singular values. // { double c; double *e; double eps; double f; double g; double h; int i; int ii; int j; int jj; int k; int kk; int kt; const int kt_max = 30; int l; int l2; int ll2; double s; int skip; double temp; double x; double y; double z; // // Householder's reduction to bidiagonal form. // if ( n == 1 ) { q[0] = a[0+0*n]; a[0+0*n] = 1.0; return; } e = new double[n]; eps = r8_epsilon ( ); g = 0.0; x = 0.0; for ( i = 1; i <= n; i++ ) { e[i-1] = g; l = i + 1; s = 0.0; for ( ii = i; ii <= n; ii++ ) { s = s + a[ii-1+(i-1)*n] * a[ii-1+(i-1)*n]; } g = 0.0; if ( tol <= s ) { f = a[i-1+(i-1)*n]; g = sqrt ( s ); if ( 0.0 <= f ) { g = - g; } h = f * g - s; a[i-1+(i-1)*n] = f - g; for ( j = l; j <= n; j++ ) { f = 0.0; for ( ii = i; ii <= n; ii++ ) { f = f + a[ii-1+(i-1)*n] * a[ii-1+(j-1)*n]; } f = f / h; for ( ii = i; ii <= n; ii++ ) { a[ii-1+(j-1)*n] = a[ii-1+(j-1)*n] + f * a[ii-1+(i-1)*n]; } } } q[i-1] = g; s = 0.0; for ( j = l; j <= n; j++ ) { s = s + a[i-1+(j-1)*n] * a[i-1+(j-1)*n]; } g = 0.0; if ( tol <= s ) { if ( i < n ) { f = a[i-1+i*n]; } g = sqrt ( s ); if ( 0.0 <= f ) { g = - g; } h = f * g - s; if ( i < n ) { a[i-1+i*n] = f - g; for ( jj = l; jj <= n; jj++ ) { e[jj-1] = a[i-1+(jj-1)*n] / h; } for ( j = l; j <= n; j++ ) { s = 0.0; for ( jj = l; jj <= n; jj++ ) { s = s + a[j-1+(jj-1)*n] * a[i-1+(jj-1)*n]; } for ( jj = l; jj <= n; jj++ ) { a[j-1+(jj-1)*n] = a[j-1+(jj-1)*n] + s * e[jj-1]; } } } } y = fabs ( q[i-1] ) + fabs ( e[i-1] ); x = r8_max ( x, y ); } // // Accumulation of right-hand transformations. // a[n-1+(n-1)*n] = 1.0; g = e[n-1]; l = n; for ( i = n - 1; 1 <= i; i-- ) { if ( g != 0.0 ) { h = a[i-1+i*n] * g; for ( ii = l; ii <= n; ii++ ) { a[ii-1+(i-1)*n] = a[i-1+(ii-1)*n] / h; } for ( j = l; j <= n; j++ ) { s = 0.0; for ( jj = l; jj <= n; jj++ ) { s = s + a[i-1+(jj-1)*n] * a[jj-1+(j-1)*n]; } for ( ii = l; ii <= n; ii++ ) { a[ii-1+(j-1)*n] = a[ii-1+(j-1)*n] + s * a[ii-1+(i-1)*n]; } } } for ( jj = l; jj <= n; jj++ ) { a[i-1+(jj-1)*n] = 0.0; } for ( ii = l; ii <= n; ii++ ) { a[ii-1+(i-1)*n] = 0.0; } a[i-1+(i-1)*n] = 1.0; g = e[i-1]; l = i; } // // Diagonalization of the bidiagonal form. // eps = eps * x; for ( k = n; 1 <= k; k-- ) { kt = 0; for ( ; ; ) { kt = kt + 1; if ( kt_max < kt ) { e[k-1] = 0.0; cerr << "\n"; cerr << "MINFIT - Fatal error!\n"; cerr << " The QR algorithm failed to converge.\n"; exit ( 1 ); } skip = 0; for ( l2 = k; 1 <= l2; l2-- ) { l = l2; if ( fabs ( e[l-1] ) <= eps ) { skip = 1; break; } if ( 1 < l ) { if ( fabs ( q[l-2] ) <= eps ) { break; } } } // // Cancellation of E(L) if 1 < L. // if ( ! skip ) { c = 0.0; s = 1.0; for ( i = l; i <= k; i++ ) { f = s * e[i-1]; e[i-1] = c * e[i-1]; if ( fabs ( f ) <= eps ) { break; } g = q[i-1]; // // q(i) = h = sqrt(g*g + f*f). // h = r8_hypot ( f, g ); q[i-1] = h; if ( h == 0.0 ) { g = 1.0; h = 1.0; } c = g / h; s = - f / h; } } // // Test for convergence for this index K. // z = q[k-1]; if ( l == k ) { if ( z < 0.0 ) { q[k-1] = - z; for ( i = 1; i <= n; i++ ) { a[i-1+(k-1)*n] = - a[i-1+(k-1)*n]; } } break; } // // Shift from bottom 2*2 minor. // x = q[l-1]; y = q[k-2]; g = e[k-2]; h = e[k-1]; f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0 * h * y ); g = r8_hypot ( f, 1.0 ); if ( f < 0.0 ) { temp = f - g; } else { temp = f + g; } f = ( ( x - z ) * ( x + z ) + h * ( y / temp - h ) ) / x; // // Next QR transformation. // c = 1.0; s = 1.0; for ( i = l + 1; i <= k; i++ ) { g = e[i-1]; y = q[i-1]; h = s * g; g = g * c; z = r8_hypot ( f, h ); e[i-2] = z; if ( z == 0.0 ) { f = 1.0; z = 1.0; } c = f / z; s = h / z; f = x * c + g * s; g = - x * s + g * c; h = y * s; y = y * c; for ( j = 1; j <= n; j++ ) { x = a[j-1+(i-2)*n]; z = a[j-1+(i-1)*n]; a[j-1+(i-2)*n] = x * c + z * s; a[j-1+(i-1)*n] = - x * s + z * c; } z = r8_hypot ( f, h ); q[i-2] = z; if ( z == 0.0 ) { f = 1.0; z = 1.0; } c = f / z; s = h / z; f = c * g + s * y; x = - s * g + c * y; } e[l-1] = 0.0; e[k-1] = f; q[k-1] = x; } } delete [] e; return; } //****************************************************************************80 void minny ( int n, int jsearch, int nits, double &d2, double &x1, double &f1, bool fk, double f ( double x[], int n ), double x[], double t, double h, double v[], double q0[], double q1[], int &nl, int &nf, double dmin, double ldt, double &fx, double &qa, double &qb, double &qc, double &qd0, double &qd1 ) //****************************************************************************80 // // Purpose: // // MINNY minimizes a scalar function of N variables along a line. // // Discussion: // // MINNY minimizes F along the line from X in the direction V(*,JSEARCH) // or else using a quadratic search in the plane defined by Q0, Q1 and X. // // If FK = true, then F1 is FLIN(X1). Otherwise X1 and F1 are ignored // on entry unless final FX is greater than F1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // Parameters: // // Input, int N, the number of variables. // // Input, int JSEARCH, indicates the kind of search. // If J is a legal columnindex, linear search in the direction of V(*,JSEARCH). // Otherwise, the search is parabolic, based on X, Q0 and Q1. // // Input, int NITS, the maximum number of times the interval // may be halved to retry the calculation. // // Input/output, double &D2, is either zero, or an approximation to // the value of (1/2) times the second derivative of F. // // Input/output, double &X1, on entry, an estimate of the // distance from X to the minimum along V(*,JSEARCH), or a curve. // On output, the distance between X and the minimizer that was found. // // Input/output, double &F1, ? // // Input, bool FK; if FK is TRUE, then on input F1 contains // the value FLIN(X1). // // Input, double F ( double X[], int N ), is the name of the function to // be minimized. // // Input/output, double X[N], ? // // Input, double T, ? // // Input, double H, ? // // Input, double V[N,N], a matrix whose columns are direction // vectors along which the function may be minimized. // // ?, double Q0[N], ? // // ?, double Q1[N], ? // // Input/output, int &NL, the number of linear searches. // // Input/output, int &NF, the number of function evaluations. // // Input, double DMIN, an estimate for the smallest eigenvalue. // // Input, double LDT, the length of the step. // // Input/output, double &FX, the value of F(X,N). // // Input/output, double &QA, &QB, &QC; // // Input/output, double &QD0, &QD1, ?. // { double d1; int dz; double f0; double f2; double fm; int i; int k; double m2; double m4; double machep; int ok; double s; double sf1; double small; double sx1; double t2; double temp; double x2; double xm; machep = r8_epsilon ( ); small = machep * machep; m2 = sqrt ( machep ); m4 = sqrt ( m2 ); sf1 = f1; sx1 = x1; k = 0; xm = 0.0; fm = fx; f0 = fx; dz = ( d2 < machep ); // // Find the step size. // s = r8vec_norm ( n, x ); if ( dz ) { temp = dmin; } else { temp = d2; } t2 = m4 * sqrt ( fabs ( fx ) / temp + s * ldt ) + m2 * ldt; s = m4 * s + t; if ( dz && s < t2 ) { t2 = s; } t2 = r8_max ( t2, small ); t2 = r8_min ( t2, 0.01 * h ); if ( fk && f1 <= fm ) { xm = x1; fm = f1; } if ( ( ! fk ) || fabs ( x1 ) < t2 ) { if ( 0.0 <= x1 ) { temp = 1.0; } else { temp = - 1.0; } x1 = temp * t2; f1 = flin ( n, jsearch, x1, f, x, nf, v, q0, q1, qd0, qd1, qa, qb, qc ); } if ( f1 <= fm ) { xm = x1; fm = f1; } // // Evaluate FLIN at another point and estimate the second derivative. // for ( ; ; ) { if ( dz ) { if ( f1 <= f0 ) { x2 = 2.0 * x1; } else { x2 = - x1; } f2 = flin ( n, jsearch, x2, f, x, nf, v, q0, q1, qd0, qd1, qa, qb, qc ); if ( f2 <= fm ) { xm = x2; fm = f2; } d2 = ( x2 * ( f1 - f0 ) - x1 * ( f2 - f0 ) ) / ( ( x1 * x2 ) * ( x1 - x2 ) ); } // // Estimate the first derivative at 0. // d1 = ( f1 - f0 ) / x1 - x1 * d2; dz = 1; // // Predict the minimum. // if ( d2 <= small ) { if ( 0.0 <= d1 ) { x2 = - h; } else { x2 = h; } } else { x2 = ( - 0.5 * d1 ) / d2; } if ( h < fabs ( x2 ) ) { if ( x2 <= 0.0 ) { x2 = - h; } else { x2 = h; } } // // Evaluate F at the predicted minimum. // ok = 1; for ( ; ; ) { f2 = flin ( n, jsearch, x2, f, x, nf, v, q0, q1, qd0, qd1, qa, qb, qc ); if ( nits <= k || f2 <= f0 ) { break; } k = k + 1; if ( f0 < f1 && 0.0 < x1 * x2 ) { ok = 0; break; } x2 = 0.5 * x2; } if ( ok ) { break; } } // // Increment the one-dimensional search counter. // nl = nl + 1; if ( fm < f2 ) { x2 = xm; } else { fm = f2; } // // Get a new estimate of the second derivative. // if ( small < fabs ( x2 * ( x2 - x1 ) ) ) { d2 = ( x2 * ( f1 - f0 ) - x1 * ( fm - f0 ) ) / ( ( x1 * x2 ) * ( x1 - x2 ) ); } else { if ( 0 < k ) { d2 = 0.0; } } d2 = r8_max ( d2, small ); x1 = x2; fx = fm; if ( sf1 < fx ) { fx = sf1; x1 = sx1; } // // Update X for linear search. // if ( 0 <= jsearch ) { for ( i = 0; i < n; i++ ) { x[i] = x[i] + x1 * v[i+jsearch*n]; } } return; } //****************************************************************************80 double praxis ( double t0, double h0, int n, int prin, double x[], double f ( double x[], int n ) ) //****************************************************************************80 // // Purpose: // // PRAXIS seeks an N-dimensional minimizer X of a scalar function F(X). // // Discussion: // // PRAXIS returns the minimum of the function F(X,N) of N variables // using the principal axis method. The gradient of the function is // not required. // // The approximating quadratic form is // // Q(x") = F(x,n) + (1/2) * (x"-x)" * A * (x"-x) // // where X is the best estimate of the minimum and // // A = inverse(V") * D * inverse(V) // // V(*,*) is the matrix of search directions; // D(*) is the array of second differences. // // If F(X) has continuous second derivatives near X0, then A will tend // to the hessian of F at X0 as X approaches X0. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // Parameters: // // Input, double T0, is a tolerance. PRAXIS attempts to return // praxis = f(x) such that if X0 is the true local minimum near X, then // norm ( x - x0 ) < T0 + sqrt ( EPSILON ( X ) ) * norm ( X ), // where EPSILON ( X ) is the machine precision for X. // // Input, double H0, is the maximum step size. H0 should be // set to about the maximum distance from the initial guess to the minimum. // If H0 is set too large or too small, the initial rate of // convergence may be slow. // // Input, int N, the number of variables. // // Input, int PRIN, controls printing intermediate results. // 0, nothing is printed. // 1, F is printed after every n+1 or n+2 linear minimizations. // final X is printed, but intermediate X is printed only // if N is at most 4. // 2, the scale factors and the principal values of the approximating // quadratic form are also printed. // 3, X is also printed after every few linear minimizations. // 4, the principal vectors of the approximating quadratic form are // also printed. // // Input/output, double X[N], is an array containing on entry a // guess of the point of minimum, on return the estimated point of minimum. // // Input, double F ( double X[], int N ), is the name of the function to be // minimized. // // Output, double PRAXIS, the function value at the minimizer. // // Local parameters: // // Local, double DMIN, an estimate for the smallest eigenvalue. // // Local, double FX, the value of F(X,N). // // Local, bool ILLC, is TRUE if the system is ill-conditioned. // // Local, double LDT, the length of the step. // // Local, int NF, the number of function evaluations. // // Local, int NL, the number of linear searches. // { double *d; double d2; double df; double dmin; double dn; double dni; double f1; bool fk; double fx; double h; int i; int ii; bool illc; int j; int jsearch; int k; int k2; int kl; int kt; int ktm; double large; double ldfac; double lds; double ldt; double m2; double m4; double machep; int nits; int nl; int nf; double *q0; double *q1; double qa; double qb; double qc; double qd0; double qd1; double qf1; double r; double s; double scbd; int seed; double sf; double sl; double small; double t; double temp; double t2; double *v; double value; double vlarge; double vsmall; double *y; double *z; // // Allocation. // d = new double[n]; q0 = new double[n]; q1 = new double[n]; v = new double[n*n]; y = new double[n]; z = new double[n]; // // Initialization. // machep = r8_epsilon ( ); small = machep * machep; vsmall = small * small; large = 1.0 / small; vlarge = 1.0 / vsmall; m2 = sqrt ( machep ); m4 = sqrt ( m2 ); seed = 123456789; // // Heuristic numbers: // // If the axes may be badly scaled (which is to be avoided if // possible), then set SCBD = 10. Otherwise set SCBD = 1. // // If the problem is known to be ill-conditioned, initialize ILLC = true. // // KTM is the number of iterations without improvement before the // algorithm terminates. KTM = 4 is very cautious; usually KTM = 1 // is satisfactory. // scbd = 1.0; illc = false; ktm = 1; if ( illc ) { ldfac = 0.1; } else { ldfac = 0.01; } kt = 0; nl = 0; nf = 1; fx = f ( x, n ); qf1 = fx; t = small + fabs ( t0 ); t2 = t; dmin = small; h = h0; h = r8_max ( h, 100.0 * t ); ldt = h; // // The initial set of search directions V is the identity matrix. // for ( j = 0; j < n; j++ ) { for ( i = 0; i < n; i++ ) { v[i+j*n] = 0.0; } v[j+j*n] = 1.0; } for ( i = 0; i < n; i++ ) { d[i] = 0.0; } qa = 0.0; qb = 0.0; qc = 0.0; qd0 = 0.0; qd1 = 0.0; r8vec_copy ( n, x, q0 ); r8vec_copy ( n, x, q1 ); if ( 0 < prin ) { print2 ( n, x, prin, fx, nf, nl ); } // // The main loop starts here. // for ( ; ; ) { sf = d[0]; d[0] = 0.0; // // Minimize along the first direction V(*,1). // jsearch = 0; nits = 2; d2 = d[0]; s = 0.0; value = fx; fk = false; minny ( n, jsearch, nits, d2, s, value, fk, f, x, t, h, v, q0, q1, nl, nf, dmin, ldt, fx, qa, qb, qc, qd0, qd1 ); d[0] = d2; if ( s <= 0.0 ) { for ( i = 0; i < n; i++ ) { v[i+0*n] = - v[i+0*n]; } } if ( sf <= 0.9 * d[0] || d[0] <= 0.9 * sf ) { for ( i = 1; i < n; i++ ) { d[i] = 0.0; } } // // The inner loop starts here. // for ( k = 2; k <= n; k++ ) { r8vec_copy ( n, x, y ); sf = fx; if ( 0 < kt ) { illc = true; } for ( ; ; ) { kl = k; df = 0.0; // // A random step follows, to avoid resolution valleys. // if ( illc ) { for ( j = 0; j < n; j++ ) { r = r8_uniform_01 ( seed ); s = ( 0.1 * ldt + t2 * pow ( 10.0, kt ) ) * ( r - 0.5 ); z[j] = s; for ( i = 0; i < n; i++ ) { x[i] = x[i] + s * v[i+j*n]; } } fx = f ( x, n ); nf = nf + 1; } // // Minimize along the "non-conjugate" directions V(*,K),...,V(*,N). // for ( k2 = k; k2 <= n; k2++ ) { sl = fx; jsearch = k2 - 1; nits = 2; d2 = d[k2-1]; s = 0.0; value = fx; fk = false; minny ( n, jsearch, nits, d2, s, value, fk, f, x, t, h, v, q0, q1, nl, nf, dmin, ldt, fx, qa, qb, qc, qd0, qd1 ); d[k2-1] = d2; if ( illc ) { s = d[k2-1] * pow ( s + z[k2-1], 2 ); } else { s = sl - fx; } if ( df <= s ) { df = s; kl = k2; } } // // If there was not much improvement on the first try, set // ILLC = true and start the inner loop again. // if ( illc ) { break; } if ( fabs ( 100.0 * machep * fx ) <= df ) { break; } illc = true; } if ( k == 2 && 1 < prin ) { r8vec_print ( n, d, " The second difference array:" ); } // // Minimize along the "conjugate" directions V(*,1),...,V(*,K-1). // for ( k2 = 1; k2 < k; k2++ ) { jsearch = k2 - 1; nits = 2; d2 = d[k2-1]; s = 0.0; value = fx; fk = false; minny ( n, jsearch, nits, d2, s, value, fk, f, x, t, h, v, q0, q1, nl, nf, dmin, ldt, fx, qa, qb, qc, qd0, qd1 ); d[k2-1] = d2; } f1 = fx; fx = sf; for ( i = 0; i < n; i++ ) { temp = x[i]; x[i] = y[i]; y[i] = temp - y[i]; } lds = r8vec_norm ( n, y ); // // Discard direction V(*,kl). // // If no random step was taken, V(*,KL) is the "non-conjugate" // direction along which the greatest improvement was made. // if ( small < lds ) { for ( j = kl - 1; k <= j; j-- ) { for ( i = 1; i <= n; i++ ) { v[i-1+j*n] = v[i-1+(j-1)*n]; } d[j] = d[j-1]; } d[k-1] = 0.0; for ( i = 1; i <= n; i++ ) { v[i-1+(k-1)*n] = y[i-1] / lds; } // // Minimize along the new "conjugate" direction V(*,k), which is // the normalized vector: (new x) - (old x). // jsearch = k - 1; nits = 4; d2 = d[k-1]; value = f1; fk = true; minny ( n, jsearch, nits, d2, lds, value, fk, f, x, t, h, v, q0, q1, nl, nf, dmin, ldt, fx, qa, qb, qc, qd0, qd1 ); d[k-1] = d2; if ( lds <= 0.0 ) { lds = - lds; for ( i = 1; i <= n; i++ ) { v[i-1+(k-1)*n] = - v[i-1+(k-1)*n]; } } } ldt = ldfac * ldt; ldt = r8_max ( ldt, lds ); if ( 0 < prin ) { print2 ( n, x, prin, fx, nf, nl ); } t2 = r8vec_norm ( n, x ); t2 = m2 * t2 + t; // // See whether the length of the step taken since starting the // inner loop exceeds half the tolerance. // if ( 0.5 * t2 < ldt ) { kt = - 1; } kt = kt + 1; if ( ktm < kt ) { if ( 0 < prin ) { r8vec_print ( n, x, " X:" ); } delete [] d; delete [] q0; delete [] q1; delete [] v; delete [] y; delete [] z; return fx; } } // // The inner loop ends here. // // Try quadratic extrapolation in case we are in a curved valley. // quad ( n, f, x, t, h, v, q0, q1, nl, nf, dmin, ldt, fx, qf1, qa, qb, qc, qd0, qd1 ); for ( j = 0; j < n; j++ ) { d[j] = 1.0 / sqrt ( d[j] ); } dn = r8vec_max ( n, d ); if ( 3 < prin ) { r8mat_print ( n, n, v, " The new direction vectors:" ); } for ( j = 0; j < n; j++ ) { for ( i = 0; i < n; i++ ) { v[i+j*n] = ( d[j] / dn ) * v[i+j*n]; } } // // Scale the axes to try to reduce the condition number. // if ( 1.0 < scbd ) { for ( i = 0; i < n; i++ ) { s = 0.0; for ( j = 0; j < n; j++ ) { s = s + v[i+j*n] * v[i+j*n]; } s = sqrt ( s ); z[i] = r8_max ( m4, s ); } s = r8vec_min ( n, z ); for ( i = 0; i < n; i++ ) { sl = s / z[i]; z[i] = 1.0 / sl; if ( scbd < z[i] ) { sl = 1.0 / scbd; z[i] = scbd; } for ( j = 0; j < n; j++ ) { v[i+j*n] = sl * v[i+j*n]; } } } // // Calculate a new set of orthogonal directions before repeating // the main loop. // // Transpose V for MINFIT: // r8mat_transpose_in_place ( n, v ); // // MINFIT finds the singular value decomposition of V. // // This gives the principal values and principal directions of the // approximating quadratic form without squaring the condition number. // minfit ( n, vsmall, v, d ); // // Unscale the axes. // if ( 1.0 < scbd ) { for ( i = 0; i < n; i++ ) { for ( j = 0; j < n; j++ ) { v[i+j*n] = z[i] * v[i+j*n]; } } for ( j = 0; j < n; j++ ) { s = 0.0; for ( i = 0; i < n; i++ ) { s = s + v[i+j*n] * v[i+j*n]; } s = sqrt ( s ); d[j] = s * d[j]; for ( i = 0; i < n; i++ ) { v[i+j*n] = v[i+j*n] / s; } } } for ( i = 0; i < n; i++ ) { dni = dn * d[i]; if ( large < dni ) { d[i] = vsmall; } else if ( dni < small ) { d[i] = vlarge; } else { d[i] = 1.0 / dni / dni; } } // // Sort the eigenvalues and eigenvectors. // svsort ( n, d, v ); // // Determine the smallest eigenvalue. // dmin = r8_max ( d[n-1], small ); // // The ratio of the smallest to largest eigenvalue determines whether // the system is ill conditioned. // if ( dmin < m2 * d[0] ) { illc = true; } else { illc = false; } if ( 1 < prin ) { if ( 1.0 < scbd ) { r8vec_print ( n, z, " The scale factors:" ); } r8vec_print ( n, d, " Principal values of the quadratic form:" ); } if ( 3 < prin ) { r8mat_print ( n, n, v, " The principal axes:" ); } // // The main loop ends here. // } if ( 0 < prin ) { r8vec_print ( n, x, " X:" ); } // // Free memory. // delete [] d; delete [] q0; delete [] q1; delete [] v; delete [] y; delete [] z; return fx; } //****************************************************************************80 void print2 ( int n, double x[], int prin, double fx, int nf, int nl ) //****************************************************************************80 // // Purpose: // // PRINT2 prints certain data about the progress of the iteration. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // Parameters: // // Input, int N, the number of variables. // // Input, double X[N], the current estimate of the minimizer. // // Input, int PRIN, the user-specifed print level. // 0, nothing is printed. // 1, F is printed after every n+1 or n+2 linear minimizations. // final X is printed, but intermediate X is printed only // if N is at most 4. // 2, the scale factors and the principal values of the approximating // quadratic form are also printed. // 3, X is also printed after every few linear minimizations. // 4, the principal vectors of the approximating quadratic form are // also printed. // // Input, double FX, the smallest value of F(X) found so far. // // Input, int NF, the number of function evaluations. // // Input, int NL, the number of linear searches. // { cout << "\n"; cout << " Linear searches = " << nl << "\n"; cout << " Function evaluations " << nf << "\n"; cout << " Function value FX = " << fx << "\n"; if ( n <= 4 || 2 < prin ) { r8vec_print ( n, x, " X:" ); } return; } //****************************************************************************80 void quad ( int n, double f ( double x[], int n ), double x[], double t, double h, double v[], double q0[], double q1[], int &nl, int &nf, double dmin, double ldt, double &fx, double &qf1, double &qa, double &qb, double &qc, double &qd0, double &qd1 ) //****************************************************************************80 // // Purpose: // // QUAD seeks to minimize the scalar function F along a particular curve. // // Discussion: // // The minimizer to be sought is required to lie on a curve defined // by Q0, Q1 and X. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // Parameters: // // Input, int N, the number of variables. // // Input, double F ( double X[], int N ), the name of the function to // be minimized. // // Input/output, double X[N], ? // // Input, double T, ? // // Input, double H, ? // // Input, double V[N,N], the matrix of search directions. // // Input/output, double Q0[N], Q1[N], two auxiliary points used to define // a curve through X. // // Input/output, int &NL, the number of linear searches. // // Input/output, int &NF, the number of function evaluations. // // Input, double DMIN, an estimate for the smallest eigenvalue. // // Input, double LDT, the length of the step. // // Input/output, double &FX, the value of F(X,N). // // Input/output, double &QF1, &QA, &QB, &QC, &QD0, &QD1 ? // { bool fk; int i; int jsearch; double l; int nits; double s; double temp; double value; temp = fx; fx = qf1; qf1 = temp; for ( i = 0; i < n; i++ ) { temp = x[i]; x[i] = q1[i]; q1[i] = temp; } qd1 = 0.0; for ( i = 0; i < n; i++ ) { qd1 = qd1 + ( x[i] - q1[i] ) * ( x[i] - q1[i] ); } qd1 = sqrt ( qd1 ); if ( qd0 <= 0.0 || qd1 <= 0.0 || nl < 3 * n * n ) { fx = qf1; qa = 0.0; qb = 0.0; qc = 1.0; s = 0.0; } else { jsearch = - 1; nits = 2; s = 0.0; l = qd1; value = qf1; fk = true; minny ( n, jsearch, nits, s, l, value, fk, f, x, t, h, v, q0, q1, nl, nf, dmin, ldt, fx, qa, qb, qc, qd0, qd1 ); qa = l * ( l - qd1 ) / ( qd0 + qd1 ) / qd0; qb = - ( l + qd0 ) * ( l - qd1 ) / qd1 / qd0; qc = ( l + qd0 ) * l / qd1 / ( qd0 + qd1 ); } qd0 = qd1; for ( i = 0; i < n; i++ ) { s = q0[i]; q0[i] = x[i]; x[i] = qa * s + qb * x[i] + qc * q1[i]; } return; } //****************************************************************************80 double r8_epsilon ( ) //****************************************************************************80 // // Purpose: // // R8_EPSILON returns the R8 roundoff unit. // // Discussion: // // The roundoff unit is a number R which is a power of 2 with the // property that, to the precision of the computer's arithmetic, // 1 < 1 + R // but // 1 = ( 1 + R / 2 ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 September 2012 // // Author: // // John Burkardt // // Parameters: // // Output, double R8_EPSILON, the R8 round-off unit. // { const double value = 2.220446049250313E-016; return value; } //****************************************************************************80 double r8_hypot ( double x, double y ) //****************************************************************************80 // // Purpose: // // R8_HYPOT returns the value of sqrt ( X^2 + Y^2 ). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 March 2012 // // Author: // // John Burkardt // // Parameters: // // Input, double X, Y, the arguments. // // Output, double R8_HYPOT, the value of sqrt ( X^2 + Y^2 ). // { double a; double b; double value; if ( fabs ( x ) < fabs ( y ) ) { a = fabs ( y ); b = fabs ( x ); } else { a = fabs ( x ); b = fabs ( y ); } // // A contains the larger value. // if ( a == 0.0 ) { value = 0.0; } else { value = a * sqrt ( 1.0 + ( b / a ) * ( b / a ) ); } return value; } //****************************************************************************80 double r8_max ( double x, double y ) //****************************************************************************80 // // Purpose: // // R8_MAX returns the maximum of two R8's. // // Discussion: // // The C++ math library provides the function fmax() which is preferred. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 18 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, Y, the quantities to compare. // // Output, double R8_MAX, the maximum of X and Y. // { double value; if ( y < x ) { value = x; } else { value = y; } return value; } //****************************************************************************80 double r8_min ( double x, double y ) //****************************************************************************80 // // Purpose: // // R8_MIN returns the minimum of two R8's. // // Discussion: // // The C++ math library provides the function fmin() which is preferred. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 31 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, double X, Y, the quantities to compare. // // Output, double R8_MIN, the minimum of X and Y. // { double value; if ( y < x ) { value = y; } else { value = x; } return value; } //****************************************************************************80 double r8_uniform_01 ( int &seed ) //****************************************************************************80 // // Purpose: // // R8_UNIFORM_01 returns a unit pseudorandom R8. // // Discussion: // // This routine implements the recursion // // seed = ( 16807 * seed ) mod ( 2^31 - 1 ) // u = seed / ( 2^31 - 1 ) // // The integer arithmetic never requires more than 32 bits, // including a sign bit. // // If the initial seed is 12345, then the first three computations are // // Input Output R8_UNIFORM_01 // SEED SEED // // 12345 207482415 0.096616 // 207482415 1790989824 0.833995 // 1790989824 2035175616 0.947702 // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 April 2012 // // Author: // // John Burkardt // // Reference: // // Paul Bratley, Bennett Fox, Linus Schrage, // A Guide to Simulation, // Second Edition, // Springer, 1987, // ISBN: 0387964673, // LC: QA76.9.C65.B73. // // Bennett Fox, // Algorithm 647: // Implementation and Relative Efficiency of Quasirandom // Sequence Generators, // ACM Transactions on Mathematical Software, // Volume 12, Number 4, December 1986, pages 362-376. // // Pierre L'Ecuyer, // Random Number Generation, // in Handbook of Simulation, // edited by Jerry Banks, // Wiley, 1998, // ISBN: 0471134031, // LC: T57.62.H37. // // Peter Lewis, Allen Goodman, James Miller, // A Pseudo-Random Number Generator for the System/360, // IBM Systems Journal, // Volume 8, Number 2, 1969, pages 136-143. // // Parameters: // // Input/output, int &SEED, the "seed" value. Normally, this // value should not be 0. On output, SEED has been updated. // // Output, double R8_UNIFORM_01, a new pseudorandom variate, // strictly between 0 and 1. // { const int i4_huge = 2147483647; int k; double r; if ( seed == 0 ) { cerr << "\n"; cerr << "R8_UNIFORM_01 - Fatal error!\n"; cerr << " Input value of SEED = 0.\n"; exit ( 1 ); } k = seed / 127773; seed = 16807 * ( seed - k * 127773 ) - k * 2836; if ( seed < 0 ) { seed = seed + i4_huge; } r = ( double ) ( seed ) * 4.656612875E-10; return r; } //****************************************************************************80 void r8mat_print ( int m, int n, double a[], string title ) //****************************************************************************80 // // Purpose: // // R8MAT_PRINT prints an R8MAT. // // Discussion: // // An R8MAT is a doubly dimensioned array of R8 values, stored as a vector // in column-major order. // // Entry A(I,J) is stored as A[I+J*M] // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 September 2009 // // Author: // // John Burkardt // // Parameters: // // Input, int M, the number of rows in A. // // Input, int N, the number of columns in A. // // Input, double A[M*N], the M by N matrix. // // Input, string TITLE, a title. // { r8mat_print_some ( m, n, a, 1, 1, m, n, title ); return; } //****************************************************************************80 void r8mat_print_some ( int m, int n, double a[], int ilo, int jlo, int ihi, int jhi, string title ) //****************************************************************************80 // // Purpose: // // R8MAT_PRINT_SOME prints some of an R8MAT. // // Discussion: // // An R8MAT is a doubly dimensioned array of R8 values, stored as a vector // in column-major order. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 June 2013 // // Author: // // John Burkardt // // Parameters: // // Input, int M, the number of rows of the matrix. // M must be positive. // // Input, int N, the number of columns of the matrix. // N must be positive. // // Input, double A[M*N], the matrix. // // Input, int ILO, JLO, IHI, JHI, designate the first row and // column, and the last row and column to be printed. // // Input, string TITLE, a title. // { # define INCX 5 int i; int i2hi; int i2lo; int j; int j2hi; int j2lo; cout << "\n"; cout << title << "\n"; if ( m <= 0 || n <= 0 ) { cout << "\n"; cout << " (None)\n"; return; } // // Print the columns of the matrix, in strips of 5. // for ( j2lo = jlo; j2lo <= jhi; j2lo = j2lo + INCX ) { j2hi = j2lo + INCX - 1; if ( n < j2hi ) { j2hi = n; } if ( jhi < j2hi ) { j2hi = jhi; } cout << "\n"; // // For each column J in the current range... // // Write the header. // cout << " Col: "; for ( j = j2lo; j <= j2hi; j++ ) { cout << setw(7) << j - 1 << " "; } cout << "\n"; cout << " Row\n"; cout << "\n"; // // Determine the range of the rows in this strip. // if ( 1 < ilo ) { i2lo = ilo; } else { i2lo = 1; } if ( ihi < m ) { i2hi = ihi; } else { i2hi = m; } for ( i = i2lo; i <= i2hi; i++ ) { // // Print out (up to) 5 entries in row I, that lie in the current strip. // cout << setw(5) << i - 1 << ": "; for ( j = j2lo; j <= j2hi; j++ ) { cout << setw(12) << a[i-1+(j-1)*m] << " "; } cout << "\n"; } } return; # undef INCX } //****************************************************************************80 void r8mat_transpose_in_place ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8MAT_TRANSPOSE_IN_PLACE transposes a square R8MAT in place. // // Discussion: // // An R8MAT is a doubly dimensioned array of R8 values, stored as a vector // in column-major order. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 26 June 2008 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of rows and columns of the matrix A. // // Input/output, double A[N*N], the matrix to be transposed. // { int i; int j; double t; for ( j = 0; j < n; j++ ) { for ( i = 0; i < j; i++ ) { t = a[i+j*n]; a[i+j*n] = a[j+i*n]; a[j+i*n] = t; } } return; } //****************************************************************************80 void r8vec_copy ( int n, double a1[], double a2[] ) //****************************************************************************80 // // Purpose: // // R8VEC_COPY copies an R8VEC. // // Discussion: // // An R8VEC is a vector of R8's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 03 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the vectors. // // Input, double A1[N], the vector to be copied. // // Output, double A2[N], the copy of A1. // { int i; for ( i = 0; i < n; i++ ) { a2[i] = a1[i]; } return; } //****************************************************************************80 double r8vec_max ( int n, double r8vec[] ) //****************************************************************************80 // // Purpose: // // R8VEC_MAX returns the value of the maximum element in an R8VEC. // // Discussion: // // An R8VEC is a vector of R8's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 August 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the array. // // Input, double R8VEC[N], a pointer to the first entry of the array. // // Output, double R8VEC_MAX, the value of the maximum element. This // is set to 0.0 if N <= 0. // { int i; double value; value = r8vec[0]; for ( i = 1; i < n; i++ ) { if ( value < r8vec[i] ) { value = r8vec[i]; } } return value; } //****************************************************************************80 double r8vec_min ( int n, double r8vec[] ) //****************************************************************************80 // // Purpose: // // R8VEC_MIN returns the value of the minimum element in an R8VEC. // // Discussion: // // An R8VEC is a vector of R8's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 July 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in the array. // // Input, double R8VEC[N], the array to be checked. // // Output, double R8VEC_MIN, the value of the minimum element. // { int i; double value; value = r8vec[0]; for ( i = 1; i < n; i++ ) { if ( r8vec[i] < value ) { value = r8vec[i]; } } return value; } //****************************************************************************80 double r8vec_norm ( int n, double a[] ) //****************************************************************************80 // // Purpose: // // R8VEC_NORM returns the L2 norm of an R8VEC. // // Discussion: // // An R8VEC is a vector of R8's. // // The vector L2 norm is defined as: // // R8VEC_NORM = sqrt ( sum ( 1 <= I <= N ) A(I)^2 ). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 01 March 2003 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of entries in A. // // Input, double A[N], the vector whose L2 norm is desired. // // Output, double R8VEC_NORM, the L2 norm of A. // { int i; double v; v = 0.0; for ( i = 0; i < n; i++ ) { v = v + a[i] * a[i]; } v = sqrt ( v ); return v; } //****************************************************************************80 void r8vec_print ( int n, double a[], string title ) //****************************************************************************80 // // Purpose: // // R8VEC_PRINT prints an R8VEC. // // Discussion: // // An R8VEC is a vector of R8's. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of components of the vector. // // Input, double A[N], the vector to be printed. // // Input, string TITLE, a title. // { int i; cout << "\n"; cout << title << "\n"; cout << "\n"; for ( i = 0; i < n; i++ ) { cout << " " << setw(8) << i << ": " << setw(14) << a[i] << "\n"; } return; } //****************************************************************************80 void svsort ( int n, double d[], double v[] ) //****************************************************************************80 // // Purpose: // // SVSORT descending sorts D and adjusts the corresponding columns of V. // // Discussion: // // A simple bubble sort is used on D. // // In our application, D contains singular values, and the columns of V are // the corresponding right singular vectors. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 04 August 2016 // // Author: // // Original FORTRAN77 version by Richard Brent. // C++ version by John Burkardt. // // Reference: // // Richard Brent, // Algorithms for Minimization with Derivatives, // Prentice Hall, 1973, // Reprinted by Dover, 2002. // // Parameters: // // Input, int N, the length of D, and the order of V. // // Input/output, double D[N], the vector to be sorted. // On output, the entries of D are in descending order. // // Input/output, double V[N,N], an N by N array to be adjusted // as D is sorted. In particular, if the value that was in D(I) on input is // moved to D(J) on output, then the input column V(*,I) is moved to // the output column V(*,J). // { int i; int j1; int j2; int j3; double t; for ( j1 = 0; j1 < n - 1; j1++ ) { // // Find J3, the index of the largest entry in D[J1:N-1]. // MAXLOC apparently requires its output to be an array. // j3 = j1; for ( j2 = j1 + 1; j2 < n; j2++ ) { if ( d[j3] < d[j2] ) { j3 = j2; } } // // If J1 != J3, swap D[J1] and D[J3], and columns J1 and J3 of V. // if ( j1 != j3 ) { t = d[j1]; d[j1] = d[j3]; d[j3] = t; for ( i = 0; i < n; i++ ) { t = v[i+j1*n]; v[i+j1*n] = v[i+j3*n]; v[i+j3*n] = t; } } } return; } #include "includefirst.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dinterpreter.hpp" namespace lib { using namespace std; class param_for_brent { public: EnvT* envt; EnvUDT* nenvt; string funcname; DDoubleGDL* arg; bool failed; string errmsg; }; static param_for_brent brent_func_data; static double brent_fake_func(double* x, int n) { brent_func_data.failed=false; brent_func_data.errmsg.clear(); // use our GDL variable for storage for (SizeT i = 0; i < n; ++i) (*(brent_func_data.arg))[i] = x[i]; // executing our wrapper function with code 0 BaseGDL* res; res = brent_func_data.envt->Interpreter()->call_fun( static_cast (brent_func_data.nenvt->GetPro())->GetTree() ); Guard res_guard(res); if (res->N_Elements() != 1) { brent_func_data.failed=true; brent_func_data.errmsg = "user-defined function \""+brent_func_data.funcname+"\" must return a single non-string value"; return std::numeric_limits::quiet_NaN(); //ensure not used. } DDoubleGDL* dres; try { // BUT: Convert2(...) with CONVERT already deletes 'res' here if the type is changed dres = static_cast(res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT_THROWIOERROR)); } catch (GDLIOException& ex) { brent_func_data.failed=true; brent_func_data.errmsg = "failed to convert the result of your function to double"; dres=new DDoubleGDL(dimension(n),BaseGDL::ZERO); //we do not return, dres MUST exist! } if (res != dres) { // prevent 'res' from being deleted again res_guard.Release(); res_guard.Init(dres); } return (*dres)[0]; } //Note: this brent is not from gsl void brent(EnvT* e) { // sanity check (for number of parameters) SizeT nParam = e->NParam(); if (nParam != 5) e->Throw("Incorrect number of arguments."); // 1-st argument : initial guess vector BaseGDL* p0 = e->GetParDefined(0); BaseGDL* P = p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); // 2nd argument : Xi // 3nd argument : gtol DDouble ftol = 0; e->AssureDoubleScalarPar(2,ftol); // 4th argument : fmin. will be set on exit. //5th argument: function BaseGDL* fun= e->GetParDefined(4); DString sfun = StrUpCase((*(DStringGDL*)fun)[0]); if (LibFunIx(sfun) != -1) e->Throw("only user-defined functions allowed (library-routine name "+sfun+" given)"); static int DOUBLEIx = e->KeywordIx("DOUBLE"); bool isDouble=(p0->Type()==GDL_DOUBLE); if(e->KeywordSet(DOUBLEIx)) isDouble=true; static int ITMAXIx = e->KeywordIx("ITMAX"); DLong itmax=200; if (e->KeywordPresent(ITMAXIx)) e->AssureLongScalarKW(ITMAXIx,itmax); // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnvfun = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx(sfun)], (DObjGDL**) NULL); newEnvfun->SetNextPar(&P); e->Interpreter()->CallStack().push_back(newEnvfun); // function parameter initialization brent_func_data.envt = e; brent_func_data.nenvt = newEnvfun; brent_func_data.funcname = sfun; brent_func_data.arg = static_cast (P); double maxstepsize=1; int n=P->N_Elements(); double* x=new double[n]; for (int i=0; iKeywordIx("ITER"); bool returnIter=e->KeywordPresent(ITERIx); if (returnIter) e->SetKW(ITERIx, new DLongGDL(1)); if (isDouble) { e->SetPar(3, new DDoubleGDL(res)); e->SetPar(0, P); } else { e->SetPar(3, new DDoubleGDL(res)); Guard P_guard(P); e->SetPar(0, P->Convert2(GDL_FLOAT, BaseGDL::COPY)); } } } gdl-0.9.9/src/brent.hpp000066400000000000000000000022271340051421000147020ustar00rootroot00000000000000/*************************************************************************** brent.hpp - GDL library function ------------------- begin : Jul 12 2017 copyright : (C) 2017 by Gilles Duvert ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #ifndef BRENT_HPP_ #define BRENT_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { void brent( EnvT* e); } // namespace #endif gdl-0.9.9/src/calendar.cpp000066400000000000000000000113551340051421000153360ustar00rootroot00000000000000/*************************************************************************** calendar.cpp - basic calendar transformations ------------------- begin : 2017 copyright : (C) 2017 by G. Duvert email : gilles.duvert@free.fr ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* The intent of this file is to unify all calendar-related pieces of code used in various * places of GDL. */ #include "includefirst.hpp" #include "calendar.hpp" #include "gdlexception.hpp" using namespace std; double Gregorian2Julian(struct tm *ts) { DDouble jd; DLong day=ts->tm_mday; DLong mon=ts->tm_mon+1; DLong year=ts->tm_year+1900; DLong hour=ts->tm_hour; DLong min=ts->tm_min; DDouble sec=ts->tm_sec; if (!dateToJD(jd, day, mon, year, hour, min, sec)) throw GDLException("Invalid Julian date input."); return jd; } bool dateToJD(DDouble &jd, DLong day, DLong month, DLong year, DLong hour, DLong minute, DDouble second) { if (year < -4716 || year > 5000000 || year == 0) return false; // the following tests seem to be NOT active in IDL. We choose to mimic it. // if (month < 1 || month > 12) return false; // if (day < 0 || day > 31) return false; //these one too... // if (hour < 0 || hour > 24) return false; // if (minute < 0 || minute > 60) return false; // if (second < 0 || second > 60) return false; DDouble a, y, b; DLong m; y = (year > 0) ? year : year + 1; //we use here a calendar with no year 0 (not astronomical) m = month; b = 0.0; if (month <= 2) { y = y - 1.0; m = m + 12; } if (y >= 0) { if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day > 14)))) { a = floor(y / 100.0); b = 2.0 - a + floor(a / 4.0); } else if (year == 1582 && month == 10 && day >= 5 && day <= 14) { jd = 2299161; //date does not move return true; } } jd = floor(365.25 * y) + floor(30.6001 * (m + 1)) + day + (hour * 1.0) / 24.0 + (minute * 1.0) / 1440.0 + (second * 1.0) / 86400.0 + 1720994.50 + b; return true; } // C code **************************************************** bool j2ymdhms(DDouble jd, DLong &iMonth, DLong &iDay , DLong &iYear , DLong &iHour , DLong &iMinute, DDouble &Second, DLong &dow, DLong &icap) { DDouble JD,Z,F; DLong A,B,C,D,E; JD = jd + 0.5; Z = floor(JD); if (Z < -1095 || Z > 1827933925 ) return FALSE; F = JD - Z; // note that IDL dow is false before Sun dec 31 12:00:00 -4714, (type: a=[-2,-1]& PRINT, FORMAT='(C())',a) // ...and ... we are not! if ((DLong)Z > 0) dow = ((DLong)Z) % 7; else dow = ((DLong)Z+1099) % 7; //just translate axis... if (Z < 2299161) A = (DLong)Z; else { DDouble a; a = (DLong) ((Z - 1867216.25) / 36524.25); A = (DLong) (Z + 1 + a - (DLong)(a / 4)); } B = A + 1524; C = (DLong) ((B - 122.1) / 365.25); D = (DLong) (365.25 * C); E = (DLong) ((B - D) / 30.6001); // month iMonth = E < 14 ? E - 1 : E - 13; iMonth--; //to get a zero-based index; // iday iDay=B - D - (DLong)(30.6001 * E); // year // iYear = iMonth > 2 ? C - 4716 : C - 4715; iYear = iMonth > 1 ? C - 4716 : C - 4715; //with a zero-based index if (iYear < 1) iYear--; //No Year Zero // hours iHour = (DLong) (F * 24); { //this prevents interpreting 04:00:00 as 03:59:60 ! //this kind of rounding up is explained in IDL doc. DDouble FF=F+6E-10; DLong test= (DLong) (FF * 24); if (test > iHour) {iHour=test;F=FF;} } icap = (iHour > 11); F -= (DDouble)iHour / 24; // minutes iMinute = (DLong) (F * 1440); { //this prevents interpreting 04:00:00 as 03:59:60 ! //this kind of rounding up is explained in IDL doc. DDouble FF=F+6E-10; DLong test= (DLong) (FF * 1440); if (test > iMinute) {iMinute=test;F=FF;} } F -= (DDouble)iMinute / (DDouble)1440; // seconds Second = F * 86400; return TRUE; } gdl-0.9.9/src/calendar.hpp000066400000000000000000000026131340051421000153400ustar00rootroot00000000000000/*************************************************************************** calendar.cpp - basic calendar transformations ------------------- begin : 2017 copyright : (C) 2017 by G. Duvert email : gilles.duvert@free.fr ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CALENDAR_HPP_ #define CALENDAR_HPP_ #include "basegdl.hpp" // DLong double Gregorian2Julian(struct tm *ts); bool dateToJD(DDouble &jd, DLong day, DLong month, DLong year, DLong hour, DLong minute, DDouble second); bool j2ymdhms(DDouble jd, DLong &iMonth, DLong &iDay , DLong &iYear , DLong &iHour , DLong &iMinute, DDouble &Second, DLong &dow, DLong &icap); #endif gdl-0.9.9/src/cformat.g000066400000000000000000000117021340051421000146600ustar00rootroot00000000000000/* ************************************************************************* cformat.g - parser for GDL format strings ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@hotmail.com ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ header "pre_include_cpp" { #include "includefirst.hpp" #include } header { #include // using namespace antlr; } options { language="Cpp"; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the C-Format Lexer ********************************************* class CFMTLexer extends Lexer; options { charVocabulary = '\3'..'\377'; caseSensitive=true ; testLiterals =true; caseSensitiveLiterals=false; exportVocab=CFMT; k=2; defaultErrorHandler = false; // defaultErrorHandler = true; } { private: antlr::TokenStreamSelector* selector; bool doubleQuotes; bool format; public: void SetSelector( antlr::TokenStreamSelector& s) { selector = &s; } void DoubleQuotes( bool dQ) { doubleQuotes = dQ; format=false; } } CSTYLE : { format}? ( ( ( CD { $setType(CD);} | CSE { $setType(CSE);} | CE { $setType(CE);} | CI { $setType(CI);} | CF { $setType(CF);} | CSG { $setType(CSG);} | CG { $setType(CG);} | CO { $setType(CO);} | CB { $setType(CB);} | CS { $setType(CS);} | CX { $setType(CX);} | CZ { $setType(CZ);} ) { format = false;} ) | PM { $setType(PM);} | MP { $setType(MP);} | MOINS { $setType(MOINS);} | PLUS { $setType(PLUS);} | CNUMBER { $setType(CNUMBER);} | CDOT { $setType(CDOT);} | CWS { _ttype=antlr::Token::SKIP; } ) | CSTR { $setType(CSTR);} ; protected CSTR : { doubleQuotes}? ( CSTR1 ( '\"'! { selector->pop();} | '%'! { format = true;} ) ) | ( CSTR2 ( '\''! { selector->pop();} | '%'! { format = true;} ) ) ; protected CSTR1 : ( '%'! '%' | ESC | ~('%' | '\"' | '\\'))* ; protected CSTR2 : ( '%'! '%' | ESC | ~('%' | '\'' | '\\'))* ; protected ESC : '\\'! ( ('a'|'A')! { $setText( "\7");} | ('b'|'B')! { $setText( "\b");} | ('f'|'F')! { $setText( "\f");} | ('n'|'N')! { $setText( "\n");} | ('r'|'R')! { $setText( "\r");} | ('t'|'T')! { $setText( "\t");} | ('v'|'V')! { $setText( "\13");} | OCTESC | ('x'|'X')! HEXESC | ~('a'|'A'|'b'|'B'|'f'|'F'|'n'|'N'|'r'|'R'|'t'|'T'|'v'|'V'| '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'x'|'X') // just insert ) ; protected OCTESC : ODIGIT (options {greedy=true;}: ODIGIT (options {greedy=true;}: ODIGIT)?)? { std::string s = $getText; char c = static_cast(strtoul(s.c_str(),NULL,8)); $setText( c); } ; protected ODIGIT: ('0'..'7'); protected HEXESC : HDIGIT (options {greedy=true;}: HDIGIT)? { std::string s = $getText; char c = static_cast(strtoul(s.c_str(),NULL,16)); $setText( c); } ; protected HDIGIT: ('0'..'9'|'a'..'f'|'A'..'F'); protected CD: ('d'|'D'); protected CSE: ('e'); protected CE: ('E'); protected CI: ('i'|'I'); protected CF: ('f'|'F'); protected CSG: ('g'); protected CG: ('G'); protected CO: ('o'|'O'); protected CB: ('b'|'B'); protected CS: ('s'|'S'); protected CX: ('x'|'X'); protected CZ: ('z'|'Z'); protected CDOT:'.'; protected PM: ('+' '-'); protected MP: ('-' '+'); protected PLUS: '+'; protected MOINS: '-'; protected DIGITS : ('0'..'9')+ ; protected CNUMBER : DIGITS ; protected CWS : (' '| '\t')+ ; gdl-0.9.9/src/color.cpp000066400000000000000000000114761340051421000147070ustar00rootroot00000000000000/*************************************************************************** color.cpp - GDL routines for color handling ------------------- begin : March 25 2004 copyright : (C) 2004 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "color.hpp" #include #ifdef _MSC_VER #define round(f) floor(f+0.5) #endif using namespace std; const DFloat maxDByte = 255.0; void RGB2HSV( const DByte r, const DByte g, const DByte b, DFloat& h, DFloat& s, DFloat& v ) { DByte cmin = (r < g)? ((r < b)? r : b) : ((g < b)? g : b); DByte cmax = (r > g)? ((r > b)? r : b) : ((g > b)? g : b); v = static_cast(cmax) / maxDByte; // v DFloat delta = static_cast(cmax - cmin); if( cmax != 0) s = delta / static_cast(cmax); // s else { // r = g = b = 0 -> s = 0 -> h undefined s = 0.0; h = 0.0; // undefined return; } if( s == 0.0) { h = 0.0; // s = 0 -> h undefined return; } if( r == cmax ) h = static_cast( g - b) / delta; // between yellow & magenta else if( g == cmax ) h = 2.0 + static_cast( b - r) / delta; // between cyan & yellow else // ( b == cmax) h = 4.0 + static_cast( r - g) / delta; // between magenta & cyan h *= 60.0; // degrees if( h < 0.0 ) h += 360.0; } void HSV2RGB( DFloat h, const DFloat s, const DFloat v, DByte& r, DByte& g, DByte& b) { DFloat maxDByteV = v * maxDByte; if( s == 0.0) { // grey r = g = b = static_cast< DByte>(round( maxDByteV)); return; } h /= 360.0; // [0,1]*n h = h - floor(h); // [0,1] h *= 6.0; // sector 0 to 5 DFloat fh = floor( h); DFloat f = h - fh; // factorial part of h DByte p = static_cast< DByte>(round( ( 1.0 - s) * maxDByteV)); DByte q = static_cast< DByte>(round( ( 1.0 - s * f) * maxDByteV)); DByte t = static_cast< DByte>(round( ( 1.0 - s * (1.0 - f)) * maxDByteV)); int i = static_cast< int>( fh); switch( i) { case 0: r = static_cast< DByte>(round( v * maxDByte)); g = t; b = p; break; case 1: r = q; g = static_cast< DByte>(round( v * maxDByte)); b = p; break; case 2: r = p; g = static_cast< DByte>(round( v * maxDByte)); b = t; break; case 3: r = p; g = q; b = static_cast< DByte>(round( v * maxDByte)); break; case 4: r = t; g = p; b = static_cast< DByte>(round( v * maxDByte)); break; default: // case 5: r = static_cast< DByte>(round( v * maxDByte)); g = p; b = q; break; } } void RGB2HLS( const DByte r, const DByte g, const DByte b, DFloat& h, DFloat& l, DFloat& s) { DFloat cmin = (r < g)? ((r < b)? r : b) : ((g < b)? g : b); DFloat cmax = (r > g)? ((r > b)? r : b) : ((g > b)? g : b); l = (cmax+cmin) / maxDByte / 2.0; if( cmax == cmin) { s = h = 0.0; // undefined return; } DFloat delta = cmax - cmin; if( l < 0.5) s = delta/(cmax+cmin); else s = delta/(2.0 * maxDByte - cmax - cmin); if( r == cmax) h = static_cast((g-b)) / delta; else if( g == cmax) h = 2.0 + static_cast((b - r)) / delta; else h = 4.0 + static_cast((r - g)) / delta; h *= 60.0; // degrees if( h < 0.0 ) h += 360.0; } DFloat Hue2RGB( const DFloat m1, const DFloat m2, DFloat h) { h = h - floor(h); if( h < 1.0/6.0) return (m1+(m2-m1)*h*6.0); if( h < 1.0/2.0) return m2; if( h < 2.0/3.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0); return m1; } void HLS2RGB( DFloat h, const DFloat l, const DFloat s, DByte& r, DByte& g, DByte& b) { if( s == 0.0) r = g = b = static_cast< DByte>(round( l * maxDByte)); else { h /= 360.0; // -> [0,1] DFloat m2; if (l <= 0.5) m2 = l*(1.0+s); else m2 = l+s-l*s; DFloat m1 = 2.0*l-m2; r = static_cast< DByte>(round( Hue2RGB(m1,m2,h+1.0/3.0) * maxDByte)); g = static_cast< DByte>(round( Hue2RGB(m1,m2,h) * maxDByte)); b = static_cast< DByte>(round( Hue2RGB(m1,m2,h-1.0/3.0) * maxDByte)); } } gdl-0.9.9/src/color.hpp000066400000000000000000000030361340051421000147050ustar00rootroot00000000000000/*************************************************************************** color.hpp - GDL routines for color handling ------------------- begin : March 25 2004 copyright : (C) 2004 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef COLOR_HPP_ #define COLOR_HPP_ #include "basegdl.hpp" // h = [0,360], s = [0,1], v = [0,1], l = [0,1] void RGB2HSV( const DByte r, const DByte g, const DByte b, DFloat& h, DFloat& s, DFloat& v ); void HSV2RGB( DFloat h, const DFloat s, const DFloat v, DByte& r, DByte& g, DByte& b); void RGB2HLS( const DByte r, const DByte g, const DByte b, DFloat& h, DFloat& l, DFloat& s); void HLS2RGB( const DFloat h, const DFloat l, const DFloat s, DByte& r, DByte& g, DByte& b); #endif gdl-0.9.9/src/convert2.cpp000066400000000000000000002420561340051421000153330ustar00rootroot00000000000000/*************************************************************************** convert2.cpp - convert one datatype into another ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // TODO: adjust the with for string conversion for each type (i2s((*this)[i],X)) // Convert2( DType) functions #include "includefirst.hpp" //#include "datatypes.hpp" #include "dstructgdl.hpp" #include "real2int.hpp" #include "ofmt.hpp" // OutAuto #include "dinterpreter.hpp" using namespace std; //#define TRACE_CONVERT2 cout << "Convert2 " << this->TypeStr() << " -> " << destTy << "\tn " << dd.size() << "\tmode " << mode << endl; #define TRACE_CONVERT2 #define SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { (*dest)[0]=(*this)[0]; if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest;} // for double -> string inline string double2string( const DDouble d) { std::ostringstream os; OutAuto( os, d, 16, 8, 0); return os.str(); } // for float -> string inline string float2string( const DFloat f) { std::ostringstream os; OutAuto( os, f, 13, 6, 0); return os.str(); } // for string -> float/double template inline real_t string2real_helper(const char* cStart, char** cEnd); template <> inline float string2real_helper(const char* cStart, char** cEnd) { #ifdef _MSC_VER return StrToD(cStart, cEnd); #else return strtof(cStart, cEnd); #endif } template <> inline double string2real_helper(const char* cStart, char** cEnd) { return StrToD(cStart, cEnd); } template inline real_t string2real(const char* cStart, char** cEnd) { const char* d = strpbrk(cStart, "Dd"); if (d == NULL) return string2real_helper(cStart, cEnd); else { string tmps(cStart); tmps[d - cStart] = 'E'; char* tmpcp; real_t tmpf = string2real_helper(tmps.c_str(), &tmpcp); *cEnd = const_cast(cStart) + (tmpcp - tmps.c_str()); return tmpf; } } // every type need this function which defines its conversion to all other types // so for every new type each of this functions has to be extended // and a new function has to be 'specialized' // not very nice, but how else to do? // each function creates the new type on the heap // non convertables BaseGDL* DStructGDL::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); //DInterpreter* testDbg = BaseGDL::interpreter; //int szDbg = BaseGDL::interpreter->CallStack().size(); if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Struct expression not allowed in this context: "+BaseGDL::interpreter->Name(this)); throw GDLException("Struct expression not allowed in this context."); return NULL; // get rid of warning } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Ptr expression not allowed in this context: "+BaseGDL::interpreter->Name(this)); throw GDLException("Ptr expression not allowed in this context."); return NULL; // get rid of warning } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Object expression not allowed in this context: "+BaseGDL::interpreter->Name(this)); throw GDLException("Object expression not allowed in this context."); return NULL; // get rid of warning } // the real Convert2 functions template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { // case GDL_BYTE: case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: // GDL_BYTE to GDL_STRING: remove first dim { if( mode == BaseGDL::COPY_BYTE_AS_INT) { Data_* dest=new Data_( dim, BaseGDL::NOZERO); // TRACEOMP( __FILE__, __LINE__) // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=i2s(static_cast((*this)[i]),4); // } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } else { dimension strDim( dim); SizeT strLen = strDim.Remove( 0); if (strLen == 0) strLen = 1; nEl /= strLen; char *buf = new char[ strLen+1]; ArrayGuard guard( buf); buf[ strLen] = 0; Data_* dest = new Data_( strDim, BaseGDL::NOZERO); for( SizeT i=0; i < nEl; ++i) { SizeT basePtr = i*strLen; for( SizeT b=0; bCallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } return NULL; // get rid of warning } // GDL_BYTE template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_INT: case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // This does not work, as the type constant is not changed // if( (mode & BaseGDL::CONVERT) != 0) // return reinterpret_cast*>(this); // else // return reinterpret_cast*>(this->Dup()); case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; // (*dest)[i]=static_cast((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=i2s((*this)[i],8); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } // GDL_INT template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // if( (mode & BaseGDL::CONVERT) != 0) // return reinterpret_cast*>(this); // else // return reinterpret_cast*>(this->Dup()); // case GDL_UINT: case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=i2s((*this)[i],8); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } // GDL_UINT template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_LONG: case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // if( (mode & BaseGDL::CONVERT) != 0) // return reinterpret_cast*>(this); // else // return reinterpret_cast*>(this->Dup()); case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=i2s((*this)[i],12); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } // GDL_LONG template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // if( (mode & BaseGDL::CONVERT) != 0) // return reinterpret_cast*>(this); // else // return reinterpret_cast*>(this->Dup()); // case GDL_ULONG: case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=i2s((*this)[i],12); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } // GDL_ULONG template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { (*dest)[0]=Real2DByte((*this)[0]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2DByte((*this)[i]); } //(*dest)[i]=Real2DByte((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { (*dest)[0]=Real2Int((*this)[0]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { (*dest)[0]= static_cast< DUInt>( ((*this)[0]));//Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]= static_cast< DUInt>( ((*this)[i]));//Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { (*dest)[0]=Real2Int((*this)[0]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=static_cast< DULong>( ((*this)[i]));//Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong>( ((*this)[i]));//Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=static_cast< DULong64>( ((*this)[i]));//Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong64>( ((*this)[i]));//Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_FLOAT: case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=float2string((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=Real2DByte((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2DByte((*this)[i]); //(*dest)[i]=Double2DByte((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=static_cast< DUInt>((*this)[i]);//Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DUInt>((*this)[i]);//Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=static_cast< DULong>((*this)[i]);//Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong>((*this)[i]);//Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) { const SizeT i = 0; (*dest)[i]=static_cast< DULong64>((*this)[i]);//Real2Int((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong64>((*this)[i]);//Real2Int((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_DOUBLE: case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=double2string((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } inline void StringConversionError( bool& errorFlag, BaseGDL::Convert2Mode mode, const string& msg) { if( (mode & BaseGDL::THROWIOERROR) != 0) { errorFlag = true; /* delete dest; throw GDLIOException( msg);*/ } else Warning( msg); } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); bool errorFlag = false; switch( destTy) { case GDL_BYTE: // GDL_STRING to GDL_BYTE: add first dim { SizeT maxLen = 1; // empty string is converted to 0b for( SizeT i=0; i < nEl; ++i) if( (*this)[i].length() > maxLen) maxLen = (*this)[i].length(); dimension bytDim( dim); bytDim >> maxLen; Data_* dest=new Data_( bytDim); // zero fields TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { SizeT basePtr = i*maxLen; SizeT strLen = (*this)[ i].length(); for( SizeT b=0; b* dest=new Data_( dim, BaseGDL::NOZERO); // TRACEOMP( __FILE__, __LINE__) // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) // { // #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to INT."); } } // } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to INT."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=strtoul(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to UINT."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to UINT."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to LONG."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to LONG."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=strtoul(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to ULONG."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to ULONG."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to LONG64."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to LONG64."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=strtoul(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to ULONG64."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to ULONG64."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i] = string2real(cStart, &cEnd); if((cEnd == cStart && (*this)[i] != "")) // || (cEnd - cStart) != strlen(cStart)) // reports error for "16 " { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to FLOAT."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to FLOAT."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i] = string2real( cStart, &cEnd); if( (cEnd == cStart && (*this)[i] != "")) // || (cEnd - cStart) != strlen(cStart)) // reports error for "16 " { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to DOUBLE."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to DOUBLE."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_STRING: case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=string2real(cStart,&cEnd); if((cEnd == cStart && (*this)[i] != "")) // || (cEnd - cStart) != strlen(cStart)) // reports error for "16 " { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to COMPLEX."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to COMPLEX."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( errorFlag, mode) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) { const char* cStart=(*this)[i].c_str(); char* cEnd; (*dest)[i]=string2real(cStart,&cEnd); if((cEnd == cStart && (*this)[i] != "")) // || (cEnd - cStart) != strlen(cStart)) // reports error for "16 " { StringConversionError( errorFlag, mode, "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[i]+"' to DCOMPLEX."); } } } if( errorFlag) { delete dest; if( (mode & BaseGDL::CONVERT) != 0) delete this; throw GDLIOException( "Type conversion error: Unable to convert given STRING to DCOMPLEX."); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2DByte(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2DByte(real((*this)[i])); } //(*dest)[i]=Real2DByte(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=static_cast< DUInt>(real((*this)[i]));//Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DUInt>(real((*this)[i]));//Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=static_cast< DULong>(real((*this)[i]));//Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong>(real((*this)[i]));//Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=static_cast< DULong64>(real((*this)[i]));//Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong64>(real((*this)[i]));//Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=real((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=real((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=real((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=real((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]="("+i2s(real((*this)[i]))+","+i2s(imag((*this)[i]))+")"; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_COMPLEX: case GDL_COMPLEXDBL: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } return NULL; // get rid of warning } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2DByte(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2DByte(real((*this)[i])); } //(*dest)[i]=Double2DByte(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=static_cast< DUInt>(real((*this)[i]));//Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DUInt>(real((*this)[i]));//Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=static_cast< DULong>(real((*this)[i]));//Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong>(real((*this)[i]));//Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; } return dest; } case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=static_cast< DULong64>(real((*this)[i]));//Real2Int(real((*this)[i])); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=static_cast< DULong64>(real((*this)[i]));//Real2Int(real((*this)[i])); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=real((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=real((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i]=real((*this)[i]); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=real((*this)[i]); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]="("+i2s(real((*this)[i]))+","+i2s(imag((*this)[i]))+")"; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); #ifdef SINGLE_ELEMENT_OPTIMIZATION if( nEl == 1) \ { const SizeT i = 0; (*dest)[i] = DComplex( static_cast((*this)[i].real()), static_cast((*this)[i].imag()) ); if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } #endif // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) //{ // #pragma omp for for( SizeT i=0; i < nEl; ++i) // (*dest)[i] = DComplex( static_cast((*this)[i].real()), // static_cast((*this)[i].imag()) ); //} (*dest)[i]=(*this)[i]; if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_COMPLEXDBL: case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } return NULL; // get rid of warning } // 64 bit integers template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // case GDL_LONG64: case GDL_ULONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // if( (mode & BaseGDL::CONVERT) != 0) // return reinterpret_cast*>(this); // else // return reinterpret_cast*>(this->Dup()); case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=i2s((*this)[i],22); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } template<> BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode mode) { TRACE_CONVERT2 if( destTy == t) return (((mode & BaseGDL::COPY) != 0)?Dup():this); SizeT nEl=dd.size(); switch( destTy) { case GDL_BYTE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_INT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_UINT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_ULONG: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_LONG64: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } // if( (mode & BaseGDL::CONVERT) != 0) // return reinterpret_cast*>(this); // else // return reinterpret_cast*>(this->Dup()); // case GDL_ULONG64: case GDL_FLOAT: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_DOUBLE: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_STRING: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*dest)[i]=i2s((*this)[i],22); } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEX: { Data_* dest=new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_COMPLEXDBL: { Data_* dest= new Data_( dim, BaseGDL::NOZERO); SINGLE_ELEMENT_OPTIMIZATION // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for( SizeT i=0; i < nEl; ++i) (*dest)[i]=(*this)[i]; } if( (mode & BaseGDL::CONVERT) != 0) delete this; return dest; } case GDL_PTR: case GDL_OBJ: case GDL_STRUCT: case GDL_UNDEF: default: if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Cannot convert to this type."); throw GDLException("Cannot convert to this type."); } // get rid of warning return NULL; } gdl-0.9.9/src/convol.cpp000066400000000000000000000346171340051421000150730ustar00rootroot00000000000000/*************************************************************************** convol.cpp - convol(), defines all datatypes ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens : 2018 by Gilles Duvert email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "nullgdl.hpp" #include "dstructgdl.hpp" #include "dinterpreter.hpp" template inline bool gdlValid( const T &value ) { T max_value = std::numeric_limits::max(); T min_value = - max_value; return ( ( min_value <= value && value <= max_value ) && (value == value)); } inline bool gdlValid( const DComplex &value ) { DFloat max_value = std::numeric_limits::max(); DFloat min_value = - max_value; return ( ( min_value <= value.real() && value.real() <= max_value ) && (value.real() == value.real()))&& ( ( min_value <= value.imag() && value.imag() <= max_value ) && (value.imag() == value.imag())); } inline bool gdlValid( const DComplexDbl &value ) { DDouble max_value = std::numeric_limits::max(); DDouble min_value = - max_value; return ( ( min_value <= value.real() && value.real() <= max_value ) && (value.real() == value.real()))&& ( ( min_value <= value.imag() && value.imag() <= max_value ) && (value.imag() == value.imag())); } template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { throw GDLException("String expression not allowed in this context."); } template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { throw GDLException("Object expression not allowed in this context."); } template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn,BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { throw GDLException("Pointer expression not allowed in this context."); } #define INCLUDE_CONVOL_CPP 1 #define CONVOL_BYTE__ #include "convol_inc.cpp" #undef CONVOL_BYTE__ #define CONVOL_UINT__ #include "convol_inc.cpp" #undef CONVOL_UINT__ #define CONVOL_INT__ #include "convol_inc.cpp" #undef CONVOL_INT__ #define CONVOL_ULONG__ #include "convol_inc.cpp" #undef CONVOL_ULONG__ #define CONVOL_ULONG64__ #include "convol_inc.cpp" #undef CONVOL_ULONG64__ #define Sp SpDLong64 #define Ty DLong64 #include "convol_inc.cpp" #undef Sp #undef Ty #define Sp SpDLong #define Ty DLong #include "convol_inc.cpp" #undef Sp #undef Ty #define Sp SpDFloat #define Ty DFloat #include "convol_inc.cpp" #undef Sp #undef Ty #define Sp SpDDouble #define Ty DDouble #include "convol_inc.cpp" #undef Sp #undef Ty #define Sp SpDComplex #define Ty DComplex #include "convol_inc.cpp" #undef Sp #undef Ty #define Sp SpDComplexDbl #define Ty DComplexDbl #include "convol_inc.cpp" #undef Sp #undef Ty #undef INCLUDE_CONVOL_CPP namespace lib { /*****************************************convol_fun*********************************************************/ BaseGDL* convol_fun( EnvT* e) { long nParam=e->NParam( 2); /************************************Checking_parameters************************************************/ BaseGDL* p0 = e->GetNumericParDefined( 0); if( p0->Rank() == 0) e->Throw( "Expression must be an array in this context: "+ e->GetParString(0)); BaseGDL* p1 = e->GetNumericParDefined( 1); if( p1->Rank() == 0) e->Throw( "Expression must be an array in this context: "+ e->GetParString(1)); if( p0->N_Elements() < p1->N_Elements()) e->Throw( "Incompatible dimensions for Array and Kernel."); // rank 1 for kernel works always if( p1->Rank() != 1) { long rank = p0->Rank(); if (rank != p1->Rank()) e->Throw("Incompatible dimensions for Array and Kernel."); for (long r = 0; r < rank; ++r) if (p0->Dim(r) < p1->Dim(r)) e->Throw("Incompatible dimensions for Array and Kernel."); } else { //check however that kernel is not too big... if (p0->Dim(0) < p1->Dim(0)) e->Throw("Incompatible dimensions for Array and Kernel."); } //compute some interesting values about kernel and array dimensions int maxposK=0,curdimK,sumofdimsK=0,maxdimK=-1; int maxpos=0, curdimprod, maxdimprod=-1; for (int i=0; iRank(); ++i) { curdimK=p1->Dim(i); sumofdimsK+=curdimK; if (curdimK>maxdimK) { maxdimK=curdimK; maxposK=i; } } // If kernel is not 1-D, test which dimension is larger. Transposing the data and kernel to have this dimension first is faster since // it is the kernel sum which is parallelized here. // Probably there is a minimum difference in size (magicfactor=1.2 ? 1.5?) at which one would benefit given the added complexity of transposition. bool doTranspose=false; if (sumofdimsK > maxdimK+(p1->Rank())-1) { // Now about dimensions. // convolution code (in convol_inc*.pro) is quite tricky. Only the inner part of the loop can be safely parallelized. // It is a double loop on the first dimension of kernel (kDim0) times the first dimension of the array (dim0 or aEnd0-aBeg0). // To benefit from this speedup, we need to have dim0*kDim0 maximum: // find largest array or kernel dimension; transpose array, makes for faster convol, will be // transposed back at end. // find maximum of dim0xkDim0 for (int i = 0; i < p1->Rank(); ++i) { //0->Rank and p1->Rank same here curdimprod = p1->Dim(i)*p0->Dim(i); if (curdimprod > maxdimprod) { maxdimprod = curdimprod; maxpos = i; } } float magicfactor=2.0; if ( maxdimprod > magicfactor*p1->Dim(0)*p0->Dim(0) ) doTranspose=true; } // array of dims for transpose DUInt* perm = new DUInt[p0->Rank()]; //direct DUInt* mrep = new DUInt[p0->Rank()]; //reverse ArrayGuard perm_guard(perm); ArrayGuard mrep_guard(mrep); if (doTranspose) { DUInt i = 0, j = 0; for (i = 0; i < p0->Rank(); ++i) if (i != maxpos) { perm[j + 1] = i; j++; } perm[0] = maxpos; for (i = 0; i < p0->Rank(); ++i) mrep[i]=i; //populate reverse for (i = 0; i < maxpos+1; ++i) mrep[i]=i+1; //this and the following line should give the reverse transpose order. mrep[maxpos]=0; } /***************************************Preparing_matrices*************************************************/ //Computations for REAL and COMPLEX are better made in double precision if we do not want to lose precision //Apparently IDL has severe problems regarding this loss of precision. // try for example the following, which should give exactly ZERO: // C=32*32*0.34564 & a=findgen(100,100)*0.0+1 & b=convol(a,fltarr(32,32)+0.34564) & print,(b-c)[20:80,50],format='(4(F20.12))' //So, we convert p0 to Double precision if necessary and convert back result. //Do it here since all other parameters are converted to p0's type. Guard p0Guard; bool deprecise=false; if (p0->Type() == GDL_FLOAT) { p0 = p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); p0Guard.Reset(p0); deprecise=true; } else if (p0->Type() == GDL_COMPLEX) { p0 = p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY); p0Guard.Reset(p0); deprecise=true; } // convert kernel to array type Guard p1Guard; if (p0->Type() == GDL_BYTE || p0->Type() == GDL_UINT || p0->Type() == GDL_INT) { if (p1->Type() != GDL_LONG) { p1 = p1->Convert2(GDL_LONG, BaseGDL::COPY); p1Guard.Reset(p1); } } else if (p0->Type() != p1->Type()) { p1 = p1->Convert2(p0->Type(), BaseGDL::COPY); p1Guard.Reset(p1); } BaseGDL* scale; Guard scaleGuard; if (nParam > 2) { scale = e->GetParDefined(2); if (scale->Rank() > 0) e->Throw("Expression must be a scalar in this context: " + e->GetParString(2)); // p1 here handles GDL_BYTE||GDL_UINT||GDL_INT case also if (p1->Type() != scale->Type()) { scale = scale->Convert2(p1->Type(), BaseGDL::COPY); scaleGuard.Reset(scale); } } else { scale = p1->New(1, BaseGDL::ZERO); } /********************************************Arguments_treatement***********************************/ bool center = true; static int centerIx = e->KeywordIx( "CENTER"); if( e->KeywordPresent( centerIx)) { DLong c; e->AssureLongScalarKW( centerIx, c); center = (c != 0); } // overrides EDGE_TRUNCATE static int edge_wrapIx = e->KeywordIx( "EDGE_WRAP"); bool edge_wrap = e->KeywordSet( edge_wrapIx); static int edge_truncateIx = e->KeywordIx( "EDGE_TRUNCATE"); bool edge_truncate = e->KeywordSet( edge_truncateIx); static int edge_zeroIx = e->KeywordIx( "EDGE_ZERO"); bool edge_zero = e->KeywordSet( edge_zeroIx); static int edge_mirrorIx = e->KeywordIx( "EDGE_MIRROR"); bool edge_mirror = e->KeywordSet( edge_mirrorIx); int edgeMode = 0; if( edge_wrap) edgeMode = 1; else if( edge_truncate) edgeMode = 2; else if( edge_zero) edgeMode = 3; else if(edge_mirror) edgeMode = 4; // p0, p1 and scale have same type // p1 has rank of 1 or same rank as p0 with each dimension smaller than p0 // scale is a scalar /***********************************Parameter_BIAS**************************************/ static int biasIx = e->KeywordIx("BIAS"); bool statusBias = e->KeywordPresent(biasIx); // DLong bias=0; BaseGDL* bias; Guard biasGuard; if (statusBias) { bias = e->GetKW(biasIx); // p1 here handles GDL_BYTE||GDL_UINT||GDL_INT case also if (p1->Type() != bias->Type()) { bias = bias->Convert2(p1->Type(), BaseGDL::COPY); biasGuard.Reset(bias); } } else bias = p1->New(1, BaseGDL::ZERO); /***********************************Parameter_Normalize**********************************/ static int normalIx = e->KeywordIx( "NORMALIZE"); bool normalize = e->KeywordPresent( normalIx); /***********************************Parameter NAN****************************************/ static int nanIx = e->KeywordIx( "NAN"); bool doNan = e->KeywordSet( nanIx); /***********************************Parameter MISSING************************************/ static int missingIx = e->KeywordIx("MISSING"); bool doMissing = e->KeywordPresent(missingIx); BaseGDL* missing; Guard missGuard; if (doMissing) { missing = e->GetKW(missingIx); if (p0->Type() != missing->Type()) { missing = missing->Convert2(p0->Type(), BaseGDL::COPY); missGuard.Reset(missing); } } else missing = p0->New(1, BaseGDL::ZERO); /***********************************Parameter INVALID************************************/ static int invalidIx = e->KeywordIx("INVALID"); bool doInvalid = e->KeywordPresent( invalidIx ); BaseGDL* invalid; Guard invalGuard; if (doInvalid) { invalid = e->GetKW(invalidIx); if (p0->Type() != invalid->Type()) { invalid = invalid->Convert2(p0->Type(), BaseGDL::COPY); invalGuard.Reset(invalid); } } else invalid = p0->New(1, BaseGDL::ZERO); if (!doNan && !doInvalid) doMissing=false; if (!doMissing && p0->Type()==GDL_FLOAT) { DFloat tmp=std::numeric_limits::quiet_NaN(); memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); } if (!doMissing && p0->Type()==GDL_DOUBLE){ DDouble tmp=std::numeric_limits::quiet_NaN(); memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); } //populating a Complex with Nans is not easy as there is no objective method for that. if (!doMissing && p0->Type()==GDL_COMPLEX) { DComplex tmp=std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); } if (!doMissing && p0->Type()==GDL_COMPLEXDBL) { DComplexDbl tmp=std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); } BaseGDL* result; //handle transpositions if (doTranspose) { BaseGDL* input; Guard inputGuard; input = p0->Transpose(perm); inputGuard.Reset(input); BaseGDL* transpP1; Guard transpP1Guard; transpP1=p1->Transpose(perm); transpP1Guard.Reset(transpP1); result=input->Convol(transpP1, scale, bias, center, normalize, edgeMode, doNan, missing, doMissing, invalid, doInvalid)->Transpose(mrep); } else result=p0->Convol( p1, scale, bias, center, normalize, edgeMode, doNan, missing, doMissing, invalid, doInvalid); if (deprecise) { Guard resultGuard; resultGuard.reset(result); if (p0->Type() == GDL_DOUBLE) return result->Convert2(GDL_FLOAT, BaseGDL::COPY); else if (p0->Type() == GDL_COMPLEXDBL) return result->Convert2(GDL_COMPLEX, BaseGDL::COPY); else return result; //should not happen! } else return result; } //end of convol_fun }//end of namespacegdl-0.9.9/src/convol.hpp000066400000000000000000000023171340051421000150700ustar00rootroot00000000000000/*************************************************************************** convol.hpp - Convolution GDL library function ------------------- begin : Jun 21 2013 copyright : (C) 2013, G. Duvert 2017 email : ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #ifndef CONVOL_HPP_ #define CONVOL_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* convol_fun( EnvT* e); } // namespace #endif gdl-0.9.9/src/convol_inc.cpp000066400000000000000000001050631340051421000157160ustar00rootroot00000000000000/*************************************************************************** convol.cpp - convol function ------------------- begin : Sep 19 2004 copyright : (C) 2004 by Marc Schellens, 2017 by G. Duvert email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // optimized version // to be included from datatypes.cpp (twice) #ifdef INCLUDE_CONVOL_CPP using namespace std; #define CONVERT_CONVOL_TO_ORIG if(res_a>CONVOL_TRUNCATE_MIN){if(res_aCONVOL_TRUNCATE_MAX) bias=CONVOL_TRUNCATE_MAX;} #if defined (CONVOL_BYTE__) #define CONVOL_TRUNCATE_MIN 0 #define CONVOL_TRUNCATE_MAX 255 template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* biasIn, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { Data_* kernel = static_cast*>( kIn); Data_* dabskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Data_* dbiaskern = new Data_( kIn->Dim(), BaseGDL::ZERO); DLong* absker = static_cast( dabskern->DataAddr()); DLong* biasker = static_cast( dbiaskern->DataAddr()); DLong scale = (*static_cast*>( scaleIn))[0]; // the result to be returned Data_* res = New( dim, BaseGDL::ZERO); DLong* ker = static_cast( kernel->DataAddr()); DLong bias = (*static_cast*>( biasIn))[0]; #elif defined (CONVOL_UINT__) #define CONVOL_TRUNCATE_MIN 0 #define CONVOL_TRUNCATE_MAX 65535 template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* biasIn, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { Data_* kernel = static_cast*>( kIn); Data_* dabskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Data_* dbiaskern = new Data_( kIn->Dim(), BaseGDL::ZERO); DLong* absker = static_cast( dabskern->DataAddr()); DLong* biasker = static_cast( dbiaskern->DataAddr()); DLong scale = (*static_cast*>( scaleIn))[0]; // the result to be returned Data_* res = New( dim, BaseGDL::ZERO); DLong* ker = static_cast( kernel->DataAddr()); DLong bias = (*static_cast*>( biasIn))[0]; #elif defined (CONVOL_INT__) #define CONVOL_TRUNCATE_MIN -32768 #define CONVOL_TRUNCATE_MAX 32767 template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* biasIn, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { Data_* kernel = static_cast*>( kIn); Data_* dabskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Data_* dbiaskern = new Data_( kIn->Dim(), BaseGDL::ZERO); DLong* absker = static_cast( dabskern->DataAddr()); DLong* biasker = static_cast( dbiaskern->DataAddr()); DLong scale = (*static_cast*>( scaleIn))[0]; // the result to be returned Data_* res = New( dim, BaseGDL::ZERO); DLong* ker = static_cast( kernel->DataAddr()); DLong bias = (*static_cast*>( biasIn))[0]; #elif defined (CONVOL_ULONG__) #define CONVOL_TRUNCATE_MIN 0 #define CONVOL_TRUNCATE_MAX 1 //not truncated, anything goes. template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* biasIn, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { Data_* kernel = static_cast*>( kIn); Data_* dabskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Data_* dbiaskern = new Data_( kIn->Dim(), BaseGDL::ZERO); DLong* absker = static_cast( dabskern->DataAddr()); DLong* biasker = static_cast( dbiaskern->DataAddr()); DLong scale = (*static_cast*>( scaleIn))[0]; // the result to be returned Data_* res = New( dim, BaseGDL::ZERO); DLong* ker = static_cast( kernel->DataAddr()); DLong bias = (*static_cast*>( biasIn))[0]; #elif defined (CONVOL_ULONG64__) #define CONVOL_TRUNCATE_MIN 0 #define CONVOL_TRUNCATE_MAX 1 //not truncated, anything goes. template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* biasIn, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { Data_* kernel = static_cast*>( kIn); Data_* dabskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Data_* dbiaskern = new Data_( kIn->Dim(), BaseGDL::ZERO); DLong64* absker = static_cast( dabskern->DataAddr()); DLong64* biasker = static_cast( dbiaskern->DataAddr()); DLong64 scale = (*static_cast*>( scaleIn))[0]; // the result to be returned Data_* res = New( dim, BaseGDL::ZERO); DLong64* ker = static_cast( kernel->DataAddr()); DLong64 bias = (*static_cast*>( biasIn))[0]; #else template<> BaseGDL* Data_::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* biasIn, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { Data_* kernel = static_cast( kIn); Data_* dabskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Data_* dbiaskern = new Data_( kIn->Dim(), BaseGDL::ZERO); Ty* absker = &(*dabskern)[0]; Ty* biasker = &(*dbiaskern)[0]; Ty scale = (*static_cast( scaleIn))[0]; // the result to be returned Data_* res = New( this->dim, BaseGDL::ZERO); Ty* ker = &(*kernel)[0]; Ty bias = (*static_cast( biasIn))[0]; #endif Ty missingValue = (*static_cast( missing))[0]; Ty invalidValue = (*static_cast (invalid))[0]; SizeT nA = N_Elements(); SizeT nKel = kernel->N_Elements(); if(normalize) { scale = this->zero; for ( SizeT ind=0; indzero; #if defined(CONVOL_BYTE__)||defined (CONVOL_UINT__) DDouble tmp=0; for ( SizeT ind=0; indCONVOL_TRUNCATE_MAX) bias=CONVOL_TRUNCATE_MAX; #endif } else { if( scale == this->zero) scale = 1; } SizeT nDim = this->Rank(); // number of dimension to run over SizeT kStride[MAXRANK+1]; kernel->Dim().Stride( kStride, nDim); // setup kIxArr[ nDim * nKel] the offset array // this handles center long* kIxArr = new long[ nDim * nKel]; ArrayGuard kIxArrGuard( kIxArr); // guard it for( SizeT k=0; kDim( 0)); if( center) kIxArr[ k * nDim + 0] = -(kIxArr[ k * nDim + 0] + kernel->Dim( 0) / 2); for( SizeT kSp=1; kSpDim( kSp); if( kDim == 0) kDim = 1; kIxArr[ k * nDim + kSp] = -((k / kStride[kSp]) % kDim); if( center) kIxArr[ k * nDim + kSp] = -(kIxArr[ k * nDim + kSp] + kDim / 2); } } SizeT aStride[ MAXRANK + 1]; this->dim.Stride( aStride, nDim); long aBeg[ MAXRANK]; long aEnd[ MAXRANK]; for( SizeT aSp=0; aSpDim( aSp); if( kDim == 0) kDim = 1; aBeg[ aSp] = (center) ? kDim/2 : kDim-1; // >= aEnd[ aSp] = (center) ? this->dim[aSp]-(kDim-1)/2 : this->dim[aSp]; // < } Ty* ddP = &(*this)[0]; //test if array has nans when donan is present (treatment would be shorter if array had no nans) if(doNan && doInvalid) { doNan = false; doInvalid=false; #pragma omp parallel if (nA >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nA)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nA)) { #pragma omp for for( OMPInt i=0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nA)) { #pragma omp for for( OMPInt i=0; idim[0]; SizeT aBeg0 = aBeg[0]; SizeT aEnd0 = aEnd[0]; SizeT dim0_1 = dim0 - 1; SizeT kDim0 = kernel->Dim( 0); SizeT kDim0_nDim = kDim0 * nDim; // Parallel acceleration: // first have static addresses for reference to the acceleratore below: static long* aInitIxRef[33]; //32 threads +1! static bool* regArrRef[33]; // Compute nchunk using parallel max number of cpu, but chunksize must be a multiple of dim0 and not zero. // We limit the number of parallel threads to 33 given the size of the array of pointers above. // It can be extended at will, but if someone is in a position to augment '33' then it's probably beacuse the problem // should be treated by another algorithm than this one. // The whole purpose of this stuff with these static arrays of pointers is to insure that the compiler does not overoptimize // the code in the conv_inc* includes regarding the accelerator. AND to keep the code in conv_inc* more or less identical to the // historical version, slow but true and tested (well, a few bugs were cured along with this version). long chunksize=nA; long nchunk=1; if (nA > 1000) { //no use start parallel threading for small numbers. chunksize=nA/((CpuTPOOL_NTHREADS>32)?32:CpuTPOOL_NTHREADS); long n_dim0=chunksize/dim0; chunksize=dim0*n_dim0; //ensures chunksize integer number of dim0. if (chunksize>0) { nchunk=nA/chunksize; if (chunksize*nchunk < nA) ++nchunk; } else {nchunk=1; chunksize=nA;} } // build a nchunk times copy of the master offset table (accelerator). Each thread will use its own copy, properly initialized. // GD: could the offset accelerator be made easier? This would certainly simplify the code. long aInitIxT[ MAXRANK+1]; //T for template for ( long aSp=0; aSp<=nDim; ++aSp) aInitIxT[ aSp] = 0; bool regArrT[ MAXRANK];for ( long aSp=0; aSpdim[ aSp]) { regArrT[ aSp] = (aInitIxT[aSp] >= aBeg[aSp] && aInitIxT[aSp] < aEnd[ aSp]); break; } aInitIxT[ aSp] = 0; regArrT[ aSp] = !aBeg[ aSp]; ++aInitIxT[ ++aSp]; } ++aInitIxT[1]; } } #define INCLUDE_CONVOL_INC_CPP //to make the include files behave. if (normalize) { #define CONVOL_NORMALIZE if (edgeMode == 0) { if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } } } else if (edgeMode == 1) { #define CONVOL_EDGE_WRAP if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_WRAP } else if (edgeMode == 2) { #define CONVOL_EDGE_TRUNCATE if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_TRUNCATE } else if (edgeMode == 3) { #define CONVOL_EDGE_ZERO if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_ZERO } else if (edgeMode == 4) { #define CONVOL_EDGE_MIRROR if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_MIRROR } #undef CONVOL_NORMALIZE } else { if (edgeMode == 0) { if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc0.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc0.cpp" } } } else if (edgeMode == 1) { #define CONVOL_EDGE_WRAP if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_WRAP } else if (edgeMode == 2) { #define CONVOL_EDGE_TRUNCATE if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_TRUNCATE } else if (edgeMode == 3) { #define CONVOL_EDGE_ZERO if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_ZERO } else if (edgeMode == 4) { #define CONVOL_EDGE_MIRROR if (doInvalid && doNan) { #define CONVOL_NAN_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN_INVALID } else if (doInvalid) { #define CONVOL_INVALID if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_INVALID } else if (doNan) { #define CONVOL_NAN if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } #undef CONVOL_NAN } else { if (center) { #define CONVOL_CENTER // /CENTER option #include "convol_inc1.cpp" #undef CONVOL_CENTER // /CENTER option } else { #include "convol_inc1.cpp" } } #undef CONVOL_EDGE_MIRROR } #undef CONVOL_NORMALIZE } #undef INCLUDE_CONVOL_INC_CPP return res; } //end of template convol #undef CONVOL_TRUNCATE_MIN #undef CONVOL_TRUNCATE_MAX //#if !defined(CONVOL_BYTE__) && !defined(CONVOL_UINT__) && !defined(CONVOL_INT__) && !defined(CONVOL_ULONG__) && !defined(CONVOL_ULONG64__) // //namespace lib { // ///*****************************************convol_fun*********************************************************/ // BaseGDL* convol_fun( EnvT* e) // { // long nParam=e->NParam( 2); // // /************************************Checking_parameters************************************************/ // // BaseGDL* p0 = e->GetNumericParDefined( 0); // if( p0->Rank() == 0) // e->Throw( "Expression must be an array in this context: "+ // e->GetParString(0)); // // BaseGDL* p1 = e->GetNumericParDefined( 1); // if( p1->Rank() == 0) // e->Throw( "Expression must be an array in this context: "+ // e->GetParString(1)); // // if( p0->N_Elements() < p1->N_Elements()) // e->Throw( "Incompatible dimensions for Array and Kernel."); // // // rank 1 for kernel works always // if( p1->Rank() != 1) { // long rank = p0->Rank(); // if (rank != p1->Rank()) // e->Throw("Incompatible dimensions for Array and Kernel."); // // for (long r = 0; r < rank; ++r) // if (p0->Dim(r) < p1->Dim(r)) // e->Throw("Incompatible dimensions for Array and Kernel."); // } else { //check however that kernel is not too big... // if (p0->Dim(0) < p1->Dim(0)) e->Throw("Incompatible dimensions for Array and Kernel."); // } // // //compute some interesting values about kernel and array dimensions // int maxposK=0,curdimK,sumofdimsK=0,maxdimK=-1; // int maxpos=0, curdimprod, maxdimprod=-1; // // for (int i=0; iRank(); ++i) { // curdimK=p1->Dim(i); // sumofdimsK+=curdimK; // if (curdimK>maxdimK) { // maxdimK=curdimK; // maxposK=i; // } // } // // // If kernel is not 1-D, test which dimension is larger. Transposing the data and kernel to have this dimension first is faster since // // it is the kernel sum which is parallelized here. // // Probably there is a minimum difference in size (magicfactor=1.2 ? 1.5?) at which one would benefit given the added complexity of transposition. // bool doTranspose=false; // if (sumofdimsK > maxdimK+(p1->Rank())-1) { // // // Now about dimensions. // // convolution code (in convol_inc*.pro) is quite tricky. Only the inner part of the loop can be safely parallelized. // // It is a double loop on the first dimension of kernel (kDim0) times the first dimension of the array (dim0 or aEnd0-aBeg0). // // To benefit from this speedup, we need to have dim0*kDim0 maximum: // // find largest array or kernel dimension; transpose array, makes for faster convol, will be // // transposed back at end. // // // find maximum of dim0xkDim0 // for (int i = 0; i < p1->Rank(); ++i) { //0->Rank and p1->Rank same here // curdimprod = p1->Dim(i)*p0->Dim(i); // if (curdimprod > maxdimprod) { // maxdimprod = curdimprod; // maxpos = i; // } // } // float magicfactor=2.0; // if ( maxdimprod > magicfactor*p1->Dim(0)*p0->Dim(0) ) doTranspose=true; // } // // array of dims for transpose // DUInt* perm = new DUInt[p0->Rank()]; //direct // DUInt* mrep = new DUInt[p0->Rank()]; //reverse // ArrayGuard perm_guard(perm); // ArrayGuard mrep_guard(mrep); // if (doTranspose) { // // DUInt i = 0, j = 0; // for (i = 0; i < p0->Rank(); ++i) if (i != maxpos) { // perm[j + 1] = i; // j++; // } // perm[0] = maxpos; // for (i = 0; i < p0->Rank(); ++i) mrep[i]=i; //populate reverse // for (i = 0; i < maxpos+1; ++i) mrep[i]=i+1; //this and the following line should give the reverse transpose order. // mrep[maxpos]=0; // } // /***************************************Preparing_matrices*************************************************/ // // //Computations for REAL and COMPLEX are better made in double precision if we do not want to lose precision // //Apparently IDL has severe problems regarding this loss of precision. // // try for example the following, which should give exactly ZERO: // // C=32*32*0.34564 & a=findgen(100,100)*0.0+1 & b=convol(a,fltarr(32,32)+0.34564) & print,(b-c)[20:80,50],format='(4(F20.12))' // //So, we convert p0 to Double precision if necessary and convert back result. // //Do it here since all other parameters are converted to p0's type. // Guard p0Guard; // bool deprecise=false; // if (p0->Type() == GDL_FLOAT) { // p0 = p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); // p0Guard.Reset(p0); // deprecise=true; // } else if (p0->Type() == GDL_COMPLEX) { // p0 = p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY); // p0Guard.Reset(p0); // deprecise=true; // } // // // convert kernel to array type // Guard p1Guard; // if (p0->Type() == GDL_BYTE || p0->Type() == GDL_UINT || p0->Type() == GDL_INT) { // if (p1->Type() != GDL_LONG) { // p1 = p1->Convert2(GDL_LONG, BaseGDL::COPY); // p1Guard.Reset(p1); // } // } else if (p0->Type() != p1->Type()) { // p1 = p1->Convert2(p0->Type(), BaseGDL::COPY); // p1Guard.Reset(p1); // } // // BaseGDL* scale; // Guard scaleGuard; // if (nParam > 2) { // scale = e->GetParDefined(2); // if (scale->Rank() > 0) // e->Throw("Expression must be a scalar in this context: " + // e->GetParString(2)); // // // p1 here handles GDL_BYTE||GDL_UINT||GDL_INT case also // if (p1->Type() != scale->Type()) { // scale = scale->Convert2(p1->Type(), BaseGDL::COPY); // scaleGuard.Reset(scale); // } // } else { // scale = p1->New(1, BaseGDL::ZERO); // } // /********************************************Arguments_treatement***********************************/ // bool center = true; // static int centerIx = e->KeywordIx( "CENTER"); // if( e->KeywordPresent( centerIx)) // { // DLong c; // e->AssureLongScalarKW( centerIx, c); // center = (c != 0); // } // // // overrides EDGE_TRUNCATE // static int edge_wrapIx = e->KeywordIx( "EDGE_WRAP"); // bool edge_wrap = e->KeywordSet( edge_wrapIx); // static int edge_truncateIx = e->KeywordIx( "EDGE_TRUNCATE"); // bool edge_truncate = e->KeywordSet( edge_truncateIx); // static int edge_zeroIx = e->KeywordIx( "EDGE_ZERO"); // bool edge_zero = e->KeywordSet( edge_zeroIx); // static int edge_mirrorIx = e->KeywordIx( "EDGE_MIRROR"); // bool edge_mirror = e->KeywordSet( edge_mirrorIx); // int edgeMode = 0; // if( edge_wrap) // edgeMode = 1; // else if( edge_truncate) // edgeMode = 2; // else if( edge_zero) // edgeMode = 3; // else if(edge_mirror) // edgeMode = 4; // // // p0, p1 and scale have same type // // p1 has rank of 1 or same rank as p0 with each dimension smaller than p0 // // scale is a scalar // // /***********************************Parameter_BIAS**************************************/ // static int biasIx = e->KeywordIx("BIAS"); // bool statusBias = e->KeywordPresent(biasIx); // // DLong bias=0; // BaseGDL* bias; // Guard biasGuard; // if (statusBias) { // bias = e->GetKW(biasIx); // // // p1 here handles GDL_BYTE||GDL_UINT||GDL_INT case also // if (p1->Type() != bias->Type()) { // bias = bias->Convert2(p1->Type(), BaseGDL::COPY); // biasGuard.Reset(bias); // } // } else bias = p1->New(1, BaseGDL::ZERO); // // /***********************************Parameter_Normalize**********************************/ // // static int normalIx = e->KeywordIx( "NORMALIZE"); // bool normalize = e->KeywordPresent( normalIx); // // /***********************************Parameter NAN****************************************/ // // static int nanIx = e->KeywordIx( "NAN"); // bool doNan = e->KeywordSet( nanIx); // // /***********************************Parameter MISSING************************************/ // static int missingIx = e->KeywordIx("MISSING"); // bool doMissing = e->KeywordPresent(missingIx); // BaseGDL* missing; // Guard missGuard; // if (doMissing) { // missing = e->GetKW(missingIx); // if (p0->Type() != missing->Type()) { // missing = missing->Convert2(p0->Type(), BaseGDL::COPY); // missGuard.Reset(missing); // } // } else missing = p0->New(1, BaseGDL::ZERO); // /***********************************Parameter INVALID************************************/ // static int invalidIx = e->KeywordIx("INVALID"); // bool doInvalid = e->KeywordPresent( invalidIx ); // BaseGDL* invalid; // Guard invalGuard; // if (doInvalid) { // invalid = e->GetKW(invalidIx); // if (p0->Type() != invalid->Type()) { // invalid = invalid->Convert2(p0->Type(), BaseGDL::COPY); // invalGuard.Reset(invalid); // } // } else invalid = p0->New(1, BaseGDL::ZERO); // if (!doNan && !doInvalid) doMissing=false; // if (!doMissing && p0->Type()==GDL_FLOAT) { // DFloat tmp=std::numeric_limits::quiet_NaN(); // memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); // } // if (!doMissing && p0->Type()==GDL_DOUBLE){ // DDouble tmp=std::numeric_limits::quiet_NaN(); // memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); // } // //populating a Complex with Nans is not easy as there is no objective method for that. // if (!doMissing && p0->Type()==GDL_COMPLEX) { // DComplex tmp=std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); // memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); // } // if (!doMissing && p0->Type()==GDL_COMPLEXDBL) { // DComplexDbl tmp=std::complex(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()); // memcpy((*missing).DataAddr(), &tmp, sizeof(tmp)); // } // BaseGDL* result; // //handle transpositions // if (doTranspose) { // BaseGDL* input; // Guard inputGuard; // input = p0->Transpose(perm); // inputGuard.Reset(input); // BaseGDL* transpP1; // Guard transpP1Guard; // transpP1=p1->Transpose(perm); // transpP1Guard.Reset(transpP1); // result=input->Convol(transpP1, scale, bias, center, normalize, edgeMode, doNan, missing, doMissing, invalid, doInvalid)->Transpose(mrep); // } else result=p0->Convol( p1, scale, bias, center, normalize, edgeMode, doNan, missing, doMissing, invalid, doInvalid); // // if (deprecise) { // Guard resultGuard; // resultGuard.reset(result); // if (p0->Type() == GDL_DOUBLE) return result->Convert2(GDL_FLOAT, BaseGDL::COPY); // else if (p0->Type() == GDL_COMPLEXDBL) return result->Convert2(GDL_COMPLEX, BaseGDL::COPY); // else return result; //should not happen! // } else // // return result; // // } //end of convol_fun // // // }//end of namespace // //#endif #endif // #ifdef INCLUDE_CONVOL_CPP gdl-0.9.9/src/convol_inc0.cpp000066400000000000000000000105731340051421000157770ustar00rootroot00000000000000/*************************************************************************** convol_inc0.cpp - convol function edgemode = 0 (skip) ------------------- begin : Sep 19 2004 copyright : (C) 2004 by Marc Schellens, 2017 by G. Duvert email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from convol.cpp // NOTE: All the unreadble #ifdef below are there to avoid IF constructs which results in much faster code when optimization is on. #ifdef INCLUDE_CONVOL_INC_CPP // for all result elements #pragma omp parallel num_threads(nchunk) firstprivate(scale,bias) shared(ker,kIxArr,res,aInitIxRef,regArrRef,nchunk,chunksize,aBeg,aEnd,nDim,aBeg0,aStride,ddP,invalidValue,kDim0,kDim0_nDim,nKel,missingValue,aEnd0,dim0,nA,absker,biasker) //default(none) { #pragma omp for for (long iloop = 0; iloop < nchunk; ++iloop) { long* aInitIx=aInitIxRef[iloop]; //permits to keep code more or less the same as before. bool* regArr=regArrRef[iloop]; //idem. for (long ia = iloop*chunksize; (ia < (iloop+1)*chunksize && ia < nA) ; ia += dim0) { bool regular = true; for (long aSp = 1; aSp < nDim;) { if (aInitIx[ aSp] < this->dim[ aSp]) { regArr[ aSp] = (aInitIx[aSp] >= aBeg[aSp] && aInitIx[aSp] < aEnd[ aSp]); if (regular) for (; aSp < nDim; ++aSp) if (!regArr[ aSp]) { regular = false; break; } break; } aInitIx[ aSp] = 0; regArr[ aSp] = !aBeg[ aSp]; if (aBeg[ aSp]) regular = false; ++aInitIx[ ++aSp]; } if (regular) { for (long aInitIx0 = aBeg0; aInitIx0 < aEnd0; ++aInitIx0) { #if (defined(CONVOL_BYTE__) || defined (CONVOL_UINT__) || defined (CONVOL_INT__)) DLong res_a = 0; DLong otfBias = 0; DLong curScale = 0; #else Ty res_a = (*res)[ ia + aInitIx0]; Ty otfBias = this->zero; Ty curScale = this->zero; #endif #if defined(CONVOL_NAN_INVALID) || defined(CONVOL_INVALID) || defined(CONVOL_NAN) SizeT counter = 0; #endif long *kIx = kIxArr; for (long k = 0; k < nKel; k += kDim0) { long aLonIx = aInitIx0 + kIx[0]; for (long rSp = 1; rSp < nDim; ++rSp) aLonIx += (aInitIx[ rSp] + kIx[ rSp]) * aStride[ rSp]; for (long k0 = 0; k0 < kDim0; ++k0) { #ifdef CONVOL_CENTER Ty ddpHlp = ddP[ aLonIx + k0]; #else Ty ddpHlp = ddP[ aLonIx - k0]; #endif #if defined(CONVOL_NAN_INVALID) if (ddpHlp != invalidValue && gdlValid(ddpHlp)) { counter++; #elif defined (CONVOL_INVALID) if (ddpHlp != invalidValue) { counter++; #elif defined (CONVOL_NAN) if (gdlValid(ddpHlp)) { counter++; #else { #endif res_a += ddpHlp * ker[ k + k0]; #if defined (CONVOL_NORMALIZE) curScale += absker[ k + k0]; otfBias += biasker[ k + k0]; #endif } } kIx += kDim0_nDim; } #if defined (CONVOL_NORMALIZE) scale = curScale; #if defined(CONVOL_BYTE__) || defined (CONVOL_UINT__) CONVERT_MODIFY_BIAS; #else bias = this->zero; #endif #endif res_a = (scale==this->zero)?missingValue:res_a/scale; res_a += bias; #if defined(CONVOL_NAN_INVALID) || defined(CONVOL_INVALID) || defined(CONVOL_NAN) if (counter == 0) res_a = missingValue; #endif #if defined(CONVOL_BYTE__) || defined (CONVOL_UINT__) || defined (CONVOL_INT__) CONVERT_CONVOL_TO_ORIG; #else (*res)[ia + aInitIx0] = res_a; #endif } }// if( regular) // in dim 1-n ++aInitIx[1]; } // for(...) } //for iloop } #endif gdl-0.9.9/src/convol_inc1.cpp000066400000000000000000000132671340051421000160030ustar00rootroot00000000000000/*************************************************************************** convol_inc1.cpp - convol function EDGE_WRAP ------------------- begin : Sep 19 2004 copyright : (C) 2004 by Marc Schellens, 2017 by G. Duvert email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from convol.cpp. Special treatment for borders, to be included only in case // NOTE: All the unreadble #ifdef below are there to avoid IF constructs which results in much faster code when optimization is on. #ifdef INCLUDE_CONVOL_INC_CPP #pragma omp parallel num_threads(nchunk) firstprivate(scale,bias) shared(ker,kIxArr,res,aInitIxRef,regArrRef,nchunk,chunksize,aBeg,aEnd,nDim,aBeg0,aStride,ddP,invalidValue,kDim0,kDim0_nDim,nKel,missingValue,aEnd0,dim0,nA,absker,biasker,dim0_1) //default(none) { #pragma omp for for (long iloop = 0; iloop < nchunk; ++iloop) { long* aInitIx=aInitIxRef[iloop]; //permits to keep code more or less the same as before. bool* regArr=regArrRef[iloop]; //idem. for (long ia = iloop*chunksize; (ia < (iloop+1)*chunksize && ia < nA) ; ia += dim0) { for (long aSp = 1; aSp < nDim;) { if (aInitIx[ aSp] < this->dim[ aSp]) { regArr[ aSp] = (aInitIx[aSp] >= aBeg[aSp] && aInitIx[aSp] < aEnd[ aSp]); break; } aInitIx[ aSp] = 0; regArr[ aSp] = !aBeg[ aSp]; ++aInitIx[ ++aSp]; } for (long aInitIx0 = 0; aInitIx0 < dim0; ++aInitIx0) { #if (defined(CONVOL_BYTE__) || defined (CONVOL_UINT__) || defined (CONVOL_INT__)) DLong res_a = 0; DLong otfBias = 0; DLong curScale = 0; #else Ty res_a = (*res)[ ia + aInitIx0]; Ty otfBias = this->zero; Ty curScale = this->zero; #endif #if defined(CONVOL_NAN_INVALID) || defined(CONVOL_INVALID) || defined(CONVOL_NAN) SizeT counter = 0; #endif long* kIx = kIxArr; for (long k = 0; k < nKel; ++k) { long aLonIx = aInitIx0 + kIx[0]; #if defined(CONVOL_EDGE_ZERO) bool doit = true; #endif if (aLonIx < 0) { #if defined (CONVOL_EDGE_WRAP) aLonIx += dim0; #elif defined (CONVOL_EDGE_MIRROR) aLonIx = -aLonIx; #elif defined(CONVOL_EDGE_TRUNCATE) aLonIx = 0; #elif defined(CONVOL_EDGE_ZERO) aLonIx = 0; doit=false; #endif } else if (aLonIx >= dim0) { #if defined (CONVOL_EDGE_WRAP) aLonIx -= dim0; #elif defined (CONVOL_EDGE_MIRROR) aLonIx = 2*dim0-aLonIx-1; #elif defined(CONVOL_EDGE_TRUNCATE) aLonIx = dim0 - 1; #elif defined(CONVOL_EDGE_ZERO) aLonIx = dim0 - 1; doit = false; #endif } #if defined(CONVOL_EDGE_ZERO) if (doit) { #endif for (long rSp = 1; rSp < nDim; ++rSp) { long aIx = aInitIx[ rSp] + kIx[ rSp]; if (aIx < 0) { #if defined (CONVOL_EDGE_WRAP) aIx += this->dim[ rSp]; #elif defined (CONVOL_EDGE_MIRROR) aIx = -aIx; #elif defined(CONVOL_EDGE_TRUNCATE) aIx = 0; #elif defined(CONVOL_EDGE_ZERO) aIx = 0; doit = false; #endif } else if (aIx >= this->dim[ rSp]) { #if defined (CONVOL_EDGE_WRAP) aIx -= this->dim[ rSp]; #elif defined (CONVOL_EDGE_MIRROR) aIx = 2*this->dim[ rSp]-aIx-1; #elif defined(CONVOL_EDGE_TRUNCATE) aIx = this->dim[ rSp] - 1; #elif defined(CONVOL_EDGE_ZERO) aIx = this->dim[ rSp] - 1; doit = false; #endif } aLonIx += aIx * aStride[ rSp]; } #if defined(CONVOL_EDGE_ZERO) } if (doit) { #endif Ty ddpHlp = ddP[ aLonIx]; #if defined(CONVOL_NAN_INVALID) if (ddpHlp != invalidValue && gdlValid(ddpHlp)) { counter++; #elif defined (CONVOL_INVALID) if (ddpHlp != invalidValue) { counter++; #elif defined (CONVOL_NAN) if (gdlValid(ddpHlp)) { counter++; #else { #endif res_a += ddpHlp * ker[ k ]; #if defined (CONVOL_NORMALIZE) curScale += absker[ k ]; otfBias += biasker[ k ]; #endif } #if defined(CONVOL_EDGE_ZERO) } #endif kIx += nDim; } #if defined (CONVOL_NORMALIZE) scale = curScale; #if defined(CONVOL_BYTE__) || defined (CONVOL_UINT__) CONVERT_MODIFY_BIAS; #else bias = this->zero; #endif #endif res_a = (scale==this->zero)?missingValue:res_a/scale; res_a += bias; #if defined(CONVOL_NAN_INVALID) || defined(CONVOL_INVALID) || defined(CONVOL_NAN) if (counter == 0) res_a = missingValue; #endif #if defined(CONVOL_BYTE__) || defined (CONVOL_UINT__) || defined (CONVOL_INT__) CONVERT_CONVOL_TO_ORIG; #else (*res)[ia + aInitIx0] = res_a; #endif } ++aInitIx[1]; } // for ia } //for iloop } //shared #endif gdl-0.9.9/src/dSFMT/000077500000000000000000000000001340051421000137715ustar00rootroot00000000000000gdl-0.9.9/src/dSFMT/LICENSE.txt000066400000000000000000000032411340051421000156140ustar00rootroot00000000000000Copyright (c) 2007, 2008, 2009 Mutsuo Saito, Makoto Matsumoto and Hiroshima University. Copyright (c) 2011, 2002 Mutsuo Saito, Makoto Matsumoto, Hiroshima University and The University of Tokyo. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Hiroshima University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. gdl-0.9.9/src/dSFMT/dSFMT-common.h000066400000000000000000000067341340051421000163570ustar00rootroot00000000000000#pragma once /** * @file dSFMT-common.h * * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom * number generator with jump function. This file includes common functions * used in random number generation and jump. * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (The University of Tokyo) * * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima * University. * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima * University and The University of Tokyo. * All rights reserved. * * The 3-clause BSD License is applied to this software, see * LICENSE.txt */ #ifndef DSFMT_COMMON_H #define DSFMT_COMMON_H #if !defined(DSFMT_MEXP) #define DSFMT_MEXP 19937 #endif #include "dSFMT/dSFMT.h" #if defined(HAVE_SSE2) # include union X128I_T { uint64_t u[2]; __m128i i128; }; union X128D_T { double d[2]; __m128d d128; }; /** mask data for sse2 */ static const union X128I_T sse2_param_mask = {{DSFMT_MSK1, DSFMT_MSK2}}; #endif #if defined(HAVE_ALTIVEC) inline static void do_recursion(w128_t *r, w128_t *a, w128_t * b, w128_t *lung) { const vector unsigned char sl1 = ALTI_SL1; const vector unsigned char sl1_perm = ALTI_SL1_PERM; const vector unsigned int sl1_msk = ALTI_SL1_MSK; const vector unsigned char sr1 = ALTI_SR; const vector unsigned char sr1_perm = ALTI_SR_PERM; const vector unsigned int sr1_msk = ALTI_SR_MSK; const vector unsigned char perm = ALTI_PERM; const vector unsigned int msk1 = ALTI_MSK; vector unsigned int w, x, y, z; z = a->s; w = lung->s; x = vec_perm(w, (vector unsigned int)perm, perm); y = vec_perm(z, (vector unsigned int)sl1_perm, sl1_perm); y = vec_sll(y, sl1); y = vec_and(y, sl1_msk); w = vec_xor(x, b->s); w = vec_xor(w, y); x = vec_perm(w, (vector unsigned int)sr1_perm, sr1_perm); x = vec_srl(x, sr1); x = vec_and(x, sr1_msk); y = vec_and(w, msk1); z = vec_xor(z, y); r->s = vec_xor(z, x); lung->s = w; } #elif defined(HAVE_SSE2) /** * This function represents the recursion formula. * @param r output 128-bit * @param a a 128-bit part of the internal state array * @param b a 128-bit part of the internal state array * @param d a 128-bit part of the internal state array (I/O) */ inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *u) { __m128i v, w, x, y, z; x = a->si; z = _mm_slli_epi64(x, DSFMT_SL1); y = _mm_shuffle_epi32(u->si, SSE2_SHUFF); z = _mm_xor_si128(z, b->si); y = _mm_xor_si128(y, z); v = _mm_srli_epi64(y, DSFMT_SR); w = _mm_and_si128(y, sse2_param_mask.i128); v = _mm_xor_si128(v, x); v = _mm_xor_si128(v, w); r->si = v; u->si = y; } #else /** * This function represents the recursion formula. * @param r output 128-bit * @param a a 128-bit part of the internal state array * @param b a 128-bit part of the internal state array * @param lung a 128-bit part of the internal state array (I/O) */ inline static void do_recursion(w128_t *r, w128_t *a, w128_t * b, w128_t *lung) { uint64_t t0, t1, L0, L1; t0 = a->u[0]; t1 = a->u[1]; L0 = lung->u[0]; L1 = lung->u[1]; lung->u[0] = (t0 << DSFMT_SL1) ^ (L1 >> 32) ^ (L1 << 32) ^ b->u[0]; lung->u[1] = (t1 << DSFMT_SL1) ^ (L0 >> 32) ^ (L0 << 32) ^ b->u[1]; r->u[0] = (lung->u[0] >> DSFMT_SR) ^ (lung->u[0] & DSFMT_MSK1) ^ t0; r->u[1] = (lung->u[1] >> DSFMT_SR) ^ (lung->u[1] & DSFMT_MSK2) ^ t1; } #endif #endif gdl-0.9.9/src/dSFMT/dSFMT-jump.c000066400000000000000000000106211340051421000160230ustar00rootroot00000000000000/** * @file dSFMT-jump.c * * @brief do jump using jump polynomial. * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (The University of Tokyo) * * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, * Hiroshima University and The University of Tokyo. * All rights reserved. * * The 3-clause BSD License is applied to this software, see * LICENSE.txt */ #include #include #include #include #include "dSFMT-params.h" #include "dSFMT.h" #include "dSFMT-jump.h" #include "dSFMT-common.h" #if defined(__cplusplus) extern "C" { #endif struct FIX_T { int mexp; uint64_t fix[4]; }; struct FIX_T fix_table[] = { {521, {UINT64_C(0x3fff56977f035125), UINT64_C(0x3ff553857b015035), UINT64_C(0x4034434434434434), UINT64_C(0x0140151151351371)}}, {1279, {UINT64_C(0x3ff87befce70e89f), UINT64_C(0x3ff5f6afa3c60868), UINT64_C(0xa4ca4caccaccacdb), UINT64_C(0x40444444444c44c4)}}, {4253, {UINT64_C(0x3ff85a66da51a81a), UINT64_C(0x3ff4f4aeab9688eb), UINT64_C(0x20524524534d34d3), UINT64_C(0xc9cc9cc9cc9ccdcf)}}, {216091, {UINT64_C(0x3ff096d54a871071), UINT64_C(0x3ffafa9bfbd5d55d), UINT64_C(0x0470470470573573), UINT64_C(0x0250250251259259)}}, {0} }; inline static void next_state(dsfmt_t * dsfmt); #if defined(HAVE_SSE2) /** * add internal state of src to dest as F2-vector. * @param dest destination state * @param src source state */ inline static void add(dsfmt_t *dest, dsfmt_t *src) { int dp = dest->idx / 2; int sp = src->idx / 2; int diff = (sp - dp + DSFMT_N) % DSFMT_N; int p; int i; for (i = 0; i < DSFMT_N - diff; i++) { p = i + diff; dest->status[i].si = _mm_xor_si128(dest->status[i].si, src->status[p].si); } for (i = DSFMT_N - diff; i < DSFMT_N; i++) { p = i + diff - DSFMT_N; dest->status[i].si = _mm_xor_si128(dest->status[i].si, src->status[p].si); } dest->status[DSFMT_N].si = _mm_xor_si128(dest->status[DSFMT_N].si, src->status[DSFMT_N].si); } #else inline static void add(dsfmt_t *dest, dsfmt_t *src) { int dp = dest->idx / 2; int sp = src->idx / 2; int diff = (sp - dp + DSFMT_N) % DSFMT_N; int p; int i; for (i = 0; i < DSFMT_N - diff; i++) { p = i + diff; dest->status[i].u[0] ^= src->status[p].u[0]; dest->status[i].u[1] ^= src->status[p].u[1]; } for (; i < DSFMT_N; i++) { p = i + diff - DSFMT_N; dest->status[i].u[0] ^= src->status[p].u[0]; dest->status[i].u[1] ^= src->status[p].u[1]; } dest->status[DSFMT_N].u[0] ^= src->status[DSFMT_N].u[0]; dest->status[DSFMT_N].u[1] ^= src->status[DSFMT_N].u[1]; } #endif /** * calculate next state * @param dsfmt dSFMT internal state */ inline static void next_state(dsfmt_t * dsfmt) { int idx = (dsfmt->idx / 2) % DSFMT_N; w128_t * lung; w128_t * pstate = &dsfmt->status[0]; lung = &pstate[DSFMT_N]; do_recursion(&pstate[idx], &pstate[idx], &pstate[(idx + DSFMT_POS1) % DSFMT_N], lung); dsfmt->idx = (dsfmt->idx + 2) % DSFMT_N64; } inline static void add_fix(dsfmt_t * dsfmt) { int i; int index = -1; for (i = 0; fix_table[i].mexp != 0; i++) { if (fix_table[i].mexp == DSFMT_MEXP) { index = i; } if (fix_table[i].mexp > DSFMT_MEXP) { break; } } if (index < 0) { return; } for (i = 0; i < DSFMT_N; i++) { dsfmt->status[i].u[0] ^= fix_table[index].fix[0]; dsfmt->status[i].u[1] ^= fix_table[index].fix[1]; } dsfmt->status[DSFMT_N].u[0] ^= fix_table[index].fix[2]; dsfmt->status[DSFMT_N].u[1] ^= fix_table[index].fix[3]; } /** * jump ahead using jump_string * @param dsfmt dSFMT internal state input and output. * @param jump_string string which represents jump polynomial. */ void dSFMT_jump(dsfmt_t * dsfmt, const char * jump_string) { dsfmt_t work; int index = dsfmt->idx; int bits; int i; int j; memset(&work, 0, sizeof(dsfmt_t)); add_fix(dsfmt); dsfmt->idx = DSFMT_N64; for (i = 0; jump_string[i] != '\0'; i++) { bits = jump_string[i]; assert(isxdigit(bits)); bits = tolower(bits); if (bits >= 'a' && bits <= 'f') { bits = bits - 'a' + 10; } else { bits = bits - '0'; } bits = bits & 0x0f; for (j = 0; j < 4; j++) { if ((bits & 1) != 0) { add(&work, dsfmt); } next_state(dsfmt); bits = bits >> 1; } } *dsfmt = work; add_fix(dsfmt); dsfmt->idx = index; } #if defined(__cplusplus) } #endif gdl-0.9.9/src/dSFMT/dSFMT-jump.h000066400000000000000000000011221340051421000160240ustar00rootroot00000000000000#pragma once #ifndef DSFMT_JUMP_H #define DSFMT_JUMP_H /** * @file SFMT-jump.h * * @brief jump header file. * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (The University of Tokyo) * * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, * Hiroshima University and The University of Tokyo. * All rights reserved. * * The 3-clause BSD License is applied to this software, see * LICENSE.txt */ #if defined(__cplusplus) extern "C" { #endif #include "dSFMT.h" void dSFMT_jump(dsfmt_t *dsfmt, const char *jump_str); #if defined(__cplusplus) } #endif #endif gdl-0.9.9/src/dSFMT/dSFMT-params.h000066400000000000000000000047151340051421000163470ustar00rootroot00000000000000#ifndef DSFMT_PARAMS_H #define DSFMT_PARAMS_H #if !defined(DSFMT_MEXP) #define DSFMT_MEXP 19937 #endif #include "dSFMT/dSFMT.h" /*---------------------- the parameters of DSFMT following definitions are in dSFMT-paramsXXXX.h file. ----------------------*/ /** the pick up position of the array. #define DSFMT_POS1 122 */ /** the parameter of shift left as four 32-bit registers. #define DSFMT_SL1 18 */ /** the parameter of shift right as four 32-bit registers. #define DSFMT_SR1 12 */ /** A bitmask, used in the recursion. These parameters are introduced * to break symmetry of SIMD. #define DSFMT_MSK1 (uint64_t)0xdfffffefULL #define DSFMT_MSK2 (uint64_t)0xddfecb7fULL */ /** These definitions are part of a 128-bit period certification vector. #define DSFMT_PCV1 UINT64_C(0x00000001) #define DSFMT_PCV2 UINT64_C(0x00000000) */ #define DSFMT_LOW_MASK UINT64_C(0x000FFFFFFFFFFFFF) #define DSFMT_HIGH_CONST UINT64_C(0x3FF0000000000000) #define DSFMT_SR 12 /* for sse2 */ #if defined(HAVE_SSE2) #define SSE2_SHUFF 0x1b #elif defined(HAVE_ALTIVEC) #if defined(__APPLE__) /* For OSX */ #define ALTI_SR (vector unsigned char)(4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4) #define ALTI_SR_PERM \ (vector unsigned char)(15,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14) #define ALTI_SR_MSK \ (vector unsigned int)(0x000fffffU,0xffffffffU,0x000fffffU,0xffffffffU) #define ALTI_PERM \ (vector unsigned char)(12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3) #else #define ALTI_SR {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4} #define ALTI_SR_PERM {15,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14} #define ALTI_SR_MSK {0x000fffffU,0xffffffffU,0x000fffffU,0xffffffffU} #define ALTI_PERM {12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3} #endif #endif #if DSFMT_MEXP == 521 #include "dSFMT-params521.h" #elif DSFMT_MEXP == 1279 #include "dSFMT-params1279.h" #elif DSFMT_MEXP == 2203 #include "dSFMT-params2203.h" #elif DSFMT_MEXP == 4253 #include "dSFMT-params4253.h" #elif DSFMT_MEXP == 11213 #include "dSFMT-params11213.h" #elif DSFMT_MEXP == 19937 #include "dSFMT/dSFMT-params19937.h" #elif DSFMT_MEXP == 44497 #include "dSFMT-params44497.h" #elif DSFMT_MEXP == 86243 #include "dSFMT-params86243.h" #elif DSFMT_MEXP == 132049 #include "dSFMT-params132049.h" #elif DSFMT_MEXP == 216091 #include "dSFMT-params216091.h" #else #ifdef __GNUC__ #error "DSFMT_MEXP is not valid." #undef DSFMT_MEXP #else #undef DSFMT_MEXP #endif #endif #endif /* DSFMT_PARAMS_H */ gdl-0.9.9/src/dSFMT/dSFMT-params19937.h000066400000000000000000000026741340051421000167660ustar00rootroot00000000000000#ifndef DSFMT_PARAMS19937_H #define DSFMT_PARAMS19937_H /* #define DSFMT_N 191 */ /* #define DSFMT_MAXDEGREE 19992 */ #define DSFMT_POS1 117 #define DSFMT_SL1 19 #define DSFMT_MSK1 UINT64_C(0x000ffafffffffb3f) #define DSFMT_MSK2 UINT64_C(0x000ffdfffc90fffd) #define DSFMT_MSK32_1 0x000ffaffU #define DSFMT_MSK32_2 0xfffffb3fU #define DSFMT_MSK32_3 0x000ffdffU #define DSFMT_MSK32_4 0xfc90fffdU #define DSFMT_FIX1 UINT64_C(0x90014964b32f4329) #define DSFMT_FIX2 UINT64_C(0x3b8d12ac548a7c7a) #define DSFMT_PCV1 UINT64_C(0x3d84e1ac0dc82880) #define DSFMT_PCV2 UINT64_C(0x0000000000000001) #define DSFMT_IDSTR "dSFMT2-19937:117-19:ffafffffffb3f-ffdfffc90fffd" /* PARAMETERS FOR ALTIVEC */ #if defined(__APPLE__) /* For OSX */ #define ALTI_SL1 (vector unsigned char)(3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3) #define ALTI_SL1_PERM \ (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) #define ALTI_SL1_MSK \ (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) #else /* For OTHER OSs(Linux?) */ #define ALTI_SL1 {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3} #define ALTI_SL1_PERM \ {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} #define ALTI_SL1_MSK \ {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} #define ALTI_MSK \ {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} #endif #endif /* DSFMT_PARAMS19937_H */ gdl-0.9.9/src/dSFMT/dSFMT-poly.h000066400000000000000000000121611340051421000160410ustar00rootroot00000000000000static const char * poly_128 = "f4dfa6c62049d0776e0bf6f1e953f3aa38abb113df86be024eab3773ad5f2b82ead936022e656dff7e562691c59dd5f7d2" "566b78d9669002503c4ddb1888a49f32333f515e6c60c4ecd221078ec6f26f0a90f4875067ca1f399a99775037adf90556" "6e2c7e6b42131420f8f04f112c92621c9b1502f2a8aefad6c667904af62f0d55e02d396902d3b89450103c5ce5fe0408d9" "7cbb864861b49e4e42048ff3310b48faac55095a7f422eea4aade752f947f947c6be0a0c665bdea099246ab9eff658ea8c" "a468bf49d0227748367878de06d7bd86ea6708fcac6e252f5f00f04309b2aac3036b64afb39d990427c6c9f03477cc7e93" "5c43c0e61bc161db8eb15516eee8cb377ecbc1849207990fb6778721b29bfe0d89bfda1b3772fa5b0b1f7ec3daf3605203" "2285898c6f6396f55010c31f8201b7e2e51d94f920bfe57684c5415cc342cb39a0045d9793d13cf8646096daeb8bb9bfc2" "0a90de8f2426da8733267a9b9674f32154e8f84a9932223a2ca3c787d0b66df6675febbdfcba2f9cef09c621c57e11098b" "3289c77397aaae8b104642ffe0c4b75598efbc53745984d68b4d6656cae299ae2be55217a9a02b009ca7be32f47fbe434b" "ce4914a34d0c9b0085bede9b8a99319c34660d66f0124b5a7714c4bf3cbfec3ee43ed817087168bad80133bebaeeb68cf7" "929a24d1bb3de831a8340d220906ab04159cf94b21d5ee813bd7c80f10f01b43052af530917513b169254c25d6fcfe6cb4" "20d6ce92f54886ef6eaf9a5ba35e893ff593834d05ddf28899e42d729c7df3d21ef036020789739366f0c11ec52ff92a0b" "fd8ba69508e27b20fabb8217bd36b90e5aa918159ac87913bc7b46c04e366c23c92807fbe9c6a407e6a4db0b4fc23c3b6c" "706b5ca058fe8c190f849f18d16d6b48b5ed760eb202fd566291a799420b9654e08b8118bcbfead8e9dd2fdb9b053e9bdf" "b665285c78718f726d0b3d6c37e116428ec9ac9db2637259e4e8d6402bbada46c6bdb03985e19a82e9b4e57de1b025a3cb" "1f850beae7e8da9941655825bce0e89d536b6ee9064865b1a85c185e9fc9cb7f435de13d44773c00eed442a286e4ab807e" "3cab4dc3441d1b7d2af693812ae8b39652bb8c835fc895d13d6da93541afeadeee450475c29f3b2dfa8ef1c1e2547463b2" "cc2f0ff7a42ac4dd35e25c4fa030d2d2766fbe9f2d04c1304671747bace2f7dd55142bfa60f8cbc968bfc3d7a342152dc6" "84a0fb5a32c0962a62b5220ac0f72add9d8b84d6cc76b97d03245e01fc8da3414a49bb4075d3488f29b56dc42ba69e3b58" "529448c943ecfd98b3784a39d0b8609a8fb945e757f4569f53bd2cf80f7f638acf5b67fe9c560a3b7b0cf7e0398f31aa8b" "03cf9c62b24296b6d8596b694469a02686c38daa16a1ef86e012d61a2f7de1693a5c00b3685175caec3c67146477eba548" "30f1d546cb18a553779aa46adb4f2010e33f3def847c7d89b51a8462b227605f6c920fd558a6daf64bc98682e508ae960c" "0c571870e603ba1fce0c13d53176f353fd319959e13db93eae1359f06e3dd4767c04f824cf34ec7bf8f60161ba1a615db8" "2852eca9e3869afa711ab9a090660b0dc6cfbea310dda77e02310fbaeacd2636f975838c2dbcdbe9ac2cd85cee28f5e3f0" "c73abf62f9fa02cd79a7606b7ba855db68a07848b057c3aaf38f1a70086e14616f6f88305a1f9ce6b41378a620d4db3e0e" "7e1d421590dccaeff86212e232eeb5eb8a8d33a8c9b25ae88f3a7bd5032b4efa68f8af3186a02ffcbf5456f12beccace94" "c81c360cc4a0dcc642b59f991eec68c59af78139ca60b96d6a18e9535f8995e89bd2cf6a0aef3acffd33d1c0c1b79b6641" "4a91d9f65b2b4ec65844b96f725d2b4b0c309f3eb9d714e9dd939bbdfd85ce8fb43679aeab13f6c29549949503c9466dbd" "337c4cdde46d6eacd15f21f4d8fdeaa627a47884c88a9c85f0b731d271a8ea7cb9e04a4a149c23c10f56b3a0476dc77a99" "9d6e4f813e4b0f805e2a693e2ae4ae0ecc423c9ba5d17b42e691abf83784a582f2b1fd85d1e0a27ba38a500963568b2450" "363d2c5e3f7b8ba3e5b56e4e9f745a3a710bf2ae233c303068c532ce78ff031e6ab28b705dd94d7db4500909edb5626b8c" "9bd5ff4f0b4741388f0b91563ee516934c013e901572cba005ac5c535f4f107903be9af7b2793dfb61b5070facbe71eefe" "1b5600f975c8c38c3a2350d78beadfecb78e981164ae8bc866e732972d3ceef4aac68e15861f9b881d9b51b4edece150bc" "124b07645defb4202ef5d0e0962db98cae6ed459561c93c74c20bd64362e4f4fffc389a6cd80514604ff22eecc10c9cbc7" "981d19a8102b24146354c463107c9dc070e29e70df3578022acf72289ef071ab9f9402a544d0399f1b1e5f206b6d46d445" "f6d612a490e72918e00c853eda8493bef511149e80c9ab56e8b4b8cba3987249f77d060e61760e5792ac321c987c03c260" "6e9393a7970212992cdbd16448078d5039d4c2c3199714f53278f4f7b1d2e514cf95bdfc078b8bb0db659cb2c3f5cc0289" "0ea84f05d414c88d2db9e9f8455659b9fa6254405317245fa070d6970cafb4dadb2522b490a5c8e02fe973a8cdbfbfbdbf" "b01535099ffba3d3896bc4d1189fc570c3e6fdc6469265b8da912772e75dd62ab71be507f700d56cac5e68fd6b57ec1661" "68ab5258a69625c142a5b1b3519f94be1bde5e51d3bd8ea0c12d5af2fe4615b1b7bd4a96628a4fabc65925ff09718f63bb" "ebaad98f89bd9543a27b3ff3b5d8bfa89f941a5eb8cc005ccd4a705190e1c9dc6a9f4264e5ee658520a4438e92de854bff" "c39f8dc7dfbb5de4f14ba63ea16a37d14a7b4610f95b6cffd55e4679b29cedbdf20e7bd16da822fad910c359ee3a68e48a" "ae6e769b0e291d5d3aa3e2ca9d8d23abe8a1d5349f4991e9300852cc0befb20c2fc0d169306b260763344024f8092cbcc2" "4c6807363e9fc548a30d5faab3a94b2af0782a2942be80c45d8b0587efd587394ef33c33022436e285806ddffdd32fe363" "45c3c38ed8d680abeb7a028b44ee6f94d060a14c7019bb6af1f1b5f0a562957d19826d8cc216f9b908c989ccd5415e3525" "dfe9422ffb5b50b7cc3083dc325544751e5683535d7439d3da2b0bb73bea551dd99e04e0e793804f4774eb6b1daf781d9c" "aa5128274e599e847862fe309027813d3e4eda0bbeb7201856a5c5d8370e44dabff0bb229c723ba0a6bcf29c44536147de" "11b7835991018100105bd4329217f7386903fe8e7363cd7b3e893244e245e0a187467664c05b0be1fd429722b9b9a5e319" "8147fad72776e8a63aab9054fa9d259af0198d088d71d132e6068676a8e9ebb0f616b51ee34aac39c2c2221c7112401727" "0d75ff4a048363c389e04e9b440ad2032a381ac2cfc54f409caa791e65ee4f5d6cd035008f219b88a803a7382ae447bf65" "a3df2176b25b3b7b67dabe34decd9a1384dc7a003916ca8fbcb29b3ad6fd8eac5bbbaa3bdfa6c6a3ad9427c4f3ed79fea2" "6e14c8ce5fa3b4f82c5f7b6d2125916753a7b92ce9b46d45";gdl-0.9.9/src/dSFMT/dSFMT.c000066400000000000000000000462471340051421000150670ustar00rootroot00000000000000/** * @file dSFMT.c * @brief double precision SIMD-oriented Fast Mersenne Twister (dSFMT) * based on IEEE 754 format. * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (Hiroshima University) * * Copyright (C) 2007,2008 Mutsuo Saito, Makoto Matsumoto and Hiroshima * University. All rights reserved. * * The new BSD License is applied to this software, see LICENSE.txt */ #include #include #include #include "dSFMT-params.h" #include "dSFMT-common.h" #if defined(__cplusplus) extern "C" { #endif /** dsfmt internal state vector */ dsfmt_t dsfmt_global_data; /** dsfmt mexp for check */ static const int dsfmt_mexp = DSFMT_MEXP; /*---------------- STATIC FUNCTIONS ----------------*/ inline static uint32_t ini_func1(uint32_t x); inline static uint32_t ini_func2(uint32_t x); inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, int size); inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, int size); inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, int size); inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, int size); inline static int idxof(int i); static void initial_mask(dsfmt_t *dsfmt); static void period_certification(dsfmt_t *dsfmt); #if defined(HAVE_SSE2) /** 1 in 64bit for sse2 */ static const union X128I_T sse2_int_one = { {1, 1}}; /** 2.0 double for sse2 */ static const union X128D_T sse2_double_two = { {2.0, 2.0}}; /** -1.0 double for sse2 */ static const union X128D_T sse2_double_m_one = { {-1.0, -1.0}}; #endif /** * This function simulate a 32-bit array index overlapped to 64-bit * array of LITTLE ENDIAN in BIG ENDIAN machine. */ #if defined(DSFMT_BIG_ENDIAN) inline static int idxof(int i) { return i ^ 1; } #else inline static int idxof(int i) { return i; } #endif #if defined(HAVE_SSE2) /** * This function converts the double precision floating point numbers which * distribute uniformly in the range [1, 2) to those which distribute uniformly * in the range [0, 1). * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } /** * This function converts the double precision floating point numbers which * distribute uniformly in the range [1, 2) to those which distribute uniformly * in the range (0, 1]. * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { w->sd = _mm_sub_pd(sse2_double_two.d128, w->sd); } /** * This function converts the double precision floating point numbers which * distribute uniformly in the range [1, 2) to those which distribute uniformly * in the range (0, 1). * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { w->si = _mm_or_si128(w->si, sse2_int_one.i128); w->sd = _mm_add_pd(w->sd, sse2_double_m_one.d128); } #else /* standard C and altivec */ /** * This function converts the double precision floating point numbers which * distribute uniformly in the range [1, 2) to those which distribute uniformly * in the range [0, 1). * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_c0o1(w128_t *w) { w->d[0] -= 1.0; w->d[1] -= 1.0; } /** * This function converts the double precision floating point numbers which * distribute uniformly in the range [1, 2) to those which distribute uniformly * in the range (0, 1]. * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0c1(w128_t *w) { w->d[0] = 2.0 - w->d[0]; w->d[1] = 2.0 - w->d[1]; } /** * This function converts the double precision floating point numbers which * distribute uniformly in the range [1, 2) to those which distribute uniformly * in the range (0, 1). * @param w 128bit stracture of double precision floating point numbers (I/O) */ inline static void convert_o0o1(w128_t *w) { w->u[0] |= 1; w->u[1] |= 1; w->d[0] -= 1.0; w->d[1] -= 1.0; } #endif /** * This function fills the user-specified array with double precision * floating point pseudorandom numbers of the IEEE 754 format. * @param dsfmt dsfmt state vector. * @param array an 128-bit array to be filled by pseudorandom numbers. * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, int size) { int i, j; w128_t lung; lung = dsfmt->status[DSFMT_N]; do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], &lung); } for (; i < DSFMT_N; i++) { do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], &lung); } for (; i < size - DSFMT_N; i++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); } for (j = 0; j < 2 * DSFMT_N - size; j++) { dsfmt->status[j] = array[j + size - DSFMT_N]; } for (; i < size; i++, j++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); dsfmt->status[j] = array[i]; } dsfmt->status[DSFMT_N] = lung; } /** * This function fills the user-specified array with double precision * floating point pseudorandom numbers of the IEEE 754 format. * @param dsfmt dsfmt state vector. * @param array an 128-bit array to be filled by pseudorandom numbers. * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, int size) { int i, j; w128_t lung; lung = dsfmt->status[DSFMT_N]; do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], &lung); } for (; i < DSFMT_N; i++) { do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], &lung); } for (; i < size - DSFMT_N; i++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); convert_c0o1(&array[i - DSFMT_N]); } for (j = 0; j < 2 * DSFMT_N - size; j++) { dsfmt->status[j] = array[j + size - DSFMT_N]; } for (; i < size; i++, j++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); dsfmt->status[j] = array[i]; convert_c0o1(&array[i - DSFMT_N]); } for (i = size - DSFMT_N; i < size; i++) { convert_c0o1(&array[i]); } dsfmt->status[DSFMT_N] = lung; } /** * This function fills the user-specified array with double precision * floating point pseudorandom numbers of the IEEE 754 format. * @param dsfmt dsfmt state vector. * @param array an 128-bit array to be filled by pseudorandom numbers. * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, int size) { int i, j; w128_t lung; lung = dsfmt->status[DSFMT_N]; do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], &lung); } for (; i < DSFMT_N; i++) { do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], &lung); } for (; i < size - DSFMT_N; i++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); convert_o0o1(&array[i - DSFMT_N]); } for (j = 0; j < 2 * DSFMT_N - size; j++) { dsfmt->status[j] = array[j + size - DSFMT_N]; } for (; i < size; i++, j++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); dsfmt->status[j] = array[i]; convert_o0o1(&array[i - DSFMT_N]); } for (i = size - DSFMT_N; i < size; i++) { convert_o0o1(&array[i]); } dsfmt->status[DSFMT_N] = lung; } /** * This function fills the user-specified array with double precision * floating point pseudorandom numbers of the IEEE 754 format. * @param dsfmt dsfmt state vector. * @param array an 128-bit array to be filled by pseudorandom numbers. * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, int size) { int i, j; w128_t lung; lung = dsfmt->status[DSFMT_N]; do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { do_recursion(&array[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], &lung); } for (; i < DSFMT_N; i++) { do_recursion(&array[i], &dsfmt->status[i], &array[i + DSFMT_POS1 - DSFMT_N], &lung); } for (; i < size - DSFMT_N; i++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); convert_o0c1(&array[i - DSFMT_N]); } for (j = 0; j < 2 * DSFMT_N - size; j++) { dsfmt->status[j] = array[j + size - DSFMT_N]; } for (; i < size; i++, j++) { do_recursion(&array[i], &array[i - DSFMT_N], &array[i + DSFMT_POS1 - DSFMT_N], &lung); dsfmt->status[j] = array[i]; convert_o0c1(&array[i - DSFMT_N]); } for (i = size - DSFMT_N; i < size; i++) { convert_o0c1(&array[i]); } dsfmt->status[DSFMT_N] = lung; } /** * This function represents a function used in the initialization * by init_by_array * @param x 32-bit integer * @return 32-bit integer */ static uint32_t ini_func1(uint32_t x) { return (x ^ (x >> 27)) * (uint32_t) 1664525UL; } /** * This function represents a function used in the initialization * by init_by_array * @param x 32-bit integer * @return 32-bit integer */ static uint32_t ini_func2(uint32_t x) { return (x ^ (x >> 27)) * (uint32_t) 1566083941UL; } /** * This function initializes the internal state array to fit the IEEE * 754 format. * @param dsfmt dsfmt state vector. */ static void initial_mask(dsfmt_t *dsfmt) { int i; uint64_t *psfmt; psfmt = &dsfmt->status[0].u[0]; for (i = 0; i < DSFMT_N * 2; i++) { psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; } } /** * This function certificate the period of 2^{SFMT_MEXP}-1. * @param dsfmt dsfmt state vector. */ static void period_certification(dsfmt_t *dsfmt) { uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; uint64_t tmp[2]; uint64_t inner; int i; #if (DSFMT_PCV2 & 1) != 1 int j; uint64_t work; #endif tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); inner = tmp[0] & pcv[0]; inner ^= tmp[1] & pcv[1]; for (i = 32; i > 0; i >>= 1) { inner ^= inner >> i; } inner &= 1; /* check OK */ if (inner == 1) { return; } /* check NG, and modification */ #if (DSFMT_PCV2 & 1) == 1 dsfmt->status[DSFMT_N].u[1] ^= 1; #else for (i = 1; i >= 0; i--) { work = 1; for (j = 0; j < 64; j++) { if ((work & pcv[i]) != 0) { dsfmt->status[DSFMT_N].u[i] ^= work; return; } work = work << 1; } } #endif return; } /*---------------- PUBLIC FUNCTIONS ----------------*/ /** * This function returns the identification string. The string shows * the Mersenne exponent, and all parameters of this generator. * @return id string. */ const char *dsfmt_get_idstring(void) { return DSFMT_IDSTR; } /** * This function returns the minimum size of array used for \b * fill_array functions. * @return minimum size of array used for fill_array functions. */ int dsfmt_get_min_array_size(void) { return DSFMT_N64; } /** * This function fills the internal state array with double precision * floating point pseudorandom numbers of the IEEE 754 format. * @param dsfmt dsfmt state vector. */ void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { int i; w128_t lung; lung = dsfmt->status[DSFMT_N]; do_recursion(&dsfmt->status[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], &lung); for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { do_recursion(&dsfmt->status[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1], &lung); } for (; i < DSFMT_N; i++) { do_recursion(&dsfmt->status[i], &dsfmt->status[i], &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); } dsfmt->status[DSFMT_N] = lung; } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range [1, 2) to the * specified array[] by one call. The number of pseudorandom numbers * is specified by the argument \b size, which must be at least (SFMT_MEXP * / 128) * 2 and a multiple of two. The function * get_min_array_size() returns this minimum size. The generation by * this function is much faster than the following fill_array_xxx functions. * * For initialization, init_gen_rand() or init_by_array() must be called * before the first call of this function. This function can not be * used after calling genrand_xxx functions, without initialization. * * @param dsfmt dsfmt state vector. * @param array an array where pseudorandom numbers are filled * by this function. The pointer to the array must be "aligned" * (namely, must be a multiple of 16) in the SIMD version, since it * refers to the address of a 128-bit integer. In the standard C * version, the pointer is arbitrary. * * @param size the number of 64-bit pseudorandom integers to be * generated. size must be a multiple of 2, and greater than or equal * to (SFMT_MEXP / 128) * 2. * * @note \b memalign or \b posix_memalign is available to get aligned * memory. Mac OSX doesn't have these functions, but \b malloc of OSX * returns the pointer to the aligned memory block. */ void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { assert(size % 2 == 0); assert(size >= DSFMT_N64); gen_rand_array_c1o2(dsfmt, (w128_t *) array, size / 2); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range (0, 1] to the * specified array[] by one call. This function is the same as * fill_array_close1_open2() except the distribution range. * * @param dsfmt dsfmt state vector. * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { assert(size % 2 == 0); assert(size >= DSFMT_N64); gen_rand_array_o0c1(dsfmt, (w128_t *) array, size / 2); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range [0, 1) to the * specified array[] by one call. This function is the same as * fill_array_close1_open2() except the distribution range. * * @param array an array where pseudorandom numbers are filled * by this function. * @param dsfmt dsfmt state vector. * @param size the number of pseudorandom numbers to be generated. * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { assert(size % 2 == 0); assert(size >= DSFMT_N64); gen_rand_array_c0o1(dsfmt, (w128_t *) array, size / 2); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range (0, 1) to the * specified array[] by one call. This function is the same as * fill_array_close1_open2() except the distribution range. * * @param dsfmt dsfmt state vector. * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa fill_array_close1_open2() */ void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { assert(size % 2 == 0); assert(size >= DSFMT_N64); gen_rand_array_o0o1(dsfmt, (w128_t *) array, size / 2); } #if defined(__INTEL_COMPILER) #pragma warning(disable : 981) #endif /** * This function initializes the internal state array with a 32-bit * integer seed. * @param dsfmt dsfmt state vector. * @param seed a 32-bit integer used as the seed. * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { int i; uint32_t *psfmt; /* make sure caller program is compiled with the same MEXP */ if (mexp != dsfmt_mexp) { fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); exit(1); } psfmt = &dsfmt->status[0].u32[0]; psfmt[idxof(0)] = seed; for (i = 1; i < (DSFMT_N + 1) * 4; i++) { psfmt[idxof(i)] = 1812433253UL * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; } initial_mask(dsfmt); period_certification(dsfmt); dsfmt->idx = DSFMT_N64; } /** * This function initializes the internal state array, * with an array of 32-bit integers used as the seeds * @param dsfmt dsfmt state vector. * @param init_key the array of 32-bit integers, used as a seed. * @param key_length the length of init_key. * @param mexp caller's mersenne expornent */ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length, int mexp) { int i, j, count; uint32_t r; uint32_t *psfmt32; int lag; int mid; int size = (DSFMT_N + 1) * 4; /* pulmonary */ /* make sure caller program is compiled with the same MEXP */ if (mexp != dsfmt_mexp) { fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); exit(1); } if (size >= 623) { lag = 11; } else if (size >= 68) { lag = 7; } else if (size >= 39) { lag = 5; } else { lag = 3; } mid = (size - lag) / 2; psfmt32 = &dsfmt->status[0].u32[0]; memset(dsfmt->status, 0x8b, sizeof (dsfmt->status)); if (key_length + 1 > size) { count = key_length + 1; } else { count = size; } r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] ^ psfmt32[idxof((size - 1) % size)]); psfmt32[idxof(mid % size)] += r; r += key_length; psfmt32[idxof((mid + lag) % size)] += r; psfmt32[idxof(0)] = r; count--; for (i = 1, j = 0; (j < count) && (j < key_length); j++) { r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ psfmt32[idxof((i + size - 1) % size)]); psfmt32[idxof((i + mid) % size)] += r; r += init_key[j] + i; psfmt32[idxof((i + mid + lag) % size)] += r; psfmt32[idxof(i)] = r; i = (i + 1) % size; } for (; j < count; j++) { r = ini_func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % size)] ^ psfmt32[idxof((i + size - 1) % size)]); psfmt32[idxof((i + mid) % size)] += r; r += i; psfmt32[idxof((i + mid + lag) % size)] += r; psfmt32[idxof(i)] = r; i = (i + 1) % size; } for (j = 0; j < size; j++) { r = ini_func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % size)] + psfmt32[idxof((i + size - 1) % size)]); psfmt32[idxof((i + mid) % size)] ^= r; r -= i; psfmt32[idxof((i + mid + lag) % size)] ^= r; psfmt32[idxof(i)] = r; i = (i + 1) % size; } initial_mask(dsfmt); period_certification(dsfmt); dsfmt->idx = DSFMT_N64; } #if defined(__INTEL_COMPILER) #pragma warning(default : 981) #endif #if defined(__cplusplus) } #endif gdl-0.9.9/src/dSFMT/dSFMT.h000066400000000000000000000550451340051421000150700ustar00rootroot00000000000000#pragma once /** * @file dSFMT.h * * @brief double precision SIMD oriented Fast Mersenne Twister(dSFMT) * pseudorandom number generator based on IEEE 754 format. * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (Hiroshima University) * * Copyright (C) 2007, 2008 Mutsuo Saito, Makoto Matsumoto and * Hiroshima University. All rights reserved. * Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, * Hiroshima University and The University of Tokyo. * All rights reserved. * * The new BSD License is applied to this software. * see LICENSE.txt * * @note We assume that your system has inttypes.h. If your system * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t, * and you have to define PRIu64 and PRIx64 in this file as follows: * @verbatim typedef unsigned int uint32_t typedef unsigned long long uint64_t #define PRIu64 "llu" #define PRIx64 "llx" @endverbatim * uint32_t must be exactly 32-bit unsigned integer type (no more, no * less), and uint64_t must be exactly 64-bit unsigned integer type. * PRIu64 and PRIx64 are used for printf function to print 64-bit * unsigned int and 64-bit unsigned int in hexadecimal format. */ /* Intrinsic declarations for this to work "automatically" withing GDL */ #if defined(__SSE2__) #define HAVE_SSE2 #elif defined(__ALTIVEC__) #define HAVE_ALTIVEC #endif #ifndef DSFMT_H #define DSFMT_H #if defined(__cplusplus) extern "C" { #endif #include #include #if !defined(DSFMT_MEXP) #define DSFMT_MEXP 19937 #endif /*----------------- BASIC DEFINITIONS -----------------*/ /* Mersenne Exponent. The period of the sequence * is a multiple of 2^DSFMT_MEXP-1. * #define DSFMT_MEXP 19937 */ /** DSFMT generator has an internal state array of 128-bit integers, * and N is its size. */ #define DSFMT_N ((DSFMT_MEXP - 128) / 104 + 1) /** N32 is the size of internal state array when regarded as an array * of 32-bit integers.*/ #define DSFMT_N32 (DSFMT_N * 4) /** N64 is the size of internal state array when regarded as an array * of 64-bit integers.*/ #define DSFMT_N64 (DSFMT_N * 2) #if !defined(DSFMT_BIG_ENDIAN) #if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) #if __BYTE_ORDER == __BIG_ENDIAN #define DSFMT_BIG_ENDIAN 1 #endif #elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) #if _BYTE_ORDER == _BIG_ENDIAN #define DSFMT_BIG_ENDIAN 1 #endif #elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) #if __BYTE_ORDER__ == __BIG_ENDIAN__ #define DSFMT_BIG_ENDIAN 1 #endif #elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) #if BYTE_ORDER == BIG_ENDIAN #define DSFMT_BIG_ENDIAN 1 #endif #elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || \ defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) #define DSFMT_BIG_ENDIAN 1 #endif #endif #if defined(DSFMT_BIG_ENDIAN) && defined(__amd64) #undef DSFMT_BIG_ENDIAN #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) #include #elif defined(_MSC_VER) || defined(__BORLANDC__) #if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; #ifndef UINT64_C #define UINT64_C(v) (v##ui64) #endif #define DSFMT_UINT32_DEFINED #if !defined(inline) && !defined(__cplusplus) # define inline __inline #endif #endif #else #include #if !defined(inline) && !defined(__cplusplus) #if defined(__GNUC__) # define inline __inline__ #else #define inline #endif #endif #endif #ifndef PRIu64 #if defined(_MSC_VER) || defined(__BORLANDC__) #define PRIu64 "I64u" #define PRIx64 "I64x" #else #define PRIu64 "llu" #define PRIx64 "llx" #endif #endif #ifndef UINT64_C #define UINT64_C(v) (v##ULL) #endif /*------------------------------------------ 128-bit SIMD like data type for standard C ------------------------------------------*/ #if defined(HAVE_ALTIVEC) #if !defined(__APPLE__) #include #endif /** 128-bit data structure */ union W128_T { vector unsigned int s; uint64_t u[2]; uint32_t u32[4]; double d[2]; }; #elif defined(HAVE_SSE2) #include /** 128-bit data structure */ union W128_T { __m128i si; __m128d sd; uint64_t u[2]; uint32_t u32[4]; double d[2]; }; #else /* standard C */ /** 128-bit data structure */ union W128_T { uint64_t u[2]; uint32_t u32[4]; double d[2]; }; #endif /** 128-bit data type */ typedef union W128_T w128_t; /** the 128-bit internal state array */ struct DSFMT_T { w128_t status[DSFMT_N + 1]; int idx; }; typedef struct DSFMT_T dsfmt_t; /** dsfmt internal state vector */ extern dsfmt_t dsfmt_global_data; /** dsfmt mexp for check */ extern const int dsfmt_global_mexp; void dsfmt_gen_rand_all(dsfmt_t *dsfmt); void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size); void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size); void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size); void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size); void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp); void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length, int mexp); const char *dsfmt_get_idstring(void); int dsfmt_get_min_array_size(void); #if defined(__GNUC__) #define DSFMT_PRE_INLINE inline static #define DSFMT_PST_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) && _MSC_VER >= 1200 #define DSFMT_PRE_INLINE __forceinline static #define DSFMT_PST_INLINE #else #define DSFMT_PRE_INLINE inline static #define DSFMT_PST_INLINE #endif DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_genrand_close_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_genrand_open_close(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_genrand_open_open(dsfmt_t *dsfmt) DSFMT_PST_INLINE; DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) DSFMT_PST_INLINE; /** * This function generates and returns unsigned 32-bit integer. * This is slower than SFMT, only for convenience usage. * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called * before this function. * @param dsfmt dsfmt internal state date * @return uint32 pseudorandom number */ inline static uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { uint32_t r; uint64_t *psfmt64 = &dsfmt->status[0].u[0]; if (dsfmt->idx >= DSFMT_N64) { dsfmt_gen_rand_all(dsfmt); dsfmt->idx = 0; } r = psfmt64[dsfmt->idx++] & 0xffffffffU; return r; } /** * This function generates and returns a signed (but positive) 32-bit integer. * This is slower than SFMT, only for convenience usage. * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called * before this function. * @param dsfmt dsfmt internal state date * @return positive int32 pseudorandom number [0..2^31-1] */ inline static int32_t dsfmt_genrand_int31(dsfmt_t *dsfmt) { int32_t r; uint64_t *psfmt64 = &dsfmt->status[0].u[0]; do { if (dsfmt->idx >= DSFMT_N64) { dsfmt_gen_rand_all(dsfmt); dsfmt->idx = 0; } r = psfmt64[dsfmt->idx++] & 0xffffffff; } while (r<0); return r; } /** * This function generates and returns unsigned 64-bit integer. * @param dsfmt dsfmt internal state date * @return uint64 pseudorandom number */ inline static uint64_t dsfmt_genrand_uint64(dsfmt_t *dsfmt) { uint64_t *psfmt64 = &dsfmt->status[0].u[0]; if (dsfmt->idx >= DSFMT_N64) { dsfmt_gen_rand_all(dsfmt); dsfmt->idx = 0; } return psfmt64[dsfmt->idx++]; } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range [1, 2). This is * the primitive and faster than generating numbers in other ranges. * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called * before this function. * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { double r; double *psfmt64 = &dsfmt->status[0].d[0]; if (dsfmt->idx >= DSFMT_N64) { dsfmt_gen_rand_all(dsfmt); dsfmt->idx = 0; } r = psfmt64[dsfmt->idx++]; return r; } /** * This function generates and returns unsigned 32-bit integer. * This is slower than SFMT, only for convenience usage. * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ inline static uint32_t dsfmt_gv_genrand_uint32(void) { return dsfmt_genrand_uint32(&dsfmt_global_data); } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range [1, 2). * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close1_open2(void) { return dsfmt_genrand_close1_open2(&dsfmt_global_data); } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range [0, 1). * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called * before this function. * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { return dsfmt_genrand_close1_open2(dsfmt) - 1.0; } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range [0, 1). * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_close_open(void) { return dsfmt_gv_genrand_close1_open2() - 1.0; } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range (0, 1]. * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called * before this function. * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { return 2.0 - dsfmt_genrand_close1_open2(dsfmt); } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range (0, 1]. * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_close(void) { return 2.0 - dsfmt_gv_genrand_close1_open2(); } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range (0, 1). * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called * before this function. * @param dsfmt dsfmt internal state date * @return double precision floating point pseudorandom number */ inline static double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { double *dsfmt64 = &dsfmt->status[0].d[0]; union { double d; uint64_t u; } r; if (dsfmt->idx >= DSFMT_N64) { dsfmt_gen_rand_all(dsfmt); dsfmt->idx = 0; } r.d = dsfmt64[dsfmt->idx++]; r.u |= 1; return r.d - 1.0; } /** * This function generates and returns double precision pseudorandom * number which distributes uniformly in the range (0, 1). * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called * before this function. This function uses \b global variables. * @return double precision floating point pseudorandom number */ inline static double dsfmt_gv_genrand_open_open(void) { return dsfmt_genrand_open_open(&dsfmt_global_data); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range [1, 2) to the * specified array[] by one call. This function is the same as * dsfmt_fill_array_close1_open2() except that this function uses * \b global variables. * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close1_open2(double array[], int size) { dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range (0, 1] to the * specified array[] by one call. This function is the same as * dsfmt_gv_fill_array_close1_open2() except the distribution range. * This function uses \b global variables. * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_fill_array_close1_open2() and \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_close(double array[], int size) { dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range [0, 1) to the * specified array[] by one call. This function is the same as * dsfmt_gv_fill_array_close1_open2() except the distribution range. * This function uses \b global variables. * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_fill_array_close1_open2() \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_close_open(double array[], int size) { dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); } /** * This function generates double precision floating point * pseudorandom numbers which distribute in the range (0, 1) to the * specified array[] by one call. This function is the same as * dsfmt_gv_fill_array_close1_open2() except the distribution range. * This function uses \b global variables. * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_fill_array_close1_open2() \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void dsfmt_gv_fill_array_open_open(double array[], int size) { dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); } /** * This function initializes the internal state array with a 32-bit * integer seed. * @param dsfmt dsfmt state vector. * @param seed a 32-bit integer used as the seed. */ inline static void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); } /** * This function initializes the internal state array with a 32-bit * integer seed. This function uses \b global variables. * @param seed a 32-bit integer used as the seed. * see also \sa dsfmt_init_gen_rand() */ inline static void dsfmt_gv_init_gen_rand(uint32_t seed) { dsfmt_init_gen_rand(&dsfmt_global_data, seed); } /** * This function initializes the internal state array, * with an array of 32-bit integers used as the seeds. * @param dsfmt dsfmt state vector * @param init_key the array of 32-bit integers, used as a seed. * @param key_length the length of init_key. */ inline static void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], int key_length) { dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); } /** * This function initializes the internal state array, * with an array of 32-bit integers used as the seeds. * This function uses \b global variables. * @param init_key the array of 32-bit integers, used as a seed. * @param key_length the length of init_key. * see also \sa dsfmt_init_by_array() */ inline static void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) { dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); } #if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) DSFMT_PRE_INLINE const char *get_idstring(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE int get_min_array_size(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close1_open2(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_close_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_close(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE double genrand_open_open(void) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) DSFMT_PST_INLINE; DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) DSFMT_PST_INLINE; /** * This function is just the same as dsfmt_get_idstring(). * @return id string. * see also \sa dsfmt_get_idstring() */ inline static const char *get_idstring(void) { return dsfmt_get_idstring(); } /** * This function is just the same as dsfmt_get_min_array_size(). * @return minimum size of array used for fill_array functions. * see also \sa dsfmt_get_min_array_size() */ inline static int get_min_array_size(void) { return dsfmt_get_min_array_size(); } /** * This function is just the same as dsfmt_gv_init_gen_rand(). * @param seed a 32-bit integer used as the seed. * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). */ inline static void init_gen_rand(uint32_t seed) { dsfmt_gv_init_gen_rand(seed); } /** * This function is just the same as dsfmt_gv_init_by_array(). * @param init_key the array of 32-bit integers, used as a seed. * @param key_length the length of init_key. * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). */ inline static void init_by_array(uint32_t init_key[], int key_length) { dsfmt_gv_init_by_array(init_key, key_length); } /** * This function is just the same as dsfmt_gv_genrand_close1_open2(). * @return double precision floating point number. * see also \sa dsfmt_genrand_close1_open2() \sa * dsfmt_gv_genrand_close1_open2() */ inline static double genrand_close1_open2(void) { return dsfmt_gv_genrand_close1_open2(); } /** * This function is just the same as dsfmt_gv_genrand_close_open(). * @return double precision floating point number. * see also \sa dsfmt_genrand_close_open() \sa * dsfmt_gv_genrand_close_open() */ inline static double genrand_close_open(void) { return dsfmt_gv_genrand_close_open(); } /** * This function is just the same as dsfmt_gv_genrand_open_close(). * @return double precision floating point number. * see also \sa dsfmt_genrand_open_close() \sa * dsfmt_gv_genrand_open_close() */ inline static double genrand_open_close(void) { return dsfmt_gv_genrand_open_close(); } /** * This function is just the same as dsfmt_gv_genrand_open_open(). * @return double precision floating point number. * see also \sa dsfmt_genrand_open_open() \sa * dsfmt_gv_genrand_open_open() */ inline static double genrand_open_open(void) { return dsfmt_gv_genrand_open_open(); } /** * This function is juset the same as dsfmt_gv_fill_array_open_close(). * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_gv_fill_array_open_close(), \sa * dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_close(double array[], int size) { dsfmt_gv_fill_array_open_close(array, size); } /** * This function is juset the same as dsfmt_gv_fill_array_close_open(). * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_gv_fill_array_close_open(), \sa * dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close_open(double array[], int size) { dsfmt_gv_fill_array_close_open(array, size); } /** * This function is juset the same as dsfmt_gv_fill_array_open_open(). * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_gv_fill_array_open_open(), \sa * dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_open_open(double array[], int size) { dsfmt_gv_fill_array_open_open(array, size); } /** * This function is juset the same as dsfmt_gv_fill_array_close1_open2(). * @param array an array where pseudorandom numbers are filled * by this function. * @param size the number of pseudorandom numbers to be generated. * see also \sa dsfmt_fill_array_close1_open2(), \sa * dsfmt_gv_fill_array_close1_open2() */ inline static void fill_array_close1_open2(double array[], int size) { dsfmt_gv_fill_array_close1_open2(array, size); } #endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ #if defined(__cplusplus) } #endif #endif /* DSFMT_H */ gdl-0.9.9/src/datalistt.hpp000066400000000000000000000173561340051421000155720ustar00rootroot00000000000000/*************************************************************************** datalistt.hpp - holds (local and global) variables ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DATALISTT_HPP_ #define DATALISTT_HPP_ #include "basegdl.hpp" struct EnvType { // EnvType( BaseGDL* pIn): p(pIn), pp(NULL) {} // EnvType( BaseGDL** ppIn): p(NULL), pp(ppIn) {} EnvType() {} // ~EnvType() { delete p;} void Null() { p = NULL; pp = NULL;} void NullP() { p = NULL;} void NullPP() { pp = NULL;} bool IsSet() const { return (p != NULL || pp != NULL);} bool IsP() const { return p != NULL;} bool IsPP() const { return pp != NULL;} bool IsNULL() const { return (pp == NULL && p == NULL);} void SetPNullPP( BaseGDL* pIn) {p = pIn; pp = NULL;} void SetPPNullP( BaseGDL** ppIn) {pp = ppIn; p = NULL;} void SetP( BaseGDL* pIn) {p = pIn;} void SetPP( BaseGDL** ppIn) {pp = ppIn;} BaseGDL* P() const { return p;} BaseGDL** PP() const { return pp;} BaseGDL*& PRef() { return p;} // BaseGDL**& PPRef() { return pp;} BaseGDL* const& PRefConst() const { return p;} // BaseGDL** const& PPRefConst() const { return pp;} private: BaseGDL* p; BaseGDL** pp; }; const SizeT DataListDefaultLength = 64; // this data structure is optimized for list sizes < defaultLength // DataListDefaultLength should be set such that it will probably never exceed // note: it will work for larger lists as well, but then copy operations are performed template< typename T, SizeT defaultLength> class EnvTypePreAllocListT { public: typedef T* iterator; private: T* eArr; T buf[defaultLength]; SizeT sz; SizeT actLen; public: EnvTypePreAllocListT(): eArr(buf), sz(0), actLen(defaultLength) {} ~EnvTypePreAllocListT() { if( eArr != buf) delete[] eArr; } void push_back( BaseGDL* p) { if( sz >= actLen) { actLen *= 4; // should only happen rarely T* newArr = new T[ actLen]; for( SizeT i=0; i= actLen) { actLen *= 4; // should only happen rarely T* newArr = new T[ actLen]; for( SizeT i=0; i= actLen) { actLen *= 4; // should only happen rarely T* newArr = new T[ actLen]; for( SizeT i=0; i= sz); if( newSz > actLen) // should only happen rarely { actLen = newSz; T* newArr = new T[ actLen]; SizeT i=0; for( ; i ListT; typedef EnvTypePreAllocListT ListT; ListT env; // holds the variables public: DataListT(): env() {} ~DataListT() { // cleanup passed by value parameters and local variables ListT::iterator pEnd = env.end(); for( ListT::iterator p = env.begin(); p!=pEnd;++p) GDLDelete( p->P()); // for( SizeT i=0; i= &env.front().PRefConst() && p <= &env.back().PRefConst()); } bool Contains( BaseGDL* p) const { return env.Contains( p); } // void RemoveLoc( BaseGDL* p) // { // env.RemoveLoc( p); // } void push_back( BaseGDL* p) { env.push_back(p); } void push_back( BaseGDL** pp) { env.push_back(pp); } void AddOne() { env.push_back(); } void pop_back() { env.pop_back(); } SizeT size() const { return env.size();} // void reserve( SizeT s) // { // env.reserve( s); // } void resize( SizeT s) { env.resize( s); //, EnvType(NULL,NULL)); } bool IsNULL( const SizeT ix) { return env[ix].IsNULL(); } BaseGDL*& operator[]( const SizeT ix) { if( env[ ix].IsPP() ) return *env[ ix].PP(); return env[ ix].PRef(); // ok, IsP } void Clear( SizeT ix) { env[ ix].Null(); } void Reset( SizeT ix, BaseGDL* p) { if( env[ ix].IsP()) // implies pp == NULL { GDLDelete(env[ ix].P()); env[ ix].SetP( p); return; } // !IsP -> p == NULL env[ ix].SetPNullPP( p); } void Reset( SizeT ix, BaseGDL** pp) { if( env[ ix].IsP()) { GDLDelete(env[ ix].P()); env[ ix].NullP(); } // !IsP -> p == NULL env[ ix].SetPP( pp); } void Set( SizeT ix, BaseGDL* p) { env[ ix].SetPNullPP( p); } void Set( SizeT ix, BaseGDL** pp) { env[ ix].SetPPNullP( pp); } bool IsSet( SizeT ix) { return env[ix].IsSet(); //(env[ ix].p != NULL || env[ ix].pp != NULL); } BaseGDL* Grab( SizeT ix) { BaseGDL* ret; if( env[ ix].IsP()) { ret=env[ ix].P(); env[ ix].NullP(); return ret; } if( env[ ix].IsPP()) return (*env[ ix].PP())->Dup(); return NULL; } // // finds the local variable pp points to // int FindLocal( BaseGDL** pp) // { // for( SizeT i=0; i(i); // return -1; // } // finds the gloabl variable pp int FindGlobal( BaseGDL** pp) { for( SizeT i=0; i(i); return -1; } BaseGDL** GetPtrTo( BaseGDL* p) { assert( p != NULL); for( SizeT i=0; i #endif #include //#include "datatypes.hpp" // included from arrayindex.hpp #include "nullgdl.hpp" #include "dstructgdl.hpp" #include "arrayindexlistt.hpp" #include "assocdata.hpp" #include "io.hpp" #include "dinterpreter.hpp" #include "terminfo.hpp" // needed with gcc-3.3.2 #include // on OS X isnan is not defined #if defined(__APPLE__) && defined(OLD_DARWIN) && !defined(isnan) #ifdef __cplusplus extern "C" { #endif // #define isnan( x ) ( ( sizeof ( x ) == sizeof(double) ) ? \ // __isnand ( x ) : \ // ( sizeof ( x ) == sizeof( float) ) ? \ // __isnanf ( x ) : \ // __isnan ( x ) ) namespace std { template bool isnan( T x) { return ( ( sizeof ( x ) == sizeof(double) ) ? __isnand ( x ) : ( sizeof ( x ) == sizeof( float) ) ? __isnanf ( x ) : __isnan ( x ) );} } #ifdef __cplusplus } #endif #endif #ifdef _MSC_VER #define isfinite _finite #define std__isnan isnan #else #define std__isnan std::isnan #endif //using namespace std; //using std::isnan; // this (ugly) including of other sourcefiles has to be done, because // on Mac OS X a template instantiation request (see bottom of file) // can only be done once #define INCLUDE_GETAS_CPP 1 #include "getas.cpp" #define INCLUDE_BASIC_OP_CPP 1 #include "basic_op.cpp" #include "basic_op_new.cpp" #define INCLUDE_DEFAULT_IO_CPP 1 #include "default_io.cpp" #define INCLUDE_IFMT_CPP 1 #include "ifmt.cpp" #define INCLUDE_OFMT_CPP 1 #include "ofmt.cpp" #define INCLUDE_DATATYPESREF_CPP 1 #include "datatypesref.cpp" #if defined(USE_PYTHON) || defined(PYTHON_MODULE) # define INCLUDE_TOPYTHON_CPP 1 # include "topython.cpp" # define INCLUDE_GDLPYTHON_CPP 1 # include "gdlpython.cpp" # ifdef PYTHON_MODULE # define INCLUDE_PYTHONGDL_CPP 1 # include "pythongdl.cpp" # endif #endif #ifdef _MSC_VER #define isnan _isnan #define isinfinite _isinfinite #endif #ifdef TESTTG #include "test_template_grouping.cpp" template void Data_::TestTemplateGrouping() { // Ty ty = Test1(); bool b = Test2(); } #endif template FreeListT Data_::freeList; #ifdef GDLARRAY_CACHE #ifdef GDLARRAY_DEBUG inline void TraceCache( SizeT& cacheSize, SizeT sz, bool cacheIsNull, SizeT smallArraySize) { // if( cacheSize > smallArraySize && cacheSize == sz && !cacheIsNull) // std::cout << "+++ CACHE HIT\tID: (" << &cacheSize << ") sz: " << cacheSize << std::endl; // else if( sz > smallArraySize) std::cout << "+ New\t\tID: (" << &cacheSize << ") sz: " << sz << " cache size: " << cacheSize < SizeT GDLArray::cacheSize = 0; template<> SizeT GDLArray::cacheSize = 0; template typename GDLArray::Ty* GDLArray::cache = NULL; template typename GDLArray::Ty* GDLArray::Cached( SizeT newSize) { assert( newSize > smallArraySize); if( cache != NULL && cacheSize == newSize) { #ifdef GDLARRAY_DEBUG std::cout << "*** CACHE HIT\tID: (" << &cacheSize << ") sz: " << cacheSize << " ***" << std::endl; #endif Ty* hit = cache; cache = NULL; return hit; } return new Ty[ newSize]; } templateGDLArray::GDLArray( const GDLArray& cp) : sz( cp.size()) { TraceCache( cacheSize, sz, cache==NULL, smallArraySize); try { buf = (sz > smallArraySize) ? Cached( sz) /* new Ty[ cp.size()]*/ : scalar; } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } std::memcpy(buf,cp.buf,sz*sizeof(Ty)); } templateGDLArray:: GDLArray( SizeT s, bool b) : sz( s) { TraceCache( cacheSize, sz, cache==NULL, smallArraySize); try { buf = (sz > smallArraySize) ? Cached( sz) /* new Ty[ sz]*/ : scalar; } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } } templateGDLArray:: GDLArray( Ty val, SizeT s) : sz( s) { TraceCache( cacheSize, sz, cache==NULL, smallArraySize); try { buf = (sz > smallArraySize) ? Cached( sz) /* new Ty[ sz]*/ : scalar; } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } for( SizeT i=0; iGDLArray:: GDLArray( const Ty* arr, SizeT s) : sz( s) { TraceCache( cacheSize, sz, cache==NULL, smallArraySize); try { buf = (sz > smallArraySize) ? Cached( sz) /* new Ty[ sz]*/ : scalar; } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } std::memcpy(buf,arr,sz*sizeof(Ty)); } templateGDLArray::~GDLArray() throw() { #ifdef GDLARRAY_DEBUG if( buf == cache) std::cout << "~~~ recycled cache\tID: (" << &cacheSize << ") sz: " << sz << "\tcacheSize: " << cacheSize << std::endl; #endif assert( buf != cache || sz == cacheSize); if ( buf != NULL && buf != scalar && buf != cache // note: assumes cacheSize never changes for a given cache ) { assert( sz > smallArraySize); if ( sz <= maxCache ) { #ifdef GDLARRAY_DEBUG std::cout << "--- free cache\tID: (" << &cacheSize << ") sz: " << cacheSize << "\tnew: " << sz << std::endl; #endif delete cache; cache = buf; cacheSize = sz; } else { delete[] buf; } } } // as strings may occupy arbitrary memory (regardless of the array size), better not cache them // note: Structs are ok, since GDL cleans up the strings they may contain and uses GDLArray as raw memory template<> GDLArray::~GDLArray() throw() { if ( buf != scalar ) { delete[] buf; } } template class GDLArray; #endif template inline bool gdlValid( const T &value ) { T max_value = std::numeric_limits::max(); T min_value = - max_value; return ( ( min_value <= value && value <= max_value ) && (value == value)); } inline bool gdlValid( const DComplex &value ) { DFloat max_value = std::numeric_limits::max(); DFloat min_value = - max_value; return ( ( min_value <= value.real() && value.real() <= max_value ) && (value.real() == value.real()))&& ( ( min_value <= value.imag() && value.imag() <= max_value ) && (value.imag() == value.imag())); } inline bool gdlValid( const DComplexDbl &value ) { DDouble max_value = std::numeric_limits::max(); DDouble min_value = - max_value; return ( ( min_value <= value.real() && value.real() <= max_value ) && (value.real() == value.real()))&& ( ( min_value <= value.imag() && value.imag() <= max_value ) && (value.imag() == value.imag())); } template void* Data_::operator new( size_t bytes) { assert( bytes == sizeof( Data_)); if( freeList.size() > 0) { return freeList.pop_back(); // void* res = freeList.back(); // freeList.pop_back(); // return res; } const size_t newSize = multiAlloc - 1; static long callCount = 0; ++callCount; // reserve space for all instances // note that reserve must do an allocation // this hack divides the number of those allocation // (for the cost of initially larger allocation - but only for pointers) const long allocDivider = 4; freeList.reserve( ((callCount/allocDivider+1)*allocDivider-1)*multiAlloc); // resize to what is needed now // freeList.resize( newSize); #ifdef USE_EIGEN // we need this allocation here as well (as in typedefs.hpp), because GDLArray needs to be aligned const int alignmentInBytes = 16; // set to multiple of 16 >= sizeof( char*) const size_t realSizeOfType = sizeof( Data_); const SizeT exceed = realSizeOfType % alignmentInBytes; const size_t sizeOfType = realSizeOfType + (alignmentInBytes - exceed); char* res = static_cast< char*>( Eigen::internal::aligned_malloc( sizeOfType * multiAlloc)); // one more than newSize #else const size_t sizeOfType = sizeof( Data_); char* res = static_cast< char*>( malloc( sizeOfType * multiAlloc)); // one more than newSize #endif res = freeList.Init( newSize, res, sizeOfType); // freeList[0] = NULL; // for( size_t i=1; i<=newSize; ++i) // { // freeList[ i] = res; // res += sizeOfType; // } // the one more return res; } template void Data_::operator delete( void *ptr) { freeList.push_back( ptr); } // destructor template Data_::~Data_() {} template<> Data_::~Data_() { if( this->dd.GetBuffer() != NULL) GDLInterpreter::DecRef( this); } template<> Data_::~Data_() { if( this->dd.GetBuffer() != NULL) GDLInterpreter::DecRefObj( this); } // default template Data_::Data_(): Sp(), dd() {} // scalar template Data_::Data_(const Ty& d_): Sp(), dd(d_) {} // template<> Data_::Data_(const Ty& d_): SpDPtr(), dd(d_) // {GDLInterpreter::IncRef(d_);} // template<> Data_::Data_(const Ty& d_): SpDObj(), dd(d_) // {GDLInterpreter::IncRefObj(d_);} // new array, zero fields template Data_::Data_(const dimension& dim_): Sp( dim_), dd( Sp::zero, this->dim.NDimElements()) { this->dim.Purge(); } // new one-dim array from Ty* template Data_::Data_( const Ty* p, const SizeT nEl): Sp( dimension( nEl)), dd( p, nEl) {} template<> Data_::Data_( const Ty* p, const SizeT nEl): SpDPtr( dimension( nEl)), dd( p, nEl) {GDLInterpreter::IncRef(this);} template<> Data_::Data_( const Ty* p, const SizeT nEl): SpDObj( dimension( nEl)), dd( p, nEl) {GDLInterpreter::IncRefObj(this);} // c-i // template Data_::Data_(const Data_& d_): // Sp(d_.dim), dd(d_.dd) {} template Data_::Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble off, DDouble inc): Sp( dim_), dd( (iT == BaseGDL::NOALLOC) ? 0 : this->dim.NDimElements(), false) { this->dim.Purge(); if (iT == BaseGDL::NOZERO) return; //very frequent else if (iT == BaseGDL::ZERO) { //rather frequent SizeT sz = dd.size(); #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (int i = 0; i < sz; ++i) { (*this)[i] = 0; } } } else if (iT == BaseGDL::INDGEN) { //less frequent SizeT sz = dd.size(); if (off==0 && inc==1) { #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (SizeT i = 0; i < sz; ++i) { (*this)[i]=i; } } } else { #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (SizeT i = 0; i < sz; ++i) { (*this)[i]=off+i*inc; } } } } } //IDL uses floats increments and offset for floats and complex (normal) . template<> Data_::Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble off, DDouble inc): SpDFloat( dim_), dd( (iT == BaseGDL::NOALLOC) ? 0 : this->dim.NDimElements(), false) { this->dim.Purge(); if (iT == BaseGDL::NOZERO) return; //very frequent else if (iT == BaseGDL::ZERO) { //rather frequent SizeT sz = dd.size(); #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (int i = 0; i < sz; ++i) { (*this)[i] = 0; } } } else if (iT == BaseGDL::INDGEN) { //less frequent SizeT sz = dd.size(); if (off==0 && inc==1) { #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (SizeT i = 0; i < sz; ++i) { (*this)[i]=i; } } } else { DFloat f_off=off; DFloat f_inc=inc; #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (SizeT i = 0; i < sz; ++i) { (*this)[i]=f_off+i*f_inc; } } } } } template<> Data_::Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble off, DDouble inc): SpDComplex( dim_), dd( (iT == BaseGDL::NOALLOC) ? 0 : this->dim.NDimElements(), false) { this->dim.Purge(); if (iT == BaseGDL::NOZERO) return; //very frequent else if (iT == BaseGDL::ZERO) { //rather frequent SizeT sz = dd.size(); #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (int i = 0; i < sz; ++i) { (*this)[i] = 0; } } } else if (iT == BaseGDL::INDGEN) { //less frequent SizeT sz = dd.size(); if (off==0 && inc==1) { #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (SizeT i = 0; i < sz; ++i) { (*this)[i]=i; } } } else { DFloat f_off=off; DFloat f_inc=inc; #pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for for (SizeT i = 0; i < sz; ++i) { (*this)[i]=f_off+i*f_inc; } } } } } template<> Data_::Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble, DDouble): SpDString(dim_), dd( (iT == BaseGDL::NOALLOC) ? 0 : this->dim.NDimElements(), false) { dim.Purge(); if( iT == BaseGDL::INDGEN) throw GDLException("DStringGDL(dim,InitType=INDGEN) called."); } template<> Data_::Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble, DDouble): SpDPtr(dim_), dd( (iT == BaseGDL::NOALLOC) ? 0 : this->dim.NDimElements(), false) { dim.Purge(); if( iT == BaseGDL::INDGEN) throw GDLException("DPtrGDL(dim,InitType=INDGEN) called."); if( iT != BaseGDL::NOALLOC && iT != BaseGDL::NOZERO) { SizeT sz = dd.size(); /*#pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for*/ for( int i=0; i Data_::Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble, DDouble): SpDObj(dim_), dd( (iT == BaseGDL::NOALLOC) ? 0 : this->dim.NDimElements(), false) { dim.Purge(); if( iT == BaseGDL::INDGEN) throw GDLException("DObjGDL(dim,InitType=INDGEN) called."); if( iT != BaseGDL::NOALLOC && iT != BaseGDL::NOZERO) { SizeT sz = dd.size(); /*#pragma omp parallel if (sz >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= sz)) { #pragma omp for*/ for( int i=0; i Data_::Data_(const Data_& d_): Sp(d_.dim), dd(d_.dd) {} template<> Data_::Data_(const Data_& d_): SpDPtr(d_.dim), dd(d_.dd) { GDLInterpreter::IncRef( this); } template<> Data_::Data_(const Data_& d_): SpDObj(d_.dim), dd(d_.dd) { GDLInterpreter::IncRefObj( this); } template Data_* Data_::Dup() const { return new Data_(*this);} // template<> // Data_* Data_::Dup() const // { // Data_* p =new Data_(*this); // GDLInterpreter::IncRef( p); // return p; // } // template<> // Data_* Data_::Dup() const // { // Data_* p =new Data_(*this); // GDLInterpreter::IncRefObj( p); // return p; // } template BaseGDL* Data_::Log() { DFloatGDL* res = static_cast (this->Convert2( GDL_FLOAT, BaseGDL::COPY)); res->LogThis(); return res; } template<> BaseGDL* Data_::Log() { Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( int i=0; i BaseGDL* Data_::Log() { Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::Log() { Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::Log() { Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::LogThis() { DFloatGDL* res = static_cast (this->Convert2( GDL_FLOAT, BaseGDL::COPY)); res->LogThis(); // calls correct LogThis for float return res; } template<> BaseGDL* Data_::LogThis() { SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::LogThis() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::LogThis() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::LogThis() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::Log10() { DFloatGDL* res = static_cast (this->Convert2( GDL_FLOAT, BaseGDL::COPY)); res->Log10This(); return res; } template<> BaseGDL* Data_::Log10() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log10( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; idim, log10(dd)); #endif*/ } template<> BaseGDL* Data_::Log10() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log10( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; idim, log10(dd)); #endif*/ } template<> BaseGDL* Data_::Log10() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log10( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; idim, log10(dd)); #endif*/ } template<> BaseGDL* Data_::Log10() { //#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) Data_* n = this->New( this->dim, BaseGDL::NOZERO); SizeT nEl = n->N_Elements(); if( nEl == 1) { (*n)[ 0] = log10( (*this)[ 0]); return n; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; idim, log10(dd)); #endif*/ } // see comment at void Data_::LogThis() template BaseGDL* Data_::Log10This() { DFloatGDL* res = static_cast (this->Convert2( GDL_FLOAT, BaseGDL::COPY)); res->Log10This(); // calls correct Log10This for float return res; } template<> BaseGDL* Data_::Log10This() { #if 1 || (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log10( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::Log10This() { #if 1 || (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log10( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::Log10This() { #if 1 || (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log10( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i BaseGDL* Data_::Log10This() { #if 1 || (__GNUC__ == 3) && (__GNUC_MINOR__ == 2) //&& (__GNUC_PATCHLEVEL__ == 2) SizeT nEl = N_Elements(); if( nEl == 1) { (*this)[ 0] = log10( (*this)[ 0]); return this; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( int i=0; i // BaseGDL* Data_::Abs() const // { // return new Data_( this->dim, dd.abs()); // } template inline bool Data_::Greater(SizeT i1, SizeT i2) const { return ((*this)[i1] > (*this)[i2]);} template<> inline bool Data_::Greater(SizeT i1, SizeT i2) const { return (abs((*this)[i1]) > abs((*this)[i2]));} template<> inline bool Data_::Greater(SizeT i1, SizeT i2) const { return (abs((*this)[i1]) > abs((*this)[i2]));} template inline bool Data_::Equal(SizeT i1, SizeT i2) const { return ((*this)[i1] == (*this)[i2]);} // calculates the shift to be applied to the destination index inline SizeT CShiftNormalize( DLong s, SizeT this_dim) { if ( s >= 0 ) return s % this_dim; // s < 0 // long dstIx = -(-s % this_dim); long dstIx = -s % this_dim; dstIx = -dstIx; if( dstIx == 0) // if this_dim == 1 return 0; assert( dstIx + this_dim > 0); return dstIx + this_dim; } template BaseGDL* Data_::CShift( DLong d) const { SizeT nEl = dd.size(); SizeT shift = CShiftNormalize( d, nEl); if( shift == 0) return this->Dup(); Data_* sh = new Data_( this->dim, BaseGDL::NOZERO); SizeT firstChunk = nEl - shift; memcpy( &sh->dd[ shift], &dd[0], firstChunk * sizeof(Ty)); memcpy( &sh->dd[ 0], &dd[firstChunk], shift * sizeof(Ty)); return sh; } template<> BaseGDL* Data_::CShift( DLong d) const { SizeT nEl = dd.size(); SizeT shift = CShiftNormalize( d, nEl); if( shift == 0) return this->Dup(); Data_* sh = new Data_( this->dim, BaseGDL::NOZERO); SizeT firstChunk = nEl - shift; SizeT i=0; for( ; idd[shift++] = dd[ i]; shift = 0; for( ; idd[shift++] = dd[ i]; return sh; } template<> BaseGDL* Data_::CShift( DLong d) const { SizeT nEl = dd.size(); SizeT shift = CShiftNormalize( d, nEl); if( shift == 0) return this->Dup(); // does IncRef Data_* sh = new Data_( this->dim, BaseGDL::NOZERO); SizeT firstChunk = nEl - shift; SizeT i=0; for( ; idd[shift++] = dd[ i]; shift = 0; for( ; idd[shift++] = dd[ i]; GDLInterpreter::IncRef( sh); return sh; } template<> BaseGDL* Data_::CShift( DLong d) const { SizeT nEl = dd.size(); SizeT shift = CShiftNormalize( d, nEl); if( shift == 0) return this->Dup(); // does IncRefObj Data_* sh = new Data_( this->dim, BaseGDL::NOZERO); SizeT firstChunk = nEl - shift; SizeT i=0; for( ; idd[shift++] = dd[ i]; shift = 0; for( ; idd[shift++] = dd[ i]; GDLInterpreter::IncRefObj( sh); return sh; } template inline void CShift1( Ty* dst, SizeT& dstLonIx, const Ty* src, SizeT& srcLonIx, SizeT stride_1, SizeT chunk0, SizeT chunk1) { memcpy( &dst[ dstLonIx], &src[ srcLonIx], chunk0 * sizeof(Ty)); dstLonIx += chunk0; srcLonIx += chunk0; dstLonIx -= stride_1; memcpy( &dst[ dstLonIx], &src[ srcLonIx], chunk1 * sizeof(Ty)); dstLonIx += chunk1 ; srcLonIx += chunk1; dstLonIx += stride_1; } #undef TEST_GOOD_OL_VERSION template BaseGDL* Data_::CShift( DLong s[ MAXRANK]) const { Data_* sh = new Data_(this->dim, BaseGDL::NOZERO); SizeT nDim = this->Rank(); SizeT nEl = N_Elements(); SizeT stride[ MAXRANK + 1]; this->dim.Stride(stride, nDim); long srcIx[ MAXRANK + 1]; long dstIx[ MAXRANK + 1]; SizeT this_dim[ MAXRANK]; const Ty* ddP = &(*this)[0]; Ty* shP = &(*sh)[0]; if (nDim == 2) { this_dim[ 0] = this->dim[ 0]; this_dim[ 1] = this->dim[ 1]; dstIx[ 0] = CShiftNormalize(s[ 0], this_dim[ 0]); dstIx[ 1] = CShiftNormalize(s[ 1], this_dim[ 1]); SizeT dstLonIx = dstIx[ 0] + dstIx[ 1] * stride[ 1]; SizeT freeDstIx_0 = this_dim[ 0] - dstIx[ 0]; SizeT freeDstIx_1 = this_dim[ 1] - dstIx[ 1]; if (Sp::t != GDL_STRING) // strings are not POD all others are { SizeT srcLonIx = 0; SizeT t = 0; for (; t < freeDstIx_1; ++t) { CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); } dstLonIx -= stride[ 2]; for (; t < this_dim[ 1]; ++t) { CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); } } else // Sp::t == GDL_STRING { SizeT a = 0; SizeT t = 0; for (; t < freeDstIx_1; ++t) { SizeT s = 0; for (; s < freeDstIx_0; ++s) { shP[ dstLonIx++] = ddP[ a++]; } dstLonIx -= stride[ 1]; for (; s < this_dim[ 0]; ++s) { shP[ dstLonIx++] = ddP[ a++]; } dstLonIx += stride[ 1]; } dstLonIx -= stride[ 2]; for (; t < this_dim[ 1]; ++t) { SizeT s = 0; for (; s < freeDstIx_0; ++s) { shP[ dstLonIx++] = ddP[ a++]; } dstLonIx -= stride[ 1]; for (; s < this_dim[ 0]; ++s) { shP[ dstLonIx++] = ddP[ a++]; } dstLonIx += stride[ 1]; } // dstLonIx += stride[ 2]; assert(a == nEl); } // if( Sp::t != GDL_STRING) else return sh; } assert(nDim > 2); #ifndef TEST_GOOD_OL_VERSION for (SizeT aSp = 0; aSp < nDim; ++aSp) { this_dim[ aSp] = this->dim[ aSp]; srcIx[ aSp] = 0; dstIx[ aSp] = CShiftNormalize(s[ aSp], this_dim[ aSp]); // dim_stride[ aSp] = this_dim[ aSp] * stride[ aSp]; } // srcIx[ nDim] = dstIx[ nDim] = 0; SizeT dstLonIx = dstIx[ 0]; for (SizeT rSp = 1; rSp < nDim; ++rSp) dstLonIx += dstIx[ rSp] * stride[ rSp]; if (Sp::t != GDL_STRING) { if (nDim == 3) { SizeT freeDstIx_0 = this_dim[ 0] - dstIx[ 0]; SizeT freeDstIx_1 = this_dim[ 1] - dstIx[ 1]; SizeT freeDstIx_2 = this_dim[ 2] - dstIx[ 2]; SizeT srcLonIx = 0; SizeT d2 = 0; for (; d2 < freeDstIx_2; ++d2) { SizeT d1 = 0; for (; d1 < freeDstIx_1; ++d1) { CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); } dstLonIx -= stride[ 2]; for (; d1 < this_dim[ 1]; ++d1) { CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); } dstLonIx += stride[ 2]; } dstLonIx -= stride[ 3]; for (; d2 < this_dim[ 2]; ++d2) { SizeT d1 = 0; for (; d1 < freeDstIx_1; ++d1) { CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); } dstLonIx -= stride[ 2]; for (; d1 < this_dim[ 1]; ++d1) { CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); } dstLonIx += stride[ 2]; } assert(srcLonIx == nEl); return sh; } // nDim == 3 if (nDim == 4) { SizeT freeDstIx_0 = this_dim[ 0] - dstIx[ 0]; SizeT freeDstIx_1 = this_dim[ 1] - dstIx[ 1]; SizeT freeDstIx_2 = this_dim[ 2] - dstIx[ 2]; SizeT freeDstIx_3 = this_dim[ 3] - dstIx[ 3]; SizeT srcLonIx = 0; SizeT d3 = 0; for (; d3 < freeDstIx_3; ++d3) { SizeT d2 = 0; for (; d2 < freeDstIx_2; ++d2) { SizeT d1 = 0; for (; d1 < freeDstIx_1; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx -= stride[ 2]; for (; d1 < this_dim[ 1]; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx += stride[ 2]; } dstLonIx -= stride[ 3]; for (; d2 < this_dim[ 2]; ++d2) { SizeT d1 = 0; for (; d1 < freeDstIx_1; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx -= stride[ 2]; for (; d1 < this_dim[ 1]; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx += stride[ 2]; } dstLonIx += stride[ 3]; } dstLonIx -= stride[ 4]; for (; d3 < this_dim[ 3]; ++d3) { SizeT d2 = 0; for (; d2 < freeDstIx_2; ++d2) { SizeT d1 = 0; for (; d1 < freeDstIx_1; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx -= stride[ 2]; for (; d1 < this_dim[ 1]; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx += stride[ 2]; } dstLonIx -= stride[ 3]; for (; d2 < this_dim[ 2]; ++d2) { SizeT d1 = 0; for (; d1 < freeDstIx_1; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx -= stride[ 2]; for (; d1 < this_dim[ 1]; ++d1) CShift1(shP, dstLonIx, ddP, srcLonIx, stride[ 1], freeDstIx_0, dstIx[0]); dstLonIx += stride[ 2]; } dstLonIx += stride[ 3]; } assert(srcLonIx == nEl); return sh; } // nDim == 4 } // if( Sp::t != GDL_STRING) #else // need to be done earlier within the TEST_GOOD_OL_VERSION section for (SizeT aSp = 0; aSp < nDim; ++aSp) { this_dim[ aSp] = this->dim[ aSp]; srcIx[ aSp] = 0; dstIx[ aSp] = CShiftNormalize(s[ aSp], this_dim[ aSp]); } SizeT dstLonIx = dstIx[ 0]; for (SizeT rSp = 1; rSp < nDim; ++rSp) dstLonIx += dstIx[ rSp] * stride[ rSp]; #endif // TEST_GOOD_OL_VERSION // good 'ol version RELOADED SizeT* dim_stride = &stride[1]; SizeT freeDstIx_0 = this_dim[ 0] - dstIx[ 0]; // how many elements till array border is reached (dim 0) // for( SizeT a=0; a= this_dim[ aSp]) { // dstIx[ aSp] -= dim[ aSp]; dstIx[ aSp] = 0; dstLonIx -= dim_stride[ aSp]; } if (srcIx[ aSp] < this_dim[ aSp]) break; srcIx[ aSp] = 0; if (++aSp >= nDim) break; // ?? ++srcIx[ aSp]; ++dstIx[ aSp]; dstLonIx += stride[ aSp]; } // code from new version (to avoid the worst :-) // copy one line SizeT s = 0; for (; s < freeDstIx_0; ++s) { shP[ dstLonIx++] = ddP[ a++]; } dstLonIx -= stride[ 1]; for (; s < this_dim[ 0]; ++s) { shP[ dstLonIx++] = ddP[ a++]; } dstLonIx += stride[ 1]; // copy one element //shP[ dstLonIx++] = ddP[ a++]; } return sh; } // assumes *perm is already checked according to uniqness and length // dim[i]_out = dim[perm[i]]_in // helper function for Transpose() DUInt* InitPermDefault() { static DUInt res[ MAXRANK]; for( SizeT i=MAXRANK-1, ii=0; ii BaseGDL* Data_::Transpose( DUInt* perm) { SizeT rank = this->Rank(); if (rank == 1) // special case: vector { if (perm != NULL) // must be [0] { return Dup(); } else { Data_* res = Dup(); res->dim >> 1; return res; } } // 2 - MAXRANK static DUInt* permDefault = InitPermDefault(); if (perm == NULL) { // following 2D code is now slower than multi-dim multicore solution below. // if (rank == 2) { // SizeT srcDim0 = this->dim[0]; // SizeT srcDim1 = this->dim[1]; // Data_* res = new Data_(dimension(srcDim1, srcDim0), BaseGDL::NOZERO); // // SizeT srcIx = 0; // for (SizeT srcIx1 = 0; srcIx1 < srcDim1; ++srcIx1) // src dim 1 // { // SizeT resIx = srcIx1; // SizeT srcLim = srcIx + srcDim0; // src dim 0 // for (; srcIx < srcLim; ++srcIx) { // (*res)[ resIx] = (*this)[ srcIx]; // resIx += srcDim1; // } // } // return res; // } // perm == NULL, rank != 2 perm = &permDefault[ MAXRANK - rank]; } //new version, parallell the job on a multithreaded machine. Gain is 3/4 number of threads. SizeT resDim[ MAXRANK]; // permutated! for (SizeT d = 0; d < rank; ++d) { resDim[ d] = this->dim[ perm[ d]]; } Data_* res = new Data_(dimension(resDim, rank), BaseGDL::NOZERO); // src stride SizeT srcStride[ MAXRANK+1]; this->dim.Stride(srcStride, rank); SizeT nElem = dd.size(); long chunksize = nElem; long nchunk = 1; if (nElem > CpuTPOOL_MIN_ELTS) { //no use start parallel threading for small numbers. chunksize = nElem / ((CpuTPOOL_NTHREADS > 32) ? 32 : CpuTPOOL_NTHREADS); nchunk = nElem / chunksize; if (chunksize * nchunk < nElem) ++nchunk; } else { nchunk = 1; chunksize = nElem; } //compute start parameter for each multiWalk chunks: // pool of accelerators SizeT srcDimPool[nchunk][MAXRANK]; for (SizeT i = 0; i < rank; ++i) for (int iloop = 0; iloop < nchunk; ++iloop) srcDimPool[iloop][i] = 0; //template accelerator SizeT templateDim[MAXRANK]; for (SizeT i = 0; i < rank; ++i) templateDim[i] = 0; //compute iloop's accelerator with fast direct method for (long iloop = 0; iloop < nchunk; ++iloop) { SizeT e = iloop*chunksize; SizeT sizeleft = e; for (long i = 0; i < rank; ++i) { DUInt pi = perm[i]; //note the transpose effect. sizeleft /= resDim[i]; templateDim[pi] = e - sizeleft * resDim[i]; e = sizeleft; } //memorize current state accelerator for chunk iloop: for (long j = 0; j < rank; ++j) srcDimPool[iloop][j] = templateDim[j]; } #pragma omp parallel num_threads(nchunk) { #pragma omp for for (long iloop = 0; iloop < nchunk; ++iloop) { // populate src multi dim SizeT srcDim[MAXRANK]; for (SizeT i = 0; i < rank; ++i) srcDim[i] = srcDimPool[iloop][i]; //inner loop for (SizeT e = iloop * chunksize; (e < (iloop + 1) * chunksize && e < nElem); ++e) { // src multi dim to one dim src offset index SizeT ix = 0; for (SizeT i = 0; i < rank; ++i) ix += srcDim[i] * srcStride[i]; (*res)[ e] = (*this)[ ix]; // update src multi dim for next dest offset index: here is the transpose effect. for (SizeT i = 0; i < rank; ++i) { DUInt pi = perm[i]; srcDim[pi]++; if (srcDim[pi] < resDim[i]) break; srcDim[pi] = 0; } } } } return res; } // used by reverse template void Data_::Reverse(DLong dim) { // SA: based on total_over_dim_template() // static Data_* tmp = new Data_(dimension(1), BaseGDL::NOZERO); //Guard tmp_guard(tmp); SizeT nEl = N_Elements(); SizeT revStride = this->dim.Stride(dim); SizeT outerStride = this->dim.Stride(dim + 1); SizeT revLimit = this->dim[dim] * revStride; #pragma omp parallel //if ((nEl/outerStride)*revStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*revStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { for (SizeT i = 0; i < revStride; ++i) { SizeT oi = o + i; SizeT last_plus_oi = revLimit + oi - revStride + oi; SizeT half = ((revLimit / revStride) / 2) * revStride + oi; for (SizeT s = oi; s < half; s += revStride) { SizeT opp = last_plus_oi - s; Ty tmp = (*this)[s]; (*this)[s] = (*this)[opp]; (*this)[opp] = tmp; } } } } } template BaseGDL* Data_::DupReverse(DLong dim) { // SA: based on total_over_dim_template() Data_* res = new Data_(this->dim, BaseGDL::NOZERO); Guard res_guard(res); SizeT nEl = N_Elements(); SizeT revStride = this->dim.Stride(dim); SizeT outerStride = this->dim.Stride(dim + 1); SizeT revLimit = this->dim[dim] * revStride; #pragma omp parallel //if ((nEl/outerStride)*revStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*revStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { for (SizeT i = 0; i < revStride; ++i) { SizeT oi = o + i; SizeT last_plus_oi = revLimit + oi - revStride + oi; SizeT half = ((revLimit / revStride) / 2) * revStride + oi; for (SizeT s = oi; s < half + 1; s += revStride) { SizeT opp = last_plus_oi - s; // cout << s <<" "<< opp << " " << (*this)[s] << " " << (*this)[opp] << endl; (*res)[s] = (*this)[opp]; (*res)[opp] = (*this)[s]; } } } } return res_guard.release(); } template<> BaseGDL* Data_::DupReverse( DLong dim) { // SA: based on total_over_dim_template() Data_* res = new Data_(this->dim, BaseGDL::NOZERO); Guard res_guard(res); SizeT nEl = N_Elements(); SizeT revStride = this->dim.Stride(dim); SizeT outerStride = this->dim.Stride(dim + 1); SizeT revLimit = this->dim[dim] * revStride; #pragma omp parallel //if ((nEl/outerStride)*revStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*revStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { for (SizeT i = 0; i < revStride; ++i) { SizeT oi = o + i; SizeT last_plus_oi = revLimit + oi - revStride + oi; SizeT half = ((revLimit / revStride) / 2) * revStride + oi; for (SizeT s = oi; s < half + 1; s += revStride) { SizeT opp = last_plus_oi - s; (*res)[s] = (*this)[opp]; (*res)[opp] = (*this)[s]; } } } } GDLInterpreter::IncRef(res); return res_guard.release(); } template<> BaseGDL* Data_::DupReverse(DLong dim) { // SA: based on total_over_dim_template() Data_* res = new Data_(this->dim, BaseGDL::NOZERO); Guard res_guard(res); SizeT nEl = N_Elements(); SizeT revStride = this->dim.Stride(dim); SizeT outerStride = this->dim.Stride(dim + 1); SizeT revLimit = this->dim[dim] * revStride; #pragma omp parallel //if ((nEl/outerStride)*revStride >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= (nEl/outerStride)*revStride)) { #pragma omp for for (SizeT o = 0; o < nEl; o += outerStride) { for (SizeT i = 0; i < revStride; ++i) { SizeT oi = o + i; SizeT last_plus_oi = revLimit + oi - revStride + oi; SizeT half = ((revLimit / revStride) / 2) * revStride + oi; for (SizeT s = oi; s < half + 1; s += revStride) { SizeT opp = last_plus_oi - s; (*res)[s] = (*this)[opp]; (*res)[opp] = (*this)[s]; } } } } GDLInterpreter::IncRefObj(res); return res_guard.release(); } // rank must be 1 or 2 (already checked) template BaseGDL* Data_::Rotate( DLong dir) { dir = (dir % 8 + 8) % 8; // bring into 0..7 range if (dir == 0) return Dup(); if (dir == 2) { Data_* res = new Data_(this->dim, BaseGDL::NOZERO); SizeT nEl = N_Elements(); //no pragma: better optimized directly by the compiler! { for (SizeT i = 0; i < nEl; ++i) (*res)[i] = (*this)[ nEl - 1 - i]; } return res; } if (this->Rank() == 1) { if (dir == 7) return Dup(); if (dir == 1 || dir == 4) { return new Data_(dimension(1, N_Elements()), dd); } if (dir == 5) // || dir == 2 { Data_* res = new Data_(this->dim, BaseGDL::NOZERO); SizeT nEl = N_Elements(); //no pragma: better optimized directly by the compiler! { for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (*this)[ nEl - 1 - i]; } return res; } // 3 || 6 Data_* res = new Data_(dimension(1, N_Elements()), BaseGDL::NOZERO); SizeT nEl = N_Elements(); //no pragma: better optimized directly by the compiler! { for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (*this)[ nEl - 1 - i]; } return res; } // rank == 2, dir == 0 and dir == 2 already handled bool keepDim = (dir == 5) || (dir == 7); Data_* res; if (keepDim) { res = new Data_(this->dim, BaseGDL::NOZERO); } else { res = new Data_(dimension(this->dim[1], this->dim[0]), BaseGDL::NOZERO); } // bool flipX = dir == 3 || dir == 5 || dir == 6; // bool flipY = dir == 1 || dir == 6 || dir == 7; SizeT xEl = this->dim[0]; SizeT yEl = this->dim[1]; SizeT i = 0; // enable fast optimzation by removing ifs outside loops. if (dir == 1) { // flipY for (SizeT y = 0; y < yEl; ++y) for (SizeT x = 0; x < xEl; ++x) (*res)[ x * yEl + yEl - 1 - y] = (*this)[ i++]; } else if (dir == 3) { // flipX for (SizeT y = 0; y < yEl; ++y) for (SizeT x = 0; x < xEl; ++x) (*res)[ (xEl - 1 - x) * yEl + y] = (*this)[ i++]; } else if (dir == 4) { for (SizeT y = 0; y < yEl; ++y) for (SizeT x = 0; x < xEl; ++x) (*res)[x * yEl + y] = (*this)[ i++]; } else if (dir == 5) { // flipX, keepDim for (SizeT y = 0; y < yEl; ++y) for (SizeT x = 0; x < xEl; ++x) (*res)[y * xEl + xEl - 1 - x] = (*this)[ i++]; } else if (dir == 6) { // flipX, flipY for (SizeT y = 0; y < yEl; ++y) for (SizeT x = 0; x < xEl; ++x) (*res)[(xEl - 1 - x )* yEl + yEl - 1 - y] = (*this)[ i++]; } else if (dir == 7) { // flipY, keepDim for (SizeT y = 0; y < yEl; ++y) for (SizeT x = 0; x < xEl; ++x) (*res)[(yEl - 1 - y) * xEl + x ] = (*this)[ i++]; } //was: // for (SizeT y = 0; y < yEl; ++y) { // SizeT yR = flipY ? yEl - 1 - y : y; // for (SizeT x = 0; x < xEl; ++x) { // SizeT xR = flipX ? xEl - 1 - x : x; // // SizeT ix = keepDim ? yR * xEl + xR : xR * yEl + yR; // // (*res)[ix] = (*this)[ i++]; // } // } return res; } template typename Data_::Ty Data_::Sum() const { Ty s= dd[ 0]; SizeT nEl = dd.size(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( s) { #pragma omp for reduction(+:s) for( int i=1; i Data_::Ty Data_::Sum() const { Ty s= dd[ 0]; SizeT nEl = dd.size(); for( SizeT i=1; i Data_::Ty Data_::Sum() const { DDouble sr= dd[ 0].real(); DDouble si= dd[ 0].imag(); SizeT nEl = dd.size(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( sr,si) { #pragma omp for reduction(+:si,sr) for( SizeT i=1; i(sr,si); } template<> Data_::Ty Data_::Sum() const { DFloat sr= dd[ 0].real(); DFloat si= dd[ 0].imag(); SizeT nEl = dd.size(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel //if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) shared( sr,si) { #pragma omp for reduction(+:si,sr) for( SizeT i=1; i(sr,si); } // template // typename Data_::DataT& Data_:: Resize( SizeT n) // { // if( n > dd.size()) // throw GDLException("Internal error: Data_::Resize(...) tried to grow."); // if( dd.size() != n) // { // DataT rsArr( n); // std::copy( &(*this)[0], &(*this)[n], &rsArr[0]); // dd.resize( n); // discards data // std::copy( &rsArr[0], &rsArr[n], &(*this)[0]); // } // return dd; // } // template // typename Data_::Ty& Data_::operator[] (const SizeT d1) // { return (*this)[d1];} // only used from DStructGDL template Data_& Data_::operator=(const BaseGDL& r) { assert( r.Type() == this->Type()); const Data_& right = static_cast&>( r); assert( &right != this); // if( &right == this) return *this; // self assignment this->dim = right.dim; dd = right.dd; return *this; } // only used from DStructGDL template<> Data_& Data_::operator=(const BaseGDL& r) { assert( r.Type() == this->Type()); const Data_& right = static_cast( r); assert( &right != this); // if( &right == this) return *this; // self assignment this->dim = right.dim; GDLInterpreter::DecRef( this); dd = right.dd; GDLInterpreter::IncRef( this); return *this; } // only used from DStructGDL template<> Data_& Data_::operator=(const BaseGDL& r) { assert( r.Type() == this->Type()); const Data_& right = static_cast( r); assert( &right != this); // if( &right == this) return *this; // self assignment this->dim = right.dim; GDLInterpreter::DecRefObj( this); dd = right.dd; GDLInterpreter::IncRefObj( this); return *this; } template void Data_::InitFrom(const BaseGDL& r) { assert( r.Type() == this->Type()); const Data_& right = static_cast&>( r); assert( &right != this); // if( &right == this) return *this; // self assignment this->dim = right.dim; dd.InitFrom( right.dd); // return *this; } // only used from DStructGDL::DStructGDL(const DStructGDL& d_) template<> void Data_::InitFrom(const BaseGDL& r) { assert( r.Type() == this->Type()); const Data_& right = static_cast( r); assert( &right != this); // if( &right == this) return *this; // self assignment this->dim = right.dim; // GDLInterpreter::DecRef( this); dd.InitFrom( right.dd); GDLInterpreter::IncRef( this); // return *this; } // only used from DStructGDL::DStructGDL(const DStructGDL& d_) template<> void Data_::InitFrom(const BaseGDL& r) { assert( r.Type() == this->Type()); const Data_& right = static_cast( r); assert( &right != this); // if( &right == this) return *this; // self assignment this->dim = right.dim; // GDLInterpreter::DecRefObj( this); dd.InitFrom( right.dd); GDLInterpreter::IncRefObj( this); // return *this; } template< class Sp> bool Data_::EqType( const BaseGDL* r) const { return (this->Type() == r->Type());} template< class Sp> void* Data_::DataAddr()// SizeT elem) { return &(*this)[0];}//elem];} // template<> // void* Data_::DataAddr()// SizeT elem) // { // throw GDLException("STRING not allowed in this context."); // return NULL; // } // template<> // void* Data_::DataAddr()// SizeT elem) // { // throw GDLException("PTR not allowed in this context."); // return NULL; // } // template<> // void* Data_::DataAddr()// SizeT elem) // { // throw GDLException("Object expression not allowed in this context."); // return NULL; // } template< class Sp> SizeT Data_::N_Elements() const { return dd.size();} template<> SizeT Data_::N_Elements() const { if( !this->StrictScalar()) return dd.size(); #if 1 // GJ change this and see how many problems it solves, creates. 2016/5/5 else return 1; #elif 0 DObj s = dd[0]; // is StrictScalar() if( s == 0) // no overloads for null object return 1; DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s); if( oStructGDL == NULL) // if object not valid -> default behaviour return 1; DStructDesc* desc = oStructGDL->Desc(); if( desc->IsParent("LIST")) { // no static here, might vary in derived object unsigned nListTag = desc->TagIndex( "NLIST"); SizeT listSize = (*static_cast(oStructGDL->GetTag( nListTag, 0)))[0]; return listSize; } if( desc->IsParent("HASH")) { // no static here, might vary in derived object unsigned nListTag = desc->TagIndex( "TABLE_COUNT"); SizeT listSize = (*static_cast(oStructGDL->GetTag( nListTag, 0)))[0]; return listSize; } return 1; #endif } template< class Sp> SizeT Data_::Size() const { return dd.size();} template< class Sp> SizeT Data_::Sizeof() const { return sizeof(Ty);} template< class Sp> void Data_::Clear() { SizeT nEl = dd.size(); /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i void Data_::Construct() { // note that this is not possible in cases where an operation // (here: 'new' which is ok) isn't defined for any POD // (although this code never executes and should be optimized away anyway) const bool isPOD = Sp::IS_POD; // do nothing for POD if( !isPOD) { SizeT nEl = dd.size(); // for( SizeT i = 0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i void Data_::Construct() { SizeT nEl = dd.size(); // for( SizeT i = 0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i void Data_::Construct() { SizeT nEl = dd.size(); // for( SizeT i = 0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i // void Data_< SpDString>::Construct() // { // SizeT nEl = dd.size(); // // for( SizeT i = 0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( SizeT i = 0; i // void Data_< SpDComplex>::Construct() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( SizeT i = 0; i // void Data_< SpDComplexDbl>::Construct() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( SizeT i = 0; i void Data_::ConstructTo0() { if( Sp::IS_POD) { SizeT nEl = dd.size(); /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i // void Data_< SpDString>::ConstructTo0() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( int i = 0; i // void Data_< SpDComplex>::ConstructTo0() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( int i = 0; i // void Data_< SpDComplexDbl>::ConstructTo0() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( int i = 0; i void Data_::Destruct() { // no destruction for POD if( !Sp::IS_POD) { SizeT nEl = dd.size(); /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i = 0; i void Data_< SpDPtr>::Destruct() { GDLInterpreter::DecRef( this); } template<> void Data_< SpDObj>::Destruct() { GDLInterpreter::DecRefObj( this); } // template<> // void Data_< SpDString>::Destruct() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( SizeT i = 0; i // void Data_< SpDComplex>::Destruct() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( SizeT i = 0; i // void Data_< SpDComplexDbl>::Destruct() // { // SizeT nEl = dd.size(); // /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) // { // #pragma omp for*/ // for( SizeT i = 0; i BaseGDL* Data_::SetBuffer( const void* b) { dd.SetBuffer( static_cast< Ty*>(const_cast( b))); return this; } template< class Sp> void Data_::SetBufferSize( SizeT s) { dd.SetBufferSize( s); } // template< class Sp> // Data_* Data_::Dup() // { return new Data_(*this);} template< class Sp> Data_* Data_::New( const dimension& dim_, BaseGDL::InitType noZero) const { if( noZero == BaseGDL::NOZERO) return new Data_(dim_, BaseGDL::NOZERO); if( noZero == BaseGDL::INIT) { Data_* res = new Data_(dim_, BaseGDL::NOZERO); SizeT nEl = res->dd.size(); /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( SizeT i=0; i Data_* Data_::NewResult() const { return new Data_(this->dim, BaseGDL::NOZERO); } // template< class Sp> // bool Data_::Scalar() const // { // return (dd.size() == 1); // } // template< class Sp> // bool Data_::Scalar(Ty& s) const // { // if( dd.size() != 1) return false; // s=(*this)[0]; // return true; // } template SizeT Data_::NBytes() const { return (dd.size() * sizeof(Ty));} // string, ptr, obj cannot calculate their bytes // only used by assoc function template<> SizeT Data_::NBytes() const { SizeT nEl = dd.size(); SizeT nB = 0; /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( int i=0; i SizeT Data_::NBytes() const // { // throw GDLException("object references"); // } // template<> SizeT Data_::NBytes() const // { // throw GDLException("pointers"); // } template SizeT Data_::ToTransfer() const { return dd.size(); } // complex has 2 elements to transfer template<> SizeT Data_::ToTransfer() const { return N_Elements() * 2; } template<> SizeT Data_::ToTransfer() const { return N_Elements() * 2; } // // note that min and max are not defined in BaseGDL // template // typename Data_::Ty Data_::min() const // { return dd.min();} // template // typename Data_::Ty Data_::max() const // { return dd.max();} // template<> // Data_::Ty Data_::min() const // { // throw GDLException("COMPLEX expression not allowed in this context."); // } // template<> // Data_::Ty Data_::max() const // { // throw GDLException("COMPLEX expression not allowed in this context."); // } // template<> // Data_::Ty Data_::min() const // { // throw GDLException("COMPLEXDBL expression not allowed in this context."); // } // template<> // Data_::Ty Data_::max() const // { // throw GDLException("COMPLEXDBL expression not allowed in this context."); // } // for HASH objects template DDouble Data_::HashValue() const { return static_cast((*this)[0]); } template<> DDouble Data_::HashValue() const { return real((*this)[0]); } template<> DDouble Data_::HashValue() const { return real((*this)[0]); } template<> DDouble Data_::HashValue() const { throw GDLException("STRING expression not allowed as index. Please report."); return 0; // get rid of warning } template<> DDouble Data_::HashValue() const { throw GDLException("PTR expression not allowed as index. Please report."); return 0; // get rid of warning } template<> DDouble Data_::HashValue() const { throw GDLException("Object expression not allowed as index. Please report."); return 0; // get rid of warning } // -1 -> p2 is greater // 0 -> equal // 1 -> this is greater // note: this is for internal use only (for HASH objects) // this should not be called on non-numeric types (also for p2) template int Data_::HashCompare( BaseGDL* p2) const { assert( dd.size() == 1); assert( p2->N_Elements() == 1); if( p2->Type() == GDL_STRING) return 1; // strings 1st (smallest) assert( NumericType(p2->Type())); if( this->IS_INTEGER) { if( IntType( p2->Type())) // make full use of data type { RangeT thisValue = this->LoopIndex(); RangeT p2Value = p2->LoopIndex(); if( thisValue == p2Value) return 0; if( thisValue < p2Value) return -1; return 1; } } DDouble thisValue = this->HashValue(); DDouble p2Value = p2->HashValue(); if( thisValue == p2Value) return 0; if( thisValue < p2Value) return -1; return 1; } template<> int Data_::HashCompare( BaseGDL* p2) const { assert( dd.size() == 1); assert( p2->N_Elements() == 1); if( p2->Type() != this->Type()) return -1; // strings 1st (smallest) Data_* p2String = static_cast(p2); if( dd[0].length() == (*p2String)[0].length()) { if( dd[0] == (*p2String)[0]) return 0; if( dd[0] < (*p2String)[0]) return -1; return 1; } else if( dd[0].length() < (*p2String)[0].length()) { return -1; } return 1; } // Scalar2Index // used by the interpreter // -2 < 0 array // -1 < 0 scalar // 0 empty or array // 1 scalar // 2 one-element array template int Data_::Scalar2Index( SizeT& st) const { if( dd.size() != 1) return 0; // the next statement gives a warning for unsigned integer types: // "comparison is always false due to limited range of data type" // This is because the same template is used here for signed and // unsigned data. A template specialization for the unsigned integer // types would result in three identical specializations, which is bad // for maintainability. And as any modern C++ compiler will optimize // away the superflous (for unsigned data) statement anyway, it is // better to keep the code this way here. if( (*this)[0] < 0) { if( this->dim.Rank() != 0) return -2; else return -1; } st= static_cast((*this)[0]); if( this->dim.Rank() != 0) return 2; return 1; } template int Data_::Scalar2RangeT( RangeT& st) const { if( dd.size() != 1) return 0; st= static_cast((*this)[0]); if( this->dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2Index( SizeT& st) const { if( dd.size() != 1) return 0; float r=real((*this)[0]); if( r < 0.0) return -1; st= static_cast(r); if( this->dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2RangeT( RangeT& st) const { if( dd.size() != 1) return 0; float r=real((*this)[0]); st= static_cast(r); if( this->dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2Index( SizeT& st) const { if( dd.size() != 1) return 0; double r=real((*this)[0]); if( r < 0.0) return -1; st= static_cast(r); if( this->dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2RangeT( RangeT& st) const { if( dd.size() != 1) return 0; double r=real((*this)[0]); st= static_cast(r); if( this->dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2Index( SizeT& st) const { if( dd.size() != 1) return 0; SizeT tSize=(*this)[0].size(); if( tSize == 0) { st=0; } else { long int number = Str2L( (*this)[0].c_str()); if( number < 0) return -1; st=number; } if( dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2RangeT( RangeT& st) const { if( dd.size() != 1) return 0; SizeT tSize=(*this)[0].size(); if( tSize == 0) { st=0; } else { long int number = Str2L( (*this)[0].c_str()); st=number; } if( dim.Rank() != 0) return 2; return 1; } template<> int Data_::Scalar2Index( SizeT& st) const { throw GDLException("PTR expression not allowed in this context."); return 0; // get rid of warning } template<> int Data_::Scalar2RangeT( RangeT& st) const { throw GDLException("PTR expression not allowed in this context."); return 0; // get rid of warning } template<> int Data_::Scalar2Index( SizeT& st) const { throw GDLException("Object expression not allowed in this context."); return 0; // get rid of warning } template<> int Data_::Scalar2RangeT( RangeT& st) const { throw GDLException("Object expression not allowed in this context."); return 0; // get rid of warning } // for FOR loop *indices* template RangeT Data_::LoopIndex() const { // if( dd.size() != 1) return 0; // the next statement gives a warning for unsigned integer types: // "comparison is always false due to limited range of data type" // This is because the same template is used here for signed and // unsigned data. A template specialization for the unsigned integer // types would result in three identical specializations, which is bad // for maintainability. And as any modern C++ compiler will optimize // away the superflous (for unsigned data) statement anyway, it is // better to keep the code this way here. // if( (*this)[0] < 0) // throw GDLException( "Index variable <0."); return static_cast((*this)[0]); } template<> RangeT Data_::LoopIndex() const { // if( (*this)[0] < 0.0f) // //if( (*this)[0] <= 1.0f) // throw GDLException( "Index variable <0."); //else // return 0; return static_cast((*this)[0]); } template<> RangeT Data_::LoopIndex() const { // if( (*this)[0] < 0.0) // //if( (*this)[0] <= 1.0) // throw GDLException( "Index variable <0."); //else // return 0; return static_cast((*this)[0]); } template<> RangeT Data_::LoopIndex() const { throw GDLException( "Complex expression not allowed as index."); return 0; } template<> RangeT Data_::LoopIndex() const { throw GDLException( "Complex expression not allowed as index."); return 0; } template<> RangeT Data_::LoopIndex() const { if( (*this)[0] == "") return 0; const char* cStart=(*this)[0].c_str(); char* cEnd; RangeT ix=strtol(cStart,&cEnd,10); if( cEnd == cStart) { Warning( "Type conversion error: " "Unable to convert given STRING: '"+ (*this)[0]+"' to index."); return 0; } return ix; } template<> RangeT Data_::LoopIndex() const { throw GDLException("PTR expression not allowed as index."); return 0; // get rid of warning } template<> RangeT Data_::LoopIndex() const { throw GDLException("Object expression not allowed as index."); return 0; // get rid of warning } // True template bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s % 2); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0.0f); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0.0); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != ""); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (real(s) != 0.0 || imag(s) != 0.0); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (real(s) != 0.0 || imag(s) != 0.0); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0); } template<> bool Data_::True() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); if( s == 0) return false; // on overloads for null object -> default is 'false' // DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s); // if( oStructGDL == NULL) // object not valid -> default behaviour // return true; // true is ok here: Default behaviour is to just checks for null object // // DStructDesc* desc = oStructGDL->Desc(); // // DFun* isTrueOverload = static_cast(desc->GetOperator( OOIsTrue)); DSubUD* isTrueOverload = static_cast(GDLInterpreter::GetObjHeapOperator( s, OOIsTrue)); if( isTrueOverload == NULL) return true; // not overloaded, false case for default already returned (s. a.) ProgNodeP callingNode = interpreter->GetRetTree(); // BaseGDL* self = this->Dup(); // Guard selfGuard( self); // EnvUDT* newEnv= new EnvUDT( callingNode, isTrueOverload, &self); // no parameters EnvUDT* newEnv; DObjGDL* self; Guard selfGuard; // Dup() here is not optimal // avoid at least for internal overload routines (which do/must not change SELF or r) bool internalDSubUD = isTrueOverload->GetTree()->IsWrappedNode(); if( internalDSubUD) { self = this; newEnv= new EnvUDT( callingNode, isTrueOverload, &self); } else { self = this->Dup(); selfGuard.Init( self); newEnv= new EnvUDT( callingNode, isTrueOverload, &self); } StackGuard guard(interpreter->CallStack()); interpreter->CallStack().push_back( newEnv); // make the call BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); if( !internalDSubUD && self != selfGuard.Get()) { // always put out warning first, in case of a later crash Warning( "WARNING: " + isTrueOverload->ObjectName() + ": Assignment to SELF detected (GDL session still ok)."); // assignment to SELF -> self was deleted and points to new variable // which it owns selfGuard.Release(); if( (BaseGDL*)self != NullGDL::GetSingleInstance()) selfGuard.Reset(self); } if( NullGDL::IsNULLorNullGDL( res)) { throw GDLException( isTrueOverload->ObjectName() + " returned an undefined value.",true,false); } Guard resGuard( res); // prevent recursion if( res->Type() == GDL_OBJ) { ostringstream os; res->ToStream(os); throw GDLException( isTrueOverload->ObjectName() + ": Object reference expression not allowed in this context: " + os.str(),true,false); } return res->LogTrue(); } // False template bool Data_::False() { return !True(); } // Sgn template int Data_::Sgn() // -1,0,1 { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); if( s > 0) return 1; if( s == 0) return 0; return -1; } template<> int Data_::Sgn() // -1,0,1 { throw GDLException("String expression not allowed in this context."); return 0; } template<> int Data_::Sgn() // -1,0,1 { throw GDLException("Complex expression not allowed in this context."); return 0; } template<> int Data_::Sgn() // -1,0,1 { throw GDLException("Complex expression not allowed in this context."); return 0; } template<> int Data_::Sgn() // -1,0,1 { throw GDLException("Ptr expression not allowed in this context."); return 0; } template<> int Data_::Sgn() // -1,0,1 { throw GDLException("Object expression not allowed in this context."); return 0; } // Equal (deletes r) only used in ForCheck(...) template bool Data_::Equal( BaseGDL* r) const { assert( r->StrictScalar()); // if( !r->Scalar()) // { // GDLDelete(r); // throw GDLException("Expression must be a scalar in this context."); // } assert( r->Type() == this->t); Data_* rr=static_cast(r); // Data_* rr=static_cast(r->Convert2( this->t)); bool ret= ((*this)[0] == (*rr)[0]); GDLDelete(rr); return ret; } template<> bool Data_::Equal( BaseGDL* r) const { assert( r->StrictScalar()); // if( !r->Scalar()) // { // GDLDelete(r); // throw GDLException("Expression must be a scalar in this context."); // } assert( r->Type() == this->t); Data_* rr=static_cast(r); // Data_* rr=static_cast(r->Convert2( this->t)); bool ret= fabs((*this)[0] - (*rr)[0]) < 1.0f; GDLDelete(rr); return ret; } template<> bool Data_::Equal( BaseGDL* r) const { assert( r->StrictScalar()); // if( !r->Scalar()) // { // GDLDelete(r); // throw GDLException("Expression must be a scalar in this context."); // } assert( r->Type() == this->t); Data_* rr=static_cast(r); // Data_* rr=static_cast(r->Convert2( this->t)); bool ret= fabs((*this)[0] - (*rr)[0]) < 1.0; GDLDelete(rr); return ret; } // Equal (does not delete r) template bool Data_::EqualNoDelete( const BaseGDL* r) const { if( !r->Scalar()) { throw GDLException("Expression must be a scalar in this context."); } bool ret; if( r->Type() != this->t) { Data_* rr=static_cast(const_cast(r)->Convert2( this->t, BaseGDL::COPY)); ret= ((*this)[0] == (*rr)[0]); GDLDelete(rr); } else { const Data_* rr=static_cast(r); ret= ((*this)[0] == (*rr)[0]); } return ret; } bool DStructGDL::Equal( BaseGDL* r) const { GDLDelete(r); throw GDLException("Struct expression not allowed in this context."); return false; } // For array_equal r must be of same type template bool Data_::ArrayEqual( BaseGDL* rIn) { Data_* r = static_cast*> (rIn); SizeT nEl = N_Elements(); SizeT rEl = r->N_Elements(); if (rEl == 1) { for (SizeT i = 0; i < nEl; ++i) if ((*this)[i] != (*r)[0]) return false; return true; } if (nEl == 1) { for (SizeT i = 0; i < rEl; ++i) if ((*this)[0] != (*r)[i]) return false; return true; } if (nEl != rEl) return false; for (SizeT i = 0; i < nEl; ++i) if ((*this)[i] != (*r)[i]) return false; return true; } bool DStructGDL::ArrayEqual( BaseGDL* r) { throw GDLException("Struct expression not allowed in this context."); return false; } // For array_equal r must be of same type template bool Data_::ArrayNeverEqual( BaseGDL* rIn) { Data_* r = static_cast< Data_*>( rIn); SizeT nEl = N_Elements(); SizeT rEl = r->N_Elements(); if( rEl == 1) { for( SizeT i=0; i bool Data_::OutOfRangeOfInt() const { assert( this->StrictScalar()); return (*this)[0] > std::numeric_limits< DInt>::max() || (*this)[0] < std::numeric_limits< DInt>::min(); } template<> bool Data_::OutOfRangeOfInt() const { return false; } template<> bool Data_::OutOfRangeOfInt() const { return false; } template<> bool Data_::OutOfRangeOfInt() const { return false; } template<> bool Data_::OutOfRangeOfInt() const { return false; } // for statement compliance (int types , float types scalar only) // (convert strings to floats here (not for first argument) template void Data_::ForCheck( BaseGDL** lEnd, BaseGDL** lStep) { // all scalars? if( !StrictScalar()) throw GDLException("Loop INIT must be a scalar in this context."); if( !(*lEnd)->StrictScalar()) throw GDLException("Loop LIMIT must be a scalar in this context."); if( lStep != NULL && !(*lStep)->StrictScalar()) throw GDLException("Loop INCREMENT must be a scalar in this context."); // only proper types? if( this->t== GDL_UNDEF) throw GDLException("Expression is undefined."); if( this->t== GDL_COMPLEX || this->t == GDL_COMPLEXDBL) throw GDLException("Complex expression not allowed in this context."); if( this->t== GDL_PTR) throw GDLException("Pointer expression not allowed in this context."); if( this->t== GDL_OBJ) throw GDLException("Object expression not allowed in this context."); if( this->t== GDL_STRING) throw GDLException("String expression not allowed in this context."); // check for promotion of this (only GDL_INT) // and GDL_LONG ??? DType lType = (*lEnd)->Type(); if( this->t == GDL_INT && lType != GDL_INT) { if( lType == GDL_COMPLEX || lType == GDL_COMPLEXDBL) throw GDLException("Complex expression not allowed in this context."); if( lType == GDL_STRING) { *lEnd=(*lEnd)->Convert2( GDL_LONG); // try with long if( !(*lEnd)->OutOfRangeOfInt()) { *lEnd=(*lEnd)->Convert2( GDL_INT); // back to GDL_INT if within range } } else if( !(*lEnd)->OutOfRangeOfInt()) { *lEnd=(*lEnd)->Convert2( GDL_INT); // regular conversion } // if the GDL_INT range is exceeded, lEnd is NOT changed if( lStep != NULL) *lStep=(*lStep)->Convert2( (*lEnd)->Type()); return; // finished for GDL_INT } if( this->t == GDL_LONG) { if( lType == GDL_COMPLEX || lType == GDL_COMPLEXDBL) throw GDLException("Complex expression not allowed in this context."); } // no promotion happened *lEnd=(*lEnd)->Convert2( this->t); if( lStep != NULL) *lStep=(*lStep)->Convert2( this->t); } void DStructGDL::ForCheck( BaseGDL** lEnd, BaseGDL** lStep) { throw GDLException("Struct expression not allowed in this context."); } // ForCheck must have been called before template bool Data_::ForAddCondUp( BaseGDL* endLoopVar) // bool Data_::ForAddCondUp( ForLoopInfoT& loopInfo) { (*this)[0] += 1; // Data_* lEnd=static_cast(lEndIn); if( endLoopVar->Type() != this->t) throw GDLException("Type of FOR index variable changed."); Data_* lEnd=static_cast(endLoopVar); /* Data_* lEnd=dynamic_cast(endLoopVar); if( lEnd == NULL) throw GDLException("Type of FOR index variable changed.");*/ return (*this)[0] <= (*lEnd)[0]; } // ForCheck must have been called before template bool Data_::ForCondUp( BaseGDL* lEndIn) { // Data_* lEnd=static_cast(lEndIn); if( lEndIn->Type() != this->t) throw GDLException("Type of FOR index variable changed."); Data_* lEnd=static_cast(lEndIn); /* Data_* lEnd=dynamic_cast(lEndIn); if( lEnd == NULL) throw GDLException("Type of FOR index variable changed.");*/ return (*this)[0] <= (*lEnd)[0]; } template bool Data_::ForCondDown( BaseGDL* lEndIn) { // Data_* lEnd=static_cast(lEndIn); if( lEndIn->Type() != this->t) throw GDLException("Type of FOR index variable changed."); Data_* lEnd=static_cast(lEndIn); /* Data_* lEnd=dynamic_cast(lEndIn); if( lEnd == NULL) throw GDLException("Type of FOR index variable changed.");*/ return (*this)[0] >= (*lEnd)[0]; } // error if the type of the loop variable changed bool DStructGDL::ForCondUp( BaseGDL*) { throw GDLException("Type of FOR index variable changed to STRUCT."); return false; } bool DStructGDL::ForCondDown( BaseGDL*) { throw GDLException("Type of FOR index variable changed to STRUCT."); return false; } template<> bool Data_::ForCondUp( BaseGDL*) { throw GDLException("Type of FOR index variable changed to COMPLEX."); return false; } template<> bool Data_::ForAddCondUp( BaseGDL* loopInfo) // bool Data_::ForAddCondUp( ForLoopInfoT& loopInfo) { throw GDLException("Type of FOR index variable changed to COMPLEX."); return false; } template<> bool Data_::ForCondDown( BaseGDL*) { throw GDLException("Type of FOR index variable changed to COMPLEX."); return false; } template<> bool Data_::ForAddCondUp( BaseGDL* loopInfo) // bool Data_::ForAddCondUp( ForLoopInfoT& loopInfo) { throw GDLException("Type of FOR index variable changed to DCOMPLEX."); return false; } template<> bool Data_::ForCondUp( BaseGDL*) { throw GDLException("Type of FOR index variable changed to DCOMPLEX."); return false; } template<> bool Data_::ForCondDown( BaseGDL*) { throw GDLException("Type of FOR index variable changed to DCOMPLEX."); return false; } // ForCheck must have been called before // general version template void Data_::ForAdd( BaseGDL* addIn) { if( addIn == NULL) { (*this)[0] += 1; return; } Data_* add=static_cast(addIn); (*this)[0] += (*add)[0]; } // cannnot be called, just to make the compiler shut-up void DStructGDL::ForAdd( BaseGDL* addIn) {} // normal (+1) version template void Data_::ForAdd() { (*this)[0] += 1; } // cannnot be called, just to make the compiler shut-up void DStructGDL::ForAdd() {} template void Data_::AssignAtIx( RangeT ixR, BaseGDL* srcIn) { if( ixR < 0) { SizeT nEl = this->N_Elements(); if( -ixR > nEl) throw GDLException("Subscript out of range: " + i2s(ixR)); SizeT ix = nEl + ixR; if( srcIn->Type() != this->Type()) { Data_* rConv = static_cast(srcIn->Convert2( this->Type(), BaseGDL::COPY_BYTE_AS_INT)); // Data_* rConv = static_cast(srcIn->Convert2( this->Type(), BaseGDL::COPY)); Guard conv_guard( rConv); (*this)[ix] = (*rConv)[0]; } else (*this)[ix] = (*static_cast(srcIn))[0]; return; } // ixR >= 0 if( srcIn->Type() != this->Type()) { Data_* rConv = static_cast(srcIn->Convert2( this->Type(), BaseGDL::COPY_BYTE_AS_INT)); // Data_* rConv = static_cast(srcIn->Convert2( this->Type(), BaseGDL::COPY)); Guard conv_guard( rConv); (*this)[ixR] = (*rConv)[0]; } else (*this)[ixR] = (*static_cast(srcIn))[0]; } // assigns srcIn to this at ixList, if ixList is NULL does linear copy // assumes: ixList has this already set as variable // used by DotAccessDescT::DoAssign // GDLInterpreter::l_array_expr template void Data_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); // bool isScalar= (srcElem == 1); bool isScalar= (srcElem == 1) && (src->Rank() == 0); if( isScalar) { // src is scalar Ty scalar=(*src)[0]; if( ixList == NULL) { SizeT nCp=Data_::N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()]=scalar; for( SizeT c=1; cSeqAccess()]=scalar; //} // (*this)[ ixList->GetIx( c)]=scalar; } } else { if( ixList == NULL) { SizeT nCp=Data_::N_Elements(); // if (non-indexed) src is smaller -> just copy its number of elements if( nCp > (srcElem-offset)) { if( offset == 0) nCp=srcElem; else throw GDLException("Source expression contains not enough elements."); } /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); if( nCp == 1) { SizeT destStart = ixList->LongIx(); // len = 1; SizeT rStride = srcIn->Stride(this->Rank()); (*this)[ destStart] = (*src)[ offset/rStride]; // InsAt( src, ixList, offset); } else { if( offset == 0) { if( srcElem < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()]=(*src)[0]; for( SizeT c=1; cSeqAccess()]=(*src)[c]; // } // (*this)[ ixList->GetIx( c)]=(*src)[c+offset]; } else { if( (srcElem-offset) < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()]=(*src)[offset]; for( SizeT c=1; cSeqAccess()]=(*src)[c+offset]; // } // (*this)[ ixList->GetIx( c)]=(*src)[c+offset]; } } } } } template void Data_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { assert( ixList != NULL); // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); bool isScalar= (srcElem == 1); if( isScalar) { // src is scalar SizeT nCp=ixList->N_Elements(); if( nCp == 1) { (*this)[ ixList->LongIx()] = (*src)[0]; } else { Ty scalar=(*src)[0]; AllIxBaseT* allIx = ixList->BuildIx(); (*this)[ allIx->InitSeqAccess()]=scalar; /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=1; cSeqAccess()]=scalar; // (*this)[ (*allIx)[ c]]=scalar; // } // (*this)[ ixList->GetIx( c)]=scalar; } } else { // crucial part SizeT nCp=ixList->N_Elements(); if( nCp == 1) { InsAt( src, ixList); } else { if( srcElem < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); (*this)[ allIx->InitSeqAccess()]=(*src)[0]; /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=1; cSeqAccess()]=(*src)[c]; // (*this)[ (*allIx)[ c]]=(*src)[c]; // } // (*this)[ ixList->GetIx( c)]=(*src)[c+offset]; } } } template void Data_::AssignAt( BaseGDL* srcIn) { // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); bool isScalar= (srcElem == 1); if( isScalar) { // src is scalar Ty scalar=(*src)[0]; /* dd = scalar;*/ SizeT nCp=Data_::N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; c just copy its number of elements if( nCp > srcElem) nCp=srcElem; /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; c void Data_::DecAt( ArrayIndexListT* ixList) { if( ixList == NULL) { dd -= 1; // SizeT nCp=Data_::N_Elements(); // for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()]--; for( SizeT c=1; cSeqAccess()]--; }// } } template void Data_::IncAt( ArrayIndexListT* ixList) { if( ixList == NULL) { dd += 1; // SizeT nCp=Data_::N_Elements(); // for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()]++; for( SizeT c=1; cSeqAccess()]++; }// } } // float, double template<> void Data_::DecAt( ArrayIndexListT* ixList) { if( ixList == NULL) { dd -= 1.0f; // SizeT nCp=Data_::N_Elements(); // for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] -= 1.0f; for( SizeT c=1; cSeqAccess()] -=1.0f; }// } } template<> void Data_::IncAt( ArrayIndexListT* ixList) { if( ixList == NULL) { dd += 1.0f; // SizeT nCp=Data_::N_Elements(); // for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] += 1.0f; for( SizeT c=1; cSeqAccess()] +=1.0f; }// } } template<> void Data_::DecAt( ArrayIndexListT* ixList) { if( ixList == NULL) { dd -= 1.0; // SizeT nCp=Data_::N_Elements(); // for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] -= 1.0; for( SizeT c=1; cSeqAccess()] -=1.0; }// } } template<> void Data_::IncAt( ArrayIndexListT* ixList) { if( ixList == NULL) { dd += 1.0; // SizeT nCp=Data_::N_Elements(); // for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] += 1.0f; for( SizeT c=1; cSeqAccess()] +=1.0f; }// } } // complex template<> void Data_::DecAt( ArrayIndexListT* ixList) { if( ixList == NULL) { // dd -= 1.0f; SizeT nCp=Data_::N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] -= 1.0; for( SizeT c=1; cSeqAccess()] -=1.0; // for( SizeT c=0; c void Data_::IncAt( ArrayIndexListT* ixList) { if( ixList == NULL) { // dd += 1.0f; SizeT nCp=Data_::N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] += 1.0; for( SizeT c=1; cSeqAccess()] +=1.0; // for( SizeT c=0; c void Data_::DecAt( ArrayIndexListT* ixList) { if( ixList == NULL) { // dd -= 1.0; SizeT nCp=Data_::N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] -= 1.0; for( SizeT c=1; cSeqAccess()] -=1.0; // for( SizeT c=0; c void Data_::IncAt( ArrayIndexListT* ixList) { if( ixList == NULL) { // dd += 1.0; SizeT nCp=Data_::N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ allIx->InitSeqAccess()] += 1.0; for( SizeT c=1; cSeqAccess()] +=1.0; // for( SizeT c=0; c void Data_::DecAt( ArrayIndexListT* ixList) { throw GDLException("String expression not allowed in this context."); } template<> void Data_::DecAt( ArrayIndexListT* ixList) { throw GDLException("Pointer expression not allowed in this context."); } template<> void Data_::DecAt( ArrayIndexListT* ixList) { throw GDLException("Object expression not allowed in this context."); } template<> void Data_::IncAt( ArrayIndexListT* ixList) { throw GDLException("String expression not allowed in this context."); } template<> void Data_::IncAt( ArrayIndexListT* ixList) { throw GDLException("Pointer expression not allowed in this context."); } template<> void Data_::IncAt( ArrayIndexListT* ixList) { throw GDLException("Object expression not allowed in this context."); } // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset // used by DotAccessDescT::DoResolve template void Data_::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { Data_* src=static_cast(srcIn); if( ixList == NULL) { SizeT nCp=src->N_Elements(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*this)[ offset]=(*src)[ allIx->InitSeqAccess()]; for( SizeT c=1; cSeqAccess()]; //} // (*this)[ c+offset]=(*src)[ ixList->GetIx( c)]; } } // used for array concatenation template Data_* Data_::CatArray( ExprListT& exprList, const SizeT catRankIx, const SizeT rank) { // breakpoint(); SizeT rankIx = RankIx( rank); SizeT maxIx = (catRankIx > rankIx)? catRankIx : rankIx; dimension catArrDim(this->dim); // list contains at least one element catArrDim.MakeRank( maxIx+1); catArrDim.SetOneDim(catRankIx,0); // clear rank which is added up SizeT dimSum=0; ExprListIterT i=exprList.begin(); for(; i != exprList.end(); ++i) { // conversion done already here to throw if type is Assoc_<> (*i)=(*i)->Convert2( this->t); for( SizeT dIx=0; dIx<=maxIx; dIx++) { if( dIx != catRankIx) { if( catArrDim[dIx] == (*i)->Dim(dIx)) continue; if( (catArrDim[dIx] > 1) || ((*i)->Dim(dIx) > 1)) throw GDLException("Unable to concatenate variables " "because the dimensions do not agree"); } else { SizeT add=(*i)->Dim(dIx); dimSum+=(add)?add:1; } } } catArrDim.SetOneDim(catRankIx,dimSum); // the concatenated array Data_* catArr=New(catArrDim, BaseGDL::NOZERO); SizeT at=0; for( i=exprList.begin(); i != exprList.end(); ++i) { catArr->CatInsert(static_cast*>( (*i)), catRankIx,at); // advances 'at' } return catArr; } // returns (*this)[ ixList] template Data_* Data_::Index( ArrayIndexListT* ixList) { // ixList->SetVariable( this); Data_* res=Data_::New( ixList->GetDim(), BaseGDL::NOZERO); SizeT nCp=ixList->N_Elements(); // cout << "nCP = " << nCp << endl; // cout << "dim = " << this->dim << endl; // DataT& res_dd = res->dd; AllIxBaseT* allIx = ixList->BuildIx(); if( nCp == 1) { (*res)[0]=(*this)[ (*allIx)[ 0]]; return res; } // else // { /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ (*res)[0]=(*this)[ allIx->InitSeqAccess()]; for( SizeT c=1; cSeqAccess()]; //} // res_(*this)[c]=(*this)[ (*allIx)[ c]]; // (*res)[c]=(*this)[ ixList->GetIx(c)]; // } return res; } // inserts srcIn at index ixDim // respects the exact structure of srcIn template void Data_::InsAt( Data_* srcIn, ArrayIndexListT* ixList, SizeT offset) { // max. number of dimensions to copy SizeT nDim = ixList->NDim(); if( nDim == 1) // { // SizeT destStart = ixList->LongIx(); // SizeT len = srcIn->Dim( 0); // length of segment to copy // // check if in bounds of a // if( (destStart+len) > this->N_Elements()) //dim[0]) // throw GDLException("Out of range subscript encountered (1)."); // DataT& srcIn_dd = srcIn->dd; // SizeT srcIx = 0; // this one simply runs from 0 to N_Elements(srcIn) // SizeT destEnd = destStart + len; // for( SizeT destIx = destStart; destIx < destEnd; ++destIx) // (*this)[ destIx] = (*srcIn)[ srcIx++]; // return; // } { SizeT destStart = ixList->LongIx(); //SizeT len; if( this->N_Elements() == 1) { // len = 1; SizeT rStride = srcIn->Stride(this->Rank()); (*this)[ destStart] = (*srcIn)[ offset/rStride]; } else { SizeT len = srcIn->Dim( 0); // length of segment to copy // TODO: IDL reports here (and probably in the insert-dimension case below as well) // the name of a variable, e.g.: // IDL> a=[0,0,0] & a[2]=[2,2,2] // % Out of range subscript encountered: A. if( (destStart+len) > this->N_Elements()) //dim[0]) throw GDLException("Out of range subscript encountered (length of insert exceeds array boundaries)."); // DataT& srcIn_dd = srcIn->dd; SizeT srcIx = 0; // this one simply runs from 0 to N_Elements(srcIn) SizeT destEnd = destStart + len; for( SizeT destIx = destStart; destIx < destEnd; ++destIx) (*this)[ destIx] = (*srcIn)[ srcIx++]; } return; } SizeT destStart; // 1-dim starting index // ATTENTION: dimension is used as an index here dimension ixDim = ixList->GetDimIx0( destStart); nDim--; dimension srcDim=srcIn->Dim(); srcDim.Purge(); // newly inserted: ticket #675 SizeT len=srcDim[0]; // length of one segment to copy (one line of srcIn) // SizeT nDim =RankIx(ixDim.Rank()); SizeT srcNDim=RankIx(srcDim.Rank()); // number of source dimensions if( srcNDim < nDim) nDim=srcNDim; // check limits (up to Rank to consider) for( SizeT dIx=0; dIx <= nDim; ++dIx) // check if in bounds of a if( (ixDim[dIx]+srcDim[dIx]) > this->dim[dIx]) throw GDLException("Out of range subscript encountered (dimension of insert exceeds array boundaries for dimension " + i2s(dIx +1) + ")."); SizeT nCp=srcIn->Stride(nDim+1)/len; // number of OVERALL copy actions // as lines are copied, we need the stride from 2nd dim on SizeT retStride[MAXRANK+1]; for( SizeT a=0; a <= nDim; ++a) retStride[a]=srcDim.Stride(a+1)/len; // a magic number, to reset destStart for this dimension SizeT resetStep[MAXRANK+1]; for( SizeT a=1; a <= nDim; ++a) resetStep[a]=(retStride[a]-1)/retStride[a-1]*this->dim.Stride(a); // SizeT destStart=this->dim.LongIndex(ixDim); // starting pos // DataT& srcIn_dd = srcIn->dd; SizeT srcIx=0; // this one simply runs from 0 to N_Elements(srcIn) for( SizeT c=1; c<=nCp; ++c) // linearized verison of nested loops { // copy one segment SizeT destEnd=destStart+len; for( SizeT destIx=destStart; destIxdim.Stride(a); break; } else { // reset destStart -= resetStep[a]; } } } } // used for concatenation, called from CatArray // assumes that everything is checked (see CatInfo) template void Data_::CatInsert( const Data_* srcArr, const SizeT atDim, SizeT& at) { // length of one segment to copy SizeT len=srcArr->dim.Stride(atDim+1); // src array SizeT nEl=srcArr->N_Elements(); // number of copy actions SizeT nCp=nEl/len; // initial offset SizeT destStart= this->dim.Stride(atDim) * at; // dest array SizeT destEnd = destStart + len; // number of elements to skip SizeT gap=this->dim.Stride(atDim+1); // dest array #ifdef _OPENMP #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt c=0; cdim[atDim]; // update 'at' at += (add > 1)? add : 1; } // Logical True // integers template bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0); } template<> bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0.0f); } template<> bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0.0); } template<> bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != ""); } template<> bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (real(s) != 0.0 || imag(s) != 0.0); } template<> bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (real(s) != 0.0 || imag(s) != 0.0); } template<> bool Data_::LogTrue() { Ty s; if( !Scalar( s)) throw GDLException("Expression must be a scalar or 1 element array in this context.",true,false); return (s != 0); } template<> bool Data_::LogTrue() { // ::_overloadIsTrue is handled in True() return this->True(); } // structs are not allowed // indexed version // integers template bool Data_::LogTrue(SizeT i) { return ((*this)[i] != 0); } template<> bool Data_::LogTrue(SizeT i) { return ((*this)[i] != 0.0f); } template<> bool Data_::LogTrue(SizeT i) { return ((*this)[i] != 0.0); } template<> bool Data_::LogTrue(SizeT i) { return ((*this)[i] != ""); } template<> bool Data_::LogTrue(SizeT i) { return ((*this)[i].real() != 0.0 || (*this)[i].imag() != 0.0); } template<> bool Data_::LogTrue(SizeT i) { return ((*this)[i].real() != 0.0 || (*this)[i].imag() != 0.0); } template<> bool Data_::LogTrue(SizeT i) { return (*this)[i] != 0; } template<> bool Data_::LogTrue(SizeT i) { return (*this)[i] != 0; } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { throw GDLException("String expression not allowed in this context."); } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { throw GDLException("Complex expression not allowed in this context."); } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { throw GDLException("Double complex expression not allowed in this context."); } // rebin over dimIx, new value: newDim // newDim != srcDim[ dimIx] -> compress or expand template< typename T> T* Rebin1( T* src, const dimension& srcDim, SizeT dimIx, SizeT newDim, bool sample) { SizeT nEl = src->N_Elements(); if( newDim == 0) newDim = 1; // get dest dim and number of summations dimension destDim = srcDim; destDim.MakeRank( dimIx + 1); SizeT srcDimIx = destDim[ dimIx]; destDim.SetOneDim( dimIx, newDim); SizeT resStride = destDim.Stride( dimIx); // dimStride is also the number of linear src indexing SizeT dimStride = srcDim.Stride( dimIx); SizeT outerStride = srcDim.Stride( dimIx + 1); SizeT rebinLimit = srcDimIx * dimStride; if( newDim < srcDimIx) // compress { SizeT ratio = srcDimIx / newDim; if( sample) { T* res = new T( destDim, BaseGDL::NOZERO); for( SizeT o=0; o < nEl; o += outerStride) // outer dim for( SizeT i=0; i < dimStride; ++i) // src element offset (lower dim) { SizeT oi = o+i; SizeT oiLimit = oi + rebinLimit; for( SizeT s=oi; sN_Elements(); /*#pragma omp parallel if (resEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= resEl)) { #pragma omp for*/ for( int r=0; r < resEl; ++r) (*res)[ r] /= ratio; // } return res; } } else // expand { T* res = new T( destDim, BaseGDL::NOZERO); if( sample) { SizeT ratio = newDim / srcDimIx; for( SizeT o=0; o < nEl; o += outerStride) // outer dim for( SizeT i=0; i < dimStride; ++i) // src element offset (lower dim) { SizeT oi = o+i; SizeT oiLimit = oi + rebinLimit; for( SizeT s=oi; s T* Rebin1Int( T* src, const dimension& srcDim, SizeT dimIx, SizeT newDim, bool sample) { SizeT nEl = src->N_Elements(); if( newDim == 0) newDim = 1; // get dest dim and number of summations dimension destDim = srcDim; destDim.MakeRank( dimIx + 1); SizeT srcDimIx = destDim[ dimIx]; destDim.SetOneDim( dimIx, newDim); SizeT resStride = destDim.Stride( dimIx); // dimStride is also the number of linear src indexing SizeT dimStride = srcDim.Stride( dimIx); SizeT outerStride = srcDim.Stride( dimIx + 1); SizeT rebinLimit = srcDimIx * dimStride; if( newDim < srcDimIx) // compress { SizeT ratio = srcDimIx / newDim; if( sample) { T* res = new T( destDim, BaseGDL::NOZERO); SizeT ratio = srcDimIx / newDim; for( SizeT o=0; o < nEl; o += outerStride) // outer dim for( SizeT i=0; i < dimStride; ++i) // src element offset (lower dim) { SizeT oi = o+i; SizeT oiLimit = oi + rebinLimit; for( SizeT s=oi; s BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { SizeT resRank = newDim.Rank(); SizeT srcRank = this->Rank(); SizeT nDim; if( resRank < srcRank) nDim = srcRank; else nDim = resRank; dimension actDim( this->dim); Data_* actIn = this; // 1st compress for( SizeT d=0; ddim[d]) { // compress Data_* act = Rebin1( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } // 2nd expand for( SizeT d=0; d this->dim[d]) { // expand Data_* act = Rebin1( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } if( actIn == this) return actIn->Dup(); return actIn; } // integer types template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { SizeT resRank = newDim.Rank(); SizeT srcRank = Rank(); SizeT nDim; if( resRank < srcRank) nDim = srcRank; else nDim = resRank; dimension actDim( dim); Data_* actIn = this; // 1st compress for( SizeT d=0; d( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } // 2nd expand for( SizeT d=0; d dim[d]) { // expand Data_* act = Rebin1Int( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } if( actIn == this) return actIn->Dup(); return actIn; } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { SizeT resRank = newDim.Rank(); SizeT srcRank = Rank(); SizeT nDim; if( resRank < srcRank) nDim = srcRank; else nDim = resRank; dimension actDim( dim); Data_* actIn = this; // 1st compress for( SizeT d=0; d( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } // 2nd expand for( SizeT d=0; d dim[d]) { // expand Data_* act = Rebin1Int( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } if( actIn == this) return actIn->Dup(); return actIn; } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { SizeT resRank = newDim.Rank(); SizeT srcRank = Rank(); SizeT nDim; if( resRank < srcRank) nDim = srcRank; else nDim = resRank; dimension actDim( dim); Data_* actIn = this; // 1st compress for( SizeT d=0; d( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } // 2nd expand for( SizeT d=0; d dim[d]) { // expand Data_* act = Rebin1Int( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } if( actIn == this) return actIn->Dup(); return actIn; } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { SizeT resRank = newDim.Rank(); SizeT srcRank = Rank(); SizeT nDim; if( resRank < srcRank) nDim = srcRank; else nDim = resRank; dimension actDim( dim); Data_* actIn = this; // 1st compress for( SizeT d=0; d( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } // 2nd expand for( SizeT d=0; d dim[d]) { // expand Data_* act = Rebin1Int( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } if( actIn == this) return actIn->Dup(); return actIn; } template<> BaseGDL* Data_::Rebin( const dimension& newDim, bool sample) { SizeT resRank = newDim.Rank(); SizeT srcRank = Rank(); SizeT nDim; if( resRank < srcRank) nDim = srcRank; else nDim = resRank; dimension actDim( dim); Data_* actIn = this; // 1st compress for( SizeT d=0; d( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } // 2nd expand for( SizeT d=0; d dim[d]) { // expand Data_* act = Rebin1Int( actIn, actDim, d, newDim[d], sample); actDim = act->Dim(); if( actIn != this) GDLDelete(actIn); actIn = act; } if( actIn == this) return actIn->Dup(); return actIn; } // plain copy of nEl from src // no checking template void Data_::Assign( BaseGDL* src, SizeT nEl) { Data_* srcT; // = dynamic_cast( src); Guard< Data_> srcTGuard; if( src->Type() != Data_::t) { srcT = static_cast( src->Convert2( Data_::t, BaseGDL::COPY)); srcTGuard.Init( srcT); } else { srcT = static_cast( src); } /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for(long k=0; k < nEl; ++k) { (*this)[ k] = (*srcT)[ k]; }// } } // return a new type of itself (only for one dimensional case) template BaseGDL* Data_::NewIx( SizeT ix) { return new Data_( (*this)[ ix]); } template Data_* Data_::NewIx( AllIxBaseT* ix, const dimension* dIn) { SizeT nCp = ix->size(); Data_* res=Data_::New( *dIn, BaseGDL::NOZERO); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; c Data_* Data_::NewIxFrom( SizeT s) { SizeT nCp = dd.size() - s; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; c Data_* Data_::NewIxFrom( SizeT s, SizeT e) { SizeT nCp = e - s + 1; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); /*#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { #pragma omp for*/ for( int c=0; c Data_* Data_::NewIxFromStride( SizeT s, SizeT stride) { SizeT nCp = (dd.size() - s + stride - 1)/stride; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); for( SizeT c=0; c Data_* Data_::NewIxFromStride( SizeT s, SizeT e, SizeT stride) { SizeT nCp = (e - s + stride)/stride; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); for( SizeT c=0; c Data_* Data_::NewIx( BaseGDL* ix, bool strict) { assert( ix->Type() != GDL_UNDEF); // no type checking needed here: GetAsIndex() will fail with grace // int typeCheck = DTypeOrder[ dType]; // if( typeCheck >= 100) // throw GDLException("Type "+ix->TypeStr()+" not allowed as subscript."); SizeT nElem = ix->N_Elements(); Data_* res = New( ix->Dim(), BaseGDL::NOZERO); Guard guard( res); SizeT upper = dd.size() - 1; Ty upperVal = (*this)[ upper]; if( strict) { for(SizeT i = 0 ; i < nElem; ++i) { SizeT actIx = ix->GetAsIndexStrict( i); if( actIx > upper) throw GDLException("Array used to subscript array " "contains out of range (>) subscript (at index: "+i2s(i)+")."); (*res)[i]= (*this)[ actIx]; } } else // not strict { for(SizeT i = 0 ; i < nElem; ++i) { SizeT actIx = ix->GetAsIndex( i); if( actIx >= upper) (*res)[i] = upperVal; else (*res)[i]= (*this)[ actIx]; } } return guard.release(); } // unsigned types template SizeT Data_::GetAsIndex( SizeT i) const { return (*this)[ i]; } template SizeT Data_::GetAsIndexStrict( SizeT i) const { return (*this)[ i]; // good for unsigned types } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( (*this)[i] < 0) return 0; return (*this)[i]; } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( (*this)[i] < 0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); return (*this)[i]; } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( (*this)[i] < 0) return 0; return (*this)[i]; } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( (*this)[i] < 0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); return (*this)[i]; } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( (*this)[i] < 0) return 0; return (*this)[i]; } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( (*this)[i] < 0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); return (*this)[i]; } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( (*this)[i] <= 0.0) return 0; return Real2Int((*this)[i]); } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( (*this)[i] <= -1.0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); if( (*this)[i] <= 0.0) return 0; return Real2Int((*this)[i]); } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( (*this)[i] <= 0.0) return 0; return Real2Int((*this)[i]); } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( (*this)[i] <= -1.0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); if( (*this)[i] <= 0.0) return 0; return Real2Int((*this)[i]); } template<> SizeT Data_::GetAsIndex( SizeT i) const { const char* cStart=(*this)[i].c_str(); char* cEnd; long l=strtol(cStart,&cEnd,10); if( cEnd == cStart) { Warning("Type conversion error: Unable to convert given STRING to LONG (at index: " + i2s(i) + ")"); return 0; } if( l < 0) return 0; return l; } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { const char* cStart=(*this)[i].c_str(); char* cEnd; long l=strtol(cStart,&cEnd,10); if( cEnd == cStart) { Warning("Type conversion error: Unable to convert given STRING to LONG (at index: " + i2s(i) + ")"); return 0; } if( l < 0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript.",true,false); return l; } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( real((*this)[i]) <= 0.0) return 0; return Real2Int(real((*this)[i])); } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( real((*this)[i]) <= -1.0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); if( real((*this)[i]) <= 0.0) return 0; return Real2Int(real((*this)[i])); } template<> SizeT Data_::GetAsIndex( SizeT i) const { if( real((*this)[i]) <= 0.0) return 0; return Real2Int(real((*this)[i])); } template<> SizeT Data_::GetAsIndexStrict( SizeT i) const { if( real((*this)[i]) <= -1.0) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range (<0) subscript (at index: " + i2s(i) + ").",true,false); if( real((*this)[i]) <= 0.0) return 0; return Real2Int(real((*this)[i])); } //#include "instantiate_templates.hpp" template class Data_< SpDByte>; template class Data_< SpDInt>; template class Data_< SpDUInt>; template class Data_< SpDLong>; template class Data_< SpDULong>; template class Data_< SpDLong64>; template class Data_< SpDULong64>; template class Data_< SpDPtr>; template class Data_< SpDFloat>; template class Data_< SpDDouble>; template class Data_< SpDString>; template class Data_< SpDObj>; template class Data_< SpDComplex>; template class Data_< SpDComplexDbl>; gdl-0.9.9/src/datatypes.hpp000066400000000000000000000443651340051421000155770ustar00rootroot00000000000000/*************************************************************************** datatypes.hpp - defines all data types of GDL except DStructGDL ------------------- begin : Tue Feb 13 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DATATYPES_HPP_ #define DATATYPES_HPP_ #include #include //#include //#include #include //#include // #include // #include #include "typedefs.hpp" #include "basegdl.hpp" #include "typetraits.hpp" #if defined(__GNUC__) && !defined(__INTEL_COMPILER) // by default intel C++ defines __GNUC__ #pragma interface #endif // for each group we need one definition // usage: GDL_DEFINE_INTEGER_FUNCTION(retType) fName( arg list) { definition} #define GDL_DEFINE_INTEGER_FUNCTION( retType ) templatetemplate< typename U> typename U::template IfInteger< retType >::type Data_:: #define GDL_DEFINE_FLOAT_FUNCTION( retType ) templatetemplate< typename U> typename U::template IfFloat< retType >::type Data_:: #define GDL_DEFINE_COMPLEX_FUNCTION( retType ) templatetemplate< typename U> typename U::template IfComplex< retType >::type Data_:: #define GDL_DEFINE_OTHER_FUNCTION( retType ) templatetemplate< typename U> typename U::template IfOther< retType >::type Data_:: const size_t multiAlloc = 256; template class Data_: public Sp { // save some typing. Declares function "fName" for all four groups (with return type "retType") #define GDL_DECLARE_FUNCTION( retType, fName, ... ) \ template< typename U = Sp > typename U::template IfInteger< retType >::type fName( __VA_ARGS__); \ template< typename U = Sp > typename U::template IfFloat< retType >::type fName( __VA_ARGS__); \ template< typename U = Sp > typename U::template IfComplex< retType >::type fName( __VA_ARGS__); \ template< typename U = Sp > typename U::template IfOther< retType >::type fName( __VA_ARGS__) public: typedef typename Sp::Ty Ty; typedef Sp Traits; #ifdef _MSC_VER public: // MSC cannot handle friend template specialization properly #else private: #endif typedef typename Sp::DataT DataT; #ifdef USE_EIGEN EIGEN_ALIGN16 DataT dd; // the data #else DataT dd; // the data #endif public: // #define TESTTG // TEST TEMPLATE GROUPING #ifdef TESTTG void TestTemplateGrouping(); // #define GDL_TEMPLATE_Integer( retType ) template< typename U = Sp > typename U::template IfInteger< retType >::type // #define GDL_TEMPLATE_IntegerDef( retType ) templatetemplate< typename U> typename U::template IfInteger< retType >::type Data_:: GDL_DECLARE_FUNCTION(bool,Test2); // template< typename U = Sp > //typename U::template IfInteger::type // GDL_TEMPLATE_Integer(bool) Test2(); // template< typename U = Sp > // typename U::template IfFloat::type // Test2(); // template< typename U = Sp > // typename U::template IfComplex::type // Test2(); // template< typename U = Sp > // typename U::template IfOther::type // Test2(); #endif public: // memory management optimization static FreeListT freeList; // operator new and delete static void* operator new( size_t bytes); static void operator delete( void *ptr); //structors ~Data_(); // default Data_(); // scalar Data_(const Ty& d_); // new array, no zero or indgen Data_(const dimension& dim_, BaseGDL::InitType iT, DDouble start = 0, DDouble increment = 1); // new array, zero fields Data_(const dimension& dim_); // new array from Ty[], one dimensional Data_( const Ty* p, SizeT nEl); // new array from DataT Data_(const dimension& dim_, const DataT& dd_): Sp( dim_), dd( dd_) {} // c-i Data_(const Data_& d_);//: Sp(d_.dim), dd(d_.dd) {} // operators // assignment. Data_& operator=(const BaseGDL& right); // for structs void InitFrom(const BaseGDL& right); // one dim array access (unchecked) inline Ty& operator[] (const SizeT d1) { return dd[d1];} inline const Ty& operator[] (const SizeT d1) const { return dd[d1];} // Ty& operator[] (const SizeT d1) { return dd[d1];} template friend std::istream& operator>>(std::istream& i, Data_& data_); // valarrays cannot be resized (without loosing data) // inline DataT& Resize( SizeT n); // // note that min and max these are not defined in BaseGDL // Ty min() const;// { return dd.min();} // Ty max() const;// { return dd.max();} bool Greater(SizeT i1, SizeT i2) const; // comp 2 elements bool Equal(SizeT i1, SizeT i2) const; // comp 2 elements BaseGDL* CShift( DLong d) const; BaseGDL* CShift( DLong d[MAXRANK]) const; BaseGDL* Transpose( DUInt* perm); BaseGDL* Rotate( DLong dir); void Reverse( DLong dim); BaseGDL* DupReverse( DLong dim); // for use by MIN and MAX functions void MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start = 0, SizeT stop = 0, SizeT step = 1, DLong valIx = -1, bool useAbs = false); bool EqType( const BaseGDL* r) const; void* DataAddr();// SizeT elem=0); Ty Sum() const; SizeT N_Elements() const; SizeT Size() const; SizeT NBytes() const; SizeT ToTransfer() const; // IO transfer count SizeT Sizeof() const; int HashCompare( BaseGDL* p2) const; void Clear(); void Construct(); // construction (for DStructGDL) void ConstructTo0(); // construction (for DStructGDL) void Destruct(); // destruction (for DStructGDL) BaseGDL* SetBuffer( const void* b); void SetBufferSize( SizeT s); BaseGDL* AssocVar( int, SizeT); std::ostream& ToStream(std::ostream& o, SizeT width = 0, SizeT* actPosPtr = NULL); std::istream& FromStream(std::istream& i); // used by the interpreter int Scalar2Index( SizeT& st) const; int Scalar2RangeT( RangeT& st) const; RangeT LoopIndex() const; DDouble HashValue() const; // used for indexing of arrays SizeT GetAsIndex( SizeT i) const; SizeT GetAsIndexStrict( SizeT i) const; // make a duplicate on the heap Data_* Dup() const; // // make a duplicate at loc // Data_* Dup( void* loc) const { return ::new ( loc) Data_(*this);} bool OutOfRangeOfInt() const; bool Scalar() const { return (dd.size() == 1);} bool StrictScalar() const { return (this->Rank() == 0);} bool Scalar(Ty& s) const { if( dd.size() != 1) return false; s=dd[0]; return true; } bool StrictScalar(Ty& s) const { if( this->Rank() != 0) return false; s=dd[0]; return true; } Data_* New( const dimension& dim_, BaseGDL::InitType noZero=BaseGDL::ZERO) const; Data_* NewResult() const; // convert *this to other 'destTy' BaseGDL* Convert2( DType destTy, BaseGDL::Convert2Mode=BaseGDL::CONVERT); // not all compilers can handle template friend member functions #ifndef _MSC_VER # if __GNUC__ >= 4 # if defined(__clang__) // suppress: warning: dependent nested name specifier 'Data_::' for friend class declaration is not supported; turning off access control for 'Data_' [-Wunsupported-friend] # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunsupported-friend" // make all other Convert2 functions friends template friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); # pragma clang diagnostic pop # endif # else // this explicit version does not work with GCC 4.0 friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); # endif #endif bool True(); bool False(); bool LogTrue(); bool LogTrue( SizeT ix); void Where(DLong* &ret, SizeT &passed_count, bool comp, DLong* &comp_ret); void Where(DLong64* &ret, SizeT &passed_count, bool comp, DLong64* &comp_ret); Data_* LogNeg(); int Sgn(); // returns -1,0,1 bool Equal( BaseGDL*) const; bool EqualNoDelete( const BaseGDL*) const; bool ArrayEqual( BaseGDL*); bool ArrayNeverEqual( BaseGDL*); void ForCheck( BaseGDL**, BaseGDL** =NULL); bool ForCondUp( BaseGDL*); bool ForCondDown( BaseGDL*); bool ForAddCondUp( BaseGDL* loopInfo); // bool ForAddCondUp( ForLoopInfoT& loopInfo); // bool ForCondUpDown( BaseGDL*); void ForAdd(); void ForAdd( BaseGDL* add); BaseGDL* Abs() const; BaseGDL* Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid); BaseGDL* Smooth(DLong* width, int edgeMode, bool doNan, BaseGDL* missing); BaseGDL* Rebin( const dimension& newDim, bool sample); void Assign( BaseGDL* src, SizeT nEl); template< typename To> typename Data_::Ty GetAs( SizeT i); // { // return dd[ i]; // } BaseGDL* Log(); BaseGDL* LogThis(); BaseGDL* Log10(); BaseGDL* Log10This(); // operators BaseGDL* UMinus(); // UMinus for SpDString returns float Data_* NotOp(); // GDL_DECLARE_FUNCTION( Data_*, AndOp, BaseGDL* r); Data_* AndOp( BaseGDL* r); Data_* AndOpInv( BaseGDL* r); Data_* OrOp( BaseGDL* r); Data_* OrOpInv( BaseGDL* r); Data_* XorOp( BaseGDL* r); BaseGDL* Add( BaseGDL* r); BaseGDL* AddInv( BaseGDL* r); BaseGDL* AddS( BaseGDL* r); BaseGDL* AddInvS( BaseGDL* r); BaseGDL* AddNew( BaseGDL* r); // implemented BaseGDL* AddInvNew( BaseGDL* r); // implemented BaseGDL* AddSNew( BaseGDL* r); // implemented BaseGDL* AddInvSNew( BaseGDL* r); // implemented // Data_* AddNew( BaseGDL* r); // Data_* AddInvNew( BaseGDL* r); BaseGDL* Sub( BaseGDL* r); BaseGDL* SubInv( BaseGDL* r); Data_* GtMark( BaseGDL* r); Data_* LtMark( BaseGDL* r); Data_* Mult( BaseGDL* r); // Data_* MultNew( BaseGDL* r); Data_* Div( BaseGDL* r); Data_* DivInv( BaseGDL* r); Data_* Mod( BaseGDL* r); Data_* ModInv( BaseGDL* r); Data_* Pow( BaseGDL* r); Data_* PowInv( BaseGDL* r); Data_* PowInt( BaseGDL* r); // Data_* PowIntNew( BaseGDL* r); Data_* MatrixOp( BaseGDL* r, bool atranspose, bool btranspose); // operators with scalar Data_* AndOpS( BaseGDL* r); Data_* AndOpInvS( BaseGDL* r); Data_* OrOpS( BaseGDL* r); Data_* OrOpInvS( BaseGDL* r); Data_* XorOpS( BaseGDL* r); // Data_* AddSNew( BaseGDL* r); // Data_* AddInvSNew( BaseGDL* r); Data_* SubS( BaseGDL* r); Data_* SubInvS( BaseGDL* r); Data_* GtMarkS( BaseGDL* r); Data_* LtMarkS( BaseGDL* r); Data_* MultS( BaseGDL* r); // Data_* MultSNew( BaseGDL* r); Data_* DivS( BaseGDL* r); Data_* DivInvS( BaseGDL* r); Data_* ModS( BaseGDL* r); Data_* ModInvS( BaseGDL* r); Data_* PowS( BaseGDL* r); Data_* PowInvS( BaseGDL* r); // operators returning a new value Data_* AndOpNew( BaseGDL* r); Data_* AndOpInvNew( BaseGDL* r); Data_* OrOpNew( BaseGDL* r); Data_* OrOpInvNew( BaseGDL* r); Data_* XorOpNew( BaseGDL* r); // Data_* EqOpNew( BaseGDL* r); // Data_* NeOpNew( BaseGDL* r); // Data_* LeOpNew( BaseGDL* r); // Data_* GeOpNew( BaseGDL* r); // Data_* LtOpNew( BaseGDL* r); // Data_* GtOpNew( BaseGDL* r); BaseGDL* SubNew( BaseGDL* r); BaseGDL* SubInvNew( BaseGDL* r); Data_* LtMarkNew( BaseGDL* r); Data_* GtMarkNew( BaseGDL* r); Data_* MultNew( BaseGDL* r); // implemented Data_* DivNew( BaseGDL* r); Data_* DivInvNew( BaseGDL* r); Data_* ModNew( BaseGDL* r); Data_* ModInvNew( BaseGDL* r); Data_* PowNew( BaseGDL* r); Data_* PowInvNew( BaseGDL* r); Data_* PowIntNew( BaseGDL* r); // implemented // operators with scalar returning a new value Data_* AndOpSNew( BaseGDL* r); Data_* AndOpInvSNew( BaseGDL* r); Data_* OrOpSNew( BaseGDL* r); Data_* OrOpInvSNew( BaseGDL* r); Data_* XorOpSNew( BaseGDL* r); BaseGDL* SubSNew( BaseGDL* r); BaseGDL* SubInvSNew( BaseGDL* r); Data_* LtMarkSNew( BaseGDL* r); Data_* GtMarkSNew( BaseGDL* r); Data_* MultSNew( BaseGDL* r); // implemented Data_* DivSNew( BaseGDL* r); Data_* DivInvSNew( BaseGDL* r); Data_* ModSNew( BaseGDL* r); Data_* ModInvSNew( BaseGDL* r); Data_* PowSNew( BaseGDL* r); Data_* PowInvSNew( BaseGDL* r); BaseGDL* EqOp( BaseGDL* r); BaseGDL* NeOp( BaseGDL* r); BaseGDL* GtOp( BaseGDL* r); BaseGDL* GeOp( BaseGDL* r); BaseGDL* LtOp( BaseGDL* r); BaseGDL* LeOp( BaseGDL* r); // used by interpreter, calls CatInsert Data_* CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank); // used for concatenation, called from CatArray // assumes that everything is checked (see CatInfo) void CatInsert( const Data_* srcArr, const SizeT atDim, SizeT& at); // assigns srcIn to this at ixList, if ixList is NULL does linear copy // assumes: ixList has this already set as variable void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset); void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList); void AssignAt( BaseGDL* srcIn); void AssignAtIx( RangeT ix, BaseGDL* srcIn); // decrement (--) and increment (++) operators void DecAt( ArrayIndexListT* ixList); void IncAt( ArrayIndexListT* ixList); void Dec(); void Inc(); // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset void InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList); // returns (*this)[ ixList] Data_* Index( ArrayIndexListT* ixList); // return a new type of itself BaseGDL* NewIx( SizeT ix); Data_* NewIx( BaseGDL* ix, bool strict); Data_* NewIx( AllIxBaseT* ix, const dimension* dIn); Data_* NewIxFrom( SizeT s); Data_* NewIxFrom( SizeT s, SizeT e); Data_* NewIxFromStride( SizeT s, SizeT stride); Data_* NewIxFromStride( SizeT s, SizeT e, SizeT stride); // binary input/output std::ostream& Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs); std::istream& Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs); SizeT OFmtA( std::ostream* os, SizeT offset, SizeT num, int width, const int code=0); SizeT OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code=0, const BaseGDL::IOMode oM = BaseGDL::FIXED); SizeT OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code=0, BaseGDL::IOMode oM = BaseGDL::DEC); SizeT OFmtCal( std::ostream* os, SizeT offs, SizeT num, int width, int minN, char *f, int code=0, BaseGDL::Cal_IOMode oM = BaseGDL::DEFAULT); // formatting input functions SizeT IFmtA( std::istream* is, SizeT offset, SizeT num, int width); SizeT IFmtF( std::istream* is, SizeT offs, SizeT num, int width); SizeT IFmtI( std::istream* is, SizeT offs, SizeT num, int width, BaseGDL::IOMode oM = BaseGDL::DEC); SizeT IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode); #ifdef USE_PYTHON public: PyObject* ToPython(); private: PyObject* ToPythonScalar(); #endif private: // inserts srcIn at ixDim, used by AssignAt(...) // respects the exact structure void InsAt( Data_* srcIn, ArrayIndexListT* ixList, SizeT offset = 0); // only to be used here #undef GDL_DECLARE_FUNCTION }; // template<> Data_::Data_(const Ty& d_); // template<> Data_::Data_(const Ty& d_); #include "specializations.hpp" typedef Data_ DByteGDL; typedef Data_ DIntGDL; typedef Data_ DUIntGDL; typedef Data_ DLongGDL; typedef Data_ DULongGDL; typedef Data_ DLong64GDL; typedef Data_ DULong64GDL; typedef Data_ DFloatGDL; typedef Data_ DDoubleGDL; typedef Data_ DStringGDL; typedef Data_ DPtrGDL; typedef Data_ DObjGDL; typedef Data_ DComplexGDL; typedef Data_ DComplexDblGDL; // DStructGDL defined separately // on OS X isfinite is not defined #if defined(__APPLE__) && defined(OLD_DARWIN) && !defined(isfinite) #ifdef __cplusplus extern "C" { #endif #define isfinite( x ) ( ( sizeof ( x ) == sizeof(double) ) ? \ __isfinited ( x ) : \ ( sizeof ( x ) == sizeof( float) ) ? \ __isfinitef ( x ) : \ __isfinite ( x ) ) #ifdef __cplusplus } #endif #endif // isfinite & isinf for Solaris #if defined(__sun__) # include # define isfinite finite # ifndef isinf # define isinf(x) (!finite(x) && x==x) # endif #endif #endif gdl-0.9.9/src/datatypes_minmax.cpp000066400000000000000000000133741340051421000171370ustar00rootroot00000000000000/*************************************************************************** datatypes_minmax.cpp - for GDL datatypes ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens : 2018 by Gilles Duvert email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifdef _OPENMP #include #endif #include "nullgdl.hpp" #include "dstructgdl.hpp" template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { throw GDLException("Object expression not allowed in this context."); } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { throw GDLException("Pointer expression not allowed in this context."); } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { //#define ABSFUNC llabs //NO as comparison is always ABS for UNSIGNEDs! #include "minmax_include.cpp" //#undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { #define ABSFUNC llabs #include "minmax_include.cpp" #undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { //#define ABSFUNC llabs //NO as comparison is always ABS for UNSIGNEDs! #include "minmax_include.cpp" //#undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { #define ABSFUNC llabs #include "minmax_include.cpp" #undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { //#define ABSFUNC llabs #include "minmax_include.cpp" //#undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { #define ABSFUNC llabs #include "minmax_include.cpp" #undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { //#define ABSFUNC llabs #include "minmax_include.cpp" //#undef ABSFUNC } //string is identical, has no absfunc. template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { #include "minmax_include.cpp" } // float etc. /nan is taken into account. // IDL treats +Inf and -Inf as normal (ordered) values unless /NAN is present. This complicates things. // Cases below are sped up by duplicating the code: NAN case and not. template<> void Data_::MinMax(DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { #define ABSFUNC fabsf if (omitNaN) { #define MINMAX_HAS_OMITNAN #include "minmax_include.cpp" #undef MINMAX_HAS_OMITNAN } else { #include "minmax_include.cpp" } #undef ABSFUNC } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { #define ABSFUNC fabs if (omitNaN) { #define MINMAX_HAS_OMITNAN #include "minmax_include.cpp" #undef MINMAX_HAS_OMITNAN } else { #include "minmax_include.cpp" } #undef ABSFUNC } //special COMPLEX treatment, adds '.real()' where needed. #define MINMAX_IS_COMPLEX #define ABSFUNC std::abs template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { if (omitNaN) { #define MINMAX_HAS_OMITNAN #include "minmax_include.cpp" #undef MINMAX_HAS_OMITNAN } else { #include "minmax_include.cpp" } } template<> void Data_::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { if (omitNaN) { #define MINMAX_HAS_OMITNAN #include "minmax_include.cpp" #undef MINMAX_HAS_OMITNAN } else { #include "minmax_include.cpp" } } #undef ABSFUNC #undef MINMAX_IS_COMPLEX gdl-0.9.9/src/datatypesref.cpp000066400000000000000000001271711340051421000162640ustar00rootroot00000000000000/************************************************************************** datatypesref.cpp - specializations for DPtrGDL and DObjGDL for reference counting ------------------- begin : March 08 2010 copyright : (C) 2010 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_DATATYPESREF_CPP #undef INCLUDE_DATATYPESREF_CPP #include "nullgdl.hpp" // reference counting for INIT template<> Data_* Data_::New( const dimension& dim_, BaseGDL::InitType noZero) const { if( noZero == BaseGDL::NOZERO) return new Data_(dim_, BaseGDL::NOZERO); if( noZero == BaseGDL::INIT) { Data_* res = new Data_(dim_, BaseGDL::NOZERO); SizeT nEl = res->dd.size(); /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( OMPInt i=0; i Data_* Data_::New( const dimension& dim_, BaseGDL::InitType noZero) const { if( noZero == BaseGDL::NOZERO) return new Data_(dim_, BaseGDL::NOZERO); if( noZero == BaseGDL::INIT) { Data_* res = new Data_(dim_, BaseGDL::NOZERO); SizeT nEl = res->dd.size(); /*#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for*/ for( OMPInt i=0; i void Data_::InsAt( Data_* srcIn, ArrayIndexListT* ixList, SizeT offset) { // max. number of dimensions to copy SizeT nDim = ixList->NDim(); if( nDim == 1) { SizeT destStart = ixList->LongIx(); //SizeT len; if( this->N_Elements() == 1) { // len = 1; SizeT rStride = srcIn->Stride(this->Rank()); Ty& a = (*this)[ destStart]; Ty b = (*srcIn)[ offset/rStride]; GDLInterpreter::IncRef( b); GDLInterpreter::DecRef( a); a = b;//(*this)[ destStart] = (*srcIn)[ offset/rStride]; } else { SizeT len = srcIn->Dim( 0); // length of segment to copy // TODO: IDL reports here (and probably in the insert-dimension case below as well) // the name of a variable, e.g.: // IDL> a=[0,0,0] & a[2]=[2,2,2] // % Out of range subscript encountered: A. if( (destStart+len) > this->N_Elements()) //dim[0]) throw GDLException("Out of range subscript encountered (length of insert exceeds array boundaries)."); // DataT& srcIn_dd = srcIn->dd; SizeT srcIx = 0; // this one simply runs from 0 to N_Elements(srcIn) SizeT destEnd = destStart + len; for( SizeT destIx = destStart; destIx < destEnd; ++destIx) { Ty& a = (*this)[ destIx]; Ty b = (*srcIn)[ srcIx++]; GDLInterpreter::IncRef( b); GDLInterpreter::DecRef( a); a = b;// (*this)[ destIx] = (*srcIn)[ srcIx++]; } } return; } SizeT destStart; // 1-dim starting index // ATTENTION: dimension is used as an index here dimension ixDim = ixList->GetDimIx0( destStart); nDim--; dimension srcDim=srcIn->Dim(); srcDim.Purge(); // newly inserted: variant of ticket #675 SizeT len=srcDim[0]; // length of one segment to copy (one line of srcIn) // SizeT nDim =RankIx(ixDim.Rank()); SizeT srcNDim=RankIx(srcDim.Rank()); // number of source dimensions if( srcNDim < nDim) nDim=srcNDim; // check limits (up to Rank to consider) for( SizeT dIx=0; dIx <= nDim; ++dIx) // check if in bounds of a if( (ixDim[dIx]+srcDim[dIx]) > this->dim[dIx]) throw GDLException("Out of range subscript encountered (dimension of insert exceeds array boundaries for dimension " + i2s(dIx +1) + ")."); SizeT nCp=srcIn->Stride(nDim+1)/len; // number of OVERALL copy actions // as lines are copied, we need the stride from 2nd dim on SizeT retStride[MAXRANK+1]; for( SizeT a=0; a <= nDim; ++a) retStride[a]=srcDim.Stride(a+1)/len; // a magic number, to reset destStart for this dimension SizeT resetStep[MAXRANK+1]; for( SizeT a=1; a <= nDim; ++a) resetStep[a]=(retStride[a]-1)/retStride[a-1]*this->dim.Stride(a); // SizeT destStart=this->dim.LongIndex(ixDim); // starting pos // DataT& srcIn_dd = srcIn->dd; SizeT srcIx=0; // this one simply runs from 0 to N_Elements(srcIn) for( SizeT c=1; c<=nCp; ++c) // linearized verison of nested loops { // copy one segment SizeT destEnd=destStart+len; for( SizeT destIx=destStart; destIxdim.Stride(a); break; } else { // reset destStart -= resetStep[a]; } } } } template<> void Data_::InsAt( Data_* srcIn, ArrayIndexListT* ixList, SizeT offset) { // max. number of dimensions to copy SizeT nDim = ixList->NDim(); if( nDim == 1) { SizeT destStart = ixList->LongIx(); //SizeT len; if( this->N_Elements() == 1) { // len = 1; SizeT rStride = srcIn->Stride(this->Rank()); Ty& a = (*this)[ destStart]; Ty b = (*srcIn)[ offset/rStride]; GDLInterpreter::IncRefObj( b); GDLInterpreter::DecRefObj( a); a = b;//(*this)[ destStart] = (*srcIn)[ offset/rStride]; } else { SizeT len = srcIn->Dim( 0); // length of segment to copy // TODO: IDL reports here (and probably in the insert-dimension case below as well) // the name of a variable, e.g.: // IDL> a=[0,0,0] & a[2]=[2,2,2] // % Out of range subscript encountered: A. if( (destStart+len) > this->N_Elements()) //dim[0]) throw GDLException("Out of range subscript encountered (length of insert exceeds array boundaries)."); // DataT& srcIn_dd = srcIn->dd; SizeT srcIx = 0; // this one simply runs from 0 to N_Elements(srcIn) SizeT destEnd = destStart + len; for( SizeT destIx = destStart; destIx < destEnd; ++destIx) { Ty& a = (*this)[ destIx]; Ty b = (*srcIn)[ srcIx++]; GDLInterpreter::IncRefObj( b); GDLInterpreter::DecRefObj( a); a = b;// (*this)[ destIx] = (*srcIn)[ srcIx++]; } } return; } SizeT destStart; // 1-dim starting index // ATTENTION: dimension is used as an index here dimension ixDim = ixList->GetDimIx0( destStart); nDim--; dimension srcDim=srcIn->Dim(); srcDim.Purge(); // newly inserted: variant of ticket #675 SizeT len=srcDim[0]; // length of one segment to copy (one line of srcIn) // SizeT nDim =RankIx(ixDim.Rank()); SizeT srcNDim=RankIx(srcDim.Rank()); // number of source dimensions if( srcNDim < nDim) nDim=srcNDim; // check limits (up to Rank to consider) for( SizeT dIx=0; dIx <= nDim; ++dIx) // check if in bounds of a if( (ixDim[dIx]+srcDim[dIx]) > this->dim[dIx]) throw GDLException("Out of range subscript encountered (dimension of insert exceeds array boundaries for dimension " + i2s(dIx +1) + ")."); SizeT nCp=srcIn->Stride(nDim+1)/len; // number of OVERALL copy actions // as lines are copied, we need the stride from 2nd dim on SizeT retStride[MAXRANK]; for( SizeT a=0; a <= nDim; ++a) retStride[a]=srcDim.Stride(a+1)/len; // a magic number, to reset destStart for this dimension SizeT resetStep[MAXRANK]; for( SizeT a=1; a <= nDim; ++a) resetStep[a]=(retStride[a]-1)/retStride[a-1]*this->dim.Stride(a); // SizeT destStart=this->dim.LongIndex(ixDim); // starting pos // DataT& srcIn_dd = srcIn->dd; SizeT srcIx=0; // this one simply runs from 0 to N_Elements(srcIn) for( SizeT c=1; c<=nCp; ++c) // linearized verison of nested loops { // copy one segment SizeT destEnd=destStart+len; for( SizeT destIx=destStart; destIxdim.Stride(a); break; } else { // reset destStart -= resetStep[a]; } } } } template<> void Data_::AssignAtIx( RangeT ix, BaseGDL* srcIn) { if( srcIn->Type() != this->Type()) throw GDLException("Only expressions of type " + srcIn->TypeStr() + " can be assigned to " + this->TypeStr()); GDLInterpreter::IncRef( (*static_cast(srcIn))[0]); GDLInterpreter::DecRef( (*this)[ix]); (*this)[ix] = (*static_cast(srcIn))[0]; } template<> void Data_::AssignAtIx( RangeT ix, BaseGDL* srcIn) { if( srcIn->Type() != this->Type()) throw GDLException("Only expressions of type " + srcIn->TypeStr() + " can be assigned to " + this->TypeStr()); GDLInterpreter::IncRefObj( (*static_cast(srcIn))[0]); GDLInterpreter::DecRefObj( (*this)[ix]); (*this)[ix] = (*static_cast(srcIn))[0]; } template<> void Data_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); // bool isScalar= (srcElem == 1); bool isScalar= (srcElem == 1) && (src->Rank() == 0); if( isScalar) { // src is scalar Ty scalar=(*src)[0]; if( ixList == NULL) { SizeT nCp=Data_::N_Elements(); GDLInterpreter::AddRef( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); GDLInterpreter::AddRef( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=scalar; } } else { if( ixList == NULL) { SizeT nCp=Data_::N_Elements(); // if (non-indexed) src is smaller -> just copy its number of elements if( nCp > (srcElem-offset)) { if( offset == 0) nCp=srcElem; else throw GDLException("Source expression contains not enough elements."); } //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cN_Elements(); if( nCp == 1) { SizeT destStart = ixList->LongIx(); // len = 1; SizeT rStride = srcIn->Stride(this->Rank()); (*this)[ destStart] = (*src)[ offset/rStride]; // InsAt( src, ixList, offset); } else { if( offset == 0) { if( srcElem < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=(*src)[c+offset]; } else { if( (srcElem-offset) < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=(*src)[c+offset]; } } } } } template<> void Data_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); // bool isScalar= (srcElem == 1); bool isScalar= (srcElem == 1) && (src->Rank() == 0); if( isScalar) { // src is scalar Ty scalar=(*src)[0]; if( ixList == NULL) { SizeT nCp=Data_::N_Elements(); GDLInterpreter::AddRefObj( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); GDLInterpreter::AddRefObj( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=scalar; } } else { if( ixList == NULL) { SizeT nCp=Data_::N_Elements(); // if (non-indexed) src is smaller -> just copy its number of elements if( nCp > (srcElem-offset)) { if( offset == 0) nCp=srcElem; else throw GDLException("Source expression contains not enough elements."); } //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cN_Elements(); if( nCp == 1) { SizeT destStart = ixList->LongIx(); // len = 1; SizeT rStride = srcIn->Stride(this->Rank()); (*this)[ destStart] = (*src)[ offset/rStride]; // InsAt( src, ixList, offset); } else { if( offset == 0) { if( srcElem < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=(*src)[c+offset]; } else { if( (srcElem-offset) < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=(*src)[c+offset]; } } } } } template<> void Data_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { assert( ixList != NULL); // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); bool isScalar= (srcElem == 1); if( isScalar) { // src is scalar SizeT nCp=ixList->N_Elements(); if( nCp == 1) { Ty& a = (*this)[ ixList->LongIx()] ; Ty b = (*src)[ 0]; GDLInterpreter::IncRef( b); GDLInterpreter::DecRef( a); a = b;//(*this)[ ixList->LongIx()] = (*src)[0]; } else { Ty scalar=(*src)[0]; AllIxBaseT* allIx = ixList->BuildIx(); GDLInterpreter::AddRef( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=scalar; } } else { // crucial part SizeT nCp=ixList->N_Elements(); if( nCp == 1) { InsAt( src, ixList); } else { if( srcElem < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=(*src)[c+offset]; } } } template<> void Data_::AssignAt( BaseGDL* srcIn) { // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); bool isScalar= (srcElem == 1); if( isScalar) { // src is scalar Ty scalar=(*src)[0]; /* dd = scalar;*/ SizeT nCp=Data_::N_Elements(); GDLInterpreter::AddRef( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c just copy its number of elements if( nCp > srcElem) nCp=srcElem; //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c void Data_::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { assert( ixList != NULL); // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); bool isScalar= (srcElem == 1); if( isScalar) { // src is scalar SizeT nCp=ixList->N_Elements(); if( nCp == 1) { Ty& a = (*this)[ ixList->LongIx()] ; Ty b = (*src)[ 0]; GDLInterpreter::IncRefObj( b); GDLInterpreter::DecRefObj( a); a = b;//(*this)[ ixList->LongIx()] = (*src)[0]; } else { Ty scalar=(*src)[0]; AllIxBaseT* allIx = ixList->BuildIx(); GDLInterpreter::AddRefObj( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=scalar; } } else { // crucial part SizeT nCp=ixList->N_Elements(); if( nCp == 1) { InsAt( src, ixList); } else { if( srcElem < nCp) throw GDLException("Array subscript must have same size as" " source expression."); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]=(*src)[c+offset]; } } } template<> void Data_::AssignAt( BaseGDL* srcIn) { // breakpoint(); // gdbg can not handle breakpoints in template functions Data_* src = static_cast(srcIn); SizeT srcElem= src->N_Elements(); bool isScalar= (srcElem == 1); if( isScalar) { // src is scalar Ty scalar=(*src)[0]; /* dd = scalar;*/ SizeT nCp=Data_::N_Elements(); GDLInterpreter::AddRefObj( scalar, nCp); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c just copy its number of elements if( nCp > srcElem) nCp=srcElem; //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::Index( ArrayIndexListT* ixList) { // ixList->SetVariable( this); Data_* res=Data_::New( ixList->GetDim(), BaseGDL::NOZERO); SizeT nCp=ixList->N_Elements(); // cout << "nCP = " << nCp << endl; // cout << "dim = " << this->dim << endl; // DataT& res_dd = res->dd; AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx(c)]; return res; } // returns (*this)[ ixList] template<> Data_* Data_::Index( ArrayIndexListT* ixList) { // ixList->SetVariable( this); Data_* res=Data_::New( ixList->GetDim(), BaseGDL::NOZERO); SizeT nCp=ixList->N_Elements(); // cout << "nCP = " << nCp << endl; // cout << "dim = " << this->dim << endl; // DataT& res_dd = res->dd; AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx(c)]; return res; } // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset // used by DotAccessDescT::DoResolve template<> void Data_::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { Data_* src=static_cast(srcIn); if( ixList == NULL) { SizeT nCp=src->N_Elements(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]; } } } // used for concatenation, called from CatArray // assumes that everything is checked (see CatInfo) template<> void Data_::CatInsert( const Data_* srcArr, const SizeT atDim, SizeT& at) { // length of one segment to copy SizeT len=srcArr->dim.Stride(atDim+1); // src array // number of copy actions SizeT nCp=srcArr->N_Elements()/len; // initial offset SizeT destStart= this->dim.Stride(atDim) * at; // dest array SizeT destEnd = destStart + len; // number of elements to skip SizeT gap=this->dim.Stride(atDim+1); // dest array #ifdef _OPENMP SizeT nEl = srcArr->N_Elements(); //#pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( SizeT c=0; cdim[atDim]; // update 'at' at += (add > 1)? add : 1; } // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset // used by DotAccessDescT::DoResolve template<> void Data_::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { Data_* src=static_cast(srcIn); if( ixList == NULL) { SizeT nCp=src->N_Elements(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cN_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; cGetIx( c)]; } } } // used for concatenation, called from CatArray // assumes that everything is checked (see CatInfo) template<> void Data_::CatInsert( const Data_* srcArr, const SizeT atDim, SizeT& at) { // length of one segment to copy SizeT len=srcArr->dim.Stride(atDim+1); // src array // number of copy actions SizeT nCp=srcArr->N_Elements()/len; // initial offset SizeT destStart= this->dim.Stride(atDim) * at; // dest array SizeT destEnd = destStart + len; // number of elements to skip SizeT gap=this->dim.Stride(atDim+1); // dest array #ifdef _OPENMP SizeT nEl = srcArr->N_Elements(); //#pragma omp parallel for if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) for( SizeT c=0; cdim[atDim]; // update 'at' at += (add > 1)? add : 1; } template<> void Data_::Assign( BaseGDL* src, SizeT nEl) { // Data_* srcT = dynamic_cast( src); // // Guard< Data_> srcTGuard; // if( srcT == NULL) // { // srcT = static_cast( src->Convert2( Data_::t, BaseGDL::COPY)); // srcTGuard.Reset( srcT); // } Data_* srcT; // = dynamic_cast( src); Guard< Data_> srcTGuard; if( src->Type() != Data_::t) { srcT = static_cast( src->Convert2( Data_::t, BaseGDL::COPY)); srcTGuard.Init( srcT); } else { srcT = static_cast( src); } //#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { //#pragma omp for for(long k=0; k < nEl; ++k) { Ty a = (*this)[ k]; Ty b = (*srcT)[k]; GDLInterpreter::IncRef( b); GDLInterpreter::DecRef( a); (*this)[ k] = (*srcT)[ k]; } } } template<> void Data_::Assign( BaseGDL* src, SizeT nEl) { // Data_* srcT = dynamic_cast( src); // // Guard< Data_> srcTGuard; // if( srcT == NULL) // { // srcT = static_cast( src->Convert2( Data_::t, BaseGDL::COPY)); // srcTGuard.Reset( srcT); // } Data_* srcT; // = dynamic_cast( src); Guard< Data_> srcTGuard; if( src->Type() != Data_::t) { srcT = static_cast( src->Convert2( Data_::t, BaseGDL::COPY)); srcTGuard.Init( srcT); } else { srcT = static_cast( src); } //#pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { //#pragma omp for for(long k=0; k < nEl; ++k) { Ty a = (*this)[ k]; Ty b = (*srcT)[k]; GDLInterpreter::IncRefObj( b); GDLInterpreter::DecRefObj( a); (*this)[ k] = (*srcT)[ k]; } } } // return a new type of itself (only for one dimensional case) template<> BaseGDL* Data_::NewIx( SizeT ix) { Ty b = (*this)[ ix]; GDLInterpreter::IncRef( b); return new Data_( (*this)[ ix]); } // return a new type of itself (only for one dimensional case) template<> BaseGDL* Data_::NewIx( SizeT ix) { if( !this->StrictScalar()) { Ty b = (*this)[ ix]; GDLInterpreter::IncRefObj( b); return new Data_( (*this)[ ix]); } DObj s = dd[0]; // is StrictScalar() if( s == 0) // no overloads for null object return new Data_( 0); DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s); if( oStructGDL == NULL) // if object not valid -> default behaviour return new Data_( 0); DStructDesc* desc = oStructGDL->Desc(); if( desc->IsParent("LIST")) { static DString cNodeName("GDL_CONTAINER_NODE"); // because of .RESET_SESSION, we cannot use static here DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; // no static here, might vary in derived object // unsigned pHeadTag = desc->TagIndex( "PHEAD"); static unsigned pTailTag = desc->TagIndex( "PTAIL"); static unsigned pNextTag = structDesc::GDL_CONTAINER_NODE->TagIndex( "PNEXT"); static unsigned pDataTag = structDesc::GDL_CONTAINER_NODE->TagIndex( "PDATA"); // unsigned nListTag = desc->TagIndex( "NLIST"); // SizeT listSize = (*static_cast(oStructGDL->GetTag( nListTag, 0)))[0]; DPtr actP = (*static_cast(oStructGDL->GetTag( pTailTag, 0)))[0]; for( SizeT elIx = 0; elIx < ix; ++elIx) { BaseGDL* actPHeap = BaseGDL::interpreter->GetHeap( actP); if( actPHeap->Type() != GDL_STRUCT) throw GDLException( "LIST node must be a STRUCT."); DStructGDL* actPStruct = static_cast( actPHeap); if( actPStruct->Desc() != containerDesc) throw GDLException( "LIST node must be a GDL_CONTAINER_NODE STRUCT."); actP = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; } BaseGDL* actPHeap = BaseGDL::interpreter->GetHeap( actP); if( actPHeap->Type() != GDL_STRUCT) throw GDLException( "LIST node must be a STRUCT."); DStructGDL* actPStruct = static_cast( actPHeap); if( actPStruct->Desc() != containerDesc) throw GDLException( "LIST node must be a GDL_CONTAINER_NODE STRUCT."); actP = (*static_cast(actPStruct->GetTag( pDataTag, 0)))[0]; BaseGDL* result = BaseGDL::interpreter->GetHeap( actP); if( result == NULL) return NullGDL::GetSingleInstance(); return result->Dup(); } if( desc->IsParent("HASH")) { static DString hashName("HASH"); static DString entryName("GDL_HASHTABLEENTRY"); static unsigned pDataTag = structDesc::HASH->TagIndex( "TABLE_DATA"); static unsigned nSizeTag = structDesc::HASH->TagIndex( "TABLE_SIZE"); static unsigned nCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); static unsigned nForEachTag = structDesc::HASH->TagIndex( "TABLE_FOREACH"); static unsigned pKeyTag = structDesc::GDL_HASHTABLEENTRY->TagIndex( "PKEY"); static unsigned pValueTag = structDesc::GDL_HASHTABLEENTRY->TagIndex( "PVALUE"); DPtr pHashTable = (*static_cast( oStructGDL->GetTag( pDataTag, 0)))[0]; DStructGDL* hashTable = static_cast(BaseGDL::interpreter->GetHeap( pHashTable)); DLong validIx = 0; DLong i = 0; for(; iN_Elements(); ++i) { DPtr pKey = (*static_cast(hashTable->GetTag( pKeyTag, i)))[0]; if( pKey != 0) { if( validIx == ix) break; ++validIx; } } assert( iN_Elements()); DPtr pValue = (*static_cast(hashTable->GetTag( pValueTag, i)))[0]; DPtr pKey = (*static_cast(hashTable->GetTag( pKeyTag, i)))[0]; (*static_cast( oStructGDL->GetTag( nForEachTag, 0)))[0] = pKey; BaseGDL* result = BaseGDL::interpreter->GetHeap( pValue); if( result == NULL) return NullGDL::GetSingleInstance(); return result->Dup(); } GDLInterpreter::IncRefObj( s); return new Data_( s); } template<> Data_* Data_::NewIx( AllIxBaseT* ix, const dimension* dIn) { SizeT nCp = ix->size(); Data_* res=Data_::New( *dIn, BaseGDL::NOZERO); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::NewIx( AllIxBaseT* ix, const dimension* dIn) { SizeT nCp = ix->size(); Data_* res=Data_::New( *dIn, BaseGDL::NOZERO); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::NewIxFrom( SizeT s) { SizeT nCp = dd.size() - s; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::NewIxFrom( SizeT s) { SizeT nCp = dd.size() - s; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::NewIxFrom( SizeT s, SizeT e) { SizeT nCp = e - s + 1; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::NewIxFrom( SizeT s, SizeT e) { SizeT nCp = e - s + 1; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); //#pragma omp parallel if (nCp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nCp)) { //#pragma omp for for( SizeT c=0; c Data_* Data_::NewIxFromStride( SizeT s, SizeT stride) { SizeT nCp = (dd.size() - s + stride - 1)/stride; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); for( SizeT c=0; c Data_* Data_::NewIxFromStride( SizeT s, SizeT e, SizeT stride) { SizeT nCp = (e - s + stride)/stride; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); for( SizeT c=0; c Data_* Data_::NewIxFromStride( SizeT s, SizeT stride) { SizeT nCp = (dd.size() - s + stride - 1)/stride; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); for( SizeT c=0; c Data_* Data_::NewIxFromStride( SizeT s, SizeT e, SizeT stride) { SizeT nCp = (e - s + stride)/stride; Data_* res=Data_::New( dimension( nCp), BaseGDL::NOZERO); for( SizeT c=0; c upper) \ { \ if( strict) \ throw GDLException("Array used to subscript array " \ "contains out of range (>) subscript."); \ (*res)[i++]= upperVal; \ break; \ } \ else \ (*res)[i]= (*this)[ (*src)[i]]; \ for(; i < nElem; ++i) \ if( (*src)[i] > upper) \ (*res)[i] = upperVal; \ else \ (*res)[i]= (*this)[ (*src)[i]]; \ GDLInterpreter::IncRef( res); \ return guard.release(); #define NEWIX_SIGNEDINT \ SizeT i = 0; \ for(; i < nElem; ++i) \ if( (*src)[i] < 0) \ { \ if( strict) \ throw GDLException("Array used to subscript array " \ "contains out of range (<0) subscript."); \ (*res)[i++]= zeroVal; \ break; \ } \ else if( (*src)[i] > upper) \ { \ if( strict) \ throw GDLException("Array used to subscript array " \ "contains out of range (>) subscript."); \ (*res)[i++]= upperVal; \ break; \ } \ else \ (*res)[ i] = (*this)[ (*src)[ i]]; \ for(; i < nElem; ++i) \ if( (*src)[i] < 0) \ (*res)[i]= zeroVal; \ else if( (*src)[i] > upper) \ (*res)[i]= upperVal; \ else \ (*res)[ i] = (*this)[ (*src)[ i]]; \ GDLInterpreter::IncRef( res); \ return guard.release(); template<> Data_* Data_::NewIx( BaseGDL* ix, bool strict) { assert( ix->Type() != GDL_UNDEF); // no type checking needed here: GetAsIndex() will fail with grace // int typeCheck = DTypeOrder[ dType]; // if( typeCheck >= 100) // throw GDLException("Type "+ix->TypeStr()+" not allowed as subscript."); SizeT nElem = ix->N_Elements(); Data_* res = New( ix->Dim(), BaseGDL::NOZERO); Guard guard( res); SizeT upper = dd.size() - 1; Ty upperVal = (*this)[ upper]; if( strict) { for(SizeT i = 0 ; i < nElem; ++i) { SizeT actIx = ix->GetAsIndexStrict( i); if( actIx > upper) throw GDLException("Array used to subscript array " "contains out of range (>) subscript (at index: "+i2s(i)+")."); (*res)[i]= (*this)[ actIx]; } } else // not strict { for(SizeT i = 0 ; i < nElem; ++i) { SizeT actIx = ix->GetAsIndex( i); if( actIx >= upper) (*res)[i] = upperVal; else (*res)[i]= (*this)[ actIx]; } } GDLInterpreter::IncRef( res); return guard.release(); } template<> Data_* Data_::NewIx( BaseGDL* ix, bool strict) { SizeT nElem = ix->N_Elements(); Data_* res = New( ix->Dim(), BaseGDL::NOZERO); Guard guard( res); SizeT upper = dd.size() - 1; Ty upperVal = (*this)[ upper]; if( strict) { for(SizeT i = 0 ; i < nElem; ++i) { SizeT actIx = ix->GetAsIndexStrict( i); if( actIx > upper) throw GDLException("Array used to subscript array " "contains out of range (>) subscript (at index: "+i2s(i)+")."); (*res)[i]= (*this)[ actIx]; } } else // not strict { for(SizeT i = 0 ; i < nElem; ++i) { SizeT actIx = ix->GetAsIndex( i); if( actIx >= upper) (*res)[i] = upperVal; else (*res)[i]= (*this)[ actIx]; } } GDLInterpreter::IncRefObj( res); return guard.release(); } #endif gdl-0.9.9/src/dcommon.cpp000066400000000000000000000053121340051421000152150ustar00rootroot00000000000000/*************************************************************************** dcommon.cpp - GDL common blocks ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "gdlexception.hpp" #include "dcommon.hpp" #include "str.hpp" #include "objects.hpp" // common block ******************************************** using namespace std; // init with common block name DCommon::DCommon(const string& n) : name(n) { // auto insert self into list of common blocks // now done when subroutine compiles ok // commonList.push_back(this); } DCommon::~DCommon() { PurgeContainer( var); } void DCommon::DeleteData() { VarListT::iterator i; for(i = var.begin(); i != var.end(); ++i) (*i)->Delete(); } void DCommon::AddVar(const string& v) { var.push_back(new DVar(v)); } const string& DCommon::Name() const { return name; } DVar* DCommon::Find(const string& n) { return FindInVarList(var,n); } int DCommon::Find(const BaseGDL* data_) { int vSize=var.size(); for( int i=0; iData() == data_) return i; } return -1; } // common block reference ********************************** // init with common block DCommonRef::DCommonRef(DCommon& c) : cRef(&c) { } DCommonRef::~DCommonRef() { } void DCommonRef::AddVar(const string& v) { // check size if( cRef->NVar() == NVar()) throw( GDLException("Attempt to extent common block: "+Name())); // add name varNames.push_back(v); } const string& DCommonRef::Name() const { return cRef->Name(); } DVar* DCommonRef::Find(const string& n) { int ix=FindInIDList(varNames,n); if( ix == -1) return NULL; return cRef->Var(ix); } int DCommonRef::Find(const BaseGDL* data_) { int ix=cRef->Find( data_); if( ix >= static_cast(varNames.size())) return -1; return ix; } DVar* DCommonRef::Var(unsigned ix) { return cRef->Var( ix); } gdl-0.9.9/src/dcommon.hpp000066400000000000000000000066251340051421000152320ustar00rootroot00000000000000/*************************************************************************** dcommon.hpp - GDL common blocks ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DCOMMON_HPP_ #define DCOMMON_HPP_ #include "gdlexception.hpp" #include "dvar.hpp" class DCommonBase { public: virtual ~DCommonBase() {} virtual const std::string& Name() const =0; virtual unsigned NVar() const =0; virtual void AddVar(const std::string&)=0; virtual DVar* Find(const std::string&)=0; virtual int Find(const BaseGDL*)=0; virtual const std::string& VarName(const unsigned i)=0; virtual DVar* Var(unsigned ix)=0; }; // common block ******************************************************* class DCommon: public DCommonBase { private: std::string name; // common block name VarListT var; // the data public: DCommon(const std::string&); ~DCommon(); void DeleteData(); // deletes only COMMON data, COMMON block itself is kept const std::string& VarName(const unsigned i) { if( i >= var.size()) throw(GDLException("Common block index out of range")); return var[i]->Name(); } unsigned NVar() const { return var.size();} void AddVar(const std::string&); const std::string& Name() const; DVar* Find(const std::string&); int Find(const BaseGDL*); DVar* Var(unsigned ix) { return var[ix];} }; class DCommon_eq: public std::unary_function { std::string name; public: explicit DCommon_eq(const std::string& s): name(s) {} bool operator() (const DCommon* v) const { return v->Name() == name;} }; // ref to common block (variable names (and number) might differ) ***** class DCommonRef: public DCommonBase { private: IDList varNames; // overridden variable names DCommon *cRef; // ptr to common blk public: DCommonRef(DCommon&); ~DCommonRef(); const std::string& VarName(const unsigned i) { if( i >= varNames.size()) throw(GDLException("CommonRef block index out of range")); return varNames[i]; } unsigned NVar() const { return varNames.size();} void AddVar(const std::string&); const std::string& Name() const; DVar* Find(const std::string&); int Find(const BaseGDL*); DVar* Var(unsigned ix); }; typedef std::vector CommonBaseListT; typedef std::vector CommonListT; class DCommon_contains_var: public std::unary_function { std::string name; public: explicit DCommon_contains_var(const std::string& s): name(s) {} bool operator() (DCommonBase* c) const { return (c->Find(name) != NULL);} }; #endif gdl-0.9.9/src/dcompiler.cpp000066400000000000000000000374541340051421000155530ustar00rootroot00000000000000/*************************************************************************** dcompiler.cpp - compiler functions ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include "str.hpp" #include "gdlexception.hpp" #include "objects.hpp" #include "dcompiler.hpp" #include "str.hpp" #include "dcommon.hpp" #include "GDLInterpreter.hpp" #include "overload.hpp" #include "prognodeexpr.hpp" // print out AST tree //#define GDL_DEBUG //#undef GDL_DEBUG #ifdef GDL_DEBUG #include "print_tree.hpp" #endif #include using namespace std; DCompiler::DCompiler(const string& f, EnvBaseT* e, const std::string& sub) : actualFile(f), subRoutine( sub), env(e), pro(NULL), activeProCompiled( false), nCompileErrors(0), tree( NULL) { // interactive mode? if( env != NULL) pro=dynamic_cast(env->GetPro()); } DCompiler::~DCompiler() { if( env != NULL) { if( pro != static_cast(env->GetPro())) delete pro; // delete if not env's pro } else delete pro; // NULL or failed to compile function/procedure ClearOwnCommon(); } void DCompiler::ClearOwnCommon() { // delete common blocks which are not added to commonList // due to compile error CommonListT::iterator it; for( it=ownCommonList.begin(); it !=ownCommonList.end(); ++it) { delete *it; } ownCommonList.clear(); } void DCompiler::ForwardFunction(const string& s) // add to function list { new DFun(s); } void DCompiler::AddPar(const string& P) // add parameter { if( pro->Find(P)) throw(GDLException(P+" is already defined with a conflicting definition.")); pro->AddPar(P); } void DCompiler::AddKey(const string& K,const string& V) // add keyword,valName { if( pro->FindKey(K) != -1) throw(GDLException("Ambiguous keyword: "+K)); if( pro->Find(V)) throw(GDLException(V+" is already defined with a conflicting definition.")); pro->AddKey(K,V); } void DCompiler::EndFunPro() // resolve gotos, add common blocks { pro->ResolveAllLabels(); // // fill the subroutines label list // // we already have all labels in labellist // LabelListT& ll = pro->LabelList(); // if( labelList.size() > 0) // { // // label - target DNode* (other type than this->labelList) // LabelListT& ll = pro->LabelList(); // for(map >::iterator i=labelList.begin(); // i != labelList.end(); i++) // { // const string& gotoLabel = (*i).first; // int proLabelIx = ll.Find( gotoLabel); // if( proLabelIx == -1) // throw( GDLException(pro->ObjectName()+ // ": Undefined label "+gotoLabel+ // " referenced in GOTO statement.")); // // set the nodes of the actual tree to the appropiate index // deque& gotoNodes = (*i).second; // for( deque::iterator gN = gotoNodes.begin(); // gN != gotoNodes.end(); ++gN) // { // (*gN)->SetGotoIx( proLabelIx); // } // } // // clear for next subroutine // labelList.clear(); // } EndInteractiveStatement(); } void DCompiler::EndInteractiveStatement() // add common blocks { for( CommonListT::iterator c = ownCommonList.begin(); c != ownCommonList.end(); ++c) commonList.push_back( *c); ownCommonList.clear(); // not responsible anymore } void DCompiler::StartPro(const string& n, const int compileOpt, const string& o) { ClearOwnCommon(); if( n != "$MAIN$" || o != "") { pro = new DPro(n,o,actualFile); pro->SetCompileOpt(compileOpt); } else { env = GDLInterpreter::CallStack()[0]; pro = static_cast( env->GetPro()); pro->DelTree(); } } void DCompiler::ContinueMainPro() { env = GDLInterpreter::CallStack()[0]; pro = static_cast( env->GetPro()); } void DCompiler::StartFun(const string& n, const int compileOpt = 0, const string& o) { ClearOwnCommon(); pro = new DFun(n,o,actualFile); pro->SetCompileOpt(compileOpt); } bool DCompiler::IsActivePro( DSub* p) { EnvStackT& cS = GDLInterpreter::CallStack(); SizeT stSz = cS.size(); for( SizeT i=1; iGetPro() == p) return true; } return false; } void DCompiler::EndPro() // inserts in proList { EndFunPro(); const string& name=pro->Name(); const string& o=pro->Object(); if( name != "$MAIN$" || o != "") { ProListT *searchList; if( o == "") searchList= &proList; else { // find struct 'id' DStructDesc* dStruct=FindInStructList( structList, o); if( dStruct == NULL) { dStruct=new DStructDesc( o); structList.push_back( dStruct); } searchList = &dStruct->ProList(); // operator overlaoding // consider only PRO operators int operatorIndex = OverloadOperatorIndexPro( name); // insert in operator list if operator if( operatorIndex != -1) { // will do nothing if not derived from GDL_OBJECT dStruct->SetOperator( operatorIndex, pro); } } // search/replace in proList ProListT::iterator p=find_if((*searchList).begin(),(*searchList).end(), Is_eq(name)); if( p != (*searchList).end()) { if( *p != NULL) { delete *p; if( IsActivePro( *p)) { Warning( "Procedure was compiled while active: "+ pro->ObjectName()+". Returning."); activeProCompiled = true; } } *p=static_cast(pro); } else { (*searchList).push_back(static_cast(pro)); WarnAboutObsoleteRoutine(pro->ObjectName()); } } if(!pro->isHidden()) { if ( subRoutine == "" || subRoutine == pro->ObjectFileName()) Message( "Compiled module: "+pro->ObjectName()+"."); } // reset pro // will be deleted otherwise if( env != NULL) pro=dynamic_cast(env->GetPro()); else pro=NULL; } void DCompiler::EndFun() // inserts in funList { EndFunPro(); const string& name=pro->Name(); const string& o=pro->Object(); FunListT *searchList; if( o == "") searchList= &funList; else { // find struct 'id' DStructDesc* dStruct=FindInStructList( structList, o); if( dStruct == NULL) { dStruct=new DStructDesc( o); structList.push_back( dStruct); } searchList = &dStruct->FunList(); // operator overlaoding // consider only FUNCTION operators int operatorIndex = OverloadOperatorIndexFun( name); // insert in operator list if operator if( operatorIndex != -1) { // will do nothing if not derived from GDL_OBJECT dStruct->SetOperator( operatorIndex, pro); } } // search/replace in funList FunListT::iterator p=find_if((*searchList).begin(),(*searchList).end(), Is_eq(name)); if( p != (*searchList).end()) { if( *p != NULL) { delete *p; if( IsActivePro( *p)) { Warning( "Procedure was compiled while active: "+ pro->ObjectName()+". Returning."); activeProCompiled = true; } } *p=static_cast(pro); } else { (*searchList).push_back(static_cast(pro)); // sort list again, however item should be inserted at good position in fact (more tricky but would save sort time). TODO. sort( libFunList.begin(), libFunList.end(), CompLibFunName()); WarnAboutObsoleteRoutine(pro->ObjectName()); } if(!pro->isHidden()) { if (subRoutine == "" || subRoutine == pro->ObjectFileName()) Message( "Compiled module: "+pro->ObjectName()+"."); } // reset pro // will be deleted otherwise if( env != NULL) pro=dynamic_cast(env->GetPro()); else pro=NULL; } // returns common block with name n DCommon* DCompiler::Common(const string& n) { CommonListT::iterator f=find_if(commonList.begin(), commonList.end(), DCommon_eq(n)); if( f != commonList.end()) return *f; return NULL; //pro->Common( n); } // Common block (re)definition (variables provided) DCommonBase* DCompiler::CommonDef(const string& N) { // search for common block DCommonBase* c=Common(N); // look also in actual subroutine if( c == NULL) c = pro->Common( N); if( c == NULL) { // not there -> create new c=new DCommon(N); ownCommonList.push_back( static_cast(c)); } else { // already there -> create reference c=new DCommonRef( *(static_cast(c))); } // variables will be checked when parsed (in CommonVar()) pro->AddCommon(c); return c; } void DCompiler::CommonVar(DCommonBase* c, const string& N) { if( pro->Find(N)) { DCommonBase* c1st = pro->FindCommon( N); // several definition/declaration of the same common block are ok if( c1st == NULL || c1st->Name() != c->Name()) { // Common block deletion (needed in case variable declaration fails) string cName = c->Name(); // c is deleted in DeleteLastAddedCommon() if( !ownCommonList.empty() && ownCommonList.back() == c) // only if added here ownCommonList.pop_back(); pro->DeleteLastAddedCommon(); // always string append = " with a conficting definition."; if( c1st != NULL) append = " in common block "+ c1st->Name()+"."; throw( GDLException("Variable: "+N+" ("+cName+") already defined"+append)); } } c->AddVar(N); } // Common block declaration (no variables provided) void DCompiler::CommonDecl(const string& N) { // search for common block DCommon* c=Common(N); if( c == NULL) { throw( GDLException("Common block: "+N+" must contain variables.")); } // check variables unsigned nVar=c->NVar(); for(unsigned u=0; u < nVar; u++) { DVar* cVar=c->Var(u); // variable from common block if( pro->Find(cVar->Name())) { DCommonBase* c1st = pro->FindCommon( cVar->Name()); // several definition/declaration of the same common block are ok if( c1st == NULL || c1st->Name() != c->Name()) throw( GDLException("Variable: "+cVar->Name()+ " ("+N+") already defined" " with a conficting definition.")); } } pro->AddCommon(c); } // always returns new variable BaseGDL* DCompiler::ConstantIndex( RefDNode n) { if( n->getType() == CONSTANT) { assert( n->CData() != NULL); return n->CData()->Dup(); } if( n->getType() == ARRAYDEF_CONST) { // cout << "RefDNode:" << endl; // antlr::print_tree pt; // pt.pr_tree(static_cast( n)); // cout << endl; // must be compiled here ARRAYDEFNode* c = new ARRAYDEFNode( n); Guard< ARRAYDEFNode> guard( c); assert( c->ConstantArray()); // cout << "ProgNodeP:" << endl; // pt.pr_tree(c); // cout << endl; BaseGDL* cData = c->Eval(); assert( cData != NULL); return cData; } return NULL; } RefDNode DCompiler::ByReference(RefDNode nIn) { static RefDNode null = static_cast(antlr::nullAST); // #ifdef GDL_DEBUG // cout << "ByReference: in:" << endl; // antlr::print_tree pt; // pt.pr_tree(static_cast( nIn)); // cout << endl; // #endif RefDNode n = nIn; // APRO,++(a=2) is passed like APRO,a // APRO,(((a=2))=3) // forbidden in GDL // Makes IDL segfault: APRO,++(((a=2))=3) int t=n->getType(); // expressions (braces) are ignored do { while( n->getType() == EXPR) n = n->getFirstChild(); t = n->getType(); if( t == DEC || t == INC) // only preinc can be reference { n = n->getFirstChild(); t = n->getType(); } } while( t == DEC || t == INC || t == EXPR); // // expressions (braces) are ignored // while( n->getType() == EXPR) n = n->getFirstChild(); // t=n->getType(); bool assignReplace = false; if( t == ASSIGN_REPLACE) { assignReplace = true; n = n->getFirstChild()->getNextSibling(); t=n->getType(); } // expressions (braces) are ignored while( n->getType() == EXPR) n = n->getFirstChild(); t=n->getType(); // only var, common block var and deref ptr are passed by reference // note: trinary op is REF_CHECK // *** see AssignReplace(...) if( !assignReplace && t != VAR && t != VARPTR && t != DEREF && !GDLTreeParser::IsREF_CHECK(t)) // && t != QUESTION) return null; // #ifdef GDL_DEBUG // cout << "ByReference: out:" << endl; // pt.pr_tree(static_cast( n)); // cout << endl; // #endif return n; } bool DCompiler::IsVar(const string& n) { // check if lib fun SizeT nLibF = libFunList.size(); for( SizeT f=0; fName() == n) return false; // check already compiled fun if( FunIx( n) != -1) return false; // No functions are compiled during var/fun lookup // // Note: problem here when actual compiled // // sub has still its own private common block list, which newly compiled // // sub would not find but possibly create the same common block again // // sollution: // // purge common blocks // // disadvantage: // // if compilation fails later, common blocks are not removed but stay defined // EndInteractiveStatement(); // // originally this was done later in the interpreter // // but something like x = x(0) would not work if x is // // a function (defined in x.pro) and a variable // bool success = GDLInterpreter::SearchCompilePro( n); // if( success) // even if file exists and compiles it might contain other stuff // if( FunIx( n) != -1) return false; // // Note: It is still possible that 'n' denotes a function: // // !PATH might be changed till run time // variables return pro->Find(n); } // variable (parameter, keyword-value) reference void DCompiler::Var(RefDNode n) { string V=n->getText(); int i=pro->FindVar(V); if( i != -1) { n->SetVarIx(i); return; } DVar *c=pro->FindCommonVar(V); if( c != NULL) { n->setType(VARPTR); n->SetVar(c); return; } SizeT u=pro->AddVar(V); if( env != NULL) { SizeT e=env->AddEnv(); if( u != e) throw GDLException("env and pro out of sync."); } n->SetVarIx(static_cast(u)); // cout << "Added Var "<SetVar(NULL); } void DCompiler::SetTree(RefDNode n) { assert( pro != NULL); #ifdef GDL_DEBUG cout << "Setting procedure/function tree:" << endl; antlr::print_tree pt; pt.pr_tree(static_cast( n)); cout << endl; #endif pro->SetTree( n); } void DCompiler::Label(RefDNode n) { LabelListT& ll = pro->LabelList(); string lab=n->getText(); int ix = ll.Find( lab); if( ix != -1) { throw( GDLException(n, "Label "+lab+" defined more than once.")); } else { ll.Add( lab, NULL); // insert first without node } } // void DCompiler::Goto(RefDNode n) // { // LabelListT& ll = pro->LabelList(); // string lab=n->getText(); // int ix = ll.Find( lab); // if( ix != -1) // { // n->SetGotoIx( ix); // } // else // { // deque& nList=labelList[lab]; // inserts if not exist // nList.push_back(n); // put node in reminder list // } // } // used by treeparser for return statements bool DCompiler::IsFun() const { return (dynamic_cast(pro) != NULL); } int DCompiler::NDefLabel() { return pro->NDefLabel(); } gdl-0.9.9/src/dcompiler.hpp000066400000000000000000000100661340051421000155460ustar00rootroot00000000000000/*************************************************************************** dcompiler.hpp - GDL compiler ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef compiler_hpp_ #define compiler_hpp_ #include #include #include #include #include "GDLLexer.hpp" #include "GDLParser.hpp" #include "gdlexception.hpp" #include "objects.hpp" #include "dcommon.hpp" #include "dnode.hpp" class GDLInterpreter; class DCompiler: public GDLTokenTypes { std::string actualFile; // actual compiled file (dbg info) std::string subRoutine; // pro/fun to compile (used for messages only) EnvBaseT *env; // intial processed environment (interactive) DSubUD *pro; // actual processed pro/function bool activeProCompiled; int nCompileErrors; // number of compilation errors // std::map > labelList; // resolving goto/label CommonListT ownCommonList; // common blocks not yet added to commonList DCommon* Common(const std::string& n); // returns common block with name n void ClearOwnCommon(); ProgNodeP tree; public: // should be private, but GDLTreeParser needs it to be public DCompiler() { std::cerr<<"DCompiler() called. Abort."< { bool operator() ( DLibFun* f1, DLibFun* f2) const { return f1->ObjectName() < f2->ObjectName();} }; }; #endif gdl-0.9.9/src/default_io.cpp000066400000000000000000001333461340051421000157050ustar00rootroot00000000000000/************************************************************************** default_io.cpp - input/output, no FORMAT keyword ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_DEFAULT_IO_CPP //#include "datatypes.hpp" //#include "dstructgdl.hpp" //#include "arrayindex.hpp". //#include "assocdata.hpp" //#include "io.hpp" #include "ofmt.hpp" #include "gdljournal.hpp" #include "list.hpp" #include "hash.hpp" using namespace std; void SkipWS( istream& is) { if( is.eof()) throw GDLIOException( "End of file encountered. "+ StreamInfo( &is)); char c; do { c = is.get(); if ( (is.rdstate() & ifstream::failbit ) != 0 ) { if ( (is.rdstate() & ifstream::eofbit ) != 0 ) throw GDLIOException( "End of file encountered. "+ StreamInfo( &is)); if ( (is.rdstate() & ifstream::badbit ) != 0 ) throw GDLIOException( "Error reading stream. "+ StreamInfo( &is)); is.clear(); return ; } } while( c == ' ' || c == '\t' || c == '\n'); is.unget(); } // helper function - reads one line, does error checking const string ReadElement(istream& is) { SkipWS( is); string buf; char c; for(;;) { c = is.get(); // int cc = c; // cout << "ReadEl: " << cc << " " << c << ":" << endl; if ( (is.rdstate() & ifstream::failbit ) != 0 ) { if ( (is.rdstate() & ifstream::badbit ) != 0 ) throw GDLIOException( "Error reading line. "+ StreamInfo( &is)); is.clear(); return buf; } if( c == '\n') return buf; if( c == ' ' || c == '\t') { is.unget(); return buf; } buf.push_back( c); } if( !is.good()) throw GDLIOException( "Error reading stream. "+StreamInfo( &is)); return buf; // // old version (read full line which is then split - does not work with // // different types on the same line) // if( is.eof()) // throw GDLIOException( "End of file encountered. "+ // StreamInfo( &is)); // string retStr; // getline( is, retStr); // if ( (is.rdstate() & ifstream::failbit ) != 0 ) // { // if ( (is.rdstate() & ifstream::eofbit ) != 0 ) // throw GDLIOException( "End of file encountered. "+ // StreamInfo( &is)); // if ( (is.rdstate() & ifstream::badbit ) != 0 ) // throw GDLIOException( "Error reading line. "+ // StreamInfo( &is)); // is.clear(); // return ""; // } // if( !is.good()) // throw GDLIOException( "Error reading line. "+StreamInfo( &is)); // cout << "Read line: " << retStr << endl; // return retStr; } // no skip of WS const string ReadComplexElement(istream& is) { SkipWS( is); string buf; char c = is.get(); if ( (is.rdstate() & ifstream::failbit ) != 0 ) { if ( (is.rdstate() & ifstream::eofbit ) != 0 ) throw GDLIOException( "End of file encountered. "+ StreamInfo( &is)); if ( (is.rdstate() & ifstream::badbit ) != 0 ) throw GDLIOException( "Error reading stream. "+ StreamInfo( &is)); is.clear(); return buf; } bool brace = (c == '('); if( !brace) { is.unget(); return ReadElement( is); } buf.push_back( c); for(;;) { c = is.get(); if ( (is.rdstate() & ifstream::failbit ) != 0 ) { if ( (is.rdstate() & ifstream::badbit ) != 0 ) throw GDLIOException( "Error reading line. "+ StreamInfo( &is)); is.clear(); return buf; } if( c == '\n') return buf; buf.push_back( c); if( c == ')') return buf; } } inline void InsNL(ostream& o, SizeT* actPosPtr) { o << '\n'; if( actPosPtr != NULL) *actPosPtr = 0; } // class CheckNL (ofmt.hpp) ostream& operator<<(ostream& os, const CheckNL& c) { if( c.actPosPtr == NULL) return os; if( (*c.actPosPtr + c.nextW) > c.width && *c.actPosPtr > 0) { os << '\n'; *c.actPosPtr = 0; } // check if output is to journal file if( *c.actPosPtr == 0) { GDLStream* s = lib::get_journal(); if( s != NULL && s->OStream().rdbuf() == os.rdbuf()) os << lib::JOURNALCOMMENT; } *c.actPosPtr += c.nextW; return os; } // *** the default input functions template< class Sp> istream& Data_::FromStream( istream& i) { i >> *this; return i;} // integer types template istream& operator>>(istream& i, Data_& data_) { long int nTrans = data_.dd.size(); SizeT assignIx = 0; while( nTrans > 0) { const string segment = ReadElement( i); const char* cStart=segment.c_str(); char* cEnd; data_[ assignIx] = strtol( cStart, &cEnd, 10); if( cEnd == cStart) { data_[ assignIx]= -1; Warning("Input conversion error."); } assignIx++; nTrans--; } return i; } // float template<> istream& operator>>(istream& i, Data_& data_) { long int nTrans = data_.dd.size(); SizeT assignIx = 0; while( nTrans > 0) { const string segment = ReadElement( i); const char* cStart=segment.c_str(); char* cEnd; data_[ assignIx] = StrToD( cStart, &cEnd); if( cEnd == cStart) { data_[ assignIx]= -1; Warning("Input conversion error."); } assignIx++; nTrans--; } return i; } // double template<> istream& operator>>(istream& i, Data_& data_) { long int nTrans = data_.dd.size(); SizeT assignIx = 0; while( nTrans > 0) { const string segment = ReadElement( i); const char* cStart=segment.c_str(); char* cEnd; data_[ assignIx] = StrToD( cStart, &cEnd); if( cEnd == cStart) { data_[ assignIx]= -1; Warning("Input conversion error."); } assignIx++; nTrans--; } return i; } // complex template<> istream& operator>>(istream& i, Data_& data_) { long int nTrans = data_.dd.size(); SizeT assignIx = 0; while( nTrans > 0) { const string& actLine = ReadComplexElement( i); SizeT strLen = actLine.length(); if( actLine[ 0] == '(') { SizeT mid = actLine.find_first_of(" \t,",1); if( mid >= strLen) mid = strLen; string seg1 = actLine.substr( 1, mid-1); mid++; SizeT next = actLine.find_first_not_of(" \t",mid); if( next >= strLen) next = strLen; SizeT last = actLine.find_first_of(")",next); if( last >= strLen) last = strLen; if( last <= next) { data_[ assignIx]= DComplex(0.0,0.0); Warning("Imaginary part of complex missing."); } else { string seg2 = actLine.substr( next, last-next); char* cEnd1, *cEnd2; const char* c1=seg1.c_str(); double re = StrToD( c1, &cEnd1); const char* c2=seg2.c_str(); double im = StrToD( c2, &cEnd2); if( cEnd1 == c1 || cEnd2 == c2) { data_[ assignIx]= DComplex(0.0,0.0); Warning("Input conversion error."); } else { data_[ assignIx] = DComplex( re, im); } } } else { // real part only read, all values are set to this // the file pointer hangs (ie. a following // float reads the same value again) // convert segment and assign const char* cStart=actLine.c_str(); char* cEnd; double val = StrToD( cStart, &cEnd); if( cEnd == cStart) { data_[ assignIx]= DComplex(0.0,0.0); Warning("Input conversion error."); } for( long int c=assignIx; c istream& operator>>(istream& i, Data_& data_) { long int nTrans = data_.dd.size(); SizeT assignIx = 0; while( nTrans > 0) { const string& actLine = ReadComplexElement( i); SizeT strLen = actLine.length(); if( actLine[ 0] == '(') { SizeT mid = actLine.find_first_of(" \t,",1); if( mid >= strLen) mid = strLen; string seg1 = actLine.substr( 1, mid-1); mid++; SizeT next = actLine.find_first_not_of(" \t",mid); if( next >= strLen) next = strLen; SizeT last = actLine.find_first_of(")",next); if( last >= strLen) last = strLen; if( last <= next) { data_[ assignIx]= DComplexDbl(0.0,0.0); Warning("Imaginary part of complex missing."); } else { string seg2 = actLine.substr( next, last-next); char* cEnd1, *cEnd2; const char* c1=seg1.c_str(); double re = StrToD( c1, &cEnd1); const char* c2=seg2.c_str(); double im = StrToD( c2, &cEnd2); if( cEnd1 == c1 || cEnd2 == c2) { data_[ assignIx]= DComplexDbl(0.0,0.0); Warning("Input conversion error."); } else { data_[ assignIx] = DComplexDbl( re, im); } } } else { // real part only read, all values are set to this // the file pointer hangs (ie. a following // float reads the same value again) // convert segment and assign const char* cStart=actLine.c_str(); char* cEnd; double val = StrToD( cStart, &cEnd); if( cEnd == cStart) { data_[ assignIx]= DComplexDbl(0.0,0.0); Warning("Input conversion error."); } for( long int c=assignIx; c istream& operator>>(istream& is, Data_& data_) { stringstream ioss; SizeT nEl = data_.dd.size(); char delim = '\n'; streampos startPos = is.tellg(); bool checkForCROnly = true; goto start; rerunCR: delim = '\r'; is.seekg( startPos); ioss.str(""); start: for( SizeT c=0; c < nEl; c++) { // is.get( *ioss.rdbuf()); is.get( *ioss.rdbuf(), delim); // error handling if ( (is.rdstate() & ifstream::failbit ) != 0 ) { if ( (is.rdstate() & ifstream::eofbit ) != 0 ) throw GDLIOException( "End of file encountered. "+ StreamInfo( &is)); if ( (is.rdstate() & ifstream::badbit ) != 0 ) throw GDLIOException( "Error reading STRING. "+ StreamInfo( &is)); is.clear(); is.get(); // remove delimiter data_[ c] = ""; continue; } if( !is.good() && !is.eof()) throw GDLIOException( "Error reading STRING. "+StreamInfo( &is)); if( !is.eof()) is.get(); // remove delimiter const string& str = ioss.str(); if( checkForCROnly) { // do only once checkForCROnly = false; SizeT posCR = str.find( '\r'); if( posCR != string::npos && posCR != str.length()-1) { goto rerunCR; } } // handle \r\n (\n not read) if( delim == '\n' && str.length() > 0 && str[ str.length()-1] == '\r') { data_[ c] = str.substr(0,str.length()-1); } else { data_[ c] = str; } ioss.str(""); } return is; } istream& operator>>(istream& i, DStructGDL& data_) { SizeT nTags = data_.NTags(); SizeT nEl = data_.N_Elements(); for( SizeT e=0; eFromStream( i); } } return i; } // end input ********************************************************* // the default output functions template ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 8) << setw(8) << (*this)[0]; return o; } SizeT nLoop=nElem / this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 12) << setw(12) << (*this)[0]; return o; } SizeT nLoop=nElem / this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 12) << setw(12) << (*this)[0]; return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 22) << setw(22) << (*this)[0]; return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 22) << setw(22) << (*this)[0]; return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l"; } else o << ""; } template<> ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << left; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 15); HeapVarString( o, (*this)[0]); return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; lDesc()->Name() <<")>"; } else o << ""; } else o << ""; } template<> ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { static bool recursive = false; if( this->StrictScalar() && !recursive) { DObj s = dd[0]; // is StrictScalar() if( s != 0) // no overloads for null object { DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s); if( oStructGDL != NULL) // if object not valid -> default behaviour { DStructDesc* desc = oStructGDL->Desc(); if( desc->IsParent("LIST")) { recursive = true; try{ LIST__ToStream(oStructGDL,o,w,actPosPtr); recursive = false; } catch( ...) { recursive = false; throw; } return o; } if( desc->IsParent("HASH")) { recursive = true; try{ HASH__ToStream(oStructGDL,o,w,actPosPtr); recursive = false; } catch( ...) { recursive = false; throw; } return o; } } } } SizeT nElem=this->Size(); if( nElem == 0) throw GDLException("Variable is undefined."); o << left; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 15); ObjHeapVarString( o, (*this)[0]); // o << CheckNL( w, actPosPtr, 15) << ""; return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l"; } InsNL( o, actPosPtr); } InsNL( o, actPosPtr); } // last block (no '\n' at the end) for( SizeT i1=0; i1"; } // if( (i1+1) < d1) InsNL( o, actPosPtr); InsNL( o, actPosPtr); } return o; } // float template<> ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { const int prec = 6; const int width = 13; SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, width); OutAuto( o, (*this)[0], width, prec, 0); return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { const int prec = 8; const int width = 16; SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, width); OutAuto( o, (*this)[0], width, prec, 0); return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { const int prec = 6; const int width = 13; const char fill = ' '; SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 2*width+3) << AsComplex< DComplex>( (*this)[0], width, prec, fill); return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l( (*this)[eIx++], width, prec, fill); InsNL( o, actPosPtr); } InsNL( o, actPosPtr); } // last block (no '\n' at the end) for( SizeT i1=0; i1( (*this)[eIx++], width, prec, fill); // if( (i1+1) < d1) InsNL( o, actPosPtr); InsNL( o, actPosPtr); } return o; } template<> ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { const int prec = 8; const int width = 16; const char fill = ' '; SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, 2*width+3) << AsComplex< DComplexDbl>( (*this)[0], width, prec, fill); return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l( (*this)[eIx++], width, prec, fill); InsNL( o, actPosPtr); } InsNL( o, actPosPtr); } // last block (no '\n' at the end) for( SizeT i1=0; i1( (*this)[eIx++], width, prec, fill); // if( (i1+1) < d1) InsNL( o, actPosPtr); InsNL( o, actPosPtr); } return o; } // byte (c++ does output as characters) template<> ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { const int width = 4; SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << right; if( this->dim.Rank() == 0) { o << CheckNL( w, actPosPtr, width) << setw(width) << static_cast((*this)[0]); return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l((*this)[eIx++]); InsNL( o, actPosPtr); } InsNL( o, actPosPtr); } // last block (no '\n' at the end) for( SizeT i1=0; i1((*this)[eIx++]); // if( (i1+1) < d1) InsNL( o, actPosPtr); InsNL( o, actPosPtr); } return o; } // strings template<> ostream& Data_::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { bool someCharacterSeen=false; SizeT nElem=N_Elements(); if( nElem == 0) throw GDLException("Variable is undefined."); o << left; SizeT length; if( this->dim.Rank() == 0) { length = (*this)[0].length(); o << CheckNL( w, actPosPtr, length) << (*this)[0]; return o; } SizeT nLoop=nElem/this->dim.Stride(2); SizeT eIx=0; // linear counter SizeT d0=this->Dim(0); SizeT d1=this->Dim(1); // d0 cannot be 0 if( d1 == 0) d1 = 1; for( SizeT l=1; l 1) o << CheckNL( w, actPosPtr, length) << (*this)[eIx++] << " "; else eIx++; } length = (*this)[eIx].length(); if( length > 0) o << CheckNL( w, actPosPtr, length) << (*this)[eIx++]; else eIx++; InsNL( o, actPosPtr); } for( SizeT i0=1; i0 1) o << CheckNL( w, actPosPtr, length) << (*this)[eIx++] << " "; else eIx++; } length = (*this)[eIx].length(); if( length > 0) o << CheckNL( w, actPosPtr, length) << (*this)[eIx++]; else eIx++; InsNL( o, actPosPtr); InsNL( o, actPosPtr); } for ( SizeT i1 = 1; i1 < d1; i1++ ) { someCharacterSeen=false; for ( SizeT i0 = 1; i0 < d0; i0++ ) { length = (*this)[eIx].length() + 1; if( length > 1) someCharacterSeen=true; // for array output a space should be inserted e.g. a=strarr(9)&a[8]=':'&a[0]='>'&aa=[[a],[a]]&print,aa // actually, blanks are inserted only between the first non-null character and the last non-null character. //see a=strarr(9)&a[6]=':'&a[1]='>'&aa=[[a],[a]]&print,aa if (someCharacterSeen) o << CheckNL( w, actPosPtr, length ) << (*this)[eIx++] << " "; else eIx++; } length = (*this)[eIx].length(); if( length > 0) o << CheckNL( w, actPosPtr, length) << (*this)[eIx++]; else eIx++; InsNL( o, actPosPtr); } someCharacterSeen=false; for ( SizeT i0 = 1; i0 < d0; i0++ ) { length = (*this)[eIx].length() + 1; // for array output a space should be inserted e.g. a=strarr(9)&a[8]=':'&a[0]='>'&aa=[[a],[a]]&print,aa // actually, blanks are inserted only between the first non-null character and the last non-null character. //see a=strarr(9)&a[6]=':'&a[1]='>'&aa=[[a],[a]]&print,aa if( length > 1) someCharacterSeen=true; if (someCharacterSeen) o << CheckNL( w, actPosPtr, length ) << (*this)[eIx++] << " "; else eIx++; } length = (*this)[eIx].length(); if( length > 0) o << CheckNL( w, actPosPtr, length) << (*this)[eIx++]; else eIx++; InsNL( o, actPosPtr); return o; } ostream& DStructGDL::ToStream(ostream& o, SizeT w, SizeT* actPosPtr) { // avoid checking actPosPtr SizeT dummyPos = 0; if( actPosPtr == NULL) actPosPtr = &dummyPos; SizeT nTags = NTags(); SizeT nEl = N_Elements(); bool arrOut = false; // remember if an array was already put out for( SizeT e=0; eType() == GDL_STRING) o << CheckNL( w, actPosPtr, 1) << " "; bool isArr = (actEl->Dim().Rank() != 0); if( isArr && arrOut && *actPosPtr != 0) InsNL( o, actPosPtr); actEl->ToStream( o, w, actPosPtr); if( isArr) { arrOut = true; if( *actPosPtr != 0) InsNL( o, actPosPtr); } } BaseGDL* actEl = GetTag( nTags-1, e); assert( actEl != NULL); // if( actEl == NULL) // throw // GDLException("Internal error: Output of UNDEF struct element."); if( actEl->Type() == GDL_STRING) o << CheckNL( w, actPosPtr, 1) << " "; actEl->ToStream( o, w, actPosPtr); o << CheckNL( w, actPosPtr, 1) << "}"; } return o; } ostream& DStructGDL::ToStreamRaw( ostream& o) { // avoid checking actPosPtr SizeT dummyPos = 0; SizeT nTags = NTags( ); SizeT nEl = N_Elements( ); bool arrOut = false; // remember if an array was already put out for ( SizeT e = 0; e < nEl; ++e ) { for ( SizeT tIx = 0; tIx < nTags - 1; ++tIx ) { BaseGDL* actEl = GetTag( tIx, e ); assert( actEl != NULL ); bool isArr = (actEl->Dim( ).Rank( ) != 0); actEl->ToStream( o, 0, &dummyPos ); if ( isArr ) arrOut = true; } BaseGDL* actEl = GetTag( nTags - 1, e ); assert( actEl != NULL ); actEl->ToStream( o, 0, &dummyPos ); } return o; } //this is the routined used by IDL as per the documentation. bool_t xdr_complex( XDR *xdrs, DComplex *p) { return(xdr_float(xdrs, reinterpret_cast(p)) && xdr_float(xdrs, reinterpret_cast(p) + 1)); } //this is the routined used by IDL as per the documentation. bool_t xdr_dcomplex(XDR *xdrs, DComplexDbl *p) { return(xdr_double(xdrs, reinterpret_cast(p)) && xdr_double(xdrs, reinterpret_cast(p) + 1)); } //Alternate version, having problems on windows (??). ////this is the routined used by IDL as per the documentation. //bool_t xdr_complex( XDR *xdrs, DComplex *p) //{ ////Don't you EVER change this code. Refer to gnudatalanguage-devel@lists.sourceforge.net for suggestions/blames. // DFloat preal = p->real(); // DFloat pimag = p->imag(); ////this convoluted code should prevent compilation problem with MINGW's GCC // bool ret1=xdr_float(xdrs, &preal); // bool ret2=xdr_float(xdrs, &pimag); // p->real()=preal; // p->imag()=pimag; // return( (ret1) && (ret2)); //} ////this is the routined used by IDL as per the documentation. //bool_t xdr_dcomplex(XDR *xdrs, DComplexDbl *p) //{ ////Don't you EVER change this code. Refer to gnudatalanguage-devel@lists.sourceforge.net for suggestions/blames. // DDouble preal = p->real(); // DDouble pimag = p->imag(); ////this convoluted code should prevent compilation problem with MINGW's GCC // bool ret1=xdr_double(xdrs, &preal); // bool ret2=xdr_double(xdrs, &pimag); // p->real()=preal; // p->imag()=pimag; // return( (ret1) && (ret2)); //} // //this is the routined used by IDL as per the documentation. //It happens to write twice the number of chars in the file, not very clever. bool_t xdr_counted_string(XDR *xdrs, char **p) { int input = (xdrs->x_op == XDR_DECODE); short length; /* If writing, obtain the length */ if (!input) length = strlen(*p); /* Transfer the string length */ if (!xdr_short(xdrs, (short *) &length)) return(FALSE); /* If reading, obtain room for the string */ if (input) { *p = (char*) malloc((unsigned) (length + 1)); (*p)[length] = '\0'; /* Null termination */ } /* If the string length is nonzero, transfer it */ return(length ? xdr_string(xdrs, p, length) : TRUE); } int xdr_convert(XDR *xdrs, DByte *buf) { assert(false); return 0; } int xdr_convert(XDR *xdrs, DInt *buf) { return (xdr_short(xdrs, buf)); } int xdr_convert(XDR *xdrs, DUInt *buf) { return (xdr_u_short(xdrs, buf)); } int xdr_convert(XDR *xdrs, DLong *buf) { #if defined(__APPLE__) && defined(__LP64__) /* xdr_long actually takes an int on 64bit darwin */ return (xdr_long(xdrs, buf)); #else return (xdr_int(xdrs, buf)); #endif } int xdr_convert(XDR *xdrs, DULong *buf) { #if defined(__APPLE__) && defined(__LP64__) /* xdr_u_long actually takes an unsigned int on 64bit darwin */ return (xdr_u_long(xdrs, buf)); #else return (xdr_u_int(xdrs, buf)); #endif } int xdr_convert(XDR *xdrs, DLong64 *buf) { return (xdr_longlong_t(xdrs, (quad_t *)(buf))); } int xdr_convert(XDR *xdrs, DULong64 *buf) { return (xdr_u_longlong_t(xdrs, (u_quad_t *) (buf))); } int xdr_convert(XDR *xdrs, DFloat *buf) { return (xdr_float(xdrs, buf)); } int xdr_convert(XDR *xdrs, DDouble *buf) { return (xdr_double(xdrs, buf)); } int xdr_convert(XDR *xdrs, DComplex *buf) { return ( xdr_complex(xdrs, buf)) ; } int xdr_convert(XDR *xdrs, DComplexDbl *buf) { return ( xdr_dcomplex(xdrs, buf)) ; } // unformatted ***************************************** template ostream& Data_::Write( ostream& os, bool swapEndian, bool compress, XDR *xdrs ) { if ( os.eof( ) ) os.clear( ); SizeT count = dd.size( ); if ( swapEndian && (sizeof (Ty) != 1) ) { char* cData = reinterpret_cast (&(*this)[0]); SizeT cCount = count * sizeof (Ty); if ( Data_::IS_COMPLEX ) { char *swapBuf = (char*) malloc( sizeof (char) * sizeof (Ty) / 2 ); for ( SizeT i = 0; i < cCount; i += sizeof (Ty) / 2 ) { SizeT src = i + sizeof (Ty) / 2 - 1; for ( SizeT dst = 0; dst(os)).write(reinterpret_cast (&(*this)[0]), count * sizeof (Ty)); if (!(static_cast (os)).good()) { throw GDLIOException("Error writing data."); } } else { os.write( reinterpret_cast (&(*this)[0]), count * sizeof (Ty) ); } if ( !os.good( ) ) { throw GDLIOException( "Error writing data." ); } return os; } template<> ostream& Data_::Write( ostream& os, bool swapEndian, bool compress, XDR *xdrs ) { if ( os.eof( ) ) os.clear( ); SizeT count = dd.size( ); if ( xdrs != NULL ) { int bufsize = 4 + 4 * ((count - 1) / 4 + 1); char *buf = (char *) calloc( bufsize, sizeof (char) ); // XDR adds an addition string length xdrmem_create( xdrs, &buf[0], 4, XDR_ENCODE ); short int length = count; if ( !xdr_short( xdrs, (short int *) &length ) ) cerr << "Error in XDR write" << endl; xdr_destroy( xdrs ); //do it ourselves for ( SizeT i = 0; i < count; i++ ) buf[i + 4] = (*this)[i]; os.write( buf, bufsize ); free( buf ); } else if (compress) { (static_cast(os)).write( reinterpret_cast (&(*this)[0]), count ); if (!(static_cast (os)).good()) { throw GDLIOException("Error writing data."); } } else { os.write( reinterpret_cast (&(*this)[0]), count ); } if ( !os.good( ) ) { throw GDLIOException( "Error writing data." ); } return os; } template<> ostream& Data_::Write( ostream& os, bool swapEndian, bool compress, XDR *xdrs ) { if ( os.eof( ) ) os.clear( ); SizeT count = dd.size( ); for ( SizeT i = 0; i < count; i++ ) { if ( xdrs != NULL ) { int bufsize = 8 + 4 * (((*this)[i].size( ) - 1) / 4 + 1); char *buf = (char *) malloc( bufsize * sizeof (char) ); xdrmem_create( xdrs, &buf[0], bufsize, XDR_ENCODE ); char* bufptr = (char *) (*this)[i].c_str( ); if ( !xdr_counted_string( xdrs, &bufptr ) ) cerr << "Error in XDR write" << endl; xdr_destroy( xdrs ); os.write( buf, bufsize ); free( buf ); } else if (compress) { (static_cast (os)).write((*this)[i].c_str( ), (*this)[i].size( )); if (!(static_cast(os)).good()) { throw GDLIOException("Error writing data."); } } else { os.write( (*this)[i].c_str( ), (*this)[i].size( ) ); } } if ( !os.good( ) ) { throw GDLIOException( "Error writing data." ); } return os; } template istream& Data_::Read( istream& os, bool swapEndian, bool compress, XDR *xdrs ) { if ( os.eof( ) ) throw GDLIOException( "End of file encountered." ); SizeT count = dd.size( ); if ( swapEndian && (sizeof (Ty) != 1) ) { char* cData = reinterpret_cast (&(*this)[0]); SizeT cCount = count * sizeof (Ty); if ( Data_::IS_COMPLEX ) { char *swapBuf = (char*) malloc( sizeof (char) * sizeof (Ty) / 2 ); for ( SizeT i = 0; i < cCount; i += sizeof (Ty) / 2 ) { os.read( swapBuf, sizeof (Ty) / 2 ); SizeT src = i + sizeof (Ty) / 2 - 1; for ( SizeT dst = 0; dst(&(*this)[i]); for (int k=0; k (os)).rdbuf()->incrementPosition(totCount); //ugly patch to maintain position //was: (static_cast(os)).read( reinterpret_cast (&(*this)[0]), count * sizeof (Ty) ); } else { os.read( reinterpret_cast (&(*this)[0]), count * sizeof (Ty) ); } if ( os.eof( ) ) throw GDLIOException( "End of file encountered." ); if ( !os.good( ) ) { throw GDLIOException( "Error reading data." ); } return os; } template<> istream& Data_::Read( istream& os, bool swapEndian, bool compress, XDR *xdrs ) { if ( os.eof( ) ) throw GDLIOException( "End of file encountered." ); SizeT count = dd.size( ); if ( xdrs != NULL ) { unsigned int nChar = this->N_Elements( ); //read byte length in file char* buf = (char *) malloc( 4 ); os.read( buf, 4 ); xdrmem_create( xdrs, &buf[0], 4, XDR_DECODE ); short int length = 0; if ( !xdr_short( xdrs, &length ) ) throw GDLIOException( "Problem reading XDR file." ); xdr_destroy( xdrs ); free( buf ); if ( length <= 0 ) return os; int bufsize = 4 * ((length - 1) / 4 + 1); buf = (char *) calloc( length, sizeof (char) ); os.read( &buf[0], bufsize ); if ( !os.good( ) ) throw GDLIOException( "Problem reading XDR file." ); //else we are correctly aligned for next read! //do it by ourselves, faster and surer! if ( bufsize < nChar ) nChar = bufsize; //truncate eventually for ( SizeT i = 0; i < nChar; i++ ) ( *this )[i] = buf[i]; free( buf ); } else if ( compress ) { /* GD: minimum (?) hack since we want to keep trace of the position in gzipped stream.*/ char* cData = reinterpret_cast (&(*this)[0]); for (SizeT i = 0; i < count; ++i) (static_cast (os)).get(cData[ i]); (static_cast (os)).rdbuf()->incrementPosition(count); //ugly patch to maintain position // (static_cast(os)).read( reinterpret_cast (&(*this)[0]), count ); } else { os.read( reinterpret_cast (&(*this)[0]), count ); } if ( os.eof( ) ) throw GDLIOException( "End of file encountered." ); if ( !os.good( ) ) { throw GDLIOException( "Error reading data." ); } return os; } template<> istream& Data_::Read( istream& os, bool swapEndian, bool compress, XDR *xdrs ) { if ( os.eof( ) ) throw GDLIOException( "End of file encountered." ); SizeT count = dd.size( ); for ( SizeT i = 0; i < count; i++ ) { SizeT nChar = (*this)[i].size( ); if ( xdrs != NULL ) { //read counted string length in file char* buf = (char *) malloc( 4 ); os.read( buf, 4 ); xdrmem_create( xdrs, &buf[0], 4, XDR_DECODE ); short int length = 0; if ( !xdr_short( xdrs, &length ) ) throw GDLIOException( "Problem reading XDR file." ); xdr_destroy( xdrs ); free( buf ); if ( length <= 0 ) { (*this)[i].clear(); } else { int bufsize = 4 + 4 * ((length - 1) / 4 + 1) ; buf = (char *) calloc( length, sizeof (char) ); os.read( &buf[0], bufsize ); if ( !os.good( ) ) throw GDLIOException( "Problem reading XDR file." ); //else we are correctly aligned for next read! (*this)[i].assign( &buf[4], length ); } } else { SizeT maxLen = 1024; vector vbuf( maxLen ); if ( nChar > 0 ) { if ( nChar > maxLen ) { maxLen = nChar; vbuf.resize( maxLen ); } if ( compress ) { /* GD: minimum (?) hack since we want to keep trace of the position in gzipped stream.*/ char c; vbuf.clear( ); for ( SizeT i = 0; i < nChar; i++ ) { (static_cast(os)).get( c ); //which does nothing more than os.get(c)... vbuf.push_back( c ); } (static_cast(os)).rdbuf()->incrementPosition(nChar); //ugly patch to maintain position } else { os.read( &vbuf[0], nChar ); } (*this)[i].assign( &vbuf[0], nChar ); } } } if ( os.eof( ) ) throw GDLIOException( "End of file encountered." ); if ( !os.good( ) ) { throw GDLIOException( "Error reading data." ); } return os; } ostream& DStructGDL::Write( ostream& os, bool swapEndian, bool compress, XDR *xdrs ) { SizeT nEl = N_Elements( ); SizeT nTags = NTags( ); for ( SizeT i = 0; i < nEl; ++i ) for ( SizeT t = 0; t < nTags; ++t ) GetTag( t, i )->Write( os, swapEndian, compress, xdrs ); return os; } istream& DStructGDL::Read( istream& os, bool swapEndian, bool compress, XDR *xdrs ) { SizeT nEl = N_Elements( ); SizeT nTags = NTags( ); for ( SizeT i = 0; i < nEl; ++i ) for ( SizeT t = 0; t < nTags; ++t ) GetTag( t, i )->Read( os, swapEndian, compress, xdrs ); return os; } template BaseGDL* Data_::AssocVar( int lun, SizeT offset) { return new Assoc_( lun, this, offset); } BaseGDL* DStructGDL::AssocVar( int lun, SizeT offset) { return new Assoc_( lun, this, offset); } //#include "instantiate_templates.hpp" #endif gdl-0.9.9/src/devicenull.hpp000066400000000000000000000046101340051421000157200ustar00rootroot00000000000000/* ************************************************************************* devicenull.hpp - NULL device ------------------- begin : 20 February 2014 copyright : (C) 2012 by Alain Coulais email : alaingdl@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICENULL_HPP_ #define DEVICENULL_HPP_ class DeviceNULL : public GraphicsDevice { // std::string fileName; // GDLNULLStream* actStream; // void InitStream() { } public: // DeviceNULL(): GraphicsDevice(), fileName( "gdl.null"), actStream( NULL) DeviceNULL(): GraphicsDevice() { name = "NULL"; DLongGDL origin( dimension( 2)); DLongGDL zoom( dimension( 2)); zoom[0] = 1; zoom[1] = 1; dStruct = new DStructGDL( "!DEVICE"); dStruct->InitTag("NAME", DStringGDL( name)); dStruct->InitTag("X_SIZE", DLongGDL( 1000)); dStruct->InitTag("Y_SIZE", DLongGDL( 1000)); dStruct->InitTag("X_VSIZE", DLongGDL( 1000)); dStruct->InitTag("Y_VSIZE", DLongGDL( 1000)); dStruct->InitTag("X_CH_SIZE", DLongGDL( 0)); dStruct->InitTag("Y_CH_SIZE", DLongGDL( 0)); dStruct->InitTag("X_PX_CM", DFloatGDL( 1000.0)); dStruct->InitTag("Y_PX_CM", DFloatGDL( 1000.0)); dStruct->InitTag("N_COLORS", DLongGDL( 256)); dStruct->InitTag("TABLE_SIZE", DLongGDL( 256)); dStruct->InitTag("FILL_DIST", DLongGDL( 0)); dStruct->InitTag("WINDOW", DLongGDL( -1)); dStruct->InitTag("UNIT", DLongGDL( 0)); dStruct->InitTag("FLAGS", DLongGDL( 266807)); dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); } ~DeviceNULL() {} }; #endif gdl-0.9.9/src/deviceps.hpp000066400000000000000000000567071340051421000154060ustar00rootroot00000000000000/* ************************************************************************* deviceps.hpp - postscript device ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICEPS_HPP_ #define DEVICEPS_HPP_ #include "gdlpsstream.hpp" #include "plotting.hpp" // get_axis_crange for TV() #include "initsysvar.hpp" #include // GSL_CONST_MKSA_INCH #include "objects.hpp" # ifdef USE_PSLIB # include // tmpnam # if !defined(_WIN32) || defined(__CYGWIN__) # include // uname # endif # include # endif #ifdef _MSC_VER #define CM2IN (.01 / GSL_CONST_MKSA_INCH) // This is not good, but works #define in2cm ( GSL_CONST_MKSA_INCH * 100) #define DPI 72.0 //in dpi; #define RESOL 1000.0 #else static const float CM2IN = .01 / GSL_CONST_MKSA_INCH; static const float in2cm = GSL_CONST_MKSA_INCH*100; static const PLFLT DPI = 72.0 ; //in dpi; static const float RESOL = 1000.0; #endif class DevicePS: public GraphicsDevice { std::string fileName; GDLPSStream* actStream; float XPageSize; float YPageSize; float XOffset; float YOffset; int color; int decomposed; // false -> use color table bool orient_portrait; bool encapsulated; int bitsPerPix; float scale; GDLStream *psUnit; void InitStream() { delete actStream; DLongGDL* pMulti = SysVar::GetPMulti(); DLong nx = (*pMulti)[ 1]; DLong ny = (*pMulti)[ 2]; if( nx <= 0) nx = 1; if( ny <= 0) ny = 1; actStream = new GDLPSStream( nx, ny, (int)SysVar::GetPFont(), encapsulated, color, bitsPerPix); actStream->sfnam( fileName.c_str()); // trying to solve bug report 3611898 // AC 29-Avril-2013: the way I found to link GDLPSStream* and GDLStream* DLong lun=GetLUN(); psUnit = &fileUnits[ lun-1]; psUnit->Open(fileName,fstream::out,false,false,false, defaultStreamWidth,false,false); (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("UNIT"))))[0]=lun; // zeroing offsets (xleng and yleng are the default ones but they need to be specified // for the offsets to be taken into account by spage(), works with plplot >= 5.9.9) actStream->spage(DPI, DPI, 540, 720, 0, 0); //plplot default: portrait! // as setting the offsets and sizes with plPlot is (extremely) tricky, and some of these setting // are hardcoded into plplot (like EPS header, and offsets in older versions of plplot) // here we play only with the aspect ratio - size and offset are handled by pslib when device,/close is called // patch 3611949 by Joanna, 29 Avril 2013 PLFLT pageRatio=XPageSize/YPageSize; std::string as = i2s( pageRatio); actStream->setopt( "a", as.c_str()); // plot orientation //std::cout << "orientation : " << orient_portrait<< std::endl; actStream->sdiori(orient_portrait ? 1 : 2); // no pause on destruction actStream->spause( false); // extended fonts actStream->fontld( 1); PLINT r[ctSize], g[ctSize], b[ctSize]; actCT.Get( r, g, b); actStream->SetColorMap0( r, g, b, ctSize); actStream->SetColorMap1( r, g, b, ctSize); // default: black+white (IDL behaviour) short font=((int)SysVar::GetPFont()>-1)?1:0; string what="text="+i2s(font)+",color="+i2s(color); actStream->setopt( "drvopt",what.c_str()); actStream->scolbg(255,255,255); // start with a white background actStream->Init(); // need to be called initially. permit to fix things actStream->ssub(1,1); actStream->adv(0); // load font actStream->font( 1); actStream->vpor(0,1,0,1); actStream->wind(0,1,0,1); actStream->DefaultCharSize(); //in case these are not initalized, here is a good place to do it. // if (actStream->updatePageInfo()==true) // { // actStream->GetPlplotDefaultCharSize(); //initializes everything in fact.. // // } // PLFLT xp, yp; // PLINT xleng, yleng, xoff, yoff; // actStream->gpage(xp, yp, xleng, yleng, xoff, yoff); // // to mimic IDL we must scale char so that the A4 charsize is constant whatever the size of the plot // PLFLT size = (XPageSize>YPageSize)?XPageSize:YPageSize; // PLFLT refsize= (xleng/xp>yleng/yp)?xleng/xp:yleng/yp; // PLFLT charScale=(refsize*in2cm)/size; // PLFLT defhmm, scalhmm; // plgchr(&defhmm, &scalhmm); // height of a letter in millimetres // actStream->RenewPlplotDefaultCharsize(defhmm * charScale); } private: void pslibHacks() { # ifndef USE_PSLIB Warning("Warning: pslib support is mandatory for the PostScript driver to handle correctly the following"); Warning(" keywords: [X,Y]OFFSET, [X,Y]SIZE, SCALE_FACTOR"); # else PSDoc *ps = PS_new(); GDLGuard psGuard( ps, PS_delete); if (ps == NULL) { Warning("Warning: pslib failed to allocate memory."); return; } FILE *fp = tmpfile(); // this creates a file which should be deleted automaticaly when it is closed FILEGuard fpGuard( fp, fclose); if (fp == NULL) { Warning("Warning: failed to create temporary PostScript file."); return; } if (PS_open_fp(ps, fp) == -1) { Warning("Warning: pslib failed to open a new PostScript file."); goto cleanup; } PS_set_parameter(ps, "imagereuse", "false"); PS_set_info(ps, "Title", "Graphics produced by GDL"); PS_set_info(ps, "Orientation", orient_portrait ? "Portrait" : "Landscape"); { string tmp; #if !defined(_WIN32) || defined(__CYGWIN__) struct utsname uts; uname(&uts); tmp = "GDL Version " + string(VERSION) + ", " + string(uts.sysname) + " " + string(uts.machine); PS_set_info(ps, "Creator", tmp.c_str()); char* login = getlogin(); if (login == NULL) Warning("Warning: getlogin() failed!"); tmp = (login == NULL ? "?" : login) + string("@") + uts.nodename; PS_set_info(ps, "Author", tmp.c_str()); #else tmp = "GDL Version " + string(VERSION) + ", Microsoft Windows x32"; PS_set_info(ps, "Creator", tmp.c_str()); WCHAR username[257]; char cusername[257]; DWORD username_len = 257; GetUserNameW(username, &username_len); WideCharToMultiByte(CP_ACP, 0, username, username_len, cusername, username_len, NULL, NULL); PS_set_info(ps, "Author", cusername); #endif } //bug: PSLIB does not return the correct boundingbox, it forgets offx and offy. Try to get it //back (using pslib own code!)! char *bb; FILE *feps; char buffer[1024]; //largely sufficient int nbytes; feps=fopen(fileName.c_str(), "r"); nbytes=fread(buffer,sizeof(char),1023,feps); fclose(feps); buffer[1023]=0; bb = strstr(buffer, "%%BoundingBox:"); float offx, offy, width, height; if(bb) { bb += 15; sscanf(bb, "%f %f %f %f", &offx, &offy, &width, &height); } else { offx=0; offy=0; width=500; height=500; //silly values, will be replaced afterwards hopefully. } // TODO //psfont = PS_findfont(ps, "Helvetica", "", 0); //PS_setfont(ps, psfont, 8.0); char bbstr [20], offstr [20]; int bbXSize, bbYSize; { int bbXoff = XOffset*CM2IN*DPI; int bbYoff = YOffset*CM2IN*DPI; bbXSize = orient_portrait ? bbXoff + XPageSize*CM2IN*DPI*scale : bbXoff + YPageSize*CM2IN*DPI*scale; bbYSize = orient_portrait ? bbYoff + YPageSize*CM2IN*DPI*scale : bbYoff + XPageSize*CM2IN*DPI*scale; sprintf(bbstr,"%i %i %i %i",bbXoff,bbYoff,bbXSize,bbYSize); sprintf(offstr,"%i %i",bbXoff,bbYoff); PS_set_info(ps,"BoundingBox",bbstr); PS_begin_page(ps, bbXSize, bbYSize); { int psimage = PS_open_image_file(ps, "eps", fileName.c_str(), NULL, 0); if (psimage == 0) { Warning("Warning: pslib failed to load plPlot output file."); goto cleanup; } float scl = 0.98*min((bbXSize-bbXoff) / (width-offx), (bbYSize-bbYoff) / (height-offy) ); int margx = ((bbXSize-bbXoff) - scl*(width-offx))/2; int margy = ((bbYSize-bbYoff) - scl*(height-offy))/2; PS_place_image(ps, psimage, bbXoff-offx*scl + margx, bbYoff-offy*scl + margy, scl ); PS_close_image(ps, psimage); } PS_end_page(ps); PS_close(ps); } // Replace PageBoundingBox and CropBox and write contents to fileName // To do that we need to remove a few chars of the line of 21 "%" at the begining of the plplot file, // since we ADD characters and that appears to be unsafe (? version dependent? compiler?). // if 21 "%" are not found, it's best to DO NOTHING! // the "%%%%%%%%%%%%%%%%%%%%%" is largely before offset 12000, thus in the first fread. { rewind(fp); FILE *fp_plplot = fopen(fileName.c_str(), "w"); FILEGuard fp_plplotGuard( fp_plplot, fclose); if (fp_plplot == NULL) { Warning("Warning: failed to open plPlot-generated file"); goto cleanup; } // When multiple pages are supported, PageBoundingBox and the cropbox // will appear more than once. Then this section will need to be redone. // Edit: change the two 0's after the PageBoundingBox string pbstr=string("%%PageBoundingBox: ")+offstr; long added=pbstr.length()-22; //number of chars to replace, compensated by //removal of equivalent number of "%" elsewhere. const size_t buflen=12000; #ifdef _MSC_VER char *buff = (char*)alloca(sizeof(char)*buflen); #else char buff[buflen]; #endif //do the first read: size_t cnt = fread(&buff, 1, buflen, fp); std::string sbuff; sbuff.assign(buff,cnt); //if "%%%%%%%%%%%%%%%%%%%%%" is not found, or 21 chars too small, do nothing: size_t junkbufferloc=sbuff.find("%%%%%%%%%%%%%%%%%%%%%"); bool doIt=((junkbufferloc != string::npos) && (added < 22) ); // find the PageBoundingBox statement size_t pos = sbuff.find("%%PageBoundingBox: 0 0"); if (doIt && pos != string::npos) { //shrink "%%%..." by the amount of added chars... sbuff.erase(junkbufferloc,added); //replace, adding some chars: sbuff.replace(pos,22,pbstr); } pos = sbuff.find("0 setlinecap"); if (doIt && pos != string::npos) { sbuff.replace(pos,1,"1"); } pos = sbuff.find("0 setlinejoin"); if (doIt && pos != string::npos) { sbuff.replace(pos,1,"1"); } // PSlib outputs pdfmarks which resize the PDF to the size of the boundingbox // this is nice, but not IDL behaviour (and anyway, the two 0's are wrong) char mychar[60]; sprintf(mychar,"[ /CropBox [0 0 %i.00 %i.00] /PAGE pdfmark",bbXSize,bbYSize); string pdfstr=string(mychar); pos = sbuff.find(pdfstr); // this replacement will shrink only the size of sbuff and is thus safe if (pos != string::npos) sbuff.erase(pos,pdfstr.length()); // write the first buflen to file strcpy(buff,sbuff.c_str()); if (fwrite(&buff, 1, sbuff.size(), fp_plplot) < sbuff.size()) //and NOT buflen! { Warning("Warning: failed to overwrite the plPlot-generated file with pslib output"); } // read the rest of fp and write to file while (true) { cnt = fread(&buff, 1, buflen, fp); if (!cnt) break; if (fwrite(&buff, 1, cnt, fp_plplot) < cnt) { Warning("Warning: failed to overwrite the plPlot-generated file with pslib output"); } } // fclose(fp_plplot); } cleanup: //all closing done by FileGuard now! // PSlib changes locale - bug no. 3428043 # ifdef HAVE_LOCALE_H setlocale(LC_ALL, "C"); # endif # endif } private: void epsHacks() { // using namespace std; //PLPLOT outputs a strange boundingbox; this hack directly edits the eps file. //if the plplot bug ever gets fixed, this hack won't be needed. char *bb; FILE *feps; const size_t buflen=2048;//largely sufficient char buffer[buflen]; int cnt; feps=fopen(fileName.c_str(), "r"); cnt=fread(buffer,sizeof(char),buflen,feps); //read original boundingbox bb = strstr(buffer, "%%BoundingBox:"); if (bb==NULL) { Warning("Warning: failed to read temporary PostScript file."); fclose(feps); return; } string sbuff = string(buffer); stringstream searchstr,replstr; size_t pos; int extralen=0; // Do not change bonding box. It is good now. // int offx, offy, width, height; // bb += 15; // sscanf(bb, "%i %i %i %i", &offx, &offy, &width, &height); // float hsize = XPageSize*CM2IN*DPI*scale; // float vsize = YPageSize*CM2IN*DPI*scale; // float newwidth = (width - offx), newheight = (height - offy); // float hscale = (orient_portrait ? hsize : vsize)/newwidth/5.0; // float vscale = (orient_portrait ? vsize : hsize)/newheight/5.0; //// hscale = min(hscale,vscale)*0.98; // hscale = min(hscale,vscale); // vscale = hscale; // float hoff = -5.*offx*hscale + ((orient_portrait ? hsize : vsize) - 5.0*hscale*newwidth)*0.5; // float voff = -5.*offy*vscale + ((orient_portrait ? vsize : hsize) - 5.0*vscale*newheight)*0.5; // // //replace with a more sensible boundingbox // searchstr << "BoundingBox: " << offx << " " << offy << " " << width << " " << height; // replstr << "BoundingBox: 0 0 " << floor((orient_portrait ? hsize : vsize)+0.5) << " " << floor((orient_portrait ? vsize : hsize)+0.5); // pos = sbuff.find(searchstr.str()); // if (pos != string::npos) { // sbuff.replace(pos,searchstr.str().length(),replstr.str()); // extralen = replstr.str().length()-searchstr.str().length(); // } //replace the values of linecap and linejoin to nice round butts (sic!) more pleasing to the eye. searchstr.str(""); searchstr << "0 setlinecap" << endl << " 0 setlinejoin"; replstr.str(""); replstr << "1 setlinecap" << endl << " 1 setlinejoin"; pos = sbuff.find(searchstr.str()); if (pos != string::npos) { sbuff.replace(pos,searchstr.str().length(),replstr.str()); extralen = extralen + replstr.str().length()-searchstr.str().length(); } //add landscape if (!orient_portrait) { searchstr.str("%%Page: 1 1"); replstr.str(""); replstr << "%%Page: 1 1" << endl << "%%PageOrientation: Landscape" << endl; pos = sbuff.find(searchstr.str()); if (pos != string::npos) { sbuff.replace(pos,searchstr.str().length(),replstr.str()); extralen = extralen + replstr.str().length()-searchstr.str().length(); } } //open temp file FILE *fp = tmpfile(); // this creates a file which should be deleted automaticaly when it is closed FILEGuard fpGuard( fp, fclose); if (fp == NULL) { Warning("Warning: failed to create temporary PostScript file."); fclose(feps); return; } // write the first buflen to temp file fwrite(sbuff.c_str(), 1, buflen+extralen, fp); // read the rest of feps and write to temp file while (true) { cnt = fread(&buffer, 1, buflen, feps); if (!cnt) break; if (fwrite(&buffer, 1, cnt, fp) < cnt) { Warning("Warning: failed to write to temporary file"); } } fclose(feps); // copy temp file to fileName rewind(fp); FILE *fp_plplot = fopen(fileName.c_str(), "w"); FILEGuard fp_plplotGuard( fp_plplot, fclose); if (fp_plplot == NULL) { Warning("Warning: failed to open plPlot-generated file"); return; } while (true) { cnt = fread(&buffer, 1, buflen, fp); if (!cnt) break; if (fwrite(&buffer, 1, cnt, fp_plplot) < cnt) { Warning("Warning: failed to overwrite the plPlot-generated file with pslib output"); } } } public: DevicePS(): GraphicsDevice(), fileName( "gdl.ps"), actStream( NULL), XPageSize(17.78), YPageSize(12.7), XOffset(0.75),YOffset(5.0), color(0), decomposed( 0), encapsulated(false), scale(1.), orient_portrait(true), bitsPerPix(8) { name = "PS"; DLongGDL origin( dimension( 2)); DLongGDL zoom( dimension( 2)); zoom[0] = 1; zoom[1] = 1; dStruct = new DStructGDL( "!DEVICE"); dStruct->InitTag("NAME", DStringGDL( name)); dStruct->InitTag("X_SIZE", DLongGDL( XPageSize*scale*RESOL)); dStruct->InitTag("Y_SIZE", DLongGDL( YPageSize*scale*RESOL)); dStruct->InitTag("X_VSIZE", DLongGDL( XPageSize*scale*RESOL)); dStruct->InitTag("Y_VSIZE", DLongGDL( YPageSize*scale*RESOL)); dStruct->InitTag("X_CH_SIZE", DLongGDL( 222)); dStruct->InitTag("Y_CH_SIZE", DLongGDL( 352)); dStruct->InitTag("X_PX_CM", DFloatGDL( RESOL)); dStruct->InitTag("Y_PX_CM", DFloatGDL( RESOL)); dStruct->InitTag("N_COLORS", DLongGDL( 256)); dStruct->InitTag("TABLE_SIZE", DLongGDL( 256)); dStruct->InitTag("FILL_DIST", DLongGDL( 1)); dStruct->InitTag("WINDOW", DLongGDL( -1)); dStruct->InitTag("UNIT", DLongGDL( 0)); dStruct->InitTag("FLAGS", DLongGDL( 266791)); //266807 if color, 266791 if monochrome. dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); SetPortrait(); # ifdef USE_PSLIB PS_boot(); // PSlib changes locale - bug no. 3428043 # ifdef HAVE_LOCALE_H setlocale(LC_ALL, "C"); # endif # endif } ~DevicePS() { delete actStream; # ifdef USE_PSLIB PS_shutdown(); // PSlib changes locale - bug no. 3428043 # ifdef HAVE_LOCALE_H setlocale(LC_ALL, "C"); # endif # endif } GDLGStream* GetStream( bool open=true) { if( actStream == NULL) { if( !open) return NULL; InitStream(); } return actStream; } bool SetFileName( const std::string& f) { fileName = f; return true; } bool CloseFile() { // trying to solve bug report 3611898 // this is needed to decrement Lun number ... (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("UNIT"))))[0]=0; if (actStream != NULL) { psUnit->Close(); psUnit->Free(); psUnit=NULL; delete actStream; actStream = NULL; if (!encapsulated) pslibHacks(); else epsHacks(); // needs to be called after the plPlot-generated file is closed } return true; } bool SetXOffset( const float xo) // xo [cm] { XOffset=xo; return true; } bool SetYOffset( const float yo) // yo [cm] { YOffset=yo; return true; } bool SetXPageSize( const float xs) // xs [cm] { XPageSize=xs; (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_SIZE"))))[0] = DLong(floor(0.5+ xs * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_PX_CM"))))[0] )); (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_VSIZE"))))[0] = DLong(floor(0.5+ xs * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_PX_CM"))))[0] )); return true; } bool SetYPageSize( const float ys) // ys [cm] { YPageSize=ys; (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_SIZE"))))[0] = DLong(floor(0.5+ ys * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_PX_CM"))))[0] )); (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_VSIZE"))))[0] = DLong(floor(0.5+ ys * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_PX_CM"))))[0] )); return true; } bool SetColor(const long hascolor) { if (hascolor==1) color=1; else color=0; if (hascolor==1) { DLong FLAG=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]; (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]=FLAG|16; //set colored device } else { DLong FLAG=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]; (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]=FLAG&(~16); //set monochrome device } //trick, to be repeated in Decomposed() DLong FLAG=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]; if (decomposed==1 && color==1) (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]= FLAG&(~512); //remove flag 'printer' since logic does not work with ps drive else (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]= FLAG|(512); //set Flag printer return true; } bool SetPortrait() { // no need to update !D orient_portrait = true; // nb: IDL defaults to: // SetXPageSize(7 * in2cm); // SetYPageSize(5 * in2cm); // SetXOffset(.75 * in2cm); // SetYOffset(5 * in2cm); return true; } bool SetLandscape() { // no need to update !D orient_portrait = false; // SetXPageSize(9.5 * in2cm); // SetYPageSize(7.0 * in2cm); // SetXOffset(.75 * in2cm); // SetYOffset(10.25 * in2cm); return true; } bool SetScale(float value) { //no effect for postscript in IDL up to 8 (?) scale = value; return true; } bool SetEncapsulated(bool val) { encapsulated = val; return true; } bool SetBPP(const int val) { int bpp = max(min(8,val),1); if (bpp > 4) bpp = 8; else if (bpp > 2) bpp = 4; bitsPerPix = bpp; return true; } bool Decomposed( bool value) { decomposed = value; if (decomposed==1) (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("N_COLORS"))))[0]=256*256*256; else (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("N_COLORS"))))[0]=256; DLong FLAG=(*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]; //trick, to be repeated in SetColor(). To compensate a problem in ps driver. Other possibilities: use only the psc driver and do the black & white directly ourselves. if (decomposed==1 && color==1) { (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]= FLAG&(~512); //remove flag 'printer' since logic does not work with ps drive } else (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]= FLAG|(512); //set Flag printer return true; } DLong GetDecomposed() { return decomposed; } DIntGDL* GetPageSize() { DIntGDL* res; res = new DIntGDL(2, BaseGDL::NOZERO); (*res)[0]= XPageSize; (*res)[1]= YPageSize; return res; } }; #endif gdl-0.9.9/src/devicesvg.hpp000066400000000000000000000200701340051421000155430ustar00rootroot00000000000000/* ************************************************************************* devicesvg.hpp - SVG device ------------------- begin : December 26 2008 copyright : (C) 2008 by Sylwester Arabas email : slayoo@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICESVG_HPP_ #define DEVICESVG_HPP_ #include "gdlsvgstream.hpp" static const float SVG_CM2IN = (1.0 / 2.54) ; static const float SVG_RESOL = 1000.0; // per cm static const PLFLT SVG_DPI = 72; class DeviceSVG : public GraphicsDevice { std::string fileName; GDLSVGStream* actStream; float XPageSize; float YPageSize; float XOffset; float YOffset; int color; int decomposed; // false -> use color table bool orient_portrait; float scale; void InitStream() { delete actStream; DLongGDL* pMulti = SysVar::GetPMulti(); DLong nx = (*pMulti)[ 1]; DLong ny = (*pMulti)[ 2]; if( nx <= 0) nx = 1; if( ny <= 0) ny = 1; actStream = new GDLSVGStream( nx, ny); actStream->sfnam( fileName.c_str()); actStream->spage(SVG_DPI, SVG_DPI, XPageSize*72*SVG_CM2IN, YPageSize*72*SVG_CM2IN, XOffset*72*SVG_CM2IN, YOffset*72*SVG_CM2IN); // no pause on destruction actStream->spause( false); // extended fonts actStream->fontld( 1); PLINT r[ctSize], g[ctSize], b[ctSize]; actCT.Get( r, g, b); actStream->SetColorMap0( r, g, b, ctSize); actStream->SetColorMap1( r, g, b, ctSize); actStream->scolbg(255,255,255); // start with a white background actStream->Init(); // need to be called initially. permit to fix things actStream->ssub(1,1); actStream->adv(0); // load font actStream->font( 1); actStream->vpor(0,1,0,1); actStream->wind(0,1,0,1); actStream->DefaultCharSize(); // //in case these are not initalized, here is a good place to do it. // if (actStream->updatePageInfo()==true) // { // actStream->GetPlplotDefaultCharSize(); //initializes everything in fact.. // } } public: DeviceSVG(): GraphicsDevice(), fileName( "gdl.svg"), actStream( NULL), XPageSize(29.7), YPageSize(21.0), XOffset(0.0), YOffset(0.0), color(1), decomposed(1), scale(1.) { name = "SVG"; DLongGDL origin( dimension( 2)); DLongGDL zoom( dimension( 2)); zoom[0] = 1; zoom[1] = 1; dStruct = new DStructGDL( "!DEVICE"); dStruct->InitTag("NAME", DStringGDL( name)); dStruct->InitTag("X_SIZE", DLongGDL( XPageSize*scale*SVG_RESOL)); dStruct->InitTag("Y_SIZE", DLongGDL( YPageSize*scale*SVG_RESOL)); dStruct->InitTag("X_VSIZE", DLongGDL( XPageSize*scale*SVG_RESOL)); dStruct->InitTag("Y_VSIZE", DLongGDL( YPageSize*scale*SVG_RESOL)); dStruct->InitTag("X_CH_SIZE", DLongGDL( 0.25*scale*SVG_RESOL)); dStruct->InitTag("Y_CH_SIZE", DLongGDL( 1.5*0.25*scale*SVG_RESOL)); dStruct->InitTag("X_PX_CM", DFloatGDL( SVG_RESOL)); dStruct->InitTag("Y_PX_CM", DFloatGDL( SVG_RESOL)); dStruct->InitTag("N_COLORS", DLongGDL( 16777216)); dStruct->InitTag("TABLE_SIZE", DLongGDL( 256)); dStruct->InitTag("FILL_DIST", DLongGDL( 0)); dStruct->InitTag("WINDOW", DLongGDL( -1)); dStruct->InitTag("UNIT", DLongGDL( 0)); dStruct->InitTag("FLAGS", DLongGDL( 266807)); dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); SetLandscape(); } ~DeviceSVG() { delete actStream; } GDLGStream* GetStream( bool open=true) { if( actStream == NULL) { if( !open) return NULL; InitStream(); } return actStream; } bool SetFileName( const std::string& f) { fileName = f; return true; } bool CloseFile() { delete actStream; actStream = NULL; return true; } bool SetXOffset( const float xo) // xo [cm] { // nothing for the moment (coordinates tricky) // XOffset=xo; return true; } bool SetYOffset( const float yo) // yo [cm] { // nothing for the moment (coordinates tricky) // YOffset=yo; return true; } bool SetXPageSize( const float xs) // xs [cm] { // nothing for the moment (coordinates tricky) // XPageSize=xs; // (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_SIZE"))))[0] // = DLong(floor(0.5+ // xs * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_PX_CM"))))[0] // )); // (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_VSIZE"))))[0] // = DLong(floor(0.5+ // xs * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("X_PX_CM"))))[0] // )); return true; } bool SetYPageSize( const float ys) // ys [cm] { // nothing for the moment (coordinates tricky) // YPageSize=ys; // (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_SIZE"))))[0] // = DLong(floor(0.5+ // ys * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_PX_CM"))))[0] // )); // (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_VSIZE"))))[0] // = DLong(floor(0.5+ // ys * (*static_cast(dStruct->GetTag(dStruct->Desc()->TagIndex("Y_PX_CM"))))[0] // )); return true; } bool SetColor(const long hascolor) { if (hascolor==1) color=1; else color=0; if (hascolor==1) { DLong FLAG=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]; (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]=FLAG|16; //set colored device } else { DLong FLAG=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]; (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]=FLAG&(~16); //set monochrome device } //trick, to be repeated in Decomposed() DLong FLAG=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("FLAGS"))))[0]; if (decomposed==1 && color==1) (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]= FLAG&(~512); //remove flag 'printer' since logic does not work with ps drive else (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0]= FLAG|(512); //set Flag printer return true; } bool SetPortrait() { // nothing for the moment (coordinates tricky) // orient_portrait = true; return true; } bool SetLandscape() { // nothing for the moment (coordinates tricky) // orient_portrait = false; return true; } bool SetScale(float value) { //no effect for postscript in IDL up to 8 (?) // scale = value; return true; } bool Decomposed( bool value) { decomposed = value; if (decomposed) (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("N_COLORS"))))[0]=256*256*256; else (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("N_COLORS"))))[0]=256; return true; } DLong GetDecomposed() { return decomposed; } DIntGDL* GetPageSize() { DIntGDL* res; res = new DIntGDL(2, BaseGDL::NOZERO); (*res)[0]= XPageSize*SVG_DPI*SVG_CM2IN; (*res)[1]= YPageSize*SVG_DPI*SVG_CM2IN; return res; } }; #endif gdl-0.9.9/src/devicewin.cpp000066400000000000000000000342351340051421000155440ustar00rootroot00000000000000/* ************************************************************************* devicewin.cpp - win32 gdi interface ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef _WIN32 #include "includefirst.hpp" #include #include "graphicsdevice.hpp" #include "gdlwinstream.hpp" #include "devicewin.hpp" #ifdef HAVE_LIBWXWIDGETS #include "gdlwxstream.hpp" #endif #include "plotting.hpp" // JP Apr 2015, HACK: hook WM_PAINT and WM_DESTROY from plplot window. HHOOK hHook[2] = {0}; DeviceWIN *p_this; LRESULT CALLBACK DeviceWIN::_CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) { return p_this->CallWndProc(nCode, wParam, lParam); } LRESULT CALLBACK DeviceWIN::_GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { return p_this->GetMsgProc(nCode, wParam, lParam); } LRESULT DeviceWIN::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) { CWPSTRUCT* lpWp = (CWPSTRUCT*)lParam; int i; BOOL windowfound = false; if (nCode >= 0) { for (i = 0; i < winList.size(); i++) { if (winList[i] && winList[i]->GetValid() && lpWp->hwnd == ((GDLWINStream *)winList[i])->GetHwnd()) { windowfound = true; break; } } if (windowfound) { switch (lpWp->message) { case WM_PAINT: { // Redraw image while resizing/moving/etc.. PAINTSTRUCT ps; BeginPaint(lpWp->hwnd, &ps); ((GDLWINStream *)winList[i])->RedrawTV(); EndPaint(lpWp->hwnd, &ps); break; } case WM_DESTROY: { winList[i]->SetValid(false); break; } } } } return CallNextHookEx(NULL, nCode, wParam, lParam); } LRESULT DeviceWIN::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { LRESULT retCode = CallNextHookEx(NULL, nCode, wParam, lParam); MSG* lpWp = (MSG*)lParam; int i; BOOL windowfound = false; if (nCode >= 0) { for (i = 0; i < winList.size(); i++) { if (winList[i] && winList[i]->GetValid() && lpWp->hwnd == ((GDLWINStream *)winList[i])->GetHwnd()) { windowfound = true; break; } } if (windowfound) { if (lpWp->message == WM_PAINT) { // Redraw image after the window is finally reactivated. //PAINTSTRUCT ps; //BeginPaint(lpWp->hwnd, &ps); ((GDLWINStream *)winList[i])->RedrawTV(); //EndPaint(lpWp->hwnd, &ps); } msghookiter iter_msg; GDLWINStream* winstream = (GDLWINStream *)winList[i]; for (iter_msg = winstream->msghooks.begin(); iter_msg != winstream->msghooks.end(); ++iter_msg) { if ((*iter_msg).first == lpWp->message) (winstream->*(*iter_msg).second)(lpWp->message, lpWp->wParam, lpWp->lParam); } } } return retCode; } // HACK end void DeviceWIN::EventHandler() { if (actWin < 0) return; int wLSize = winList.size(); for (int i = 0; i < wLSize; i++) { if (winList[i] != NULL) winList[i]->EventHandler(); } TidyWindowsList(); } bool DeviceWIN::WDelete(int wIx) { TidyWindowsList(); int wLSize = winList.size(); if (wIx >= wLSize || wIx < 0 || winList[wIx] == NULL) return false; #ifdef HAVE_LIBWXWIDGETS if (dynamic_cast(winList[wIx]) != NULL) { Warning("Attempt to delete widget (ID=" + i2s(wIx) + "). Will be auto-deleted upon window destruction."); return false; } #endif delete winList[wIx]; winList[wIx] = NULL; oList[wIx] = 0; // set to most recently created std::vector< long>::iterator mEl = std::max_element(oList.begin(), oList.end()); // no window open if (*mEl == 0) { SetActWin(-1); oIx = 1; if (hHook[0]) { UnhookWindowsHookEx(hHook[0]); hHook[0] = 0; } if (hHook[1]) { UnhookWindowsHookEx(hHook[1]); hHook[1] = 0; } } else SetActWin(std::distance(oList.begin(), mEl)); return true; } #ifdef HAVE_LIBWXWIDGETS bool DeviceWIN::GUIOpen(int wIx, int xSize, int ySize) { TidyWindowsList(); int wLSize = winList.size(); if (wIx >= wLSize || wIx < 0) return false; if (winList[wIx] != NULL) { delete winList[wIx]; winList[wIx] = NULL; } winList[wIx] = new GDLWINStream(xSize, ySize); // no pause on win destruction winList[wIx]->spause(false); // extended fonts winList[wIx]->fontld(1); // we want color winList[wIx]->scolor(1); PLINT r[ctSize], g[ctSize], b[ctSize]; actCT.Get(r, g, b); winList[wIx]->SetColorMap0(r, g, b, ctSize); //set colormap 0 to 256 values // need to be called initially. permit to fix things winList[wIx]->ssub(1, 1); winList[wIx]->adv(0); // load font winList[wIx]->font(1); winList[wIx]->vpor(0, 1, 0, 1); winList[wIx]->wind(0, 1, 0, 1); winList[wIx]->DefaultCharSize(); //in case these are not initalized, here is a good place to do it. if (winList[wIx]->updatePageInfo() == true) { winList[wIx]->GetPlplotDefaultCharSize(); //initializes everything in fact.. } // sets actWin and updates !D SetActWin(wIx); return true; //winList[ wIx]->Valid(); // Valid() need to called once } // GUIOpen #endif bool DeviceWIN::WOpen(int wIx, const std::string& title, int xSize, int ySize, int xPos, int yPos, bool hide) { TidyWindowsList(); int wLSize = winList.size(); if (wIx >= wLSize || wIx < 0) return false; if (winList[wIx] != NULL) { delete winList[wIx]; winList[wIx] = NULL; } DLongGDL* pMulti = SysVar::GetPMulti(); DLong nx = (*pMulti)[1]; DLong ny = (*pMulti)[2]; if (nx <= 0) nx = 1; if (ny <= 0) ny = 1; winList[wIx] = new GDLWINStream(nx, ny); // as wxwidgets never set this, they can be intermixed oList[wIx] = oIx++; // set initial window size PLFLT xp; PLFLT yp; PLINT xleng; PLINT yleng; PLINT xoff; PLINT yoff; winList[wIx]->plstream::gpage(xp, yp, xleng, yleng, xoff, yoff); DLong xMaxSize, yMaxSize; //DeviceWIN::MaxXYSize(&xMaxSize, &yMaxSize); RECT rt; SystemParametersInfo(SPI_GETWORKAREA, 0, &rt, 0); xMaxSize = rt.right; yMaxSize = rt.bottom; bool noPosx = (xPos == -1); bool noPosy = (yPos == -1); xPos = max(1, xPos); //starts at 1 to avoid problems plplot! yPos = max(1, yPos); xleng = min(xSize, xMaxSize); yleng = min(ySize, yMaxSize); rt.left = 0; rt.top = 0; rt.right = xleng; rt.bottom = yleng; AdjustWindowRect(&rt, WS_OVERLAPPEDWINDOW, false); xleng = rt.right - rt.left; yleng = rt.bottom - rt.top; if (xPos + xleng > xMaxSize) xPos = xMaxSize - xleng - 1; if (yPos + yleng > yMaxSize) yPos = yMaxSize - yleng - 1; // dynamic allocation needed! PLINT Quadx[4] = { xMaxSize - xleng - 1, xMaxSize - xleng - 1, 1, 1 }; PLINT Quady[4] = { 1, yMaxSize - yleng - 1, 1, yMaxSize - yleng - 1 }; if (noPosx && noPosy) { //no init given, use 4 quadrants: xoff = Quadx[wIx % 4]; yoff = Quady[wIx % 4]; } else if (noPosx) { xoff = Quadx[wIx % 4]; yoff = yMaxSize - yPos - yleng; } else if (noPosy) { xoff = xPos; yoff = Quady[wIx % 4]; } else { xoff = xPos; yoff = yMaxSize - yPos - yleng; } winList[wIx]->spage(xp, yp, xleng, yleng, xoff, yoff); // no pause on win destruction winList[wIx]->spause(false); // extended fonts winList[wIx]->fontld(1); // we want color winList[wIx]->scolor(1); // window title static char buf[256]; strncpy(buf, title.c_str(), 255); buf[255] = 0; winList[wIx]->setopt("plwindow", buf); // we want color (and the driver options need to be overwritten) // winList[ wIx]->setopt( "drvopt","color=1"); // ---- alternate setopt in devicex.hpp // set color map PLINT r[256], g[256], b[256]; actCT.Get(r, g, b); // winList[ wIx]->scmap0( r, g, b, actCT.size()); winList[wIx]->SetColorMap1(r, g, b, ctSize); winList[wIx]->Init(); // need to be called initially. permit to fix things winList[wIx]->ssub(1, 1); winList[wIx]->adv(0); // load font winList[wIx]->font(1); winList[wIx]->vpor(0, 1, 0, 1); winList[wIx]->wind(0, 1, 0, 1); winList[wIx]->DefaultCharSize(); //in case these are not initalized, here is a good place to do it. if (winList[wIx]->updatePageInfo() == true) { winList[wIx]->GetPlplotDefaultCharSize(); //initializes everything in fact.. } // sets actWin and updates !D SetActWin(wIx); // Currently Plplot ignores to update window title on Windows. it should be done manually.. ((GDLWINStream *)winList[wIx])->SetWindowTitle(buf); // HACK: setup hook for redrawing/validating windows p_this = this; if (!hHook[0]) hHook[0] = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)_CallWndProc, NULL, GetCurrentThreadId()); if (!hHook[1]) hHook[1] = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)_GetMsgProc, NULL, GetCurrentThreadId()); // HACK end return true; //winList[ wIx]->Valid(); // Valid() need to called once } bool DeviceWIN::WState(int wIx) { return wIx >= 0 && wIx < oList.size() && oList[wIx] != 0; } bool DeviceWIN::WSize(int wIx, int *xSize, int *ySize) { TidyWindowsList(); int wLSize = winList.size(); if (wIx > wLSize || wIx < 0) return false; long xleng, yleng; winList[wIx]->GetGeometry(xleng, yleng); *xSize = xleng; *ySize = yleng; return true; } bool DeviceWIN::WSet(int wIx) { TidyWindowsList(); int wLSize = winList.size(); if (wIx >= wLSize || wIx < 0 || winList[wIx] == NULL) return false; SetActWin(wIx); return true; } bool DeviceWIN::WShow(int ix, bool show, int iconic) { TidyWindowsList(); int wLSize = winList.size(); if (ix >= wLSize || ix < 0 || winList[ix] == NULL) return false; if (iconic!=-1) { //iconic asked. do nothing else. if (iconic==1) winList[ix]->Iconic(); else winList[ix]->DeIconic(); return true; } if (show) winList[ix]->Raise(); else winList[ix]->Lower(); UnsetFocus(); return true; } int DeviceWIN::WAdd() { TidyWindowsList(); int wLSize = winList.size(); for (int i = 0; i < wLSize; i++) if (winList[i] == NULL) return i; // plplot allows only 101 windows if (wLSize == 101) return -1; winList.push_back(NULL); oList.push_back(0); return wLSize; } DLongGDL* DeviceWIN::GetScreenSize(char *disp) { DLong xsize, ysize; MaxXYSize(&xsize, &ysize); DLongGDL* res; res = new DLongGDL(2, BaseGDL::NOZERO); (*res)[0] = xsize; (*res)[1] = ysize; return res; } DDoubleGDL* DeviceWIN::GetScreenResolution(char* disp) { HDC hscreenDC = GetWindowDC(GetDesktopWindow()); int screen_width, screen_height; int screen_width_mm, screen_height_mm; screen_width = GetDeviceCaps(hscreenDC, HORZRES); screen_width_mm = GetDeviceCaps(hscreenDC, HORZSIZE); screen_height = GetDeviceCaps(hscreenDC, VERTRES); screen_height_mm = GetDeviceCaps(hscreenDC, VERTSIZE); ReleaseDC(GetDesktopWindow(), hscreenDC); DDoubleGDL* resolution; resolution = new DDoubleGDL(2, BaseGDL::NOZERO); (*resolution)[0] = (screen_width_mm / 10.) / screen_width; (*resolution)[1] = (screen_height_mm / 10.) / screen_height; return resolution; } DIntGDL* DeviceWIN::GetWindowPosition() { TidyWindowsList(); this->GetStream(); //to open a window if none opened. long xpos, ypos; if (winList[actWin]->GetWindowPosition(xpos, ypos)) { DIntGDL* res; res = new DIntGDL(2, BaseGDL::NOZERO); (*res)[0] = xpos; (*res)[1] = ypos; return res; } else return NULL; } DLong DeviceWIN::GetVisualDepth() { TidyWindowsList(); this->GetStream(); //to open a window if none opened. return winList[actWin]->GetVisualDepth(); } DString DeviceWIN::GetVisualName() { TidyWindowsList(); this->GetStream(); //to open a window if none opened. return winList[actWin]->GetVisualName(); } //This function is reserved to device Z, should not exist for WIN! //DLong DeviceWIN::GetPixelDepth() //{ // HDC hscreenDC = GetWindowDC(GetDesktopWindow()); // int bitsperpixel = GetDeviceCaps(hscreenDC, BITSPIXEL); // ReleaseDC(NULL, hscreenDC); // return bitsperpixel; //} DByteGDL* DeviceWIN::WindowState() { int maxwin = MaxWin(); if (maxwin > 0){ DByteGDL* ret = new DByteGDL(dimension(maxwin), BaseGDL::NOZERO); for (int i = 0; i < maxwin; i++) (*ret)[i] = WState(i); return ret; } else return NULL; } bool DeviceWIN::UnsetFocus() { if (actWin == -1) { return false; } return winList[actWin]->UnsetFocus(); } int DeviceWIN::MaxWin() { TidyWindowsList(); return winList.size(); } int DeviceWIN::ActWin() { TidyWindowsList(); return actWin; } void DeviceWIN::DefaultXYSize(DLong *xSize, DLong *ySize) { *xSize = 680; *ySize = 480; DLong XS, YS; MaxXYSize(&XS, &YS); *ySize = YS / 2; *xSize = XS / 2; if (*xSize > 1.5*(*ySize)) *xSize = floor(float(*ySize)*.1375) * 10; bool noQscreen = true; string gdlQscreen = GetEnvString("GDL_GR_WIN_QSCREEN"); if (gdlQscreen == "1") noQscreen = false; string gdlXsize = GetEnvString("GDL_GR_WIN_WIDTH"); if (gdlXsize != "" && noQscreen) *xSize = atoi(gdlXsize.c_str()); string gdlYsize = GetEnvString("GDL_GR_WIN_HEIGHT"); if (gdlYsize != "" && noQscreen) *ySize = atoi(gdlYsize.c_str()); return; } void DeviceWIN::MaxXYSize(DLong *xSize, DLong *ySize) { *xSize = GetSystemMetrics(SM_CXSCREEN); *ySize = GetSystemMetrics(SM_CYSCREEN); } void DeviceWIN::TidyWindowsList() { int wLSize = winList.size(); for (int i = 0; i < wLSize; i++) { if (winList[i] != NULL && !winList[i]->GetValid()) { delete winList[i]; winList[i] = NULL; oList[i] = 0; } } // set new actWin IF NOT VALID ANY MORE if (actWin < 0 || actWin >= wLSize || winList[actWin] == NULL || !winList[actWin]->GetValid()) { // set to most recently created std::vector< long>::iterator mEl = std::max_element(oList.begin(), oList.end()); // no window open if (*mEl == 0) { SetActWin(-1); oIx = 1; if (hHook[0]) { UnhookWindowsHookEx(hHook[0]); hHook[0] = 0; } if (hHook[1]) { UnhookWindowsHookEx(hHook[1]); hHook[1] = 0; } } else { SetActWin(std::distance(oList.begin(), mEl)); } } } #endif gdl-0.9.9/src/devicewin.hpp000066400000000000000000000133121340051421000155420ustar00rootroot00000000000000/* ************************************************************************* devicewin.hpp - M$ windows device ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICEWIN_HPP_ #define DEVICEWIN_HPP_ #ifdef _WIN32 #include #include #include #include #include "graphicsdevice.hpp" #include "datatypes.hpp" #include "initsysvar.hpp" #include "gdlexception.hpp" //defined in graphicsdevice.hpp //#define MAX_WIN 32 //IDL free and widgets start at 33 ... //#define MAX_WIN_RESERVE 256 class DeviceWIN : public GraphicsDevice { private: static LRESULT CALLBACK _CallWndProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CallWndProc(int nCode, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK _GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam); std::vector winList; std::vector oList; long oIx; int actWin; int decomposed; // false -> use color table int cursorId; //should be 3 by default. long gcFunction; int backingStoreMode; void EventHandler(); bool WDelete(int); bool WOpen(int, const std::string&, int, int, int, int, bool); bool WState(int); bool WSize(int, int*, int*); bool WSet(int); bool WShow(int, bool, int); int WAdd(); DIntGDL* GetWindowPosition(); DLong GetVisualDepth(); DString GetVisualName(); //This function is reserved to device Z, should not exist for WIN! // DLong GetPixelDepth(); DByteGDL* WindowState(); bool UnsetFocus(); int MaxWin(); int ActWin(); void DefaultXYSize(DLong *xSize, DLong *ySize); void MaxXYSize(DLong *xSize, DLong *ySize); DLongGDL* GetScreenSize(char* disp = NULL); DDoubleGDL* GetScreenResolution(char* disp = NULL); void SetActWin(int wIx) { // update !D if (wIx >= 0 && wIx < winList.size()) { // window size and pos long xsize, ysize; winList[wIx]->GetGeometry(xsize, ysize); (*static_cast(dStruct->GetTag(xSTag)))[0] = xsize; (*static_cast(dStruct->GetTag(ySTag)))[0] = ysize; (*static_cast(dStruct->GetTag(xVSTag)))[0] = xsize; (*static_cast(dStruct->GetTag(yVSTag)))[0] = ysize; winList[wIx]->CheckValid(); // runs an IsWindow(hwnd) check } // window number (*static_cast(dStruct->GetTag(wTag)))[0] = wIx; actWin = wIx; } // process user deleted windows void TidyWindowsList(); public: DeviceWIN() : GraphicsDevice(), oIx(1), actWin(-1), decomposed(-1) { name = "WIN"; DLongGDL origin(dimension(2)); DLongGDL zoom(dimension(2)); zoom[0] = 1; zoom[1] = 1; dStruct = new DStructGDL("!DEVICE"); dStruct->InitTag("NAME", DStringGDL(name)); dStruct->InitTag("X_SIZE", DLongGDL(640)); dStruct->InitTag("Y_SIZE", DLongGDL(512)); dStruct->InitTag("X_VSIZE", DLongGDL(640)); dStruct->InitTag("Y_VSIZE", DLongGDL(512)); dStruct->InitTag("X_CH_SIZE", DLongGDL(9)); dStruct->InitTag("Y_CH_SIZE", DLongGDL(12)); dStruct->InitTag("X_PX_CM", DFloatGDL(40.0)); dStruct->InitTag("Y_PX_CM", DFloatGDL(40.0)); dStruct->InitTag("N_COLORS", DLongGDL(256)); dStruct->InitTag("TABLE_SIZE", DLongGDL(ctSize)); dStruct->InitTag("FILL_DIST", DLongGDL(0)); dStruct->InitTag("WINDOW", DLongGDL(-1)); dStruct->InitTag("UNIT", DLongGDL(0)); dStruct->InitTag("FLAGS", DLongGDL(328124)); dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); winList.reserve(MAX_WIN_RESERVE); winList.resize(MAX_WIN); for (int i = 0; i < MAX_WIN; i++) winList[i] = NULL; oList.reserve(MAX_WIN_RESERVE); oList.resize(MAX_WIN); for (int i = 0; i < MAX_WIN; i++) oList[i] = 0; } ~DeviceWIN() { std::vector::iterator i; for (i = winList.begin(); i != winList.end(); ++i) { delete *i; /* *i = NULL;*/ } } GDLGStream* GetStreamAt(int wIx) const { return winList[wIx]; } // should check for valid streams GDLGStream* GetStream(bool open = true) { TidyWindowsList(); if (actWin == -1) { if (!open) return NULL; DString title = "GDL 0"; DLong xSize, ySize; DefaultXYSize(&xSize, &ySize); bool success = WOpen(0, title, xSize, ySize, -1, -1, false); if (!success) return NULL; if (actWin == -1) { std::cerr << "Internal error: plstream not set." << std::endl; exit(EXIT_FAILURE); } } return winList[actWin]; } #ifdef HAVE_LIBWXWIDGETS bool GUIOpen(int wIx, int xSize, int ySize); #endif bool Decomposed(bool value) { decomposed = value; return true; } void RaiseWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->Raise(); } void LowerWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->Lower(); } void IconicWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->Iconic(); } void DeIconicWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->DeIconic(); } }; //#undef MAX_WIN //#undef MAX_WIN_RESERVE #endif #endif gdl-0.9.9/src/devicewx.hpp000066400000000000000000000316361340051421000154140ustar00rootroot00000000000000/* ************************************************************************* devicewx.hpp - WXwidgets device ------------------- begin : Sep 19 2014 author : Jeongbin Park email : pjb7687@snu.ac.kr ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICEWX_HPP_ #define DEVICEWX_HPP_ #ifndef HAVE_LIBWXWIDGETS #else #include #include #include #include #include "graphicsdevice.hpp" #include "gdlwxstream.hpp" #include #include #include "initsysvar.hpp" #include "gdlexception.hpp" //#define MAX_WIN 32 //IDL free and widgets start at 32 ... //#define MAX_WIN_RESERVE 256 class DeviceWX : public GraphicsMultiDevice { public: DeviceWX(string name_="MAC") : GraphicsMultiDevice( 1, 3, 3, 0) { //force decomposed=true until we find a better way (::wxDispayDepth() crashes) name = name_; //temporary hack to avoid coyoteGraphics crash in ATV.PRO DLongGDL origin(dimension(2)); DLongGDL zoom(dimension(2)); zoom[0] = 1; zoom[1] = 1; dStruct = new DStructGDL("!DEVICE"); dStruct->InitTag("NAME", DStringGDL(name)); dStruct->InitTag("X_SIZE", DLongGDL(640)); dStruct->InitTag("Y_SIZE", DLongGDL(512)); dStruct->InitTag("X_VSIZE", DLongGDL(640)); dStruct->InitTag("Y_VSIZE", DLongGDL(512)); dStruct->InitTag("X_CH_SIZE", DLongGDL(6)); dStruct->InitTag("Y_CH_SIZE", DLongGDL(9)); dStruct->InitTag("X_PX_CM", DFloatGDL(40.0)); dStruct->InitTag("Y_PX_CM", DFloatGDL(40.0)); dStruct->InitTag("N_COLORS", DLongGDL( (decomposed==1)?256*256*256:256)); dStruct->InitTag("TABLE_SIZE", DLongGDL(ctSize)); dStruct->InitTag("FILL_DIST", DLongGDL(1)); dStruct->InitTag("WINDOW", DLongGDL(-1)); dStruct->InitTag("UNIT", DLongGDL(0)); dStruct->InitTag("FLAGS", DLongGDL(328124)); dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); } bool WOpen(int wIx, const std::string& title, int xSize, int ySize, int xPos, int yPos, bool hide = false) { if (wIx >= winList.size() || wIx < 0) return false; if (winList[ wIx] != NULL) winList[ wIx]->SetValid(false); TidyWindowsList(); // set initial window size int xleng; int yleng; int xoff; int yoff; DLong xMaxSize, yMaxSize; DeviceWX::MaxXYSize(&xMaxSize, &yMaxSize); bool noPosx = (xPos == -1); bool noPosy = (yPos == -1); xPos = max(1, xPos); //starts at 1 to avoid problems plplot! yPos = max(1, yPos); xleng = min(xSize, xMaxSize); if (xPos + xleng > xMaxSize) xPos = xMaxSize - xleng - 1; yleng = min(ySize, yMaxSize); if (yPos + yleng > yMaxSize) yPos = yMaxSize - yleng - 1; // dynamic allocation needed! PLINT Quadx[4] = {xMaxSize - xleng - 1, xMaxSize - xleng - 1, 1, 1}; PLINT Quady[4] = {1, yMaxSize - yleng - 1, 1, yMaxSize - yleng - 1}; if (noPosx && noPosy) { //no init given, use 4 quadrants: xoff = Quadx[wIx % 4]; yoff = Quady[wIx % 4]; } else if (noPosx) { xoff = Quadx[wIx % 4]; yoff = yMaxSize - yPos - yleng; } else if (noPosy) { xoff = xPos; yoff = Quady[wIx % 4]; } else { xoff = xPos; yoff = yMaxSize - yPos - yleng; } WidgetIDT mbarID = 0; GDLWidgetGraphicWindowBase* base = new GDLWidgetGraphicWindowBase(mbarID, xoff, yoff, title); GDLWidgetDraw* draw = new GDLWidgetDraw(base->WidgetID(), NULL, wIx, xleng, yleng, -1, -1, false, 0); base->setWindow(static_cast(draw->GetWxWidget())); base->Realize(!hide); //just avoid to map the widget. if(hide) winList[ wIx]->UnMapWindow(); //needed: will set the "pixmap" property // else { winList[ wIx]->UnsetFocus(); winList[wIx]->Raise();} return true; } // should check for valid streams GDLGStream* GetStream(bool open = true) { TidyWindowsList(); if (actWin == -1) { if (!open) return NULL; DString title = "GDL 0"; DLong xSize, ySize; DefaultXYSize(&xSize, &ySize); bool success = WOpen(0, title, xSize, ySize, -1, -1, false); if (!success) return NULL; if (actWin == -1) { std::cerr << "Internal error: plstream not set." << std::endl; exit(EXIT_FAILURE); } } return winList[actWin]; } bool SetGraphicsFunction(DLong value) { gcFunction = max(0, min(value, 15)); this->GetStream(); //to open a window if none opened. bool ret=false; for (int i = 0; i < winList.size(); i++) { if (winList[i] != NULL) { ret = winList[i]->SetGraphicsFunction(gcFunction); if (ret == false) return ret; } } return true; } DLong GetGraphicsFunction() { this->GetStream(); //to open a window if none opened. return gcFunction; } DLongGDL* GetScreenSize(char* disp) { DLongGDL* res; res = new DLongGDL(2, BaseGDL::NOZERO); (*res)[0] = wxSystemSettings::GetMetric(wxSYS_SCREEN_X); (*res)[1] = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y); return res; } DDoubleGDL* GetScreenResolution(char* disp) { this->GetStream(); //to open a window if none opened. double resx, resy; if (winList[actWin]->GetScreenResolution(resx, resy)) { DDoubleGDL* res; res = new DDoubleGDL(2, BaseGDL::NOZERO); (*res)[0] = resx; (*res)[1] = resy; return res; } else return NULL; } DIntGDL* GetWindowPosition() { this->GetStream(); //to open a window if none opened. long xpos, ypos; if (winList[actWin]->GetWindowPosition(xpos, ypos)) { DIntGDL* res; res = new DIntGDL(2, BaseGDL::NOZERO); (*res)[0] = xpos; (*res)[1] = ypos; return res; } else return NULL; } // DLong GetVisualDepth() { // this->GetStream(); //to open a window if none opened. // return winList[actWin]->GetVisualDepth(); // } // // DString GetVisualName() { // this->GetStream(); //to open a window if none opened. // return winList[actWin]->GetVisualName(); // } // BaseGDL* GetFontnames(){ // this->GetStream(); //to open a window if none opened. // return winList[actWin]->GetFontnames(fontname); // } // DLong GetFontnum(){ // this->GetStream(); //to open a window if none opened. // return winList[actWin]->GetFontnum(fontname); // } DLong GetVisualDepth() { TidyWindowsList(); if (actWin == -1) { this->GetStream(true); //this command SHOULD NOT open a window if none opened, but how to do it? DLong val=winList[actWin]->GetVisualDepth(); WDelete(actWin); return val; } else { return winList[actWin]->GetVisualDepth(); } } DString GetVisualName() { TidyWindowsList(); if (actWin == -1) { this->GetStream(true); //this command SHOULD NOT open a window if none opened, but how to do it? DString val=winList[actWin]->GetVisualName(); WDelete(actWin); return val; } else { return winList[actWin]->GetVisualName(); } } BaseGDL* GetFontnames(){ TidyWindowsList(); if (actWin == -1) { this->GetStream(); BaseGDL* val=winList[actWin]->GetFontnames(fontname); return val; } else { return winList[actWin]->GetFontnames(fontname); } } DLong GetFontnum(){ TidyWindowsList(); if (actWin == -1) { this->GetStream(); DLong val=winList[actWin]->GetFontnum(fontname); return val; } else { return winList[actWin]->GetFontnum(fontname); } } bool CursorStandard(int cursorNumber) { cursorId = cursorNumber; this->GetStream(); //to open a window if none opened. bool ret; for (int i = 0; i < winList.size(); i++) { if (winList[i] != NULL) { ret = winList[i]->CursorStandard(cursorNumber); if (ret == false) return ret; } } return true; } bool CursorCrosshair() { return CursorStandard(33); } void DefaultXYSize(DLong *xSize, DLong *ySize) { *xSize = wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2; *ySize = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2; bool noQscreen = true; string gdlQscreen = GetEnvString("GDL_GR_X_QSCREEN"); if (gdlQscreen == "1") noQscreen = false; string gdlXsize = GetEnvString("GDL_GR_X_WIDTH"); if (gdlXsize != "" && noQscreen) *xSize = atoi(gdlXsize.c_str()); string gdlYsize = GetEnvString("GDL_GR_X_HEIGHT"); if (gdlYsize != "" && noQscreen) *ySize = atoi(gdlYsize.c_str()); } void MaxXYSize(DLong *xSize, DLong *ySize) { *xSize = wxSystemSettings::GetMetric(wxSYS_SCREEN_X); *ySize = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y); } bool GUIOpen( int wIx, int xSize, int ySize)//, int xPos, int yPos) { if( wIx >= winList.size() || wIx < 0) return false; if( winList[ wIx] != NULL) winList[ wIx]->SetValid(false); TidyWindowsList(); winList[ wIx] = new GDLWXStream( xSize, ySize); oList[ wIx] = oIx++; winList[ wIx]->SetCurrentFont(fontname); // sets actWin and updates !D SetActWin( wIx); return true; } // GUIOpen bool SetCharacterSize( DLong x, DLong y) { DStructGDL* dStruct=SysVar::D(); int tagx = dStruct->Desc()->TagIndex( "X_CH_SIZE"); int tagy = dStruct->Desc()->TagIndex( "Y_CH_SIZE"); DLongGDL* newxch = static_cast( dStruct->GetTag( tagx)); DLongGDL* newych = static_cast( dStruct->GetTag( tagy)); (*newxch)[0]=x; (*newych)[0]=y; int tagxppcm = dStruct->Desc()->TagIndex( "X_PX_CM"); int tagyppcm = dStruct->Desc()->TagIndex( "Y_PX_CM"); DFloat xppm = (*static_cast(dStruct->GetTag(tagxppcm)))[0]*0.1; DFloat yppm = (*static_cast(dStruct->GetTag(tagyppcm)))[0]*0.1; PLFLT newsize=x/xppm/1.5; //1.5 is probably due to height / width ratio . PLFLT newSpacing=y/yppm; GDLGStream* actStream=GetStream(false); if( actStream != NULL) {actStream->setLineSpacing(newSpacing); actStream->RenewPlplotDefaultCharsize(newsize);} return true; } //Please find how to specialize TidyWindowsList for wx and x11 widgets when this function is called //as GraphicsDevice::GetDevice()->TidyWindowsList(); which does not return a specialized version. // Util then, do not uncomment the following. // void TidyWindowsList() { // int wLSize = winList.size(); // for (int i = 0; i < wLSize; i++) if (winList[i] != NULL && !winList[i]->GetValid()) { // if (dynamic_cast (winList[i]) != NULL) { // GDLDrawPanel* panel = NULL; // panel = dynamic_cast (static_cast (winList[i])->GetGDLDrawPanel()); // //test if stream is associated to graphic window or widget_draw. If graphic, destroy directly TLB widget. // GDLWidgetDraw *draw = panel->GetGDLWidgetDraw(); // if (draw) { // //parent of panel may be a GDLFrame. If frame is actually made by the WOpen function, destroy everything. // GDLWidgetBase* container = NULL; // container = static_cast (draw->GetTopLevelBaseWidget(draw->WidgetID())); // if (container && container->IsGraphicWindowFrame()) container->SelfDestroy(); // else delete draw; // } else delete winList[i]; // } else delete winList[i]; // winList[i] = NULL; // oList[i] = 0; // } // // set new actWin IF NOT VALID ANY MORE // if (actWin < 0 || actWin >= wLSize || winList[actWin] == NULL || !winList[actWin]->GetValid()) { // // set to most recently created // std::vector< long>::iterator mEl = std::max_element(oList.begin(), oList.end()); // if (*mEl == 0) { // no window open // SetActWin(-1); //sets oIx = 1; // } else SetActWin(GraphicsDevice::GetDevice()->GetNonManagedWidgetActWin(false)); //get first non-managed window. false is needed. // } // } }; #endif #endif gdl-0.9.9/src/devicex.hpp000066400000000000000000000346641340051421000152310ustar00rootroot00000000000000/* ************************************************************************* devicex.hpp - X windows device ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICEX_HPP_ #define DEVICEX_HPP_ #ifndef HAVE_X #else #include #include #include #include #include "graphicsdevice.hpp" #include "gdlxstream.hpp" #include "initsysvar.hpp" #include "gdlexception.hpp" //defined in graphicsdevice.hpp //#define MAX_WIN 32 //IDL free and widgets start at 32 ... //#define MAX_WIN_RESERVE 256 class DeviceX : public GraphicsMultiDevice { public: DeviceX() : GraphicsMultiDevice( -1, XC_crosshair, 3, 0) { name = "X"; DLongGDL origin(dimension(2)); DLongGDL zoom(dimension(2)); zoom[0] = 1; zoom[1] = 1; Display* display = XOpenDisplay(NULL); if (display != NULL) { int Depth; Depth=DefaultDepth(display, DefaultScreen(display)); decomposed = (Depth >= 15 ? 1 : 0); } else { //try ":0" //IDL also opens :0 when DISPLAY is not set. display = XOpenDisplay(":0"); if (display != NULL) { int Depth; Depth=DefaultDepth(display, DefaultScreen(display)); decomposed = (Depth >= 15 ? 1 : 0); } } if (display != NULL) { Visual *visual=DefaultVisual( display, DefaultScreen(display) ); switch ( visual->c_class ) { case TrueColor: case StaticColor: case StaticGray: staticDisplay=1; break; //ok, are static default: //dynamic: problems if cmaps not initialized. staticDisplay=0; } } else { staticDisplay=0; } dStruct = new DStructGDL("!DEVICE"); dStruct->InitTag("NAME", DStringGDL(name)); dStruct->InitTag("X_SIZE", DLongGDL(640)); dStruct->InitTag("Y_SIZE", DLongGDL(512)); dStruct->InitTag("X_VSIZE", DLongGDL(640)); dStruct->InitTag("Y_VSIZE", DLongGDL(512)); dStruct->InitTag("X_CH_SIZE", DLongGDL(6)); dStruct->InitTag("Y_CH_SIZE", DLongGDL(9)); dStruct->InitTag("X_PX_CM", DFloatGDL(40.0)); dStruct->InitTag("Y_PX_CM", DFloatGDL(40.0)); dStruct->InitTag("N_COLORS", DLongGDL( (decomposed==1)?256*256*256:256)); dStruct->InitTag("TABLE_SIZE", DLongGDL(ctSize)); dStruct->InitTag("FILL_DIST", DLongGDL(1)); dStruct->InitTag("WINDOW", DLongGDL(-1)); dStruct->InitTag("UNIT", DLongGDL(0)); dStruct->InitTag("FLAGS", DLongGDL(328124)); dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); } bool WOpen( int wIx, const std::string& title, int xSize, int ySize, int xPos, int yPos, bool hide=false) { if( wIx >= winList.size() || wIx < 0) return false; if( winList[ wIx] != NULL) winList[ wIx]->SetValid(false); TidyWindowsList(); // set initial window size PLFLT xp; PLFLT yp; PLINT xleng; PLINT yleng; PLINT xoff; PLINT yoff; DLong xMaxSize, yMaxSize; DeviceX::MaxXYSize(&xMaxSize, &yMaxSize); bool noPosx=(xPos==-1); bool noPosy=(yPos==-1); xPos=max(1,xPos); //starts at 1 to avoid problems plplot! yPos=max(1,yPos); xleng = min(xSize,xMaxSize); if (xPos+xleng > xMaxSize) xPos=xMaxSize-xleng-1; yleng = min(ySize,yMaxSize); if (yPos+yleng > yMaxSize) yPos=yMaxSize-yleng-1; // dynamic allocation needed! PLINT Quadx[4]={xMaxSize-xleng-1,xMaxSize-xleng-1,1,1}; PLINT Quady[4]={1,yMaxSize-yleng-1,1,yMaxSize-yleng-1}; if (noPosx && noPosy) { //no init given, use 4 quadrants: xoff = Quadx[wIx%4]; yoff = Quady[wIx%4]; } else if (noPosx) { xoff = Quadx[wIx%4]; yoff = yMaxSize-yPos-yleng; } else if (noPosy) { xoff = xPos; yoff = Quady[wIx%4]; } else { xoff = xPos; yoff = yMaxSize-yPos-yleng; } //apparently this is OK to get same results as IDL on X11... yoff+=1; xp=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("X_PX_CM"))))[0]*2.5; yp=(*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("Y_PX_CM"))))[0]*2.5; winList[ wIx] = new GDLXStream( xleng, yleng); oList[ wIx] = oIx++; winList[ wIx]->spage( xp , yp, xleng, yleng, xoff, yoff); //must be before 'Init' // no pause on win destruction winList[ wIx]->spause( false); // extended fonts winList[ wIx]->fontld( 1); // we want color winList[ wIx]->scolor( 1); //if plplot uses a non-staticColor device [TrueColor, StaticColor, StaticGray] //(because it does not ask for a static even if it exists), we must initialize here colormaps //otherwise our direct X11 color commands work well and are faster than plplot's. if (!this->isStatic()){ PLINT r[ctSize], g[ctSize], b[ctSize]; GDLCT* myCT=GraphicsDevice::GetGUIDevice( )->GetCT(); myCT->Get( r, g, b); winList[ wIx]->scmap0( r, g, b, ctSize); //set colormap 0 to 256 values } // window title static char buf[ 256]; strncpy( buf, title.c_str(), 255); buf[ 255] = 0; // winList[ wIx]->setopt( "db", 0); //handled elsewhere // winList[ wIx]->setopt( "debug", "1"); //useful for debugging plplot! winList[ wIx]->setopt( "plwindow", buf); // Do not init colors --- we handle colors ourseves, very much faster! winList[ wIx]->setopt( "drvopt","noinitcolors=1"); // Please no threads, no gain especially in remote X11 winList[ wIx]->setopt( "drvopt","usepth=0"); //all the options must be passed BEFORE INIT=plinit. winList[ wIx]->Init(); // get actual size, and resize to it (overcomes some window managers problems, solves bug #535) // bug #535 had other causes. removed until further notice. // bool success = WSize( wIx ,&xleng, &yleng, &xoff, &yoff); // ResizeWin((UInt)xleng, (UInt) yleng); // need to be called initially. permit to fix things winList[ wIx]->ssub(1,1); winList[ wIx]->adv(0); // load font winList[ wIx]->font( 1); winList[ wIx]->vpor(0,1,0,1); winList[ wIx]->wind(0,1,0,1); winList[ wIx]->DefaultCharSize(); // //in case these are not initalized, here is a good place to do it. // if (winList[ wIx]->updatePageInfo()==true) // { // winList[ wIx]->GetPlplotDefaultCharSize(); //initializes everything in fact.. // } // sets actWin and updates !D SetActWin( wIx); bool success; if ( hide ) { success=this->Hide(); } else success=this->UnsetFocus(); return true; //winList[ wIx]->Valid(); // Valid() need to called once } GDLGStream* GetStream(bool open = true) { TidyWindowsList(); if (actWin == -1) { if (!open) return NULL; DString title = "GDL 0"; DLong xSize, ySize; DefaultXYSize(&xSize, &ySize); bool success = WOpen(0, title, xSize, ySize, -1, -1, false); if (!success) return NULL; if (actWin == -1) { std::cerr << "Internal error: plstream not set." << std::endl; exit(EXIT_FAILURE); } } return winList[actWin]; } bool SetGraphicsFunction(DLong value) { gcFunction = max(0, min(value, 15)); this->GetStream(); //to open a window if none opened. bool ret=false; for (int i = 0; i < winList.size(); i++) { if (winList[i] != NULL) { ret = winList[i]->SetGraphicsFunction(gcFunction); if (ret == false) return ret; } } return true; } DLong GetGraphicsFunction() { this->GetStream(); //MUST open a window if none opened (even if it is not useful with GDL, this is to mimic IDL). return gcFunction; } DLongGDL* GetScreenSize(char* disp) { Display* display = XOpenDisplay(disp); int screen_num, screen_width, screen_height; DLongGDL* res; if (display == NULL) { screen_width = 0; screen_height = 0; } else { screen_num = DefaultScreen(display); screen_width = DisplayWidth(display, screen_num); screen_height = DisplayHeight(display, screen_num); XCloseDisplay(display); } res = new DLongGDL(2, BaseGDL::NOZERO); (*res)[0]= screen_width; (*res)[1]= screen_height; return res; } DDoubleGDL* GetScreenResolution(char* disp) { Display* display = XOpenDisplay(disp); if (display == NULL) ThrowGDLException("Cannot connect to X server: "+string(disp)); int screen_num, screen_width, screen_height; screen_num = DefaultScreen(display); screen_width = DisplayWidth(display, screen_num); screen_height = DisplayHeight(display, screen_num); int screen_width_mm; int screen_height_mm; screen_width_mm = DisplayWidthMM(display, screen_num); screen_height_mm = DisplayHeightMM(display, screen_num); XCloseDisplay(display); DDoubleGDL* resolution; resolution = new DDoubleGDL(2, BaseGDL::NOZERO); (*resolution)[0]=(screen_width_mm/10.)/screen_width; (*resolution)[1]=(screen_height_mm/10.)/screen_height; return resolution; } DIntGDL* GetWindowPosition() { this->GetStream(); //MUST open a window if none opened. long xpos, ypos; if (winList[actWin]->GetWindowPosition(xpos, ypos)) { DIntGDL* res; res = new DIntGDL(2, BaseGDL::NOZERO); (*res)[0] = xpos; (*res)[1] = ypos; return res; } else return NULL; } DLong GetVisualDepth() { TidyWindowsList(); if (actWin == -1) { this->GetStream(true); //this command SHOULD NOT open a window if none opened, but how to do it? DLong val=winList[actWin]->GetVisualDepth(); WDelete(actWin); return val; } else { return winList[actWin]->GetVisualDepth(); } } DString GetVisualName() { TidyWindowsList(); if (actWin == -1) { this->GetStream(true); //this command SHOULD NOT open a window if none opened, but how to do it? DString val=winList[actWin]->GetVisualName(); WDelete(actWin); return val; } else { return winList[actWin]->GetVisualName(); } } BaseGDL* GetFontnames(){ TidyWindowsList(); if (actWin == -1) { this->GetStream(); BaseGDL* val=winList[actWin]->GetFontnames(fontname); return val; } else { return winList[actWin]->GetFontnames(fontname); } } DLong GetFontnum(){ TidyWindowsList(); if (actWin == -1) { this->GetStream(); DLong val=winList[actWin]->GetFontnum(fontname); return val; } else { return winList[actWin]->GetFontnum(fontname); } } bool CursorStandard(int cursorNumber) { cursorId = cursorNumber; this->GetStream(); //to open a window if none opened. bool ret; for (int i = 0; i < winList.size(); i++) { if (winList[i] != NULL) { ret = winList[i]->CursorStandard(cursorNumber); if (ret == false) return ret; } } return true; } bool CursorCrosshair() { return CursorStandard(XC_crosshair); } void DefaultXYSize(DLong *xSize, DLong *ySize) { *xSize = 640; *ySize = 512; Display* display = XOpenDisplay(NULL); if (display != NULL) { *xSize = DisplayWidth(display, DefaultScreen(display)) / 2; *ySize = DisplayHeight(display, DefaultScreen(display)) / 2; XCloseDisplay(display); } bool noQscreen=true; string gdlQscreen=GetEnvString("GDL_GR_X_QSCREEN"); if( gdlQscreen == "1") noQscreen=false; string gdlXsize=GetEnvString("GDL_GR_X_WIDTH"); if( gdlXsize != "" && noQscreen ) *xSize=atoi(gdlXsize.c_str()); string gdlYsize=GetEnvString("GDL_GR_X_HEIGHT"); if( gdlYsize != "" && noQscreen) *ySize=atoi(gdlYsize.c_str()); } void MaxXYSize(DLong *xSize, DLong *ySize) { *ySize = 640; *ySize = 512; Display* display = XOpenDisplay(NULL); if (display != NULL) { *xSize = DisplayWidth(display, DefaultScreen(display)); *ySize = DisplayHeight(display, DefaultScreen(display)); XCloseDisplay(display); } } //Please find how to specialize TidyWindowsList for wx and x11 widgets when this function is called //as GraphicsDevice::GetDevice()->TidyWindowsList(); which does not return a specialized version. // Util then, do not uncomment the following. //void TidyWindowsList() { // int wLSize = winList.size(); // for (int i = 0; i < wLSize; i++) if (winList[i] != NULL && !winList[i]->GetValid()) { // // //general purpose winlist cleaning with destruction of "closed" plstreams and (eventually) associated widgets: // //X11 case only. For some bad programming reason, sometimes the parent classe (graphicmultidevice) version is // // used. // delete winList[i]; // winList[i] = NULL; // oList[i] = 0; // } // // set new actWin IF NOT VALID ANY MORE // if (actWin < 0 || actWin >= wLSize || winList[actWin] == NULL || !winList[actWin]->GetValid()) { // std::vector< long>::iterator mEl = std::max_element(oList.begin(), oList.end()); // set to most recently created // if (*mEl == 0) { // no window open // SetActWin(-1); //sets oIx = 1; // } else SetActWin(GraphicsDevice::GetDevice()->GetNonManagedWidgetActWin(false)); //get first non-managed window. false is needed. // } //} }; //#undef MAX_WIN //#undef MAX_WIN_RESERVE #endif #endif gdl-0.9.9/src/devicez.hpp000066400000000000000000000163741340051421000152310ustar00rootroot00000000000000/* ************************************************************************* devicez.hpp - Z-buffer device ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEVICEZ_HPP_ #define DEVICEZ_HPP_ //#include "dstructgdl.hpp" #include "gdlzstream.hpp" #if defined (_MSC_VER) && (_MSC_VER < 1800) /* replacement of Unix rint() for Windows */ static int rint (double x) { char *buf; int i,dec,sig; buf = _fcvt(x, 0, &dec, &sig); i = atoi(buf); if(sig == 1) { i = i * -1; } return(i); } #endif class DeviceZ: public GraphicsDevice { GDLZStream* actStream; char* memBuffer; DInt* zBuffer; int decomposed; void SetZBuffer( DLong x, DLong y) { delete[] zBuffer; zBuffer = new DInt[ x*y]; SizeT n = x*y; for( SizeT i=0; i( dStruct->GetTag( xSTag, 0)))[0]; DLong& actY = (*static_cast( dStruct->GetTag( ySTag, 0)))[0]; // always allocate the buffer with creating a new stream actStream = new GDLZStream( nx, ny); // here we allocate the memory // plplot frees this with 'free' // memBuffer = new char[ actX * actY * 3]; // memBuffer = (char*) malloc( sizeof( char) * actX * actY * 3); // plplot mem driver error, lines could be drawn upto actY (rather that // actY-1) memBuffer = (char*) calloc( sizeof( char), actX * (actY+1) * 3); // make it known to plplot plsmem( actX, actY, memBuffer); // no pause on destruction actStream->spause( false); // extended fonts actStream->fontld( 1); // we want color actStream->scolor( 1); // set color map (always grey ramp) PLINT r[ctSize], g[ctSize], b[ctSize]; for( PLINT i = 0; iSetColorMap0( r, g, b, ctSize); actStream->SetColorMap1( r, g, b, ctSize); actStream->setopt( "drvopt","text=0"); // clear drvopt actStream->Init(); // need to be called initially. permit to fix things actStream->ssub(1,1); actStream->adv(0); // load font actStream->font( 1); actStream->vpor(0,1,0,1); actStream->wind(0,1,0,1); actStream->DefaultCharSize(); // //in case these are not initalized, here is a good place to do it. // if (actStream->updatePageInfo()==true) // { // actStream->GetPlplotDefaultCharSize(); //initializes everything in fact.. // // } } public: DeviceZ(): GraphicsDevice(), actStream( NULL), memBuffer( NULL), zBuffer( NULL), decomposed(0) { name = "Z"; DLongGDL origin( dimension( 2)); DLongGDL zoom( dimension( 2)); zoom[0] = 1; zoom[1] = 1; dStruct = new DStructGDL( "!DEVICE"); dStruct->InitTag("NAME", DStringGDL( name)); dStruct->InitTag("X_SIZE", DLongGDL( 640)); dStruct->InitTag("Y_SIZE", DLongGDL( 480)); dStruct->InitTag("X_VSIZE", DLongGDL( 640)); dStruct->InitTag("Y_VSIZE", DLongGDL( 480)); dStruct->InitTag("X_CH_SIZE", DLongGDL( 8)); dStruct->InitTag("Y_CH_SIZE", DLongGDL( 12)); dStruct->InitTag("X_PX_CM", DFloatGDL( 26.0)); dStruct->InitTag("Y_PX_CM", DFloatGDL( 26.0)); dStruct->InitTag("N_COLORS", DLongGDL( 256)); //our default is 24bpp dStruct->InitTag("TABLE_SIZE", DLongGDL( 256)); dStruct->InitTag("FILL_DIST", DLongGDL( 1)); dStruct->InitTag("WINDOW", DLongGDL( -1)); dStruct->InitTag("UNIT", DLongGDL( 0)); dStruct->InitTag("FLAGS", DLongGDL( 414908)); dStruct->InitTag("ORIGIN", origin); dStruct->InitTag("ZOOM", zoom); } ~DeviceZ() { delete[] zBuffer; DeleteStream(); } GDLGStream* GetStream( bool open=true) { if( actStream == NULL) { if( !open) return NULL; InitStream(); } return actStream; } bool CloseFile() // CLOSE keyword { delete[] zBuffer; zBuffer = NULL; DeleteStream(); return true; } bool ZBuffering( bool yes) { if( !yes) { delete[] zBuffer; zBuffer = NULL; } else if( zBuffer == NULL) { DLong& actX = (*static_cast( dStruct->GetTag( xSTag, 0)))[0]; DLong& actY = (*static_cast( dStruct->GetTag( ySTag, 0)))[0]; SetZBuffer( actX, actY); } return true; } bool SetResolution( DLong nx, DLong ny) { DLong& actX = (*static_cast( dStruct->GetTag( xSTag, 0)))[0]; DLong& actY = (*static_cast( dStruct->GetTag( ySTag, 0)))[0]; if( nx == actX && ny == actY) return true; DeleteStream(); if( zBuffer != NULL) { SetZBuffer( nx, ny); } actX = nx; actY = ny; DLong& actXV = (*static_cast( dStruct->GetTag( xVSTag, 0)))[0]; DLong& actYV = (*static_cast( dStruct->GetTag( yVSTag, 0)))[0]; actXV = nx; actYV = ny; return true; } void ClearStream( DLong bColor) { DLong& actX = (*static_cast( dStruct->GetTag( xSTag, 0)))[0]; DLong& actY = (*static_cast( dStruct->GetTag( ySTag, 0)))[0]; for( SizeT i=0; i( dStruct->GetTag( xSTag, 0)))[0]; DLong& actY = (*static_cast( dStruct->GetTag( ySTag, 0)))[0]; SetZBuffer( actX, actY); return true; } bool Decomposed( bool value) { decomposed = value; // if (decomposed==1) (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("N_COLORS"))))[0]=256*256*256; // else (*static_cast( dStruct->GetTag(dStruct->Desc()->TagIndex("N_COLORS"))))[0]=256; return true; } DLong GetDecomposed() { return decomposed; } }; #endif gdl-0.9.9/src/dialog.cpp000066400000000000000000000421541340051421000150250ustar00rootroot00000000000000/*************************************************************************** dialog.cpp - GDL library function for dialogs ------------------- begin : 04 Apr 2015 Copyright : (C) 2015 by Jeongbin Park email : pjb7687@gmail.com ****************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifdef HAVE_LIBWXWIDGETS //following includes are 1) not necessary and 2) create a problem with gcc6 //#include //#include #endif #include "envt.hpp" #include "dialog.hpp" #include "file.hpp" #include "gdlwidget.hpp" using namespace std; namespace lib { #ifdef HAVE_LIBWXWIDGETS BaseGDL* wxwidgets_exists(EnvT* e) { return new DIntGDL(1); } BaseGDL* dialog_pickfile_wxwidgets(EnvT* e) { if (!GDLWidget::wxIsStarted()){ if( ! wxInitialize( ) ) e->Throw("Unable to initialize wxWidgets"); GDLWidget::SetWxStarted(); } /* results = DIALOG_PICKFILE_WXWIDGETS(DEFAULT_EXTENSION=default_extension, $ DIRECTORY=directory, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, FILE=file, FILTER=filter, $ FIX_FILTER=fix_filter, GET_PATH=get_path, GROUP=group, $ MULTIPLE_FILES=multiple_files, MUST_EXIST=must_exist, $ OVERWRITE_PROMPT=overwrite_prompt, PATH=path, $ READ=read, WRITE=write, RESOURCE_NAME=resource_name, $ TITLE=title) */ #ifdef HAVE_LOCALE_H setlocale(LC_ALL, "C"); #endif bool isdefault_extension = false; bool isdirectory = false; bool isdialog_parent = false; bool isdisplay_name = false; bool isfile = false; bool isfilter = false; bool isfix_filter = false; bool isgroup = false; bool ismultiple_files = false; bool ismust_exist = false; bool isoverwrite_prompt = false; bool ispath = false; bool isread = false; bool iswrite = false; bool isresource_name = false; bool istitle = false; static int default_extensionIx = e->KeywordIx("DEFAULT_EXTENSION"); // Partially implemented. See below for details. bool default_extensionKW = e->KeywordPresent(default_extensionIx); if (default_extensionKW) isdefault_extension = e->KeywordSet(default_extensionIx); static int directoryIx = e->KeywordIx("DIRECTORY"); bool directoryKW = e->KeywordPresent(directoryIx); if (directoryKW) isdirectory = e->KeywordSet(directoryIx); static int dialog_parentIx = e->KeywordIx("DIALOG_PARENT"); // Not tested bool dialog_parentKW = e->KeywordPresent(dialog_parentIx); if (dialog_parentKW) isdialog_parent = e->KeywordSet(dialog_parentIx); static int display_nameIx = e->KeywordIx("DISPLAY_NAME"); // Not implemented bool display_nameKW = e->KeywordPresent(display_nameIx); if (display_nameKW) isdisplay_name = e->KeywordSet(display_nameIx); static int fileIx = e->KeywordIx("FILE"); bool fileKW = e->KeywordPresent(fileIx); if (fileKW) isfile = e->KeywordSet(fileIx); static int filterIx = e->KeywordIx("FILTER"); bool filterKW = e->KeywordPresent(filterIx); if (filterKW) isfilter = e->KeywordSet(filterIx); static int fix_filterIx = e->KeywordIx("FIX_FILTER"); // Not implemented bool fix_filterKW = e->KeywordPresent(fix_filterIx); if (fix_filterKW) isfix_filter = e->KeywordSet(fix_filterIx); static int get_pathIx = e->KeywordIx("GET_PATH"); bool get_pathKW = e->KeywordPresent(get_pathIx); static int groupIx = e->KeywordIx("GROUP"); // Not tested bool groupKW = e->KeywordPresent(groupIx); if (groupKW) isgroup = e->KeywordSet(groupIx); static int multiple_filesIx = e->KeywordIx("MULTIPLE_FILES"); bool multiple_filesKW = e->KeywordPresent(multiple_filesIx); if (multiple_filesKW) ismultiple_files = e->KeywordSet(multiple_filesIx); static int must_existIx = e->KeywordIx("MUST_EXIST"); bool must_existKW = e->KeywordPresent(must_existIx); if (must_existKW) ismust_exist = e->KeywordSet(must_existIx); static int overwrite_promptIx = e->KeywordIx("OVERWRITE_PROMPT"); bool overwrite_promptKW = e->KeywordPresent(overwrite_promptIx); if (overwrite_promptKW) isoverwrite_prompt = e->KeywordSet(overwrite_promptIx); static int pathIx = e->KeywordIx("PATH"); bool pathKW = e->KeywordPresent(pathIx); if (pathKW) ispath = e->KeywordSet(pathIx); static int readIx = e->KeywordIx("READ"); bool readKW = e->KeywordPresent(readIx); if (readKW) isread = e->KeywordSet(readIx); static int writeIx = e->KeywordIx("WRITE"); bool writeKW = e->KeywordPresent(writeIx); if (writeKW) iswrite = e->KeywordSet(writeIx); static int resource_nameIx = e->KeywordIx("RESOURCE_NAME"); // Not implemented bool resource_nameKW = e->KeywordPresent(resource_nameIx); if (resource_nameKW) isresource_name = e->KeywordSet(resource_nameIx); static int titleIx = e->KeywordIx("TITLE"); bool titleKW = e->KeywordPresent(titleIx); if (titleKW) istitle = e->KeywordSet(titleIx); if (ismultiple_files && isdirectory) Warning("DIALOG_PICKFILE: Selecting multiple directories is not supported."); if (get_pathKW) e->AssureGlobalKW(get_pathIx); // Set parent widget. // WARNING: THIS PART IS NOT TESTED GDLWidget *widget; wxWindow *parent; if (isgroup || isdialog_parent) { DLong groupLeader = 0; // GROUP == DIALOG_PARENT. // However GROUP is deprecated, so we prefer DIALOG_PARENT here. e->AssureLongScalarKWIfPresent(groupIx, groupLeader); e->AssureLongScalarKWIfPresent(dialog_parentIx, groupLeader); widget = GDLWidget::GetWidget(groupLeader); if (widget == NULL) ThrowGDLException("Message code is invalid."); parent = static_cast (widget->GetWxWidget()); } else parent = 0; // Set style long style = 0; if (isdirectory) { style |= wxDD_DEFAULT_STYLE; if (ismust_exist) style |= wxDD_DIR_MUST_EXIST; } else { if (iswrite) style |= wxFD_SAVE; else style |= wxFD_OPEN; if (ismust_exist) style |= wxFD_FILE_MUST_EXIST; if (ismultiple_files) style |= wxFD_MULTIPLE; if (iswrite && isoverwrite_prompt) style |= wxFD_OVERWRITE_PROMPT; } // Set title wxString wxtitlestr = wxT("Select File"); if (istitle) { DString titlestr; e->AssureStringScalarKW(titleIx, titlestr); } else { if (iswrite) wxtitlestr = wxT("Select File to Write"); else if (isread) wxtitlestr = wxT("Select File to Read"); } // Set default path, with recent Gnome, default path is "the previous" wxString wxpathstr = wxT(""); DString pathstr; if (ispath) { e->AssureStringScalarKW(pathIx, pathstr); } else { pathstr=GetCWD(); } wxpathstr = wxString(pathstr.c_str(), wxConvUTF8); // Show dialog wxArrayString wxpathstrarr; long pathcnt; if (isdirectory) { // If DIRECTORY is set, show DirDialog wxDirDialog gdlDirDialog(parent, wxtitlestr, wxpathstr, style); if (gdlDirDialog.ShowModal() != wxID_CANCEL) { wxpathstr = gdlDirDialog.GetPath(); wxpathstrarr.push_back(wxpathstr); pathcnt = 1; } else pathcnt = 0; } else { // If DIRECTORY is not set, show FileDialog wxString wxfilterstr; if (isfilter) { DStringGDL* filterstrarr = e->IfDefGetKWAs(filterIx); dimension dim = filterstrarr->Dim(); if (dim.Rank() > 2 || (dim.Rank() == 2 && dim[1] != 2)) ThrowGDLException("Filter must be a one dimensional or [N,2] string array."); if (dim.Rank() <= 1) { for (int i = 0; i < filterstrarr->Size(); i++) { DString filterstr = (*filterstrarr)[i]; if (i != 0) wxfilterstr += wxT("|"); wxfilterstr += wxString((filterstr + "|" + filterstr).c_str(), wxConvUTF8); } } else // rank == 2 { long filtercnt = filterstrarr->Dim(0); for (int i = 0; i < filtercnt; i++) { if (i != 0) wxfilterstr += wxT("|"); wxfilterstr += wxString(((DString)((*filterstrarr)[i + filtercnt]) + "|" + (DString)((*filterstrarr)[i])).c_str(), wxConvUTF8); } } } else wxfilterstr = wxT("*.*|*.*"); wxString wxfilestr; if (isfile) { DString filestr; e->AssureStringScalarKW(fileIx, filestr); wxfilestr = wxString(filestr.c_str(), wxConvUTF8); } wxFileDialog gdlFileDialog(parent, wxtitlestr, wxpathstr, wxfilestr, wxfilterstr, style); if (gdlFileDialog.ShowModal() != wxID_CANCEL) { if (ismultiple_files) { gdlFileDialog.GetPaths(wxpathstrarr); pathcnt = wxpathstrarr.size(); } else { wxString wxpath = gdlFileDialog.GetPath(); wxpathstrarr.push_back(wxpath); pathcnt = 1; } } else pathcnt = 0; } // If MULTIPLE_FILES is set, result is string array of filenames; otherwise result is string scalar. // If DIRECTORY is set, result is always string scalar. DStringGDL* res; if (pathcnt == 0) res = new DStringGDL(""); else { if (ismultiple_files && !isdirectory) { res = new DStringGDL(dimension(pathcnt), BaseGDL::NOZERO); for (SizeT r = 0; r < pathcnt; ++r) (*res)[r] = _D(wxpathstrarr[r]); } else if (isdirectory) res = new DStringGDL(_D(wxpathstrarr[0]) + PathSeparator()); else res = new DStringGDL(_D(wxpathstrarr[0])); } // Set the given GET_PATH variable if (get_pathKW) { if (pathcnt > 0) { DStringGDL* pathstrgdl; if (isdirectory) pathstrgdl = new DStringGDL((*res)[0]); else { static int file_dirnameIx = LibFunIx("FILE_DIRNAME"); EnvT *newEnv = new EnvT(e, libFunList[file_dirnameIx], NULL); Guard guard(newEnv); newEnv->SetNextPar(new DStringGDL((*res)[0])); pathstrgdl = (DStringGDL *)file_dirname(newEnv); guard.release(); (*pathstrgdl)[0].append(PathSeparator()); } e->SetKW(get_pathIx, pathstrgdl); } else e->SetKW(get_pathIx, new DStringGDL("")); } // Add default extension to the results if (isdefault_extension && !isdirectory && pathcnt > 0) { DString defaultextstr; e->AssureStringScalarKW(default_extensionIx, defaultextstr); bool fileexists; EnvT *newEnv; // TODO: below is not valid when 'write' and 'filter' keys are simultaneously specified. // See http://www.exelisvis.com/docs/DIALOG_PICKFILE.html for (int i = 0; i < pathcnt; i++) { // Check file exists ifstream f((*res)[i].c_str()); fileexists = f.good(); f.close(); if (!fileexists) { static int file_basenameIx = LibFunIx("FILE_BASENAME"); newEnv = new EnvT(e, libFunList[file_basenameIx], NULL); Guard guard(newEnv); newEnv->SetNextPar(new DStringGDL((*res)[i])); DStringGDL *basenamestrgdl = (DStringGDL *)file_basename(newEnv); guard.release(); // Add default extention when the file does not have one if ((*basenamestrgdl)[0].find(".") == string::npos) (*res)[i] += "." + defaultextstr; } } } return res; } BaseGDL* dialog_message_wxwidgets(EnvT* e) { if (!GDLWidget::wxIsStarted()){ if( ! wxInitialize( ) ) e->Throw("Unable to initialize wxWidgets"); GDLWidget::SetWxStarted(); } #ifdef HAVE_LOCALE_H setlocale(LC_ALL, "C"); #endif DStringGDL* messagestr; bool iscancel = false; bool iscenter = false; bool isdefault_cancel = false; bool isdefault_no = false; bool isdialog_parent = false; bool isdisplay_name = false; bool iserror = false; bool isinformation = false; bool isquestion = false; bool isresource_name = false; bool istitle = false; messagestr = e->GetParAs(0); static int cancelIx = e->KeywordIx("CANCEL"); bool cancelKW = e->KeywordPresent(cancelIx); if (cancelKW) iscancel = e->KeywordSet(cancelIx); static int centerIx = e->KeywordIx("CENTER"); bool centerKW = e->KeywordPresent(centerIx); if (centerKW) iscenter = e->KeywordSet(centerIx); static int default_cancelIx = e->KeywordIx("DEFAULT_CANCEL"); bool default_cancelKW = e->KeywordPresent(default_cancelIx); if (default_cancelKW) isdefault_cancel = e->KeywordSet(default_cancelIx); static int default_noIx = e->KeywordIx("DEFAULT_NO"); bool default_noKW = e->KeywordPresent(default_noIx); if (default_noKW) isdefault_no = e->KeywordSet(default_noIx); static int dialog_parentIx = e->KeywordIx("DIALOG_PARENT"); // Not tested bool dialog_parentKW = e->KeywordPresent(dialog_parentIx); if (dialog_parentKW) isdialog_parent = e->KeywordSet(dialog_parentIx); static int display_nameIx = e->KeywordIx("DISPLAY_NAME"); // Not implemented bool display_nameKW = e->KeywordPresent(display_nameIx); if (display_nameKW) isdisplay_name = e->KeywordSet(display_nameIx); static int errorIx = e->KeywordIx("ERROR"); bool errorKW = e->KeywordPresent(errorIx); if (errorKW) iserror = e->KeywordSet(errorIx); static int informationIx = e->KeywordIx("INFORMATION"); bool informationKW = e->KeywordPresent(informationIx); if (informationKW) isinformation = e->KeywordSet(informationIx); static int questionIx = e->KeywordIx("QUESTION"); bool questionKW = e->KeywordPresent(questionIx); if (questionKW) isquestion = e->KeywordSet(questionIx); static int resource_nameIx = e->KeywordIx("RESOURCE_NAME"); // Not implemented bool resource_nameKW = e->KeywordPresent(resource_nameIx); if (resource_nameKW) isresource_name = e->KeywordSet(resource_nameIx); static int titleIx = e->KeywordIx("TITLE"); bool titleKW = e->KeywordPresent(titleIx); if (titleKW) istitle = e->KeywordSet(titleIx); #ifndef wxCANCEL_DEFAULT #define wxCANCEL_DEFAULT 0 if (isdefault_cancel) Warning("DIALOG_MESSAGE: Keyword DEFAULT_CANCEL is ignored."); #endif // If two or three styles are specified simultaneously, set INFORMATION as default. if ((iserror && isquestion) || (iserror && isinformation) || (isquestion && isinformation)) { iserror = false; isquestion = false; isinformation = true; } // Set style long style = wxOK|wxSTAY_ON_TOP; if (isquestion) style = wxYES_NO; if (iscancel || isdefault_cancel) style |= wxCANCEL; if (iscenter) style |= wxCENTRE; // On windows, dialog is always centered with or without this option. if (isdefault_cancel) style |= wxCANCEL_DEFAULT; if (isquestion && isdefault_no) style |= wxNO_DEFAULT; if (isquestion) style |= wxICON_QUESTION; else if (iserror) style |= wxICON_ERROR; else if (isinformation) style |= wxICON_INFORMATION; else style |= wxICON_WARNING; // Default type is 'Warning' // Set parent widget. // WARNING: THIS PART IS NOT TESTED GDLWidget *widget; wxWindow *parent; if (isdialog_parent) { DLong groupLeader = 0; e->AssureLongScalarKWIfPresent(dialog_parentIx, groupLeader); widget = GDLWidget::GetWidget(groupLeader); if (widget == NULL) ThrowGDLException("Message code is invalid."); parent = static_cast (widget->GetWxWidget()); } else parent = 0; // Set title wxString wxtitlestr; if (istitle) { DString titlestr; e->AssureStringScalarKW(titleIx, titlestr); wxtitlestr = wxString(titlestr.c_str(), wxConvUTF8); } else { if (iserror) wxtitlestr = wxT("Error"); else if (isinformation) wxtitlestr = wxT("Information"); else if (isquestion) wxtitlestr = wxT("Question"); else wxtitlestr = wxT("Warning"); } // convert eventual array of strings in a string: DString local_string; for( int i=0; iN_Elements(); ++i) local_string += (*messagestr)[i]+'\n'; // remove last \n if (local_string.length() > 1) local_string.resize(local_string.length()-1); // Show dialog wxMessageDialog gdlMessageDialog(parent, wxString(local_string.c_str(), wxConvUTF8), wxtitlestr, style); int rtn = gdlMessageDialog.ShowModal(); if (wxID_OK == rtn) return new DStringGDL("OK"); else if (wxID_YES == rtn) return new DStringGDL("Yes"); else if (wxID_NO == rtn) return new DStringGDL("No"); else return new DStringGDL("Cancel"); } #else BaseGDL* wxwidgets_exists(EnvT* e) { return new DIntGDL(0); }; BaseGDL* dialog_pickfile_wxwidgets(EnvT* e) { ThrowGDLException("wxWidgets is not available!"); return 0; } BaseGDL* dialog_message_wxwidgets(EnvT* e) { ThrowGDLException("wxWidgets is not available!"); return 0; } #endif } gdl-0.9.9/src/dialog.hpp000066400000000000000000000025711340051421000150310ustar00rootroot00000000000000/*************************************************************************** dialog.hpp - GDL library function for dialogs ------------------- begin : 04 Apr 2015 copyright : (C) 2015 by Jeongbin Park email : pjb7687@gmail.com ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "datatypes.hpp" #include "dinterpreter.hpp" //#ifndef _U //// only in wxWidget 3.0 and after : //#define _U(x) wxString(x, wxConvUTF8) //#endif #ifndef _D #define _D(x) DString((x).mb_str(wxConvUTF8)) #endif namespace lib { BaseGDL* wxwidgets_exists(EnvT* e); BaseGDL* dialog_pickfile_wxwidgets(EnvT* e); BaseGDL* dialog_message_wxwidgets(EnvT* e); } // namespace gdl-0.9.9/src/dimension.hpp000066400000000000000000000235151340051421000155600ustar00rootroot00000000000000/*************************************************************************** dimension.hpp - GDL array structure info ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DIMENSION_HPP_ #define DIMENSION_HPP_ #include #include "typedefs.hpp" #include "gdlexception.hpp" // const SizeT MAXRANK=8; // arrays are limited to 8 dimensions // const std::string MAXRANK_STR("8"); // for use in strings (error messages) typedef char RankT; inline SizeT RankIx( const SizeT rank) { return (rank <= 1)? 0 : rank-1; } class dimension { SizeT dim[MAXRANK]; // dimension mutable SizeT stride[MAXRANK+1]; // stride char rank; // how many dim are valid public: // structors dimension(): rank(0) { stride[0] = 0; // mark as not set } // c-i dimension(const dimension& dim_) { rank = dim_.rank; for(char i=0; i MAXRANK) throw GDLException("Only "+MAXRANK_STR+" dimensions allowed."); for( SizeT i=thisRank; i>(const SizeT add) { SizeT thisRank = rank++; if( rank > MAXRANK) throw GDLException("Only "+MAXRANK_STR+" dimensions allowed."); for( int i=thisRank-1; i>=0; i--) { dim[i+1]=dim[i]; } dim[0]=add; stride[0] = 0; // not set } // cat add to left void operator>>(const dimension& add) { int thisRank = rank; int addRank = add.rank; rank += addRank; if( rank > static_cast(MAXRANK)) throw GDLException("Only "+MAXRANK_STR+" dimensions allowed."); // shift dim by addRank for( int i=thisRank-1; i>=0; i--) { dim[i+addRank]=dim[i]; } // insert add on the left for( int i=0; i static_cast(MAXRANK)) throw GDLException("Only "+MAXRANK_STR+" dimensions allowed."); // shift dim by addRank for( int i=thisRank-1; i>=0; i--) { dim[i+addRank]=dim[i]; } // insert add on the left for( int i=0; i= rank) return 0; return dim[d1]; } // members // number of elements SizeT NDimElements() { if( stride[0] == 0) InitStride(); return stride[ rank]; // SizeT res=1; // for(unsigned i=0; i= rank) rank = ix+1; dim[ix]=d; stride[0] = 0; // not set } SizeT Stride(const SizeT i) const { if( stride[0] == 0) this->InitStride(); // const_cast(this)->InitStride(); return stride[ (iInitStride(); return stride; } void Stride( SizeT s[], SizeT upto) const { assert( upto >= 1); if( stride[0] == 0) this->InitStride(); // copy for(int m=0; m<=upto; ++m) s[m] = stride[m]; // s[0]=1; // upto must be at least 1 // if( stride[0] == 0) // stride not set yet // { // unsigned m=1; // if( upto <= rank) // for(; m<=upto; ++m) // s[m] = s[m-1] * dim[m-1]; // else // { // for(; m<=rank; ++m) // s[m] = s[m-1] * dim[m-1]; // for(; m<=upto; ++m) // s[m] = s[m-1]; // } // } // else // stride already calculated -> copy // { // unsigned m=1; // if( upto <= rank) // for(; m<=upto; ++m) // s[m] = stride[m]; // else // { // for(; m<=rank; ++m) // s[m] = stride[m]; // for(; m<=upto; ++m) // s[m] = s[m-1]; // } // } } // we must do a full stride calculation here because // variables might be indexed with more dimensions they actually have // (which indices then must all be zero) void InitStride() const { if( rank == 0) { for(int m=0; m<=MAXRANK; ++m) stride[m] = 1; } else { stride[0]=1; stride[1]=dim[0]; int m=1; for(; mscalar .. MAXRANK) // dim[rank]=0 for rank1 && dim[eqrank-1] <= 1; --eqrank); return eqrank-i; } // throw away unused ranks (ie. ranks == 1) inline void Purge() { for(; rank>1 && dim[rank-1] <= 1; --rank); } // set the rank to r (pads 1s) if it is smaller than r void MakeRank(SizeT r) { SizeT rNow=rank; if( rNow >= r) return; if( r > MAXRANK) throw GDLException("Maximum "+MAXRANK_STR+" dimensions are allowed."); for( SizeT i=rNow; i #ifdef _MSC_VER #include // isatty, windows #else #include // isatty, usleep #endif //#include #include "dnodefactory.hpp" #include "str.hpp" #include "envt.hpp" #include "dinterpreter.hpp" #include "gdljournal.hpp" #include "gdleventhandler.hpp" #ifdef USE_MPI #include "mpi.h" #endif #include // print out AST tree //#define GDL_DEBUG //#undef GDL_DEBUG #ifdef GDL_DEBUG #include "print_tree.hpp" #endif #include // C++11 using namespace std; using namespace antlr; string inputstr; bool historyIntialized = false; // instantiation of static data GDLInterpreter::HeapT GDLInterpreter::heap; GDLInterpreter::ObjHeapT GDLInterpreter::objHeap; SizeT GDLInterpreter::objHeapIx; SizeT GDLInterpreter::heapIx; EnvStackT GDLInterpreter::callStack; DLong GDLInterpreter::stepCount; ProgNode GDLInterpreter::NULLProgNode; ProgNodeP GDLInterpreter::NULLProgNodeP = &GDLInterpreter::NULLProgNode; void LibInit(); // defined in libinit.cpp DInterpreter::DInterpreter(): GDLInterpreter() { // DataStackT::Init(); // heap.push_back(NULL); // init heap index 0 (used as NULL ptr) // objHeap.push_back(NULL); // init heap index 0 (used as NULL ptr) interruptEnable = true; objHeapIx=1; // map version (0 is NULL ptr) heapIx=1; // map version (0 is NULL ptr) returnValue = NULL; returnValueL = NULL; stepCount = 0; // setup main level environment DPro* mainPro=new DPro(); // $MAIN$ NOT inserted into proList EnvUDT* mainEnv=new EnvUDT(NULL, mainPro); callStack.push_back(mainEnv); // push main environment (necessary) assert( ProgNode::interpreter == NULL); GDLException::SetInterpreter( this); ProgNode::interpreter = this; // interface to expr( ProgNodeP) EnvT::interpreter = this; BaseGDL::interpreter = this; // tmpList.reserve(100); } // void SetActualCompileOpt( unsigned int cOpt) // { // if( BaseGDL::interpreter!=NULL && BaseGDL::interpreter->CallStack().size()>0) // BaseGDL::interpreter->CallStack().back()->SetCompileOpt( cOpt); // } // used in the statement function. // runs a new instance of the interpreter if not // at main level RetCode GDLInterpreter::NewInterpreterInstance( SizeT lineOffset) { if( callStack.size() <= 1 && lineOffset == 0) return RC_ABORT; // stay in main loop assert( dynamic_cast( this) != NULL); return static_cast( this)->InnerInterpreterLoop(lineOffset); } DStructGDL* GDLInterpreter::ObjectStruct( DObjGDL* self, ProgNodeP mp) { // DType selfType = self->Type(); // if( selfType != GDL_OBJ) // throw GDLException( mp, "Object reference type" // " required in this context: "+Name(self)); DObjGDL* obj=self;//static_cast(self); SizeT o; if( !obj->Scalar( o)) throw GDLException( mp, "Object reference" " must be scalar in this context: "+Name(self)); if( o == 0) throw GDLException( mp, "Unable to invoke method" " on NULL object reference: "+Name(self)); DStructGDL* oStructGDL; try { oStructGDL= GetObjHeap( o); } catch ( HeapException&) { throw GDLException( mp, "Object not valid: "+Name(self)); } return oStructGDL; } void GDLInterpreter::SetRootL( ProgNodeP tt, DotAccessDescT* aD, BaseGDL* r, ArrayIndexListT* aL) { if( r->Type() == GDL_STRUCT) { if( r->IsAssoc()) { ArrayIndexListGuard guard( aL); throw GDLException( tt, "File expression not allowed in this context: "+ Name(r),true,false); } DStructGDL* structR=static_cast(r); aD->ADRoot(structR, aL); } else { if( r->Type() != GDL_OBJ) { throw GDLException( tt, "Expression must be a STRUCT in this context: "+ Name(r),true,false); } ArrayIndexListGuard guard( aL); DStructGDL* oStruct = ObjectStruct( static_cast(r), tt); DStructDesc* desc = oStruct->Desc(); bool isObj = callStack.back()->IsObject(); // called from member subroutine? if( desc->IsParent( GDL_OBJECT_NAME)) { SizeT sss = 0; SizeT ooo = 0; if( isObj) { static_cast(r)->Scalar( ooo); // checked in ObjectStruct BaseGDL* self = callStack.back()->GetKW(callStack.back()->GetPro()->NKey()); // SELF assert( dynamic_cast(self) != NULL); if( !static_cast(self)->Scalar( sss)) throw GDLException( tt, "Internal error: SELF Object reference" " must be scalar in this context: "+Name(self)); assert( sss != 0); } if( !isObj || (sss != ooo)) { // call SetProperty throw GDLException( tt, "Calling SetProperty not yet implemented: "+Name(r)); //return; } } if( isObj) // member access to object? { if( !desc->IsParent( callStack.back()->GetPro()->Object())) { throw GDLException( tt, "Object of type "+desc->Name()+ " is not accessible within "+ callStack.back()->GetProName() + ": "+Name(r)); } // DStructGDL* oStruct = // ObjectStructCheckAccess( static_cast(r), tt); // oStruct cannot be "Assoc_" aD->ADRoot( oStruct, guard.release()); } else { throw GDLException( tt, "Expression must be a" " STRUCT in this context: "+Name(r), true,false); } } } void GDLInterpreter::SetRootR( ProgNodeP tt, DotAccessDescT* aD, BaseGDL* r, ArrayIndexListT* aL) { // check here for object and get struct if( r->Type() == GDL_STRUCT) { if( r->IsAssoc()) { ArrayIndexListGuard guard( aL); throw GDLException( tt, "File expression not allowed in this context: "+ Name(r),true,false); } DStructGDL* structR=static_cast(r); aD->ADRoot( structR, aL); } else { ArrayIndexListGuard guard( aL); if( r->Type() != GDL_OBJ) { throw GDLException( tt, "Expression must be a" " STRUCT in this context: "+Name(r), true,false); } DStructGDL* oStruct = ObjectStruct( static_cast(r), tt); DStructDesc* desc = oStruct->Desc(); bool isObj = callStack.back()->IsObject(); if( desc->IsParent( GDL_OBJECT_NAME)) { SizeT sss = 0; SizeT ooo = 0; if( isObj) { static_cast(r)->Scalar( ooo); // checked in ObjectStruct BaseGDL* self = callStack.back()->GetKW(callStack.back()->GetPro()->NKey()); // SELF assert( dynamic_cast(self) != NULL); if( !static_cast(self)->Scalar( sss)) throw GDLException( tt, "Internal error: SELF Object reference" " must be scalar in this context: "+Name(self)); assert( sss != 0); } if( !isObj || (sss != ooo)) { // call GetProperty throw GDLException( tt, "Calling GetProperty not yet implemented: "+Name(r)); //aD->ADRootGetProperty( oStruct, guard.release()); return; } } if( isObj) { if( !desc->IsParent( callStack.back()->GetPro()->Object())) { throw GDLException( tt, "Object of type "+desc->Name()+ " is not accessible within "+ callStack.back()->GetProName() + ": "+Name(r)); } // DStructGDL* oStruct = // ObjectStructCheckAccess( static_cast(r), tt); if( aD->IsOwner()) delete r; aD->SetOwner( false); // object struct, not owned aD->ADRoot( oStruct, guard.release()); } else { throw GDLException( tt, "Expression must be a" " STRUCT in this context: "+Name(r),true,false); } } } // DStructDesc* GDLInterpreter::GDLObjectDesc( DStructGDL* oStruct, ProgNodeP mp) // { // //DStructGDL* oStruct = ObjectStruct( self, mp); // // // check accessibility // DStructDesc* desc = oStruct->Desc(); // if( !desc->IsParent( GDL_OBJECT_NAME)) // { // return NULL; // } // // return desc; // } // // void GDLInterpreter::ObjectStructCheckAccess( DStructGDL* oStruct, ProgNodeP mp) // { // //DStructGDL* oStruct = ObjectStruct( self, mp); // // // check accessibility // DStructDesc* desc = oStruct->Desc(); // if( !desc->IsParent( callStack.back()->GetPro()->Object())) // { // throw GDLException( mp, "Object of type "+desc->Name()+ // " is not accessible within "+ // callStack.back()->GetProName() + ": "+Name(self)); // } // // //return oStruct; // } // searches and compiles procedure (searchForPro == true) or function (searchForPro == false) 'pro' bool GDLInterpreter::SearchCompilePro(const string& pro, bool searchForPro) { static StrArr openFiles; string proFile=StrLowCase(pro)+".pro"; //AppendIfNeeded( proFile, ".pro"); bool found=CompleteFileName(proFile); if( !found) return false; // file already opened? for( StrArr::iterator i=openFiles.begin(); i != openFiles.end(); ++i) { if( proFile == *i) return false; } StackSizeGuard guard( openFiles); // append file to list openFiles.push_back(proFile); return CompileFile( proFile, pro, searchForPro); // this might trigger recursion } // returns the struct descriptor with name 'name' // read/compiles 'name'__define.pro if necessary // cN is the calling node, passed for (runtime) debug information DStructDesc* GDLInterpreter::GetStruct(const string& name, ProgNodeP cN) { // find struct 'id' DStructDesc* dStruct=FindInStructList( structList, name); // member function/pro declaration inserts an empty DStructDesc if( dStruct != NULL && dStruct->NTags() > 0) return dStruct; static StrArr getStructList; // read/compile of IDENTIFIER__define.pro string proName=name+"__DEFINE"; for( StrArr::iterator i=getStructList.begin(); i != getStructList.end(); ++i) { if( proName == *i) throw GDLException(cN, "Structure type not defined (recursive call): "+name,true,false); } StackSizeGuard guardStructList( getStructList); // append file to list getStructList.push_back(proName); // if( Called( proName)) // { // throw GDLException(cN, "Structure type not defined (recursive call): "+name); // } /*bool found=*/ SearchCompilePro(proName, true); // if an exception occurs in SearchCompilePro, the struct is not compiled int proIx=ProIx(proName); if( proIx == -1) { throw GDLException(cN, "Procedure not found: "+proName, true, false); } // 'guard' call stack StackGuard guard(callStack); // interpret it EnvUDT* newEnv=new EnvUDT( cN, proList[proIx]); // push id.pro onto call stack callStack.push_back(newEnv); // make the call call_pro(static_cast(callStack.back()->GetPro())->GetTree()); dStruct=FindInStructList( structList, name); if( dStruct == NULL) { throw GDLException(cN, "Structure type not defined: "+name,true,false); } return dStruct; } void GDLInterpreter::SetFunIx( ProgNodeP f) { if( f->funIx == -1) f->funIx=GetFunIx(f); } int GDLInterpreter::GetFunIx( ProgNodeP f) { string subName = f->getText(); int funIx=FunIx(subName); if( funIx == -1) { // trigger reading/compiling of source file /*bool found=*/ SearchCompilePro(subName, false); funIx=FunIx(subName); if( funIx == -1) { throw GDLException(f, "Function not found: "+subName, true, false); } } return funIx; } int GDLInterpreter::GetFunIx( const string& subName) { int funIx=FunIx(subName); if( funIx == -1) { // trigger reading/compiling of source file /*bool found=*/ SearchCompilePro(subName, false); funIx=FunIx(subName); if( funIx == -1) { throw GDLException("Function not found: "+subName); } } return funIx; } void GDLInterpreter::SetProIx( ProgNodeP f, bool throwImmediately) { if( f->proIx == -1) f->proIx=GetProIx(f, throwImmediately);//->getText()); } int GDLInterpreter::GetProIx( ProgNodeP f, bool throwImmediately) { string subName = f->getText(); int proIx=ProIx(subName); if( proIx == -1) { // trigger reading/compiling of source file /*bool found=*/ SearchCompilePro(subName, true); proIx=ProIx(subName); if (throwImmediately){ if( proIx == -1) { throw GDLException(f,"Procedure not found: "+subName,true,false); } } } return proIx; } int GDLInterpreter::GetProIx( const string& subName) { int proIx=ProIx(subName); if( proIx == -1) { // trigger reading/compiling of source file /*bool found=*/ SearchCompilePro(subName, true); proIx=ProIx(subName); if( proIx == -1) { throw GDLException("Procedure not found: "+subName); } } return proIx; } // converts inferior type to superior type void GDLInterpreter::AdjustTypes(BaseGDL* &a, BaseGDL* &b) { DType aTy=a->Type(); DType bTy=b->Type(); if( aTy == bTy) return; if( DTypeOrder[aTy] > 100 || DTypeOrder[bTy] > 100) { //exception throw GDLException( "Expressions of this type cannot be converted."); } if( DTypeOrder[aTy] > DTypeOrder[bTy]) { // convert b to a b=b->Convert2( aTy); } else { // convert a to b a=a->Convert2( bTy); } } void GDLInterpreter::ReportCompileError( GDLException& e, const string& file) { cout << flush; cerr << SysVar::MsgPrefix() << e.toString() << endl; if( file != "") { cerr << " At: " << file; SizeT line = e.getLine(); if( line != 0) { cerr << ", Line " << line; SizeT col = e.getColumn(); if( col != 0) cerr << " Column " << e.getColumn(); } cerr << endl; } } // compiles file, returns success // if untilPro is set to "" the whole file is compiled // procedure (searchForPro == true (default)) or function (searchForPro == false) bool GDLInterpreter::CompileFile(const string& f, const string& untilPro, bool searchForPro) { ifstream in(f.c_str()); if( !in) return false; // maybe throw exception here RefDNode theAST; try { GDLLexer lexer(in, f, GDLParser::NONE, untilPro, searchForPro); GDLParser& parser=lexer.Parser(); // parsing parser.translation_unit(); theAST=parser.getAST(); if( !theAST) { cout << "No parser output generated." << endl; return false; } } catch( GDLException& e) { ReportCompileError( e, f); return false; } catch( ANTLRException& e) { cerr << "Lexer/Parser exception: " << e.getMessage() << endl; return false; } #ifdef GDL_DEBUG cout << "Parser output:" << endl; antlr::print_tree pt; pt.pr_tree(static_cast(theAST)); cout << "CompileFile: Parser end." << endl; #endif #ifdef GDL_DEBUG RefDNode trAST; #endif GDLTreeParser treeParser( f, untilPro); try { treeParser.translation_unit(theAST); // #ifdef GDL_DEBUG // nothing is returned (pro/funList are changed) // trAST=treeParser.getAST(); // #endif if( treeParser.ActiveProCompiled()) RetAll(); } catch( GDLException& e) { ReportCompileError( e, f); if( treeParser.ActiveProCompiled()) RetAll(); return false; } catch( ANTLRException& e) { cerr << "Compiler exception: " << e.getMessage() << endl; if( treeParser.ActiveProCompiled()) RetAll(); return false; } // #ifdef GDL_DEBUG // cout << "Tree parser output:" << endl; // pt.pr_tree(static_cast(trAST)); // cout << "ExecuteLine: Tree parser end." << endl; // #endif /*#ifdef GDL_DEBUG cout << "Tree parser output:" << endl; antlr::print_tree ptTP; ptTP.pr_tree(static_cast(trAST)); cout << "CompileFile: Tree parser end." << endl; #endif*/ return true; } void AppendExtension( string& argstr) { SizeT slPos = argstr.find_last_of( '/'); SizeT dotPos = argstr.find_last_of( '.'); if( dotPos == string::npos || (slPos != string::npos && slPos > dotPos)) // if( argstr.length() <= 4 || argstr.find( '.', 1) == string::npos) // StrLowCase( argstr.substr(argstr.length()-4,4)) != ".pro") { argstr += ".pro"; } } DInterpreter::CommandCode DInterpreter::CmdReset() { RetAll( RetAllException::RESET); return CC_OK; } DInterpreter::CommandCode DInterpreter::CmdFullReset() { RetAll( RetAllException::FULL_RESET); return CC_OK; } DInterpreter::CommandCode DInterpreter::CmdCompile( const string& command) { string cmdstr = command; size_t sppos = cmdstr.find(" ",0); if (sppos == string::npos) { cout << "Interactive COMPILE not implemented yet." << endl; return CC_OK; } bool retAll = false; // Remember if Retall is needed // Parse each file name size_t pos = sppos + 1; while (pos < command.length()) { sppos = command.find(" ",pos); if (sppos == string::npos) sppos = command.length(); // Found a file if ((sppos - pos) > 0) { string argstr = command.substr(pos, sppos-pos); string origstr = argstr; // try first with extension AppendExtension( argstr); bool found = CompleteFileName( argstr); // 2nd try without extension if( !found) { argstr = origstr; found = CompleteFileName( argstr); } if (found) { try { // default is more verbose CompileFile( argstr); //, origstr); } catch( RetAllException&) { // delay the RetAllException until finished retAll = true; } } else { Message( "Error opening file. File: "+origstr+"."); return CC_OK; } } pos = sppos + 1; } if( retAll) RetAll(); return CC_OK; } DInterpreter::CommandCode DInterpreter::CmdRun( const string& command) { string cmdstr = command; size_t sppos = cmdstr.find(" ",0); if (sppos == string::npos) { cout << "Interactive RUN not implemented yet." << endl; return CC_OK; } bool retAll = false; // Remember if Retall is needed // Parse each file name size_t pos = sppos + 1; while (pos < command.length()) { sppos = command.find(" ",pos); size_t spposComma = command.find(",",pos); if (sppos == string::npos && spposComma == string::npos) sppos = command.length(); else if (sppos == string::npos) sppos = spposComma; // Found a file if ((sppos - pos) > 0) { string argstr = command.substr(pos, sppos-pos); string origstr = argstr; // try 1st with extension AppendExtension( argstr); bool found = CompleteFileName(argstr); // 2nd try without extension if( !found) { argstr = origstr; found = CompleteFileName( argstr); } if (found) { try { // default is more verbose CompileFile( argstr); //, origstr); } catch( RetAllException&) { // delay the RetAllException until finished retAll = true; } } else { Message( "Error opening file. File: "+origstr+"."); return CC_OK; } } pos = sppos + 1; } if( retAll) Warning( "Compiled a main program while inside a procedure. " "Returning."); // actual run is perfomed in InterpreterLoop() RetAll( RetAllException::RUN); // throws (always) return CC_OK; //avoid warnings } // execute GDL command (.run, .step, ...) DInterpreter::CommandCode DInterpreter::ExecuteCommand(const string& command) { string cmdstr = command; string args; size_t sppos = cmdstr.find(" ",0); if (sppos != string::npos) { args = cmdstr.substr(sppos+1); cmdstr = cmdstr.substr(0, sppos); } // cout << "Execute command: " << command << endl; String_abbref_eq cmd( StrUpCase( cmdstr)); // AC: Continue before Compile to have ".c" giving ".continue" if( cmd( "CONTINUE")) { return CC_CONTINUE; } if( cmd( "COMPILE")) { return CmdCompile( command); } if( cmd( "EDIT")) { cout << "Can't edit file without running GDLDE." << endl; return CC_OK; } if( cmd( "FULL_RESET_SESSION")) { return CmdFullReset(); } if( cmd( "GO")) { cout << "GO not implemented yet." << endl; return CC_OK; } if( cmd( "OUT")) { cout << "OUT not implemented yet." << endl; return CC_OK; } if( cmd( "RUN")) { return CmdRun( command); } if( cmd( "RETURN")) { cout << "RETURN not implemented yet." << endl; return CC_OK; } if( cmd( "RESET_SESSION")) { return CmdReset(); } if( cmd( "RNEW")) { EnvUDT* mainEnv = static_cast(GDLInterpreter::callStack[0]); SizeT nEnv = mainEnv->EnvSize(); dynamic_cast(mainEnv->GetPro())->Reset(); if(!mainEnv->Removeall()) cout << " Danger ! Danger! Unexpected result. Please exit asap & report" <good() && ( line == "" || line[0] == ';' )) // skip also comment lines (bug #663) { getline( *in, line); StrTrim(line); } return line; } void AddLineOffset( SizeT lineOffset, RefDNode astR) { astR->SetLine( astR->getLine() + lineOffset); if( astR->getFirstChild() != NULL) AddLineOffset( lineOffset, (RefDNode)astR->getFirstChild() ); if( astR->getNextSibling() != NULL) AddLineOffset( lineOffset, (RefDNode)astR->getNextSibling() ); } // execute one line of code (commands and statements) DInterpreter::CommandCode DInterpreter::ExecuteLine( istream* in, SizeT lineOffset) { string line = (in != NULL) ? ::GetLine(in) : GetLine(); // cout << "ExecuteLine: " << line << endl; string firstChar = line.substr(0,1); // command if( firstChar == ".") { return ExecuteCommand( line.substr(1)); } // online help (if possible, start a browser) if( firstChar == "?") { // later, we will have to check whether we have X11/Display or not // on some computing nodes on supercomputers, this is de-activated. if (line.substr(1).length() > 0) { line=line.substr(1); StrTrim(line); line="online_help, '"+line+"'"; //' } else { line="online_help"; } } // shell command if( firstChar == "#") { if (line.substr(1).length() > 0) { line=line.substr(1); StrTrim(line); line=StrUpCase(line); //cout << "yes ! >>"<Name()) == 0) { cout << "Internal PROCEDURE : " << libProList[ i]->ToString() << endl; nbFound++; break; } } // looking in internal functions nProFun = libFunList.size(); for( SizeT i = 0; iName()) == 0) { cout << "Internal FUNCTION : " << libFunList[ i]->ToString() << endl; nbFound++; break; } } // looking in compiled functions nProFun = funList.size(); for( SizeT i = 0; iName()) == 0) { cout << "Compiled FUNCTION : " << funList[ i]->ToString() << endl; nbFound++; break; } } // looking in compiled procedures nProFun = proList.size(); for( SizeT i = 0; iName()) == 0) { cout << "Compiled PROCEDURE : " << proList[ i]->ToString() << endl; nbFound++; break; } } if (nbFound == 0) { cout << "No Procedure/Function, internal or compiled, with name : "<< line << endl; } } else { cout << "Please provide a pro/fun name !" << endl; } return CC_OK; } // shell command if( firstChar == "$") { ExecuteShellCommand( line.substr(1)); return CC_OK; } // include (only when at $MAIN$) // during compilation this is handled by the interpreter if( firstChar == "@" && callStack.size() <= 1) { string fileRaw = line.substr(1); StrTrim( fileRaw); string file = fileRaw; AppendExtension( file); bool found = CompleteFileName( file); if( !found) { file = fileRaw; CompleteFileName( file); } ExecuteFile( file); return CC_OK; } // statement -> execute it executeLine.clear(); // clear EOF (for executeLine) executeLine.str( line + "\n"); // append new line RefDNode theAST; try { Guard lexer; // LineContinuation LC // conactenate the strings and insert \n // the resulting string can be fed to the lexer // print if expr parse ok int lCNum = 0; for(;;) { lexer.Reset( new GDLLexer(executeLine, "", callStack.back()->CompileOpt())); try { // works, but ugly -> depends from parser detecting an error // (which it always will due to missing END_U token in case of LC) //lexer->Parser().SetCompileOpt(callStack.back()->CompileOpt()); lexer.Get()->Parser().interactive(); break; // no error -> everything ok } catch( GDLException& e) { int lCNew = lexer.Get()->LineContinuation(); if( lCNew == lCNum) // throw; // no LC -> real error { #ifdef AUTO_PRINT_EXPR #ifndef GDL_DEBUG try { // executeLine.clear(); // clear EOF (for executeLine) // lexer.reset( new GDLLexer(executeLine, "", callStack.back()->CompileOpt())); // lexer->Parser().expr(); executeLine.clear(); // clear EOF (for executeLine) executeLine.str( "print,/implied_print," + executeLine.str()); // append new line lexer.reset( new GDLLexer(executeLine, "", callStack.back()->CompileOpt())); lexer->Parser().interactive(); break; // no error -> everything ok } catch( GDLException& e2) #endif #endif { throw e; } } lCNum = lCNew; // save number to see if next line also has LC } // line continuation -> get next line if( in != NULL && !in->good()) throw GDLException( "End of file encountered during line continuation."); string cLine = (in != NULL) ? ::GetLine(in) : GetLine(); executeLine.clear(); // clear EOF (for executeLine) executeLine.str( executeLine.str() + cLine + "\n"); // append new line } // lexer->Parser().interactive(); theAST = lexer.Get()->Parser().getAST(); } catch( GDLException& e) { ReportCompileError( e); return CC_OK; } catch( ANTLRException& e) { cerr << "Lexer/Parser exception: " << e.getMessage() << endl; return CC_OK; } if( theAST == NULL) return CC_OK; // consider line offset if( lineOffset > 0) AddLineOffset( lineOffset, theAST); #ifdef GDL_DEBUG antlr::print_tree pt; cout << "Parser output:" << endl; pt.pr_tree(static_cast(theAST)); cout << "ExecuteLine: Parser end." << endl; #endif ProgNodeP progAST = NULL; RefDNode trAST; assert( dynamic_cast(callStack.back()) != NULL); EnvUDT* env = static_cast(callStack.back()); int nForLoopsIn = env->NForLoops(); try { GDLTreeParser treeParser( callStack.back()); treeParser.interactive(theAST); trAST=treeParser.getAST(); if( trAST == NULL) { // normal condition for cmd line procedure calls return CC_OK; } #ifdef GDL_DEBUG cout << "Tree parser output (RefDNode):" << endl; pt.pr_tree(static_cast(trAST)); cout << "ExecuteLine: Tree parser end." << endl; #endif // ************************************** // this is the call of the ProgNode factory // ************************************** progAST = ProgNode::NewProgNode( trAST); assert( dynamic_cast(callStack.back()) != NULL); EnvUDT* env = static_cast(callStack.back()); int nForLoops = ProgNode::NumberForLoops( progAST, nForLoopsIn); env->ResizeForLoops( nForLoops); } catch( GDLException& e) { env->ResizeForLoops( nForLoopsIn); ReportCompileError( e); return CC_OK; } catch( ANTLRException& e) { env->ResizeForLoops( nForLoopsIn); cerr << "Compiler exception: " << e.getMessage() << endl; return CC_OK; } Guard< ProgNode> progAST_guard( progAST); try { #ifdef GDL_DEBUG cout << "Converted tree (ProgNode):" << endl; pt.pr_tree( progAST); cout << "end." << endl; #endif RetCode retCode = interactive( progAST); env->ResizeForLoops( nForLoopsIn); // write to journal file string actualLine = GetClearActualLine(); if( actualLine != "") lib::write_journal( actualLine); if( retCode == RC_RETURN) return CC_RETURN; return CC_OK; } catch( GDLException& e) { env->ResizeForLoops( nForLoopsIn); cerr << "Unhandled GDL exception: " << e.toString() << endl; return CC_OK; } catch( ANTLRException& e) { env->ResizeForLoops( nForLoopsIn); cerr << "Interpreter exception: " << e.getMessage() << endl; return CC_OK; } return CC_OK; } void inputThread() { while (1) { // patch by Ole, 2017-01-06 //char ch = getchar(); if (ch==EOF) return NULL; char ch = getchar(); if (ch==EOF) { return; } inputstr += ch; if (ch == '\n') break; } } // if readline is not available or !EDIT_INPUT set to zero char* DInterpreter::NoReadline( const string& prompt) { if (isatty(0)) cout << prompt << flush; if( feof(stdin)) return NULL; thread th(inputThread); for (;;) { GDLEventHandler(); if (inputstr.size() && inputstr[inputstr.size() - 1] == '\n') break; if (feof(stdin)) { th.join(); return NULL; } #ifdef WIN32 Sleep(10); #else usleep(10); #endif } inputstr = inputstr.substr(0, inputstr.size() - 1); // removes '\n' //if (inputstr[inputstr.size() - 1] == '\r') // inputstr = inputstr.substr(0, inputstr.size() - 1); // removes '\r' too, if exists char *result = (char*)malloc((inputstr.length() + 1) * sizeof(char)); strcpy(result, inputstr.c_str()); // copies including terminating '\0' inputstr.clear(); th.join(); return result; } bool lineEdit = false; string actualPrompt; void ControlCHandler(int) { cout << SysVar::MsgPrefix() << "Interrupt encountered." << endl; if( lineEdit) cout << actualPrompt /*SysVar::Prompt()*/ /*.c_str()*/ << flush; sigControlC = true; signal(SIGINT,ControlCHandler); } string DInterpreter::GetLine() { clog << flush; cout << flush; #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) int edit_input = SysVar::Edit_Input() && isatty(0); #endif string line; do { char *cline; actualPrompt = SysVar::Prompt(); lineEdit = true; #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) if( edit_input != 0) cline = readline(const_cast(actualPrompt.c_str())); else cline = NoReadline(actualPrompt); #else cline = NoReadline(actualPrompt); #endif lineEdit = false; sigControlC = false; // reset all control-c which occured during line editing if( !cline) { if (isatty(0)) cout << endl; // instead or going out (EXITing) immediately, we go to // the "exitgdl" in order to save the history // exit( EXIT_SUCCESS); //break; // readline encountered eof line="EXIT"; StrTrim(line); break; } else // make a string line = cline; #ifndef _MSC_VER free(cline); // done here for compatibility with readline #endif StrTrim(line); } while( line == "" || line[0] == ';'); // skip also comment lines (bug #663) #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) // SA: commented out to comply with IDL behaviour- allowing to // set the history-file length only in the startup file //if( edit_input > 20) // { // stifle_history( edit_input); // } static string lastAdded; // we would not like to add the current command if is "EXIT" !! if ( StrUpCase(line) != "EXIT" && line != lastAdded) { // const_cast to make it work with older readline versions add_history(const_cast(line.c_str())); lastAdded = line; } /* cout << "################ " << history_length << endl; for( int h=0;hline) << endl; else cout << h << ": NULL" << endl; } */ #endif return line; } // reads user input and executes it // inner loop (called via Control-C, STOP, error) RetCode DInterpreter::InnerInterpreterLoop(SizeT lineOffset) { ProgNodeP retTreeSave = _retTree; for (;;) { #if defined (_MSC_VER) && _MSC_VER < 1800 _clearfp(); #else feclearexcept(FE_ALL_EXCEPT); #endif DInterpreter::CommandCode ret=ExecuteLine(NULL, lineOffset); _retTree = retTreeSave; // on return, _retTree should be kept if( ret == CC_SKIP) { for( int s=0; sgetNextSibling(); } // cout << ".SKIP " << stepCount << " " << _retTree << endl; stepCount = 0; retTreeSave = _retTree; // we stay at the command line here if( _retTree == NULL) Message( "Can't continue from this point."); else DebugMsg( _retTree, "Skipped to: "); } else if( ret == CC_RETURN) return RC_RETURN; else if( ret == CC_CONTINUE) return RC_OK; else if( ret == CC_STEP) return RC_OK; } } // used by pyhton module bool DInterpreter::RunBatch( istream* in) { ValueGuard guard( interruptEnable); interruptEnable = false; while( in->good()) { #if defined (_MSC_VER) && _MSC_VER < 1800 _clearfp(); #else feclearexcept(FE_ALL_EXCEPT); #endif try { DInterpreter::CommandCode ret=ExecuteLine( in); if( debugMode != DEBUG_CLEAR) { debugMode = DEBUG_CLEAR; return false; } } catch( RetAllException& retAllEx) { } catch( exception& e) { cerr << "Batch" << ": Exception: " << e.what() << endl; } catch (...) { cerr << "Batch" << ": Unhandled Error." << endl; } } // while return true; } // used for @file // Note: As long as we are in batch mode we are at $MAIN$ void DInterpreter::ExecuteFile( const string& file) { ifstream in(file.c_str()); if( in.fail()) Warning( "Error opening file: "+file); // ValueGuard guard( interruptEnable); // interruptEnable = false; bool runCmd = false; while( in.good()) { #if defined (_MSC_VER) && _MSC_VER < 1800 _clearfp(); #else feclearexcept(FE_ALL_EXCEPT); #endif try { if( runCmd) { runCmd = false; RunDelTree(); } else { DInterpreter::CommandCode ret=ExecuteLine( &in); if( debugMode != DEBUG_CLEAR) { debugMode = DEBUG_CLEAR; // Warning( "Prematurely closing batch file: "+startup); break; } } } catch( RetAllException& retAllEx) { runCmd = (retAllEx.Code() == RetAllException::RUN); if( !runCmd) throw; } // catch( exception& e) // { // cerr << file << ": Exception: " << e.what() << endl; // } // catch (...) // { // cerr << file << ": Unhandled Error." << endl; // } } // while } // this must be run only from $MAIN$ void DInterpreter::RunDelTree() { if( static_cast (callStack.back()->GetPro())->GetTree() != NULL) { try { call_pro(static_cast (callStack.back()->GetPro())->GetTree()); static_cast (callStack.back()->GetPro())->DelTree(); } catch( RetAllException&) { static_cast (callStack.back()->GetPro())->DelTree(); throw; } } } // reads user input and executes it // the main loop RetCode DInterpreter::InterpreterLoop(const string& startup, vector& batch_files, const std::string& statement) { // process startup file if (startup != "") { ifstream in(startup.c_str()); if (in.fail()) Warning("Error opening startup file: " + startup); ValueGuard guard(interruptEnable); interruptEnable = false; bool runCmd = false; try { while (in.good()) { #if defined (_MSC_VER) && _MSC_VER < 1800 _clearfp(); #else feclearexcept(FE_ALL_EXCEPT); #endif try { if (runCmd) { runCmd = false; RunDelTree(); } else { DInterpreter::CommandCode ret = ExecuteLine(&in); if (debugMode != DEBUG_CLEAR) { debugMode = DEBUG_CLEAR; Warning("Prematurely closing batch file: " + startup); break; } } } catch (RetAllException& retAllEx) { runCmd = (retAllEx.Code() == RetAllException::RUN); if (!runCmd) throw; } catch (exception& e) { cerr << startup << ": Exception: " << e.what() << endl; } catch (...) { cerr << startup << ": Unhandled Error." << endl; } } // while } catch (RetAllException& retAllEx) { } } // if( startup... #ifdef USE_MPI int myrank = 0; int tag = 0; char mpi_procedure[256]; MPI_Status status; MPI_Comm_rank(MPI_COMM_WORLD, &myrank); int size; MPI_Comm_size(MPI_COMM_WORLD, &size); if (size > 1) { MPI_Recv(mpi_procedure, 256, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status); istringstream istr(StrUpCase(mpi_procedure) + "\n"); DInterpreter::CommandCode ret = ExecuteLine(&istr); MPI_Finalize(); exit(EXIT_SUCCESS); } #endif if (statement.length() > 0) { // execute single statement and exit (a new-line is added to statement in gdl.cpp) // (e.g. $ gdl -e "print, 'hello world'") istringstream iss(statement, ios_base::out); try { ExecuteLine(&iss); } catch (RetAllException& retAllEx) { } return RC_OK; } else { // execute batch files (e.g. $ gdl script.pro) // before entering the interactive mode for (vector::iterator it = batch_files.begin(); it < batch_files.end(); ++it) ExecuteFile(*it); batch_files.clear(); // not needed anymore... } #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) // initialize readline (own version - not pythons one) // in includefirst.hpp readline is disabled for python_module // http://www.delorie.com/gnu/docs/readline/rlman.html char rlName[] = "GDL"; rl_readline_name = rlName; //Our handler takes too long //when editing the command line with ARROW keys. (bug 562). (used also in gdl.cpp) //but... without it we have no graphics event handler! FIXME!!! rl_event_hook = GDLEventHandler; { int edit_input = SysVar::Edit_Input(); stifle_history(edit_input == 1 || edit_input < 0 ? 200 : edit_input); } // Eventually read back the ".gdl" path in user $HOME // we do not make one commun function with the save side // because on the save side we may need to create the .gdl/ PATH ... int result, debug = 0; #ifdef _WIN32 char *homeDir = getenv("HOMEPATH"); #else char *homeDir = getenv("HOME"); #endif if (homeDir != NULL) { string pathToGDL_history; pathToGDL_history = homeDir; AppendIfNeeded(pathToGDL_history, "/"); pathToGDL_history = pathToGDL_history + ".gdl"; string history_filename; AppendIfNeeded(pathToGDL_history, "/"); history_filename = pathToGDL_history + "history"; if (debug) cout << "History file name: " << history_filename << endl; result = read_history(history_filename.c_str()); if (debug) { if (result == 0) cout << "Successfull reading of ~/.gdl/history" << endl; else cout << "Fail to read back ~/.gdl/history" << endl; } } historyIntialized = true; #endif bool runCmd = false; // should tree from $MAIN$ be executed? bool continueCmd = false; // .CONTINUE command given already? // go into main loop for (;;) { #if defined (_MSC_VER) && _MSC_VER < 1800 _clearfp(); #else feclearexcept(FE_ALL_EXCEPT); #endif try { if (runCmd) { runCmd = false; continueCmd = false; RunDelTree(); } else { DInterpreter::CommandCode ret = ExecuteLine(); // stop steppig when at main level stepCount = 0; debugMode = DEBUG_CLEAR; if (ret == CC_SKIP) { Message("Can't continue from this point."); } else if (ret == CC_CONTINUE) { if (static_cast (callStack.back()->GetPro())->GetTree() != NULL) { if (continueCmd) runCmd = true; else { cout << SysVar::MsgPrefix() << "Starting at: $MAIN$" << endl; continueCmd = true; } } else cout << SysVar::MsgPrefix() << "Cannot continue from this point." << endl; } } } catch (RetAllException& retAllEx) { runCmd = (retAllEx.Code() == RetAllException::RUN); bool resetCmd = (retAllEx.Code() == RetAllException::RESET); bool fullResetCmd = (retAllEx.Code() == RetAllException::FULL_RESET); if (resetCmd || fullResetCmd) { // remove $MAIN$ delete callStack.back(); callStack.pop_back(); assert(callStack.empty()); ResetObjects(); ResetHeap(); if (fullResetCmd) { PurgeContainer(libFunList); PurgeContainer(libProList); } // initially done in InitGDL() // initializations InitObjects(); // init library functions if (fullResetCmd) { LibInit(); } // initially done in constructor: setup main level environment DPro* mainPro = new DPro(); // $MAIN$ NOT inserted into proList EnvUDT* mainEnv = new EnvUDT(NULL, mainPro); callStack.push_back(mainEnv); // push main environment (necessary) // re-process startup file if (startup != "") { ifstream in(startup.c_str()); if (in.fail()) Warning("Error opening startup file: " + startup); ValueGuard guard(interruptEnable); interruptEnable = false; bool runCmd = false; try { while (in.good()) { #if defined (_MSC_VER) && _MSC_VER < 1800 _clearfp(); #else feclearexcept(FE_ALL_EXCEPT); #endif try { if (runCmd) { runCmd = false; RunDelTree(); } else { DInterpreter::CommandCode ret = ExecuteLine(&in); if (debugMode != DEBUG_CLEAR) { debugMode = DEBUG_CLEAR; Warning("Prematurely closing batch file: " + startup); break; } } } catch (RetAllException& retAllEx) { runCmd = (retAllEx.Code() == RetAllException::RUN); if (!runCmd) throw; } catch (exception& e) { cerr << startup << ": Exception: " << e.what() << endl; } catch (...) { cerr << startup << ": Unhandled Error." << endl; } } // while } catch (RetAllException& retAllEx) { } } // if( startup... } } catch (exception& e) { cerr << "InterpreterLoop: Exception: " << e.what() << endl; } catch (...) { cerr << "InterpreterLoop: Unhandled Error." << endl; } } } gdl-0.9.9/src/dinterpreter.hpp000066400000000000000000000112301340051421000162710ustar00rootroot00000000000000/*************************************************************************** dinterpreter.hpp - main class which controls it all ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DINTERPRETER_HPP_ #define DINTERPRETER_HPP_ #ifdef HAVE_CONFIG_H #include #endif #include #include #ifdef __cplusplus extern "C" { #if defined(__OpenBSD__) // SA: based on http://ftp2.cz.freesbie.org/pub/FreeBSD-cvs/gnats/i386/75862 # include # define feclearexcept(e) (void)fpsetsticky(~((fp_except)(e))) # define fetestexcept(e) ((int)(fpgetsticky() & (fp_except)(e))) # define FE_ALL_EXCEPT (FP_X_INV | FP_X_DNML | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP) # define FE_DIVBYZERO FP_X_DZ # define FE_INEXACT FP_X_IMP # define FE_INVALID FP_X_INV # define FE_OVERFLOW FP_X_OFL # define FE_UNDERFLOW FP_X_UFL #elif defined(_MSC_VER) && _MSC_VER < 1800 # include # pragma fenv_access(on) #else # ifdef __MINGW32__ // hack for MINGW # define FE_INVALID 0x01 # define FE_DENORMAL 0x02 # define FE_DIVBYZERO 0x04 # define FE_OVERFLOW 0x08 # define FE_UNDERFLOW 0x10 # define FE_INEXACT 0x20 # define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO \ | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) extern int __cdecl __MINGW_NOTHROW feclearexcept (int); extern int __cdecl __MINGW_NOTHROW fetestexcept (int excepts); # endif # include #endif # if defined(__FreeBSD__) # pragma STDC FENV_ACCESS ON # endif } #endif //#include "initsysvar.hpp" //#include "objects.hpp" #include "GDLLexer.hpp" #include "GDLParser.hpp" #include "GDLTreeParser.hpp" #include "GDLInterpreter.hpp" //#include "gdleventhandler.hpp" #ifdef HAVE_LIBREADLINE #include #include #endif #ifdef HAVE_LIBEDITLINE #include extern int (*rl_event_hook)(); /* missing from editline/readline.h */ // see https://sourceforge.net/p/ngspice/ngspice/ci/master/tree/src/main.c #endif #include #include // enable to print out an expression entered at the comand line #define AUTO_PRINT_EXPR void ControlCHandler(int); extern bool lineEdit; // = false; extern bool historyIntialized; extern std::string actualPrompt; class DInterpreter: public GDLInterpreter { public: enum CommandCode { CC_OK=0, CC_CONTINUE, CC_STEP, CC_SKIP, CC_RETURN }; char* NoReadline(const std::string&); private: // execute GDL command (.run, .step, ...) CommandCode ExecuteCommand(const std::string& command); CommandCode CmdCompile(const std::string& command); CommandCode CmdRun(const std::string& command); CommandCode CmdReset(); CommandCode CmdFullReset(); // execute OS shell command (interactive shell if command == "") static void ExecuteShellCommand(const std::string& command); std::string GetLine(); // get one line of input, trims it void RunDelTree(); public: ~DInterpreter() { #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) // seems to cause valgrind to complain clear_history(); // for testing of memory leaks (in GDL) #endif } // this is executed at the beginning (gdl.cpp) DInterpreter(); // execute one line of code CommandCode ExecuteLine( std::istream* in = NULL, SizeT lineOffset = 0); // execute a whole file (used by @ and for batch files specified as arguments to gdl) void ExecuteFile( const std::string& file); // run a list of commands from 'in'. Used by python module. Returns success bool RunBatch( std::istream* in); // the main program for interactive mode RetCode InterpreterLoop( const std::string& startup, std::vector& batch_files, const std::string& statement); // called within InterpreterLoop() RetCode InnerInterpreterLoop(SizeT lineOffset); }; #endif gdl-0.9.9/src/dll/000077500000000000000000000000001340051421000136275ustar00rootroot00000000000000gdl-0.9.9/src/dll/two.cpp000066400000000000000000000013651340051421000151510ustar00rootroot00000000000000#include "envt.hpp" using namespace std; template< typename T> BaseGDL* two_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); for( SizeT i=0; iNParam(); if (nParam != 1) { cout << "TWO: Improper Number of Variables" << endl; return new DLongGDL( -1); } BaseGDL* p0 = e->GetPar( 0);//, "TWO"); if( p0->Type() == GDL_DOUBLE) return two_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return two_fun_template< DFloatGDL>( p0); else { return new DLongGDL( -1); } } gdl-0.9.9/src/dnode.cpp000066400000000000000000000205051340051421000146530ustar00rootroot00000000000000/*************************************************************************** dnode.cpp - GDL's AST is made of DNodes ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include #include "dnode.hpp" #include "datatypes.hpp" #include "arrayindexlistt.hpp" #include "dinterpreter.hpp" #include "objects.hpp" // SA: fun/proList for warning about obsolete-routine calls #include using namespace std; namespace antlr { RefAST ConvertAST( ProgNodeP p) { if( p == NULL) return TreeParser::ASTNULL; RefDNode refNode = RefDNode( new DNode); refNode->setType( p->getType()); refNode->setText( p->getText()); refNode->SetLine( p->getLine()); return static_cast( refNode); } } DInterpreter* ProgNode::interpreter; DNode::DNode( const DNode& cp): // keepRight( false), CommonAST( cp), //down(), right(), lineNumber( cp.getLine()), cData(NULL), var(cp.var), libFun( cp.libFun), libPro( cp.libPro), arrIxList(NULL),arrIxListNoAssoc(NULL), labelStart( cp.labelStart), labelEnd( cp.labelEnd) { if( cp.cData != NULL) cData = cp.cData->Dup(); if( cp.arrIxList != NULL) arrIxList = cp.arrIxList->Clone(); if( cp.arrIxListNoAssoc != NULL) arrIxListNoAssoc = cp.arrIxListNoAssoc->Clone(); // arrIxList = new ArrayIndexListT( *cp.arrIxList); initInt = cp.initInt; } ArrayIndexListT* DNode::CloneArrIxList() { if( arrIxList == NULL) return NULL; return arrIxList->Clone(); } ArrayIndexListT* DNode::CloneArrIxNoAssocList() { if( arrIxListNoAssoc == NULL) return NULL; return arrIxListNoAssoc->Clone(); } void DNode::ResetCData( BaseGDL* newCData) { // delete cData; // as used (UMinus, ARRARYDEF_CONST) deletion is done automatically cData = newCData; } void DNode::RemoveNextSibling() { right = static_cast(static_cast(antlr::nullAST)); } DNode::~DNode() { // delete cData in case this node is a constant if( (getType() == GDLTokenTypes::CONSTANT) && cData != NULL) { GDLDelete(cData); } if( (getType() == GDLTokenTypes::ARRAYIX)) { delete arrIxList; delete arrIxListNoAssoc; } } void DNode::Text2Byte(int base) { // cout << "byte" << endl; DByte val; Text2Number( val, base); cData=new DByteGDL(val); } // promote: make Long (Long64) if number is to large void DNode::Text2Int(int base, bool promote) { static const DLong64 maxDInt= static_cast(numeric_limits::max()); static const DLong64 maxDLong= static_cast(numeric_limits::max()); if( promote) { DLong64 ll; Text2Number( ll, base); if( ll <= maxDInt) { DInt val = static_cast(ll); cData=new DIntGDL( val); } else if( ll <= maxDLong) { DLong val = static_cast(ll); cData=new DLongGDL( val); } else { cData=new DLong64GDL( ll); } } else { DInt val; Text2Number( val, base); cData=new DIntGDL(val); } } void DNode::Text2UInt(int base, bool promote) { static const DULong64 maxDUInt= static_cast(numeric_limits::max()); static const DULong64 maxDULong= static_cast(numeric_limits::max()); if( promote) { DULong64 ll; Text2Number( ll, base); if( ll <= maxDUInt) { DUInt val = static_cast(ll); cData=new DUIntGDL( val); } else if( ll <= maxDULong) { DULong val = static_cast(ll); cData=new DULongGDL( val); } else { cData=new DULong64GDL( ll); } } else { DUInt val; Text2Number( val, base); cData=new DUIntGDL(val); } } void DNode::Text2Long(int base, bool promote) { static const DLong64 maxDInt= static_cast(numeric_limits::max()); static const DLong64 maxDLong= static_cast(numeric_limits::max()); if( promote) { DLong64 ll; Text2Number( ll, base); if( ll <= maxDLong) { DLong val = static_cast(ll); cData=new DLongGDL( val); } else { cData=new DLong64GDL( ll); } return; } if( base == 16) { if( text.size() > sizeof( DLong)*2) throw GDLException( "Long hexadecimal constant can only have "+ i2s(sizeof( DLong)*2)+" digits."); DLong val; Text2Number( val, base); cData=new DLongGDL(val); return; } DLong64 val; bool noOverFlow = Text2Number( val, base); if( !noOverFlow || val > std::numeric_limits< DLong>::max()) throw GDLException( "Long constant must be smaller than or equal to "+ i2s(std::numeric_limits< DLong>::max())); cData=new DLongGDL(val); } void DNode::Text2ULong(int base, bool promote) { static const DULong64 maxDUInt= static_cast(numeric_limits::max()); static const DULong64 maxDULong= static_cast(numeric_limits::max()); if( promote) { DULong64 ll; Text2Number( ll, base); if( ll <= maxDULong) { DULong val = static_cast(ll); cData=new DULongGDL( val); } else { cData=new DULong64GDL( ll); } return; } if( base == 16) { if( text.size() > sizeof(DULong)*2) throw GDLException( "ULong hexadecimal constant can only have "+ i2s(sizeof( DLong)*2)+" digits."); DULong val; Text2Number( val, base); cData=new DULongGDL(val); return; } DULong64 val; bool noOverFlow = Text2Number( val, base); if( !noOverFlow || val > std::numeric_limits< DULong>::max()) throw GDLException( "ULong constant must be smaller than or equal to "+ i2s(std::numeric_limits< DULong>::max())); cData=new DULongGDL(val); } void DNode::Text2Long64(int base) { DLong64 val; bool noOverFlow = Text2Number( val, base); if( noOverFlow) cData=new DLong64GDL(val); else cData=new DLong64GDL( -1); } void DNode::Text2ULong64(int base) { DULong64 val; bool noOverFlow = Text2Number( val, base); if( noOverFlow) cData=new DULong64GDL(val); else cData=new DULong64GDL( std::numeric_limits< DULong64>::max()); } void DNode::Text2Float() { const char* cStr=text.c_str(); #ifdef _MSC_VER DFloat val=strtod(cStr,NULL); #else DFloat val=strtof(cStr,NULL); #endif cData=new DFloatGDL(val); } void DNode::Text2Double() { const char* cStr=text.c_str(); DDouble val=strtod(cStr,NULL); cData=new DDoubleGDL(val); } void DNode::Text2String() { cData=new DStringGDL(text); } // used by DNodeFactory void DNode::initialize( RefDNode t ) { CommonAST::setType( t->getType()); CommonAST::setText( t->getText()); DNode::SetLine(t->getLine() ); if( t->getType() == GDLTokenTypes::CONSTANT) { if( t->cData != NULL) cData=t->cData->Dup(); else cData = NULL; } else if( t->getType() == GDLTokenTypes::GOTO) { targetIx=t->targetIx; } else if( t->getType() == GDLTokenTypes::SYSVAR || t->getType() == GDLTokenTypes::VARPTR) { var=t->var; } else { initInt=t->initInt; } labelStart = t->labelStart; labelEnd = t->labelEnd; // copy union stuff //initPtr=t->initPtr; } void DNode::SetFunIx(const int ix) { funIx = ix; if (ix != -1 && funList[ix]->isObsolete()) WarnAboutObsoleteRoutine(this, funList[ix]->Name()); } void DNode::SetProIx(const int ix) { proIx = ix; if (ix != -1 && proList[ix]->isObsolete()) WarnAboutObsoleteRoutine(this, proList[ix]->Name()); } gdl-0.9.9/src/dnode.hpp000066400000000000000000000211751340051421000146640ustar00rootroot00000000000000/*************************************************************************** dnode.hpp - the node used for the AST ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef dnode_hpp__ #define dnode_hpp__ #include #include #include #include "typedefs.hpp" #include "GDLTokenTypes.hpp" #include //ANTLR_USING_NAMESPACE(std) //ANTLR_USING_NAMESPACE(antlr) // used together with some defines do // allow using non-ref nodes with ANTLR // see gdlc.i.g class ProgNode; typedef ProgNode* ProgNodeP; namespace antlr { RefAST ConvertAST( ProgNodeP p); } class DInterpreter; class DNode; typedef antlr::ASTRefCount RefDNode; class DVar; class DPro; class DLibFun; class DLibPro; class BaseGDL; class ArrayIndexListT; class DNode : public antlr::CommonAST { public: ~DNode(); DNode(): CommonAST(), //down(), right(), // keepRight( false), lineNumber(0), cData(NULL), var(NULL), libFun(NULL), libPro(NULL), arrIxList(NULL),arrIxListNoAssoc(NULL), labelStart( -1), labelEnd( -1) { } DNode( const DNode& cp); DNode(antlr::RefToken t) : antlr::CommonAST(t) //, down(), right() // , keepRight( false) { // antlr::CommonAST::setType(t->getType() ); // antlr::CommonAST::setText(t->getText() ); DNode::SetLine(t->getLine() ); } // void DoKeepRight() { keepRight = true;} void initialize(int t, const std::string& txt) { antlr::CommonAST::setType(t); antlr::CommonAST::setText(txt); // keepRight = false; lineNumber = 0; cData=NULL; libFun=NULL; libPro=NULL; labelStart = -1; labelEnd = -1; var=NULL; arrIxList=NULL; arrIxListNoAssoc=NULL; } // used by DNodeFactory void initialize( RefDNode t ); // we deal only with RefDNode here void initialize( antlr::RefAST t ) { // antlr::CommonAST::initialize(t); initialize(static_cast(t)); } void initialize( antlr::RefToken t ) { antlr::CommonAST::initialize(t); // DNode::SetLine( t->getLine()); SetLine( t->getLine()); } antlr::RefAST clone( void ) const { DNode *newNode = new DNode( *this); return antlr::RefAST( newNode); } void setText(const std::string& txt) { antlr::CommonAST::setText(txt); } void setType(int type) { antlr::CommonAST::setType(type); } void addChild( RefDNode c ) { BaseAST::addChild( static_cast(c) ); } static antlr::RefAST factory() { antlr::RefAST ret = static_cast(RefDNode(new DNode)); return ret; } RefDNode GetFirstChild() const { return static_cast(BaseAST::getFirstChild()); } RefDNode GetNextSibling() const { return static_cast(BaseAST::getNextSibling()); } void RemoveNextSibling(); // Extensions void SetLine(int l_) { lineNumber = l_; } int getLine() const { if( lineNumber != 0 || BaseAST::getFirstChild() == NULL) return lineNumber; // this handles inserted nodes return static_cast(BaseAST::getFirstChild())->getLine(); // This was just too clever :-) // if( lineNumber != 0) // return lineNumber; // else // { // if( BaseAST::getFirstChild() == NULL) // { // if( BaseAST::getNextSibling() == NULL) // { // return lineNumber; // } // else // { // return // static_cast(BaseAST::getNextSibling())->getLine(); // } // return lineNumber; // } // else // { // return // static_cast(BaseAST::getFirstChild())->getLine(); // } // } } void SetVarIx(int vIx) { varIx=vIx; } void SetVar(DVar* v) { var=v; } template bool Text2Number( T& out, int base) { bool noOverflow = true; T number=0; for(unsigned i=0; i < text.size(); ++i) { char c=text[i]; if( c >= '0' && c <= '9') { c -= '0'; } else if( c >= 'a' && c <= 'f') { c -= 'a'-10; } else { c -= 'A'-10; } T newNumber = base * number + c; // check for overflow if( newNumber < number) { noOverflow = false; } number=newNumber; } out=number; return noOverflow; } void Text2Byte(int base); // promote: use Long if number to large void Text2Int(int base, bool promote=false); void Text2UInt(int base, bool promote=false); void Text2Long(int base, bool promote=false); void Text2ULong(int base, bool promote=false); void Text2Long64(int base); void Text2ULong64(int base); void Text2Float(); void Text2Double(); void Text2String(); void SetNumBranch(const int nB) { numBranch=nB;} void SetArrayDepth(const int aD) { arrayDepth=aD;} void SetFunIx(const int ix); void SetProIx(const int ix); void SetLibFun(DLibFun* const l) { libFun=l;} void SetLibPro(DLibPro* const l) { libPro=l;} void SetNDot(const int n) { nDot=n;} int GetNDot() const { return nDot;} void SetNParam(const int n) { nParam=n;} int GetNParam() const { return nParam;} void SetCompileOpt(const int n) { compileOpt=n; } int GetCompileOpt() { return compileOpt; } void SetLabelRange( const int s, const int e) { labelStart = s; labelEnd = e;} // bool LabelInRange( const int lIx) // { return (lIx >= labelStart) && (lIx < labelEnd);} void DefinedStruct( const bool noTagName) { if( noTagName) structDefined = 1; else structDefined = 0;} void SetArrayIndexList( ArrayIndexListT* aL, ArrayIndexListT* aLNoAssoc) { arrIxList = aL; arrIxListNoAssoc = aLNoAssoc; } BaseGDL* CData() { return cData;} void ResetCData( BaseGDL* newCData); DVar* GetVar() { return var;} int GetVarIx() { return varIx;} private: BaseGDL* StealCData() { BaseGDL* res = cData; cData=NULL; return res;} ArrayIndexListT* StealArrIxList() { ArrayIndexListT* res = arrIxList; arrIxList=NULL; return res;} ArrayIndexListT* CloneArrIxList(); ArrayIndexListT* StealArrIxNoAssocList() { ArrayIndexListT* res = arrIxListNoAssoc; arrIxListNoAssoc=NULL; return res;} ArrayIndexListT* CloneArrIxNoAssocList(); // bool keepRight; // for passing to ProgNode, nodes here are reference counted // RefDNode down; // RefDNode right; // track line number in node int lineNumber; // void* initPtr; // for c-i not actaully used BaseGDL* cData; // constant data // DNode* gotoTarget; // for goto statement DVar* var; // ptr to variable (for system variables and common blocks) DLibFun* libFun; DLibPro* libPro; ArrayIndexListT* arrIxList; // ptr to array index list ArrayIndexListT* arrIxListNoAssoc; // ptr to array index list // ArrayIndexT* arrIx; // ptr to array index (1-dim) union { int initInt; // for c-i not actually used int numBranch; // number of branches in switch/case statements int nDot; // nesting level for tag access int arrayDepth; // dimension to cat int proIx; // Index into proList int funIx; // Index into funList int varIx; // Index into variable list int targetIx; // Index into label list int structDefined; // struct contains entry with no tag name int nParam; // number of positional parameters in this parameter list, // stored at first parameter (keyword or positional) int compileOpt; // for PRO and FUNCTION nodes }; int labelStart; // for loops to determine if to bail out int labelEnd; // for loops to determine if to bail out friend class ProgNode; friend class DCompiler; friend class GDLTreeParser; // private: // // forbid usage of these // DNode& operator=( const DNode& r) // { return *this;} // make c++ compiler shut up // DNode( const DNode& cp) // {} }; #endif gdl-0.9.9/src/dnodefactory.hpp000066400000000000000000000023231340051421000162460ustar00rootroot00000000000000/*************************************************************************** dnodefactory.hpp ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DNodeFactory_hpp__ #define DNodeFactory_hpp__ #include "dnode.hpp" #include //ANTLR_USING_NAMESPACE(std) //ANTLR_USING_NAMESPACE(antlr) extern antlr::ASTFactory DNodeFactory; #endif gdl-0.9.9/src/dpro.cpp000066400000000000000000000266631340051421000145410ustar00rootroot00000000000000/*************************************************************************** dpro.cpp - GDL procedures/functions ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // DPro/DFun classes #include "includefirst.hpp" #include "dpro.hpp" #include "dvar.hpp" #include "str.hpp" #include "objects.hpp" #include "GDLTreeParser.hpp" #include "GDLParser.hpp" // SA: GDLParser::CompileOpt for isObsolete()/isHidden() // print out AST tree //#define GDL_DEBUG #undef GDL_DEBUG #ifdef GDL_DEBUG #include "print_tree.hpp" #endif using namespace std; // vtable DSub::~DSub() {} // DLib ****************************************************** DLib::DLib( const string& n, const string& o, const int nPar_, const string keyNames[], const string warnKeyNames[], const int nParMin_) : DSub(n,o) , hideHelp( false) { nPar=nPar_; nParMin = nParMin_; // find out number of keywords and set them SizeT nKey_=0; if( keyNames != NULL) { while( keyNames[nKey_] != "") ++nKey_; } key.resize(nKey_); for( SizeT k=0; k= 1) { if( keyNames[0] == "_EXTRA") { extra = EXTRA; extraIx = 0; } else if( keyNames[0] == "_REF_EXTRA") { extra = REFEXTRA; extraIx = 0; } } SizeT nWarnKey_=0; if( warnKeyNames != NULL) { while( warnKeyNames[nWarnKey_] != "") ++nWarnKey_; } warnKey.resize(nWarnKey_); for( SizeT wk=0; wk 1) s += ",["+i2s( nPar)+" Args]"; for( SizeT i=0; i 1) s += ",["+i2s( nPar)+" Args]"; for( SizeT i=0; i 1) s += "["+i2s( nPar)+" Args]"; if( key.size() > 0) { if( nPar != 0) s += ","; for( SizeT i=0; i 1) s += "["+i2s( nPar)+" Args]"; if( key.size() > 0) { if( nPar != 0) s += ","; for( SizeT i=0; i(*it); delete cRef; // also ok if cRef is NULL } labelList.Clear(); delete tree; } DSubUD::DSubUD(const string& n,const string& o,const string& f) : DSub(n,o), file(f), tree( NULL), compileOpt(GDLParser::NONE), labelList(), nForLoops( 0) { if( o != "") AddPar( "SELF"); } // for .RNEW and $MAIN$ // clears all COMMON blocks, VARIABLES, JUMPLABELS and the CODE // name, keywords etc. are kept void DSubUD::Reset() { var.clear(); // delete only common references (common blocks only if owner) CommonBaseListT::iterator it; for( it=common.begin(); it !=common.end(); ++it) { DCommonRef* cRef=dynamic_cast(*it); delete cRef; // also ok if cRef is NULL } common.clear(); DelTree(); } void DSubUD::DelTree() { labelList.Clear(); // labels are invalid after tree is deleted delete tree; tree = NULL; //static_cast(antlr::nullAST); nForLoops = 0; } DSubUD* DSubUD::AddPar(const string& p) { var.push_back(p); nPar++; return this; } unsigned DSubUD::AddVar(const string& v) { var.push_back(v); return var.size()-1; } DSubUD* DSubUD::AddKey(const string& k, const string& v) { if( k == "_REF_EXTRA") { if( extra == EXTRA) throw GDLException("Routines cannot be declared with both" " _EXTRA and _REF_EXTRA."); extra=REFEXTRA; extraIx=0; } else if( k == "_EXTRA") { if( extra == REFEXTRA) throw GDLException("Routines cannot be declared with both" " _EXTRA and _REF_EXTRA."); extra=EXTRA; extraIx=0; } else { if(extraIx != -1) extraIx++; // update extra ix index } // as we only push_front during compilation, we better use a vector here // key.push_front(k); // var.push_back(v); // we want push_front key.resize( key.size() + 1); for( int i= key.size()-1; i>0; --i) key[ i] = key[ i-1]; key[ 0] = k; var.resize( var.size() + 1); for( int i= var.size()-1; i>0; --i) var[ i] = var[ i-1]; var[ 0] = v; return this; } // must be done after the tree is converted void DSubUD::ResolveAllLabels() { ResolveLabel( tree); } void DSubUD::ResolveLabel( ProgNodeP p) { if( p == NULL) return; // if( p->getNextSibling() != NULL) // std::cout << "Resolve("<< p->getLine()<<"): " << p << " keepRight: " << p->KeepRight()<< ": "<< p->getText() <<" r: "<< p->GetNextSibling()->getText() << std::endl; // else // std::cout << "Resolve("<< p->getLine()<<"): " << p << " keepRight: " << p->KeepRight()<< ": "<< p->getText() <<" r: NULL"<< std::endl; if( p->getType() == GDLTreeParser::ON_IOERROR || p->getType() == GDLTreeParser::GOTO) { int ix = labelList.Find( p->getText()); if( ix == -1) throw GDLException( p, ObjectName()+": Undefined label "+p->getText()+ " referenced in GOTO statement.",false,false); p->SetGotoIx( ix); } else if( p->getType() == GDLTreeParser::LABEL) { labelList.SetLabelNode( p); } if( !p->KeepDown()) ResolveLabel( p->getFirstChild()); if( !p->KeepRight()) ResolveLabel( p->getNextSibling()); // else // ResolveLabel( p->getNextSibling()); } // ************************************** // the final "compilation" takes part here // ************************************** void DSubUD::SetTree( RefDNode n) { // // Converter Translation Transcription Rewrite RefDNode ProgNode ProgNodeP // *************************************************** // here the conversion RefDNode -> ProgNode is done // *************************************************** tree = ProgNode::NewProgNode( n); // if( tree != NULL) nForLoops = ProgNode::NumberForLoops( tree); // else // nForLoops = 0; #ifdef GDL_DEBUG cout << "DSubUD::SetTree:" << endl; antlr::print_tree pt; pt.pr_tree(tree); cout << "DSubUD::SetTree end." << endl; #endif } bool DSubUD::GetCommonVarName(const BaseGDL* p, std::string& varName) { CommonBaseListT::iterator it; for( it=common.begin(); it != common.end(); it++) { int vIx = (*it)->Find( p); if( vIx >= 0) { varName=(*it)->VarName( vIx); return true; } } return false; } BaseGDL* DSubUD::GetCommonVarNameList() { DStringGDL* res = new DStringGDL(dimension(this->CommonsSize()), BaseGDL::NOZERO); CommonBaseListT::iterator it; SizeT iname=0; for( it=common.begin(); it != common.end(); it++) { SizeT nVar=(*it)->NVar(); for (SizeT i=0; i< nVar ; ++i) (*res)[iname++]=(*it)->VarName(i); } return res; } bool DSubUD::GetCommonVarName4Help(const BaseGDL* p, std::string& varName) { CommonBaseListT::iterator it; for( it=common.begin(); it != common.end(); it++) { int vIx = (*it)->Find( p); if( vIx >= 0) { varName=(*it)->VarName( vIx) +" ("+(*it)->Name()+')'; return true; } } return false; } bool DSubUD::isObsolete() { return compileOpt & GDLParser::OBSOLETE; } bool DSubUD::isStatic() { return compileOpt & GDLParser::STATIC; } bool DSubUD::isHidden() { return compileOpt & GDLParser::HIDDEN; } gdl-0.9.9/src/dpro.hpp000066400000000000000000000342471340051421000145430ustar00rootroot00000000000000/*************************************************************************** dpro.hpp - GDL procedure/function ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DPRO_HPP_ #define DPRO_HPP_ // #include #include #include #include //#include #include "basegdl.hpp" #include "dcommon.hpp" #include "dvar.hpp" #include "prognode.hpp" #include "str.hpp" #include template class Is_eq: public std::unary_function { std::string name; public: explicit Is_eq(const std::string& n): name(n) {} bool operator() (const T* p) const { return (p->Name() == name);} }; // for jumps (goto, on_ioerror) struct LabelT { std::string label; ProgNodeP target; LabelT( const std::string& l, ProgNodeP t): label( l), target( t) {} }; class LabelListT { std::vector list; public: LabelListT(): list() {} ~LabelListT() {} void Add( const std::string& l, ProgNodeP t) { list.push_back( LabelT( l, t)); } SizeT Size() { return list.size();} int Find( const std::string& s) { SizeT nEl = list.size(); for( SizeT i=0; i(i); return -1; } ProgNodeP Get( SizeT ix) { return list[ ix].target; } void SetLabelNode( ProgNodeP t) { int ix = Find( t->getText()); // already checked for presence list[ ix].target = t; } const std::string& GetLabel( SizeT ix) { return list[ ix].label; } void Clear() { list.clear(); } }; // Fun/Pro classes ***************************************************** // Base class ********************************************************** class DSub { public: enum ExtraType { NONE=0, EXTRA, REFEXTRA }; protected: std::string name; // name (of procedure/function) std::string object; // name of class for methods (might not be defined // when method is compiled) // keywords are pushed in front so they are first // followed by the parameters // (which are pushed back, // but due to the syntax are first, // so the layout is: // keyVar_N (ID in key[0]),..,keyVar_1 (key[n-1]), // par_1,..,par_nPar, var1,..,varK // N=size(key) // K=size(var)-nPar-N KeyVarListT key; // keyword names (IDList: typedefs.hpp) // (KEYWORD_NAME=keyword_value) int nPar; // number of parameters (-1 = infinite) int nParMin; // minimum number of parameters (-1 = infinite) ExtraType extra; int extraIx; // index of extra keyword IDList warnKey; // keyword names to accept but warn // (IDList: typedefs.hpp) public: DSub( const std::string& n, const std::string& o=""): name(n), object(o), key(), nPar(0), nParMin(0), extra(NONE), extraIx(-1), warnKey() {} virtual ~DSub(); // polymorphism const std::string& Name() const { return name;} const std::string& Object() const { return object;} std::string ObjectName() const { if( object == "") return name; return object+"::"+name; } std::string ObjectFileName() const { if( object == "") return name; return object+"__"+name; } ExtraType Extra() { return extra; } int ExtraIx() { return extraIx; } // returns the (abbreviated) keyword value index int FindKey(const std::string& s) { String_abbref_eq searchKey(s); int ix=0; for(KeyVarListT::iterator i=key.begin(); i != key.end(); ++i, ++ix) if( searchKey(*i)) { return ix; } return -1; } int NKey() const { return key.size();} int NPar() const { return nPar;} int NParMin() const { return nParMin;} // bool AKey() { return aKey;} // additional keywords allowed friend class EnvBaseT; friend class EnvT; friend class ExtraT; friend void SetupOverloadSubroutines(); // overload base class methods }; // Lib pro/fun ******************************************************** // moved to prognode.hpp // class EnvT; // // typedef void (*LibPro)(EnvT*); // typedef BaseGDL* (*LibFun)(EnvT*); // typedef BaseGDL* (*LibFunDirect)(BaseGDL* param,bool canGrab); // library procedure/function (in cases both are handled the same way) class DLib: public DSub { bool hideHelp; // if set HELP,/LIB will not list this subroutine public: DLib( const std::string& n, const std::string& o, const int nPar_, const std::string keyNames[], const std::string warnKeyNames[], const int nParMin_); virtual const std::string ToString() = 0; bool GetHideHelp() const { return hideHelp;} void SetHideHelp( bool v) { hideHelp = v;} // for sorting lists by name. Not used (lists too short to make a time gain. Long lists would, if existing, // benefit from sorting by hash number in a std::map instead of a std::list. struct CompLibFunName: public std::binary_function< DLib*, DLib*, bool> { bool operator() ( DLib* f1, DLib* f2) const { return f1->ObjectName() < f2->ObjectName();} }; }; // library procedure class DLibPro: public DLib { LibPro pro; public: // warnKeyNames are keywords wich are not supported, but which // should not make the compilation fail. // A warning will be issued. // use this for keywords which are truly optional and don't // change the results. // Note that due to their nature, there should never be keywords // on which a value is returned. DLibPro( LibPro p, const std::string& n, const int nPar_=0, const std::string keyNames[]=NULL, const std::string warnKeyNames[]=NULL, const int nParMin_=0); DLibPro( LibPro p, const std::string& n, const std::string& o, const int nPar_=0, const std::string keyNames[]=NULL, const std::string warnKeyNames[]=NULL, const int nParMin_=0); LibPro Pro() { return pro;} const std::string ToString(); }; // library function class DLibFun: public DLib { LibFun fun; public: DLibFun( LibFun f, const std::string& n, const int nPar_=0, const std::string keyNames[]=NULL, const std::string warnKeyNames[]=NULL, const int nParMin_=0); DLibFun( LibFun f, const std::string& n, const std::string& o, const int nPar_=0, const std::string keyNames[]=NULL, const std::string warnKeyNames[]=NULL, const int nParMin_=0); LibFun Fun() { return fun;} const std::string ToString(); virtual bool RetNew() { return false;} virtual bool DirectCall() { return false;} }; // library function which ALWAYS return a new value // (as opposite to returning an input value) class DLibFunRetNew: public DLibFun { bool retConstant; // means: can be pre-evaluated with constant input public: DLibFunRetNew( LibFun f, const std::string& n, const int nPar_=0, const std::string keyNames[]=NULL, const std::string warnKeyNames[]=NULL, bool rConstant=false, const int nParMin_=0); DLibFunRetNew( LibFun f, const std::string& n, const std::string& o, const int nPar_=0, const std::string keyNames[]=NULL, const std::string warnKeyNames[]=NULL, const int nParMin_=0); bool RetNew() { return true;} bool RetConstant() { return this->retConstant;} }; // direct call functions must have: // ony one parameter, no keywords // these functions are called "direct", no environment is created class DLibFunDirect: public DLibFunRetNew { LibFunDirect funDirect; public: DLibFunDirect( LibFunDirect f, const std::string& n, bool retConstant_=true); LibFunDirect FunDirect() { return funDirect;} // bool RetNew() { return true;} bool DirectCall() { return true;} }; // UD pro/fun ******************************************************** // function/procedure (differ because they are in different lists) // User Defined class DSubUD: public DSub { std::string file; // filename were procedure is defined in KeyVarListT var; // keyword values, parameters, local variables CommonBaseListT common; // common blocks or references ProgNodeP tree; // the 'code' unsigned int compileOpt; // e.g. hidden or obsolete LabelListT labelList; void ResolveLabel( ProgNodeP); protected: int nForLoops; public: DSubUD(const std::string&,const std::string& o="",const std::string& f=""); ~DSubUD(); void Reset(); void DelTree(); void SetTree( ProgNodeP t) { tree = t;} void AddCommon(DCommonBase* c) { common.push_back(c);} void DeleteLastAddedCommon(bool kill=true) { if(kill) delete common.back(); common.pop_back(); } void commonPtrs( std::vector& cptr) { cptr.clear(); CommonBaseListT::iterator c = common.begin(); for(; c != common.end(); ++c) cptr.push_back((*c)); return; } void ResolveAllLabels(); LabelListT& LabelList() { return labelList;} ProgNodeP GotoTarget( int ix) { if( ix >= labelList.Size()) throw GDLException( "Undefined label."); return labelList.Get( ix); } // int LabelOrd( int ix) { return labelList.GetOrd( ix);} int NDefLabel() { return labelList.Size();} std::string GetFilename() { return file; } // add variables DSubUD* AddPar(const std::string&); // add paramter unsigned AddVar(const std::string&); // add local variable DSubUD* AddKey(const std::string&, const std::string&); // add keyword=value void DelVar(const int ix) {var.erase(var.begin() + ix);} void Resize( SizeT s) { var.resize( s);} SizeT Size() {return var.size();} SizeT CommonsSize() { SizeT commonsize=0; CommonBaseListT::iterator c = common.begin(); for(; c != common.end(); ++c) commonsize+=(*c)->NVar(); return commonsize; } int NForLoops() const { return nForLoops;} // search for variable returns true if its found in var or common blocks bool Find(const std::string& n) { KeyVarListT::iterator f=std::find(var.begin(),var.end(),n); if( f != var.end()) return true; CommonBaseListT::iterator c= std::find_if(common.begin(),common.end(),DCommon_contains_var(n)); return (c != common.end()); } // returns common block with name n DCommon* Common(const std::string& n) { CommonBaseListT::iterator c = common.begin(); for(; c != common.end(); ++c) if( dynamic_cast< DCommon*>( *c) != NULL && (*c)->Name() == n) return static_cast< DCommon*>( *c); return NULL; } // returns common block which holds variable n DCommonBase* FindCommon(const std::string& n) { CommonBaseListT::iterator c= std::find_if(common.begin(),common.end(),DCommon_contains_var(n)); return (c != common.end())? *c : NULL; } void ReName( SizeT ix, const std::string& s) { var[ix] = s; return; } const std::string& GetVarName( SizeT ix) { return var[ix]; } const std::string& GetKWName( SizeT ix) { return key[ix]; } BaseGDL* GetCommonVarNameList(); bool GetCommonVarName(const BaseGDL* p, std::string& varName); bool GetCommonVarName4Help(const BaseGDL* p, std::string& varName); BaseGDL** GetCommonVarPtr(const BaseGDL* p) { for( CommonBaseListT::iterator c=common.begin(); c != common.end(); ++c) { int vIx = (*c)->Find( p); if( vIx >= 0) { DVar* var = (*c)->Var( vIx); return &(var->Data()); } } return NULL; } BaseGDL** GetCommonVarPtr(std::string& s) { for(CommonBaseListT::iterator c=common.begin(); c != common.end(); ++c) { DVar* v=(*c)->Find(s); if (v) return &(v->Data()); } return NULL; } bool ReplaceExistingCommonVar(std::string& s, BaseGDL* val) { for(CommonBaseListT::iterator c=common.begin(); c != common.end(); ++c) { DVar* v=(*c)->Find(s); if (v) { delete (v)->Data(); (v)->SetData(val); return true; } } return false; } // returns the variable index (-1 if not found) int FindVar(const std::string& s) { return FindInKeyVarListT(var,s); } // returns ptr to common variable (NULL if not found) DVar* FindCommonVar(const std::string& s) { for(CommonBaseListT::iterator c=common.begin(); c != common.end(); ++c) { DVar* v=(*c)->Find(s); if( v) return v; } return NULL; } // the final "compilation" takes part here void SetTree( RefDNode n); // { // // // // Converter Translation Transcription Rewrite RefDNode ProgNode ProgNodeP // // // // here the conversion RefDNode -> ProgNode is done // // // tree = ProgNode::NewProgNode( n); // } ProgNodeP GetTree() { return tree; } unsigned int GetCompileOpt() { return compileOpt; } void SetCompileOpt(const unsigned int n) { compileOpt = n; } bool isObsolete(); bool isHidden(); bool isStatic(); friend class EnvUDT; }; class DPro: public DSubUD { public: // for main function, not inserted into proList // should be fine (way too much): 32 NESTED loops in $MAIN$ (elswhere: unlimited) DPro(): DSubUD("$MAIN$","","") { this->nForLoops = 32;} DPro(const std::string& n,const std::string& o="",const std::string& f=""): DSubUD(n,o,f) {} const std::string ToString(); ~DPro() {}; }; class DFun: public DSubUD { public: DFun(const std::string& n,const std::string& o="",const std::string& f=""): DSubUD(n,o,f) {} const std::string ToString(); ~DFun() {}; }; typedef std::vector FunListT; typedef std::vector ProListT; typedef std::vector LibFunListT; typedef std::vector LibProListT; #endif gdl-0.9.9/src/dstructdesc.cpp000066400000000000000000000215721340051421000161160ustar00rootroot00000000000000/*************************************************************************** dstructdesc.cpp - GDL struct descriptor ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "datatypes.hpp" #include "dstructdesc.hpp" #include "GDLInterpreter.hpp" #include "dstructgdl.hpp" using namespace std; // store vtable in this obj file DStructBase::~DStructBase() { SizeT nTags = NTags(); for( SizeT i=0; i < nTags; ++i) { delete tags[ i]; } } // DUStructDesc::~DUStructDesc() // {} DStructDesc::~DStructDesc() { assert( !isUnnamed || (operatorList == NULL)); if( !isUnnamed) // only named structs have members and overloaded operators // (usually they are never deleted only with .RESET_SESSION and .FULL_RESET_SESSION dot commands) { delete operatorList; for(FunListT::iterator i = this->fun.begin(); i != this->fun.end(); ++i) { delete *i;} for(ProListT::iterator i = this->pro.begin(); i != this->pro.end(); ++i) { delete *i;} } } DStructDesc* FindInStructList(StructListT v, const string& s) { StructListT::iterator f=find_if(v.begin(),v.end(),DStruct_eq(s)); if( f == v.end()) return NULL; return *f; } bool DStructBase::ContainsStringPtrObject() { for( SizeT t=0; tType() == GDL_STRING) return true; if( tags[t]->Type() == GDL_PTR) return true; if( tags[t]->Type() == GDL_OBJ) return true; if( tags[t]->Type() == GDL_STRUCT) { if( static_cast( tags[t])->Desc()->ContainsStringPtrObject()) return true; } } return false; } void DUStructDesc::AddTag( const string& tagName, const BaseGDL* data) { for( SizeT i=0; i < tNames.size(); i++) if( tNames[i] == tagName) throw GDLException(tagName+" is already defined " "with a conflicting definition"); tNames.push_back(tagName); Add( data->GetTag()); } void DStructDesc::AddParent( DStructDesc* p) { SizeT nTags=p->NTags(); for( SizeT t=0; t < nTags; t++) AddTag( p->TagName(t), (*p)[t]); parent.push_back(p); OperatorList* parentOperatorList = p->GetOperatorList(); if( parentOperatorList != NULL) { assert( this->operatorList == NULL); // GDL_OBJECT can only be inherited once operatorList = new OperatorList(*parentOperatorList); } } // copy appropiate member subroutines from fun and pro lists void DStructDesc::SetupOperators() { assert( this->operatorList != NULL); for( FunListT::iterator f = this->fun.begin(); f != this->fun.end(); ++f) { int ix = OverloadOperatorIndexFun( (*f)->Name()); if( ix != -1) operatorList->SetOperator(ix,*f); } for( ProListT::iterator p = this->pro.begin(); p != this->pro.end(); ++p) { int ix = OverloadOperatorIndexPro( (*p)->Name()); if( ix != -1) operatorList->SetOperator(ix,*p); } } // more sophisticated error messages than operator== void DStructDesc::AssureIdentical( DStructDesc* d) { // name is the same if( NTags() != d->NTags()) { throw GDLException( "STRUCT: "+name+": redefinition with different " "number of tags."); } if( parent.size() != d->parent.size()) { throw GDLException( "STRUCT: "+name+": redefinition with different " "number of parents."); } // compare all tag names // compare the tags (type and dim) for( SizeT i=0; i < NTags(); i++) { if( TagName(i) != d->TagName(i)) { throw GDLException( "STRUCT: "+name+": "+TagName(i)+ " tag name differs in redefinition."); } if( tags[i]->Dim() != d->tags[i]->Dim()) { throw GDLException( "STRUCT: "+name+": "+TagName(i)+ " tag dimension " "differs in redefinition."); } // tag type is converted for convertable types if( (!ConvertableType( tags[i]->Type()) || !ConvertableType( d->tags[i]->Type())) && tags[i]->Type() != d->tags[i]->Type()) { throw GDLException( "STRUCT: "+name+": "+TagName(i)+ " tag type differs in redefinition."); } if( tags[i]->Type() == GDL_STRUCT) { SpDStruct* castLeft= static_cast(tags[i]); SpDStruct* castRight= static_cast(d->tags[i]); DStructDesc* leftD=castLeft->Desc(); DStructDesc* rightD=castRight->Desc(); if( !(*leftD == *rightD)) { throw GDLException( "STRUCT: "+name+": "+TagName(i)+ " tag struct differs in" " redefinition."); } } } // compare all parents for( SizeT i=0; i < parent.size(); i++) { if( parent[i] != d->parent[i]) { throw GDLException( "STRUCT: "+name+": "+parent[i]->Name()+ " parent class differs in redefinition."); } } } // two structs are equal if the contain the same datatypes in the // same order (although names might differ) bool operator==(const DStructDesc& left, const DStructDesc& right) { // name is the same if( left.NTags() != right.NTags()) return false; // struct layout can be same with different inheritance // if( left.parent.size() != right.parent.size()) return false; // compare all tag names // compare the tags (type and dim) for( SizeT i=0; i < left.NTags(); i++) { // if( left.TagName(i) != right.TagName(i)) return false; if( left.tags[i]->Dim() != right.tags[i]->Dim()) return false; if( left.tags[i]->Type() != right.tags[i]->Type()) return false; if( left.tags[i]->Type() == GDL_STRUCT) { SpDStruct* castLeft= static_cast(left.tags[i]); SpDStruct* castRight= static_cast(right.tags[i]); DStructDesc* leftD=castLeft->Desc(); DStructDesc* rightD=castRight->Desc(); // recursive call of operator == if( (leftD != rightD) && !(*leftD == *rightD)) return false; } } // compare all parents // for( SizeT i=0; i < left.parent.size(); i++) // { // if( left.parent[i] != right.parent[i]) return false; // } return true; } bool operator!=(const DStructDesc& left, const DStructDesc& right) { return !(left == right); } // DStructDesc* DStructDesc::FindEqual( const StructListT& sL) // { // for( SizeT i=0; i search for procedure if( found) { p=FindInProList( pName); if( p != NULL) return p; } else noDirectMembers.push_back(pName); } SizeT nParents=parent.size(); for( SizeT i=0; iGetPro( pName); if( p != NULL) return p; } return NULL; } DFun* DStructDesc::GetFun( const string& pName) { DFun* p; p=FindInFunList( pName); if( p != NULL) return p; int fInIDList=FindInIDList( noDirectMembers, pName); if( fInIDList == -1) { bool found=GDLInterpreter::SearchCompilePro( name+"__"+pName, false); // false -> search for function if( found) { p=FindInFunList( pName); if( p != NULL) return p; } else noDirectMembers.push_back(pName); } SizeT nParents=parent.size(); for( SizeT i=0; iGetFun( pName); if( p != NULL) return p; } return NULL; } DPro* DStructDesc::GetPro( const string& pName, const string& parentName) { if( !IsParent( parentName)) throw GDLException( parentName+" is not a parent of "+name); DStructDesc* d=FindInStructList( structList, parentName); if( d == NULL) throw GDLException("Internal error: Struct "+parentName+" not found."); return d->GetPro( pName); } DFun* DStructDesc::GetFun( const string& pName, const string& parentName) { if( !IsParent( parentName)) throw GDLException( parentName+" is not a parent of "+name); DStructDesc* d=FindInStructList( structList, parentName); if( d == NULL) throw GDLException("Internal error: Struct "+parentName+" not found."); return d->GetFun( pName); } gdl-0.9.9/src/dstructdesc.hpp000066400000000000000000000167351340051421000161300ustar00rootroot00000000000000/*************************************************************************** dstructdesc.hpp - GDL struct descriptor ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DSTRUCTDESC_HPP_ #define DSTRUCTDESC_HPP_ #include "includefirst.hpp" // USE_EIGEN3 #include #include #include #include #include "basegdl.hpp" #include "dpro.hpp" #include "typedefs.hpp" #include "overload.hpp" class DStructBase { private: std::vector tagOffset; // data offset of tags protected: std::vector tags; // Data_ for data, 'Sp' for structList elements void Add( BaseGDL* t) { tags.push_back(t); // grabs // attention: there is a subtle difference for NBytes() // for SpDString (considers sizeof( DString)), used here // and DStringGDL (considers actual string sizes) SizeT nBytes = tags.back()->NBytes(); // alignment #ifdef USE_EIGEN assert( sizeof( char*) <= 16); const int alignmentInBytes = 16; // set to multiple of 16 >= sizeof( char*) #else const int alignmentInBytes = sizeof( char*); #endif SizeT exceed = nBytes % alignmentInBytes; if( exceed > 0) nBytes += alignmentInBytes - exceed; // valid tagOffset (used by NBytes()) tagOffset.push_back( tagOffset.back() + nBytes); } public: DStructBase(): tagOffset( 1, 0) {} DStructBase( const DStructBase* d_): tags( d_->NTags()) { SizeT nTags = d_->NTags(); for( SizeT t=0; ttags[ t]->GetTag(); } tagOffset = d_->tagOffset; } virtual ~DStructBase(); BaseGDL*& operator[] (const SizeT d1) { return tags[d1];} const BaseGDL* operator[] (const SizeT d1) const { return tags[d1];} SizeT Offset( SizeT t, SizeT ix) const { return (tagOffset[ t] + ix * NBytes()); } SizeT Offset( SizeT t) const { return tagOffset[ t]; } SizeT NTags() const { return tags.size();} SizeT NBytes() const { return tagOffset.back();} bool ContainsStringPtrObject(); }; class DStructDesc; typedef std::vector StructListT; // descriptor of structs layout ************************************************ // unnamed struct // this is never used directly, only DStructDesc (see below) class DUStructDesc: public DStructBase { private: std::vector tNames; // tag names public: DUStructDesc(): DStructBase() {} DUStructDesc( const DUStructDesc* d_): DStructBase( d_), tNames( d_->tNames) {} // ~DUStructDesc(); void AddTag( const std::string& tagName, const BaseGDL* data); int TagIndex( const std::string& tN) const { for( SizeT i=0; i< tNames.size(); i++) if( tNames[i] == tN) return static_cast(i); return -1; } const std::string& TagName( const SizeT ix) const { return tNames[ ix]; } }; // named struct class DStructDesc: public DUStructDesc { private: SizeT refCount; bool isUnnamed; // operatorList != NULL means inherited from GDL_OBJECT OperatorList* operatorList; // avoid extra allocation // char operatorListBuffer[ sizeof(operatorList)]; // ONLY FOR GDL_OBJECT void InitOperatorList() { assert( operatorList == NULL); operatorList = new OperatorList();} friend void InitStructs(); // restrict usage to definition of GDL_OBECT private: std::string name; StructListT parent; // parent classes IDList noDirectMembers; FunListT fun; // member functions ProListT pro; // member procedures DStructDesc( const DStructDesc&) {} // disabeld public: DStructDesc( const std::string& n): DUStructDesc(), refCount( 1), operatorList( NULL), name(n) { // name=n; // if this is to be changed, see also: // DStructGDL::DStructGDL( const string& name_) // (dstructgdl.cpp) isUnnamed = (name[0] == '$'); } // private: // // this is only used for unnamed structs -> only copy name from 'this' // DStructDesc( const DStructDesc* d_): // DUStructDesc( d_), // name( d_->name) // must be "$..." // {} // public: ~DStructDesc(); friend bool operator==(const DStructDesc& left, const DStructDesc& right); friend bool operator!=(const DStructDesc& left, const DStructDesc& right); const std::string& Name() const { return name;} FunListT& FunList() { return fun; } DFun* FindInFunList( const std::string& n) { FunListT::iterator p=std::find_if(fun.begin(),fun.end(),Is_eq(n)); if( p != fun.end()) return *p; return NULL; } ProListT& ProList() { return pro; } DPro* FindInProList( const std::string& n) { ProListT::iterator p=std::find_if(pro.begin(),pro.end(),Is_eq(n)); if( p != pro.end()) return *p; return NULL; } DPro* GetPro( const std::string& pName); DPro* GetPro( const std::string& pName, const std::string& parentName); DFun* GetFun( const std::string& pName); DFun* GetFun( const std::string& pName, const std::string& parentName); // if this is to be changed, see also: // DStructGDL::DStructGDL( const string& name_) // (dstructgdl.cpp) bool IsUnnamed() const { return isUnnamed;} // bool InheritsGDL_OBJECT() const { return (operatorList != NULL);} OperatorList* GetOperatorList() const { return operatorList;} DSubUD* GetOperator( SizeT i) const { if( operatorList == NULL) return NULL; return (*operatorList)[ i];} void SetOperator( SizeT i, DSubUD* op) { if( operatorList == NULL) return; operatorList->SetOperator( i, op);} // copy appropiate member subroutines from fun and pro lists void SetupOperators(); bool IsParent( const std::string& p) const { if( p == name) return true; SizeT nParents=parent.size(); for( SizeT i=0; iIsParent( p)) return true; } return false; } void AddParent( DStructDesc*); void GetParentNames( std::vector< std::string>& pNames) const { SizeT nParents=parent.size(); for( SizeT i=0; iName()); } } void AssureIdentical( DStructDesc* d); // DStructDesc* FindEqual( const StructListT& sL); // for unnamed structs (typetraits.cpp) void AddRef() { ++refCount; } void Delete() { if( --refCount) return; delete this; } }; class DStruct_eq: public std::unary_function { std::string name; public: explicit DStruct_eq(const std::string& s): name(s) {} bool operator() (const DStructDesc* v) const { return v->Name() == name;} }; DStructDesc* FindInStructList(StructListT, const std::string& name); // actually holding the data ********************************************** // class DStructGDL see dstructgdl.hpp #endif gdl-0.9.9/src/dstructfactory.cxx000066400000000000000000000027741340051421000166720ustar00rootroot00000000000000/*************************************************************************** dstructfactory.cxx - DStructGDL creation helper ------------------- begin : May 28 2018 copyright : (C) 2018 by Remi A. Solås email : remi.solaas (at) edinsights.no ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "dstructfactory.hxx" DStructFactory::DStructFactory() : desc_(new DStructDesc("$truct")) { } DStructFactory::~DStructFactory() { for(auto& pair : vals_) delete pair.second; } DStructGDL* DStructFactory::Create() { if(vals_.empty()) return nullptr; auto res = new DStructGDL(desc_, dimension()); for(auto& pair : vals_) { res->InitTag(pair.first, *pair.second); delete pair.second; } vals_.clear(); return res; } gdl-0.9.9/src/dstructfactory.hxx000066400000000000000000000046411340051421000166720ustar00rootroot00000000000000/*************************************************************************** dstructfactory.hxx - DStructGDL creation helper ------------------- begin : May 28 2018 copyright : (C) 2018 by Remi A. Solås email : remi.solaas (at) edinsights.no ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DSTRUCTFACTORY_HXX #define DSTRUCTFACTORY_HXX #include "includefirst.hpp" #include "dstructgdl.hpp" #include class DStructFactory { public: DStructFactory(); ~DStructFactory(); template void Add(const char* name, const Vs&... vals) { constexpr auto N = sizeof...(Vs); auto proto = new typename T::Traits(dimension(N)); typename T::Ty arr[] = { static_cast(vals)... }; desc_->AddTag(name, proto); vals_[name] = (N > 1 ? new T(arr, N) : new T(arr[0])); delete proto; } template void AddArr(const char* name, size_t count, const V* vals) { auto proto = new typename T::Traits(dimension(count)); typename T::Traits::DataT arr(vals, count); desc_->AddTag(name, proto); vals_[name] = new T(dimension(count), arr); delete proto; } template void AddMat(const char* name, size_t cols, size_t rows, const V* vals) { auto proto = new typename T::Traits(dimension(cols, rows)); typename T::Traits::DataT mat(vals, rows * cols); desc_->AddTag(name, proto); vals_[name] = new T(dimension(cols, rows), mat); delete proto; } DStructGDL* Create(); private: DStructDesc* desc_ = nullptr; std::map vals_; }; #endif gdl-0.9.9/src/dstructgdl.cpp000066400000000000000000001104201340051421000157350ustar00rootroot00000000000000/*************************************************************************** dstructgdl.cpp - GDL struct datatype ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "arrayindexlistt.hpp" #include "dstructgdl.hpp" #include "accessdesc.hpp" #include "objects.hpp" using namespace std; vector< void*> DStructGDL::freeList; #ifdef HAVE_LIBWXWIDGETS #include wxMutex mutexNewDelete; #define LOCK_MUTEXNEWDELETE mutexNewDelete.Lock(); #define UNLOCK_MUTEXNEWDELETE mutexNewDelete.Unlock(); #else #define LOCK_MUTEXNEWDELETE ; #define UNLOCK_MUTEXNEWDELETE ; #endif void* DStructGDL::operator new( size_t bytes) { assert( bytes == sizeof( DStructGDL)); if( freeList.size() > 0) { LOCK_MUTEXNEWDELETE void* res = freeList.back(); freeList.pop_back(); UNLOCK_MUTEXNEWDELETE return res; } //cout << "Alloc: " << bytes << " " << "STRUCT" << endl; char* res = static_cast< char*>( malloc( sizeof( DStructGDL) * multiAlloc)); // one more than newSize const size_t newSize = multiAlloc - 1; LOCK_MUTEXNEWDELETE freeList.resize( newSize); for( size_t i=0; iSetBuffer( NULL); delete typeVar[ t]; } else for( SizeT t=0; t < nTags; ++t) { typeVar[ t]->SetBuffer( NULL); delete typeVar[ t]; } } } // new scalar, creating new descriptor // intended for internal (C++) use to ease struct definition DStructGDL::DStructGDL( const string& name_) : SpDStruct( NULL, dimension(1)) , typeVar() , dd() { assert( name_[0] != '$'); // check for unnamed struct desc = FindInStructList( structList, name_); if( desc == NULL) { desc = new DStructDesc( name_); structList.push_back( desc); } else { SizeT nTags=NTags(); dd.SetSize( Desc()->NBytes()); typeVar.resize( nTags); for( SizeT t=0; t < nTags; ++t) { InitTypeVar( t); ConstructTagTo0( t); } } } // c-i // only used from Assoc_ DStructGDL::DStructGDL(const DStructGDL& d_) : SpDStruct(d_.desc, d_.dim) , typeVar( d_.NTags()) , dd(d_.NBytes(), false) { MakeOwnDesc(); SizeT nTags = NTags(); SizeT nEl = N_Elements(); for( SizeT t=0; t < nTags; ++t) { typeVar[ t] = d_.typeVar[ t]->GetEmptyInstance(); typeVar[ t]->SetBufferSize( d_.typeVar[ t]->N_Elements()); // problem: // for struct typeVar // typeVar[ t].typeVar[] has their buffers not set yet ConstructTag( t); for( SizeT i=0; i < nEl; ++i) GetTag( t, i)->InitFrom( *d_.GetTag( t, i)); } } // // assignment. // DStructGDL& DStructGDL::operator=(const DStructGDL& right) // { // // std::cout << "DStructGDL& operator=(const DStructGDL& right): " << desc <<" "<< right.desc << std::endl; // if( &right == this) return *this; // self assignment // dim=right.dim; // // if( right.desc->IsUnnamed()) // // SetDesc( new DStructDesc( right.desc)); // // delete actual data // SizeT nD=dd.size(); // for( SizeT i=0; i < nD; i++) delete dd[i]; // // copy new data // SizeT nEl=right.N_Elements(); // dd.resize(nEl); // for( SizeT i=0; iDup(); // } // return *this; // } // called from GDLInterpreter and basic_fun // NOT for array of struct // DStructDesc::AssureIdentical already passed void DStructGDL::SetDesc( DStructDesc* nDesc) { SizeT nTags = nDesc->NTags(); for( SizeT t=0; t < nTags; t++) { BaseGDL* actTag = (*nDesc)[t]; DType actTType = actTag->Type(); // convert to this type if( ConvertableType( actTType)) // not for struct, obj, ptr { if( typeVar[ t]->Type() != actTType) typeVar[ t] = typeVar[ t]->Convert2( actTType); } } // finally replace the descriptor this->SpDStruct::SetDesc( nDesc); } DStructGDL* DStructGDL::SetBuffer( const void* b) { dd.SetBuffer( static_cast< Ty*>(const_cast( b))); return this; } void DStructGDL::SetBufferSize( SizeT s) { dd.SetBufferSize( s * Desc()->NBytes()); } DStructGDL* DStructGDL::CShift( DLong d) const { // must be nulled for correct reference counting DStructGDL* sh = new DStructGDL( Desc(), dim);//, BaseGDL::NOZERO); SizeT nEl = N_Elements(); SizeT nTag = NTags(); if( d >= 0) for( SizeT i=0; iGetTag( t, (i + d) % nEl) = *GetTag( t, i); else for( SizeT i=0; iGetTag( t, i) = *GetTag( t, (i - d) % nEl); return sh; } // TODO: Implement fast 2D version (see datatypes.cpp) DStructGDL* DStructGDL::CShift( DLong s[MAXRANK]) const { // must be nulled for correct reference counting DStructGDL* sh = new DStructGDL( Desc(), dim);//, BaseGDL::NOZERO); SizeT nDim = Rank(); SizeT nEl = N_Elements(); SizeT nTags = NTags(); SizeT stride[ MAXRANK + 1]; dim.Stride( stride, nDim); long srcIx[ MAXRANK+1]; long dstIx[ MAXRANK+1]; SizeT dim_stride[ MAXRANK]; for( SizeT aSp=0; aSp= 0) dstIx[ aSp] = s[ aSp] % dim[ aSp]; else dstIx[ aSp] = -(-s[aSp] % dim[ aSp]); if( dstIx[ aSp] < 0) dstIx[ aSp] += dim[ aSp]; dim_stride[ aSp] = dim[ aSp] * stride[ aSp]; } srcIx[ nDim] = dstIx[ nDim] = 0; SizeT dstLonIx = dstIx[ 0]; for( SizeT rSp=1; rSpdd[0];*/ for( SizeT a=0; a= dim[ aSp]) { // dstIx[ aSp] -= dim[ aSp]; dstIx[ aSp] = 0; dstLonIx -= dim_stride[ aSp]; } if( srcIx[ aSp] < dim[ aSp]) break; srcIx[ aSp] = 0; ++srcIx[ ++aSp]; ++dstIx[ aSp]; dstLonIx += stride[ aSp]; } for( SizeT t=0; tGetTag( t, dstLonIx) = *GetTag( t, a); // shP[ dstLonIx * nTags + t] = ddP[ a * nTags + t]->Dup(); } return sh; } // assigns srcIn to this at ixList, if ixList is NULL does linear copy // assumes: ixList has this already set as variable // used by DotAccessDescT::DoAssign // GDLInterpreter::l_array_expr void DStructGDL::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { DStructGDL* src=static_cast(srcIn); // check struct compatibility if( src->Desc() != this->Desc() && (*src->Desc()) != (*this->Desc())) throw GDLException( "Conflicting data structures."); SizeT nTags=NTags(); bool isScalar= src->N_Elements() == 1; if( isScalar) { // src is scalar if( ixList == NULL) { SizeT nCp=N_Elements(); for( SizeT c=0; cdd[tagIx]->Dup(); *GetTag( tagIx, c) = *src->GetTag( tagIx); } } } else { SizeT nCp=ixList->N_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); for( SizeT c=0; cdd[tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx); } } } } else { SizeT srcElem=src->N_Elements(); if( ixList == NULL) { SizeT nCp=N_Elements(); // if (non-indexed) src is smaller -> just copy its number of elements if( nCp > (srcElem-offset)) { if( offset == 0) nCp=srcElem; else throw GDLException("Source expr contains not enough elements."); } for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx, srcTag); } } } else { SizeT nCp=ixList->N_Elements(); if( nCp == 1) { // InsAt( src, ixList->GetDim()); InsAt( src, ixList); } else { if( (srcElem-offset) < nCp) throw GDLException("Array subscript must have" " same size as source expression."); AllIxBaseT* allIx = ixList->BuildIx(); for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx, srcTag); } } } } } } void DStructGDL::AssignAtIx( RangeT ixR, BaseGDL* srcIn) { if( srcIn->Type() != this->Type()) throw GDLException( "Conflicting data structures."); DStructGDL* src=static_cast(srcIn); // check struct compatibility if( src->Desc() != this->Desc() && (*src->Desc()) != (*this->Desc())) throw GDLException( "Conflicting data structures."); SizeT nTags=NTags(); if( ixR < 0) { SizeT nEl = this->N_Elements(); if( -ixR > nEl) throw GDLException("Subscript out of range: " + i2s(ixR)); SizeT ix = nEl + ixR; //(*this)[ix] = (*static_cast(srcIn))[0]; for( SizeT tagIx=0; tagIxGetTag( tagIx); } return; } // ixR >= 0 //(*this)[ixR] = (*static_cast(srcIn))[0]; for( SizeT tagIx=0; tagIxGetTag( tagIx); } } void DStructGDL::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { DStructGDL* src=static_cast(srcIn); // check struct compatibility if( src->Desc() != this->Desc() && (*src->Desc()) != (*this->Desc())) throw GDLException( "Conflicting data structures."); SizeT nTags=NTags(); bool isScalar= src->N_Elements() == 1; if( isScalar) { // src is scalar if( ixList == NULL) { SizeT nCp=N_Elements(); for( SizeT c=0; cdd[tagIx]->Dup(); *GetTag( tagIx, c) = *src->GetTag( tagIx); } } } else { SizeT nCp=ixList->N_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); for( SizeT c=0; cdd[tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx); } } } } else { SizeT srcElem=src->N_Elements(); if( ixList == NULL) { SizeT nCp=N_Elements(); // if (non-indexed) src is smaller -> just copy its number of elements if( nCp > srcElem) nCp=srcElem; for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, c) = *src->GetTag( tagIx, c); } } } else { SizeT nCp=ixList->N_Elements(); if( nCp == 1) { // InsAt( src, ixList->GetDim()); InsAt( src, ixList); } else { if( srcElem < nCp) throw GDLException("Array subscript must have" " same size as source expression."); AllIxBaseT* allIx = ixList->BuildIx(); for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx, c); } } } } } } void DStructGDL::AssignAt( BaseGDL* srcIn) { DStructGDL* src=static_cast(srcIn); // check struct compatibility if( src->Desc() != this->Desc() && (*src->Desc()) != (*this->Desc())) throw GDLException( "Conflicting data structures."); SizeT nTags=NTags(); bool isScalar= src->N_Elements() == 1; if( isScalar) { // src is scalar SizeT nCp=N_Elements(); for( SizeT c=0; cdd[tagIx]->Dup(); *GetTag( tagIx, c) = *src->GetTag( tagIx); } } } else { SizeT srcElem=src->N_Elements(); SizeT nCp=N_Elements(); // if (non-indexed) src is smaller -> just copy its number of elements if( nCp > srcElem) nCp = srcElem; for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, c) = *src->GetTag( tagIx, c); } } } } // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset // used by DotAccessDescT::DoResolve // there d is initially empty -> no deleting of old data in InsertAt void DStructGDL::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { DStructGDL* src=static_cast(srcIn); SizeT nTags=NTags(); if( ixList == NULL) { SizeT nCp=src->N_Elements(); for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx, c); } } else { SizeT nCp=ixList->N_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); for( SizeT c=0; cdd[srcTag+tagIx]->Dup(); *GetTag( tagIx, cTag) = *src->GetTag( tagIx, srcTag); } } } // used for array concatenation DStructGDL* DStructGDL::CatArray( ExprListT& exprList, const SizeT catRankIx, const SizeT rank) { // breakpoint(); SizeT rankIx = RankIx( rank); SizeT maxIx = (catRankIx > rankIx)? catRankIx : rankIx; dimension catArrDim(dim); // list contains at least one element catArrDim.MakeRank( maxIx+1); catArrDim.SetOneDim(catRankIx,0); // clear rank which is added up SizeT dimSum=0; ExprListIterT i=exprList.begin(); for(; i != exprList.end(); i++) { for( SizeT dIx=0; dIx<=maxIx; dIx++) { if( dIx != catRankIx) { if( catArrDim[dIx] == (*i)->Dim(dIx)) continue; if( (catArrDim[dIx] > 1) || ((*i)->Dim(dIx) > 1)) throw GDLException("Unable to concatenate variables " "because the dimensions do not agree."); } else { SizeT add=(*i)->Dim(dIx); dimSum+=(add)?add:1; } } } catArrDim.SetOneDim(catRankIx,dimSum); // the concatenated array DStructGDL* catArr=New( catArrDim, BaseGDL::NOZERO); SizeT at=0; for( i=exprList.begin(); i != exprList.end(); i++) { // for GDL_STRUCT all types are compatible structs already (array_def in gdlc.i.g) // if( (*i)->Type() != t) (*i)=(*i)->Convert2( t); catArr->CatInsert(static_cast( (*i)), catRankIx,at); // advances 'at' } return catArr; } // returns (*this)[ ixList] DStructGDL* DStructGDL::Index( ArrayIndexListT* ixList) { // ixList->SetVariable( this); DStructGDL* res=New( ixList->GetDim(), BaseGDL::NOZERO); SizeT nTags=NTags(); SizeT nCp=ixList->N_Elements(); AllIxBaseT* allIx = ixList->BuildIx(); for( SizeT c=0; cGetTag( tagIx, c) = *GetTag( tagIx, srcTag); } if( nCp == 1) { res->SetDim( dimension(1)); } return res; } DStructGDL* DStructGDL::NewIx( SizeT ix) { SizeT nTags=NTags(); // bug ID 3091599: Indexed struct arrays retrun always an array DStructGDL* res=New( dimension(1), BaseGDL::NOZERO); for( SizeT tagIx=0; tagIxGetTag( tagIx, 0) = *GetTag( tagIx, ix); return res; } // void DStructGDL::AddTag(const BaseGDL* data) // { // // SizeT oldSize = dd.size(); // dd.resize( Desc()->NBytes()); // typeVar.push_back( data->GetEmptyInstance()); // typeVar.back()->SetBufferSize( data->N_Elements()); // GetTag( NTags()-1)->Construct(); // construct // *GetTag( NTags()-1) = *data; // copy // } // void DStructGDL::NewTag(const string& tName, const BaseGDL& data) // { // Desc()->AddTag( tName, &data); // makes a copy of data // AddTag( &data); // } void DStructGDL::NewTag(const string& tName, BaseGDL* data) { assert( dd.size() == 0); Desc()->AddTag( tName, data); // makes a copy of data // AddTag( data); typeVar.push_back( data); } void DStructGDL::AddParent( DStructDesc* p) { SizeT oldTags = NTags(); Desc()->AddParent( p); // dd.resize( Desc()->NBytes()); SizeT newTags = NTags(); for( SizeT t=oldTags; t < newTags; ++t) { typeVar.push_back( (*Desc())[ t]->GetInstance()); // typeVar.back()->SetBufferSize( (*Desc())[ t]->N_Elements()); // GetTag( t)->ConstructTo0(); // construct } } // inserts srcIn at ixDim // respects the exact structure // used by Assign -> old data must be freed void DStructGDL::InsAt( DStructGDL* srcIn, ArrayIndexListT* ixList) { SizeT nTags=NTags(); SizeT nDim = ixList->NDim(); // max. number of dimensions to copy if( nDim == 1) { SizeT destStart = ixList->LongIx(); SizeT len = srcIn->Dim( 0); // length of segment to copy // check if in bounds of a if( (destStart+len) > this->N_Elements()) //dim[0]) throw GDLException("Out of range subscript encountered."); SizeT srcIx = 0; // this one simply runs from 0 to N_Elements(srcIn) SizeT destEnd = destStart + len; for( SizeT destIx = destStart; destIx < destEnd; ++destIx) { // SizeT destIxTag = destIx*nTags; // SizeT srcIxTag = srcIx*nTags; for( SizeT tagIx=0; tagIxdd[ srcIxTag+tagIx]->Dup(); *GetTag( tagIx, destIx) = *srcIn->GetTag( tagIx, srcIx); } srcIx++; } return; } SizeT destStart; // ATTENTION: dimension is used as an index here dimension ixDim = ixList->GetDimIx0( destStart); nDim--; //const DStructGDL* srcArr=static_cast(srcIn->Convert2( t)); dimension srcDim=srcIn->Dim(); srcDim.Purge(); // newly inserted: variant of ticket #675 // SizeT nDim =RankIx(ixDim.Rank()); SizeT srcNDim=RankIx(srcDim.Rank()); // number of source dimensions if( srcNDim < nDim) nDim=srcNDim; // check limits (up to Rank to consider) for( SizeT dIx=0; dIx <= nDim; dIx++) // check if in bounds of a if( (ixDim[dIx]+srcDim[dIx]) > dim[dIx]) throw GDLException("Out of range subscript encountered."); SizeT len=srcDim[0]; // length of one segment to copy (one line of srcIn) SizeT nCp=srcIn->Stride(nDim+1)/len; // number of OVERALL copy actions // as lines are copied, we need the stride from 2nd dim on SizeT retStride[MAXRANK]; for( SizeT a=0; a <= nDim; a++) retStride[a]=srcDim.Stride(a+1)/len; // a magic number, to reset destStart for this dimension SizeT resetStep[MAXRANK]; for( SizeT a=1; a <= nDim; a++) resetStep[a]=(retStride[a]-1)/retStride[a-1]*dim.Stride(a); // SizeT destStart=dim.LongIndex(ixDim); // starting pos SizeT srcIx=0; // this one simply runs from 0 to N_Elements(srcIn) for( SizeT c=1; c<=nCp; c++) // linearized verison of nested loops { // copy one segment SizeT destEnd=destStart+len; for( SizeT destIx = destStart; destIx < destEnd; ++destIx) { // SizeT destIxTag = destIx*nTags; // SizeT srcIxTag = srcIx*nTags; for( SizeT tagIx=0; tagIxdd[ srcIxTag+tagIx]->Dup(); *GetTag( tagIx, destIx) = *srcIn->GetTag( tagIx, srcIx); } srcIx++; } // update destStart for all dimensions for( SizeT a=1; a<=nDim; a++) { if( c % retStride[a]) { // advance to next destStart += dim.Stride(a); break; } else { // reset destStart -= resetStep[a]; } } } } // used for concatenation, called from CatArray // assumes that everything is checked (see CatInfo) void DStructGDL::CatInsert( const DStructGDL* srcArr, const SizeT atDim, SizeT& at) { // length of one segment to copy SizeT len=srcArr->dim.Stride(atDim+1); // src array // number of copy actions SizeT nCp=srcArr->N_Elements()/len; // initial offset SizeT destStart= dim.Stride(atDim) * at; // dest array SizeT destEnd = destStart + len; // number of elements to skip SizeT gap=dim.Stride(atDim+1); // dest array SizeT nTags=NTags(); SizeT srcIx=0; for( SizeT c=0; cdd[ srcIxTag+tagIx]->Dup(); *GetTag( tagIx, destIx) = *srcArr->GetTag( tagIx, srcIx); } srcIx++; } // set new destination pointer destStart += gap; destEnd += gap; } SizeT add=srcArr->dim[atDim]; // update 'at' at += (add > 1)? add : 1; } BaseGDL* DStructGDL::Get( SizeT tag) { DotAccessDescT aD( 2); // like a.b (=2 levels) aD.ADRoot( this); // set root, implicit no index aD.ADAdd( tag); // tag to extract aD.ADAddIx( NULL); // no index -> ALL return aD.ADResolve(); } // basic_op_add.cpp DStructGDL* DStructGDL::Add( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::AddInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::AddS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::AddInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } // basic_op_sub.cpp DStructGDL* DStructGDL::Sub( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::SubInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::SubS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::SubInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } // datatypes.cpp int DStructGDL::Scalar2Index( SizeT& st) const { throw GDLException("STRUCT expression not allowed in this context."); return 0; // get rid of warning } int DStructGDL::Scalar2RangeT( RangeT& st) const { throw GDLException("STRUCT expression not allowed in this context."); return 0; // get rid of warning } RangeT DStructGDL::LoopIndex() const { throw GDLException("STRUCT expression not allowed in this context."); return 0; // get rid of warning } int DStructGDL::Sgn() // -1,0,1 { throw GDLException("Struct expression not allowed in this context."); return 0; } bool DStructGDL::EqualNoDelete( const BaseGDL* r) const { throw GDLException("Struct expression not allowed in this context."); return false; } void DStructGDL::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { throw GDLException("Struct expression not allowed in this context."); } // basic_op_mult.cpp DStructGDL* DStructGDL::Mult( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::MultS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } // basic_op_div.cpp DStructGDL* DStructGDL::Div( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::DivInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::DivS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::DivInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } // basic_op_new.cpp DStructGDL* DStructGDL::AndOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AndOpInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AndOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AndOpInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::OrOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::OrOpInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::OrOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::OrOpInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::XorOpNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::XorOpSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AddNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AddInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AddSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AddInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::SubNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::SubInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::SubSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::SubInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::LtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::LtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::GtMarkNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::GtMarkSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::MultNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::MultSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::DivNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::DivInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::DivSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::DivInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::ModNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::ModInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::ModSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::ModInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::PowIntNew( BaseGDL* r) { assert( 0); throw GDLException("Internal error: DStructGDL::PowIntNew called.",true,false); return NULL; } DStructGDL* DStructGDL::PowNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::PowInvNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::PowSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::PowInvSNew( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } // basic_op.cpp DStructGDL* DStructGDL::NotOp() { throw GDLException("Cannot apply operation to datatype "+str+".",true,false); return this; } BaseGDL* DStructGDL::UMinus() { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } BaseGDL* DStructGDL::EqOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } BaseGDL* DStructGDL::NeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } BaseGDL* DStructGDL::LeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } BaseGDL* DStructGDL::LtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } BaseGDL* DStructGDL::GeOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } BaseGDL* DStructGDL::GtOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return NULL; } DStructGDL* DStructGDL::AndOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::AndOpInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::AndOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::AndOpInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::OrOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::OrOpInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::OrOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::OrOpInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::XorOp( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::XorOpS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::LtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::LtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::GtMark( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::GtMarkS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::Mod( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::ModInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::ModS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::ModInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::PowInt( BaseGDL* r) { assert( 0); return this; } DStructGDL* DStructGDL::PowS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::PowInvS( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::Pow( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } DStructGDL* DStructGDL::PowInv( BaseGDL* r) { throw GDLException("Cannot apply operation to datatype STRUCT.",true,false); return this; } gdl-0.9.9/src/dstructgdl.hpp000066400000000000000000000543741340051421000157610ustar00rootroot00000000000000/*************************************************************************** dstructgdl.hpp - GDL struct datatype ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef dstructgdl_hpp_ #define dstructgdl_hpp_ #include // #include #include "typedefs.hpp" #include "datatypes.hpp" // for friend declaration //#include "typetraits.hpp" #include "dstructdesc.hpp" // NOTE: lot of the code together with Data_<...>::functions // does not fit really into the template because of different // constructor // also here a vector is used instead of a valarray class DStructGDL: public SpDStruct { public: typedef SpDStruct::Ty Ty; typedef SpDStruct Traits; private: typedef SpDStruct::DataT DataT; //public: std::vector typeVar; // for accessing data #ifdef USE_EIGEN EIGEN_ALIGN16 DataT dd; // the data #else DataT dd; // the data #endif void InitTypeVar( SizeT t) { typeVar[ t] = (*Desc())[ t]->GetEmptyInstance(); typeVar[ t]->SetBufferSize( (*Desc())[ t]->N_Elements()); // no initial SetBuffer here, done anyway in ConstructTag() } const char* Buf() const { return &dd[0];} char* Buf() { return &dd[0];} public: static std::vector< void*> freeList; // operator new and delete static void* operator new( size_t bytes); static void operator delete( void *ptr); //structors ~DStructGDL(); // default (needed for test instantiation) // DStructGDL(): SpDStruct(), d() {} // new array (desc defined) DStructGDL( DStructDesc* desc_, const dimension& dim_) : SpDStruct( desc_, dim_) , typeVar( desc_->NTags()) , dd( dim.NDimElements() * desc_->NBytes(), false) //,SpDStruct::zero) { dim.Purge(); SizeT nTags = NTags(); for( SizeT t=0; t < nTags; ++t) { InitTypeVar( t); ConstructTagTo0( t); } } // new array (desc defined), don't init fields (only for New()) // (non POD must be initialized (constructed) nevertheless) // or no memeory allocation DStructGDL( DStructDesc* desc_, const dimension& dim_, BaseGDL::InitType iT) : SpDStruct( desc_, dim_) , typeVar( desc_->NTags()) , dd( (iT == BaseGDL::NOALLOC) ? 0 : dim.NDimElements() * desc_->NBytes(), false) { assert( iT == BaseGDL::NOZERO || iT == BaseGDL::NOALLOC); dim.Purge(); if( iT != BaseGDL::NOALLOC) { SizeT nTags = NTags(); // SizeT nEl = dim.N_Elements(); for( SizeT t=0; t < nTags; ++t) { InitTypeVar( t); ConstructTag( t); } } else // iT == BaseGDL::NOALLOC { SizeT nTags = NTags(); for( SizeT t=0; t < nTags; ++t) { InitTypeVar( t); } } } // c-i (desc defined) // only called from Assoc_'s c-i DStructGDL(const DStructGDL& d_); // For creating new structs (always scalar) DStructGDL( DStructDesc* desc_) : SpDStruct(desc_, dimension(1)) , typeVar() , dd() { assert( desc_->NTags() == 0); // SizeT nTags = NTags(); // for( SizeT t=0; t < nTags; ++t) // { // InitTypeVar( t); // } } // new struct (always scalar), creating new descriptor // intended for internal (C++) use to ease struct definition // ATTENTION: This can only be used for NAMED STRUCTS! // please use the normal constructor (above) for unnamed structs DStructGDL( const std::string& name_); // operators // assignment. DStructGDL& operator=(const BaseGDL& r) { assert( r.Type() == GDL_STRUCT); const DStructGDL& right = static_cast( r); assert( *Desc() == *right.Desc()); assert( &right != this); if( &right == this) return *this; // self assignment this->dim = right.dim; SizeT nTags = NTags(); SizeT nEl = N_Elements(); for( SizeT e=0; e < nEl; ++e) for( SizeT t=0; t < nTags; ++t) { *GetTag( t, e) = *right.GetTag( t, e); } return *this; } void InitFrom(const BaseGDL& r) { assert( r.Type() == GDL_STRUCT); const DStructGDL& right = static_cast( r); assert( *Desc() == *right.Desc()); assert( &right != this); this->dim = right.dim; SizeT nTags = NTags(); SizeT nEl = N_Elements(); for( SizeT e=0; e < nEl; ++e) for( SizeT t=0; t < nTags; ++t) { GetTag( t, e)->InitFrom( *right.GetTag( t, e)); } } inline BaseGDL* operator[] (const SizeT d1) { return GetTag( d1 % NTags(), d1 / NTags()); } inline const BaseGDL* operator[] (const SizeT d1) const { return GetTag( d1 % NTags(), d1 / NTags()); } // void* DataAddr( SizeT elem) // { // return &(*this)[elem]; // } void* DataAddr()// SizeT elem) { if( Buf() == NULL) throw GDLException("DStructGDL: Data not set."); return Buf(); }//elem];} void* DataAddr(SizeT tag)// SizeT elem) { if( dd.size() == 0) return typeVar[ t]; return Buf(); }//elem];} // used for named struct definition // (GDLInterpreter, basic_fun (create_struct)) void SetDesc( DStructDesc* newDesc); DStructGDL* SetBuffer( const void* b); void SetBufferSize( SizeT s); DStructGDL* CShift( DLong d) const; DStructGDL* CShift( DLong d[MAXRANK]) const; // for use by MIN and MAX functions void MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs); // const DType Type() const { return SpDStruct::t;} // const std::string& TypeStr() const { return SpDStruct::str;} bool EqType( const BaseGDL* r) const { return (SpDStruct::t == r->Type());} SizeT N_Elements() const { if( dd.size() == 0) return 1; return dd.size()/Sizeof(); } SizeT Size() const { return N_Elements();} SizeT NBytes() const // for assoc function { return (Sizeof() * N_Elements()); } SizeT ToTransfer() const // number of elements for IO transfer { SizeT nB = 0; SizeT nTags=NTags(); for( SizeT i=0; i < nTags; i++) { nB += GetTag( i)->ToTransfer(); } return ( nB * N_Elements()); // *** error for string? } SizeT NBytesToTransfer() // number of elements for IO transfer without padding { SizeT nB = 0; SizeT nTags=this->NTags(); for( SizeT j=0; j < this->N_Elements(); j++) { //eventually with no error for variable-length strings (in output, input will never work) for( SizeT i=0; i < nTags; i++) { if (this->GetTag(i,j)->Type()==GDL_STRUCT) { DStructGDL* str= static_cast(this->GetTag( i, j)); nB += str->NBytesToTransfer();} else nB += this->GetTag( i, j)->NBytes(); } } return nB ; } SizeT Sizeof() const { return Desc()->NBytes(); // SizeT nB = 0; // SizeT nTags=NTags(); // for( SizeT i=0; i < nTags; i++) // { // nB += desc->GetTag( &dd[0], i)->NBytes(); // } // return nB; } SizeT SizeofTags() const { SizeT nB = 0; SizeT nTags=NTags(); for( SizeT i=0; i < nTags; i++) { nB += this->GetTag(i)->NBytes(); } return nB; } private: void ClearTag( SizeT t) { if( dd.size() == 0) { typeVar[ t]->Clear(); } else { char* offs = Buf() + Desc()->Offset( t); BaseGDL* tVar = typeVar[ t]; SizeT step = Desc()->NBytes(); SizeT endIx = step * N_Elements(); for( SizeT ix=0; ixSetBuffer( offs + ix)->Clear(); } } } void ConstructTagTo0( SizeT t) { char* offs = Buf() + Desc()->Offset( t); BaseGDL* tVar = typeVar[ t]; SizeT step = Desc()->NBytes(); SizeT endIx = step * N_Elements(); for( SizeT ix=0; ixSetBuffer( offs + ix)->ConstructTo0(); } } void ConstructTag( SizeT t) { BaseGDL* tVar = typeVar[ t]; if( NonPODType( tVar->Type())) { char* offs = Buf() + Desc()->Offset( t); SizeT step = Desc()->NBytes(); SizeT endIx = step * N_Elements(); for( SizeT ix=0; ixSetBuffer( offs + ix)->Construct(); } } else tVar->SetBuffer( Buf() + Desc()->Offset( t)); } void DestructTag( SizeT t) { BaseGDL* tVar = typeVar[ t]; if( NonPODType( tVar->Type())) { char* offs = Buf() + Desc()->Offset( t); SizeT step = Desc()->NBytes(); SizeT endIx = step * N_Elements(); for( SizeT ix=0; ixSetBuffer( offs + ix)->Destruct(); } } } public: void Clear() { SizeT nTags = NTags(); for( SizeT t=0; t < nTags; t++) { ClearTag( t); } } void ConstructTo0() { SizeT nTags = NTags(); for( SizeT t=0; t < nTags; t++) { ConstructTagTo0( t); } } void Construct() { SizeT nTags = NTags(); for( SizeT t=0; t < nTags; t++) { ConstructTag( t); } } void Destruct() { SizeT nTags = NTags(); for( SizeT t=0; t < nTags; t++) { DestructTag( t); } } // code in default_io.cpp BaseGDL* AssocVar( int, SizeT); // single element access. // BaseGDL*& Get( SizeT tag, SizeT ix) BaseGDL* GetTag( SizeT t, SizeT ix) { if( dd.size() == 0) return typeVar[ t]; return typeVar[ t]->SetBuffer( Buf() + Desc()->Offset( t, ix)); } BaseGDL* GetTag( SizeT t) { if( dd.size() == 0) return typeVar[ t]; return typeVar[ t]->SetBuffer( Buf() + Desc()->Offset( t)); } const BaseGDL* GetTag( SizeT t, SizeT ix) const { if( dd.size() == 0) return typeVar[ t]; return typeVar[ t]->SetBuffer( Buf() + Desc()->Offset( t, ix)); } const BaseGDL* GetTag( SizeT t) const { if( dd.size() == 0) return typeVar[ t]; return typeVar[ t]->SetBuffer( Buf() + Desc()->Offset( t)); } // single tag access. BaseGDL* Get( SizeT tag); //*** // friend std::ostream& operator<<(std::ostream& o, DStructGDL& data_); friend std::istream& operator>>(std::istream& i, DStructGDL& data_); std::ostream& ToStream(std::ostream& o, SizeT width = 0, SizeT* actPosPtr = NULL); // std::ostream& ToStream(std::ostream& o) // { o << *this; return o;} std::ostream& ToStreamRaw(std::ostream& o); std::istream& FromStream(std::istream& i) { i >> *this; return i;} void AddParent( DStructDesc* p); // private: // void AddTag( const BaseGDL* data); // adds copy of data // void AddTagGrab(BaseGDL* data); // adds data (only used by ExtraT) // friend class ExtraT; public: // adds data, grabs, adds also to descriptor (for initialization only) // note that initialization is only for scalars void NewTag( const std::string& tName, BaseGDL* data); // for easier internal (c++) usage template< class DataGDL> void InitTag(const std::string& tName, const DataGDL& data) { int tIx = Desc()->TagIndex( tName); if( tIx == -1) throw GDLException("Struct "+Desc()->Name()+ " does not contain tag "+tName+"."); assert( GetTag( tIx)->N_Elements() == data.N_Elements()); // SA: removed, apparently unnecessary, static_cast() which was causing // numerous compiler (e.g., i686-apple-darwin9-g++-4.0.1) warnings, e.g.: // // warning: inline function // 'Data_& Data_::operator=(const Data_&)' // used but never defined // //static_cast( *GetTag( tIx)) = data; // copy data GetTag( tIx)->InitFrom( data); // copy data } // members // used by the interpreter // throws (datatypes.cpp) int Scalar2Index( SizeT& st) const; int Scalar2RangeT( RangeT& st) const; RangeT LoopIndex() const; bool Scalar() const { return (N_Elements() == 1);} // make a duplicate on the heap BaseGDL* Dup() const { return new DStructGDL(*this);} DStructGDL* New ( const dimension& dim_, BaseGDL::InitType noZero=BaseGDL::ZERO ) const { // No NOZERO for structs if ( noZero == BaseGDL::NOZERO ) { DStructGDL* res = new DStructGDL ( Desc(), dim_, noZero ); res->MakeOwnDesc(); return res; } if ( noZero == BaseGDL::INIT ) { DStructGDL* res = new DStructGDL ( Desc(), dim_, BaseGDL::NOZERO ); res->MakeOwnDesc(); SizeT nEl = res->N_Elements(); SizeT nTags = NTags(); for ( SizeT t=0; tGetTag ( t, i )->InitFrom( cpTag); // res->dd[ i] = dd[ i % nTags]->Dup(); } return res; } DStructGDL* res = new DStructGDL ( Desc(), dim_ ); res->MakeOwnDesc(); return res; } DStructGDL* NewResult() const { DStructGDL* res = new DStructGDL ( Desc(), this->dim, BaseGDL::NOZERO); res->MakeOwnDesc(); return res; } // used by interpreter, calls CatInsert DStructGDL* CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank); template< typename To> typename Data_::Ty GetAs( SizeT i); BaseGDL* Convert2( DType destTy, BaseGDL::Convert2Mode mode = BaseGDL::CONVERT); #if (defined( TEMPLATE_FRIEND_OK_) || (__GNUC__ >= 4)) && (!__clang__) // make all other Convert2 functions friends template friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); #else // this explicit version should work in all cases friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); friend BaseGDL* Data_::Convert2( DType destTy, BaseGDL::Convert2Mode); #endif std::ostream& Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs); std::istream& Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs); bool True() { throw GDLException("Struct expression not allowed in this context.");} bool False() { throw GDLException("Struct expression not allowed in this context.");} bool LogTrue() { throw GDLException("Struct expression not allowed in this context.");} bool LogTrue( SizeT ix) { throw GDLException("Struct expression not allowed in this context.");} void Where(DLong* &ret, SizeT &passed_count, bool comp, DLong* &comp_ret) { throw GDLException("Struct expression not allowed in this context.");} void Where(DLong64* &ret, SizeT &passed_count, bool comp, DLong64* &comp_ret) { throw GDLException("Struct expression not allowed in this context.");} Data_* LogNeg() { throw GDLException("Struct expression not allowed in this context.");} int Sgn(); // -1,0,1 bool Equal( BaseGDL*) const; bool EqualNoDelete( const BaseGDL*) const; bool ArrayEqual( BaseGDL*); bool ArrayNeverEqual( BaseGDL*); // 'for' statement compliance (int types , float types scalar only) void ForCheck( BaseGDL**, BaseGDL** =NULL); bool ForCondUp( BaseGDL*); bool ForCondDown( BaseGDL*); void ForAdd(); void ForAdd( BaseGDL* add=NULL); BaseGDL* UMinus(); // UMinus for SpDString returns float DStructGDL* NotOp(); DStructGDL* AndOp( BaseGDL* r); DStructGDL* AndOpInv( BaseGDL* r); DStructGDL* OrOp( BaseGDL* r); DStructGDL* OrOpInv( BaseGDL* r); DStructGDL* XorOp( BaseGDL* r); DStructGDL* Add( BaseGDL* r); DStructGDL* AddInv( BaseGDL* r); DStructGDL* Sub( BaseGDL* r); DStructGDL* SubInv( BaseGDL* r); DStructGDL* GtMark( BaseGDL* r); DStructGDL* LtMark( BaseGDL* r); DStructGDL* Mult( BaseGDL* r); DStructGDL* Div( BaseGDL* r); DStructGDL* DivInv( BaseGDL* r); DStructGDL* Mod( BaseGDL* r); DStructGDL* ModInv( BaseGDL* r); DStructGDL* Pow( BaseGDL* r); DStructGDL* PowInv( BaseGDL* r); DStructGDL* PowInt( BaseGDL* r); DStructGDL* MatrixOp( BaseGDL* r, bool atranspose, bool btranspose); DStructGDL* AndOpS( BaseGDL* r); DStructGDL* AndOpInvS( BaseGDL* r); DStructGDL* OrOpS( BaseGDL* r); DStructGDL* OrOpInvS( BaseGDL* r); DStructGDL* XorOpS( BaseGDL* r); DStructGDL* AddS( BaseGDL* r); DStructGDL* AddInvS( BaseGDL* r); DStructGDL* SubS( BaseGDL* r); DStructGDL* SubInvS( BaseGDL* r); DStructGDL* GtMarkS( BaseGDL* r); DStructGDL* LtMarkS( BaseGDL* r); DStructGDL* MultS( BaseGDL* r); DStructGDL* DivS( BaseGDL* r); DStructGDL* DivInvS( BaseGDL* r); DStructGDL* ModS( BaseGDL* r); DStructGDL* ModInvS( BaseGDL* r); DStructGDL* PowS( BaseGDL* r); DStructGDL* PowInvS( BaseGDL* r); // operators returning a new value DStructGDL* AndOpNew( BaseGDL* r); DStructGDL* AndOpInvNew( BaseGDL* r); DStructGDL* OrOpNew( BaseGDL* r); DStructGDL* OrOpInvNew( BaseGDL* r); DStructGDL* XorOpNew( BaseGDL* r); // DStructGDL* EqOpNew( BaseGDL* r); // DStructGDL* NeOpNew( BaseGDL* r); // DStructGDL* LeOpNew( BaseGDL* r); // DStructGDL* GeOpNew( BaseGDL* r); // DStructGDL* LtOpNew( BaseGDL* r); // DStructGDL* GtOpNew( BaseGDL* r); DStructGDL* AddNew( BaseGDL* r); // implemented DStructGDL* AddInvNew( BaseGDL* r); // implemented DStructGDL* SubNew( BaseGDL* r); DStructGDL* SubInvNew( BaseGDL* r); DStructGDL* LtMarkNew( BaseGDL* r); DStructGDL* GtMarkNew( BaseGDL* r); DStructGDL* MultNew( BaseGDL* r); // implemented DStructGDL* DivNew( BaseGDL* r); DStructGDL* DivInvNew( BaseGDL* r); DStructGDL* ModNew( BaseGDL* r); DStructGDL* ModInvNew( BaseGDL* r); DStructGDL* PowNew( BaseGDL* r); DStructGDL* PowInvNew( BaseGDL* r); DStructGDL* PowIntNew( BaseGDL* r); // implemented // operators with scalar returning a new value DStructGDL* AndOpSNew( BaseGDL* r); DStructGDL* AndOpInvSNew( BaseGDL* r); DStructGDL* OrOpSNew( BaseGDL* r); DStructGDL* OrOpInvSNew( BaseGDL* r); DStructGDL* XorOpSNew( BaseGDL* r); DStructGDL* AddSNew( BaseGDL* r); // implemented DStructGDL* AddInvSNew( BaseGDL* r); // implemented DStructGDL* SubSNew( BaseGDL* r); DStructGDL* SubInvSNew( BaseGDL* r); DStructGDL* LtMarkSNew( BaseGDL* r); DStructGDL* GtMarkSNew( BaseGDL* r); DStructGDL* MultSNew( BaseGDL* r); // implemented DStructGDL* DivSNew( BaseGDL* r); DStructGDL* DivInvSNew( BaseGDL* r); DStructGDL* ModSNew( BaseGDL* r); DStructGDL* ModInvSNew( BaseGDL* r); DStructGDL* PowSNew( BaseGDL* r); DStructGDL* PowInvSNew( BaseGDL* r); BaseGDL* EqOp( BaseGDL* r); BaseGDL* NeOp( BaseGDL* r); BaseGDL* GtOp( BaseGDL* r); BaseGDL* GeOp( BaseGDL* r); BaseGDL* LtOp( BaseGDL* r); BaseGDL* LeOp( BaseGDL* r); // assigns srcIn to this at ixList, if ixList is NULL does linear copy // assumes: ixList has this already set as variable // frees overwritten members void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset); void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList); void AssignAt( BaseGDL* srcIn); void AssignAtIx( RangeT ixR, BaseGDL* srcIn); void DecAt( ArrayIndexListT* ixList) { throw GDLException("Struct expression not allowed in this context."); } void IncAt( ArrayIndexListT* ixList) { throw GDLException("Struct expression not allowed in this context."); } void Dec() { throw GDLException("Struct expression not allowed in this context."); } void Inc() { throw GDLException("Struct expression not allowed in this context."); } // used by AccessDescT for resolving, no checking is done // inserts srcIn[ ixList] at offset // here d is initially empty -> no deleting of old data in InsertAt void InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList); // returns (*this)[ ixList] DStructGDL* Index( ArrayIndexListT* ixList); DStructGDL* NewIx( SizeT ix); // formatting output functions SizeT OFmtA( std::ostream* os, SizeT offset, SizeT num, int width, int code); SizeT OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code=0, const BaseGDL::IOMode oM = FIXED); SizeT OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code=0, BaseGDL::IOMode oM = DEC); SizeT IFmtA( std::istream* is, SizeT offset, SizeT num, int width); SizeT IFmtF( std::istream* is, SizeT offs, SizeT num, int width); SizeT IFmtI( std::istream* is, SizeT offs, SizeT num, int width, BaseGDL::IOMode oM = DEC); SizeT IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode); private: void IFmtAll( SizeT offs, SizeT r, SizeT& firstOut, SizeT& firstOffs, SizeT& tCount, SizeT& tCountOut); void OFmtAll( SizeT offs, SizeT r, SizeT& firstOut, SizeT& firstOffs, SizeT& tCount, SizeT& tCountOut); SizeT OFmtCal( std::ostream* os, SizeT offs, SizeT r, int w, int d, char *f, int code, BaseGDL::Cal_IOMode oMode); // inserts srcIn at ixDim // respects the exact structure // used by Assign -> old data must be freed void InsAt( DStructGDL* srcIn, ArrayIndexListT* ixList); // used for concatenation, called from CatArray // assumes that everything is checked (see CatInfo) void CatInsert( const DStructGDL* srcArr, const SizeT atDim, SizeT& at); }; #endif gdl-0.9.9/src/dvar.cpp000066400000000000000000000036711340051421000145230ustar00rootroot00000000000000/*************************************************************************** dvar.cpp - GDL system and common block variables ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "dvar.hpp" #include "nullgdl.hpp" using namespace std; DVar::DVar(const string& n, BaseGDL* data) : name(n), d(data) {} DVar::DVar() : name(), d(0) {} DVar::~DVar() { // Note: !NULL would be naturally destroyed from here at program end // we explicitely preventing the deltion to be able to flag possible // other destructions of !NULL (which are bugs) //if( d != NullGDL::GetSingleInstance()) GDLDelete(d); } void DVar::Delete() // for ResetObjects() to resolve COMMON/STRUCT mutual dependency { GDLDelete( d); d = NULL; } DVar* FindInVarList(VarListT& v, const string& s) { VarListT::iterator f=find_if(v.begin(),v.end(),DVar_eq(s)); if( f == v.end()) return NULL; return *f; } DVar* FindInVarList(VarListT& v, BaseGDL* p) { VarListT::iterator f=find_if(v.begin(),v.end(),DVar_eq(p)); if( f == v.end()) return NULL; return *f; } gdl-0.9.9/src/dvar.hpp000066400000000000000000000040441340051421000145230ustar00rootroot00000000000000/*************************************************************************** dvar.hpp - GDL common block and system variables ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DVAR_HPP_ #define DVAR_HPP_ #include #include #include #include "basegdl.hpp" // variable type class DVar { private: std::string name; // the name BaseGDL* d; public: DVar(); DVar(const std::string& n, BaseGDL* = 0); ~DVar(); void Delete(); // for ResetObjects() to resolve COMMON/STRUCT mutual dependency const std::string& Name() const {return name;} BaseGDL*& Data() { return d; } BaseGDL* Data() const { return d; } void SetData(BaseGDL* val){d=val;} }; typedef std::vector VarListT; class DVar_eq: public std::unary_function { std::string name; BaseGDL* pp; public: explicit DVar_eq(const std::string& s): name(s), pp(NULL) {} explicit DVar_eq( BaseGDL* p): name(), pp(p) {} bool operator() ( DVar* v) const { if( pp != NULL) return v->Data() == pp; return v->Name() == name; } }; DVar* FindInVarList(VarListT&, const std::string& name); DVar* FindInVarList(VarListT&, BaseGDL* p); #endif gdl-0.9.9/src/envt.cpp000066400000000000000000001325471340051421000145500ustar00rootroot00000000000000/*************************************************************************** envt.cpp - description ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "envt.hpp" #include "objects.hpp" #include "dinterpreter.hpp" #include "basic_pro.hpp" #include "nullgdl.hpp" #include // always as last using namespace std; // instance of static data DInterpreter* EnvBaseT::interpreter; // EnvBaseT::ContainerT EnvBaseT::toDestroy; // EnvT::new & delete vector< void*> EnvT::freeList; const int multiAllocEnvT = 4; void* EnvT::operator new( size_t bytes) { assert( bytes == sizeof( EnvT)); if( freeList.size() > 0) { void* res = freeList.back(); freeList.pop_back(); return res; } // cout << "*** Resize EnvT " << endl; const size_t newSize = multiAllocEnvT - 1; freeList.resize( newSize); char* res = static_cast< char*>( malloc( sizeof( EnvT) * multiAllocEnvT)); // one more than newSize for( size_t i=0; i EnvUDT::freeList; FreeListT EnvUDT::freeList; const int multiAllocEnvUDT = 16; void* EnvUDT::operator new( size_t bytes) { assert( bytes == sizeof( EnvUDT)); if( freeList.size() > 0) { return freeList.pop_back(); // void* res = freeList.back(); // freeList.pop_back(); // return res; } // cout << "*** Resize EnvUDT " << endl; const size_t newSize = multiAllocEnvUDT - 1; static long callCount = 0; ++callCount; freeList.reserve( multiAllocEnvUDT * callCount); // char* res = static_cast< char*>( malloc( sizeof( EnvUDT) * multiAllocEnvUDT)); // one more than newSize // for( size_t i=0; i( malloc( sizeOfType * multiAllocEnvUDT)); // one more than newSize res = freeList.Init( newSize, res, sizeOfType); // the one more return res; } void EnvUDT::operator delete( void *ptr) { freeList.push_back( ptr); } EnvBaseT::EnvBaseT( ProgNodeP cN, DSub* pro_): toDestroy() ,env() ,pro(pro_) ,callingNode( cN) ,lineNumber( 0) ,obj(false) ,extra(NULL) ,newEnvOff(NULL) ,ptrToReturnValue(NULL) //, toDestroyInitialIndex( toDestroy.size()) {} EnvUDT::EnvUDT( ProgNodeP cN, DSubUD* pro_, CallContext lF): EnvBaseT( cN, pro_), ioError(NULL), onError( -1), catchVar(NULL), catchNode(NULL), callContext( lF), // callContext( RFUNCTION), nJump( 0), lastJump( -1) { DSubUD* proUD=static_cast(pro); forLoopInfo.InitSize( proUD->NForLoops()); SizeT envSize; SizeT keySize; envSize=proUD->var.size(); keySize=proUD->key.size(); env.resize(envSize); parIx=keySize; // set to first parameter } EnvT::EnvT ( ProgNodeP cN, DSub* pro_): EnvBaseT ( cN, pro_) { // SizeT envSize; // SizeT keySize; parIx=pro->key.size(); if ( pro->nPar > 0 ) { env.resize ( pro->nPar + parIx); // envSize=pro->nPar+parIx; } else { env.resize ( parIx); // envSize=parIx; // performance optimization //env.reserve(envSize+5); } // env.resize ( envSize); // parIx=keySize; // set to first parameter } // member pro EnvUDT::EnvUDT( ProgNodeP cN, BaseGDL* self, const string& parent): EnvBaseT( cN, NULL), ioError(NULL), onError( -1), catchVar(NULL), catchNode(NULL), callContext( RFUNCTION), nJump( 0), lastJump( -1) { obj = true; DType selfType = self->Type(); if( selfType != GDL_OBJ) throw GDLException( cN, "Object reference type" " required in this context: "+interpreter->Name(self)); DStructGDL* oStructGDL = interpreter->ObjectStruct( static_cast(self), cN); const string& mp = cN->getText(); DStructDesc* desc=oStructGDL->Desc(); if( parent != "") { pro=desc->GetPro( mp, parent); if( pro == NULL) throw GDLException(cN,"Attempt to call undefined method: "+ parent+"::"+mp,true,false); } else { pro=desc->GetPro( mp); if( pro == NULL) throw GDLException(cN,"Attempt to call undefined method: "+ desc->Name()+"::"+mp,true,false); } DSubUD* proUD=static_cast(pro); forLoopInfo.InitSize( proUD->NForLoops()); SizeT envSize; // SizeT keySize; envSize=proUD->var.size(); parIx=proUD->key.size(); env.resize(envSize); // parIx=keySize; // set to first parameter // pass by value (self must not be changed) env.Set( parIx++, self); //static_cast(oStructGDL)); } // member fun EnvUDT::EnvUDT( BaseGDL* self, ProgNodeP cN, const string& parent, CallContext lF): EnvBaseT( cN, NULL), ioError(NULL), onError( -1), catchVar(NULL), catchNode(NULL), callContext( lF), nJump( 0), lastJump( -1) { obj = true; DType selfType = self->Type(); if( selfType != GDL_OBJ) throw GDLException( cN, "Object reference type" " required in this context: "+interpreter->Name(self)); DStructGDL* oStructGDL = interpreter->ObjectStruct( static_cast(self), cN); const string& mp = cN->getText(); DStructDesc* desc=oStructGDL->Desc(); if( parent != "") { pro=desc->GetFun( mp, parent); if( pro == NULL) throw GDLException(cN,"Attempt to call undefined method: "+ parent+"::"+mp,true,false); } else { pro=desc->GetFun( mp); if( pro == NULL) throw GDLException(cN,"Attempt to call undefined method: "+ desc->Name()+"::"+mp,true,false); } DSubUD* proUD=static_cast(pro); forLoopInfo.InitSize( proUD->NForLoops()); SizeT envSize=proUD->var.size(); parIx=proUD->key.size(); env.resize(envSize); // parIx=keySize; // set to first parameter // pass by value (self must not be changed) env.Set( parIx++, self); //static_cast(oStructGDL)); } // for obj_new, obj_destroy, call_procedure and call_function EnvT::EnvT( EnvT* pEnv, DSub* newPro, DObjGDL** self): EnvBaseT( pEnv->callingNode, newPro) { obj = (self != NULL); SizeT envSize; parIx=pro->key.size(); if( pro->nPar > 0) { envSize=pro->nPar+parIx; } else { envSize=parIx; } env.resize(envSize); // parIx=keySize; // set to first parameter // pass by reference (self must not be deleted) if( self != NULL) env.Set( parIx++, (BaseGDL**)self); //static_cast(oStructGDL)); } //EnvUDT::EnvUDT( EnvBaseT* pEnv, DSub* newPro, BaseGDL** self): EnvUDT::EnvUDT( ProgNodeP callingNode_, DSubUD* newPro, DObjGDL** self): // EnvBaseT( pEnv->CallingNode(), newPro), EnvBaseT( callingNode_, newPro), ioError(NULL), onError( -1), catchVar(NULL), catchNode(NULL), callContext( RFUNCTION), nJump( 0), lastJump( -1) { obj = (self != NULL); DSubUD* proUD= newPro; //static_cast(pro); forLoopInfo.InitSize( proUD->NForLoops()); SizeT envSize; // SizeT keySize; envSize=proUD->var.size(); parIx=proUD->key.size(); env.resize(envSize); // parIx=keySize; // set to first parameter // pass by reference (self must not be deleted) if( self != NULL) env.Set( parIx++, (BaseGDL**)self); //static_cast(oStructGDL)); } void EnvBaseT::AddStruct( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DStructGDL* stru) { if( stru == NULL) return; SizeT nEl = stru->N_Elements(); const DStructDesc* desc = stru->Desc(); // avoid recursion on LIST (for > 100000 list elements a segfault is generated otherwise) if( desc->IsParent("LIST")) { AddLIST(ptrAccessible, objAccessible, stru); return; } SizeT nTags = desc->NTags(); for( SizeT t=0; tType() == GDL_PTR) { for( SizeT e = 0; e( stru->GetTag( t, e)); AddPtr( ptrAccessible, objAccessible, ptr); } } else if( (*desc)[ t]->Type() == GDL_STRUCT) { for( SizeT e = 0; e( stru->GetTag( t, e)); AddStruct( ptrAccessible, objAccessible, ptr); } } else if( (*desc)[ t]->Type() == GDL_OBJ) { for( SizeT e = 0; e( stru->GetTag( t, e)); AddObj( ptrAccessible, objAccessible, obj); } } } } void EnvBaseT::AddPtr( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DPtrGDL* ptr) { if( ptr == NULL) return; SizeT nEl = ptr->N_Elements(); for( SizeT e = 0; ePtrValid( p)) { if( ptrAccessible.find( p) == ptrAccessible.end()) { ptrAccessible.insert( p); Add( ptrAccessible, objAccessible, interpreter->GetHeap( p)); } } } } void EnvBaseT::AddObj( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DObjGDL* ptr) { if( ptr == NULL) return; SizeT nEl = ptr->Size();// N_Elements(); for( SizeT e = 0; eObjValid( p)) { if( objAccessible.find( p) == objAccessible.end()) { objAccessible.insert( p); AddStruct( ptrAccessible, objAccessible, interpreter->GetObjHeap( p)); } } } } void EnvBaseT::Add( DPtrListT& ptrAccessible, DPtrListT& objAccessible, BaseGDL* p) { if( p == NULL) return; DType pType = p->Type(); if( pType == GDL_PTR) AddPtr( ptrAccessible, objAccessible, static_cast< DPtrGDL*>( p)); else if( pType == GDL_STRUCT) AddStruct( ptrAccessible, objAccessible, static_cast< DStructGDL*>( p)); else if( pType == GDL_OBJ) AddObj( ptrAccessible, objAccessible, static_cast< DObjGDL*>( p)); } void EnvBaseT::AddEnv( DPtrListT& ptrAccessible, DPtrListT& objAccessible) { for( SizeT e=0; e VectorDObj; void EnvT::HeapGC( bool doPtr, bool doObj, bool verbose) { // within CLEANUP method HEAP_GC could be called again // within CLEANUP common block or global variables may be freed // thus HEAP_GC has to be called again if called (but only once) static SizeT inProgress = 0; if( inProgress > 0) { inProgress = 2; return; } startGC: inProgress = 1; try { DPtrListT ptrAccessible; DPtrListT objAccessible; // search common blocks for( CommonListT::iterator c = commonList.begin(); c != commonList.end(); ++c) { DCommon* common = *c; SizeT nVar = common->NVar(); for( SizeT v = 0; v < nVar; ++v) { DVar* var = common->Var( v); if( var != NULL) { Add( ptrAccessible, objAccessible, var->Data()); } } } SizeT nVar = sysVarList.size(); for( SizeT v=0; vData()); } } EnvStackT& cS=interpreter->CallStack(); // for( EnvStackT::reverse_iterator r = cS.rbegin(); r != cS.rend(); ++r) for( long ix = cS.size()-1; ix >= 0; --ix) { cS[ix]->AddEnv( ptrAccessible, objAccessible); } // add all data already set for destruction (not to be deleted now) AddToDestroy( ptrAccessible, objAccessible); // do OBJ first as the cleanup might need the GDL_PTR be valid if( doObj) { std::vector* heap = interpreter->GetAllObjHeapSTL(); Guard< std::vector > heap_guard( heap); SizeT nH = heap->size();//N_Elements(); if( nH > 0 && (*heap)[0] != 0) { for( SizeT h=0; hObjValid( p)) if( objAccessible.find( p) == objAccessible.end()) { if( verbose) { BaseGDL* hV = GetObjHeap( p); lib::help_item( cout, hV, DString( "", false); } ObjCleanup( p); } // else // objAccessible.erase( p); } } } if( doPtr) { std::vector* heap = interpreter->GetAllHeapSTL(); Guard< std::vector > heap_guard( heap); SizeT nH = heap->size(); if( nH > 0 && (*heap)[0] != 0) { for( SizeT h=0; hPtrValid( p)) if( ptrAccessible.find( p) == ptrAccessible.end()) { if( verbose) { BaseGDL* hV = GetHeap( p); lib::help_item( cout, hV, DString( "", false); } interpreter->FreeHeap( p); } // else // ptrAccessible.erase( p); } } } } catch( ...) { // make sure HEAP_GC stays not disabled in case of unhandled error inProgress = 0; throw; } if( inProgress == 2) { inProgress = 1; goto startGC; } inProgress = 0; } set< DObj> EnvBaseT::inProgress; class InProgressGuard { private: DObj actID; public: InProgressGuard( DObj id): actID( id) { EnvBaseT::inProgress.insert( actID); } ~InProgressGuard() { EnvBaseT::inProgress.erase( actID); } }; // for CLEANUP calls due to reference counting // note: refcount is already zero for actID void EnvBaseT::ObjCleanup( DObj actID) { if( actID == 0 || (inProgress.find( actID) != inProgress.end())) return; DStructGDL* actObj; try{ actObj=GetObjHeap( actID); } catch( GDLInterpreter::HeapException&){ // not found return; } // found actID if( actObj != NULL) { InProgressGuard inProgressGuard( actID); // exception save Guard actObjGDL_guard; try{ // call CLEANUP function DPro* objCLEANUP= actObj->Desc()->GetPro( "CLEANUP"); if( objCLEANUP != NULL) { DObjGDL* actObjGDL = new DObjGDL( actID); actObjGDL_guard.Init( actObjGDL); GDLInterpreter::IncRefObj( actID); // set refcount to 1 PushNewEmptyEnvUD( objCLEANUP, &actObjGDL); interpreter->call_pro( objCLEANUP->GetTree()); EnvBaseT* callStackBack = interpreter->CallStack().back(); interpreter->CallStack().pop_back(); delete callStackBack; } } catch( ...) { FreeObjHeap( actID); // make sure actObj is freed throw; // rethrow } // actObjGDL_guard goes out of scope -> refcount is (would be) decreased FreeObjHeap( actID); } else // actObj == NULL { Warning("Cleaning up invalid (NULL) OBJECT ID <"+i2s(actID)+">."); FreeObjHeap( actID); // make sure actObj is freed } } void EnvT::ObjCleanup( DObj actID) { if( actID != 0 && (inProgress.find( actID) == inProgress.end())) { DStructGDL* actObj; try { actObj=GetObjHeap( actID); // GDLInterpreter::ObjHeapT::iterator it; // actObj=GDLInterpreter::GetObjHeap( actID, it); } catch( GDLInterpreter::HeapException) { actObj=NULL; } if( actObj != NULL) { // call CLEANUP function DPro* objCLEANUP= actObj->Desc()->GetPro( "CLEANUP"); if( objCLEANUP != NULL) { DObjGDL* actObjGDL = new DObjGDL( actID); Guard actObjGDL_guard( actObjGDL); GDLInterpreter::IncRefObj( actID); StackGuard guard( interpreter->CallStack()); EnvUDT* newEnv = PushNewEnvUD( objCLEANUP, 1, &actObjGDL); inProgress.insert( actID); interpreter->call_pro( objCLEANUP->GetTree()); inProgress.erase( actID); // delete newEnv; // interpreter->CallStack().pop_back(); } FreeObjHeap( actID); // the actual freeing } } } // these two functions should be inlined SizeT EnvBaseT::NewObjHeap( SizeT n, DStructGDL* v) { return interpreter->NewObjHeap(n,v); } SizeT EnvBaseT::NewHeap( SizeT n, BaseGDL* v) { return interpreter->NewHeap(n,v); } void EnvBaseT::FreeObjHeap( DObj id) { interpreter->FreeObjHeap( id); } void EnvBaseT::FreeHeap( DPtrGDL* p) { interpreter->FreeHeap(p); } // // DStructGDL* EnvT::GetObjHeap( DObj ID, ObjHeapT::iterator& it) // // { // // return interpreter->GetObjHeap( ID, it); // // } DStructGDL* EnvBaseT::GetObjHeap( DObj ID) { return interpreter->GetObjHeap( ID); } BaseGDL* EnvBaseT::GetHeap( DPtr ID) { return interpreter->GetHeap( ID); } // returns name of BaseGDL*& const string EnvBaseT::GetString( BaseGDL*& p, bool calledFromHELP) { DSubUD* subUD=dynamic_cast(pro); SizeT nVar=env.size(); const string Default = ""; string name = Default; for( SizeT ix=0; ixGetVarName(ix);} string callerName = Default; if( this->Caller() != NULL) callerName = this->Caller()->GetString( p, calledFromHELP); if( callerName.length() < Default.length() || callerName.substr(0,Default.length()) != Default) return callerName; if( ix < pro->key.size()) {name="";break;} name="key.size())+">"; break; } } // search system variables // note: system variables are never passed by reference // ie. always a copy is passed. // therefore the help function never returns the sys var's name here // DVar* sysVar=FindInVarList( sysVarList, p); // if( sysVar != NULL) return sysVar->Name(); // search common blocks if( name == Default && subUD != NULL) { string varName; if( subUD->GetCommonVarName4Help( p, varName)) return varName; } if( !p) { return ""; } if( !calledFromHELP) { ostringstream os; os << '<' << left; os.width(10); os << p->TypeStr() << right; // Data display if( p->Type() == GDL_STRUCT) { /* DStructGDL* s = static_cast( p); os << "-> "; os << (s->Desc()->IsUnnamed()? "" : s->Desc()->Name()); os << " ";*/ } else if( p->Dim( 0) == 0) { os << "("; if (p->Type() == GDL_STRING) { // trim string larger than 45 characters DString dataString = (*static_cast(p))[0]; os << "'" << StrMid( dataString,0,45,0) << "'"; if( dataString.length() > 45) os << "..."; } else { p->ToStream( os); } os << ")"; } // Dimension display if( p->Dim( 0) != 0) os << p->Dim(); os << ">"; name += " " + os.str(); // return os.str(); } return name; //string(""); } // // returns name of BaseGDL* // const string EnvBaseT::GetString( BaseGDL* p) // { // DSubUD* subUD=dynamic_cast(pro); // // SizeT nVar=env.size(); // for( SizeT ix=0; ixGetVarName(ix); // if( ix < pro->key.size()) return "KEYWORD_"+i2s(ix); // return "PAR_VAR_"+i2s(ix - pro->key.size()); // } // } // // // search system variables // // note: system variables are never passed by reference // // ie. always a copy is passed. // // therefore the help function never returns the sys var's name here // // DVar* sysVar=FindInVarList( sysVarList, p); // // if( sysVar != NULL) return sysVar->Name(); // // // search common blocks // if( subUD != NULL) // { // string varName; // if( subUD->GetCommonVarName( p, varName)) return varName; // } // // if( !p) // { // return ""; // } // // // if( !calledFromHELP) // { // ostringstream os; // os << '<' << left; // os.width(10); // os << p->TypeStr() << right; // // // Data display // if( p->Type() == GDL_STRUCT) // { // DStructGDL* s = static_cast( p); // os << "-> "; // os << (s->Desc()->IsUnnamed()? "" : s->Desc()->Name()); // os << " "; // } // else if( p->Dim( 0) == 0) // { // os << "("; // if (p->Type() == GDL_STRING) // { // // trim string larger than 45 characters // DString dataString = (*static_cast(p))[0]; // os << "'" << StrMid( dataString,0,45,0) << "'"; // if( dataString.length() > 45) os << "..."; // } // else // { // p->ToStream( os); // } // os << ")"; // } // // // Dimension display // if( p->Dim( 0) != 0) os << p->Dim(); // // os << ">"; // // return os.str(); // } // // return string(""); // } void EnvT::Help(const std::string s_help[], int size_of_s) { if (size_of_s == 0) throw GDLException( CallingNode(), pro->ObjectName()+": no inline doc ready"); else { int i; for (i = 0; i < size_of_s; i++) Message(pro->ObjectName()+": "+s_help[i]); throw GDLException( CallingNode(), pro->ObjectName()+": call to inline help"); } } //TODO: variant enabling static ints in lieu of const string& (speedup!) void EnvBaseT::SetKeyword( const string& k, BaseGDL* const val) // value { int varIx=GetKeywordIx( k); // -4 means ignore (warn keyword) if( varIx == -4) return; // -2 means _EXTRA keyword // -3 means _STRICT_EXTRA keyword if( varIx <= -2) { if( extra == NULL) extra = new ExtraT( this); extra->Set(val); extra->SetStrict( varIx == -3); return; } // -1 means an extra (additional) keyword if( varIx == -1) { if( extra == NULL) extra = new ExtraT( this); extra->Add(k,val); return; } env.Set( varIx,val); } //TODO: variant enabling static ints in lieu of const string& (speedup!) void EnvBaseT::SetKeyword( const string& k, BaseGDL** const val) // reference { int varIx=GetKeywordIx( k); // -4 means ignore (warn keyword) if( varIx == -4) return; // -2 means _EXTRA keyword // -3 means _STRICT_EXTRA keyword if( varIx <= -2) { if( extra == NULL) extra = new ExtraT( this); extra->Set(val); extra->SetStrict( varIx == -3); return; } // -1 means an extra (additional) keyword if( varIx == -1) { if( extra == NULL) extra = new ExtraT( this); extra->Add(k,val); return; } env.Set( varIx,val); } // called after parameter definition void EnvBaseT::ResolveExtra() { if( extra != NULL) extra->ResolveExtra( NULL); } // // for internal non-library routines (e.g. operator overloads) ('this' is on the stack) // EnvUDT* EnvUDT::CallingEnv() // { // EnvStackT& callStack=interpreter->CallStack(); // assert( callStack.size() >= 2); // must be: "$MAIN$" and the EnvUDT of the internal routine // return callStack[callStack.size()-2]; // } // for library subroutines, get the EnvUDT from which they are called EnvBaseT* EnvBaseT::Caller() { EnvStackT& callStack=interpreter->CallStack(); //if( callStack.size() <= 1) return NULL; // library environments are no longer on the call stack // but since we have WRAPPED_FUNNode it is convenient // assert( callStack.back() != this); if( callStack.back() == this) { assert( callStack.size() >= 2); return callStack[ callStack.size() - 2]; } return callStack.back(); // if( callStack.back() != this) // return callStack.back(); // // return static_cast< EnvUDT*>( callStack.back()); // // return callStack[ callStack.size()-2]; // // return static_cast< EnvUDT*>( callStack[ callStack.size()-2]); } // used by obj_new (basic_fun.cpp) // and obj_destroy (basic_pro.cpp) void EnvBaseT::PushNewEmptyEnvUD( DSubUD* newPro, DObjGDL** newObj) { EnvUDT* newEnv= new EnvUDT( this->CallingNode(), newPro, newObj); // pass the parameters, skip the first 'skipP' // SizeT nParam = NParam(); // for( SizeT p=skipP; pSetNextPar( &GetPar( p)); // pass as global // } interpreter->CallStack().push_back( newEnv); // _REF_EXTRA is set to the keyword string array // newEnv->extra = new ExtraT( newEnv); // newEnv->extra->Set( &env[0]); // newEnv->extra->Resolve(); } // used by obj_new (basic_fun.cpp) // and obj_destroy (basic_pro.cpp) // and call_function (basic_fun.cpp) // and call_procedure (basic_pro.cpp) EnvUDT* EnvT::PushNewEnvUD( DSubUD* newPro, SizeT skipP, DObjGDL** newObj) { EnvUDT* newEnv= new EnvUDT( this->CallingNode(), newPro, newObj); // pass the parameters, skip the first 'skipP' SizeT nParam = NParam(); for( SizeT p=skipP; pSetNextPar( &GetPar( p)); // pass as global } // interpreter->CallStack().push_back( newEnv); // problem with call_function if done here s. b. // _REF_EXTRA is set to the keyword string array newEnv->extra = new ExtraT( newEnv); newEnv->extra->Set( &env[0]); newEnv->extra->ResolveExtra( this); // s. a. problem caused here due to a call to EnvBaseT::Caller() in Resolve() interpreter->CallStack().push_back( newEnv); return newEnv; } // used by obj_new (basic_fun.cpp) // and obj_destroy (basic_pro.cpp) // and call_function (basic_fun.cpp) // and call_procedure (basic_pro.cpp) EnvT* EnvT::NewEnv( DSub* newPro, SizeT skipP, DObjGDL** newObj) { EnvT* newEnv= new EnvT( this, newPro, newObj); // pass the parameters, skip the first 'skipP' SizeT nParam = NParam(); for( SizeT p=skipP; pSetNextPar( &GetPar( p)); // pass as global } // interpreter->CallStack().push_back( newEnv); // _REF_EXTRA is set to the keyword string array newEnv->extra = new ExtraT( newEnv); newEnv->extra->Set( &env[0]); newEnv->extra->ResolveExtra( this); return newEnv; } void EnvT::AssureGlobalPar( SizeT pIx) { SizeT ix= pIx + pro->key.size(); AssureGlobalKW( ix); } void EnvBaseT::AssureGlobalKW( SizeT ix) { if( env.Env( ix) == NULL) { if( env.Loc( ix) != NULL) Throw( "Attempt to store into an expression."); else Throw( "Parameter must be a named variable."); } } DStructGDL* EnvT::GetObjectPar( SizeT pIx) { BaseGDL* p1 = GetParDefined(pIx); if( p1->Type() != GDL_OBJ) { Throw( "Parameter must be an object reference" " in this context: "+ GetParString(pIx)); } else { DObjGDL* oRef = static_cast (p1); DObj objIx; if (!oRef->Scalar(objIx)) Throw("Parameter must be a scalar or 1 element array in this context: " + GetParString(pIx)); if (objIx == 0) Throw("Unable to invoke method" " on NULL object reference: " + GetParString(pIx)); try { return GetObjHeap(objIx); } catch ( GDLInterpreter::HeapException) { Throw("Object not valid: " + GetParString(pIx)); } } return NULL; //keep clang happy. } // for exclusive use by lib::catch_pro void EnvT::Catch() { EnvUDT* caller = static_cast(Caller()); if( caller == NULL) return; SizeT nParam = NParam(); if( nParam == 0) { if( KeywordSet( 0)) // CANCEL { caller->catchVar = NULL; caller->catchNode = NULL; } return; } if( !GlobalPar( 0)) Throw( "Expression must be named variable " "in this context: " + GetParString(0)); caller->catchNode = callingNode->getNextSibling(); caller->catchVar = &GetPar( 0); GDLDelete(*caller->catchVar); *caller->catchVar = new DLongGDL( 0); } // for exclusive use by lib::on_error void EnvT::OnError() { SizeT nParam = NParam(); DLong onE = 0; if( nParam > 0) AssureLongScalarPar( 0, onE); if( onE < 0 || onE > 3) Throw( "Value out of allowed range: " + GetParString(0)); EnvUDT* caller = static_cast(Caller()); if( caller == NULL) return; caller->onError = onE; } int EnvT::KeywordIx( const std::string& k) { // cout << pro->ObjectName() << " Key: " << k << endl; assert( pro != NULL); int val=pro->FindKey( k); if( val == -1) { // assert( val != -1); cout << "Invalid Keyword lookup (EnvT::KeywordIx) ! " " from "+pro->ObjectName() + " Key: " + k << endl; // cout << pro->ObjectName() << " Key: " << k << endl; // << " Returning the wrong (but a valid) key index of zero" << endl; // val = 0; // too lax - may allow most tests to pass assert( val != -1); } return val; } bool EnvT::KeywordPresent( const std::string& kw) { int ix = KeywordIx( kw); return EnvBaseT::KeywordPresent( ix); } const string EnvBaseT::GetString( SizeT ix) { const string unnamed(""); DSubUD* subUD=dynamic_cast(pro); if( subUD == NULL) { // internal subroutine DLib* subLib=dynamic_cast(pro); if( subLib != NULL) { EnvBaseT* caller = Caller(); if( caller != NULL) return caller->GetString( env[ ix]); } return unnamed; } // UD subroutine return subUD->GetVarName( ix); } // SA: used by GDL_STRING() for VMS-compat hack void EnvT::ShiftParNumbering(int n) { assert(abs(n) == 1); // currently the code below works for n = +/- 1 only SizeT nParam = NParam(); SizeT oParam = pro->key.size(); if (n == 1) { BaseGDL* tmp = env[oParam + nParam - 1]; for (int i = nParam - 1; i > 0; --i) { env[oParam + i] = env[oParam + i - 1]; } env[oParam] = tmp; } else if (n == -1) { BaseGDL* tmp = env[oParam]; for (int i = 0; i < nParam - 1; ++i) { env[oParam + i] = env[oParam + i + 1]; } env[oParam + nParam - 1] = tmp; } } BaseGDL*& EnvBaseT::GetParDefined(SizeT i) { SizeT ix = i + pro->key.size(); // cout << i << " -> " << ix << " " << env.size() << " env[ix] " << env[ix] << endl; if( ix >= env.size()) Throw("Incorrect number of arguments."); if( env[ ix] == NULL || env[ ix] == NullGDL::GetSingleInstance()) Throw("Variable is undefined: "+GetString( ix)); return env[ ix]; } BaseGDL*& EnvT::GetParDefined(SizeT i) { return EnvBaseT::GetParDefined( i); } BaseGDL*& EnvT::GetParGlobal(SizeT pIx) { AssureGlobalPar( pIx); return GetPar( pIx); } // get i'th parameter, subName is used for error reporting // throws if not present (ie. not global) // paramter might be NULL (but ¶mter is a valid BaseGDL** to store into) // BaseGDL*& EnvT::GetParPresent(SizeT i, const std::string& subName = "") // { // SizeT ix = i + pro->key.size(); // if( ix >= env.size() || env.Env( ix) == NULL) // if( subName != "") // throw GDLException( callingNode, subName+": Paramter must be a " // "named variable in this context: "+ // GetString( ix)); // else // throw GDLException( callingNode, "Paramter must be a " // "named variable in this context: "+ // GetString( ix)); // return env[ ix]; // } SizeT EnvBaseT::NParam( SizeT minPar) { assert( pro != NULL); SizeT nPar = parIx - pro->key.size(); if( nPar < minPar) Throw( "Incorrect number of arguments."); return nPar; } SizeT EnvT::NParam( SizeT minPar) { return EnvBaseT::NParam( minPar); } bool EnvBaseT::Removeall() { DSubUD* proD=dynamic_cast(pro); int osz = env.size(); for( SizeT ix=0; ix < osz; ix++) { if( env[ix] != NULL) GDLDelete( env[ix]); env.pop_back(); } proD->Resize(0); return true; } bool EnvBaseT::Remove(int* rindx) { DSubUD* proD=dynamic_cast(pro); static volatile bool debug( false); // switch off/on static int ix, osz, inrem; osz = env.size(); inrem = 0; int itrg = rindx[0]; ix=itrg; if(debug) printf(" env.size() = %d", osz); while( ix >= 0) { inrem++; if(debug) printf(" env.now.size() = %d env[%d] = %p ", osz - inrem, ix,static_cast (env[ix]) ); if ( env[ix] != NULL) GDLDelete( env[ix]); int esrc = rindx[inrem]; if(esrc < 0) esrc = osz; if(debug) cout << " limit:"<< esrc ; while( ++ix < esrc) { if(debug) cout << ", @:"<ReName(itrg++, proD->GetVarName(ix)); } ix=rindx[inrem]; if(debug) cout << " inrem:"< 0) env.pop_back(); env.resize(osz); proD->Resize(osz); return true; } int EnvBaseT::findvar(const std::string& s) { DSubUD* proD=dynamic_cast(pro); int kIx = proD->FindVar(s); return kIx; } int EnvBaseT::findvar(BaseGDL* delP) { // static BaseGDL* null=NULL; for(int Ix=0; Ix < env.size(); Ix++) { if(delP != env[ Ix] ) continue; return Ix; } return -1; } void EnvBaseT::SetNextParUnchecked( BaseGDL* const nextP) // by value (reset loc) { // if(!( static_cast(parIx - pro->key.size()) < pro->nPar)) assert( static_cast(parIx - pro->key.size()) < pro->nPar); env.Set(parIx++,nextP); // check done in parameter_def } void EnvBaseT::SetNextParUncheckedVarNum( BaseGDL* const nextP) // by reference (reset env) { AddEnv(); env.Set(parIx++,nextP); } void EnvBaseT::SetNextParUnchecked( BaseGDL** const nextP) // by reference (reset env) { assert( static_cast(parIx - pro->key.size()) < pro->nPar); env.Set(parIx++,nextP); } void EnvBaseT::SetNextParUncheckedVarNum( BaseGDL** const nextP) // by reference (reset env) { AddEnv(); env.Set(parIx++,nextP); } void EnvBaseT::SetNextPar( BaseGDL* const nextP) // by value (reset loc) { if( pro->nPar >= 0) { if( static_cast(parIx - pro->key.size()) >= pro->nPar) { throw GDLException(callingNode, pro->Name()+": Incorrect number of arguments.",false,false); } } else { // variable number of parameters (only lib functions) AddEnv(); } env.Set(parIx++,nextP); } void EnvBaseT::SetNextPar( BaseGDL** const nextP) // by reference (reset env) { if( pro->nPar >= 0) { if( static_cast(parIx - pro->key.size()) >= pro->nPar) { throw GDLException(callingNode, pro->Name()+": Incorrect number of arguments.",false,false); } } else { // variable number of parameters (only lib functions) AddEnv(); } env.Set(parIx++,nextP); } // returns the keyword index, used for UD functions int EnvBaseT::GetKeywordIx( const std::string& k) { String_abbref_eq strAbbrefEq_k(k); // if there are no keywords, even _EXTRA isn't allowed if( pro->key.size() == 0) { if( pro->warnKey.size() == 0) Throw( "Keyword parameters not allowed in call."); // look if warnKeyword IDList::iterator wf=std::find_if(pro->warnKey.begin(), pro->warnKey.end(), strAbbrefEq_k); if( wf == pro->warnKey.end()) Throw( "Keyword parameter -"+k+"- not allowed in call " "to: "+pro->Name()); // throw GDLException(callingNode, // "Keyword parameter "+k+" not allowed in call " // "to: "+pro->Name()); Warning("Warning: Keyword parameter "+k+" not supported in call " "to: "+pro->Name() + ". Ignored."); return -4; } // search keyword KeyVarListT::iterator f=std::find_if(pro->key.begin(), pro->key.end(), strAbbrefEq_k); if( f == pro->key.end()) { // every routine (which accepts keywords), also accepts (_STRICT)_EXTRA if( strAbbrefEq_k("_EXTRA")) return -2; if( strAbbrefEq_k("_STRICT_EXTRA")) return -3; if( pro->Extra() == DSub::NONE) { // look if warnKeyword IDList::iterator wf=std::find_if(pro->warnKey.begin(), pro->warnKey.end(), strAbbrefEq_k); if( wf == pro->warnKey.end()) Throw( "Keyword parameter <"+k+"> not allowed in call " "to: "+pro->Name()); /* throw GDLException(callingNode, "Keyword parameter "+k+" not allowed in call " "to: "+pro->Name());*/ Warning("Warning: Keyword parameter "+k+" not supported in call " "to: "+pro->Name() + ". Ignored."); return -4; } // extra keyword return -1; } // continue search (for ambiguity) KeyVarListT::iterator ff=std::find_if(f+1, pro->key.end(), strAbbrefEq_k); if( ff != pro->key.end()) { Throw("Ambiguous keyword abbreviation: "+k); } // every routine (which accepts keywords), also accepts (_STRICT)_EXTRA if( strAbbrefEq_k("_EXTRA")) return -2; if( strAbbrefEq_k("_STRICT_EXTRA")) return -3; SizeT varIx=std::distance(pro->key.begin(),f); // already set? -> Warning // (move to Throw by AC on June 25, 2014, bug found by Levan.) // Removed G. Jung 2016: // mungs things up. Could not determine 2014 bug. // if( KeywordPresent(varIx)) // just a message in the original // { // Throw( "Duplicate keyword "+k+" in call to: "+pro->Name()); // } return varIx; } // for use within library functions bool EnvT::KeywordSet( const std::string& kw) { assert( pro != NULL); int ix=pro->FindKey( kw); if( ix == -1) return false; return KeywordSet( static_cast(ix)); } bool EnvT::KeywordSet( SizeT ix) { return EnvBaseT::KeywordSet( ix); } bool EnvBaseT::KeywordSet( SizeT ix) { BaseGDL* keyword=env[ix]; if( keyword == NULL) return false; if( !keyword->Scalar()) return true; if( keyword->Type() == GDL_STRUCT) return true; return keyword->LogTrue(); } // returns the ix'th parameter (for library function API only) BaseGDL*& EnvT::GetPar(SizeT i) { static BaseGDL* null=NULL; SizeT ix= i + pro->key.size(); if( ix >= env.size()) { // Warning( "EnvT::GetPar(): Index out of env size ("+i2s(env.size())+"): " + i2s(i) +" (+ "+i2s(pro->key.size())+" KW)"); return null; } return env[ ix]; } // BaseGDL*& EnvT::GetParUnchecked(SizeT i) // { // SizeT ix= i + pro->key.size(); // return env[ ix]; // } void EnvBaseT::AssureLongScalarPar( SizeT pIx, DLong64& scalar) { BaseGDL* p = GetParDefined( pIx); DLong64GDL* lp = static_cast(p->Convert2( GDL_LONG64, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Parameter must be a scalar or 1 element array in this context: "+ GetParString(pIx)); } void EnvBaseT::AssureLongScalarPar( SizeT pIx, DLong& scalar) { BaseGDL* p = GetParDefined( pIx); DLongGDL* lp = static_cast(p->Convert2( GDL_LONG, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Parameter must be a scalar or 1 element array in this context: "+ GetParString(pIx)); } void EnvT::AssureLongScalarPar( SizeT pIx, DLong64& scalar) { EnvBaseT::AssureLongScalarPar( pIx, scalar); } void EnvT::AssureLongScalarPar( SizeT pIx, DLong& scalar) { EnvBaseT::AssureLongScalarPar( pIx, scalar); } // if keyword 'kw' is not set, 'scalar' is left unchanged void EnvT::AssureLongScalarKWIfPresent( const std::string& kw, DLong& scalar) { int ix = KeywordIx( kw); if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureLongScalarKW( ix, scalar); } void EnvT::AssureLongScalarKWIfPresent( SizeT ix, DLong& scalar) { if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureLongScalarKW( ix, scalar); } // converts keyword 'kw' if necessary and sets 'scalar' void EnvT::AssureLongScalarKW( const std::string& kw, DLong& scalar) { AssureLongScalarKW( KeywordIx( kw), scalar); } void EnvT::AssureLongScalarKW( const std::string& kw, DLong64& scalar) { AssureLongScalarKW( KeywordIx( kw), scalar); } void EnvT::AssureLongScalarKW( SizeT eIx, DLong64& scalar) { BaseGDL* p = GetKW( eIx); if( p == NULL) Throw("Expression undefined: "+GetString(eIx)); DLong64GDL* lp= static_cast(p->Convert2( GDL_LONG64, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Expression must be a scalar or 1 element array in this context: "+ GetString(eIx)); } void EnvT::AssureLongScalarKW( SizeT eIx, DLong& scalar) { BaseGDL* p = GetKW( eIx); if( p == NULL) Throw("Expression undefined: "+GetString(eIx)); DLongGDL* lp= static_cast(p->Convert2( GDL_LONG, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Expression must be a scalar or 1 element array in this context: "+ GetString(eIx)); } void EnvT::AssureDoubleScalarPar( SizeT pIx, DDouble& scalar) { BaseGDL* p = GetParDefined( pIx); DDoubleGDL* lp = static_cast(p->Convert2( GDL_DOUBLE, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Parameter must be a scalar or 1 element array in this context: "+ GetParString(pIx)); } void EnvT::AssureDoubleScalarKWIfPresent( const std::string& kw, DDouble& scalar) { int ix = KeywordIx( kw); if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureDoubleScalarKW( ix, scalar); } void EnvT::AssureDoubleScalarKWIfPresent( SizeT ix, DDouble& scalar) { if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureDoubleScalarKW( ix, scalar); } void EnvT::AssureDoubleScalarKW( const std::string& kw, DDouble& scalar) { AssureDoubleScalarKW( KeywordIx( kw), scalar); } void EnvT::AssureDoubleScalarKW( SizeT eIx, DDouble& scalar) { BaseGDL* p = GetKW( eIx); if( p == NULL) Throw("Expression undefined: "+GetString(eIx)); DDoubleGDL* lp= static_cast(p->Convert2( GDL_DOUBLE, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Expression must be a scalar or 1 element array in this context: "+ GetString(eIx)); } void EnvT::AssureFloatScalarPar( SizeT pIx, DFloat& scalar) { BaseGDL* p = GetParDefined( pIx); DFloatGDL* lp = static_cast(p->Convert2( GDL_FLOAT, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Parameter must be a scalar or 1 element array in this context: "+ GetParString(pIx)); } void EnvT::AssureFloatScalarKWIfPresent( const std::string& kw, DFloat& scalar) { int ix = KeywordIx( kw); if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureFloatScalarKW( ix, scalar); } void EnvT::AssureFloatScalarKWIfPresent( SizeT ix, DFloat& scalar) { if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureFloatScalarKW( ix, scalar); } void EnvT::AssureFloatScalarKW( const std::string& kw, DFloat& scalar) { AssureFloatScalarKW( KeywordIx( kw), scalar); } void EnvT::AssureFloatScalarKW( SizeT eIx, DFloat& scalar) { BaseGDL* p = GetKW( eIx); if( p == NULL) Throw("Expression undefined: "+GetString(eIx)); DFloatGDL* lp= static_cast(p->Convert2( GDL_FLOAT, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Expression must be a scalar or 1 element array in this context: "+ GetString(eIx)); } void EnvT::AssureStringScalarPar( SizeT pIx, DString& scalar) { BaseGDL* p = GetParDefined( pIx); DStringGDL* lp = static_cast(p->Convert2( GDL_STRING, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Parameter must be a scalar or 1 element array in this context: "+ GetParString(pIx)); } void EnvT::AssureStringScalarKWIfPresent( const std::string& kw, DString& scalar) { int ix = KeywordIx( kw); if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureStringScalarKW( ix, scalar); } void EnvT::AssureStringScalarKWIfPresent( SizeT ix, DString& scalar) { if( env[ix] == NULL) return; // if( !KeywordPresent( ix)) return; AssureStringScalarKW( ix, scalar); } void EnvT::AssureStringScalarKW( const std::string& kw, DString& scalar) { AssureStringScalarKW( KeywordIx( kw), scalar); } void EnvT::AssureStringScalarKW( SizeT eIx, DString& scalar) { BaseGDL* p = GetKW( eIx); if( p == NULL) Throw("Expression undefined: "+GetString(eIx)); DStringGDL* lp= static_cast(p->Convert2( GDL_STRING, BaseGDL::COPY)); Guard guard_lp( lp); if( !lp->Scalar( scalar)) Throw("Expression must be a scalar or 1 element array in this context: "+ GetString(eIx)); } void EnvBaseT::SetKW( SizeT ix, BaseGDL* newVal) { // can't use Guard here as data has to be released Guard guard( newVal); AssureGlobalKW( ix); GDLDelete(GetKW( ix)); GetKW( ix) = guard.release(); } void EnvT::SetPar( SizeT ix, BaseGDL* newVal) { // can't use Guard here as data has to be released Guard guard( newVal); AssureGlobalPar( ix); GDLDelete(GetPar( ix)); GetPar( ix) = guard.release(); } // bool EnvBaseT::Contains( BaseGDL* p) const // { // if( env.Contains( p)) return true; // if (static_cast(pro)->GetCommonVarPtr( p) != NULL) return true; // // horrible slow... but correct // return Interpreter()->GetPtrToHeap( p) != NULL; // } // BaseGDL** EnvBaseT::GetPtrTo( BaseGDL* p) // { // BaseGDL** pp = env.GetPtrTo( p); // if( pp != NULL) return pp; // pp = static_cast(pro)->GetCommonVarPtr( p); // if( pp != NULL) return pp; // return GDLInterpreter::GetPtrToHeap( p); // } gdl-0.9.9/src/envt.hpp000066400000000000000000000661541340051421000145550ustar00rootroot00000000000000/*************************************************************************** envt.hpp - the environment for each GDL module ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ENVT_HPP_ #define ENVT_HPP_ #include #include #include #include "typedefs.hpp" #include "str.hpp" #include "dpro.hpp" #include "datatypes.hpp" #include "dstructgdl.hpp" #include "datalistt.hpp" #include "extrat.hpp" #include "calendar.hpp" //#define GDL_DEBUG #undef GDL_DEBUG class DInterpreter; namespace lib { BaseGDL* obj_new( EnvT* e); void obj_destroy( EnvT* e); } class EnvBaseT { private: // typedef std::deque ContainerT; typedef ExprListT ContainerT; // SizeT toDestroyInitialIndex; EnvBaseT(){} protected: // stores all data which has to deleted upon destruction ContainerT toDestroy; // static ContainerT toDestroy; public: // needed to delete temporary ptr parameters only after subroutine completion // 'guards' a newly created variable which should be deleted // upon library routines exit (normal or on error) // elimates the need of auto_ptr and in some places later destruction is needed void DeleteAtExit( BaseGDL* toGuard) { // if( toDestroy == NULL) // toDestroy = new ContainerT(); toDestroy.push_back( toGuard); } protected: // for obj cleanup static std::set< DObj> inProgress; static DInterpreter* interpreter; DataListT env; SizeT parIx; // ix of next parameter to put DSub* pro; ProgNodeP callingNode; int lineNumber; bool obj; // member subroutine? ExtraT* extra; EnvBaseT* newEnvOff; // finds the local variable pp points to // int FindLocalKW( BaseGDL** pp) { return env.FindLocal( pp);} private: BaseGDL** ptrToReturnValue; public: void SetPtrToReturnValue(BaseGDL** p) { ptrToReturnValue = p;} BaseGDL** GetPtrToReturnValueNull() { BaseGDL** p = ptrToReturnValue;ptrToReturnValue=NULL;return p;} BaseGDL** GetPtrToReturnValue() const { return ptrToReturnValue;} BaseGDL** GetPtrToGlobalReturnValue() { if( ptrToReturnValue == NULL) return NULL; if( env.InLoc(ptrToReturnValue)) { *ptrToReturnValue = NULL; // steal local value return NULL; // return as not global } return ptrToReturnValue; } bool InLoc( BaseGDL** pp) { return env.InLoc(pp); } void SetKW( SizeT ix, BaseGDL* newVal); // used by the interperter returns the keyword index, used for UD functions // and used by WRAPPED subroutines int GetKeywordIx( const std::string& k); int findvar(const std::string& s); int findvar(BaseGDL* delP); bool Remove(int* rindx); bool Removeall(); bool StealLocalKW( SizeT ix) { if( LocalKW( ix)) { env.Clear( ix); return true; } return false; } // bool StealLocalKW( BaseGDL** ref) // { // if( !env.InLoc( pp)) // return false; // // *ref = NULL; // return true; // } bool LocalKW( SizeT ix) const { if( ix >= env.size()) return false; return ( env.Loc( ix) != NULL); } bool GlobalKW( SizeT ix) const { if( ix >= env.size()) return false; return ( env.Env( ix) != NULL); } bool KeywordSet( SizeT ix); protected: // for HEAP_GC static void AddStruct( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DStructGDL* stru); static void AddPtr( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DPtrGDL* ptr); static void AddObj( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DObjGDL* obj); static void Add( DPtrListT& ptrAccessible, DPtrListT& objAccessible, BaseGDL* p); // definition in list.cpp static void AddLIST( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DStructGDL* listStruct); public: // void DebugInfo() // { // std::cout << this->pro->ObjectName() << std::endl; // } EnvBaseT* GetNewEnv() {return newEnvOff; } void SetNewEnv( EnvBaseT* nE) { newEnvOff = nE;} virtual void ObjCleanup( DObj actID); // for CLEANUP calls due to reference counting void PushNewEmptyEnvUD( DSubUD* newPro, DObjGDL** newObj = NULL); // void PushNewEmptyEnvUDWithExtra( DSubUD* newPro, BaseGDL** newObj = NULL); void AddEnv( DPtrListT& ptrAccessible, DPtrListT& objAccessible); void AddToDestroy( DPtrListT& ptrAccessible, DPtrListT& objAccessible); virtual ~EnvBaseT() { delete extra; // delete toDestroy; // cleans up its content /* for( SizeT i=toDestroyInitialIndex; i(pro); if( proUD == NULL) throw GDLException("Intenal error: CompileOpt called non DSub object."); return proUD->GetCompileOpt(); } void SetCompileOpt( unsigned int cOpt) { DSubUD* proUD = dynamic_cast(pro); if( proUD == NULL) throw GDLException("Intenal error: CompileOpt called non DSub object."); proUD->SetCompileOpt( cOpt); } // raise an exception from within a library function // automatically cares for adding line/column info and the // function name. 's' should be set to the 'raw' error message // saves some typing :-) void Throw( const std::string& s) { throw GDLException( CallingNode(), pro->ObjectName()+": "+s, false, false);} // finds the global variable pp (used by arg_present function) int FindGlobalKW( BaseGDL** pp) { return env.FindGlobal( pp);} // checks if pp points to a local variable bool IsLocalKW( BaseGDL** pp) const { return env.InLoc( pp);} // void RemoveLoc( BaseGDL* p) { env.RemoveLoc( p);} // called after parameter definition void ResolveExtra(); friend class ExtraT; // used by compiler and from EnvT (for variable number of paramters) SizeT AddEnv() { SizeT s = env.size(); env.AddOne(); return s; } void DelEnv() { env.pop_back(); } // the upper (calling) environment // a EnvT must have always a /*EnvUDT*/ caller // i.e. library functions never call each other // with a new EnvT environment // for library subroutines, get the EnvUDT from which they are called EnvBaseT* Caller(); // returns environment data, by value (but that by C++ reference) BaseGDL*& GetKW(SizeT ix) { return env[ix];} // used by HELP, SetNextPar(...) SizeT EnvSize() const { return env.size();} // next four are used by Parameter...(...) functions void SetNextParUnchecked( BaseGDL* const nextP); // by value (reset loc) void SetNextParUnchecked( BaseGDL** const nextP); // by reference (reset env) void SetNextParUncheckedVarNum( BaseGDL* const nextP); // by value (reset loc) void SetNextParUncheckedVarNum( BaseGDL** const nextP); // by reference (reset env) // these are used outside Parameter functions void SetNextPar( BaseGDL* const nextP); // by value (reset loc) void SetNextPar( BaseGDL** const nextP); // by reference (reset env) void SetKeyword( const std::string& k, BaseGDL* const val); // value void SetKeyword( const std::string& k, BaseGDL** const val); // reference // to check if a lib function returned a variable of this env // bool Contains( BaseGDL* p) const; // BaseGDL** GetPtrTo( BaseGDL* p); DInterpreter* Interpreter() const { return interpreter;} bool IsObject() const { return obj;} DSub* GetPro() const { return pro;} ProgNodeP CallingNode() { return callingNode;} SizeT NParam( SizeT minPar = 0); //, const std::string& subName = ""); const std::string GetProName() const { if( pro == NULL) return ""; return pro->ObjectName(); } // get the name of 'i'th parameter const std::string GetParString( SizeT i) { SizeT ix= i + pro->key.size(); return GetString( ix); } // get the name of 'ix'th environment entry (asks 'pro') const std::string GetString( SizeT ix); // get name of 'p' const std::string GetString( BaseGDL*& p, bool calledFromHELP=false); // // get name of 'p' // const std::string GetString( BaseGDL* p); virtual const std::string GetFilename() const=0; void AssureGlobalKW( SizeT ix); // converts parameter 'ix' if necessary and sets 'scalar' void AssureLongScalarPar( SizeT ix, DLong& scalar); void AssureLongScalarPar( SizeT ix, DLong64& scalar); // get i'th parameter // throws if not defined (ie. never returns NULL) BaseGDL*& GetParDefined(SizeT i); //, const std::string& subName = ""); bool KeywordPresent( SizeT ix) { return (env.Loc(ix)!=NULL)||(env.Env(ix)!=NULL);} void SetNextParUnckeckedVarNum(BaseGDL** arg1); friend class DInterpreter; // gcc 4.4 compatibility friend class InProgressGuard; }; // preallocates a buffer which should never be exceeded // but will work with any number of elements template< typename T, SizeT defaultLength> class ForInfoListT { public: typedef T* iterator; private: T* eArr; char buf[defaultLength * sizeof(T)]; // prevent constructor calls SizeT sz; public: ForInfoListT(): eArr( reinterpret_cast(buf)), sz( 0) { } ~ForInfoListT() { if( eArr != reinterpret_cast(buf)) delete[] eArr; else { T* pEnd = &eArr[sz]; for( T* p = &eArr[0]; p!=pEnd; ++p) p->Clear(); } } // must be called before access void InitSize( SizeT s) { assert( sz == 0); if( s == 0) return; sz = s; if( s < defaultLength) { for( SizeT i=0; i sz -> grow if( s <= defaultLength && eArr == reinterpret_cast(buf)) { for( SizeT i=sz; i defaultLength T* newArr = new T[ s]; // ctor called if( eArr != reinterpret_cast(buf)) { for( SizeT i=0; i freeList; static FreeListT freeList; public: static void* operator new( size_t bytes); static void operator delete( void *ptr); enum CallContext { RFUNCTION = 0 ,LFUNCTION ,LRFUNCTION }; private: ForInfoListT forLoopInfo; // std::vector forLoopInfo; ProgNodeP ioError; DLong onError; // on_error setting BaseGDL** catchVar; ProgNodeP catchNode; CallContext callContext; // assignment paramter for functions as l_value SizeT nJump; // number of jumps in current environment int lastJump; // to which label last jump went public: ForLoopInfoT& GetForLoopInfo( int forIx) { return forLoopInfo[forIx];} int NForLoops() const { return forLoopInfo.size();} void ResizeForLoops( int newSize) { forLoopInfo.resize(newSize);} // UD pro/fun EnvUDT( ProgNodeP idN, DSubUD* pro_, CallContext lF = RFUNCTION); // member procedure EnvUDT( ProgNodeP idN, BaseGDL* self, const std::string& parent=""); // member function EnvUDT( BaseGDL* self, ProgNodeP idN, const std::string& parent="", CallContext lF = RFUNCTION); // for obj_new and obj_destroy //EnvUDT( EnvBaseT* pEnv, DSub* newPro, BaseGDL** self); EnvUDT( ProgNodeP callindNode_, DSubUD* newPro, DObjGDL** self); DLong GetOnError() const { return onError;} ProgNodeP GetCatchNode() const { return catchNode;} BaseGDL** GetCatchVar() const { return catchVar;} SizeT NJump() const { return nJump;} int LastJump() const { return lastJump;} ProgNodeP GotoTarget( int ix) { lastJump = ix; //static_cast( pro)->LabelOrd( ix); ++nJump; return static_cast( pro)->GotoTarget( ix); } CallContext GetCallContext() const { return callContext;} // left-function void SetCallContext(CallContext cC) { callContext = cC;} // left-function void SetIOError( int targetIx) { // this isn't a jump if( targetIx != -1) ioError = static_cast( pro)->GotoTarget( targetIx)-> getNextSibling(); else ioError = NULL; } ProgNodeP GetIOError() { return ioError;} const std::string GetFilename() const { DSubUD* subUD=static_cast( pro); return subUD->GetFilename(); } // // for internal non-library routines (e.g. operator overloads) ('this' is on the stack) // EnvUDT* CallingEnv(); friend class DInterpreter; friend class EnvT; }; // for library subroutines ************************************** // this contains the library function API *********************** class EnvT: public EnvBaseT { static std::vector< void*> freeList; public: static void* operator new( size_t bytes); static void operator delete( void *ptr); // Please use non library API (see below) function with caution // (most of them can be ignored by library function authors) public: ~EnvT() { } EnvT( ProgNodeP cN, DSub* pro_); // for obj_new and obj_destroy EnvT( EnvT* pEnv, DSub* newPro, DObjGDL** self); void HeapGC( bool doPtr, bool doObj, bool verbose); void ObjCleanup( DObj actID); // used by obj_new (basic_fun.cpp) EnvT* NewEnv( DSub* newPro, SizeT skipP, DObjGDL** newObj=NULL); EnvUDT* PushNewEnvUD( DSubUD* newPro, SizeT skipP, DObjGDL** newObj=NULL); // for exclusive use by lib::on_error void OnError(); // for exclusive use by lib::catch_pro void Catch(); const std::string GetFilename() const { static const std::string internal(INTERNAL_LIBRARY_STR); return internal; } // ************************* // API for library functions // ************************* // // raise an exception from within a library function // // automatically cares for adding line/column info and the // // function name. 's' should be set to the 'raw' error message // // saves some typing :-) // void Throw( const std::string& s) // { throw GDLException( CallingNode(), pro->ObjectName()+": "+s);} // From now on all library functions which return a l-value must // call SetPtrToReturnValue with the ptr to the returned value void SetPtrToReturnValue(BaseGDL** p) { EnvBaseT::SetPtrToReturnValue(p);} // will print the message (can be multiline) and exit // first usage in "math_fun_ac.cpp" void Help(const std::string s_help[], int size_of_s); // returns environment data, by value (but that by C++ reference) // in EnvBaseT // BaseGDL*& GetKW(SizeT ix) { return env[ix];} // it is now possible to define a niminum number of parameters for library subroutines // if this is done the next function can be used // BaseGDL*& GetParUnchecked(SizeT i); // returns the ix'th parameter (NULL if not defined) BaseGDL*& GetPar( SizeT i); // get i'th parameter // throws if not defined (ie. never returns NULL) BaseGDL*& GetParDefined(SizeT i); //, const std::string& subName = ""); // throw for GDL_STRING, GDL_STRUCT, GDL_PTR and GDL_OBJ BaseGDL*& GetNumericParDefined( SizeT ix) { BaseGDL*& p0 = GetParDefined( ix); if( NumericType( p0->Type())) return p0; // AC 2014-08-14 : in fact, in most case, a tentative of String to Numeric // convertion is done. E.g. invert(['1']) is OK ! // if( p0->Type() == GDL_STRING) // Throw( "String expression not allowed in this context: "+GetParString(ix)); if( p0->Type() == GDL_STRUCT) Throw( "Struct expression not allowed in this context: "+GetParString(ix)); if( p0->Type() == GDL_PTR) Throw( "Pointer expression not allowed in this context: "+GetParString(ix)); if( p0->Type() == GDL_OBJ) Throw( "Object reference not allowed in this context: "+GetParString(ix)); assert( false); return p0; } // throw for non-Arrays BaseGDL*& GetNumericArrayParDefined( SizeT ix) { BaseGDL*& p0 = GetNumericParDefined( ix); if (p0->Rank() != 0) return p0; Throw("Expression must be an array in this context: "+GetParString(ix)); assert(false); throw; } // get i'th parameter // throws if not global (might be NULL), for assigning a new variable to // (write only) BaseGDL*& GetParGlobal(SizeT i); // get the pIx'th paramter and converts it to T if necessary // implies that the parameter must be defined // if it converts it cares for the destruction of the copy // CAUTION: this is for *read only* data, as the returned data might // be a copy or not template T* GetParAs( SizeT pIx) { BaseGDL* p = GetParDefined( pIx); if( p->Type() == T::t) return static_cast( p); // T* res = dynamic_cast( p); // if( res != NULL) return res; T* res = static_cast( p->Convert2( T::t, BaseGDL::COPY)); this->DeleteAtExit( res); return res; } // same as before for keywords template T* GetKWAs( SizeT ix) { BaseGDL* p = GetKW( ix); if( p == NULL) Throw( "Keyword is undefined: "+GetString( ix)); if( p->Type() == T::t) return static_cast( p); // T* res = dynamic_cast( p); // if( res != NULL) return res; T* res = static_cast( p->Convert2( T::t, BaseGDL::COPY)); this->DeleteAtExit( res); return res; } // next two same as last two, but return NULL if parameter/keyword is not defined template T* IfDefGetParAs( SizeT pIx) { BaseGDL* p = GetPar( pIx); if( p == NULL) return NULL; if( p->Type() == T::t) return static_cast( p); // T* res = dynamic_cast( p); // if( res != NULL) return res; T* res = static_cast( p->Convert2( T::t, BaseGDL::COPY)); this->DeleteAtExit( res); return res; } // same as before for keywords template T* IfDefGetKWAs( SizeT ix) { BaseGDL* p = GetKW( ix); if( p == NULL) return NULL; if( p->Type() == T::t) return static_cast( p); // T* res = dynamic_cast( p); // if( res != NULL) return res; T* res = static_cast( p->Convert2( T::t, BaseGDL::COPY)); this->DeleteAtExit( res); return res; } // returns the struct of a valid object reference or throws DStructGDL* GetObjectPar( SizeT pIx); // returns the actual number of paramters passed to a library function // minPar is the minimal number of paramters the function needs // (if less it throws), subName is used for error reporting SizeT NParam( SizeT minPar = 0); //, const std::string& subName = ""); // for library functions (keyword must be exact) // returns the index of keyword k int KeywordIx( const std::string& k); // for use within library functions // consider to use (note: 'static' is the point here): // static int kwIx = env->KeywordIx( "KEYWORD"); // bool kwSet = env->KeywordSet( kwIx); // // instead of: // bool kwSet = env->KeywordSet( "KEYWORD"); // // this one adds some overhead, but is easy to use bool KeywordSet( const std::string& kw); // this one together with a static int holding the index is faster // (after the first call) bool KeywordSet( SizeT ix); // GD added -- possibly very wrong? bool KeywordPresent( const std::string& kw); bool KeywordPresent( SizeT ix) { return EnvBaseT::KeywordPresent( ix);} // local/global keyword/paramter bool LocalKW( SizeT ix) const { return EnvBaseT::LocalKW( ix); // if( ix >= env.size()) return false; // return ( env.Loc( ix) != NULL); } bool GlobalKW( SizeT ix) const { return EnvBaseT::GlobalKW( ix); } bool LocalPar( SizeT ix) { return LocalKW( ix + pro->key.size());} bool StealLocalPar( SizeT ix) { if( LocalKW( ix + pro->key.size())) { env.Clear( ix + pro->key.size()); return true; } return false; } // removed: IDL does not undefine the global parameter with OVERWRITE // void StealLocalParUndefGlobal( SizeT ix) // { // if( LocalKW( ix + pro->key.size())) // { // env.Clear( ix + pro->key.size()); // } // else // { // env[ ix + pro->key.size()] = NULL; // } // } bool GlobalPar( SizeT ix) { return GlobalKW( ix + pro->key.size());} // next two to set keywords/paramters // note that the value MUST be created in the library function // with operator new // Before it must be tested with KeywordPresent() or NParam() if // the keyword/paramter is present // this is not done automatically because its more effective, to // create the data (newVal) only if its necessary // if the functions throw, they delete newVal before -> no // guarding of newVal is needed // void SetKW( SizeT ix, BaseGDL* newVal); void SetPar( SizeT ix, BaseGDL* newVal); // Assure functions: // if name contains "Par" they must be used for paramters, else for keywords // (the error messages are defined for this usage and the indexing is // done respectively) // next two: NO CONVERSION (throw if wrong type) // NOTE: only few functions need to be so restrictive // converts parameter to scalar, throws if parameter is of different type, // non-scalar or not defined template void AssureScalarPar( SizeT pIx, typename T::Ty& scalar) { BaseGDL* p = GetParDefined( pIx); if( p->Type() != T::t) Throw( "Variable must be a "+T::str+" in this context: "+ GetParString(pIx)); T* tp= static_cast(p); if( !tp->Scalar( scalar)) Throw("Variable must be a scalar in this context: "+ GetParString(pIx)); } // same as before for keywords template void AssureScalarKW( SizeT ix, typename T::Ty& scalar) { BaseGDL* p = GetKW( ix); if( p == NULL) Throw("Keyword undefined: "+GetString(ix)); if( p->Type() != T::t) Throw("Keyword must be a "+T::str+" in this context: "+ GetString(ix)); T* tp= static_cast(p); if( !tp->Scalar( scalar)) Throw("Keyword must be a scalar in this context: "+ GetString(ix)); } void AssureGlobalPar( SizeT pIx); // void AssureGlobalKW( SizeT ix); // if keyword 'kw' is not set, 'scalar' is left unchanged void AssureLongScalarKWIfPresent( const std::string& kw, DLong& scalar); void AssureLongScalarKWIfPresent( SizeT ix, DLong& scalar); // converts keyword 'kw' if necessary and sets 'scalar' void AssureLongScalarKW( const std::string& kw, DLong& scalar); void AssureLongScalarKW( const std::string& kw, DLong64& scalar); // converts ix'th keyword if necessary and sets 'scalar' void AssureLongScalarKW( SizeT ix, DLong& scalar); void AssureLongScalarKW( SizeT ix, DLong64& scalar); // converts parameter 'ix' if necessary and sets 'scalar' void AssureLongScalarPar( SizeT ix, DLong& scalar); void AssureLongScalarPar( SizeT ix, DLong64& scalar); // same as for Long void AssureDoubleScalarKWIfPresent( const std::string& kw, DDouble& scalar); void AssureDoubleScalarKWIfPresent( SizeT ix, DDouble& scalar); void AssureDoubleScalarKW( const std::string& kw, DDouble& scalar); void AssureDoubleScalarKW( SizeT ix, DDouble& scalar); void AssureDoubleScalarPar( SizeT ix, DDouble& scalar); // same as for Long void AssureFloatScalarKWIfPresent( const std::string& kw, DFloat& scalar); void AssureFloatScalarKWIfPresent( SizeT ix, DFloat& scalar); void AssureFloatScalarKW( const std::string& kw, DFloat& scalar); void AssureFloatScalarKW( SizeT ix, DFloat& scalar); void AssureFloatScalarPar( SizeT ix, DFloat& scalar); // same as for Long void AssureStringScalarKWIfPresent( const std::string& kw, DString& scalar); void AssureStringScalarKWIfPresent( SizeT ix, DString& scalar); void AssureStringScalarKW( const std::string& kw, DString& scalar); void AssureStringScalarKW( SizeT ix, DString& scalar); void AssureStringScalarPar( SizeT ix, DString& scalar); // to be extended on demand for other data types // SA: used by GDL_STRING() for VMS-compat hack void ShiftParNumbering(int n); }; const int defaultStackDepth = 64; class EnvStackT { EnvUDT** envStackFrame; EnvUDT** envStack; SizeT top; SizeT sz; public: typedef SizeT size_type; typedef EnvUDT* pointer_type; EnvStackT(): top(0), sz(defaultStackDepth) { envStackFrame = new EnvUDT* [ sz+1]; envStack = envStackFrame + 1; } ~EnvStackT() { delete[] envStackFrame;} bool empty() const { return top == 0;} void push_back( EnvUDT* b) { if( top >= sz) { if( sz >= 32768) throw GDLException("Recursion limit reached ("+i2s(sz)+")."); EnvUDT** newEnvStackFrame = new EnvUDT* [ sz + sz + 1]; EnvUDT** newEnvStack = newEnvStackFrame + 1; for( SizeT i=0; i0); --top;} EnvUDT* back() const { assert(top>0); return envStackFrame[ top];} SizeT size() const { return top;} EnvUDT* operator[]( SizeT ix) const { return envStack[ ix];} EnvUDT*& operator[]( SizeT ix) { return envStack[ ix];} // EnvUDT** begin() const { return &envStack[0];} // EnvUDT** end() const { return &envStack[sz];} }; // typedef std::deque EnvStackT; // typedef std::deque EnvStackT; #endif gdl-0.9.9/src/exists_fun.cpp000066400000000000000000000111061340051421000157460ustar00rootroot00000000000000/*************************************************************************** exists_fun.hpp - basic GDL library functions ------------------- begin : December 2017 copyright : (C) 2017 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 // default: assume we have ImageMagick #define USE_MAGICK 1 #endif #include "includefirst.hpp" #include #include #include #include "initsysvar.hpp" #include "datatypes.hpp" #include "envt.hpp" //#include "dpro.hpp" //#include "dinterpreter.hpp" #include "basic_fun_cl.hpp" //#include "terminfo.hpp" #define MAX_DATE_STRING_LENGTH 80 #ifdef _MSC_VER #include "gtdhelper.hpp" #else #include #endif namespace lib { using namespace std; using namespace antlr; BaseGDL* eigen_exists(EnvT* e) { #ifdef USE_EIGEN return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* fftw_exists(EnvT *e) { #ifdef USE_FFTW return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* glpk_exists(EnvT *e) { #ifdef USE_GLPK return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* grib_exists(EnvT *e) { #ifdef USE_GRIB return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* gshhg_exists( EnvT* e ) { #ifdef USE_GSHHS // e->Message( "GDL was compiled with support for GSHHG" ); return new DIntGDL(1); #else //e->Message( "GDL was compiled without support for GSHHG" ); return new DIntGDL(0); #endif } BaseGDL* hdf_exists(EnvT* e) { #ifdef USE_HDF return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* hdf5_exists(EnvT* e) { #ifdef USE_HDF5 return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* magick_exists(EnvT *e) { #ifdef USE_MAGICK return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* ncdf_exists(EnvT* e) { #ifdef USE_NETCDF return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* ncdf4_exists(EnvT* e) { #ifdef USE_NETCDF4 return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* openmp_exists(EnvT* e) { #ifdef USE_OPENMP return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* pnglib_exists(EnvT* e) { #ifdef USE_PNGLIB return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* proj4_exists( EnvT* e ) { #if defined(USE_LIBPROJ4) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* proj4new_exists( EnvT* e ) { #if defined(USE_LIBPROJ4_NEW) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* pslib_exists( EnvT* e ) { #if defined(USE_PSLIB) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* python_exists( EnvT* e ) { #if defined(USE_PYTHON) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* tiff_exists( EnvT* e ) { #if defined(USE_TIFF) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* geotiff_exists( EnvT* e ) { #if defined(USE_GEOTIFF) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* udunits_exists( EnvT* e ) { #if defined(USE_UDUNITS) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* x11_exists( EnvT* e ) { #if defined(USE_X) return new DIntGDL(1); #else return new DIntGDL(0); #endif } BaseGDL* dsfmt_exists(EnvT* e) { //dSFMT (random generator) is used AT THE MOMENT only if Eigen is present, and only if useDSFMTAcceleration == true #ifdef USE_EIGEN return new DIntGDL(useDSFMTAcceleration == true); #else return new DIntGDL(0); #endif } } // namespace gdl-0.9.9/src/exists_fun.hpp000066400000000000000000000035151340051421000157600ustar00rootroot00000000000000/*************************************************************************** exists_fun.hpp - basic GDL library functions ------------------- begin : December 2017 copyright : (C) 2017 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef BASIC_FUN_HPP_CL #define BASIC_FUN_HPP_CL namespace lib { BaseGDL* eigen_exists(EnvT *e); BaseGDL* fftw_exists(EnvT *e); BaseGDL* glpk_exists(EnvT *e); BaseGDL* grib_exists(EnvT *e); BaseGDL* gshhg_exists(EnvT *e); BaseGDL* hdf5_exists(EnvT *e); BaseGDL* hdf_exists(EnvT *e); BaseGDL* magick_exists(EnvT *e); BaseGDL* ncdf_exists(EnvT *e); BaseGDL* ncdf4_exists(EnvT *e); BaseGDL* openmp_exists(EnvT *e); BaseGDL* pnglib_exists(EnvT *e); BaseGDL* proj4_exists(EnvT *e); BaseGDL* proj4new_exists(EnvT *e); BaseGDL* pslib_exists(EnvT *e); BaseGDL* python_exists(EnvT *e); BaseGDL* tiff_exists(EnvT *e); BaseGDL* geotiff_exists(EnvT *e); BaseGDL* udunits_exists(EnvT *e); // only exception wxwidgets_exists in "dialop.hpp" BaseGDL* x11_exists(EnvT *e); BaseGDL* dsfmt_exists(EnvT *e); } // namespace #endif gdl-0.9.9/src/export.hpp000066400000000000000000000016201340051421000151050ustar00rootroot00000000000000typedef BaseGDL *GDL_VPTR; typedef BaseGDL GDL_VARIABLE; #define GDL_BARR_INI_ZERO BaseGDL::ZERO #define GDL_BARR_INI_NOP BaseGDL::NOZERO #define GDL_Deltmp delete template< typename T1, typename T2> T2* GDL_GetScratch(GDL_VPTR *p, DLong nElem) { BaseGDL* data = new T1( dimension( nElem), GDL_BARR_INI_ZERO); bzero( data->DataAddr(), nElem*sizeof(T2)); *p = data; return (T2 *) data->DataAddr(); } template< typename T1, typename T2> T2* GDL_MakeTempArray( DLong rank, DLong *dim, BaseGDL::InitType iT, GDL_VPTR *v) { BaseGDL* data = new T1( dimension(dim, rank), iT); if ( iT == GDL_BARR_INI_ZERO) { DLong nElem = 1; for( SizeT i=0; iDataAddr(), nElem*sizeof(T2)); } *v = data; return (T2 *) data->DataAddr(); } void GDL_VarCopy( EnvT* e, GDL_VPTR v_src, DLong ipar) { BaseGDL** p = &e->GetPar( ipar); *p = v_src; } gdl-0.9.9/src/extrat.cpp000066400000000000000000000174571340051421000151050ustar00rootroot00000000000000/*************************************************************************** extrat.cpp - (_REF)_EXTRA keyword handling ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "objects.hpp" #include "extrat.hpp" #include "envt.hpp" #include "nullgdl.hpp" using namespace std; void ExtraT::ResolveExtra(EnvBaseT* callerIn) { // if the subroutine has _REF_EXTRA, explicit keywords override // if the subroutine has _EXTRA, _EXTRA keywords override // 1. extract own keywords from _EXTRA data (override explicit ones) // put all others to extra data BaseGDL* extraVal= (envExtraVal != NULL)? *envExtraVal : locExtraVal; DSub* pro=thisEnv->pro; DSub::ExtraType extraType= pro->Extra(); // EnvBaseT* callerDebug=thisEnv->Caller(); // DSub::ExtraType extraTypeDebug= callerDebug->pro->Extra(); if( extraVal != NULL) { if( extraVal->Type() == GDL_STRUCT) // _EXTRA { DStructGDL* extraStruct= static_cast(extraVal); DStructDesc* desc=extraStruct->Desc(); SizeT nTag=desc->NTags(); for( SizeT t=0; tTagName( t); // search keyword KeyVarListT::iterator f=find_if(pro->key.begin(), pro->key.end(), String_abbref_eq( tName)); if (f != pro->key.end()) { // found, _EXTRA always overrides explicit keywords SizeT varIx = distance(pro->key.begin(), f); thisEnv->env.Reset(varIx, extraStruct->Get(t)); // local } else // not found -> add tag to extra data { if (extraType != DSub::NONE) { listName.push_back(tName); listEnv.push_back(extraStruct->Get(t)); // always local } else if (strict || callerIn != NULL) // always strict if callerIn is set { // pro has no (_REF)_EXTRA and _STRICT_EXTRA -> error // ... unless keyword is a warnkey! // search warn keyword IDList::iterator wf=find_if(pro->warnKey.begin(), pro->warnKey.end(), String_abbref_eq( tName)); if (wf == pro->warnKey.end()) { thisEnv->Throw("Keyword " + tName + " not allowed in call to: " + pro->ObjectName()); } } } } } else // _REF_EXTRA { if( extraVal->Type() == GDL_STRING) // _EXTRA { DStringGDL* extraString= static_cast(extraVal); EnvBaseT* caller; if( callerIn == NULL) caller = thisEnv->Caller(); else caller = callerIn; // GDL_STRING only works, if the *caller* has _REF_EXTRA if( caller->pro->Extra() == DSub::REFEXTRA) { // caller's extra member holds the actual data assert( caller->extra != NULL); ExtraT& cExtra=*caller->extra; SizeT nStr=extraString->N_Elements(); for( SizeT t=0; tkey.begin(), pro->key.end(), String_abbref_eq( kName)); if( f != pro->key.end()) { // found, _EXTRA always overrides SizeT varIx=distance(pro->key.begin(),f); // global, caller is owner thisEnv->env.Reset( varIx, &cExtra.listEnv[dataIx]); } else // not found -> add to extra data { if( extraType != DSub::NONE) { listName.push_back( kName); // global listEnv.push_back( &cExtra.listEnv[dataIx]); } else if( strict) { // pro has no (_REF)_EXTRA) and _STRICT_EXTRA -> // error thisEnv->Throw( "Keyword "+kName+ " not allowed in call to: "+ pro->ObjectName()); } } } // dataIx != -1 } // for } // caller->pro->Extra() == DSub::REFEXTRA) } // extraString != NULL } } // all keywords are now overridden in the actual environment // listName/listEnv holds all _EXTRA data, which is not used by this // subroutine // 2. if pro has (_REF)_EXTRA: // combine additional keywords and the (remaining) _EXTRA data to pro's // (_REF)_EXTRA value if( extraType == DSub::REFEXTRA) { // make string array SizeT nEl = listName.size(); if( nEl > 0) { dimension dim( &nEl, 1); DStringGDL* extraString = new DStringGDL( dim); for( SizeT i=0; ienv.Loc(static_cast(pro->extraIx)) == NULL /*|| thisEnv->env.Loc(static_cast(pro->extraIx)) == NullGDL::GetSingleInstance()*/); // assert( thisEnv->env.Env(static_cast(pro->extraIx)) == NULL ); delete thisEnv->env.Loc(static_cast(pro->extraIx)); thisEnv->env.Set( static_cast(pro->extraIx), static_cast(extraString)); // thisEnv->env.Reset( static_cast(pro->extraIx), // static_cast(extraString)); } else { assert( thisEnv->env.Loc(static_cast(pro->extraIx)) == NULL); assert( thisEnv->env.Env(static_cast(pro->extraIx)) == NULL); } } else if( extraType == DSub::EXTRA) { // make structure SizeT nEl = listName.size(); if( nEl > 0) { DStructDesc* extraStructDesc; DStructGDL* extraStruct = NULL; // from back -> _EXTRA overrides additional keyword for( int i=nEl-1; i>=0; --i) { if( listEnv[i] != NULL) // if undef just skip (pass by value) { if( extraStruct == NULL) { extraStructDesc = new DStructDesc( "$truct"); // extraStruct = new DStructGDL( extraStructDesc, dimension(1)); extraStruct = new DStructGDL( extraStructDesc); // extraStructDesc->AddTag( listName[i], listEnv[i]); // extraStruct->AddTagGrab( listEnv.Grab(i)); extraStruct->NewTag( listName[i], listEnv.Grab(i)); } else if( extraStructDesc->TagIndex( listName[i]) == -1) { extraStruct->NewTag( listName[i], listEnv.Grab(i)); // extraStructDesc->AddTag( listName[i], listEnv[i]); // extraStruct->AddTagGrab( listEnv.Grab(i)); // extraStruct->AddTag( listEnv[i]); } } } // look if equal is already there (very possible eg. _EXTRA in loops) // DStructDesc* oStructDesc=extraStructDesc->FindEqual( structList); // if( oStructDesc != NULL) // { // extraStruct->SetDesc(oStructDesc); // delete extraStructDesc; // } // else // { // // insert into struct list // NOT ANYMORE!!! // structList.push_back( extraStructDesc); // } // structList.push_back( extraStructDesc); assert( thisEnv->env.Loc(static_cast(pro->extraIx)) == NULL); assert( thisEnv->env.Env(static_cast(pro->extraIx)) == NULL); thisEnv->env.Set( static_cast(pro->extraIx), static_cast(extraStruct)); // thisEnv->env.Reset( static_cast(pro->extraIx), // static_cast(extraStruct)); } } } gdl-0.9.9/src/extrat.hpp000066400000000000000000000073641340051421000151060ustar00rootroot00000000000000/*************************************************************************** extrat.hpp - (_REF)_EXTRA keyword handling ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // used by EnvT #ifndef EXTRA_HPP_ #define EXTRA_HPP_ #include #include #include "datatypes.hpp" #include "datalistt.hpp" class EnvBaseT; class ExtraT { EnvBaseT* thisEnv; // extra keywords IDList listName; DataListT listEnv; // for (_REF)_EXTRA // the _EXTRA keyword BaseGDL* locExtraVal; // extra keywords value BaseGDL** envExtraVal; // extra keywords value bool strict; // _STRICT_EXTRA // disable use of default constructor ExtraT() {} public: ExtraT( EnvBaseT* e): thisEnv(e), locExtraVal(NULL), envExtraVal(NULL), strict(false) {} ~ExtraT() { GDLDelete(locExtraVal); } void SetStrict( bool s) { strict = s; } void Set( BaseGDL* const val) { if( val->Type() != GDL_STRUCT && val->Type() != GDL_STRING) throw GDLException("Invalid value for _EXTRA keyword."); GDLDelete(locExtraVal); locExtraVal=val; } void Set( BaseGDL** const val) { if( *val != NULL && (*val)->Type() != GDL_STRUCT && (*val)->Type() != GDL_STRING) throw GDLException("Invalid value for _EXTRA keyword."); envExtraVal=val; } void Add( const std::string& k, BaseGDL* const val) { listName.push_back(k); listEnv.push_back(val); } void Add( const std::string& k, BaseGDL** const val) { listName.push_back(k); listEnv.push_back(val); } //previous version used class String_abbref_eq = find first occurence of string starting with name //however this may be good for cases where _extra passes arguments are function keywords (disambiguation) //but certainly not for _extra passing variables, e.g., in the following case //extra={a:[1,2],aa:33L} one needs to find what is pointed by a and not by aa which may be returned first //if we use String_abbref_eq. String_eq on the contrary calls for the *exact* match. int Find( const std::string& name) { String_eq strEq_name(name); // search keyword IDList::iterator f=std::find_if(listName.begin(), listName.end(), strEq_name); if( f == listName.end()) return -1; // Note: there might be duplicate extra keyword names, return first one // // continue search (for ambiguity) // IDList::iterator ff=std::find_if(f+1, // listName.end(), // strEq_name); // if( ff != listName.end()) // { // throw GDLException("Ambiguous keyword abbreviation in _EXTRA: "+name); // } return std::distance( listName.begin(),f); } // 1. extract own keywords from _EXTRA data (override explicit ones) // 2. if pro has (_REF)_EXTRA: // combine additional keywords and the (remaining) _EXTRA data to pro's // (_REF)_EXTRA value void ResolveExtra(EnvBaseT* caller); }; #endif gdl-0.9.9/src/fftw.cpp000066400000000000000000000153461340051421000145370ustar00rootroot00000000000000/*************************************************************************** fftw.cpp - GDL FFTW library function ------------------- begin : Sep 21 2005 copyright : (C) 2005 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifdef USE_FFTW #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "fftw3.h" #include #include "gsl_fun.hpp" #undef GDL_DEBUG namespace lib { using namespace std; // static int szdbl=sizeof(double); // static int szflt=sizeof(float); template < typename T> T* fftw_template(EnvT* e, BaseGDL* p0, SizeT nEl, SizeT dbl, SizeT overwrite, double direct, bool recenter) { int dim[MAXRANK]; T* res; BaseGDL* data; Guard guard_data; // if recenter and inverse (direct > 0) we will work on a "de-centered" p0 variant. // and of course not center the result. if (recenter && direct == 1) { DLong centerIx[ MAXRANK]; for (int i = 0; i < p0->Rank(); ++i) centerIx[i] = (p0->Dim(i)%2==1)?((p0->Dim(i))/2)+1:((p0->Dim(i))/2); data = p0->CShift(centerIx); recenter = false; guard_data.Reset(data); } else data = p0; if (overwrite == 0) res = new T(data->Dim(), BaseGDL::ZERO); else { res = (T*) p0; //we overwrite the real p0. if (e->GlobalPar(0)) e->SetPtrToReturnValue(&e->GetPar(0)); } for (SizeT i = 0; i < data->Rank(); ++i) { dim[i] = (int) data->Dim(data->Rank() - i - 1); } DComplexDblGDL* p0C = static_cast (data); DComplexGDL* p0CF = static_cast (data); if (data->Type() == GDL_COMPLEXDBL) { double *dptr; dptr = (double*) &(*res)[0]; fftw_plan p; fftw_complex *in, *out; in = (fftw_complex *) &(*p0C)[0]; out = (fftw_complex *) & dptr[0]; p = fftw_plan_dft((int) data->Rank(), dim, in, out, (int) direct, FFTW_ESTIMATE); fftw_execute(p); if (direct == -1) { // TRACEOMP(__FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (OMPInt i = 0; i < nEl; ++i) { out[i][0] /= nEl; out[i][1] /= nEl; } } } // 02 06 2010 //cout << "fftw dest" << endl ; fftw_destroy_plan(p); // 1 } else if (data->Type() == GDL_COMPLEX) { float *dptrf; dptrf = (float*) &(*res)[0]; fftwf_plan p_f; fftwf_complex *in_f, *out_f; in_f = (fftwf_complex *) &(*p0CF)[0]; out_f = (fftwf_complex *) & dptrf[0]; p_f = fftwf_plan_dft((int) data->Rank(), dim, in_f, out_f, (int) direct, FFTW_ESTIMATE); fftwf_execute(p_f); if (direct == -1) { // TRACEOMP(__FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (OMPInt i = 0; i < nEl; ++i) { out_f[i][0] /= nEl; out_f[i][1] /= nEl; } } } // 02 06 2010 //cout << "fftwF dest" << endl ; fftwf_destroy_plan(p_f); // 2 } if (recenter) { Guard guard_res(res); DLong centerIx[ MAXRANK]; for (int i = 0; i < data->Rank(); ++i) centerIx[i] = (p0->Dim(i))/2; return (T*) res->CShift(centerIx); } else return res; } BaseGDL* fftw_fun( EnvT* e) { SizeT nParam=e->NParam(); SizeT overwrite=0, dbl=0; bool recenter=false; SizeT stride; SizeT offset; // If DIMENSION keyword set then use GSL fft // which is bad practice. We should do the same as in min_fun or max_fun, use the stride facility. if(e->KeywordSet(3)) { return fft_fun(e); } double direct=-1.0; if( nParam == 0) throw GDLException( e->CallingNode(), "FFT: Incorrect number of arguments."); BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) throw GDLException( e->CallingNode(), "FFT: Variable is undefined: "+e->GetParString(0)); if( nParam == 2) { BaseGDL* p1 = e->GetPar( 1); if (p1->N_Elements() > 1) throw GDLException( e->CallingNode(), "FFT: Expression must be a scalar or 1 element array: " +e->GetParString(1)); DDoubleGDL* direction = static_cast(p1->Convert2( GDL_DOUBLE, BaseGDL::COPY)); direct = GSL_SIGN((*direction)[0]); } if( e->KeywordSet(0)) dbl = 1; if( e->KeywordSet(1)) direct = +1.0; if( e->KeywordSet(2)) overwrite = 1; if( e->KeywordSet(4)) recenter = true; // If not global parameter no overwrite // ok as we steal it then //if( !e->GlobalPar( 0)) overwrite = 0; // If double keyword no overwrite if( dbl) overwrite = 0; if( p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_DOUBLE || dbl) { DComplexDblGDL *p0C; Guard guard_p0C; if( p0->Type() != GDL_COMPLEXDBL) { p0C = static_cast(p0->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY)); guard_p0C.Init(p0C); } else { if( overwrite) { e->StealLocalPar(0); // e->StealLocalParUndefGlobal(0); } p0C = (DComplexDblGDL *) p0; } return fftw_template< DComplexDblGDL> (e, p0C, nEl, dbl, overwrite, direct, recenter); } else if( p0->Type() == GDL_COMPLEX) { // DComplexGDL* res; if( overwrite) e->StealLocalPar(0); // e->StealLocalParUndefGlobal(0); return fftw_template< DComplexGDL> (e, p0, nEl, dbl, overwrite, direct, recenter); } else { overwrite = 0; DComplexGDL* p0C = static_cast (p0->Convert2( GDL_COMPLEX, BaseGDL::COPY)); Guard guard_p0C( p0C); return fftw_template< DComplexGDL> (e, p0C, nEl, dbl, overwrite, direct, recenter); } } } // namespace #endif // USE_FFTW gdl-0.9.9/src/fftw.hpp000066400000000000000000000023271340051421000145370ustar00rootroot00000000000000/*************************************************************************** fftw.hpp - FFTW GDL library function ------------------- begin : Sep 21 2005 copyright : (C) 2005 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #ifndef FFTW_HPP_ #define FFTW_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* fftw_fun( EnvT* e); } // namespace #endif gdl-0.9.9/src/file.cpp000066400000000000000000002540171340051421000145100ustar00rootroot00000000000000/*************************************************************************** file.cpp - file related library functions ------------------- begin : July 22 2004 copyright : (C) 2004 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifndef _MSC_VER # include # include #endif #include #include #ifndef _MSC_VER # include #endif #include "basegdl.hpp" #include "str.hpp" #include "envt.hpp" #include "file.hpp" #include "objects.hpp" #include #include // PATH_MAX //patch #90 #ifndef PATH_MAX #define PATH_MAX 4096 #endif //#ifndef _MSC_VER #ifndef _WIN32 # include # include // glob in MinGW ok for mingw >=3.21 11/2014 #else # include # include # if !defined(S_IFLNK) # define S_IFLNK 0xA000 # define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK) # endif #endif #ifndef _MSC_VER # include #else # include # define access _access # define R_OK 4 /* Test for read permission. */ # define W_OK 2 /* Test for write permission. */ //# define X_OK 1 /* execute permission - unsupported in windows*/ # define F_OK 0 /* Test for existence. */ # define PATH_MAX 255 // MAX_PATH is a windows-only macro. # include # if !defined(S_ISDIR) # define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) # define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR) # define S_ISREG(mode) __S_ISTYPE((mode), S_IFREG) #endif #endif // workaround for HP-UX. A better solution is needed i think //#if defined(__hpux__) || defined(__sun__) #if !defined(GLOB_TILDE) # define GLOB_TILDE 0 #endif #if !defined(GLOB_BRACE) # define GLOB_BRACE 0 #endif //#if defined(__hpux__) || defined(__sun__) || defined(__CYGWIN__) || defined(__OpenBSD__) #if !defined(GLOB_ONLYDIR) # define GLOB_ONLYDIR 0 #endif #if !defined(GLOB_PERIOD) # define GLOB_PERIOD 0 #endif #ifdef _MSC_VER /* Implementation of POSIX directory browsing functions and types for Win32. Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) History: Created March 1997. Updated June 2003 and July 2012. Rights: See end of file. */ #include #include /* _findfirst and _findnext set errno iff they return -1 */ #include #include struct dirent { char *d_name; }; #ifdef __cplusplus extern "C" { #endif typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */ struct DIR { handle_type handle; /* -1 for failed rewind */ struct _finddata_t info; struct dirent result; /* d_name null iff first time */ char *name; /* null-terminated char string */ }; DIR *opendir(const char *name) { DIR *dir = 0; if(name && name[0]) { size_t base_length = strlen(name); const char *all = /* search pattern must end with suitable wildcard */ strchr("/\\", name[base_length - 1]) ? "*" : "/*"; if((dir = (DIR *) malloc(sizeof *dir)) != 0 && (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) { strcat(strcpy(dir->name, name), all); if((dir->handle = (handle_type) _findfirst(dir->name, &dir->info)) != -1) { dir->result.d_name = 0; } else /* rollback */ { free(dir->name); free(dir); dir = 0; } } else /* rollback */ { free(dir); dir = 0; errno = ENOMEM; } } else { errno = EINVAL; } return dir; } int closedir(DIR *dir) { int result = -1; if(dir) { if(dir->handle != -1) { result = _findclose(dir->handle); } free(dir->name); free(dir); } if(result == -1) /* map all errors to EBADF */ { errno = EBADF; } return result; } struct dirent *readdir(DIR *dir) { struct dirent *result = 0; if(dir && dir->handle != -1) { if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) { result = &dir->result; result->d_name = dir->info.name; } } else { errno = EBADF; } return result; } static void rewinddir(DIR *dir) { if(dir && dir->handle != -1) { _findclose(dir->handle); dir->handle = (handle_type) _findfirst(dir->name, &dir->info); dir->result.d_name = 0; } else { errno = EBADF; } } #ifdef __cplusplus } #endif /* Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives. This software is supplied "as is" without express or implied warranty. But that said, if there are any problems please get in touch. */ #endif #define NTEST_SEARCH 7 #if defined(__CYGWIN__) || defined(__FreeBSD__) #define stat64 stat #define lstat64 lstat // for religious reasons, CYGWIN doesn't do lstat64 // FreeBSD doesn't do lstat64 because there is no need for it #endif using namespace std; #ifdef _WIN32 // #ifdef _MSC_VER // MSVC uses 64bit internally # define stat64 stat # define lstat64(x,y) stat(x,y) #else // Patch by Greg Jung: Using _stati64 is acceptable down to winXP version and will // result in a 64-bit st_size for both mingw-org and for mingw-w64. // The times st_atime, st_mtime, etc. will be 32-bit in mingw-org. #ifndef stat64 /* case of mingw-org .vs. mingw-w64 */ # define stat64 _stati64 #endif # define lstat64(x,y) stat64(x,y) #endif // modifications : 2014, 2015 by Greg Jung // fstat_win32 used for symlink treatment static void fstat_win32(const DString& DSpath, int& st_mode, DWORD &dwattrib) { DWORD reparsetag; WCHAR filepath[MAX_PATH+1]; HANDLE hFind; BOOL foundnext; WIN32_FIND_DATAW FindFileData; // Native NTFS symlinks (not Junctions) are found // also cygwin symlinks are sniffed out. MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) DSpath.c_str(), -1, filepath, MAX_PATH+1); hFind = FindFirstFileExW( filepath, FindExInfoStandard, &FindFileData, FindExSearchNameMatch, NULL, 0); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); return; } dwattrib = FindFileData.dwFileAttributes; if( (dwattrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0 ) { reparsetag = FindFileData.dwReserved0; if(reparsetag == IO_REPARSE_TAG_SYMLINK) st_mode |= S_IFLNK; } else if ( (dwattrib & FILE_ATTRIBUTE_SYSTEM) != 0 ) { // This is the first step to a cygwin symlink. // next, '!' is first 10 bytes. // following this, 0xFF 0xFE // for now, just assume it is a link. HANDLE hFile = CreateFileW( filepath, FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_RANDOM_ACCESS, 0); if (hFile == INVALID_HANDLE_VALUE) { CloseHandle(hFile); // happens for "hidden" files or protected files: // cout << " stat_win32: could not open " + DSpath << endl; return; } char header[12]; DWORD nbytesread; BOOL result = ReadFile(hFile, header, 12, &nbytesread, 0 ); if (strncmp( header, "!",10) == 0 ) st_mode |= S_IFLNK; CloseHandle(hFile); } FindClose(hFind); return; } #endif namespace lib { string PathSeparator() { #ifdef _WIN32 return string ("\\"); #else return string ("/"); #endif } DString GetCWD() { SizeT bufSize = PATH_MAX; char *buf = new char[ bufSize]; for(;;) { char* value = getcwd( buf, bufSize); if( value != NULL) break; delete[] buf; if( bufSize > 32000) throw GDLException("Cannot get CWD."); bufSize += PATH_MAX; buf = new char[ bufSize]; } DString cur( buf); delete[] buf; #ifdef _WIN32 size_t pp; // This is to make path names uniform w.r.t. Unix // and compliant with posix shell. pp=0; for(;;){ pp=cur.find( "\\",pp); if (pp==string::npos) break; cur[pp]='/'; } #endif /* */ return cur; } void cd_pro( EnvT* e) { if( e->KeywordPresent( 0)) // CURRENT { DString cur = GetCWD(); e->SetKW( 0, new DStringGDL( cur)); } SizeT nParam=e->NParam(); if( nParam == 0) return; DString dir; e->AssureScalarPar( 0, dir); WordExp( dir); // // expand tilde #ifdef _WIN32 if( dir[0] == '~') { char* homeDir = getenv( "HOME"); if( homeDir == NULL) homeDir = getenv("HOMEPATH"); if( homeDir != NULL){ dir = string( homeDir) + "/" + dir.substr(1); size_t pp; pp=0; for(;;){ pp=dir.find( "\\",pp); if (pp==string::npos) break; dir[pp]='/'; } } } #endif int success = chdir( dir.c_str()); if( success != 0) e->Throw( "Unable to change current directory to: "+dir+"."); } static bool FindInDir( const DString& dirN, const DString& pat) { DIR* dir = opendir( dirN.c_str()); if( dir == NULL) return false; struct stat64 statStruct; #ifdef _WIN32 // JP Mar 2015: Below code block is inspired by Greg's code to improve speed wchar_t entryWStr[PATH_MAX+1] = {0,}; wchar_t patW[PATH_MAX+1] = {0,}; MultiByteToWideChar(CP_UTF8, 0, pat.c_str(), -1, patW, MAX_PATH+1); #endif DString root = dirN; AppendIfNeeded( root, "/"); for(;;) { struct dirent* entry = readdir( dir); if( entry == NULL) break; DString entryStr( entry->d_name); if( entryStr == "." || entryStr == "..") continue; DString testFile = root + entryStr; int actStat = lstat64( testFile.c_str(), &statStruct); if( S_ISDIR(statStruct.st_mode) == 0) { // only test non-dirs #ifdef _WIN32 MultiByteToWideChar(CP_UTF8, 0, entryStr.c_str(), -1, entryWStr, MAX_PATH+1); int match = !PathMatchSpecW( entryWStr, patW ); #else int match = fnmatch( pat.c_str(), entryStr.c_str(), 0); #endif if( match == 0) { closedir( dir); return true; } } } closedir( dir); return false; } static void ExpandPathN( FileListT& result, const DString& dirN, const DString& pat, bool all_dirs ) { // expand "+" int fnFlags = 0; // fnFlags |= FNM_PERIOD; // fnFlags |= FNM_NOESCAPE; DString root = dirN; AppendIfNeeded( root, "/"); struct stat64 statStruct; FileListT recurDir; bool notAdded = !all_dirs; DIR* dir = opendir( dirN.c_str()); if( dir == NULL) return; // JP Mar 2015: Below code block is inspired by Greg's code to improve speed #if defined (_WIN32) wchar_t entryWStr[PATH_MAX+1] = {0,}; wchar_t patW[PATH_MAX+1] = {0,}; MultiByteToWideChar(CP_UTF8, 0, pat.c_str(), -1, patW, PATH_MAX+1); #endif for (;; ) { struct dirent* entry = readdir( dir); if( entry == NULL) break; DString entryStr( entry->d_name); if( entryStr == "." || entryStr == "..") continue; DString testDir = root + entryStr; int actStat = lstat64(testDir.c_str(), &statStruct); #ifdef _WIN32 DWORD dwattrib; int addlink = 0; fstat_win32(testDir, addlink, dwattrib); statStruct.st_mode |= addlink; #endif bool isASymLink = S_ISLNK(statStruct.st_mode); // // follow for expand_path, as per documented behavior of IDL // if(isASymLink) actStat = stat64(testDir.c_str(), &statStruct); if( S_ISDIR(statStruct.st_mode) != 0) { // if( debug && isASymLink ) cout << " following a symlink directory: " << testDir << endl; recurDir.push_back( testDir); } else if( notAdded) { #ifdef _WIN32 MultiByteToWideChar(CP_UTF8, 0, entryStr.c_str(), -1, entryWStr, PATH_MAX+1); int match = !PathMatchSpecW(entryWStr, patW); #else int match = fnmatch( pat.c_str(), entryStr.c_str(), 0); #endif if( match == 0) notAdded = false; } } int c = closedir( dir); if( c == -1) return; // recursive search SizeT nRecur = recurDir.size(); for ( SizeT d = 0; d < nRecur; ++d ) { ExpandPathN( result, recurDir[d], pat, all_dirs); } if( !notAdded) result.push_back( dirN); } // modifications : 2014, 2015 by Greg Jung void ExpandPath( FileListT& result, const DString& dirN, const DString& pat, bool all_dirs) { if( dirN == "") return; if( StrUpCase( dirN) == "" || StrUpCase( dirN) == "") { // result.push_back( the default path here); return; } if( dirN[0] != '+' && dirN[0] != '~') { result.push_back( dirN); return; } if( dirN.length() == 1) { // dirN == "+" if (dirN[0] == '+') return; } // dirN == "+DIRNAME" #ifdef _WIN32 DString initDir = dirN; if(dirN[0] == '+') initDir = dirN.substr(1); #else // do first a glob because of '~' int flags = GLOB_TILDE | GLOB_NOSORT; glob_t p; int offset_tilde=0; if (dirN[0] == '+') offset_tilde=1; int gRes = glob( dirN.substr(offset_tilde).c_str(), flags, NULL, &p); if( gRes != 0 || p.gl_pathc == 0) { globfree( &p); return; } DString initDir = p.gl_pathv[ 0]; globfree( &p); #endif if (dirN[0] == '+') { ExpandPathN( result, initDir, pat, all_dirs); } else { result.push_back(initDir); } } BaseGDL* expand_path( EnvT* e) { e->NParam( 1); DString s; e->AssureStringScalarPar( 0, s); FileListT sArr; static int all_dirsIx = e->KeywordIx( "ALL_DIRS"); bool all_dirs = e->KeywordSet( all_dirsIx); static int arrayIx = e->KeywordIx( "ARRAY"); bool array = e->KeywordSet( arrayIx); static int countIx = e->KeywordIx( "COUNT"); DString pattern; static int typeIx = e->KeywordIx( "PATTERN"); if(e->KeywordPresent(typeIx)) { e->AssureStringScalarKWIfPresent( typeIx, pattern); } else pattern = "*.pro"; SizeT d; long sPos=0; #ifdef _WIN32 char pathsep[]=";"; #else char pathsep[]=":"; #endif do { d=s.find(pathsep[0],sPos); string act = s.substr(sPos,d-sPos); ExpandPath( sArr, act, pattern, all_dirs); sPos=d+1; } while( d != s.npos); SizeT nArr = sArr.size(); if( e->KeywordPresent( countIx)) { e->SetKW( countIx, new DLongGDL( nArr)); } if( nArr == 0) return new DStringGDL( ""); if( array) { DStringGDL* res = new DStringGDL( dimension( nArr), BaseGDL::NOZERO); for( SizeT i=0; i 0) && // find end of root's viable name. ( (rootC[ endR] == PS) || (rootC[ endR] == '/') || (rootC[ endR] == ' '))) endR--; if( endR >= 0) root = root.substr( 0, endR+1); FileListT recurDir; DIR* dir; if( root != "") dir = opendir( dirN.c_str()); else dir = opendir( "."); if( dir == NULL) { if( accErr) throw GDLException( "FILE_SEARCH: Error opening dir: "+root); else return; } DString prefix = root; if(root != "") AppendIfNeeded(prefix,"/"); // If Dir_specification does not have a "/" at end then we will include /.. // but this is a fix for other issues. // if(onlyDir) fL.push_back(prefix); if( onlyDir && (pat == "" ) ) { fL.push_back(prefix); return; } // file_search('nn','') != file_search('nn/','') // where 'nn' is a directory in CWD. // if(prefix == "./") prefix=""; int accessmode = 0; if(dotest) { if( tests[0]) accessmode = R_OK; if( tests[1]) accessmode |= W_OK; #ifndef _WIN32 if( tests[2]) accessmode |= X_OK; #endif } const char* patC = pat.c_str(); // if(pat == "") patC = "*"; // pat="" can be done by sending pat=" " while(*patC == ' ')patC++; // doesn't work with leading blanks. #ifdef _WIN32 wchar_t patW[MAX_PATH+1]; wchar_t entryWstr[MAX_PATH+1]; MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)patC, -1, patW, MAX_PATH+1); #endif DString filepath; const char* fpC; // if(trace_me) std::cout << " prefix:" << prefix; struct stat64 statStruct, statlink; for(;;) { struct dirent* entry = readdir( dir); if( entry == NULL) break; DString entryStr( entry->d_name); if( entryStr == "." || entryStr == "..") continue; const char* entryStrC = entryStr.c_str(); filepath = prefix + entryStr; fpC = filepath.c_str(); // if(trace_me) std::cout << "| "<< entryStr; int actStat = lstat64( fpC, &statStruct); #ifdef _WIN32 if(*entryStrC == '.' && !match_dot) continue; MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)entryStrC, -1, entryWstr, MAX_PATH+1); int match = !PathMatchSpecW(entryWstr, patW); #else int match = fnmatch( patC, entryStrC, fnFlags); #endif if( match == 0) { if( onlyDir ) { if( mark ) filepath.append("/"); if(S_ISDIR(statStruct.st_mode) != 0) fL.push_back( filepath); continue; } #ifdef _WIN32 DWORD dwattrib; int addlink = 0; fstat_win32(filepath, addlink, dwattrib); statStruct.st_mode |= addlink; #endif bool isaDir = (S_ISDIR(statStruct.st_mode) != 0); bool isASymLink = (S_ISLNK(statStruct.st_mode) != 0); if(isASymLink) { actStat = stat64( fpC, &statlink); statStruct.st_mode |= statlink.st_mode; isaDir = (S_ISDIR(statlink.st_mode) != 0); } if(dotest) { if( tests[testregular] && (S_ISREG( statStruct.st_mode) == 0)) continue; if( tests[testdir] && !isaDir) continue; if( tests[testsymlink] && !isASymLink) continue; if( tests[testzero] && (statStruct.st_size != 0)) continue; // now read, write, execute: if(accessmode != 0 && (access(fpC, accessmode) != 0) ) continue; } if( isaDir and mark) { filepath.append("/"); fpC = filepath.c_str(); } if(forceAbsPath) { char actualpath [PATH_MAX+1]; char *ptr; ptr = realpath(fpC, actualpath); if( ptr != NULL ) { #ifdef _WIN32 for(int i=0;ptr[i] != 0;i++) if(ptr[i] == '\\') ptr[i] = '/'; #endif fL.push_back( string(ptr)); } } else fL.push_back( filepath); } #ifndef _WIN32 if( root == "") continue; #endif if( (S_ISDIR(statStruct.st_mode) != 0) && ( S_ISLNK(statStruct.st_mode) == 0) ) recurDir.push_back( filepath); } int c = closedir( dir); if( c == -1) { if( accErr) throw GDLException( "FILE_SEARCH: Error closing dir: "+dirN); else return; } // recursive search if( !recursive ) return; SizeT nRecur = recurDir.size(); for( SizeT d=0; d='A' && s[i]<='Z') || (s[i]>='a' && s[i]<='z')) { char m,M; if(s[i]>='a' && s[i]<='z') m=s[i],M=m+'A'-'a'; else M=s[i],m=M-'A'+'a'; if(bracket) // If bracket is open, then don't add bracket couple[0]=m,couple[1]=M,insen+=couple; else // else [aA] coupleBracket[1]=m,coupleBracket[2]=M,insen+=coupleBracket; } else { if(s[i]=='[') { bracket=false; for( size_t ii=i;ii 0 ) { size_t pp; pp=0; do { pp=st.find( "/./"); if (pp!=string::npos) { st.erase(pp, 2);} } while (pp!=string::npos); pp=0; do { pp=st.find( "//"); if (pp!=string::npos) { st.erase(pp, 1);} } while (pp!=string::npos); //Last "/.." pp=st.rfind( "/.."); //remove and back if last if (pp!=string::npos && pp==st.size()-3) { //erase from previous "/" to pp+3. Unless there is no previous "/"! size_t prevdir = st.rfind("/",pp-1); if (prevdir != string::npos) {st.erase(prevdir, pp+3-prevdir);} } //Last "/." pp=st.rfind( "/."); //remove if last if (pp!=string::npos && pp==st.size()-2) st.erase(pp); //Last "/" if removeMark is true if (removeMark) { pp=st.rfind( "/"); //remove and back if last if (pp!=string::npos && pp==st.size()-1) st.erase(pp); } // other places for "/..": between directories pp=0; do { pp=st.find( "/../"); if (pp!=string::npos) { //erase from previous "/" to pp+3. Unless there is no previous "/"! size_t prevdir = st.rfind("/",pp-1); if (prevdir != string::npos) {st.erase(prevdir, pp+3-prevdir);} else break; //what should I do? } } while (pp!=string::npos); //First "./" pp=st.find( "./"); //remove if first if (pp==0) st.erase(pp,2); } return st; } #include static void FileSearch( FileListT& fileList, const DString& pathSpec, bool environment, bool tilde, bool accErr, bool mark, bool noSort, bool quote, bool period, bool forceAbsPath, bool fold_case, bool dir, bool *tests=NULL) { enum { testregular = 3, testdir, testzero, testsymlink }; bool dotest = false; for ( SizeT i = 0; i < NTEST_SEARCH; i++ ) dotest |= tests[i]; int globflags = 0; DString st; if ( environment ) globflags |= GLOB_BRACE; if ( tilde ) globflags |= GLOB_TILDE; if ( accErr ) globflags |= GLOB_ERR; if ( mark && !dir ) // only mark directory if not in dir mode globflags |= GLOB_MARK; // if( noSort) sorting is done again later in file_search. globflags |= GLOB_NOSORT; #if !defined(__APPLE__) && !defined(__FreeBSD__) if ( !quote ) // n/a on OS X globflags |= GLOB_NOESCAPE; if ( dir ) // simulate with lstat() globflags |= GLOB_ONLYDIR; if ( period ) // n/a on OS X globflags |= GLOB_PERIOD; #endif if( fold_case) st=makeInsensitive(pathSpec); else st=pathSpec; glob_t p; int gRes; if ( !forceAbsPath ) { if ( st != "" ) gRes = glob( st.c_str( ), globflags, NULL, &p ); else gRes = glob( "*", globflags, NULL, &p ); } else { string pattern; if ( st == "" ) { pattern = GetCWD( ); pattern.append( "/*" ); gRes = glob( pattern.c_str( ), globflags, NULL, &p ); } else { if ( st.at( 0 ) != '/' && !(tilde && st.at( 0 ) == '~') && !(environment && st.at( 0 ) == '$') ) { pattern = GetCWD( ); pattern.append( "/" ); if ( !(st.size( ) == 1 && st.at( 0 ) == '.') ) pattern.append( st ); gRes = glob( pattern.c_str( ), globflags, NULL, &p ); } else { gRes = glob( st.c_str( ), globflags, NULL, &p ); } } } #ifndef __APPLE__ if ( accErr && (gRes == GLOB_ABORTED || gRes == GLOB_NOSPACE) ) throw GDLException( "FILE_SEARCH: Read error: " + pathSpec ); #else if ( accErr && (gRes != 0 && p.gl_pathc > 0) ) // NOMATCH is no error throw GDLException( "FILE_SEARCH: Read error: " + pathSpec ); #endif struct stat64 statStruct, statlink; int accessmode = 0; if ( tests[0] ) accessmode = R_OK; if ( tests[1] ) accessmode |= W_OK; if ( tests[2] ) accessmode |= X_OK; if ( gRes == 0 ) for ( SizeT f = 0; f < p.gl_pathc; ++f ) { int actStat; std::string actFile = p.gl_pathv[ f]; if ( dotest != 0 ) { actStat = lstat64( actFile.c_str(), &statStruct ); if ( tests[testregular] && // (excludes dirs, sym) (S_ISREG( statStruct.st_mode ) == 0) ) continue; bool isASymLink = (S_ISLNK(statStruct.st_mode) != 0); if(isASymLink) actStat = stat64( actFile.c_str(), &statStruct); bool isaDir = (S_ISDIR( statStruct.st_mode ) != 0); if ( tests[testdir] && !isaDir ) continue; if ( tests[testsymlink] && !isASymLink ) continue; if ( tests[testzero] && (statStruct.st_size != 0) ) continue; // now read, write, execute: if ( accessmode != 0 ) if ( access( actFile.c_str(), accessmode ) != 0 ) continue; } #ifndef __APPLE__ fileList.push_back( BeautifyPath(actFile, !mark) ); #else if ( !dir ) fileList.push_back( BeautifyPath(actFile, !mark) ); else { // push only if dir actStat = lstat64( actFile.c_str(), &statStruct ); if ( S_ISDIR( statStruct.st_mode ) != 0 ) fileList.push_back( BeautifyPath(actFile, !mark) ); } #endif } globfree( &p ); if ( st == "" && dir ) fileList.push_back( "" ); } // static void FileSearch #endif #ifdef _WIN32 // the unix version (as of Oct 2017) is copied to here std::string BeautifyPath(std::string st, bool removeMark=true) { //removes series of "//", "/./" and "/.." and adjust path accordingly. if ( st.length( ) > 0 ) { size_t pp; pp=0; do { pp=st.find( "/./"); if (pp!=string::npos) { st.erase(pp, 2);} } while (pp!=string::npos); pp=0; do { pp=st.find( "//"); if (pp!=string::npos) { st.erase(pp, 1);} } while (pp!=string::npos); //Last "/.." pp=st.rfind( "/.."); //remove and back if last if (pp!=string::npos && pp==st.size()-3) { //erase from previous "/" to pp+3. Unless there is no previous "/"! size_t prevdir = st.rfind("/",pp-1); if (prevdir != string::npos) {st.erase(prevdir, pp+3-prevdir);} } //Last "/." pp=st.rfind( "/."); //remove if last if (pp!=string::npos && pp==st.size()-2) st.erase(pp); //Last "/" if removeMark is true if (removeMark) { pp=st.rfind( "/"); //remove and back if last if (pp!=string::npos && pp==st.size()-1) st.erase(pp); } // other places for "/..": between directories pp=0; do { pp=st.find( "/../"); if (pp!=string::npos) { //erase from previous "/" to pp+3. Unless there is no previous "/"! size_t prevdir = st.rfind("/",pp-1); if (prevdir != string::npos) {st.erase(prevdir, pp+3-prevdir);} else break; //what should I do? } } while (pp!=string::npos); //First "./" pp=st.find( "./"); //remove if first if (pp==0) st.erase(pp,2); } return st; } #endif static std::string Dirname(const string& tmp, bool mark_dir = false) { char buf[ PATH_MAX+1]; // G. Jung Simplify the alternatives to psalt, PS using same processing. // for mark_dir, always just place a "/" char PS='\\'; char psalt[] = "/"; #ifndef _WIN32 strncpy(buf, tmp.c_str(), PATH_MAX+1); string dname = dirname(buf); #else char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; DString::size_type pos = 0, offset = 0; DString tmp2(tmp); // if 0/ if 1: by preference. while ((pos = tmp2.find(psalt, offset)) != string::npos) { tmp2[pos] = PS; offset = pos + 1; } int size=tmp2.size(); if(tmp2[size--] == PS) do tmp2.resize(size); while((size != 0) && tmp2[size--] == PS); _splitpath( tmp2.c_str(),drive,dir,fname,ext); dir[strlen(dir) - 1] = 0; // Remove separator DString dname = DString(drive) + dir; if( dname == "" ) dname = string("."); // if( trace_me ) std::cout << " dirname(win32) drive=" << drive << // " dir: "<< dir << std::endl; size = dname.size(); if(dname[size--] == PS) do dname.resize(size); while((size != 0) && dname[size--] == PS); size_t pp; // This is to make path names uniform w.r.t. Unix // and compliant with posix shell. pp=0; for(;;){ pp=dname.find( "\\",pp); if (pp==string::npos) break; dname[pp]='/'; } #endif if (mark_dir) dname = dname + string("/"); return dname; } // modifications : 2014, 2015 by Greg Jung static void PathSearch( FileListT& fileList, const DString& pathSpec, bool noexpand_path=false, bool recursive=false, bool accErr=false, bool mark=false, bool quote=false, bool match_dot=false, bool forceAbsPath=false, bool fold_case=false, bool onlyDir=false, bool *tests = NULL) { string dir = pathSpec; if( forceAbsPath ) { size_t dlen = dir.length(); if( dlen > 0) { if( dir[0] == '.' ) { if(dlen == 1) dir = GetCWD(); else if (dir[1] == '/') dir = GetCWD() + dir.substr(1); #ifdef _WIN32 else if (dir[1] == '\\') dir = GetCWD() + dir.substr(1); #endif else if (dlen >= 2 && dir[1] =='.') { if( dlen == 2) dir = Dirname(GetCWD()); else if (dir[2] == '/') dir = Dirname(GetCWD()) + dir.substr(2); #ifdef _WIN32 else if (dir[2] == '\\') dir = Dirname(GetCWD()) + dir.substr(2); #endif } // (dlen >= 2 && dir[1]='.') } // dir[0] == '.' } // dlen > 0 if ( dir.substr(0,2) == "./") dir = GetCWD() + dir.substr(1); else if( dir.substr(0,3) == "../") { char actualpath [PATH_MAX+1]; char *ptr; ptr = realpath("../", actualpath); #ifdef _WIN32 for(int i=0;ptr[i] != 0;i++) if(ptr[i] == '\\') ptr[i] = '/'; #endif dir = string(ptr) + dir.substr(2); } } // forceAbsPath size_t pp = dir.rfind( " "); if (pp!=string::npos && pp== dir.size()-1) dir.erase(pp); // if(trace_me) std::cout << "PathSearch, dir=" << dir ; if(!noexpand_path) WordExp(dir); // always expanding tilde in same manner, WIN32 or not, ignoring "noexpand" if( dir[0] == '~') { char* homeDir = getenv( "HOME"); if( homeDir == NULL) homeDir = getenv("HOMEPATH"); if( homeDir != NULL) { dir = string( homeDir) + "/" + dir.substr(1); #ifdef _WIN32 size_t pp; // This is to make path names uniform w.r.t. Unix // and compliant with posix shell. pp=0; for(;;){ pp=dir.find( "\\",pp); if (pp==string::npos) break; dir[pp]='/'; } #endif } } #ifndef _WIN32 if( fold_case) dir = BeautifyPath(makeInsensitive(dir)); else dir = BeautifyPath(dir); #endif DString dirsearch = ""; // Look for the last dir-separator at end of string. i.e. file_search('/d/bld/gdl*') char PS0 = '/'; char PS1 = '/'; // win32 could be either PathSeparator, or both: #ifdef _WIN32 PS1 = '\\'; #endif int dirsep=-1; int lenpath = dir.length(); int ii=0; do { if((dir[ii] == PS0) || (dir[ii] == PS1)) dirsep=ii; } while( ii++ < lenpath ); if( dirsep != lenpath) { struct stat64 statStruct; int dirStat = lstat64( dir.c_str(), &statStruct); if( dirStat == 0) { // if(trace_me) cout << "PathSearch:"<< "quicky " // << pathSpec <<" -simple? "<< dirStat<= 0) dir.resize(dirsep); } } if(dirsep == -1) { dir = "."; dirsearch = pathSpec; } // if(trace_me) std::cout << "PathSearch:"<GetParString(0)); DStringGDL* p0S = static_cast(p0); SizeT nPath = p0S->N_Elements(); DStringGDL* res = new DStringGDL(p0S->Dim(), BaseGDL::NOZERO); for( SizeT r=0; r (tmp.c_str()); char actualpath [PATH_MAX+1]; char *ptr; ptr = realpath(symlinkpath, actualpath); #ifdef _WIN32 for(int i=0;ptr[i] != 0;i++) if(ptr[i] == '\\') ptr[i] = '/'; #endif if( ptr != NULL ){ (*res)[r] =string(ptr); } else { //( errors are not managed ...) (*res)[r] = tmp ; } } } return res; } /* Result = FILE_SEARCH(Path_Specification) (Standard) or for recursive searching, Result = FILE_SEARCH(Dir_Specification, Recur_Pattern) Standard: When called with a single Path_Specification argument, FILE_SEARCH returns all files that match that specification. This is the same operation, sometimes referred to as file globbing, performed by most operating system command interpreters when wildcard characters are used in file specifications. Recursive: When called with two arguments, FILE_SEARCH performs recursive searching of directory hierarchies. In a recursive search, FILE_SEARCH looks recursively for any and all subdirectories in the file hierarchy rooted at the Dir_Specification argument. Within each of these subdirectories, it returns the names of all files that match the pattern in the Recur_Pattern argument. This operation is similar to that performed by the UNIX find(1) command. NOTE: in order to avoid infinite reference loops, IDL policy states that symlinks are not followed. symlnk references should therefore be returned as found, without resolution, and can be processed by the FILE_READLINK function. NOTE: Contrary to above documented intention, acutal IDL behavior is that when called with two arguments the Dir_specification argument could itself be a pattern-search; hence the dance below where, for Nparam > 1, first duty is to search on the 1st parameter for directories. // modifications : 2014, 2015 by Greg Jung */ BaseGDL* file_search( EnvT* e) { enum { testregular=3, testdir, testzero, testsymlink }; SizeT nParam=e->NParam(); // 0 -> "*" DStringGDL* pathSpec; SizeT nPath = 0; bool recursive_dirsearch = true; DString Pattern = ""; if( nParam > 0) { BaseGDL* p0 = e->GetParDefined( 0); pathSpec = dynamic_cast( p0); if( pathSpec == NULL) e->Throw( "String expression required in this context."); nPath = pathSpec->N_Elements(); bool leading_nullst = ((*pathSpec)[0] == ""); if( leading_nullst ) Pattern = "*"; // If Path_Specification is not supplied, or if it is supplied as an empty string, FILE_SEARCH uses a // default pattern of '*', which matches all files in the current directory if( nParam > 1) { e->AssureScalarPar< DStringGDL>( 1, Pattern); // 'If Dir_Specification is supplied as an empty string, FILE_SEARCH searches the current directory.' if( (nPath == 1) && leading_nullst ) recursive_dirsearch = false; } } static int TEST_READIx = e->KeywordIx("TEST_READ"); static int TEST_WRITEIx = e->KeywordIx("TEST_WRITE"); static int TEST_EXECUTABLEIx = e->KeywordIx("TEST_EXECUTABLE"); static int TEST_REGULARIx = e->KeywordIx("TEST_REGULAR"); static int TEST_DIRECTORYIx = e->KeywordIx("TEST_DIRECTORY"); static int TEST_ZERO_LENGTHIx = e->KeywordIx("TEST_ZERO_LENGTH"); static int TEST_SYMLINKIx = e->KeywordIx("TEST_SYMLINK"); static int REGULARIx = e->KeywordIx("REGULAR"); static int DIRECTORYIx = e->KeywordIx("DIRECTORY"); static int ZERO_LENGTHIx = e->KeywordIx("ZERO_LENGTH"); static int SYMLINKIx = e->KeywordIx("SYMLINK"); const int test_kwIx[]={ TEST_READIx, TEST_WRITEIx, TEST_EXECUTABLEIx, TEST_REGULARIx, TEST_DIRECTORYIx, TEST_ZERO_LENGTHIx, TEST_SYMLINKIx}; // const string test_kw[]={ // "TEST_READ", "TEST_WRITE", "TEST_EXECUTABLE", // "TEST_REGULAR", "TEST_DIRECTORY", "TEST_ZERO_LENGTH", // "TEST_SYMLINK"}; bool tests[NTEST_SEARCH]; static int keyindex; for( SizeT i=0; i < NTEST_SEARCH; i++) { if (e->KeywordPresent(test_kwIx[i])) tests[i] = e->KeywordSet(test_kwIx[i]); else tests[i] = false; } // extra options for convenience: if( e->KeywordSet( DIRECTORYIx )) tests[testdir]=true; if( e->KeywordSet( SYMLINKIx )) tests[testsymlink]=true; if( e->KeywordSet( REGULARIx )) tests[testregular]=true; if( e->KeywordSet( ZERO_LENGTHIx )) tests[testzero]=true; // keywords bool tilde = true; bool fold_case = false; // next three have default behaviour static int tildeIx = e->KeywordIx( "EXPAND_TILDE"); bool tildeKW = e->KeywordPresent( tildeIx); if( tildeKW) tilde = e->KeywordSet( tildeIx); bool environment = true; static int environmentIx = e->KeywordIx( "EXPAND_ENVIRONMENT"); bool environmentKW = e->KeywordPresent( environmentIx); if( environmentKW) { bool Set = e->KeywordSet( environmentIx); if( Set) { environment = true; ;} else environment = false; } bool noexpand_path = !environment; static int fold_caseIx = e->KeywordIx( "FOLD_CASE"); bool fold_caseKW = e->KeywordPresent( fold_caseIx); if( fold_caseKW) fold_case = e->KeywordSet( fold_caseIx); // static int countIx = e->KeywordIx( "COUNT"); bool countKW = e->KeywordPresent( countIx); static int accerrIx = e->KeywordIx( "ISSUE_ACCESS_ERROR"); bool accErr = e->KeywordSet( accerrIx); static int markIx = e->KeywordIx( "MARK_DIRECTORY"); bool mark = e->KeywordSet( markIx); static int nosortIx = e->KeywordIx( "NOSORT"); bool noSort = e->KeywordSet( nosortIx); static int quoteIx = e->KeywordIx( "QUOTE"); bool quote = e->KeywordSet( quoteIx); static int match_dotIx = e->KeywordIx( "MATCH_INITIAL_DOT"); bool match_dot = e->KeywordSet( match_dotIx); static int match_all_dotIx = e->KeywordIx( "MATCH_ALL_INITIAL_DOT"); bool match_all_dot = e->KeywordSet( match_all_dotIx); static int fully_qualified_pathIx = e->KeywordIx( "FULLY_QUALIFY_PATH"); bool forceAbsPath = e->KeywordSet( fully_qualified_pathIx); if( match_all_dot) Warning( "FILE_SEARCH: MATCH_ALL_INITIAL_DOT keyword ignored (not supported)."); bool onlyDir = nParam > 1; FileListT fileList; DLong count; #ifndef _WIN32 // The alternative can be used in Linux, also. // replace above with #if 0 to unify methods. // Differences? please notify me (GVJ) //#if 0 if( nPath == 0) FileSearch( fileList, "", environment, tilde, accErr, mark, noSort, quote, match_dot, forceAbsPath, fold_case, onlyDir, tests); else if( !recursive_dirsearch ) fileList.push_back(string("./")); else // it appears glob is incapable of returning a symlink.! for( SizeT f=0; f < nPath; ++f) FileSearch( fileList, (*pathSpec)[f], environment, tilde, accErr, mark, noSort, quote, match_dot, forceAbsPath, fold_case, onlyDir, tests); #else // if(trace_me) std::cout << "file_search: fileList.size()=" // << fileList.size() << std::endl; if(nPath == 0) PathSearch( fileList, "./*", noexpand_path, false, accErr, mark, quote, match_dot, forceAbsPath,fold_case, onlyDir, tests); else if( !recursive_dirsearch ) fileList.push_back(string("./")); else for( SizeT f=0; f < nPath; ++f) { PathSearch( fileList, (*pathSpec)[f], noexpand_path, false, accErr, mark, quote, match_dot, forceAbsPath,fold_case, onlyDir, tests); } #endif onlyDir = false; count = fileList.size(); FileListT fileOut; for( SizeT f=0; f 1) PatternSearch( fileOut, fileList[f], Pattern, recursive_dirsearch, accErr, mark, quote, match_dot, forceAbsPath,fold_case, onlyDir , tests); else fileOut.push_back(fileList[f]); } DLong pCount = fileOut.size(); if( countKW) e->SetKW( countIx, new DLongGDL( pCount)); if(nParam > 2) { // provision for a third parameter = filecount return. e->AssureGlobalPar(2); e->SetPar(2, new DLongGDL(pCount)); } // use this only for interactive sessions: not an IDL feature. if( pCount == 0) return new DStringGDL(""); if( !noSort) sort( fileOut.begin(), fileOut.end()); // fileOut -> res DStringGDL* res = new DStringGDL( dimension( pCount), BaseGDL::NOZERO); for( SizeT r=0; rNParam( 1); // accepting only strings as parameters BaseGDL* p0 = e->GetParDefined(0); if( p0->Type() != GDL_STRING) e->Throw("String expression required in this context: " + e->GetParString(0)); DStringGDL* p0S = static_cast(p0); BaseGDL* p1; DStringGDL* p1S; bool DoRemoveSuffix = false; if (nParams == 2) { // shall we remove a suffix ? p1 = e->GetPar(1); if( p1 == NULL || p1->Type() != GDL_STRING) e->Throw("String expression required in this context: " + e->GetParString(1)); p1S = static_cast(p1); if (p1S->N_Elements() == 1) { if ((*p1S)[0].length() >0) DoRemoveSuffix=true; } if (p1S->N_Elements() > 1) e->Throw(" Expression must be a scalar or 1 element array in this context: " + e->GetParString(1)); } dimension resDim; resDim=p0S->Dim(); DStringGDL* res = new DStringGDL(resDim, BaseGDL::NOZERO); for (SizeT i = 0; i < p0S->N_Elements(); i++) { const string& tmp=(*p0S)[i]; if (tmp.length() > 0) { #ifdef _WIN32 char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath( tmp.c_str(),drive,dir,fname,ext); string bname = string(fname)+ext; #else char buf[ PATH_MAX+1]; strncpy(buf, tmp.c_str(), PATH_MAX+1); string bname = basename(buf); #endif (*res)[i] = bname; } else (*res)[i]=""; } // managing suffixe if (DoRemoveSuffix) { string suffixe=(*p1S)[0]; int suffLength=(*p1S)[0].length(); static int fold_caseIx = e->KeywordIx( "FOLD_CASE"); bool fold_case = e->KeywordSet( fold_caseIx); if (fold_case) suffixe=StrUpCase(suffixe); //cout << "suffixe :"<< suffixe << endl; string tmp1, fin_tmp; for (SizeT i = 0; i < p0S->N_Elements(); i++) { tmp1=(*res)[i]; // Strickly greater : if equal, we keep it ! if (tmp1.length() > suffLength) { fin_tmp=tmp1.substr(tmp1.length()-suffLength); if (fold_case) fin_tmp=StrUpCase(fin_tmp); if (fin_tmp.compare(suffixe) == 0) (*res)[i]=tmp1.substr(0,tmp1.length()-suffLength); } } } return res; } BaseGDL* file_dirname( EnvT* e) { // accepting only strings as parameters BaseGDL* p0 = e->GetParDefined(0); if( p0->Type() != GDL_STRING) e->Throw("String expression required in this context: " + e->GetParString(0)); DStringGDL* p0S = static_cast(p0); bool mark_dir; dimension resDim; resDim=p0S->Dim(); DStringGDL* res = new DStringGDL(resDim, BaseGDL::NOZERO); static int mark_dirIx = e->KeywordIx("MARK_DIRECTORY"); mark_dir = e->KeywordSet(mark_dirIx);// mark_dir = add a "/" at end of result. for (SizeT i = 0; i < p0S->N_Elements(); i++) { const string& tmp = (*p0S)[i]; (*res)[i] = Dirname(tmp, mark_dir); } return res; } BaseGDL* file_same( EnvT* e) { // assuring right number of parameters SizeT nParam=e->NParam(2); // accepting only strings as parameters BaseGDL* p0 = e->GetParDefined(0); DStringGDL* p0S = dynamic_cast(p0); if (p0S == NULL) e->Throw("String expression required in this context: " + e->GetParString(0)); BaseGDL* p1 = e->GetParDefined(1); DStringGDL* p1S = dynamic_cast(p1); if (p1S == NULL) e->Throw("String expression required in this context: " + e->GetParString(1)); // no empty strings accepted { int empty = 0; for (SizeT i = 0; i < p0S->N_Elements(); i++) empty += (*p0S)[i].empty(); for (SizeT i = 0; i < p1S->N_Elements(); i++) empty += (*p1S)[i].empty(); if (empty != 0) e->Throw("Null filename not allowed."); } // allocating memory for the comparison result DByteGDL* res; { dimension resDim; if (p0S->Rank() == 0 || p1S->Rank() == 0) { resDim = (p0S->N_Elements() > p1S->N_Elements() ? p0S : p1S)->Dim(); } else { resDim = (p0S->N_Elements() < p1S->N_Elements() ? p0S : p1S)->Dim(); } res = new DByteGDL(resDim); // zero } // comparison loop for (SizeT i = 0; i < res->N_Elements(); i++) { // deciding which filename to compare SizeT p0idx = p0S->Rank() == 0 ? 0 : i; SizeT p1idx = p1S->Rank() == 0 ? 0 : i; // checking for lexically identical paths if ((*p0S)[p0idx].compare((*p1S)[p1idx]) == 0) { (*res)[i] = 1; continue; } // expanding if needed (tilde, shell variables, etc) const char *file0, *file1; string tmp0, tmp1; static int noexpand_pathIx=e->KeywordIx("NOEXPAND_PATH"); if (!e->KeywordSet(noexpand_pathIx)) { tmp0 = (*p0S)[p0idx]; WordExp(tmp0); tmp1 = (*p1S)[p1idx]; WordExp(tmp1); // checking again for lexically identical paths (e.g. ~/ and $HOME) if (tmp0.compare(tmp1) == 0) { (*res)[i] = 1; continue; } file0 = tmp0.c_str(); file1 = tmp1.c_str(); } else { file0 = (*p0S)[p0idx].c_str(); file1 = (*p1S)[p1idx].c_str(); } // checking for the same inode/device numbers struct stat64 statStruct; dev_t file0dev; ino_t file0ino; int ret = stat64(file0, &statStruct); if (ret != 0) continue; file0dev = statStruct.st_dev; file0ino = statStruct.st_ino; ret = stat64(file1, &statStruct); if (ret != 0) continue; (*res)[i] = (file0dev == statStruct.st_dev && file0ino == statStruct.st_ino); } return res; } BaseGDL* file_test( EnvT* e) { SizeT nParam=e->NParam( 1); BaseGDL* p0 = e->GetParDefined( 0); DStringGDL* p0S = dynamic_cast( p0); if( p0S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(0)); static int directoryIx = e->KeywordIx( "DIRECTORY"); bool directory = e->KeywordSet( directoryIx); static int executableIx = e->KeywordIx( "EXECUTABLE"); bool executable = e->KeywordSet( executableIx); static int readIx = e->KeywordIx( "READ"); bool read = e->KeywordSet( readIx); static int writeIx = e->KeywordIx( "WRITE"); bool write = e->KeywordSet( writeIx); static int zero_lengthIx = e->KeywordIx( "ZERO_LENGTH"); bool zero_length = e->KeywordSet( zero_lengthIx); static int get_modeIx = e->KeywordIx( "GET_MODE"); bool get_mode = e->KeywordPresent( get_modeIx); static int regularIx = e->KeywordIx( "REGULAR"); bool regular = e->KeywordSet( regularIx); static int block_specialIx = e->KeywordIx( "BLOCK_SPECIAL"); bool block_special = e->KeywordSet( block_specialIx); static int character_specialIx = e->KeywordIx( "CHARACTER_SPECIAL"); bool character_special = e->KeywordSet( character_specialIx); static int named_pipeIx = e->KeywordIx( "NAMED_PIPE"); bool named_pipe = e->KeywordSet( named_pipeIx); static int socketIx = e->KeywordIx( "SOCKET"); bool socket = e->KeywordSet( socketIx); static int symlinkIx = e->KeywordIx( "SYMLINK"); bool symlink = e->KeywordSet( symlinkIx); static int dSymlinkIx = e->KeywordIx( "DANGLING_SYMLINK"); bool dsymlink = e->KeywordSet( dSymlinkIx); static int noexpand_pathIx = e->KeywordIx( "NOEXPAND_PATH"); bool noexpand_path = e->KeywordSet( noexpand_pathIx); DLongGDL* getMode = NULL; if( get_mode) { getMode = new DLongGDL( p0S->Dim()); // zero e->SetKW( get_modeIx, getMode); } DLongGDL* res = new DLongGDL( p0S->Dim()); // zero // bool doStat = // zero_length || get_mode || directory || // regular || block_special || character_special || // named_pipe || socket || symlink; SizeT nEl = p0S->N_Elements(); for( SizeT f=0; f 1 && tmp[ tmp.length()-1] == '/') actFile = tmp.substr(0,tmp.length()-1); else actFile = tmp; } else { const string& tmp = (*p0S)[f]; if( tmp.length() > 1 && tmp[ tmp.length()-1] == '/') actFile = tmp.substr(0,tmp.length()-1); else actFile = tmp; } struct stat64 statStruct, statlink; int actStat = lstat64(actFile.c_str(), &statStruct); int addlink = 0; #ifdef _WIN32 DWORD dwattrib; fstat_win32(actFile, addlink, dwattrib); statStruct.st_mode |= addlink; #endif bool isASymLink = (S_ISLNK(statStruct.st_mode) != 0); if (isASymLink ) addlink = stat64(actFile.c_str(), &statlink); // //be more precise in case of symlinks --- use stat // to check if target exists or is a dangling symlink // keep result in addlink bool isADanglingSymLink = (addlink != 0 && isASymLink); if( actStat != 0) continue; if( read && access( actFile.c_str(), R_OK) != 0) continue; if( write && access( actFile.c_str(), W_OK) != 0) continue; if( zero_length && statStruct.st_size != 0) continue; #ifndef _WIN32 if( executable && access( actFile.c_str(), X_OK) != 0) continue; if( get_mode) (*getMode)[ f] = statStruct.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); if( block_special && S_ISBLK(statStruct.st_mode) == 0) continue; if( character_special && S_ISCHR(statStruct.st_mode) == 0) continue; if( named_pipe && S_ISFIFO(statStruct.st_mode) == 0) continue; if( socket && S_ISSOCK(statStruct.st_mode) == 0) continue; #endif if( dsymlink && !isADanglingSymLink ) continue; if( symlink && !isASymLink ) continue; if( directory && ( S_ISDIR(statStruct.st_mode) || S_ISDIR(statlink.st_mode) ) == 0) continue; if( regular && S_ISREG(statStruct.st_mode) == 0) continue; (*res)[ f] = 1; } return res; } BaseGDL* file_lines( EnvT* e) { SizeT nParam = e->NParam(1); //, "FILE_LINES"); DStringGDL* p0S = e->GetParAs(0); //, "FILE_LINES"); SizeT nEl = p0S->N_Elements(); if (nEl == 0) e->Throw("invalid argument"); static int compressIx = e->KeywordIx("COMPRESS"); bool compressed = e->KeywordSet(compressIx); // we actually don't use it. zlib does it all for us! static int noExpIx = e->KeywordIx("NOEXPAND_PATH"); bool noExp = e->KeywordSet(noExpIx); DLongGDL* res = new DLongGDL( p0S->Dim(), BaseGDL::NOZERO); gzFile gfd = NULL; char newinput, lastchar = 0; SizeT lines; for( SizeT i=0; iThrow("Could not open file for reading ");// + p0[i]); } lines = 0; while (gzread(gfd, &newinput, 1) == 1) { if (newinput == '\r') lines++; if (newinput == '\n') lines++; // if (newinput == '\r' && lastchar == '\n') length--; if (newinput == '\n' && lastchar == '\r') lines--; lastchar = newinput; } gzclose(gfd); if (lastchar != '\n' && lastchar != '\r') lines++; (*res)[ i] = lines; } return res; } // Result = FILE_READLINK(Path [, /ALLOW_NONEXISTENT] [, /ALLOW_NONSYMLINK] [, /NOEXPAND_PATH] ) BaseGDL* file_readlink( EnvT* e) { SizeT nParam=e->NParam( 1); DStringGDL* p0S = dynamic_cast(e->GetParDefined(0)); if( p0S == NULL) e->Throw( "String expression required in this context: "+e->GetParString(0)); static int noexpand_pathIx = e->KeywordIx( "NOEXPAND_PATH"); bool noexpand_path = e->KeywordSet(noexpand_pathIx); static int allow_nonexistIx = e->KeywordIx( "ALLOW_NONEXISTENT"); bool allow_nonexist = e->KeywordSet(allow_nonexistIx); static int allow_nonsymlinkIx = e->KeywordIx( "ALLOW_NONSYMLINK"); bool allow_nonsymlink = e->KeywordSet(allow_nonsymlinkIx); SizeT nPath = p0S->N_Elements(); DStringGDL* res = new DStringGDL(p0S->Dim(), BaseGDL::NOZERO); { for( SizeT r=0; rThrow(" Link path does not exist "+tmp); (*res)[r]=""; continue; } #ifdef _WIN32 DWORD dwattrib; int addlink = 0; fstat_win32(tmp, addlink, dwattrib); statStruct.st_mode |= addlink; #endif SizeT lenpath = statStruct.st_size; bool isASymLink = (S_ISLNK(statStruct.st_mode) != 0); if(!isASymLink ) { if(!allow_nonsymlink) e->Throw(" Path provided is not a symlink "+tmp); (*res)[r]=""; continue; } char *symlinkpath =const_cast (tmp.c_str()); char actualpath [PATH_MAX+1]; char *ptr; #ifndef _WIN32 // SizeT len; // doesn't work this way (opengroup doc): // if( len = readlink(symlinkpath, actualpath, PATH_MAX) != -1) // actualpath[len] = '\0'; if( readlink(symlinkpath, actualpath, PATH_MAX) != -1) actualpath[lenpath]='\0'; ptr = &actualpath[0]; #else ptr = realpath(symlinkpath, actualpath); for(int i=0;ptr[i] != 0;i++) if(ptr[i] == '\\') ptr[i] = '/'; #endif if( ptr != NULL ){ (*res)[r] =string(ptr); } else { (*res)[r] = tmp ; } } } return res; } } BaseGDL* file_info( EnvT* e) { SizeT nParam=e->NParam( 1); DStringGDL* p0S = dynamic_cast(e->GetParDefined(0)); if( p0S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(0)); bool noexpand_path = e->KeywordSet( "NOEXPAND_PATH"); DStructGDL* res = new DStructGDL( FindInStructList(structList, "FILE_INFO"), p0S->Rank() == 0 ? dimension(1) : p0S->Dim() ); static int tName = tName = res->Desc()->TagIndex("NAME"); static int tExists, tRead, tWrite, tExecute, tRegular, tDirectory, tBlockSpecial, tCharacterSpecial, tNamedPipe, tSetuid, tSetgid, tSocket, tStickyBit, tSymlink, tDanglingSymlink, tMode, tAtime, tCtime, tMtime, tSize; static int indices_known = false; // checking struct tag indices (once) if (!indices_known) { tExists = res->Desc()->TagIndex("EXISTS"); tRead = res->Desc()->TagIndex("READ"); tWrite = res->Desc()->TagIndex("WRITE"); tRegular = res->Desc()->TagIndex("REGULAR"); tDirectory = res->Desc()->TagIndex("DIRECTORY"); //#ifndef _MSC_VER tBlockSpecial = res->Desc()->TagIndex("BLOCK_SPECIAL"); tCharacterSpecial = res->Desc()->TagIndex("CHARACTER_SPECIAL"); tNamedPipe = res->Desc()->TagIndex("NAMED_PIPE"); tExecute = res->Desc()->TagIndex("EXECUTE"); //#ifndef _WIN32 tSetuid = res->Desc()->TagIndex("SETUID"); tSetgid = res->Desc()->TagIndex("SETGID"); //#else // tSetuid = res->Desc()->TagIndex("SYSTEM"); // tSetgid = res->Desc()->TagIndex("HIDDEN"); //#endif tSocket = res->Desc()->TagIndex("SOCKET"); tStickyBit = res->Desc()->TagIndex("STICKY_BIT"); tSymlink = res->Desc()->TagIndex("SYMLINK"); tDanglingSymlink = res->Desc()->TagIndex("DANGLING_SYMLINK"); tMode = res->Desc()->TagIndex("MODE"); //#endif tAtime = res->Desc()->TagIndex("ATIME"); tCtime = res->Desc()->TagIndex("CTIME"); tMtime = res->Desc()->TagIndex("MTIME"); tSize = res->Desc()->TagIndex("SIZE"); indices_known = true; } SizeT nEl = p0S->N_Elements(); for (SizeT f = 0; f < nEl; f++) { // NAME const char* actFile; string p0Sf = (*p0S)[f]; while(p0Sf.compare(0,1," ")==0) p0Sf.erase(p0Sf.begin()); // remove leading whitespaces if (!noexpand_path) { // p0Sf = (*p0S)[f]; WordExp(p0Sf); // Ilia2015 : about "|" : see 2 places (file_test() and file_info()) in "file.cpp", // and one place in "str.cpp" same label p0Sf=p0Sf.substr(0, p0Sf.find("|", 0)); //take the first file that corresponds the pattern. if( p0Sf.length() > 1 && p0Sf[ p0Sf.length()-1] == '/') p0Sf = p0Sf.substr(0,p0Sf.length()-1); } actFile = p0Sf.c_str(); *(res->GetTag(tName, f)) = DStringGDL(p0Sf); // stating the file (and moving on to the next file if failed) struct stat64 statStruct, statlink; int actStat = lstat64(actFile, &statStruct); int addlink = 0; #ifdef _WIN32 DWORD dwattrib; fstat_win32(actFile, addlink, dwattrib); statStruct.st_mode |= addlink; #endif bool isaDir = (S_ISDIR(statStruct.st_mode) != 0); bool isASymLink = S_ISLNK(statStruct.st_mode); SizeT lenpath = statStruct.st_size; // if a symlink, this is path size. if (isASymLink ) { addlink = stat64(actFile, &statlink); // preserving the original actStat isaDir = (S_ISDIR(statlink.st_mode) != 0); // This works ok here but fails in FileSearch } bool isADanglingSymLink = (addlink != 0 && isASymLink); // DANGLING_SYMLINK good place // SYMLINK if (isASymLink) { *(res->GetTag(tSymlink, f)) = DByteGDL(1); if( addlink != 0 ) *(res->GetTag(tDanglingSymlink, f)) = DByteGDL(1); } if( actStat != 0 ) continue; // EXISTS (would not reach here if stat failed) *(res->GetTag(tExists, f)) = DByteGDL(1); // READ, WRITE, EXECUTE *(res->GetTag(tRead, f)) = DByteGDL(access(actFile, R_OK) == 0); *(res->GetTag(tWrite, f)) = DByteGDL(access(actFile, W_OK) == 0); #ifndef _MSC_VER *(res->GetTag(tExecute, f)) = DByteGDL(access(actFile, X_OK) == 0); #endif // REGULAR, DIRECTORY, BLOCK_SPECIAL, CHARACTER_SPECIAL, NAMED_PIPE, SOCKET *(res->GetTag(tRegular, f)) = DByteGDL(S_ISREG( statStruct.st_mode) != 0); *(res->GetTag(tDirectory, f)) = DByteGDL(isaDir); #ifndef _WIN32 *(res->GetTag(tBlockSpecial, f)) = DByteGDL(S_ISBLK( statStruct.st_mode) != 0); *(res->GetTag(tCharacterSpecial, f)) = DByteGDL(S_ISCHR( statStruct.st_mode) != 0); *(res->GetTag(tNamedPipe, f)) = DByteGDL(S_ISFIFO(statStruct.st_mode) != 0); #ifndef __MINGW32__ *(res->GetTag(tSocket, f)) = DByteGDL(S_ISSOCK(statStruct.st_mode) != 0); #endif #endif // SETUID, SETGID, STICKY_BIT #ifndef _WIN32 *(res->GetTag(tSetuid, f)) = DByteGDL((S_ISUID & statStruct.st_mode) != 0); *(res->GetTag(tSetgid, f)) = DByteGDL((S_ISGID & statStruct.st_mode) != 0); *(res->GetTag(tStickyBit, f)) = DByteGDL((S_ISVTX & statStruct.st_mode) != 0); // MODE *(res->GetTag(tMode, f)) = DLongGDL( statStruct.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) ); #else if(tSetuid != 0) *(res->GetTag(tSetuid, f)) = DByteGDL( (FILE_ATTRIBUTE_SYSTEM & dwattrib) != 0); if(tSetgid != 0) *(res->GetTag(tSetgid, f)) = DByteGDL( (FILE_ATTRIBUTE_HIDDEN & dwattrib) != 0); *(res->GetTag(tMode, f)) = DLongGDL(dwattrib); #endif // ATIME, CTIME, MTIME *(res->GetTag(tAtime, f)) = DLong64GDL(statStruct.st_atime); *(res->GetTag(tCtime, f)) = DLong64GDL(statStruct.st_ctime); *(res->GetTag(tMtime, f)) = DLong64GDL(statStruct.st_mtime); // SIZE *(res->GetTag(tSize, f)) = DLong64GDL(statStruct.st_size); } return res; } // file_info void file_mkdir( EnvT* e) { // sanity checks SizeT nParam=e->NParam( 1); for (int i=0; i(e->GetParDefined(i)) == NULL) e->Throw( "All arguments must be string scalars/arrays, argument " + i2s(i+1) + " is: " + e->GetParString(i)); } static int noexpand_pathIx = e->KeywordIx( "NOEXPAND_PATH"); bool noexpand_path = e->KeywordSet( noexpand_pathIx); for (int i=0; i(e->GetParDefined(i)); for (int j=0; jN_Elements(); j++) { string tmp = (*pi)[j]; if (!noexpand_path) WordExp(tmp); #ifndef _WIN32 int status = mkdir(tmp.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); #else int status = mkdir(tmp.c_str()); #endif } } } // file_mkdir static void FileDelete( DString& name, bool verbose, bool recursive) { struct stat64 statStruct; int actStat = lstat64(name.c_str(), &statStruct); if(actStat != 0) { cout << " (status="< 2 && recursive) { dir = opendir( name.c_str()); while( (entry = readdir( dir)) != NULL) { DString entryStr( entry->d_name); if( entryStr == "." || entryStr == "..") continue; entryStr = name+"/"+entryStr; FileDelete( entryStr, verbose, recursive); } closedir(dir); } else if(nument > 2) { if(verbose) cout << " /RECURSIVE keyword needed to remove non-empty directory"<NParam( 1); static int noexpand_pathIx = e->KeywordIx( "NOEXPAND_PATH"); bool noexpand_path = e->KeywordSet( noexpand_pathIx); static int noexistokIx = e->KeywordIx( "ALLOW_NONEXISTENT"); bool noexistok = e->KeywordSet( noexistokIx); static int recursiveIx = e->KeywordIx( "RECURSIVE"); bool recursive = e->KeywordSet( recursiveIx); static int quietIx = e->KeywordIx( "QUIET"); bool quiet = e->KeywordSet( quietIx); static int verboseIx = e->KeywordIx( "VERBOSE"); bool verbose = e->KeywordSet( verboseIx); EnvBaseT* caller = e->Caller(); // trace_me = trace_arg(); // set trace for (int i=0; i(e->GetParDefined(i)); if (pi == NULL) { if (quiet) continue; // par = e->GetPar(i); cout << " file_delete: error parameter " << caller->GetString( e->GetPar(i),false) <<" is not a string "<GetString( e->GetPar(i),false); for (SizeT j=0; jN_Elements(); j++) { DString srctmp = (*pi)[j]; FileListT fileList; PathSearch( fileList, srctmp, noexpand_path ); for(SizeT k=0; k < fileList.size(); k++) { if(!noexpand_path) WordExp(fileList[k]); FileDelete( fileList[k], verbose, recursive); } } } } #include static int copy_basic(const char *source, const char *dest) { u_int64_t tsize; size_t size; struct stat64 statStruct; int status = stat64(source, &statStruct); if(status != 0) return status; time_t src_mtime = statStruct.st_mtime; // get mod time to stamp on dest tsize = statStruct.st_size; FILE* src = fopen(source, "rb"); // overwrite is prevented in calling procedure (unless /OVERWRITE) FILE* dst = fopen(dest, "w+b"); int doneyet = 0; int bufsize = BUFSIZ; // if(trace_me) printf(" copy_basic: %s to: %s size = %d \n",source,dest, tsize); if(tsize < BUFSIZ*16) { char buf[BUFSIZ]; while ((size = fread( buf, 1, BUFSIZ, src )) > 0) { // if( trace_me) printf(" 0:%d ",size ); fwrite( buf, 1, size, dst); } } else if( tsize < BUFSIZ*1024) { char buf[BUFSIZ*16]; while(1) { size = fread( buf, 1, BUFSIZ*16, src ); // if( trace_me) printf(" 1:%d ",size ); if (size <= 0) break; fwrite( buf, 1, size, dst); } } else { char buf[BUFSIZ*1024]; while ((size = fread( buf, 1, BUFSIZ*1024, src )) > 0) { // if( trace_me) printf(" 2:%d ",size ); fwrite( buf, 1, size, dst); } } // if( trace_me) printf(" done \n"); fclose(src); struct utimbuf times[2]; times[0].actime = statStruct.st_atime; times[1].actime = statStruct.st_atime; times[0].modtime = statStruct.st_mtime; times[1].modtime = statStruct.st_mtime; fclose(dst); status = utime( dest, times); int srcmode = statStruct.st_mode; status = lstat64(dest, &statStruct); if( statStruct.st_mode != srcmode) status = chmod(dest, srcmode); return status; } static void FileCopy( FileListT& fileList, const DString& destdir, bool overwrite, bool recursive=false, bool copy_symlink=false, bool verbose = true) { // trace_me = trace_arg(); DString destination; string srctmp; struct stat64 statStruct; SizeT nmove = fileList.size(); std::string PS = string("/"); #ifdef _WIN32 PS = string("\\"); #endif string bname, dname; for(SizeT isrc = 0; isrc < nmove; isrc++) { char actualpath [PATH_MAX+1]; const char* fileC = fileList[isrc].c_str(); #ifdef _WIN32 char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath( fileC ,drive,dir,fname,ext); bname = string(fname)+ext; #else char buf[ PATH_MAX+1]; strncpy(buf, fileC , PATH_MAX+1); bname = basename(buf); #endif // if(trace_me && (isrc ==0)) cout << // " fileCopy[0]: bname>"<< bname << // " destdir>"<< destdir << // " recursive?"<< recursive << std::endl; int actStat = lstat64(fileC , &statStruct); #ifdef _WIN32 DWORD dwattrib; int addlink = 0; fstat_win32(fileList[isrc], addlink, dwattrib); statStruct.st_mode |= addlink; #endif bool isalink = S_ISLNK(statStruct.st_mode); bool isaDir = false; SizeT lenpath= statStruct.st_size; if(isalink) actStat = stat64(fileC , &statStruct); int srcmode = statStruct.st_mode; if(actStat == 0) isaDir = (S_ISDIR(srcmode) != 0); if(!isaDir) { destination = destdir + PS + bname; int dstStat = lstat64(destination.c_str(), &statStruct); int result = 1; if(dstStat != 0 || overwrite) { if( isalink && copy_symlink) { if(verbose) cout << " FILE_COPY: symlink " << fileList[isrc]; #ifndef _WIN32 if(readlink(fileC, actualpath, PATH_MAX) != -1) { actualpath[lenpath] = '\0'; result = symlink(actualpath,destination.c_str()); } if(verbose) printf(" to %s ->%s \n",destination.c_str(),actualpath); #else if(verbose) cout << " detected for _WIN32. no /copy_symlink option ! "<NParam( 2); DStringGDL* p0S = dynamic_cast(e->GetParDefined(0)); if( p0S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(0)); DStringGDL* p1S = dynamic_cast(e->GetParDefined(1)); if( p1S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(1)); struct stat64 statStruct, srcStruct; // trace_me = trace_arg(); bool recursive = e->KeywordSet( "RECURSIVE"); bool noexpand_path = e->KeywordSet( "NOEXPAND_PATH"); bool copy_symlink = e->KeywordSet( "COPY_SYMLINK"); bool allow_same = e->KeywordSet( "ALLOW_SAME"); bool overwrite = e->KeywordSet( "OVERWRITE"); bool require_directory = e->KeywordSet( "REQUIRE_DIRECTORY"); bool verbose = e->KeywordSet( "VERBOSE"); int nsrc = p0S->N_Elements(); int ndest = p1S->N_Elements(); string dsttmp = string(""); string srctmp = string(""); string dstdir = string(""); string cwd = GetCWD(); if(ndest > 0) dstdir = (*p1S)[0]; // trace_me = trace_arg(); /* if(trace_me) { string test = dstdir; if(!noexpand_path) WordExp(test); std::cout << " file_copy:dstdir=<" << dstdir <<"> WordExp("")=<" << test <<">"< 0) srctmp = (*p0S)[0]; bool dest_is_directory= false; // when parameter 2 is an existing directory. int actStat, result, dstStat; if(ndest == 1) { // if(trace_me) std::cout << " dstdir: " << dstdir; size_t dlen = dstdir.length(); if( dlen > 0) { if( dstdir[0] == '.' ) { if(dlen == 1) dstdir = GetCWD(); else if (dstdir[1] == '/') dstdir = GetCWD() + dstdir.substr(1); #ifdef _WIN32 else if (dstdir[1] == '\\') dstdir = GetCWD() + dstdir.substr(1); #endif else if (dlen >= 2 && dstdir[1] =='.') { if( dlen == 2) dstdir = Dirname(GetCWD()); else if (dstdir[2] == '/') dstdir = Dirname(GetCWD()) + dstdir.substr(2); #ifdef _WIN32 else if (dstdir[2] == '\\') dstdir = Dirname(GetCWD()) + dstdir.substr(2); #endif } // (dlen >= 2 && dstdir[1]='.') }// dstdir[0] == '.' // Now trim any marks off the trailing string // if(trace_me) std::cout << " dstdir: " << dstdir; size_t pp = dstdir.rfind( "/"); //remove and back if last if (pp!=string::npos && pp==dstdir.size()-1) dstdir.erase(pp); #ifdef _WIN32 pp = dstdir.rfind("\\"); if (pp!=string::npos && pp==dstdir.size()-1) dstdir.erase(pp); #endif // if(trace_me) std::cout << " dstdir: " << dstdir // << std::endl; } // dlen > 0 actStat = lstat64(dstdir.c_str(), &statStruct); if(actStat == 0) { dest_is_directory = (S_ISDIR(statStruct.st_mode) != 0); if(require_directory && !dest_is_directory) e->Throw(" destination (arg #2) is not a directory, /REQUIRE_DIRECTORY specified"); } } // ndest == 1 // if(trace_me) { // printf(" file_copy: nsrc= %d , 1st=%s ",nsrc,srctmp.c_str()); // printf("\n ... ndest= %d dstdir = %s \n",ndest, dstdir.c_str()); // } if(nsrc != ndest && !dest_is_directory) e->Throw(" destination array must be same size as source "); for(int k=0; k < nsrc; k++) { srctmp = (*p0S)[k]; FileListT fileList; PathSearch( fileList, srctmp, noexpand_path); SizeT nmove=fileList.size(); // if( trace_me) // printf(" file_copy: srctmp=%s ; nmove= %d",srctmp.c_str(),nmove); if(nmove == 0) { cout << " FILE_COPY: Invalid source file specified:"+srctmp< 1) { cout << " FILE_COPY: target for "<%s \n", dsttmp.c_str(),actualpath); } #else if(verbose) cout << " detected. WIN32 copy_symlink doesn't work"<GetParString(0)); DStringGDL* p1S = dynamic_cast(e->GetParDefined(1)); if( p1S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(1)); string srctmp, dsttmp, dstdir; struct stat64 statStruct; bool noexpand_path = e->KeywordSet( "NOEXPAND_PATH"); bool allow_same = e->KeywordSet( "ALLOW_SAME"); bool hardlink = e->KeywordSet( "HARDLINK"); bool verbose = e->KeywordSet( "VERBOSE"); int nsrc = p0S->N_Elements(); int ndest = p1S->N_Elements(); bool dest_is_directory= false; int actStat, result, dststat; if(ndest == 1) { dstdir = (*p1S)[0]; if(!noexpand_path) WordExp(dstdir); actStat = lstat64(dstdir.c_str(), &statStruct); if(actStat == 0) { dest_is_directory = (S_ISDIR(statStruct.st_mode) != 0); if(dest_is_directory) AppendIfNeeded(dstdir,"/"); else e->Throw(" destination (arg #2) is not a directory, /REQUIRE_DIRECTORY specified"); } } if(nsrc != ndest && !dest_is_directory) e->Throw(" destination array must be same size as source "); for(int k=0; k < nsrc; k++) { srctmp = (*p0S)[k]; FileListT fileList; PathSearch( fileList, srctmp, noexpand_path); SizeT nmove=fileList.size(); if(nmove == 0) { cout << " FILE_LINK: Invalid source file to link:"+srctmp< 1) { cout << " FILE_LINK: target for "<NParam( 2); DStringGDL* p0S = dynamic_cast(e->GetParDefined(0)); if( p0S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(0)); DStringGDL* p1S = dynamic_cast(e->GetParDefined(1)); if( p1S == NULL) e->Throw( "String expression required in this context: "+ e->GetParString(1)); string srctmp, dsttmp, dstdir; struct stat64 statStruct; bool noexpand_path = e->KeywordSet( "NOEXPAND_PATH"); bool allow_same = e->KeywordSet( "ALLOW_SAME"); bool overwrite = e->KeywordSet( "OVERWRITE"); bool require_directory = e->KeywordSet( "REQUIRE_DIRECTORY"); bool verbose = e->KeywordSet( "VERBOSE"); int nsrc = p0S->N_Elements(); int ndest = p1S->N_Elements(); if(ndest > 0) dstdir = (*p1S)[0]; if(!noexpand_path) WordExp(dstdir); if( dstdir[0] == '~') { char* homeDir = getenv( "HOME"); if( homeDir == NULL) homeDir = getenv("HOMEPATH"); if( homeDir != NULL) dstdir = string( homeDir) + "/" + dstdir.substr(1); } bool dest_is_directory= false; int actStat, result, dststat; if(ndest == 1) { size_t dlen = dstdir.length(); if( dlen > 0) { if( dstdir[0] == '.' ) { if(dlen == 1) dstdir = GetCWD(); else if (dstdir[1] == '/') dstdir = GetCWD() + dstdir.substr(1); #ifdef _WIN32 else if (dstdir[1] == '\\') dstdir = GetCWD() + dstdir.substr(1); #endif else if (dlen >= 2 && dstdir[1] =='.') { if( dlen == 2) dstdir = Dirname(GetCWD()); else if (dstdir[2] == '/') dstdir = Dirname(GetCWD()) + dstdir.substr(2); #ifdef _WIN32 else if (dstdir[2] == '\\') dstdir = Dirname(GetCWD()) + dstdir.substr(2); #endif } // (dlen >= 2 && dstdir[1]='.') }// dstdir[0] == '.' size_t pp = dstdir.rfind( "/"); //remove and back if last if (pp!=string::npos && pp==dstdir.size()-1) dstdir.erase(pp); #ifdef _WIN32 pp = dstdir.rfind("\\"); if (pp!=string::npos && pp==dstdir.size()-1) dstdir.erase(pp); #endif } // dlen > 0 actStat = lstat64(dstdir.c_str(), &statStruct); if(actStat == 0) { dest_is_directory = (S_ISDIR(statStruct.st_mode) != 0); if(require_directory && !dest_is_directory) e->Throw(" destination (arg #2) is not a directory, /REQUIRE_DIRECTORY specified"); if(dest_is_directory) AppendIfNeeded(dstdir,"/"); } } // (ndest == 1) if(nsrc != ndest && !dest_is_directory) { // Throw replaced by do-nothing & print. // e->Throw(" destination array must be same size as source "); cout << " FILE_MOVE: destination array must be same size as source " << std::endl; return; } for(int k=0; k < nsrc; k++) { srctmp = (*p0S)[k]; FileListT fileList; PathSearch( fileList, srctmp, noexpand_path ); SizeT nmove=fileList.size(); if(nmove == 0) { cout << " FILE_MOVE: Invalid source file to move:"+srctmp< 1) { cout << " FILE_MOVE: target for "<getType()); CommonAST::setText( t->getText()); w = t->w; d = t->d; rep = t->rep; } gdl-0.9.9/src/fmtnode.hpp000066400000000000000000000070641340051421000152300ustar00rootroot00000000000000/*************************************************************************** FMTNode.hpp - node for formatted io processing ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef FMTNode_hpp__ #define FMTNode_hpp__ #include "typedefs.hpp" #include "FMTTokenTypes.hpp" #include //ANTLR_USING_NAMESPACE(std) //ANTLR_USING_NAMESPACE(antlr) class FMTNode; typedef antlr::ASTRefCount RefFMTNode; class FMTNode : public antlr::CommonAST { public: ~FMTNode(); FMTNode(): CommonAST(), down(), right(), w(-1), d(-1), rep(1), code(0) { } FMTNode( antlr::RefToken t) : CommonAST(t), down(), right(), w(-1), d(-1), rep(1), code(0) { } void initialize(int t, const std::string& txt) { CommonAST::setType(t); CommonAST::setText(txt); } // used by FMTNodeFactory void initialize( RefFMTNode t ); // we deal only with RefFMTNode here void initialize( antlr::RefAST t ) { // CommonAST::initialize(t); initialize(static_cast(t)); } void initialize( antlr::RefToken t ) { CommonAST::initialize(t); } void setText(const std::string& txt) { CommonAST::setText(txt); } void setType(int type) { CommonAST::setType(type); } void addChild( RefFMTNode c ) { BaseAST::addChild( static_cast(c) ); } static antlr::RefAST factory() { antlr::RefAST ret = static_cast(RefFMTNode(new FMTNode)); return ret; } // RefFMTNode getFirstChild() const // { // return static_cast(BaseAST::getFirstChild()); // } // RefFMTNode getNextSibling() const // { // return static_cast(BaseAST::getNextSibling()); // } void setW( const int w_) { w=w_; } int getW() { return w; } void setD( const int d_) { d=d_; } int getD() { return d; } void setRep( const int rep_) { rep=rep_; } int getRep() { return rep; } typedef enum codeFlags_ { fmtALIGN_LEFT = 1 ,fmtSHOWPOS = 2 ,fmtPAD = 4 ,fmtUPPER = 8 } codeFlags; void setALignLeft() { code |= fmtALIGN_LEFT; } void setShowSign() { code |= fmtSHOWPOS; } void setUpper() { code |= fmtUPPER; } void setPadding() { code |= fmtPAD; } int getCode() { return code; } private: RefFMTNode down; RefFMTNode right; int w; int d; int rep; int code; // bitfield for alignment (bit 0 set: left-align unset: right-align) (bit 1 set: '+' code) (bit 2 set: use fill character) // private: // // forbid usage of these // FMTNode& operator=( const FMTNode& r) // { return *this;} // make compiler shut up // FMTNode( const FMTNode& cp) // {} }; #endif gdl-0.9.9/src/format.g000066400000000000000000000263751340051421000145310ustar00rootroot00000000000000/* ************************************************************************* format.g - parser for GDL format strings ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@hotmail.com ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ header "pre_include_cpp" { #include "includefirst.hpp" } header { #include #include #include "fmtnode.hpp" #include "CFMTLexer.hpp" #include //using namespace antlr; } options { language="Cpp"; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the format Parser ********************************************* class FMTParser extends Parser; options { importVocab = CFMT; // use vocab generated by clexer exportVocab = FMT; // use vocab generated by lexer buildAST = true; ASTLabelType = "RefFMTNode"; k=1; // defaultErrorHandler = true; defaultErrorHandler = false; } tokens { FORMAT; } { // class extensions } format [ int repeat] // mark last format for format reversion : LBRACE! qfq (COMMA! qfq)* RBRACE! { #format = #( [FORMAT,"FORMAT"], #format); #format->setRep( repeat); } ; qfq : q (f q)? ; q! { int n1 = 0; } : (SLASH { n1++;})* { if( n1 > 0) { #q = #([SLASH,"/"]); #q->setRep( n1); } } ; f_csubcode // note: IDL doesn't allow hollerith strings inside C() { int n1; } : STRING // just write it out (H strings are handled in the scanner) | cstring | tl:TL n1=nn { #tl->setW( n1);} | tr:TR n1=nn { #tr->setW( n1);} ; cstring : (s:CSTR { #s->setType( STRING);} | cformat)+ // : (CSTR | cformat)+ ; cformat { int w = 0; int infos[4]={0,0,0,0}; int d = -1; } : ( (PM!|MP!) {infos[1]=1;infos[2]=1;} | (PLUS! {infos[1]=1;}) | (MOINS! {infos[2]=1;}) )? (cnnf [infos] { w=infos[0]; } (CDOT! d=cnn)?)? ( c:CD { if (infos[1])#c->setShowSign(); if (infos[2])#c->setALignLeft(); if (infos[3])#c->setPadding(); #c->setW( w); #c->setD( d); #c->setType( I); } | se:CSE { if (infos[1])#se->setShowSign(); if (infos[2])#se->setALignLeft(); if (infos[3])#se->setPadding(); #se->setW( w); #se->setD( d); #se->setType( SE); } | e:CE { if (infos[1])#e->setShowSign(); if (infos[2])#e->setALignLeft(); if (infos[3])#e->setPadding(); #e->setW( w); #e->setD( d); #e->setType( E); } | i:CI { if (infos[1])#i->setShowSign(); if (infos[2])#i->setALignLeft(); if (infos[3])#i->setPadding(); #i->setW( w); #i->setD( d); #i->setType( I); } | ff:CF { if (infos[1])#ff->setShowSign(); if (infos[2])#ff->setALignLeft(); if (infos[3])#ff->setPadding(); #ff->setW( w); #ff->setD( d); #ff->setType( F); } | sg:CSG { if (infos[1])#sg->setShowSign(); if (infos[2])#sg->setALignLeft(); if (infos[3])#sg->setPadding(); #sg->setW( w); #sg->setD( d); #sg->setType( SG);} | g:CG { if (infos[1])#g->setShowSign(); if (infos[2])#g->setALignLeft(); if (infos[3])#g->setPadding(); #g->setW( w); #g->setD( d); #g->setType( G); } | o:CO { if (infos[1])#o->setShowSign(); if (infos[2])#o->setALignLeft(); if (infos[3])#o->setPadding(); #o->setW( w); #o->setD( d); #o->setType( O); } | b:CB { if (infos[1])#b->setShowSign(); if (infos[2])#b->setALignLeft(); if (infos[3])#b->setPadding(); #b->setW( w); #b->setD( d); #b->setType( B); } | x:CX { if (infos[1])#x->setShowSign(); if (infos[2])#x->setALignLeft(); if (infos[3])#x->setPadding(); #x->setW( w); #x->setD( d); #x->setType( Z); } | z:CZ { if (infos[1])#z->setShowSign(); if (infos[2])#z->setALignLeft(); if (infos[3])#z->setPadding(); #z->setW( w); #z->setD( d); #z->setType( Z); } | s:CS { if (infos[1])#s->setShowSign(); if (infos[2])#s->setALignLeft(); if (infos[3])#s->setPadding(); #s->setW( w); #s->setType( A);} ) ; // no nodes for cnumbers cnn! returns[ int n] : num:CNUMBER { std::istringstream s(#num->getText()); s >> n; } ; // no nodes for cnumbers with zero padding cnnf! [int *infos] //returns[ int *infos] : num:CNUMBER { char c; std::istringstream s(#num->getText()); c=s.get(); s.putback(c); s >> infos[0]; if (c == '0') infos[3]=-1;; } ; f { int n1; } : TERM | NONL | Q | t:T n1=nn { #t->setW( n1);} | f_csubcode | rep_fmt[ 1] | n1=nn (rep_fmt[ n1] | x:X { #x->setW( n1);}) | xx:X { #xx->setW( 1);} ; rep_fmt [ int repeat] { int n1; } : format[ repeat] | a:A (n1=nnf [#a] { #a->setW( n1);})? { #a->setRep( repeat);} | ff:F w_d [ #ff] {#ff->setRep( repeat);} // F and D are the same -> D->F | d:D w_d [ #d] { #d->setRep( repeat); #d->setText("f"); #d->setType(F);} | e:E w_d_e[ #e] { #e->setRep( repeat);} | se:SE w_d_e[ #se] { #se->setRep( repeat);} | g:G w_d_e[ #g] { #g->setRep( repeat);} | sg:SG w_d_e[ #sg] { #sg->setRep( repeat);} | i:I w_d [ #i] { #i->setRep( repeat);} | o:O w_d [ #o] { #o->setRep( repeat);} | b:B w_d [ #b] { #b->setRep( repeat);} | z:Z w_d [ #z] { #z->setRep( repeat);} | zz:ZZ w_d [ #zz] { #zz->setRep( repeat);} | c:C^ LBRACE! calendar_string RBRACE! { #c->setRep( repeat);} ; calendar_string : ( (calendar_code (COMMA! calendar_code)*) | ) ; calendar_code { int n1; } : c1:CMOA (n1=nn { #c1->setW( n1);})? | c2:CMoA (n1=nn { #c2->setW( n1);})? | c3:CmoA (n1=nn { #c3->setW( n1);})? | c4:CHI w_d[ #c4] | c5:ChI w_d[ #c5] | c6:CDWA (n1=nn { #c6->setW( n1);})? | c7:CDwA (n1=nn { #c7->setW( n1);})? | c8:CdwA (n1=nn { #c8->setW( n1);})? | c9:CAPA (n1=nn { #c9->setW( n1);})? | c10:CApA (n1=nn { #c10->setW( n1);})? | c11:CapA (n1=nn { #c11->setW( n1);})? | c12:CMOI w_d[ #c12] | c13:CDI w_d[ #c13] | c14:CYI w_d[ #c14] | c15:CMI w_d[ #c15] | c16:CSI w_d[ #c16] | c17:CSF w_d[ #c17] | (n1=nn|) x:X { #x->setW( n1);} | f_csubcode ; // no nodes for numbers nn! returns[ int n] { int sgn=1; } : num:NUMBER { std::istringstream s(#num->getText()); s >> n; } ; // no nodes for numbers with zero padding nnf! [ RefFMTNode fNode] returns[ int n=-1] : ( ( (PM|MP) { fNode->setShowSign(); fNode->setALignLeft(); } | PLUS {fNode->setShowSign();} | MOINS {fNode->setALignLeft();} ) )? ( num:NUMBER //as we are left-aligned, 0 leading (padding) can be read as number since there will be no 0 padding. { std::istringstream s(#num->getText()); char c = s.get(); char next = s.peek(); s.putback(c); s >> n; if (c == '0') fNode->setPadding(); } )? ; w_d! [ RefFMTNode fNode] { int n1=-1, n2=-1; fNode->setW( -1); fNode->setD( -1); } : (n1=nnf[ fNode] { fNode->setW( n1);} (DOT n2=nn { fNode->setD( n2);} )?)? ; w_d_e! [ RefFMTNode fNode] : (options { greedy=true;}: w_d[ fNode] ((E|SE) ignored:NUMBER { int n=0; std::istringstream s(#ignored->getText()); s >> n; //does not work (loops probably at format_reversion) if (n < 0 || n > 255) throw GDLException("Value is out of allowed range (0 - 255)."); } )?)? ; // the Format Lexer ********************************************* class FMTLexer extends Lexer; options { charVocabulary = '\3'..'\377'; caseSensitive=true ; testLiterals =true; caseSensitiveLiterals=false; // importVocab = CFMT; // use vocab generated by clexer exportVocab = FMT; k=4; defaultErrorHandler = false; // defaultErrorHandler = true; // analyzerDebug=true; } // the reserved words tokens { TL="tl"; TR="tr"; } { private: antlr::TokenStreamSelector* selector; CFMTLexer* cLexer; public: void SetSelector( antlr::TokenStreamSelector& s) { selector = &s; } void SetCLexer( CFMTLexer& l) { cLexer = &l; } } STRING // : '\"'! (~('\"'|'\r'|'\n')| '\"' '\"'! )* '\"'! // | '\''! (~('\''|'\r'|'\n')| '\'' '\''! )* '\''! : '\"'! (~('\"')| '\"' '\"'! )* '\"'! | '\''! (~('\'')| '\'' '\''! )* '\''! ; CSTRING! : '%' '\"' { cLexer->DoubleQuotes( true); selector->push( cLexer); selector->retry();} | '%' '\'' { cLexer->DoubleQuotes( false); selector->push( cLexer); selector->retry();} ; LBRACE: '('; RBRACE: ')'; SLASH: '/'; COMMA: ','; A:('A'|'a'); TERM:':'; NONL:'$'; F:('f'|'F'); D:('d'|'D'); E:('E'); SE:('e'); G:('G'); SG:('g'); I:('i'|'I'); O:('o'|'O'); B:('b'|'B'); Z:('Z'); ZZ:('z'); // lower case output Q:('q'|'Q'); H:('h'|'H'); T:('t'|'T'); L:('l'|'L'); R:('r'|'R'); X:('x'|'X'); C:('c'|'C'); CMOA: ( 'C' 'M' 'O' 'A'); CMoA: ( 'C' 'M' 'o' 'A'); CmoA: ( 'C' 'm' 'o' 'A'); CMOI: ( 'C' 'M' 'O' 'I'); CDI: ( 'C' 'D' 'I'); CMI: ( 'C' 'M' 'I'); CYI: ( 'C' 'Y' 'I'); CSI: ( 'C' 'S' 'I'); CSF: ( 'C' 'S' 'F'); CHI: ( 'C' 'H' 'I'); ChI: ( 'C' 'h' 'I'); CDWA: ( 'C' 'D' 'W' 'A'); CDwA: ( 'C' 'D' 'w' 'A'); CdwA: ( 'C' 'd' 'w' 'A'); CAPA: ( 'C' 'A' 'P' 'A'); CApA: ( 'C' 'A' 'p' 'A'); CapA: ( 'C' 'a' 'p' 'A'); PERCENT:'%'; DOT:'.'; PM: ('+' '-'); MP: ('-' '+'); PLUS: '+'; MOINS: '-'; protected W // : ( '\003'..'\010' | '\t' | '\r' | '\013' | '\f' | '\016'.. '\037' | ' ' ) : (' '| '\t') ; WHITESPACE : (W)+ { _ttype=antlr::Token::SKIP; } ; protected DIGITS : ('0'..'9')+ ; protected CHAR: ('\003'..'\377'); NUMBER // handles hollerith strings also { SizeT n = -1; SizeT i = 0; } : ( num:DIGITS ( { $setType(STRING); std::istringstream s(num->getText()); s >> n; $setText(""); // clear string (remove number) } H! ( { // init action gets executed even in guessing mode if( i == n ) break; i++; // count chars here so that guessing mode works }: // ":" makes it an init action CHAR )+ )? )? ;gdl-0.9.9/src/format.in.g000066400000000000000000000465241340051421000151340ustar00rootroot00000000000000/* ************************************************************************* format.in.g - interpreter for formatted input ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@hotmail.com ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ header "pre_include_cpp" { #include "includefirst.hpp" } header "post_include_cpp" { // gets inserted after the antlr generated includes in the cpp file } header { #include #include #include "envt.hpp" #include "io.hpp" // StreamInfo() #include "fmtnode.hpp" //#include "getfmtast.hpp" // for FMTNodeFactory; } options { language="Cpp"; // genHashLines = true; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the format Parser ********************************************* class FMTIn extends TreeParser; options { importVocab = FMT; // use vocab generated by format lexer buildAST = false; ASTLabelType = "RefFMTNode"; defaultErrorHandler = false; // defaultErrorHandler = true; // codeGenBitsetTestThreshold=999; // codeGenMakeSwitchThreshold=1; } { public: FMTIn( RefFMTNode fmt, std::istream* is_, EnvT* e_, int parOffset, BaseGDL* prompt_) : antlr::TreeParser(), noPrompt( true), ioss(), is(is_), prompt( prompt_), e( e_), nextParIx( parOffset), valIx(0), termFlag(false), nElements(0) { nParam = e->NParam(); NextPar(); format( fmt); SizeT nextParIxComp = nextParIx; SizeT valIxComp = valIx; // format reversion while( actPar != NULL) { format_reversion( reversionAnker); if( (nextParIx == nextParIxComp) && (valIx == valIxComp)) throw GDLException("Infinite format loop detected."); } } private: void NextPar() { valIx = 0; restart: if( nextParIx < nParam) { BaseGDL** par = &e->GetPar( nextParIx); if( (*par) != NULL) { if( e->GlobalPar( nextParIx)) { // defined global actPar = *par; nElements = actPar->ToTransfer(); } else { // defined local if( prompt != NULL) { // prompt keyword there -> error throw GDLException( e->CallingNode(), "Expression must be named variable " "in this context: "+e->GetParString( nextParIx)); } else { // prompt not there -> put out or ignore if( is == &std::cin) { (*par)->ToStream( std::cout); std::cout << std::flush; noPrompt = false; } nextParIx++; goto restart; } } } else { // undefined if( e->LocalPar( nextParIx)) throw GDLException( e->CallingNode(), "Internal error: Input: UNDEF is local."); nElements = 1; (*par) = new DFloatGDL( 0.0); actPar = *par; } } else { actPar = NULL; nElements = 0; } nextParIx++; } void NextVal( SizeT n=1) { // std::cout << "NextVal("<= nElements) NextPar(); // std::cout << "valIx: " << valIx << std::endl; // std::cout << "nElements: " << nElements << std::endl; } void GetLine() { if( is == &std::cin && noPrompt) { if( prompt != NULL) { prompt->ToStream( std::cout); std::cout << std::flush; } else { std::cout << ": " << std::flush; } } else { if( is->eof()) throw GDLIOException( e->CallingNode(), "End of file encountered. "+ StreamInfo( is)); } // std::string retStr; // getline( *is, retStr); // ioss.str( retStr); std::string initStr(""); ioss.str( initStr); // ioss.seekg( 0); // ioss.seekp( 0); ioss.rdbuf()->pubseekpos(0,std::ios_base::in | std::ios_base::out); ioss.clear(); is->get( *ioss.rdbuf()); if ( (is->rdstate() & std::ifstream::failbit ) != 0 ) { if ( (is->rdstate() & std::ifstream::eofbit ) != 0 ) throw GDLException( e->CallingNode(), "End of file encountered. "+ StreamInfo( is)); if ( (is->rdstate() & std::ifstream::badbit ) != 0 ) throw GDLException( e->CallingNode(), "Error reading line. "+ StreamInfo( is)); is->clear(); is->get(); // remove delimiter return; // assuming rdbuf == "" } if( !is->good()) { if( !is->eof()) throw GDLException( e->CallingNode(), "Error 1 reading data. "+ StreamInfo( is)); } if( !is->eof()) is->get(); // remove delimiter //*** // std::cout << "FMTIn::GetLine: " << ioss.str() << "." << std::endl; // std::cout << "tellg: " << ioss.tellg() << std::endl; } bool noPrompt; std::stringstream ioss; std::istream* is; BaseGDL* prompt; EnvT* e; SizeT nextParIx; SizeT valIx; bool termFlag; SizeT nParam; BaseGDL* actPar; SizeT nElements; RefFMTNode reversionAnker; } format : #(fmt:FORMAT { goto realCode; } // fool ANTLR q (f q)+ // this gets never executed { realCode: reversionAnker = #fmt; RefFMTNode blk = _t; // q (f q)+ // as later format_recursive is used, this loop only // loops once (ie. could be eliminated - left here in // case of later changes) for( int r = #fmt->getRep(); r > 0; r--) { GetLine(); q( blk); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL && termFlag) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition if( actPar == NULL && termFlag) break; } } ) ; format_recursive // don't read in a new line : #(fmt:FORMAT { goto realCode; } // fool ANTLR q (f q)+ // this gets never executed { realCode: reversionAnker = #fmt; RefFMTNode blk = _t; // q (f q)+ for( int r = #fmt->getRep(); r > 0; r--) { // GetLine(); // the difference to format q( blk); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL && termFlag) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition if( actPar == NULL && termFlag) break; } } ) ; format_reversion : format // use the non-recursive format here { goto realCode; } q (f q)* // this gets never executed { realCode: q( _t); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: } ; q : (s:SLASH { for( int r=s->getRep(); r > 0; r--) GetLine(); } )? ; f_csubcode // note: IDL doesn't allow hollerith strings inside C() : s:STRING { SizeT actP = ioss.tellg(); int strlen = s->getText().length(); ioss.seekg( actP + strlen); } | tl:TL { SizeT actP = ioss.tellg(); int tlVal = tl->getW(); if( tlVal > actP) ioss.seekg( 0); else ioss.seekg( actP - tlVal); } | tr:TR { int tlVal = tl->getW(); ioss.seekg( tlVal, std::ios_base::cur); } ; f { RefFMTNode actNode; } : TERM { termFlag = true; } | NONL // ignored on input | Q { SizeT nLeft = ioss.rdbuf()->in_avail(); std::istringstream iossTmp( i2s( nLeft)); int r = 1; do { SizeT tCount = actPar->IFmtA( &iossTmp, valIx, r, 0); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | t:T { int tVal = t->getW(); assert( tVal >= 1); ioss.seekg( tVal-1, std::ios_base::beg); } | f_csubcode | x | format_recursive // following are repeatable formats | a:A { if( actPar == NULL) break; int r = a->getRep(); int w = a->getW(); do { SizeT tCount = actPar->IFmtA( &ioss, valIx, r, w); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | ( ff:F { actNode = ff;} | ee:E { actNode = ee;} | se:SE { actNode = se;} | g:G { actNode = g;} | sg:SG { actNode = sg;} // | d:D // D is transformed to F ) { if( actPar == NULL) break; int r = actNode->getRep(); int w = actNode->getW(); // if( w <= 0) // if( actPar->Type() == FLOAT) // w = 15; // set default // else // w = 25; do { SizeT tCount = actPar->IFmtF( &ioss, valIx, r, w); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | i:I { if( actPar == NULL) break; int r = i->getRep(); int w = i->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::DEC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | o:O { if( actPar == NULL) break; int r = o->getRep(); int w = o->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::OCT); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | b:B { if( actPar == NULL) break; int r = b->getRep(); int w = b->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::BIN); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | ( z:Z { actNode = z;} | zz:ZZ { actNode = zz;} ) { if( actPar == NULL) break; int r = actNode->getRep(); int w = actNode->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::HEX); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | ( #( c:C { int r = c->getRep(); if (r<1) r=1; if( actPar == NULL) break; } ( (calendar_code[r])+ |{ if( actPar == NULL) break; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, 24, BaseGDL::DEFAULT); } ) { SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, 0, BaseGDL::COMPUTE); NextVal(tCount); if( actPar == NULL) break; } ) // exception // catch [ antlr::RecognitionException& e] {std::cerr<getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMOA); } | c2:CMoA { int w = c2->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMoA); } | c3:CmoA { int w = c3->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CmoA); } | c4:CHI { int w = c4->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CHI); } | c5:ChI { int w = c5->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::ChI); } | c6:CDWA { int w = c6->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CDWA); } | c7:CDwA { int w = c7->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CDwA); } | c8:CdwA { int w = c8->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CdwA); } | c9:CAPA { int w = c9->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CAPA); } | c10:CApA { int w = c10->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CApA); } | c11:CapA { int w = c11->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CapA); } | c12:CMOI { int w = c12->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMOI); } | c13:CDI { int w = c13->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CDI); } | c14:CYI { int w = c14->getW(); if(w<1) w=4; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CYI); } | c15:CMI { int w = c15->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMI); } | c16:CSI { int w = c16->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CSI); } | c17:CSF { int w = c17->getW(); SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CSF); } | x | f_csubcode ; x : tl:X { if( _t != static_cast(antlr::nullAST)) { int tlVal = #tl->getW();if (tlVal<1) tlVal=1; ioss.seekg( tlVal, std::ios_base::cur); } } ; gdl-0.9.9/src/format.out.g000066400000000000000000000502711340051421000153270ustar00rootroot00000000000000/* ************************************************************************* format.out.g - interpreter for formatted output ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@hotmail.com ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ header "pre_include_cpp" { #include "includefirst.hpp" } header "post_include_cpp" { // gets inserted after the antlr generated includes in the cpp file } header { #include #include //***test #include "print_tree.hpp" #include "envt.hpp" #include "fmtnode.hpp" //#include "getfmtast.hpp" // for FMTNodeFactory; #include "gdljournal.hpp" } options { language="Cpp"; // genHashLines = true; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the format Parser ********************************************* class FMTOut extends TreeParser; options { importVocab = FMT; // use vocab generated by format lexer buildAST = false; ASTLabelType = "RefFMTNode"; defaultErrorHandler = false; // defaultErrorHandler = true; // codeGenBitsetTestThreshold=999; // codeGenMakeSwitchThreshold=1; } { public: FMTOut( RefFMTNode fmt, std::ostream* os_, EnvT* e_, int parOffset) : antlr::TreeParser(), os(os_), e( e_), nextParIx( parOffset), valIx(0), termFlag(false), nonlFlag(false), nElements(0) { std::ostringstream* osLocal; std::unique_ptr osLocalGuard; //if( *os_ == std::cout) // SA: this did not work with win32 if( os_->rdbuf() == std::cout.rdbuf()) { // e.g. print, 1, f='(A)' osLocal = new std::ostringstream(); osLocalGuard.reset( osLocal); os = osLocal; } else { // e.g. print, string(1, f='(A)') os = os_; } nParam = e->NParam(); NextPar(); GDLStream* j = lib::get_journal(); if( j != NULL && j->OStream().rdbuf() == os->rdbuf()) (*os) << lib::JOURNALCOMMENT; format( fmt); SizeT nextParIxComp = nextParIx; SizeT valIxComp = valIx; // format reversion while( actPar != NULL) { (*os) << '\n'; if( j != NULL && j->OStream().rdbuf() == os->rdbuf()) (*os) << lib::JOURNALCOMMENT; format_reversion( reversionAnker); if( (nextParIx == nextParIxComp) && (valIx == valIxComp)) throw GDLException("Infinite format loop detected."); } os->seekp( 0, std::ios_base::end); if( !nonlFlag) { (*os) << '\n'; } (*os) << std::flush; if( os_->rdbuf() == std::cout.rdbuf()) // SA: see note above { os = os_; (*os) << osLocal->str(); (*os) << std::flush; } } private: void NextPar() { valIx = 0; if( nextParIx < nParam) { actPar = e->GetPar( nextParIx); if( actPar != NULL) nElements = actPar->ToTransfer(); else nElements = 0; } else { actPar = NULL; nElements = 0; } nextParIx++; } void NextVal( SizeT n=1) { valIx += n; if( valIx >= nElements) NextPar(); } std::ostream* os; EnvT* e; SizeT nextParIx; SizeT valIx; bool termFlag; bool nonlFlag; SizeT nParam; BaseGDL* actPar; SizeT nElements; RefFMTNode reversionAnker; } format : #(fmt:FORMAT { goto realCode; } // note: following is never executed in order to fool ANTLR q (f q)+ // this gets never executed { realCode: reversionAnker = #fmt; RefFMTNode blk = _t; // q (f q)+ for( int r = #fmt->getRep(); r > 0; r--) { q( blk); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { if( actPar == NULL && termFlag) goto endFMT; // no break } case STRING: case CSTRING: { f(_t); // if( actPar == NULL && termFlag) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition if( actPar == NULL && termFlag) break; } } ) ; format_reversion : format { goto realCode; } // note: following is never executed in order to fool ANTLR q (f q)* { realCode: q( _t); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition } ; q : (s:SLASH { // only one newline to journal file GDLStream* j = lib::get_journal(); if( j != NULL && j->OStream().rdbuf() == os->rdbuf()) (*os) << '\n' << lib::JOURNALCOMMENT; else for( int r=s->getRep(); r > 0; r--) (*os) << '\n'; } )? ; f_csubcode // note: IDL doesn't allow hollerith strings inside C() : s:STRING { (*os) << s->getText(); } // | CSTRING // *** requires special handling | tl:TL { SizeT actP = os->tellp(); int tlVal = tl->getW(); if( tlVal > actP) os->seekp( 0); else os->seekp( actP - tlVal); } | tr:TR { int tlVal = tl->getW(); for( int i=tlVal; i>0; --i) (*os) << " "; // os->seekp( tlVal, std::ios_base::cur); } ; f : TERM { termFlag = true; } | NONL { nonlFlag = true; } | Q // ignored on output | t:T { int tVal = t->getW(); assert( tVal >= 1); os->seekp( tVal-1, std::ios_base::beg); } | f_csubcode | x | format // following are repeatable formats | a:A { if( actPar == NULL) break; int r = a->getRep(); int w = a->getW(); int c = a->getCode(); do { SizeT tCount = actPar->OFmtA( os, valIx, r, w, c); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } // | d:D // D is transformed to F below: | ff:F { if( actPar == NULL) break; int r = ff->getRep(); int w = ff->getW(); int d = ff->getD(); int c = ff->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::FIXED); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | se:SE { if( actPar == NULL) break; int r = se->getRep(); int w = se->getW(); int d = se->getD(); int c = se->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::SCIENTIFIC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | ee:E { if( actPar == NULL) break; int r = ee->getRep(); int w = ee->getW(); int d = ee->getD(); ee->setUpper(); //'E' in uppercase int c = ee->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::SCIENTIFIC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | sg:SG { if( actPar == NULL) break; int r = sg->getRep(); int w = sg->getW(); int d = sg->getD(); int c = sg->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::AUTO); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | g:G { if( actPar == NULL) break; int r = g->getRep(); int w = g->getW(); int d = g->getD(); g->setUpper(); //'E' in uppercase int c = g->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::AUTO); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | i:I { if( actPar == NULL) break; int r = i->getRep(); int w = i->getW(); int d = i->getD(); int c = i->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::DEC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | o:O { if( actPar == NULL) break; int r = o->getRep(); int w = o->getW(); int d = o->getD(); int c = o->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::OCT); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | b:B { if( actPar == NULL) break; int r = b->getRep(); int w = b->getW(); int d = b->getD(); int c = b->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::BIN); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | z:Z { if( actPar == NULL) break; int r = z->getRep(); int w = z->getW(); int d = z->getD(); int c = z->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::HEX); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | zz:ZZ { if( actPar == NULL) break; int r = zz->getRep(); int w = zz->getW(); int d = zz->getD(); int c = zz->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::HEXL); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); } | ( #( c:C { int r = c->getRep(); if (r<1) r=1; if( actPar == NULL) break; SizeT nTrans = actPar->ToTransfer(); if (r > nTrans) r=nTrans; actPar->OFmtCal( os, valIx, r, 0, 0, NULL, 0, BaseGDL::COMPUTE); //convert to hour, min, etc } ( (calendar_code[r])+ | { if( actPar == NULL) break; actPar->OFmtCal( os, valIx, r, 0, 0, NULL, 0, BaseGDL::DEFAULT); } ) { if( actPar == NULL) break; SizeT tCount = actPar->OFmtCal( os, valIx, r, 0, 0, NULL, 0, BaseGDL::WRITE); //Write the complete formatted string to os. NextVal( tCount); if( actPar == NULL) break; } ) // exception // catch [ antlr::RecognitionException& e] {std::cerr<getW(); int d = c1->getD(); int c = c1->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMOA); } | c2:CMoA { if( actPar == NULL) break; int w = c2->getW(); int d = c2->getD(); int c = c2->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMoA); } | c3:CmoA { if( actPar == NULL) break; int w = c3->getW(); int d = c3->getD(); int c = c3->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CmoA); } | c4:CHI { if( actPar == NULL) break; int w = c4->getW(); int d = c4->getD(); int c = c4->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CHI); } | c5:ChI { if( actPar == NULL) break; int w = c5->getW(); int d = c5->getD(); int c = c5->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::ChI); } | c6:CDWA { if( actPar == NULL) break; int w = c6->getW(); int d = c6->getD(); int c = c6->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CDWA); } | c7:CDwA { if( actPar == NULL) break; int w = c7->getW(); int d = c7->getD(); int c = c7->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CDwA); } | c8:CdwA { if( actPar == NULL) break; int w = c8->getW(); int d = c8->getD(); int c = c8->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CdwA); } | c9:CAPA { if( actPar == NULL) break; int w = c9->getW(); int d = c9->getD(); int c = c9->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CAPA); } | c10:CApA { if( actPar == NULL) break; int w = c10->getW(); int d = c10->getD(); int c = c10->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CApA); } | c11:CapA { if( actPar == NULL) break; int w = c11->getW(); int d = c11->getD(); int c = c11->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CapA); } | c12:CMOI { if( actPar == NULL) break; int w = c12->getW(); int d = c12->getD(); int c = c12->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMOI); } | c13:CDI { if( actPar == NULL) break; int w = c13->getW(); int d = c13->getD(); int c = c13->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CDI); } | c14:CYI { if( actPar == NULL) break; int w = c14->getW(); int d = c14->getD(); int c = c14->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CYI); } | c15:CMI { if( actPar == NULL) break; int w = c15->getW(); int d = c15->getD(); int c = c15->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMI); } | c16:CSI { if( actPar == NULL) break; int w = c16->getW(); int d = c16->getD(); int c = c16->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CSI); } | c17:CSF { if( actPar == NULL) break; int w = c17->getW(); int d = c17->getD(); int c = c17->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CSF); } | c18:X { if( actPar == NULL) break; int tlVal = c18->getW(); if (tlVal < 1) tlVal=1; std::string *s=new std::string(tlVal,' '); SizeT tCount = actPar->OFmtCal( os, valIx, r, 0, 0, (char*)s->c_str(), BaseGDL::STRING); delete s; } | c19:STRING { if( actPar == NULL) break; SizeT tCount = actPar->OFmtCal( os, valIx, r, 0, 0, (char*)c19->getText().c_str(), 0, BaseGDL::STRING); } ; //AND NOTHING ELSE PERMITTED! x : tl:X { // if( _t != static_cast(antlr::nullAST)) // { // int tlVal = #tl->getW(); // (*os) << " "; //for format "X" (no width) // for( int i=tlVal; i>1; --i) // (*os) << " "; //for format "nX" //// os->seekp( tlVal, std::ios_base::cur); // } for( int r=tl->getW(); r > 0; r--) (*os) << ' '; } ; gdl-0.9.9/src/gdl.cpp000066400000000000000000000363531340051421000143400ustar00rootroot00000000000000/*************************************************************************** gdl.cpp - main program ------------------- begin : Wed Apr 18 16:58:14 JST 2001 copyright : (C) 2002-2006 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" // #ifndef VERSION // #define VERSION "0.9" // #endif #include #include #include #if defined(_MSC_VER) || defined (_WIN32) #include #define isatty _isatty #else #include // isatty #endif #include // PATH_MAX //patch #90 #ifndef PATH_MAX #define PATH_MAX 4096 #endif #ifndef _WIN32 #include //rlimits to augment stack size (needed fot DICOM objects) #endif //#include #include "str.hpp" #include "dinterpreter.hpp" #include "terminfo.hpp" #include "sigfpehandler.hpp" #include "gdleventhandler.hpp" #ifdef _OPENMP #include #endif #ifdef USE_MPI # include "mpi.h" #endif #ifdef HAVE_LOCALE_H # include #endif // GDLDATADIR #include "config.h" using namespace std; static void StartupMessage() { cerr << endl; cerr << " GDL - GNU Data Language, Version " << VERSION << endl; cerr << endl; cerr << "- For basic information type HELP,/INFO" << endl; } void LibInit(); // defined in libinit.cpp namespace lib { void SetGDLGenericGSLErrorHandler(); // defined in gsl_fun.cpp } // Nodar and Alain, May 2013: we try to optimize the value for CpuTPOOL_NTHREADS // if *valid* external value for OMP_NUM_THREADS (0 < OMP_NUM_THREADS < nb_cores) we used it // if not provided, we try to estimate a value looking at the average load void InitOpenMP() { #ifdef _OPENMP int suggested_num_threads, omp_num_core; suggested_num_threads=get_suggested_omp_num_threads(); omp_num_core=omp_get_num_procs(); // cout << "estimated Threads :" << suggested_num_threads << endl; // we update iff needed (by default, "omp_num_threads" is initialiazed to "omp_num_core" if ((suggested_num_threads > 0) && (suggested_num_threads < omp_num_core)) { // update of !cpu.TPOOL_NTHREADS DStructGDL* cpu = SysVar::Cpu(); static unsigned NTHREADSTag = cpu->Desc()->TagIndex( "TPOOL_NTHREADS"); (*static_cast( cpu->GetTag( NTHREADSTag, 0)))[0] =suggested_num_threads; // effective gloabl change of num of treads using omp_set_num_threads() omp_set_num_threads(suggested_num_threads); } #endif } void AtExit() { //this function probably cleans otherwise cleaned objets and should be called only for debugging purposes. cerr << "Using AtExit() for debugging" << endl; cerr << flush; cout << flush; clog << flush; // clean up everything // (for debugging memory leaks) ResetObjects(); PurgeContainer(libFunList); PurgeContainer(libProList); } #ifndef _WIN32 void GDLSetLimits() { #define GDL_PREFERED_STACKSIZE 20480000 //20000*1024 OK for the time being struct rlimit* gdlstack=new struct rlimit; int r=getrlimit(RLIMIT_STACK,gdlstack); // cerr <<"Current rlimit = "<rlim_cur< command_line_args; bool gdlarg_present(const char* s) { for (size_t i = 0; i < command_line_args.size(); i++) if( command_line_args[i] == s ) return true; return false; } bool trace_arg() { for (size_t i = 0; i < command_line_args.size(); i++) if( command_line_args[i] == "trace" ) return true; return false; } } int main(int argc, char *argv[]) { #if GDL_DEBUG if( atexit( AtExit) != 0) cerr << "atexit registration failed." << endl; #endif // indicates if the user wants to see the welcome message bool quiet = false; bool gdlde = false; // keeps a list of files to be executed after the startup file // and before entering the interactive mode vector batch_files; string statement; string pretendRelease; bool strict_syntax=false; bool syntaxOptionSet=false; //start with a default value: useWxWidgetsForGraphics = false; bool force_no_wxgraphics = false; useDSFMTAcceleration = true; for( SizeT a=1; a< argc; ++a) { if( string( argv[a]) == "--help" | string( argv[a]) == "-h") { cout << "Usage: gdl [ OPTIONS ] [ batch_file ... ]" << endl; cout << "Start the GDL interpreter (incremental compiler)" << endl; cout << endl; cout << "GDL options:" << endl; cout << " --help (-h) display this message" << endl; cout << " --version (-V, -v) show version information" << endl; cout << " --fakerelease X.y pretend that !VERSION.RELEASE is X.y" << endl; cout << " --fussy implies that procedures adhere with modern IDL, where \"()\" are for functions and \"[]\" are for arrays." <>" << params_file << "<<" << endl; WordExp(params_file); ifstream file_params; file_params.open(params_file.c_str()); if (!file_params.is_open()) { cerr << "Error opening file. File: "<< params_file << endl; cerr << "No such file or directory"<< endl; return 0; } file_params.close(); } else if (string(argv[a]) == "-e") { if (a == argc - 1) { cerr << "gdl: -e must be followed by a user argument." << endl; return 0; } statement = string(argv[++a]); statement.append("\n"); // apparently not needed but this way the empty-string case is covered // (e.g. $ gdl -e "") } else if ( string(argv[a]) == "-demo" || string(argv[a]) == "-em" || string(argv[a]) == "-novm" || string(argv[a]) == "-queue" || string(argv[a]) == "-rt" || string(argv[a]) == "-ulicense" || string(argv[a]) == "-vm" ) cerr << argv[0] << ": " << argv[a] << " option ignored." << endl; else if (string(argv[a]) == "-gdlde") { gdlde = true; } else if (string(argv[a]) == "--fussy") { strict_syntax = true; syntaxOptionSet = true; } else if (string(argv[a]) == "--sloppy") { strict_syntax = false; syntaxOptionSet = true; } else if (string(argv[a]) == "--no-dSFMT") { useDSFMTAcceleration = false; } else if (string(argv[a]) == "--use-wx") { useWxWidgetsForGraphics = true; } else if (string(argv[a]) == "--no-use-wx") { force_no_wxgraphics = true; } else if (string(argv[a]) == "--fakerelease") { if (a == argc - 1) { cerr << "gdl: --fakerelease must be followed by a string argument like \"6.4\"" << endl; return 0; } pretendRelease = string(argv[++a]); } else if (*argv[a] == '-') { cerr << argv[0] << ": " << argv[a] << " option not recognized." << endl; return 0; } else { batch_files.push_back(argv[a]); } } if (0&&statement.length() > 0 && batch_files.size() > 0) { cerr << argv[0] << ": " << "-e option cannot be specified with batch files" << endl; return 0; } //before InitGDL() as InitGDL() starts graphic! std::string useWX=GetEnvString("GDL_USE_WX"); if ( useWX.length() > 0) useWxWidgetsForGraphics=true; //not necessary "YES". if (force_no_wxgraphics) useWxWidgetsForGraphics=false; //this has the last answer, whatever the setup. if (useWxWidgetsForGraphics) cerr << "- Using WxWidgets as graphics library (windows and widgets)." < 0)) useDSFMTAcceleration=false; SysVar::SetGDLPath( gdlPath); if (!pretendRelease.empty()) SysVar::SetFakeRelease(pretendRelease); //fussyness setup and change if switch at start if (syntaxOptionSet) { //take it no matters any env. var. if (strict_syntax == true) SetStrict(true); } else { if (GetEnvString("GDL_IS_FUSSY").size()> 0) SetStrict(true); } string startup=GetEnvString("GDL_STARTUP"); if( startup == "") startup=GetEnvString("IDL_STARTUP"); if( startup == "") { if (gdlde || (isatty(0) && !quiet)) cerr << "- No startup file read (GDL_STARTUP/IDL_STARTUP env. var. not set). " << endl; } if (gdlde || (isatty(0) && !quiet)) { cerr << "- Please report bugs, feature or help requests and patches at:" << endl << " https://github.com/gnudatalanguage/gdl" << endl << endl; } // else // { // // if path not given, add users home // if( !PathGiven(startup)) // { // string home=GetEnvString("HOME"); // if( home != "") // { // AppendIfNeeded(home,"/"); // startup=home+startup; // } // } // } #ifdef USE_MPI { // warning the user if MPI changes the working directory of GDL char wd1[PATH_MAX], wd2[PATH_MAX]; char *wd1p, *wd2p; wd1p = getcwd(wd1, PATH_MAX); MPI_Init(&argc, &argv); wd2p = getcwd(wd2, PATH_MAX); if (strcmp(wd1, wd2) != 0) cerr << "Warning: MPI has changed the working directory of GDL!" << endl; } int myrank = 0; MPI_Comm_rank( MPI_COMM_WORLD, &myrank); int size; MPI_Comm_size(MPI_COMM_WORLD, &size); int tag = 0; char* mpi_procedure = getenv("GDL_MPI"); if (myrank == 0 && mpi_procedure != NULL){ for( SizeT i = 0; i < size; i++) MPI_Send(mpi_procedure, strlen(mpi_procedure)+1, MPI_CHAR, i, tag, MPI_COMM_WORLD); } #endif // USE_MPI interpreter.InterpreterLoop( startup, batch_files, statement); return 0; } gdl-0.9.9/src/gdlarray.hpp000066400000000000000000000164341340051421000154020ustar00rootroot00000000000000/*************************************************************************** gdlarray.hpp - basic typedefs ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLARRAY_HPP_ #define GDLARRAY_HPP_ // #define GDLARRAY_CACHE #undef GDLARRAY_CACHE //#define GDLARRAY_DEBUG #undef GDLARRAY_DEBUG // for complex (of POD) const bool TreatPODComplexAsPOD = true; template class GDLArray { private: enum GDLArrayConstants { smallArraySize = 27, maxCache = 1000 * 1000 // ComplexDbl is 16 bytes }; typedef T Ty; #ifdef USE_EIGEN EIGEN_ALIGN16 char scalarBuf[ smallArraySize * sizeof(Ty)]; #else char scalarBuf[ smallArraySize * sizeof(Ty)]; #endif Ty* InitScalar() { assert( sz <= smallArraySize); if( IsPOD) { return reinterpret_cast(scalarBuf); } else { Ty* b = reinterpret_cast(scalarBuf); for( int i = 0; i( s); #else return new Ty[ s]; #endif } public: GDLArray() throw() : buf( NULL), sz( 0) {} #ifndef GDLARRAY_CACHE ~GDLArray() throw() { if( IsPOD) { #ifdef USE_EIGEN if( buf != reinterpret_cast(scalarBuf)) Eigen::internal::aligned_delete( buf, sz); #else if( buf != reinterpret_cast(scalarBuf)) delete[] buf; // buf == NULL also possible #endif // no cleanup of "buf" here } else { #ifdef USE_EIGEN if( buf != reinterpret_cast(scalarBuf)) Eigen::internal::aligned_delete( buf, sz); else for( int i = 0; i(scalarBuf)) delete[] buf; // buf == NULL also possible else for( int i = 0; i smallArraySize) ? New(cp.size()) /*New T[ cp.size()]*/ : InitScalar(); } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } std::memcpy(buf,cp.buf,sz*sizeof(T)); } else { try { buf = (cp.size() > smallArraySize) ? New(cp.size()) /*new Ty[ cp.size()]*/ : InitScalar(); } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } for( SizeT i=0; i smallArraySize) ? New(s) /*T[ s]*/ : InitScalar(); } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } } GDLArray( T val, SizeT s) : sz( s) { try { buf = (s > smallArraySize) ? New(s) /*T[ s]*/ : InitScalar(); } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } for( SizeT i=0; i smallArraySize ) ? New(s) /*T[ s]*/: InitScalar(); } catch ( std::bad_alloc& ) { ThrowGDLException ( "Array requires more memory than available" ); } std::memcpy(buf,arr,sz*sizeof(T)); } else { try { buf = (s > smallArraySize) ? New(s) /*new Ty[ s]*/: InitScalar(); } catch (std::bad_alloc&) { ThrowGDLException("Array requires more memory than available"); } for( SizeT i=0; i(scalarBuf); buf[0] = s; } else { Ty* b = reinterpret_cast(scalarBuf); new (&(b[ 0])) Ty( s); buf = b; } } T& operator[]( SizeT ix) throw() { assert( ix < sz); return buf[ ix]; } const T& operator[]( SizeT ix) const throw() { assert( ix < sz); return buf[ ix]; } // private: // disable // only used (indirect) by DStructGDL::DStructGDL(const DStructGDL& d_) void InitFrom( const GDLArray& right ) { assert( &right != this); assert ( sz == right.size() ); if( IsPOD) { std::memcpy(buf,right.buf,sz*sizeof(Ty)); } else { for ( SizeT i=0; i smallArraySize ) { try { buf = New(sz) /*new T[ newSz]*/; } catch ( std::bad_alloc& ) { ThrowGDLException ( "Array requires more memory than available" ); } } else { // default constructed instances have buf == NULL and size == 0 // make sure buf is set corectly if such instances are resized buf = InitScalar(); } } // protected: // void assert(ix #include } header { #include #include "GDLParser.hpp" #include "str.hpp" #include "dnodefactory.hpp" #include "objects.hpp" #include "initsysvar.hpp" #include #include #include #include #include //#include "dinterpreter.hpp" // defintion in dinterpreter.cpp //void SetActualCompileOpt( unsigned int cOpt); } options { language="Cpp"; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the GDL Parser ********************************************* class GDLParser extends Parser; options { exportVocab = GDL; // use vocab generated by lexer buildAST = true; ASTLabelType = "RefDNode"; k=2; defaultErrorHandler = false; // defaultErrorHandler = true; } // if something is changed here // identifier below probably needs to change as well // also, imperative to change values of _TokenSet_xxx farther on in the file. tokens { ALL; // arrayindex (*, e.g. [1:*]) ASSIGN; ASSIGN_INPLACE; ASSIGN_REPLACE; ASSIGN_ARRAYEXPR_MFCALL; ARRAYDEF; ARRAYDEF_CONST; ARRAYDEF_GENERALIZED_INDGEN; ARRAYIX; ARRAYIX_ALL; ARRAYIX_ORANGE; ARRAYIX_RANGE; ARRAYIX_ORANGE_S; // with stride ARRAYIX_RANGE_S; ARRAYEXPR; ARRAYEXPR_FCALL; ARRAYEXPR_MFCALL; BLOCK; BREAK; CSBLOCK; CONTINUE; COMMONDECL; COMMONDEF; CONSTANT; DEREF; ELSEBLK; EXPR; FOR; FOR_STEP; // for with step FOREACH; FOREACH_INDEX; // foreach with index (hash) variable FOR_LOOP; FOR_STEP_LOOP; // for with step FOREACH_LOOP; FOREACH_INDEX_LOOP; FCALL; FCALL_LIB; // library function call FCALL_LIB_DIRECT; // direct call FCALL_LIB_N_ELEMENTS; // N_ELEMENTS FCALL_LIB_RETNEW; // library function call always return newly allocated data GDLNULL; IF_ELSE; KEYDECL; KEYDEF; KEYDEF_REF; // keyword passed by reference KEYDEF_REF_CHECK; // keyword maybe passed by reference KEYDEF_REF_EXPR; // keyword with assign/inc/dec passed by reference LABEL; MPCALL; MPCALL_PARENT; // explicit call to parent MFCALL; MFCALL_LIB; MFCALL_LIB_RETNEW; MFCALL_PARENT; // explicit call to parent MFCALL_PARENT_LIB; MFCALL_PARENT_LIB_RETNEW; NOP; // no operation NSTRUC; // named struct NSTRUC_REF; // named struct reference ON_IOERROR_NULL; PCALL; PCALL_LIB; // libraray procedure call PARADECL; PARAEXPR; // parameter PARAEXPR_VN; // _VN Variable Number of parameters version DEC_REF_CHECK; // called from EvalRefCheck() (no temporary needed then) INC_REF_CHECK; // called from EvalRefCheck() (no temporary needed then) POSTDEC; POSTINC; DECSTATEMENT; // as a statement INCSTATEMENT; // as a statement REF; // expr pass by reference REF_VN; // expr pass by reference REF_CHECK; // expr maybe be passed by reference REF_CHECK_VN; // expr maybe be passed by reference REF_EXPR; // assign/dec/inc expr passed by reference REF_EXPR_VN; // assign/dec/inc expr passed by reference REPEAT; REPEAT_LOOP; RETURN; // unspecified return (replaced by tree parser with RETF/RETP) RETF; // return from function (return argument) RETP; // return from procedure (no return argument) STRUC; // struct SYSVAR; // UPLUS; UMINUS; VAR; // varaible, referenced through index VARPTR; // variable, referenced through pointer WHILE; } { public: enum CompileOpt { NONE=0, DEFINT32=1, HIDDEN=2, OBSOLETE=4, STRICTARR=8, LOGICAL_PREDICATE=16, // *** functionality not implemeted yet IDL2=DEFINT32 | STRICTARR, STRICTARRSUBS=32, STATIC=64, NOSAVE=128 }; void SetCompileOpt( unsigned int cOpt) { this->compileOpt = cOpt; } private: void AddCompileOpt( const std::string &opt) { if( opt == "DEFINT32") compileOpt |= DEFINT32; else if( opt == "HIDDEN") compileOpt |= HIDDEN; else if( opt == "OBSOLETE") compileOpt |= OBSOLETE; else if( opt == "STRICTARR") compileOpt |= STRICTARR; else if( opt == "LOGICAL_PREDICATE") compileOpt |= LOGICAL_PREDICATE; else if( opt == "IDL2") compileOpt |= IDL2; else if( opt == "STRICTARRSUBS") compileOpt |= STRICTARRSUBS; else if( opt == "STATIC") compileOpt |= STATIC; else if( opt == "NOSAVE") compileOpt |= NOSAVE; else throw GDLException("Unrecognised COMPILE_OPT option: "+opt); // SetActualCompileOpt( compileOpt); } std::string subName; // name of procedure function to be compiled ("" -> all file) bool searchForPro; // true -> procedure subName, false -> function subName bool subReached; unsigned int compileOpt; bool ConstantExprNode( int t) { return (t == CONSTANT) || (t == ARRAYDEF_CONST); } public: GDLParser(antlr::TokenStream& selector, const std::string& sName, bool searchPro, // true -> search for procedure sName, false -> for function unsigned int compileOptIn): antlr::LLkParser(selector,2), subName(sName), searchForPro( searchPro), subReached(false), compileOpt(compileOptIn) { // setTokenNames(_tokenNames); } } // 'reverse' identifier // allows reserved words as identifiers // needed for keyword abbreviations // if you change some keywords here you probably need to change // the reserved word list above identifier : IDENTIFIER | a:AND_OP { #a->setType( IDENTIFIER);} | b:BEGIN { #b->setType( IDENTIFIER);} | c:CASE { #c->setType( IDENTIFIER);} | co:COMMON { #co->setType( IDENTIFIER);} | com:COMPILE_OPT { #com->setType( IDENTIFIER);} | d:DO { #d->setType( IDENTIFIER);} | e:ELSE { #e->setType( IDENTIFIER);} | en:END { #en->setType( IDENTIFIER);} | end:ENDCASE { #end->setType( IDENTIFIER);} | ende:ENDELSE { #ende->setType( IDENTIFIER);} | endf:ENDFOR { #endf->setType( IDENTIFIER);} | endfe:ENDFOREACH { #endf->setType( IDENTIFIER);} | endi:ENDIF { #endi->setType( IDENTIFIER);} | endr:ENDREP { #endr->setType( IDENTIFIER);} | ends:ENDSWITCH { #ends->setType( IDENTIFIER);} | endw:ENDWHILE { #endw->setType( IDENTIFIER);} | eq:EQ_OP { #eq->setType( IDENTIFIER);} | f:FOR { #f->setType( IDENTIFIER);} | fe:FOREACH { #f->setType( IDENTIFIER);} | fo:FORWARD { #fo->setType( IDENTIFIER);} | fu:FUNCTION { #fu->setType( IDENTIFIER);} | g:GE_OP { #g->setType( IDENTIFIER);} | go:GOTO { #go->setType( IDENTIFIER);} | gt:GT_OP { #gt->setType( IDENTIFIER);} | i:IF { #i->setType( IDENTIFIER);} | in:INHERITS { #in->setType( IDENTIFIER);} | l:LE_OP { #l->setType( IDENTIFIER);} | lt:LT_OP { #lt->setType( IDENTIFIER);} | m:MOD_OP { #m->setType( IDENTIFIER);} | n:NE_OP { #n->setType( IDENTIFIER);} | no:NOT_OP { #no->setType( IDENTIFIER);} | o:OF { #o->setType( IDENTIFIER);} | on:ON_IOERROR { #on->setType( IDENTIFIER);} | o_:OR_OP { #o_->setType( IDENTIFIER);} | p:PRO { #p->setType( IDENTIFIER);} | r:REPEAT { #r->setType( IDENTIFIER);} | s:SWITCH { #s->setType( IDENTIFIER);} | t:THEN { #t->setType( IDENTIFIER);} | u:UNTIL { #u->setType( IDENTIFIER);} | w:WHILE { #w->setType( IDENTIFIER);} | x:XOR_OP { #x->setType( IDENTIFIER);} ; // file parsing translation_unit { subReached=false; compileOpt=NONE; // reset compileOpt } : ( options {greedy=true;}: end_unit | forward_function end_unit | procedure_def { compileOpt=NONE; // reset compileOpt if( subReached) goto bailOut; } | function_def { compileOpt=NONE; // reset compileOpt if( subReached) goto bailOut; } | common_block )* // optional - only main program is also ok ( statement_list END! (end_unit)? )? // $MAIN$ program (EOF!) // braces necessary because goto crosses initialization otherwise { bailOut:;} // bailout jump label // catch lexer exceptions also exception catch [ GDLException& e] { throw; } catch [ antlr::NoViableAltException& e] { // PARSER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Parser syntax error: "+e.getMessage()); } catch [ antlr::NoViableAltForCharException& e] { // LEXER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer syntax error: "+e.getMessage()); } catch [ antlr::RecognitionException& e] { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer/Parser syntax error: "+e.getMessage()); } catch [ antlr::TokenStreamIOException& e] { // IO ERROR throw GDLException( returnAST, "Input/Output error: "+e.getMessage()); } catch [ antlr::TokenStreamException& e] { throw GDLException( returnAST, "Token stream error: "+e.getMessage()); } ; // to give a more precise error message // interactive compilation is not allowed interactive_compile! : (FUNCTION | PRO) IDENTIFIER { throw GDLException( "Programs can't be compiled from " "single statement mode."); } (METHOD IDENTIFIER)? (COMMA parameter_declaration)? end_unit ; // intercative usage interactive : ( end_unit (end_mark)? | interactive_statement | interactive_compile )+ // catch lexer exceptions also exception catch [ GDLException& e] { throw; } catch [ antlr::NoViableAltException& e] { // PARSER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Parser syntax error: "+ e.getMessage()); } catch [ antlr::NoViableAltForCharException& e] { // LEXER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer syntax error: "+ e.getMessage()); } catch [ antlr::RecognitionException& e] { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer/Parser syntax error: "+e.getMessage()); } catch [ antlr::TokenStreamIOException& e] { // IO ERROR throw GDLException( returnAST, "Input/Output error: "+e.getMessage()); } catch [ antlr::TokenStreamException& e] { throw GDLException( returnAST, "Token stream error: "+e.getMessage()); } ; // compound statements in the original don't care about the specific end_mark // in interactive mode end need not to be there and labels are ignored interactive_statement : (BEGIN! | IDENTIFIER! COLON!)* statement end_unit ; // idl allows more than one ELSE: first is executed, *all* // (including expr) later branches are ignored (case) or // executed (switch) switch_statement { int numBranch=0; } : SWITCH^ expr OF! (end_unit)? (switch_body { numBranch++; } )* endswitch_mark { #SWITCH->SetNumBranch(numBranch); } ; switch_body : expr COLON! ( statement | BEGIN! statement_list endswitch_mark)? end_unit { #switch_body = #([BLOCK, "block"], #switch_body);} | ELSE! COLON! ( statement | BEGIN! statement_list endswitchelse_mark)? end_unit { #switch_body = #([ELSEBLK, "elseblk"], #switch_body);} ; case_statement { int numBranch=0; } : CASE^ expr OF! (end_unit)? (case_body { numBranch++; } )* endcase_mark { #CASE->SetNumBranch(numBranch); } ; case_body : expr COLON! (statement | BEGIN! statement_list endcase_mark)? end_unit { #case_body = #([BLOCK, "block"], #case_body);} | ELSE! COLON! (statement | BEGIN! statement_list endcaseelse_mark)? end_unit { #case_body = #([ELSEBLK, "elseblk"], #case_body);} ; // whereever one END_U is there might be more // end_unit is syntactical necessary, but not for the AST end_unit! : (options {greedy=true;}: END_U)+ ; forward_function : FORWARD^ identifier_list ; parameter_declaration : (IDENTIFIER | keyword_declaration) (COMMA! (IDENTIFIER | keyword_declaration))* { #parameter_declaration = #([PARADECL,"paradecl"], #parameter_declaration);} ; keyword_declaration : IDENTIFIER EQUAL! IDENTIFIER { #keyword_declaration = #([KEYDECL,"keydecl"], #keyword_declaration);} ; object_name! returns [std::string name] // !// : i1:IDENTIFIER m:METHOD i2:IDENTIFIER { // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( #i1->getText() == "IDL_OBJECT") #i1->setText(GDL_OBJECT_NAME); else if( #i1->getText() == "IDL_CONTAINER") #i1->setText(GDL_CONTAINER_NAME); } #object_name = #(NULL, i2, m, i1); // NULL -> no root name= std::string( i1->getText()+"__"+i2->getText()); } ; procedure_def { std::string name; } : p:PRO^ ( n:IDENTIFIER { name=n->getText(); } | name=object_name ) (COMMA! parameter_declaration)? end_unit (statement_list)? END! { if( subName == name && searchForPro == true) subReached=true; #p->SetCompileOpt( compileOpt); } ; function_def { std::string name; } : f:FUNCTION^ ( n:IDENTIFIER { name=n->getText(); } | name=object_name ) (COMMA! parameter_declaration)? end_unit (statement_list)? END! { if( subName == name && searchForPro == false) subReached=true; #f->SetCompileOpt( compileOpt); } ; // change defaultbehaviour of the compiling compile_opt! : COMPILE_OPT i:IDENTIFIER { AddCompileOpt( i->getText()); } (COMMA ii:IDENTIFIER { AddCompileOpt( ii->getText()); } )* ; common_block : COMMON! IDENTIFIER ( { #common_block = #([COMMONDECL,"commondecl"], #common_block);} | COMMA! identifier_list { #common_block = #([COMMONDEF,"commondef"], #common_block);} ) ; identifier_list : IDENTIFIER (COMMA! IDENTIFIER)* ; // no ASTs for end marks end_mark! : END | ENDIF | ENDELSE | ENDCASE | ENDSWITCH | ENDFOR | ENDFOREACH | ENDWHILE | ENDREP ; endforeach_mark! : ENDFOREACH | END ; endfor_mark! : ENDFOR | END ; endrep_mark! : ENDREP | END ; endwhile_mark! : ENDWHILE | END ; endif_mark! : ENDIF | END ; endelse_mark! : ENDELSE | END ; endcase_mark! : ENDCASE | END ; endcaseelse_mark! : endcase_mark | ENDELSE ; endswitch_mark! : ENDSWITCH | END ; endswitchelse_mark! : endswitch_mark | ENDELSE ; statement_list : (end_unit | compound_statement end_unit | label_statement end_unit)+ ; label : IDENTIFIER^ COLON ; label_statement : (label)+ (compound_statement)? ; // compound statements don't care about the specific end_mark compound_statement : statement | BEGIN! statement_list end_mark { #compound_statement = #([BLOCK, "block"], #compound_statement);} ; baseclass_method : s:IDENTIFIER METHOD! // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( #s->getText() == "IDL_OBJECT") #s->setText(GDL_OBJECT_NAME); else if( #s->getText() == "IDL_CONTAINER") #s->setText(GDL_CONTAINER_NAME); } ; statement // assignment and member_procedure_call starting with deref_expr { bool parent=false; } : (assign_expr)=> assign_expr (DEC^ | INC^)? // | (deref_expr_dot)=> // (deref_expr // // assignment // (EQUAL! expr // { #statement = #([ASSIGN,":="], #statement);} // | ( AND_OP_EQ^ // | ASTERIX_EQ^ // | EQ_OP_EQ^ // | GE_OP_EQ^ // | GTMARK_EQ^ // | GT_OP_EQ^ // | LE_OP_EQ^ // | LTMARK_EQ^ // | LT_OP_EQ^ // | MATRIX_OP1_EQ^ // | MATRIX_OP2_EQ^ // | MINUS_EQ^ // | MOD_OP_EQ^ // | NE_OP_EQ^ // | OR_OP_EQ^ // | PLUS_EQ^ // | POW_EQ^ // | SLASH_EQ^ // | XOR_OP_EQ^) expr // | (DEC^ | INC^) // no POSTDEC/POSTINC for statements // | MEMBER! // member procedure call // (baseclass_method { parent=true; })? // formal_procedure_call // { // if( parent) // #statement = #([MPCALL_PARENT, "mpcall::"], // #statement); // else // #statement = #([MPCALL, "mpcall"], #statement); // } // | // empty -> member procedure call with DOT parsed by tag_access // ) // ) | (deref_dot_expr_keeplast IDENTIFIER COMMA)=> d1:deref_dot_expr_keeplast formal_procedure_call { #statement = #([MPCALL, "mpcall"], #statement); #statement->SetLine( #d1->getLine()); } | (deref_dot_expr_keeplast baseclass_method)=> d2:deref_dot_expr_keeplast baseclass_method formal_procedure_call { #statement = #([MPCALL_PARENT, "mpcall::"], #statement); #statement->SetLine( #d2->getLine()); } | ( deref_expr ( EQUAL | AND_OP_EQ^ | ASTERIX_EQ^ | EQ_OP_EQ^ | GE_OP_EQ^ | GTMARK_EQ^ | GT_OP_EQ^ | LE_OP_EQ^ | LTMARK_EQ^ | LT_OP_EQ^ | MATRIX_OP1_EQ^ | MATRIX_OP2_EQ^ | MINUS_EQ^ | MOD_OP_EQ^ | NE_OP_EQ^ | OR_OP_EQ^ | PLUS_EQ^ | POW_EQ^ | SLASH_EQ^ | XOR_OP_EQ^ | DEC^ | INC^ // no POSTDEC/POSTINC for statements | MEMBER! // member procedure call ) )=> deref_expr (EQUAL! expr { #statement = #([ASSIGN,":="], #statement);} | ( AND_OP_EQ^ | ASTERIX_EQ^ | EQ_OP_EQ^ | GE_OP_EQ^ | GTMARK_EQ^ | GT_OP_EQ^ | LE_OP_EQ^ | LTMARK_EQ^ | LT_OP_EQ^ | MATRIX_OP1_EQ^ | MATRIX_OP2_EQ^ | MINUS_EQ^ | MOD_OP_EQ^ | NE_OP_EQ^ | OR_OP_EQ^ | PLUS_EQ^ | POW_EQ^ | SLASH_EQ^ | XOR_OP_EQ^) expr | (DEC^ | INC^) // no POSTDEC/POSTINC for statements | MEMBER! // member procedure call (baseclass_method { parent=true; })? formal_procedure_call { if( parent) #statement = #([MPCALL_PARENT, "mpcall::"], #statement); else #statement = #([MPCALL, "mpcall"], #statement); } ) | // (deref_dot_expr_keeplast IDENTIFIER)=> d3:deref_dot_expr_keeplast formal_procedure_call { #statement = #([MPCALL, "mpcall"], #statement); #statement->SetLine( #d3->getLine()); } | (DEC^ | INC^) expr | procedure_call // next two handled by procedure_call also // | BREAK // only valid in loops and switch_statement // | CONTINUE // only valid in loops | for_statement | foreach_statement | repeat_statement | while_statement | jump_statement | if_statement | case_statement | switch_statement | forward_function | common_block | compile_opt ; repeat_statement : REPEAT^ repeat_block UNTIL! expr ; repeat_block : st:statement { #repeat_block = #([BLOCK, "block"], #st);} | BEGIN! stl:statement_list endrep_mark { #repeat_block = #([BLOCK, "block"], #stl);} ; while_statement : WHILE^ expr DO! while_block ; while_block : statement | BEGIN! statement_list endwhile_mark { #while_block = #([BLOCK, "block"], #while_block);} ; for_statement : FOR^ IDENTIFIER EQUAL! expr COMMA! expr (COMMA! expr)? DO! for_block ; for_block : st:statement { #for_block = #([BLOCK, "block"], #st);} | BEGIN! stl:statement_list endfor_mark { #for_block = #([BLOCK, "block"], #stl);} ; foreach_statement : FOREACH^ IDENTIFIER COMMA! expr (COMMA! IDENTIFIER)? DO! foreach_block ; foreach_block : st:statement { #foreach_block = #([BLOCK, "block"], #st);} | BEGIN! stl:statement_list endforeach_mark { #foreach_block = #([BLOCK, "block"], #stl);} ; jump_statement : GOTO^ COMMA! IDENTIFIER // now handled as a procedure_call because RETURN is no reserved word // | RETURN^ (COMMA! expr)? | ON_IOERROR^ COMMA! IDENTIFIER ; // the classical greedy case (match ELSE as soon as possible) if_statement : IF^ expr THEN! if_block ( options {greedy=true;}: ELSE! else_block )? ; if_block : statement | BEGIN! statement_list endif_mark { #if_block = #([BLOCK, "block"], #if_block);} ; else_block : statement | BEGIN! statement_list endelse_mark { #else_block = #([BLOCK, "block"], #else_block);} ; formal_procedure_call : IDENTIFIER (COMMA! parameter_def_list)? ; // must handle RETURN, BREAK, CONTINUE also procedure_call!// // was: // formal_procedure_call : id:IDENTIFIER ( {id->getText() == "RETURN"}? (COMMA! e:expr)? { #id->setType(RETURN); // text is already "return" #procedure_call = #( #id, #e); // make root } | {id->getText() == "BREAK"}? { #id->setType(BREAK); // text is already "break" #procedure_call = #id; } | {id->getText() == "CONTINUE"}? { #id->setType(CONTINUE); // text is already "continue" #procedure_call = #id; } | (COMMA! pa:parameter_def_list)? { #procedure_call = #([PCALL, "pcall"], #id, #pa); #procedure_call->SetLine(id->getLine()); } ) ; // ambiguity with arrays // but as arrays got priority, only real function calls need // to be handled here formal_function_call : IDENTIFIER LBRACE! (parameter_def_list)? RBRACE! ; parameter_def // : IDENTIFIER EQUAL! expr : identifier EQUAL! expr { #parameter_def = #([KEYDEF,"!=!"], #parameter_def);} | expr // | SLASH! id:IDENTIFIER | SLASH! id:identifier { RefDNode c=static_cast( #[CONSTANT,"1"]); c->Text2Int(10); c->SetLine( #id->getLine()); #parameter_def = #([KEYDEF,"!=!"], id, c); } ; parameter_def_list : parameter_def ( COMMA! parameter_def)* ; // [expr,...] array_def { bool constant = true; int flexible_array_def_count=1; } : LSQUARE! e:expr {if( !ConstantExprNode( #e->getType())) constant = false;} ( (COMMA! ee:expr {if( !ConstantExprNode( #ee->getType())) constant = false;} )* RSQUARE! { if( constant) #array_def = #([ARRAYDEF_CONST, "array_def_const"], #array_def); else #array_def = #([ARRAYDEF, "array_def"], #array_def); } | (COLON! eee:expr {flexible_array_def_count++;})+ RSQUARE! { if (flexible_array_def_count>3 || flexible_array_def_count<2) throw GDLException( "Illegal array creation syntax."); #array_def = #([ARRAYDEF_GENERALIZED_INDGEN, "array_def_generalized_indgen"], #array_def); } ) ; struct_identifier : ( IDENTIFIER | s:SYSVARNAME { #s->setType( IDENTIFIER);} | e:EXCLAMATION { #e->setType( IDENTIFIER);} | i:INHERITS { #i->setType( IDENTIFIER);} ) // fake IDENTIFIER (struct tag can also be "!" or "!XXXX") // no additinal subtype is needed here, as struct_def already creates // the appropriate node (ie. there is no ambiguity in the parser output) ; struct_name : s:struct_identifier // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( #s->getText() == "IDL_OBJECT") #s->setText(GDL_OBJECT_NAME); else if( #s->getText() == "IDL_CONTAINER") #s->setText(GDL_CONTAINER_NAME); } ; struct_def : LCURLY! (struct_name (COMMA! named_tag_def_list)? RCURLY! { #struct_def = #([NSTRUC_REF, "nstruct_ref"], #struct_def);} | tag_def_list RCURLY! { #struct_def = #([STRUC, "struct"], #struct_def);} ) ; tag_def : struct_identifier COLON! expr ; tag_def_list : tag_def (options {greedy=true;} : COMMA! tag_def)* ; ntag_def : tag_def | expr // for named structs, just the definition is ok ; ntag_defs : ntag_def (options {greedy=true;} : COMMA! ntag_def)* ; named_tag_def_entry : ( (INHERITS) => INHERITS struct_name | ntag_def ) ; named_tag_def_list : named_tag_def_entry ( COMMA! named_tag_def_entry)* ; numeric_constant!// : c1:CONSTANT_HEX_BYTE { #numeric_constant=#[CONSTANT,c1->getText()]; #numeric_constant->Text2Byte(16); #numeric_constant->SetLine( c1->getLine()); } | c2:CONSTANT_HEX_LONG { #numeric_constant=#[CONSTANT,c2->getText()]; #numeric_constant->Text2Long(16); #numeric_constant->SetLine( c2->getLine()); } | c3:CONSTANT_HEX_LONG64 { #numeric_constant=#[CONSTANT,c3->getText()]; #numeric_constant->Text2Long64(16); #numeric_constant->SetLine( c3->getLine()); } | c4:CONSTANT_HEX_INT { #numeric_constant=#[CONSTANT,c4->getText()]; #numeric_constant->Text2Int(16); #numeric_constant->SetLine( c4->getLine()); } | c44:CONSTANT_HEX_I // DEFINT32 { #numeric_constant=#[CONSTANT,c44->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2Long(16,true); else #numeric_constant->Text2Int(16,true); #numeric_constant->SetLine( c44->getLine()); } | c5:CONSTANT_HEX_ULONG { #numeric_constant=#[CONSTANT,c5->getText()]; #numeric_constant->Text2ULong(16); #numeric_constant->SetLine( c5->getLine()); } | c6:CONSTANT_HEX_ULONG64 { #numeric_constant=#[CONSTANT,c6->getText()]; #numeric_constant->Text2ULong64(16); #numeric_constant->SetLine( c6->getLine()); } | c77:CONSTANT_HEX_UI // DEFINT32 { #numeric_constant=#[CONSTANT,c77->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2ULong(16,true); else #numeric_constant->Text2UInt(16,true); #numeric_constant->SetLine( c77->getLine()); } | c7:CONSTANT_HEX_UINT { #numeric_constant=#[CONSTANT,c7->getText()]; #numeric_constant->Text2UInt(16); #numeric_constant->SetLine( c7->getLine()); } | c8:CONSTANT_BYTE { #numeric_constant=#[CONSTANT,c8->getText()]; #numeric_constant->Text2Byte(10); #numeric_constant->SetLine( c8->getLine()); } | c9:CONSTANT_LONG { #numeric_constant=#[CONSTANT,c9->getText()]; #numeric_constant->Text2Long(10); #numeric_constant->SetLine( c9->getLine()); } | c10:CONSTANT_LONG64 { #numeric_constant=#[CONSTANT,c10->getText()]; #numeric_constant->Text2Long64(10); #numeric_constant->SetLine( c10->getLine()); } | c11:CONSTANT_INT { #numeric_constant=#[CONSTANT,c11->getText()]; #numeric_constant->Text2Int(10); #numeric_constant->SetLine( c11->getLine()); } | c111:CONSTANT_I // DEFINT32 { #numeric_constant=#[CONSTANT,c111->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2Long(10,true); else #numeric_constant->Text2Int(10,true); #numeric_constant->SetLine( c111->getLine()); } | c12:CONSTANT_ULONG { #numeric_constant=#[CONSTANT,c12->getText()]; #numeric_constant->Text2ULong(10); #numeric_constant->SetLine( c12->getLine()); } | c13:CONSTANT_ULONG64 { #numeric_constant=#[CONSTANT,c13->getText()]; #numeric_constant->Text2ULong64(10); #numeric_constant->SetLine( c13->getLine()); } | c144:CONSTANT_UI // DEFINT32 { #numeric_constant=#[CONSTANT,c144->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2ULong(10,true); else #numeric_constant->Text2UInt(10,true); #numeric_constant->SetLine( c144->getLine()); } | c14:CONSTANT_UINT { #numeric_constant=#[CONSTANT,c14->getText()]; #numeric_constant->Text2UInt(10); #numeric_constant->SetLine( c14->getLine()); } | c15:CONSTANT_OCT_BYTE { #numeric_constant=#[CONSTANT,c15->getText()]; #numeric_constant->Text2Byte(8); #numeric_constant->SetLine( c15->getLine()); } | c16:CONSTANT_OCT_LONG { #numeric_constant=#[CONSTANT,c16->getText()]; #numeric_constant->Text2Long(8); #numeric_constant->SetLine( c16->getLine()); } | c17:CONSTANT_OCT_LONG64 { #numeric_constant=#[CONSTANT,c17->getText()]; #numeric_constant->Text2Long64(8); #numeric_constant->SetLine( c17->getLine()); } | c18:CONSTANT_OCT_INT { #numeric_constant=#[CONSTANT,c18->getText()]; #numeric_constant->Text2Int(8); #numeric_constant->SetLine( c18->getLine()); } | c188:CONSTANT_OCT_I // DEFINT32 { #numeric_constant=#[CONSTANT,c188->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2Long(8,true); else #numeric_constant->Text2Int(8,true); #numeric_constant->SetLine( c188->getLine()); } | c19:CONSTANT_OCT_ULONG { #numeric_constant=#[CONSTANT,c19->getText()]; #numeric_constant->Text2ULong(8); #numeric_constant->SetLine( c19->getLine()); } | c20:CONSTANT_OCT_ULONG64 { #numeric_constant=#[CONSTANT,c20->getText()]; #numeric_constant->Text2ULong64(8); #numeric_constant->SetLine( c20->getLine()); } | c211:CONSTANT_OCT_UI // DEFINT32 { #numeric_constant=#[CONSTANT,c211->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2ULong(8,true); else #numeric_constant->Text2UInt(8,true); #numeric_constant->SetLine( c211->getLine()); } | c21:CONSTANT_OCT_UINT { #numeric_constant=#[CONSTANT,c21->getText()]; #numeric_constant->Text2UInt(8); #numeric_constant->SetLine( c21->getLine()); } | c22:CONSTANT_FLOAT { #numeric_constant=#[CONSTANT,c22->getText()]; #numeric_constant->Text2Float(); #numeric_constant->SetLine( c22->getLine()); } | c23:CONSTANT_DOUBLE { #numeric_constant=#[CONSTANT,c23->getText()]; #numeric_constant->Text2Double(); #numeric_constant->SetLine( c23->getLine()); } | c24:CONSTANT_BIN_BYTE { #numeric_constant=#[CONSTANT,c24->getText()]; #numeric_constant->Text2Byte(2); #numeric_constant->SetLine( c24->getLine()); } | c25:CONSTANT_BIN_LONG { #numeric_constant=#[CONSTANT,c25->getText()]; #numeric_constant->Text2Long(2); #numeric_constant->SetLine( c25->getLine()); } | c26:CONSTANT_BIN_LONG64 { #numeric_constant=#[CONSTANT,c26->getText()]; #numeric_constant->Text2Long64(2); #numeric_constant->SetLine( c26->getLine()); } | c27:CONSTANT_BIN_INT { #numeric_constant=#[CONSTANT,c27->getText()]; #numeric_constant->Text2Int(2); #numeric_constant->SetLine( c27->getLine()); } | c277:CONSTANT_BIN_I // DEFINT32 { #numeric_constant=#[CONSTANT,c277->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2Long(2,true); else #numeric_constant->Text2Int(2,true); #numeric_constant->SetLine( c277->getLine()); } | c28:CONSTANT_BIN_ULONG { #numeric_constant=#[CONSTANT,c28->getText()]; #numeric_constant->Text2ULong(2); #numeric_constant->SetLine( c28->getLine()); } | c29:CONSTANT_BIN_ULONG64 { #numeric_constant=#[CONSTANT,c29->getText()]; #numeric_constant->Text2ULong64(2); #numeric_constant->SetLine( c29->getLine()); } | c300:CONSTANT_BIN_UI // DEFINT32 { #numeric_constant=#[CONSTANT,c300->getText()]; if( compileOpt & DEFINT32) #numeric_constant->Text2ULong(2,true); else #numeric_constant->Text2UInt(2,true); #numeric_constant->SetLine( c300->getLine()); } | c30:CONSTANT_BIN_UINT { #numeric_constant=#[CONSTANT,c30->getText()]; #numeric_constant->Text2UInt(2); #numeric_constant->SetLine( c30->getLine()); } ; arrayindex_list { int rank = 1; } : LSQUARE! arrayindex ({++rank <= MAXRANK}? COMMA! arrayindex)* RSQUARE! | { IsRelaxed()}? LBRACE! arrayindex ({++rank <= MAXRANK}? COMMA! arrayindex )* RBRACE! ; all_elements! : ASTERIX { #all_elements = #([ALL,"*"]);} ; // used only from arrayindex_list arrayindex : ((ASTERIX (COMMA|{ IsRelaxed()}? RBRACE|RSQUARE))=> all_elements | expr (COLON! ( (ASTERIX (COMMA|{ IsRelaxed()}? RBRACE|RSQUARE|COLON))=> all_elements | expr ) (COLON! ( (ASTERIX (COMMA|{ IsRelaxed()}? RBRACE|RSQUARE))=> ASTERIX! { throw GDLException( "n:n:* subscript form not allowed."); } | expr ) )? )? ) { #arrayindex = #([ARRAYIX,"arrayix"], #arrayindex);} ; // the expressions ************************************* // system variable name sysvar : SYSVARNAME { #sysvar = #([SYSVAR,"SYSVAR"],sysvar);} ; // variable name var! : ( id:IDENTIFIER { #var = #([VAR,"VAR"],id); } | ih:INHERITS { #ih->setType( IDENTIFIER); #var = #([VAR,"VAR"],ih); } // fake IDENTIFIER (variable name can be "INHERITS") ) ; // this is SYNTACTIALLY ok as an lvalue, but if one try to assign // something to an non-var an error is raised brace_expr // tags need this : LBRACE! expr RBRACE! { #brace_expr = #([EXPR,"expr"], #brace_expr);} ; // only used in deref_expr // sysvar or expr (first in struct access - therefore the name) array_expr_1st_sub // a variable MUST be already defined here : var | sysvar | brace_expr ; array_expr_1st! // a variable MUST be already defined here : e:array_expr_1st_sub ( al:arrayindex_list { #array_expr_1st = #([ARRAYEXPR,"arrayexpr"], #e, #al);} | // empty { #array_expr_1st = #e;} ) ; array_expr_nth_sub : IDENTIFIER | brace_expr ; // expr array_expr_nth! : e:array_expr_nth_sub ( al:arrayindex_list { #array_expr_nth = #([ARRAYEXPR,"arrayexpr"], #e, #al);} | // empty { #array_expr_nth = #e;} ) ; tag_array_expr_nth_sub : IDENTIFIER | s:SYSVARNAME { #s->setType( IDENTIFIER); /* #s->setText( "!" + #s->getText()); */} | e:EXCLAMATION { #e->setType( IDENTIFIER);} | brace_expr ; tag_array_expr_nth! : e:tag_array_expr_nth_sub ( al:arrayindex_list { #tag_array_expr_nth = #([ARRAYEXPR,"arrayexpr"], #e, #al);} | // empty { #tag_array_expr_nth = #e;} ) ; tag_access_keeplast returns [int nDot] { int t; bool parent = false; nDot=1; } : DOT! ( (tag_array_expr_nth DOT)=> // not working: (tag_array_expr_nth tag_access_keeplast)=> (tag_array_expr_nth t=tag_access_keeplast { nDot += t;}) | //(tag_array_expr_nth DOT tag_array_expr_nth)=> // (tag_array_expr_nth) ) ; deref_dot_expr_keeplast { RefDNode dot; int nDot; } : a1:array_expr_1st (// (tag_access_keeplast)=> nDot=tag_access_keeplast { if( --nDot > 0) { dot=#[DOT,"."]; dot->SetNDot( nDot); dot->SetLine( #a1->getLine()); #deref_dot_expr_keeplast = #(dot, #deref_dot_expr_keeplast); } } // | { #deref_dot_expr_keeplast = #a1;} ) | ASTERIX! deref_dot_expr_keeplast { #deref_dot_expr_keeplast = #([DEREF,"deref"], #deref_dot_expr_keeplast);} ; tag_access returns [SizeT nDot] { nDot=0; } : (options {greedy=true;}: DOT! { ++nDot;} tag_array_expr_nth)+ ; deref_dot_expr { RefDNode dot; SizeT nDot; } // : array_expr_1st (DOT array_expr_nth)* : a1:array_expr_1st (nDot=tag_access { dot=#[DOT,"."]; dot->SetNDot( nDot); dot->SetLine( #a1->getLine()); #deref_dot_expr = #(dot, #deref_dot_expr); } // | { #deref_expr = #a1;} ) | ASTERIX! deref_dot_expr { #deref_dot_expr = #([DEREF,"deref"], #deref_dot_expr);} ; deref_expr { RefDNode dot; SizeT nDot; } // : array_expr_1st (DOT array_expr_nth)* : a1:array_expr_1st // ((tag_access)=> nDot=tag_access ((DOT)=> nDot=tag_access { dot=#[DOT,"."]; dot->SetNDot( nDot); dot->SetLine( #a1->getLine()); #deref_expr = #(dot, #deref_expr); } | { #deref_expr = #a1;} ) | ASTERIX! deref_expr { #deref_expr = #([DEREF,"deref"], #deref_expr);} ; member_function_call returns [bool parent] : { parent = false;} MEMBER! (s:IDENTIFIER METHOD! { // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( #s->getText() == "IDL_OBJECT") #s->setText(GDL_OBJECT_NAME); else if( #s->getText() == "IDL_CONTAINER") #s->setText(GDL_CONTAINER_NAME); } parent = true; } )? formal_function_call ; member_function_call_dot : DOT! (s:IDENTIFIER METHOD! // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( #s->getText() == "IDL_OBJECT") #s->setText(GDL_OBJECT_NAME); else if( #s->getText() == "IDL_CONTAINER") #s->setText(GDL_CONTAINER_NAME); } ) formal_function_call ; assign_expr : LBRACE! deref_expr EQUAL! expr RBRACE! // assignment { #assign_expr = #([ASSIGN,":="], #assign_expr);} ; // arrayexpr_mfcall_last // : (IDENTIFIER^ arrayindex_list) // ; // only used for production in primary_expr arrayexpr_mfcall! { RefDNode dot; RefDNode tag; int nDot; } : a1:array_expr_1st ( // this rule is only for prodction // (tag_access_keeplast)=> nDot=t1:tag_access_keeplast { if( --nDot > 0) { dot=#[DOT,"DOT_A_MF"]; dot->SetNDot( nDot); dot->SetLine( #a1->getLine()); tag = #(dot, #a1, #t1); } } ) id:IDENTIFIER al:arrayindex_list { if( nDot > 0) #arrayexpr_mfcall = #([ARRAYEXPR_MFCALL,"arrayexpr_mfcall"], #tag, #id, #al); else #arrayexpr_mfcall = #([ARRAYEXPR_MFCALL,"arrayexpr_mfcall"], #a1, #id, #al); } | ASTERIX deref_arrayexpr_mfcall:arrayexpr_mfcall { #arrayexpr_mfcall = #([DEREF,"deref"], #deref_arrayexpr_mfcall);} ; primary_expr_tail { bool parent; } : // a member function call starts with a deref_expr (deref_dot_expr)=> // same parsing as (deref_expr)=> see below deref_expr ( parent=member_function_call { if( parent) { #primary_expr_tail = #([MFCALL_PARENT, "mfcall::"], #primary_expr_tail); } else { #primary_expr_tail = #([MFCALL, "mfcall"], #primary_expr_tail); } } | // empty -> array expression ) | // ambiguity (arrayexpr or fcall) (IDENTIFIER LBRACE expr (COMMA expr)* RBRACE)=> ( // already known function // (could be reordered, but this is conform to original) { IsFun(LT(1))}? formal_function_call { #primary_expr_tail = #([FCALL, "fcall"], #primary_expr_tail); } | // still ambiguity (arrayexpr or fcall) (var arrayindex_list)=> var arrayindex_list // array_expr_fn { #primary_expr_tail = #([ARRAYEXPR_FCALL,"arrayexpr_fcall"], #primary_expr_tail); } | // if arrayindex_list failed (due to to many indices) // this must be a function call formal_function_call { #primary_expr_tail = #([FCALL, "fcall"], #primary_expr_tail); } ) | // not the above => keyword parameter (or no args) => function call (formal_function_call)=> formal_function_call { #primary_expr_tail = #([FCALL, "fcall"], #primary_expr_tail);} | // a member function call starts with a deref_expr // deref_dot_expr already failed (deref_expr)=> deref_expr ( parent=member_function_call { if( parent) { #primary_expr_tail = #([MFCALL_PARENT, "mfcall::"], #primary_expr_tail); } else { #primary_expr_tail = #([MFCALL, "mfcall"], #primary_expr_tail); } } | // empty -> array expression ) | assign_expr | array_def | struct_def | ! ls:LSQUARE !RSQUARE { #primary_expr_tail=#[GDLNULL,"GDLNULL[]"]; #primary_expr_tail->SetLine( #ls->getLine()); } | ! lc:LCURLY !RCURLY { #primary_expr_tail=#[GDLNULL,"GDLNULL{}"]; #primary_expr_tail->SetLine( #lc->getLine()); } ; primary_expr_deref { // the following needs to be updated if the symbols are rearranged (e. g. a symbol is inserted) // (it is taken from GDLParser.cpp: const antlr::BitSet GDLParser::_tokenSet_XX) const unsigned long _tokenSet_4_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 536870912UL, 4UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" LBRACE SYSVARNAME ASTERIX const antlr::BitSet _tokenSet_4(_tokenSet_4_data_,16); const unsigned long _tokenSet_5_data_[] = { 0UL, 0UL, 268435456UL, 34603008UL, 536871296UL, 4294967253UL, 5013503UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" "not" DEC INC LBRACE LSQUARE SYSVARNAME LCURLY // CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL // PLUS MINUS LOG_NEG const antlr::BitSet _tokenSet_5(_tokenSet_5_data_,16); const unsigned long _tokenSet_23_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 536870912UL, 21UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" LBRACE LSQUARE SYSVARNAME LCURLY ASTERIX const antlr::BitSet _tokenSet_23(_tokenSet_23_data_,16); const unsigned long _tokenSet_24_data_[] = { 2UL, 0UL, 805306368UL, 2549424140UL, 4026532283UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF IDENTIFIER "and" "do" "else" "eq" "ge" "gt" "inherits" "le" "lt" // "mod" "ne" "not" "of" "or" "then" "until" "xor" COMMA COLON END_U DEC // INC MEMBER LBRACE RBRACE SLASH LSQUARE RSQUARE SYSVARNAME EXCLAMATION // LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 // CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 // CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 // CONSTANT_INT CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI // CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 // CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 // CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE // CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I // CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT // ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 MATRIX_OP2 PLUS MINUS LTMARK // GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet _tokenSet_24(_tokenSet_24_data_,16); bool parent; bool skip; int markIn = mark(); inputState->guessing++; bool tailLa1La2 = (_tokenSet_23.member(LA(1))) && (_tokenSet_24.member(LA(2))); bool derefLa1La2 = (_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))); if ( derefLa1La2) { skip = false; try { deref_dot_expr_keeplast(); } catch (antlr::RecognitionException& pe) { skip = true; } } else skip = true; if( skip && tailLa1La2) { rewind( markIn); inputState->guessing--; primary_expr_tail(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_deref_AST = RefDNode(currentAST.root); returnAST = primary_expr_deref_AST; return; } bool arrayexpr_mfcallParse = false; bool function_callParse = false; int mark2nd = mark(); bool baseclass_methodParse = true; try { { baseclass_method(); } } catch (antlr::RecognitionException& pe) { baseclass_methodParse = false; } rewind( mark2nd); if( !baseclass_methodParse) { int mark3rd = mark(); arrayexpr_mfcallParse = true; try { { match(IDENTIFIER); match(LBRACE); expr(); { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); expr(); } else { break; } } } // ( ... )* match(RBRACE); } } catch (antlr::RecognitionException& pe) { arrayexpr_mfcallParse = false; } rewind( mark3rd); if( !arrayexpr_mfcallParse) { function_callParse = true; try { { formal_function_call(); } } catch (antlr::RecognitionException& pe) { function_callParse = false; } if( !function_callParse && tailLa1La2) { rewind( markIn); inputState->guessing--; primary_expr_tail(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_deref_AST = RefDNode(currentAST.root); returnAST = primary_expr_deref_AST; return; } } } rewind( markIn); inputState->guessing--; } : // with METHOD // (deref_dot_expr_keeplast baseclass_method)=> {baseclass_methodParse}? deref_dot_expr_keeplast baseclass_method formal_function_call { #primary_expr_deref = #([MFCALL_PARENT, "mfcall::"], #primary_expr_deref); } | // ambiguity (arrayexpr or mfcall) // (deref_dot_expr_keeplast (IDENTIFIER LBRACE expr (COMMA expr)* RBRACE))=> {arrayexpr_mfcallParse}? arrayexpr_mfcall | // not the above -> unambigous mfcall (or unambigous array expr handled below) // (deref_dot_expr_keeplast formal_function_call)=> {function_callParse}? deref_dot_expr_keeplast // here it is impossible to decide about function call // as we do not know the object type/struct tag formal_function_call { #primary_expr_deref = #([MFCALL, "mfcall"], #primary_expr_deref);} | primary_expr_tail ; // only here a function call is ok also (all other places must be an array) primary_expr : ! sl:STRING_LITERAL // also a CONSTANT { #primary_expr=#[CONSTANT,sl->getText()]; #primary_expr->Text2String(); #primary_expr->SetLine( #sl->getLine()); } | numeric_constant | primary_expr_deref ; // only one INC/DEC allowed per target decinc_expr : primary_expr ( i:INC^ { #i->setType( POSTINC); #i->setText( "_++");} | d:DEC^ { #d->setType( POSTDEC); #d->setText( "_--");} | // empty ) | INC^ primary_expr | DEC^ primary_expr ; exponential_expr : decinc_expr (POW^ decinc_expr )* ; multiplicative_expr : exponential_expr ( ( ASTERIX^ | MATRIX_OP1^ | MATRIX_OP2^ | SLASH^ | MOD_OP^ ) exponential_expr )* ; // only one allowed per target signed_multiplicative_expr : PLUS! multiplicative_expr | m:MINUS^ multiplicative_expr { #m->setType( UMINUS); #m->setText( "u-"); } | multiplicative_expr ; additive_expr : (signed_multiplicative_expr | neg_expr) ( ( PLUS^ | MINUS^ | LTMARK^ | GTMARK^ ) (multiplicative_expr | neg_expr) )* // // | NOT_OP^ additive_expr // multiple allowed // | NOT_OP^ multiplicative_expr // multiple not allowed // // true precedence of ~ operator // | LOG_NEG^ multiplicative_expr // multiple not allowed ; neg_expr : NOT_OP^ multiplicative_expr // true precedence of ~ operator | LOG_NEG^ multiplicative_expr ; relational_expr : additive_expr ( ( EQ_OP^ | NE_OP^ | LE_OP^ | LT_OP^ | GE_OP^ | GT_OP^ ) additive_expr )* ; boolean_expr : relational_expr ( ( AND_OP^ | OR_OP^ | XOR_OP^ ) relational_expr )* ; logical_expr : boolean_expr ( ( LOG_AND^ | LOG_OR^ ) boolean_expr )* ; // expr is referenced in several places expr : logical_expr ( QUESTION^ expr COLON! expr )? ; // the GDL Lexer ********************************************* class GDLLexer extends Lexer; options { charVocabulary = '\3'..'\377'; caseSensitive=false; testLiterals =false; caseSensitiveLiterals=false; exportVocab=GDL; k=3; defaultErrorHandler = false; // defaultErrorHandler = true; // analyzerDebug=true; } // the reserved words tokens { AND_OP="and"; BEGIN="begin"; // BREAK="break"; CASE="case"; COMMON="common"; COMPILE_OPT="compile_opt"; // CONTINUE="continue"; DO="do"; ELSE="else"; END="end"; ENDCASE="endcase"; ENDELSE="endelse"; ENDFOR="endfor"; ENDFOREACH="endforeach"; ENDIF="endif"; ENDREP="endrep"; ENDSWITCH="endswitch"; ENDWHILE="endwhile"; EQ_OP="eq"; FOR="for"; FOREACH="foreach"; FORWARD="forward_function"; FUNCTION="function"; GE_OP="ge"; GOTO="goto"; GT_OP="gt"; IF="if"; INHERITS="inherits"; LE_OP="le"; LT_OP="lt"; MOD_OP="mod"; NE_OP="ne"; NOT_OP="not"; OF="of"; ON_IOERROR="on_ioerror"; OR_OP="or"; PRO="pro"; REPEAT="repeat"; // RETURN="return"; SWITCH="switch"; THEN="then"; UNTIL="until"; WHILE="while"; XOR_OP="xor"; } { // Stuff for include files (@filename) private: std::unique_ptr inputFile; // stores ifsteam* and deletes // it when it is deleted itself antlr::TokenStreamSelector* selector; GDLLexer* mainLexerPtr; GDLParser* parserPtr; int lineContinuation; public: ~GDLLexer() { if( mainLexerPtr != this) selector->pop(); // return to old lexer/stream else { delete parserPtr; delete selector; } } // main lexer constructor GDLLexer( std::istream& in, const std::string &f, unsigned int compileOptIn, const std::string &pro="", bool searchForPro=true) : antlr::CharScanner(new antlr::CharBuffer(in),false), lineContinuation( 0) // : antlr::CharScanner(in) { setCaseSensitive(false); initLiterals(); selector= new antlr::TokenStreamSelector(); mainLexerPtr= this; parserPtr= new GDLParser( *selector, pro, searchForPro, compileOptIn); parserPtr->setFilename(f); parserPtr->initializeASTFactory( DNodeFactory); parserPtr->setASTFactory( &DNodeFactory ); // parserPtr->setASTNodeFactory( DNode::factory ); selector->addInputStream(this, f); selector->select(f); // start with main lexer // set line number to 0 in interactive mode if( f == "") { setLine(0); } // p=parserPtr; } // sublexer constructor GDLLexer( std::ifstream& in, const std::string& name, GDLLexer* parent) : antlr::CharScanner(new antlr::CharBuffer(in),false), inputFile( &in) // : antlr::CharScanner(new antlr::CharInputBuffer(in)) // : antlr::CharScanner(new antlr::CharBuffer(in)) { setCaseSensitive(false); initLiterals(); selector= parent->selector; mainLexerPtr= parent->mainLexerPtr; parserPtr= parent->parserPtr; // inputFile.Reset( &in); // make sure file // // gets deleted (closed) // // when lexer finish // make sure errors are reported in right file setFilename(name); parserPtr->setFilename(name); selector->push(this); } GDLParser& Parser() { return *parserPtr; } int LineContinuation() { int lC = lineContinuation; lineContinuation = 0; return lC; } void uponEOF() /*throws TokenStreamException, CharStreamException*/ { if ( selector->getCurrentStream() != mainLexerPtr ) { //if( this != mainLexerPtr ) { // make copy as we delete 'this' antlr::TokenStreamSelector* sel=selector; // here 'this' is deleted (pops selector) delete sel->getCurrentStream(); // make sure errors are reported in right file parserPtr->setFilename( static_cast(selector->getCurrentStream())->getFilename()); // don't allow EOF until main lexer. Force the // selector to retry for another token. sel->retry(); } } } protected STRING : ( ~('\n' | '\r' ))* ; INCLUDE! : '@' f:STRING { ANTLR_USING_NAMESPACE(std) // create lexer to handle include std::string name = f->getText(); // find comments on the same line size_t pos = name.find_first_of(';', 0); if( pos != std::string::npos) // remove them name = name.substr(0, pos); StrTrim(name); std::string appName=name; AppendIfNeeded(appName,".pro"); errno = 0; // zero it to detect errors bool found = CompleteFileName( appName); if( found) name = appName; else found = CompleteFileName( name); if( !found) { if( errno == EMFILE) throw GDLException( "Too many open files " "(recursive use of '@'?): " + name); else throw GDLException( "File not found: " + name); } std::ifstream* input = new std::ifstream(name.c_str()); if (!*input) { delete input; throw GDLException( "Error opening file. File: " + name); cerr << SysVar::MsgPrefix() << "Error opening file. File: " << name << endl; } if( *input) { new GDLLexer(*input,name,this); selector->retry(); // throws TokenStreamRetryException } } ; AND_OP_EQ: { LA(4) == '='}? "and="; ASTERIX_EQ:"*="; EQ_OP_EQ:"eq="; GE_OP_EQ:"ge="; GTMARK_EQ:">="; GT_OP_EQ:"gt="; LE_OP_EQ:"le="; LTMARK_EQ:"<="; LT_OP_EQ:"lt="; MATRIX_OP1_EQ:"#="; MATRIX_OP2_EQ:"##="; MINUS_EQ:"-="; MOD_OP_EQ: { LA(4) == '='}? "mod="; NE_OP_EQ:"ne="; OR_OP_EQ:"or="; PLUS_EQ:"+="; POW_EQ:"^="; SLASH_EQ:"/="; XOR_OP_EQ: { LA(4) == '='}? "xor="; MATRIX_OP1:'#'; MATRIX_OP2:"##"; METHOD:"::"; MEMBER:"->"; COMMA:','; COLON:':'; EQUAL:'='; LCURLY:'{'; RCURLY:'}'; LSQUARE:'['; RSQUARE:']'; LBRACE:'('; RBRACE:')'; QUESTION:'?'; EXCLAMATION:'!'; POW:'^'; ASTERIX:'*'; SLASH:'/'; MINUS:'-'; PLUS:'+'; INC:"++"; DEC:"--"; GTMARK:'>'; LTMARK:'<'; LOG_AND:"&&"; LOG_OR:"||"; LOG_NEG:'~'; protected END_U:; protected EOL : ( ("\r\n")=> "\r\n" // WINDOOF // | ("\n\r")=> "\n\r" // ??? | '\n' // Unix | '\r' // macintosh ) { newline(); } ; protected W // : ( '\003'..'\010' | '\t' | '\r' | '\013' | '\f' | '\016'.. '\037' | ' ' ) : (' ' | '\t' | '\014') // 014=FF ; protected D : ('0'..'9') ; protected L : ('a'..'z'|'_') ; protected H : ('a'..'f'|'0'..'9') ; protected O : ('0'..'7') ; protected B : ('0'..'1') ; protected EXP : ('e' (('+'|'-')? (D)+)? ) ; protected DBL_E : 'd' { $setText( "E");} ; protected DBL : (DBL_E (('+'|'-')? (D)+)? ) ; protected CONSTANT_HEX_BYTE:; protected CONSTANT_HEX_LONG:; protected CONSTANT_HEX_LONG64:; protected CONSTANT_HEX_I:; // integer or larger protected CONSTANT_HEX_INT:; protected CONSTANT_HEX_ULONG:; protected CONSTANT_HEX_ULONG64:; protected CONSTANT_HEX_UI:; protected CONSTANT_HEX_UINT:; protected CONSTANT_BYTE:; protected CONSTANT_LONG:; protected CONSTANT_LONG64:; protected CONSTANT_I:; // integer or larger if necessary protected CONSTANT_INT:; protected CONSTANT_ULONG:; protected CONSTANT_ULONG64:; protected CONSTANT_UI:; protected CONSTANT_UINT:; protected CONSTANT_OCT_BYTE:; protected CONSTANT_OCT_LONG:; protected CONSTANT_OCT_LONG64:; protected CONSTANT_OCT_I:; // integer or larger if necessary protected CONSTANT_OCT_INT:; protected CONSTANT_OCT_ULONG:; protected CONSTANT_OCT_ULONG64:; protected CONSTANT_OCT_UI:; protected CONSTANT_OCT_UINT:; protected CONSTANT_FLOAT:; protected CONSTANT_DOUBLE:; protected STRING_LITERAL:; protected DOT:; CONSTANT_OR_STRING_LITERAL // returns everything 'cleaned', ready to use // could be a string, but octals have priority : ('\"'(O)+ ( 'b' | 's' | "us" | "ub" | 'l' | 'u' | "ul" )?) => ('\"'! (O)+ { _ttype=CONSTANT_OCT_I; } // DEFINT32 ( 's'! { _ttype=CONSTANT_OCT_INT; } | 'b'! { _ttype=CONSTANT_OCT_BYTE; } | 'u'! { _ttype=CONSTANT_OCT_UI; } // DEFINT32 | "us"! { _ttype=CONSTANT_OCT_UINT; } | "ub"! { _ttype=CONSTANT_OCT_BYTE; } | 'l'! { _ttype=CONSTANT_OCT_LONG; } | "ll"! { _ttype=CONSTANT_OCT_LONG64; } | "ul"! { _ttype=CONSTANT_OCT_ULONG; } | "ull"! { _ttype=CONSTANT_OCT_ULONG64; } )?) | ('\''(H)+'\'' ( 'x' | "xs" | "xb" | "xl" | "xu" | "xus" | "xub" | "xul")) => ('\''! (H)+ '\''! 'x'! ( { _ttype=CONSTANT_HEX_I; } // DEFINT32 | 's'! { _ttype=CONSTANT_HEX_INT; } | 'b'! { _ttype=CONSTANT_HEX_BYTE; } | 'u'! { _ttype=CONSTANT_HEX_UI; } // DEFINT32 | "us"! { _ttype=CONSTANT_HEX_UINT; } | "ub"! { _ttype=CONSTANT_HEX_BYTE; } | 'l'! { _ttype=CONSTANT_HEX_LONG; } | "ll"! { _ttype=CONSTANT_HEX_LONG64; } | "ul"! { _ttype=CONSTANT_HEX_ULONG; } | "ull"! { _ttype=CONSTANT_HEX_ULONG64; } )) | ('\''(O)+'\'' ( 'o' | "os" | "ol" | "ou" | "oul")) => ('\''! (O)+ '\''! 'o'! ( { _ttype=CONSTANT_OCT_I; } // DEFINT32 | 's'! { _ttype=CONSTANT_OCT_INT; } | 'b'! { _ttype=CONSTANT_OCT_BYTE; } | 'u'! { _ttype=CONSTANT_OCT_UI; } // DEFINT32 | "us"! { _ttype=CONSTANT_OCT_UINT; } | "ub"! { _ttype=CONSTANT_OCT_BYTE; } | 'l'! { _ttype=CONSTANT_OCT_LONG; } | "ll"! { _ttype=CONSTANT_OCT_LONG64; } | "ul"! { _ttype=CONSTANT_OCT_ULONG; } | "ull"! { _ttype=CONSTANT_OCT_ULONG64; } )) | ('\''(B)+'\'' ( 'b' | "bs" | "bl" | "bu" | "bul" )) => ('\''! (B)+ '\''! 'b'! ( { _ttype=CONSTANT_BIN_I; } // DEFINT32 | 's'! { _ttype=CONSTANT_BIN_INT; } | 'b'! { _ttype=CONSTANT_BIN_BYTE; } | 'u'! { _ttype=CONSTANT_BIN_UI; } // DEFINT32 | "us"! { _ttype=CONSTANT_BIN_UINT; } | "ub"! { _ttype=CONSTANT_BIN_BYTE; } | 'l'! { _ttype=CONSTANT_BIN_LONG; } | "ll"! { _ttype=CONSTANT_BIN_LONG64; } | "ul"! { _ttype=CONSTANT_BIN_ULONG; } | "ull"! { _ttype=CONSTANT_BIN_ULONG64; } )) // strings in the original do not need trailing " or ' | '\"'! (~('\"'|'\r'|'\n')| '\"' '\"'! )* ( '\"'! | ) { _ttype=STRING_LITERAL; } | '\''! (~('\''|'\r'|'\n')| '\'' '\''! )* ( '\''! | ) { _ttype=STRING_LITERAL; } | (((D)+ (DBL | '.'(D)*(DBL))) | '.'(D)+(DBL)) => ( ( (D)+ ( DBL | '.'(D)*(DBL) ) ) | '.'(D)+(DBL)) { _ttype=CONSTANT_DOUBLE; } | (((D)+ (EXP | '.'(D)*(EXP)?)) | '.'(D)+(EXP)?) => ( ( (D)+ ( EXP | '.'(D)*(EXP)? ) ) | '.'(D)+(EXP)?) { _ttype=CONSTANT_FLOAT; } | '.' { _ttype=DOT; } | (D)+ { _ttype=CONSTANT_I; } ( 's'! { _ttype=CONSTANT_INT; } | 'b'! { _ttype=CONSTANT_BYTE; } | 'u'!('s'!)? { _ttype=CONSTANT_UINT; } | "ub"! { _ttype=CONSTANT_BYTE; } | 'l'! { _ttype=CONSTANT_LONG; } | "ll"! { _ttype=CONSTANT_LONG64; } | "ul"! { _ttype=CONSTANT_ULONG; } | "ull"! { _ttype=CONSTANT_ULONG64; } )? ; COMMENT : ';' (options {greedy=true;}: ~('\r'|'\n'))* {_ttype=antlr::Token::SKIP;} ; // look here for reserved words IDENTIFIER options { testLiterals = true; } : (L)(L|D|'$')* { std::string s=StrUpCase( $getText); $setText( s); } ; SYSVARNAME : ('!') (L|D|'$')+ { std::string s=StrUpCase( $getText); $setText( s); } ; END_MARKER : '&' { _ttype=END_U; } ; WHITESPACE : (W)+ { _ttype=antlr::Token::SKIP; } ; // this subrule eats lines to skip // 1. comment only lines // 2. blank lines protected SKIP_LINES : ( COMMENT | W | EOL )* ; // IDL ignores everything on the line after the $ CONT_STATEMENT : '$' (~('\r'|'\n'))* EOL SKIP_LINES { ++lineContinuation; _ttype=antlr::Token::SKIP; } ; END_OF_LINE : EOL SKIP_LINES { _ttype=END_U; } ; // just to know how many tokens are there protected MAX_TOKEN_NUMBER :; gdl-0.9.9/src/gdlc.i.g000066400000000000000000002350321340051421000143710ustar00rootroot00000000000000/* ************************************************************************* gdlc.i.g the GDL interpreter interprets the output of the treeparser/compiler ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@hotmail.com ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ header "pre_include_cpp" { // gets inserted before the antlr generated includes in the cpp file #include "includefirst.hpp" } header "post_include_cpp" { // gets inserted after the antlr generated includes in the cpp file #include "dinterpreter.hpp" #include "prognodeexpr.hpp" #include // tweaking ANTLR #define ASTNULL NULLProgNodeP #define ProgNodeP( xxx ) NULL /* ProgNodeP(antlr::nullAST) */ #define RefAST( xxx) ConvertAST( xxx) /* antlr::RefAST( Ref type) */ #define match( a, b) /* remove from source */ using namespace std; } header { // antlr header // make sure it gets included before the 'tweak' #include "GDLParser.hpp" #include "GDLTreeParser.hpp" #include #include //#include #include "datatypes.hpp" #include "objects.hpp" #include "dpro.hpp" #include "accessdesc.hpp" #include "initsysvar.hpp" #include "gdljournal.hpp" //class ProgNode; //typedef ProgNode* ProgNodeP; // tweaking ANTLR #define RefAST( xxx) ConvertAST( xxx) /* antlr::RefAST( Ref type) */ // print out AST tree //#define GDL_DEBUG //#undef GDL_DEBUG //#define GDL_DEBUG_HEAP bool IsEnabledGC(); // defined in GDLInterpreter.hpp with EnableGC(bool); void EnableGC(bool); } options { language="Cpp"; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the GDL TreeParser **************************************** class GDLInterpreter extends TreeParser; options { importVocab = GDL; // use vocab generated by lexer buildAST = false; // no modifying of AST anymore // no AST is created in the interpreter, hence we don't need ref counting // ASTLabelType = "RefDNode"; ASTLabelType = "ProgNodeP"; // defaultErrorHandler = true; defaultErrorHandler = false; // codeGenMakeSwitchThreshold = 2; // codeGenBitsetTestThreshold = 32; } { private: // ASTNULL replacement static ProgNode NULLProgNode; static ProgNodeP NULLProgNodeP; friend class BaseGDL; friend class ProgNode; friend class ARRAYDEFNode; friend class ARRAYDEF_GENERALIZED_INDGENNode; friend class STRUCNode; friend class NSTRUCNode; friend class NSTRUC_REFNode; friend class ASSIGNNode; friend class ASSIGN_ARRAYEXPR_MFCALLNode; friend class ASSIGN_REPLACENode; friend class PCALL_LIBNode;//: public CommandNode friend class MPCALLNode;//: public CommandNode friend class MPCALL_PARENTNode;//: public CommandNode friend class PCALLNode;//: public CommandNode friend class RETFNode; friend class RETPNode; friend class FORNode; friend class FOR_LOOPNode; friend class FOREACHNode; friend class FOREACH_LOOPNode; friend class FOREACH_INDEXNode; friend class FOREACH_INDEX_LOOPNode; friend class FOR_STEPNode; friend class FOR_STEP_LOOPNode; friend class KEYDEFNode; friend class KEYDEF_REFNode; friend class KEYDEF_REF_CHECKNode; friend class KEYDEF_REF_EXPRNode; friend class REFNode; friend class REF_CHECKNode; friend class REF_EXPRNode; friend class ParameterNode; friend class REFVNNode; friend class REF_CHECKVNNode; friend class REF_EXPRVNNode; friend class ParameterVNNode; friend class WRAPPED_FUNNode; friend class WRAPPED_PRONode; public: // RetCode returnCode; ProgNodeP GetNULLProgNodeP() const { return NULLProgNodeP;} void SetRetTree( ProgNodeP rT) { this->_retTree = rT; } ProgNodeP GetRetTree() const { return this->_retTree; } // void SetReturnCode( RetCode rC) // { // this->returnCode = rC; // } // enum RetCode { // RC_OK=0, // RC_BREAK, // RC_CONTINUE, // RC_RETURN, // RC_ABORT, // checked as retCode >= RC_RETURN // }; // code in: dinterpreter.cpp // procedure (searchForPro == true) or function (searchForPro == false) static bool SearchCompilePro(const std::string& pro, bool searchForPro); static int GetFunIx( ProgNodeP); static int GetFunIx( const std::string& subName); static int GetProIx( ProgNodeP);//const std::string& subName); static int GetProIx( const std::string& subName); DStructGDL* ObjectStruct( DObjGDL* self, ProgNodeP mp); void SetRootR( ProgNodeP tt, DotAccessDescT* aD, BaseGDL* r, ArrayIndexListT* aL); void SetRootL( ProgNodeP tt, DotAccessDescT* aD, BaseGDL* r, ArrayIndexListT* aL); // DStructGDL* ObjectStructCheckAccess( DObjGDL* self, ProgNodeP mp); // DStructDesc* GDLObjectDesc( DObjGDL* self, ProgNodeP mp); // code in: dinterpreter.cpp static void SetFunIx( ProgNodeP f); // triggers read/compile private: static void SetProIx( ProgNodeP f); // triggers read/compile static void AdjustTypes( BaseGDL*&, BaseGDL*&); protected: std::istringstream executeLine; // actual interactive executed line // std::vector tmpList; // void ClearTmpList() // { // std::vector::iterator i; // for(i = tmpList.begin(); i != tmpList.end(); ++i) // { delete *i;} // tmpList.clear(); // } class RetAllException { public: enum ExCode { NONE=0 // normal RETALL ,RUN // RETALL from .RUN command ,RESET // RETALL from .RESET command ,FULL_RESET // RETALL from .FULL_RESET command }; private: ExCode code; public: RetAllException( ExCode code_=NONE): code( code_) {} ExCode Code() { return code;} }; // code in: dinterpreter.cpp // static bool CompleteFileName(std::string& fn); -> str.cpp BaseGDL* returnValue; // holding the return value for functions BaseGDL** returnValueL; // holding the return value for l_functions bool interruptEnable; public: bool InterruptEnable() const { return interruptEnable;} // procedure (searchForPro == true) or function (searchForPro == false) static bool CompileFile(const std::string& f, const std::string& untilPro="", bool searchForPro=true); typedef RefHeap RefBaseGDL; typedef RefHeap RefDStructGDL; typedef std::map HeapT; typedef std::map ObjHeapT; protected: // typedef std::map HeapT; // typedef std::map ObjHeapT; // the following must be all static because several interpreter might be active // the heap for all dynamic variables // ease the handling, no memory leaks, gc possible static HeapT heap; static ObjHeapT objHeap; // index for newly allocated heap variables static SizeT objHeapIx; static SizeT heapIx; static EnvStackT callStack; static DLong stepCount; // smuggle optimizations in //#include "GDLInterpreterOptimized.inc" public: // triggers read/compile/interpret DStructDesc* GetStruct(const std::string& name, const ProgNodeP cN); // bool Called( std::string proName) // { // for( EnvStackT::reverse_iterator env = callStack.rbegin(); // env != callStack.rend(); // ++env) // { // //std::cout << (*env)->GetPro()->ObjectFileName() << std::endl; // if( proName == (*env)->GetPro()->ObjectFileName()) return true; // } // return false; // } // static bool IsEnabledGC() { return enable_GC;} static bool IsEnabledGC() { return true;} // the New... functions 'own' their BaseGDL* SizeT NewObjHeap( SizeT n=1, DStructGDL* var=NULL) { SizeT tmpIx=objHeapIx; for( SizeT i=0; i( objHeapIx++, (DStructGDL*)var)); return tmpIx; } SizeT NewHeap( SizeT n=1, BaseGDL* var=NULL) { SizeT tmpIx=heapIx; for( SizeT i=0; i( heapIx++, var)); return tmpIx; } static void FreeObjHeapDirect( DObj id, ObjHeapT::iterator it) { BaseGDL* del = (*it).second.get(); objHeap.erase( id); delete del; // delete (*it).second.get(); // objHeap.erase( id); } static void FreeObjHeap( DObj id) { if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if ( it != objHeap.end()) { FreeObjHeapDirect( id, it); // delete (*it).second.get(); // objHeap.erase( id); } } } static void FreeHeapDirect( DPtr id, HeapT::iterator it) { BaseGDL* del = (*it).second.get(); heap.erase( id); delete del; // delete (*it).second.get(); // // useless because of next: (*it).second.get() = NULL; // heap.erase( id); } static void FreeHeap( DPtr id) { if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end()) { FreeHeapDirect( id, it); // delete (*it).second.get(); // heap.erase( id); } } } static void HeapErase( DPtr id) // for LIST { if( id != 0) { heap.erase( id); } } static void FreeHeap( DPtrGDL* p) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; FreeHeap( id); } } static DByteGDL* IsEnabledGC( DPtrGDL* p) { SizeT nEl=p->N_Elements(); if( nEl == 0) return new DByteGDL( 0); DByteGDL* ret = new DByteGDL( p->Dim()); Guard guard(ret); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end() and (*it).second.IsEnabledGC()) (*ret)[ix] = 1; } } return guard.release(); } static DByteGDL* IsEnabledGCObj( DObjGDL* p) { SizeT nEl=p->N_Elements(); if( nEl == 0) return new DByteGDL( 0); DByteGDL* ret = new DByteGDL( p->Dim()); Guard guard(ret); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end() and (*it).second.IsEnabledGC()) (*ret)[ix] = 1; } } return guard.release(); } static void EnableGC( DPtr id, bool set=true) { if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end()) (*it).second.EnableGC(set); } } static void EnableGC( DPtrGDL* p, bool set=true) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; EnableGC( id, set); } } static void EnableAllGC() { SizeT nEl = heap.size(); for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) it->second.EnableGC(true); nEl = objHeap.size(); for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) it->second.EnableGC(true); } static void EnableGCObj( DObj id, bool set=true) { if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) (*it).second.EnableGC(set); } } static void EnableGCObj( DObjGDL* p, bool set=true) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; EnableGCObj( id, set); } } static void DecRef( DPtr id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "-- " << std::endl; #endif HeapT::iterator it=heap.find( id); if( it != heap.end()) { if( (*it).second.Dec() and (*it).second.IsEnabledGC() ) { #ifdef GDL_DEBUG_HEAP std::cout << "Out of scope (garbage collected): " << " at: " << callStack.back()->GetProName() << " line: " << callStack.back()->GetLineNumber() << std::endl; #endif FreeHeapDirect( id, it); } #ifdef GDL_DEBUG_HEAP else std::cout << " = " << (*it).second.Count() << std::endl; #endif } } } static void DecRef( DPtrGDL* p) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; DecRef( id); } } static void DecRefObj( DObj id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "-- " << std::endl; #endif ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) { if( (*it).second.Dec() and (*it).second.IsEnabledGC() ) { #ifdef GDL_DEBUG_HEAP std::cout << "Out of scope (garbage collected): " << " at: " << callStack.back()->GetProName() << " line: " << callStack.back()->GetLineNumber() << std::endl; #endif callStack.back()->ObjCleanup( id); // FreeObjHeapDirect( id, it); } #ifdef GDL_DEBUG_HEAP else std::cout << " = " << (*it).second.Count() << std::endl; #endif } } } static void DecRefObj( DObjGDL* p) { SizeT nEl=p->Size();//N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; DecRefObj( id); } } static void IncRef( DPtr id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "++ " << std::endl; #endif HeapT::iterator it=heap.find( id); if( it != heap.end()) { (*it).second.Inc(); #ifdef GDL_DEBUG_HEAP std::cout << " = " << (*it).second.Count() << std::endl; #endif } } } static void AddRef( DPtr id, SizeT add) { if( id != 0) { #ifdef GDL_DEBUG_HEAP std::cout << add << " + " << std::endl; #endif HeapT::iterator it=heap.find( id); if( it != heap.end()) { (*it).second.Add(add); } } } static SizeT RefCountHeap( DPtr id) { SizeT result = 0; if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end()) result = (*it).second.Count(); } return result; } static SizeT RefCountHeapObj( DObj id) { SizeT result = 0; if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) result = (*it).second.Count(); } return result; } static void IncRef( DPtrGDL* p) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; IncRef( id); } } static void IncRefObj( DObj id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "++ " << std::endl; #endif ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) { (*it).second.Inc(); } } } static void AddRefObj( DObj id, SizeT add) { if( id != 0) { #ifdef GDL_DEBUG_HEAP std::cout << add << " + " << std::endl; #endif ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) { (*it).second.Add(add); } } } static void IncRefObj( DObjGDL* p) { SizeT nEl=p->Size();//N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; IncRefObj( id); } } class HeapException {}; static BaseGDL*& GetHeap( DPtr ID) { HeapT::iterator it=heap.find( ID); if( it == heap.end()) throw HeapException(); return it->second.get(); } static BaseGDL* GetHeapNoThrow( DPtr ID) { HeapT::iterator it=heap.find( ID); if( it == heap.end()) return NULL; return it->second.get(); } static DStructGDL*& GetObjHeap( DObj ID) { ObjHeapT::iterator it=objHeap.find( ID); if( it == objHeap.end()) throw HeapException(); return it->second.get(); } // for overload functions static DSubUD* GetObjHeapOperator( DObj ID, int opIx) { if( ID == 0) return NULL; ObjHeapT::iterator it=objHeap.find( ID); if( it == objHeap.end()) return NULL; return it->second.get()->Desc()->GetOperator( opIx); } static DStructGDL* GetObjHeapNoThrow( DObj ID) { ObjHeapT::iterator it=objHeap.find( ID); if( it == objHeap.end()) return NULL; return it->second.get(); } // static DStructGDL*& GetObjHeap( DObj ID, ObjHeapT::iterator& it) // { // // ObjHeapT::iterator it=objHeap.find( ID); // it=objHeap.find( ID); // if( it == objHeap.end()) throw HeapException(); // return it->second.get(); // } static bool PtrValid( DPtr ID) { HeapT::iterator it=heap.find( ID); return (it != heap.end()); } static SizeT HeapSize() { return heap.size(); } static DPtr FindInHeap( BaseGDL** p) { for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { if( &it->second.get() == p) return it->first; } return 0; } // static BaseGDL** GetPtrToHeap( BaseGDL* p) // { // for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) // { // if( it->second.get() == p) // return &it->second.get(); // } // return NULL; // } static DPtrGDL* GetAllHeap() { SizeT nEl = heap.size(); if( nEl == 0) return new DPtrGDL( 0); DPtrGDL* ret = new DPtrGDL( dimension( &nEl, 1), BaseGDL::NOZERO); SizeT i=0; for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { IncRef( it->first); (*ret)[ i++] = it->first; } return ret; } // no ref counting here static std::vector* GetAllHeapSTL() { SizeT nEl = heap.size(); if( nEl == 0) return new std::vector(); std::vector* ret = new std::vector( nEl); SizeT i=0; for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { (*ret)[ i++] = it->first; } return ret; } static bool ObjValid( DObj ID) { ObjHeapT::iterator it=objHeap.find( ID); return (it != objHeap.end()); } static SizeT ObjHeapSize() { return objHeap.size(); } // static DObj FindInObjHeap( BaseGDL** p) // { // for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) // { // if( &it->second == reinterpret_cast(p)) // return it->first; // } // return 0; // } static DObjGDL* GetAllObjHeap() { SizeT nEl = objHeap.size(); if( nEl == 0) return new DObjGDL( 0); DObjGDL* ret = new DObjGDL( dimension( &nEl, 1), BaseGDL::NOZERO); SizeT i=0; for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) { IncRefObj( it->first); (*ret)[ i++] = it->first; } return ret; } // no ref counting here static std::vector* GetAllObjHeapSTL() { SizeT nEl = objHeap.size(); if( nEl == 0) return new std::vector(); std::vector* ret = new std::vector( nEl); SizeT i=0; for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) { (*ret)[ i++] = it->first; } return ret; } static void ResetHeap() // purges both heaps { for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { delete (*it).second.get(); heap.erase( it->first); } for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) { delete (*it).second.get(); objHeap.erase( it->first); } // The counters are reset for easier human readability. heapIx = 1; objHeapIx = 1; } // name of data static const std::string Name( BaseGDL* p) // const { return callStack.back()->GetString( p); } static const std::string Name( BaseGDL** p) // const { assert( *p == NULL); DPtr h = FindInHeap( p); if( h != 0) return std::string(""; // DObj o = FindInObjHeap( p); // if( o != 0) return std::string(""; return "<(ptr to undefined expression not found on the heap)>"; } // compiler (lexer, parser, treeparser) def in dinterpreter.cpp static void ReportCompileError( GDLException& e, const std::string& file = ""); // interpreter static void ReportError( GDLException& e, const std::string &emsg, bool dumpStack=true) { DString msgPrefix = SysVar::MsgPrefix(); std::cout << std::flush; if( dumpStack) { if( e.Prefix()) { std::cerr << msgPrefix << e.toString() << std::endl; lib::write_journal_comment(msgPrefix+e.toString()); } else { std::cerr << e.toString() << std::endl; lib::write_journal_comment(e.toString()); } } std::cerr << msgPrefix << emsg << " " << std::left << std::setw(16) << callStack.back()->GetProName(); std::string file=callStack.back()->GetFilename(); if( file != "") { SizeT line = e.getLine(); if( line != 0) { std::cerr << std::right << std::setw(6) << line; } else { std::cerr << std::right << std::setw(6) << ""; } std::cerr << std::left << " " << file; } std::cerr << std::endl; if( dumpStack) DumpStack( emsg.size() + 1); } static void DumpStack( SizeT w) { DString msgPrefix = SysVar::MsgPrefix(); // EnvStackT::reverse_iterator upEnv = callStack.rbegin(); // //EnvStackT::reverse_iterator env = upEnv++; // upEnv++; // for(; // upEnv != callStack.rend(); // ++upEnv /*,++env*/) long actIx = callStack.size() - 2; for( ; actIx >= 0; --actIx) { EnvStackT::pointer_type upEnv = callStack[ actIx]; std::cerr << msgPrefix << std::right << std::setw( w) << ""; std::cerr << std::left << std::setw(16) << upEnv->GetProName(); std::string file = upEnv->GetFilename(); if( file != "") { // ProgNodeP cNode= (*env)->CallingNode(); // if( cNode != NULL) // { // std::cerr << std::right << std::setw(6) << cNode->getLine(); // } // else // { // std::cerr << std::right << std::setw(6) << ""; // } // ProgNodeP cNode= (*env)->CallingNode(); // if( cNode != NULL && cNode->getLine() != 0) // { // (*upEnv)->SetLineNumber( cNode->getLine()); // } int lineNumber = upEnv->GetLineNumber(); if( lineNumber != 0) { std::cerr << std::right << std::setw(6) << lineNumber; } else { std::cerr << std::right << std::setw(6) << ""; } std::cerr << std::left << " " << file; } std::cerr << std::endl; } } static void DebugMsg( ProgNodeP _t, const std::string& msg) { DString msgPrefix = SysVar::MsgPrefix(); std::cout << std::flush; std::cerr << msgPrefix << msg << std::left << std::setw(16) << callStack.back()->GetProName(); std::string file=callStack.back()->GetFilename(); if( file != "") { ProgNodeP eNode = _t; if( eNode != NULL) { std::cerr << std::right << std::setw(6) << eNode->getLine(); } else { std::cerr << std::right << std::setw(6) << ""; } std::cerr << std::left << " " << file; } std::cerr << std::endl; } static void RetAll( RetAllException::ExCode c=RetAllException::NONE) { throw RetAllException( c); } static EnvStackT& CallStack() { return callStack;} // the callstack // static EnvBaseT* CallStackBack() { return callStack.back();} static EnvUDT* CallStackBack() { return callStack.back();} std::string GetClearActualLine() { std::string ret = executeLine.str(); executeLine.str(""); return ret; } RetCode NewInterpreterInstance(SizeT lineOffset); // code in dinterpreter.cpp ~GDLInterpreter() { } } //*********************************************************************** // interpreter functions ************************************************ //*********************************************************************** // intercative usage interactive returns[ RetCode retCode] // { // return interactive_statement_list(_t); // } // : retCode=statement_list // ; // // used from interactive nulls line number // interactive_statement_list returns[ RetCode retCode] { for (; _t != NULL;) { //_t->setLine(0); retCode=statement(_t); _t = _retTree; if( retCode != RC_OK) break; // break out if non-regular } _retTree = _t; return retCode; } : (retCode=statement { if( retCode != RC_OK) break; // break out if non-regular } )+ ; // execute statement execute returns[ RetCode retCode] { // RetCode retCode; ValueGuard guard( interruptEnable); interruptEnable = false; return statement_list(_t); } : retCode=statement_list ; // used to call functions // same as statement list, but different behaviour for returncodes call_fun returns[ BaseGDL* res] { res = NULL; assert(returnValue == NULL); RetCode retCode; for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; // if( retCode == RC_RETURN) if( retCode >= RC_RETURN) { res=returnValue; returnValue=NULL; // already done in RETFNode::Run() : // if( returnValueL != NULL) // { // callStack.back()->SetPtrToReturnValue( returnValueL); // returnValueL = NULL; // } break; } } // default return value if none was set if( res == NULL) res = new DIntGDL( 0); _retTree = _t; return res; } : (retCode=statement )* ; call_lfun returns[ BaseGDL** res] { res = NULL; assert(returnValueL == NULL); RetCode retCode; ProgNodeP in = _t; for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; if( retCode >= RC_RETURN) { res=returnValueL; returnValueL=NULL; break; } } // res must be defined here if( res == NULL) throw GDLException( in, "Function "+callStack.back()->GetProName()+ " must return a global left-value in this context.", false,false); _retTree = _t; return res; } : (retCode=statement )* ; // used to call procedures call_pro { RetCode retCode; for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; // added RC_ABORT here if( retCode >= RC_RETURN) break; } _retTree = _t; return; } : (retCode=statement )* ; // used on many occasions statement_list returns[ RetCode retCode] { for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; if( retCode != RC_OK) break; // break out if non-regular } _retTree = _t; return retCode; } : (retCode=statement )+ ; statement returns[ RetCode retCode] { // ProgNodeP& actPos = statement_AST_in; assert( _t != NULL); ProgNodeP last; _retTree = _t; // if( callStack.back()->GetLineNumber() == 0) // if( _t->getLine() != 0) // callStack.back()->SetLineNumber( _t->getLine()); } : { do { // if( _t->getLine() != 0) // callStack.back()->SetLineNumber( _t->getLine()); last = _retTree; // track actual line number callStack.back()->SetLineNumber( last->getLine()); retCode = last->Run(); // Run() sets _retTree } while( _retTree != NULL && retCode == RC_OK && !(sigControlC && interruptEnable) && (debugMode == DEBUG_CLEAR)); // commented out, because we are only at the last statement // if( _retTree != NULL) // last = _retTree; goto afterStatement; } ( // note: assignment must take care to update the owner of lvalue // a real copy must be performed (creating a new BaseGDL) ASSIGN | ASSIGN_ARRAYEXPR_MFCALL | ASSIGN_REPLACE | PCALL_LIB | MPCALL | MPCALL_PARENT | PCALL | DEC | INC | FOR | FOR_LOOP | FOREACH | FOREACH_LOOP | FOREACH_INDEX | FOREACH_INDEX_LOOP | FOR_STEP | FOR_STEP_LOOP | REPEAT | REPEAT_LOOP | WHILE | IF | IF_ELSE | CASE | SWITCH | BLOCK | LABEL | ON_IOERROR_NULL | ON_IOERROR | BREAK | CONTINUE | GOTO | RETF | RETP ) // control-c and debugging { afterStatement:; // possible optimization: make sigControlC a debugMode if( interruptEnable && sigControlC) { DebugMsg( last, "Interrupted at: "); sigControlC = false; retCode = NewInterpreterInstance( last->getLine());//-1); } else if( debugMode != DEBUG_CLEAR) { if( debugMode == DEBUG_STOP) { DebugMsg( last, "Stop encountered: "); if( !interruptEnable) debugMode = DEBUG_PROCESS_STOP; } if( debugMode == DEBUG_STEP) { if( stepCount == 1) { stepCount = 0; DebugMsg( last, "Stepped to: "); debugMode = DEBUG_CLEAR; retCode = NewInterpreterInstance( last->getLine());//-1); } else { --stepCount; #ifdef GDL_DEBUG std::cout << "stepCount-- = " << stepCount << std::endl; #endif } } // else if( debugMode == DEBUG_SKIP) // { // if( last != NULL) // { // last = last->getNextSibling(); // DebugMsg( last, "Skipped to: "); // } // else // DebugMsg( last, "Cannot SKIP fro here"); // debugMode = DEBUG_CLEAR; // retCode = RC_OK; // } else if( interruptEnable) { if( debugMode == DEBUG_PROCESS_STOP) { DebugMsg( last, "Stepped to: "); } debugMode = DEBUG_CLEAR; retCode = NewInterpreterInstance( last->getLine());//-1); } else { retCode = RC_ABORT; } } return retCode; } ; exception catch [ GDLException& e] { // reset _retTree to last statement // (might otherwise be inside an expression in which case // .CONTINUE does not work) _retTree = last; if( last->IsWrappedNode()) throw e; // WRAPPED_... nodes should not stop inside // set !ERROR_STATE sys var DStructDesc* errorStateDesc = SysVar::Error_State()->Desc(); //MUST NOT BE STATIC, due to .reset static unsigned nameTag = errorStateDesc->TagIndex( "NAME"); static unsigned codeTag = errorStateDesc->TagIndex( "CODE"); static unsigned msgTag = errorStateDesc->TagIndex( "MSG"); if( e.IsIOException()) { assert( dynamic_cast< GDLIOException*>( &e) != NULL); // set the jump target - also logs the jump ProgNodeP onIOErr = static_cast(callStack.back())->GetIOError(); if( onIOErr != NULL) { DStructGDL* errorState = SysVar::Error_State(); (*static_cast( errorState->GetTag( nameTag)))[0] = "IDL_M_FAILURE"; (*static_cast( errorState->GetTag( codeTag)))[0] = e.ErrorCode(); SysVar::SetErrError( e.ErrorCode()); (*static_cast( errorState->GetTag( msgTag)))[0] = e.getMessage(); SysVar::SetErr_String( e.getMessage()); _retTree = onIOErr; return RC_OK; } } // handle CATCH ProgNodeP catchNode = callStack.back()->GetCatchNode(); if( catchNode != NULL) { DStructGDL* errorState = SysVar::Error_State(); (*static_cast( errorState->GetTag( nameTag)))[0] = "IDL_M_FAILURE"; (*static_cast( errorState->GetTag( codeTag)))[0] = e.ErrorCode(); SysVar::SetErrError( e.ErrorCode()); (*static_cast( errorState->GetTag( msgTag)))[0] = e.getMessage(); SysVar::SetErr_String( e.getMessage()); BaseGDL** catchVar = callStack.back()->GetCatchVar(); GDLDelete(*catchVar); *catchVar = new DLongGDL( e.ErrorCode()); _retTree = catchNode; return RC_OK; } EnvUDT* targetEnv = e.GetTargetEnv(); if( targetEnv == NULL) { // initial exception, set target env // set !ERROR_STATE here DStructGDL* errorState = SysVar::Error_State(); (*static_cast( errorState->GetTag( nameTag)))[0] = "IDL_M_FAILURE"; (*static_cast( errorState->GetTag( codeTag)))[0] = e.ErrorCode(); SysVar::SetErrError( e.ErrorCode()); (*static_cast( errorState->GetTag( msgTag)))[0] = e.getMessage(); SysVar::SetErr_String( e.getMessage()); // look if ON_ERROR is set somewhere // for( EnvStackT::reverse_iterator i = callStack.rbegin(); // i != callStack.rend(); ++i) for( long ix = callStack.size() - 1; ix>=0; --ix) { EnvUDT** i = &callStack[ ix]; DLong oE = -1; EnvUDT* envUD = dynamic_cast(*i); if( envUD != NULL) oE = envUD->GetOnError(); if( oE != -1) { // oE was set // 0 -> stop here if( oE == 0) targetEnv = static_cast(callStack.back()); // 1 -> $MAIN$ else if( oE == 1) { EnvUDT* cS_begin = static_cast(callStack[0]); // static_cast(*callStack.begin()); targetEnv = cS_begin; } // 2 -> caller of routine which called ON_ERROR else if( oE == 2) { // set to caller, handle nested while( ix > 0 && static_cast(callStack[--ix])->GetOnError() == 2) ; // just set ix EnvUDT* iUDT = static_cast(callStack[ix]); targetEnv = iUDT; // while( static_cast(*(++i))->GetOnError() == 2 // && i != callStack.rend()); // if( i == callStack.rend()) // { // EnvUDT* cS_begin = // static_cast(*callStack.begin()); // targetEnv = cS_begin; // } // else // { // EnvUDT* iUDT = static_cast(*i); // targetEnv = iUDT; // } } // 3 -> routine which called ON_ERROR else if( oE == 3) { EnvUDT* iUDT = static_cast(callStack[ix]); // EnvUDT* iUDT = static_cast(*i); targetEnv = iUDT; } // State where error occured // if( e.getLine() == 0 && _t != NULL) // e.SetLine( _t->getLine()); // if( e.getLine() == 0 && _retTree != NULL) // e.SetLine( _retTree->getLine()); if( e.getLine() == 0 && last != NULL) e.SetLine( last->getLine()); if( interruptEnable) ReportError(e, "Error occurred at:"); // remeber where to stop e.SetTargetEnv( targetEnv); if( targetEnv->GetLineNumber() != 0) e.SetLine( targetEnv->GetLineNumber()); // ProgNodeP errorNodeP = targetEnv->CallingNode(); // e.SetErrorNodeP( errorNodeP); // break on first occurence of set oE break; } } } if( targetEnv != NULL && targetEnv != callStack.back()) { throw e; // rethrow } lib::write_journal( GetClearActualLine()); // many low level routines don't have errorNode info // set line number here in this case // if( e.getLine() == 0 && _t != NULL) // e.SetLine( _t->getLine()); // if( e.getLine() == 0 && _retTree != NULL) // e.SetLine( _retTree->getLine()); // if( e.getLine() == 0 && actPos != NULL) // e.SetLine( actPos->getLine()); if( interruptEnable) { if( e.getLine() == 0 && last != NULL) e.SetLine( last->getLine()); // tell where we are ReportError(e, "Execution halted at:", targetEnv == NULL); retCode = NewInterpreterInstance(e.getLine());//-1); } else { DString msgPrefix = SysVar::MsgPrefix(); if( e.Prefix()) { std::cerr << msgPrefix << e.toString() << std::endl; lib::write_journal_comment(msgPrefix+e.toString()); } else { std::cerr << e.toString() << std::endl; lib::write_journal_comment(e.toString()); } retCode = RC_ABORT; } return retCode; } // catch [ GDLException& e] // *************************************************************************** // the expressions *********************************************************** // *************************************************************************** l_deref returns [BaseGDL** res] { ProgNodeP retTree = _t->getNextSibling(); BaseGDL* e1; ProgNodeP evalExpr = _t->getFirstChild(); if( NonCopyNode( evalExpr->getType())) { e1 = evalExpr->EvalNC(); } else { BaseGDL** ref = evalExpr->EvalRefCheck(e1); if( ref == NULL) { // use new env if set (during parameter parsing) EnvBaseT* actEnv = DInterpreter::CallStackBack()->GetNewEnv(); if( actEnv == NULL) actEnv = DInterpreter::CallStackBack(); assert( actEnv != NULL); // this is crucial, a guard does not work here as a temporary // ptr will be cleaned up at return from this function actEnv->DeleteAtExit( e1); } else e1 = *ref; } if( e1 == NULL || e1->Type() != GDL_PTR) throw GDLException( evalExpr, "Pointer type required in this context: "+Name(e1),true,false); DPtrGDL* ptr=static_cast(e1); DPtr sc; if( !ptr->Scalar(sc)) throw GDLException( _t, "Expression must be a scalar in this context: "+Name(e1),true,false); if( sc == 0) throw GDLException( _t, "Unable to dereference NULL pointer: "+Name(e1),true,false); try { res = &GetHeap(sc); } catch( HeapException) { throw GDLException( _t, "Invalid pointer: "+Name(e1),true,false); } _retTree = retTree; return res; } : DEREF ; // l expressions for DEC/INC ******************************** // l_decind_expr is the only function called from external // l_decinc_expr is the only external function of the l_decinc_* expressions // called from l_decinc_array_expr l_decinc_indexable_expr [ BaseGDL*& res] returns [BaseGDL** e] { e = _t->LEval(); res = *e; if( res == NULL) throw GDLException( _t, "Variable is undefined: "+Name(e),true,false); return e; } : e=l_function_call_internal | e=l_deref | e=l_defined_simple_var | e=l_sys_var ; // called from l_decinc_expr l_decinc_array_expr [int dec_inc, BaseGDL*& res] returns [BaseGDL** e] { ArrayIndexListT* aL; ArrayIndexListGuard guard; if( _t->getType() == ARRAYEXPR) { ProgNodeP arrExNP = _t; // match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); BaseGDL** tmp =_t->LEval();// l_decinc_indexable_expr(_t, res); res = *tmp; if( res == NULL) throw GDLException( _t, "Variable is undefined: " + Name(tmp), true,false); _t = _t->getNextSibling(); aL=arrayindex_list(_t,!res->IsAssoc()); _retTree = arrExNP->getNextSibling(); guard.reset( aL); aL->SetVariable( res); if( dec_inc == DECSTATEMENT) { res->DecAt( aL); return NULL; } if( dec_inc == INCSTATEMENT) { res->IncAt( aL); return NULL; } if( dec_inc == DEC || dec_inc == DEC_REF_CHECK) res->DecAt( aL); else if( dec_inc == INC || dec_inc == INC_REF_CHECK) res->IncAt( aL); BaseGDL* resBefore = res; res = resBefore->Index( aL); if( dec_inc == POSTDEC) resBefore->DecAt( aL); else if( dec_inc == POSTINC) resBefore->IncAt( aL); return NULL; } else { e =_t->LEval();// l_decinc_indexable_expr(_t, res); res = *e; if( res == NULL) throw GDLException( _t, "Variable is undefined: " + Name(e), true,false); _retTree = _t->getNextSibling(); // e=l_decinc_indexable_expr(_t, res); // _t = _retTree; if( dec_inc == DECSTATEMENT || dec_inc == DEC_REF_CHECK) { res->Dec(); return e; } if( dec_inc == INCSTATEMENT || dec_inc == INC_REF_CHECK) { res->Inc(); return e; } if( dec_inc == DEC) res->Dec(); else if( dec_inc == INC) res->Inc(); BaseGDL* resBefore = res; res = resBefore->Dup(); if( dec_inc == POSTDEC) resBefore->Dec(); else if( dec_inc == POSTINC) resBefore->Inc(); return e; } assert(false); return e; // not used _______________________________________ // ------------------------------------------------ } : ARRAYEXPR | e= l_decinc_indexable_expr[ res] ; // struct assignment // MAIN function: called from l_decinc_expr l_decinc_dot_expr [int dec_inc] returns [BaseGDL* res] { ProgNodeP dot = _t; //match(antlr::RefAST(_t),DOT); _t = _t->getFirstChild(); SizeT nDot=dot->nDot; Guard aD( new DotAccessDescT(nDot+1)); l_dot_array_expr(_t, aD.Get()); _t = _retTree; while( _t != NULL) { tag_array_expr(_t, aD.Get()); _t = _retTree; } _retTree = dot->getNextSibling(); if( dec_inc == DECSTATEMENT) { aD.Get()->Dec(); return NULL; } if( dec_inc == INCSTATEMENT) { aD.Get()->Inc(); return NULL; } if( dec_inc == DEC || dec_inc == DEC_REF_CHECK) aD.Get()->Dec(); //*** aD->Assign( dec_inc); else if( dec_inc == INC || dec_inc == INC_REF_CHECK) aD.Get()->Inc(); res=aD.Get()->ADResolve(); if( dec_inc == POSTDEC) aD.Get()->Dec(); else if( dec_inc == POSTINC) aD.Get()->Inc(); return res; } : DOT ; // l_decinc_expr is only used in dec/inc statements and within itself l_decinc_expr [int dec_inc, BaseGDL*& res] returns [BaseGDL** refRet] { refRet = NULL; BaseGDL* e1; ProgNodeP startNode = _t; } : #(QUESTION e1=expr { Guard e1_guard(e1); if( e1->True()) { refRet=l_decinc_expr(_t, dec_inc, res); } else { _t=_t->GetNextSibling(); // jump over 1st expression refRet=l_decinc_expr(_t, dec_inc, res); } } ) // trinary operator | #(ASSIGN { Guard r_guard; } ( e1=indexable_expr | e1=indexable_tmp_expr { r_guard.Init( e1);} | e1=lib_function_call_internal { // if( !callStack.back()->Contains( e1)) if( callStack.back()->GetPtrToReturnValueNull() == NULL) r_guard.Init( e1); // guard if no global data } ) { ProgNodeP l = _t; BaseGDL** tmp; } tmp=l_expr_internal[ e1] // assign { _t = l; } refRet=l_decinc_expr[dec_inc, res] ) | #(ASSIGN_ARRAYEXPR_MFCALL { Guard r_guard; } ( e1=indexable_expr | e1=indexable_tmp_expr { r_guard.Init( e1);} | e1=lib_function_call_internal { // if( !callStack.back()->Contains( e1)) if( callStack.back()->GetPtrToReturnValueNull() == NULL) r_guard.Init( e1); // guard if no global data } ) { ProgNodeP l = _t; BaseGDL** tmp; // try MFCALL try { tmp=l_arrayexpr_mfcall_as_mfcall(l); if( e1 != (*tmp)) { delete *tmp; if( r_guard.Get() == e1) *tmp = r_guard.release(); else *tmp = e1->Dup(); } refRet=l_decinc_expr( l, dec_inc, res); } catch( GDLException& ex) { // try ARRAYEXPR try { tmp=l_arrayexpr_mfcall_as_arrayexpr(l, e1); } catch( GDLException& ex2) { throw GDLException(ex.toString() + " or "+ex2.toString()); } refRet=l_decinc_expr( l, dec_inc, res); } } ) | #(ASSIGN_REPLACE { Guard r_guard; } ( e1=tmp_expr { r_guard.Init( e1); } | e1=lib_function_call_internal { // if( !callStack.back()->Contains( e1)) if( callStack.back()->GetPtrToReturnValueNull() == NULL) r_guard.Init( e1); } ) { ProgNodeP l = _t; BaseGDL** tmp; } // tmp=l_expr_internal[ e1] // assign ( tmp=l_function_call_internal // FCALL_LIB, MFCALL, MFCALL_PARENT, FCALL | tmp=l_deref // DEREF | tmp=l_simple_var // VAR, VARPTR ) { if( e1 != (*tmp)) { delete *tmp; if( r_guard.Get() == e1) *tmp = r_guard.release(); else *tmp = e1->Dup(); } } { _t = l; } refRet=l_decinc_expr[dec_inc, res] ) | refRet=l_decinc_array_expr[dec_inc, res] | #(ARRAYEXPR_MFCALL { ProgNodeP mark = _t; _t = _t->getNextSibling(); // step over DOT BaseGDL* self; } //BaseGDL** e = l_arrayexpr_mfcall_as_mfcall( _t); self=expr mp2:IDENTIFIER { Guard self_guard(self); EnvUDT* newEnv; DObjGDL* selfObj = NULL; if( self->Type() == GDL_OBJ) selfObj = static_cast( self); try { newEnv=new EnvUDT( selfObj, mp2, "", EnvUDT::LFUNCTION); self_guard.release(); } catch( GDLException& ex) { _t = mark; res=l_decinc_dot_expr(_t, dec_inc); _retTree = startNode->getNextSibling(); return refRet; } } // no exception caught parameter_def[ newEnv] { // push environment onto call stack callStack.push_back(newEnv); // make the call BaseGDL** ee=call_lfun(static_cast( newEnv->GetPro())->GetTree()); BaseGDL* e = *ee; if( e == NULL) throw GDLException( _t, "Variable is undefined: "+Name(ee),true,false); if( dec_inc == DECSTATEMENT || dec_inc == DEC_REF_CHECK) { e->Dec(); _retTree = startNode->getNextSibling(); return ee; } if( dec_inc == INCSTATEMENT || dec_inc == INC_REF_CHECK) { e->Inc(); _retTree = startNode->getNextSibling(); return ee; } if( dec_inc == DEC) e->Dec(); else if( dec_inc == INC) e->Inc(); // res = e->Dup(); if( dec_inc == POSTDEC) e->Dec(); else if( dec_inc == POSTINC) e->Inc(); _retTree = startNode->getNextSibling(); return ee; } ) | res=l_decinc_dot_expr[dec_inc] | e1=r_expr { delete e1; throw GDLException( _t, "Expression not allowed with decrement/increment operator.",true,false); } | CONSTANT //e1=constant_nocopy { throw GDLException( _t, "Constant not allowed with decrement/increment operator.",true,false); } ; // l expressions for assignment ************************* // an indexable expression must be defined l_indexable_expr returns [BaseGDL** res] { res = _t->LEval(); if( *res == NULL) { // check not needed for SYSVAR assert( _t->getType() != SYSVAR); if( _t->getType() == VARPTR) throw GDLException( _t, "Common block variable is undefined: "+ callStack.back()->GetString( *res),true,false); if( _t->getType() == VAR) throw GDLException( _t, "Variable is undefined: "+ callStack.back()->GetString(_t->varIx),true,false); throw GDLException( _t, "Heap variable is undefined: "+Name(res),true,false); } _retTree = _t->getNextSibling(); return res; } : EXPR // for l_dot_array_expr | res=l_function_call_internal | res=l_arrayexpr_mfcall_as_mfcall | res=l_deref | res=l_defined_simple_var | res=l_sys_var ; // called only from unused part of l_expr_internal unused_l_array_expr [BaseGDL* right] returns [BaseGDL** res] { ArrayIndexListT* aL; } : #(ARRAYEXPR res=l_indexable_expr aL=arrayindex_list[ false]) ; l_dot_array_expr [DotAccessDescT* aD] // 1st { ArrayIndexListT* aL; BaseGDL** rP; if( _t->getType() == ARRAYEXPR) { rP=l_indexable_expr(_t->getFirstChild()); aL=arrayindex_list(_retTree,!(*rP)->IsAssoc()); _retTree = _t->getNextSibling(); SetRootL( _t, aD, *rP, aL); } else // case ARRAYEXPR_MFCALL: // case DEREF: // case EXPR: // case FCALL: // case FCALL_LIB: // case MFCALL: // case MFCALL_PARENT: // case SYSVAR: // case VAR: // case VARPTR: { rP=l_indexable_expr(_t); SetRootL( _t, aD, *rP, NULL); } return; // _retTree = _t; } : #(ARRAYEXPR rP=l_indexable_expr aL=arrayindex_list[ false]) | rP=l_indexable_expr ; // l_expr_internal is only used in assignment and within itself l_expr_internal [BaseGDL* right] returns [BaseGDL** res] { res = _t->LExpr( right); _retTree = _t->getNextSibling(); return res; BaseGDL* e1; } : QUESTION | res=unused_l_array_expr[ right] | res=l_sys_var // sysvars cannot change their type | res=l_function_call_internal // FCALL_LIB, MFCALL, MFCALL_PARENT, FCALL | res=l_deref // DEREF | res=l_simple_var // VAR, VARPTR | res=l_arrayexpr_mfcall[ right] | DOT | ASSIGN | ASSIGN_ARRAYEXPR_MFCALL | ASSIGN_REPLACE | e1=r_expr // illegal | CONSTANT // illegal ; // used in l_expr_internal but also in parameter_def l_simple_var returns [BaseGDL** res] { assert( _t != NULL); res = _t->LEval(); _retTree = _t->getNextSibling(); return res; } : VAR // DNode.varIx is index into functions/procedures environment | VARPTR // DNode.var is ptr to common block variable ; l_defined_simple_var returns [BaseGDL** res] { assert( _t != NULL); res = _t->LEval(); _retTree = _t->getNextSibling(); if( *res == NULL) { if( _t->getType() == VAR) throw GDLException( _t, "Variable is undefined: "+ callStack.back()->GetString(_t->varIx),true,false); else throw GDLException( _t, "Common block variable is undefined: "+ callStack.back()->GetString( *res),true,false); } return res; } : VAR // DNode.varIx is index into functions/procedures environment | VARPTR // DNode.var is ptr to common block variable ; l_sys_var returns [BaseGDL** res] { ProgNodeP sysVar = _t; //match(antlr::RefAST(_t),SYSVAR); res=sysVar->LEval(); _retTree = sysVar->getNextSibling(); return res; } : SYSVAR ; // right expressions ********************************************************** // expressions which always only return a value // expecting to delete any sub-expressions r_expr returns [BaseGDL* res] { res=_t->Eval(); _retTree = _t->getNextSibling(); return res; BaseGDL** refRet; // not used } : EXPR | ARRAYDEF | ARRAYDEF_GENERALIZED_INDGEN | STRUC | NSTRUC | NSTRUC_REF | #(DEC refRet=l_decinc_expr[ DEC, res]) | #(INC refRet=l_decinc_expr[ INC, res]) | #(POSTDEC refRet=l_decinc_expr[ POSTDEC, res]) | #(POSTINC refRet=l_decinc_expr[ POSTINC, res]) ; // for l and r expr tag_expr [DotAccessDescT* aD] // 2nd... { BaseGDL* e; if( _t->getType() == EXPR) { ProgNodeP tIn = _t; _t = _t->getFirstChild(); e=expr(_t); Guard e_guard(e); SizeT tagIx; int ret=e->Scalar2Index(tagIx); if( ret < 1) // this is a return code, not the index throw GDLException( tIn, "Expression must be a scalar" " >= 0 in this context: "+Name(e),true,false); aD->ADAdd( tagIx); _retTree = tIn->getNextSibling(); } else // case IDENTIFIER: { assert( _t->getType() == IDENTIFIER); std::string tagName=_t->getText(); aD->ADAdd( tagName); _retTree = _t->getNextSibling(); } return; } : EXPR | IDENTIFIER ; // for l and r expr tag_array_expr [DotAccessDescT* aD] // 2nd... { ArrayIndexListT* aL; if( _t->getType() == ARRAYEXPR) { ProgNodeP tIn = _t; _t = _t->getFirstChild(); tag_expr(_t, aD); _t = _retTree; // noAssoc==true, as assoc vars cannot be struct members aL=arrayindex_list(_t,true); //_t = _retTree; aD->ADAddIx(aL); _retTree = tIn->getNextSibling(); } else // case EXPR: // case IDENTIFIER: { tag_expr(_t, aD); //_t = _retTree; aD->ADAddIx(NULL); } //_retTree = _t; return; } : #(ARRAYEXPR tag_expr[ aD] aL=arrayindex_list[ true] /*{ aD->ADAddIx(aL);}*/ ) | tag_expr[ aD] //{ aD->ADAddIx(NULL);} ; r_dot_indexable_expr [DotAccessDescT* aD] returns [BaseGDL* res] // 1st { res=NULL; switch ( _t->getType()) { case EXPR: { ProgNodeP tIn = _t; _t = _t->getFirstChild(); //res=expr(_t); res = _t->Eval(); aD->SetOwner( true); _retTree = tIn->getNextSibling(); break; } case VAR: case VARPTR: { BaseGDL** v=l_defined_simple_var(_t); //_t = _retTree; res = *v; break; } case SYSVAR: { res = _t->EvalNC(); _retTree = _t->getNextSibling(); //res=sys_var_nocopy(_t); //_t = _retTree; break; } } //_retTree = _t; return res; BaseGDL** e; } : #(EXPR res=expr { aD->SetOwner( true);}) // ({tag:0}).tag should work | e=l_defined_simple_var | // we cant use l_sys_var here because of copy protection // could use sysvar and SetOwner( true), but this is quicker SYSVAR //res=sys_var_nocopy // system variables are always defined ; r_dot_array_expr [DotAccessDescT* aD] // 1st { BaseGDL* r; ArrayIndexListT* aL; if( _t->getType() == ARRAYEXPR) { //match(antlr::RefAST(_t),ARRAYEXPR); r=r_dot_indexable_expr(_t->getFirstChild(), aD); aL=arrayindex_list(_retTree,!r->IsAssoc()); _retTree = _t->getNextSibling(); // check here for object and get struct SetRootR( _t, aD, r, aL); } else { r=r_dot_indexable_expr(_t, aD); //_t = _retTree; // check here for object and get struct SetRootR( _t, aD, r, NULL); } return; } // NOTE: r is owned by aD or a l_... (r must not be deleted here) : #(ARRAYEXPR r=r_dot_indexable_expr[ aD] aL=arrayindex_list[ false] /*{ guard.reset(aL);}*/ ) | r=r_dot_indexable_expr[ aD] ; // indexable expressions are used to minimize copying of data // ( via Dup()) // owned by caller indexable_tmp_expr returns [BaseGDL* res] { res = _t->Eval(); //lib_function_call_retnew_internal(_t); _retTree = _t->getNextSibling(); return res; } : (QUESTION) // trinary operator | (ARRAYEXPR) //res=array_expr | DOT | res=assign_expr | res=unused_function_call | res=r_expr | res=lib_function_call_retnew_internal ; // not owned by caller indexable_expr returns [BaseGDL* res] { res = _t->EvalNC(); _retTree = _t->getNextSibling(); return res; BaseGDL** e2; } : e2=l_defined_simple_var | SYSVAR | CONSTANT //res=constant_nocopy | e2=l_deref ; // l_expr_internal used as r_expr and true r_expr expr returns [BaseGDL* res] { assert( _t != NULL); res = _t->Eval(); _retTree = _t->getNextSibling(); return res; //tmp_expr(_t); } : res=tmp_expr | res=lib_function_call_internal ; // l_expr_internal used as r_expr and true r_expr tmp_expr returns [BaseGDL* res] { res = _t->Eval(); _retTree = _t->getNextSibling(); return res; BaseGDL** e2; } // tmp_expr : e2=l_deref | (QUESTION) // trinary operator | (ARRAYEXPR) //res=array_expr // | res=array_expr | DOT | res=assign_expr | res=unused_function_call | res=r_expr | CONSTANT // ********* | res=simple_var | res=sys_var | res=lib_function_call_retnew_internal ; assign_expr returns [BaseGDL* res] { res = _t->Eval(); _retTree = _t->getNextSibling(); return res; BaseGDL** l; } : ASSIGN | ASSIGN_ARRAYEXPR_MFCALL | ASSIGN_REPLACE ; simple_var returns [BaseGDL* res] { assert( _t != NULL); BaseGDL* vData = _t->EvalNC(); if( vData == NULL) { if( _t->getType() == VAR) throw GDLException( _t, "Variable is undefined: "+_t->getText(),true,false); else // VARPTR throw GDLException( _t, "Common block variable is undefined.",true,false); } _retTree = _t->getNextSibling(); return vData->Dup(); } : VAR // DNode.varIx is index into functions/procedures environment | VARPTR // DNode.var is ptr to common block variable ; sys_var returns [BaseGDL* res] { res = _t->Eval(); _retTree = _t->getNextSibling(); return res; // no ->Dup() } : SYSVAR ; lib_function_call_internal returns[ BaseGDL* res] { assert( _t->getType() == FCALL_LIB); BaseGDL** retValPtr; res = static_cast(_t)->EvalFCALL_LIB(retValPtr); _retTree = _t->getNextSibling(); callStack.back()->SetPtrToReturnValue( retValPtr); return res; } : FCALL_LIB ; lib_function_call_retnew_internal returns[ BaseGDL* res] { res = _t->Eval(); _retTree = _t->getNextSibling(); return res; //_t->cData->Dup(); } : FCALL_LIB_RETNEW ; unused_function_call returns[ BaseGDL* res] {res=NULL;} : MFCALL | MFCALL_PARENT | FCALL | ARRAYEXPR_MFCALL ; l_arrayexpr_mfcall [BaseGDL* right] returns [BaseGDL** res] { // better than Guard: Guard wouldn't remove newEnv from the stack StackGuard guard(callStack); BaseGDL *self; EnvUDT* newEnv; ProgNodeP startNode = _t; } : #(ARRAYEXPR_MFCALL { ProgNodeP mark = _t; _t = _t->getNextSibling(); // skip DOT } self=expr mp2:IDENTIFIER { Guard self_guard(self); try { newEnv=new EnvUDT( self, mp2, "", EnvUDT::LFUNCTION); self_guard.release(); } catch( GDLException& ex) { goto tryARRAYEXPR; } } parameter_def[ newEnv] ) { // push environment onto call stack callStack.push_back(newEnv); // make the call res=call_lfun(static_cast( newEnv->GetPro())->GetTree()); _retTree = startNode->getNextSibling(); return res; tryARRAYEXPR:; _t = mark; } #(dot:DOT // struct assignment { SizeT nDot=dot->nDot; Guard aD( new DotAccessDescT(nDot+1)); } l_dot_array_expr[ aD.Get()] (tag_array_expr[ aD.Get()] /* nDot times*/ )+ ) { if( right == NULL) throw GDLException( _t, "Struct expression not allowed in this context.", true,false); aD.Get()->ADAssign( right); res=NULL; _retTree = startNode->getNextSibling(); return res; } ; l_arrayexpr_mfcall_as_arrayexpr [BaseGDL* right] returns [BaseGDL** res] : #(ARRAYEXPR_MFCALL #(dot:DOT // struct assignment { SizeT nDot=dot->nDot; Guard aD( new DotAccessDescT(nDot+1)); } l_dot_array_expr[ aD.Get()] (tag_array_expr[ aD.Get()] /* nDot times*/ )+ ) ) { if( right == NULL) throw GDLException( _t, "Struct expression not allowed in this context.", true,false); aD.Get()->ADAssign( right); res=NULL; } ; // function call can be l_values (within (#EXPR ...) only) l_arrayexpr_mfcall_as_mfcall returns[ BaseGDL** res] { // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(callStack); BaseGDL *self; EnvUDT* newEnv; } : #(ARRAYEXPR_MFCALL { _t = _t->getNextSibling(); // skip DOT } self=expr mp2:IDENTIFIER { Guard self_guard(self); newEnv=new EnvUDT( self, mp2, "", EnvUDT::LFUNCTION); self_guard.release(); } parameter_def[ newEnv] ) { // push environment onto call stack callStack.push_back(newEnv); // make the call res=call_lfun(static_cast( newEnv->GetPro())->GetTree()); } ; // function call can be l_values (within (#EXPR ...) only) l_function_call_internal returns[ BaseGDL** res] { res = _t->LEval(); _retTree = _t->getNextSibling(); return res; } : FCALL_LIB | MFCALL | MFCALL_PARENT | FCALL ; // for N_ELEMENTS() the environment is (as well) not on the callstack // needed because N_ELEMENTS must handle undefined variables different parameter_def_n_elements [EnvBaseT* actEnv] { Guard guard(actEnv); _retTree = _t; // bool interruptEnableIn = interruptEnable; if( _retTree != NULL) { int nPar = _retTree->GetNParam(); //int nSub = actEnv->GetPro()->NPar(); assert( actEnv->GetPro()->NPar() == 1); // N_ELEMENTS // fixed number of parameters if( nPar > 1)//nSub) // check here { throw GDLException( _t, actEnv->GetProName() + ": Incorrect number of arguments.", false, false); } if( _retTree->getType() == REF || _retTree->getType() == REF_EXPR || _retTree->getType() == REF_CHECK || _retTree->getType() == PARAEXPR) { try { // interruptEnable = false; static_cast(_retTree)->Parameter( actEnv); // interruptEnable = interruptEnableIn; } catch( GDLException& e) { // an error occured -> parameter is undefined // interruptEnable = interruptEnableIn; if( actEnv->NParam() == 0) // not set yet { BaseGDL* nullP = NULL; actEnv->SetNextPar( nullP); } } } else // used for error handling: keywords are checked only here in Parameter() { try { // as N_ELEMENTS has no keywords this should throw always static_cast(_retTree)->Parameter( actEnv); assert( 0); } catch( GDLException& e) { // update line number, currently set to caller->CallingNode() // because actEnv is not on the stack yet, // report caller->Pro()'s name is ok, because we are not inside // the call yet e.SetErrorNodeP( actEnv->CallingNode()); throw e; } } // actEnv->Extra(); // expand _EXTRA } // if( _retTree != NULL) guard.release(); return; } : KEYDEF_REF_EXPR IDENTIFIER ; // the environment is not on the callstack parameter_def [EnvBaseT* actEnv] { // as actEnv is not on the stack guard it here Guard guard(actEnv); EnvBaseT* callerEnv = callStack.back(); EnvBaseT* oldNewEnv = callerEnv->GetNewEnv(); callerEnv->SetNewEnv( actEnv); try{ _retTree = _t; if( _retTree != NULL) { int nPar = _retTree->GetNParam(); int nSub = actEnv->GetPro()->NPar(); // // variable number of parameters // if( nSub == -1) // { // // _retTree != NULL, save one check // static_cast(_retTree)->Parameter( actEnv); // while(_retTree != NULL) // static_cast(_retTree)->Parameter( actEnv); // } // // fixed number of parameters if( nSub != -1 && nPar > nSub) // check here { throw GDLException( _t, actEnv->GetProName() + ": Incorrect number of arguments.", false, false); } else { // _retTree != NULL, save one check static_cast(_retTree)->Parameter( actEnv); // Parameter does no checking while(_retTree != NULL) static_cast(_retTree)->Parameter( actEnv); } actEnv->ResolveExtra(); // expand _EXTRA } } catch( GDLException& e) { callerEnv->SetNewEnv( oldNewEnv); // update line number, currently set to caller->CallingNode() // because actEnv is not on the stack yet, // report caller->Pro()'s name is ok, because we are not inside // the call yet e.SetErrorNodeP( actEnv->CallingNode()); throw e; } callerEnv->SetNewEnv( oldNewEnv); guard.release(); return; } : KEYDEF_REF IDENTIFIER ; // the environment is not on the callstack // for library subroutines, their number of parameters is already checked in the compiler parameter_def_nocheck [EnvBaseT* actEnv] { Guard guard(actEnv); EnvBaseT* callerEnv = callStack.back(); EnvBaseT* oldNewEnv = callerEnv->GetNewEnv(); callerEnv->SetNewEnv( actEnv); try{ if( _t != NULL) { _retTree = _t; // _retTree != NULL, save one check // 'if' is needed already for Extra() static_cast(_retTree)->Parameter( actEnv); // Parameter does no checking while(_retTree != NULL) static_cast(_retTree)->Parameter( actEnv); actEnv->ResolveExtra(); // expand _EXTRA } } catch( GDLException& e) { callerEnv->SetNewEnv( oldNewEnv); // update line number, currently set to caller->CallingNode() // because actEnv is not on the stack yet, // report caller->Pro()'s name is ok, because we are not inside // the call yet e.SetErrorNodeP( actEnv->CallingNode()); throw e; } callerEnv->SetNewEnv( oldNewEnv); guard.release(); return; } : KEYDEF_REF IDENTIFIER ; arrayindex_list[ bool noAssoc] returns [ArrayIndexListT* aL] { // IxExprListT cleanupList; // for cleanup IxExprListT ixExprList; SizeT nExpr; BaseGDL* s; // ProgNodeP retTree = _t->getNextSibling(); ProgNodeP ax = _t; // match(antlr::RefAST(_t),ARRAYIX); _t = _t->getFirstChild(); if( noAssoc) aL = ax->arrIxListNoAssoc; else aL = ax->arrIxList; assert( aL != NULL); nExpr = aL->NParam(); if( nExpr == 0) { aL->Init(); _retTree = ax->getNextSibling();//retTree; return aL; } IxExprListT* cleanupList = aL->GetCleanupIx(); // for cleanup while( true) { assert( _t != NULL); if( NonCopyNode( _t->getType())) { s = _t->EvalNC(); } else { BaseGDL** ref =_t->EvalRefCheck( s); if( ref == NULL) cleanupList->push_back( s); else s = *ref; } assert( s != NULL); ixExprList.push_back( s); if( ixExprList.size() == nExpr) break; // allows some manual tuning _t = _t->getNextSibling(); } aL->Init( ixExprList);//, &cleanupList); _retTree = ax->getNextSibling();//retTree; return aL; } : ARRAYIX ; // for _overloadBracketsLeftSide/_overloadBracketsRightSide arrayindex_list_overload [IxExprListT& indexList] { ArrayIndexListT* aL; // IxExprListT cleanupList; // for cleanup IxExprListT ixExprList; SizeT nExpr; BaseGDL* s; // ProgNodeP retTree = _t->getNextSibling(); ProgNodeP ax = _t; // match(antlr::RefAST(_t),ARRAYIX); _t = _t->getFirstChild(); aL = ax->arrIxListNoAssoc; assert( aL != NULL); nExpr = aL->NParam(); if( nExpr == 0) { aL->InitAsOverloadIndex( ixExprList, /* NULL,*/ indexList); _retTree = ax->getNextSibling();//retTree; return; } IxExprListT* cleanupList = aL->GetCleanupIx(); while( true) { assert( _t != NULL); if( NonCopyNode( _t->getType())) { s= _t->EvalNCNull(); // in this case (overload) NULL is ok //_t = _retTree; } else { BaseGDL** ref=_t->EvalRefCheck( s); //indexable_tmp_expr(_t); //_t = _retTree; if( ref == NULL) cleanupList->push_back( s); else s = *ref; } ixExprList.push_back( s); if( ixExprList.size() == nExpr) break; // allows some manual tuning _t = _t->getNextSibling(); } aL->InitAsOverloadIndex( ixExprList, /*&cleanupList,*/ indexList); _retTree = ax->getNextSibling();//retTree; return; } : ARRAYIX ; gdl-0.9.9/src/gdlc.tree.g000066400000000000000000001647351340051421000151130ustar00rootroot00000000000000/* ************************************************************************* gdlc.tree.g the GDL tree parser used after the lexer/parser (gdlc.g) calls the compiler (dcompiler.cpp) put out trees suitable to be interpreted (gdlc.i.g) ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@hotmail.com ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // possible source of errors: // #id and id (as label) are not the same because tree generation is ON // #id refers to the generated (output) tree id to the input tree header "pre_include_cpp" { #include "includefirst.hpp" } header "post_include_cpp" { #include #include // **** #include "print_tree.hpp" using namespace std; // print out AST tree //#define GDL_DEBUG //#undef GDL_DEBUG } header { #include "objects.hpp" #include "dcompiler.hpp" #include "dnodefactory.hpp" #include "arrayindexlistt.hpp" } options { language="Cpp"; genHashLines = false; namespaceStd="std"; // cosmetic option to get rid of long defines namespaceAntlr="antlr"; // cosmetic option to get rid of long defines } // the GDL TreeParser **************************************** class GDLTreeParser extends TreeParser; options { importVocab = GDL; // use vocab generated by lexer buildAST = true; ASTLabelType = "RefDNode"; // defaultErrorHandler = true; defaultErrorHandler = false; } { private: // ProgNodeP returnProgNodeP; DCompiler comp; // each tree parser has its own compiler IDList loopVarStack; bool LoopVar( RefDNode& lN) { int lT = lN->getType(); if( lT == VAR || lT == VARPTR) return (FindInIDList( loopVarStack, lN->getText()) != -1); return false; } public: static bool IsREF_CHECK(int t) { return t == FCALL_LIB // || t == MFCALL_LIB // //t == FCALL_LIB_N_ELEMENTS || // || t == MFCALL_PARENT_LIB || t == QUESTION // TODO: These are ref check as well, but parameter nodes need to know || t == FCALL || t == MFCALL || t == MFCALL_PARENT || t == ARRAYEXPR_FCALL || t == ARRAYEXPR_MFCALL ; } private: // Replaces ASSIGN with ASSIGN_REPLACE if appropiate void AssignReplace( RefDNode& lN, RefDNode& aN) { if( LoopVar( lN)) { Warning( "Warning: Assignment to loop variable detected."); } int lT = lN->getType(); if( lT == FCALL || lT == MFCALL || lT == MFCALL_PARENT || lT == FCALL_LIB || // lT == FCALL_LIB_N_ELEMENTS || lT == FCALL_LIB_RETNEW || lT == FCALL_LIB_DIRECT || lT == MFCALL_LIB || lT == MFCALL_LIB_RETNEW || lT == MFCALL_PARENT_LIB || lT == MFCALL_PARENT_LIB_RETNEW || lT == DEREF || lT == VAR || lT == VARPTR ) { aN->setType( ASSIGN_REPLACE); aN->setText( "r="); } if( lT == ARRAYEXPR_MFCALL) // is MFCALL or DOT { aN->setType( ASSIGN_ARRAYEXPR_MFCALL); aN->setText( "?="); } } bool SelfAssignment( RefDNode& lN, RefDNode& rN) { int lT = lN->getType(); int rT = rN->getType(); if( rT == VARPTR && lT == VARPTR) { return (lN->GetVar() == rN->GetVar()); } if( rT == VAR && lT == VAR) { return (lN->GetVarIx() == rN->GetVarIx()); } return false; } RefDNode RemoveNextSibling( RefDNode l) { RefDNode newNode = RefDNode(astFactory->dupTree( antlr::RefAST(l))); newNode->SetLine( l->getLine()); return newNode; // newNode->setNextSibling( RefDNode(antlr::nullAST)); } public: // constructor with processed file GDLTreeParser(const std::string& f, const std::string& sub) : antlr::TreeParser(), comp(f, NULL, sub) { // setTokenNames(_tokenNames); // setASTNodeFactory( DNode::factory ); initializeASTFactory( DNodeFactory); setASTFactory( &DNodeFactory ); } // constructor for command line/execute GDLTreeParser( EnvBaseT* env) : antlr::TreeParser(), comp( "", env, "") { initializeASTFactory( DNodeFactory); setASTFactory( &DNodeFactory ); } bool ActiveProCompiled() const { return comp.ActiveProCompiled();} int NCompileErrors() const { return comp.NCompileErrors();} } // file parsing translation_unit { // returnProgNodeP = _t; bool mainStarted = false; } : ( options {greedy=true;}: procedure_def | function_def | forward_function | { EnvBaseT* envBefore = comp.GetEnv(); if( !mainStarted) { comp.StartPro( "$MAIN$"); mainStarted = true; } comp.ContinueMainPro(); } common_block { comp.EndInteractiveStatement(); comp.SetEnv( envBefore); } )* ( { if( !mainStarted) { comp.StartPro( "$MAIN$"); mainStarted = true; } comp.ContinueMainPro(); } retAST:statement_list { comp.SetTree( #retAST); comp.EndPro(); #ifdef GDL_DEBUG cout << "TreeParser output:" << endl; antlr::print_tree pt; pt.pr_tree(static_cast(retAST)); cout << "CompileFile: TreeParser end." << endl; #endif } )? // optional main program // ( main_program)? exception catch [ GDLException& e] { throw; } catch [ antlr::NoViableAltException& e] { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Compiler syntax error: "+e.getMessage()); } catch [ antlr::RecognitionException& e] { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "General syntax error: "+e.getMessage()); } ; // intercative usage interactive : (statement { comp.EndInteractiveStatement();})+ exception catch [ GDLException& e] { throw; } catch [ antlr::NoViableAltException& e] { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Compiler syntax error: "+e.getMessage()); } catch [ antlr::RecognitionException& e] { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "General syntax error: "+e.getMessage()); } ; forward_function! : #(FORWARD (id:IDENTIFIER { comp.ForwardFunction(id->getText()); } )+ ) ; parameter_declaration! : #(PARADECL (id:IDENTIFIER { comp.AddPar(id->getText()); } | keyword_declaration )+ ) ; keyword_declaration! : #(KEYDECL key:IDENTIFIER val:IDENTIFIER) { comp.AddKey(key->getText(),val->getText()); } ; procedure_def! : #(p:PRO name:IDENTIFIER (METHOD obj:IDENTIFIER { comp.StartPro(name->getText(),#p->GetCompileOpt(),obj->getText()); } | { comp.StartPro(name->getText(),#p->GetCompileOpt()); } ) (parameter_declaration)? (statement_list { comp.SetTree( returnAST); } )? { if( NCompileErrors() > 0) throw GDLException( i2s(NCompileErrors()) + " compilation error(s) in module " + name->getText() + "."); comp.EndPro(); } ) ; function_def! : #(f:FUNCTION name:IDENTIFIER (METHOD obj:IDENTIFIER { comp.StartFun(name->getText(),#f->GetCompileOpt(),obj->getText()); } | { comp.StartFun(name->getText(),#f->GetCompileOpt()); } ) (parameter_declaration)? (statement_list { comp.SetTree( returnAST); } )? { if( NCompileErrors() > 0) throw GDLException( i2s(NCompileErrors()) + " compilation error(s) in module " + name->getText() + "."); comp.EndFun(); } ) ; common_block!// : #(COMMONDEF id:IDENTIFIER { DCommonBase* actCommon=comp.CommonDef(id->getText()); } ( cv:IDENTIFIER { comp.CommonVar(actCommon,cv->getText()); } )+ ) | #(COMMONDECL id2:IDENTIFIER { comp.CommonDecl(id2->getText()); } ) ; // more than one ELSE is allowed: first is executed, *all* // (including expr) later branches are ignored // labeled_expr // : ex:expr // { // if( #ex->getType() != EXPR) // #labeled_expr = #([EXPR, "expr"],#labeled_expr); // } // ; caseswitch_body : #(b:BLOCK { #b->setType(CSBLOCK);#b->setText("csblock");} expr //labeled_expr (statement_list)? ) | #(ELSEBLK (statement_list)? ) ; switch_statement { int labelStart = comp.NDefLabel(); } : #(s:SWITCH expr (caseswitch_body)*) { #s->SetLabelRange( labelStart, comp.NDefLabel()); } ; case_statement { int labelStart = comp.NDefLabel(); } : #(c:CASE expr (caseswitch_body)*) { #c->SetLabelRange( labelStart, comp.NDefLabel()); } ; block { // int labelStart = comp.NDefLabel(); } : #(b:BLOCK (statement_list)?) { // #b->SetLabelRange( labelStart, comp.NDefLabel()); } ; unblock! : #(b:BLOCK ( s:statement_list { #unblock = #s;} | { #unblock = #b;} ) ) ; unblock_empty! : #(b:BLOCK ( s:statement_list { #unblock_empty = #s;} | ) ) ; statement_list // note: proper syntax is provided already by the parser : ( statement | label )+ ; statement : assign_expr_statement // | assign_expr | comp_assign_expr | procedure_call | for_statement | foreach_statement | repeat_statement | while_statement | jump_statement | if_statement | case_statement | switch_statement | forward_function | common_block | block | #(DEC expr) //unbrace_expr) | #(INC expr) //unbrace_expr) | BREAK // only in loops or case/switch_statement | CONTINUE // only in loops ; repeat_statement! { int labelStart = comp.NDefLabel(); } : #(r:REPEAT b:unblock_empty e:expr) { #r->SetLabelRange( labelStart, comp.NDefLabel()); #repeat_statement=#( r, e, b); if( #b == static_cast(antlr::nullAST)) Warning( "Warning: Empty REPEAT UNTIL loop detected."); } ; while_statement! { int labelStart = comp.NDefLabel(); } : #(w:WHILE e:expr s:statement) { #w->SetLabelRange( labelStart, comp.NDefLabel()); // swap e <-> s for easier access in interpreter #while_statement=#( w, e, s); } ; // for_block! // : u:unblock // { // #for_block=#( u, [ENDFOR,"endfor"]); // } // ; for_statement //! { StackSizeGuard guard( loopVarStack); int labelStart = comp.NDefLabel(); } : #(f:FOR i:IDENTIFIER { #i->setType(VAR); comp.Var(#i); loopVarStack.push_back(#i->getText()); } expr expr (expr { #f->setType(FOR_STEP); #f->setText("for_step"); } )? // for_block unblock_empty ) { #f->SetLabelRange( labelStart, comp.NDefLabel()); } ; foreach_statement //! { StackSizeGuard guard( loopVarStack); int labelStart = comp.NDefLabel(); } : #(f:FOREACH i:IDENTIFIER { #i->setType(VAR); comp.Var(#i); loopVarStack.push_back(#i->getText()); } expr (l:IDENTIFIER { #l->setType(VAR); comp.Var(#l); loopVarStack.push_back(#l->getText()); #f->setType(FOREACH_INDEX); #f->setText("foreach_index"); } )? // for_block unblock_empty // unblock ) { #f->SetLabelRange( labelStart, comp.NDefLabel()); } ; label! : #(i:IDENTIFIER COLON) { #label=#[LABEL,i->getText()]; #label->SetLine( i->getLine()); comp.Label(#label); } ; jump_statement!// : #(g:GOTO i1:IDENTIFIER) { #jump_statement=astFactory->create(GOTO,i1->getText()); #jump_statement->SetLine(g->getLine()); // #jump_statement=#[GOTO,i1->getText()]; // doesn't work // comp.Goto(#jump_statement); } | #(r:RETURN {bool exprThere=false;} (e:expr {exprThere=true;})?) { if( comp.IsFun()) { if( !exprThere) throw GDLException( r, "Return statement in functions " "must have 1 value."); // // wrong: this is only true for l_function as return value // // a ARRAYEXPR_MFCALL can only be a MFCALL here -> change tree // if( #e->getType() == ARRAYEXPR_MFCALL) // { // #e->setType( MFCALL); // #e->setText( "mfcall"); // RefDNode mfc; // mfc = #e->getFirstChild(); // mfc = mfc->getNextSibling(); // #e->setFirstChild( antlr::RefAST(mfc)); // } #jump_statement=#([RETF,"retf"],e); #jump_statement->SetLine(r->getLine()); } else { if( exprThere) throw GDLException( _t, "Return statement in " "procedures cannot have values."); #jump_statement=#[RETP,"retp"]; // astFactory.create(RETP,"retp"); #jump_statement->SetLine(r->getLine()); } } | #(o:ON_IOERROR i2:IDENTIFIER) { if( i2->getText() == "NULL") { #jump_statement=astFactory->create(ON_IOERROR_NULL, "on_ioerror_null"); #jump_statement->SetLine(o->getLine()); } else { #jump_statement=astFactory->create(ON_IOERROR,i2->getText()); #jump_statement->SetLine(o->getLine()); // #jump_statement=#[ON_IOERROR,i2->getText()]; // comp.Goto(#jump_statement); // same handling } } ; if_statement!// { // int labelStart = comp.NDefLabel(); RefDNode block; } : #(i:IF e:expr s1:statement ( { // #i->SetLabelRange( labelStart, comp.NDefLabel()); #if_statement=#(i,e,s1); } | s2:statement { #i->setText( "if_else"); #i->setType( IF_ELSE); // #i->SetLabelRange( labelStart, comp.NDefLabel()); if( #s1->getType() != BLOCK) { #block = astFactory->create(BLOCK,"block"); #block->SetLine( #s1->getLine()); #if_statement=#(i,e, #(block, s1), s2); } else #if_statement=#(i,e,s1,s2); } ) ) // { // #i->SetLabelRange( labelStart, comp.NDefLabel()); // } ; procedure_call : #(MPCALL expr IDENTIFIER parameter_def[ false] ) | #(MPCALL_PARENT expr IDENTIFIER IDENTIFIER parameter_def[ false] ) | #(p:PCALL id:IDENTIFIER { // first search library procedures int i=LibProIx(#id->getText()); } para:parameter_def[ i != -1 && libProList[ i]->NPar() == -1] { if( i != -1) { int nParam = 0; if( #para != RefDNode(antlr::nullAST)) nParam = #para->GetNParam(); int libParam = libProList[i]->NPar(); int libParamMin = libProList[i]->NParMin(); if( libParam != -1 && nParam > libParam) throw GDLException( p, libProList[i]->Name() + ": Too many arguments."); if( libParam != -1 && nParam < libParamMin) throw GDLException( p, libProList[i]->Name() + ": Too few arguments."); #p->setType(PCALL_LIB); #p->setText("pcall_lib"); #id->SetLibPro( libProList[i]); } else { // then search user defined procedures i=ProIx(#id->getText()); #id->SetProIx(i); } } ) ; parameter_def [bool varNum] { // count positional parameters int nKey = 0; int nPar = 0; } : ( key_parameter { ++nKey; } | pos_parameter[ varNum] { ++nPar; } )* { if( nPar > 0 || nKey > 0) { RefDNode(currentAST.root)->SetNParam( nPar); } } ; key_parameter!// { RefDNode variable; } : #(d:KEYDEF i:IDENTIFIER k:expr //unbrace_expr { variable=comp.ByReference(#k); if( variable != static_cast(antlr::nullAST)) { int vT = variable->getType(); if( IsREF_CHECK(vT)) { #d=#[KEYDEF_REF_CHECK,"keydef_ref_check"]; #key_parameter=#(d,i,k); } else if( variable == #k) { #d=#[KEYDEF_REF,"keydef_ref"]; #key_parameter=#(d,i,variable); } else { #d=#[KEYDEF_REF_EXPR,"keydef_ref_expr"]; #key_parameter=#(d,i,k,variable); } } else { int t = #k->getType(); // Note: Right now there are no MFCALL_LIB or MFCALL_PARENT_LIB nodes if( IsREF_CHECK(t)) // t == FCALL_LIB // || t == MFCALL_LIB // || t == FCALL_LIB_N_ELEMENTS // || t == MFCALL_PARENT_LIB // || t == QUESTION // || t == FCALL || t == MFCALL || t == MFCALL_PARENT // || t == ARRAYEXPR_FCALL // || t == ARRAYEXPR_MFCALL // // t == FCALL_LIB_RETNEW || t == MFCALL_LIB_RETNEW || // // t == MFCALL_PARENT_LIB_RETNEW //|| // // t == ARRARYEXPR_MFCALL_LIB // MFCALL_LIB or VAR or DEREF // // ) { #d=#[KEYDEF_REF_CHECK,"keydef_ref_check"]; #key_parameter=#(d,i,k); } // else if( t == FCALL_LIB_RETNEW || t == MFCALL_LIB_RETNEW) // { // // #d=#[KEYDEF_REF,"keydef_ref"]; // #key_parameter=#(d,i,k); // } else { #key_parameter=#(d,i,k); } } } ) ; pos_parameter! [bool varNum] // varNum: is variable number of parameters subroutine (e. g. PRINT) { RefDNode variable; } : e:expr //unbrace_expr { variable=comp.ByReference(#e); if( variable != static_cast(antlr::nullAST)) { int vT = variable->getType(); if( IsREF_CHECK(vT)) { if( varNum) #pos_parameter=#([REF_CHECK_VN,"ref_check_vn"],e); else #pos_parameter=#([REF_CHECK,"ref_check"],e); } else if( variable == #e) { if( varNum) #pos_parameter=#([REF_VN,"ref_vn"],variable); else #pos_parameter=#([REF,"ref"],variable); } else { if( varNum) #pos_parameter=#([REF_EXPR_VN,"ref_expr_vn"],e,variable); else #pos_parameter=#([REF_EXPR,"ref_expr"],e,variable); } } else { int t = #e->getType(); // Note: Right now there are no MFCALL_LIB or MFCALL_PARENT_LIB nodes if( IsREF_CHECK(t)) // if( t == FCALL_LIB // || t == MFCALL_LIB //t == FCALL_LIB_N_ELEMENTS || // || t == MFCALL_PARENT_LIB // || t == QUESTION // // TODO: These are ref check as well, but parameter nodes need to know // || t == FCALL || t == MFCALL || t == MFCALL_PARENT // || t == ARRAYEXPR_FCALL // || t == ARRAYEXPR_MFCALL // // t == FCALL_LIB_RETNEW || t == MFCALL_LIB_RETNEW || // // t == MFCALL_PARENT_LIB_RETNEW // // t == ARRARYEXPR_MFCALL_LIB // MFCALL_LIB or VAR or DEREF // ) { // something like: CALLAPRO,reform(a,/OVERWRITE) if( varNum) #pos_parameter=#([REF_CHECK_VN,"ref_check_vn"],e); else #pos_parameter=#([REF_CHECK,"ref_check"],e); } else { if( varNum) #pos_parameter= #([PARAEXPR_VN,"paraexpr_vn"], e); else #pos_parameter= #([PARAEXPR,"paraexpr"], e); } } } ; // counts the [[[ ]]] // 0 -> [ ] (add dim if scalar) // 1 -> [[ ]] ... array_def returns [int depth] { RefDNode sPos; } : #(a:ARRAYDEF {sPos=_t;} (/*e:*/expr {/*check for constant expression*/})*) { // better check here as then CONSTANT is propagated depth=0; // bool constant = true; // bool depth0 = false; for( RefDNode e=sPos; e != static_cast(antlr::nullAST); e=e->getNextSibling()) { // if( e->getType() != CONSTANT) // constant = false; // if( !depth0) if( (e->getType() != ARRAYDEF) && (e->getType() != ARRAYDEF_CONST) && (e->getType() != ARRAYDEF_GENERALIZED_INDGEN)) { depth=0; break; // depth0 = true; } else { int act=array_def(e); // recursive call act=act+1; if( depth == 0) { depth=act; } else { if( depth > act) depth=act; } } } #a->SetArrayDepth(depth); } | #(aa:ARRAYDEF_CONST {sPos=_t;} (expr)*) { depth=0; for( RefDNode e=sPos; e != static_cast(antlr::nullAST); e=e->getNextSibling()) { if( (e->getType() != ARRAYDEF) && (e->getType() != ARRAYDEF_CONST) && (e->getType() != ARRAYDEF_GENERALIZED_INDGEN)) { depth=0; break; } else { int act=array_def(e); // recursive call act=act+1; if( depth == 0) { depth=act; } else { if( depth > act) depth=act; } } } #aa->SetArrayDepth(depth); } | #(aaa:ARRAYDEF_GENERALIZED_INDGEN {sPos=_t;} (expr)*) { depth=0; for( RefDNode e=sPos; e != static_cast(antlr::nullAST); e=e->getNextSibling()) { if( (e->getType() != ARRAYDEF) && (e->getType() != ARRAYDEF_CONST) && (e->getType() != ARRAYDEF_GENERALIZED_INDGEN)) { depth=0; break; } else { int act=array_def(e); // recursive call act=act+1; if( depth == 0) { depth=act; std::cerr< act) depth=act; } } } #aaa->SetArrayDepth(depth); } ; struct_def { bool noTagName = false; } : #(n:NSTRUC_REF // parser delivers always nstruct_ref IDENTIFIER ((expr {noTagName = true;} | IDENTIFIER expr | INHERITS IDENTIFIER)+ { // set to nstruct if defined here #n->setType(NSTRUC); #n->setText("nstruct"); #n->DefinedStruct( noTagName); } )? ) | #(STRUC (tag_def)+) ; tag_def : IDENTIFIER expr ; arrayindex! [ArrayIndexVectorT* ixList] { BaseGDL *c1, *c2, *c3, *c4; } : ( #(ARRAYIX ( ALL { ixList->push_back( new ArrayIndexAll()); } | ( e1:expr // 0 or 2 { // in ConstantIndex the cData of all nodes is stolen // (in case it succeeds) // therefore we build here the new constant node with // proper cData. See below (e2) c1 = comp.ConstantIndex( #e1); if( c1 != NULL) { int e1Line = #e1->getLine(); #e1 = #[CONSTANT,"CONST_IX"]; #e1->ResetCData( c1); #e1->SetLine( e1Line); } } ( // empty { bool constantOK = false; if( c1 != NULL) { DType dType = c1->Type(); int typeCheck = DTypeOrder[ dType]; if( dType == GDL_STRING || typeCheck >= 100) { //delete c1; } else { try { // ATTENTION: These two grab c1 (all others don't) // a bit unclean, but for maximum efficiency if( c1->Rank() == 0) ixList->push_back( new CArrayIndexScalar( c1)); else ixList->push_back( new CArrayIndexIndexed( c1)); // prevent c1 from being deleted #e1->StealCData(); // ok, as #e1 is not used anymore constantOK = true; } catch( GDLException& e) { //delete c1; // owned by #e1 } } } if( !constantOK) { if( LoopVar( #e1)) { if( #e1->getType() == VAR) ixList->push_back( new ArrayIndexScalar( #e1)); else ixList->push_back( new ArrayIndexScalarVP( #e1)); } else { ## = #e1; ixList->push_back( new ArrayIndexIndexed()); } } } | ALL ( // empty { //c1 = comp.ConstantIndex( #e1); if( c1 != NULL) { ixList->push_back( new CArrayIndexORange( c1)); } else { ## = #e1; ixList->push_back( new ArrayIndexORange()); } } | e2:expr { // in ConstantIndex the cData of all nodes is stolen // (in case it succeeds) // therefore we build here the new constant node with // proper cData. This is crucial because if e. g. only e1 but not e2 // is constant, #e1 is put to the output tree (with stolen cData) -> crash c2 = comp.ConstantIndex( #e2); if( c2 != NULL) { int e2Line = #e2->getLine(); #e2 = #[CONSTANT,"CONST_IX"]; #e2->ResetCData( c2); #e2->SetLine( e2Line); } } { //c1 = comp.ConstantIndex( #e1); //c2 = comp.ConstantIndex( #e2); if( c1 != NULL && c2 != NULL) { ixList->push_back( new CArrayIndexORangeS( c1, c2)); } else { //delete c1; //delete c2; ## = #( NULL, e1, e2); ixList->push_back( new ArrayIndexORangeS()); } } ) | e3:expr { // see above (#e2) c3 = comp.ConstantIndex( #e3); if( c3 != NULL) { int e3Line = #e3->getLine(); #e3 = #[CONSTANT,"CONST_IX"]; #e3->ResetCData( c3); #e3->SetLine( e3Line); } } ( // empty { //c1 = comp.ConstantIndex( #e1); //c3 = comp.ConstantIndex( #e3); if( c1 != NULL && c3 != NULL) { ixList->push_back( new CArrayIndexRange( c1, c3)); } else { //delete c1; //delete c3; ## = #( NULL, e1, e3); ixList->push_back( new ArrayIndexRange()); } } | e4:expr { // see above (#e2) c4 = comp.ConstantIndex( #e4); if( c4 != NULL) { int e4Line = #e4->getLine(); #e4 = #[CONSTANT,"CONST_IX"]; #e4->ResetCData( c4); #e4->SetLine( e4Line); } } { //c1 = comp.ConstantIndex( #e1); //c3 = comp.ConstantIndex( #e3); //c4 = comp.ConstantIndex( #e4); if( c1 != NULL && c3 != NULL && c4 != NULL) { ixList->push_back( new CArrayIndexRangeS( c1, c3, c4)); } else { //delete c1; //delete c3; //delete c4; ## = #( NULL, e1, e3, e4); ixList->push_back( new ArrayIndexRangeS()); } } ) ) ) ) ) ) ; arrayindex_list { ArrayIndexVectorT* ixList = new ArrayIndexVectorT(); PtrGuard< ArrayIndexVectorT> guard( ixList); } : ( arrayindex[ ixList])+ { #arrayindex_list = #([ARRAYIX,"[...]"], arrayindex_list); // ixList->Freeze(); // do all initial one-time settings // if( ixList->NDim() == 1) // #arrayindex_list = #([ARRAYIX1,"[ix]"], arrayindex_list); // else // { // #arrayindex_list = #([ARRAYIX,"[...]"], arrayindex_list); // ixList->Freeze(); // do all initial one-time settings // } guard.Release(); ArrayIndexListT* arrayIndexNoAssoc; ArrayIndexListT* arrayIndex; MakeArrayIndex( ixList, &arrayIndex, &arrayIndexNoAssoc); delete ixList; #arrayindex_list->SetArrayIndexList( arrayIndex, arrayIndexNoAssoc); } ; // arrayindex // : #(ax:ARRAYIX // ( ALL // { // #ax->setType(ARRAYIX_ALL); // 1 // #ax->setText("*"); // } // | ( expr // 0 or 2 // ( ( !ALL // { // #ax->setType(ARRAYIX_ORANGE); // 3 // #ax->setText("s:*"); // } // ) // ( expr // { // #ax->setType(ARRAYIX_ORANGE_S); // 5 // #ax->setText("s:*:s"); // } // )? // | expr // { // #ax->setType(ARRAYIX_RANGE); // 4 // #ax->setText("s:e"); // } // ( expr // { // #ax->setType(ARRAYIX_RANGE_S); // 6 // #ax->setText("s:e:s"); // } // )? // )? // ) // ) // ) // ; // removes last pair of braces // for non functions lassign_expr!// : ex:expr { // remove last pair of braces if( #ex->getType()==EXPR) { // int cT = #ex->getFirstChild()->getType(); // if( cT != FCALL && // cT != MFCALL && // cT != MFCALL_PARENT && // cT != FCALL_LIB && // cT != MFCALL_LIB && // cT != MFCALL_PARENT_LIB) #ex=#ex->getFirstChild(); } if( #ex->getType()==ASSIGN) throw GDLException( _t, "Assign expression is not allowed as " "l-expression in assignment"); #lassign_expr= #ex; //#( NULL, ex); } ; assign_expr! : #(a:ASSIGN l:lassign_expr r:expr) { if( !SelfAssignment( #l, #r)) { AssignReplace( #l, #a); // int lT = #l->getType(); // if( lT == FCALL || lT == MFCALL || lT == MFCALL_PARENT || // lT == FCALL_LIB || lT == MFCALL_LIB || lT == MFCALL_PARENT_LIB || // lT == DEREF || lT == VAR || lT == VARPTR) // #a->setType( ASSIGN_REPLACE); #assign_expr=#(a,r,l); } else { #assign_expr=#(l); } } ; // different return tree with self assignment assign_expr_statement! : #(a:ASSIGN l:lassign_expr r:expr) { if( !SelfAssignment( #l, #r)) { AssignReplace( #l, #a); // int lT = #l->getType(); // if( lT == FCALL || lT == MFCALL || lT == MFCALL_PARENT || // lT == FCALL_LIB || lT == MFCALL_LIB || lT == MFCALL_PARENT_LIB || // lT == DEREF || lT == VAR || lT == VARPTR) // #a->setType( ASSIGN_REPLACE); #assign_expr_statement=#(a,r,l); } else { #assign_expr_statement=#([BLOCK,"block"]); } } ; /// *** to be done (ASSIGN_REPLACE) // +=, *=, ... // ATTENTION: This gives a different result than IDL on something like: // a=intarr(3)&i=1&a[[i++]]+=1&print,i,a comp_assign_expr!// { RefDNode l; } : ( #(a1:AND_OP_EQ l1:lassign_expr r1:expr) { l=#l1; #comp_assign_expr=#([ASSIGN,":="],([AND_OP,"and"],l1,r1),RemoveNextSibling(l1));} | #(a2:ASTERIX_EQ l2:lassign_expr r2:expr) { l=#l2; #comp_assign_expr=#([ASSIGN,":="],([ASTERIX,"*"],l2,r2),RemoveNextSibling(l2));} | #(a3:EQ_OP_EQ l3:lassign_expr r3:expr) { l=#l3; #comp_assign_expr=#([ASSIGN,":="],([EQ_OP,"eq"],l3,r3),RemoveNextSibling(l3));} | #(a4:GE_OP_EQ l4:lassign_expr r4:expr) { l=#l4; #comp_assign_expr=#([ASSIGN,":="],([GE_OP,"ge"],l4,r4),RemoveNextSibling(l4));} | #(a5:GTMARK_EQ l5:lassign_expr r5:expr) { l=#l5; #comp_assign_expr=#([ASSIGN,":="],([GTMARK,">"],l5,r5),RemoveNextSibling(l5));} | #(a6:GT_OP_EQ l6:lassign_expr r6:expr) { l=#l6; #comp_assign_expr=#([ASSIGN,":="],([GT_OP,"gt"],l6,r6),RemoveNextSibling(l6));} | #(a7:LE_OP_EQ l7:lassign_expr r7:expr) { l=#l7; #comp_assign_expr=#([ASSIGN,":="],([LE_OP,"le"],l7,r7),RemoveNextSibling(l7));} | #(a8:LTMARK_EQ l8:lassign_expr r8:expr) { l=#l8; #comp_assign_expr=#([ASSIGN,":="],([LTMARK,"<"],l8,r8),RemoveNextSibling(l8));} | #(a9:LT_OP_EQ l9:lassign_expr r9:expr) { l=#l9; #comp_assign_expr=#([ASSIGN,":="],([LT_OP,"lt"],l9,r9),RemoveNextSibling(l9));} | #(a10:MATRIX_OP1_EQ l10:lassign_expr r10:expr) { l=#l10; #comp_assign_expr=#([ASSIGN,":="],([MATRIX_OP1,"#"],l10,r10),RemoveNextSibling(l10));} | #(a11:MATRIX_OP2_EQ l11:lassign_expr r11:expr) { l=#l11; #comp_assign_expr=#([ASSIGN,":="],([MATRIX_OP2,"##"],l11,r11),RemoveNextSibling(l11));} | #(a12:MINUS_EQ l12:lassign_expr r12:expr) { l=#l12; #comp_assign_expr=#([ASSIGN,":="],([MINUS,"-"],l12,r12),RemoveNextSibling(l12));} | #(a13:MOD_OP_EQ l13:lassign_expr r13:expr) { l=#l13; #comp_assign_expr=#([ASSIGN,":="],([MOD_OP,"mod"],l13,r13),RemoveNextSibling(l13));} | #(a14:NE_OP_EQ l14:lassign_expr r14:expr) { l=#l14; #comp_assign_expr=#([ASSIGN,":="],([NE_OP,"ne"],l14,r14),RemoveNextSibling(l14));} | #(a15:OR_OP_EQ l15:lassign_expr r15:expr) { l=#l15; #comp_assign_expr=#([ASSIGN,":="],([OR_OP,"or"],l15,r15),RemoveNextSibling(l15));} | #(a16:PLUS_EQ l16:lassign_expr r16:expr) { l=#l16; #comp_assign_expr=#([ASSIGN,":="],([PLUS,"+"],l16,r16),RemoveNextSibling(l16));} | #(a17:POW_EQ l17:lassign_expr r17:expr) { l=#l17; #comp_assign_expr=#([ASSIGN,":="],([POW,"^"],l17,r17),RemoveNextSibling(l17));} | #(a18:SLASH_EQ l18:lassign_expr r18:expr) { l=#l18; #comp_assign_expr=#([ASSIGN,":="],([SLASH,"/"],l18,r18),RemoveNextSibling(l18));} | #(a19:XOR_OP_EQ l19:lassign_expr r19:expr) { l=#l19; #comp_assign_expr=#([ASSIGN,":="],([XOR_OP,"xor"],l19,r19),RemoveNextSibling(l19));} ) { AssignReplace( l, #comp_assign_expr); } ; // NEW for correct behaviour // comp_assign_expr!// // { // RefDNode l; // } // : // #(a1:AND_OP_EQ l1:lassign_expr r1:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a1,r1,l1);} // | #(a2:ASTERIX_EQ l2:lassign_expr r2:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a2,r2,l2);} // | #(a3:EQ_OP_EQ l3:lassign_expr r3:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a3,r3,l3);} // | #(a4:GE_OP_EQ l4:lassign_expr r4:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a4,r4,l4);} // | #(a5:GTMARK_EQ l5:lassign_expr r5:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a5,r5,l5);} // | #(a6:GT_OP_EQ l6:lassign_expr r6:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a6,r6,l6);} // | #(a7:LE_OP_EQ l7:lassign_expr r7:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a7,r7,l7);} // | #(a8:LTMARK_EQ l8:lassign_expr r8:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a8,r8,l8);} // | #(a9:LT_OP_EQ l9:lassign_expr r9:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a9,r9,l9);} // | #(a10:MATRIX_OP1_EQ l10:lassign_expr r10:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a10,r10,l10);} // | #(a11:MATRIX_OP2_EQ l11:lassign_expr r11:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a11,r11,l11);} // | #(a12:MINUS_EQ l12:lassign_expr r12:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a12,r12,l12);} // | #(a13:MOD_OP_EQ l13:lassign_expr r13:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a13,r13,l13);} // | #(a14:NE_OP_EQ l14:lassign_expr r14:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a14,r14,l14);} // | #(a15:OR_OP_EQ l15:lassign_expr r15:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a15,r15,l15);} // | #(a16:PLUS_EQ l16:lassign_expr r16:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a16,r15,l16);} // | #(a17:POW_EQ l17:lassign_expr r17:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a17,r17,l17);} // | #(a18:SLASH_EQ l18:lassign_expr r18:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a18,r18,l18);} // | #(a19:XOR_OP_EQ l19:lassign_expr r19:expr) // { #comp_assign_expr=#([ASSIGN_INPLACE,"op="],a19,r19,l19);} // ; // the expressions *************************************/ // system variables have as variable ptr NULL initially sysvar!// : #(s:SYSVAR i:SYSVARNAME) { std::string sysVarName = i->getText(); // here we create the real sysvar node #sysvar=astFactory->create(SYSVAR, sysVarName.substr(1)); #sysvar->SetLine(s->getLine()); // #sysvar=#[SYSVAR,i->getText()]; comp.SysVar(#sysvar); // sets var to NULL } ; // variables are converted to: // VAR with index into functions/procedures variable list or // VARPTR for common block variables with a ptr to the // variable in the common block var!// : #(v:VAR i:IDENTIFIER) { #var=astFactory->create(VAR,i->getText()); #var->SetLine(v->getLine()); // #var=#[VAR,i->getText()]; comp.Var(#var); } ; arrayindex_list_to_parameter_list! [bool varNum]// ??? { int nPar = 0; } : (options {greedy=true;}: #(ARRAYIX e:pos_parameter[ varNum]) { #arrayindex_list_to_parameter_list= #(NULL, arrayindex_list_to_parameter_list, e); ++nPar; } )+ { arrayindex_list_to_parameter_list_AST->SetNParam( nPar); } ; // for function calls the arrayindex list is properly converted arrayexpr_fn!// { std::string id_text; bool isVar; RefDNode mark, va2, vaAlt, fn, arrayindex_listAST; } : #(aIn:ARRAYEXPR_FCALL // always here: #(VAR IDENTIFIER) #(va:VAR id:IDENTIFIER) { mark = _t; id_text = #id->getText(); // IsVar is not needed, we must emit an ARRAYEXPR_FCALL even if the variable is known // (rule: Accessible functions always override variables //isVar = comp.IsVar( id_text); // isVar == true -> VAR for sure // (== false: maybe VAR nevertheless) int libIx = -1; // if( id_text != "LIST" && id_text != "HASH") libIx = LibFunIx(id_text); } ( el:arrayindex_list_to_parameter_list[ libIx != -1 && libFunList[ libIx]->NPar() == -1] ) { // first search library functions if( libIx != -1) { int nParam = 0; if( #el != RefDNode(antlr::nullAST)) nParam = #el->GetNParam(); int libParam = libFunList[libIx]->NPar(); int libParamMin = libFunList[libIx]->NParMin(); if( libParam != -1 && nParam > libParam) throw GDLException( aIn, libFunList[libIx]->Name() + ": Too many arguments."); if( libParam != -1 && nParam < libParamMin) throw GDLException( aIn, libFunList[libIx]->Name() + ": Too few arguments."); #id->SetLibFun( libFunList[libIx]); if( libFunList[ libIx]->RetNew()) { if( libFunList[ libIx]->Name() == "N_ELEMENTS") #id->setType( FCALL_LIB_N_ELEMENTS); else if( libFunList[ libIx]->DirectCall()) #id->setType( FCALL_LIB_DIRECT); else #id->setType( FCALL_LIB_RETNEW); #arrayexpr_fn = #( id, el); // #([/*FCALL_LIB_RETNEW,"fcall_lib_retnew"],*/ id, el); } else { #id->setType( FCALL_LIB); #arrayexpr_fn = #( id, el); // #(/*[FCALL_LIB,"fcall_lib"],*/ id, el); } } // then search user defined functions else { int funIx=FunIx( id_text); // we use #id for the FCALL part #id->setType( FCALL); #id->SetFunIx( funIx); if( funIx != -1) // found -> FCALL { #arrayexpr_fn = #( id, el); // #(/*[FCALL,"fcall"],*/ id, el); } else // function not found -> still ambiguous { // _t = mark; // rewind to parse again arrayindex_list( mark); //_t = _retTree; arrayindex_listAST = returnAST; #va2=astFactory->create( VAR, id_text); // #va=#[VAR,id->getText()]; comp.Var( #va2); // we declare the variable here! // if IsVar() still would be used this would lead to surprising behavior: // e. g.: function_call(42) & function_call(43) // The first (42) would be an ARRAYEXPR_FCALL the 2nd (43) an ARRAYEXPR // if then at runtime function "function_call" is known, // it will be called only at the first appearance of the call. // that's why we cannot allow unambiguous VAR here #vaAlt = #([ARRAYEXPR,"arrayexpr"], va2, arrayindex_listAST); #fn = #( id, el); #arrayexpr_fn = #( aIn, vaAlt, fn); } } // // not valid s. a. (kept for reference): unambiguous VAR // { // variable -> arrayexpr // // make var // #va=astFactory->create(VAR,#id->getText()); // // #va=#[VAR,id->getText()]; // comp.Var(#va); // #arrayexpr_fn= // #([ARRAYEXPR,"arrayexpr"], va, al); // } } ) ; arrayexpr_mfcall!// : #(a:ARRAYEXPR_MFCALL { RefDNode mark = _t; // mark } e:expr i:IDENTIFIER //al:arrayindex_list { bool success = true; RefDNode #first; try { arrayindex_list(_t); RefDNode al = returnAST; RefDNode #ae = #([ARRAYEXPR,"arrayexpr"], #i, al); if( e->getType() == DOT) { int nDot = #e->GetNDot(); #e->SetNDot( ++nDot); #e->addChild( #ae); #first = #e; } else { RefDNode #dot = #([DOT,"."], e, ae); #dot->SetNDot( 1); #first = #dot; } } catch( GDLException& ex) { Message( "Ambiguity resolved: member function call " "due to invalid array index."); success = false; #a->setType( MFCALL); #a->setText( "mfcall"); } _t = mark; // rewind to parse again } e2:expr i2:IDENTIFIER a2:arrayindex_list_to_parameter_list[ false] { if( success) #arrayexpr_mfcall = #(a, first, e2, i2, a2); else #arrayexpr_mfcall = #(a, e2, i2, a2); } ) ; // only here a function call is ok also primary_expr { int dummy; RefDNode mark; } : assign_expr | comp_assign_expr | arrayexpr_mfcall | #(MFCALL expr IDENTIFIER parameter_def[ false] ) | #(MFCALL_PARENT expr IDENTIFIER IDENTIFIER parameter_def[ false] ) // | #(nEl:FCALL_LIB_N_ELEMENTS id2:IDENTIFIER! parameter_def // ) | #(f:FCALL id:IDENTIFIER! { // first search library functions int i=LibFunIx(id->getText()); } p:parameter_def[ i != -1 && libFunList[ i]->NPar() == -1] { if( i != -1) { // N_ELEMENTS must handle exceptions during parameter evaluation // if( StrUpCase( #id->getText()) == "N_ELEMENTS") // { // #f->setType(FCALL_LIB_N_ELEMENTS); // #f->setText(#id->getText()); // #f->SetLibFun( libFunList[i]); // // #id->SetFunIx(i); // } // else { int nParam = 0; if( #p != RefDNode(antlr::nullAST)) nParam = #p->GetNParam(); int libParam = libFunList[i]->NPar(); int libParamMin = libFunList[i]->NParMin(); if( libParam != -1 && nParam > libParam) throw GDLException( f, libFunList[i]->Name() + ": Too many arguments."); if( libParam != -1 && nParam < libParamMin) throw GDLException( f, libFunList[i]->Name() + ": Too few arguments."); if( libFunList[ i]->RetNew()) { if( libFunList[ i]->Name() == "N_ELEMENTS") #f->setType( FCALL_LIB_N_ELEMENTS); else if( libFunList[ i]->DirectCall()) #f->setType( FCALL_LIB_DIRECT); else #f->setType(FCALL_LIB_RETNEW); #f->setText(#id->getText()); #f->SetLibFun( libFunList[i]); // #id->SetFunIx(i); } else { #f->setType(FCALL_LIB); #f->setText(#id->getText()); #f->SetLibFun( libFunList[i]); // #id->SetFunIx(i); } } } else { // then search user defined functions #f->setType(FCALL); #f->setText(#id->getText()); i=FunIx(#id->getText()); #f->SetFunIx(i); } } ) | arrayexpr_fn // converts fo FCALL(_LIB) or ARRAYEXPR_FCALL | CONSTANT | dummy=array_def | struct_def | g:GDLNULL { #g->setType(SYSVAR); #g->setText("NULL"); comp.SysVar(#g); // sets var to NULL } ; op_expr : #(QUESTION expr expr expr) // trinary operator | #(AND_OP expr expr) // binary/unary operators... | #(OR_OP expr expr) | #(XOR_OP expr expr) | #(LOG_AND expr expr) | #(LOG_OR expr expr) | #(EQ_OP expr expr) | #(NE_OP expr expr) | #(LE_OP expr expr) | #(LT_OP expr expr) | #(GE_OP expr expr) | #(GT_OP expr expr) | #(NOT_OP expr) | #(PLUS expr expr) | #(MINUS expr expr) | #(LTMARK expr expr) | #(GTMARK expr expr) // | #(UPLUS e:expr { #op_expr=#e;}) // elimintated | uminus | #(LOG_NEG expr) | #(ASTERIX expr expr) | #(MATRIX_OP1 expr expr) | #(MATRIX_OP2 expr expr) | #(SLASH expr expr) | #(MOD_OP expr expr) | #(POW expr expr) | #(DEC expr) //unbrace_expr) | #(INC expr) //unbrace_expr) | #(POSTDEC expr) //unbrace_expr) | #(POSTINC expr) //unbrace_expr) | primary_expr ; uminus : #(u:UMINUS e:expr) { // eliminate (pre-calculate) uminus for constants if( #e->getType() == CONSTANT) { #e->ResetCData( #e->CData()->UMinus()); #e->setText( "-"+#e->getText()); #uminus = #e; } // else // { // #uminus = #( [UMINUS,"u-"], e); // } } ; // remove multiple braces brace_expr!// : #(e:EXPR ex:expr) { while( #ex->getType()==EXPR) #ex=#ex->getFirstChild(); #brace_expr=#(e, ex); } ; // removes ALL braces unbrace_expr!// : #(EXPR ex:expr) { while( #ex->getType()==EXPR) #ex=#ex->getFirstChild(); #unbrace_expr=#ex; } ; // array and struct accessing indexable_expr // only used by array_expr : var | sysvar // | brace_expr | unbrace_expr ; array_expr // only used by expr : #(ARRAYEXPR indexable_expr arrayindex_list) | indexable_expr ; tag_indexable_expr // only used by tag_array_expr_1st : var | sysvar | brace_expr ; tag_array_expr_1st // only used by expr : #(ARRAYEXPR tag_indexable_expr arrayindex_list) | tag_indexable_expr ; tag_expr : brace_expr | IDENTIFIER ; tag_array_expr : #(ARRAYEXPR tag_expr arrayindex_list) | tag_expr ; // the everywhere used expression expr : array_expr | #(DOT tag_array_expr_1st (tag_array_expr)+) | #(DEREF expr) // deref | op_expr ; gdl-0.9.9/src/gdleventhandler.cpp000066400000000000000000000036201340051421000167270ustar00rootroot00000000000000/*************************************************************************** gdleventhandler.hpp - global event handler routine ------------------- begin : February 23 2004 copyright : (C) 2004 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // later this should become a thread // right now its called in DInterpreter::NoReadline(...) or via readline #include "includefirst.hpp" #ifdef __APPLE__ #include #endif #ifdef _WIN32 #include #endif #include "gdleventhandler.hpp" #include "graphicsdevice.hpp" #ifdef HAVE_LIBWXWIDGETS #include "gdlwidget.hpp" #endif using namespace std; int GDLEventHandler() { GraphicsDevice::HandleEvents(); #ifdef HAVE_LIBWXWIDGETS GDLWidget::HandleEvents(); #endif const long OS_X_DELAY_NS = 20000000; // 20ms //ONLY APPLE? or WIN? Why? (GD) #ifdef __APPLE__ // under OS X the event loop burns to much CPU time struct timespec delay; delay.tv_sec=0; delay.tv_nsec = OS_X_DELAY_NS; // 20ms nanosleep(&delay,NULL); #endif #ifdef _WIN32 Sleep(10); // this just to quiet down the character input from readline. 2 was not enough. 20 was ok. #endif return 0; } gdl-0.9.9/src/gdleventhandler.hpp000066400000000000000000000021701340051421000167330ustar00rootroot00000000000000/*************************************************************************** gdleventhandler.hpp - description ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLEVENTHANDLER_HPP_ #define GDLEVENTHANDLER_HPP_ // called from readline int GDLEventHandler(); #endif gdl-0.9.9/src/gdlexception.cpp000066400000000000000000000200111340051421000162370ustar00rootroot00000000000000/*************************************************************************** gdlexception.cpp - exception handling ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "gdlexception.hpp" #include "dnode.hpp" #include "initsysvar.hpp" #include "gdljournal.hpp" #include "dinterpreter.hpp" //#define GDL_DEBUG //#undef GDL_DEBUG using namespace std; DInterpreter* GDLException::interpreter = NULL; string GDLException::Name( BaseGDL* b) { if(interpreter!=NULL && interpreter->CallStack().size()>0) return interpreter->Name(b); return ""; } GDLException::GDLException(DLong eC, const string& s, bool pre, bool decorate): ANTLRException(s), errorNode(static_cast(antlr::nullAST)), errorNodeP( NULL), errorCode(eC), line( 0), col( 0), prefix( pre), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) { if(decorate && interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } // note: This is for cases, when form a destructor is thrown // in these cases, program aborts #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(const string& s, bool pre, bool decorate): ANTLRException(s), errorNode(static_cast(antlr::nullAST)), errorNodeP( NULL), errorCode(-1), line( 0), col( 0), prefix( pre), ioException( false), targetEnv( NULL) { if(decorate && interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } // note: This is for cases, when form a destructor is thrown // in these cases, program aborts #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(const RefDNode eN, const string& s): ANTLRException(s), errorNode(eN), errorNodeP( NULL), errorCode(-1), line( 0), col( 0), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) { if(interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(DLong eC, const RefDNode eN, const string& s): ANTLRException(s), errorNode(eN), errorNodeP( NULL), errorCode(eC), line( 0), col( 0), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) { if(interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(const ProgNodeP eN, const string& s, bool decorate, bool overWriteNode): ANTLRException(s), errorNode(static_cast(antlr::nullAST)), errorNodeP( eN), errorCode(-1), line( 0), col( 0), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) { if( overWriteNode && interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); } if( decorate && interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(DLong eC, const ProgNodeP eN, const string& s, bool decorate, bool overWriteNode): ANTLRException(s), errorNode(static_cast(antlr::nullAST)), errorNodeP( eN), errorCode(eC), line( 0), col( 0), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) { if( overWriteNode && interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); } if( decorate && interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(SizeT l, SizeT c, const string& s): ANTLRException(s), errorNode(static_cast(antlr::nullAST)), errorNodeP( NULL), errorCode(-1), line( l), col( c), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) { if(interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } #ifdef GDL_DEBUG cerr << s << endl; #endif } GDLException::GDLException(DLong eC, SizeT l, SizeT c, const string& s): ANTLRException(s), errorNode(static_cast(antlr::nullAST)), errorNodeP( NULL), errorCode(eC), line( l), col( c), prefix( true), arrayexprIndexeeFailed(false), targetEnv( NULL) { if(interpreter!=NULL && interpreter->CallStack().size()>0) { EnvBaseT* e = interpreter->CallStack().back(); errorNodeP = e->CallingNode(); msg = e->GetProName(); if( msg != "$MAIN$") msg += ": "+ s; else msg = s; } else { msg = s; } #ifdef GDL_DEBUG cerr << s << endl; #endif } void Message(const string& s) { if( SysVar::Quiet() == 0) { cout << SysVar::MsgPrefix() << s << endl; lib::write_journal_comment( SysVar::MsgPrefix() + s); } } void Warning(const std::string& s) { cout << SysVar::MsgPrefix() << s << endl; lib::write_journal_comment( SysVar::MsgPrefix() + s); } void ThrowGDLException( const std::string& str) { throw GDLException( str); } void WarnAboutObsoleteRoutine(const string& name) { // no static here due to .RESET_SESSION DStructGDL* warnStruct = SysVar::Warn(); // this static is ok as it will evaluate always to the same value static unsigned obs_routinesTag = warnStruct->Desc()->TagIndex( "OBS_ROUTINES"); if (((static_cast( warnStruct->GetTag(obs_routinesTag, 0)))[0]).LogTrue()) Message("Routine compiled from an obsolete library: " + name); // TODO: journal / !QUIET?? } void WarnAboutObsoleteRoutine(const RefDNode eN, const string& name) { // TODO: journal? // no static here due to .RESET_SESSION DStructGDL* warnStruct = SysVar::Warn(); // this static is ok as it will evaluate always to the same value static unsigned obs_routinesTag = warnStruct->Desc()->TagIndex( "OBS_ROUTINES"); if (((static_cast( warnStruct->GetTag(obs_routinesTag, 0)))[0]).LogTrue()) { GDLException* e = new GDLException(eN, "Routine compiled from an obsolete library: " + name ); Guard eGuard(e); GDLInterpreter::ReportCompileError(*e, ""); // TODO: file } } gdl-0.9.9/src/gdlexception.hpp000066400000000000000000000114701340051421000162550ustar00rootroot00000000000000/*************************************************************************** gdlexception.hpp ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLEXCEPTION_HPP_ #define GDLEXCEPTION_HPP_ #include #include #include "prognode.hpp" #include //using namespace std; class EnvUDT; class GDLException: public antlr::ANTLRException { static DInterpreter* interpreter; std::string msg; RefDNode errorNode; ProgNodeP errorNodeP; DLong errorCode; SizeT line; SizeT col; bool prefix; bool arrayexprIndexeeFailed; protected: bool ioException; private: EnvUDT* targetEnv; // where to stop (depending on ON_ERROR) public: static DInterpreter* Interpreter() { return interpreter;} static void SetInterpreter( DInterpreter* i) { interpreter = i;} static std::string Name( BaseGDL* b); void SetErrorNodeP( ProgNodeP p) { errorNodeP = p;} bool GetArrayexprIndexeeFailed() const { return arrayexprIndexeeFailed;} void SetArrayexprIndexeeFailed( bool b) { arrayexprIndexeeFailed = b;} GDLException(): ANTLRException(), errorNode(static_cast(antlr::nullAST)), errorNodeP( NULL), errorCode(-1), line( 0), col( 0), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) {} GDLException( DLong eC): ANTLRException(), errorNode(static_cast(antlr::nullAST)), errorNodeP( NULL), errorCode(eC), line( 0), col( 0), prefix( true), arrayexprIndexeeFailed(false), ioException( false), targetEnv( NULL) {} GDLException(const std::string& s, bool pre = true, bool decorate=true); GDLException(const RefDNode eN, const std::string& s); GDLException(const ProgNodeP eN, const std::string& s, bool decorate=true, bool overWriteNode=true); GDLException(SizeT l, SizeT c, const std::string& s); GDLException(DLong eC, const std::string& s, bool pre = true, bool decorate=true); GDLException(DLong eC, const RefDNode eN, const std::string& s); GDLException(DLong eC, const ProgNodeP eN, const std::string& s, bool decorate=true, bool overWriteNode=true); GDLException(DLong eC, SizeT l, SizeT c, const std::string& s); ~GDLException() throw() {} DLong ErrorCode() const { return errorCode;} std::string toString() const { return msg; } SizeT getLine() const { if( line != 0) return line; if( errorNodeP != NULL) return errorNodeP->getLine(); if( errorNode != static_cast(antlr::nullAST)) return errorNode->getLine(); return 0; } void SetLine( SizeT l) { line = l;} SizeT getColumn() const { // if( errorNode != static_cast(antlr::nullAST)) // return errorNode->getColumn(); return col; } bool Prefix() const { return prefix; } void SetTargetEnv( EnvUDT* tEnv) { targetEnv = tEnv; } EnvUDT* GetTargetEnv() { return targetEnv; } bool IsIOException() const { return ioException;} }; // for ON_IOERROR class GDLIOException: public GDLException { public: GDLIOException(): GDLException() { ioException = true;} GDLIOException(const std::string& s, bool pre = true): GDLException( s, pre) { ioException = true;} GDLIOException(const ProgNodeP eN, const std::string& s): GDLException( eN, s) { ioException = true;} GDLIOException(DLong eC): GDLException(eC) { ioException = true;} GDLIOException(DLong eC,const std::string& s, bool pre = true): GDLException( eC, s, pre) { ioException = true;} GDLIOException(DLong eC,const ProgNodeP eN, const std::string& s): GDLException( eC, eN, s) { ioException = true;} }; // warnings ignore !QUIET void Warning(const std::string& s); // messages honor !QUIET void Message(const std::string& s); void ThrowGDLException( const std::string& str); void WarnAboutObsoleteRoutine(const std::string& name); void WarnAboutObsoleteRoutine(const RefDNode eN, const std::string& name); #endif gdl-0.9.9/src/gdlgstream.cpp000066400000000000000000001310301340051421000157070ustar00rootroot00000000000000/* ************************************************************************* gdlgstream.cpp - graphic stream ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "graphicsdevice.hpp" #include "gdlgstream.hpp" #include "initsysvar.hpp" using namespace std; // bool GDLGStream::plstreamInitCalled = false; // void PLPlotAbortHandler(const char *c) // { // cout << "PLPlot abort handler: " << c << endl; // } // // int PLPlotExitHandler(const char *c) // { // cout << "PLPlot exit handler: " << c << endl; // return 0; // } // // void GDLGStream::SetErrorHandlers() // { // plsexit( PLPlotExitHandler); // plsabort( PLPlotAbortHandler); // } void GDLGStream::Thick(DFloat thick) { //note that 'cmake' may not able to find correct value of HAVE_PLPLOT_WIDTH. Please report. // in the meantime, you may edit "config.h" by hand. #ifdef HAVE_PLPLOT_WIDTH plstream::width(static_cast(thick*thickFactor)); #else plstream::wid(static_cast(floor((thick*thickFactor)-0.5))); #endif } #define BLACK 0 #define WHITE 16777215 void GDLGStream::Color( ULong color, DLong decomposed) { bool printer = (((*static_cast (SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0] & 512) == 512); bool bw = (((*static_cast (SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0] & 16) == 0); //in that case, //plplot postscript driver uses gray levels instead of colorindex, and 1 is black, not 0 !!! if (decomposed == 0) { if (printer && (color & 0xFF) == 0) { color=(bw)?WHITE:BLACK; //note that if bw other colors will be a gray value GDLGStream::SetColorMap1SingleColor(color); plstream::col1(1); //send specifically color ZERO = black. return; } else plstream::col0(color & 0xFF); //just set color index [0..255]. simple and fast. } else { if (printer && color == 0) color=(bw)?WHITE:BLACK; GDLGStream::SetColorMap1SingleColor(color); plstream::col1(1); //send specifically color ZERO = black. return; } } #undef BLACK void GDLGStream::SetColorMap1SingleColor( ULong color) { PLINT red[2],green[2],blue[2]; red[0] =red[1] = color & 0xFF; green[0] = green[1] =(color >> 8) & 0xFF; blue[0]= blue[1]=(color >> 16) & 0xFF; SetColorMap1(red, green, blue, 2); } void GDLGStream::SetColorMap1DefaultColors(PLINT ncolors, DLong decomposed) { if (decomposed == 0) { //just copy Table0 to Table1 so that scale from 0 to 1 in table 1 goes through the whole table PLINT r[ctSize], g[ctSize], b[ctSize]; GraphicsDevice::GetCT()->Get( r, g, b); SetColorMap1(r, g, b, ctSize); } else { PLFLT r[2], g[2], b[2], pos[2]; r[0] = pos[0] = 0.0; r[1] = pos[1] = 1.0; g[0] = g[1] = 0.0; b[0] = b[1] = 0.0; SetColorMap1n(ncolors); SetColorMap1l(TRUE,2,pos,r, g, b, NULL); } } void GDLGStream::SetColorMap1Table( PLINT tableSize, BaseGDL *passed_colors, DLong decomposed) { //cycle on passed colors to fill tableSize. DLongGDL *colors=static_cast(passed_colors); DLong n=colors->N_Elements(); #ifdef _MSC_VER PLINT *r = (PLINT*)alloca(sizeof(PLINT)*tableSize); PLINT *g = (PLINT*)alloca(sizeof(PLINT)*tableSize); PLINT *b = (PLINT*)alloca(sizeof(PLINT)*tableSize); #else PLINT r[tableSize], g[tableSize], b[tableSize]; #endif if (decomposed == 0) { PLINT red[ctSize], green[ctSize], blue[ctSize], col; GraphicsDevice::GetCT()->Get( red, green, blue); for (SizeT i=0; i< tableSize; ++i) { col = (*colors)[i%n]& 0xFF; r[i] = red[col]; g[i] = green[col]; b[i] = blue[col]; } } else { PLINT col; for (SizeT i=0; i< tableSize; ++i) { col = (*colors)[i%n]; r[i] = col & 0xFF; g[i] = (col >> 8) & 0xFF; b[i] = (col >> 16) & 0xFF; } } SetColorMap1(r, g, b, tableSize); } void GDLGStream::SetColorMap1Ramp(DLong decomposed, PLFLT minlight) { //cycle on passed colors to fill table1 with ramp. PLFLT h[2], l[2], s[2], pos[2]; h[0] = h[1] = s[0] = s[1] = pos[0] = 0.0; l[0] = minlight; l[1] = pos[1] = 1.0; SetColorMap1n(256); SetColorMap1l(FALSE,2,pos,h, l, s, NULL); } #define WHITEB 255 void GDLGStream::Background( ULong color, DLong decomposed) { if ((*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0] & 512 ) { ;//printer like PostScript GraphicsDevice::GetDevice()->SetDeviceBckColor(WHITEB, WHITEB, WHITEB ); return; } DByte r,g,b; PLINT red,green,blue; if (decomposed == 0) { //just an index GraphicsDevice::GetCT()->Get( color & 0xFF, r, g, b); red=r; green=g; blue=b; } else { red = color & 0xFF; green = (color >> 8) & 0xFF; blue = (color >> 16) & 0xFF; } GraphicsDevice::GetDevice()->SetDeviceBckColor( red, green, blue); } void GDLGStream::DefaultBackground() { if ((*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0] & 512 ) { ;//printer like PostScript GraphicsDevice::GetDevice()->SetDeviceBckColor(WHITEB, WHITEB, WHITEB ); return; } DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DLong background=(*static_cast(pStruct->GetTag(pStruct->Desc()->TagIndex("BACKGROUND"), 0)))[0]; DByte r,g,b; PLINT red,green,blue; if (GraphicsDevice::GetDevice()->GetDecomposed() == 0) { //just an index GraphicsDevice::GetCT()->Get( background & 0xFF, r, g, b); red=r; green=g; blue=b; } else { red = background & 0xFF; green = (background >> 8) & 0xFF; blue = (background >> 16) & 0xFF; } GraphicsDevice::GetDevice()->SetDeviceBckColor( red, green, blue); } #undef WHITEB void GDLGStream::DefaultCharSize() { DStructGDL* d = SysVar::D(); DStructDesc* s = d->Desc(); int X_CH_SIZE = s->TagIndex("X_CH_SIZE"); int Y_CH_SIZE = s->TagIndex("Y_CH_SIZE"); int X_PX_CM = s->TagIndex("X_PX_CM"); int Y_PX_CM = s->TagIndex("Y_PX_CM"); // int NAME = s->TagIndex("NAME"); // DString name = (*static_cast(d->GetTag(NAME, 0)))[0]; ////values must be those that plplot think are good. Most of the time they are not. // if (name == "PS" || name=="SVG") schr( 2.5, 1.0, 2.5); // else { //#if defined(_WIN32) // schr(2.1, 1.4, 2.1); // from 1.5, 1.0 2014/09/18 //This is a feature of windows --- or of windows plplot -- to be confirmed. //#else DLong chx = (*static_cast (d->GetTag(X_CH_SIZE, 0)))[0]; DLong chy = (*static_cast (d->GetTag(Y_CH_SIZE, 0)))[0]; DFloat xpxcm = (*static_cast (d->GetTag(X_PX_CM, 0)))[0]; DFloat ypxcm = (*static_cast (d->GetTag(Y_PX_CM, 0)))[0]; DFloat xchsizemm = chx * CM_IN_MM / xpxcm; DFloat linespacingmm = chy * CM_IN_MM / ypxcm; schr(xchsizemm, 1.0, linespacingmm); //#endif // } } void GDLGStream::RenewPlplotDefaultCharsize(PLFLT newMmSize) { plstream::schr(newMmSize, 1.0); gdlDefaultCharInitialized=0; GetPlplotDefaultCharSize(); } void GDLGStream::GetPlplotDefaultCharSize() { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"GetPlPlotDefaultCharsize()\n"); if (thePage.nbPages==0) {return;} //dimensions in normalized, device and millimetres if (gdlDefaultCharInitialized==1) {if (GDL_DEBUG_PLSTREAM) fprintf(stderr," Already initialized\n"); return;} theDefaultChar.scale=1.0; theDefaultChar.mmsx=pls->chrht; //millimeter theDefaultChar.mmsy=pls->chrht; theDefaultChar.ndsx=mm2ndx(theDefaultChar.mmsx); //normalized device theDefaultChar.ndsy=mm2ndy(theDefaultChar.mmsy); theDefaultChar.dsy=theDefaultChar.ndsy*thePage.height; theDefaultChar.dsx=theDefaultChar.ndsx*thePage.length; theDefaultChar.mmspacing=theLineSpacing_in_mm; theDefaultChar.nspacing=mm2ndy(theDefaultChar.mmspacing); theDefaultChar.dspacing=theDefaultChar.nspacing*thePage.height; theDefaultChar.wspacing=mm2wy(theDefaultChar.mmspacing); theDefaultChar.wsx=mm2wx(theDefaultChar.mmsx); //world theDefaultChar.wsy=mm2wy(theDefaultChar.mmsy); if (GDL_DEBUG_PLSTREAM) fprintf(stderr," %fx%f,%f (mm)\n",theDefaultChar.mmsx ,theDefaultChar.mmsy ,theDefaultChar.mmspacing); if (GDL_DEBUG_PLSTREAM) fprintf(stderr," %fx%f,%f (norm)\n",theDefaultChar.ndsx ,theDefaultChar.ndsy ,theDefaultChar.nspacing); if (GDL_DEBUG_PLSTREAM) fprintf(stderr," %fx%f,%f (dev)\n",theDefaultChar.dsx ,theDefaultChar.dsy ,theDefaultChar.dspacing); if (GDL_DEBUG_PLSTREAM) fprintf(stderr," %fx%f,%f (world)\n",theDefaultChar.wsx ,theDefaultChar.wsy ,theDefaultChar.wspacing); gdlDefaultCharInitialized=1; } void GDLGStream::NextPlot( bool erase ) { DLongGDL* pMulti = SysVar::GetPMulti(); DLong nx = (*pMulti)[ 1]; DLong ny = (*pMulti)[ 2]; DLong nz = (*pMulti)[ 3]; DLong dir = (*pMulti)[ 4]; nx = (nx>0)?nx:1; ny = (ny>0)?ny:1; nz = (nz>0)?nz:1; if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"NextPlot(erase=%d)\n",erase); // set subpage numbers in X and Y // plstream::ssub( nx, ny ); // ssub does not change charsize it seems ssub( nx, ny ); DLong pMod = (*pMulti)[0] % (nx*ny); // if( (*pMulti)[0] <= 0 || (*pMulti)[0] == nx*ny) // clear and restart to first subpage if( pMod == 0 ) // clear and restart to first subpage { if( erase ) { eop(); // overridden (for Z-buffer) //get background value (*not pen 0*, we try to avoid plplot's silly behaviour). //use it for bop(), then reset the pen 0 to correct value. PLINT red,green,blue; DByte r,g,b; PLINT red0,green0,blue0; GraphicsDevice::GetCT()->Get(0,r,g,b);red=r;green=g;blue=b; red0=GraphicsDevice::GetDevice()->BackgroundR(); green0=GraphicsDevice::GetDevice()->BackgroundG(); blue0=GraphicsDevice::GetDevice()->BackgroundB(); plstream::scolbg(red0,green0,blue0); //overwrites col[0] plstream::bop(); // note: changes charsize plstream::scolbg(red,green,blue); //resets col[0] } // plstream::adv(1); //advance to first subpage adv(1); //advance to first subpage (*pMulti)[0] = nx*ny*nz-1; //set PMULTI[0] to this page } else { if( dir == 0 ) { // plstream::adv(nx*ny - pMod + 1); adv(nx*ny - pMod + 1); } else { int p = nx*ny - pMod; int pp = p*nx % (nx*ny) + p/ny + 1; // plstream::adv(pp); adv(pp); } if( erase ) { --(*pMulti)[0]; } } // restore charsize to default for newpage sizeChar(1.0); } void GDLGStream::NoSub() { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"NoSub()\n"); ssub( 1, 1); // changes charsize ? //plstream::adv( 0); adv( 0); // DefaultCharSize(); } // default is a wrapper for gpage(). Is overriden by, e.g., X driver. void GDLGStream::GetGeometry( long& xSize, long& ySize) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"GDLGStream::GetGeometry()\n"); PLFLT xp; PLFLT yp; PLINT xleng; PLINT yleng; PLINT plxoff; PLINT plyoff; plstream::gpage( xp, yp, xleng, yleng, plxoff, plyoff); //for X-Window, wrapper give sizes from X11, not plplot which seems bugged. // for PostScript, Page size is FIXED (720x540) and GDLPSStream::GetGeometry replies correctly //since the page sizes for PS and EPS images are processed by GDL after plplot finishes //its work, gpage will not output correct sizes DString name = (*static_cast( SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("NAME"), 0) ))[0]; if (name == "PS") { xSize = (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("X_SIZE"), 0)))[0]; ySize = (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("Y_SIZE"), 0)))[0]; } else { xSize = xleng; ySize = yleng; } if (xSize<1.0||ySize<1) //plplot gives back crazy values! z-buffer for example! { PLFLT xmin,xmax,ymin,ymax; plstream::gspa(xmin,xmax,ymin,ymax); //subpage in mm xSize=min(1.0,xmax-xmin); ySize=min(1.0,ymax-ymin); } if (GDL_DEBUG_PLSTREAM) fprintf(stderr," found (%ld %ld)\n", xSize, ySize); } // SA: embedded font attributes handling (IDL to plPlot syntax translation) std::string GDLGStream::TranslateFormatCodes(const char *in, double *stringLength=NULL) { bool debug = false; static char errmsg[] = "No such font: "; static const size_t errmsglen = strlen(errmsg); static double fact[]={1.,0.9,0.666,0.5,0.45,0.33,0.2}; double base=1.0; // TODO: // - in IDL the D.FLAGS bit value ((!D.FLAGS AND 4096) EQ 0) // is designed to indicate if the device does not support extended commands // - unicode substitution for non-unicode terminals results in plplot controll // sequences being printed // do something about handling of !C and !S and !R // - ... a look-up table instead of the long switch/case blocks ... size_t len = strlen(in); if (stringLength) *stringLength=0; // skip conversion if the string is empty if (len == 0) return ""; int default_fnt = activeFontCodeNum; std::string out = std::string(internalFontCodes[default_fnt]); //no, take current value, initialized to 3. was: activeFontCodeNum = default_fnt; // (current font number from the above table) int curr_fnt = default_fnt; // (current font number from the above table) int next_fnt = default_fnt; // (next letter font - same as curr_fnt save for the case of !G, !W and !M commands) int curr_lev = 0; // (incremented with #u, decremented with #d) int curr_pos = 0; // (current position in string) int save_pos = 0; // (position in string used in !S/!R save/restore) for (size_t i = 0; i < len; i++) { if (in[i] == '!' && in[i + 1] != '!') { size_t j = 1; // number of characters analysed (after !) switch (in[i + 1]) { case '1' : // 2-char codes begining with !1 { switch (in[i + 2]) { case '6' : // !16 : Cyrillic base=17./15.;//approx size of a hershey char with this font. j++; out += internalFontCodes[activeFontCodeNum = curr_fnt = next_fnt = 10 - 48 + in[i + 2]]; break; case '8' : // !18 : Triplex Italic base=16.5/15.;//approx size of a hershey char with this font. j++; out += internalFontCodes[activeFontCodeNum = curr_fnt = next_fnt = 10 - 48 + in[i + 2]]; break; case '0' : // !10 : Special characters case '1' : // !11 : Gothic English case '2' : // !12 : Simplex Script case '3' : // !13 : Complex Script case '4' : // !14 : Gothic Italian case '5' : // !15 : Gothic German case '7' : // !17 : Triplex Roman case '9' : // !19 : base=1.0; j++; out += internalFontCodes[activeFontCodeNum = curr_fnt = next_fnt = 10 - 48 + in[i + 2]]; break; default : // illegal command / end of string errmsg[errmsglen - 2] = in[i + 1]; errmsg[errmsglen - 1] = in[i + 2]; j++; Warning(errmsg); } break; } case '2' : // 2-char codes begining with !2 { switch (in[i + 2]) { case '0' : // !20 : Miscellaneous base=17.5/15.;//approx size of a hershey char with this font. j++; out += internalFontCodes[activeFontCodeNum = curr_fnt = next_fnt = 20 - 48 + in[i + 2]]; break; default : // illegal command / end of string errmsg[errmsglen - 2] = in[i + 1]; errmsg[errmsglen - 1] = in[i + 2]; j++; Warning(errmsg); } break; } case '7' : // complex greek case '8' : // complex italic base=16.5/15.; //approx size of a hershey char with these fonts. out += internalFontCodes[activeFontCodeNum = next_fnt = curr_fnt = in[i + 1] - 48]; break; case '3' : // simplex roman case '4' : // greek script case '5' : // duplex roman case '6' : // complex roman case '9' : // Math/special characters base=1.0; out += internalFontCodes[activeFontCodeNum = next_fnt = curr_fnt = in[i + 1] - 48]; break; case 'M' : case 'm' : // one Math/special character curr_fnt = 9; break; case 'G' : case 'g' : // one Gothic English character curr_fnt = 11; break; case 'W' : case 'w' : // one Simplex Script character curr_fnt = 12; break; case 'C' : case 'c' : // carriage return (TODO FIXME: does not work in PostScript!) out += "#[0xD]"; break; case 'X' : case 'x' : // reversion to entry font out += internalFontCodes[curr_fnt = next_fnt = default_fnt]; break; case 'S' : case 's' : // save position save_pos = curr_pos; break; case 'L' : case 'l' : // 2nd level subscript curr_lev--; out += "#d"; // continues! case 'B' : case 'b' : case 'D' : case 'd' : // subscript case 'I' : case 'i' : // index curr_lev--; out += "#d"; break; case 'R' : case 'r' : // restore position for (; save_pos < curr_pos; curr_pos--) out += "#b"; // continues! //case 'A' : case 'a' : // shift above the division line //TODO: plplot seems not to support it ----> treated as upperscript for the moment // case 'B' : case 'b' : // shift below the division line //TODO: plplot seems not to support it ----> treated as subscript for the moment case 'N' : case 'n' : // back to normal size while (curr_lev != 0) { if (curr_lev > 0) out += "#d", curr_lev--; else out += "#u", curr_lev++; } // assumed from examples in documentation //if (in[i + 1] == 'N' || in[i + 1] == 'n') out += internalFontCodes[curr_fnt = next_fnt = default_fnt]; break; case 'A' : case 'a' : case 'U' : case 'u' : // superscript case 'E' : case 'e' : // exponent curr_lev++; out += "#u"; break; case 'Z' : case 'z' : // unicode chars via "#[nnn]" // first, the only two examples from IDL doc: // - !Z(00B0) - degree symbol // - !Z(U+0F1) - Spanish "n" with tilde (as in El ni\~no) // searching for the left parenthesis if (in[i + 2] != '(') { if (in[i + 2] == '!' && in[i + 3] == 'Z') break; // !Z!Z is valid if (in[i + 2] == '\0') break; // end of string after !Z is valid Warning("Error using Hershey characters: Parentheses required for !Z."); goto retrn; } else { // searching for the right parenthesis size_t right_par = i + 2; while (in[++right_par] != ')') if (right_par == len) { Warning("Error using Hershey characters: Parentheses required for !Z."); goto retrn; } size_t chars = 0; while (j + i + 1 != right_par) { // tokenizing (plethora of other tokens is accepted by IDL!) while (++j + i + 1 != right_par && in[j + i + 1] != ',') chars++; if (in[j + i + 1 - chars] == 'U' && in[j + i + 2 - chars] == '+') chars-=2; // U+NNNN syntax if (chars > 4) { Warning("Error using Hershey characters: !Z hexadecimal value too large."); goto retrn; } else if (chars > 0) { out += "#[0x"; for (; chars > 0; chars--) out += in[j + i + 1 - chars]; out += "]"; curr_pos++; } } j++; // right parenthesis } break; case '\0' : // end of string default : // unknown command j--; curr_pos++; out += "!"; break; } i += j; } else { if (stringLength) *stringLength+=base*fact[curr_lev%7]; curr_pos++; // handling IDL exclamation mark escape '!!' if (in[i] == '!') { i++; if (stringLength) *stringLength+=base*fact[curr_lev%7]; } // handling plplot number sign escape '##' if ( curr_fnt != 9 && curr_fnt != 10 && curr_fnt != 16 && curr_fnt != 20 && in[i] == '#' ) out += "##"; else switch (curr_fnt) { case 9 : // math symbols switch (in[i]) { case '!' : out += "#(2229)"; break; // vertical line case '%' : out += "#(218)"; break; // degree circle case 'X' : out += "#(227)"; break; // x (cross) sign case 'D' : // as below case 'd' : out += "#(2265)"; break; // partial deriv sign case 'r' : out += "#(2267)"; break; // square root sign bigger case 'R' : out += "#(2411)"; break; // square root sign biggest case 'S' : out += "#(2267)"; break; // square root sign case 'I' : out += "#(2412)"; break; // big integral sign case 'i' : out += "#(2268)"; break; // small integral sign case '/' : out += "#(2237)"; break; // range (dot dash dot) sign case '=' : out += "#(2239)"; break; // non equal sign case '6' : out += "#(2261)"; break; // arrow right case '7' : out += "#(2262)"; break; // arrow up case '4' : out += "#(2263)"; break; // arrow left case '5' : out += "#(2264)"; break; // arrow down case 'f' : out += "#(2283)"; break; // female sex sign case 'm' : out += "#(2285)"; break; // male sex sign case '<' : out += "#(2407)"; break; // big curly brace left case '>' : out += "#(2408)"; break; // big curly brace right case '#' : out += "#(737)"; break; // two vertical lines case '$' : out += "#(766)"; break; // infty case '&' : out += "#(2276)"; break; // paragraph case 'P' : out += "#(2147)"; break; // phi case 'p' : out += "#fsp"; out += internalFontCodes[curr_fnt]; break; // p script case 'q' : out += "#fsq"; out += internalFontCodes[curr_fnt]; break; // q script case ':' : out += "#(2240)"; break; // equal by definition sign case '.' : out += "#(850)"; break; // filled dot case 'B' : out += "#(841)"; break; // empty square case 'F' : out += "#fsF"; out += internalFontCodes[curr_fnt]; break; // F script case 'J' : out += "#(2269)"; break; // closed path integral case 'O' : out += "#(2277)"; break; // 'upper' cross sign case 'o' : out += "#(2278)"; break; // double cross sign case 'j' : out += "#fsj"; out += internalFontCodes[curr_fnt]; break; // j italic case 's' : out += "#(687)"; break; // some greek zig-zag case 't' : out += "#fs#(634)"; break; // theta-like greek zig-zag case 'A' : out += "#(2246)"; break; // similar / tilde case 'T' : out += "#(740)"; break; // three dots case 'U' : out += "#(741)"; break; // spades (card sign) case 'V' : out += "#(743)"; break; // diamonds (card sign) case 'W' : out += "#(745)"; break; // clover sign case 'u' : out += "#(742)"; break; // hearts (card sign) case 'v' : out += "#(744)"; break; // clubs (card sign) case 'w' : out += "#(746)"; break; // ? case '_' : // as below case 127u : out += "#(830)"; break; // '---' sign case 'H' : out += "#(908)"; break; // ? case '@' : out += "#(2077)"; break; // ? kappa like case 'n' : out += "#(2281)"; break; // circle with dot inside case 'e' : out += "#(2260)"; break; // mirrored E case 'E' : out += "#(2279)"; break; // element of case 'G' : out += "#(2266)"; break; // nabla case 'l' : out += "#(2243)"; break; // less or equal case 'b' : out += "#(2244)"; break; // grater or equal case '?' : out += "#(2245)"; break; // proportional case '^' : // as below case '~' : out += "#(2247)"; break; // ^ case '+' : out += "#(2233)"; break; // plus minus case '-' : out += "#(2234)"; break; // minus plus case '(' : out += "#(2403)"; break; // big bracket left case ')' : out += "#(2404)"; break; // big bracket right case '[' : // as below case '{' : out += "#(2405)"; break; // big rect. brace left case ']' : // as below case '}' : out += "#(2406)"; break; // big rect. brace right case 'h' : out += "#(909)"; break; // ? police badge-like case 'x' : out += "#(738)"; break; // perpendicular sign case 'a' : out += "#(739)"; break; // angle case 'c' : out += "#(823)"; break; // ? case '0' : out += "#(2256)"; break; // set theory C-like case '1' : out += "#(2257)"; break; // set theory U-like case '2' : out += "#(2258)"; break; // set theory )-like case '3' : out += "#(2259)"; break; // set theory ^-like case 'N' : out += "#(2311)"; break; // double wave case '`' : out += "'"; break; // ` -> ' // empty chars: case '8' : case '9' : case ';' : case 'K' : case 'L' : case 'M' : case 'Q' : case 'Y' : case 'Z' : case '\\' : case 'k' : case 'y' : case 'z' : case '|' : case 'g' : // unsupported chars: case 'C' : // tick sign out += " "; break; break; default : out.append(in, i, 1); break; } break; case 20 : // misc symbols switch (in[i]) { case 'b' : out += "#(851)"; break; // filled square case ':' : // small filled triangle up case 'C' : out += "#(852)"; break; // filled triangle up case 'D' : out += "#(854)"; break; // filled triangle down case '/' : out += "#(2323)"; break; // musical sharp sign case 'M' : out += "#(874)"; break; // ? case 'K' : out += "#(870)"; break; // palm sign case '^' : // as below case '~' : out += "#(834)"; break; // upside down triangle case 'N' : out += "#(900)"; break; // circle smallest case 'n' : out += "#(901)"; break; // circle smaller case 'O' : out += "#(902)"; break; // circle small case 'o' : out += "#(903)"; break; // circle case 'P' : out += "#(904)"; break; // circle case 'p' : out += "#(905)"; break; // circle big case 'Q' : out += "#(906)"; break; // circle bigger case 'q' : out += "#(907)"; break; // circle biggest case '?' : out += "#(767)"; break; // flash case '<' : out += "#(768)"; break; // paragraph-like case 'A' : out += "#(754)"; break; // upper semicircle filled case 'G' : out += "#(862)"; break; // two hammers case 'E' : out += "#(856)"; break; // star case 'e' : out += "#(857)"; break; // flag case 'f' : out += "#(861)"; break; // ? case 'g' : out += "#(863)"; break; // tower / look-out case 'h' : out += "#(865)"; break; // grave case 'L' : out += "#(872)"; break; // deciduous tree case 'k' : out += "#(871)"; break; // coniferous tree case '"' : out += "#(2409)"; break; // big inverted-s-like shape case '$' : out += "#(2376)"; break; // ? case '%' : out += "#(2382)"; break; // ? case '`' : case '\'' : out += "#(766)"; break; // infty case '(' : out += "#(2374)"; break; // natural (music) case ')' : out += "#(2375)"; break; // flat (music) case '*' : out += "#(2372)"; break; // ? minim (music) case '-' : // as below case '+' : out += "#(2371)"; break; // ? 2xminim length note (music) case ',' : out += "#(2329)"; break; // ? rest (music) case '.' : out += "#(2380)"; break; // treble clef case '0' : out += "#(2306)"; break; // ? Gothic-like m case '1' : out += "#(2307)"; break; // ? underlined omega case '2' : out += "#(2308)"; break; // ? Gothic-like m case '3' : out += "#(2309)"; break; // NE double arrow case '4' : out += "#(2310)"; break; // ? case '5' : out += "#(2311)"; break; // ? case '6' : out += "#(2312)"; break; // ? case '7' : out += "#(2317)"; break; // ? case '8' : out += "#(2318)"; break; // ? case '9' : out += "#(2319)"; break; // ? case '=' : out += "#(2377)"; break; // ? case '>' : out += "#(831)"; break; // ? case 'V' : out += "#(2291)"; break; // crescent case 'W' : out += "#(2293)"; break; // 8-arm star case 'X' : out += "#(2295)"; break; // ? case 'Y' : out += "#(2302)"; break; // ? case 'Z' : out += "#(2304)"; break; // 69 ;) case 'r' : out += "#(2282)"; break; // ? female sex sign like case 'u' : out += "#(2290)"; break; // ? P-like case 'v' : out += "#(2292)"; break; // ? case 'w' : out += "#(2294)"; break; // ? omega-like case 'x' : out += "#(2301)"; break; // ? fountain-like case 'y' : out += "#(2303)"; break; // ? case '[' : // as below case '{' : out += "#(2332)"; break; // ? ladder-like case ']' : // as below case '}' : out += "#(2381)"; break; // bass clef case '_' : // as below case 127 : out += "#(2410)"; break; // big s-like shape case '!' : out += "#(764)"; break; // S-like case '&' : out += "#(765)"; break; // tilde-like half-infty sign case 'B' : out += "#(850)"; break; // filled dot case 'F' : out += "#(860)"; break; // anchor case 'I' : out += "#(866)"; break; // cross case 'J' : out += "#(868)"; break; // Jewish star case 'R' : out += "#(735)"; break; // square-like case 'a' : out += "#(755)"; break; // filled triangle case 'i' : out += "#(867)"; break; // small screscent case 'j' : out += "#(869)"; break; // bell case ' ' : out += "#(2328)"; break; // ? case '#' : out += "#(2331)"; break; // ? case 'S' : out += "#(2284)"; break; // empty circel with plus sign inside case 'T' : out += "#(2287)"; break; // ? case 'U' : out += "#(2289)"; break; // ? greep psi-like case '\\' : // as below case '|' : out += "#(833)"; break; // ? electrical ground sign-like case 'c' : out += "#(853)"; break; // filled triangle left case 'd' : out += "#(855)"; break; // filled triangle right case '@' : out += "#(832)"; break; // ^ case 'H' : out += "#(864)"; break; // flower in a flowerpot case 's' : out += "#(2286)"; break; // 4-like case 't' : out += "#(2288)"; break; // ? case ';' : out += "#(840)"; break; // empty circle case 'l' : out += "#(873)"; break; // ? case 'z' : out += "#(2305)"; break; // ? case 'm' : out += "#(899)"; break; // smallest circle - dot default : out.append(in, i, 1); break; } break; case 16 : // Cyrillic switch (in[i]) { // uppercase lowercase case 'A' : out += "#(2801)"; break; case 'a' : out += "#(2901)"; break; // [a] case 'B' : out += "#(2802)"; break; case 'b' : out += "#(2902)"; break; // [b] case 'C' : out += "#(2803)"; break; case 'c' : out += "#(2903)"; break; // [v] case 'D' : out += "#(2804)"; break; case 'd' : out += "#(2904)"; break; // [g] case 'E' : out += "#(2805)"; break; case 'e' : out += "#(2905)"; break; // [d] case 'F' : out += "#(2806)"; break; case 'f' : out += "#(2906)"; break; // [ye] case 'G' : out += "#(2807)"; break; case 'g' : out += "#(2907)"; break; // [zsh] case 'H' : out += "#(2808)"; break; case 'h' : out += "#(2908)"; break; // [z] case 'I' : out += "#(2809)"; break; case 'i' : out += "#(2909)"; break; // [i/e] case 'J' : out += "#(2810)"; break; case 'j' : out += "#(2910)"; break; // [ii] case 'K' : out += "#(2811)"; break; case 'k' : out += "#(2911)"; break; // [k] case 'L' : out += "#(2812)"; break; case 'l' : out += "#(2912)"; break; // [l] case 'M' : out += "#(2813)"; break; case 'm' : out += "#(2913)"; break; // [m] case 'N' : out += "#(2814)"; break; case 'n' : out += "#(2914)"; break; // [n] case 'O' : out += "#(2815)"; break; case 'o' : out += "#(2915)"; break; // [o] case 'P' : out += "#(2816)"; break; case 'p' : out += "#(2916)"; break; // [p] case 'Q' : out += "#(2817)"; break; case 'q' : out += "#(2917)"; break; // [r] case 'R' : out += "#(2818)"; break; case 'r' : out += "#(2918)"; break; // [s] case 'S' : out += "#(2819)"; break; case 's' : out += "#(2919)"; break; // [t] case 'T' : out += "#(2820)"; break; case 't' : out += "#(2920)"; break; // [u/woo] case 'U' : out += "#(2821)"; break; case 'u' : out += "#(2921)"; break; // [f] case 'V' : out += "#(2822)"; break; case 'v' : out += "#(2922)"; break; // [h] case 'W' : out += "#(2823)"; break; case 'w' : out += "#(2923)"; break; // [c] case 'X' : out += "#(2824)"; break; case 'x' : out += "#(2924)"; break; // [ch] case 'Y' : out += "#(2825)"; break; case 'y' : out += "#(2925)"; break; // [sh] case 'Z' : out += "#(2826)"; break; case 'z' : out += "#(2926)"; break; // [shch] case '#' : out += "#(2827)"; break; case '<' : out += "#(2927)"; break; // hard sign case '{' : case '[' : out += "#(2828)"; break; case '>' : out += "#(2928)"; break; // [y] case '}' : case ']' : out += "#(2829)"; break; case '@' : out += "#(2929)"; break; // soft sign case '%' : out += "#(2830)"; break; case '\\' : case '|' : out += "#(2930)"; break; // [eh] case '"' : out += "#(2831)"; break; case '^' : case '~' : out += "#(2931)"; break; // [yu] case 127u : case '_' : out += "#(2832)"; break; case ';' : out += "#(2932)"; break; // [ya] default : out.append(in, i, 1); break; } break; case 4 : // greek letters case 7 : switch (in[i]) { // non-equivalent letters case 'C' : out += "#gG"; break; case 'c' : out += "#gg"; break; case 'F' : out += "#gZ"; break; case 'f' : out += "#gz"; break; case 'G' : out += "#gY"; break; case 'g' : out += "#gy"; break; case 'J' : out += "#gK"; break; case 'j' : out += "#gk"; break; case 'K' : out += "#gL"; break; case 'k' : out += "#gl"; break; case 'L' : out += "#gM"; break; case 'l' : out += "#gm"; break; case 'M' : out += "#gN"; break; case 'm' : out += "#gn"; break; case 'N' : out += "#gC"; break; case 'n' : out += "#gc"; break; case 'Q' : out += "#gR"; break; case 'q' : out += "#gr"; break; case 'R' : out += "#gS"; break; case 'r' : out += "#gs"; break; case 'S' : out += "#gT"; break; case 's' : out += "#gt"; break; case 'T' : out += "#gU"; break; case 't' : out += "#gu"; break; case 'U' : out += "#gF"; break; case 'u' : out += "#gf"; break; case 'V' : out += "#gX"; break; case 'v' : out += "#gx"; break; case 'W' : out += "#gQ"; break; case 'w' : out += "#gq"; break; case 'X' : out += "#gW"; break; case 'x' : out += "#gw"; break; case 'Y' : case 'y' : out += "#(766)"; break; case '{' : out += '['; break; case '}' : out += ']'; break; // equivalent letters case 'A' : case 'a' : case 'B' : case 'b' : case 'D' : case 'd' : case 'E' : case 'e' : case 'H' : case 'h' : case 'I' : case 'i' : case 'O' : case 'o' : case 'P' : case 'p' : out += "#g"; default : out.append(in, i, 1); break; } break; case 3 : // simplex roman switch ((unsigned char)in[i]) { // unsupported chars case '^' : case '~' : case '\\' : out += " "; break; // 8th bit chars case 144u : out += "1"; break; case 154u : out += "#(218)"; break; // degree circle case 163u : out += "#(272)"; break; // pound sign case 167u : out += "#(2276)"; break; // paragraph case 169u : out += "#(274)"; break; // copyright sign case 174u : out += "#(273)"; break; // registered sign case 181u : out += "#gm"; break; // greek mu case 188u : out += "#(270)"; break; // 1/4 case 189u : out += "#(261)"; break; // 1/2 case 190u : out += "#(271)"; break; // 3/4 case 215u : out += "#(846)"; break; // cross sign case 223u : out += "#fs#gb"; out += internalFontCodes[curr_fnt]; break; // beta script default : out.append(in, i, 1); break; } break; default : // simply pass the char out.append(in, i, 1); break; } curr_fnt = next_fnt; } } activeFontCodeNum = curr_fnt; //if gdlGetStringLength function is available, use it to give back a better value ("X" and "I" do not have the same width in hershey format!) #if PLPLOT_PRIVATE_NOT_HIDDEN if (stringLength) *stringLength=gdlGetStringLength(out)/this->mmCharLength(); #endif return out; retrn: activeFontCodeNum = curr_fnt; if (stringLength) *stringLength=0; if (debug) cout << "GDLGStream::TranslateFormatCodes(\"" << in << "\") = \"" << out << "\"" << endl; return ""; } void GDLGStream::setSymbolSize( PLFLT scale ) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"setSymbolScale(%f)\n",scale); plstream::ssym(0.0, scale); theCurrentSymSize=scale; } void GDLGStream::setLineSpacing(PLFLT newSpacing) { theLineSpacing_in_mm=newSpacing; } PLFLT GDLGStream::getSymbolSize(){return theCurrentSymSize;} void GDLGStream::mtex( const char *side, PLFLT disp, PLFLT pos, PLFLT just, const char *text) { plstream::mtex(side,disp,pos,just,TranslateFormatCodes(text).c_str()); } void GDLGStream::mtex3( const char *side, PLFLT disp, PLFLT pos, PLFLT just, const char *text) { plstream::mtex3(side,disp,pos,just,TranslateFormatCodes(text).c_str()); } void GDLGStream::ptex( PLFLT x, PLFLT y, PLFLT dx, PLFLT dy, PLFLT just, const char *text , double *stringCharLength) { plstream::ptex(x,y,dx,dy,just,TranslateFormatCodes(text,stringCharLength).c_str()); } void GDLGStream::schr( PLFLT charwidthmm, PLFLT scale , PLFLT lineSpacingmm) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"schr(%f,%f,%f)\n",charwidthmm,scale,lineSpacingmm); plstream::schr(charwidthmm, scale); this->setLineSpacing(lineSpacingmm); gdlDefaultCharInitialized=0; CurrentCharSize(scale); } void GDLGStream::sizeChar( PLFLT scale ) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"SizeChar(%f)\n",scale); plstream::schr(theDefaultChar.mmsx, scale); // plstream::schr(0, scale); CurrentCharSize(scale); } void GDLGStream::vpor(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax ) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"vpor(): requesting x[%f:%f],y[%f:%f] (normalized, subpage)\n",xmin,xmax,ymin,ymax); //note that plplot apparently does not write the y=0 line of pixels (in device coords). IDL page is on the contrary limited to // [0..1[ in both axes (normalized coordinates) plstream::vpor(xmin, xmax, ymin, ymax); theBox.nx1=xmin; theBox.nx2=xmax; theBox.ny1=ymin; theBox.ny2=ymax; PLFLT x1,x2,y1,y2; plstream::gvpd(x1,x2,y1,y2); //retrieve NORMALIZED DEVICE coordinates of viewport theBox.ndx1=x1; theBox.ndx2=x2; theBox.ndy1=y1; theBox.ndy2=y2; theBox.ondx=x1; theBox.ondy=y1; theBox.sndx=x2-x1; theBox.sndy=y2-y1; theBox.initialized=true; if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"vpor(): got x[%f:%f],x[%f:%f] (normalized, device)\n",theBox.ndx1,theBox.ndx2,theBox.ndy1,theBox.ndy2); syncPageInfo(); } void GDLGStream::wind( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax ) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"wind(): setting x[%f:%f],y[%f:%f] (world) \n",xmin,xmax,ymin,ymax); plstream::wind(xmin, xmax, ymin, ymax); theBox.wx1=xmin; theBox.wx2=xmax; theBox.wy1=ymin; theBox.wy2=ymax; updateBoxDeviceCoords(); UpdateCurrentCharWorldSize(); } void GDLGStream::ssub(PLINT nx, PLINT ny) { plstream::ssub( nx, ny ); // does not appear to change charsize. // set subpage numbers in X and Y thePage.nbPages=nx*ny; thePage.nx=nx; thePage.ny=ny; if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"ssub() %dx%d pages\n",nx,ny); thePage.curPage=1; syncPageInfo(); } void GDLGStream::adv(PLINT page) { plstream::adv(page); if (page==0) {thePage.curPage++;} else {thePage.curPage=page;} if (thePage.curPage > thePage.nbPages) thePage.curPage=1; if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"adv() now at page %d\n",thePage.curPage); } //get region (3BPP data) bool GDLGStream::GetRegion(DLong& x_gdl, DLong& y_gdl, DLong& nx_gdl, DLong& ny_gdl){ DByteGDL *bitmap = static_cast(this->GetBitmapData()); if (bitmap==NULL) return false; //need to GDLDelete bitmap on exit after this line. bool error=false; DLong nx=bitmap->Dim(0); DLong ny=bitmap->Dim(1); DLong xref,xval,xinc,yref,yval,yinc,xmax11,ymin11; long x_11=0; long y_11=0; xref=0;xval=0;xinc=1; yref=0;yval=0;yinc=1; x_11=xval+(x_gdl-xref)*xinc; y_11=yval+(y_gdl-yref)*yinc; xmax11=xval+(x_gdl+nx_gdl-1-xref)*xinc; ymin11=yval+(y_gdl+ny_gdl-1-yref)*yinc; if (y_11 < 0 || y_11 > ny-1) error=true; if (x_11 < 0 || x_11 > nx-1) error=true; if (xmax11 < 0 || xmax11 > nx-1) error=true; if (ymin11 < 0 || ymin11 > ny-1) error=true; if (error) { GDLDelete(bitmap); return false; } GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); unsigned char* data=actDevice->SetCopyBuffer(nx_gdl*ny_gdl*3); for ( SizeT i =0; i < nx_gdl ; ++i ) { for ( SizeT j = 0; j < ny_gdl ; ++j ) { for ( SizeT k = 0 ; k < 3 ; ++k) data[3 * (j * nx_gdl + i) + k] = (*bitmap)[3 * ((j+y_11) * nx + (i+x_11)) + k]; } } GDLDelete(bitmap); return true; } bool GDLGStream::SetRegion(DLong& xs, DLong& ys, DLong& nx, DLong& ny){ DLong pos[4]={xs,nx,ys,ny}; GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); return this->PaintImage(actDevice->GetCopyBuffer(), nx, ny, pos, 1, 0); } gdl-0.9.9/src/gdlgstream.hpp000066400000000000000000001033171340051421000157230ustar00rootroot00000000000000/* ************************************************************************* gdlgstream.hpp - graphic stream ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLGSTREAM_HPP_ #define GDLGSTREAM_HPP_ //debug aid. Put to 1 to debug #ifdef GDL_DEBUG #define GDL_DEBUG_PLSTREAM 1 #else #define GDL_DEBUG_PLSTREAM 0 #endif #ifdef HAVE_CONFIG_H // we should not add all the plplot's internal defines (which are // added if HAVE_CONFIG_H is defined) to ours. Makes problem with distros. #undef HAVE_CONFIG_H #include #include #include #define HAVE_CONFIG_H 1 #endif //this include should be removed as soon as plplot has a public method to give the size of a string in mm when plotted. #if PLPLOT_PRIVATE_NOT_HIDDEN #include #endif #include #include #include "typedefs.hpp" #include "gdlexception.hpp" #include "initsysvar.hpp" #ifdef _MSC_VER #include #endif const double MMToINCH = 0.039370078 ; // 1./2.54; const double CM_IN_MM = 10.00000000 ; using namespace std; static std::string internalFontCodes[] = { "#fn", // !0 : unused "#fn", // !1 : unused "#fn", // !2 : unused "#fn", // !3 : simplex Roman (default) "#fn", // !4 : simplex Greek "#fn", // !5 : duplex Roman "#fr", // !6 : complex Roman "#fr", // !7 : complex Greek "#fi", // !8 : complex italic "#fn", // !9 : math/special characters "#fn", // !10 : special characters "#fn", // !11 : Gothic English "#fs", // !12 : simplex script "#fs", // !13 : complex script "#fn", // !14 : Gothic Italian "#fn", // !15 : Gothic German "#fn", // !16 : Cyrillic "#fr", // !17 : triplex Roman "#fi", // !18 : triplex Italic "#fn", // !19 : "#fn", // !20 : miscellaneous "#fn", // !21 : "#fn", // !22 : "#fn", // !23 : "#fn", // !24 : "#fn", // !25 : "#fn", // !26 : "#fn", // !27 : "#fn", // !28 : "#fn", // !29 : }; // Graphic Structures: // typedef struct _P_GRAPHICS { // DLong background; // DFloat charSize; // DFloat charThick; // DLong clip[6]; // DLong color; // DLong font; // DLong lineStyle; // DLong multi[5]; // DLong noClip; // DLong noErase; // DLong nsum; // DFloat position[4]; // DLong psym; // DFloat region[4]; // DString subTitle; // DFloat symSize; // DDouble t[4][4]; // DLong t3d; // DFloat thick; // DString title; // DFloat ticklen; // DLong channel; // } pstruct ; typedef struct GDL_BOX { bool initialized; PLFLT wx1; //world coord of x min PLFLT wx2; PLFLT wy1; PLFLT wy2; PLFLT nx1; //normalized position in subpage PLFLT nx2; PLFLT ny1; PLFLT ny2; PLFLT ndx1; //normalized device position PLFLT ndx2; PLFLT ndy1; PLFLT ndy2; PLFLT ondx; //offset x of box in device coords PLFLT ondy; // in y PLFLT sndx; //size of box, x , device PLFLT sndy; PLFLT dx1; //position in device coords (e.g. pixels) PLFLT dx2; PLFLT dy1; PLFLT dy2; PLFLT pageWorldCoordinates[4]; PLFLT subPageWorldCoordinates[4]; } gdlbox ; typedef struct GDL_SUBPAGE { PLFLT dxsize; //subpage x size device units PLFLT dysize; //subpage y size device units PLFLT dxoff; // subpage x offset PLFLT dyoff; // subpage y offset } gdlsubpage ; typedef struct GDL_PAGE { PLFLT xdpmm; // x resolution Dots per mm PLFLT ydpmm; // y resolution Dots per mm PLFLT length; //x length (device coordinates) PLFLT height; //y lenght PLFLT plxoff; // x offset PLFLT plyoff; // y iffset PLFLT xsizemm; // size in mm, x PLFLT ysizemm; PLINT curPage; //current Page PLINT nbPages; //nx*ny PLINT nx; PLINT ny; gdlsubpage subpage; } gdlpage ; typedef struct GDL_CHARINFO { PLFLT scale; PLFLT ndsx; // size of char in normalized device units, x direction PLFLT ndsy; // idem y PLFLT dsx; // size of char in device units, x direction PLFLT dsy; // idem y DDouble mmsx; //in mm DDouble mmsy; // PLFLT wsx; //in current world coordinates PLFLT wsy; PLFLT convx; //symbol size conversion factor, (for PSYMs, not characters: PSYMs are handled by GDL, CHARS by plplot) PLFLT convy; //set only while in 2D mode, used in 2D or 3D mode. PLFLT dspacing; // spacing of line, device units, 2nd element of device,set_character_size PLFLT nspacing; // in normalized units PLFLT mmspacing; // in mm PLFLT wspacing; // in world } gdlCharInfo; class GDLGStream: public plstream { // protected: // void init(); // prevent plstream::init from being called directly private: gdlpage pageLayout; gdlbox boxLayout; protected: bool valid; gdlCharInfo theCurrentChar; gdlCharInfo theDefaultChar; int gdlDefaultCharInitialized; gdlbox theBox; gdlpage thePage; PLStream* pls; DFloat thickFactor; PLFLT theCurrentSymSize; PLFLT theLineSpacing_in_mm; bool usedAsPixmap; //for WINDOW,/PIXMAP retains the fact that this is a pixmap (invisible) window. int activeFontCodeNum; //simplex Roman by default. public: GDLGStream( int nx, int ny, const char *driver, const char *file=NULL) : plstream( nx, ny, driver, file), valid( true), thickFactor(1.0), usedAsPixmap(false), activeFontCodeNum(3) { if (!checkPlplotDriver(driver)) ThrowGDLException(std::string("PLplot installation lacks the requested driver: ") + driver); gdlDefaultCharInitialized=0; thePage.nbPages=0; thePage.length=0; thePage.height=0; thePage.plxoff=0; thePage.plyoff=0; theBox.initialized=false; plgpls( &pls); //you can debug plplot things with // pls->verbose=1; if (GDL_DEBUG_PLSTREAM) printf(" new GDLGstream( %d , %d , %s ):pls=%p \n", nx, ny, driver, (void *)pls); } virtual ~GDLGStream() { if (GDL_DEBUG_PLSTREAM) printf(" retire GDLGstream:pls=0x%p \n", (void *)pls); } static bool checkPlplotDriver(const char *driver) { int numdevs_plus_one = 64; const char **devlongnames = NULL; const char **devnames = NULL; static std::vector devNames; // do only once if( devNames.empty()) { // acquireing a list of drivers from plPlot for (int maxnumdevs = numdevs_plus_one;; numdevs_plus_one = maxnumdevs += 16) { //handles gracefully the improbable failure of realloc void* tmp = realloc(devlongnames, maxnumdevs * sizeof(char*)); if (tmp) devlongnames = static_cast(tmp); else return false; tmp = realloc(devnames, maxnumdevs * sizeof(char*)); if (tmp) devnames = static_cast(tmp); else return false; plgDevs(&devlongnames, &devnames, &numdevs_plus_one); numdevs_plus_one++; if (numdevs_plus_one < maxnumdevs) break; else Message("The above PLPlot warning message, if any, can be ignored"); } free(devlongnames); // we do not need this information for( int i = 0; i < numdevs_plus_one - 1; ++i) devNames.push_back(std::string(devnames[ i])); free(devnames); } return std::find( devNames.begin(), devNames.end(), std::string( driver)) != devNames.end(); } std::string getActiveFontCode(){ return internalFontCodes[activeFontCodeNum]; } static void SetErrorHandlers(); virtual void Init()=0; // called after draw operation //virtual void Update() {} virtual void Update(){plstream::cmd(PLESC_EXPOSE, NULL);} virtual void EventHandler() {} virtual void GetGeometry( long& xSize, long& ySize); virtual unsigned long GetWindowDepth () {return 0;} virtual DLong GetVisualDepth() {return -1;} virtual DString GetVisualName() {return "";} virtual BaseGDL* GetFontnames(DString pattern) {return NULL;} virtual DLong GetFontnum(DString pattern) {return -1;} virtual bool UnsetFocus(){return false;} virtual bool SetBackingStore(int value){return false;} virtual bool SetGraphicsFunction(long value ){return false;} virtual bool GetWindowPosition(long& xpos, long& ypos ){return false;} virtual bool GetScreenResolution(double& resx, double& resy){return false;} virtual bool CursorStandard(int cursorNumber){return false;} virtual void eop() { plstream::eop();} virtual void SetDoubleBuffering() {} virtual void UnSetDoubleBuffering() {} virtual bool HasDoubleBuffering() {return pls->db;} virtual bool HasSafeDoubleBuffering() {return false;} virtual void Raise() {} virtual void Lower() {} virtual void Iconic() {} virtual void DeIconic() {} virtual bool GetGin(PLGraphicsIn *gin, int mode) {return 0;} virtual void WarpPointer(DLong x, DLong y){} virtual void Flush() {} virtual void Clear() {} virtual void Clear( DLong chan) {} virtual bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan){return false;} virtual bool HasCrossHair() {return false;} virtual void UnMapWindow() {usedAsPixmap=true;} bool IsPixmapWindow() {return usedAsPixmap;} virtual BaseGDL* GetBitmapData(){return NULL;} virtual void SetCurrentFont(std::string fontname){}//do nothing bool GetRegion(DLong& xs, DLong& ys, DLong& nx, DLong& ny);//{return false;} bool SetRegion(DLong& xd, DLong& yd, DLong& nx, DLong& ny);//{return false;} virtual void CheckValid() {} void SetValid( bool v) { valid = v;} bool GetValid() { return valid;} bool validWorldBox() { if (((theBox.wx1==0) && (theBox.wx2==0)) || ((theBox.wy1==0) && (theBox.wy2==0))) return false; else return true; } void getCurrentWorldBox(PLFLT &xmin, PLFLT &xmax, PLFLT &ymin, PLFLT &ymax) { xmin=theBox.wx1; ymin=theBox.wy1; xmax=theBox.wx2; ymax=theBox.wy2; } bool validNormdBox() { if (((theBox.nx1==0) && (theBox.nx2==0)) || ((theBox.ny1==0) && (theBox.ny2==0))) return false; else return true; } void getCurrentNormBox(PLFLT &xmin, PLFLT &xmax, PLFLT &ymin, PLFLT &ymax) { xmin=theBox.nx1; ymin=theBox.ny1; xmax=theBox.nx2; ymax=theBox.ny2; } inline PLFLT getPsymConvX(){return theCurrentChar.convx;} inline PLFLT getPsymConvY(){return theCurrentChar.convy;} inline void setSymbolSizeConversionFactors(){ PLFLT symsize=this->getSymbolSize(); theCurrentChar.convx=(0.5*symsize*(this->wCharLength()/this->charScale())); //be dependent only on symsize! theCurrentChar.convy=(0.5*symsize*(this->wCharHeight()/this->charScale())); PLFLT wun, wdeux, wtrois, wquatre; //take care of axes world orientation! this->pageWorldCoordinates(wun, wdeux, wtrois, wquatre); if ((wdeux-wun)<0) theCurrentChar.convx*=-1.0; if ((wquatre-wtrois)<0) theCurrentChar.convy*=-1.0;} inline PLFLT charScale(){return theCurrentChar.scale;} inline PLFLT nCharLength(){return theCurrentChar.ndsx;} inline PLFLT nCharHeight(){return theCurrentChar.ndsy;} inline PLFLT nLineSpacing(){return theCurrentChar.nspacing;} inline PLFLT dCharLength(){return theCurrentChar.dsx;} inline PLFLT dCharHeight(){return theCurrentChar.dsy;} inline PLFLT dLineSpacing(){return theCurrentChar.dspacing;} inline PLFLT wCharLength(){return theCurrentChar.wsx;} inline PLFLT wCharHeight(){return theCurrentChar.wsy;} inline PLFLT wLineSpacing(){return theCurrentChar.wspacing;} inline DDouble mmCharLength(){return theCurrentChar.mmsx;} inline DDouble mmCharHeight(){return theCurrentChar.mmsy;} inline DDouble mmLineSpacing(){return theCurrentChar.mmspacing;} inline PLFLT xResolution(){return thePage.xdpmm;} inline PLFLT yResolution(){return thePage.ydpmm;} inline PLFLT mmxPageSize(){return thePage.xsizemm;} //size in mm inline PLFLT mmyPageSize(){return thePage.ysizemm;} inline PLFLT boxnXSize(){return theBox.sndx;} inline PLFLT boxnYSize(){return theBox.sndy;} inline PLFLT xPageSize(){return thePage.length;} //size in units (alternate:{return pls->xlength;}) inline PLFLT yPageSize(){return thePage.height;} //alternate: {return pls->ylength;} inline PLFLT xSubPageSize(){return thePage.subpage.dxsize;} //size in units inline PLFLT ySubPageSize(){return thePage.subpage.dysize;} // bunch of conversion functions that should be used in the future now that pls is here! // (normed) device coords to physical coords (x,y) 0..1 -> 0->32768 inline PLFLT nd2px(PLFLT x){ return ( pls->phyxmi + pls->phyxlen * x );} inline PLFLT nd2py(PLFLT y){ return ( pls->phyymi + pls->phyylen * y );} inline void norm2physical(PLFLT devx, PLFLT devy, PLFLT &physx, PLFLT &physy) { physx=nd2px(devx); physy=nd2py(devy);} // (normed) device to mm inline PLFLT nd2mx(PLFLT x){ return (PLFLT) ( x * abs( pls->phyxma - pls->phyxmi ) / pls->xpmm ) ;} inline PLFLT nd2my(PLFLT y){ return (PLFLT) ( y * abs( pls->phyyma - pls->phyymi ) / pls->ypmm ) ;} inline void norm2mm(PLFLT devx, PLFLT devy, PLFLT &mmx, PLFLT &mmy) { mmx=nd2mx(devx); mmy=nd2my(devy);} //(normed) device to world inline PLFLT nd2wx(PLFLT x){return (PLFLT) ( (x- pls->wdxoff) / pls->wdxscl );} inline PLFLT nd2wy(PLFLT y){return (PLFLT) ( (y- pls->wdyoff) / pls->wdyscl );} inline void norm2world(PLFLT devx, PLFLT devy, PLFLT &wx, PLFLT &wy) { wx=nd2wx(devx); wy=nd2wy(devy);} // (normed) device coords to subpage coords inline PLFLT nd2spx(PLFLT x){ return (PLFLT) ( ( x - pls->spdxmi ) / ( pls->spdxma - pls->spdxmi ) ) ;} inline PLFLT nd2spy(PLFLT y){ return (PLFLT) ( ( y - pls->spdymi ) / ( pls->spdyma - pls->spdymi ) ) ;} inline void norm2subpage(PLFLT devx, PLFLT devy, PLFLT &spx, PLFLT &spy) { spx=nd2spx(devx); spy=nd2spy(devy);} // millimeters to physical coords (x,y) inline PLFLT mm2px(PLFLT x){ return ( pls->phyxmi + pls->xpmm * x );} inline PLFLT mm2py(PLFLT y){ return ( pls->phyymi + pls->ypmm * y );} inline void mm2physical(PLFLT mmx, PLFLT mmy, PLFLT &physx, PLFLT &physy) { physx=mm2px(mmx); physy=mm2py(mmy);} // mm to (absolute) device inline PLFLT mm2adx(PLFLT x){ return (PLFLT) ( ( x * pls->xpmm ) / abs( pls->phyxma - pls->phyxmi )*thePage.length);} inline PLFLT mm2ady(PLFLT y){ return (PLFLT) ( ( y * pls->ypmm ) / abs( pls->phyyma - pls->phyymi )*thePage.height);} inline void mm2device(PLFLT mmx, PLFLT mmy, PLFLT &devx, PLFLT &devy) { devx=mm2adx(mmx); devy=mm2ady(mmy);} // mm to (normed) device inline PLFLT mm2ndx(PLFLT x){ return (PLFLT) ( ( x * pls->xpmm ) / abs( pls->phyxma - pls->phyxmi ));} inline PLFLT mm2ndy(PLFLT y){ return (PLFLT) ( ( y * pls->ypmm ) / abs( pls->phyyma - pls->phyymi ));} inline void mm2norm(PLFLT mmx, PLFLT mmy, PLFLT &devx, PLFLT &devy) { devx=mm2ndx(mmx); devy=mm2ndy(mmy);} // mm to world inline PLFLT mm2wx(PLFLT x){ x=mm2ndx(x); return nd2wx(x);} inline PLFLT mm2wy(PLFLT y){ y=mm2ndy(y); return nd2wy(y);} inline void mm2world(PLFLT mmx, PLFLT mmy, PLFLT &wx, PLFLT &wy) { wx=mm2wx(mmx); wy=mm2wy(mmy);} // mm to subpage coord inline PLFLT mm2spx(PLFLT x){ x=mm2ndx(x); return nd2spx(x);} inline PLFLT mm2spy(PLFLT y){ y=mm2ndy(y); return nd2spy(y);} inline void mm2subpage(PLFLT mmx, PLFLT mmy, PLFLT &spx, PLFLT &spy) { spx=mm2spx(mmx); spy=mm2spy(mmy);} // world to physical coords inline PLFLT w2px(PLFLT x){ return ( pls->wpxoff + pls->wpxscl * x );} inline PLFLT w2py(PLFLT y){ return ( pls->wpyoff + pls->wpyscl * y );} inline void world2physical(PLFLT wx, PLFLT wy, PLFLT &physx, PLFLT &physy) { physx=w2px(wx); physy=w2py(wy);} // world to (normed) device inline PLFLT w2ndx(PLFLT x){ return (PLFLT) ( pls->wdxoff + pls->wdxscl * x );} inline PLFLT w2ndy(PLFLT y){ return (PLFLT) ( pls->wdyoff + pls->wdyscl * y );} inline void world2norm(PLFLT wx, PLFLT wy, PLFLT &devx, PLFLT &devy) { devx=w2ndx(wx); devy=w2ndy(wy);} // world to (absolute) device inline PLFLT w2adx(PLFLT x){ return (PLFLT) ( pls->wdxoff + pls->wdxscl * x )*thePage.length;} inline PLFLT w2ady(PLFLT y){ return (PLFLT) ( pls->wdyoff + pls->wdyscl * y )*thePage.height;} inline void world2device(PLFLT wx, PLFLT wy, PLFLT &devx, PLFLT &devy) { devx=w2adx(wx); devy=w2ady(wy);} //world to mm inline PLFLT w2mmx(PLFLT x){ return (PLFLT) ( pls->wmxoff + pls->wmxscl * x );} inline PLFLT w2mmy(PLFLT y){ return (PLFLT) ( pls->wmyoff + pls->wmyscl * y );} inline void world2mm(PLFLT wx, PLFLT wy, PLFLT &mmx, PLFLT &mmy) { mmx=w2mmx(wx); mmy=w2mmy(wy);} //world to subpage coord inline PLFLT w2spx(PLFLT x){ x=w2ndx(x) ; return nd2spx(x);} inline PLFLT w2spy(PLFLT y){ y=w2ndy(y) ; return nd2spy(y);} inline void world2subpage(PLFLT wx, PLFLT wy, PLFLT &spx, PLFLT &spy) { spx=w2spx(wx); spy=w2spy(spy);} // physical to (normed) device inline PLFLT p2ndx(PLFLT x){ return (PLFLT) ( ( x - pls->phyxmi ) / (double) pls->phyxlen );} inline PLFLT p2ndy(PLFLT y){ return (PLFLT) ( ( y - pls->phyymi ) / (double) pls->phyylen );} inline void physical2device(PLFLT physx, PLFLT physy, PLFLT &devx, PLFLT &devy) { devx=p2ndx(physx); devy=p2ndy(physy);} //physical to world //physical to mm //physical to subpage coord // subpage coords to (normed) device coords inline PLFLT sp2ndx(PLFLT x){ return (PLFLT) ( pls->spdxmi + ( pls->spdxma - pls->spdxmi ) * x ) ;} inline PLFLT sp2ndy(PLFLT y){ return (PLFLT) ( pls->spdymi + ( pls->spdyma - pls->spdymi ) * y ) ;} inline void subpage2norm(PLFLT spx, PLFLT spy, PLFLT &devx, PLFLT &devy) { devx=sp2ndx(spx); devy=sp2ndy(spy);} //subpage to world //subpage to mm //subpage to physical #if PLPLOT_PRIVATE_NOT_HIDDEN //use simple internal function PLFLT gdlGetStringLength(const std::string s) { return plstrl(s.c_str()); } #endif // void currentPhysicalPos(PLFLT &x, PLFLT &y) // { // x=pls->currx; //Physical x-coordinate of current point // y=pls->curry; // } // void currentWorldPos(PLFLT &x, PLFLT &y) // { // x=pls->currx; //Physical x-coordinate of current point // y=pls->curry; // x=(x-pls->wpxoff)/pls->wpxscl; // y=(y-pls->wpyoff)/pls->wpyscl; // } // void currentNormedDevicePos(PLFLT &x, PLFLT &y) // { // x=pls->currx; //Physical x-coordinate of current point // y=pls->curry; // x=p2ndx(x); // y=p2ndy(y); // } // void currentMmPos(PLFLT &x, PLFLT &y) // { // x=pls->currx; //Physical x-coordinate of current point // y=pls->curry; // x=p2ndx(x);x=nd2mx(x); // y=p2ndy(y);y=nd2my(y); // } void pageWorldCoordinates(PLFLT &wxmin, PLFLT &wxmax, PLFLT &wymin, PLFLT &wymax) { wxmin=theBox.pageWorldCoordinates[0]; wxmax=theBox.pageWorldCoordinates[1]; wymin=theBox.pageWorldCoordinates[2]; wymax=theBox.pageWorldCoordinates[3]; } // void subPageWorldCoordinates(PLFLT &wxmin, PLFLT &wxmax, PLFLT &wymin, PLFLT &wymax) // { // wxmin=theBox.subPageWorldCoordinates[0]; // wxmax=theBox.subPageWorldCoordinates[1]; // wymin=theBox.subPageWorldCoordinates[2]; // wymax=theBox.subPageWorldCoordinates[3]; // } // void boxDeviceCoordinates(PLFLT &wxmin, PLFLT &wxmax, PLFLT &wymin, PLFLT &wymax) // { // wxmin=theBox.dx1; // wxmax=theBox.dx2; // wymin=theBox.dy1; // wymax=theBox.dy2; // } PLFLT boxAspectDevice(){return (theBox.dy2-theBox.dy1)/(theBox.dx2-theBox.dx1);} PLFLT boxAspectWorld(){return fabs(theBox.wy2-theBox.wy1)/fabs(theBox.wx2-theBox.wx1);} void SaveLayout() { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"SaveLayout():\n"); pageLayout.nbPages=thePage.nbPages; pageLayout.nx=thePage.nx; pageLayout.ny=thePage.ny; pageLayout.curPage=thePage.curPage; pageLayout.length=thePage.length; pageLayout.height=thePage.height; pageLayout.xsizemm=thePage.xsizemm; pageLayout.ysizemm=thePage.ysizemm; pageLayout.plxoff=thePage.plxoff; pageLayout.plyoff=thePage.plyoff; boxLayout.nx1=theBox.nx1; boxLayout.nx2=theBox.nx2; boxLayout.ny1=theBox.ny1; boxLayout.ny2=theBox.ny2; boxLayout.ndx1=theBox.ndx1; boxLayout.ndx2=theBox.ndx2; boxLayout.ndy1=theBox.ndy1; boxLayout.ndy2=theBox.ndy2; boxLayout.ondx=theBox.ondx; boxLayout.ondy=theBox.ondy; boxLayout.sndx=theBox.sndx; boxLayout.sndy=theBox.sndy; boxLayout.dx1=theBox.dx1; boxLayout.dx2=theBox.dx2; boxLayout.dy1=theBox.dy1; boxLayout.dy2=theBox.dy2; boxLayout.wx1=theBox.wx1; boxLayout.wx2=theBox.wx2; boxLayout.wy1=theBox.wy1; boxLayout.wy2=theBox.wy2; if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"saving box [%f,%f,%f,%f] at [%f,%f,%f,%f] in subpage %d of %dx%d (device coords [%f,%f,%f,%f]\n",boxLayout.wx1,boxLayout.wy1,boxLayout.wx2,boxLayout.wy2,boxLayout.nx1,boxLayout.ny1,boxLayout.nx2,boxLayout.ny2,pageLayout.curPage,pageLayout.nx,pageLayout.ny,boxLayout.dx1,boxLayout.dy1,boxLayout.dx2,boxLayout.dy2); } void RestoreLayout() { ssub(pageLayout.nx,pageLayout.ny); adv(pageLayout.curPage); vpor(boxLayout.nx1,boxLayout.nx2,boxLayout.ny1,boxLayout.ny2); wind(boxLayout.wx1,boxLayout.wx2,boxLayout.wy1,boxLayout.wy2); } void OnePageSaveLayout() { SaveLayout(); NoSub(); } bool updatePageInfo() { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"updatePageInfo():\n"); if (thePage.nbPages==0) {if (GDL_DEBUG_PLSTREAM) fprintf(stderr," FAILED\n");return false;} long xsize,ysize; GetGeometry(xsize,ysize); if (thePage.length==xsize && thePage.height==ysize ) return true; thePage.length=xsize; thePage.height=ysize; (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("X_SIZE"), 0)))[0] = xsize; (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("Y_SIZE"), 0)))[0] = ysize; (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("X_VSIZE"), 0)))[0] = xsize; (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("Y_VSIZE"), 0)))[0] = ysize; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," %fx%f device units.\n",thePage.length, thePage.height); return true; } inline void NormToDevice(PLFLT normx, PLFLT normy, PLFLT &devx, PLFLT &devy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"NormToDevice()\n"); devx=normx*thePage.subpage.dxsize+thePage.subpage.dxoff; devy=normy*thePage.subpage.dysize+thePage.subpage.dyoff; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] output [%f,%f]\n", normx, normy, devx, devy); } inline void NormedDeviceToDevice(PLFLT normx, PLFLT normy, PLFLT &devx, PLFLT &devy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"NormedDeviceToDevice()\n"); devx=normx*thePage.length; devy=normy*thePage.height; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] output [%f,%f]\n", normx, normy, devx, devy); } inline void DeviceToNorm(PLFLT devx, PLFLT devy, PLFLT &normx, PLFLT &normy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"DeviceToNorm()\n"); normx=(devx-thePage.subpage.dxoff)/thePage.subpage.dxsize; normy=(devy-thePage.subpage.dyoff)/thePage.subpage.dysize; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] output [%f,%f]\n", devx, devy, normx, normy); } inline void DeviceToNormedDevice(PLFLT devx, PLFLT devy, PLFLT &normx, PLFLT &normy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"DeviceToNormedDevice()\n"); normx=devx/thePage.length; normy=devy/thePage.height; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] output [%f,%f]\n", devx, devy, normx, normy); } inline void NormToWorld(PLFLT normx, PLFLT normy, PLFLT &worldx, PLFLT &worldy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"NormToWorld()\n"); DDouble s1,s2; s1=(theBox.wx2-theBox.wx1)/(theBox.nx2-theBox.nx1); s2=theBox.wx1; worldx=s1*(normx-theBox.nx1)+s2; s1=(theBox.wy2-theBox.wy1)/(theBox.ny2-theBox.ny1); s2=theBox.wy1; worldy=s1*(normy-theBox.ny1)+s2; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] output [%f,%f]\n", normx, normy, worldx, worldy); } inline void NormedDeviceToWorld(PLFLT normx, PLFLT normy, PLFLT &worldx, PLFLT &worldy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"NormedDeviceToWorld()\n"); DDouble s1,s2; s1=(theBox.wx2-theBox.wx1)/(theBox.ndx2-theBox.ndx1); s2=theBox.wx1; worldx=s1*(normx-theBox.ndx1)+s2; s1=(theBox.wy2-theBox.wy1)/(theBox.ndy2-theBox.ndy1); s2=theBox.wy1; worldy=s1*(normy-theBox.ndy1)+s2; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] (nd) output [%f,%f] (w)\n", normx, normy, worldx, worldy); } inline void WorldToNorm(PLFLT worldx, PLFLT worldy, PLFLT &normx, PLFLT &normy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"WorldToNormedDevice()\n"); DDouble s1,s2; s1=(theBox.nx2-theBox.nx1)/(theBox.wx2-theBox.wx1); s2=theBox.nx1; normx=s1*(worldx-theBox.wx1)+s2; s1=(theBox.ny2-theBox.ny1)/(theBox.wy2-theBox.wy1); s2=theBox.ny1; normy=s1*(worldy-theBox.wy1)+s2; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f] output [%f,%f]\n", worldx, worldy, normx, normy); } inline void WorldToNormedDevice(PLFLT worldx, PLFLT worldy, PLFLT &normx, PLFLT &normy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"WorldToNormedDevice()\n"); DDouble s1,s2; s1=(theBox.ndx2-theBox.ndx1)/(theBox.wx2-theBox.wx1); s2=theBox.ndx1; normx=s1*(worldx-theBox.wx1)+s2; s1=(theBox.ndy2-theBox.ndy1)/(theBox.wy2-theBox.wy1); s2=theBox.ndy1; normy=s1*(worldy-theBox.wy1)+s2; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," input [%f,%f](w) output [%f,%f](nd)\n", worldx, worldy, normx, normy); } inline void DeviceToWorld(PLFLT devx, PLFLT devy, PLFLT &worldx, PLFLT &worldy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"DeviceToWorld()\n"); PLFLT normx, normy; DeviceToNormedDevice(devx, devy, normx, normy); NormedDeviceToWorld(normx, normy, worldx, worldy); } inline void WorldToDevice(PLFLT worldx, PLFLT worldy, PLFLT &devx, PLFLT &devy) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"WorldToDevice()\n"); PLFLT normx, normy; WorldToNormedDevice(worldx, worldy, normx, normy); NormedDeviceToDevice(normx, normy, devx, devy); } void Thick( DFloat thick); virtual void Color( ULong c, DLong decomposed=0); void Background( ULong c, DLong decomposed=0); void DefaultBackground(); void SetColorMap1SingleColor( ULong color); //if decomposed, create a red ramp. If not, copy the colormap0 in colormap1 void SetColorMap1DefaultColors(PLINT ncolors, DLong decomposed=0); //if create a colormap1 color with passed colors, palette will be tableSize and colors assigned like in contour. void SetColorMap1Table(PLINT tableSize, BaseGDL *passed_colors, DLong decomposed=0); //if create a colormap1 with a black to white ramp. void SetColorMap1Ramp(DLong decomposed=0, PLFLT minlight=0.0); void DefaultCharSize(); void NextPlot( bool erase=true); // handles multi plots void NoSub(); // no subwindows (/NORM, /DEVICE) void CurrentCharSize(PLFLT scale) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"CurrentCharsize()\n"); if (gdlDefaultCharInitialized==0) { if (updatePageInfo()==true) { GetPlplotDefaultCharSize(); } } theCurrentChar.scale=scale; theCurrentChar.ndsx=scale*theDefaultChar.ndsx; theCurrentChar.ndsy=scale*theDefaultChar.ndsy; theCurrentChar.dsx=scale*theDefaultChar.dsx; theCurrentChar.dsy=scale*theDefaultChar.dsy; theCurrentChar.mmsx=scale*theDefaultChar.mmsx; theCurrentChar.mmsy=scale*theDefaultChar.mmsy; theCurrentChar.wsx=scale*theDefaultChar.wsx; theCurrentChar.wsy=scale*theDefaultChar.wsy; theCurrentChar.mmspacing=scale*theDefaultChar.mmspacing; theCurrentChar.nspacing=scale*theDefaultChar.nspacing; theCurrentChar.dspacing=scale*theDefaultChar.dspacing; theCurrentChar.wspacing=scale*theDefaultChar.wspacing; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," sized by %f is %fx%f mm or %fx%f device or %fx%f world\n",scale,theCurrentChar.mmsx,theCurrentChar.mmsy,theCurrentChar.dsx,theCurrentChar.dsy,theCurrentChar.wsx, theCurrentChar.wsy); } void UpdateCurrentCharWorldSize() { PLFLT x,y,dx,dy; DeviceToWorld(0,0,x,y); DeviceToWorld(theDefaultChar.dsx,theDefaultChar.dsy, dx, dy); theDefaultChar.wsx=abs(dx-x); theDefaultChar.wsy=abs(dy-y); theCurrentChar.wsx=theCurrentChar.scale*theDefaultChar.wsx; theCurrentChar.wsy=theCurrentChar.scale*theDefaultChar.wsy; DeviceToWorld(0,theDefaultChar.dspacing, dx, dy); theDefaultChar.wspacing=abs(dy-y); if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"UpdateCurrentCharWorldSize(%f,%f)\n", theCurrentChar.wsx,theCurrentChar.wsy); } void RenewPlplotDefaultCharsize(PLFLT newMmSize); void GetPlplotDefaultCharSize(); // SA: overloading plplot methods in order to handle IDL-plplot extended // text formating syntax conversion std::string TranslateFormatCodes(const char *text, double *stringLength); void setSymbolSize( PLFLT scale ); void setLineSpacing( PLFLT spacing ); PLFLT getSymbolSize(); void mtex( const char *side, PLFLT disp, PLFLT pos, PLFLT just, const char *text); void mtex3( const char *side, PLFLT disp, PLFLT pos, PLFLT just, const char *text); void ptex( PLFLT x, PLFLT y, PLFLT dx, PLFLT dy, PLFLT just, const char *text, double *stringCharLength=NULL ); void schr( PLFLT charwidthmm, PLFLT scale, PLFLT lineSpacingmm); void sizeChar(PLFLT scale); void vpor( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax ); // void gvpd( PLFLT& xmin, PLFLT& xmax, PLFLT& ymin, PLFLT& ymax ); void wind( PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax ); void ssub( PLINT nx, PLINT ny); void adv(PLINT page); inline void syncPageInfo() { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"SyncPageInfo()\n"); PLINT level; plstream::glevel(level); if (level>1 && thePage.nbPages!=0) //we need to have a vpor defined, and a page! { PLFLT bxsize_mm, bysize_mm, offx_mm, offy_mm; PLFLT xmin,ymin,xmax,ymax; plstream::gspa(xmin,xmax,ymin,ymax); //subpage in mm bxsize_mm=xmax-xmin; bysize_mm=ymax-ymin; offx_mm=xmin; offy_mm=ymin; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," gspa returned size[%f,%f] at offset [%f,%f] (mm) for subpage %d of %dx%d subpages\n",bxsize_mm,bysize_mm,offx_mm,offy_mm,thePage.curPage,thePage.nx,thePage.ny); //we can derive the dpm in x and y which converts mm to device coords: thePage.xdpmm=abs(thePage.length/(thePage.nx*bxsize_mm)); thePage.ydpmm=abs(thePage.height/(thePage.ny*bysize_mm)); //and the page width and height in mm: thePage.xsizemm=thePage.length/thePage.xdpmm; thePage.ysizemm=thePage.height/thePage.ydpmm; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," device resolution [%f,%f]mm^-1, device size [%f,%f], [%f,%f] mm\n", thePage.xdpmm,thePage.ydpmm,thePage.length,thePage.height,thePage.xsizemm,thePage.ysizemm); thePage.subpage.dxoff=offx_mm*thePage.xdpmm; thePage.subpage.dyoff=offy_mm*thePage.ydpmm; thePage.subpage.dxsize=bxsize_mm*thePage.xdpmm; thePage.subpage.dysize=bysize_mm*thePage.ydpmm; if (GDL_DEBUG_PLSTREAM) fprintf(stderr," subpage is %fx%f at [%f,%f] device units\n", thePage.subpage.dxsize,thePage.subpage.dysize,thePage.subpage.dxoff,thePage.subpage.dyoff); } else if (GDL_DEBUG_PLSTREAM) fprintf(stderr," WARNING: not initalized\n"); } inline void updateBoxDeviceCoords() { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"updateBoxDeviceCoords()\n"); // world coordinates of current subpage boundaries and page boundaries NormedDeviceToWorld(0.0, 0.0,theBox.pageWorldCoordinates[0],theBox.pageWorldCoordinates[2]); NormedDeviceToWorld(1.0, 1.0,theBox.pageWorldCoordinates[1],theBox.pageWorldCoordinates[3]); NormToWorld(0.0, 0.0,theBox.subPageWorldCoordinates[0],theBox.subPageWorldCoordinates[2]); NormToWorld(1.0, 1.0,theBox.subPageWorldCoordinates[1],theBox.subPageWorldCoordinates[3]); NormToDevice(theBox.nx1,theBox.ny1,theBox.dx1,theBox.dy1); NormToDevice(theBox.nx2,theBox.ny2,theBox.dx2,theBox.dy2); } inline void setThickFactor(DFloat tf) { thickFactor=tf; } //GD: enables overloading scmap0,1... to accelerate plots for X11 and possibly others // Set color map 0 colors by 8 bit RGB values virtual void SetColorMap0( PLINT *r, PLINT *g, PLINT *b, PLINT ncol0 ) { plstream::scmap0( r, g, b, ncol0); } // Set color map 1 colors by 8 bit RGB values virtual void SetColorMap1( PLINT *r, PLINT *g, PLINT *b, PLINT ncol1 ) { plstream::scmap1( r, g, b, ncol1); } // Set color map 1 colors using a piece-wise linear relationship between // intensity [0,1] (cmap 1 index) and position in HLS or RGB color space. virtual void SetColorMap1l( bool itype, PLINT npts, PLFLT *intensity, PLFLT *coord1, PLFLT *coord2, PLFLT *coord3, const bool *rev = NULL ) { plstream::scmap1l(itype,npts,intensity,coord1,coord2,coord3,rev); } // Set number of colors in cmap 1 virtual void SetColorMap1n( PLINT ncol1 ){ plstream::scmap1n(ncol1); } }; #endif gdl-0.9.9/src/gdlhelp.cpp000066400000000000000000001301541340051421000152030ustar00rootroot00000000000000/*************************************************************************** gdlhelp.cpp - GDL help procedure ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net - Numerous enhancements by Alain Coulais - May 2015 code cleanup by Greg Jung: * gdlhelp.cpp, gdlhelp.hpp for HELP and DELVAR * OUTPUT= and NAMES= keywords implemented for help. * /COMMON to list all common blocks anywhere * Undefined variables normally not listed. ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include #include #include #ifndef _WIN32 //#include // stregex #include #else #include #endif #ifndef _MSC_VER # include #else // MSC workaround implementation in file.cpp /* Declaration of POSIX directory browsing functions and types for Win32. Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) History: Created March 1997. Updated June 2003. Rights: See end of file. */ extern "C" { typedef struct DIR DIR; struct dirent { char *d_name; }; DIR *opendir(const char *); int closedir(DIR *); struct dirent *readdir(DIR *); void rewinddir(DIR *); /* Copyright Kevlin Henney, 1997, 2003. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives. This software is supplied "as is" without express or implied warranty. But that said, if there are any problems please get in touch. */ } // extern "C" #endif #if 0 #ifdef __APPLE__ # include # define environ (*_NSGetEnviron()) #else #ifdef _WIN32 #include #include #define R_OK 4 /* Test for read permission. */ #define W_OK 2 /* Test for write permission. */ #define F_OK 0 /* Test for existence. */ #else #include #endif #endif #endif #include "dinterpreter.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "graphicsdevice.hpp" #include "dcommon.hpp" #include "dpro.hpp" #include "gdlhelp.hpp" // for sorting compiled pro/fun lists by name struct CompFunName: public std::binary_function< DFun*, DFun*, bool> { bool operator() ( DFun* f1, DFun* f2) const { return f1->ObjectName() < f2->ObjectName(); } }; struct CompProName: public std::binary_function< DPro*, DPro*, bool> { bool operator() ( DPro* f1, DPro* f2) const { return f1->ObjectName() < f2->ObjectName(); } }; static bool CompareWithJokers(string names, string sourceFiles) { #ifdef _WIN32 WCHAR wnames[MAX_PATH]; WCHAR wsourceFiles[MAX_PATH]; const char* cnames = names.c_str(); const char* csourceFiles = sourceFiles.c_str(); MultiByteToWideChar(CP_UTF8, 0, cnames, -1, (LPWSTR) wnames, MAX_PATH); MultiByteToWideChar(CP_UTF8, 0, csourceFiles, -1, (LPWSTR) wsourceFiles, MAX_PATH); int match = 1 - PathMatchSpecW(wsourceFiles, wnames); #else int match = fnmatch(names.c_str(), sourceFiles.c_str(), 0 ); #endif if ( match == 0) return true; else return false; } extern GDLFileListT fileUnits; using namespace std; // (static = internal) helper routines serving the lib:: routines called out in // gdlhelper.hpp static void help_files(ostream& os, EnvT* e) { for( DLong lun=maxUserLun+1; lun <= fileUnits.size(); ++lun) if( fileUnits[ lun-1].InUse() || fileUnits[ lun-1].GetGetLunLock()) { os << " lun "<< lun << ": "+fileUnits[lun-1].Name() << endl; } return; } static void help_keys(ostream& ostr) { ostr << "GDL is using Readline to manage keys shortcuts, few useful listed below." << endl; ostr << "A summary can be read here : http://www.bigsmoke.us/readline/shortcuts " << endl; ostr << endl; ostr << "Moving in the command line :"<< endl; ostr << " Ctrl-a : going to the beginning of the line"<< endl; ostr << " Ctrl-e : going to the end of the line"<< endl; ostr << " Ctrl-u : removing from here to the beginning of the line"<< endl; ostr << " Ctrl-k : removing from here to the end of the line"<< endl; ostr << " Ctrl-RightArrow : jumping one word on the right"<< endl; ostr << " Ctrl-LeftArrow : jumping one word on the left"<< endl; ostr << endl; ostr << "Moving in the history :"<< endl; ostr << " HELP, /recall : listing the whole history" << endl; ostr << " Ctrl-p or UpArrow : previous entry in history" << endl; ostr << " Ctrl-n or DownArrow : next entry in history" << endl; ostr << endl; return; } static void help_info() { cout << "* Homepage: http://gnudatalanguage.sf.net" << endl; cout << endl; cout << "* #NameOfRoutine for list of params and keywords" " for a given NameOfRoutine (internal or compiled pro/func)" << endl; cout << endl; cout << "* ?NameOfRoutine for starting a browser to access online doc" " for a given routine (if exists ! internal or compiled pro/func)" ; cout << endl; cout << endl; cout << "* HELP, /INTERNAL_LIB_GDL for a list of all internal library " "functions/procedures." << endl; cout << "* HELP, /LIB Additional subroutines are written in GDL language, " "look for *.pro files (e.g. in CVS in src/pro/)." << endl; cout << endl; cout << "* HELP, /KEYS for useful CLI keys shortcuts." << endl; cout << endl; return; } static void help_sysvar(ostream& os , bool briefKW=true) { if (briefKW) { string tmp_line="", tmp_word=""; for( SizeT v=0; vName(); if (tmp_line.length()+tmp_word.length() >= 80) { os << tmp_line < 0) os << tmp_line <(var->Data()); lib::help_item(os, tmp, "!"+var->Name(), false); } } return; } static void help_Output(BaseGDL** outputKW, ostringstream& ostr, SizeT &nlines, bool doOutput=true) { // Setup output return variable ostream& os, int &lines_count std::string s = ostr.rdbuf()->str().erase(ostr.rdbuf()->str().length(),1); char delimiter = '\n'; SizeT nOut = 0; size_t found=0; if(doOutput) { do { ++nOut; found=s.find( delimiter,found); } while( (found++ != std::string::npos) ); nlines = --nOut; if(nlines == 0) return; GDLDelete((*outputKW)); dimension dim(&nlines, (size_t) 1); *outputKW = new DStringGDL(dim, BaseGDL::NOZERO); } size_t pos = 0; nOut = 0; std::string token; while ((found = s.find(delimiter,pos)) != std::string::npos) { token = s.substr(pos, found-pos); if( doOutput and (nOut not_eq nlines)) (*(DStringGDL *) *outputKW)[nOut] = token; else cout << token << endl; ++nOut; pos = found+1; } ostr.str(""); // if( nOut not_eq nlines and debug) cout << // " help_Output: Error counting lines -" << // " nOut: "<>" << (*CurrentDir).c_str() << "<<" <>" << dirp << "<<" <d_name; found = tmp_fname.rfind(ProSuffix); if (found != std::string::npos) { if ((found + ProSuffixLen) == tmp_fname.length()) ++NbProFilesInCurrentDir; } } closedir(dirp); ++lines_count; ostr << *CurrentDir << " (" << NbProFilesInCurrentDir << " files)" << endl; } } } // a simplification of codes (DebugMsg & DumpStack) in GDLInterpreter.cpp // ProgNodeP cN = e->CallingNode(); // DInterpreter::DebugMsg(cN, "At "); // DInterpreter::DumpStack(3); static void SimpleDumpStack(EnvT* e, ostream& ost=std::cerr) { EnvStackT& callStack = e->Interpreter()->CallStack(); // simple way to manage the first line : exception SizeT w = 0; string msgPrefix = "% At "; long actIx = callStack.size() - 1; for (; actIx >= 0; --actIx) { EnvStackT::pointer_type upEnv = callStack[actIx]; ost << msgPrefix << std::right << std::setw(w) << ""; // simple way to manage the first line : exception msgPrefix = ""; w = 5; ost << std::left << std::setw(16) << upEnv->GetProName(); std::string file = upEnv->GetFilename(); if (file != "") { int lineNumber = upEnv->GetLineNumber(); if (lineNumber != 0) { ost << std::right << std::setw(6) << lineNumber; } else { ost << std::right << std::setw(6) << ""; } ost << std::left << " " << file; } ost << std::endl; } return; } static void help_ListMethods(DString names, ostream& ostr, FunListT& funlist, ProListT& prolist) { bool searchbyname; searchbyname = (names != ""); vector subList; DString proname; for( SizeT i = 0; iName(); if(searchbyname and not CompareWithJokers(names, proname)) continue; subList.push_back(proname); } sort( subList.begin(), subList.end()); ostr << "Method procedures (" << subList.size() <<"):" << endl; for( SizeT i = 0; iName(); if(searchbyname and not CompareWithJokers(names, proname)) continue; subList.push_back(proname); } sort( subList.begin(), subList.end()); ostr << "Method functions (" << subList.size() <<"):" << endl; for( SizeT i = 0; i guard(dumm); lib::help_struct(ostr, dumm , 0 , false); FunListT& funlist = desc->FunList(); ProListT& prolist = desc->ProList(); help_ListMethods("", ostr, funlist, prolist); } } static void help_ListLib(DString names, ostream& ostr, bool internal=true) { bool searchbyname; searchbyname = (names != ""); vector subList; // for( libProListT::iterator i=libProList.begin(); i != libProList.end(); i++) for( SizeT i = 0; iGetHideHelp()) { if(searchbyname and not CompareWithJokers(names, libProList[i]->Name())) continue; subList.push_back(libProList[ i]->ToString()); } } sort( subList.begin(), subList.end()); if(internal) ostr << "Internal l"; else ostr << "L"; ostr << "ibrary procedures (" << subList.size() <<"):" << endl; for( SizeT i = 0; iGetHideHelp()) { if(searchbyname and not CompareWithJokers(names, libFunList[i]->Name())) continue; subList.push_back(libFunList[ i]->ToString()); } } sort( subList.begin(), subList.end()); if(internal) ostr << "Internal l"; else ostr << "L"; ostr << "ibrary functions (" << subList.size() <<"):" << endl; for( SizeT i = 0; iInterpreter()->HeapSize(); SizeT numObj = e->Interpreter()->ObjHeapSize(); ostr << "Heap Variables:" << std::endl; ostr << " # Pointer: " << numPtr << std::endl; ostr << " # Object : " << numObj << std::endl<< std::endl; if( ! verbose) return; std::vector* heap = e->Interpreter()->GetAllHeapSTL(); Guard< std::vector > heap_guard( heap); SizeT nH = heap->size(); if( nH <= 0 || (*heap)[0] == 0) return; SizeT nDisp = (nH < 50) ? nH : 15; for( SizeT h=0; hInterpreter()->PtrValid( p)) // if( ptrAccessible.find( p) == ptrAccessible.end()) { BaseGDL* hV = BaseGDL::interpreter->GetHeap( p); lib::help_item( ostr, hV, DString( "", false); } } if(nH > nDisp) ostr << nH << " pointers in total"<< endl; return; } static void help_lastmsg(EnvT* e) { // if LAST_MESSAGE is present, it is the only output. // All other kw are ignored *EXCEPT 'output'*. BaseGDL** outputKW = NULL; DStructGDL* errorState = SysVar::Error_State(); static unsigned msgTag = errorState->Desc()->TagIndex( "MSG"); static int outputIx = e->KeywordIx( "OUTPUT"); if (e->KeywordPresent( outputIx)) { // Setup output return variable outputKW = &e->GetKW( outputIx); GDLDelete((*outputKW)); *outputKW = static_cast((errorState->GetTag( msgTag)) ->Convert2( GDL_STRING, BaseGDL::COPY)); return; } else { cout << (*static_cast( errorState->GetTag( msgTag)))[0]<< endl; return; } } static DStringGDL* recall_commands_internal() { // maybe obsolete ??? to be check // AC 24 Oct 2016 if defined(HAVE_LIBREADLINE) && !defined(__APPLE__) //int status=0; DStringGDL* retVal; retVal = new DStringGDL(1, BaseGDL::NOZERO); (*retVal)[ 0] =""; #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE) //status=1; // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX14 HIST_ENTRY **the_list; // cout << "history_length" << history_length << endl; the_list = history_list(); if (the_list) { DStringGDL* retVal = new DStringGDL(history_length - 1, BaseGDL::NOZERO); for (SizeT i = 0; i < history_length - 1; ++i) (*retVal)[i] = the_list[i]->line; return retVal; } else return new DStringGDL(""); #else Message("RECALL_COMMANDS: nothing done, because compiled without READLINE"); return new DStringGDL(""); #endif return retVal; } namespace lib { using namespace std; BaseGDL* recall_commands( EnvT* e) { return recall_commands_internal(); } // display help for one variable or one structure tag void help_item(ostream& ostr, BaseGDL* par, DString parString, bool doIndentation = false) { static volatile bool debug(false); if (debug and (par not_eq NULL)) { cout << par->Type() << " :" << par->TypeStr() << " :" // << &par->TypeStr() << ": " << parString << endl; } if (doIndentation) ostr << " "; // Name display ostr.width(16); ostr << left << parString; if (parString.length() >= 16) { ostr << " " << endl; // for cmsv compatible output (uses help,OUTPUT) ostr.width(doIndentation ? 19 : 16); ostr << ""; } // Type display (we have two "null" : defined !null and undefined variables ... if (par == NULL) { ostr << "UNDEFINED = " << endl; return; } if (!par) { ostr << "UNDEFINED = !NULL" << endl; return; } ostr.width(10); bool doTypeString = true; // Data display if (par->Type() == GDL_STRUCT) { ostr << par->TypeStr() << right; if (!doIndentation) ostr << "= "; doTypeString = false; DStructGDL* s = static_cast (par); ostr << "-> "; ostr << (s->Desc()->IsUnnamed() ? "" : s->Desc()->Name()); ostr << " "; } else if( par->Dim( 0) == 0) { if (par->Type() == GDL_STRING) { ostr << par->TypeStr() << right; if (!doIndentation) ostr << "= "; doTypeString = false; // trim string larger than 45 characters DString dataString = (*static_cast (par))[0]; ostr << "'" << StrMid(dataString, 0, 45, 0) << "'"; if (dataString.length() > 45) ostr << "..."; } else if (par->Type() == GDL_OBJ && par->StrictScalar()) { DObj s = (*static_cast (par))[0]; // is StrictScalar() if (s != 0) // no overloads for null object { DStructGDL* oStructGDL = GDLInterpreter::GetObjHeapNoThrow(s); if (oStructGDL != NULL) // if object not valid -> default behaviour { DStructDesc* desc = oStructGDL->Desc(); static DString listName("LIST"); if (desc->IsParent(listName)) { ostr << desc->Name(); unsigned nListTag = desc->TagIndex("NLIST"); DLong nList = (*static_cast (oStructGDL->GetTag(nListTag, 0)))[0]; ostr << left; ostr << ""; doTypeString = false; } static DString hashName("HASH"); if (desc->IsParent(hashName)) { ostr << desc->Name(); unsigned nListTag = desc->TagIndex("TABLE_COUNT"); DLong nList = (*static_cast (oStructGDL->GetTag(nListTag, 0)))[0]; ostr << left; ostr << ""; doTypeString = false; } } } } if (doTypeString) { ostr << par->TypeStr() << right; if (!doIndentation) ostr << "= "; doTypeString = false; par->ToStream(ostr); } } if (doTypeString) { ostr << par->TypeStr() << right; if (!doIndentation) ostr << "= "; if (par->IsAssoc()) par->ToStream(ostr); } // Dimension display if (par->Dim(0) != 0) ostr << par->Dim(); // End of line ostr << endl; } void help_struct(ostream& ostr, BaseGDL* par, int indent=0, bool debug=false) { // STRUCTURES DStructGDL* s = static_cast( par); SizeT nTags = s->Desc()->NTags(); for(int i=0; i < indent; ++i) ostr <<" "; ostr << "** Structure "; ostr << (s->Desc()->IsUnnamed() ? "" : s->Desc()->Name()); ostr << ", " << nTags << " tags"; if(indent == 0) { ostr << ",memsize =" << s->Sizeof(); ostr << ", data length=" << s->NBytesToTransfer() // << "/" << s->RealBytes() ; GJ has this but only applied here. << "/" << s->SizeofTags() ; } ostr << ":" << endl; for (SizeT t=0; t < nTags; ++t) { for(int i=0; i < indent; ++i) ostr <<" "; if(debug) ostr.width(18); if(debug) ostr <<"dbg: OFFSET="<Desc()->Offset(t); help_item( ostr, s->GetTag(t), s->Desc()->TagName(t), true); if(s->GetTag(t)->Type() == GDL_STRUCT) help_struct(ostr, s->GetTag(t), indent+1); } // lines_count += nTags; } #if 0 void help_struct(ostream& ostr, DStructDesc* dsc) { SizeT nTags = dsc->NTags(); ostr << "** Structure "; ostr << (dsc->IsUnnamed() ? "" : dsc->Name()); ostr << ", " << nTags << " tags"; ostr << ",length =" << dsc->NBytes(); for (SizeT t=0; t < nTags; ++t) { help_item( ostr, dsc->GetTag(t), dsc->TagName(t), true); if(dsc->GetTag(t)->Type() == GDL_STRUCT) help_struct(ostr, dsc->GetTag(t)->Desc()); } ostr << ":" << endl; } #endif void help_help(EnvT* e) { string inline_help[]={"Usage: "+e->GetProName()+", expr1, ..., exprN,", " /ALL_KEYS, /BRIEF, /CALLS, /FUNCTIONS, /HELP, /INFO,", " /INTERNAL_LIB_GDL, /KEYS, /LAST_MESSAGE, /LIB, /MEMORY,", " NAMES=string_filter, OUTPUT=res, /PATH_CACHE, /FILES, ", " /PREFERENCES, /PROCEDURES, /RECALL_COMMANDS, /ROUTINES,", " /SOURCE_FILES, /STRUCTURES, /SYSTEM_VARIABLES, /TRACEBACK"}; int size_of_s = sizeof(inline_help) / sizeof(inline_help[0]); e->Help(inline_help, size_of_s); return; } void SortAndPrintStream(ostringstream& oss) { std::string delimiter = "\n"; std::string s = oss.rdbuf()->str().erase(oss.rdbuf()->str().length(), 1); size_t pos = 0; vector stringList; while ((pos = s.find(delimiter)) != std::string::npos) { stringList.push_back(s.substr(0, pos)); s.erase(0, pos + delimiter.length()); } oss.str(""); sort(stringList.begin(), stringList.end()); vector::iterator it = stringList.begin(); while (it != stringList.end()) std::cout << *it++; std::cout << std::endl; } DStringGDL* StreamToGDLString(ostringstream& oss, bool sorted=false) { std::string delimiter = "\n"; int nlines = 0; size_t pos = 0; while ((pos = oss.str().find(delimiter, pos + 1)) != std::string::npos) { ++nlines; } if (!nlines) return new DStringGDL(""); dimension dim(nlines, (size_t) 1); DStringGDL* out = new DStringGDL(dim, BaseGDL::NOZERO); std::string s = oss.rdbuf()->str().erase(oss.rdbuf()->str().length(), 1); pos = 0; vector stringList; SizeT nOut = 0; while ((pos = s.find(delimiter)) != std::string::npos) { stringList.push_back(s.substr(0, pos)); s.erase(0, pos + delimiter.length()); } oss.str(""); if (sorted) sort(stringList.begin(), stringList.end()); vector::iterator it = stringList.begin(); while (it != stringList.end()) (*out)[nOut++] = *it++; return out; } void help_pro(EnvT* e) { // in order of priority bool kw = false; static int lastmKWIx = e->KeywordIx("LAST_MESSAGE"); bool lastmKW = e->KeywordPresent(lastmKWIx); if( lastmKW) { help_lastmsg(e); return;} SizeT nParam=e->NParam(); BaseGDL** outputKW = NULL; static int outputIx = e->KeywordIx("OUTPUT"); bool doOutput = e->KeywordPresent( outputIx); if (doOutput) { // Setup output return variable outputKW = &e->GetKW(outputIx); GDLDelete((*outputKW)); } static SizeT OutputLines; OutputLines = 0; std::ostringstream ostr; // Use mostly ostrp* << from here on and then push onto outputKW if need be. std::ostream* ostrp = (doOutput) ? &ostr : &cout; static int helpIx = e->KeywordIx( "HELP"); if( e->KeywordSet( helpIx)) {help_help(e); return;} static int allkeysIx=e->KeywordIx("ALL_KEYS"); static int keysIx=e->KeywordIx("KEYS"); if (e->KeywordSet(allkeysIx) || e->KeywordSet(keysIx)) // ALL_KEYS is an obsolete keyword {help_keys(ostr); if (doOutput) (*outputKW)=StreamToGDLString(ostr); else cout << ostr.str(); return;} static volatile bool debugKW(false); static int debugIx = e->KeywordIx( "DEBUG"); if(e->KeywordSet(debugIx)) { debugKW = !debugKW; cout << " Help debug option set/reset: "<< debugKW << endl; return; } static int pathIx = e->KeywordIx( "PATH_CACHE"); if( e->KeywordSet( pathIx)) { // exercising two methods help_path_cached( ostr, OutputLines); if (debugKW) { cout << OutputLines << endl; cout << "begin" << ostr.rdbuf()->str() << "end"<KeywordIx("TRACEBACK"); bool tracebackKW = e->KeywordSet(tracebackKWIx); if (tracebackKW) { SimpleDumpStack(e, ostr); if (doOutput) (*outputKW)=StreamToGDLString(ostr); else cout << ostr.str(); return; } static int briefKWIx = e->KeywordIx("BRIEF"); bool briefKW = e->KeywordSet(briefKWIx); // briefKw should be default usage with DLM HEAP_VARIABLES // also MESSAGES OBJECTS ROUTINES SOURCE_FILES STRUCTURES SYSTEM_VARIABLES static int fullKWIx = e->KeywordIx("FULL"); bool fullKW = e->KeywordSet(fullKWIx); // AC 14-08-11 : detailed info (display size, deep ...) are missing static int deviceKWIx = e->KeywordIx("DEVICE"); bool deviceKW = e->KeywordPresent(deviceKWIx); if (deviceKW) { GraphicsDevice::ListDevice(ostr); DString name = (*static_cast (SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("NAME"), 0)))[0]; ostr << "Current graphics device: " << name << endl; if (doOutput) (*outputKW)=StreamToGDLString(ostr,true); else cout<KeywordIx( "HEAP"); if( e->KeywordSet( heapIx)) { help_heap(e, *ostrp, fullKW); if (doOutput) (*outputKW)=StreamToGDLString(ostr,true); else SortAndPrintStream(ostr); return;} static int namesIx = e->KeywordIx( "NAMES"); bool isKWSetNames= e->KeywordPresent( namesIx); static int sysvarIx = e->KeywordIx( "SYSTEM_VARIABLES"); if( e->KeywordSet( sysvarIx)) { help_sysvar(*ostrp, briefKW); if (doOutput) (*outputKW)=StreamToGDLString(ostr,true); else SortAndPrintStream(ostr); return;} /* OBJECTS Set this keyword to display information on defined object classes. * If no arguments are provided, all currently-defined object classes are shown. * If arguments are provided, the definition of the object class * for the heap variables referred to is displayed. */ static int objectsIx = e->KeywordIx( "OBJECTS"); if( e->KeywordSet( objectsIx) and (nParam ==0)) { SizeT nObj = structList.size(); for( SizeT i=0; iFunList().size() + structList[i]->ProList().size(); if( num_methods == 0) continue; ostrp->width(20); *ostrp << right << structList[i]->Name() << endl; } help_Output(outputKW, ostr, OutputLines); return; } DString names = ""; if (isKWSetNames) { e->AssureStringScalarKWIfPresent(namesIx, names); // since routines and var. are stored in Maj, we convert ... names = StrUpCase(names); } static int sourceFilesKWIx = e->KeywordIx("SOURCE_FILES"); bool sourceFilesKW = e->KeywordPresent(sourceFilesKWIx); static int routinesKWIx = e->KeywordIx("ROUTINES"); bool routinesKW = e->KeywordSet(routinesKWIx); static int ProceduresIx = e->KeywordIx("PROCEDURES"); bool isKWSetProcedures = e->KeywordSet(ProceduresIx); static int FunctionsIx = e->KeywordIx("FUNCTIONS"); bool isKWSetFunctions = e->KeywordSet(FunctionsIx); if (sourceFilesKW) { if (!isKWSetFunctions) { // AC 2018-01-09 : Duplicating the pro list to avoid messing up the order of "proList" // otherwise, a call to HELP,/source created in future calls // e.g. of crashing sequence : TEST_TV & HELP, /source & TEST_TV // ProListT proList_tmp; proList_tmp=proList; sort(proList_tmp.begin(), proList_tmp.end(), CompProName()); *ostrp << "Compiled Procedures:" << endl; *ostrp << "$MAIN$" << endl; OutputLines += 2; for( SizeT i = 0; i < proList_tmp.size(); ++i) { if( proList_tmp[i]->isHidden() and !fullKW ) continue; if (isKWSetNames and !(CompareWithJokers(names,proList_tmp[i]->ObjectName()))) continue; *ostrp << setw(25) << left << proList_tmp[i]->ObjectName() << setw(0); *ostrp << proList_tmp[i]->GetFilename() << endl; } } if (!isKWSetProcedures) { if (!isKWSetFunctions) *ostrp << endl; // AC 2018-01-09 : Duplicating the fun list to avoid messing up the order of "funList" // see above in (do_pro). FunListT funList_tmp; funList_tmp=funList; sort(funList_tmp.begin(), funList_tmp.end(), CompFunName()); *ostrp << "Compiled Functions:" << endl; ++OutputLines; for( SizeT i = 0; i < funList_tmp.size(); ++i) { if( funList_tmp[i]->isHidden() and !fullKW ) continue; if (isKWSetNames and !(CompareWithJokers(names,funList_tmp[i]->ObjectName()))) continue; *ostrp << setw(25) << left << funList_tmp[i]->ObjectName() << setw(0); *ostrp << funList_tmp[i]->GetFilename() << endl; ++OutputLines; } } if (doOutput) (*outputKW)=StreamToGDLString(ostr,true); else cout< fList; static volatile int npro = 0, nfun =0; for( FunListT::iterator i=funList.begin(); i != funList.end(); ++i) if( fullKW or !((*i)->isHidden() ) ) { fList.push_back((*i)->ObjectName()); ++nfun; } sort( fList.begin(), fList.end()); if(debugKW) cout << " #functions=" << nfun; vector pList; pList.push_back("$MAIN$"); for( ProListT::iterator i=proList.begin(); i != proList.end(); ++i) if( fullKW or !((*i)->isHidden() ) ) { pList.push_back((*i)->ObjectName()); ++npro; } sort( pList.begin(), pList.end()); if(debugKW) cout << " #procedures=" << npro; if(debugKW) cout << " #env:" << e->Caller()->EnvSize() << endl; static int callsKWIx = e->KeywordIx("CALLS"); bool callsKW = e->KeywordPresent(callsKWIx); if (callsKW) { // this is a code derived from SimpleDumpStack() above EnvStackT& callStack = e->Interpreter()->CallStack(); long actIx = callStack.size() - 1; DStringGDL* retVal = new DStringGDL(dimension(actIx + 1), BaseGDL::NOZERO); SizeT rIx = 0; for (; actIx >= 0; --actIx) { EnvStackT::pointer_type upEnv = callStack[actIx]; DString actString = upEnv->GetProName(); std::string file = upEnv->GetFilename(); if (file != "") { actString += " <" + file + "("; actString += i2s(upEnv->GetLineNumber(), 4); actString += ")>"; } (*retVal)[rIx++] = actString; } e->SetKW(callsKWIx, retVal); return; } static int filesIx = e->KeywordIx("FILES"); if(e->KeywordPresent( filesIx)) { help_files( ostr, e); if (doOutput) (*outputKW)=StreamToGDLString(ostr,true); else cout<KeywordIx("INFO"); if( e->KeywordSet( infoIx)){ kw = true; help_info(); } static int libIx = e->KeywordIx("LIB"); // internal library functions static int INTERNAL_LIB_GDLIx=e->KeywordIx("INTERNAL_LIB_GDL"); bool kwLibInternal = e->KeywordSet(INTERNAL_LIB_GDLIx); if (kwLibInternal) { cout << "NOTE: Internal subroutines are subject to change without notice." << endl; cout << "They should never be called directly from a GDL program." << endl; } if( e->KeywordSet( libIx)) { kw = true; help_ListLib(names, *ostrp, kwLibInternal); } static int STRUCTURESIx = e->KeywordIx("STRUCTURES"); bool isKWSetStructures = e->KeywordSet(STRUCTURESIx); static int RECALL_COMMANDSIx = e->KeywordIx("RECALL_COMMANDS"); bool isKWSetRecall = e->KeywordSet(RECALL_COMMANDSIx); static int MEMORYIx = e->KeywordIx("MEMORY"); bool isKWSetMemory = e->KeywordSet(MEMORYIx); static int PREFERENCESIx = e->KeywordIx("PREFERENCES"); bool isKWSetPreferences = e->KeywordSet( "PREFERENCES"); if (isKWSetStructures) kw = true; if ( (isKWSetStructures or isKWSetRecall or isKWSetMemory or isKWSetPreferences) and (isKWSetProcedures or isKWSetFunctions)) e->Throw("Conflicting keywords."); if (isKWSetRecall) { DStringGDL *previous_commands; previous_commands = recall_commands_internal(); SizeT nEl2 = previous_commands->N_Elements(); cout << "Recall buffer length: " << nEl2 << endl; for (SizeT i = 0; i < nEl2; ++i) { if (isKWSetNames and !CompareWithJokers(names, (*previous_commands)[i])) continue; *ostrp << i+1 << " " <<(*previous_commands)[i] << endl; } GDLDelete(previous_commands); if (doOutput) (*outputKW)=StreamToGDLString(ostr); else cout<(pList[i])); if( p == proList.end()) continue; DPro *pro = *p; if (isKWSetNames and !CompareWithJokers(names, pro->ObjectName())) continue; *ostrp << setw(25) << left << pro->ObjectName() << setw(0); int nPar = pro->NPar(); int nKey = pro->NKey(); // Loop through parameters and keywords for( SizeT j=0; jNPar(); ++j) *ostrp << StrLowCase(pro->GetVarName(nKey+j)) << " "; for( SizeT j=0; jNKey(); ++j) *ostrp << StrUpCase(pro->GetVarName(j)) << " "; *ostrp << endl; ++OutputLines; } } if (isKWSetFunctions or routinesKW) { *ostrp << "Compiled Functions:" << endl; ++OutputLines; // Loop through functions for( SizeT i=0; i(fList[i])); if( p == funList.end()) continue; DFun *pro = *p; if (isKWSetNames and !CompareWithJokers(names, pro->ObjectName())) continue; int nPar = pro->NPar(); int nKey = pro->NKey(); *ostrp << setw(25) << left << pro->ObjectName() << setw(0); for (SizeT j = 0; j < nPar; ++j) *ostrp << StrLowCase(pro->GetVarName(nKey+j)) << " "; for (SizeT j = 0; j < nKey; ++j) *ostrp << StrUpCase(pro->GetVarName(j)) << " "; *ostrp << endl; OutputLines++; } } if( isKWSetProcedures or isKWSetFunctions) { if(doOutput) help_Output(outputKW, ostr, OutputLines); return; } } // Excluding keywords which are exclusive is not finished ... if (isKWSetPreferences) { //cout << "ici 1 " << isKWSetPreferences << endl; *ostrp << "Preferences: this is not ready ..."<KeywordIx( "COMMON"); if(e->KeywordSet( commonIx)) { // list in internal order CommonListT::iterator it; for( it=commonList.begin(); it != commonList.end(); ++it) { SizeT nVar = (*it)->NVar(); if(nVar == 0) continue; *ostrp << " Common block (" << (*it)->Name() << ") listed in internal order:" <VarName( vIx) +" ("+(*it)->Name()+')'; DVar* var = (*it)->Var( vIx); if( var->Data() not_eq NULL || fullKW) help_item( *ostrp , var->Data(), parString, false); } } if (doOutput) (*outputKW)=StreamToGDLString(ostr); else cout << ostr.str(); if(nParam == 0) return; } if(debugKW) std::cout << " help_pro: nParam=" << nParam ; const string objectnotfound = ": Object not found"; bool objectsKW = e->KeywordSet(objectsIx); for( SizeT i=0; iGetPar( i); DString parString = e->Caller()->GetString( par, true);//= string(" ??? "); if(debugKW) std::cout << ". " ; if(par == NULL) { if(debugKW) std::cout << " par ==(NULL)" << endl; if( objectsKW) { help_object( ostr, parString, !briefKW); continue; } if(!briefKW) help_item( ostr, par, parString, false); continue; } if(objectsKW && par->Type() != GDL_OBJ) { if(par->Type() == GDL_STRING) { for( SizeT kobj=0; kobj < par->N_Elements(); ++kobj) help_object( ostr, (*static_cast(par))[kobj], !briefKW); continue;} else { cout << parString+ ":error (help,prm,/OBJECTS - prm is not object nor string) " << endl; continue; ;} } help_item( ostr, par, parString, false); // NON-STRUCTURES except if one and only one param is a Struct. if(par->Type() == GDL_STRUCT and (nParam == 1 or isKWSetStructures ) and !briefKW) help_struct(ostr, par, 0, debugKW); else if ( nParam != 1) continue; else if (par->Type() == GDL_OBJ and par->StrictScalar()) { bool isKWSetMethods = e->KeywordSet( "METHODS"); DObj s = (*static_cast(par))[0]; DStructGDL* oStructGDL; if(s != 0) oStructGDL = GDLInterpreter::GetObjHeapNoThrow( s); if( s!= 0 and (isKWSetStructures or fullKW)) help_struct(ostr, oStructGDL, 0, debugKW); if( s!= 0 and (isKWSetMethods or fullKW)){ DStructDesc* desc = oStructGDL->Desc(); FunListT& funlist = desc->FunList(); ProListT& prolist = desc->ProList(); help_ListMethods(names, ostr, funlist, prolist); } } else if (par->Type() == GDL_OBJ) { SizeT nObj = par->N_Elements(); if(debugKW) std::cout << "nObj="<( par))[iobj]; // object_help( ostr, s, false); DStructGDL* oStructGDL; DString classname; DString nameobj=" ["+i2s(iobj)+"] "; if(s != 0) { // Name display if(debugKW) std::cout << "-"; std::vector< std::string> pNames; ostr.width(16); ostr << left << nameobj; oStructGDL = GDLInterpreter::GetObjHeapNoThrow( s); if(oStructGDL == NULL) continue; if(debugKW) std::cout << "."; classname = oStructGDL->Desc()->Name() ; oStructGDL->Desc()->GetParentNames(pNames); ostr.width(10); ostr << classname << right; ostr << left << " " << right; DString parents; if(pNames.size() == 0) parents = ""; else if( pNames.size() == 1) parents = " parent:"; else parents = " parents:"; ostr << left << parents; for (SizeT i=0; i < pNames.size(); ++i) ostr << " " << pNames[i]; ostr << endl; } else help_item( ostr, NULL, nameobj, false); } } } if(debugKW) std::cout << " :=:" << std::endl; if(nParam > 0) { if (doOutput) (*outputKW)=StreamToGDLString(ostr); else cout<KeywordIx("LEVEL"); if(e->KeywordPresent(levelIx) ) { std::ostringstream parameters_ostringstream; DLongGDL* level = e->IfDefGetKWAs(levelIx); //will list (all) variables, incl. common defined, at desired level. EnvStackT& callStack = e->Interpreter()->CallStack(); DLong curlevnum = callStack.size(); DLong desiredlevnum = curlevnum; if (level != NULL) { desiredlevnum = (*level)[0]; if (desiredlevnum <= 0) desiredlevnum += curlevnum; if (desiredlevnum < 1) desiredlevnum = 0; if (desiredlevnum > curlevnum) desiredlevnum = curlevnum; } DSubUD* pro = static_cast (callStack[desiredlevnum-1]->GetPro()); SizeT nVar = pro->Size(); // # var in GDL for desired level SizeT nComm = pro->CommonsSize(); // # has commons? SizeT nTotVar = nVar + nComm; //All the variables availables at that lev. if(debugKW) cout << " Level section: nTotVar=" << nTotVar << endl; if (nTotVar > 0) { set helpStr; // "Sorted List" if (nVar > 0) { for (SizeT i = 0; i < nVar; ++i) { BaseGDL*& par = (static_cast (callStack[desiredlevnum - 1]))->GetKW(i); if (par != NULL) { stringstream ss; string parName = pro->GetVarName(i); help_item(ss, par, parName, false); helpStr.insert(ss.str()); } } } if (nComm > 0) { DStringGDL* list=static_cast(pro->GetCommonVarNameList()); for (SizeT i = 0; i < list->N_Elements(); ++i) { BaseGDL** par = pro->GetCommonVarPtr((*list)[i]); DCommonBase* common = pro->FindCommon((*list)[i]); DString parName = (*list)[i] + " (" + common->Name() + ')'; stringstream ss; help_item(ss, (*par), parName, false); helpStr.insert(ss.str()); } } copy(helpStr.begin(), helpStr.end(),ostream_iterator(parameters_ostringstream)); } } // if /brief and /routines then no var. to be shown if( routinesKW and briefKW) kw = true; if( nParam == 0 and !kw) { routinesKW = true; briefKW = true; // list all variables of caller EnvBaseT* caller = e->Caller(); SizeT nEnv = caller->EnvSize(); //cout << "EnvSize() " << nEnv << endl; set helpStr; // "Sorted List" stringstream ss; for ( int i = 0; i < nEnv; ++i ) { BaseGDL*& par=caller->GetKW( i); if(par == NULL && !fullKW) continue; // if( par == NULL) continue; DString parString = caller->GetString( par,true); if(debugKW ) cout << " GetKW(i)->GetString(par) "< cptr; DSubUD* proUD = dynamic_cast(caller->GetPro()); proUD->commonPtrs(cptr); std::vector::iterator ic; for( ic=cptr.begin(); ic != cptr.end(); ++ic) { SizeT nVar = (*ic)->NVar(); for( SizeT vIx = 0; vIx < nVar; ++vIx) { DString parString = (*ic)->VarName( vIx) +" ("+(*ic)->Name()+')'; if (isKWSetNames and !CompareWithJokers(names, parString)) continue; DVar* var = (*ic)->Var( vIx); if( (var->Data() not_eq NULL) || fullKW) { help_item( ss, var->Data(), parString, false); helpStr.insert(ss.str()); ss.str(""); } } } copy( helpStr.begin(), helpStr.end(), ostream_iterator( *ostrp) ); OutputLines += helpStr.size(); } // if( nParam == 0 and !kw) if( routinesKW and briefKW) { // Display compiled procedures & functions if (!isKWSetProcedures and !isKWSetFunctions) { *ostrp << "Compiled Procedures:" << endl; for( SizeT i=0; i #endif #include #include #include "envt.hpp" #include "dinterpreter.hpp" #include "gdljournal.hpp" #include "io.hpp" #include "str.hpp" #include "initsysvar.hpp" #include "basic_pro.hpp" #include "file.hpp" namespace lib { using namespace std; const int MAX_DATE_STRING_LENGTH = 80; const char* JOURNALCOMMENT = ";"; static GDLStream *gdljournal; void journal(EnvT *e) { /*case 1: journal closed 1a:no argument open journal with default filename 'gdljournal.pro' 1b:1 argument open journal with filename from argument case 2: journal open 2a:no argument close journal 2b:1 argument print argument to journal */ //setup SizeT nParam=e->NParam(); if( SysVar::JournalLUN() == 0) { string gdljournal_filename; //case 1 if(nParam == 0) { //case 1a = default open gdljournal_filename="gdljournal.pro"; } else if (nParam == 1) { //case 1b: open with filename e->AssureStringScalarPar(0,gdljournal_filename); } DLong jLUN = GetLUN(); if( jLUN == 0) e->Throw( "All available logical units are currently in use."); SysVar::JournalLUN( jLUN); gdljournal= &fileUnits[ jLUN-1]; gdljournal->Open(gdljournal_filename,fstream::out,false,false,false, defaultStreamWidth,false,false); //message DStructGDL* version = SysVar::Version(); /* static unsigned releaseTag = version->Desc()->TagIndex( "RELEASE");*/ static unsigned osTag = version->Desc()->TagIndex( "OS"); static unsigned archTag = version->Desc()->TagIndex( "ARCH"); static unsigned mTag = version->Desc()->TagIndex( "MEMORY_BITS"); /* DString release = (*static_cast( version->GetTag( releaseTag, 0)))[0];*/ DString os = (*static_cast( version->GetTag( osTag, 0)))[0]; DString arch = (*static_cast( version->GetTag( archTag, 0)))[0]; DInt m = (*static_cast( version->GetTag( mTag, 0)))[0]; write_journal_comment( string("GDL Version ")+VERSION/*release*/+" ("+os+" "+arch+" m"+ i2s(m)+")"); string user = GetEnvString( "USER"); // depending the system, HOST variable is not always set up. int debug=0; string host = GetEnvString( "HOST"); if (debug) cout << "HOST: " << host << ".." << endl; if (host == "") { host = GetEnvString( "HOSTNAME"); if (debug) cout << "HOSTNAME: " << host << endl; } if (host == "") { //char *gethost; #define GDL_HOST_NAME_MAX 255 char gethost[GDL_HOST_NAME_MAX]; size_t lgethost=GDL_HOST_NAME_MAX; // don't know if this primitive is available on Mac OS X int success = gethostname(gethost, lgethost); if( success != 0) // we are here only if all 3 methods failed {e->Throw( "Unknown hostname !");} else { host=string(gethost); //if (debug) cout << "lgethost: [" << lgethost << "]"<< endl; //if (debug) cout << "1GETHOSTNAME: [" << gethost << "]"<< endl; if (debug) cout << "GETHOSTNAME: [" << host.c_str() << "]"<< endl; } } write_journal_comment("Journal File for "+user+"@"+host); DString cur = GetCWD(); write_journal_comment("Working directory: "+cur); time_t t=time(0); struct tm * tstruct; tstruct=localtime(&t); char *st=new char[MAX_DATE_STRING_LENGTH]; const char *format="%a %h %d %T %Y";// day,month,day number,time,year SizeT res=strftime(st,MAX_DATE_STRING_LENGTH,format,tstruct); if(res != 0) write_journal_comment(string("Date: ") + st + string("\n")); delete[] st; // clear input line (should not be put into the journal file GDLInterpreter* ip = e->Interpreter(); ip->GetClearActualLine(); } else { //case 2 if(nParam == 0) { //case 2a = close file if(gdljournal != NULL) { gdljournal->Close(); gdljournal=NULL; SysVar::JournalLUN( 0); } } else if (nParam == 1) { //case 2b = print arg to journal // tricky because WITHOUT ';' this time // solution: fake writing to normal file BaseGDL* outPar = e->GetParDefined( 0); GDLStream* gdljournalSav = gdljournal; gdljournal = NULL; try{ SizeT actPos = 0; outPar->ToStream( gdljournalSav->OStream(), gdljournalSav->Width(), &actPos); gdljournal = gdljournalSav; } catch(...) { gdljournal = gdljournalSav; throw; } } } } GDLStream* get_journal() { return gdljournal; } // used only with GetClearActualLine, which already contains a trailinf '\n' void write_journal(string str) { if(gdljournal == NULL) return; gdljournal->OStream() << str; } void write_journal_comment(string str) { if(gdljournal == NULL) return; gdljournal->OStream() << JOURNALCOMMENT << " " << str << "\n"; } void write_journal_comment(EnvT *e, int offset, SizeT width) { if(gdljournal == NULL) return; if(e->NParam() == 0) return; print_os( &gdljournal->OStream(), e, offset, width); } } #endif gdl-0.9.9/src/gdljournal.hpp000066400000000000000000000026721340051421000157350ustar00rootroot00000000000000/*************************************************************************** gdljournal.cpp - exception handling ------------------- begin : September 26 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDL_JOURNAL_H #define GDL_JOURNAL_H #ifdef HAVE_CONFIG_H #include #endif #include "datatypes.hpp" #include "envt.hpp" #include "io.hpp" namespace lib { extern const char* JOURNALCOMMENT; void journal(EnvT *e); void write_journal(std::string str); void write_journal_comment(std::string str); void write_journal_comment(EnvT *e, int offset, SizeT width); GDLStream* get_journal(); } #endif gdl-0.9.9/src/gdlpsstream.cpp000066400000000000000000000207421340051421000161120ustar00rootroot00000000000000/* ************************************************************************* gdlpsstream.cpp - graphic stream postscript ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" //#include #include "graphicsdevice.hpp" #include "gdlpsstream.hpp" using namespace std; void GDLPSStream::Init() { plstream::init(); page = 0; } void GDLPSStream::eop() { if (page != 0) { if (encapsulated) { Warning("Warning: multi-page output violates Encapsulated PostScript specification"); } else { #ifdef USE_PSLIB Warning("Warning: multi-page PostScript not supported yet (FIXME!)"); #endif } plstream::eop(); } page++; }; void image_compress(unsigned char *idata, PLINT size, long bpp) { unsigned char byt=0x0; SizeT i,j,k; // static unsigned char mask[]={0x0,0x1,0x3,0x0,0x7}; static short count[]={0,7,3,0,1}; static short shiftLeft[] ={0,1,2,0,4}; static short shiftRight[] ={0,7,6,0,4}; bool complete=false; for (i=0, j=0, k=0; i> shiftRight[bpp])); if (j == count[bpp]) {idata[k++]=byt; byt=0x0; j=0; complete=true;} else {j++;complete=false;} } if (!complete) { //something left undone... for (int l=0; l< count[bpp]-j+1; ++l ) byt=(byt<OnePageSaveLayout(); this->vpor(0, 1, 0, 1); //ALL PAGE this->wind(0, 1, 0, 1); //ALL PAGE PLFLT x=0; PLFLT y=0; this->poin(1,&x,&y,-1); //put a point at 0,0 wherever it is on the plot this->Flush(); pls->bytecnt += fprintf(pls->OutFile, "\ncurrentpoint /YMIN exch def /XMIN exch def\n"); x=1; y=1; this->poin(1,&x,&y,-1); //put a point at 0,0 wherever it is on the plot this->Flush(); this->RestoreLayout(); //autotest whether PS was rotated + define good sizes. pls->bytecnt += fprintf(pls->OutFile, "\ncurrentpoint /YMAX exch def /XMAX exch def\n"); pls->bytecnt += fprintf(pls->OutFile, "YMAX YMIN lt /LAND exch def \n"); pls->bytecnt += fprintf(pls->OutFile, "LAND { YMAX /YMAX YMIN def /YMIN exch def /ROT 270 def} {/ROT 0 def} ifelse\n"); pls->bytecnt += fprintf(pls->OutFile, "XMAX XMIN sub /XRANGE exch def YMAX YMIN sub /YRANGE exch def\n"); pls->bytecnt += fprintf(pls->OutFile, "LAND {/X0 XMIN def /Y0 YMAX def /RX YRANGE def /RY XRANGE def}" "{/X0 XMIN def /Y0 YMIN def /RX XRANGE def /RY YRANGE def} ifelse\n"); } //need to : check position in file Ok; update bounding box values. //test black and white: bool bw = (((*static_cast (SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0] & 16) == 0); long xs, ys; GDLPSStream::GetGeometry(xs, ys); SizeT nelem; if (channel > 0) { cerr << "TV: Value of CHANNEL (use TRUE instead) is out of allowed range." << endl; return false; } pls->bytecnt += fprintf(pls->OutFile, "%%BeginObject: Image\n S gsave\nX0 Y0 translate ROT rotate RX RY scale\n"); pls->bytecnt += fprintf(pls->OutFile, "%d %ld div %d %ld div translate\n", pos[0], xs, pos[2], ys); pls->bytecnt += fprintf(pls->OutFile, "%d %ld div %d %ld div scale\n", pos[1], xs, pos[3], ys); #define LINEWIDTH 80 if (trueColorOrder == 0) { if (bw) { //black and white native value 0->255: image pls->bytecnt += fprintf(pls->OutFile, "/gdlImagePixString %ld string def ", (long)ceil(1.0 * nx * bitsPerPix / 8.)); pls->bytecnt += fprintf(pls->OutFile, "%d %d %ld ", nx, ny, bitsPerPix); pls->bytecnt += fprintf(pls->OutFile, "[%d 0 0 %d 0 0] \n {currentfile gdlImagePixString readhexstring pop} bind\n image\n", nx, ny); //if bpp is not 8, convert to, else use it directly if (bitsPerPix != 8) image_compress(idata,1*nx*ny,bitsPerPix); //output data in lines of LINEWIDTH chars: nelem=(long)ceil(1.0 * nx * ny * bitsPerPix / 8.); for (SizeT i = 0, k=0 ; i < nelem ; ++i) { fprintf(pls->OutFile, "%2.2X", idata[i]); k+=2; if( (k % LINEWIDTH) == 0 ) fprintf(pls->OutFile, "\n"); } pls->bytecnt += (nelem*2 + nelem*2/LINEWIDTH); } else { pls->bytecnt += fprintf(pls->OutFile, "/gdlImagePixString 1 string def "); pls->bytecnt += fprintf(pls->OutFile, "%d %d %ld ", nx, ny, bitsPerPix); pls->bytecnt += fprintf(pls->OutFile, "[%d 0 0 %d 0 0]\n", nx, ny); PLINT r[ctSize], g[ctSize], b[ctSize]; GraphicsDevice::GetCT()->Get( r, g, b); //OUR colors, *NOT* plplot's colors (background mess) unsigned char *data=(unsigned char*)malloc(nx*ny*3*sizeof(unsigned char)); //following is false for bits_per_pix not equal to 8. Colortable must be written differently. FIXME! for (SizeT i = 0; i < nx*ny; ++i) {data[i*3+0]=r[idata[i]];data[i*3+1]=g[idata[i]];data[i*3+2]=b[idata[i]];} pls->bytecnt += fprintf(pls->OutFile, "{currentfile gdlImagePixString readhexstring pop} bind false 3 colorimage\n"); //if bpp is not 8, convert to, else use it directly if (bitsPerPix != 8) image_compress(data,3*nx*ny,bitsPerPix); //output data in lines of LINEWIDTH chars: nelem=(long)ceil(3.0 * nx * ny * bitsPerPix / 8.); for (SizeT i = 0, k = 0 ; i < nelem ; ++i) { fprintf(pls->OutFile, "%2.2X", data[i]); k+=2; if( (k % LINEWIDTH) == 0 ) fprintf(pls->OutFile, "\n"); } free(data); pls->bytecnt += (nelem*2 + nelem*2/LINEWIDTH); } } else { //true color: native value (degrees of R, G and B) switch (trueColorOrder) { case 1: pls->bytecnt += fprintf(pls->OutFile, "/gdlImagePixString %d string def\n", nx * 3); pls->bytecnt += fprintf(pls->OutFile, "%d %d %ld\n", nx, ny, bitsPerPix); pls->bytecnt += fprintf(pls->OutFile, "[%d 0 0 %d 0 0] {currentfile gdlImagePixString readhexstring pop} bind\n false 3 colorimage\n", nx, ny); break; case 2: pls->bytecnt += fprintf(pls->OutFile, "/gdlImagePixStringR %d string def /gdlImagePixStringG %d string def /gdlImagePixStringB %d string def\n", nx, nx, nx); pls->bytecnt += fprintf(pls->OutFile, "%d %d %ld\n", nx, ny, bitsPerPix); pls->bytecnt += fprintf(pls->OutFile, "[%d 0 0 %d 0 0] {currentfile gdlImagePixStringR readhexstring pop} bind\n {currentfile gdlImagePixStringG readhexstring pop} bind\n {currentfile gdlImagePixStringB readhexstring pop} bind\n true 3 colorimage\n", nx, ny); break; case 3: pls->bytecnt += fprintf(pls->OutFile, "/gdlImagePixStringR %d string def /gdlImagePixStringG %d string def /gdlImagePixStringB %d string def\n", nx*ny, nx*ny, nx*ny); pls->bytecnt += fprintf(pls->OutFile, "%d %d %ld\n", nx, ny, bitsPerPix); pls->bytecnt += fprintf(pls->OutFile, "[%d 0 0 %d 0 0] {currentfile gdlImagePixStringR readhexstring pop} bind\n {currentfile gdlImagePixStringG readhexstring pop} bind\n {currentfile gdlImagePixStringB readhexstring pop} bind\n true 3 colorimage\n", nx, ny); break; default: cerr<<"you should not get here!"<OutFile, "%2.2X", idata[i]); k+=2; if( (k % LINEWIDTH) == 0 ) fprintf(pls->OutFile, "\n"); } pls->bytecnt += (nelem*2 + nelem*2/LINEWIDTH); } pls->bytecnt += fprintf(pls->OutFile, "\ngrestore\n%%EndObject: Image\n "); return true; #undef LINEWIDTH } gdl-0.9.9/src/gdlpsstream.hpp000066400000000000000000000035121340051421000161130ustar00rootroot00000000000000/* ************************************************************************* gdlpsstream.hpp - graphic stream postscript ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLPSSTREAM_HPP_ #define GDLPSSTREAM_HPP_ #include "initsysvar.hpp" #include "gdlgstream.hpp" class GDLPSStream: public GDLGStream { private: int page; bool encapsulated; long bitsPerPix; bool firstTime; //to enable a PS hack on correspondence postscript pixels - plplot position. public: GDLPSStream( int nx, int ny, int pfont, bool encaps, int color, int bpp): #ifdef _MSC_VER GDLGStream( nx, ny, /*pfont == 1 ? "psttf" :*/ (color==0)?"ps":"psc") #else GDLGStream::GDLGStream( nx, ny, /*pfont == 1 ? "psttf" :*/(color==0)?"ps":"psc") #endif { encapsulated = encaps; page = 0; firstTime=true; bitsPerPix=bpp; } ~GDLPSStream() {} void eop(); void Init(); bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan); }; #endif gdl-0.9.9/src/gdlpython.cpp000066400000000000000000000202601340051421000155700ustar00rootroot00000000000000/*************************************************************************** gdlpython.cpp - python embedded in GDL ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef INCLUDE_GDLPYTHON_CPP //#include "includefirst.hpp" // this part contains variable conversion stuff // used by both GDL embedded in python and python embedded in GDL //#if defined(USE_PYTHON) || defined(PYTHON_MODULE) //#include //#include //#include "datatypes.hpp" //#include "envt.hpp" //#include "objects.hpp" using namespace std; void PythonInit() { if( Py_IsInitialized()) return; Py_Initialize(); // signal handlers? static int argc = 1; static char* arg0 = (char*)"./py/python.exe"; static char* argv[] = {arg0}; PySys_SetArgv(argc, argv); // http://docs.scipy.org/doc/numpy/reference/c-api.array.html#miscellaneous import_array(); } void PythonEnd() { // was not possible with numarray (numarray cannot be restarted) // but now we use Numpy??? (TODO/FIXME) //if( !Py_IsInitialized()) return; //Py_Finalize(); } template< typename T> T* NewFromPyArrayObject( const dimension& dim, PyArrayObject *array) { T* res = new T( dim, BaseGDL::NOZERO); SizeT nEl = res->N_Elements(); typename T::Ty* dPtr = reinterpret_cast( PyArray_DATA(array)); for( SizeT i=0; i( pyObj)); if( array == NULL) throw GDLException( "Error getting python array.") ; int nDim = array->nd; SizeT dimArr[ MAXRANK]; if( nDim > MAXRANK) { Warning( "Python array has more than "+MAXRANK_STR+ " dimensions. Extending last one."); SizeT lastDim = array->dimensions[ MAXRANK-1]; for( SizeT i=MAXRANK; idimensions[ i]; for( SizeT i=0; idimensions[ i]; dimArr[ MAXRANK-1] = lastDim; nDim = MAXRANK; } else { for( SizeT i=0; idimensions[ i]; } dimension dim( dimArr, nDim); switch( array->descr->type_num) { case NPY_UINT8: //GDL_BYTE return NewFromPyArrayObject< DByteGDL>( dim, array); case NPY_INT16: //GDL_INT return NewFromPyArrayObject< DIntGDL>( dim, array); case NPY_INT32: //GDL_LONG return NewFromPyArrayObject< DLongGDL>( dim, array); case NPY_FLOAT32: //GDL_FLOAT return NewFromPyArrayObject< DFloatGDL>( dim, array); case NPY_FLOAT64: //GDL_DOUBLE return NewFromPyArrayObject< DDoubleGDL>( dim, array); case NPY_COMPLEX64: //GDL_COMPLEX return NewFromPyArrayObject< DComplexGDL>( dim, array); case NPY_COMPLEX128: //GDL_COMPLEXDBL return NewFromPyArrayObject< DComplexDblGDL>( dim, array); case NPY_UINT16: //GDL_UINT* return NewFromPyArrayObject< DUIntGDL>( dim, array); case NPY_UINT32: //GDL_ULONG* return NewFromPyArrayObject< DULongGDL>( dim, array); default: Py_DECREF(array); // must be decremented throw GDLException( "FromPython: Unknown array type.") ; } return NULL; // compiler shut-up } // you can compile GDL as a python module without supporting // python *within* GDL #ifdef USE_PYTHON namespace lib { using namespace std; BaseGDL* gdlpython( EnvT* e, int kIx) { PythonInit(); SizeT nParam = e->NParam(); static int argvIx = e->KeywordIx( "ARGV"); BaseGDL* argv1 = e->GetKW( argvIx); if( argv1 != NULL) { DStringGDL* argvS = dynamic_cast( argv1); if( argvS == NULL) e->Throw( "ARGV keyword must be of type STRING."); int argc = argvS->N_Elements(); char** argv = new char*[ argc]; // pyhton copies the value -> threats it as const for( int i=0; i((*argvS)[ i].c_str()); PySys_SetArgv(argc, argv); delete[] argv; } if( nParam < 2 && kIx != -1) e->Throw( "Function must have at least 2 parameters."); if( nParam == 0) return NULL; // ok, just keywords DString module; e->AssureScalarPar( 0, module); // PyObject* pName = PyString_FromString( module.c_str()); // // Error checking of pName left out // PyObject* pModule = PyImport_Import(pName); // Py_DECREF(pName); PyObject* pModule = PyImport_ImportModule(const_cast(module.c_str())); if (pModule == NULL) { PyErr_Print(); e->Throw( "Failed to load module: "+module); } if( nParam == 1) { Py_DECREF(pModule); return NULL; // ok, only load module } DString function; e->AssureScalarPar( 1, function); PyObject* pDict = PyModule_GetDict(pModule); /* pDict is a borrowed reference */ PyObject* pFunc = PyDict_GetItemString(pDict, function.c_str()); /* pFunc: Borrowed reference */ if( !(pFunc && PyCallable_Check(pFunc))) { if (PyErr_Occurred()) PyErr_Print(); e->Throw( "Cannot find function: "+function); } PyObject* pArgs = PyTuple_New( nParam-2); for( SizeT i = 2; iGetParDefined( i); PyObject* pValue = actPar->ToPython(); if (!pValue) { Py_DECREF(pArgs); Py_DECREF(pModule); e->Throw( "Cannot convert value: "+ e->GetParString( i)); } /* pValue reference stolen here: */ PyTuple_SetItem(pArgs, i-2, pValue); } PyObject* pResult = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); Py_DECREF(pModule); // pDict and pFunc are borrowed and must not be Py_DECREF-ed if( pResult == NULL) { PyErr_Print(); e->Throw( "Call failed: "+module+"."+function); } if( kIx == -1) // called as procedures { Py_DECREF(pResult); return NULL; } // as function BaseGDL* res; if( pResult == Py_None) { Py_DECREF(pResult); BaseGDL* defRet = e->GetKW( kIx); if( defRet == NULL) e->Throw( "Function returned 'None' " "and DEFAULTRETURN not defined."); res = defRet->Dup(); } else { try { res = FromPython( pResult); Py_DECREF(pResult); } catch(...) { Py_DECREF(pResult); throw; } } return res; } // GDL PYTHON procedure // PYTHON,module,function[,args] void gdlpython_pro( EnvT* e) { gdlpython( e, -1); } // GDL PYTHON function BaseGDL* gdlpython_fun( EnvT* e) { static int kIx = e->KeywordIx( "DEFAULTRETURNVALUE"); return gdlpython( e, kIx); } } // namespace #endif // #ifdef USE_PYTHON //#endif // #if defined(USE_PYTHON) || defined(PYTHON_MODULE) #endif // #ifdef INCLUDE_GDLPYTHON_CPP gdl-0.9.9/src/gdlpython.hpp000066400000000000000000000023451340051421000156010ustar00rootroot00000000000000/*************************************************************************** gdlpython.hpp - python embedding ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLPYTHON_HPP_ #define GDLPYTHON_HPP_ void PythonInit(); void PythonEnd(); BaseGDL* FromPython( PyObject* pyObj); namespace lib { BaseGDL* gdlpython_fun( EnvT* e); void gdlpython_pro( EnvT* e); } #endif gdl-0.9.9/src/gdlsvgstream.cpp000066400000000000000000000226621340051421000162720ustar00rootroot00000000000000/* ************************************************************************* gdlsvgstream.cpp - graphic stream SVG ------------------- begin : December 26 2008 copyright : (C) 2002 by Sylwester Arabas email : slayoo@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "gdlsvgstream.hpp" #ifdef _WIN32 #include #include #include #include #include #else #include #endif using namespace std; void GDLSVGStream::Init() { plstream::init(); } // this lookup table defines the base64 encoding static const string svgBase64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); static const char svgfillchar = '='; string encodesvg(unsigned char buf[], unsigned int len) { string ret; if(len==0) return ""; ret.reserve((len-1)/3*4 + 4 + 1); for (string::size_type i = 0; i < len; ++i) { char c; c = (buf[i] >> 2) & 0x3f; ret.append(1, svgBase64Table[c]); c = (buf[i] << 4) & 0x3f; if (++i < len) c |= (buf[i] >> 4) & 0x0f; ret.append(1, svgBase64Table[c]); if (i < len) { c = (buf[i] << 2) & 0x3f; if (++i < len) c |= (buf[i] >> 6) & 0x03; ret.append(1, svgBase64Table[c]); } else { ++i; ret.append(1, svgfillchar); } if (i < len) { c = buf[i] & 0x3f; ret.append(1, svgBase64Table[c]); } else { ret.append(1, svgfillchar); } } return(ret); } #ifdef USE_PNGLIB std::string GDLSVGStream::svg_to_png64(int width,int height, png_byte *image, int bit_depth, int nbpp, int whattype, int *error) { static std::string tmpstr; tmpstr.clear(); FILE *fp; png_structp png_ptr; png_infop info_ptr; static const int np=pls->ncol0; int k; png_bytep *row_pointers; png_colorp palette; char line[512]; char filename[512]; char *in,*out; int lin, lout; int fd; *error = 0; /* open a temporary file */ sprintf(filename,"%sgdlsvgpng64.XXXXXX",getenv("IDL_TMPDIR")); //Insecure, check! #ifdef _WIN32 static const char *letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char *XXXXXX = &filename[strlen(filename)-6]; srand((unsigned int)time(NULL)); for (int i=0; i<6; i++) XXXXXX[i] = letters[rand()%63]; /* _sopen replaces _sopen_s(&fd, ...) so that XP can still run without fetching a new MSVCRT. !! */ /* Also, sopen_s is not in all win32 compilers' io.h header */ fd = _sopen(filename, O_RDWR | O_CREAT | O_EXCL, _SH_DENYNO, _S_IREAD | _S_IWRITE); #else fd=mkstemp(filename); #endif if (fd==-1) { *error=1; cerr<<"unable to create temporary file \""<cmap0[k].r; palette[k].green=pls->cmap0[k].g; palette[k].blue=pls->cmap0[k].b; } png_set_PLTE(png_ptr, info_ptr, palette, np); } /* Write the file header information. REQUIRED */ png_write_info(png_ptr, info_ptr); /* The easiest way to write the image (you may have a different memory * layout, however, so choose what fits your needs best). You need to * use the first method if you aren't handling interlacing yourself. */ row_pointers=(png_bytepp)malloc(height*sizeof(png_bytep)); for (k = 0; k < height; ++k) { row_pointers[k] = (png_bytep)(image + k*width*nbpp*sizeof(png_byte)); } /* Write it */ png_write_image(png_ptr, row_pointers); /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); fflush(fp); /* just in case we core-dump before finishing... */ /* if you malloced the palette, free it here */ if (haspalette){ free(palette); } free(row_pointers); /* clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); /* rewind */ rewind(fp); /* count size. Note that string functions do not work since NULL is valid */ lout=0; while ((lin=(fread((void *)line, (size_t)1, (size_t)512, fp))) != 0) { lout+=lin; } /* compute in and out length */ /* allocate in */ lin=lout+1; in=(char*)calloc(lin,sizeof(char)); /* allocate out */ lout=((lout + 2) / 3 * 4) + 1; /* bufread, convert, back to char */ /* rewind */ rewind(fp); lin=fread((void *)in, (size_t)1, (size_t)lin, fp); tmpstr = encodesvg((unsigned char*)in, lin); free(in); /* close and destroy fp, return */ fclose(fp); unlink(filename); return tmpstr; } bool GDLSVGStream::PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong trueColorOrder, DLong channel) { c_plflush(); if (channel > 0) { cerr << "TV+SVG device: Value of CHANNEL (use TRUE instead) is out of allowed range. (FIXME!)" << endl; return false; } if (trueColorOrder > 1) { cerr << "TV+SVG device: True Color images must be [3,*,*] only. (FIXME!)" << endl; return false; } pls->bytecnt += fprintf(pls->OutFile,"diorot == 1.0 ) { // } else { // } if ( channel == 0 ) { if ( trueColorOrder == 0 ) { //indexed value 0->255: image ret = GDLSVGStream::svg_to_png64( nx, ny, idata, 8, 1 ,PNG_COLOR_TYPE_PALETTE, &error ); if ( error == 0 ) pls->bytecnt += fprintf( pls->OutFile, "%s", ret.c_str( ) ); } else { switch ( trueColorOrder ) { case 1: ret = GDLSVGStream::svg_to_png64( nx, ny, idata, 8, 3 ,PNG_COLOR_TYPE_RGB, &error ); if ( error == 0 ) pls->bytecnt += fprintf( pls->OutFile, "%s", ret.c_str( ) ); break; case 2: break; case 3: break; } } // } else { //channel = 1 to 3 } pls->bytecnt += fprintf(pls->OutFile,"\"/>\n"); return true; #undef BUFLEN } #else bool GDLSVGStream::PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong trueColorOrder, DLong channel) {return false;} #endif gdl-0.9.9/src/gdlsvgstream.hpp000066400000000000000000000035611340051421000162740ustar00rootroot00000000000000/* ************************************************************************* gdlsvgstream.hpp - graphic stream SVG ------------------- begin : December 26 2008 copyright : (C) 2008 by Sylwester Arabas email : slayoo@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLSVGSTREAM_HPP_ #define GDLSVGSTREAM_HPP_ #include "gdlgstream.hpp" #ifdef USE_PNGLIB // PNG_SKIP_SETJMP_CHECK seems to be a way to get round a png lib 'feature' see https://bugs.launchpad.net/ubuntu/+source/libpng/+bug/218409 #define PNG_SKIP_SETJMP_CHECK 1 #include "png.h" #endif class GDLSVGStream: public GDLGStream { bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan); #ifdef USE_PNGLIB std::string svg_to_png64(int height, int width, unsigned char *image, int bit_depth, int bpp, int whattype, int *error); #endif public: GDLSVGStream( int nx, int ny): GDLGStream( nx, ny, "svg") //cairo is nice but buffering prevents TV to work... // GDLGStream( nx, ny, checkPlplotDriver("svgcairo") ? "svgcairo" : "svg") { } ~GDLSVGStream() { } void eop() { } void Init(); }; #endif gdl-0.9.9/src/gdlwidget.cpp000066400000000000000000005012621340051421000155400ustar00rootroot00000000000000/*************************************************************************** gdlwidget.cpp - GDL widget system implementation ------------------- begin : Fri May 7 2004 copyright : (C) 2004 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifdef HAVE_LIBWXWIDGETS #include #include #include #include #include "basegdl.hpp" #include "dstructgdl.hpp" #include "dinterpreter.hpp" #include "gdlwxstream.hpp" #include "gdlwidget.hpp" #include "widget.hpp" #include "graphicsdevice.hpp" #define TIDY_WIDGET {this->SetSensitive(sensitive);\ if (!font.IsSameAs(wxNullFont)) {\ wxWindow* ww=static_cast(wxWidget); if (ww) ww->SetFont(font);\ }\ ConnectToDesiredEvents();\ } #define UPDATE_WINDOW {\ GDLWidgetBase *tlb = GetTopLevelBaseWidget( this->WidgetID( ) );\ GDLFrame *tlbFrame=static_cast (tlb->GetWxWidget( ));\ /* this->RefreshWidget();*/ \ if (tlb->IsStretchable()) {\ tlbFrame->Fit( );\ }\ } const WidgetIDT GDLWidget::NullID = 0; // instantiation WidgetListT GDLWidget::widgetList; GDLEventQueue GDLWidget::eventQueue; // the event queue GDLEventQueue GDLWidget::readlineEventQueue; // for process at command line level bool GDLWidget::wxIsOn=false; bool GDLWidget::handlersOk=false; void GDLEventQueue::Purge() { for ( SizeT i = 0; i < dq.size( ); ++i ) delete dq[i]; dq.clear( ); // isEmpty = true; } // removes all events for TLB 'topID' void GDLEventQueue::Purge( WidgetIDT topID) { for( long i=dq.size()-1; i>=0;--i) { DStructGDL* ev = dq[i]; static int topIx = ev->Desc( )->TagIndex( "TOP" ); assert( topIx == 1 ); DLong top = (*static_cast (ev->GetTag( topIx, 0 )))[0]; if( top == topID) { delete ev; dq.erase( dq.begin( ) + i ); } } // isEmpty = true; } inline long GDLWidget::textAlignment() { long myAlign = 0; if ( alignment & gdlwALIGN_TOP ) myAlign |= wxTE_LEFT; if ( alignment & gdlwALIGN_BOTTOM ) myAlign |= wxTE_LEFT; if ( alignment & gdlwALIGN_LEFT ) myAlign |= wxTE_LEFT; if ( alignment & gdlwALIGN_CENTER ) myAlign |= wxTE_CENTER; if ( alignment & gdlwALIGN_RIGHT ) myAlign |= wxTE_RIGHT; if (myAlign == 0) myAlign = wxTE_LEFT; //center is the default return myAlign; } inline long GDLWidget::buttonTextAlignment() { long myAlign = 0; if ( alignment & gdlwALIGN_TOP ) myAlign |= wxBU_TOP; if ( alignment & gdlwALIGN_BOTTOM ) myAlign |= wxBU_BOTTOM; if ( alignment & gdlwALIGN_LEFT ) myAlign |= wxBU_LEFT; if ( alignment & gdlwALIGN_CENTER ) myAlign |= wxBU_EXACTFIT; if ( alignment & gdlwALIGN_RIGHT ) myAlign |= wxBU_RIGHT; if (myAlign == 0) myAlign = wxBU_EXACTFIT; //center is the default return myAlign; } inline long GDLWidget::widgetAlignment() { GDLWidgetBase* base = static_cast(this->GetWidget(parentID)); if (base) { if (alignment == gdlwALIGN_NOT ) alignment=base->getChildrenAlignment(); } if (alignment == gdlwALIGN_NOT ) return wxEXPAND; long myAlign= 0; if ( alignment & gdlwALIGN_TOP ) myAlign |= wxALIGN_TOP; if ( alignment & gdlwALIGN_BOTTOM ) myAlign |= wxALIGN_BOTTOM; if ( alignment & gdlwALIGN_LEFT ) myAlign |= wxALIGN_LEFT; if ( alignment & gdlwALIGN_CENTER ) myAlign |= wxALIGN_CENTER; if ( alignment & gdlwALIGN_RIGHT ) myAlign |= wxALIGN_RIGHT; return myAlign; } inline wxSizer* GetBaseSizer( DLong col, DLong row, bool grid, long space) { wxSizer* sizer = NULL; if ( row <= 0 && col <= 0) {sizer = new wxGridBagSizer(space,space); } // else if ( row == 0 && col == 1) {sizer = new wxBoxSizer( wxVERTICAL ); if (space) sizer->AddSpacer(space);}//no no space is not OK with boxsizer! else if ( row == 0 && col >= 1) {sizer = (grid)?new wxGridSizer( 0, col, space, space ):new wxFlexGridSizer( 0, col, space, space );} // else if ( col == 0 && row == 1) {sizer = new wxBoxSizer( wxHORIZONTAL );if (space) sizer->AddSpacer(space);} else if ( col == 0 && row >= 1) {sizer = (grid)?new wxGridSizer( row, 0, space, space ):new wxFlexGridSizer( row, 0, space, space );} else sizer = new wxFlexGridSizer( row, col, space, space ); //which should not happen. return sizer; } inline wxSize GDLWidgetText::computeWidgetSize() { //widget text size is in LINES in Y and CHARACTERS in X. But overridden by scr_xsize et if present wxSize widgetSize = wxDefaultSize; //note: apparently GetPixelSize can return 0 at least under windows. Here this will only put widgetsize to 20 x 20. In other places; //it should be protected agains zero divides. wxSize fontSize = wxSystemSettings::GetFont( wxSYS_SYSTEM_FONT ).GetPixelSize(); if (!font.IsSameAs(wxNullFont)) fontSize = font.GetPixelSize(); if ( xSize > 0 ) { widgetSize.x = (xSize+0.5) * fontSize.x; if ( widgetSize.x < 20 ) widgetSize.x=20;} else { widgetSize.x = (maxlinelength+0.5) * fontSize.x; if ( widgetSize.x < 140 ) widgetSize.x=20* fontSize.x; } //TBC //but.. if (scrXSize > 0) widgetSize.x=scrXSize; if ( ySize > 0 ) widgetSize.y = (ySize * 1.5 * fontSize.y); else widgetSize.y = fontSize.y*1.5; //instead of nlines*fontSize.y to be compliant with *DL if (widgetSize.y < 20) widgetSize.y = 20; //but.. if (scrYSize > 0) widgetSize.y=scrYSize; return widgetSize; } inline wxSize GDLWidgetList::computeWidgetSize() { //widget text size is in LINES in Y and CHARACTERS in X. But overridden by scr_xsize et if present //note: apparently GetPixelSize can return 0 at least under windows. Here this will only put widgetsize to 20 x 20. In other places; //it should be protected agains zero divides. wxSize fontSize = wxSystemSettings::GetFont( wxSYS_SYSTEM_FONT ).GetPixelSize(); if (!font.IsSameAs(wxNullFont)) fontSize = font.GetPixelSize(); //wxSystemSettings::GetFont( wxSYS_SYSTEM_FONT ).GetPixelSize(); wxSize widgetSize = wxDefaultSize; if ( xSize > 0 ) {widgetSize.x = (xSize+0.5) * fontSize.x;if ( widgetSize.x < 20 ) widgetSize.x=20;} else { widgetSize.x = (maxlinelength+1.5) * fontSize.x; if ( widgetSize.x < 140 ) widgetSize.x=20* fontSize.x; } //but.. if (scrXSize > 0) widgetSize.x=scrXSize; if ( ySize > 0 ) widgetSize.y = (ySize * 1.5 * fontSize.y); else widgetSize.y = fontSize.y+1.5; //instead of nlines*fontSize.y to be compliant with *DL if (widgetSize.y < 20) widgetSize.y = 20; //but.. if (scrYSize > 0) widgetSize.y=scrYSize; return widgetSize; } inline wxSize GDLWidget::computeWidgetSize() { //here is a good place to make dynamic widgets static, since dynamic_resize is permitted only if size is not given. if (xSize > 0 || ySize > 0 || scrXSize > 0 || scrYSize > 0) dynamicResize=-1; wxSize widgetSize; if ( xSize > 0 ) widgetSize.x = xSize*unitConversionFactor.x; else widgetSize.x = wxDefaultSize.x; //but.. if (scrXSize > 0) widgetSize.x=scrXSize; if ( ySize > 0 ) widgetSize.y = ySize * unitConversionFactor.y; else widgetSize.y = wxDefaultSize.y; //but.. if (scrYSize > 0) widgetSize.y=scrYSize; return widgetSize; } // widget from ID GDLWidget* GDLWidget::GetWidget( WidgetIDT widID) { if ( widID == GDLWidget::NullID ) return NULL; WidgetListT::iterator it = widgetList.find( widID ); if ( it == widgetList.end( ) ) return NULL; return it->second; } // widget parent from ID GDLWidget* GDLWidget::GetParent( WidgetIDT widID) { GDLWidget *widget = GetWidget( widID ); if ( widget == NULL ) return NULL; WidgetIDT parentID = widget->parentID; GDLWidget *parent = GetWidget( parentID ); return parent; } void GDLWidget::widgetUpdate(bool update){ // GDLWidgetBase *tlb = GetTopLevelBaseWidget( this->WidgetID( ) ); // wxWindow * me = static_cast(tlb->GetWxWidget()); wxWindow * me = static_cast(wxWidget); if (me) {if (update) {if ( me->IsFrozen()) me->Thaw(); else me->Refresh(); } else me->Freeze();} else cerr<<"freezing unknown widget\n"; } // base widget ID from ID GDLWidgetBase* GDLWidget::GetBaseWidget( WidgetIDT widID) { WidgetIDT actID = widID; while ( 1 ) { GDLWidget* widget = GetWidget( actID ); if ( widget == NULL ) return NULL; if ( widget->IsBase( ) ) return static_cast (widget); assert( widget->parentID != GDLWidget::NullID ); actID = widget->parentID; } } WidgetIDT GDLWidget::GetBase( WidgetIDT widID) { GDLWidget *widget; WidgetIDT actID = widID; while ( 1 ) { GDLWidget* widget = GetWidget( actID ); if ( widget == NULL ) return GDLWidget::NullID; if ( widget->IsBase( ) ) return actID; assert( widget->parentID != GDLWidget::NullID ); actID = widget->parentID; } } GDLWidgetBase* GDLWidget::GetTopLevelBaseWidget( WidgetIDT widID) { WidgetIDT actID = widID; while ( 1 ) { GDLWidget *widget = GetWidget( actID ); if ( widget == NULL ) return (GDLWidgetBase*)GDLWidget::NullID; if ( widget->parentID == GDLWidget::NullID ) return static_cast (widget); else actID = widget->parentID; } } WidgetIDT GDLWidget::GetTopLevelBase( WidgetIDT widID) { WidgetIDT actID = widID; while ( 1 ) { GDLWidget *widget = GetWidget( actID ); if ( widget == NULL ) return GDLWidget::NullID; if ( widget->parentID == GDLWidget::NullID ) return actID; else actID = widget->parentID; } } void GDLWidget::RefreshWidget( ) { if ( widgetPanel->IsShownOnScreen( ) ) { if ( this->parentID == GDLWidget::NullID ) return; GDLWidget* gdlParent = GetWidget( parentID ); while ( gdlParent->IsBase() ) { wxSizer * s = gdlParent->GetSizer( ); if ( s ) s->Layout( ); if ( gdlParent->parentID == GDLWidget::NullID ) break; gdlParent = GetWidget( gdlParent->GetParentID( ) ); } static_cast(this->GetWxWidget())->Refresh(); //next event loop // wxWindow* me=static_cast(this->GetWxWidget()); if (me) me->Update(); else cerr<<"Refresh unknown widget!\n"; //immediate } } int GDLWidget::HandleEvents() { //make one loop for wxWidgets Events... if (wxIsStarted() && wxTheApp) { wxTheApp->OnRun(); //wxTheApp may not be started //treat our GDL events... DStructGDL* ev = NULL; while( (ev = GDLWidget::readlineEventQueue.Pop()) != NULL) { static int idIx = ev->Desc( )->TagIndex( "ID" ); // 0 static int topIx = ev->Desc( )->TagIndex( "TOP" ); // 1 static int handlerIx = ev->Desc( )->TagIndex( "HANDLER" ); // 2 assert( idIx == 0 ); assert( topIx == 1 ); assert( handlerIx == 2 ); WidgetIDT id = (*static_cast (ev->GetTag( idIx, 0 )))[0]; ev = CallEventHandler( ev ); if( ev != NULL) { Warning( "Unhandled event. ID: " + i2s( id ) ); GDLDelete( ev ); ev = NULL; return 0; } } if (wxIsBusy()) wxEndBusyCursor( ); } return 0; } void GDLWidget::PushEvent( WidgetIDT baseWidgetID, DStructGDL* ev) { // Get XmanagerActiveCommand status GDLWidget *baseWidget = GDLWidget::GetWidget( baseWidgetID ); if ( baseWidget != NULL ) { bool xmanActCom = baseWidget->GetXmanagerActiveCommand( ); if ( !xmanActCom ) { //Not blocking: events in eventQueue. // wxMessageOutputStderr().Printf(_T("eventQueue.Push: %d\n"),baseWidgetID); eventQueue.Push( ev ); } else { //Blocking: events in readlineeventQueue. // wxMessageOutputStderr().Printf(_T("readLineEventQueue.Push: %d\n"),baseWidgetID); readlineEventQueue.Push( ev ); } } else cerr << "NULL baseWidget (possibly Destroyed?) found in GDLWidget::PushEvent( WidgetIDT baseWidgetID=" << baseWidgetID << ", DStructGDL* ev=" << ev << "), please report!\n"; } bool GDLWidget::GetXmanagerBlock() { bool xmanBlock = false; WidgetListT::iterator it; // (*it).first is widgetID // (*it).second is pointer to widget bool managed; bool xmanActCom; #ifdef GDL_DEBUG_WIDGETS std::cout << "+ GetXmanagerBlock: widgetList:" << std::endl; for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) { std::cout << (*it).first << ": " << (*it).second->widgetID << " parentID: " << (*it).second->parentID << " uname: " << (*it).second->uName << std::endl; } std::cout << "- GetXmanagerBlock: widgetList end" << std::endl; #endif for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) { // Only consider base widgets if ( (*it).second->parentID == GDLWidget::NullID ) { managed = (*it).second->GetManaged( ); xmanActCom = (*it).second->GetXmanagerActiveCommand( ); } if ( managed && !xmanActCom ) { xmanBlock = true; break; } } return xmanBlock; } DLong GDLWidget::GetNumberOfWidgets() { WidgetListT::iterator it; DLong result=0; for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) result++; return result; } BaseGDL* GDLWidget::GetWidgetsList() { DLong nw=GetNumberOfWidgets(); if (nw<=0) return new DLongGDL(0); WidgetListT::iterator it; SizeT index=0; DLongGDL* result=new DLongGDL(nw,BaseGDL::NOZERO); for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) { (*result)[index]=(*it).second->widgetID; index++; } return result; } BaseGDL* GDLWidget::GetManagedWidgetsList() { DLong nw=GetNumberOfWidgets(); if (nw<=0) return new DLongGDL(0); WidgetListT::iterator it; SizeT index; for (index=0, it = widgetList.begin( ); it != widgetList.end( ); ++it ) { if ((*it).second->GetManaged() == true) index++; } if (index<=0) return new DLongGDL(0); DLongGDL* result=new DLongGDL(index,BaseGDL::NOZERO); for (index=0, it = widgetList.begin( ); it != widgetList.end( ); ++it ) { if ((*it).second->GetManaged() == true) (*result)[index++]=(*it).second->widgetID; } return result; } // UnInit void GDLWidget::UnInit() { if (wxIsStarted()) { WidgetListT::iterator it; for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) { GDLWidget* w=(*it).second; if ( w != NULL) delete w; } GDLWidget::HandleEvents(); // the following cannot be done: once unitialized, the wxWidgets library cannot be safely initilized again. // wxUninitialize( ); UnsetWxStarted();//reset handlersOk too. } } void GDLWidget::ConnectToDesiredEvents(){ if ( eventFlags & GDLWidget::EV_TRACKING ) { static_cast(wxWidget)->Connect(widgetID,wxEVT_ENTER_WINDOW, wxMouseEventHandler(GDLFrame::OnEnterWindow)); static_cast(wxWidget)->Connect(widgetID,wxEVT_LEAVE_WINDOW, wxMouseEventHandler(GDLFrame::OnLeaveWindow)); } if ( eventFlags & GDLWidget::EV_CONTEXT ) static_cast(wxWidget)->Connect(widgetID,wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(GDLFrame::OnContextEvent)); if ( eventFlags & GDLWidget::EV_KBRD_FOCUS ) { static_cast(wxWidget)->Connect(widgetID,wxEVT_SET_FOCUS, wxFocusEventHandler(GDLFrame::OnKBRDFocusChange)); static_cast(wxWidget)->Connect(widgetID,wxEVT_KILL_FOCUS, wxFocusEventHandler(GDLFrame::OnKBRDFocusChange)); } } //initialize static member int GDLWidget::gdl_lastControlId=0; GDLWidget::GDLWidget( WidgetIDT p, EnvT* e, BaseGDL* vV, DULong eventFlags_) : wxWidget( NULL ) , widgetID (0) , parentID( p ) , uValue( NULL ) , vValue( vV ) , scrolled(FALSE) , sensitive(TRUE) , managed( false ) , eventFlags( eventFlags_ ) , buttonState(FALSE) , exclusiveMode( 0 ) , xOffset(-1), yOffset(-1), xSize(-1), ySize(-1), scrXSize(-1), scrYSize(-1) , topWidgetSizer( NULL ) , widgetSizer( NULL ) , widgetPanel( NULL ) , scrollSizer( NULL ) , scrollPanel( NULL ) , frameSizer( NULL ) , framePanel( NULL ) , widgetType(GDLWidget::WIDGET_UNKNOWN) , widgetName("") , groupLeader(GDLWidget::NullID) , unitConversionFactor(wxRealPoint(1.0,1.0)) //no conversion at start. , frameWidth(-1) , font(wxNullFont) , valid(TRUE) , alignment(gdlwALIGN_NOT) , widgetStyle(wxSTRETCH_NOT) , dynamicResize(-1) //not permitted { if ( e != NULL ) GetCommonKeywords( e ); else DefaultValuesInAbsenceofEnv(); // was widgetID = wxWindow::NewControlId( ); // but some scripts use the fact that widget ids are positive (graffer.pro) widgetID = GDLNewControlId( ); if ( parentID != GDLWidget::NullID ) { GDLWidget* gdlParent = GetWidget( parentID ); assert( gdlParent != NULL); if ( gdlParent->IsBase( ) ) { GDLWidgetBase* base = static_cast (gdlParent); base->AddChild( widgetID ); // if (alignment == -1) alignment=base->getChildrenAlignment(); } else if ( gdlParent->IsTab( ) ) { GDLWidgetTab* base = static_cast (gdlParent); base->AddChild( widgetID ); } else { GDLWidget* w = GetBaseWidget( parentID ); if (w && w->IsBase()) static_cast(w)->AddChild( widgetID ); if (w && w->IsTab()) static_cast(w)->AddChild( widgetID ); } } widgetList.insert( widgetList.end( ), std::pair(widgetID, this) ); #ifdef GDL_DEBUG_WIDGETS wxMessageOutputStderr( ).Printf( _T( "inserted: ID: %d parentID: %d\n" ), widgetID, parentID ); #endif if (groupLeader != 0) { GDLWidget* leader=this->GetWidget(groupLeader); if (leader) leader->AddToFollowers(widgetID); } } void GDLWidget::SetSensitive(bool value) { wxWindow *me=static_cast(this->GetWxWidget()); if (me!=NULL) { if (value) me->Enable(); else me->Disable(); } else { if (this->IsButton()) static_cast(this)->SetSensitive(value); else cerr<<"Making (Un)Sensitive unknown widget!\n"; } } void GDLWidget::SetFocus() //gives focus to the CHILD of the panel. { // if (this->GetWidgetName()=="DRAW") static_cast(this->wxWidget)->SetFocus(); // else if (this->GetWidgetName()=="TABLE") static_cast(this->wxWidget)->SetFocus(); // else static_cast (this->widgetPanel)->SetFocus(); wxWindow *me=static_cast(this->GetWxWidget()); if (me!=NULL) me->SetFocus(); else cerr<<"Setting Focus for unknown widget!\n"; } void GDLWidget::SetSizeHints() { assert( parentID == NullID ); #ifdef GDL_DEBUG_WIDGETS wxMessageOutputStderr( ).Printf( _T( "GDLWidget:SetSizeHints: %d\n" ), this->widgetID ); #endif GDLFrame *frame = static_cast (this->wxWidget); if (frame) topWidgetSizer->SetSizeHints( frame ); else cerr<<"Setting size hints for unknown widget!\n"; } void GDLWidget::SetSize(DLong sizex, DLong sizey) //in pixels. Always. { //Sizes are in pixels. Units must be converted before calling this function. wxWindow* me=static_cast(this->GetWxWidget()); wxSize currentSize; if (me) currentSize=me->GetClientSize(); else {cerr<<"Setting size of unknown widget!\n"; return;} if (currentSize==wxSize(sizex,sizey)) return; //note particular case of 0 for base widgets: 0 means stretch otherwise not. if (this->IsBase()) { static_cast(this)->SetStretchX((sizex<=0)); static_cast(this)->SetStretchY((sizey<=0)); } //is this needed? xSize=(sizex<=0)?currentSize.x:sizex; ySize=(sizey<=0)?currentSize.y:sizey; GDLWidgetBase *tlb = GetTopLevelBaseWidget( this->WidgetID( ) ); GDLFrame *tlbFrame=static_cast(tlb->GetWxWidget( )); //we should prevent resize event if ( (tlb->GetEventFlags() & GDLWidget::EV_SIZE) == GDLWidget::EV_SIZE ) tlbFrame->Disconnect(tlb->WidgetID(), wxEVT_SIZE, gdlSIZE_EVENT_HANDLER); //(GDLFrame::OnSizeWithTimer)); me->SetClientSize(xSize,ySize); widgetSizer->SetItemMinSize(me,xSize,ySize); this->RefreshWidget(); if (tlb->IsStretchable()) { tlbFrame->SetMinSize(wxDefaultSize); tlbFrame->Fit( ); //makes a mess in atv.pro while resizing. TB checked. } if ((tlb->GetEventFlags() & GDLWidget::EV_SIZE) == GDLWidget::EV_SIZE) tlbFrame->Connect(tlb->WidgetID(), wxEVT_SIZE, gdlSIZE_EVENT_HANDLER);//wxSizeEventHandler(GDLFrame::OnSizeWithTimer)); } void GDLWidget::SendWidgetTimerEvent(DDouble secs) { if( parentID == NullID) { assert( this->IsBase( ) ); GDLFrame *frame = static_cast (this->wxWidget); frame->SendWidgetTimerEvent(secs,widgetID); } else { GDLWidgetBase* tlb = GetTopLevelBaseWidget( parentID ); assert( tlb != NULL ); GDLFrame *frame = static_cast (tlb->wxWidget); frame->SendWidgetTimerEvent(secs,widgetID); } } void GDLWidget::Realize( bool map) { if( parentID == NullID) { assert( this->IsBase( ) ); #ifdef GDL_DEBUG_WIDGETS wxMessageOutputStderr( ).Printf( _T( "GDLWidget:Realize: %d\n"), this->widgetID ); #endif GDLFrame *frame = static_cast (this->wxWidget); GDLApp* theGDLApp = new GDLApp; theGDLApp->OnInit(); // add an idle event seems necessary for Linux (wxGTK2) and does not harm Windows either wxIdleEvent idlevent; theGDLApp->AddPendingEvent(idlevent); theGDLApp->OnRun(); frame->SetTheApp(theGDLApp); if( frame->IsMapped() != map) { this->OnRealize( ); if (map) frame->SendShowRequestEvent(); else frame->SendHideRequestEvent(); } } else { #ifdef GDL_DEBUG_WIDGETS wxMessageOutputStderr( ).Printf( _T( "GDLWidget:Realize TLB of: %d\n"), this->widgetID ); #endif GDLWidgetBase* tlb = GetTopLevelBaseWidget( parentID ); assert( tlb != NULL ); GDLFrame *frame = static_cast (tlb->wxWidget); if( frame->IsMapped() != map) { this->OnRealize( ); if (map) frame->SendShowRequestEvent(); else frame->SendHideRequestEvent(); } } } bool GDLWidget::GetRealized() { GDLWidgetBase *tlb = GetTopLevelBaseWidget( widgetID ); assert( tlb != NULL ); GDLFrame* frame=static_cast(tlb->GetWxWidget()); return (frame->GetTheApp()!=NULL); } #define GetSysC(x) { col=wxSystemSettings::GetColour(x); r=col.Red();g=col.Green();b=col.Blue(); (*val)[0]=r;(*val)[1]=g;(*val)[2]=b; } BaseGDL * GDLWidget::getSystemColours() { DStructGDL* colo = new DStructGDL( "WIDGET_SYSTEM_COLORS"); DIntGDL* val=new DIntGDL( dimension(3), BaseGDL::NOZERO); int r,g,b; wxColour col; GetSysC(wxSYS_COLOUR_3DDKSHADOW ); colo->InitTag("DARK_SHADOW_3D",(*val)); colo->InitTag("SHADOW_3D", (*val)); GetSysC(wxSYS_COLOUR_3DLIGHT ); colo->InitTag("FACE_3D", (*val)); colo->InitTag("LIGHT_EDGE_3D", (*val)); colo->InitTag("LIGHT_3D", (*val)); GetSysC(wxSYS_COLOUR_ACTIVEBORDER ); colo->InitTag("ACTIVE_BORDER", (*val)); GetSysC(wxSYS_COLOUR_ACTIVECAPTION ); colo->InitTag("ACTIVE_CAPTION", (*val)); GetSysC(wxSYS_COLOUR_APPWORKSPACE ); colo->InitTag("APP_WORKSPACE", (*val)); GetSysC(wxSYS_COLOUR_DESKTOP ); colo->InitTag("DESKTOP", (*val)); GetSysC(wxSYS_COLOUR_BTNTEXT ); colo->InitTag("BUTTON_TEXT", (*val)); GetSysC(wxSYS_COLOUR_CAPTIONTEXT ); colo->InitTag("CAPTION_TEXT", (*val)); GetSysC(wxSYS_COLOUR_GRAYTEXT ); colo->InitTag("GRAY_TEXT", (*val)); GetSysC(wxSYS_COLOUR_HIGHLIGHT ); colo->InitTag("HIGHLIGHT", (*val)); GetSysC(wxSYS_COLOUR_HIGHLIGHTTEXT ); colo->InitTag("HIGHLIGHT_TEXT", (*val)); GetSysC(wxSYS_COLOUR_INACTIVEBORDER ); colo->InitTag("INACTIVE_BORDER", (*val)); GetSysC(wxSYS_COLOUR_INACTIVECAPTION ); colo->InitTag("INACTIVE_CAPTION", (*val)); GetSysC(wxSYS_COLOUR_INACTIVECAPTIONTEXT ); colo->InitTag("INACTIVE_CAPTION_TEXT", (*val)); GetSysC(wxSYS_COLOUR_INFOBK ); colo->InitTag("TOOLTIP_BK", (*val)); GetSysC(wxSYS_COLOUR_INFOTEXT ); colo->InitTag("TOOLTIP_TEXT", (*val)); GetSysC(wxSYS_COLOUR_MENU ); colo->InitTag("MENU", (*val)); GetSysC(wxSYS_COLOUR_MENUTEXT ); colo->InitTag("MENU_TEXT", (*val)); GetSysC(wxSYS_COLOUR_SCROLLBAR ); colo->InitTag("SCROLLBAR", (*val)); GetSysC(wxSYS_COLOUR_WINDOW ); colo->InitTag("WINDOW_BK", (*val)); GetSysC(wxSYS_COLOUR_WINDOWFRAME ); colo->InitTag("WINDOW_FRAME", (*val)); GetSysC(wxSYS_COLOUR_WINDOWTEXT ); colo->InitTag("WINDOW_TEXT", (*val)); return colo; } GDLWidget::~GDLWidget( ) { //TBD DESTROY CLEANLY EVERYTHING!!! #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidget(): " << widgetID << std::endl; #endif assert( this->IsValid( ) ); //for debug if (!this->IsValid()) return; //to avoid crashing if asserts are not honored //unvalidate widget to prevent some further actions this->SetUnValid( ); // call KILL_NOTIFY procedures this->OnKill( ); // kill followers (here?) // delete all children (in reverse order ?) while (followers.size()) { GDLWidget* follower = GetWidget(followers[followers.size() - 1]); if (follower) delete follower; else followers.pop_back(); // Maybe should not be reachable } // managed = false; DInt type = this->GetWidgetType( ); bool badtype = (type == GDLWidget::WIDGET_BASE || type == GDLWidget::WIDGET_MBAR || type == GDLWidget::WIDGET_TAB); if ( scrollSizer != NULL ) { if ( badtype ) { #ifdef GDL_DEBUG_WIDGETS cerr << "Warning, found and ignored a Scrolled Container." << endl; #endif } else this->UnScrollWidget( ); } if ( frameSizer != NULL ) { if ( badtype ) { #ifdef GDL_DEBUG_WIDGETS cerr << "Warning, found and ignored a Framed Container." << endl; #endif } else this->UnFrameWidget( ); } //destroy, unless... if ( widgetType == GDLWidget::WIDGET_MBAR ) { //widget is a MBAR ---> do nothing? deleted with TLB #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidget(): not destroying WIDGET_MBAR container" << widgetName << ": " << widgetID << endl; #endif } else if ( widgetType == GDLWidget::WIDGET_TREE ) { //deleted elsewhere. #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidget(): not destroying WIDGET_TREE container" << widgetName << ": " << widgetID << endl; #endif } else if ( parentID != GDLWidget::NullID ) { //not the TLB //parent is a panel or a tab or a buttonmenu GDLWidget* gdlParent = GetWidget( parentID ); assert( gdlParent != NULL ); if ( gdlParent->IsContainer( ) ) { #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidget(): destroy container-parent " << widgetName << ": " << widgetID << endl; #endif GDLWidgetContainer* container = static_cast (gdlParent); if(container) container->RemoveChild( widgetID ); wxWindow *me = static_cast (this->GetWxWidget( )); if ( me ) { if ( gdlParent->IsTab( ) ) me->Hide( ); else me->Destroy( ); } //do not delete the page, it will be removed by the notebook deletion!!! } else if ( gdlParent->IsButton( ) ) { #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidget(): destroy button-container-parent " << widgetName << ": " << widgetID << endl; #endif GDLWidgetButton* container = static_cast (gdlParent); if(container) container->RemoveChild( widgetID ); wxWindow *me = static_cast (this->GetWxWidget( )); if ( me ) { me->Destroy( ); } } else { #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidget(): destroy " << widgetName << ": " << widgetID << endl; #endif wxWindow *me = static_cast (this->GetWxWidget( )); if ( me ) me->Destroy( ); #ifdef GDL_DEBUG_WIDGETS else cerr<<"Found unknown widget "<IsBase( ) ); win = static_cast (this->wxWidget); } else { GDLWidgetBase* tlb = GetTopLevelBaseWidget( parentID ); assert( tlb != NULL ); win = static_cast (tlb->wxWidget); } if (win!=NULL) win->Raise(); } void GDLWidget::Lower() { wxWindow * win; if( parentID == NullID) { assert( this->IsBase( ) ); win = static_cast (this->wxWidget); } else { GDLWidgetBase* tlb = GetTopLevelBaseWidget( parentID ); assert( tlb != NULL ); win = static_cast (tlb->wxWidget); } if (win!=NULL) win->Lower(); } DStructGDL* GDLWidget::GetGeometry( wxRealPoint fact ) { int ixs=0, iys=0, ixscr=0, iyscr=0; float xs, ys, xscr, yscr, xoff, yoff, margin=0; wxPoint position; wxWindow* test = static_cast (wxWidget); if ( test != NULL ) { test->GetClientSize( &ixs, &iys ); ixscr=ixs; iyscr=iys; position = test->GetPosition( ); } if (frameSizer != NULL) {framePanel->GetSize(&ixscr,&iyscr); margin = gdlFRAME_MARGIN / fact.x;} if (scrollSizer != NULL) {scrollPanel->GetSize(&ixscr,&iyscr);ixs=ixscr-gdlSCROLL_WIDTH;iys=iyscr-gdlSCROLL_WIDTH;} //size is in pixels, pass in requested units (1.0 default) xs = ixs / fact.x; ys = iys / fact.y; xscr = ixscr / fact.x; yscr = iyscr / fact.y; xoff = position.x / fact.x; yoff = position.y / fact.y; DStructGDL* ex = new DStructGDL( "WIDGET_GEOMETRY" ); ex->InitTag( "XOFFSET", DFloatGDL( xoff) ); ex->InitTag( "YOFFSET", DFloatGDL( yoff ) ); ex->InitTag( "XSIZE", DFloatGDL( xs ) ); ex->InitTag( "YSIZE", DFloatGDL( ys ) ); ex->InitTag( "SCR_XSIZE", DFloatGDL( xscr ) ); ex->InitTag( "SCR_YSIZE", DFloatGDL( yscr ) ); ex->InitTag( "MARGIN", DFloatGDL( margin ) ); return ex; } GDLWidgetContainer::GDLWidgetContainer( WidgetIDT parentID, EnvT* e, ULong eventFlags_, bool map) : GDLWidget( parentID, e, NULL, eventFlags_) , map(map) { } GDLWidgetGraphicWindowBase::GDLWidgetGraphicWindowBase(WidgetIDT mbarID, int xoff, int yoff, DString title) : GDLWidgetBase(GDLWidget::NullID, NULL, (ULong) GDLWidget::EV_NONE, false, /*ref*/ mbarID, false, 1, 0, BGNORMAL, true, "", "", title, "", 0, 0, -1, -1, false, 0, 0, false, true), child(NULL) { GDLFrame* f=static_cast(wxWidget); f->SetPosition(wxPoint(xoff,yoff)); f->Connect(f->GetId(), wxEVT_SIZE, gdlSIZE_EVENT_HANDLER); } /*********************************************************/ // for WIDGET_BASE /*********************************************************/ GDLWidgetBase::GDLWidgetBase( WidgetIDT parentID, EnvT* e, ULong eventFlags_, bool mapWid, WidgetIDT& mBarIDInOut, bool modal_, DLong col, DLong row, int exclusiveMode_, bool floating_, const DString& resource_name, const DString& rname_mbar, const DString& title_, const DString& display_name, DLong xpad_, DLong ypad_, DLong x_scroll_size, DLong y_scroll_size, bool grid, long children_alignment, long space_, bool iscontextmenu, bool isagraphicwindow) : GDLWidgetContainer( parentID, e, eventFlags_, mapWid) , modal( modal_ ) , mbarID( mBarIDInOut ) , lastRadioSelection( NullID ) , nrows(row) , ncols(col) , stretchX(FALSE) , stretchY(FALSE) , childrenAlignment( children_alignment ) , space(space_) , xpad(xpad_) , ypad(ypad_) , IsContextMenu(iscontextmenu) { //Cannot find how to implement the notion of xpad and ypad in the sizer of the child widgets (GetBaseSizer). //Impossible to have different x and y borders for the panel itself, hence the following: int panelBorderFlag; int pad; if (xpad<1 && ypad<1) {panelBorderFlag=0;pad=0;} else if (xpad>0 && ypad>0) {panelBorderFlag=wxALL;pad=max(xpad,ypad);xpad=pad;ypad=pad;} else if (xpad>0 ) {panelBorderFlag=(wxLEFT|wxRIGHT);pad=xpad;} else{panelBorderFlag=(wxTOP|wxBOTTOM);pad=ypad;} // All bases can receive events: EV_CONTEXT, EV_KBRD_FOCUS, EV_TRACKING xmanActCom = false; //get immediately rid of scroll sizes in case of scroll or not... Here is the logic: if (x_scroll_size > 0) {scrolled=TRUE;x_scroll_size*=unitConversionFactor.x; x_scroll_size+=(gdlSCROLL_WIDTH);} if (y_scroll_size > 0) {scrolled=TRUE;y_scroll_size*=unitConversionFactor.y; y_scroll_size+=(gdlSCROLL_WIDTH);} if ( xSize <= 0 ) {stretchX=TRUE; xSize=-1;} else xSize*=unitConversionFactor.x; if ( ySize <= 0 ) {stretchY=TRUE; ySize=-1;} else ySize*=unitConversionFactor.y; // Set exclusiveMode // If exclusive then set to -1 to signal first radiobutton if ( exclusiveMode_ == BGEXCLUSIVE ) this->SetExclusiveMode( BGEXCLUSIVE1ST ); else this->SetExclusiveMode( exclusiveMode_ ); // If first base widget = Top Level Base Widget: // can receive special events: tlb_size, tlb_move, tlb_icon and tlb_kill. if ( parentID == GDLWidget::NullID ) { wxString titleWxString = wxString( title_.c_str( ), wxConvUTF8 ); GDLFrame *gdlFrame; if (xOffset>-1&&yOffset>-1) { gdlFrame = new GDLFrame( this, widgetID, titleWxString , isagraphicwindow, wxPoint(xOffset,yOffset)); } else { gdlFrame = new GDLFrame( this, widgetID, titleWxString, isagraphicwindow); } //it is the FRAME that manage all events. Here we dedicate particularly the tlb_* events: // note that we have the choice for Size Event Handler for Frames, but need to change also is widgets.cpp if (eventFlags & GDLWidget::EV_SIZE ) gdlFrame->Connect(widgetID, wxEVT_SIZE, gdlSIZE_EVENT_HANDLER); if (eventFlags & GDLWidget::EV_MOVE ) gdlFrame->Connect(widgetID, wxEVT_MOVE, wxMoveEventHandler(GDLFrame::OnMove)); if (eventFlags & GDLWidget::EV_ICONIFY ) gdlFrame->Connect(widgetID, wxEVT_ICONIZE, wxIconizeEventHandler(GDLFrame::OnIconize)); if (eventFlags & GDLWidget::EV_KILL ) { gdlFrame->Connect(widgetID, wxEVT_CLOSE_WINDOW, wxCloseEventHandler(GDLFrame::OnCloseFrame)); } else gdlFrame->Connect(widgetID, wxEVT_CLOSE_WINDOW, wxCloseEventHandler(GDLFrame::OnUnhandledCloseFrame)); #ifdef GDL_DEBUG_WIDGETS gdlFrame->SetBackgroundColour(wxColour(255,0,255)); //violet #endif wxWidget = gdlFrame; if( mbarID != 0) { GDLWidgetMBar* mBar = new GDLWidgetMBar( widgetID, e ); mbarID = mBar->WidgetID( ); mBarIDInOut = mbarID; wxMenuBar* me=static_cast (mBar->GetWxWidget( )); if (me) gdlFrame->SetMenuBar( me ); else cerr<<"Warning: GDLWidgetBase::GDLWidgetBase: Non-existent menubar widget!\n"; } topWidgetSizer = new wxBoxSizer( wxVERTICAL); gdlFrame->SetSizer( topWidgetSizer ); //create the first panel, fix size. Offset is not taken into account. widgetPanel = new wxPanel( gdlFrame, wxID_ANY , wxDefaultPosition, wxDefaultSize);// no FRAME here! , (frameWidth>0)?wxBORDER_SUNKEN:wxBORDER_NONE); //note: wxWidget should probably be widgetPanel, not gdlFrame. #ifdef GDL_DEBUG_WIDGETS widgetPanel->SetBackgroundColour(wxColour(255,0,0)); //rouge #endif //give size hints for this panel. if (!stretchX && !stretchY) widgetPanel->SetSizeHints(xSize, ySize); else if (!stretchX) widgetPanel->SetSizeHints(xSize, -1); else if (!stretchY) widgetPanel->SetSizeHints(-1, ySize); //force frame to wrap around panel topWidgetSizer->Add(widgetPanel, 1, widgetAlignment()|panelBorderFlag|wxALL,(frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); //I cannot succeed to have a correct size if the //base sizer is gridbag and no sizes are given. Thus in the case xsize=ysize=undefined and col=0, //I force col=1. if (stretchX && stretchY && ncols==0 && nrows==0) ncols=1; //Allocate the sizer for children according to col or row layout widgetSizer = GetBaseSizer( ncols, nrows, grid , space); //Attach sizer to panel widgetPanel->SetSizer( widgetSizer ); if (scrolled) { scrollPanel = new wxScrolledWindow(gdlFrame, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN); #ifdef GDL_DEBUG_WIDGETS scrollPanel->SetBackgroundColour(wxColour(0,255,255)); //bleu clair #endif scrollSizer = new wxBoxSizer(wxVERTICAL ); scrollPanel->SetSizer( scrollSizer ); scrollPanel->SetSizeHints((x_scroll_size>0)?x_scroll_size:gdlDEFAULT_SCROLL_SIZE,(y_scroll_size>0)?y_scroll_size:gdlDEFAULT_SCROLL_SIZE); topWidgetSizer->Detach(widgetPanel); widgetPanel->Reparent(scrollPanel); scrollSizer->Add(widgetPanel); topWidgetSizer->Add(scrollPanel, 0, wxEXPAND|widgetAlignment()|panelBorderFlag,(frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); scrollPanel->SetScrollRate(gdlSCROLL_RATE,gdlSCROLL_RATE); //show scrollbars } TIDY_WIDGET; UPDATE_WINDOW; } else if ( IsContextMenu ) //Note: THIS IS WRONG. We should only add a contextMenu using the 'PopupMenu' member function of a wxWindow. // Current implementation as poputptransientwindow makes very different results, in IDL the widgets of a context_menu are only of the "menu" type. { GDLWidget* gdlParent = GetWidget( parentID ); assert( gdlParent != NULL); wxWindow* parentWindow=static_cast(gdlParent->GetWxWidget()); assert( parentWindow != NULL); wxPopupTransientWindow* transient = new wxPopupTransientWindow(parentWindow ); wxWidget = transient; topWidgetSizer = new wxBoxSizer( wxVERTICAL); transient->SetSizer( topWidgetSizer); widgetPanel = new wxPanel( transient, widgetID , wxDefaultPosition, wxDefaultSize); // no frame also! , (frameWidth>0)?wxBORDER_SUNKEN:wxBORDER_NONE); #ifdef GDL_DEBUG_WIDGETS widgetPanel->SetBackgroundColour(wxColour(255,0,0)); //rouge #endif //give size hints for this panel. if (!stretchX && !stretchY) widgetPanel->SetSizeHints(xSize, ySize); else if (!stretchX) widgetPanel->SetSizeHints(xSize, -1); else if (!stretchY) widgetPanel->SetSizeHints(-1, ySize); //force frame to wrap around panel topWidgetSizer->Add( widgetPanel, 1, wxEXPAND|wxALL, (frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); //I cannot succeed to have a correct size if the //base sizer is gridbag and no sizes are given. Thus in the case xsize=ysize=undefined and col=0, //I force col=1. if (stretchX && stretchY && ncols==0 && nrows==0) ncols=1; //Allocate the sizer for children according to col or row layout widgetSizer = GetBaseSizer( ncols, nrows, grid , space); //Attach sizer to panel widgetPanel->SetSizer( widgetSizer ); //transients are not like that in IDL. They are much simpler. Anyway, for the moment, let it be like that if (scrolled) { scrollPanel = new wxScrolledWindow(transient, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN); #ifdef GDL_DEBUG_WIDGETS scrollPanel->SetBackgroundColour(wxColour(0,255,255)); //bleu clair #endif scrollSizer = new wxBoxSizer(wxVERTICAL ); scrollPanel->SetSizer( scrollSizer ); scrollPanel->SetSizeHints((x_scroll_size>0)?x_scroll_size:gdlDEFAULT_SCROLL_SIZE,(y_scroll_size>0)?y_scroll_size:gdlDEFAULT_SCROLL_SIZE); topWidgetSizer->Detach(widgetPanel); widgetPanel->Reparent(scrollPanel); scrollSizer->Add(widgetPanel); topWidgetSizer->Add(scrollPanel, 0, wxEXPAND|wxALL,(frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); scrollPanel->SetScrollRate(gdlSCROLL_RATE, gdlSCROLL_RATE); //show scrollbars } TIDY_WIDGET; UPDATE_WINDOW; } else { // If parent base widget exists .... GDLWidget* gdlParent = GetWidget( parentID ); assert( gdlParent != NULL); wxSizer* parentSizer = gdlParent->GetSizer( ); if( gdlParent->IsTab()) { GDLWidgetTab* parentTab = static_cast (gdlParent); assert( parentTab != NULL); wxNotebook* wxParent = static_cast (parentTab->GetWxWidget( )); assert( wxParent != NULL); //create the panel, fix size. Offset is not taken into account unless we create an intermediate container panel. widgetPanel = new wxPanel( wxParent, widgetID , wxPoint(xOffset,yOffset), wxDefaultSize, (frameWidth>0)?wxBORDER_SUNKEN:wxBORDER_NONE); #ifdef GDL_DEBUG_WIDGETS widgetPanel->SetBackgroundColour(wxColour(64,128,33)); //for tests! #endif wxWidget = widgetPanel; //give size hints for this panel. if (!stretchX && !stretchY) widgetPanel->SetSizeHints(xSize, ySize); else if (!stretchX) widgetPanel->SetSizeHints(xSize, -1); else if (!stretchY) widgetPanel->SetSizeHints(-1, ySize); //if no cols or rows are given, MUST at least fix one IF wxWidgets 3 if (ncols==0 && nrows==0) ncols=1; //Allocate the sizer for children according to col or row layout widgetSizer = GetBaseSizer( ncols, nrows, grid, space ); //Attach sizer to panel widgetPanel->SetSizer( widgetSizer ); wxString titleWxString = wxString( title_.c_str( ), wxConvUTF8 ); //TAB-PARENT WIDGET CANNOT BE SCROLLED (crash)! // if (scrolled) { // scrollPanel = new wxScrolledWindow(wxParent, wxID_ANY, wxPoint(xOffset,yOffset), wxDefaultSize, wxBORDER_SUNKEN); //#ifdef GDL_DEBUG_WIDGETS // scrollPanel->SetBackgroundColour(wxColour(0,255,255)); //bleu clair //#endif // scrollPanel->SetScrollRate(gdlSCROLL_WIDTH, gdlSCROLL_WIDTH); //show scrollbars // scrollSizer = new wxBoxSizer(wxVERTICAL ); // scrollPanel->SetSizer( scrollSizer ); // scrollPanel->SetSizeHints((x_scroll_size>0)?x_scroll_size:DEFAULT_SCROLL_SIZE,(y_scroll_size>0)?y_scroll_size:DEFAULT_SCROLL_SIZE); // // widgetPanel->Reparent(scrollPanel); // scrollSizer->Add(widgetPanel); // wxParent->AddPage(scrollPanel, titleWxString ); // } // else wxParent->AddPage( widgetPanel, titleWxString ); TIDY_WIDGET; UPDATE_WINDOW; } else { wxWindow* wxParent = static_cast (gdlParent->GetPanel()); assert( wxParent != NULL); widgetPanel = new wxPanel( wxParent, widgetID , wxPoint(xOffset,yOffset), wxDefaultSize, (frameWidth>0)?wxBORDER_SUNKEN:wxBORDER_NONE); #ifdef GDL_DEBUG_WIDGETS widgetPanel->SetBackgroundColour(wxColour(255,255,0)); //jaune #endif wxWidget = widgetPanel; //give size hints for this panel. if (!stretchX && !stretchY) widgetPanel->SetSizeHints(xSize, ySize); else if (!stretchX) widgetPanel->SetSizeHints(xSize, -1); else if (!stretchY) widgetPanel->SetSizeHints(-1, ySize); parentSizer->Add( widgetPanel, 0, widgetAlignment()|panelBorderFlag, (frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); //if no cols or rows are given, MUST at least fix one IF wxWidgets 3 if (ncols==0 && nrows==0) ncols=1; //Allocate the sizer for children according to col or row layout widgetSizer = GetBaseSizer( ncols, nrows, grid, space ); //Attach sizer to panel widgetPanel->SetSizer( widgetSizer ); if (scrolled) { scrollPanel = new wxScrolledWindow(wxParent, wxID_ANY, wxPoint(xOffset,yOffset), wxDefaultSize, wxBORDER_SUNKEN); #ifdef GDL_DEBUG_WIDGETS scrollPanel->SetBackgroundColour(wxColour(0,255,255)); //bleu clair #endif scrollSizer = new wxBoxSizer(wxVERTICAL ); scrollPanel->SetSizer( scrollSizer ); scrollPanel->SetSizeHints((x_scroll_size>0)?x_scroll_size:gdlDEFAULT_SCROLL_SIZE,(y_scroll_size>0)?y_scroll_size:gdlDEFAULT_SCROLL_SIZE); parentSizer->Detach(widgetPanel); widgetPanel->Reparent(scrollPanel); scrollSizer->Add(widgetPanel); parentSizer->Add(scrollPanel, 0, widgetAlignment()|panelBorderFlag, (frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); scrollPanel->SetScrollRate(gdlSCROLL_RATE, gdlSCROLL_RATE); //show scrollbars } TIDY_WIDGET; UPDATE_WINDOW; } } } DStructGDL* GDLWidgetBase::GetGeometry( wxRealPoint fact ) { int ixs=0, iys=0, ixscr=0, iyscr=0, imargin=0; long ixpad=0, iypad=0, ispace=0; float xs, ys, xscr, yscr, xoff, yoff, margin, xpad, ypad, space; wxPoint position; wxWindow* test = static_cast (wxWidget); if ( test != NULL ) { test->GetClientSize( &ixs, &iys ); ixscr=ixs; iyscr=iys; position = test->GetPosition( ); ixpad=this->getXPad(); iypad=this->getYPad(); ispace=this->getSpace(); } if (frameSizer != NULL) framePanel->GetSize(&ixscr,&iyscr); if (scrollSizer != NULL) {scrollPanel->GetSize(&ixscr,&iyscr);ixs=ixscr-gdlSCROLL_WIDTH;iys=iyscr-gdlSCROLL_WIDTH;} //size is in pixels, pass in requested units (1.0 default) xs = ixs / fact.x; ys = iys / fact.y; xscr = ixscr / fact.x; yscr = iyscr / fact.y; xoff = position.x / fact.x; yoff = position.y / fact.y; xpad = ixpad / fact.x; ypad = iypad / fact.y; space = ispace / fact.x; margin = imargin / fact.x; DStructGDL* ex = new DStructGDL( "WIDGET_GEOMETRY" ); ex->InitTag( "XOFFSET", DFloatGDL( xoff) ); ex->InitTag( "YOFFSET", DFloatGDL( yoff ) ); ex->InitTag( "XSIZE", DFloatGDL( xs ) ); ex->InitTag( "YSIZE", DFloatGDL( ys ) ); ex->InitTag( "SCR_XSIZE", DFloatGDL( xscr ) ); ex->InitTag( "SCR_YSIZE", DFloatGDL( yscr ) ); ex->InitTag( "MARGIN", DFloatGDL( margin ) ); ex->InitTag( "XPAD", DFloatGDL( xpad ) ); ex->InitTag( "YPAD", DFloatGDL( ypad ) ); ex->InitTag( "SPACE", DFloatGDL( space ) ); return ex; } GDLWidgetBase::~GDLWidgetBase() { #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetBase(): " << widgetID << std::endl; #endif // delete all children (in reverse order ?) while (children.size()) { GDLWidget* child = GetWidget( children[children.size()-1]); if (child) delete child; else children.pop_back(); // Maybe should not be reachable } // remove all widgets still in the queue for current TLB eventQueue.Purge( widgetID); readlineEventQueue.Purge( widgetID); if( this->parentID == GDLWidget::NullID) { // Close widget frame (might be already closed) if( static_cast(this->wxWidget) != NULL) { static_cast (this->wxWidget)->NullGDLOwner( ); delete static_cast (this->wxWidget); //closes the frame etc. } //IMPORTANT: unxregister TLB if was managed if (this->GetManaged()) CallEventPro( "UNXREGISTER" , new DLongGDL(widgetID)); //send RIP // create GDL event struct DStructGDL* ev = new DStructGDL( "*TOPLEVEL_DESTROYED*" ); ev->InitTag( "ID", DLongGDL( widgetID ) ); ev->InitTag( "TOP", DLongGDL( widgetID ) ); ev->InitTag( "HANDLER", DLongGDL( 0 ) ); ev->InitTag( "MESSAGE", DLongGDL( 0 ) ); if ( this->GetXmanagerActiveCommand( ) || !this->GetManaged() ){ readlineEventQueue.PushFront( ev ); // push front (will be handled next) } else { eventQueue.PushFront( ev ); // push front (will be handled next) } } } // called from event handling thread // sends a destroy event for itself void GDLWidgetBase::SelfDestroy() { assert( parentID == NullID ); // create GDL event struct DStructGDL* ev = new DStructGDL( "*WIDGET_DESTROY*" ); ev->InitTag( "ID", DLongGDL( widgetID ) ); ev->InitTag( "TOP", DLongGDL( widgetID ) ); ev->InitTag( "HANDLER", DLongGDL( 0 ) ); ev->InitTag( "MESSAGE", DLongGDL( 0 ) ); if ( this->GetXmanagerActiveCommand( ) || !this->GetManaged() ){ readlineEventQueue.PushFront( ev ); // push front (will be handled next) } else { eventQueue.PushFront( ev ); // push front (will be handled next) } } void GDLWidgetBase::mapBase(bool val){ wxWindow* me=static_cast(wxWidget); if (me) me->Show(val); else {cerr<<"Warning: GDLWidgetBase::mapBase(): Non-existent widget!\n"; return;} me->Update(); //immediate if (val) this->RefreshWidget(); } //Children of a column-oriented base are plotted in successive columns in IDL, whic is not the case for wxWidgets. void GDLWidgetBase::ReorderWidgets() { wxGridSizer* s=static_cast(widgetSizer); int ncols=s->GetCols();//GetEffectiveColsCount(); int nrows=s->GetRows();//GetEffectiveRowsCount(); int nchild=widgetPanel->GetChildren().GetCount(); if (ncols>1 && nchild>ncols) { nrows=nchild/ncols; if (nrows*ncolsGetChildren(); wxWindowList::iterator iter; for (iter = childrenList.begin(); iter != childrenList.end(); ++iter) { wxWindow* w=(*iter); s->Detach(*iter); } s->SetCols(0); s->SetRows(nrows); for (int i = 0; i < nrows; i++) { for (int j = 0; j < ncols; j++) { int index=j*nrows+i; if (indexAdd(w); } } } widgetSizer->Layout(); widgetPanel->Refresh(); } } /*********************************************************/ // for WIDGET_TAB /*********************************************************/ GDLWidgetTab::GDLWidgetTab( WidgetIDT p, EnvT* e, ULong eventFlags_, DLong location, DLong multiline ) : GDLWidgetContainer( p, e, eventFlags ) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); long style = wxNB_TOP; if ( location == 1 ) style = wxNB_BOTTOM; if ( location == 2 ) style = wxNB_LEFT; if ( location == 3 ) style = wxNB_RIGHT; if ( multiline != 0 ) style |= wxNB_MULTILINE; wxNotebook * notebook = new wxNotebook( widgetPanel, widgetID, wxPoint( xOffset, yOffset ), computeWidgetSize( ), style ); this->wxWidget = notebook; notebook->Connect(widgetID,wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,wxNotebookEventHandler(GDLFrame::OnPageChanged)); widgetStyle=widgetAlignment(); widgetSizer->Add( notebook, 0, widgetStyle, 0 ); widgetSizer->Layout(); TIDY_WIDGET; UPDATE_WINDOW } BaseGDL* GDLWidgetTab::GetTabNumber(){ wxNotebook * notebook=static_cast(wxWidget); assert( notebook != NULL); return new DIntGDL(notebook->GetPageCount()); } BaseGDL* GDLWidgetTab::GetTabCurrent(){ wxNotebook * notebook=static_cast(wxWidget); assert( notebook != NULL); return new DIntGDL(notebook->GetSelection()); } void GDLWidgetTab::SetTabCurrent(int val){ wxNotebook * notebook=static_cast(wxWidget); assert( notebook != NULL); if (valGetPageCount()){ // notebook->GetPage(val)->Raise(); notebook->ChangeSelection(val); } } BaseGDL* GDLWidgetTab::GetTabMultiline(){ wxNotebook * notebook=static_cast(wxWidget); assert( notebook != NULL); return new DIntGDL(notebook->GetExtraStyle()&wxNB_MULTILINE); } GDLWidgetTab::~GDLWidgetTab(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "in ~GDLWidgetTab(): " << widgetID << std::endl; #endif // delete all children (in reverse order ?) while (children.size()) { GDLWidget* child = GetWidget(children[children.size() - 1]); if (child) delete child; else children.pop_back(); // Maybe should not be reachable } } /*********************************************************/ // for WIDGET_TABLE /*********************************************************/ //overrides method to label the columns & lines wxString wxGridTableBase::GetRowLabelValue( int row ) { wxString s; // RD: Starting the rows at zero confuses users, // no matter how much it makes sense to us geeks. // GD: So IDL and GDL are for geeks. s << row ; return s; } wxString wxGridTableBase::GetColLabelValue( int col ) { wxString s; s << col ; return s; } GDLWidgetTable::GDLWidgetTable( WidgetIDT p, EnvT* e, DByteGDL* alignment_, DStringGDL* amPm_, DByteGDL* backgroundColor_, DByteGDL* foregroundColor_, DStringGDL* columnLabels_, int majority_, DLongGDL* columnWidth_, DStringGDL* daysOfWeek_, bool disjointSelection_, DByteGDL* editable_, DStringGDL* format_, //bool ignoreAccelerators_, DStringGDL* month_, bool noColumnHeaders_, bool noRowHeaders_, bool resizeableColumns_, bool resizeableRows_, DLongGDL* rowHeights_, DStringGDL* rowLabels_, //DLong tabMode_, BaseGDL* value_, DLong xScrollSize_, DLong yScrollSize_, DStringGDL* valueAsStrings_, DULong eventFlags_ ) : GDLWidget( p, e, value_, eventFlags_ ) , table_alignment( alignment_ ) , amPm( amPm_ ) , backgroundColor( backgroundColor_ ) , foregroundColor( foregroundColor_ ) , columnLabels( columnLabels_ ) , majority ( majority_ ) , columnWidth( columnWidth_ ) , daysOfWeek( daysOfWeek_ ) , disjointSelection( disjointSelection_ ) , editable( editable_) , format( format_ ) //, ignoreAccelerators( ignoreAccelerators_ ) , month( month_ ) , noColumnHeaders( noColumnHeaders_ ) , noRowHeaders( noRowHeaders_ ) , resizeableColumns( resizeableColumns_ ) , resizeableRows( resizeableRows_ ) , rowHeights( rowHeights_ ) , rowLabels( rowLabels_ ) //, tabMode( tabMode_ ) , x_scroll_size( xScrollSize_ ) , y_scroll_size( yScrollSize_) , valueAsStrings( valueAsStrings_ ) , updating(FALSE) { GDLWidget* gdlParent = GetWidget( parentID ); wxPanel *panel = gdlParent->GetPanel( ); widgetPanel = panel; widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); //at this stage, valueAsStrings is OK dim 1 or 2 BUT vVALUE MAY BE NULL! SizeT numRows,numCols; if (valueAsStrings->Rank()==1) { numRows=1; numCols=valueAsStrings->Dim(0); //lines } else { numRows=valueAsStrings->Dim(1); numCols=valueAsStrings->Dim(0); } SizeT grid_nrows=(ySize<=0)?numRows:ySize; SizeT grid_ncols=(xSize<=0)?numCols:xSize; gdlGrid *grid = new gdlGrid( widgetPanel, widgetID); //important:set wxWidget here. this->wxWidget = grid; //Column Width Before creating bool hasColumnWidth=(columnWidth!=NULL); if (hasColumnWidth) { //one value set for all? if (columnWidth->N_Elements()==1) { grid->SetDefaultColSize((*columnWidth)[0]*unitConversionFactor.x) ; hasColumnWidth=FALSE; } } //RowHeight bool hasRowHeights=(rowHeights!=NULL); if (hasRowHeights) { //one value set for all? if (rowHeights->N_Elements()==1) { grid->SetDefaultRowSize((*rowHeights)[0]*unitConversionFactor.y) ; hasRowHeights=FALSE; } } //Alignment bool hasAlignment=(table_alignment!=NULL); if (hasAlignment) { if (table_alignment->N_Elements()==1) { //singleton case switch( (*table_alignment)[0] ){ case 0: grid->SetDefaultCellAlignment(wxALIGN_LEFT,wxALIGN_CENTRE); break; case 1: grid->SetDefaultCellAlignment(wxALIGN_CENTRE,wxALIGN_CENTRE); break; case 2: grid->SetDefaultCellAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE); } hasAlignment=FALSE; } } //General Editability bool isEditable=(editable!=NULL); if (isEditable) { if (editable->N_Elements()==1) { //singleton case if ((*editable)[0]==0) isEditable=FALSE; else {grid->EnableEditing(TRUE); isEditable=FALSE;} } } else grid->EnableEditing(FALSE); if (isEditable) grid->EnableEditing(TRUE); //since now isEditable means "individually editable", which needs global editing set. //Single Background Colour bool isBackgroundColored=(backgroundColor!=NULL); if (isBackgroundColored) { //one value set for all? if (backgroundColor->N_Elements()==3) { grid->SetDefaultCellBackgroundColour(wxColour((*backgroundColor)[0],(*backgroundColor)[1],(*backgroundColor)[2])) ; isBackgroundColored=FALSE; } } //Single Text Colour bool isForegroundColored=(foregroundColor!=NULL); if (isForegroundColored) { //one value set for all? if (foregroundColor->N_Elements()==3) { grid->SetDefaultCellTextColour(wxColour((*foregroundColor)[0],(*foregroundColor)[1],(*foregroundColor)[2])) ; isForegroundColored=FALSE; } } //No column Headers if (noColumnHeaders) grid->SetColLabelSize(0); //No row Headers if (noRowHeaders) grid->SetRowLabelSize(0); //end General Setup int selmode = wxGrid::wxGridSelectCells; //wxWidgets's modes do not reflect IDL's. We trick the selections according to modes in eventhandler. if (!resizeableColumns) grid->DisableDragColSize(); if (!resizeableRows) grid->DisableDragRowSize(); grid->CreateGrid( grid_nrows, grid_ncols, static_cast(selmode)); // Set grid cell contents as strings. Note that there may be less or more cells than valueAsStrings, due to possibly different xSize,ySize : for ( int ival=0, i=0; iSetCellValue( i, j ,wxString(((*valueAsStrings)[jval*numRows+ival]).c_str(), wxConvUTF8 ) ); } //Editability //take too long as soon as table has a more than a few elements. Fixme! //if (isEditable) {SizeT k=0; for (SizeT irow=0; irow< grid_nrows; ++irow) for (SizeT icol=0; icol< grid_ncols; ++icol) {grid->SetReadOnly( irow, icol, ((*editable)[k%editable->N_Elements()]==0));++k;}} //colors per element if (isBackgroundColored) this->DoBackgroundColor(); if (isForegroundColored) this->DoForegroundColor(); if (hasColumnWidth) this->DoColumnWidth(); if (hasRowHeights) this->DoRowHeights(); //treat other alignment cases. if (hasAlignment) this->DoAlign(); if (columnLabels!=NULL)this->DoColumnLabels(); if (rowLabels!=NULL) this->DoRowLabels(); //get back on sizes. Do we enforce some size or scroll_size, in columns/rows: int currentColLabelHeight = grid->GetColLabelSize(); int currentRowLabelWidth = grid->GetRowLabelSize(); int fullsizex=currentRowLabelWidth; int fullsizey=currentColLabelHeight; for (SizeT i=0; i< numCols ; ++i) fullsizex+=(iGetColSize(i):grid->GetDefaultColSize(); for (SizeT j=0; j< numRows ; ++j) fullsizey+=(jGetRowHeight(j):grid->GetDefaultRowSize(); int visiblesizex=currentRowLabelWidth; int visiblesizey=currentColLabelHeight; for (SizeT i=0; i< grid_ncols ; ++i) visiblesizex+=grid->GetColSize(i); for (SizeT j=0; j< grid_nrows ; ++j) visiblesizey+=grid->GetRowHeight(j); int sizex=-1; int sizey=-1; int scr_sizex=-1; int scr_sizey=-1; if ( xSize > 0 ) { sizex = visiblesizex; //size in columns given } else {sizex=fullsizex;} if ( ySize > 0 ) { sizey = visiblesizey; //size in rows given } else {sizey=fullsizey;} if ( x_scroll_size > 0 ) { //scroll size is in columns scrolled=TRUE; scr_sizex=currentRowLabelWidth+gdlSCROLL_WIDTH; for (SizeT i=0; i< x_scroll_size ; ++i) scr_sizex+=grid->GetColSize(i); scr_sizex=min(scr_sizex,fullsizex); if (y_scroll_size <=0) y_scroll_size=x_scroll_size; } if ( y_scroll_size > 0 ) { //rows scrolled=TRUE; scr_sizey=currentColLabelHeight+gdlSCROLL_WIDTH; for (SizeT j=0; j< y_scroll_size ; ++j) scr_sizey+=grid->GetRowHeight(j); scr_sizey=min(scr_sizey,fullsizey); } //fix size if relevant if (scrolled && scr_sizex == -1) scr_sizex = (sizex>0)?sizex:fullsizex; if (scrolled && scr_sizey == -1) scr_sizey = (sizey>0)?sizey:fullsizey; //scrXSize etc to be considered since sizes are not in pixels: if (scrXSize>0) {if (scrolled) scr_sizex=scrXSize; else sizex=scrXSize;} if (scrYSize>0) {if (scrolled) scr_sizey=scrYSize; else sizey=scrYSize;} //wxGrid IS a scrolled window if (scrolled) { grid->SetInitialSize(wxSize(scr_sizex, scr_sizey)); } else { if (xSize>0||ySize>0) grid->SetInitialSize(wxSize(sizex,sizey)); } grid->SetScrollLineX(grid->GetColSize(0)); grid->SetScrollLineY(grid->GetRowHeight(0)); widgetStyle=widgetAlignment(); widgetSizer->Add(grid, 0, widgetStyle, 0 ); if ((frameWidth>0)) this->FrameWidget(); TIDY_WIDGET; UPDATE_WINDOW } bool GDLWidgetTable::IsSomethingSelected(){ gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); return grid->IsSomethingSelected(); } DLongGDL* GDLWidgetTable::GetSelection( ) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); SizeT k = 0; DLongGDL * sel; std::vector list = grid->GetSelectedDisjointCellsList( ); if ( disjointSelection ) { //pairs lists if ( list.size( ) < 1 ) {sel = new DLongGDL( 2, BaseGDL::ZERO ); sel->Dec(); return sel;} //returns [-1,-1] if nothing selected SizeT dims[2]; dims[0] = 2; dims[1] = list.size( ); dimension dim( dims, 2 ); sel = new DLongGDL( dim ); for ( std::vector::iterator it = list.begin( ); it != list.end( ); ++it ) { (*sel)[k++] = (*it).y; (*sel)[k++] = (*it).x; } } else { //4 values wxGridCellCoordsArray selectionTL = grid->GetSelectionBlockTopLeft( ); wxGridCellCoordsArray selectionBR = grid->GetSelectionBlockBottomRight( ); sel = new DLongGDL( 4, BaseGDL::ZERO ); sel->Dec(); //will return [-1,-1,-1,-1] if nothing selected if (!selectionTL.IsEmpty() && !selectionBR.IsEmpty()){ //ok with a block... //LEFT TOP BOTTOM RIGHT (*sel)[0] = selectionTL[0].GetCol( ); (*sel)[1] = selectionTL[0].GetRow( ); (*sel)[2] = selectionBR[0].GetCol( ); (*sel)[3] = selectionBR[0].GetRow( ); } else { //try columns, rows, and singletons wxArrayInt selectionRow=grid->GetSelectedRows(); wxArrayInt selectionCol=grid->GetSelectedCols(); if ( selectionRow.GetCount() >0 ) { (*sel)[0] = 0; (*sel)[1] = selectionRow[0]; (*sel)[2] = grid->GetNumberCols()-1; (*sel)[3] = selectionRow[selectionRow.GetCount()-1]; } else if ( selectionCol.GetCount() >0 ) { (*sel)[0] = selectionCol[0]; (*sel)[1] = 0; (*sel)[2] = selectionCol[selectionCol.GetCount()-1]; (*sel)[3] = grid->GetNumberRows()-1; } else { wxGridCellCoordsArray cellSelection = grid->GetSelectedCells( ); if (cellSelection.size()>0) { int row = cellSelection[0].GetRow(); int col = cellSelection[0].GetCol(); (*sel)[0] = col; (*sel)[1] = row; (*sel)[2] = col; (*sel)[3] = row; } } return sel; } } return sel; } void GDLWidgetTable::ClearSelection() { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); updating=TRUE; grid->ClearSelection(); updating=FALSE; UPDATE_WINDOW } void GDLWidgetTable::DoAlign() { if (table_alignment->N_Elements( )==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nRows = grid->GetNumberRows( ); int nCols = grid->GetNumberCols( ); SizeT k = 0; grid->BeginBatch(); for ( SizeT i = 0; i < nRows; ++i ) { for ( SizeT j = 0; j < nCols; ++j ) { switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) { case 0: grid->SetCellAlignment( i, j, wxALIGN_LEFT, wxALIGN_CENTRE ); break; case 1: grid->SetCellAlignment( i, j, wxALIGN_CENTRE, wxALIGN_CENTRE ); break; case 2: grid->SetCellAlignment( i, j, wxALIGN_RIGHT, wxALIGN_CENTRE ); } k++; if ( table_alignment->N_Elements( ) > 1 ) if ( k == table_alignment->N_Elements( ) ) break; } if ( table_alignment->N_Elements( ) > 1 ) if ( k == table_alignment->N_Elements( ) ) break; } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoAlign(DLongGDL* selection) { if (table_alignment->N_Elements( )==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); SizeT k = 0; grid->BeginBatch(); if (selection->Rank()==0) { //use current wxWidgets selection std::vector list=grid->GetSelectedDisjointCellsList(); for ( std::vector::iterator it = list.begin(); it !=list.end(); ++it) { int ali; switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) { case 0: ali = wxALIGN_LEFT; break; case 1: ali = wxALIGN_CENTRE; break; case 2: ali = wxALIGN_RIGHT; } grid->SetCellAlignment( (*it).x, (*it).y, ali, wxALIGN_CENTRE ); k++; } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists for (SizeT n=0,l=0; nDim(1); ++n) { int col = (*selection)[l++]; int row = (*selection)[l++]; int ali; switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) { case 0: ali = wxALIGN_LEFT; break; case 1: ali = wxALIGN_CENTRE; break; case 2: ali = wxALIGN_RIGHT; } grid->SetCellAlignment( row, col, ali, wxALIGN_CENTRE ); k++; } }else{ //4 values int colTL = (*selection)[0]; int rowTL = (*selection)[1]; int colBR = (*selection)[2]; int rowBR = (*selection)[3]; for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j) { int ali; switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) { case 0: ali = wxALIGN_LEFT; break; case 1: ali = wxALIGN_CENTRE; break; case 2: ali = wxALIGN_RIGHT; } grid->SetCellAlignment( i, j, ali, wxALIGN_CENTRE ); k++; } } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoBackgroundColor() { SizeT nbColors=backgroundColor->N_Elements( ); if (nbColors==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nRows = grid->GetNumberRows( ); int nCols = grid->GetNumberCols( ); SizeT k=0; grid->BeginBatch(); for (SizeT i=0; i< nRows; ++i) for (SizeT j=0; j< nCols; ++j) //Row by Row, from top. { grid->SetCellBackgroundColour( i, j, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2])); k+=3; } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoBackgroundColor(DLongGDL* selection) { SizeT nbColors=backgroundColor->N_Elements( ); if (nbColors==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch(); SizeT k=0; if (selection->Rank()==0) { //use current wxWidgets selection std::vector list=grid->GetSelectedDisjointCellsList(); for ( std::vector::iterator it = list.begin(); it !=list.end(); ++it) { grid->SetCellBackgroundColour( (*it).x, (*it).y, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2])); k+=3; } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists for (SizeT n=0,l=0; nDim(1); ++n) { int col = (*selection)[l++]; int row = (*selection)[l++]; grid->SetCellBackgroundColour( row, col, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2])); k+=3; } }else{ //4 values int colTL = (*selection)[0]; int rowTL = (*selection)[1]; int colBR = (*selection)[2]; int rowBR = (*selection)[3]; for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j) { grid->SetCellBackgroundColour( i, j, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2])); k+=3; } } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoForegroundColor() { SizeT nbColors=foregroundColor->N_Elements( ); if (nbColors==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nRows = grid->GetNumberRows( ); int nCols = grid->GetNumberCols( ); SizeT k=0; grid->BeginBatch(); for (SizeT i=0; i< nRows; ++i) for (SizeT j=0; j< nCols; ++j) //Row by Row, from top. { grid->SetCellTextColour( i, j, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2])); k+=3; } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoForegroundColor(DLongGDL* selection) { SizeT nbColors=foregroundColor->N_Elements( ); if (nbColors==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch(); SizeT k=0; if (selection->Rank()==0) { //use current wxWidgets selection std::vector list=grid->GetSelectedDisjointCellsList(); for ( std::vector::iterator it = list.begin(); it !=list.end(); ++it) { grid->SetCellTextColour( (*it).x, (*it).y, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2])); k+=3; } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists for (SizeT n=0,l=0; nDim(1); ++n) { int col = (*selection)[l++]; int row = (*selection)[l++]; grid->SetCellTextColour( row, col, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2])); k+=3; } }else{ //4 values int colTL = (*selection)[0]; int rowTL = (*selection)[1]; int colBR = (*selection)[2]; int rowBR = (*selection)[3]; for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j) { grid->SetCellTextColour( i, j, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2])); k+=3; } } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoColumnLabels( ) { if (columnLabels->N_Elements( )==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nCols = grid->GetNumberCols( ); grid->BeginBatch(); if ( columnLabels->N_Elements( ) == 1 ) { //singleton case if ( static_cast ((*columnLabels)[0]).length( ) == 0 ) { for ( SizeT j = 0; j < nCols; ++j ) grid->SetColLabelValue( j, wxEmptyString ); } else { for ( SizeT j = 0; j < nCols; ++j ) { if ( j > (columnLabels->N_Elements( ) - 1) ) break; grid->SetColLabelValue( j, wxString( static_cast ((*columnLabels)[j]).c_str( ), wxConvUTF8 ) ); } } } else { for ( SizeT j = 0; j < nCols; ++j ) { if ( j > (columnLabels->N_Elements( ) - 1) ) break; grid->SetColLabelValue( j, wxString( static_cast ((*columnLabels)[j]).c_str( ), wxConvUTF8 ) ); } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoColumnWidth( ) { if (columnWidth->N_Elements( )==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nCols = grid->GetNumberCols( ); grid->BeginBatch(); if ( columnWidth->N_Elements( ) == 1 ) for ( SizeT j = 0; j < nCols; ++j ) grid->SetColSize(j,(*columnWidth)[0]*unitConversionFactor.x); else { for ( SizeT j = 0; j < nCols; ++j ) { if ( j > (columnWidth->N_Elements( ) - 1) ) break; grid->SetColSize(j,(*columnWidth)[j]*unitConversionFactor.x); } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoColumnWidth( DLongGDL* selection ) { SizeT nbCols = columnWidth->N_Elements( ); if ( nbCols == 0 ) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); SizeT k=0; if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedColsList(); //find concerned cols for ( int it = 0; it SetColSize( list[it], (*columnWidth)[it % nbCols]*unitConversionFactor.x); } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allCols; std::vector::iterator iter; //find concerned cols for ( SizeT n=0, l=0 ; nDim(1); ++n) { int col = (*selection)[l++];l++; allCols.push_back(col); } std::sort (allCols.begin(), allCols.end()); int theCol=-1; for ( iter = allCols.begin(); iter !=allCols.end(); ++iter) { if ((*iter)!=theCol) { theCol=(*iter); //if index is -1, we want to size the label column instead of the grid columns. if (theCol==-1) grid->SetRowLabelSize((*columnWidth)[k % nbCols]*unitConversionFactor.x); else if (theCol>=0 && theColGetNumberCols()) grid->SetColSize( theCol, (*columnWidth)[k % nbCols]*unitConversionFactor.x ); k++; } } } else { //4 values int colTL = (*selection)[0]; int colBR = (*selection)[2]; for (int j=colTL; j<=colBR; ++j) { //if index is -1, we want to size the label column instead of the grid columns. if (j==-1) grid->SetRowLabelSize((*columnWidth)[k % nbCols]*unitConversionFactor.x); else if (j>=0 && jGetNumberCols()) grid->SetColSize( j, (*columnWidth)[k % nbCols]*unitConversionFactor.x ); k++; } } } grid->EndBatch( ); UPDATE_WINDOW } DFloatGDL* GDLWidgetTable::GetColumnWidth(DLongGDL* selection){ gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); SizeT k=0; int nCols = grid->GetNumberCols( ); if ( selection == NULL) { DFloatGDL* res=new DFloatGDL(dimension(nCols)); for ( SizeT j = 0; j < nCols; ++j ) (*res)[j]=grid->GetColSize(j); return res; } else if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedColsList(); //find concerned cols if (list.GetCount()==0) return NULL; DFloatGDL* res=new DFloatGDL(dimension(list.GetCount())); for ( int it = 0; it GetColSize( list[it] ); } return res; } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allCols; std::vector::iterator iter; std::vector theCols; //find concerned cols for ( SizeT n=0, l=0 ; nDim(1); ++n) { int col = (*selection)[l++];l++; allCols.push_back(col); } std::sort (allCols.begin(), allCols.end()); int theCol=-1; for ( iter = allCols.begin(); iter !=allCols.end(); ++iter) { if ((*iter)!=theCol) { theCol=(*iter); k++; theCols.push_back(theCol); } } //final list: if (theCols.size()==0) return NULL; DFloatGDL* res=new DFloatGDL(dimension(theCols.size())); for ( iter = theCols.begin(); iter !=theCols.end(); ++iter) { (*res)[k++]=grid->GetColSize( (*iter)); } return res; } else { //4 values int colTL = (*selection)[0]; int colBR = (*selection)[2]; int count = colBR-colTL+1; if (count==0) return NULL; DFloatGDL* res=new DFloatGDL(dimension(count)); for (int j=colTL; j<=colBR; ++j) { (*res)[k++]=grid->GetColSize(j); } } } return new DFloatGDL(0); //to keep compiler happy } DFloatGDL* GDLWidgetTable::GetRowHeight(DLongGDL* selection){ gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); SizeT k=0; int nRows = grid->GetNumberRows( ); if ( selection == NULL) { DFloatGDL* res=new DFloatGDL(dimension(nRows)); for ( SizeT i = 0; i < nRows; ++i ) (*res)[i]=grid->GetRowSize(i); return res; } else if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedRowsList(); //find concerned rows if (list.GetCount()==0) return NULL; DFloatGDL* res=new DFloatGDL(dimension(list.GetCount())); for ( int it = 0; it GetRowSize( list[it] ); } return res; } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allRows; std::vector::iterator iter; std::vector theRows; //find concerned rows for ( SizeT n=0, l=0 ; nDim(1); ++n) { int row = (*selection)[l++];l++; allRows.push_back(row); } std::sort (allRows.begin(), allRows.end()); int theRow=-1; for ( iter = allRows.begin(); iter !=allRows.end(); ++iter) { if ((*iter)!=theRow) { theRow=(*iter); k++; theRows.push_back(theRow); } } //final list: if (theRows.size()==0) return NULL; DFloatGDL* res=new DFloatGDL(dimension(theRows.size())); for ( iter = theRows.begin(); iter !=theRows.end(); ++iter) { (*res)[k++]=grid->GetRowSize( (*iter)); } return res; } else { //4 values int rowTL = (*selection)[1]; int rowBR = (*selection)[3]; int count = rowBR-rowTL+1; if (count==0) return NULL; DFloatGDL* res=new DFloatGDL(dimension(count)); for (int j=rowTL; j<=rowBR; ++j) { (*res)[k++]=grid->GetRowSize(j); } } } return new DFloatGDL(0); //to keep compiler happy } void GDLWidgetTable::DoRowHeights( ) { if (rowHeights->N_Elements( )==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nRows = grid->GetNumberRows( ); grid->BeginBatch(); if ( rowHeights->N_Elements( ) == 1 ) for ( SizeT i = 0; i < nRows; ++i ) grid->SetRowSize(i,(*rowHeights)[0]*unitConversionFactor.y); else { for ( SizeT i = 0; i < nRows; ++i ) { if ( i > (rowHeights->N_Elements( ) - 1) ) break; grid->SetRowSize(i,(*rowHeights)[i]*unitConversionFactor.y); } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DoRowHeights( DLongGDL* selection ) { SizeT nbRows = rowHeights->N_Elements( ); if ( nbRows == 0 ) { return; } gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); SizeT k=0; if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedRowsList(); for ( int it = 0; it GetNumberRows()) grid->SetRowSize( list[it], (*rowHeights)[it % nbRows]*unitConversionFactor.y ); } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allRows; std::vector::iterator iter; for ( SizeT n=0, l=0 ; nDim(1); ++n) { l++; int row = (*selection)[l++]; allRows.push_back(row); } std::sort (allRows.begin(), allRows.end()); int theRow=-1; for ( iter = allRows.begin(); iter !=allRows.end(); ++iter) { if ((*iter)!=theRow) { theRow=(*iter); //if index is -1, we want to size the label column instead of the grid columns. if (theRow==-1) grid->SetColLabelSize((*columnWidth)[k % nbRows]*unitConversionFactor.x); else if (theRow>=0 && theRowGetNumberRows()) grid->SetRowSize( theRow, (*rowHeights)[k % nbRows] *unitConversionFactor.y); k++; } } } else { //4 values int rowTL = (*selection)[1]; int rowBR = (*selection)[3]; for (int i=rowTL; i<=rowBR; ++i) { //if index is -1, we want to size the label column instead of the grid columns. if (i==-1) grid->SetColLabelSize((*columnWidth)[k % nbRows]*unitConversionFactor.x); else if (i>=0 && iGetNumberRows()) grid->SetRowSize( i, (*rowHeights)[k % nbRows]*unitConversionFactor.y ); k++; } } } grid->EndBatch( ); UPDATE_WINDOW } void GDLWidgetTable::DoRowLabels( ) { if (rowLabels->N_Elements( )==0) {return;} gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); int nRows = grid->GetNumberRows( ); grid->BeginBatch(); if ( rowLabels->N_Elements( ) == 1 ) { //singleton case if ( static_cast ((*rowLabels)[0]).length( ) == 0 ) { for ( SizeT i = 0; i < nRows; ++i ) grid->SetRowLabelValue( i, wxEmptyString ); } else { for ( SizeT i = 0; i < nRows; ++i ) { if ( i > (rowLabels->N_Elements( ) - 1) ) break; grid->SetRowLabelValue( i, wxString( static_cast ((*rowLabels)[i]).c_str( ), wxConvUTF8 ) ); } } } else { for ( SizeT i = 0; i < nRows; ++i ) { if ( i > (rowLabels->N_Elements( ) - 1) ) break; grid->SetRowLabelValue( i, wxString( static_cast ((*rowLabels)[i]).c_str( ), wxConvUTF8 ) ); } } grid->EndBatch(); UPDATE_WINDOW } void GDLWidgetTable::DeleteColumns(DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); if ( selection==NULL || selection->Rank( ) == 0 ) { //use current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedColsList(); //delete in reverse order to avoid column-numbering problems for ( int it = list.GetCount()-1; it >-1 ; --it) { grid->DeleteCols( list[it], 1, TRUE); } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allCols; std::vector::reverse_iterator riter; //find concerned cols for ( SizeT n=0, l=0 ; nDim(1); ++n) { int col = (*selection)[l++];l++; allCols.push_back(col); } std::sort (allCols.begin(), allCols.end()); int theCol=-1; for ( riter = allCols.rbegin(); riter !=allCols.rend(); ++riter) { if ((*riter)!=theCol) { theCol=(*riter); grid->DeleteCols( theCol, 1, TRUE); } } } else { //4 values, cols are contiguous, easy. int colTL = (*selection)[0]; int colBR = (*selection)[2]; int count=colBR-colTL+1; grid->DeleteCols( colTL , count, TRUE ); } } grid->EndBatch( ); UPDATE_WINDOW } bool GDLWidgetTable::InsertColumns(DLong count, DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); bool success; grid->BeginBatch( ); if ( selection==NULL ){ //add count to rightmost position int pos=grid->GetNumberCols(); success=grid->InsertCols(pos,count,TRUE); // Set new grid cell contents TBD FIXME! {SizeT k=0; for (SizeT i=0; i< grid->GetNumberRows(); ++i) for (SizeT j=pos; jGetNumberCols() ; ++j) {grid->SetCellValue( i, j, wxString( "0" , wxConvUTF8 ) );++k;}} } else if (selection->Rank( ) == 0 ) { //add left of current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedColsList(); //insert to left of first one success=grid->InsertCols( list[0], count, TRUE); } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allCols; //find concerned cols for ( SizeT n=0, l=0 ; nDim(1); ++n) { int col = (*selection)[l++];l++; allCols.push_back(col); } std::sort (allCols.begin(), allCols.end()); success=grid->InsertCols( *(allCols.begin()), 1, TRUE); } else { //4 values, cols are contiguous, easy. int colTL = (*selection)[0]; success=grid->InsertCols( colTL , count, TRUE ); } } grid->EndBatch( ); UPDATE_WINDOW return success; } void GDLWidgetTable::DeleteRows(DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); if ( selection==NULL || selection->Rank( ) == 0 ) { //use current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedRowsList(); //delete in reverse order to avoid column-numbering problems for ( int it = list.GetCount()-1; it >-1 ; --it) { grid->DeleteRows( list[it], 1, TRUE); } } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allRows; std::vector::reverse_iterator riter; //find concerned Rows for ( SizeT n=0, l=0 ; nDim(1); ++n) { int row = (*selection)[l++];l++; allRows.push_back(row); } std::sort (allRows.begin(), allRows.end()); int theRow=-1; for ( riter = allRows.rbegin(); riter !=allRows.rend(); ++riter) { if ((*riter)!=theRow) { theRow=(*riter); grid->DeleteRows( theRow, 1, TRUE); } } } else { //4 values, Rows are contiguous, easy. int rowTL = (*selection)[1]; int rowBR = (*selection)[3]; int count=rowBR-rowTL+1; grid->DeleteRows( rowTL , count, TRUE ); } } grid->EndBatch( ); UPDATE_WINDOW } bool GDLWidgetTable::InsertRows(DLong count, DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); bool success; grid->BeginBatch( ); if ( selection==NULL ){ //add count to rightmost position int pos=grid->GetNumberRows(); success=grid->InsertRows(pos,count,TRUE); // Set new grid cell contents TBD FIXME! {SizeT k=0; for (SizeT i=pos; iGetNumberRows(); ++i) for (SizeT j=0; jGetNumberCols() ; ++j) {grid->SetCellValue( i, j, wxString( "0" , wxConvUTF8 ) );++k;}} } else if (selection->Rank( ) == 0 ) { //add left of current wxWidgets selection wxArrayInt list=grid->GetSortedSelectedRowsList(); //insert to left of first one success=grid->InsertRows( list[0], count, TRUE); } else { //use the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector allRows; //find concerned rows for ( SizeT n=0, l=0 ; nDim(1); ++n) { int row = (*selection)[l++];l++; allRows.push_back(row); } std::sort (allRows.begin(), allRows.end()); success=grid->InsertRows( *(allRows.begin()), 1, TRUE); } else { //4 values, cols are contiguous, easy. int rowTL = (*selection)[1]; success=grid->InsertRows( rowTL , count, TRUE ); } } grid->EndBatch( ); UPDATE_WINDOW return success; } void GDLWidgetTable::SetTableValues(DStringGDL* val, DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch(); if ( selection==NULL ){ //reset table to everything. val replaces valueAsStrings. GDLDelete(valueAsStrings); valueAsStrings=val->Dup(); SizeT numRows,numCols; if (valueAsStrings->Rank()==1) { numRows=1; numCols=valueAsStrings->Dim(0); //lines } else { numRows=valueAsStrings->Dim(1); numCols=valueAsStrings->Dim(0); } grid->ClearGrid(); int curr_rows=grid->GetNumberRows(); int curr_cols=grid->GetNumberCols(); //adjust rows and cols: if (numRows > curr_rows) grid->AppendRows(numRows-curr_rows); if (numCols > curr_cols) grid->AppendCols(numCols-curr_cols); // Set grid cell contents as strings {SizeT k=0; for (SizeT i=0; iSetCellValue( i, j, wxString(((*valueAsStrings)[k]).c_str(), wxConvUTF8 ) );++k;}} } else { //use the wxWidget selection or the passed selection, mode-dependent: if (disjointSelection) { //pairs lists if (selection->Rank()==0) { std::vector list=grid->GetSelectedDisjointCellsList(); SizeT k=0; for (std::vector::iterator it = list.begin(); it !=list.end(); ++it) { grid->SetCellValue( (*it).x, (*it).y ,wxString(((*val)[k++]).c_str(), wxConvUTF8 ) ); if (k==val->N_Elements()) break; } } else { for (SizeT k=0,n=0,l=0; nDim(1); ++n) { int col = (*selection)[l++]; int row = (*selection)[l++]; grid->SetCellValue( row, col ,wxString(((*val)[k++]).c_str(), wxConvUTF8 ) ); if (k==val->N_Elements()) break; } } } else { //IDL maintains the 2D-structure of val! SizeT numRows,numCols; if (val->Rank()==1) { numRows=1; numCols=val->Dim(0); //lines } else { numRows=val->Dim(1); numCols=val->Dim(0); } int colTL,colBR,rowTL,rowBR; if (selection->Rank()==0) { wxArrayInt block=grid->GetSelectedBlockOfCells(); //normally only ONE block is available. colTL = block[0]; rowTL = block[1]; colBR = block[2]; rowBR = block[3]; } else { colTL = (*selection)[0]; rowTL = (*selection)[1]; colBR = (*selection)[2]; rowBR = (*selection)[3]; } for ( int ival=0, i=rowTL; i<=rowBR; ++i, ++ival) for (int jval=0, j=colTL; j<=colBR; ++j, ++jval) { if (ival < numRows && jval < numCols ) grid->SetCellValue( i, j ,wxString(((*val)[jval*numRows+ival]).c_str(), wxConvUTF8 ) ); } } } grid->EndBatch( ); UPDATE_WINDOW } BaseGDL* GDLWidgetTable::GetTableValuesAsStruct(DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); BaseGDL* res; int numRows=valueAsStrings->Dim(0); int numCols=valueAsStrings->Dim(1); DStringGDL* stringres=this->GetTableValues(selection); if (stringres==NULL) return NULL; //pass error back. if ( selection==NULL ){ //just convert res=vValue->Dup(); stringstream is; // if (majority == GDLWidgetTable::ROW_MAJOR ) { // BaseGDL* tmp=static_cast(stringres)->Transpose(NULL); // GDLDelete(stringres); // stringres=static_cast(tmp); // for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n'; // } else { for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n'; // } res->FromStream( is); } else { //use the wxWidget selection or the passed selection, mode-dependent: if (disjointSelection) { //pairs lists std::vector list; if (selection->Rank()==0) { //use current wxWidgets selection. Result is a STRUCT list=grid->GetSelectedDisjointCellsList(); } else { //make equivalent vector. for (SizeT k=0,n=0,l=0; nDim(1); ++n) { int col = (*selection)[l++]; int row = (*selection)[l++]; list.push_back(wxPoint(row,col)); } } SizeT k=0; DStructGDL* typecodes = new DStructGDL( "GDL_TYPECODES_AS_STRUCT"); // creating the output anonymous structure DStructDesc* res_desc = new DStructDesc("$truct"); for ( std::vector::iterator it = list.begin(); it !=list.end(); ++it, ++k) { //get tag values: BaseGDL* tested; if (majority == GDLWidgetTable::ROW_MAJOR ) tested=static_cast(vValue)->GetTag((*it).y); //table columns are tags else tested=static_cast(vValue)->GetTag((*it).x); //table rows are tags stringstream os; os << std::setfill ('_') << std::setw (12) << k ; //as IDL does std::string tagName; os >> tagName; res_desc->AddTag(tagName, typecodes->GetTag(tested->Type())); } stringstream is; for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n'; res = new DStructGDL(res_desc, dimension()); res->FromStream( is); } else { //IDL maintains the 2D-structure of val! int colTL,colBR,rowTL,rowBR; if (selection->Rank()==0) { wxArrayInt block=grid->GetSelectedBlockOfCells(); //normally only ONE block is available. colTL = block[0]; rowTL = block[1]; colBR = block[2]; rowBR = block[3]; } else { colTL = (*selection)[0]; rowTL = (*selection)[1]; colBR = (*selection)[2]; rowBR = (*selection)[3]; } //complication: if only one row (col) is selected, result is an array of . //else result is a structure with correct tag names. Very clever! if ((majority == GDLWidgetTable::ROW_MAJOR && colTL==colBR)||(majority == GDLWidgetTable::COLUMN_MAJOR && rowTL==rowBR)) { DType what=GDL_BYTE; SizeT size; if (majority == GDLWidgetTable::ROW_MAJOR && colTL==colBR) { what=static_cast(vValue)->GetTag(colTL)->Type(); size=rowBR-rowTL+1; } else if (rowTL==rowBR) { what=static_cast(vValue)->GetTag(rowTL)->Type(); size=colBR-colTL+1; } switch(what) { case GDL_STRING: res=new DStringGDL(dimension(size)); break; case GDL_BYTE: res=new DByteGDL(dimension(size)); break; case GDL_INT: res=new DIntGDL(dimension(size)); break; case GDL_LONG: res=new DLongGDL(dimension(size)); break; case GDL_FLOAT: res=new DFloatGDL(dimension(size)); break; case GDL_DOUBLE: res=new DDoubleGDL(dimension(size)); break; case GDL_COMPLEX: res=new DComplexGDL(dimension(dimension(size))); break; case GDL_COMPLEXDBL: res=new DComplexDblGDL(dimension(size)); break; case GDL_UINT: res=new DUIntGDL(dimension(size)); break; case GDL_ULONG: res=new DULongGDL(dimension(size)); break; case GDL_LONG64: res=new DLong64GDL(dimension(size)); break; case GDL_ULONG64: res=new DULong64GDL(dimension(size)); break; default: cerr<<"Unhandled Table Type, please report!"<(vValue)->GetTag(j); tagName=static_cast(vValue)->Desc()->TagName(j); //preserve tag names res_desc->AddTag(tagName, typecodes->GetTag(tested->Type())); } } else { size=colBR-colTL+1; for (SizeT i=rowTL; i<=rowBR; ++i) { //get tag values: BaseGDL* tested; std::string tagName; tested=static_cast(vValue)->GetTag(i); tagName=static_cast(vValue)->Desc()->TagName(i); //preserve tag names res_desc->AddTag(tagName, typecodes->GetTag(tested->Type())); } } //create res with correct dim: res = new DStructGDL(res_desc, dimension(size)); } //populate res: stringstream is; for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n'; res->FromStream( is); } } return res; } DStringGDL* GDLWidgetTable::GetTableValues(DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); DStringGDL * stringres; int numRows=valueAsStrings->Dim(0); int numCols=valueAsStrings->Dim(1); if ( selection==NULL ){ int ncols=grid->GetNumberCols(); int nrows=grid->GetNumberCols(); SizeT dims[2]; dims[1]=(nrows>numRows)?numRows:nrows; dims[0]=(ncols>numCols)?numCols:ncols; dimension dim(dims,2); stringres=new DStringGDL(dim); for ( int ival=0, i=0; iGetCellValue( i, j).mb_str(wxConvUTF8); } } else { //use the wxWidget selection or the passed selection, mode-dependent: if (disjointSelection) { //pairs lists if (selection->Rank()==0) { //use current wxWidgets selection std::vector list=grid->GetSelectedDisjointCellsList(); stringres=new DStringGDL(list.size()); SizeT k=0; for ( std::vector::iterator it = list.begin(); it !=list.end(); ++it) { if ((*it).x >= numRows || (*it).y >= numCols) return static_cast(NULL); (*stringres)[k++]=grid->GetCellValue( (*it).x, (*it).y ).mb_str(wxConvUTF8); } } else { stringres=new DStringGDL(selection->Dim(1)); for (SizeT k=0,n=0,l=0; nDim(1); ++n) { int col = (*selection)[l++]; int row = (*selection)[l++]; if ( row >= numRows || col >= numCols) return static_cast(NULL); (*stringres)[k++]=grid->GetCellValue( row, col).mb_str(wxConvUTF8); } } } else { //IDL maintains the 2D-structure of val! int colTL,colBR,rowTL,rowBR; if (selection->Rank()==0) { wxArrayInt block=grid->GetSelectedBlockOfCells(); //normally only ONE block is available. colTL = block[0]; rowTL = block[1]; colBR = block[2]; rowBR = block[3]; } else { colTL = (*selection)[0]; rowTL = (*selection)[1]; colBR = (*selection)[2]; rowBR = (*selection)[3]; } SizeT dims[2]; dims[1]=(rowBR-rowTL+1); dims[0]=(colBR-colTL+1); dimension dim(dims,2); stringres=new DStringGDL(dim); for (SizeT k=0,i=rowTL; i<=rowBR; ++i) for (SizeT j=colTL; j<=colBR; ++j) { if ( i >= numRows || j >= numCols) return static_cast(NULL); (*stringres)[k++]=grid->GetCellValue(i, j).mb_str(wxConvUTF8); } } } //convention: if value is of type struct, string array will always be row_major. thus if we are column major, transpose return string array if (vValue->Type()==GDL_STRUCT && majority==GDLWidgetTable::COLUMN_MAJOR) return static_cast(stringres->Transpose(NULL))->Dup(); else return stringres; } void GDLWidgetTable::SetSelection(DLongGDL* selection) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); updating=TRUE; //prevent sending unwanted events grid->ClearSelection(); wxPoint firstVisible=wxPoint(0,0); if (disjointSelection) { //pairs lists SizeT k=0; for (SizeT i=0; i< selection->Dim(1); ++i) { int col=(*selection)[k++]; int row=(*selection)[k++]; grid->SelectBlock(row,col,row,col,TRUE); if (k==2) {firstVisible.x=row;firstVisible.y=col;} } } else { int colTL = (*selection)[0]; int rowTL = (*selection)[1]; int colBR = (*selection)[2]; int rowBR = (*selection)[3]; grid->SelectBlock(rowTL,colTL,rowBR,colBR,FALSE); firstVisible.x=rowTL;firstVisible.y=colTL; } grid->EndBatch( ); grid->MakeCellVisible(firstVisible.x,firstVisible.y); UPDATE_WINDOW updating=FALSE; //allow events } void GDLWidgetTable::SetTableView(DLongGDL* pos) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->MakeCellVisible((*pos)[1],(*pos)[0]); } void GDLWidgetTable::EditCell(DLongGDL* pos) { gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->SetReadOnly((*pos)[0],(*pos)[1],FALSE); } void GDLWidgetTable::SetTableNumberOfColumns( DLong ncols){ gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); int old_ncols=grid->GetNumberCols(); int numRows=valueAsStrings->Dim(0); int numCols=valueAsStrings->Dim(1); if (ncols > old_ncols) { grid->AppendCols(ncols-old_ncols); if (numCols > old_ncols) { int colTL,colBR,rowTL,rowBR; colTL=old_ncols-1; colBR=ncols-1; rowTL=0; rowBR=grid->GetNumberRows()-1; for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j) { if (i < numRows && j < numCols ) grid->SetCellValue( i, j ,wxString(((*valueAsStrings)[j*numRows+i]).c_str(), wxConvUTF8 ) ); } } } else grid->DeleteCols(ncols,old_ncols-ncols); grid->EndBatch( ); } void GDLWidgetTable::SetTableNumberOfRows( DLong nrows){ gdlGrid * grid = static_cast (wxWidget); assert( grid != NULL); grid->BeginBatch( ); SizeT old_nrows=grid->GetNumberRows(); int numRows=valueAsStrings->Dim(0); int numCols=valueAsStrings->Dim(1); if (nrows > old_nrows) { grid->AppendRows(nrows-old_nrows); if (numRows > old_nrows) { int colTL,colBR,rowTL,rowBR; colTL=0; colBR=grid->GetNumberCols()-1; rowTL=old_nrows-1; rowBR=nrows-1; for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j) { if (i < numRows && j < numCols ) grid->SetCellValue( i, j ,wxString(((*valueAsStrings)[j*numRows+i]).c_str(), wxConvUTF8 ) ); } } } else grid->DeleteRows(nrows,old_nrows-nrows); grid->EndBatch( ); } DStructGDL* GDLWidgetTable::GetGeometry(wxRealPoint fact) { int ixs=0, iys=0, ixscr=0, iyscr=0; float xs, ys, xscr, yscr, xoff, yoff, margin=0; wxPoint position; int rowsize=1; int rowlabelsize=0; int colsize=1; int collabelsize=0; gdlGrid* grid = static_cast (wxWidget); assert( grid != NULL); if ( grid != NULL ) { grid->GetClientSize( &ixs, &iys ); ixscr=ixs; iyscr=iys; position = grid->GetPosition( ); rowsize=grid->GetRowSize(0); rowlabelsize=grid->GetRowLabelSize(); colsize=grid->GetColSize(0); collabelsize=grid->GetColLabelSize(); } if (frameSizer != NULL) {framePanel->GetSize(&ixscr,&iyscr); margin = gdlFRAME_MARGIN / fact.x;} if (scrollSizer != NULL) {scrollPanel->GetSize(&ixscr,&iyscr);ixs=ixscr-gdlSCROLL_WIDTH;iys=iyscr-gdlSCROLL_WIDTH;} //size is in pixels, pass in requested units (1.0 default) xs = (ixs-rowlabelsize) / colsize ; ys = (iys-collabelsize) / rowsize ; xscr = ixscr / fact.x; yscr = iyscr / fact.y; xoff = position.x / fact.x; yoff = position.y / fact.y; DStructGDL* ex = new DStructGDL( "WIDGET_GEOMETRY" ); ex->InitTag( "XOFFSET", DFloatGDL( xoff) ); ex->InitTag( "YOFFSET", DFloatGDL( yoff ) ); ex->InitTag( "XSIZE", DFloatGDL( xs ) ); ex->InitTag( "YSIZE", DFloatGDL( ys ) ); ex->InitTag( "SCR_XSIZE", DFloatGDL( xscr ) ); ex->InitTag( "SCR_YSIZE", DFloatGDL( yscr ) ); ex->InitTag( "MARGIN", DFloatGDL( margin ) ); return ex; } GDLWidgetTable::~GDLWidgetTable() { #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetTable: " << this << std::endl; #endif GDLDelete( table_alignment ); GDLDelete( editable ); GDLDelete( amPm ); GDLDelete( backgroundColor ); GDLDelete( foregroundColor ); GDLDelete( columnLabels ); GDLDelete( columnWidth ); GDLDelete( daysOfWeek ); GDLDelete( format ); GDLDelete( month ); GDLDelete( rowHeights ); GDLDelete( rowLabels ); GDLDelete( valueAsStrings ); } /*********************************************************/ // for WIDGET_TREE /*********************************************************/ GDLWidgetTree::GDLWidgetTree( WidgetIDT p, EnvT* e, BaseGDL* value_, DULong eventFlags_ //,bool alignBottom_ //,bool alignTop_ ,wxBitmap* bitmap //,bool checkbox_ //,DLong checked_ //,DString dragNotify_ ,DLong dragability ,DLong dropability ,bool expanded_ ,bool folder_ ,DLong treeindex //,bool mask_ //,bool multiple_ //,bool noBitmaps_ //,DLong tabMode_ //,DString toolTip_ ) : GDLWidget( p, e, value_, eventFlags_ ) //,alignBottom( alignBottom_ ) //,alignTop( alignTop_ ) //,checkbox( checkbox_ ) //,checked( checked_ ) //,dragNotify( dragNotify_ ) ,droppable( FALSE ) ,draggable( FALSE ) //,mask( mask_ ) //,multiple( multiple_ ) //,noBitmaps( noBitmaps_ ) //,tabMode( tabMode_ ) //,toolTip( toolTip_ ) ,expanded(expanded_) ,folder(folder_) //,treeItemID( 0L ) //is an object! ,rootID(0L) ,buttonImageId(0L) ,imageId(0L) ,treeItemData(NULL) { GDLWidget* gdlParent = GetWidget( parentID ); wxPanel *panel = gdlParent->GetPanel( ); widgetPanel = panel; widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget( parentID )->GetSizer( ); DStringGDL* value=static_cast(vValue); if ( gdlParent->IsBase( ) ) { if ( xSize <= 0 ) xSize = 200; //yes, has a default value! if ( ySize <= 0 ) ySize = 200; long style = (wxTR_HIDE_ROOT|wxTR_DEFAULT_STYLE| wxTR_HAS_BUTTONS | wxSUNKEN_BORDER | wxTR_TWIST_BUTTONS) ; // should be as of 2.9.0: wxDataViewTreeCtrl* tree = new gdlTreeCtrl( widgetPanel, widgetID, gdlTreeCtrl* tree = new gdlTreeCtrl( widgetPanel, widgetID, wxPoint( xOffset, yOffset ), computeWidgetSize( ), style ); //our widget will ALWAYS have an image list... wxImageList* images=new wxImageList(16,16,TRUE,3); images->Add(wxArtProvider::GetBitmap(wxART_FOLDER)); //0 images->Add(wxArtProvider::GetBitmap(wxART_FOLDER_OPEN)); //1 images->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE)); //2 images->Add(wxArtProvider::GetBitmap(wxART_FILE_OPEN)); //3 tree->AssignImageList(images); folder=TRUE; this->wxWidget = tree; rootID=widgetID; treeItemData=new gdlTreeItemData(widgetID); if (bitmap) { int index=images->Add(*bitmap); treeItemID = tree->AddRoot(wxString( (*value)[0].c_str( ), wxConvUTF8 ), index ,-1, treeItemData); } else { //use open and closed folder icons treeItemID = tree->AddRoot(wxString( (*value)[0].c_str( ), wxConvUTF8 ), 0 ,1, treeItemData); } widgetStyle=widgetAlignment( ); widgetSizer->Add( tree, 0, widgetStyle, 0 ); if ( (frameWidth>0) ) this->FrameWidget( ); draggable=(dragability == 1); droppable=(dropability == 1); // tree->Expand(treeItemID); //do not expand root if hidden TIDY_WIDGET; UPDATE_WINDOW } else { GDLWidgetTree* parentTree = static_cast (gdlParent); assert( parentTree != NULL); wxWidget = parentTree->GetWxWidget( ); rootID = parentTree->GetRootID(); treeItemData=new gdlTreeItemData(widgetID); gdlTreeCtrl * tree = static_cast (wxWidget); assert( tree != NULL); wxImageList* images=tree->GetImageList(); //if image is provided use it otherwise (since no image is a bit disappointing) use an internal wxWigdets icon if (bitmap) { int imindex=images->Add(*bitmap); if (treeindex>-1) treeItemID = tree->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) , imindex ,-1, treeItemData); else treeItemID = tree->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) , imindex ,-1, treeItemData); } else { //use open and closed folder icons if (folder) { if (treeindex>-1) treeItemID = tree->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,0,1, treeItemData); else treeItemID = tree->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,0,1, treeItemData); } else if (treeindex>-1) treeItemID = tree->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,2,3, treeItemData); else treeItemID = tree->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,2,3, treeItemData); } if ( parentTree->IsFolder() && parentTree->IsExpanded()) parentTree->DoExpand(); //dragability inheritance. if (dragability == -1) draggable=parentTree->IsDraggable(); else draggable=(dragability == 1); //dropability inheritance. if (dropability == -1) droppable=parentTree->IsDroppable(); else droppable=(dropability == 1); } } DInt GDLWidgetTree::GetTreeIndex() { DInt count=0; gdlTreeCtrl* tree=static_cast(wxWidget); assert( tree != NULL); wxTreeItemId id=this->treeItemID; wxTreeItemId prev_id=tree->GetPrevSibling(id); while (prev_id.IsOk()){ count++; id=prev_id; prev_id=tree->GetPrevSibling(id); } return count+1; //to give compatible results with idl -- wxwidgets does not behave as idl! } GDLWidgetTree::~GDLWidgetTree() { #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetTree: " << this << std::endl; #endif gdlTreeCtrl* tree=static_cast(wxWidget); if (tree) { wxTreeItemId id=this->treeItemID; if (id.IsOk()) { wxTreeItemIdValue cookie; wxTreeItemId child=tree->GetFirstChild(id, cookie); while (child.IsOk()) { WidgetIDT childID=static_cast(tree->GetItemData(child))->widgetID; GDLWidgetTree* GDLchild= static_cast(GDLWidget::GetWidget(childID)); child=tree->GetNextSibling(child); //nextChild did not find the last (?) nextSibling does the job. delete GDLchild; } treeItemID.Unset(); tree->Delete(id); } } } void GDLWidgetTree::SetValue(DString val) { GDLDelete(vValue); vValue=new DStringGDL(val); gdlTreeCtrl* tree=static_cast(wxWidget); assert( tree != NULL); tree->SetItemText(treeItemID, wxString( val.c_str( ), wxConvUTF8 )); } /*********************************************************/ // for WIDGET_SLIDER /*********************************************************/ GDLWidgetSlider::GDLWidgetSlider( WidgetIDT p, EnvT* e, DLong value_ , DULong eventFlags_ , DLong minimum_ , DLong maximum_ , bool vertical , bool suppressValue , DString title_ ) : GDLWidget( p, e, NULL, eventFlags_ ) , value( value_ ) //should disappear , duplicates vValue! , minimum( minimum_ ) , maximum( maximum_ ) , title( title_) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); if (( xSize <= 0 ) && !vertical) xSize=200; //yes, has a default value! if (( ySize <= 0 ) && vertical) ySize=200; long style = wxSL_HORIZONTAL; if ( vertical ) style = wxSL_VERTICAL; if ( !suppressValue ) { #if wxCHECK_VERSION(2,9,1) style |= wxSL_VALUE_LABEL; #else style |= wxSL_LABELS; #endif } wxSlider * slider; widgetStyle=widgetAlignment(); if (title.size()>0){ wxBoxSizer *sz = new wxBoxSizer(wxVERTICAL); wxPanel *p = new wxPanel(widgetPanel, wxID_ANY , wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN); slider = new wxSlider( p, widgetID, value, minimum, maximum, wxPoint( xOffset, yOffset ), computeWidgetSize( ), style ); wxStaticText *st=new wxStaticText(p,wxID_ANY,wxString( title.c_str( ), wxConvUTF8 )); sz->Add(slider); sz->Add(st); p->SetSizer(sz); widgetSizer->Add(p, 0, widgetStyle, 0); // if ((frameWidth>0)) this->FrameWidget(); //do not frame (problems: would need a different widget): already framed by default. } else { slider = new wxSlider( widgetPanel , widgetID, value, minimum, maximum, wxPoint( xOffset, yOffset ), computeWidgetSize( ), style ); widgetSizer->Add(slider, 0, widgetStyle, 0 ); widgetStyle=(wxEXPAND | wxALL); // if ((frameWidth>0)) this->FrameWidget(); //do not frame, crashes on a bug (FIXME). } this->wxWidget = slider; slider->Connect(widgetID,wxEVT_SCROLL_CHANGED,wxScrollEventHandler(GDLFrame::OnThumbRelease)); //dynamically select drag, saves resources! (note: there is no widget_control,/drag for sliders) if ( eventFlags & GDLWidget::EV_DRAG ) slider->Connect(widgetID,wxEVT_SCROLL_THUMBTRACK,wxScrollEventHandler(GDLFrame::OnThumbTrack)); TIDY_WIDGET; UPDATE_WINDOW } void GDLWidgetSlider::ControlSetValue(DLong v){ value=v; wxSlider* s=static_cast(wxWidget); assert( s != NULL); s->SetValue(v); } void GDLWidgetSlider::ControlSetMinValue(DLong v) { value = v; wxSlider* s = static_cast (wxWidget); assert(s != NULL); s->SetRange(v, s->GetMax()); } void GDLWidgetSlider::ControlSetMaxValue(DLong v) { value = v; wxSlider* s = static_cast (wxWidget); assert(s != NULL); s->SetRange(s->GetMin(),v); } GDLWidgetSlider::~GDLWidgetSlider(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetSlider(): " << widgetID << std::endl; #endif } GDLWidgetButton::GDLWidgetButton( WidgetIDT p, EnvT* e, const DString& value , DULong eventflags, bool isMenu, bool hasSeparatorAbove, wxBitmap* bitmap_, DStringGDL* buttonToolTip) : GDLWidget( p, e, NULL, eventflags ) , buttonType( UNDEFINED ) , addSeparatorAbove(hasSeparatorAbove) , buttonBitmap(bitmap_) , menuItem(NULL) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); //update vValue delete(vValue); vValue = new DStringGDL( value ); if ( gdlParent->IsMenuBar( ) ) { //A button in a menubar is automatically a MENU wxMenuBar *menuBar = static_cast (gdlParent->GetWxWidget( )); assert( menuBar != NULL); wxMenu* menu = new wxMenu( ); wxWidget = menu; wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); menuBar->Append( menu, valueWxString ); buttonType = MENU; } else { if ( gdlParent->IsBase( ) && isMenu ) { //A menu button in a base is a button starting a popup menu. it is a container also. wxString MenuTitle = wxString( value.c_str( ), wxConvUTF8 ); //2 different buttons, if bitmap or not, waiting for version > 2.9.1 to have bitmaps handled for ALL buttontypes: if (bitmap_ == NULL) { gdlMenuButton *button = new gdlMenuButton( widgetPanel, widgetID, MenuTitle, wxPoint( xOffset, yOffset ) , computeWidgetSize( ), buttonTextAlignment()); buttonType = POPUP_NORMAL; //gdlMenuButton is a wxButton --> normal. Bitmaps will be supported starting from 2.9.1 wxWidget = button; // wxWidget = button->GetPopupMenu(); wxWindow* win=static_cast(button); if (buttonToolTip) win->SetToolTip( wxString((*buttonToolTip)[0].c_str(),wxConvUTF8)); widgetSizer->Add( win, 0, widgetAlignment(), 0); } else { gdlMenuButtonBitmap *button = new gdlMenuButtonBitmap( widgetPanel, widgetID, *bitmap_, wxPoint( xOffset, yOffset ) , computeWidgetSize( ), buttonTextAlignment()); buttonType = POPUP_BITMAP; // wxWidget = button; // wxWidget = button->GetPopupMenu(); wxWindow* win=static_cast(button); if (buttonToolTip) win->SetToolTip( wxString((*buttonToolTip)[0].c_str(),wxConvUTF8)); widgetSizer->Add( win, 0, widgetAlignment(), 0); } if ((frameWidth>0)) { widgetStyle= widgetAlignment(); this->FrameWidget();} widgetSizer->Layout(); TIDY_WIDGET; UPDATE_WINDOW // Check influence of: // widgetType=GDLWidget::WIDGET_MBAR; } else if( gdlParent->IsButton()) //so it is a container { //get default value: a menu. May be NULL here wxMenu *menu = static_cast (gdlParent->GetWxWidget( )); //special treatment for popups menus: the menu is retrieved differently GDLWidgetButton* whatSortofBut=static_cast(gdlParent); if (whatSortofBut->buttonType==POPUP_NORMAL ) { menu=static_cast(whatSortofBut->GetWxWidget())->GetPopupMenu(); } else if (whatSortofBut->buttonType==POPUP_BITMAP ) { menu=static_cast(whatSortofBut->GetWxWidget())->GetPopupMenu(); } else { if ( dynamic_cast (gdlParent->GetWxWidget( )) == NULL ) { if (e!=NULL) { e->Throw("Parent is of incorrect type."); } else { //yes, e may be null. Not here, but for draw windows. cerr<<"Impossible case of null environment, please report to authors!"<AppendSeparator(); wxMenu *submenu=new wxMenu( ); wxWidget = submenu; wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); if (bitmap_) { menuItem = menu->AppendSubMenu(submenu, wxString( " ", wxConvUTF8 ) ); //the ' ' is needed. Null strings raise complaints by wxWidgets (???) menuItem->SetBitmap(*bitmap_); } else { menuItem = menu->AppendSubMenu(submenu, valueWxString ); } buttonType = MENU; TIDY_WIDGET; UPDATE_WINDOW } else //only an entry. { wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); if (bitmap_) { menuItem = new wxMenuItem( menu, widgetID, wxString( " ", wxConvUTF8 ) ); //the ' ' is needed. Null strings raise complaints by wxWidgets (???) menuItem->SetBitmap(*bitmap_); } else { menuItem = new wxMenuItem( menu, widgetID, valueWxString ); } if (addSeparatorAbove) menu->AppendSeparator(); menu->Append( menuItem ); wxWidget = NULL; // should be menuItem; but is not even a wxWindow! buttonType = ENTRY; } } else cerr<<"Warning GDLWidgetButton::GDLWidgetButton(): widget type confusion(2)\n"; } else { //we deliberately prevent exclusive buttons when bitmap are present (exclusive buttons w/ pixmap do not exist in wxWidgets. if ( gdlParent->GetExclusiveMode() == BGNORMAL || bitmap_ ) { if (bitmap_){ wxBitmapButton *button = new wxBitmapButton( widgetPanel, widgetID, *bitmap_, wxPoint( xOffset, yOffset ) ,computeWidgetSize( )); this->wxWidget = button; buttonType = BITMAP; button->Connect(widgetID, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(GDLFrame::OnButton)); } else { wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); wxButton *button = new wxButton( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ) , computeWidgetSize( ), buttonTextAlignment()); this->wxWidget = button; buttonType = NORMAL; button->Connect(widgetID, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(GDLFrame::OnButton)); } } else if ( gdlParent->GetExclusiveMode() == BGEXCLUSIVE1ST) { wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); wxRadioButton *radioButton = new wxRadioButton( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ), computeWidgetSize( ), //wxDefaultSize, wxRB_GROUP ); gdlParent->SetExclusiveMode( 1 ); GDLWidgetBase* b=static_cast (gdlParent); if (b) b->SetLastRadioSelection( widgetID ); else cerr<<"Warning GDLWidgetButton::GDLWidgetButton(): widget type confusion(3)\n"; this->wxWidget = radioButton; radioButton->Connect(widgetID, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler(GDLFrame::OnRadioButton)); buttonType = RADIO; } else if ( gdlParent->GetExclusiveMode() == BGEXCLUSIVE) { wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); wxRadioButton *radioButton = new wxRadioButton( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ), computeWidgetSize( ) ); this->wxWidget = radioButton; radioButton->Connect(widgetID, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler(GDLFrame::OnRadioButton)); buttonType = RADIO; } else if ( gdlParent->GetExclusiveMode() == BGNONEXCLUSIVE) { wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); wxCheckBox *checkBox = new wxCheckBox( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ),computeWidgetSize( ) ); this->wxWidget = checkBox; checkBox->Connect(widgetID, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(GDLFrame::OnCheckBox)); buttonType = CHECKBOX; } wxWindow *win=static_cast(wxWidget); if (win) { if (buttonToolTip) win->SetToolTip( wxString((*buttonToolTip)[0].c_str(),wxConvUTF8)); widgetSizer->Add( win, 0, widgetAlignment(), 0); } else cerr<<"Warning GDLWidgetButton::GDLWidgetButton(): widget type confusion(4)\n"; if ((frameWidth>0)) { widgetStyle= widgetAlignment(); this->FrameWidget();} widgetSizer->Layout(); TIDY_WIDGET; UPDATE_WINDOW } } } GDLWidgetButton::~GDLWidgetButton(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetButton(): " << widgetID << std::endl; #endif switch(buttonType){ case MENU: case ENTRY: if (menuItem) { menuItem->GetMenu()->Remove(menuItem); //do not destroy the wxWidgets object, troubles will follow. } break; default: break; } } void GDLWidgetButton::SetButtonWidgetLabelText( const DString& value_ ) { if ( buttonType == BITMAP ) return; if ( buttonType == POPUP_BITMAP ) return; if ( buttonType == UNDEFINED ) return; //update vValue delete(vValue); vValue = new DStringGDL( value_ ); if ( buttonType == NORMAL ) { if ( this->wxWidget != NULL ) { wxButton *b = static_cast (wxWidget); assert(b!=NULL); b->SetLabel( wxString( value_.c_str( ), wxConvUTF8 ) ); } else std::cerr << "Null widget in GDLWidgetButton::SetButtonWidgetLabelText(), please report!" << std::endl; return; } if ( buttonType == POPUP_NORMAL ) { if ( this->wxWidget != NULL ) { wxButton *b = static_cast (wxWidget); assert(b!=NULL); b->SetLabel( wxString( value_.c_str( ), wxConvUTF8 ) ); } else std::cerr << "Null widget in GDLWidgetButton::SetButtonWidgetLabelText(), please report!" << std::endl; return; } if ( buttonType == RADIO ) { if ( this->wxWidget != NULL ) { wxRadioButton *b = static_cast (wxWidget); assert(b!=NULL); b->SetLabel( wxString( value_.c_str( ), wxConvUTF8 ) ); } else std::cerr << "Null widget in GDLWidgetButton::SetButtonWidgetLabelText(), please report!" << std::endl; return; } if ( buttonType == MENU || buttonType ==ENTRY) { if ( menuItem != NULL ) { menuItem->SetItemLabel( wxString( value_.c_str( ), wxConvUTF8 ) ); } else std::cerr << "Problem in GDLWidgetButton::SetButtonWidgetLabelText(), please report!" << std::endl; return; } if ( buttonType == CHECKBOX ) { if ( this->wxWidget != NULL ) { wxCheckBox *b = static_cast (wxWidget); assert(b!=NULL); b->SetLabel( wxString( value_.c_str( ), wxConvUTF8 ) ); } else std::cerr << "Null widget in GDLWidgetButton::SetButtonWidgetLabelText(), please report!" << std::endl; return; } } void GDLWidgetButton::SetButtonWidgetBitmap( wxBitmap* bitmap_ ) { if ( buttonType == POPUP_NORMAL ) return; if ( buttonType == BITMAP || buttonType == POPUP_BITMAP ) { wxBitmapButton *b = static_cast (wxWidget); if ( b ) b->SetBitmapLabel( *bitmap_ ); return; } if ( buttonType == MENU || buttonType ==ENTRY) { if ( menuItem != NULL ) menuItem->SetBitmap( *bitmap_ ); return; } //probably not useful yet - TBC #if wxCHECK_VERSION(2,9,1) if ( buttonType == NORMAL ) { wxButton *b = static_cast (wxWidget); if ( b ) b->SetBitmapLabel( *bitmap_ ); } #endif } GDLWidgetList::GDLWidgetList( WidgetIDT p, EnvT* e, BaseGDL *value, DLong style, DULong eventflags ) : GDLWidget( p, e, value, eventflags) , maxlinelength(0) , nlines(0) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); if( vValue->Type() != GDL_STRING) { vValue = static_cast (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT )); } DStringGDL* val = static_cast (vValue); nlines = val->N_Elements( ); wxArrayString choices; // = new wxString[n]; for ( SizeT i = 0; i < nlines; ++i ){ int length=(*val)[i].length(); maxlinelength=(length>maxlinelength)?length:maxlinelength; choices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) ); } wxListBox * list = new wxListBox( gdlParent->GetPanel( ), widgetID, wxPoint( xOffset, yOffset ), computeWidgetSize( ), choices, style|wxLB_NEEDED_SB ); this->wxWidget = list; list->Connect(widgetID,wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,wxCommandEventHandler(GDLFrame::OnListBoxDoubleClicked)); list->Connect(widgetID,wxEVT_COMMAND_LISTBOX_SELECTED,wxCommandEventHandler(GDLFrame::OnListBox)); list->SetSelection(wxNOT_FOUND);//necessary to avoid spurious event on first click. widgetStyle=widgetAlignment(); if ((frameWidth>0)) this->FrameWidget(); else widgetSizer->Add(list, 0, widgetStyle, 0); TIDY_WIDGET; UPDATE_WINDOW } void GDLWidgetList::SetValue(BaseGDL *value){ GDLDelete(vValue); vValue=value; if( vValue->Type() != GDL_STRING) { vValue = static_cast (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT )); } DStringGDL* val = static_cast (vValue); wxArrayString newchoices; // = new wxString[n]; for ( SizeT i = 0; i < val->N_Elements( ); ++i ) newchoices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) ); wxListBox * list = static_cast(wxWidget); assert( list != NULL); list->Clear(); list->InsertItems(newchoices,0); list->SetSelection(wxNOT_FOUND); } void GDLWidgetList::SelectEntry(DLong entry_number){ wxListBox * list=static_cast(wxWidget); assert( list != NULL); list->Select(entry_number); } BaseGDL* GDLWidgetList::GetSelectedEntries(){ wxListBox * list=static_cast(wxWidget); assert( list != NULL); wxArrayInt selections; list->GetSelections(selections); DIntGDL* liste; if (selections.Count()<1) { liste=new DIntGDL(-1); return liste; } liste=new DIntGDL(dimension(selections.Count())); for (SizeT i=0; i< selections.Count(); ++i) (*liste)[i]=selections[i]; return liste; } DStructGDL* GDLWidgetList::GetGeometry(wxRealPoint fact) { int ixs=0, iys=0, ixscr=0, iyscr=0; float xs, ys, xscr, yscr, xoff, yoff, margin; wxPoint position; wxSize fontSize=wxNORMAL_FONT->GetPixelSize(); wxListBox* test = static_cast (wxWidget); assert( test != NULL); if ( test != NULL ) { test->GetClientSize( &ixs, &iys ); ixscr=ixs; iyscr=iys; position = test->GetPosition( ); fontSize = test->GetFont().GetPixelSize(); } //Apparently Windows may return 0 for fontsize.x (probably if too small)? if (fontSize.x == 0) fontSize.x=0.65*fontSize.y; //last chance to get a correct value if (fontSize.x == 0) fontSize.x=1; if (fontSize.y == 0) fontSize.y=1; if (frameSizer != NULL) {framePanel->GetSize(&ixscr,&iyscr); margin = gdlFRAME_MARGIN / fact.x;} if (scrollSizer != NULL) {scrollPanel->GetSize(&ixscr,&iyscr);ixs=ixscr-gdlSCROLL_WIDTH;iys=iyscr-gdlSCROLL_WIDTH;} //size is in pixels, pass in requested units (1.0 default) xs = ixs / fontSize.x; ys = iys / fontSize.y; xscr = ixscr / fact.x; yscr = iyscr / fact.y; xoff = position.x / fact.x; yoff = position.y / fact.y; DStructGDL* ex = new DStructGDL( "WIDGET_GEOMETRY" ); ex->InitTag( "XOFFSET", DFloatGDL( xoff) ); ex->InitTag( "YOFFSET", DFloatGDL( yoff ) ); ex->InitTag( "XSIZE", DFloatGDL( xs ) ); ex->InitTag( "YSIZE", DFloatGDL( ys ) ); ex->InitTag( "SCR_XSIZE", DFloatGDL( xscr ) ); ex->InitTag( "SCR_YSIZE", DFloatGDL( yscr ) ); ex->InitTag( "MARGIN", DFloatGDL( margin ) ); return ex; } GDLWidgetList::~GDLWidgetList(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetList: " << this << std::endl; #endif } GDLWidgetDropList::GDLWidgetDropList( WidgetIDT p, EnvT* e, BaseGDL *value, DULong eventflags , const DString& title_, DLong style_ ) : GDLWidget( p, e, static_cast (value->Convert2( GDL_STRING, BaseGDL::CONVERT )), eventflags) , title( title_ ) , style( style_) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); DStringGDL* val = static_cast (vValue); DLong n = val->N_Elements( ); wxArrayString choices; // = new wxString[n]; for ( SizeT i = 0; i < n; ++i ) {choices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) );} wxChoice * droplist = new wxChoice( widgetPanel, widgetID, wxPoint( xOffset, yOffset ), computeWidgetSize( ), choices, style ); droplist->SetSelection(0); this->wxWidget = droplist; widgetStyle=widgetAlignment(); if (title.size()>0){ wxBoxSizer *sz = new wxBoxSizer(wxHORIZONTAL); wxPanel *p = new wxPanel(widgetPanel); wxStaticText *st=new wxStaticText(p,wxID_ANY,wxString( title.c_str( ), wxConvUTF8 )); droplist->Reparent(p); sz->Add(st, 0, wxALIGN_CENTRE, 0); sz->AddSpacer(5); sz->Add(droplist, 0, wxALIGN_CENTRE, 0); p->SetSizer(sz); widgetSizer->Add(p, 0, widgetStyle, 0); } else { widgetSizer->Add( droplist, 0, widgetStyle, 0); if ((frameWidth>0)) this->FrameWidget(); } droplist->Connect(widgetID, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(GDLFrame::OnDropList)); TIDY_WIDGET; UPDATE_WINDOW } void GDLWidgetDropList::SetValue(BaseGDL *value){ GDLDelete(vValue); vValue=value; if( vValue->Type() != GDL_STRING) { vValue = static_cast (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT )); } DStringGDL* val = static_cast (vValue); wxArrayString newchoices; // = new wxString[n]; for ( SizeT i = 0; i < val->N_Elements( ); ++i ) newchoices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) ); wxChoice* droplist=static_cast(wxWidget); assert( droplist != NULL); droplist->Clear(); droplist->Append(newchoices); droplist->SetSelection(0); } void GDLWidgetDropList::SelectEntry(DLong entry_number){ wxChoice * droplist=static_cast(wxWidget); assert( droplist != NULL); droplist->Select(entry_number); } BaseGDL* GDLWidgetDropList::GetSelectedEntry(){ wxChoice * droplist=static_cast(wxWidget); assert( droplist != NULL); return new DIntGDL(droplist->GetSelection()); } GDLWidgetDropList::~GDLWidgetDropList(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetDroplist: " << this << std::endl; #endif } GDLWidgetComboBox::GDLWidgetComboBox( WidgetIDT p, EnvT* e, BaseGDL *value, DULong eventflags, const DString& title_, DLong style_ ) : GDLWidget( p, e, static_cast (value->Convert2( GDL_STRING, BaseGDL::CONVERT )) , eventflags) , title( title_ ) , style( style_) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); DStringGDL* val = static_cast (vValue); DLong n = val->N_Elements( ); wxArrayString choices; // = new wxString[n]; for ( SizeT i = 0; i < n; ++i ) choices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) ); wxString val0WxString = wxString( (*val)[0].c_str( ), wxConvUTF8 ); wxComboBox * combo = new wxComboBox( widgetPanel, widgetID, val0WxString, wxPoint( xOffset, yOffset ), computeWidgetSize( ), choices, style ); this->wxWidget = combo; combo->Connect(widgetID,wxEVT_COMMAND_COMBOBOX_SELECTED,wxCommandEventHandler(GDLFrame::OnComboBox)); if (style & wxTE_PROCESS_ENTER) combo->Connect(widgetID,wxEVT_COMMAND_TEXT_ENTER,wxCommandEventHandler(GDLFrame::OnComboBoxTextEnter)); widgetStyle=widgetAlignment(); widgetSizer->Add(combo, 0, widgetStyle, 0); if ((frameWidth>0)) this->FrameWidget(); TIDY_WIDGET; UPDATE_WINDOW } void GDLWidgetComboBox::SetValue(BaseGDL *value){ GDLDelete(vValue); vValue=value; if( vValue->Type() != GDL_STRING) { vValue = static_cast (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT )); } DStringGDL* val = static_cast (vValue); wxArrayString newchoices; // = new wxString[n]; for ( SizeT i = 0; i < val->N_Elements( ); ++i ) newchoices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) ); wxComboBox * combo = static_cast(wxWidget); assert( combo != NULL); combo->Clear(); combo->Append(newchoices); combo->SetSelection(0,0); } void GDLWidgetComboBox::AddItem(DString value, DLong pos) { wxComboBox * combo = static_cast(wxWidget); assert( combo != NULL); int nvalues=combo->GetCount(); if (pos == -1) combo->Append( wxString( value.c_str( ), wxConvUTF8 ) ); else if (pos > -1 && pos < nvalues) combo->Insert( wxString( value.c_str( ), wxConvUTF8 ), pos); } void GDLWidgetComboBox::DeleteItem(DLong pos) { wxComboBox * combo = static_cast(wxWidget); assert( combo != NULL); int nvalues=combo->GetCount(); int selected=combo->GetSelection(); if (pos > -1 && pos < nvalues) combo->Delete( pos ); if (pos==selected && (nvalues-1) > 0 ) combo->Select((pos+1)%(nvalues-1)); else if (selected==-1 && pos==0) combo->Select(0); } void GDLWidgetComboBox::SelectEntry(DLong entry_number){ wxComboBox * combo=static_cast(wxWidget); assert( combo != NULL); combo->Select(entry_number); } BaseGDL* GDLWidgetComboBox::GetSelectedEntry(){ wxComboBox * combo=static_cast(wxWidget); assert( combo != NULL); DStringGDL* stringres=new DStringGDL(dimension(1)); (*stringres)[0]=combo->GetStringSelection().mb_str(wxConvUTF8); //return null string if no selection return stringres; } GDLWidgetComboBox::~GDLWidgetComboBox(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetComboBox(): " << widgetID << std::endl; #endif } GDLWidgetText::GDLWidgetText( WidgetIDT p, EnvT* e, DStringGDL* valueStr, DULong eventflags, bool noNewLine_, bool editable_ ) : GDLWidget( p, e, valueStr, eventflags ) , noNewLine( noNewLine_ ) , editable(editable_) { DString value = ""; maxlinelength = 0; nlines=0; if (ySize<2 && !scrolled) noNewLine=TRUE; if( vValue != NULL) { for( int i=0; iN_Elements(); ++i) { int length=((*static_cast (vValue))[i]).length(); value += (*static_cast (vValue))[i]; maxlinelength=(length>maxlinelength)?length:maxlinelength; if ( !noNewLine ) //&& (i + 1) < vValue->N_Elements( ) ) #ifdef _WIN32 {value += "\r\n"; nlines++;} #else {value += '\n'; nlines++;} #endif } } lastValue = value; GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); wxString valueWxString = wxString( lastValue.c_str( ), wxConvUTF8 ); long style = wxTE_NOHIDESEL|wxTE_PROCESS_ENTER|textAlignment(); if ( ySize > 1 || scrolled ) style |= wxTE_MULTILINE; // else style |= wxTE_NO_VSCROLL; wxTextCtrl * text; if ( !editable ) { // style |= wxTE_READONLY; //note: *DL provides READONLY and still give events. text = new gdlTextCtrl( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ), computeWidgetSize(), style ); // this permits to a procedure (cw_field.pro for example) to filter the editing of text fields. // so wxTextCtrl::OnChar is overwritten in gdlwidgeteventhandler.cpp just for this reason. } else { text = new wxTextCtrl( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ), computeWidgetSize(), style ); } text->SetInsertionPoint(0); text->SetSelection(0,0); this->wxWidget = text; text->Connect(widgetID,wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GDLFrame::OnTextEnter)); text->Connect(widgetID,wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(GDLFrame::OnText)); widgetStyle=widgetAlignment(); widgetSizer->Add(text, 0, widgetStyle , 0); if ((frameWidth>0)) this->FrameWidget(); TIDY_WIDGET; UPDATE_WINDOW } GDLWidgetText::~GDLWidgetText(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetText(): " << widgetID << std::endl; #endif } void GDLWidgetText::ChangeText( DStringGDL* valueStr, bool noNewLine) { delete vValue; vValue = valueStr; DString value = ""; if (ySize < 2 && !scrolled) noNewLine=TRUE; nlines=0; for( int i=0; iN_Elements(); ++i) { value += (*valueStr)[ i]; if ( !noNewLine ) #ifdef _WIN32 {value += "\r\n"; nlines++;} #else {value += '\n'; nlines++;} #endif } lastValue = value; wxString valueWxString = wxString( lastValue.c_str( ), wxConvUTF8 ); if ( this->wxWidget != NULL ) { wxTextCtrl* txt=static_cast (wxWidget); assert( txt != NULL); txt->ChangeValue( valueWxString ); //by contrast with SetValue, does not generate an EVENT -- IDL does not either. // txt->Refresh(); // txt->Update(); } else std::cerr << "Null widget in GDLWidgetText::SetTextValue(), please report!" << std::endl; } void GDLWidgetText::InsertText( DStringGDL* valueStr, bool noNewLine, bool insertAtEnd) { long from,to; wxTextCtrl* txt=static_cast (wxWidget); assert( txt != NULL); txt->GetSelection(&from,&to); if (insertAtEnd) {from=txt->GetLastPosition(); to=from;} if (ySize < 2 && !scrolled) noNewLine=TRUE; DString value = ""; nlines=0; for ( int i = 0; i < valueStr->N_Elements( ); ++i ) { value += (*valueStr)[ i]; if ( !noNewLine ) { #ifdef _WIN32 value += "\r\n"; nlines++; #else value += '\n'; nlines++; #endif } } lastValue.replace(from,to-from,value); delete vValue; vValue = new DStringGDL(lastValue); // cout<"<wxWidget != NULL ) { txt->ChangeValue( valueWxString ); //by contrast with SetValue, does not generate an EVENT (neither does *DL). // txt->Refresh(); // txt->Update(); txt->SetSelection(from,from); } else std::cerr << "Null widget in GDLWidgetText::SetTextValue(), please report!" << std::endl; } void GDLWidgetText::SetTextSelection(DLongGDL* pos) { //*DL selection are [start,length] [3,20] -> pos (3,23) //numerous cases to handle with invalid values (negative, too large). //Hope it works for all cases: long from,to,len; long oldSelStart, oldSelEnd; wxTextCtrl* txt=static_cast (wxWidget); assert( txt != NULL); txt->GetSelection(&oldSelStart,&oldSelEnd); len = txt->GetLastPosition()+1; if ((*pos)[0] < 0 ) from=0; else if ((*pos)[0] > len ) from=len; else from=(*pos)[0]; if (pos->N_Elements()<2) { //selection = insertion txt->SetSelection(from,from); return; } //2 elements, define selection to=(*pos)[1]; if ( from+to >= len ) { //set insertion position at end of last selection (?) txt->SetSelection(oldSelEnd,oldSelEnd); return; } if ( to < 0 ) { //set insertion position at from txt->SetSelection(from,from); return; } txt->SetSelection(from,from+to); } DLongGDL* GDLWidgetText::GetTextSelection() { DLongGDL* pos=new DLongGDL(dimension(2),BaseGDL::ZERO); long from,to; wxTextCtrl* txt=static_cast (wxWidget); assert( txt != NULL); txt->GetSelection(&from,&to); (*pos)[0]=from; (*pos)[1]=to-from; return pos; } DStringGDL* GDLWidgetText::GetSelectedText() { wxTextCtrl* txt=static_cast(wxWidget); assert( txt != NULL); return new DStringGDL(txt->GetStringSelection().mb_str(wxConvUTF8).data()); } GDLWidgetLabel::GDLWidgetLabel( WidgetIDT p, EnvT* e, const DString& value_ , DULong eventflags, bool sunken) : GDLWidget( p, e , NULL, eventflags ) , value(value_) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 ); wxStaticText* label = new wxStaticText( widgetPanel, widgetID, valueWxString, wxPoint( xOffset, yOffset ), computeWidgetSize(), textAlignment()|wxST_NO_AUTORESIZE|(sunken)?wxBORDER_SUNKEN:0 ); this->wxWidget = label; widgetStyle=widgetAlignment(); widgetSizer->Add(label,0,widgetStyle, 0); if ((frameWidth>0)) this->FrameWidget(); TIDY_WIDGET; UPDATE_WINDOW } DStructGDL* GDLWidgetText::GetGeometry(wxRealPoint fact) { int ixs=0, iys=0, ixscr=0, iyscr=0; float xs, ys, xscr, yscr, xoff, yoff, margin; wxPoint position; wxSize fontSize=wxNORMAL_FONT->GetPixelSize(); wxTextCtrl* txt = static_cast (wxWidget); assert( txt != NULL); if ( txt != NULL ) { txt->GetClientSize( &ixs, &iys ); ixscr=ixs; iyscr=iys; position = txt->GetPosition( ); fontSize = txt->GetFont().GetPixelSize(); } //Apparently Windows may return 0 for fontsize.x (probably if too small)? if (fontSize.x == 0) fontSize.x=0.65*fontSize.y; //last chance to get a correct value if (fontSize.x == 0) fontSize.x=1; if (fontSize.y == 0) fontSize.y=1; if (frameSizer != NULL) {framePanel->GetSize(&ixscr,&iyscr); margin = gdlFRAME_MARGIN / fact.x;} if (scrollSizer != NULL) {scrollPanel->GetSize(&ixscr,&iyscr);ixs=ixscr-gdlSCROLL_WIDTH;iys=iyscr-gdlSCROLL_WIDTH;} //size is in pixels, pass in requested units (1.0 default) xs = ixs / fontSize.x; ys = iys / fontSize.y; xscr = ixscr / fact.x; yscr = iyscr / fact.y; xoff = position.x / fact.x; yoff = position.y / fact.y; DStructGDL* ex = new DStructGDL( "WIDGET_GEOMETRY" ); ex->InitTag( "XOFFSET", DFloatGDL( xoff) ); ex->InitTag( "YOFFSET", DFloatGDL( yoff ) ); ex->InitTag( "XSIZE", DFloatGDL( xs ) ); ex->InitTag( "YSIZE", DFloatGDL( ys ) ); ex->InitTag( "SCR_XSIZE", DFloatGDL( xscr ) ); ex->InitTag( "SCR_YSIZE", DFloatGDL( yscr ) ); ex->InitTag( "MARGIN", DFloatGDL( margin ) ); return ex; } GDLWidgetLabel::~GDLWidgetLabel(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLWidgetLabel: " << this << std::endl; #endif } void GDLWidget::FrameWidget() { //to frame a widget, create a panel and a staticBoxSizer as panel's child. Put the widget inside the panel //an replace the widget wby the panel in the parent sizer. if (this->IsBase()) return; //function invalid with base widgets. if (frameSizer==NULL) { //protect against potential problems //panel style: // long panelStyle=widgetStyle&wxBORDER_MASK; //wxBORDER_MASK selects only the 'border' part of the Style, to pass to wxPanel long alignment=widgetStyle&wxALIGN_MASK; //same for alignment framePanel = new wxPanel(this->widgetPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN); frameSizer = new wxBoxSizer( wxHORIZONTAL ); framePanel->SetSizer( frameSizer ); if (scrollSizer==NULL) { widgetSizer->Detach(static_cast(this->wxWidget)); static_cast(this->wxWidget)->Reparent(framePanel); frameSizer->Add(static_cast(this->wxWidget),0,wxALL,(frameWidth==-1)?gdlFRAME_MARGIN:frameWidth ); } else { widgetSizer->Detach(scrollPanel); static_cast(this->scrollPanel)->Reparent(framePanel); frameSizer->Add(static_cast(this->scrollPanel), 0,wxALL,(frameWidth==-1)?gdlFRAME_MARGIN:frameWidth); } widgetSizer->Add(framePanel, 0, alignment, 0); // frameSizer->Layout(); // widgetSizer->Layout(); } } void GDLWidget::UnFrameWidget() { if (this->IsBase()) return; //function invalid with base widgets. if (frameSizer!=NULL) { //protect against potential problems widgetSizer->Detach(framePanel); // long panelStyle=widgetStyle&wxBORDER_MASK; //wxBORDER_MASK selects only the 'border' part of the Style, to pass to wxPanel long alignment=widgetStyle&wxALIGN_MASK; //same for alignment if (scrollSizer==NULL) { frameSizer->Detach(static_cast(this->wxWidget)); static_cast(this->wxWidget)->Reparent(widgetPanel); widgetSizer->Add(static_cast(this->wxWidget), 0, alignment, 0); } else { frameSizer->Detach(static_cast(this->scrollPanel)); static_cast(this->scrollPanel)->Reparent(widgetPanel); widgetSizer->Add(static_cast(this->scrollPanel),0, alignment, 0); } delete framePanel; frameSizer=NULL; framePanel=NULL; // widgetSizer->Layout(); } } void GDLWidget::ScrollWidget( DLong x_scroll_size, DLong y_scroll_size) { if (this->IsBase()) return; //function invalid with base widgets. if (scrollSizer==NULL) { //protect against potential problems scrollPanel = new wxScrolledWindow(this->widgetPanel, wxID_ANY, wxPoint(xOffset,yOffset), wxSize(x_scroll_size, y_scroll_size ), wxBORDER_SUNKEN); scrollPanel->SetScrollRate(gdlSCROLL_RATE, gdlSCROLL_RATE); //show scrollbars scrollSizer = new wxBoxSizer(wxVERTICAL ); scrollPanel->SetSizer( scrollSizer ); static_cast(this->wxWidget)->Reparent(scrollPanel); scrollSizer->Add(static_cast(this->wxWidget)); if (frameSizer!=NULL) { frameSizer->Detach(static_cast(this->wxWidget)); frameSizer->Add(scrollPanel,0, wxFIXED_MINSIZE|wxALL, gdlFRAME_MARGIN); } else { widgetSizer->Detach(static_cast(this->wxWidget)); widgetSizer->Add(scrollPanel, 0, wxFIXED_MINSIZE|widgetStyle, 0); } widgetSizer->Layout(); } } void GDLWidget::UnScrollWidget() { if (this->IsBase()) return; //function invalid with base widgets. if (scrollSizer!=NULL) { //protect against potential problems scrollSizer->Detach(static_cast(this->wxWidget)); if (frameSizer!=NULL) { static_cast(this->wxWidget)->Reparent(framePanel); frameSizer->Detach(scrollPanel); frameSizer->Add(static_cast(this->wxWidget), 0, widgetStyle, gdlFRAME_MARGIN); frameSizer->Layout(); } else { static_cast(this->wxWidget)->Reparent(widgetPanel); widgetSizer->Detach(scrollPanel); widgetSizer->Add(static_cast(this->wxWidget), 0, widgetStyle, 0); } delete scrollPanel; scrollSizer=NULL; scrollPanel=NULL; widgetSizer->Layout(); } } //void GDLWidgetLabel::OnShow() //{ // // std::cout << "In Label: " << widgetID << " " << p << std::endl; //} void GDLWidgetLabel::SetLabelValue( const DString& value_) { value = value_; //update vValue delete(vValue); vValue = new DStringGDL( value ); wxString valueWxString = wxString( value_.c_str( ), wxConvUTF8 ); if ( this->wxWidget != NULL ) { wxWindowID id = static_cast (wxWidget)->GetId( ); wxStaticText *txt= static_cast (wxWidget); if (txt) txt->SetLabel( valueWxString ); else cerr << "Warning GDLWidgetLabel::SetLabelValue(): widget type confusion\n"; //SetLabel, unless SetLabelText, interprets markup ( etc) } else std::cerr << "Null widget in GDLWidgetLabel::SetLabelValue(), please report!" << std::endl; } //propertysheet #ifdef HAVE_WXWIDGETS_PROPERTYGRID GDLWidgetPropertySheet::GDLWidgetPropertySheet( WidgetIDT parentID, EnvT* e) : GDLWidget( p, e , value, eventflag) { GDLWidget* gdlParent = GetWidget( parentID ); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer(); // Construct wxPropertyGrid control wxPropertyGrid* pg = new wxPropertyGrid(gdlParent,wxID_ANY,wxDefaultPosition,wxDefaultSize, // Here are just some of the supported window styles wxPG_AUTO_SORT | // Automatic sorting after items added wxPG_SPLITTER_AUTO_CENTER | // Automatically center splitter until user manually adjusts it // Default style wxPG_DEFAULT_STYLE ); // Window style flags are at premium, so some less often needed ones are // available as extra window styles (wxPG_EX_xxx) which must be set using // SetExtraStyle member function. wxPG_EX_HELP_AS_TOOLTIPS, for instance, // allows displaying help strings as tool tips. pg->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS ); this->wxWidget=pg; // Add int property pg->Append( new wxIntProperty("IntProperty", wxPG_LABEL, 12345678) ); // Add float property (value type is actually double) pg->Append( new wxFloatProperty("FloatProperty", wxPG_LABEL, 12345.678) ); // Add a bool property pg->Append( new wxBoolProperty("BoolProperty", wxPG_LABEL, false) ); // A string property that can be edited in a separate editor dialog. pg->Append( new wxLongStringProperty("LongStringProperty", wxPG_LABEL, "This is much longer string than the " "first one. Edit it by clicking the button.")); // String editor with dir selector button. pg->Append( new wxDirProperty("DirProperty", wxPG_LABEL, ::wxGetUserHome()) ); // wxArrayStringProperty embeds a wxArrayString. pg->Append( new wxArrayStringProperty("Label of ArrayStringProperty", "NameOfArrayStringProp")); // A file selector property. pg->Append( new wxFileProperty("FileProperty", wxPG_LABEL, wxEmptyString) ); if (frame) this->FrameWidget(widgetStyle); TIDY_WIDGET; UPDATE_WINDOW } #endif // GDL widgets ===================================================== // GDLFrame ======================================================== GDLFrame::GDLFrame( GDLWidgetBase* gdlOwner_, wxWindowID id, const wxString& title , const bool nofocus, const wxPoint& pos ) : wxFrame( NULL, id, title, pos, wxDefaultSize, (nofocus)? wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX|wxFRAME_TOOL_WINDOW:wxDEFAULT_FRAME_STYLE ) , mapped( false ) , noFocus ( nofocus ) //for graphic windows. They do not have focus. Never. , frameSize(wxSize(0,0)) , gdlOwner( gdlOwner_) , appOwner(NULL) { m_resizeTimer = new wxTimer(this,RESIZE_TIMER); m_windowTimer = new wxTimer(this,WINDOW_TIMER); } GDLFrame::~GDLFrame() { if (m_resizeTimer->IsRunning()) m_resizeTimer->Stop(); if (m_windowTimer->IsRunning()) m_windowTimer->Stop(); //really necessary, try stopping xdice.pro when rolling dices.. #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLFrame: " << this << std::endl; #endif //frame is part of a TLB. if frame is destroyed, destroy TLB if still existing. if( gdlOwner != NULL) { #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLFrame: Destroying Base Container" << gdlOwner->WidgetID() << std::endl; #endif gdlOwner->NullWxWidget( ); //remove one's reference from container gdlOwner->SelfDestroy( ); // send delete request to GDL owner = container. } } // GDLDrawPanel ======================================================== GDLDrawPanel::GDLDrawPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel( parent, id, pos, size, style, name ) , pstreamIx( -1 ) , pstreamP( NULL ) , m_dc( NULL) , GDLWidgetDrawID(id) , drawSize(size) { } void GDLDrawPanel::InitStream(int windowIndex) { if (windowIndex < 0) pstreamIx = GraphicsDevice::GetGUIDevice( )->WAddFree( ); else pstreamIx = windowIndex; if ( pstreamIx == -1 ) throw GDLException( "Failed to allocate GUI stream." ); bool success = GraphicsDevice::GetGUIDevice( )->GUIOpen( pstreamIx, this->GetClientSize( ).x, this->GetClientSize( ).y ); if( !success) { throw GDLException( "Failed to open GUI stream: " + i2s( pstreamIx ) ); } pstreamP = static_cast (GraphicsDevice::GetGUIDevice( )->GetStreamAt( pstreamIx )); pstreamP->SetGDLDrawPanel( this ); m_dc = pstreamP->GetDC( ); } //void GDLDrawPanel::AssociateStream(GDLWXStream* stream) //{ // pstreamP = stream; // pstreamP->SetGDLDrawPanel( this ); // m_dc = pstreamP->GetDC( ); //} void GDLDrawPanel::Resize(int sizex, int sizey) { if (pstreamP != NULL) { // not useful as long we recreate a wxstream! // pstreamP->SetSize(sizex,sizey); //The following should not be necessary . It is a bad idea to create a new stream, but font size handling //with plplot's wx implementation that is too awkward to do anything else now. //get a new stream with good dimensions. Only possibility (better than resize) to have correct size of fonts and symbols. GDLWXStream * newStream = new GDLWXStream(sizex, sizey); // replace old by new, called function destroys old: GraphicsDevice::GetGUIDevice( )->ChangeStreamAt( pstreamIx, newStream ); pstreamP = static_cast (GraphicsDevice::GetGUIDevice( )->GetStreamAt( pstreamIx )); pstreamP->SetGDLDrawPanel( this ); m_dc = pstreamP->GetDC( ); } drawSize=wxSize(sizex,sizey); } GDLDrawPanel::~GDLDrawPanel() { #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLDrawPanel: " << this << std::endl; // std::cout << "This IsMainThread: " << wxIsMainThread() << std::endl; #endif // if (m_resizeTimer->IsRunning()) m_resizeTimer->Stop(); if ( pstreamP != NULL ) pstreamP->SetValid( false ); //panel destroyed in future call to TidyWindowsList(). } GDLWidgetDraw::GDLWidgetDraw( WidgetIDT p, EnvT* e, int windowIndex, DLong special_xsize, DLong special_ysize, DLong x_scroll_size_, DLong y_scroll_size_, bool app_scroll, DULong eventFlags_, DStringGDL* drawToolTip) : GDLWidget( p, e, NULL, eventFlags_) , pstreamIx(windowIndex) , x_scroll_size(x_scroll_size_) , y_scroll_size(y_scroll_size_) { // std::cout << "In GDLWidgetDraw::GDLWidgetDraw: " << widgetID << std::endl assert( parentID != GDLWidget::NullID); if (xSize <= 0 && special_xsize > 0) xSize = special_xsize; //override in case this is a graphic window (no env kw used since no command) if (ySize <= 0 && special_ysize > 0) ySize = special_ysize; //override in case this is a graphic window (no env kw used since no command) //get immediately rid of scroll sizes in case of scroll or not... Here is the logic: if (app_scroll) scrolled=TRUE; if (x_scroll_size > 0) {scrolled=TRUE;x_scroll_size*=unitConversionFactor.x; x_scroll_size+=(gdlSCROLL_WIDTH);} if (y_scroll_size > 0) {scrolled=TRUE;y_scroll_size*=unitConversionFactor.y; y_scroll_size+=(gdlSCROLL_WIDTH);} if (scrolled) x_scroll_size=(x_scroll_size<100)?100:x_scroll_size; //min values if (scrolled) y_scroll_size=(y_scroll_size<100)?100:y_scroll_size; if ( xSize <= 0 ) xSize=scrolled?100+gdlSCROLL_WIDTH:100; else xSize*=unitConversionFactor.x; //provide a default value! if ( ySize <= 0 ) ySize=scrolled?100+gdlSCROLL_WIDTH:100; else ySize*=unitConversionFactor.y; GDLWidget* gdlParent = GetWidget( parentID); widgetPanel = gdlParent->GetPanel( ); widgetSizer = gdlParent->GetSizer( ); long style = 0; GDLDrawPanel* draw = new GDLDrawPanel( widgetPanel, widgetID, wxPoint(xOffset,yOffset), wxSize(xSize,ySize), style); //these widget specific events are always set: draw->Connect(widgetID, wxEVT_PAINT, wxPaintEventHandler(GDLDrawPanel::OnPaint)); draw->Connect(widgetID, wxEVT_SIZE, wxSizeEventHandler(GDLDrawPanel::OnSize)); draw->Connect(widgetID, wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(GDLDrawPanel::OnErase)); //other set event handling according to flags if (eventFlags & GDLWidget::EV_MOTION) draw->Connect(widgetID, wxEVT_MOTION, wxMouseEventHandler(GDLDrawPanel::OnMouseMove)); // if ( eventFlags & GDLWidget::EV_DROP) nothing to do yet, fixme!; // if ( eventFlags & GDLWidget::EV_EXPOSE) nothing to do yet, fixme!; // if ( eventFlags & GDLWidget::EV_VIEWPORT) idem; if ( eventFlags & GDLWidget::EV_WHEEL) draw->Connect(widgetID, wxEVT_MOUSEWHEEL, wxMouseEventHandler(GDLDrawPanel::OnMouseWheel)); if ( eventFlags & GDLWidget::EV_BUTTON) { draw->Connect(widgetID, wxEVT_LEFT_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_LEFT_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); draw->Connect(widgetID, wxEVT_LEFT_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_MIDDLE_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_MIDDLE_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); draw->Connect(widgetID, wxEVT_RIGHT_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_RIGHT_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_RIGHT_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); } if (eventFlags & GDLWidget::EV_KEYBOARD2 || eventFlags & GDLWidget::EV_KEYBOARD){ draw->Connect(widgetID, wxEVT_KEY_DOWN, wxKeyEventHandler(GDLDrawPanel::OnKey)); draw->Connect(widgetID, wxEVT_KEY_UP, wxKeyEventHandler(GDLDrawPanel::OnKey)); } draw->SetCursor(wxCURSOR_CROSS); if (drawToolTip) static_cast(draw)->SetToolTip( wxString((*drawToolTip)[0].c_str(),wxConvUTF8)); wxWidget = draw; widgetStyle= widgetAlignment(); widgetSizer->Add( draw );// , 0, widgetStyle, 0); if (scrolled) this->ScrollWidget(x_scroll_size, y_scroll_size ); if ((frameWidth>0)) this->FrameWidget(); static_cast(wxWidget)->InitStream(windowIndex); pstreamIx = static_cast(wxWidget)->PStreamIx(); GDLDelete( vValue); this->vValue = new DLongGDL(pstreamIx); this->SetSensitive(sensitive); TIDY_WIDGET; UPDATE_WINDOW } void GDLWidgetDraw::AddEventType( DULong evType){ GDLDrawPanel* draw=(GDLDrawPanel*)wxWidget; //this one is for the moment defined globally: // if ( evType == GDLWidget::EV_TRACKING) { // draw->Connect(widgetID, wxEVT_ENTER_WINDOW, wxMouseEventHandler(GDLFrame::OnEnterWindow)); // draw->Connect(widgetID, wxEVT_LEAVE_WINDOW, wxMouseEventHandler(GDLFrame::OnLeaveWindow)); // } else if ( evType == GDLWidget::EV_MOTION) draw->Connect(widgetID, wxEVT_MOTION, wxMouseEventHandler(GDLDrawPanel::OnMouseMove)); //else if ( evType == GDLWidget::EV_DROP) nothing to do yet, fixme!; //else if ( evType == GDLWidget::EV_EXPOSE) nothing to do yet, fixme!; //else if ( evType == GDLWidget::EV_VIEWPORT) idem; else if ( evType == GDLWidget::EV_WHEEL) draw->Connect(widgetID, wxEVT_MOUSEWHEEL, wxMouseEventHandler(GDLDrawPanel::OnMouseWheel)); else if ( evType == GDLWidget::EV_BUTTON) { draw->Connect(widgetID, wxEVT_LEFT_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_LEFT_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); draw->Connect(widgetID, wxEVT_LEFT_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_MIDDLE_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_MIDDLE_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); draw->Connect(widgetID, wxEVT_RIGHT_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_RIGHT_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Connect(widgetID, wxEVT_RIGHT_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); } else if (evType == GDLWidget::EV_KEYBOARD2 || evType == GDLWidget::EV_KEYBOARD){ draw->Connect(widgetID, wxEVT_KEY_DOWN, wxKeyEventHandler(GDLDrawPanel::OnKey)); draw->Connect(widgetID, wxEVT_KEY_UP, wxKeyEventHandler(GDLDrawPanel::OnKey)); } } void GDLWidgetDraw::RemoveEventType( DULong evType){ GDLDrawPanel* draw=(GDLDrawPanel*)wxWidget; //this one is for the moment defined globally: // if ( evType == GDLWidget::EV_TRACKING) { // draw->Disconnect(widgetID, wxEVT_ENTER_WINDOW, wxMouseEventHandler(GDLFrame::OnEnterWindow)); // draw->Disconnect(widgetID, wxEVT_LEAVE_WINDOW, wxMouseEventHandler(GDLFrame::OnLeaveWindow)); // } else if ( evType == GDLWidget::EV_MOTION) draw->Disconnect(widgetID, wxEVT_MOTION, wxMouseEventHandler(GDLDrawPanel::OnMouseMove)); //else if ( evType == GDLWidget::EV_DROP) nothing to do yet, fixme!; //else if ( evType == GDLWidget::EV_EXPOSE) nothing to do yet, fixme!; //else if ( evType == GDLWidget::EV_VIEWPORT) idem; else if ( evType == GDLWidget::EV_WHEEL) draw->Disconnect(widgetID, wxEVT_MOUSEWHEEL, wxMouseEventHandler(GDLDrawPanel::OnMouseWheel)); else if ( evType == GDLWidget::EV_BUTTON) { draw->Disconnect(widgetID, wxEVT_LEFT_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Disconnect(widgetID, wxEVT_LEFT_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); draw->Disconnect(widgetID, wxEVT_LEFT_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Disconnect(widgetID, wxEVT_MIDDLE_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Disconnect(widgetID, wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Disconnect(widgetID, wxEVT_MIDDLE_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); draw->Disconnect(widgetID, wxEVT_RIGHT_DOWN, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Disconnect(widgetID, wxEVT_RIGHT_DCLICK, wxMouseEventHandler(GDLDrawPanel::OnMouseDown)); draw->Disconnect(widgetID, wxEVT_RIGHT_UP, wxMouseEventHandler(GDLDrawPanel::OnMouseUp)); } else if (evType == GDLWidget::EV_KEYBOARD2 || evType == GDLWidget::EV_KEYBOARD){ draw->Disconnect(widgetID, wxEVT_KEY_DOWN, wxKeyEventHandler(GDLDrawPanel::OnKey)); draw->Disconnect(widgetID, wxEVT_KEY_UP, wxKeyEventHandler(GDLDrawPanel::OnKey)); } } DStructGDL* GDLWidgetDraw::GetGeometry( wxRealPoint fact ) { int ixds=0, iyds=0, ixs=0, iys=0, ixscr=0, iyscr=0; float xds, yds, xs, ys, xscr, yscr, xoff, yoff, margin; wxPoint position; GDLDrawPanel* test = static_cast (wxWidget); if ( test != NULL ) { test->GetSize( &ixs, &iys ); ixscr=ixs; iyscr=iys; test->GetClientSize( &ixds, &iyds ); position = test->GetPosition( ); } if (frameSizer != NULL) {framePanel->GetSize(&ixscr,&iyscr); margin = gdlFRAME_MARGIN / fact.x;} if (scrollSizer != NULL) {scrollPanel->GetSize(&ixscr,&iyscr);ixs=ixscr-gdlSCROLL_WIDTH;iys=iyscr-gdlSCROLL_WIDTH;} //size is in pixels, pass in requested units (1.0 default) xs = ixs / fact.x; ys = iys / fact.y; xds = ixds / fact.x; yds = iyds / fact.y; xscr = ixscr / fact.x; yscr = iyscr / fact.y; xoff = position.x / fact.x; yoff = position.y / fact.y; DStructGDL* ex = new DStructGDL( "WIDGET_GEOMETRY" ); ex->InitTag( "XOFFSET", DFloatGDL( xoff) ); ex->InitTag( "YOFFSET", DFloatGDL( yoff ) ); ex->InitTag( "XSIZE", DFloatGDL( xs ) ); ex->InitTag( "YSIZE", DFloatGDL( ys ) ); ex->InitTag( "SCR_XSIZE", DFloatGDL( xscr ) ); ex->InitTag( "SCR_YSIZE", DFloatGDL( yscr ) ); ex->InitTag( "DRAW_XSIZE", DFloatGDL( xds ) ); ex->InitTag( "DRAW_YSIZE", DFloatGDL( yds ) ); ex->InitTag( "MARGIN", DFloatGDL( margin ) ); return ex; } // GDLApp ================================================= #include "wx/evtloop.h" #include "wx/ptr_scpd.h" wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoop); bool GDLApp::OnInit() { return true; } int GDLApp::MainLoop() { wxEventLoopTiedPtr mainLoop((wxEventLoop **)&m_mainLoop, new wxEventLoop); m_mainLoop->SetActive(m_mainLoop); wxEventLoop * const loop = (wxEventLoop *)wxEventLoop::GetActive(); while(loop->Pending()) // Unprocessed events in queue { loop->Dispatch(); // Dispatch next event in queue } return 0; } int GDLApp::OnExit() { std::cout << " In GDLApp::OnExit()" << std::endl; // Defined in guiThread::OnExit() in gdlwidget.cpp // std::cout << "Exiting thread (GDLApp::OnExit): " << thread << std::endl; return 0; } #endif gdl-0.9.9/src/gdlwidget.hpp000066400000000000000000001462141340051421000155470ustar00rootroot00000000000000/*************************************************************************** gdlwidget - base class for GDL widgets ------------------- begin : Fri May 7 2004 copyright : (C) 2004 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLWIDGET_HPP #define GDLWIDGET_HPP #ifdef HAVE_LIBWXWIDGETS // #define GDL_DEBUG_WIDGETS #include #include #include #include #ifdef HAVE_WXWIDGETS_PROPERTYGRID #include #endif #include //for timer. #include #include #include #include //#include #include #include #include "typedefs.hpp" #include "str.hpp" #include "datatypes.hpp" #include "widget.hpp" #include "plotting.hpp" #define gdlSCROLL_RATE 20 #define gdlSCROLL_WIDTH 20 #define gdlDEFAULT_XSIZE 100 #define gdlDEFAULT_YSIZE 100 #define gdlDEFAULT_SCROLL_SIZE gdlDEFAULT_XSIZE+gdlSCROLL_WIDTH #define gdlFRAME_MARGIN 2 #ifdef _WIN32 #define NEWLINECHARSIZE 2 //length of #else #define NEWLINECHARSIZE 1 //length of #endif //#if wxCHECK_VERSION(3,0,0) //#define gdlSIZE_EVENT_HANDLER wxSizeEventHandler(GDLFrame::OnIgnoreSize) //takes all size events ////#define gdlSIZE_EVENT_HANDLER wxSizeEventHandler(GDLFrame::OnSize) //takes all size events //#else #define gdlSIZE_EVENT_HANDLER wxSizeEventHandler(GDLFrame::OnSizeWithTimer) //filter mouse events (manual resize) to avoid too many updtes for nothing //#endif typedef DLong WidgetIDT; static string widgetNameList[14]={"BASE","BUTTON","SLIDER","TEXT","DRAW","LABEL","LIST","MBAR","DROPLIST","TABLE","TAB","TREE","COMBOBOX","PROPERTYSHEET"}; static int widgetTypeList[14]={0,1,2,3,4,5,6,7,8,9,10,11,12,13}; static bool handlersInited=false; //handlers of graphic formats for bitmaps (magick). class DStructGDL; class GDLApp; //static GDLApp *theGDLApp=NULL; // thread safe deque class GDLEventQueue { private: std::deque dq; public: GDLEventQueue() //normally we should have ~GDLEventQueue removing the DStructGDLs? {} DStructGDL* Pop() { if( dq.empty()) return NULL; // if( dq.empty()) // needed again for thread safe behaviour // return NULL; DStructGDL* front = dq.front(); dq.pop_front(); return front; } // for all regular events void Push( DStructGDL* ev) { dq.push_back( ev); } // for priority events (like delete widget) void PushFront( DStructGDL* ev) { dq.push_front( ev); } // Not good: between call of Empty and Pop another thread's Pop could be executed // -> Empty is useless (dangerous) for polling // although: as used here (there is only one thread calling Pop) it would work // bool Empty() const // { // return isEmpty; // } void Purge(); void Purge( WidgetIDT topID); }; // all locker classes are identical. For control of locking separately // class GUIMutexLockerT // { // bool left; // public: // GUIMutexLockerT(): left(false) { wxMutexGuiEnter();} // ~GUIMutexLockerT() { if(!left) wxMutexGuiLeave();} // void Leave() { wxMutexGuiLeave(); left=true;} // }; class GDLWidget; // global widget list type // typedef DLong WidgetIDT; // typedef std::map WidgetListT; // typedef std::deque EventQueueT; class WidgetListT { public: typedef std::map mapT; typedef mapT::iterator iterator; typedef mapT::size_type size_type; typedef WidgetIDT key_type; typedef GDLWidget* mapped_type; typedef std::pair value_type; private: mapT map; public: WidgetListT(): map(){} ~WidgetListT() {} void erase (iterator position) { map.erase(position); } size_type erase (const key_type& k) { return map.erase(k); } iterator find (const key_type& k) { return map.find(k); } iterator begin() { return map.begin(); } iterator end() { return map.end(); } iterator insert (iterator position, value_type val) { return map.insert( position, val); } }; // main App class class GDLApp: public wxApp { public: // virtual int OnRun(); virtual int OnExit(); virtual int MainLoop(); // virtual int OneLoop(); virtual bool OnInit(); // bool Pending(); //Returns true if unprocessed events are in the window system event queue. // int FilterEvent(wxEvent& event) //This function is called before processing any event and //allows the application to preempt the processing of some events. If this method returns -1 //the event is processed normally, otherwise either true or false should be returned and //the event processing stops immediately considering that the event had been already processed //(for the former return value) or that it is not going to be processed at all (for the latter one). }; // GUI base class ********************************** class GDLWidgetBase; class GDLWidgetContainer; class GDLWidget { // static part is used for the abstraction // all widgets are refered to as IDs static int gdl_lastControlId; static bool wxIsOn; //tells if wx is started, permits to starts wxInit() as soon as needed but not before (speedup). static bool handlersOk; //tells if wx is started, permits to starts wxInit() as soon as needed but not before (speedup). private: // the global widget list // a widget is added by the constructor and removed by the destructor // so no other action is necessary for list handling static WidgetListT widgetList; public: static GDLEventQueue eventQueue; static GDLEventQueue readlineEventQueue; static void PushEvent( WidgetIDT baseWidgetID, DStructGDL* ev); static WidgetIDT HandleEvents(); static const WidgetIDT NullID; // get widget from ID static GDLWidget* GetWidget( WidgetIDT widID); static GDLWidget* GetParent( WidgetIDT widID); static GDLWidgetBase* GetTopLevelBaseWidget( WidgetIDT widID); static GDLWidgetBase* GetBaseWidget( WidgetIDT widID); // static void RefreshWidgets(); void RefreshWidget(); // get ID of base widgets static WidgetIDT GetBase( WidgetIDT widID); static WidgetIDT GetTopLevelBase( WidgetIDT widID); static void Init(); // global GUI intialization upon GDL startup static void UnInit(); // global GUI desinitialization in case it is useful (?) static bool wxIsStarted(){return (wxIsOn);} static void SetWxStarted(){wxIsOn=true;} static bool AreWxHandlersOk(){return (handlersOk);} static void SetWxHandlersOk(){handlersOk=true;} static void UnsetWxStarted(){gdl_lastControlId=0;/* not possible: wxWidgets library does not survive wxUniitiailze() ... wxIsOn=false; handlersOk=false;*/} static int GDLNewControlId(){ gdl_lastControlId++; if (gdl_lastControlId >= wxID_LOWEST && gdl_lastControlId <= wxID_HIGHEST) gdl_lastControlId=wxID_HIGHEST+1; return gdl_lastControlId; } protected: // only TLB have to care for this // (they do by sending messages to each other in a thread save way) // as the rest is deleted automatically // Note: wxWidget is GDL name not wxWidgets (JMG) wxObject* wxWidget; WidgetIDT widgetID; // own index to widgetList WidgetIDT parentID; // parent ID (0 for TLBs) BaseGDL* uValue; // the UVALUE BaseGDL* vValue; // the VVALUE bool scrolled; bool sensitive; bool managed; DULong eventFlags; // event types widget should reply to bool buttonState; //only for buttons int exclusiveMode; DLong xOffset, yOffset, xSize, ySize, scrXSize, scrYSize; wxSizer* topWidgetSizer; //the frame sizer (contains all widgets) wxSizer* widgetSizer; // the sizer which governs the placement of the widget in its Panel wxPanel* widgetPanel; // the Panel in which the widget is placed wxSizer* scrollSizer; // the sizer for the (optional) Scroll Panel wxScrolledWindow* scrollPanel; // Panel with scrollBars in which the widget may be shown wxSizer* frameSizer; // the sizer of the (optional) "frame" (its not a wxFrame its a StaticBox) drawn around a widget wxPanel* framePanel; // the corresponding panel DInt widgetType; DString widgetName; WidgetIDT groupLeader; wxRealPoint unitConversionFactor; DLong frameWidth; wxFont font; bool valid; //if not, is in the process of being destroyed (prevent reentrance). long alignment; //alignment of the widget long widgetStyle; //style (alignment code + other specific codes used as option to widgetsizer) int dynamicResize; //for some widgets, will enable resizing: -1: not resizable, 0/1 resizable std::vector followers; //all the widgets that use me as group_leader private: DString uName; DString proValue; DString funcValue; DString eventPro; // event handler PRO DString eventFun; // event handler FUN DString notifyRealize; DString killNotify; void GetCommonKeywords( EnvT* e); void DefaultValuesInAbsenceofEnv(); public: typedef enum BGroupMode_ { BGNORMAL=0 , BGEXCLUSIVE=1 , BGNONEXCLUSIVE=2 , BGEXCLUSIVE1ST=3 } BGroupMode; typedef enum EventTypeFlags_ { EV_NONE = 0 , EV_ALL = 1 , EV_CONTEXT = 2 , EV_KBRD_FOCUS = 4 , EV_TRACKING = 8 , EV_DROP = 16 , EV_EXPOSE = 32 , EV_MOTION = 64 , EV_VIEWPORT = 128 , EV_WHEEL = 256 , EV_BUTTON = 512 , EV_KEYBOARD = 1024 //widget_draw, normal keys in the KEY field, modifiers reported in the "MODIFIERS" field , EV_KEYBOARD2 = 2048 //widget_draw, normal keys and compose keys reported in the KEY field , EV_SIZE = 4096 , EV_MOVE = 8192 , EV_ICONIFY = 16384 , EV_DRAG = 32768 , EV_KILL = 65536 } EventTypeFlags; typedef enum WidgetTypes_ { WIDGET_UNKNOWN = -1 ,WIDGET_BASE = 0 ,WIDGET_BUTTON ,WIDGET_SLIDER ,WIDGET_TEXT ,WIDGET_DRAW ,WIDGET_LABEL ,WIDGET_LIST ,WIDGET_MBAR //actually this is not present in IDL, but this place is void in IDL... ,WIDGET_DROPLIST ,WIDGET_TABLE ,WIDGET_TAB ,WIDGET_TREE ,WIDGET_COMBOBOX ,WIDGET_PROPERTYSHEET } WidgetTypes; enum { gdlwALIGN_NOT=0, gdlwALIGN_LEFT=1, gdlwALIGN_CENTER=2, gdlwALIGN_RIGHT=4, gdlwALIGN_TOP=8, gdlwALIGN_BOTTOM=16 } gdlAlignmentPossibilities; DULong GetEventFlags() const { return eventFlags;} bool HasEventType( DULong evType) const { return (eventFlags & evType) != 0;} void AddEventType( DULong evType) { eventFlags |= evType;} void RemoveEventType( DULong evType) { eventFlags &= ~evType;} void Raise(); void Lower(); long buttonTextAlignment(); long textAlignment(); long widgetAlignment(); long getDefautAlignment(); void widgetUpdate(bool update); void ChangeUnitConversionFactor( EnvT* e); wxRealPoint GetRequestedUnitConversionFactor( EnvT* e); wxRealPoint GetCurrentUnitConversionFactor(){return unitConversionFactor;} void SetCurrentUnitConversionFactor(wxRealPoint value){unitConversionFactor = value;} DStructGDL* GetGeometry(wxRealPoint fact=wxRealPoint(1.0,1.0)); GDLWidget( WidgetIDT p, EnvT* e, BaseGDL* vV=NULL, DULong eventFlags_=0); virtual ~GDLWidget(); // this is called from the GUI thread on (before) Show() // wxTextCtrl and maybe other controls crash when called from the // main thread // virtual void OnShow(); // this is called from the main thread on (before) Realize() // for latest initialzation (like allocating the plplot stream) // calls NOTIFY_REALIZE procedure virtual void OnRealize() { if( notifyRealize != "") { //insure it is called once only for this. std::string note=notifyRealize; notifyRealize.clear(); CallEventPro( note, new DLongGDL( widgetID)); } } virtual void OnKill() { if( killNotify != ""){ //remove kill notify for this widget BEFORE calling it (avoid infinite recursal) std::string RIP=killNotify; killNotify.clear(); CallEventPro( RIP, new DLongGDL( widgetID)); } } virtual void ReorderWidgets(){} //do Nothing, only for Base. virtual void AddToFollowers(WidgetIDT him) { followers.insert( followers.end( ), him ); } void SetSizeHints(); void SetSize(DLong sizex, DLong sizey); DLong GetXSize(){return xSize;} DLong GetYSize(){return ySize;} DLong GetXPos(){return static_cast(wxWidget)->GetPosition().x;} DLong GetYPos(){return static_cast(wxWidget)->GetPosition().y;} bool IsValid(){return valid;} void SetUnValid(){valid=false;} void SetValid(){valid=true;} bool IsDynamicResize(){return dynamicResize>0;} void SetDynamicResize(){if (dynamicResize > -1) dynamicResize=1;} void UnsetDynamicResize(){if (dynamicResize > -1) dynamicResize=0;} void authorizeDynamicResize(){dynamicResize=1;} WidgetIDT GetParentID() const { return parentID;} wxObject* GetWxWidget() const { return wxWidget;} void FrameWidget(); void ScrollWidget(DLong x_scroll_size, DLong y_scroll_size); void UnFrameWidget(); void UnScrollWidget(); BaseGDL* GetUvalue() const { return uValue;} BaseGDL* GetVvalue() const { return vValue;} void Realize( bool); void SendWidgetTimerEvent(DDouble secs); // for query of children virtual bool IsContainer() const { return false;} virtual bool IsBase() const { return false;} virtual bool IsButton() const { return false;} virtual bool IsDropList() const { return false;} virtual bool IsList() const { return false;} virtual bool IsComboBox() const { return false;} virtual bool IsTab() const { return false;} virtual bool IsTable() const { return false;} virtual bool IsText() const { return false;} virtual bool IsLabel() const { return false;} virtual bool IsTree() const { return false;} virtual bool IsSlider() const { return false;} virtual bool IsDraw() const { return false;} virtual bool IsMenuBar() const { return false;} virtual bool IsPropertySheet() const { return false;} virtual bool IsGraphicWindowFrame() const { return false;} virtual WidgetIDT GetChild( DLong) const {return NullID;} virtual DLong NChildren() const { return 0;} virtual DLongGDL* GetChildrenList() const {return new DLongGDL(0);} virtual void SetXmanagerActiveCommand() {} virtual bool GetXmanagerActiveCommand() const { return false;} void SetEventPro( const DString& ePro) { eventPro = StrUpCase( ePro);} const DString& GetEventPro() const { return eventPro;}; void SetEventFun( const DString& eFun) { eventFun = StrUpCase( eFun);} const DString& GetEventFun() const { return eventFun;} void SetNotifyRealize( const DString& eNR) { notifyRealize = StrUpCase( eNR);} const DString& GetNotifyRealize() const { return notifyRealize;} void SetKillNotify( const DString& eKN) { killNotify = StrUpCase( eKN);} const DString& GetKillNotify() const { return killNotify;} static bool GetXmanagerBlock(); static DLong GetNumberOfWidgets(); static BaseGDL* GetWidgetsList(); static BaseGDL* GetManagedWidgetsList(); WidgetIDT WidgetID() { return widgetID;} wxSizer* GetSizer() { return widgetSizer;} wxSizer* GetTopSizer() { return topWidgetSizer;} wxPanel* GetPanel() { return widgetPanel;} bool GetManaged() const { return managed;} bool GetRealized(); void SetManaged( bool manval){managed = manval;} virtual void SetSensitive( bool value); virtual void SetFocus(); int GetExclusiveMode() const { return exclusiveMode;} void SetExclusiveMode( int exclusiveval){exclusiveMode = exclusiveval;} void SetUvalue( BaseGDL *uV){uValue = uV;} // void SetVvalue( BaseGDL *vV){vValue = vV;} //unused! const DString& GetWidgetName() const { return widgetName;} void SetWidgetName( const DString& wName){widgetName = wName;} DInt GetWidgetType() { return widgetType;} void SetWidgetType( DInt type){widgetType=widgetTypeList[type]; widgetName = widgetNameList[type];} virtual bool GetButtonSet() const { return 0;} //normally not a button // void SetButtonSet(bool onOff){buttonSet = onOff;} const DString& GetUname() const { return uName;} void SetUname( const DString& uname){uName = uname;} const DString& GetProValue() const { return proValue;} void SetProValue( const DString& provalue){proValue = StrUpCase(provalue);} const DString& GetFuncValue() const { return funcValue;} void SetFuncValue( const DString& funcvalue){funcValue = StrUpCase(funcvalue);} wxSize computeWidgetSize(); BaseGDL * getSystemColours(); void ConnectToDesiredEvents(); }; class GDLWidgetContainer: public GDLWidget { bool map; protected: typedef std::deque::iterator cIter; typedef std::deque::reverse_iterator rcIter; std::deque children; public: GDLWidgetContainer( WidgetIDT parentID, EnvT* e, ULong eventFlags_=0, bool map=TRUE); // ~GDLWidgetContainer(){} bool IsContainer() const { return true;} void OnRealize() { if(this->IsBase()){ this->ReorderWidgets(); } for( cIter c=children.begin(); c!=children.end(); ++c) { GDLWidget* w = GetWidget( *c); if( w != NULL) w->OnRealize(); } GDLWidget::OnRealize(); } // as this is called in the constructor, no type checking of c can be done // hence the AddChild() function should be as simple as that void AddChild( WidgetIDT c) { children.push_back( c);} void RemoveChild( WidgetIDT c) { std::deque::iterator it = find(children.begin(), children.end(), c); // Find first, if (it != children.end()) children.erase(it); // ... and remove. } DLong NChildren() const { return children.size( ); } WidgetIDT GetChild( DLong childIx) const { assert( childIx >= 0 ); assert( childIx < children.size( ) ); return children[childIx]; } DLongGDL* GetChildrenList() { DLong size=children.size( ); if (size<1) return new DLongGDL(0); DLongGDL* ret=new DLongGDL(dimension(size),BaseGDL::ZERO); for (SizeT i=0; i< size; ++i) (*ret)[i]=children[i]; return ret; } bool GetMap() const { return map;} void SetMap( bool mapval){ map = mapval;} }; // base widget ************************************************** class GDLWidgetBase: public GDLWidgetContainer { bool xmanActCom; bool modal; WidgetIDT mbarID; // for radio buttons to generate deselect event WidgetIDT lastRadioSelection; DLong ncols; DLong nrows; bool stretchX; bool stretchY; long childrenAlignment; long space; long xpad; long ypad; bool IsContextMenu; public: GDLWidgetBase( WidgetIDT parentID, EnvT* e, ULong eventFlags_, bool mapWid, WidgetIDT& mBarIDInOut, bool modal, DLong col, DLong row, int exclusiveMode, bool floating, const DString& resource_name, const DString& rname_mbar, const DString& title, const DString& display_name, DLong xpad, DLong ypad, DLong x_scroll_size, DLong y_scroll_size, bool grid_layout, long children_alignment=wxALIGN_LEFT, long space=0, bool iscontextmenu=false, bool isAGraphicWindow=false); ~GDLWidgetBase(); void ClearEvents() { if (!this->GetXmanagerActiveCommand( )) eventQueue.Purge(); else readlineEventQueue.Purge(); } void NullWxWidget() { this->wxWidget = NULL;} WidgetIDT GetLastRadioSelection() const { return lastRadioSelection;} void SetLastRadioSelection(WidgetIDT lastSel) { lastRadioSelection = lastSel;} void SelfDestroy(); // sends delete event to itself void SetXmanagerActiveCommand() { xmanActCom = true; } bool GetXmanagerActiveCommand() const { return xmanActCom; } bool IsBase() const { return true;} bool IsContainer() const { return true;} bool IsScrolled() { return scrolled;} bool IsStretchable() {return stretchX||stretchY;} void SetStretchX(bool stretch) {stretchX=stretch;} void SetStretchY(bool stretch) {stretchY=stretch;} long getChildrenAlignment(){return childrenAlignment;} long getSpace(){return space;} long getXPad(){return xpad;} long getYPad(){return ypad;} void mapBase(bool val); DStructGDL* GetGeometry(wxRealPoint fact=wxRealPoint(1.0,1.0)); //Apparently children of a base are plotted in reverse order in IDL (last first) void ReorderWidgets(); }; class gdlMenuButton: public wxButton { wxMenu* popupMenu; // wxPoint* popupPosition; public: gdlMenuButton(wxWindow *parent, wxWindowID id, const wxString &label=wxEmptyString, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0, const wxValidator &validator=wxDefaultValidator, const wxString &name=wxButtonNameStr): wxButton(parent,id,label,pos,size,style,validator,name){ popupMenu=new wxMenu(); Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(gdlMenuButton::OnButton)); Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gdlMenuButton::OnButton)); } // ~gdlMenuButton(){delete popupMenu;} wxMenu* GetPopupMenu(){return popupMenu;} void SetPopupMenu(wxMenu* menu){popupMenu=menu;} private: void OnButton(wxCommandEvent& event); }; class gdlMenuButtonBitmap: public wxBitmapButton { wxMenu* popupMenu; // wxPoint* popupPosition; public: gdlMenuButtonBitmap(wxWindow *parent, wxWindowID id, const wxBitmap &bitmap_, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxBU_AUTODRAW, const wxValidator &validator=wxDefaultValidator, const wxString &name=wxButtonNameStr): wxBitmapButton(parent,id,bitmap_,pos,size,style,validator,name){ popupMenu=new wxMenu(); Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(gdlMenuButtonBitmap::OnButton)); Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gdlMenuButtonBitmap::OnButton)); } // ~gdlMenuButtonBitmap(){delete popupMenu;} wxMenu* GetPopupMenu(){return popupMenu;} void SetPopupMenu(wxMenu* menu){popupMenu=menu;} private: void OnButton(wxCommandEvent& event); }; class GDLWidgetButton: public GDLWidget { typedef enum ButtonType_ { UNDEFINED=-1, NORMAL=0, RADIO=1, CHECKBOX=2, MENU=3, ENTRY=4, BITMAP=5, POPUP_NORMAL=6, POPUP_BITMAP=7} ButtonType; ButtonType buttonType; bool addSeparatorAbove; wxBitmap* buttonBitmap; wxMenuItem* menuItem; protected: typedef std::deque::iterator cIter; typedef std::deque::reverse_iterator rcIter; std::deque children; //as for Containers since buttons may be menus and thus containers. // bool buttonState; //defined in base class now. public: GDLWidgetButton( WidgetIDT parentID, EnvT* e, const DString& value, DULong eventflags, bool isMenu, bool hasSeparatorAbove=FALSE, wxBitmap* bitmap=NULL, DStringGDL* buttonTooltip=NULL); ~GDLWidgetButton(); // for WIDGET_CONTROL bool IsBitmapButton(){return ( buttonType==POPUP_BITMAP || buttonType==BITMAP);} bool IsEntry(){return ( buttonType==ENTRY);} void SetButtonWidget( bool onOff) { if( wxWidget != NULL) { switch( buttonType) { case RADIO: { SetButton( onOff); wxRadioButton* radioButton = static_cast(wxWidget); radioButton->SetValue(onOff); break; } case CHECKBOX: { SetButton( onOff); wxCheckBox* checkBox = static_cast(wxWidget); checkBox->SetValue(onOff); break; } default: break; } } } void SetButtonWidgetLabelText( const DString& value_ );//code in gdlwidget void SetButtonWidgetBitmap( wxBitmap* bitmap_ );//code in gdlwidget void SetButton( bool onOff) { buttonState = onOff; } bool GetButtonSet() const { return buttonState; } bool IsButton() const { return true;} void SetSensitive(bool value) { switch(buttonType){ case MENU: case ENTRY: if (menuItem) menuItem->Enable(value); break; default: wxWindow *me=static_cast(wxWidget); if (me) { if (value) me->Enable(); else me->Disable();} } } //same as containers void AddChild( WidgetIDT c) { children.push_back( c);} void RemoveChild( WidgetIDT c) { std::deque::iterator it = find(children.begin(), children.end(), c); // Find first, if (it != children.end()) children.erase(it); // ... and remove. } DLong NChildren() const { return children.size( ); } WidgetIDT GetChild( DLong childIx) const { assert( childIx >= 0 ); assert( childIx < children.size( ) ); return children[childIx]; } DLongGDL* GetChildrenList() { DLong size=children.size( ); if (size<1) return new DLongGDL(0); DLongGDL* ret=new DLongGDL(dimension(size),BaseGDL::ZERO); for (SizeT i=0; i< size; ++i) (*ret)[i]=children[i]; return ret; } }; // droplist widget ************************************************** class GDLWidgetDropList: public GDLWidget { std::string lastValue; DString title; DLong style; public: GDLWidgetDropList( WidgetIDT p, EnvT* e, BaseGDL *value, DULong eventflags, const DString& title, DLong style); ~GDLWidgetDropList(); bool IsDropList() const { return true;} void SetLastValue( const std::string& v) { lastValue = v;} std::string GetLastValue() { return lastValue;} void SetValue(BaseGDL *value); void SelectEntry(DLong entry_number); BaseGDL* GetSelectedEntry(); }; // combobox widget ************************************************** class GDLWidgetComboBox: public GDLWidget { std::string lastValue; DString title; DLong style; public: GDLWidgetComboBox( WidgetIDT p, EnvT* e, BaseGDL *value, DULong eventflags, const DString& title, DLong style); ~GDLWidgetComboBox(); // void OnShow(); // void SetSelectOff(); bool IsComboBox() const { return true;} void SetLastValue( const std::string& v) { lastValue = v;} std::string GetLastValue() { return lastValue;} void SetValue(BaseGDL *value); void SelectEntry(DLong entry_number); BaseGDL* GetSelectedEntry(); void AddItem(DString value, DLong pos); void DeleteItem(DLong pos); }; // list widget ************************************************** class GDLWidgetList : public GDLWidget { int maxlinelength; int nlines; public: GDLWidgetList( WidgetIDT p, EnvT* e, BaseGDL *value, DLong style, DULong eventflags); ~GDLWidgetList(); bool IsList() const { return true;} void SetValue(BaseGDL *value); void SelectEntry(DLong entry_number); BaseGDL* GetSelectedEntries(); wxSize computeWidgetSize(); DStructGDL* GetGeometry(wxRealPoint fact=wxRealPoint(1.0,1.0)); }; // text widget ************************************************** class gdlTextCtrl : public wxTextCtrl { public: gdlTextCtrl(wxWindow *parent, wxWindowID id, const wxString &value = wxEmptyString, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString &name = wxTextCtrlNameStr): wxTextCtrl(parent, id,value,pos,size,style,validator,name){ Connect(id,wxEVT_CHAR, wxKeyEventHandler(gdlTextCtrl::OnChar)); } ~ gdlTextCtrl(){} private: void OnChar(wxKeyEvent& event ); }; class GDLWidgetText: public GDLWidget { std::string lastValue; bool noNewLine; bool editable; int maxlinelength; int nlines; public: GDLWidgetText( WidgetIDT parentID, EnvT* e, DStringGDL* value, DULong eventflags, bool noNewLine, bool editable); ~GDLWidgetText(); bool IsEditable(){return editable;} void ChangeText( DStringGDL* value, bool noNewLine=false); void InsertText( DStringGDL* value, bool noNewLine=false, bool insertAtEnd=false); void SetTextSelection(DLongGDL* pos); DLongGDL* GetTextSelection(); DStringGDL* GetSelectedText(); void AppendTextValue( DStringGDL* value, bool noNewLine); bool IsText() const { return true;} void SetLastValue( const std::string& v) { lastValue = v;} std::string GetLastValue() { return lastValue;} wxSize computeWidgetSize(); DStructGDL* GetGeometry(wxRealPoint fact=wxRealPoint(1.0,1.0)); }; // label widget ************************************************** class GDLWidgetLabel: public GDLWidget { DString value; public: GDLWidgetLabel( WidgetIDT parentID, EnvT* e, const DString& value_, DULong eventflags, bool sunken); ~GDLWidgetLabel(); void SetLabelValue( const DString& value_); bool IsLabel() const { return true;} }; // draw widget ************************************************** class GDLWidgetDraw: public GDLWidget { int pstreamIx; DLong x_scroll_size; DLong y_scroll_size; public: GDLWidgetDraw( WidgetIDT parentID, EnvT* e, int windowIndex, DLong special_xsize, DLong special_ysize, DLong x_scroll_size, DLong y_scroll_size, bool app_scroll, DULong eventFlags, DStringGDL* drawToolTip=NULL); // ~GDLWidgetDraw(); // void OnRealize(); bool IsDraw() const { return true;} void AddEventType( DULong evType); //specific for draw widgets void RemoveEventType( DULong evType); DStructGDL* GetGeometry(wxRealPoint fact=wxRealPoint(1.0,1.0)); }; // menu bar widget ************************************************** class GDLWidgetMBar: public GDLWidgetContainer//Base { // disable // ~GDLWidgetMBar(); public: GDLWidgetMBar( WidgetIDT p, EnvT* e): GDLWidgetContainer( p, e) { this->wxWidget = new wxMenuBar(); if (this->GetWidgetType()==GDLWidget::WIDGET_UNKNOWN ) this->SetWidgetType(WIDGET_MBAR); } bool IsMenuBar() const { return true;} }; // tab widget ************************************************** class GDLWidgetTab: public GDLWidgetContainer { public: GDLWidgetTab( WidgetIDT parentID, EnvT* e, ULong eventFlags, DLong location, DLong multiline); ~GDLWidgetTab(); bool IsTab() const { return true;} bool IsContainer() const { return true;} BaseGDL* GetTabNumber(); BaseGDL* GetTabCurrent(); void SetTabCurrent(int val); BaseGDL* GetTabMultiline(); //not exactly what expected, fixme. }; // table widget ************************************************** class GDLWidgetTable: public GDLWidget { DByteGDL* table_alignment; DStringGDL* amPm; DByteGDL* backgroundColor; DByteGDL* foregroundColor; DStringGDL* columnLabels; int majority; DLongGDL* columnWidth; DStringGDL* daysOfWeek; bool disjointSelection; DByteGDL* editable; DStringGDL* format; // bool ignoreAccelerators; DStringGDL* month; bool noColumnHeaders; bool noRowHeaders; bool resizeableColumns; bool resizeableRows; DLongGDL* rowHeights; DStringGDL* rowLabels; // DLong tabMode; DLong x_scroll_size; DLong y_scroll_size; DStringGDL * valueAsStrings; bool updating; //widget is modified by program (avoid sending events) public: typedef enum TableMajority_ {NONE_MAJOR = 0, ROW_MAJOR, COLUMN_MAJOR} TableMajority; GDLWidgetTable( WidgetIDT p, EnvT* e, DByteGDL* alignment_, DStringGDL* amPm_, DByteGDL* backgroundColor_, DByteGDL* foregroundColor_, DStringGDL* columnLabels_, int majority_, DLongGDL* columnWidth_, DStringGDL* daysOfWeek_, bool disjointSelection_, DByteGDL* editable_, DStringGDL* format_, // bool ignoreAccelerators_, DStringGDL* month_, bool noColumnHeaders_, bool noRowHeaders_, bool resizeableColumns_, bool resizeableRows_, DLongGDL* rowHeights_, DStringGDL* rowLabels_, // DLong tabMode_, BaseGDL* value_, DLong xScrollSize_, DLong yScrollSize_, DStringGDL* valueAsStrings_, DULong eventFlags_ ); ~GDLWidgetTable(); int GetMajority(){return majority;} bool IsTable() const { return true;} void SetDOW(DStringGDL* val){GDLDelete(daysOfWeek); daysOfWeek=val->Dup();} void SetAmPm(DStringGDL* val){GDLDelete(amPm); amPm=val->Dup();}; void SetMonth(DStringGDL* val){GDLDelete(month); month=val->Dup();}; DLongGDL* GetSelection(); void SetAlignment(DByteGDL* val){GDLDelete(table_alignment); table_alignment=val->Dup();}; void DoAlign(); void DoAlign(DLongGDL* selection); void SetBackgroundColor(DByteGDL* val){GDLDelete(backgroundColor); backgroundColor=val->Dup();}; void DoBackgroundColor(); void DoBackgroundColor(DLongGDL* selection); void SetForegroundColor(DByteGDL* val){GDLDelete(foregroundColor); foregroundColor=val->Dup();}; void DoForegroundColor(); void DoForegroundColor(DLongGDL* selection); void SetColumnLabels(DStringGDL* val){GDLDelete(columnLabels); columnLabels=val->Dup();}; void DoColumnLabels(); void SetRowLabels(DStringGDL* val){GDLDelete(rowLabels); rowLabels=val->Dup();}; void DoRowLabels(); void SetColumnWidth(DLongGDL* val){GDLDelete(columnWidth); columnWidth=val->Dup();}; void DoColumnWidth(); void DoColumnWidth(DLongGDL* selection); DFloatGDL* GetColumnWidth(DLongGDL* selection=NULL); void SetRowHeights(DLongGDL* val){GDLDelete(rowHeights); rowHeights=val->Dup();}; void DoRowHeights(); void DoRowHeights(DLongGDL* selection); DFloatGDL* GetRowHeight(DLongGDL* selection=NULL); bool GetDisjointSelection(){return disjointSelection;} void SetDisjointSelection(bool b){disjointSelection = b;} void ClearSelection(); void DeleteColumns(DLongGDL* selection=NULL); void DeleteRows(DLongGDL* selection=NULL); bool InsertColumns(DLong count, DLongGDL* selection=NULL); bool InsertRows(DLong count, DLongGDL* selection=NULL); void SetSelection(DLongGDL* selection); DStringGDL* GetTableValues(DLongGDL* selection=NULL); BaseGDL* GetTableValuesAsStruct(DLongGDL* selection=NULL); void SetTableValues(DStringGDL *val, DLongGDL* selection=NULL); void SetValue(BaseGDL * val){GDLDelete(vValue); vValue=val->Dup();}; void SetTableView(DLongGDL* pos); void EditCell(DLongGDL* pos); void SetTableNumberOfColumns( DLong ncols); void SetTableNumberOfRows( DLong nrows); bool IsSomethingSelected(); bool IsUpdating(){return updating;} void ClearUpdating(){updating=FALSE;} void SetUpdating(){updating=TRUE;} DStructGDL* GetGeometry(wxRealPoint fact=wxRealPoint(1.0,1.0)); }; // tree widget ************************************************** class gdlTreeCtrl: public wxTreeCtrl { wxWindowID GDLWidgetTableID; public: gdlTreeCtrl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_DEFAULT_STYLE, const wxValidator &validator = wxDefaultValidator, const wxString& name = wxTreeCtrlNameStr) :wxTreeCtrl( parent, id, pos, size, style, wxDefaultValidator , name ) { GDLWidgetTableID=id; Connect(id, wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler(gdlTreeCtrl::OnItemActivated)); Connect(id, wxEVT_COMMAND_TREE_ITEM_ACTIVATED,wxTreeEventHandler(gdlTreeCtrl::OnItemActivated)); Connect(id, wxEVT_COMMAND_TREE_BEGIN_DRAG,wxTreeEventHandler(gdlTreeCtrl::OnBeginDrag)); Connect(id, wxEVT_COMMAND_TREE_END_DRAG,wxTreeEventHandler(gdlTreeCtrl::OnItemDropped)); Connect(id, wxEVT_COMMAND_TREE_ITEM_COLLAPSED,wxTreeEventHandler(gdlTreeCtrl::OnItemCollapsed)); Connect(id, wxEVT_COMMAND_TREE_ITEM_EXPANDED,wxTreeEventHandler(gdlTreeCtrl::OnItemExpanded)); Connect(id, wxEVT_COMMAND_TREE_SEL_CHANGED,wxTreeEventHandler(gdlTreeCtrl::OnItemSelected)); } //necessary to define the destructor otherwise compiler will try to find the bind event table for destruction event! ~gdlTreeCtrl(){} private: void OnItemActivated(wxTreeEvent & event); void OnItemCollapsed(wxTreeEvent & event); void OnItemExpanded(wxTreeEvent & event); void OnBeginDrag(wxTreeEvent & event); void OnItemDropped(wxTreeEvent & event); void OnItemSelected(wxTreeEvent & event); }; class gdlTreeItemData : public wxTreeItemData { public: WidgetIDT widgetID; gdlTreeItemData(WidgetIDT id) : widgetID(id) {} }; class GDLWidgetTree: public GDLWidget { //bool alignBottom; //bool alignTop ; //BaseGDL* bitmap ; //bool checkbox ; //DLong checked ; //DString dragNotify ; bool droppable ; bool draggable ; //bool mask ; //bool multiple ; //bool noBitmaps ; //DLong tabMode ; //DString toolTip ; bool expanded; bool folder; int buttonImageId; int imageId; WidgetIDT selectedID; wxTreeItemId treeItemID; gdlTreeItemData* treeItemData; WidgetIDT rootID; public: GDLWidgetTree( WidgetIDT p, EnvT* e, BaseGDL* value_, DULong eventFlags //,bool alignBottom_ //,bool alignTop_ ,wxBitmap* bitmap_ //,bool checkbox_ //,DLong checked_ //,DString dragNotify_ ,DLong dropability ,DLong dragability ,bool expanded_ ,bool folder_ ,DLong treeindex //,bool mask_ //,bool multiple_ //,bool noBitmaps_ //,DLong tabMode_ //,DString toolTip_ ); ~GDLWidgetTree(); bool IsTree() const { return true;} bool IsDraggable() {return draggable;} bool IsDroppable() {return droppable;} bool IsFolder() {return folder;} bool IsExpanded() {return expanded;} void DoExpand(){ gdlTreeCtrl * me = static_cast(wxWidget); if (me) me->Expand(treeItemID); } WidgetIDT GetRootID(){ return rootID;} void SetSelectedID( WidgetIDT id){selectedID=id;} WidgetIDT GetSelectedID(){ return selectedID;} DInt GetTreeIndex(); wxTreeItemId GetItemID(){ return treeItemID;} void SetValue(DString val); }; // slider widget ************************************************** class GDLWidgetSlider: public GDLWidget { DLong value; DLong minimum; DLong maximum; DString title; public: GDLWidgetSlider( WidgetIDT parentID, EnvT* e, DLong value_, DULong eventFlags_ , DLong minimum_, DLong maximum_, bool vertical, bool suppressValue, DString title ); ~GDLWidgetSlider(); void SetValue( DLong v) { value = v;} void ControlSetValue ( DLong v ); void ControlSetMinValue ( DLong v ); void ControlSetMaxValue ( DLong v ); DLong GetValue() const { return value;} bool IsSlider() const { return true;} }; // GDL versions of wxWidgets controls ======================================= DECLARE_LOCAL_EVENT_TYPE(wxEVT_SHOW_REQUEST, -1) DECLARE_LOCAL_EVENT_TYPE(wxEVT_HIDE_REQUEST, -1) class wxNotebookEvent; class wxGridEvent; class wxGridSizeEvent; class wxGridRangeSelectEvent; class gdlGrid : public wxGrid { wxWindowID GDLWidgetTableID; public: gdlGrid(wxWindow* container, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr): wxGrid( container, id, pos, size, style, name ) , GDLWidgetTableID(id) { Connect(id,wxEVT_GRID_COL_SIZE,wxGridSizeEventHandler(gdlGrid::OnTableColResizing)); Connect(id,wxEVT_GRID_ROW_SIZE,wxGridSizeEventHandler(gdlGrid::OnTableRowResizing)); Connect(id,wxEVT_GRID_RANGE_SELECT,wxGridRangeSelectEventHandler(gdlGrid::OnTableRangeSelection)); Connect(id,wxEVT_GRID_SELECT_CELL,wxGridEventHandler(gdlGrid::OnTableCellSelection)); // Connect(id,wxEVT_GRID_CELL_LEFT_CLICK,wxGridEventHandler(gdlGrid::OnTableCellSelection)); } ~gdlGrid(){ #ifdef GDL_DEBUG_WIDGETS std::cout << "~GDLGrid: " << this << std::endl; #endif } bool IsSomethingSelected(){ wxGridCellCoordsArray cellSelection=this->GetSelectedCells(); if ( cellSelection.Count() > 0 ) return TRUE; wxGridCellCoordsArray selectionBR=this->GetSelectionBlockBottomRight(); if ( selectionBR.Count() > 0 ) return TRUE; wxArrayInt selectionRow=this->GetSelectedRows(); if ( selectionRow.GetCount() > 0 ) return TRUE; wxArrayInt selectionCol=this->GetSelectedCols(); if ( selectionCol.GetCount() > 0 ) return TRUE; return FALSE; } std::vector GetSelectedDisjointCellsList(){ std::vector list; wxGridCellCoordsArray cellSelection=this->GetSelectedCells(); for( int i=0; iGetSelectionBlockTopLeft(); wxGridCellCoordsArray selectionBR=this->GetSelectionBlockBottomRight(); for( int k=0; kGetSelectedRows(); for( int k=0; kGetNumberCols(); ++i) list.push_back(wxPoint(row,i)); } wxArrayInt selectionCol=this->GetSelectedCols(); for( int k=0; kGetNumberRows(); ++i) list.push_back(wxPoint(i,col)); } return list; } wxArrayInt GetSelectedBlockOfCells() { wxArrayInt block; wxGridCellCoordsArray selectionTL = this->GetSelectionBlockTopLeft(); wxGridCellCoordsArray selectionBR = this->GetSelectionBlockBottomRight(); if (selectionBR.Count() > 0) { for (int k = 0; k < selectionBR.Count(); k++) { int colTL = selectionTL[k].GetCol(); block.push_back(colTL); int rowTL = selectionTL[k].GetRow(); block.push_back(rowTL); int colBR = selectionBR[k].GetCol(); block.push_back(colBR); int rowBR = selectionBR[k].GetRow(); block.push_back(rowBR); } return block; } wxArrayInt selectionRow=this->GetSelectedRows(); if (selectionRow.GetCount() > 0) { block.push_back(0); block.push_back(selectionRow[0]); block.push_back(this->GetNumberCols()-1); block.push_back(selectionRow[selectionRow.GetCount()-1]); return block; } wxArrayInt selectionCol=this->GetSelectedCols(); if (selectionCol.GetCount() > 0) { block.push_back(selectionCol[0]); block.push_back(0); block.push_back(selectionCol[selectionCol.GetCount()-1]); block.push_back(this->GetNumberRows()-1); return block; } wxGridCellCoordsArray cellSelection=this->GetSelectedCells(); //last chance for block selection, return only first if exist! if (cellSelection.Count()==0) return block; //should produce error... int row = cellSelection[0].GetRow(); int col = cellSelection[0].GetCol(); block.push_back(col); block.push_back(row); block.push_back(col); block.push_back(row); return block; } wxArrayInt GetSortedSelectedColsList(){ std::vector list=GetSelectedDisjointCellsList(); wxArrayInt cols; if (list.empty()) return cols; std::vector::iterator iPoint; std::vector allCols; std::vector::iterator iter; for ( iPoint = list.begin(); iPoint !=list.end(); ++iPoint) { allCols.push_back((*iPoint).y); } std::sort (allCols.begin(), allCols.end()); int theCol=-1; for ( iter = allCols.begin(); iter !=allCols.end(); ++iter) { if ((*iter)!=theCol) {theCol=(*iter);cols.Add(theCol);} } return cols; } wxArrayInt GetSortedSelectedRowsList(){ std::vector list=GetSelectedDisjointCellsList(); wxArrayInt rows; if (list.empty()) return rows; std::vector::iterator iPoint; std::vector allRows; std::vector::iterator iter; for ( iPoint = list.begin(); iPoint !=list.end(); ++iPoint) { allRows.push_back((*iPoint).x); } std::sort (allRows.begin(), allRows.end()); int theRow=-1; for ( iter = allRows.begin(); iter !=allRows.end(); ++iter) { if ((*iter)!=theRow) {theRow=(*iter);rows.Add(theRow);} } return rows; } private: void OnTableCellSelection(wxGridEvent & event); void OnTableRangeSelection(wxGridRangeSelectEvent & event); void OnTableColResizing(wxGridSizeEvent & event); void OnTableRowResizing(wxGridSizeEvent & event); // void OnText( wxCommandEvent& event); // void OnTextEnter( wxCommandEvent& event); }; #ifdef HAVE_WXWIDGETS_PROPERTYGRID class GDLWidgetPropertySheet : public GDLWidget { public: GDLWidgetPropertySheet( WidgetIDT parentID, EnvT* e); ~GDLWidgetPropertySheet(); bool IsPropertySheet() const { return true;} }; #endif class GDLFrame : public wxFrame { enum {WINDOW_TIMER = wxID_HIGHEST, RESIZE_TIMER}; bool mapped; bool noFocus; wxSize frameSize; GDLApp* appOwner; GDLWidgetBase* gdlOwner; wxTimer * m_resizeTimer; wxTimer * m_windowTimer; // bool updating; // called from ~GDLWidgetBase void NullGDLOwner() { gdlOwner = NULL;} friend class GDLWidgetBase; public: // ctor(s) GDLFrame(GDLWidgetBase* gdlOwner_, wxWindowID id, const wxString& title, const bool nofocus=false, const wxPoint& pos=wxDefaultPosition); ~GDLFrame(); GDLApp* GetTheApp(){return appOwner;} void SetTheApp(GDLApp* myApp){appOwner=myApp;} GDLWidgetBase* GetGDLOwner(){return gdlOwner;} bool IsMapped() const { return mapped;} bool focusNotPermitted() const {return noFocus;} void SendWidgetTimerEvent(DDouble secs, WidgetIDT winId) { WidgetIDT* id=new WidgetIDT(winId); int millisecs=floor(secs*1000.0); this->GetEventHandler()->SetClientData(id); m_windowTimer->SetOwner(this->GetEventHandler(),WINDOW_TIMER); m_windowTimer->Start(millisecs, wxTIMER_ONE_SHOT); } void SendShowRequestEvent() { wxCommandEvent* event; event = new wxCommandEvent( wxEVT_SHOW_REQUEST, GetId() ); event->SetEventObject( this ); // only for wWidgets > 2.9 (takes ownership of event) // this->QueueEvent( event); //this->AddPendingEvent( *event); // copies event this->OnShowRequest( *event); // JP Apr 2015: Should block the main thread until the window opens, // so that the following WIDGET_INFO can properly read // the window's properties. delete event; mapped = TRUE; } void SendHideRequestEvent() { wxCommandEvent* event; event = new wxCommandEvent( wxEVT_HIDE_REQUEST, GetId() ); event->SetEventObject( this ); // only for wWidgets > 2.9 (takes ownership of event) // this->QueueEvent( event); this->AddPendingEvent( *event); // copies event delete event; mapped = FALSE; } // event handlers (these functions should _not_ be virtual) void OnDropList( wxCommandEvent& event); void OnListBox( wxCommandEvent& event); void OnListBoxDoubleClicked( wxCommandEvent& event); void OnComboBox( wxCommandEvent& event); void OnComboBoxTextEnter( wxCommandEvent& event); void OnButton( wxCommandEvent& event); void OnRadioButton( wxCommandEvent& event); void OnCheckBox( wxCommandEvent& event); void OnPageChanged( wxNotebookEvent& event); void OnText( wxCommandEvent& event); void OnTextEnter( wxCommandEvent& event); void OnThumbTrack( wxScrollEvent& event); void OnThumbRelease( wxScrollEvent& event); void OnSize( wxSizeEvent& event); //unused. void OnIconize( wxIconizeEvent & event); void OnMove( wxMoveEvent & event); void OnCloseFrame( wxCloseEvent & event); void OnUnhandledCloseFrame( wxCloseEvent & event); void OnCloseWindow( wxCloseEvent & event); void OnEnterWindow(wxMouseEvent& event); void OnLeaveWindow(wxMouseEvent& event); void OnShowRequest( wxCommandEvent& event); void OnHideRequest( wxCommandEvent& event); void OnIdle( wxIdleEvent& event); void OnMenu( wxCommandEvent& event); void OnSizeWithTimer( wxSizeEvent& event); void OnTimerResize(wxTimerEvent& event); void OnContextEvent( wxContextMenuEvent& event); void OnTracking( wxFocusEvent& event); void OnWidgetTimer( wxTimerEvent & event); void OnKBRDFocusChange( wxFocusEvent &event ); private: void OnListBoxDo( wxCommandEvent& event, DLong clicks); DECLARE_EVENT_TABLE() }; class GDLWXStream; class GDLDrawPanel : public wxPanel { int pstreamIx; GDLWXStream* pstreamP; wxSize drawSize; wxDC* m_dc; wxWindowID GDLWidgetDrawID; public: // ctor(s) GDLDrawPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxPanelNameStr); ~GDLDrawPanel(); GDLWidgetDraw* GetGDLWidgetDraw(){ return static_cast(GDLWidget::GetWidget(GDLWidgetDrawID));} void Resize(int sizex, int sizey); void Update() { wxClientDC dc( this); dc.SetDeviceClippingRegion( GetUpdateRegion() ); dc.Blit( 0, 0, drawSize.x, drawSize.y, m_dc, 0, 0 ); if (wxTheApp) wxTheApp->ProcessIdle(); // wxPanel::Update(); // this->Refresh(); } //example for multithreading? //void Update() //{ // // cout << "in GDLDrawPanel::Update()" << endl; // SendPaintEvent( ); // // wxClientDC dc( this); // // dc.SetDeviceClippingRegion( GetUpdateRegion() ); // // GUIMutexLockerT gdlMutexGuiEnterLeave; // // dc.Blit( 0, 0, drawSize.x, drawSize.y, m_dc, 0, 0 ); // // wxPanel::Update(); // // gdlMutexGuiEnterLeave.Leave(); //} // void GetEventFlags(DULong eventFlags); int PStreamIx() { return pstreamIx;} void InitStream(int windowIndex=-1); // void AssociateStream(GDLWXStream* stream); void SendPaintEvent() { wxPaintEvent* event; event = new wxPaintEvent( GetId()); event->SetEventObject( this ); // only for wWidgets > 2.9 (takes ownership of event) // this->QueueEvent( event); this->AddPendingEvent( *event); // copies event delete event; } // event handlers (these functions should _not_ be virtual) void OnPaint(wxPaintEvent& event); void OnErase(wxEraseEvent& event); void OnClose(wxCloseEvent& event); void OnMouseMove( wxMouseEvent& event); void OnMouseDown( wxMouseEvent& event); void OnMouseUp( wxMouseEvent& event); void OnMouseWheel( wxMouseEvent& event); void OnKey( wxKeyEvent& event); void OnSize(wxSizeEvent &event); // void OnSizeWithTimer(wxSizeEvent& event); //not yet ready // void OnTimerResize( wxTimerEvent& event); // private: // DECLARE_EVENT_TABLE() }; class GDLWidgetGraphicWindowBase: public GDLWidgetBase { GDLDrawPanel* child; public: GDLDrawPanel* getWindow(){return child;} void setWindow(GDLDrawPanel* w){child=w;} GDLWidgetGraphicWindowBase(WidgetIDT mbarID, int xoff=0, int yoff=0, DString title=""); bool IsGraphicWindowFrame() const { return true;} }; #endif #endif gdl-0.9.9/src/gdlwidgeteventhandler.cpp000066400000000000000000002216741340051421000201460ustar00rootroot00000000000000/*************************************************************************** gdlwidgeteventhandler.cpp - GDL widget event handling ------------------- begin : Fri May 7 2004 copyright : (C) 2004-2013 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifdef HAVE_LIBWXWIDGETS #include #include #include #include "basegdl.hpp" #include "dstructgdl.hpp" #include "dinterpreter.hpp" #include "gdlwxstream.hpp" #include "gdlwidget.hpp" #include "widget.hpp" // #define GDL_DEBUG_ALL_EVENTS 1 // #define GDL_DEBUG_MOVE_EVENTS 1 // #define GDL_DEBUG_KBRD_EVENTS 1 // #define GDL_DEBUG_TIMER_EVENTS 1 // #define GDL_DEBUG_VISIBILITY_EVENTS 1 // #define GDL_DEBUG_SIZE_EVENTS 1 // #define GDL_DEBUG_TEXT_EVENTS 1 // #define GDL_DEBUG_BUTTON_EVENTS 1 // #define GDL_DEBUG_PAINT_EVENTS 1 // #define GDL_DEBUG_OTHER_EVENTS 1 //TO BE DONE: CONTINUE to REPLACE ALL STATIC CONNECTS WITH DYNAMIC. SEE http://wxwidgets.blogspot.com/2007/01/in-praise-of-connect.html // replace, e.g; // //BEGIN_EVENT_TABLE(MyFrame, wxFrame) // EVT_MENU(wxID_EXIT, MyFrame::OnQuit) //END_EVENT_TABLE() //instead write (in the body of some method of MyFrame and not at global scope as with the event tables) // MyFrame::MyFrame(...) // { // Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, // wxCommandEventHandler(MyFrame::OnQuit)); // } // see also the example of how to connect an event of some object to a method of another object. // and note that in this particular case one should always remember to disconnect the event handler // in the event handler object's destructor, otherwise the application may crash if/when the handler // is called after the event handler object is destroyed. // // Note that this may be tedious since all the event_table events below are events that can be set or removed // for each type of widget. // Besides, the misuse of event.Skip() can pose severe problems (blank widgets, etc...) since (quoting fdocumentation) // "Sizers rely on size events to function correctly. Therefore, in a sizer-based layout, do not forget to call Skip // on all size events you catch (and don't catch size events at all when you don't need to). DEFINE_EVENT_TYPE(wxEVT_SHOW_REQUEST) DEFINE_EVENT_TYPE(wxEVT_HIDE_REQUEST) //general-purpose events still left to Frame: BEGIN_EVENT_TABLE(GDLFrame, wxFrame) EVT_COMMAND(wxID_ANY, wxEVT_SHOW_REQUEST, GDLFrame::OnShowRequest) EVT_COMMAND(wxID_ANY, wxEVT_HIDE_REQUEST, GDLFrame::OnHideRequest) // EVT_ENTER_WINDOW( GDLFrame::OnEnterWindow) // EVT_LEAVE_WINDOW( GDLFrame::OnLeaveWindow) //impossible to replace with Connect() method? EVT_MENU(wxID_ANY, GDLFrame::OnMenu) EVT_TIMER(GDLFrame::WINDOW_TIMER, GDLFrame::OnWidgetTimer) // EVT_CONTEXT_MENU(GDLFrame::OnContextEvent) //CONTEXT //KBRD_FOCUS: // EVT_SET_FOCUS(GDLFrame::OnKBRDFocusChange) // EVT_KILL_FOCUS(GDLFrame::OnKBRDFocusChange) // frame specific events // EVT_SIZE(GDLFrame::OnSize) EVT_TIMER(GDLFrame::RESIZE_TIMER, GDLFrame::OnTimerResize) //... where size event is really done here. But does not work (refresh not OK) // EVT_SIZE(GDLFrame::OnSizeWithTimer) //use a timer to pass only once the resize event // EVT_MOVE(GDLFrame::OnMove) //TLB_MOVE_EVENTS // EVT_ICONIZE(GDLFrame::OnIconize) //ICONIFY // EVT_CLOSE(GDLFrame::OnCloseFrame) //KILL_REQUEST // widget-specific events // EVT_BUTTON( wxID_ANY, GDLFrame::OnButton) // EVT_RADIOBUTTON(wxID_ANY, GDLFrame::OnRadioButton) // EVT_CHECKBOX(wxID_ANY, GDLFrame::OnCheckBox) // EVT_COMBOBOX(wxID_ANY, GDLFrame::OnComboBox) // EVT_CHOICE(wxID_ANY, GDLFrame::OnDropList) //handled directly // EVT_LISTBOX_DCLICK(wxID_ANY, GDLFrame::OnListBoxDoubleClicked) // EVT_LISTBOX(wxID_ANY, GDLFrame::OnListBox) // EVT_TEXT_ENTER(wxID_ANY, GDLFrame::OnTextEnter) // EVT_TEXT(wxID_ANY, GDLFrame::OnText) // EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, GDLFrame::OnPageChanged) // EVT_SLIDER(wxID_ANY,GDLFrame::OnSlider) // EVT_SCROLL_THUMBRELEASE(GDLFrame::OnThumbRelease) // EVT_SCROLL_THUMBTRACK(GDLFrame::OnThumbTrack) END_EVENT_TABLE() //BEGIN_EVENT_TABLE(GDLDrawPanel, wxPanel) // EVT_PAINT(GDLDrawPanel::OnPaint) // EVT_MOTION (GDLDrawPanel::OnMouseMove) // EVT_LEFT_DOWN (GDLDrawPanel::OnMouseDown) // EVT_LEFT_UP (GDLDrawPanel::OnMouseUp) // EVT_LEFT_DCLICK(GDLDrawPanel::OnMouseDown) // EVT_MIDDLE_DOWN(GDLDrawPanel::OnMouseDown) // EVT_MIDDLE_UP(GDLDrawPanel::OnMouseUp) // EVT_MIDDLE_DCLICK(GDLDrawPanel::OnMouseDown) // EVT_RIGHT_DOWN(GDLDrawPanel::OnMouseDown) // EVT_RIGHT_UP(GDLDrawPanel::OnMouseUp) // EVT_RIGHT_DCLICK(GDLDrawPanel::OnMouseDown) // //EVT_MOUSE_AUX1_DOWN //EVT_MOUSE_AUX1_UP //EVT_MOUSE_AUX1_DCLICK //EVT_MOUSE_AUX2_DOWN //EVT_MOUSE_AUX2_UP //EVT_MOUSE_AUX2_DCLICK // EVT_MOUSEWHEEL(GDLDrawPanel::OnMouseWheel) // EVT_KEY_DOWN(GDLDrawPanel::OnKey) // EVT_KEY_UP(GDLDrawPanel::OnKey) // EVT_SHOW(GDLWindow::OnShow) // EVT_CLOSE(GDLWindow::OnClose) // EVT_SIZE(GDLDrawPanel::OnSize) //END_EVENT_TABLE() IMPLEMENT_APP_NO_MAIN( GDLApp) void gdlTextCtrl::OnChar(wxKeyEvent& event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS ) wxMessageOutputStderr().Printf(_T("in gdlTextCtrl::OnChar: %d\n"),event.GetId()); #endif //I cannot get cw_field to work if OnChar is not overwritten as it is here GDLWidgetText* txt = static_cast(GDLWidget::GetWidget( event.GetId())); if( txt == NULL) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS) wxMessageOutputStderr().Printf(_T("GDLWidget == NULL: %d\n"),event.GetId()); #endif event.Skip(); return; } DStructGDL* widg; bool report = txt->HasEventType( GDLWidget::EV_ALL ); bool edit = txt->IsEditable( ); WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); if ( !report ) { if ( !edit ) { event.Skip( ); return; } else { //editable if ( event.GetKeyCode( ) == WXK_RETURN ) { //only widg = new DStructGDL( "WIDGET_TEXT_CH" ); widg->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widg->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widg->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widg->InitTag( "TYPE", DIntGDL( 0 ) ); // selection widg->InitTag( "OFFSET", DLongGDL( this->GetInsertionPoint() ) ); widg->InitTag( "CH", DByteGDL( 10 ) ); GDLWidget::PushEvent( baseWidgetID, widg ); } event.Skip( ); return; } } else { //report ALL (text) events, editable or not int sign = 1; long from, to; this->GetSelection( &from, &to ); long oldpos = this->GetInsertionPoint( ), newpos; switch ( event.GetKeyCode( ) ) { case WXK_LEFT: sign = -1; case WXK_RIGHT: newpos = oldpos + sign * 1; if ( newpos >= 0 && newpos <= this->GetLastPosition( ) ) this->SetInsertionPoint( newpos ); widg = new DStructGDL( "WIDGET_TEXT_SEL" ); widg->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widg->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widg->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widg->InitTag( "TYPE", DIntGDL( 3 ) ); // selection widg->InitTag( "OFFSET", DLongGDL( this->GetInsertionPoint( ) ) ); widg->InitTag( "LENGTH", DLongGDL( 0 ) ); GDLWidget::PushEvent( baseWidgetID, widg ); return; break; case WXK_BACK: if ( oldpos > 0 ) { widg = new DStructGDL( "WIDGET_TEXT_DEL" ); widg->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widg->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widg->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widg->InitTag( "TYPE", DIntGDL( 2 ) ); // selection widg->InitTag( "OFFSET", DLongGDL( from - 1 ) ); widg->InitTag( "LENGTH", DLongGDL( to - from + 1 ) ); GDLWidget::PushEvent( baseWidgetID, widg ); } if (edit) event.Skip( ); //do it! return; break; case WXK_DELETE: if ( oldpos <= this->GetLastPosition() ) { widg = new DStructGDL( "WIDGET_TEXT_DEL" ); widg->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widg->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widg->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widg->InitTag( "TYPE", DIntGDL( 2 ) ); // selection widg->InitTag( "OFFSET", DLongGDL( from ) ); widg->InitTag( "LENGTH", DLongGDL( to - from ) ); GDLWidget::PushEvent( baseWidgetID, widg ); } if (edit) event.Skip( ); //do it! return; break; case WXK_RETURN: //important, *DL returns CH=10 instead of 13 for widg = new DStructGDL( "WIDGET_TEXT_CH" ); widg->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widg->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widg->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widg->InitTag( "TYPE", DIntGDL( 0 ) ); // selection widg->InitTag( "OFFSET", DLongGDL( from ) ); widg->InitTag( "CH", DByteGDL( 10 ) ); GDLWidget::PushEvent( baseWidgetID, widg ); return; break; } if (edit) event.Skip( ); //else do it! } //else return a CHAR event for most keys (as *DL) widg = new DStructGDL( "WIDGET_TEXT_CH" ); widg->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widg->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widg->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widg->InitTag( "TYPE", DIntGDL( 0 ) ); // single char widg->InitTag( "OFFSET", DLongGDL( this->GetInsertionPoint( ) ) ); widg->InitTag( "CH", DByteGDL( event.GetKeyCode( ) ) ); GDLWidget::PushEvent( baseWidgetID, widg ); } void GDLFrame::OnWidgetTimer( wxTimerEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TIMER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnWidgetTimer: %d\n"),event.GetId()); #endif GDLWidget* owner=static_cast(gdlOwner); WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( owner->WidgetID()); // create GDL event struct if widget still exist.. DStructGDL* widgtimer = new DStructGDL( "WIDGET_TIMER" ); WidgetIDT * originating_id=static_cast(this->GetEventHandler()->GetClientData()); widgtimer->InitTag( "ID", DLongGDL(*originating_id)); widgtimer->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgtimer->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); GDLWidget::PushEvent( baseWidgetID, widgtimer); } void GDLFrame::OnShowRequest( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnShowRequest: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("GDLWidget == NULL: %d\n"),event.GetId()); #endif return; } GDLFrame *frame = static_cast( widget->GetWxWidget()); if( !frame->IsShown()) { widget->SetSizeHints(); //fundamental, insure main frame wrapping around widgets. // //I though found it: how to not have the focus for graphic windows. But this has adverse effects. // if (frame->focusNotPermitted()) { // frame->ShowWithoutActivating(); // } // else bool stat = frame->Show(true); } event.Skip(); } void GDLFrame::OnHideRequest( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnHideRequest: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("GDLWidget == NULL: %d\n"),event.GetId()); #endif return; } GDLFrame *frame = static_cast( widget->GetWxWidget()); if( frame->IsShown()) { bool stat = frame->Show(false); } event.Skip(); } void gdlMenuButton::OnButton( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_BUTTON_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlMenuButton::OnButton: %d\n"),event.GetId()); #endif this->PopupMenu(static_cast(popupMenu)); event.Skip(); } void gdlMenuButtonBitmap::OnButton( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_BUTTON_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlMenuButtonBitmap::OnButton: %d\n"),event.GetId()); #endif this->PopupMenu(static_cast(popupMenu)); event.Skip(); } void GDLFrame::OnButton( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_BUTTON_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnButton: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); // create GDL event struct DStructGDL* widgbut = new DStructGDL( "WIDGET_BUTTON"); widgbut->InitTag("ID", DLongGDL( event.GetId())); widgbut->InitTag("TOP", DLongGDL( baseWidgetID)); widgbut->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgbut->InitTag("SELECT", DLongGDL( 1)); GDLWidget::PushEvent( baseWidgetID, widgbut); } //change bitmap or parent button? void GDLFrame::OnMenu( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_BUTTON_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnMenu: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); // create GDL event struct DStructGDL* widgbut = new DStructGDL( "WIDGET_BUTTON"); widgbut->InitTag("ID", DLongGDL( event.GetId())); widgbut->InitTag("TOP", DLongGDL( baseWidgetID)); widgbut->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgbut->InitTag("SELECT", DLongGDL( 1)); GDLWidget::PushEvent( baseWidgetID, widgbut); } void GDLFrame::OnRadioButton( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_BUTTON_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnRadioButton: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); // bool selectValue = event.IsSelection(); // int selectValue = event.GetSelection(); GDLWidgetBase* gdlParentWidget = static_cast(GDLWidget::GetParent( event.GetId())); WidgetIDT lastSelection = gdlParentWidget->GetLastRadioSelection(); if( lastSelection != GDLWidget::NullID) { if( lastSelection == event.GetId()) return; // create GDL event struct DStructGDL* widgbut = new DStructGDL( "WIDGET_BUTTON"); widgbut->InitTag("ID", DLongGDL( lastSelection)); widgbut->InitTag("TOP", DLongGDL( baseWidgetID)); widgbut->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgbut->InitTag("SELECT", DLongGDL( 0)); GDLWidget* widget = GDLWidget::GetWidget( lastSelection); assert(widget->IsButton()); static_cast(widget)->SetButton( false); GDLWidget::PushEvent( baseWidgetID, widgbut); } // create GDL event struct DStructGDL* widgbut = new DStructGDL( "WIDGET_BUTTON"); widgbut->InitTag("ID", DLongGDL( event.GetId())); widgbut->InitTag("TOP", DLongGDL( baseWidgetID)); widgbut->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widgbut->InitTag("SELECT", DLongGDL( selectValue ? 1 : 0)); widgbut->InitTag("SELECT", DLongGDL( 1)); gdlParentWidget->SetLastRadioSelection(event.GetId()); GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); assert(widget->IsButton()); static_cast(widget)->SetButton( true); GDLWidget::PushEvent( baseWidgetID, widgbut); } void GDLFrame::OnCheckBox( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_BUTTON_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnCheckBox: %d\n"),event.GetId()); #endif bool selectValue = event.IsChecked(); WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); assert(widget->IsButton()); static_cast(widget)->SetButton( selectValue); // create GDL event struct DStructGDL* widgbut = new DStructGDL( "WIDGET_BUTTON"); widgbut->InitTag("ID", DLongGDL( event.GetId())); widgbut->InitTag("TOP", DLongGDL( baseWidgetID)); widgbut->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgbut->InitTag("SELECT", DLongGDL( selectValue ? 1 : 0)); GDLWidget::PushEvent( baseWidgetID, widgbut); } void GDLFrame::OnComboBox( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnComboBox: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); int selectValue = event.GetSelection(); // create GDL event struct DStructGDL* widgcbox; wxString strValue = event.GetString(); widgcbox = new DStructGDL( "WIDGET_COMBOBOX"); widgcbox->InitTag("ID", DLongGDL( event.GetId())); widgcbox->InitTag("TOP", DLongGDL( baseWidgetID)); widgcbox->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgcbox->InitTag("INDEX", DLongGDL( selectValue)); widgcbox->InitTag("STR", DStringGDL( string(strValue.mb_str(wxConvUTF8)) )); GDLWidget::PushEvent( baseWidgetID, widgcbox); } void GDLFrame::OnComboBoxTextEnter( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TEXT_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnComboBoxTextEvent: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); int selectValue = event.GetSelection(); // create GDL event struct DStructGDL* widgcbox; wxString strValue = event.GetString(); widgcbox = new DStructGDL( "WIDGET_COMBOBOX"); widgcbox->InitTag("ID", DLongGDL( event.GetId())); widgcbox->InitTag("TOP", DLongGDL( baseWidgetID)); widgcbox->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgcbox->InitTag("INDEX", DLongGDL( selectValue)); widgcbox->InitTag("STR", DStringGDL( string(strValue.mb_str(wxConvUTF8)) )); GDLWidget::PushEvent( baseWidgetID, widgcbox); } void GDLFrame::OnDropList( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnDropList: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); int selectValue = event.GetSelection(); DStructGDL* widdrplst; widdrplst = new DStructGDL( "WIDGET_DROPLIST"); widdrplst->InitTag("ID", DLongGDL( event.GetId())); widdrplst->InitTag("TOP", DLongGDL( baseWidgetID)); widdrplst->InitTag("HANDLER", DLongGDL( baseWidgetID )); widdrplst->InitTag("INDEX", DLongGDL( selectValue)); GDLWidget::PushEvent( baseWidgetID, widdrplst); } void GDLFrame::OnListBoxDo( wxCommandEvent& event, DLong clicks) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnListBoxDo: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); int selectValue = event.GetSelection(); // create GDL event struct DStructGDL* widgcbox; widgcbox = new DStructGDL( "WIDGET_LIST"); widgcbox->InitTag("ID", DLongGDL( event.GetId())); widgcbox->InitTag("TOP", DLongGDL( baseWidgetID)); widgcbox->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgcbox->InitTag("INDEX", DLongGDL( selectValue)); widgcbox->InitTag("CLICKS", DLongGDL( clicks)); GDLWidget::PushEvent( baseWidgetID, widgcbox); } void GDLFrame::OnListBox( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnListBox: %d\n"),event.GetId()); #endif OnListBoxDo( event, 1); } void GDLFrame::OnListBoxDoubleClicked( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnListBoxDoubleClicked: %d\n"),event.GetId()); #endif // Note: IDL sends one click AND two click event on double click OnListBoxDo( event, 1); OnListBoxDo( event, 2); } void GDLFrame::OnText( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TEXT_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnText: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); bool isModified=false; long selStart, selEnd; DLong offset; std::string lastValue; std::string newValue; GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TEXT_EVENTS) wxMessageOutputStderr().Printf(_T("GDLWidget == NULL: %d\n"),event.GetId()); #endif event.Skip(); return; } if( widget->IsText()) { wxTextCtrl* textCtrl = static_cast(widget->GetWxWidget()); if( textCtrl == NULL) { event.Skip(); return; // happens on construction } textCtrl->GetSelection( &selStart, &selEnd); offset = textCtrl->GetInsertionPoint(); lastValue = static_cast(widget)->GetLastValue(); newValue = textCtrl->GetValue().mb_str(wxConvUTF8); isModified = lastValue != newValue; static_cast(widget)->SetLastValue(newValue); //return without producing event struct if eventType is not set if (!(widget->HasEventType( GDLWidget::EV_ALL ))) return; } else if ( widget->IsComboBox()) { wxComboBox* control = static_cast(widget->GetWxWidget()); if( control == NULL) { event.Skip(); return; // happens on construction } if (!control->IsEditable()) return; //no OnText Events shoudl be generated! int pos = control->GetCurrentSelection() ; //would be control->GetSelection( &selStart, &selEnd); // with GTK offset = control->GetInsertionPoint(); lastValue = static_cast(widget)->GetLastValue(); newValue = control->GetValue().mb_str(wxConvUTF8); isModified = lastValue != newValue; // if (isModified) control->SetString(pos,wxString(newValue.c_str(), wxConvUTF8 )); static_cast(widget)->SetLastValue(newValue); return; } else { assert( widget->IsDropList()); wxChoice* control = static_cast(widget->GetWxWidget()); if( control == NULL) { event.Skip(); return; // happens on construction } int where = control->GetSelection(); if (where != wxNOT_FOUND) { newValue=control->GetString(where).mb_str(wxConvUTF8); lastValue = static_cast(widget)->GetLastValue(); isModified = lastValue != newValue; static_cast(widget)->SetLastValue(newValue); } } DStructGDL* widg; if( !isModified) { widg = new DStructGDL( "WIDGET_TEXT_SEL"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 3)); // selection widg->InitTag("OFFSET", DLongGDL( offset)); widg->InitTag("LENGTH", DLongGDL( selEnd-selStart)); } else { int lengthDiff = newValue.length() - lastValue.length(); if( lengthDiff < 0) // deleted { widg = new DStructGDL( "WIDGET_TEXT_DEL"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 2)); // delete widg->InitTag("OFFSET", DLongGDL( offset-1)); widg->InitTag("LENGTH", DLongGDL( -lengthDiff)); } else if( lengthDiff == 0) // replace TODO: just flag the real change { // 1st delete all widg = new DStructGDL( "WIDGET_TEXT_DEL"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 2)); // delete widg->InitTag("OFFSET", DLongGDL( 0)); widg->InitTag("LENGTH", DLongGDL( lastValue.length())); GDLWidget::PushEvent( baseWidgetID, widg); // 2nd insert new widg = new DStructGDL( "WIDGET_TEXT_STR"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 1)); // multiple char widg->InitTag("OFFSET", DLongGDL( 0)); widg->InitTag("STR", DStringGDL( newValue)); } else if( lengthDiff == 1) { widg = new DStructGDL( "WIDGET_TEXT_CH"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 0)); // single char widg->InitTag("OFFSET", DLongGDL( offset+1)); widg->InitTag("CH", DByteGDL( newValue[offset 1 { int nVLenght = newValue.length(); if( offset < lengthDiff) lengthDiff = offset; string str = ""; if( offset <= nVLenght && lengthDiff > 0) str = newValue.substr(offset-lengthDiff,lengthDiff); widg = new DStructGDL( "WIDGET_TEXT_STR"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 1)); // multiple char widg->InitTag("OFFSET", DLongGDL( offset)); widg->InitTag("STR", DStringGDL( str)); } } GDLWidget::PushEvent( baseWidgetID, widg); } void GDLFrame::OnTextEnter( wxCommandEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TEXT_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnTextEnter: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); DLong offset; std::string newValue; GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TEXT_EVENTS) wxMessageOutputStderr().Printf(_T("GDLWidget == NULL: %d\n"),event.GetId()); #endif event.Skip(); return; } if( widget->IsText()) { wxTextCtrl* textCtrl = static_cast(widget->GetWxWidget()); offset = textCtrl->GetInsertionPoint(); newValue = textCtrl->GetValue().mb_str(wxConvUTF8); static_cast(widget)->SetLastValue(newValue); // create GDL event struct DStructGDL* widg; widg = new DStructGDL( "WIDGET_TEXT_CH"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TYPE", DIntGDL( 0)); // single char widg->InitTag("OFFSET", DLongGDL( offset)); widg->InitTag("CH", DByteGDL( '\n')); GDLWidget::PushEvent( baseWidgetID, widg); } else if( widget->IsComboBox()) { // create GDL event struct DStructGDL* widgcbox; int selectValue = event.GetSelection(); wxString strValue = event.GetString(); widgcbox = new DStructGDL( "WIDGET_COMBOBOX"); widgcbox->InitTag("ID", DLongGDL( event.GetId())); widgcbox->InitTag("TOP", DLongGDL( baseWidgetID)); widgcbox->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgcbox->InitTag("INDEX", DLongGDL( selectValue)); widgcbox->InitTag("STR", DStringGDL( string(strValue.mb_str(wxConvUTF8)) )); GDLWidget::PushEvent( baseWidgetID, widgcbox); } else { assert( widget->IsDropList()); // create GDL event struct DStructGDL* widdrplst; int selectValue = event.GetSelection(); widdrplst = new DStructGDL( "WIDGET_DROPLIST"); widdrplst->InitTag("ID", DLongGDL( event.GetId())); widdrplst->InitTag("TOP", DLongGDL( baseWidgetID)); widdrplst->InitTag("HANDLER", DLongGDL( baseWidgetID )); widdrplst->InitTag("INDEX", DLongGDL( selectValue)); GDLWidget::PushEvent( baseWidgetID, widdrplst); } } void GDLFrame::OnPageChanged( wxNotebookEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnPageChanged: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); // create GDL event struct DStructGDL* widg; widg = new DStructGDL( "WIDGET_TAB"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("TAB", DLongGDL( event.GetSelection())); GDLWidget::PushEvent( baseWidgetID, widg); } //Timer-filtered resizing are not clever enough for graphics. FIXME! // Besides, mouse.LeftIsDown() is not present before wxWidgets 2.8.12 , find an alternative. void GDLFrame::OnTimerResize( wxTimerEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TIMER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnTimerResize: %d (%d,%d).."),event.GetId(),frameSize.x,frameSize.y); #endif wxMouseState mouse=wxGetMouseState(); #if wxCHECK_VERSION(3,0,0) if (mouse.LeftIsDown()) { #else if (mouse.LeftDown()) { #endif m_resizeTimer->Start(50, wxTIMER_ONE_SHOT); return; } #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TIMER_EVENTS) wxMessageOutputStderr().Printf(_T("Processed.\n")); #endif GDLWidget* owner=static_cast(gdlOwner); if (!owner) return; if (owner->IsGraphicWindowFrame()) { //do something clever GDLDrawPanel* w=static_cast(owner)->getWindow(); wxSize sizeleft=this->GetClientSize(); w->Resize(sizeleft.x,sizeleft.y); w->SetMinSize(sizeleft); //must enforce min size to work==>General wrong use of sizers. w->GetGDLWidgetDraw()->GetPanel()->Layout(); this->Fit(); } else { DULong flags=0; if( owner ) flags=owner->GetEventFlags(); if (flags & GDLWidget::EV_SIZE ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( owner->WidgetID()); // create GDL event struct DStructGDL* widgbase = new DStructGDL( "WIDGET_BASE" ); widgbase->InitTag( "ID", DLongGDL( owner->WidgetID() ) ); widgbase->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgbase->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgbase->InitTag( "X", DLongGDL( frameSize.x ) ); widgbase->InitTag( "Y", DLongGDL( frameSize.y ) ); GDLWidget::PushEvent( baseWidgetID, widgbase); } } event.Skip(); } //Timer-filtered resizing are not clever enough for graphcis. FIXME! void GDLFrame::OnSizeWithTimer( wxSizeEvent& event) { wxSize newSize=event.GetSize(); #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TIMER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnSizeWithTimer: %d.."),event.GetId()); #endif assert (gdlOwner != NULL); GDLWidget* owner=static_cast(gdlOwner); if (owner->GetParentID() != 0) { event.Skip(); return; //ignore non-TLB size events. } //this is a good position to suppress a minimum default size on frame. this->SetMinSize(wxDefaultSize); if (newSize==frameSize){ event.Skip(); return;} //saves a looooot of unuseful refreshes... //is it a resize of frame due to a manual intervention? wxMouseState mouse=wxGetMouseState(); #if wxCHECK_VERSION(3,0,0) if (mouse.LeftIsDown()) { #else if (mouse.LeftDown()) { #endif #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_TIMER_EVENTS) wxMessageOutputStderr().Printf(_T("framesize was %d %d , set to %d %d & Processed.\n"),frameSize.x,frameSize.y,newSize.x,newSize.y); #endif frameSize=newSize; m_resizeTimer->Start(50, wxTIMER_ONE_SHOT); event.Skip(); //absolutely vital to pass to others! return; } else { frameSize=newSize; event.Skip(); //absolutely vital to pass to others! } } //must override wxWidget's OnSize method void GDLFrame::OnSize( wxSizeEvent& event) { assert (gdlOwner != NULL); #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_SIZE_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnSize: %d.."),event.GetId()); #endif // current bug: // onsize should not be called 1) when TLB is resized with widget_control // and 2) only at the end of a mouse resizing (wxSizeEvent is sent multiple times // when resizing a TLB. But variant with timer does not work correctly...) GDLWidget* owner=static_cast(gdlOwner); if (owner->GetParentID() != 0) { event.Skip(); return; //ignore non-TLB size events. } wxSize newSize=event.GetSize(); if (newSize==frameSize){event.Skip(); return;} //saves a looooot of unuseful refreshes... this->SetMinSize(wxDefaultSize); #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_SIZE_EVENTS) wxMessageOutputStderr().Printf(_T("Processed.\n")); #endif frameSize=newSize; if (owner->IsGraphicWindowFrame()) { //do something clever GDLDrawPanel* w=static_cast(owner)->getWindow(); wxSize sizeleft=this->GetClientSize(); w->Resize(sizeleft.x,sizeleft.y); w->SetMinSize(sizeleft); //must enforce min size to work==>General wrong use of sizers. w->GetGDLWidgetDraw()->GetPanel()->Layout(); this->Fit(); } else { DULong flags=0; if( owner ) flags=owner->GetEventFlags(); if (flags & GDLWidget::EV_SIZE ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( owner->WidgetID()); // create GDL event struct DStructGDL* widgbase = new DStructGDL( "WIDGET_BASE" ); widgbase->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgbase->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgbase->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgbase->InitTag( "X", DLongGDL( frameSize.x ) ); widgbase->InitTag( "Y", DLongGDL( frameSize.y ) ); GDLWidget::PushEvent( baseWidgetID, widgbase); } } event.Skip(); //important, pass to others! } void GDLFrame::OnThumbTrack( wxScrollEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnScroll: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); //only slider for now: // if( widget->IsSlider()) // { GDLWidgetSlider* sl = static_cast(widget); DLong oldValue = sl->GetValue(); DLong newSelection = event.GetSelection(); if( newSelection != oldValue) { sl->SetValue( newSelection); // create GDL event struct DStructGDL* widg; widg = new DStructGDL( "WIDGET_SLIDER"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("VALUE", DLongGDL( newSelection)); widg->InitTag("DRAG", DIntGDL( 1)); // dragging events from here GDLWidget::PushEvent( baseWidgetID, widg); } return; // } } void GDLFrame::OnThumbRelease( wxScrollEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnThumbRelease: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId()); //only slider for now: // if( widget->IsSlider()) // { GDLWidgetSlider* sl = static_cast(widget); DLong newSelection = event.GetSelection(); sl->SetValue( newSelection); // create GDL event struct DStructGDL* widg; widg = new DStructGDL( "WIDGET_SLIDER"); widg->InitTag("ID", DLongGDL( event.GetId())); widg->InitTag("TOP", DLongGDL( baseWidgetID)); widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); widg->InitTag("VALUE", DLongGDL( newSelection)); widg->InitTag("DRAG", DIntGDL( 0)); // set events from here GDLWidget::PushEvent( baseWidgetID, widg); return; } //TRACKING. void GDLFrame::OnEnterWindow( wxMouseEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnEnterWindow: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); if( widget == NULL) { event.Skip(); return; } } if ( widget->GetEventFlags() & GDLWidget::EV_TRACKING ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtracking = new DStructGDL( "WIDGET_TRACKING" ); widgtracking->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgtracking->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgtracking->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgtracking->InitTag( "ENTER", DIntGDL( 1 ) ); GDLWidget::PushEvent( baseWidgetID, widgtracking ); } //normal end of event processing! event.Skip(); } void GDLFrame::OnLeaveWindow( wxMouseEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnLeaveWindow: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); if( widget == NULL) { event.Skip(); return; } } if ( widget->GetEventFlags() & GDLWidget::EV_TRACKING ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtracking = new DStructGDL( "WIDGET_TRACKING" ); widgtracking->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgtracking->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgtracking->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgtracking->InitTag( "ENTER", DIntGDL( 0 ) ); GDLWidget::PushEvent( baseWidgetID, widgtracking ); } //normal end of event processing! event.Skip(); } void GDLFrame::OnKBRDFocusChange( wxFocusEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnFocusChange: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) { if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); if( widget == NULL) { event.Skip(); return; } } if ( widget->GetEventFlags() & GDLWidget::EV_KBRD_FOCUS ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgkbrdfocus = new DStructGDL( "WIDGET_KBRD_FOCUS" ); widgkbrdfocus->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgkbrdfocus->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgkbrdfocus->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); int enter=(event.GetEventType()==wxEVT_SET_FOCUS); widgkbrdfocus->InitTag( "ENTER", DIntGDL( enter ) ); GDLWidget::PushEvent( baseWidgetID, widgkbrdfocus ); } //normal end of event processing! event.Skip(); //"The focus event handlers should almost invariably call wxEvent::Skip() on their event argument to allow the default handling to take place. Failure to do this may result in incorrect behaviour of the native controls." } void GDLFrame::OnContextEvent( wxContextMenuEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnContextEvent: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); WidgetIDT baseWidgetID; WidgetIDT eventID; if( widget == NULL) { if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); if( owner == NULL) { event.Skip(); return; } else { widget=owner; baseWidgetID = owner->WidgetID(); eventID = owner->WidgetID(); } } else { baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); eventID = event.GetId( ); } if ( widget->GetEventFlags() & GDLWidget::EV_CONTEXT ) { DStructGDL* widgcontext = new DStructGDL( "WIDGET_CONTEXT" ); widgcontext->InitTag( "ID", DLongGDL( eventID ) ); widgcontext->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgcontext->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); wxPoint position=event.GetPosition( ); if (position==wxDefaultPosition) { //issued from keyboard position=wxGetMousePosition(); } widgcontext->InitTag( "X", DLongGDL( position.x ) ); widgcontext->InitTag( "Y", DLongGDL( position.y ) ); //ROW AND COL, to be added for TABLE Widget if (widget->IsTable()){ gdlGrid * grid = static_cast (widget->GetWxWidget()); int col = grid->XToCol(position.x); int row = grid->YToRow(position.y); widgcontext->InitTag( "ROW", DLongGDL( row ) ); widgcontext->InitTag( "ROW", DLongGDL( col ) ); } GDLWidget::PushEvent( baseWidgetID, widgcontext ); } //normal end of event processing! } void GDLFrame::OnIconize( wxIconizeEvent & event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnIconize: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) {event.Skip(); return;} if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); DULong flags=0; if( owner ) flags=owner->GetEventFlags(); if ( flags & GDLWidget::EV_ICONIFY ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtlb_iconify_events = new DStructGDL( "WIDGET_TLB_ICONIFY" ); widgtlb_iconify_events->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgtlb_iconify_events->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgtlb_iconify_events->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgtlb_iconify_events->InitTag( "ICONIFIED", DIntGDL( event.IsIconized() ) ); GDLWidget::PushEvent( baseWidgetID, widgtlb_iconify_events ); } //normal end of event processing! } void GDLFrame::OnMove( wxMoveEvent & event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_MOVE_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnMove: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) {event.Skip(); return;} if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); DULong flags=0; if( owner ) flags=owner->GetEventFlags(); if ( flags & GDLWidget::EV_MOVE ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtlb_move_events = new DStructGDL( "WIDGET_TLB_MOVE" ); widgtlb_move_events->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgtlb_move_events->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgtlb_move_events->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgtlb_move_events->InitTag( "X", DLongGDL( event.GetPosition().x ) ); widgtlb_move_events->InitTag( "Y", DLongGDL( event.GetPosition().y ) ); GDLWidget::PushEvent( baseWidgetID, widgtlb_move_events ); } //normal end of event processing! } void GDLFrame::OnCloseFrame( wxCloseEvent & event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnCloseFrame: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) {event.Skip(); return;} if (!gdlOwner) {event.Skip(); return;} GDLWidget* owner=static_cast(gdlOwner); WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtlb_kill_request_events = new DStructGDL( "WIDGET_KILL_REQUEST" ); widgtlb_kill_request_events->InitTag( "ID", DLongGDL( event.GetId( ) ) ); widgtlb_kill_request_events->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgtlb_kill_request_events->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); GDLWidget::PushEvent( baseWidgetID, widgtlb_kill_request_events ); } void GDLFrame::OnUnhandledCloseFrame( wxCloseEvent & event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnUnhandledCloseFrame: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) {event.Skip(); return;} if (!gdlOwner) {event.Skip(); return;} //destroy TLB widget static_cast(gdlOwner)->SelfDestroy(); } void GDLFrame::OnCloseWindow( wxCloseEvent & event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnCloseWindow: %d\n"),event.GetId()); #endif GDLWidget* widget = GDLWidget::GetWidget( event.GetId()); if( widget == NULL) {event.Skip(); return;} wxWindowList childrenList=this->GetChildren(); wxWindowList::iterator iter = childrenList.begin(); GDLDrawPanel* draw =static_cast(*iter); delete draw; event.Skip(); } void GDLDrawPanel::OnErase(wxEraseEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLFrame::OnErase: %d\n"),event.GetId()); #endif event.Skip(); } //Draw void GDLDrawPanel::OnPaint(wxPaintEvent& event) { if (drawSize.x<1||drawSize.y<1) return; #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_PAINT_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnPaint: %d (%d,%d)\n"),event.GetId(),drawSize.x, drawSize.y); #endif this->Update(); event.Skip(); } void GDLDrawPanel::OnClose(wxCloseEvent& event) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_VISIBILITY_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnClose: %d\n"),event.GetId()); #endif event.Skip(); } void GDLDrawPanel::OnSize( wxSizeEvent &event ) { wxSize newSize=event.GetSize(); if (newSize.x<1||newSize.y<1) { event.Skip(); return;} if (newSize==drawSize){ event.Skip(); return;} //saves a looooot of unuseful refreshes... #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_SIZE_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnSize: %d (%d,%d)\n"),event.GetId(),event.GetSize().x,event.GetSize().y); #endif Resize(newSize.x,newSize.y); event.Skip(); } void GDLDrawPanel::OnMouseMove( wxMouseEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_MOVE_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnMouseMove: %d\n"),event.GetId()); #endif GDLWidgetDraw* draw = static_cast(GDLWidget::GetWidget(GDLWidgetDrawID)); if (!draw) {event.Skip(); return;}; //temporary hack for devicewx... DULong eventFlags=draw->GetEventFlags(); if ( eventFlags & GDLWidget::EV_MOTION ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgdraw = new DStructGDL( "WIDGET_DRAW" ); widgdraw->InitTag( "ID", DLongGDL( GDLWidgetDrawID) ); widgdraw->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "TYPE", DIntGDL( 2 ) ); //motion widgdraw->InitTag( "X", DLongGDL( event.GetX() ) ); widgdraw->InitTag( "Y", DLongGDL( drawSize.y-event.GetY() ) ); GDLWidget::PushEvent( baseWidgetID, widgdraw ); } //normal end of event processing! } void GDLDrawPanel::OnMouseDown( wxMouseEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnMouseDown: %d\n"),event.GetId()); #endif GDLWidgetDraw* draw = static_cast(GDLWidget::GetWidget(GDLWidgetDrawID)); if (!draw) {event.Skip(); return;}; //temporary hack for devicewx... DULong eventFlags=draw->GetEventFlags(); if ( eventFlags & GDLWidget::EV_BUTTON ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgdraw = new DStructGDL( "WIDGET_DRAW" ); widgdraw->InitTag( "ID", DLongGDL( GDLWidgetDrawID) ); widgdraw->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "TYPE", DIntGDL( 0 ) ); //button Press widgdraw->InitTag( "X", DLongGDL( event.GetX() ) ); widgdraw->InitTag( "Y", DLongGDL( drawSize.y-event.GetY() ) ); unsigned long btn=1<<(event.GetButton()-1); widgdraw->InitTag( "PRESS", DByteGDL( btn )); widgdraw->InitTag( "RELEASE", DByteGDL( 0 ) ); widgdraw->InitTag( "CLICKS", DLongGDL( 1 ) ); widgdraw->InitTag( "MODIFIERS", DLongGDL( 0 ) ); widgdraw->InitTag( "CH", DByteGDL( 0 ) ); widgdraw->InitTag( "KEY", DLongGDL( 0 ) ); GDLWidget::PushEvent( baseWidgetID, widgdraw ); } //normal end of event processing! } void GDLDrawPanel::OnMouseUp( wxMouseEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnMouseUp: %d\n"),event.GetId()); #endif GDLWidgetDraw* draw = static_cast(GDLWidget::GetWidget(GDLWidgetDrawID)); if (!draw) {event.Skip(); return;}; //temporary hack for devicewx... DULong eventFlags=draw->GetEventFlags(); if ( eventFlags & GDLWidget::EV_BUTTON ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgdraw = new DStructGDL( "WIDGET_DRAW" ); widgdraw->InitTag( "ID", DLongGDL( GDLWidgetDrawID) ); widgdraw->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "TYPE", DIntGDL( 1 ) ); //button Release widgdraw->InitTag( "X", DLongGDL( event.GetX() ) ); widgdraw->InitTag( "Y", DLongGDL( drawSize.y-event.GetY() ) ); unsigned long btn=1<<(event.GetButton()-1); widgdraw->InitTag( "PRESS", DByteGDL( 0 ) ); widgdraw->InitTag( "RELEASE", DByteGDL( btn ) ); widgdraw->InitTag( "CLICKS", DLongGDL( 1 ) ); widgdraw->InitTag( "MODIFIERS", DLongGDL( 0 ) ); widgdraw->InitTag( "CH", DByteGDL( 0 ) ); widgdraw->InitTag( "KEY", DLongGDL( 0 ) ); GDLWidget::PushEvent( baseWidgetID, widgdraw ); } //normal end of event processing! } void GDLDrawPanel::OnMouseWheel( wxMouseEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnMouseWheel: %d\n"),event.GetId()); #endif GDLWidgetDraw* draw = static_cast(GDLWidget::GetWidget(GDLWidgetDrawID)); if (!draw) {event.Skip(); return;}; //temporary hack for devicewx... DULong eventFlags=draw->GetEventFlags(); if ( eventFlags & GDLWidget::EV_WHEEL ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgdraw = new DStructGDL( "WIDGET_DRAW" ); widgdraw->InitTag( "ID", DLongGDL( GDLWidgetDrawID ) ); widgdraw->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "TYPE", DIntGDL( 7 ) ); //wheel event widgdraw->InitTag( "X", DLongGDL( event.GetX() ) ); widgdraw->InitTag( "Y", DLongGDL( drawSize.y-event.GetY() ) ); widgdraw->InitTag( "PRESS", DByteGDL( 0 ) ); widgdraw->InitTag( "RELEASE", DByteGDL( 0 ) ); widgdraw->InitTag( "CLICKS", DLongGDL( event.GetWheelRotation() ) ); widgdraw->InitTag( "MODIFIERS", DLongGDL( 0 ) ); widgdraw->InitTag( "CH", DByteGDL( 0 ) ); widgdraw->InitTag( "KEY", DLongGDL( 0 ) ); GDLWidget::PushEvent( baseWidgetID, widgdraw ); } } void GDLDrawPanel::OnKey( wxKeyEvent &event ) { #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_KBRD_EVENTS) wxMessageOutputStderr().Printf(_T("in GDLDrawPanel::OnKey: %d\n"),event.GetId()); #endif GDLWidgetDraw* draw = static_cast(GDLWidget::GetWidget(GDLWidgetDrawID)); if (!draw) {event.Skip(); return;}; //temporary hack for devicewx... DULong eventFlags=draw->GetEventFlags(); int mode=1; if ( eventFlags & GDLWidget::EV_KEYBOARD || eventFlags & GDLWidget::EV_KEYBOARD2 ) { if (eventFlags & GDLWidget::EV_KEYBOARD2) mode=2; WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgdraw = new DStructGDL( "WIDGET_DRAW" ); widgdraw->InitTag( "ID", DLongGDL( GDLWidgetDrawID ) ); widgdraw->InitTag( "TOP", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "HANDLER", DLongGDL( baseWidgetID ) ); widgdraw->InitTag( "X", DLongGDL( event.GetX() ) ); widgdraw->InitTag( "Y", DLongGDL( drawSize.y-event.GetY() ) ); widgdraw->InitTag( "CLICKS", DLongGDL( 0 ) ); widgdraw->InitTag( "PRESS", DByteGDL( (event.GetEventType() == wxEVT_KEY_DOWN) ) ); widgdraw->InitTag( "RELEASE", DByteGDL( (event.GetEventType() == wxEVT_KEY_UP) ) ); int start=0; int keyc=event.GetKeyCode( ); //get key switch ( keyc ) { case WXK_NUMPAD_END: case WXK_END: start++; case WXK_NUMPAD_HOME: case WXK_HOME: start++; case WXK_NUMPAD_PAGEDOWN: case WXK_PAGEDOWN: start++; case WXK_NUMPAD_PAGEUP: case WXK_PAGEUP: start++; case WXK_NUMPAD_DOWN:case WXK_DOWN: start++; case WXK_NUMPAD_UP:case WXK_UP: start++; case WXK_NUMPAD_RIGHT:case WXK_RIGHT: start++; case WXK_NUMPAD_LEFT:case WXK_LEFT: start++; case WXK_ALT: start++; case WXK_CAPITAL: //not sure OK! start++; case WXK_CONTROL: start++; case WXK_SHIFT: start++; if ( mode==2 || start > 4 ) { widgdraw->InitTag( "TYPE", DIntGDL( 6 ) ); //special key widgdraw->InitTag( "KEY", DLongGDL( start ) ); widgdraw->InitTag( "CH", DByteGDL( 0 ) ); widgdraw->InitTag( "MODIFIERS", DLongGDL( event.GetModifiers()) ); GDLWidget::PushEvent( baseWidgetID, widgdraw ); } break; default: widgdraw->InitTag( "TYPE", DIntGDL( 5 ) ); //normal key widgdraw->InitTag( "KEY", DLongGDL( 0 ) ); widgdraw->InitTag( "CH", DByteGDL( event.GetRawKeyCode() & 0xFF ) ); widgdraw->InitTag( "MODIFIERS", DLongGDL( event.GetModifiers() ) ); GDLWidget::PushEvent( baseWidgetID, widgdraw ); } } } void gdlGrid::OnTableRowResizing(wxGridSizeEvent & event){ #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlGrid::OnTableRowResizing: %d\n"),event.GetId()); #endif GDLWidgetTable* table = static_cast(GDLWidget::GetWidget(GDLWidgetTableID)); DULong eventFlags=table->GetEventFlags(); if (eventFlags & GDLWidget::EV_ALL) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtablerowheight = new DStructGDL( "WIDGET_TABLE_ROW_HEIGHT"); widgtablerowheight->InitTag("ID", DLongGDL( event.GetId( ) )); widgtablerowheight->InitTag("TOP", DLongGDL( baseWidgetID)); widgtablerowheight->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgtablerowheight->InitTag("TYPE", DIntGDL(6)); // 6 widgtablerowheight->InitTag("ROW", DLongGDL( event.GetRowOrCol() )); widgtablerowheight->InitTag("HEIGHT",DLongGDL( this->GetRowSize(event.GetRowOrCol()))); // insert into structList GDLWidget::PushEvent( baseWidgetID, widgtablerowheight ); } event.Skip(); } void gdlGrid::OnTableColResizing(wxGridSizeEvent & event){ #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlGrid::OnTableColResizing: %d\n"),event.GetId()); #endif GDLWidgetTable* table = static_cast(GDLWidget::GetWidget(GDLWidgetTableID)); DULong eventFlags=table->GetEventFlags(); if (eventFlags & GDLWidget::EV_ALL) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtablerowheight = new DStructGDL( "WIDGET_TABLE_COL_WIDTH"); widgtablerowheight->InitTag("ID", DLongGDL( event.GetId( ) )); widgtablerowheight->InitTag("TOP", DLongGDL( baseWidgetID)); widgtablerowheight->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgtablerowheight->InitTag("TYPE", DIntGDL(7)); // 7 widgtablerowheight->InitTag("COL", DLongGDL( event.GetRowOrCol() )); widgtablerowheight->InitTag("WIDTH",DLongGDL( this->GetColSize(event.GetRowOrCol()))); // insert into structList GDLWidget::PushEvent( baseWidgetID, widgtablerowheight ); } event.Skip(); } void gdlGrid::OnTableRangeSelection(wxGridRangeSelectEvent & event){ #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlGrid::OnTableRangeSelection: %d\n"),event.GetId()); #endif //this event is called when a selection is added or changed (control-click, etc). //If we are not in disjoint mode, clear previous selection to mimick idl's when the user control-clicked. GDLWidgetTable* table = static_cast(GDLWidget::GetWidget(GDLWidgetTableID)); DULong eventFlags=table->GetEventFlags(); if (eventFlags & GDLWidget::EV_ALL && !table->IsUpdating() ) { if (event.Selecting()) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtablecelsel = new DStructGDL( "WIDGET_TABLE_CELL_SEL"); widgtablecelsel->InitTag("ID", DLongGDL( event.GetId( ) )); widgtablecelsel->InitTag("TOP", DLongGDL( baseWidgetID)); widgtablecelsel->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgtablecelsel->InitTag("TYPE",DIntGDL(4)); // 4 or 9 widgtablecelsel->InitTag("SEL_LEFT", DLongGDL( event.GetLeftCol())); widgtablecelsel->InitTag("SEL_TOP", DLongGDL( event.GetTopRow())); widgtablecelsel->InitTag("SEL_RIGHT", DLongGDL( event.GetRightCol())); widgtablecelsel->InitTag("SEL_BOTTOM", DLongGDL( event.GetBottomRow())); GDLWidget::PushEvent( baseWidgetID, widgtablecelsel ); } else { int ncols = static_cast(event.GetEventObject())->GetNumberCols(); int nrows = static_cast(event.GetEventObject())->GetNumberRows(); if (event.GetLeftCol()==0 && event.GetRightCol()==ncols-1 && event.GetTopRow()==0 && event.GetBottomRow()==nrows-1 ) { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtablecelsel = new DStructGDL( "WIDGET_TABLE_CELL_SEL"); widgtablecelsel->InitTag("ID", DLongGDL( event.GetId( ) )); widgtablecelsel->InitTag("TOP", DLongGDL( baseWidgetID )); widgtablecelsel->InitTag("HANDLER", DLongGDL( baseWidgetID ) ); widgtablecelsel->InitTag("TYPE",DIntGDL( 4 )); // widgtablecelsel->InitTag("SEL_LEFT", DLongGDL( -1 )); widgtablecelsel->InitTag("SEL_TOP", DLongGDL( -1 )); widgtablecelsel->InitTag("SEL_RIGHT", DLongGDL( -1 )); widgtablecelsel->InitTag("SEL_BOTTOM", DLongGDL( -1 )); GDLWidget::PushEvent( baseWidgetID, widgtablecelsel ); } else { if (!table->GetDisjointSelection() && event.ControlDown() ) this->ClearSelection(); else { WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); DStructGDL* widgtablecelsel = new DStructGDL( "WIDGET_TABLE_CELL_DESEL"); widgtablecelsel->InitTag("ID", DLongGDL( event.GetId( ) )); widgtablecelsel->InitTag("TOP", DLongGDL( baseWidgetID )); widgtablecelsel->InitTag("HANDLER", DLongGDL( baseWidgetID )); widgtablecelsel->InitTag("TYPE",DIntGDL( 9 )); // 9 widgtablecelsel->InitTag("SEL_LEFT", DLongGDL( event.GetLeftCol() )); widgtablecelsel->InitTag("SEL_TOP", DLongGDL( event.GetTopRow() )); widgtablecelsel->InitTag("SEL_RIGHT", DLongGDL( event.GetRightCol() )); widgtablecelsel->InitTag("SEL_BOTTOM", DLongGDL( event.GetBottomRow())); GDLWidget::PushEvent( baseWidgetID, widgtablecelsel ); } } } } event.Skip(); } void gdlGrid::OnTableCellSelection(wxGridEvent & event){ #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlGrid::OnTableCellSelection: %d\n"),event.GetId()); #endif //This event is called only when the user left-clicks somewhere, thus deleting all previous selection. GDLWidgetTable* table = static_cast(GDLWidget::GetWidget(GDLWidgetTableID)); if (!table->GetDisjointSelection() && event.ControlDown() ) { table->ClearSelection(); } event.Skip(); //For compatibility with idl, we should force to select the current table entry. this->SelectBlock(event.GetRow(),event.GetCol(),event.GetRow(),event.GetCol(),FALSE); } //Forget this function for the time being! // void gdlGrid::OnTableCellSelection(wxGridEvent & event){ //#if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_ALL_EVENTS) // wxMessageOutputStderr().Printf(_T("in gdlGrid::OnTableCellSelection: %d\n"),event.GetId()); //#endif ////This event is called only when the user left-clicks somewhere, thus deleting all previous selection. // // GDLWidgetTable* table = static_cast(GDLWidget::GetWidget(GDLWidgetTableID)); // DULong eventFlags=table->GetEventFlags(); // // if (eventFlags & GDLWidget::EV_ALL && !table->IsUpdating()) { // WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); // DStructGDL* widgtablecelsel = new DStructGDL( "WIDGET_TABLE_CELL_SEL"); // widgtablecelsel->InitTag("ID", DLongGDL( event.GetId( ) )); // widgtablecelsel->InitTag("TOP", DLongGDL( baseWidgetID)); // widgtablecelsel->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widgtablecelsel->InitTag("TYPE",DIntGDL(4)); // 4 // widgtablecelsel->InitTag("SEL_LEFT", DLongGDL(event.Selecting()?event.GetCol():-1)); // widgtablecelsel->InitTag("SEL_TOP", DLongGDL(event.Selecting()?event.GetRow(): -1 )); // widgtablecelsel->InitTag("SEL_RIGHT", DLongGDL( event.Selecting()?event.GetCol():-1 )); // widgtablecelsel->InitTag("SEL_BOTTOM", DLongGDL( event.Selecting()?event.GetCol():-1 )); // GDLWidget::PushEvent( baseWidgetID, widgtablecelsel ); // } // event.Skip(); ////For compatibility with idl, we should force to select the current table entry. //// this->SelectBlock(event.GetRow(),event.GetCol(),event.GetRow(),event.GetCol(),FALSE); // if (table->IsUpdating()) {cerr<<"cleared"<ClearUpdating();} // } //void gdlGrid::OnTextEnter( wxCommandEvent& event) //{ //#if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_ALL_EVENTS) // wxMessageOutputStderr().Printf(_T("in gdlGrid::OnTextEnter: %d\n"),event.GetId()); //#endif //} //void gdlGrid::OnText( wxCommandEvent& event) //{ //#if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_ALL_EVENTS) // wxMessageOutputStderr().Printf(_T("in gdlGrid::OnText: %d\n"),event.GetId()); //#endif // GDLWidgetTable* table = static_cast(GDLWidget::GetWidget(GDLWidgetTableID)); // DULong eventFlags=table->GetEventFlags(); // // WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase(GDLWidgetTableID); // // bool isModified; // long selStart, selEnd; // DLong offset; // std::string lastValue; // std::string newValue; // // wxTextCtrl* textCtrl = static_cast(event.GetEventObject()); // if( textCtrl == NULL) // { // event.Skip(); // return; // happens on construction // } // textCtrl->GetSelection( &selStart, &selEnd); // offset = textCtrl->GetInsertionPoint(); // lastValue = textCtrl->GetLabelText().mb_str(wxConvUTF8); // newValue = textCtrl->GetValue().mb_str(wxConvUTF8); // isModified = lastValue != newValue; //// textCtrl->SetValue(wxString(newValue, wxConvUTF8)); ////return without producing event struct if eventType is not set // if (!(eventFlags & GDLWidget::EV_ALL )) return; // // DStructGDL* widg; // if( !isModified) // { // widg = new DStructGDL( "WIDGET_TABLE_TEXT_SEL"); // widg->InitTag("ID", DLongGDL( GDLWidgetTableID)); // widg->InitTag("TOP", DLongGDL( baseWidgetID)); // widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widg->InitTag("TYPE", DIntGDL( 3)); // selection // widg->InitTag("OFFSET", DLongGDL( offset)); // widg->InitTag("LENGTH", DLongGDL( selEnd-selStart)); // widg->InitTag("X", DLongGDL( 0 )); // widg->InitTag("Y", DLongGDL( 0 )); // } // else // { // int lengthDiff = newValue.length() - lastValue.length(); // if( lengthDiff < 0) // deleted // { // widg = new DStructGDL( "WIDGET_TABLE_DEL"); // widg->InitTag("ID", DLongGDL( GDLWidgetTableID)); // widg->InitTag("TOP", DLongGDL( baseWidgetID)); // widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widg->InitTag("TYPE", DIntGDL( 2)); // delete // widg->InitTag("OFFSET", DLongGDL( offset-1)); // widg->InitTag("LENGTH", DLongGDL( -lengthDiff)); // widg->InitTag("X", DLongGDL( 0 )); // widg->InitTag("Y", DLongGDL( 0 )); // } // else if( lengthDiff == 0) // replace TODO: just flag the real change // { // // 1st delete all // widg = new DStructGDL( "WIDGET_TABLE_DEL"); // widg->InitTag("ID", DLongGDL( GDLWidgetTableID)); // widg->InitTag("TOP", DLongGDL( baseWidgetID)); // widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widg->InitTag("TYPE", DIntGDL( 2)); // delete // widg->InitTag("OFFSET", DLongGDL( 0)); // widg->InitTag("LENGTH", DLongGDL( lastValue.length())); // widg->InitTag("X", DLongGDL( 0 )); // widg->InitTag("Y", DLongGDL( 0 )); // // GDLWidget::PushEvent( baseWidgetID, widg); // // // 2nd insert new // widg = new DStructGDL( "WIDGET_TABLE_STR"); // widg->InitTag("ID", DLongGDL( GDLWidgetTableID)); // widg->InitTag("TOP", DLongGDL( baseWidgetID)); // widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widg->InitTag("TYPE", DIntGDL( 1)); // multiple char // widg->InitTag("OFFSET", DLongGDL( 0)); // widg->InitTag("STR", DStringGDL( newValue)); // widg->InitTag("X", DLongGDL( 0 )); // widg->InitTag("Y", DLongGDL( 0 )); // } // else if( lengthDiff == 1) // { // widg = new DStructGDL( "WIDGET_TABLE_CH"); // widg->InitTag("ID", DLongGDL( GDLWidgetTableID)); // widg->InitTag("TOP", DLongGDL( baseWidgetID)); // widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widg->InitTag("TYPE", DIntGDL( 0)); // single char // widg->InitTag("OFFSET", DLongGDL( offset+1)); // widg->InitTag("CH", DByteGDL( newValue[offsetInitTag("X", DLongGDL( 0 )); // widg->InitTag("Y", DLongGDL( 0 )); // } // else // lengthDiff > 1 // { // int nVLenght = newValue.length(); // if( offset < lengthDiff) lengthDiff = offset; // string str = ""; // if( offset <= nVLenght && lengthDiff > 0) str = newValue.substr(offset-lengthDiff,lengthDiff+1); // // widg = new DStructGDL( "WIDGET_TABLE_STR"); // widg->InitTag("ID", DLongGDL( GDLWidgetTableID)); // widg->InitTag("TOP", DLongGDL( baseWidgetID)); // widg->InitTag("HANDLER", DLongGDL( baseWidgetID )); // widg->InitTag("TYPE", DIntGDL( 1)); // multiple char // widg->InitTag("OFFSET", DLongGDL( offset)); // widg->InitTag("STR", DStringGDL( str)); // widg->InitTag("X", DLongGDL( 0 )); // widg->InitTag("Y", DLongGDL( 0 )); // } // } // GDLWidget::PushEvent( baseWidgetID, widg); //} // void gdlTreeCtrl::OnItemActivated(wxTreeEvent & event){ #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlTreeCtrl::OnItemActivated: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); //get GDLWidgetTree ID which was passed as wxTreeItemData at creation to identify //the GDL widget that received the event gdlTreeCtrl* me=static_cast(event.GetEventObject()); DStructGDL* treeselect = new DStructGDL( "WIDGET_TREE_SEL"); treeselect->InitTag("ID", DLongGDL( static_cast(me->GetItemData(event.GetItem()))->widgetID )); treeselect->InitTag("TOP", DLongGDL( baseWidgetID)); treeselect->InitTag("HANDLER", DLongGDL( GDLWidgetTableID )); treeselect->InitTag("TYPE", DIntGDL(0)); // 0 treeselect->InitTag("CLICKS",DLongGDL(2)); // insert into structList GDLWidget::PushEvent( baseWidgetID, treeselect ); } void gdlTreeCtrl::OnItemSelected(wxTreeEvent & event){ #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlTreeCtrl::OnItemActivated: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); //get GDLWidgetTree ID which was passed as wxTreeItemData at creation to identify //the GDL widget that received the event gdlTreeCtrl* me=static_cast(event.GetEventObject()); WidgetIDT selected=static_cast(me->GetItemData(event.GetItem()))->widgetID; GDLWidgetTree* tree= static_cast(GDLWidget::GetWidget(static_cast(me->GetItemData(event.GetItem()))->widgetID)); //inform root widget it is selected GDLWidgetTree* root=static_cast(GDLWidget::GetWidget(tree->GetRootID())); root->SetSelectedID(selected); DStructGDL* treeselect = new DStructGDL( "WIDGET_TREE_SEL"); treeselect->InitTag("ID", DLongGDL( selected )); treeselect->InitTag("TOP", DLongGDL( baseWidgetID)); treeselect->InitTag("HANDLER", DLongGDL( GDLWidgetTableID )); treeselect->InitTag("TYPE", DIntGDL(0)); // 0 treeselect->InitTag("CLICKS",DLongGDL(1)); // insert into structList GDLWidget::PushEvent( baseWidgetID, treeselect ); } void gdlTreeCtrl::OnBeginDrag(wxTreeEvent & event){ //largely useful protection!!! if (!event.GetItem().IsOk()) return; #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlTreeCtrl::OnBeginDrag: %d\n"),event.GetId()); #endif //needed to explicitly authorize dragging. //get GDLWidgetTree ID which was passed as wxTreeItemData at creation to identify //the GDL widget that received the event gdlTreeCtrl* me=static_cast(event.GetEventObject()); GDLWidgetTree* item = static_cast(GDLWidget::GetWidget(static_cast(me->GetItemData(event.GetItem()))->widgetID)); if (item->IsDraggable()) event.Allow(); } void gdlTreeCtrl::OnItemDropped(wxTreeEvent & event){ if (!event.GetItem().IsOk()) return; #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlTreeCtrl::OnItemDropped: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); gdlTreeCtrl* me=static_cast(event.GetEventObject()); GDLWidgetTree* item = static_cast(GDLWidget::GetWidget(static_cast(me->GetItemData(event.GetItem()))->widgetID)); if (item->IsDroppable()) { //get GDLWidgetTree ID which was passed as wxTreeItemData at creation to identify //the GDL widget that received the event DStructGDL* treedrop = new DStructGDL( "WIDGET_DROP"); treedrop->InitTag("ID", DLongGDL( item->WidgetID() )); //ID of the destination treedrop->InitTag("TOP", DLongGDL( baseWidgetID)); treedrop->InitTag("HANDLER", DLongGDL( GDLWidgetTableID )); treedrop->InitTag("DRAG_ID", DLongGDL( item->GetRootID())); // ID of the source TREE treedrop->InitTag("POSITION",DIntGDL(2)); //ALWAYS 2 IT SEEMS THAT wxW cannot do better? ! 1 above 2 on 3 below destination widget treedrop->InitTag("X",DLongGDL(event.GetPoint().x)); //x and Y coord of position wrt lower left corner of destination tree widget treedrop->InitTag("Y",DLongGDL(event.GetPoint().y)); treedrop->InitTag("MODIFIERS",DIntGDL(0)); //mask with 1 shift 2 control 4 caps lock 8 alt // insert into structList GDLWidget::PushEvent( baseWidgetID, treedrop ); } } void gdlTreeCtrl::OnItemExpanded(wxTreeEvent & event){ if (!event.GetItem().IsOk()) return; #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlTreeCtrl::OnItemExpanded: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); //get GDLWidgetTree ID which was passed as wxTreeItemData at creation to identify //the GDL widget that received the event gdlTreeCtrl* me=static_cast(event.GetEventObject()); DStructGDL* treeexpand = new DStructGDL( "WIDGET_TREE_EXPAND"); treeexpand->InitTag("ID", DLongGDL( static_cast(me->GetItemData(event.GetItem()))->widgetID )); treeexpand->InitTag("TOP", DLongGDL( baseWidgetID)); treeexpand->InitTag("HANDLER", DLongGDL( GDLWidgetTableID )); treeexpand->InitTag("TYPE", DIntGDL(1)); // 1 treeexpand->InitTag("EXPAND",DLongGDL(1)); //1 expand // insert into structList GDLWidget::PushEvent( baseWidgetID, treeexpand ); } void gdlTreeCtrl::OnItemCollapsed(wxTreeEvent & event){ if (!event.GetItem().IsOk()) return; #if (GDL_DEBUG_ALL_EVENTS || GDL_DEBUG_OTHER_EVENTS) wxMessageOutputStderr().Printf(_T("in gdlTreeCtrl::OnItemCollapsed: %d\n"),event.GetId()); #endif WidgetIDT baseWidgetID = GDLWidget::GetTopLevelBase( event.GetId( ) ); //get GDLWidgetTree ID which was passed as wxTreeItemData at creation to identify //the GDL widget that received the event gdlTreeCtrl* me=static_cast(event.GetEventObject()); DStructGDL* treeexpand = new DStructGDL( "WIDGET_TREE_EXPAND"); treeexpand->InitTag("ID", DLongGDL( static_cast(me->GetItemData(event.GetItem()))->widgetID )); treeexpand->InitTag("TOP", DLongGDL( baseWidgetID)); treeexpand->InitTag("HANDLER", DLongGDL( GDLWidgetTableID )); treeexpand->InitTag("TYPE", DIntGDL(1)); // 1 treeexpand->InitTag("EXPAND",DLongGDL(0)); //0 collapse // insert into structList GDLWidget::PushEvent( baseWidgetID, treeexpand ); } #endif gdl-0.9.9/src/gdlwinstream.cpp000066400000000000000000000402331340051421000162620ustar00rootroot00000000000000/* ************************************************************************* gdlwinstream.cpp - graphic stream M$ windows ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "graphicsdevice.hpp" using namespace std; #include "gdlwinstream.hpp" #include "devicewin.hpp" #include "gdleventhandler.hpp" #ifndef PLESC_TELLME #define PLESC_TELLME 41 #endif BYTE ANDmaskCursor[128] = { 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; BYTE XORmaskCursor[128] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; GDLWINStream::~GDLWINStream() { // // wingdi.c is a plplot driver in development which may // in future be preferable to the use of wingcc. // The macro USE_WINGDI_NOT_WINGCC is sufficient to // accomodate that driver in this same code // that uses wingcc.c. GetHwnd() and GetHdc() allow // access to the window and device context handles, // respectively, for either case. // if (tv_buf.has_data) { tv_buf.has_data = false; delete[] tv_buf.lpbitmap; } DestroyWindow(GetHwnd()); // Manually destroy window } void GDLWINStream::Init() { this->plstream::init(); plgpls(&pls); #ifdef USE_WINGDI_NOT_WINGCC #else wingcc_Dev* dev = (wingcc_Dev *)pls->dev; dev->waiting = 1; #endif UnsetFocus(); tv_buf.has_data = false; HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); CrosshairCursor = CreateCursor(hInstance, 15, 14, 32, 32, ANDmaskCursor, XORmaskCursor); } void GDLWINStream::SetWindowTitle(char* buf) { SetWindowTextA(GetHwnd(), buf); } void GDLWINStream::EventHandler() { if (!valid) return; if (GetHwnd() == NULL) { cerr << "Invalid window." << endl; valid = false; return; } // if wxWidgets is available, then use wxWidgets' event handler instead. #ifndef HAVE_LIBWXWIDGETS MSG Message; if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Message); if (Message.message == WM_DESTROY) { this->SetValid(false); cout << "WM_DESTROY detected in GDLWINSTREAM:: " << endl; } DispatchMessage(&Message); } #endif } void GDLWINStream::Load_gin(HWND window){ RECT rcClient; GetClientRect(window, &rcClient); ScreenToClient(window, &GinPoint); _gin->pX = GinPoint.x; _gin->pY = (rcClient.bottom - rcClient.top) - GinPoint.y; if (xbutton) _gin->button = 4; else if (rbutton) _gin->button = 3; else if (mbutton) _gin->button = 2; _gin->dX = ((PLFLT)_gin->pX) / (rcClient.right - rcClient.left - 1); _gin->dY = ((PLFLT)_gin->pY) / (rcClient.bottom - rcClient.top - 1); return; } void CALLBACK GDLWINStream::GinCallback(UINT message, WPARAM wParam, LPARAM lParam) { HWND window = GetHwnd(); RECT rcClient; _gin->button = 0; buttonpressed = false; rbutton = false; xbutton = false; mbutton = false; GetClientRect(window, &rcClient); // https://msdn.microsoft.com/library/windows/desktop/ms633503%28v=vs.85%29.aspx ClientToScreen(window, (LPPOINT)&rcClient.left); // http://support.microsoft.com/en-us/kb/11570 ClientToScreen(window, (LPPOINT)&rcClient.right); switch (message) { case WM_XBUTTONDOWN: xbutton = true; break; case WM_RBUTTONDOWN: rbutton = true; break; case WM_MBUTTONDOWN: mbutton = true; break; case WM_LBUTTONDOWN: if (wParam != MK_LBUTTON && wParam != MK_MBUTTON && wParam != MK_RBUTTON && wParam != MK_XBUTTON1 && wParam != MK_XBUTTON1) return; if (_mode == 4) break; // Looking for button up _gin->button = 1; buttonpressed = true; break; case WM_XBUTTONUP: xbutton = true; break; case WM_RBUTTONUP: rbutton = true; break; case WM_MBUTTONUP: mbutton = true; break; case WM_LBUTTONUP: if (wParam != MK_LBUTTON && wParam != MK_MBUTTON && wParam != MK_RBUTTON && wParam != MK_XBUTTON1 && wParam != MK_XBUTTON1) return; if (_mode == 3) break; // Looking for button down _gin->button = 1; buttonpressed = true; break; case WM_CHAR: _gin->keysym = wParam; buttonpressed = true; break; default: if (_mode == 0) { GetCursorPos(&GinPoint); buttonpressed = true; } } if (_mode == 2) buttonpressed = true; GetCursorPos(&GinPoint); if (!buttonpressed || rcClient.left > GinPoint.x || GinPoint.x > rcClient.right || rcClient.top > GinPoint.y || GinPoint.y > rcClient.bottom) { buttonpressed = false; return; } Load_gin(window); return; } bool GDLWINStream::GetGin(PLGraphicsIn *gin, int mode) { LPPOINT lpt; _gin = gin; _mode = mode; HWND window = GetHwnd(); HCURSOR previous; UINT SWP = (SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); HWND resetFG = GetForegroundWindow(); previous = SetCursor(CrosshairCursor); SetClassLongPtr(window, GCLP_HCURSOR, reinterpret_cast(CrosshairCursor)); SetWindowPos(window, HWND_BOTTOM, // DeIconic() 0,0,0,0, (SWP_NOMOVE | SWP_NOSIZE |SWP_SHOWWINDOW)); BringWindowToTop(window); if(_mode == 0) { GetCursorPos(&GinPoint); buttonpressed = true; Load_gin(window); SetCursor(previous); Sleep(2); return true; } buttonpressed = false; msghooks[WM_XBUTTONDOWN] = &GDLWINStream::GinCallback; msghooks[WM_RBUTTONDOWN] = &GDLWINStream::GinCallback; msghooks[WM_MBUTTONDOWN] = &GDLWINStream::GinCallback; msghooks[WM_LBUTTONDOWN] = &GDLWINStream::GinCallback; msghooks[WM_XBUTTONUP] = &GDLWINStream::GinCallback; msghooks[WM_RBUTTONUP] = &GDLWINStream::GinCallback; msghooks[WM_MBUTTONUP] = &GDLWINStream::GinCallback; msghooks[WM_LBUTTONUP] = &GDLWINStream::GinCallback; msghooks[WM_CHAR] = &GDLWINStream::GinCallback; while (!buttonpressed) { if (valid == false) return false; // TODO: Instead this, it should spawn a new window! GDLEventHandler(); RedrawTV(); Sleep(10); } msghooks.erase(WM_XBUTTONDOWN); msghooks.erase(WM_RBUTTONDOWN); msghooks.erase(WM_MBUTTONDOWN); msghooks.erase(WM_LBUTTONDOWN); msghooks.erase(WM_XBUTTONUP); msghooks.erase(WM_RBUTTONUP); msghooks.erase(WM_MBUTTONUP); msghooks.erase(WM_LBUTTONUP); msghooks.erase(WM_CHAR); SetForegroundWindow(resetFG); SetCursor(previous); Sleep(2); BringWindowToTop(window); Sleep(2); SetFocus(resetFG); return true; } bool GDLWINStream::PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan) { plstream::cmd(PLESC_FLUSH, NULL); RECT rt; PLINT kxLimit, kyLimit; PLINT kx, ky; PLINT xoff, yoff; xoff = (PLINT)pos[0]; yoff = (PLINT)pos[2]; kxLimit = pls->phyxma - xoff; kyLimit = pls->phyyma - yoff; if (nx < kxLimit) kxLimit = nx; if (ny < kyLimit) kyLimit = ny; if (nx > 0 && ny > 0) { unsigned char iclr1, ired, igrn, iblu; GetClientRect(GetHwnd(), &rt); if (tv_buf.has_data && (tv_buf.bi.bmiHeader.biWidth != rt.right + 1 || -(tv_buf.bi.bmiHeader.biHeight) != rt.bottom + 1)) { // Resize tv_buf.lpbitmap RGBQUAD* lpbitmap = new RGBQUAD[(rt.right + 1) * (rt.bottom + 1)]; memset(lpbitmap, 0, sizeof(RGBQUAD) * (rt.right + 1) * (rt.bottom + 1)); for (SizeT ix = 0; ix < min(tv_buf.bi.bmiHeader.biWidth, rt.right + 1); ix++) for (SizeT iy = 0; iy < min((-tv_buf.bi.bmiHeader.biHeight), rt.bottom + 1); iy++) lpbitmap[iy*(rt.right + 1) + ix] = tv_buf.lpbitmap[iy*tv_buf.bi.bmiHeader.biWidth + ix]; delete[] tv_buf.lpbitmap; tv_buf.lpbitmap = lpbitmap; } else if (!tv_buf.has_data) { tv_buf.lpbitmap = new RGBQUAD[(rt.right + 1) * (rt.bottom + 1)]; } memset(&tv_buf.bi, 0, sizeof(BITMAPINFO)); tv_buf.bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); tv_buf.bi.bmiHeader.biWidth = rt.right + 1; tv_buf.bi.bmiHeader.biHeight = -(rt.bottom + 1); tv_buf.bi.bmiHeader.biPlanes = 1; tv_buf.bi.bmiHeader.biBitCount = 32; tv_buf.bi.bmiHeader.biCompression = BI_RGB; for (SizeT ix = 0; ix < kxLimit; ++ix) { for (SizeT iy = 0; iy < kyLimit; ++iy) { kx = xoff + ix; ky = rt.bottom - (yoff + iy + 1); // To be the same as IDL if (ky < 0 || kx >= rt.right + 1) continue; if (tru == 0 && chan == 0) { iclr1 = idata[iy * nx + ix]; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbBlue = pls->cmap1[iclr1].b; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbGreen = pls->cmap1[iclr1].g; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbRed = pls->cmap1[iclr1].r; } else { if (chan == 0) { if (tru == 1) { ired = idata[3 * (iy * nx + ix) + 0]; igrn = idata[3 * (iy * nx + ix) + 1]; iblu = idata[3 * (iy * nx + ix) + 2]; } else if (tru == 2) { ired = idata[nx * (iy * 3 + 0) + ix]; igrn = idata[nx * (iy * 3 + 1) + ix]; iblu = idata[nx * (iy * 3 + 2) + ix]; } else if (tru == 3) { ired = idata[nx * (0 * ny + iy) + ix]; igrn = idata[nx * (1 * ny + iy) + ix]; iblu = idata[nx * (2 * ny + iy) + ix]; } tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbBlue = iblu; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbGreen = igrn; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbRed = ired; } else if (chan == 1) { //1 byte bitmap passed ired = idata[1 * (iy * nx + ix) + 0]; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbRed = ired; } else if (chan == 2) { igrn = idata[1 * (iy * nx + ix) + 0]; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbGreen = igrn; } else if (chan == 3) { iblu = idata[1 * (iy * nx + ix) + 0]; tv_buf.lpbitmap[ky * (rt.right + 1) + kx].rgbBlue = iblu; } // if (chan == 0) else } // if (tru == 0 && chan == 0) else } // for() inner (indent error) } // for() outer SetDIBitsToDevice(GetHdc(), 0, 0, rt.right + 1, rt.bottom + 1, 0, 0, 0, rt.bottom + 1, tv_buf.lpbitmap, &tv_buf.bi, DIB_RGB_COLORS); BringWindowToTop(GetHwnd()); UnsetFocus(); tv_buf.has_data = true; } return true; } void GDLWINStream::Raise() { BringWindowToTop(GetHwnd()); return; } void GDLWINStream::GetGeometry(long& xSize, long& ySize) { // GetGeometry is called from // 1. 'plotting_contour.cpp' to calculate plot area, // 2. 'initsysvar.cpp' to update '!D'. // http://support.microsoft.com/en-us/kb/11570 RECT Rect; HWND window = GetHwnd(); GetClientRect(window, &Rect); ClientToScreen(window, (LPPOINT)&Rect.left); ClientToScreen(window, (LPPOINT)&Rect.right); xSize = Rect.right - Rect.left + 1; ySize = Rect.bottom - Rect.top + 1; // xoff = Rect.left; // yoff = GetSystemMetrics(SM_CYSCREEN) - Rect.bottom; return; } bool GDLWINStream::GetWindowPosition(long& xpos, long& ypos) { /* GET_WINDOW_POSITION (WIN, X) Set this keyword to a named variable that returns a two-element array containing the (X,Y) position of the lower left corner of the current window on the screen. The origin is also in the lower left corner of the screen. */ RECT rt; GetWindowRect(GetHwnd(), &rt); xpos = rt.left + 1; ypos = GetSystemMetrics(SM_CYSCREEN) - rt.bottom + 1; return true; } void GDLWINStream::Lower() { SetWindowPos(GetHwnd(), HWND_BOTTOM, 0,0,0,0, (SWP_NOMOVE | SWP_NOSIZE)); return; } void GDLWINStream::Iconic() { SetWindowPos(GetHwnd(), HWND_BOTTOM, 0,0,0,0, (SWP_NOMOVE | SWP_NOSIZE |SWP_HIDEWINDOW)); return; } void GDLWINStream::DeIconic() { SetWindowPos(GetHwnd(), HWND_BOTTOM, 0,0,0,0, (SWP_NOMOVE | SWP_NOSIZE |SWP_SHOWWINDOW)); return; } void GDLWINStream::CheckValid() { if(!IsWindow(GetHwnd())) this->SetValid(false); } void GDLWINStream::Flush() { GdiFlush(); } DLong GDLWINStream::GetVisualDepth(){ return GetDeviceCaps(GetHdc(),PLANES); } unsigned long GDLWINStream::GetWindowDepth(){ return GetVisualDepth(); } bool GDLWINStream::UnsetFocus() { SetFocus(this->refocus); return true; } void GDLWINStream::Clear() { PLINT red,green,blue; DByte r,g,b; PLINT red0,green0,blue0; GraphicsDevice::GetCT()->Get(0,r,g,b);red=r;green=g;blue=b; red0=GraphicsDevice::GetDevice()->BackgroundR(); green0=GraphicsDevice::GetDevice()->BackgroundG(); blue0=GraphicsDevice::GetDevice()->BackgroundB(); plstream::scolbg(red0,green0,blue0); //overwrites col[0] ::c_plbop(); // ::c_plclear(); plstream::scolbg(red,green,blue); //resets col[0] } HWND GDLWINStream::GetHwnd() { if (pls) { #ifdef USE_WINGDI_NOT_WINGCC wingdi_Dev *dev = (wingdi_Dev *)pls->dev; #else wingcc_Dev* dev = (wingcc_Dev *)pls->dev; #endif if (dev) return dev->hwnd; } return NULL; } HDC GDLWINStream::GetHdc() { if (pls) { #ifdef USE_WINGDI_NOT_WINGCC wingdi_Dev *dev = (wingdi_Dev *)pls->dev; #else wingcc_Dev* dev = (wingcc_Dev *)pls->dev; #endif if (dev) return dev->hdc; } return NULL; } void GDLWINStream::RedrawTV() { RECT rt; HWND tvwnd = GetHwnd(); // If tv_buf has data, draw it on screen if (tv_buf.has_data && tvwnd) { GetClientRect(tvwnd, &rt); if (tv_buf.bi.bmiHeader.biWidth != rt.right + 1 || -tv_buf.bi.bmiHeader.biHeight != rt.bottom + 1) { // Resize tv_buf.lpbitmap RGBQUAD* lpbitmap = new RGBQUAD[(rt.right + 1) * (rt.bottom + 1)]; memset(lpbitmap, 0, sizeof(RGBQUAD) * (rt.right + 1) * (rt.bottom + 1)); for (SizeT ix = 0; ix < min(tv_buf.bi.bmiHeader.biWidth, rt.right + 1); ix++) for (SizeT iy = 0; iy < min(-tv_buf.bi.bmiHeader.biHeight, rt.bottom + 1); iy++) lpbitmap[iy*(rt.right + 1) + ix] = tv_buf.lpbitmap[iy*tv_buf.bi.bmiHeader.biWidth + ix]; delete[] tv_buf.lpbitmap; tv_buf.lpbitmap = lpbitmap; tv_buf.bi.bmiHeader.biWidth = rt.right + 1; tv_buf.bi.bmiHeader.biHeight = -(rt.bottom + 1); } SetDIBitsToDevice(GetHdc(), 0, 0, rt.right + 1, rt.bottom + 1, 0, 0, 0, rt.bottom + 1, tv_buf.lpbitmap, &tv_buf.bi, DIB_RGB_COLORS); } } gdl-0.9.9/src/gdlwinstream.hpp000066400000000000000000000140511340051421000162660ustar00rootroot00000000000000/* ************************************************************************* gdlwinstream.hpp - graphic stream M$ windows ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** \file gdlwinstream.hpp \brief graphic stream M$ windows \struc wingcc_Dev \class GDLWINStream */ #ifndef GDLWINSTREAM_HPP_ #define GDLWINSTREAM_HPP_ #include "gdlgstream.hpp" /* For mingw-org, setting WINVER to at least Win2k (windef.h) This is required for the cursor callback method. */ #ifndef WINVER # define WINVER 0x0500 #else # if (WINVER < 0x0500) # define WINVER 0x0500 # endif #endif #include #include #ifdef USE_WINGDI_NOT_WINGCC struct wingdi_Dev { // // WIN32 API variables // HWND hwnd; // Handle for the plot area HDC hdc; // Plot window device context }; #else // Copied from wingcc.c // Struct to hold device-specific info. struct wingcc_Dev { PLFLT scale; // scaling factor to "blow up" to the "virtual" page in removing hidden lines PLINT width; // Window width (which can change) PLINT height; // Window Height PLFLT PRNT_scale; PLINT PRNT_width; PLINT PRNT_height; char FT_smooth_text; // // WIN32 API variables // COLORREF colour; // Current Colour COLORREF oldcolour; // Used for high-speed background erasing MSG msg; // A Win32 message structure. WNDCLASSEX wndclass; // An extended window class structure. HWND hwnd; // Handle for the main window. HPEN pen; // Windows pen used for drawing HDC hdc; // Driver Context HDC hdc2; // Driver Context II - used for Blitting HDC SCRN_hdc; // The screen's context HDC PRNT_hdc; // used for printing PAINTSTRUCT ps; // used to paint the client area of a window owned by that application RECT rect; // defines the coordinates of the upper-left and lower-right corners of a rectangle RECT oldrect; // used for re-sizing comparisons RECT paintrect; // used for painting etc... HBRUSH fillbrush; // brush used for fills HCURSOR cursor; // Current windows cursor for this window HBITMAP bitmap; // Bitmap of current display; used for fast redraws via blitting HGDIOBJ oldobject; // Used for tracking objects probably not really needed but HMENU PopupMenu; PLINT draw_mode; char truecolour; // Flag to indicate 24 bit mode char waiting; // Flag to indicate drawing is done, and it is waiting; // we only do a windows redraw if plplot is plotting char enterresize; // Used to keep track of reszing messages from windows char already_erased; // Used to track first and only first backgroudn erases struct wingcc_Dev *push; }; #endif typedef struct { BITMAPINFO bi; RGBQUAD *lpbitmap; bool has_data; } tv_buf_t; class GDLWINStream : public GDLGStream { private: //Atom wm_protocols; //Atom wm_delete_window; HWND refocus; PLStream* pls; plstream *plst; tv_buf_t tv_buf; int _mode; PLGraphicsIn *_gin; POINT GinPoint; HCURSOR CrosshairCursor; bool rbutton, xbutton, mbutton, buttonpressed; public: std::map msghooks; GDLWINStream(int nx, int ny) : #ifdef USE_WINGDI_NOT_WINGCC GDLGStream(nx, ny, "wingdi") #else GDLGStream(nx, ny, "wingcc") #endif { pls = 0; // get the command interpreter window's handle // plsetopt("drvopt","nofocus"); // avoid stealing focus on window creation // plsetopt("drvopt","text"); // use freetype fonts refocus = GetForegroundWindow(); } ~GDLWINStream(); void Init(); void EventHandler(); // static int GetImageErrorHandler(Display *display, XErrorEvent *error); void GetGeometry(long& xSize, long& ySize); bool GetGin(PLGraphicsIn *gin, int mode); unsigned long GetWindowDepth(); DLong GetVisualDepth(); // DString GetVisualName(); bool UnsetFocus(); // bool SetBackingStore(int value); // bool SetGraphicsFunction(long value ); bool GetWindowPosition(long& xpos, long& ypos); void Clear(); void Raise(); void Lower(); void Iconic(); void DeIconic(); void Flush(); void CheckValid(); void Update(){ this->eop();} bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan); // bool SetGraphicsFunction(long value ); virtual bool HasCrossHair() { return true; } void SetWindowTitle(char* buf); HWND GetHwnd(void); HDC GetHdc(void); void Load_gin(HWND window); void RedrawTV(); void CALLBACK GinCallback(UINT message, WPARAM wParam, LPARAM lParam); }; typedef std::map::iterator msghookiter; #endif gdl-0.9.9/src/gdlwxstream.cpp000066400000000000000000000372631340051421000161340ustar00rootroot00000000000000/*************************************************************************** gdlwxstream.cpp - adapted from plplot wxWidgets driver documentation ------------------- begin : Wed Oct 16 2013 copyright : (C) 2013 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifdef HAVE_LIBWXWIDGETS #include "gdlwxstream.hpp" GDLWXStream::GDLWXStream( int width, int height ) : GDLGStream( width, height, "wxwidgets") , m_dc(NULL) , m_bitmap(NULL) , m_width(width), m_height(height) , gdlWindow(NULL) { m_dc = new wxMemoryDC(); m_bitmap = new wxBitmap( width, height, 32); m_dc->SelectObject( *m_bitmap); if( !m_dc->IsOk()) { m_dc->SelectObject( wxNullBitmap ); delete m_bitmap; delete m_dc; throw GDLException("GDLWXStream: Failed to create DC."); } #if ( (PLPLOT_VERSION_MAJOR < 6) && (PLPLOT_VERSION_MINOR < 10) ) // if ( GetEnvString("GDL_WX_BACKEND") == "2" ) setopt("drvopt", "hrshsym=1,backend=2,text=0" ); // else if ( GetEnvString("GDL_WX_BACKEND") == "1") setopt("drvopt", "hrshsym=1,backend=1,text=0" ); // else setopt("drvopt", "hrshsym=1,backend=0,text=0" ); // do not use freetype. Backend=0 enable compatibility (sort of) with X11 behaviour in plots. To be augmented one day... #else else setopt("drvopt", "hrshsym=1,text=0" ); // #endif PLFLT XDPI=(*static_cast( SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("X_PX_CM"))))[0]*2.5; PLFLT YDPI=(*static_cast( SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("Y_PX_CM"))))[0]*2.5; spage( XDPI, YDPI, width, height, 0, 0 ); //width and height have importance. 90 dpi is what is in the driver code. this->plstream::init(); plstream::cmd(PLESC_DEVINIT, (void*)m_dc ); //Apparently no effect on fonts!!! //#if ( (PLPLOT_VERSION_MAJOR > 4) && (PLPLOT_VERSION_MINOR > 10) ) // bool fixed=true; // cerr << "fixed\n"; // plstream::cmd(PLESC_FIXASPECT, (void*)&fixed ); //#endif // plstream::set_stream(); // no pause on win destruction spause( false); // extended fonts fontld( 1); // we want color scolor( 1); PLINT r[ctSize], g[ctSize], b[ctSize]; GDLCT* myCT=GraphicsDevice::GetGUIDevice( )->GetCT(); myCT->Get( r, g, b); SetColorMap0( r, g, b, ctSize); //set colormap 0 to 256 values // need to be called initially. permit to fix things ssub(1,1); adv(0); // load font font( 1); vpor(0,1,0,1); wind(0,1,0,1); DefaultCharSize(); // PLFLT defhmm, scalhmm; // plgchr(&defhmm, &scalhmm); // height of a letter in millimetres // RenewPlplotDefaultCharsize(defhmm /1.5 ); } GDLWXStream::~GDLWXStream() { m_dc->SelectObject( wxNullBitmap ); delete m_bitmap; delete m_dc; } void GDLWXStream::SetGDLDrawPanel(GDLDrawPanel* w) { gdlWindow = w; } void GDLWXStream::Update() { if( this->valid && gdlWindow != NULL) gdlWindow->Update(); } ////should be used when one does not recreate a wxstream each time size changes... //void GDLWXStream::SetSize( int width, int height ) //{ // if ( width<1 || height <1) return; // m_dc->SelectObject( wxNullBitmap ); // delete m_bitmap; // m_bitmap = new wxBitmap( width, height, 32 ); // m_dc->SelectObject( *m_bitmap); // if( !m_dc->IsOk()) // { // m_dc->SelectObject( wxNullBitmap ); // delete m_bitmap; // delete m_dc; // throw GDLException("GDLWXStream: Failed to resize DC."); // } // // wxSize screenPPM = m_dc->GetPPI(); //integer. Loss of precision if converting to PPM using wxSize operators. // wxSize size = wxSize( width, height); // // plstream::cmd(PLESC_RESIZE, (void*)&size ); // m_width = width; // m_height = height; //} void GDLWXStream::WarpPointer(DLong x, DLong y) { int xx=x; int yy=y; wxPanel *p = static_cast(gdlWindow); p->WarpPointer(xx,gdlWindow->GetSize().y-yy); } void GDLWXStream::Init() { this->plstream::init(); // set_stream(); // private // test : gdlFrame->Show(); } void GDLWXStream::RenewPlot() { plstream::cmd( PLESC_CLEAR, NULL ); replot(); } void GDLWXStream::GetGeometry( long& xSize, long& ySize) { // plplot does not return the real size xSize = m_width; ySize = m_height; if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"GDLWXStream::GetGeometry(%ld %ld)\n", xSize, ySize); } unsigned long GDLWXStream::GetWindowDepth() { return wxDisplayDepth(); } void GDLWXStream::Clear() { PLINT red,green,blue; DByte r,g,b; PLINT red0,green0,blue0; GraphicsDevice::GetCT()->Get(0,r,g,b);red=r;green=g;blue=b; red0=GraphicsDevice::GetDevice()->BackgroundR(); green0=GraphicsDevice::GetDevice()->BackgroundG(); blue0=GraphicsDevice::GetDevice()->BackgroundB(); plstream::scolbg(red0,green0,blue0); //overwrites col[0] ::c_plbop(); // ::c_plclear(); plstream::scolbg(red,green,blue); //resets col[0] } //FALSE: REPLACE With Clear(DLong chan) as in X //TBD void GDLWXStream::Clear(DLong bColor) { Clear(); } bool GDLWXStream::PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong trueColorOrder, DLong chan) { // plstream::cmd( PLESC_FLUSH, NULL ); // Update(); DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); wxMemoryDC temp_dc; temp_dc.SelectObject(*m_bitmap); wxImage image=m_bitmap->ConvertToImage(); unsigned char* mem=image.GetData(); PLINT xoff = (PLINT) pos[0]; //(pls->wpxoff / 32767 * dev->width + 1); PLINT yoff = (PLINT) pos[2]; //(pls->wpyoff / 24575 * dev->height + 1); PLINT xsize = m_width; PLINT ysize = m_height; PLINT kxLimit = xsize - xoff; PLINT kyLimit = ysize - yoff; if (nx < kxLimit) kxLimit = nx; if (ny < kyLimit) kyLimit = ny; if ( nx > 0 && ny > 0 ) { SizeT p = (ysize - yoff - 1)*3*xsize; for ( int iy = 0; iy < kyLimit; ++iy ) { SizeT rowStart = p; p += xoff*3; for ( int ix = 0; ix < kxLimit; ++ix ) { if ( trueColorOrder == 0 && chan == 0 ) { if (decomposed == 1){ mem[p++] = idata[iy * nx + ix]; mem[p++] = idata[iy * nx + ix]; mem[p++] = idata[iy * nx + ix]; } else { mem[p++] = pls->cmap0[idata[iy * nx + ix]].r; mem[p++] = pls->cmap0[idata[iy * nx + ix]].g; mem[p++] = pls->cmap0[idata[iy * nx + ix]].b; } } else { if ( chan == 0 ) { if ( trueColorOrder == 1 ) { mem[p++] = idata[3 * (iy * nx + ix) + 0]; mem[p++] = idata[3 * (iy * nx + ix) + 1]; mem[p++] = idata[3 * (iy * nx + ix) + 2]; } else if ( trueColorOrder == 2 ) { mem[p++] = idata[nx * (iy * 3 + 0) + ix]; mem[p++] = idata[nx * (iy * 3 + 1) + ix]; mem[p++] = idata[nx * (iy * 3 + 2) + ix]; } else if ( trueColorOrder == 3 ) { mem[p++] = idata[nx * (0 * ny + iy) + ix]; mem[p++] = idata[nx * (1 * ny + iy) + ix]; mem[p++] = idata[nx * (2 * ny + iy) + ix]; } } else { //1 byte bitmap passed. if ( chan == 1 ) { mem[p++] = idata[1 * (iy * nx + ix) + 0]; p += 2; } else if ( chan == 2 ) { p ++; mem[p++] = idata[1 * (iy * nx + ix) + 0]; p ++; } else if ( chan == 3 ) { p += 2; mem[p++] = idata[1 * (iy * nx + ix) + 0]; } } } } p = rowStart - (xsize*3); } } m_dc->DrawBitmap(image,0,0); image.Destroy(); temp_dc.SelectObject( wxNullBitmap); *m_bitmap = m_dc->GetAsBitmap(); Update(); return true; } bool GDLWXStream::SetGraphicsFunction( long value) { //use switch since passing an enum to a function is problematic for some compilers, grrrrrrrrrrrr! value=(value<0)?0:(value>15)?15:value; switch ( value ) { case 0: //wxCLEAR: m_dc->SetLogicalFunction( wxCLEAR); break; case 1: //wxAND: m_dc->SetLogicalFunction( wxAND); break; case 2: //wxAND_REVERSE: m_dc->SetLogicalFunction( wxAND_REVERSE); break; default: case 3: //wxCOPY: m_dc->SetLogicalFunction( wxCOPY); break; case 4: //wxAND_INVERT: m_dc->SetLogicalFunction( wxAND_INVERT); break; case 5: //wxNO_OP: m_dc->SetLogicalFunction( wxNO_OP); break; case 6: //wxXOR: m_dc->SetLogicalFunction( wxXOR); break; case 7: //wxNOR: m_dc->SetLogicalFunction( wxNOR); break; case 8: //wxEQUIV: m_dc->SetLogicalFunction( wxEQUIV); break; case 9: //wxINVERT: m_dc->SetLogicalFunction( wxINVERT); break; case 10: //wxOR_REVERSE: m_dc->SetLogicalFunction( wxOR_REVERSE); break; case 11: //wxSRC_INVERT: m_dc->SetLogicalFunction( wxSRC_INVERT); break; case 12: //wxOR_INVERT: m_dc->SetLogicalFunction( wxOR_INVERT); break; case 13: //wxNAND: m_dc->SetLogicalFunction( wxNAND); break; case 14: //wxSET: m_dc->SetLogicalFunction( wxSET); break; } return true; } bool GDLWXStream::GetWindowPosition(long& xpos, long& ypos ) { cerr<<"Get Window Position not ready for wxWindow draw panel, please contribute."<GetPPI(); resx = reso.x/2.54; resy = reso.y/2.54; return true; } bool GDLWXStream::CursorStandard(int cursorNumber) { cerr<<"Cursor Setting not ready for wxWindow draw panel, please contribute."<GetFontnames(pattern) == NULL) return -1; if (pattern.length()==0) return 0; return this->GetFontnames(pattern)->N_Elements(); } void GDLWXStream::SetCurrentFont(std::string fontname){ if (fontname.size() > 0) { wxFont font=wxFont(wxString(fontname.c_str( ), wxConvLibc)); if (!font.IsSameAs(wxNullFont)) m_dc->SetFont(font); } } DString GDLWXStream::GetVisualName() { static const char* visual="TrueColor"; return visual; } DByteGDL* GDLWXStream::GetBitmapData() { // plstream::cmd( PLESC_FLUSH, NULL ); wxMemoryDC temp_dc; temp_dc.SelectObject(*m_bitmap); wxImage image=m_bitmap->ConvertToImage(); unsigned char* mem=image.GetData(); if ( mem == NULL ) return NULL; unsigned int nx = m_bitmap->GetWidth(); unsigned int ny = m_bitmap->GetHeight(); SizeT datadims[3]; datadims[0] = nx; datadims[1] = ny; datadims[2] = 3; dimension datadim(datadims, (SizeT) 3); DByteGDL *bitmap = new DByteGDL( datadim, BaseGDL::NOZERO); //PADDING is 3BPP -- we revert Y to respect IDL default SizeT kpad = 0; for ( SizeT iy =0; iy < ny ; ++iy ) { for ( SizeT ix = 0; ix < nx; ++ix ) { (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 0] = mem[kpad++]; (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 1] = mem[kpad++]; (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 2] = mem[kpad++]; } } image.Destroy(); return bitmap; } void GDLWXStream::Raise() { static_cast(this->GetGDLDrawPanel()->GetGrandParent())->Raise(); } void GDLWXStream::Lower() { static_cast(this->GetGDLDrawPanel()->GetGrandParent())->Lower(); } void GDLWXStream::Iconic() { static_cast(this->GetGDLDrawPanel()->GetGrandParent())->Iconize(true); } void GDLWXStream::DeIconic() { static_cast(this->GetGDLDrawPanel()->GetGrandParent())->Iconize(false); } //bool GDLWXStream::UnsetFocus(){ //UnsetFocus is dangerous: it prevents using wxEvents correctly. // return static_cast(this->GetGDLDrawPanel()->GetGrandParent())->Disable(); //} bool GDLWXStream::GetGin(PLGraphicsIn *gin, int mode) { enum CursorOpt { NOWAIT = 0, WAIT, //1 CHANGE, //2 DOWN, //3 UP //4 }; wxMouseState mouse=wxGetMouseState(); wxPoint mousePoint = wxGetMousePosition (); unsigned int state=0, ostate=0; //start with null state unsigned int button=0; //gets the button state 1,2,3 int x,y; x = mouse.GetX(); y = mouse.GetY(); gin->pX = x; gin->pY = y; //state is like the button state value, combination of all buttonstate masks of X11. It is merely to know what buttons are down if (mouse.LeftIsDown()) {button = 1; ostate |= 1;} if (mouse.MiddleIsDown()){button = 2; ostate |= 2;} if (mouse.RightIsDown()) {button = 3; ostate |= 4;} #if wxCHECK_VERSION(3,0,0) if (mouse.Aux1IsDown()) {button = 4; ostate |= 8;} if (mouse.Aux2IsDown()) {button = 5; ostate |= 16;} #endif //return if NOWAIT or WAIT and Button pressed if ((mode == NOWAIT) || (mode == WAIT && button > 0)) { state=ostate; goto end; //else wait below for a down... } while (1) { //poll repeatedly -- waiting for event would be better but needs start locally the wx eventloop. if (gdlWindow->GetScreenRect().Contains(wxGetMousePosition())) { //if cursor is in the window... mouse=wxGetMouseState(); x = mouse.GetX(); y = mouse.GetY(); if (mouse.LeftIsDown()) {button = 1; state |= 1;} if (mouse.MiddleIsDown()) {button = 2; state |= 2;} if (mouse.RightIsDown()) {button = 3; state |= 4;} #if wxCHECK_VERSION(3,0,0) if (mouse.Aux1IsDown()) {button = 4; state |= 8;} if (mouse.Aux2IsDown()) {button = 5; state |= 16;} #endif int change=(state^ostate); //is it a button up or down? int diff=(state&change)-(ostate&change); bool ButtonRelease=( diff < 0 ); //from 1 to 0: negative if (change > 0) { //press or release gin->pX = x; gin->pY = y; if (mode==CHANGE) goto end; if (mode==UP && ButtonRelease) goto end; if (!ButtonRelease && (mode==WAIT || mode==DOWN) ) goto end; } if ( (pow((float)x-gin->pX,2)+pow((float)y-gin->pY,2) > 0) && mode==CHANGE) { gin->pX = x; gin->pY = y; goto end; } ostate=state; //update state state=0; gin->pX = x; //update new position gin->pY = y; } //We must get out of this loop sometime! wxMilliSleep( 50 ); // Sleep a bit to prevent CPU overuse if ( sigControlC ) return false; } end: //convert screen to client coord gdlWindow->ScreenToClient(&x,&y); //now in coordinates gin->pX = x; gin->pY = gdlWindow->GetSize().y - y; gin->dX = (PLFLT) gin->pX / ( gdlWindow->GetSize().x - 1); gin->dY = (PLFLT) gin->pY / ( gdlWindow->GetSize().y - 1); gin->string[0] = '\0'; gin->keysym = 0x20; gin->button = button; return true; } #endif gdl-0.9.9/src/gdlwxstream.hpp000066400000000000000000000067771340051421000161470ustar00rootroot00000000000000/*************************************************************************** gdlwxstream.hpp - adapted from plplot wxWidgets driver documentation ------------------- begin : Wed Oct 16 2013 copyright : (C) 2013 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //#ifdef FOR_IMPORT #ifndef GDLWXSTREAM_HPP_ #define GDLWXSTREAM_HPP_ #ifdef HAVE_LIBWXWIDGETS #include "gdlgstream.hpp" #include "gdlwidget.hpp" #include #include //#include //#include class GDLDrawPanel; class GDLWXStream: public GDLGStream { private: wxMemoryDC* m_dc; wxBitmap* m_bitmap; // wxDC* m_dc; //!< Pointer to wxDC to plot into. int m_width; //!< Width of dc/plot area. int m_height; //!< Height of dc/plot area. GDLDrawPanel* gdlWindow; // for Update() public: GDLWXStream( int width, int height ); //!< Constructor. ~GDLWXStream(); //!< Constructor. wxMemoryDC* GetDC() const { return m_dc;} // void set_stream(); //!< Calls some code before every PLplot command. // void SetSize( int width, int height ); //!< Set new size of plot area. void RenewPlot(); //!< Redo plot. void Update(); void SetGDLDrawPanel(GDLDrawPanel* w); GDLDrawPanel* GetGDLDrawPanel(){return gdlWindow;} void Init(); //void EventHandler(); // //static int GetImageErrorHandler(Display *display, XErrorEvent *error); // void GetGeometry( long& xSize, long& ySize); unsigned long GetWindowDepth() ; // bool UnsetFocus(); UnsetFocus is dangerous: it prevents using wxEvents correctly. bool SetBackingStore(int value){return true;} void Clear(); void Clear( DLong bColor); void Raise(); void Lower(); void Iconic(); void DeIconic(); bool GetGin(PLGraphicsIn *gin, int mode); //bool GetExtendedGin(PLGraphicsIn *gin, int mode); void WarpPointer(DLong x, DLong y); void Flush(){ }// plstream::cmd( PLESC_FLUSH, NULL );} //void SetDoubleBuffering(); //void UnSetDoubleBuffering(); bool HasDoubleBuffering(){return true;} bool HasSafeDoubleBuffering(){return ( m_dc->GetLogicalFunction() == wxCOPY);}; bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong trueColorOrder, DLong channel); virtual bool HasCrossHair() {return true;} bool SetGraphicsFunction( long value); bool GetWindowPosition(long& xpos, long& ypos ); bool CursorStandard(int cursorNumber); DLong GetVisualDepth(); BaseGDL* GetFontnames(DString pattern); DLong GetFontnum(DString pattern); void SetCurrentFont(std::string fontname); DString GetVisualName(); bool GetScreenResolution(double& resx, double& resy); DByteGDL* GetBitmapData(); }; #endif #endif gdl-0.9.9/src/gdlxstream.cpp000066400000000000000000000730421340051421000157400ustar00rootroot00000000000000/* ************************************************************************* gdlxstream.cpp - graphic stream x windows ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "graphicsdevice.hpp" #include "gdlxstream.hpp" #include "devicex.hpp" #ifndef HAVE_X #else using namespace std; void GDLXStream::Init() { // plstream::init() calls exit() if it cannot establish a connection with X-server bool okToRevertToTerminal=false; int revert_to; { Display* display = XOpenDisplay(NULL); if (display == NULL) { display = XOpenDisplay(":0");//IDL also opens :0 when DISPLAY is not set. if (display == NULL) { valid = false; ThrowGDLException("Cannot connect to X server"); } } XGetInputFocus(display, &term_window, &revert_to); //avoid doing impossible things if term_window is *not* a bona fide window. if (term_window == PointerRoot || term_window == None) term_window=0; XCloseDisplay(display); } this->plstream::init(); XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; wm_protocols = XInternAtom(xwd->display, "WM_PROTOCOLS", false); wm_delete_window = XInternAtom(xwd->display, "WM_DELETE_WINDOW", false); XSetWMProtocols(xwd->display, dev->window, &wm_delete_window, 1); //give back focus to caller -- hopefully the terminal. XWindowAttributes from_attr; if(term_window) { XGetWindowAttributes(xwd->display,term_window,&from_attr); if(from_attr.map_state==IsViewable) okToRevertToTerminal=true; } if ( okToRevertToTerminal ) XSetInputFocus(xwd->display,term_window,RevertToParent,CurrentTime); else UnsetFocus(); //desperate method, since it prevents iconifying etc... // XFlush(xwd->display); GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); //current cursor: CursorStandard(actDevice->getCursorId()); //current graphics function SetGraphicsFunction(actDevice->GetGraphicsFunction()); //BackingStore SetBackingStore(actDevice->getBackingStore()); } void GDLXStream::EventHandler() { if (!valid) return; XwDev *dev = (XwDev *) pls->dev; if (dev == NULL) { cerr << "X window invalid." << endl; valid = false; return; } XwDisplay *xwd = (XwDisplay *) dev->xwd; if (xwd == NULL) { cerr << "X window not set." << endl; valid = false; return; } XEvent event; if (XCheckTypedWindowEvent(xwd->display, dev->window, ClientMessage, &event)) { if (event.xclient.message_type == wm_protocols && event.xclient.data.l[0] == wm_delete_window) { valid = false; GraphicsDevice::GetDevice()->TidyWindowsList(); //necessary since we removed TidyWindowList() from GraphicsMultiDevice::EventHandler() return; // no more event handling } else XPutBackEvent(xwd->display, &event); } // plplot event handler plstream::cmd(PLESC_EH, NULL); } bool GDLXStream::SetGraphicsFunction( long value) { XGCValues gcValues; gcValues.function = (value<0)?0:(value>15)?15:value; XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; return XChangeGC( xwd->display, dev->gc, GCFunction, &gcValues ); } bool GDLXStream::GetWindowPosition(long& xpos, long& ypos ) { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XWindowAttributes wa; int addx, addy; Window child; XGetWindowAttributes( xwd->display, dev->window, &wa ); if ( XTranslateCoordinates( xwd->display, dev->window, wa.root, 0, 0, &addx, &addy, &child ) ) { xpos = addx - wa.x; ypos = DisplayHeight( xwd->display, DefaultScreen( xwd->display ) ) - wa.height + 1 - (addy - wa.y) + 1; return true; } else return false; } void GDLXStream::GetGeometry(long& xSize, long& ySize) { //for some reason, with the x11 driver, this is better than plstream::gpage to get actual sizes. XwDev *dev = (XwDev *) pls->dev; xSize=dev->width; ySize=dev->height; } bool GDLXStream::CursorStandard(int cursorNumber) { int num=max(0,min(XC_num_glyphs-1,cursorNumber)); XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XDefineCursor(xwd->display,dev->window,XCreateFontCursor(xwd->display,num)); return true; } // plplot 5.3 does not provide the clear function for c++ void GDLXStream::Clear() { Clear(-1); // // this mimics better the *DL behaviour but plbop create a new page, etc.. // //plclear clears only the current subpage. But it clears it. One has // //just to set the number of subpages to 1 // PLINT red, green, blue; // DByte r, g, b; // PLINT red0, green0, blue0; // // GraphicsDevice::GetCT( )->Get( 0, r, g, b ); // red = r; // green = g; // blue = b; ////we get around the index 0=background color "feature" of plplot. GDL uses a separate backgroud color. // red0 = GraphicsDevice::GetDevice( )->BackgroundR( ); // green0 = GraphicsDevice::GetDevice( )->BackgroundG( ); // blue0 = GraphicsDevice::GetDevice( )->BackgroundB( ); // plstream::scolbg( red0, green0, blue0 ); //overwrites col[0] // ::c_plbop( ); //// ::c_plclear( ); // plstream::scolbg( red, green, blue ); //resets col[0] } void GDLXStream::Clear(DLong chan) { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; DByte r = (GraphicsDevice::GetDevice()->BackgroundR()); DByte g = (GraphicsDevice::GetDevice()->BackgroundG()); DByte b = (GraphicsDevice::GetDevice()->BackgroundB()); unsigned long curcolor= ((unsigned long)(r) << (ffs(xwd->visual->red_mask)-1) ) + ((unsigned long)(g) << (ffs(xwd->visual->green_mask)-1) ) + ((unsigned long)(b) << (ffs(xwd->visual->blue_mask)-1) ); XSetForeground( xwd->display, dev->gc, curcolor); // myColor.pixel ); switch(chan){ case 0: XSetPlaneMask(xwd->display,dev->gc,xwd->visual->red_mask); break; case 1: XSetPlaneMask(xwd->display,dev->gc,xwd->visual->green_mask); break; case 2: XSetPlaneMask(xwd->display,dev->gc,xwd->visual->blue_mask); break; } if (dev->write_to_pixmap==1) XFillRectangle(xwd->display, dev->pixmap, dev->gc, 0, 0, dev->width, dev->height); if (dev->write_to_window) XFillRectangle(xwd->display, dev->window, dev->gc, 0, 0, dev->width, dev->height); XSetForeground(xwd->display,dev->gc,dev->curcolor.pixel); XSetPlaneMask(xwd->display,dev->gc,AllPlanes); } unsigned long GDLXStream::GetWindowDepth() { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; return xwd->depth; } DLong GDLXStream::GetVisualDepth() { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XWindowAttributes wa; if(XGetWindowAttributes( xwd->display, dev->window, &wa )) return (long)wa.depth; else return -1; } BaseGDL* GDLXStream::GetFontnames(DString pattern) { if (pattern.length()<=0) return NULL; XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; int actual_count_return; char **list= XListFonts(xwd->display, pattern.c_str(), 30000, &actual_count_return); if (!actual_count_return) return NULL; DStringGDL* myList=new DStringGDL(dimension(actual_count_return)); for (int i=0; i< actual_count_return; ++i) (*myList)[i].assign(list[i]); XFreeFontNames(list); return myList; } DLong GDLXStream::GetFontnum(DString pattern){ // never occurs ... if (pattern.length()<0) return -1; if (this->GetFontnames(pattern) == NULL) return -1; if (pattern.length()==0) return 0; return this->GetFontnames(pattern)->N_Elements(); } DString GDLXStream::GetVisualName() { static const char* visual_classes_names[] = { "StaticGray" , "GrayScale" , "StaticColor" , "PseudoColor" , "TrueColor" , "DirectColor" }; XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XWindowAttributes wa; if(XGetWindowAttributes( xwd->display, dev->window, &wa )) { /* need some works to go to Visual Name */ int junk; XVisualInfo vistemplate, *vinfo; vistemplate.visualid = XVisualIDFromVisual(wa.visual); vinfo = XGetVisualInfo(xwd->display, VisualIDMask, &vistemplate, &junk); if (vinfo->c_class < 5){ std::string ret; ret=std::string(visual_classes_names[vinfo->c_class]); return ret; } else return ""; } else return ""; } bool GDLXStream::UnsetFocus() { XwDev *dev = (XwDev *) pls->dev; if( dev == NULL) return false; XwDisplay *xwd = (XwDisplay *) dev->xwd; if(term_window) { XWindowAttributes from_attr; XGetWindowAttributes(xwd->display,term_window,&from_attr); if(from_attr.map_state==IsViewable) XSetInputFocus(xwd->display,term_window,RevertToParent,CurrentTime); } else { XSetInputFocus(xwd->display, DefaultRootWindow(xwd->display),RevertToParent,CurrentTime); } return true; } // This helps cursor window leave focus. // bool GDLXStream::setFocus(bool value=true) { XwDev *dev = (XwDev *) pls->dev; if( dev == NULL) return false; XwDisplay *xwd = (XwDisplay *) dev->xwd; XWMHints gestw; gestw.input = value; gestw.flags = InputHint; XSetWMHints(xwd->display, dev->window, &gestw); return true; } bool GDLXStream::SetBackingStore(int value) { XwDev *dev = (XwDev *) pls->dev; if( dev == NULL) return false; XwDisplay *xwd = (XwDisplay *) dev->xwd; XSetWindowAttributes attr; if (value > 0) { attr.backing_store = Always; } else { attr.backing_store = NotUseful; } XChangeWindowAttributes(xwd->display, dev->window,CWBackingStore,&attr); return true; } void GDLXStream::Raise() { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XRaiseWindow(dev->xwd->display, dev->window); } void GDLXStream::Lower() { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XLowerWindow(dev->xwd->display, dev->window); } void GDLXStream::Iconic() { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XIconifyWindow(xwd->display, dev->window, xwd->screen); // really hides the window XWithdrawWindow(xwd->display, dev->window, xwd->screen); } void GDLXStream::DeIconic() { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XMapWindow(dev->xwd->display, dev->window); } void GDLXStream::UnMapWindow() { //Used for /PIXMAP windows: 1) insure write_to_pixmap and not write_to_window, and 2) hide the window. XwDev *dev = (XwDev *) pls->dev; dev->write_to_pixmap=1; dev->write_to_window=0; XwDisplay *xwd = (XwDisplay *) dev->xwd; XWithdrawWindow(xwd->display, dev->window, xwd->screen); usedAsPixmap=true; } void GDLXStream::Flush() { // XwDev *dev = (XwDev *) pls->dev; // XwDisplay *xwd = (XwDisplay *) dev->xwd; // XFlush(xwd->display); } void GDLXStream::Update() { XFlush(static_cast(static_cast(pls->dev)->xwd)->display); } void GDLXStream::WarpPointer(DLong x, DLong y) { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XWarpPointer(xwd->display, None, dev->window, 0, 0, 0, 0, x, dev->height - y); } void GDLXStream::SetDoubleBuffering() { XwDev *dev = (XwDev *) pls->dev; dev->write_to_window = 0; pls->db = 1; } void GDLXStream::UnSetDoubleBuffering() { XwDev *dev = (XwDev *) pls->dev; dev->write_to_window = 1; pls->db = 0; } //modified version. Will not tell double buffering is available if current graphic function is not pure "copy". bool GDLXStream::HasSafeDoubleBuffering() { XwDev *dev = (XwDev *) pls->dev; if( dev == NULL || dev->xwd == NULL) return false; XwDisplay *xwd = (XwDisplay *) dev->xwd; XGCValues gcValues; XGetGCValues(xwd->display, dev->gc, GCFunction, &gcValues); if (gcValues.function == GXcopy ) return true; else return false; } //simple GetGin that reproduces IDL's own. //However, trapping controlC should be done inside, to clean properly. //Below, a more complicated version that adds other functionalities, and ^C trapping, but //grabs the keyboard, which is not recommended. bool GDLXStream::GetGin(PLGraphicsIn *gin, int mode) { enum CursorOpt { NOWAIT = 0, WAIT, //1 CHANGE, //2 DOWN, //3 UP //4 }; XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; Window root, child; int root_x, root_y, oldx, oldy; unsigned int ostate; XQueryPointer(xwd->display, dev->window, &root, &child, &root_x, &root_y, &oldx, &oldy, &ostate); gin->pX = oldx; gin->pY = dev->height - oldy; gin->state = ostate; gin->dX = (PLFLT) gin->pX / (dev->width - 1); gin->dY = (PLFLT) gin->pY / (dev->height - 1); gin->string[0] = '\0'; gin->keysym = 0x20; gin->button = 0; if (ostate & Button1Mask) gin->button = 1; if (ostate & Button2Mask) gin->button = 2; if (ostate & Button3Mask) gin->button = 3; if (ostate & Button4Mask) gin->button = 4; if (ostate & Button5Mask) gin->button = 5; //IDL does not support buttons 4-5 but we may? //return if NOWAIT setFocus(false); // first try to get out of focus. if (mode == NOWAIT) return true; unsigned long event_mask = (PointerMotionMask|ButtonMotionMask); switch (mode) { case WAIT: if (gin->button > 0) return true; //else wait below for a down... case DOWN: event_mask |= ButtonPressMask; break; case UP: case CHANGE: event_mask |= (ButtonPressMask | ButtonReleaseMask); } XEvent event; XRaiseWindow(xwd->display, dev->window); XSelectInput(xwd->display, dev->window, event_mask); XSync(xwd->display, true); //useful? while (1) { if ( sigControlC ) return false; XWindowEvent(xwd->display, dev->window, event_mask, &event); switch (event.type) { int nchars; KeySym mykey; case ButtonRelease: gin->pX = event.xbutton.x; gin->pY = event.xbutton.y; gin->state = event.xbutton.state; gin->button = event.xbutton.button; gin->string[0] = '\0'; gin->keysym = 0x20; if (mode==UP || mode==CHANGE) goto end; break; case ButtonPress: gin->pX = event.xbutton.x; gin->pY = event.xbutton.y; gin->state = event.xbutton.state; gin->button = event.xbutton.button; gin->string[0] = '\0'; gin->keysym = 0x20; if (mode==WAIT || mode==DOWN || mode==CHANGE) goto end; break; case MotionNotify: if (mode==CHANGE) { gin->pX = event.xmotion.x; gin->pY = event.xmotion.y; gin->state = event.xmotion.state; gin->string[0] = '\0'; gin->keysym = 0x20; goto end; } break; default: break; } } end: gin->pY = dev->height - gin->pY; gin->dX = (PLFLT) gin->pX / (dev->width - 1); gin->dY = (PLFLT) gin->pY / (dev->height - 1); return true; } bool GDLXStream::GetExtendedGin(PLGraphicsIn *gin, int mode) { enum CursorOpt { NOWAIT = 0, WAIT, //1 CHANGE, //2 DOWN, //3 UP //4 }; bool status = true; bool warp = false; int dx, dy; XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; Window root, child; int root_x, root_y, oldx, oldy; unsigned int ostate; XQueryPointer(xwd->display, dev->window, &root, &child, &root_x, &root_y, &oldx, &oldy, &ostate); gin->pX = oldx; gin->pY = dev->height - oldy; gin->state = ostate; gin->dX = (PLFLT) gin->pX / (dev->width - 1); gin->dY = (PLFLT) gin->pY / (dev->height - 1); bool alreadyInside=(gin->dX >=0.0 && gin->dX <1.0 && gin->dY >=0.0 && gin->dY <1.0); gin->string[0] = '\0'; gin->keysym = 0x20; gin->button = 0; if (ostate & Button1Mask) gin->button = 1; if (ostate & Button2Mask) gin->button = 2; if (ostate & Button3Mask) gin->button = 3; if (ostate & Button4Mask) gin->button = 4; if (ostate & Button5Mask) gin->button = 5; //IDL does not support buttons 4-5 but we may? //return if NOWAIT if (mode == NOWAIT) return true; int x, x1, xmin = 0, xmax = (int) dev->width - 1; int y, y1, ymin = 0, ymax = (int) dev->height - 1; // If we want to trap keyboard events we need to set focus (complicated) OR grab keyboard: bool kbgrabbed= (XGrabKeyboard(xwd->display, dev->window, True, GrabModeAsync, GrabModeAsync, CurrentTime)==GrabSuccess); unsigned long event_mask = (EnterWindowMask| LeaveWindowMask | KeyPressMask | KeyReleaseMask | PointerMotionMask); switch (mode) { case WAIT: if (gin->button > 0) return true; //else wait below for a down... case DOWN: event_mask |= ButtonPressMask; break; case UP: case CHANGE: event_mask |= ButtonPressMask | ButtonReleaseMask; break; } bool grabbed = false; unsigned long grab_mask = (EnterWindowMask|LeaveWindowMask|PointerMotionMask|ButtonPressMask | ButtonReleaseMask); if (alreadyInside) grabbed=(XGrabPointer(xwd->display, dev->window, False, grab_mask,GrabModeAsync,GrabModeAsync,dev->window,None,CurrentTime)==GrabSuccess); XEvent event; //we do our own event handling and furthermore we need to grab the pointer since plplot owns this window, too. int first=0; XSelectInput(xwd->display, dev->window, event_mask); XRaiseWindow(xwd->display, dev->window); XSync(xwd->display, true); while (1) { XWindowEvent(xwd->display, dev->window, event_mask, &event); switch (event.type) { int nchars; KeySym mykey; case EnterNotify: if(!grabbed) grabbed=(XGrabPointer(xwd->display, dev->window, False, grab_mask,GrabModeAsync,GrabModeAsync,None,None,CurrentTime)==GrabSuccess); break; case LeaveNotify: XUngrabPointer(xwd->display,CurrentTime); grabbed = false; break; case ButtonRelease: gin->pX = event.xbutton.x; gin->pY = event.xbutton.y; gin->state = event.xbutton.state; gin->button = event.xbutton.button; gin->string[0] = '\0'; gin->keysym = 0x20; if (mode==UP || mode==CHANGE) goto end; break; case ButtonPress: gin->pX = event.xbutton.x; gin->pY = event.xbutton.y; gin->state = event.xbutton.state; gin->button = event.xbutton.button; gin->string[0] = '\0'; gin->keysym = 0x20; if (mode==WAIT || mode==DOWN || mode==CHANGE) goto end; break; case KeyPress: // exit in error if ^C gin->pX = event.xkey.x; gin->pY = event.xkey.y; gin->state = event.xkey.state; nchars = XLookupString(&event.xkey, gin->string, PL_MAXKEY - 1, &mykey, NULL); gin->string[nchars] = '\0'; gin->keysym = (unsigned int) mykey; goto end; if (gin->state&0x4 && (gin->keysym==67 || gin->keysym==99)) { status = false; goto end; } warp = false; dx = 0; dy = 0; switch (mykey) { case XK_Cancel: case XK_Break: status = false; goto end; case XK_Left: dx = -1; warp = true; break; case XK_Up: dy = -1; warp = true; break; case XK_Right: dx = 1; warp = true; break; case XK_Down: dy = 1; warp = true; break; } if (warp) { // Each modifier key added increases the multiplication factor by 5 // Shift if (gin->state & 0x01) { dx *= 5; dy *= 5; } // Caps Lock if (gin->state & 0x02) { dx *= 5; dy *= 5; } // Control if (gin->state & 0x04) { dx *= 5; dy *= 5; } // Alt if (gin->state & 0x08) { dx *= 5; dy *= 5; } // Bounds checking so that we don't send cursor out of window x1 = gin->pX + dx; y1 = gin->pY + dy; if (x1 < xmin) dx = xmin - gin->pX; if (y1 < ymin) dy = ymin - gin->pY; if (x1 > xmax) dx = xmax - gin->pX; if (y1 > ymax) dy = ymax - gin->pY; XWarpPointer(xwd->display, dev->window, None, 0, 0, 0, 0, dx, dy); if (mode==CHANGE) goto end; } break; case MotionNotify: gin->pX = event.xmotion.x; gin->pY = event.xmotion.y; gin->state = event.xmotion.state; gin->string[0] = '\0'; gin->keysym = 0x20; if (mode==CHANGE) goto end; // crosshair not available if we exit on motion!!! if(event.type==MotionNotify){ x=event.xmotion.x; y=event.xmotion.y; } else { x=event.xcrossing.x; y=event.xcrossing.y; } break; default: break; } } end: gin->pY = dev->height - gin->pY; gin->dX = (PLFLT) gin->pX / (dev->width - 1); gin->dY = (PLFLT) gin->pY / (dev->height - 1); if(grabbed) XUngrabPointer(xwd->display,CurrentTime); if(kbgrabbed) XUngrabKeyboard(xwd->display,CurrentTime); // XFlush(xwd->display); return status; } bool GDLXStream::PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong trueColorOrder, DLong chan) { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; //how much do we need? PLINT xoff = (PLINT) pos[0]; //(pls->wpxoff / 32767 * dev->width + 1); PLINT yoff = (PLINT) pos[2]; //(pls->wpyoff / 24575 * dev->height + 1); PLINT xmax = dev->width - xoff; PLINT ymax = dev->height - yoff; if (nx < xmax) xmax = nx; if (ny < ymax) ymax = ny; PLINT rint[ctSize], gint[ctSize], bint[ctSize]; //load original table GDLCT* actCT = GraphicsDevice::GetCT(); actCT->Get(rint,gint,bint,ctSize); DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); //define & populate if necessary XImage img. XImage *ximg = NULL; if (chan>0) { //we need to get the destination part of screen image back to write on it int x, y; // XFlush(xwd->display); //could be overkill... int (*oldErrorHandler)(Display*, XErrorEvent*); oldErrorHandler = XSetErrorHandler(GetImageErrorHandler); if (dev->write_to_pixmap == 1) { ximg = XGetImage(xwd->display, dev->pixmap, xoff, dev->height-yoff-ymax, xmax, ymax, AllPlanes, ZPixmap); } else { ximg = XGetImage(xwd->display, dev->window, xoff, dev->height-yoff-ymax, xmax, ymax, AllPlanes, ZPixmap); } if (ximg == NULL) { //last chance!!! // XSync(xwd->display, 0); //could be overkill... x = 0; y = 0; if (dev->write_to_pixmap == 1) { XCopyArea(xwd->display, dev->pixmap, dev->window, dev->gc, xoff, dev->height-yoff-ymax, xmax, ymax, x, y); // XSync(xwd->display, 0); //could be overkill... } } XSetErrorHandler(oldErrorHandler); if (ximg == NULL) { cerr << "Unhandled unsuccessful XCopyArea, returning." << endl; return false; } } else { void *imgData=malloc(xmax*ymax*4); //too much size allocated, but keeps X11 happy (no need of scanline length computation) ximg = XCreateImage(xwd->display, xwd->visual, xwd->depth, ZPixmap, 0, (char*)imgData , xmax, ymax, 8, 0); //8 seems reasonable, see XCreateImage doc. } PLINT ix, iy; XColor curcolor; curcolor = xwd->fgcolor; //default PLINT iclr1, ired, igrn, iblu; // parallelize does not work when using XGet[Put]Pixel in the loop below, otherwise would be OK! // please allow parallelization only after removing this problem ;^) //#ifdef _OPENMP // SizeT nOp = kxLimit * kyLimit; //#endif // #pragma omp parallel if (nOp >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nOp)) private(ired,igrn,iblu,kx,ky,iclr1,curcolor) // { // #pragma omp for for (ix = 0; ix < xmax; ++ix) { for (iy = 0; iy < ymax; ++iy) { if (xwd->color) { if (trueColorOrder == 0 && chan == 0) { iclr1 = idata[iy * nx + ix]; if (decomposed == 1){ curcolor.pixel = iclr1 * 256 * 256 + iclr1 * 256 + iclr1; } else { if (xwd->rw_cmap==0) { ired = rint[iclr1]; igrn = gint[iclr1]; iblu = bint[iclr1]; } else { ired = pls->cmap0[iclr1].r; igrn = pls->cmap0[iclr1].g; iblu = pls->cmap0[iclr1].b; } curcolor.pixel = ired * 256 * 256 + igrn * 256 + iblu; } } else { if (chan == 0) { if (trueColorOrder == 1) { ired = idata[3 * (iy * nx + ix) + 0]; igrn = idata[3 * (iy * nx + ix) + 1]; iblu = idata[3 * (iy * nx + ix) + 2]; } else if (trueColorOrder == 2) { ired = idata[nx * (iy * 3 + 0) + ix]; igrn = idata[nx * (iy * 3 + 1) + ix]; iblu = idata[nx * (iy * 3 + 2) + ix]; } else if (trueColorOrder == 3) { ired = idata[nx * (0 * ny + iy) + ix]; igrn = idata[nx * (1 * ny + iy) + ix]; iblu = idata[nx * (2 * ny + iy) + ix]; } curcolor.pixel = ired * 256 * 256 + igrn * 256 + iblu; } else { //channel mode -> ximg was got from display -> is reversed unsigned long pixel = XGetPixel(ximg, ix, ymax-1-iy); if (chan == 1) { //1 byte bitmap passed pixel &= 0x00ffff; ired = idata[1 * (iy * nx + ix) + 0]; curcolor.pixel = ired * 256 * 256 + pixel; } else if (chan == 2) { pixel &= 0xff00ff; igrn = idata[1 * (iy * nx + ix) + 0]; curcolor.pixel = igrn * 256 + pixel; } else if (chan == 3) { pixel &= 0xffff00; iblu = idata[1 * (iy * nx + ix) + 0]; curcolor.pixel = iblu + pixel; } } } } XPutPixel(ximg, ix, ymax-1-iy, curcolor.pixel); //ximg IS reversed allways. } } // } //end parallelize if (dev->write_to_pixmap == 1) XPutImage(xwd->display, dev->pixmap, dev->gc, ximg, 0, 0, xoff, dev->height-yoff-ymax, xmax, ymax); if (dev->write_to_window==1) //always write XPutImage(xwd->display, dev->window, dev->gc, ximg, 0, 0, xoff, dev->height-yoff-ymax, xmax, ymax); XDestroyImage(ximg); return true; } void GDLXStream::Color( ULong color, DLong decomposed ) { XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; if (xwd->rw_cmap) { //not treated here, revert to safety with plplot's overhead. if ( decomposed == 0 ) { //get current colormap plstream::col0( color & 0xFF ); //just set color index [0..255]. simple and fast. } else { GDLGStream::SetColorMap1SingleColor(color); plstream::col1(1); } return; } unsigned int curcolor; DByte r, g, b; if ( decomposed == 0 ) { //get current colormap //load original table GDLCT* actCT = GraphicsDevice::GetCT(); actCT->Get(color & 0xFF,r,g,b); } else { //truecolor=decomposed case r = (color & 0xFF); g = (color >> 8 & 0xFF); b = (color >> 16 & 0xFF); } curcolor= ( (unsigned long) (r) << (ffs(xwd->visual->red_mask)-1)) + ((unsigned long)(g) << (ffs(xwd->visual->green_mask)-1) ) + ((unsigned long)(b) << (ffs(xwd->visual->blue_mask)-1) ); XSetForeground( xwd->display, dev->gc, curcolor); } //Read X11 bitmapdata -- normally on 4BPP=Allplanes, return 3BPP ignoring Alpha plane. DByteGDL* GDLXStream::GetBitmapData() { // plstream::cmd( PLESC_FLUSH, NULL ); GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); XwDev *dev = (XwDev *) pls->dev; XwDisplay *xwd = (XwDisplay *) dev->xwd; XImage *ximg = NULL; XWindowAttributes win_attr; /* query the window's attributes. */ Status rc = XGetWindowAttributes(xwd->display, dev->window, &win_attr); unsigned int nx = win_attr.width; unsigned int ny = win_attr.height; int (*oldErrorHandler)(Display*, XErrorEvent*); oldErrorHandler = XSetErrorHandler(GetImageErrorHandler); if (dev->write_to_pixmap==1) { ximg = XGetImage(xwd->display, dev->pixmap, 0, 0, nx, ny, AllPlanes, ZPixmap); } else { ximg = XGetImage( xwd->display, dev->window, 0, 0, nx, ny, AllPlanes, ZPixmap); } XSetErrorHandler(oldErrorHandler); if (ximg == NULL) return NULL; if (ximg->bits_per_pixel != 32) return NULL; SizeT datadims[3]; datadims[0] = nx; datadims[1] = ny; datadims[2] = 3; dimension datadim(datadims, (SizeT) 3); DByteGDL *bitmap = new DByteGDL( datadim, BaseGDL::NOZERO); //PADDING is 4BPP -- we take 3BPP and revert Y to respect IDL default SizeT kpad = 0; for ( SizeT iy =0; iy < ny ; ++iy ) { for ( SizeT ix = 0; ix < nx; ++ix ) { (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 2] = ximg->data[kpad++]; (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 1] = ximg->data[kpad++]; (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 0] = ximg->data[kpad++]; kpad++; //pad to 4 } } XDestroyImage(ximg); return bitmap; } #endif gdl-0.9.9/src/gdlxstream.hpp000066400000000000000000000075051340051421000157460ustar00rootroot00000000000000/* ************************************************************************* gdlxstream.hpp - graphic stream X windows ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLXSTREAM_HPP_ #define GDLXSTREAM_HPP_ #include "gdlgstream.hpp" #ifdef HAVE_X # include class GDLXStream: public GDLGStream { Atom wm_protocols; Atom wm_delete_window; Window term_window; public: GDLXStream( int nx, int ny) : GDLGStream( nx, ny, "xwin",XOpenDisplay(NULL)==NULL?":0":NULL) //IDL also opens :0 when DISPLAY is not set. , term_window(0) { } ~GDLXStream() {} void Init(); void EventHandler(); /*------------------------------------------------------------------------*\ * GetImageErrorHandler() * * Error handler used in XGetImage() to catch errors when pixmap or window * are not completely viewable. \*-----------------------------------------------------------------------*/ static int GetImageErrorHandler(Display *display, XErrorEvent *error) { if (error->error_code != BadMatch) { char buffer[256]; XGetErrorText(display, error->error_code, buffer, 256); std::cerr << "xwin: Error in XGetImage: " << buffer << std::endl; } return 1; } void Update(); void GetGeometry( long& xSize, long& ySize); unsigned long GetWindowDepth(); DLong GetVisualDepth(); DString GetVisualName(); BaseGDL* GetFontnames(DString pattern); DLong GetFontnum(DString pattern); bool setFocus(bool value); bool UnsetFocus(); bool SetBackingStore(int value); bool SetGraphicsFunction(long value ); bool GetWindowPosition(long& xpos, long& ypos ); bool CursorStandard(int cursorNumber); void Clear(); void Clear( DLong chan); void Raise(); void Lower(); void Iconic(); void DeIconic(); bool GetGin(PLGraphicsIn *gin, int mode); bool GetExtendedGin(PLGraphicsIn *gin, int mode); void WarpPointer(DLong x, DLong y); void Flush(); void SetDoubleBuffering(); void UnSetDoubleBuffering(); bool HasSafeDoubleBuffering(); bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan); virtual bool HasCrossHair() {return true;} void UnMapWindow(); DByteGDL* GetBitmapData(); void Color( ULong color, DLong decomposed); // void Update(){plstream::cmd(PLESC_EXPOSE, NULL);} //GD: overloading scmap0 to accelerate plots for X11 and possibly others void SetColorMap0(PLINT *r, PLINT *g, PLINT *b, PLINT ncol0) { } //DO NOTHING! //GD probably impossible to avoid plplot's XAllocColor for contours (since plcol is called inside driver) unless //we make our own contouring function (quite easy in fact). // void SetColorMap1(const PLINT *r, const PLINT *g, const PLINT *b, PLINT ncol1) { // } //DO NOTHING! // // void SetColorMap1l(bool itype, PLINT npts, const PLFLT *intensity, const PLFLT *coord1, // const PLFLT *coord2, const PLFLT *coord3, const bool *rev = NULL) { // } //DO NOTHING // // void SetColorMap1n(PLINT ncol1) { // } //DO NOTHING }; #endif #endif gdl-0.9.9/src/gdlzstream.cpp000066400000000000000000000112141340051421000157330ustar00rootroot00000000000000/* ************************************************************************* gdlzstream.cpp - graphic stream z-buffer ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //#include #include "includefirst.hpp" #include "gdlzstream.hpp" using namespace std; void GDLZStream::eop() { GraphicsDevice* actDevice=GraphicsDevice::GetDevice(); actDevice->ClearStream( (DLong) 0); } void GDLZStream::Clear() { GraphicsDevice* actDevice=GraphicsDevice::GetDevice(); actDevice->ClearStream( (DLong) 0); } void GDLZStream::Clear( DLong bColor) { GraphicsDevice* actDevice=GraphicsDevice::GetDevice(); actDevice->ClearStream( bColor); } void GDLZStream::Init() { this->plstream::init(); } void GDLZStream::GetGeometry(long& xSize, long& ySize) { xSize=pls->phyxma; ySize=pls->phyyma; } unsigned long GDLZStream::GetWindowDepth(){ GraphicsDevice* actDevice=GraphicsDevice::GetDevice(); return actDevice->GetPixelDepth(); } bool GDLZStream::PaintImage( unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong trueColorOrder, DLong chan ) { plstream::cmd( PLESC_FLUSH, NULL ); unsigned char *mem = (unsigned char *) pls->dev; PLINT xoff = (PLINT) pos[0]; PLINT yoff = (PLINT) pos[2]; PLINT xsize = pls->phyxma; PLINT ysize = pls->phyyma; PLINT kxLimit = xsize - xoff; PLINT kyLimit = ysize - yoff; if ( nx < kxLimit ) kxLimit = nx; if ( ny < kyLimit ) kyLimit = ny; if ( nx > 0 && ny > 0 ) { SizeT p = (ysize - yoff - 1)*3*xsize; for ( int iy = 0; iy < kyLimit; ++iy ) { SizeT rowStart = p; p += xoff*3; for ( int ix = 0; ix < kxLimit; ++ix ) { if ( trueColorOrder == 0 && chan == 0 ) { mem[p++] = pls->cmap0[idata[iy * nx + ix]].r; mem[p++] = pls->cmap0[idata[iy * nx + ix]].g; mem[p++] = pls->cmap0[idata[iy * nx + ix]].b; } else { if ( chan == 0 ) { if ( trueColorOrder == 1 ) { mem[p++] = idata[3 * (iy * nx + ix) + 0]; mem[p++] = idata[3 * (iy * nx + ix) + 1]; mem[p++] = idata[3 * (iy * nx + ix) + 2]; } else if ( trueColorOrder == 2 ) { mem[p++] = idata[nx * (iy * 3 + 0) + ix]; mem[p++] = idata[nx * (iy * 3 + 1) + ix]; mem[p++] = idata[nx * (iy * 3 + 2) + ix]; } else if ( trueColorOrder == 3 ) { mem[p++] = idata[nx * (0 * ny + iy) + ix]; mem[p++] = idata[nx * (1 * ny + iy) + ix]; mem[p++] = idata[nx * (2 * ny + iy) + ix]; } } else { //1 byte bitmap passed. if ( chan == 1 ) { mem[p++] = idata[1 * (iy * nx + ix) + 0]; p += 2; } else if ( chan == 2 ) { p ++; mem[p++] = idata[1 * (iy * nx + ix) + 0]; p ++; } else if ( chan == 3 ) { p += 2; mem[p++] = idata[1 * (iy * nx + ix) + 0]; } } } } p = rowStart - (xsize*3); } } return true; } DByteGDL* GDLZStream::GetBitmapData() { plstream::cmd( PLESC_FLUSH, NULL ); unsigned char *mem = (unsigned char *) pls->dev; if (mem == NULL) return NULL; PLINT nx = pls->phyxma; PLINT ny = pls->phyyma; SizeT datadims[3]; datadims[0] = nx; datadims[1] = ny; datadims[2] = 3; dimension datadim(datadims, (SizeT) 3); DByteGDL *bitmap = new DByteGDL( datadim, BaseGDL::NOZERO); //PADDING is 3BPP -- we revert Y to respect IDL default SizeT kpad = 0; for ( SizeT iy =0; iy < ny ; ++iy ) { for ( SizeT ix = 0; ix < nx; ++ix ) { (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 0] = mem[kpad++]; (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 1] = mem[kpad++]; (*bitmap)[3 * ((ny-1-iy) * nx + ix) + 2] = mem[kpad++]; } } return bitmap; }gdl-0.9.9/src/gdlzstream.hpp000066400000000000000000000033551340051421000157470ustar00rootroot00000000000000/* ************************************************************************* gdlzstream.hpp - graphic stream z-buffer ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GDLZSTREAM_HPP_ #define GDLZSTREAM_HPP_ #include #include "graphicsdevice.hpp" #include "gdlgstream.hpp" class GDLZStream: public GDLGStream { public: GDLZStream( int nx, int ny): GDLGStream( nx, ny, "mem") { } ~GDLZStream() { } // void eop() {} // never eop (mem drivers eop() sets pls->dev to NULL) void eop(); void Clear(); void Clear( DLong bColor); void Init(); bool PaintImage(unsigned char *idata, PLINT nx, PLINT ny, DLong *pos, DLong tru, DLong chan); void GetGeometry( long& xSize, long& ySize); unsigned long GetWindowDepth(); DByteGDL* GetBitmapData(); //to be written. Needed by same needs as for X11 // bool SetGraphicsFunction(long value ); }; #endif gdl-0.9.9/src/getas.cpp000066400000000000000000000365011340051421000146700ustar00rootroot00000000000000/*************************************************************************** getas.cpp - get element as different type ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_GETAS_CPP // #include "includefirst.hpp" // //#include "datatypes.hpp" // #include "dstructgdl.hpp" // #include "real2int.hpp" #include "ofmt.hpp" // OutAuto // // #include "dinterpreter.hpp" using namespace std; // for double -> string inline string double2string( DDouble d) { std::ostringstream os; OutAuto( os, d, 16, 8, ' '); return os.str(); } // for float -> string inline string float2string( DFloat f) { std::ostringstream os; OutAuto( os, f, 13, 6, ' '); return os.str(); } // typedef Data_ DByteGDL; // typedef Data_ DIntGDL; // typedef Data_ DUIntGDL; // typedef Data_ DLongGDL; // typedef Data_ DULongGDL; // typedef Data_ DLong64GDL; // typedef Data_ DULong64GDL; // typedef Data_ DFloatGDL; // typedef Data_ DDoubleGDL; // typedef Data_ DStringGDL; // typedef Data_ DPtrGDL; // typedef Data_ DObjGDL; // typedef Data_ DComplexGDL; // typedef Data_ DComplexDblGDL; // general case template template typename Data_::Ty Data_::GetAs( SizeT i) { return this->dd[ i]; } // non convertable types // DPtrGDL specialization template<> template typename Data_::Ty Data_::GetAs( SizeT i) { if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Ptr expression not allowed in this context: "+BaseGDL::interpreter->Name(this)); throw GDLException("Ptr expression not allowed in this context."); } // DObjGDL specialization template<> template typename Data_::Ty Data_::GetAs( SizeT i) { if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Object expression not allowed in this context: "+BaseGDL::interpreter->Name(this)); throw GDLException("Object expression not allowed in this context."); } // DStructGDL template typename Data_::Ty DStructGDL::GetAs( SizeT i) { if(BaseGDL::interpreter!=NULL&&BaseGDL::interpreter->CallStack().size()>0) BaseGDL::interpreter->CallStack().back()->Throw("Struct expression not allowed in this context: "+BaseGDL::interpreter->Name(this)); throw GDLException("Struct expression not allowed in this context."); } // Ptr, Obj, Struct: GetAs throws // The operators are overloaded for these types, they throw // hence GetAs( SizeT i) is never called and does not need to be overloaded // integer types // DByteGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],4); } // DIntGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],8); } // DUIntGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],8); } // DLongGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],12); } // DULongGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],12); } // DLong64GDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],22); } // DULong64GDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return i2s<>(this->dd[ i],22); } // DFloatGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2DByte((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DUInt>((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong>((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong64>((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return float2string((*this)[i]); } // DDoubleGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2DByte((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DUInt>((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong>((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong64>((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return double2string((*this)[i]); } // DStringGDL full specializations inline void StringConversionErrorGetAs( const string& msg) { // if( (mode & BaseGDL::THROWIOERROR) != 0) // { // errorFlag = true; // } // else Warning( msg); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; long int result =strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to BYTE."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; long int result =strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to INT."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; unsigned long int result =strtoul(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to UINT."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; long int result =strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to LONG."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; unsigned long int result =strtoul(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to ULONG."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; Data_::Ty result =strtol(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to LONG64."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; Data_::Ty result =strtoul(cStart,&cEnd,10); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to ULONG64."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; float result = StrToD(cStart,&cEnd); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to FLOAT."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; double result = StrToD(cStart,&cEnd); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to DOUBLE."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; float result = StrToD(cStart,&cEnd); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to COMPLEX."); } return result; } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { const char* cStart=(*this)[i].c_str(); char* cEnd; double result = StrToD(cStart,&cEnd); if( cEnd == cStart && (*this)[i] != "") { StringConversionErrorGetAs( "Type conversion error: " "Unable to convert given STRING: '"+(*this)[i]+"' to DCOMPLEX."); } return result; } // DComplexGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2DByte(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DUInt>(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong>(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong64>(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return real((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return real((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return "("+i2s(real((*this)[i]))+","+i2s(imag((*this)[i]))+")"; } // DComplexDblGDL full specializations template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2DByte(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DUInt>(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return Real2Int(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong>(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return static_cast< DULong64>(real((*this)[i])); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return real((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return real((*this)[i]); } template<> template<> /*typename*/ Data_::Ty Data_::GetAs( SizeT i) { return "("+i2s(real((*this)[i]))+","+i2s(imag((*this)[i]))+")"; } #endif gdl-0.9.9/src/getfmtast.cpp000066400000000000000000000050041340051421000155550ustar00rootroot00000000000000/*************************************************************************** getfmtast.cpp - returns the AST for formatted IO ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //#define FMT_DEBUG #undef FMT_DEBUG #include "includefirst.hpp" #include "basegdl.hpp" #include "fmtnode.hpp" #include "print_tree.hpp" #include "FMTLexer.hpp" #include "FMTParser.hpp" #include using namespace std; antlr::ASTFactory FMTNodeFactory("FMTNode",FMTNode::factory); RefFMTNode GetFMTAST( DString fmtString) { istringstream istr(fmtString); //+"\n"); RefFMTNode fmtAST; try { antlr::TokenStreamSelector selector; FMTLexer lexer( istr); lexer.SetSelector( selector); CFMTLexer cLexer( lexer.getInputState()); cLexer.SetSelector( selector); lexer.SetCLexer( cLexer); selector.select( &lexer); FMTParser parser( selector); // because we use the standard (ANTLR generated) constructor here // we cannot do it in the constructor parser.initializeASTFactory( FMTNodeFactory); parser.setASTFactory( &FMTNodeFactory ); parser.format( 1); fmtAST=parser.getAST(); #ifdef FMT_DEBUG antlr::print_tree pt; pt.pr_tree(static_cast(fmtAST)); cout << endl; #endif } catch( GDLException& ex) { throw GDLException("Format: "+ex.getMessage()); } catch( antlr::ANTLRException& ex) { throw GDLException("Format parser: "+ex.getMessage()); } catch( exception& ex) { throw GDLException("Format exception: "+string(ex.what())); } catch(...) { throw GDLException("Format: general exception."); } return fmtAST; } gdl-0.9.9/src/getfmtast.hpp000066400000000000000000000023571340051421000155720ustar00rootroot00000000000000/*************************************************************************** getfmtast.hpp - converts string to format AST ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GETFMTAST_HPP_ #define GETFMTAST_HPP_ #include "fmtnode.hpp" #include "basegdl.hpp" #include extern antlr::ASTFactory FMTNodeFactory; RefFMTNode GetFMTAST( DString fmtString); #endif gdl-0.9.9/src/graphicsdevice.cpp000066400000000000000000000506121340051421000165440ustar00rootroot00000000000000/************************************************************************** graphicsdevice.cpp - GDL base class for all graphic devices renamed from: graphics.cpp ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "objects.hpp" #include "graphicsdevice.hpp" #include "devicewin.hpp" #include "devicewx.hpp" #include "devicex.hpp" #include "deviceps.hpp" #include "devicesvg.hpp" #include "devicez.hpp" #include "devicenull.hpp" #include "initsysvar.hpp" #include "color.hpp" using namespace std; bool GDLCT::Get( PLINT r_[], PLINT g_[], PLINT b_[], UInt nCol) const { if( nCol > ctSize) return false; for(UInt i=0; i(r[i]); g_[i] = static_cast(g[i]); b_[i] = static_cast(b[i]); } return true; } bool GDLCT::Get( UInt ix, DByte& r_, DByte& g_, DByte& b_) const { if( ix >= ctSize) return false; r_ = r[ix]; g_ = g[ix]; b_ = b[ix]; return true; } bool GDLCT::Set( UInt ix, DByte r_, DByte g_, DByte b_) { if( ix >= ctSize) return false; r[ix] = r_; g[ix] = g_; b[ix] = b_; return true; } bool GDLCT::SetHLS( UInt ix, DFloat h, DFloat l, DFloat s) { if( ix >= ctSize) return false; DByte r_, g_, b_; HLS2RGB( h, l, s, r_, g_, b_); r[ix] = r_; g[ix] = g_; b[ix] = b_; return true; } bool GDLCT::SetHSV( UInt ix, DFloat h, DFloat s, DFloat v) { if( ix >= ctSize) return false; DByte r_, g_, b_; HSV2RGB( h, s, v, r_, g_, b_); r[ix] = r_; g[ix] = g_; b[ix] = b_; return true; } std::vector GraphicsDevice::CT; // predefined colortables GDLCT GraphicsDevice::actCT; // actual used colortable DeviceListT GraphicsDevice::deviceList; GraphicsDevice* GraphicsDevice::actDevice = NULL; GraphicsDevice* GraphicsDevice::actGUIDevice = NULL; int GraphicsDevice::wTag; int GraphicsDevice::xSTag; int GraphicsDevice::ySTag; int GraphicsDevice::xVSTag; int GraphicsDevice::yVSTag; int GraphicsDevice::n_colorsTag; DByte GraphicsDevice::deviceBckColorR; DByte GraphicsDevice::deviceBckColorG; DByte GraphicsDevice::deviceBckColorB; GraphicsDevice::~GraphicsDevice() { // actDevice's dStruct is or will be deleted from sysVarList if( actDevice != this) delete dStruct; } // v-table instatiation GraphicsDevice::GraphicsDevice(): dStruct( NULL), CopyBufferSize(0) { } void GraphicsDevice::ListDevice(std::ostream& oss) { int size = deviceList.size(); oss << "Available Graphics Devices: "; for( int i=0; iName() << " "; oss << endl; } bool GraphicsDevice::ExistDevice( const string& device, int &index) { index=-1; int size = deviceList.size(); for( int i=0; iName() == device) { index=i; return true; } } return false; } bool GraphicsDevice::SetDevice( const string& device) { int size = deviceList.size(); for( int i=0; iName() == device) { actDevice=deviceList[ i]; // update !D SysVar::SetD( actDevice->DStruct()); return true; } } return false; } DStructGDL* GraphicsDevice::GetDeviceStruct( const string& device) { int size = deviceList.size(); for( int i=0; iName() == device) { return deviceList[ i]->DStruct(); } } return NULL; } void GraphicsDevice::Init() { InitCT(); DefineDStructDesc(); // 4 devices types without surprise ! deviceList.push_back( new DeviceNULL()); deviceList.push_back( new DevicePS()); deviceList.push_back( new DeviceSVG()); deviceList.push_back( new DeviceZ()); // if GDL_USE_WX (or switch --use-wx) , and has wxWidgets, the wxWidgets device becomes 'X' or 'WIN' depending on machine, // no other device is defined. if (useWxWidgetsForGraphics) { #ifdef HAVE_LIBWXWIDGETS //start wxWidgets here instead of first call of a widget function. if( ! wxInitialize( ) ) ThrowGDLException("Unable to initialize wxWidgets"); GDLWidget::SetWxStarted(); #ifdef HAVE_X deviceList.push_back( new DeviceWX("X")); #else #ifdef _WIN32 deviceList.push_back( new DeviceWX("WIN")); #endif #endif #else #ifdef HAVE_X deviceList.push_back( new DeviceX()); #endif #ifdef _WIN32 deviceList.push_back( new DeviceWIN()); #endif #endif } else { #ifdef HAVE_LIBWXWIDGETS deviceList.push_back( new DeviceWX()); //traditional use, device will be called "MAC" #endif #ifdef HAVE_X deviceList.push_back( new DeviceX()); #endif #ifdef _WIN32 deviceList.push_back( new DeviceWIN()); #endif } // we try to set X, WIN or WX as default // (and NULL if X11 system (Linux, OSX, Sun) but without X11 at compilation) #if defined(HAVE_X) // Check X11 first if( !SetDevice( "X")) #elif defined(_WIN32) // If Windows enable WinGCC driver if( !SetDevice( "WIN")) #elif defined (HAVE_LIBWXWIDGETS) // Finally check WX if (!SetDevice("MAC")) #else if( !SetDevice( "NULL")) # endif # if !defined (HAVE_X) && !defined (HAVE_LIBWXWIDGETS) && !defined (_WIN32) { } # else { cerr << "Error initializing graphics." << endl; exit( EXIT_FAILURE); } # endif // GDL (at least with device X and Wx) handle equally any types of screens, // with an equivalent depth of 24 (tested and true). So there is no // need to return any depth, color number etc that would be anything // else than a truecolor (24 bits). So we force !P.color to be set // to the depth of a truecolor screen. This // is what 'set_plot' does, but set_plot is not called by default. DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset unsigned colorTag=pStruct->Desc()->TagIndex("COLOR"); unsigned bckTag=pStruct->Desc()->TagIndex("BACKGROUND"); (*static_cast(pStruct->GetTag(colorTag, 0)))[0]=16777215; (*static_cast(pStruct->GetTag(bckTag, 0)))[0]=0; #ifdef HAVE_LIBWXWIDGETS // some X error message suggested this call #ifdef HAVE_X // XInitThreads(); #endif #endif int index=0; // setting the GUI dev. There is only ONE possibility: the wxWidgets. // depending on how we build GDL, wxWidgets may replace X and WIN entirely, or not. // If not, it will be called "MAC" (temporarily). // If yes (replaces either X or WIN) it will be called 'X' or 'WIN' accordingly. if (ExistDevice( "MAC", index)) { //wxWidgets present, in concurrence with others. actGUIDevice = deviceList[index]; } else if (ExistDevice( "X", index)) { #ifdef HAVE_LIBWXWIDGETS actGUIDevice = deviceList[index]; //true existing device #else actGUIDevice = deviceList[0]; //will be a fake GUI and procedures will complain. #endif } else if (ExistDevice("WIN", index)) { #ifdef HAVE_LIBWXWIDGETS actGUIDevice = deviceList[index]; //true existing device #else actGUIDevice = deviceList[0]; //will be a fake GUI and procedures will complain. #endif } else { actGUIDevice = deviceList[0]; //will be a fake GUI and procedures will complain. } } void GraphicsDevice::DestroyDevices() { PurgeContainer( deviceList); actDevice = NULL; } void GraphicsDevice::DefineDStructDesc() { DStructDesc* dSysVarDesc = FindInStructList( structList, "!DEVICE"); if( dSysVarDesc != NULL) return; dSysVarDesc = new DStructDesc( "!DEVICE"); SpDString aString; SpDLong aLong; SpDLong aLongArr2( dimension(2)); SpDFloat aFloat; dSysVarDesc->AddTag("NAME", &aString); dSysVarDesc->AddTag("X_SIZE", &aLong); dSysVarDesc->AddTag("Y_SIZE", &aLong); dSysVarDesc->AddTag("X_VSIZE", &aLong); dSysVarDesc->AddTag("Y_VSIZE", &aLong); dSysVarDesc->AddTag("X_CH_SIZE", &aLong); dSysVarDesc->AddTag("Y_CH_SIZE", &aLong); dSysVarDesc->AddTag("X_PX_CM", &aFloat); dSysVarDesc->AddTag("Y_PX_CM", &aFloat); dSysVarDesc->AddTag("N_COLORS", &aLong); dSysVarDesc->AddTag("TABLE_SIZE", &aLong); dSysVarDesc->AddTag("FILL_DIST", &aLong); dSysVarDesc->AddTag("WINDOW", &aLong); dSysVarDesc->AddTag("UNIT", &aLong); dSysVarDesc->AddTag("FLAGS", &aLong); dSysVarDesc->AddTag("ORIGIN", &aLongArr2); dSysVarDesc->AddTag("ZOOM", &aLongArr2); structList.push_back( dSysVarDesc); // !D tag indices wTag = dSysVarDesc->TagIndex( "WINDOW"); xSTag = dSysVarDesc->TagIndex( "X_SIZE"); ySTag = dSysVarDesc->TagIndex( "Y_SIZE"); xVSTag = dSysVarDesc->TagIndex( "X_VSIZE"); yVSTag = dSysVarDesc->TagIndex( "Y_VSIZE"); n_colorsTag = dSysVarDesc->TagIndex( "N_COLORS"); } void GraphicsDevice::HandleEvents() { DeviceListT::iterator i; for( i=deviceList.begin(); i != deviceList.end(); ++i) { (*i)->EventHandler(); } } void GraphicsDevice::LoadCT( UInt iCT) { actCT = CT[iCT]; } //---------------Multi-Windows Device------------------------------------------- int GraphicsMultiDevice::actWin; WindowListT GraphicsMultiDevice::winList; std::vector GraphicsMultiDevice::oList; int GraphicsMultiDevice::oIx; void GraphicsMultiDevice::Init() { GraphicsDevice::Init(); //populate the one and only list of windows. winList.reserve(max_win_reserve); winList.resize(max_win); for (int i = 0; i < max_win; i++) winList[i] = NULL; oList.reserve(max_win_reserve); oList.resize(max_win); for (int i = 0; i < max_win; i++) oList[i] = 0; actWin=-1; oIx=-1; } DByteGDL* GraphicsMultiDevice::WindowState() { int maxwin = MaxWin(); if (maxwin > 0) { DByteGDL* ret = new DByteGDL(dimension(maxwin < 65 ? 65 : maxwin), BaseGDL::ZERO); for (int i = 0; i < maxwin; i++) (*ret)[i] = WState(i); return ret; } else return NULL; } bool GraphicsMultiDevice::WState(int wIx) { return wIx >= 0 && wIx < oList.size() && oList[wIx] != 0; } int GraphicsMultiDevice::MaxWin() { TidyWindowsList(); return winList.size(); } void GraphicsMultiDevice::SetActWin(int wIx) { // Special behaviour for !D.WINDOW etc: // Update window number in all equivalent !D: !D is local to the Device, and sysvar's !D point to it. // So there are actually several !D per GraphicsMultiDevice! // we need to update *all* the different !D in action, which are 2 if widgets + X11 device, and ony one if widget + wX device. // another option would be to make !D static like !P. // At the moment only "sharing" !D.WINDOW seems useful. string listOfEquivalentDevices[]={"X","MAC","WIN"}; for (int i=0; i<3; ++i) { DStructGDL *s=GraphicsDevice::GetDeviceStruct( listOfEquivalentDevices[i]); if (s) { //most important: window number, which CAN BE -1 (*static_cast (s->GetTag(wTag)))[0] = wIx; //Rest of informations if (wIx >= 0 && wIx < winList.size()) { assert(winList[ wIx] != NULL); long xsize, ysize; winList[ wIx]->GetGeometry(xsize, ysize); (*static_cast (s->GetTag(xSTag)))[0] = xsize; (*static_cast (s->GetTag(ySTag)))[0] = ysize; (*static_cast (s->GetTag(xVSTag)))[0] = xsize; (*static_cast (s->GetTag(yVSTag)))[0] = ysize; } } } actWin = wIx; if (actWin == -1) oIx=1; //better set it here instead of in all places where actwin is called. } // process user deleted windows // should be done in a thread void GraphicsMultiDevice::TidyWindowsList() { int wLSize = winList.size(); for (int i = 0; i < wLSize; i++) if (winList[i] != NULL && !winList[i]->GetValid()) { //general purpose winlist cleaning with destruction of "closed" plstreams and (eventually) associated widgets: //in case winList groups X11 streams (or WIN streams) *and* wxWidgets streams (GDL_USE_WX="NO") the following //permits to delete the widget_draw also, not only the plplot stream. #ifdef HAVE_LIBWXWIDGETS if (dynamic_cast (winList[i]) != NULL) { GDLDrawPanel* panel = NULL; panel = dynamic_cast (static_cast (winList[i])->GetGDLDrawPanel()); //test if stream is associated to graphic window or widget_draw. If graphic, destroy directly TLB widget. GDLWidgetDraw *draw = panel->GetGDLWidgetDraw(); if (draw) { //parent of panel may be a GDLFrame. If frame is actually made by the WOpen function, destroy everything. GDLWidgetBase* container = NULL; container = static_cast (draw->GetTopLevelBaseWidget(draw->WidgetID())); if (container && container->IsGraphicWindowFrame()) container->SelfDestroy(); else delete draw; } else delete winList[i]; } else #endif delete winList[i]; winList[i] = NULL; oList[i] = 0; } // set new actWin IF NOT VALID ANY MORE if (actWin < 0 || actWin >= wLSize || winList[actWin] == NULL || !winList[actWin]->GetValid()) { std::vector< long>::iterator mEl = std::max_element(oList.begin(), oList.end()); // most recently created if (*mEl == 0) { // no window open SetActWin(-1); //sets oIx = 1; } else SetActWin(GraphicsDevice::GetDevice()->GetNonManagedWidgetActWin(false)); //get first non-managed window. false is needed. } } void GraphicsMultiDevice::RaiseWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->Raise(); } void GraphicsMultiDevice::LowerWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->Lower(); } void GraphicsMultiDevice::IconicWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->Iconic(); } void GraphicsMultiDevice::DeIconicWin(int wIx) { if (wIx >= 0 && wIx < winList.size()) winList[wIx]->DeIconic(); } void GraphicsMultiDevice::EventHandler() { if (actWin < 0) return; //would this have side effects? int wLSize = winList.size(); for (int i = 0; i < wLSize; i++) if (winList[i] != NULL) winList[i]->EventHandler(); // TidyWindowsList(); //removing it here removes a lot of loops but needs TidyWindowsList() to be called at all places needed. } bool GraphicsMultiDevice::WDelete(int wIx) { if( wIx >= 0 && winList[ wIx] != NULL) {winList[ wIx]->SetValid(false); TidyWindowsList();//if WDelete is always called with a valid wIx and is always a window, not a widget, this should be OK. return true; } else return false; } bool GraphicsMultiDevice::WSize(int wIx, int *xSize, int *ySize) { TidyWindowsList(); int wLSize = winList.size(); if (wIx > wLSize || wIx < 0) return false; long xleng, yleng; winList[wIx]->GetGeometry(xleng, yleng); *xSize = xleng; *ySize = yleng; return true; } bool GraphicsMultiDevice::WSet(int wIx) { TidyWindowsList(); int wLSize = winList.size(); if (wIx >= wLSize || wIx < 0 || winList[wIx] == NULL) return false; SetActWin(wIx); return true; } bool GraphicsMultiDevice::WShow(int ix, bool show, int iconic) { TidyWindowsList(); int wLSize = winList.size(); if (ix >= wLSize || ix < 0 || winList[ix] == NULL) return false; if (iconic!=-1) { //iconic asked. do nothing else. if (iconic==1) IconicWin(ix); else DeIconicWin(ix); return true; } if (show) RaiseWin(ix); else LowerWin(ix); //UnsetFocus(); return true; } int GraphicsMultiDevice::WAddFree() { TidyWindowsList(); int wLSize = winList.size(); // plplot allows only 101 windows if (wLSize == 101) return -1; for (int i = max_win; i < wLSize; i++) if (winList[i] == NULL) return i; winList.push_back(NULL); oList.push_back(0); return wLSize; } GDLGStream* GraphicsMultiDevice::GetStreamAt(int wIx) const { return winList[wIx]; } void GraphicsMultiDevice::ChangeStreamAt(int wIx, GDLGStream* newStream) { if (winList[wIx]==NULL) return; GDLGStream* oldStream=winList[wIx]; winList[wIx]=newStream; delete oldStream; } bool GraphicsMultiDevice::UnsetFocus() { return winList[actWin]->UnsetFocus(); } bool GraphicsMultiDevice::Decomposed(bool value) { decomposed = value; return true; } DLong GraphicsMultiDevice::GetDecomposed() { // initial setting (information from the X-server needed) if (this->decomposed == -1) { if (actWin < 0) { cerr << "requesting GetDecomposed() on unexistent window " << endl; return 0;} //should not happen unsigned long Depth = winList[actWin]->GetWindowDepth(); decomposed = (Depth >= 15 ? true : false); unsigned long nSystemColors = (1 << Depth); unsigned long oldColor = (*static_cast (SysVar::P()->GetTag(SysVar::P()->Desc()->TagIndex("COLOR"), 0)))[0]; unsigned long oldNColor = (*static_cast (dStruct->GetTag(n_colorsTag)))[0]; if (this->decomposed == 1 && oldNColor == 256) { (*static_cast (dStruct->GetTag(n_colorsTag)))[0] = nSystemColors; if (oldColor == 255) (*static_cast (SysVar::P()->GetTag(SysVar::P()->Desc()->TagIndex("COLOR"), 0)))[0] = nSystemColors - 1; } else if (this->decomposed == 0 && oldNColor == nSystemColors) { (*static_cast (dStruct->GetTag(n_colorsTag)))[0] = 256; if (oldColor == nSystemColors - 1) (*static_cast (SysVar::P()->GetTag(SysVar::P()->Desc()->TagIndex("COLOR"), 0)))[0] = 255; } } if (decomposed) return 1; return 0; } bool GraphicsMultiDevice::SetBackingStore(int value) { backingStoreMode = value; return true; } bool GraphicsMultiDevice::Hide() //used as a substitute for /PIXMAP in DEVICE { TidyWindowsList(); winList[ actWin]->UnMapWindow(); return true; } int GraphicsMultiDevice::MaxNonFreeWin() { return max_win; } int GraphicsMultiDevice::ActWin() { TidyWindowsList(); return actWin; } int GraphicsMultiDevice::GetNonManagedWidgetActWin(bool doTidyWindowList) { //for case of "WSET,-1" or cases where the program has to find //by itself the first available window: this window must not be an active managed widget. //where the returned actwin is the first NON-MANAGED-WIDGET_DRAW available. if (doTidyWindowList) TidyWindowsList(); //bool is used in cas this function is called from... TidyWindowList itself #ifndef HAVE_LIBWXWIDGETS for (int i = 0; i < winList.size(); i++) if (winList[i] != NULL ) { if (!(winList[i]->IsPixmapWindow())) {return i;}//first non-pixmap window. } return -1; #else for (int i = 0; i < winList.size(); i++) if (winList[i] != NULL ) { if (!(winList[i]->IsPixmapWindow())) {//forget a pixmap window. if (dynamic_cast (winList[i]) == NULL) { //found non-widget window, probably an X11 one. Will return it if it is not a PIXMAP window if (!(winList[i]->IsPixmapWindow())) return i; } else { //special case of a graphic window which is either a draw widget (needs to be not managed) // or a wxWindow "normal window" (in which case we return it immediately). GDLDrawPanel* panel = NULL; panel = dynamic_cast (static_cast (winList[i])->GetGDLDrawPanel()); //test if stream is associated to graphic window or widget_draw. If graphic, return. If widget, return if not managed. GDLWidgetDraw *draw = panel->GetGDLWidgetDraw(); if (draw) { //panel. Managed? //parent of panel may be a GDLFrame. GDLWidgetBase* container = NULL; container = static_cast (draw->GetTopLevelBaseWidget(draw->WidgetID())); if (container && !(container->GetManaged())) return i; //first non-managed draw widget } else return i; //a wxWidgets "plot" (as opposed to) "widget" bona fide window to be returned. } } } return -1; //nothing found #endif } bool GraphicsMultiDevice::CopyRegion(DLongGDL* me) { TidyWindowsList(); DLong xs, ys, nx, ny, xd, yd; DLong source; xs = (*me)[0]; ys = (*me)[1]; nx = (*me)[2]; ny = (*me)[3]; xd = (*me)[4]; yd = (*me)[5]; if (me->N_Elements() == 7) source = (*me)[6]; else source = actWin; if (!winList[ source]->GetRegion(xs, ys, nx, ny)) return false; return winList[ actWin ]->SetRegion(xd, yd, nx, ny); } gdl-0.9.9/src/graphicsdevice.hpp000066400000000000000000000344651340051421000165610ustar00rootroot00000000000000/* ************************************************************************* graphicsdevice.hpp - GDL graphical output renamed from: graphics.hpp ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* GDL Graphic subsytem: GraphicsDevice - base subsystem class DeviceXXX - derived from Graphics, subsystem for device XXX GDLGStream - base graphic stream class (= windows, printer page) GDLXXXStream - derived from GDLGStream for XXX type of stream So for each device XXX there is a: DeviceXXX and at least one GDLXXXStream Devices are (note that on a given platform not all devices are available): X - X windows (GDLXStream, GDLWXStream) WIN - Windows PS - postscript output SVG - a SVG compliant file. */ #ifndef GRAPHICSDEVICE_HPP_ #define GRAPHICSDEVICE_HPP_ #include #include "datatypes.hpp" // DByte #include "dstructgdl.hpp" #include "gdlgstream.hpp" #define MAX_WIN 32 //IDL free and widgets start at 32 ... #define MAX_WIN_RESERVE 256 const UInt max_win = MAX_WIN; const UInt max_win_reserve = MAX_WIN_RESERVE; const UInt ctSize = 256; class GDLCT { DByte r[ ctSize]; DByte g[ ctSize]; DByte b[ ctSize]; UInt actSize; std::string name; public: GDLCT( const std::string& n, DByte* r_, DByte* g_, DByte* b_, SizeT nCol = ctSize): actSize( nCol), name( n) { SizeT i=0; for(;i DeviceListT; class GraphicsDevice { static void InitCT(); // preset CT and actCT static GraphicsDevice* actDevice; static DeviceListT deviceList; static GraphicsDevice* actGUIDevice; static void DefineDStructDesc(); // modifies structList unsigned char* CopyBuffer; SizeT CopyBufferSize; protected: static int wTag, xSTag, ySTag, xVSTag, yVSTag, n_colorsTag; // !D tag indices static std::vector CT; // predefined colortables static GDLCT actCT; // actual used colortable static DByte deviceBckColorR; static DByte deviceBckColorG; static DByte deviceBckColorB; std::string name; DStructGDL* dStruct; void GetWinSize( DLong& x, DLong& y) { int tag = dStruct->Desc()->TagIndex( "X_SIZE"); DLongGDL* xSize = static_cast( dStruct->GetTag( tag)); tag = dStruct->Desc()->TagIndex( "Y_SIZE"); DLongGDL* ySize = static_cast( dStruct->GetTag( tag)); x = (*xSize)[0]; y = (*ySize)[0]; } public: GraphicsDevice(); virtual ~GraphicsDevice(); static void Init(); static void DestroyDevices(); static void HandleEvents(); static void LoadCT(UInt iCT); void SetDeviceBckColor(DByte r, DByte g, DByte b) { deviceBckColorR=r; deviceBckColorG=g; deviceBckColorB=b; } DByte BackgroundR() {return deviceBckColorR;} DByte BackgroundG() {return deviceBckColorG;} DByte BackgroundB() {return deviceBckColorB;} static GDLCT* GetCT() { return &actCT;} static GDLCT* GetCT( SizeT ix) { return &CT[ix];} static SizeT N_CT() { return CT.size();} static void ListDevice(std::ostream& oss=cout); static bool ExistDevice( const std::string& device, int &index); static bool SetDevice( const std::string& devName); DStructGDL* GetDeviceStruct( const std::string& device); static GraphicsDevice* GetDevice() { return actDevice;} static GraphicsDevice* GetGUIDevice() { return actGUIDevice;} static DStructGDL* DStruct() { return actDevice->dStruct;} const DString Name() { return name;} unsigned char* GetCopyBuffer() {return CopyBuffer;} SizeT GetCopyBufferSize() {return CopyBufferSize;} unsigned char* SetCopyBuffer(SizeT size) { if (CopyBufferSize != 0) {free (CopyBuffer); CopyBufferSize = 0;} CopyBuffer=(unsigned char*)calloc(size, sizeof(char)); //set to zero CopyBufferSize = size; return CopyBuffer; } virtual GDLGStream* GetStreamAt( int wIx) const { return NULL;} virtual void ChangeStreamAt(int wIx, GDLGStream* newStream){}; virtual GDLGStream* GetStream( bool open=true) { return NULL;} virtual bool WSet( int ix) { return false;} virtual int WAddFree() { return false;} // for WIDGET_DRAW virtual bool GUIOpen( int wIx, int xSize, int ySize) { return false;} // for plot windows virtual bool WOpen( int ix, const std::string& title, int xsize, int ysize, int xpos, int ypos, bool hide) { return false;} virtual bool WSize( int ix, int* xsize, int* ysize) { return false;} virtual bool WShow( int ix, bool show, int iconic) { return false;} virtual bool WState( int ix) { return false;} virtual bool WDelete( int ix) { return false;} virtual int MaxWin() { return 0;} virtual void TidyWindowsList() {} virtual int MaxNonFreeWin() { return MaxWin();} virtual int ActWin() { return -1;} virtual int GetNonManagedWidgetActWin(bool doTidy=true) {return -1;} virtual void SetActWin(int wIx) {} virtual void EventHandler() {} virtual void DefaultXYSize(DLong *xsize, DLong *ysize) { *xsize=640, *ysize=480; return;} virtual void MaxXYSize(DLong *xsize, DLong *ysize) { *xsize=1200, *ysize=800; return;} virtual DLong GetDecomposed() { return -1;} virtual BaseGDL* GetFontnames() { ThrowGDLException("DEVICE: Keyword GET_FONTNAMES not allowed for call to: DEVICE" ); return NULL;} virtual DLong GetFontnum() { ThrowGDLException("DEVICE: Keyword GET_FONTNUM not allowed for call to: DEVICE" ); return -1;} virtual bool SetFont(DString f) {static int warning_sent=1; if (warning_sent) {Warning("SET_FONT not active for this device (FIXME)."); warning_sent=0;} return true;} virtual DString GetCurrentFont() {return NULL;} virtual DLong GetGraphicsFunction() { return -1;} virtual DIntGDL* GetPageSize() { return NULL;} virtual DLong GetPixelDepth() { return -1;} virtual bool SetPixelDepth(DInt depth) { return false;} virtual DDoubleGDL* GetScreenResolution(char* disp=NULL) //fake a basic screen if not implemented: { DDoubleGDL* res; res = new DDoubleGDL(2, BaseGDL::NOZERO); (*res)[0]=1.0; (*res)[1]=1.0; return res; } // virtual DFloatGDL* GetScreenSize(char* disp=NULL) { return NULL;} virtual DLongGDL* GetScreenSize(char* disp=NULL) //fake a basic screen if not implemented: { DLongGDL* res; res = new DLongGDL(2, BaseGDL::NOZERO); (*res)[0]=640; (*res)[1]=480; return res; } virtual DLong GetVisualDepth() { return -1;} virtual DString GetVisualName() { return "";} virtual DIntGDL* GetWindowPosition() { return NULL;} virtual DLong GetWriteMask() { return -1;} virtual DByteGDL* WindowState() { return NULL;} virtual bool CloseFile() { return false;} virtual bool SetFileName( const std::string& f) { return false;} virtual bool Decomposed( bool value) { return false;} virtual bool SetGraphicsFunction( DLong value) { return false;} virtual bool CursorStandard( int value) { return false;} virtual bool CursorCrosshair() { return false;} virtual int getCursorId() { return -1;} virtual bool UnsetFocus() { return false;} virtual bool SetBackingStore(int value) { return false;} virtual int getBackingStore() { return -1;} virtual bool SetXPageSize( const float xs) { return false;} virtual bool SetYPageSize( const float ys) { return false;} virtual bool SetColor(const long color=0) { return false;} virtual bool SetScale(const float) { return false;} virtual bool SetXOffset(const float) { return false;} virtual bool SetYOffset(const float) { return false;} virtual bool SetPortrait() { return false;} virtual bool SetLandscape() { return false;} virtual bool SetEncapsulated(bool val) { return false;} virtual bool SetBPP(const int bpp) { return false;} virtual bool Hide() { return false;} virtual bool CopyRegion(DLongGDL* me) { return false;} // Z buffer device virtual bool ZBuffering( bool yes) { return false;} virtual bool SetResolution( DLong nx, DLong ny) { return false;} // virtual bool SetCharacterSize( DLong x, DLong y) { return false;} virtual bool SetCharacterSize( DLong x, DLong y) { int tagx = dStruct->Desc()->TagIndex( "X_CH_SIZE"); int tagy = dStruct->Desc()->TagIndex( "Y_CH_SIZE"); DLongGDL* newxch = static_cast( dStruct->GetTag( tagx)); DLongGDL* newych = static_cast( dStruct->GetTag( tagy)); (*newxch)[0]=x; (*newych)[0]=y; int tagxppcm = dStruct->Desc()->TagIndex( "X_PX_CM"); int tagyppcm = dStruct->Desc()->TagIndex( "Y_PX_CM"); DFloat xppm = (*static_cast(dStruct->GetTag(tagxppcm)))[0]*0.1; DFloat yppm = (*static_cast(dStruct->GetTag(tagyppcm)))[0]*0.1; PLFLT newsize=x/xppm; PLFLT newSpacing=y/yppm; GDLGStream* actStream=GetStream(false); if( actStream != NULL) {actStream->setLineSpacing(newSpacing); actStream->RenewPlplotDefaultCharsize(newsize);} return true; } virtual void ClearStream( DLong bColor) { throw GDLException( "Device "+Name()+" does not support ClearStream."); } }; typedef std::vector< GDLGStream*> WindowListT; class GraphicsMultiDevice : public GraphicsDevice { private: public: int decomposed; // false -> use color table int cursorId; //should be 3 by default. long gcFunction; int backingStoreMode; DString fontname; int staticDisplay; int getCursorId(){return cursorId;} long getGCFunction(){return gcFunction;} int GetBackingStore(){return backingStoreMode;} bool isStatic(){return staticDisplay==1;} static int actWin; static WindowListT winList; static std::vector oList; static int oIx; static void Init(); GraphicsMultiDevice( int _decomposed, int _cursorId, long _gcFunction, int _backingStoreMode) : GraphicsDevice(), decomposed(_decomposed), cursorId(_cursorId), gcFunction(_gcFunction), backingStoreMode(_backingStoreMode), fontname(""), staticDisplay(1) { //pretty much nothing to do... } ~GraphicsMultiDevice() { WindowListT::iterator i; for (i = winList.begin(); i != winList.end(); ++i) if ((*i) != NULL) {delete *i; *i = NULL; } } DByteGDL* WindowState(); bool WState( int ix); int MaxWin(); void SetActWin(int wIx); void TidyWindowsList(); void RaiseWin(int wIx); void LowerWin(int wIx); void IconicWin(int wIx); void DeIconicWin(int wIx); void EventHandler(); bool WDelete(int wIx); bool WSize(int wIx, int *xSize, int *ySize); bool WSet(int wIx); bool WShow(int ix, bool show, int iconic); int WAddFree(); GDLGStream* GetStreamAt(int wIx) const; void ChangeStreamAt(int wIx, GDLGStream* newStream); bool UnsetFocus(); bool Decomposed(bool value); DLong GetDecomposed(); BaseGDL* GetFontnames(){ ThrowGDLException("DEVICE: Keyword GET_FONTNAMES not allowed for call to: DEVICE" );return NULL;} DLong GetFontnum(){ ThrowGDLException("DEVICE: Keyword GET_FONTNUM not allowed for call to: DEVICE" );return -1;} bool SetFont(DString f) {fontname=f; return true;} DString GetCurrentFont() {return fontname;} bool SetBackingStore(int value); bool Hide(); int MaxNonFreeWin(); int ActWin(); int GetNonManagedWidgetActWin(bool doTidyWindowList=true); bool CopyRegion(DLongGDL* me); virtual bool SetCharacterSize( DLong x, DLong y) { int tagx = dStruct->Desc()->TagIndex( "X_CH_SIZE"); int tagy = dStruct->Desc()->TagIndex( "Y_CH_SIZE"); DLongGDL* newxch = static_cast( dStruct->GetTag( tagx)); DLongGDL* newych = static_cast( dStruct->GetTag( tagy)); (*newxch)[0]=x; (*newych)[0]=y; WindowListT::iterator i; int tagxppcm = dStruct->Desc()->TagIndex( "X_PX_CM"); int tagyppcm = dStruct->Desc()->TagIndex( "Y_PX_CM"); DFloat xppm = (*static_cast(dStruct->GetTag(tagxppcm)))[0]*0.1; DFloat yppm = (*static_cast(dStruct->GetTag(tagyppcm)))[0]*0.1; PLFLT newsize=x/xppm; PLFLT newSpacing=y/yppm; for (i = winList.begin(); i != winList.end(); ++i) if ((*i) != NULL) {(*i)->setLineSpacing(newSpacing); (*i)->RenewPlplotDefaultCharsize(newsize);} return true; } }; #endif gdl-0.9.9/src/grib.cpp000066400000000000000000000242701340051421000145100ustar00rootroot00000000000000/*************************************************************************** grib.cpp - GRIB GDL library function ------------------- begin : Jan 18 2009 copyright : (C) 2009 by Sylwester Arabas email : slayoo@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have GRIB #define USE_GRIB 1 #endif #include "includefirst.hpp" #include "grib.hpp" #ifdef USE_GRIB # include # include #endif namespace lib { using namespace std; #ifdef USE_GRIB // GRIB file/handle lists implemented as a global maps // perhaps using the code in GRIB_API F90 interface would be better... ? map GribHandleList; map GribFileList; #endif /* * GRIB: FILE RELATED FUNCTIONS AND PROCEDURES */ BaseGDL* grib_open_file_fun(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); return NULL; #else { SizeT nParam = e->NParam(1); } DString filename; e->AssureScalarPar( 0, filename); FILE* in = NULL; // TODO: handle RO/RW parameters (but currently anyhow no write methods are implemented...) in = fopen(filename.c_str(), "r"); if (!in) e->Throw("unable to open file: " + filename); DLong ifile = GribFileList.end()->first; GribFileList[ifile] = in; return new DLongGDL(ifile); #endif } void grib_close_file_pro(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); #else { SizeT nParam = e->NParam(1); } DLong ifile; e->AssureScalarPar(0, ifile); if (GribFileList.find(ifile) == GribFileList.end()) e->Throw("unrecognized file id: " + i2s(ifile)); fclose(GribFileList[ifile]); GribFileList.erase(ifile); #endif } BaseGDL* grib_count_in_file_fun(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); return NULL; #else { SizeT nParam = e->NParam(1); } DLong ifile; e->AssureScalarPar(0, ifile); if (GribFileList.find(ifile) == GribFileList.end()) e->Throw("unrecognized file id: " + i2s(ifile)); int count; grib_count_in_file(NULL, GribFileList[ifile], &count); return new DIntGDL(count); #endif } /* * GRIB: MESSAGE RELATED FUNCTIONS AND PROCEDURES */ BaseGDL* grib_new_from_file_fun(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); return NULL; #else { SizeT nParam = e->NParam(1); } DLong ifile; e->AssureScalarPar(0, ifile); if (GribFileList.find(ifile) == GribFileList.end()) e->Throw("unrecognized file id: " + i2s(ifile)); grib_handle *h = NULL; int err = GRIB_SUCCESS; h = grib_handle_new_from_file(0, GribFileList[ifile], &err); if (h == NULL) e->Throw("unable get message using file id: " + i2s(ifile) + "\n" + "% GRIB API message: " + grib_get_error_message(err) ); DLong gribid = GribHandleList.end()->first; GribHandleList[gribid] = h; return new DLongGDL(gribid); #endif } BaseGDL* grib_clone_fun(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); return NULL; #else { SizeT nParam = e->NParam(1); } DLong gribid; e->AssureScalarPar(0, gribid); if (GribHandleList.find(gribid) == GribHandleList.end()) e->Throw("unrecognized message id: " + i2s(gribid)); DLong gribid_new = GribHandleList.end()->first; GribHandleList[gribid_new] = grib_handle_clone(GribHandleList[gribid]); if (GribHandleList[gribid_new] == NULL) e->Throw("failed to clone message: " + i2s(gribid)); return new DLongGDL(gribid_new); #endif } void grib_release_pro(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); #else { SizeT nParam = e->NParam(1); } DLong gribid; e->AssureScalarPar(0, gribid); if (GribHandleList.find(gribid) == GribHandleList.end()) e->Throw("unrecognized message id: " + i2s(gribid)); grib_handle_delete(GribHandleList[gribid]); GribHandleList.erase(gribid); #endif } /* BaseGDL* grib_get_message_size_fun(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); #else { SizeT nParam = e->NParam(1); } DLong gribid; e->AssureScalarPar(0, gribid); if (GribHandleList.find(gribid) == GribHandleList.end()) e->Throw("unrecognized message id: " + i2s(gribid)); e->Throw("not implemented yet..."); //return new DLongGDL(GribHandleList[gribid]->buffer->ulength); // the above will not work because grib_handle structure is defined // in an internal library header, not the grib_api.h. It might be // possible to get this info via fortran api function but then it // should be enclosed in #ifdef ... #endif as not everyone compiles // GRIB API with fortran support enabled... but is it that important? return new DLongGDL(-1); #endif } */ /* * GRIB: DATA RELATED FUNCTIONS AND PROCEDURES */ BaseGDL* grib_get_size_fun(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); return NULL; #else { SizeT nParam = e->NParam(2); } DLong gribid; e->AssureScalarPar(0, gribid); if (GribHandleList.find(gribid) == GribHandleList.end()) e->Throw("unrecognized message id: " + i2s(gribid)); DString key; e->AssureScalarPar(1, key); size_t size; int err = GRIB_SUCCESS; if (GRIB_SUCCESS != (err = grib_get_size(GribHandleList[gribid], key.c_str(), &size))) e->Throw("failed to get size of: " + key + "\n% GRIB API message: " + grib_get_error_message(err)); return new DLongGDL(size); #endif } void grib_get_pro(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); #else { SizeT nParam = e->NParam(3); } DLong gribid; e->AssureScalarPar(0, gribid); if (GribHandleList.find(gribid) == GribHandleList.end()) e->Throw("unrecognized message id: " + i2s(gribid)); DString key; e->AssureScalarPar(1, key); int err = GRIB_SUCCESS, type = GRIB_TYPE_UNDEFINED; if (GRIB_SUCCESS != (err = grib_get_native_type(GribHandleList[gribid], key.c_str(), &type))) e->Throw("failed to get type of: " + key + "\n% GRIB API message: " + grib_get_error_message(err)); size_t size; if (GRIB_SUCCESS != (err = grib_get_size(GribHandleList[gribid], key.c_str(), &size))) e->Throw("failed to get size of: " + key + "\n% GRIB API message: " + grib_get_error_message(err)); BaseGDL* data; switch (type) { case GRIB_TYPE_LONG: { if (size == 1) { data = new DLongGDL(0); err = grib_get_long(GribHandleList[gribid], key.c_str(), (long*)&(*(DLongGDL*)data)[0]); } else { data = new DLongGDL(dimension(size), BaseGDL::NOZERO); err = grib_get_long_array( GribHandleList[gribid], key.c_str(), (long*)&(*(DLongGDL*)data)[0], &size); } break; } case GRIB_TYPE_DOUBLE: { if (size == 1) { data = new DDoubleGDL(0); err = grib_get_double(GribHandleList[gribid], key.c_str(), (double*) &(*(DDoubleGDL*)data)[0]); } else { data = new DDoubleGDL(dimension(size), BaseGDL::NOZERO); err = grib_get_double_array( GribHandleList[gribid], key.c_str(), (double*) &(*(DDoubleGDL*)data)[0], &size); } break; } /* case GRIB_TYPE_STRING: { data = new DStringGDL(dim, BaseGDL::NOZERO); break; } case GRIB_TYPE_BYTES: { data = new DByteGDL(dim, BaseGDL::NOZERO); break; } */ default: e->Throw("unsupported native data type: " + string(grib_get_type_name(type)) + " (" + i2s(type) + ")"); } if (err != GRIB_SUCCESS) e->Throw("failed to get value[s] of: " + key + "\n% GRIB API message: " + grib_get_error_message(err)); GDLDelete(e->GetParGlobal(2)); e->GetPar(2) = data; #endif } void grib_get_data_pro(EnvT* e) { #ifndef USE_GRIB e->Throw("GDL was compiled without support for GRIB"); #else { // no more checking is needed as it will be done by get_data() SizeT nParam = e->NParam(4); } // substituting to make use of grib_get() GDLDelete(e->GetParGlobal(1)); e->GetPar(1) = new DStringGDL("values"); grib_get_pro(e); GDLDelete(e->GetParGlobal(3)); e->GetPar(3) = e->GetPar(2); DLong gribid; e->AssureScalarPar(0, gribid); // using the iterator from C interface to retrieve lats/lons int err = GRIB_SUCCESS; grib_iterator* iter = grib_iterator_new(GribHandleList[gribid], 0, &err); if (err != GRIB_SUCCESS) e->Throw("failed to iterate over lat/lons\n% GRIB API message: " + string(grib_get_error_message(err))); GDLDelete(e->GetPar(1)); e->GetPar(1) = new DDoubleGDL(((DDoubleGDL*)e->GetPar(3))->Size(), BaseGDL::NOZERO); e->GetPar(2) = new DDoubleGDL(((DDoubleGDL*)e->GetPar(3))->Size(), BaseGDL::NOZERO); double *lat = (double*) &(*(DDoubleGDL*)e->GetPar(1))[0]; double *lon = (double*) &(*(DDoubleGDL*)e->GetPar(2))[0]; double null; while (grib_iterator_next(iter, lat++, lon++, &null)); grib_iterator_delete(iter); #endif } } // namespace gdl-0.9.9/src/grib.hpp000066400000000000000000000031441340051421000145120ustar00rootroot00000000000000/*************************************************************************** grib.hpp - GRIB GDL library function ------------------- begin : Jan 18 2009 copyright : (C) 2009 by Sylwester Arabas email : slayoo@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GRIB_HPP_ #define GRIB_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { // file related: BaseGDL* grib_open_file_fun(EnvT* e); void grib_close_file_pro(EnvT* e); BaseGDL* grib_count_in_file_fun(EnvT* e); // message related: BaseGDL* grib_new_from_file_fun(EnvT* e); void grib_release_pro(EnvT* e); // see comment in grib.cpp // BaseGDL* grib_get_message_size_fun(EnvT* e); BaseGDL* grib_clone_fun(EnvT* e); // data related: BaseGDL* grib_get_size_fun(EnvT* e); void grib_get_pro(EnvT* e); void grib_get_data_pro(EnvT* e); } // namespace #endif gdl-0.9.9/src/gshhg.h000066400000000000000000000122701340051421000143270ustar00rootroot00000000000000/* $Id: gshhg.h,v 1.1 2014-09-19 02:30:28 pjb7687 Exp $ * * Include file defining structures used in the binary GSHHG files * * Paul Wessel, SOEST * * Copyright (c) 1996-2014 by P. Wessel and W. H. F. Smith * See LICENSE.TXT file for copying and redistribution conditions. * * 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; version 2 or 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. * * Contact info: www.soest.hawaii.edu/pwessel * * 14-SEP-2004. PW: Version 1.3. Header is now n * 8 bytes (n = 5) * For use with version 1.3 of GSHHG * 2-MAY-2006. PW: Version 1.4. Header is now 32 bytes (all int 4) * For use with version 1.4 of GSHHG * 31-MAR-2007. PW: Version 1.5. no format change * For use with version 1.5 of GSHHG * 28-AUG-2007. PW: Version 1.6. no format change * For use with version 1.6 of GSHHG which now has WDBII * borders and rivers. * 03-JUL-2008. PW: Version 1.11. New -I option to pull out a single pol * 27-MAY-2009. PW: Version 1.12. Now includes container polygon ID in header, * an ancestor ID, and area of the reduced polygon. Works on * GSHHG 2.0 data. * Header is now 44 bytes (all 4-byte integers) * 24-MAY-2010. PW: Data version is now 2.1.0. [no change to format] * 15-JUL-2011. PW: Data version is now 2.2.0. [Change in header format to store * area magnitude and let greenwich be 2-bit flag (0-3)]. Also * flag WDBII riverlakes with the river flag as used for GSHHG. * 15-APR-2012. PW: Data version is now 2.2.1. [no change to format] * 1-JAN-2013. PW: Data version is now 2.2.2. [no change to format] * 1-JUL-2013. PW: Data version is now 2.2.3. [no change to format] * 1-NOV-2013: PW: Data version is now 2.2.4. [no change to format] * 1-MAR-2014. PW: Data version is now 2.3.0. [no change to format]. This version * adds new Antarctica coastlines from the Atlas of the Cryosphere (AC) and * has grounding line as Level = 5 and ice-front line as Level = 6. * Only use one of those two Levels and consider either to be Level = 1. * 1-JUL-2014. PW: Data version is now 2.3.1. [no change to format] * * The format of binary GSHHG files are simply sequential: * [ Item Header 0 ] * [ Point 1 ] * [ Point 2 ] * [ ....... ] * [ Point n0 ] * [ Item Header 1 ] * [ Point 1 ] * [ Point 2 ] * [ ....... ] * [ Point n1 ] * [ Item Header 2 ] * etc etc. * * Each header is contained in a GSHHG_HEADER struct and each point is contained in a GSHHG_POINT struct. * These two structures are defined below, together with the scalefactor that converts micro-degrees to degrees. * * Note: Antarctica shorelines/islands come in two flavors: Grounding Line or IceFront Line. These are both * present in the database but given levels of 5 and 6 respectively, to uniquely identify them. Developers * should decide (or have their users decide via an option) which flavor to use. For further processing these * polygons should be thought of as level = 1 like any other shoreline. */ #ifndef _GSHHG #define _GSHHG #ifdef _MSC_VER typedef __int32 int32_t; typedef unsigned __int32 uint32_t; #else #include #endif #define GSHHG_SCL 1.0e-6 /* Convert micro-degrees to degrees */ struct GSHHG_HEADER { /* Global Self-consistent Hierarchical High-resolution Shorelines */ uint32_t id; /* Unique polygon id number, starting at 0 */ uint32_t n; /* Number of points in this polygon */ uint32_t flag; /* = level + version << 8 + greenwich << 16 + source << 24 + river << 25 + p << 26 */ /* flag contains 6 items, as follows: * low byte: level = flag & 255: Values: 1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake, 5 Antarctic Ice-front, 6 Antarctic grounding line. * 2nd byte: version = (flag >> 8) & 255: Values: Should be 9 for GSHHG release 9. * 3rd byte: greenwich = (flag >> 16) & 3: Values: 0 if Greenwich nor Dateline are crossed, * 1 if Greenwich is crossed, 2 if Dateline is crossed, 3 if both is crossed. * 4th byte: source = (flag >> 24) & 1: Values: 0 = CIA WDBII, 1 = WVS. If level = 5,6 then source is instad AC * 4th byte: river = (flag >> 25) & 1: Values: 0 = not set, 1 = river-lake and GSHHG level = 2 (or WDBII class 0) * 4th byte: area magnitude scale p (as in 10^p) = flag >> 26. We divide area by 10^p. */ int32_t west, east, south, north; /* Signed min/max extent in micro-degrees */ uint32_t area; /* Area of polygon in km^2 * 10^p for this resolution file */ uint32_t area_full; /* Area of corresponding full-resolution polygon in km^2 * 10^p */ int32_t container; /* Id of container polygon that encloses this polygon (-1 if none) */ int32_t ancestor; /* Id of ancestor polygon in the full resolution set that was the source of this polygon (-1 if none) */ }; struct GSHHG_POINT { /* Each lon, lat pair is stored in micro-degrees in 4-byte signed integer format */ int32_t x; int32_t y; }; #endif /* _GSHHG */ gdl-0.9.9/src/gshhs.cpp000066400000000000000000000273061340051421000147040ustar00rootroot00000000000000/*************************************************************************** gshhs.cpp - GSHHS-related routines ------------------- begin : Apr 18 2010 copyright : (C) 2010 by Sylwester Arabas based on the GPL-licensed code (see note below) by P. Wessel and W. H. F. Smith email : slayoo@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have GSHHS #define USE_GSHHS 1 #endif #if defined(USE_LIBPROJ4)||defined(USE_LIBPROJ4_NEW) #include "includefirst.hpp" #include "plotting.hpp" #include "math_utl.hpp" #include "initsysvar.hpp" #ifdef USE_GSHHS #include "gshhs.h" #endif #define DPI (double)(4*atan(1.0)) #define DEGTORAD DPI/180.0 namespace lib { using namespace std; class map_continents_call: public plotting_routine_call { bool doT3d; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd; DDouble zValue; DDoubleGDL* plplot3d; Guard plplot3d_guard; ORIENTATION3D axisExchangeCode; DDouble az, alt, ay, scale; private: bool handle_args( EnvT* e ) { //T3D doT3d=(e->KeywordSet("T3D") || T3Denabled()); return true; } private: void old_body( EnvT* e, GDLGStream * actStream ) { #ifndef USE_GSHHS e->Throw( "GDL was compiled without support for GSHHS" ); #else static struct GSHHS_POINT p; bool externalMap; bool mapSet; // Get MATRIX DStructGDL* map = GetMapAsMapStructureKeyword( e, externalMap); if (!externalMap){ get_mapset(mapSet); if (!mapSet) e->Throw( "Map transform not established." ); } ref = map_init( map ); if ( ref == NULL ) { e->Throw( "Projection initialization failed." ); } #ifdef USE_LIBPROJ4 LPTYPE idata; XYTYPE odata; #endif static int continentsIx = e->KeywordIx( "CONTINENTS" ); bool kw_continents = true; //by default, plot continents even if no kw static int riversIx = e->KeywordIx( "RIVERS" ); bool kw_rivers = e->KeywordSet( riversIx ); if ( kw_rivers ) kw_continents = e->KeywordSet( continentsIx ); static int countriesIx = e->KeywordIx( "COUNTRIES" ); bool kw_countries = e->KeywordSet( countriesIx ); if ( kw_countries ) kw_continents = e->KeywordSet( continentsIx ); static int usaIx = e->KeywordIx( "USA" ); bool kw_usa = e->KeywordSet( usaIx ); if ( kw_usa ) kw_continents = e->KeywordSet( continentsIx ); static int coastsIx = e->KeywordIx( "COASTS" ); bool kw_coasts = e->KeywordSet( coastsIx ); if ( kw_coasts ) kw_continents = e->KeywordSet( continentsIx ); static int hiresIx = e->KeywordIx( "HIRES" ); bool kw_hires = e->KeywordSet( hiresIx ); static int fillIx = e->KeywordIx( "FILL_CONTINENTS" ); bool kw_fill = e->KeywordSet( fillIx ); if ( kw_fill ) kw_continents = true; string dir = SysVar::GshhsDir(); enum set { continents, countries, rivers, coasts }; string sufix = kw_hires ? "_h.b" : "_c.b"; //easy: should improve resolution based on actual size of exposed area and screen resolution!! // TODO: use mmap! vector files( 4 ); files[continents] = dir + "gshhs" + sufix; files[countries] = dir + "wdb_borders" + sufix; files[rivers] = dir + "wdb_rivers" + sufix; files[coasts] = dir + "gshhs" + sufix; bool do_fill = false; //get DATA limits (not necessary CRANGE, see AXIS / SAVE behaviour!) GetCurrentUserLimits(actStream, xStart, xEnd, yStart, yEnd); // get !Z.CRANGE gdlGetCurrentAxisRange("Z", zStart, zEnd); if ( doT3d ) { //if X,Y and Z are passed, we will use !P.T and not our plplot "interpretation" of !P.T //if the x and y scaling is OK, using !P.T directly permits to use other projections //than those used implicitly by plplot. See @showhaus example for *DL // case where we project 2D data on 3D: use plplot-like matrix. static DDouble x0,y0,xs,ys; //conversion to normalized coords x0=-xStart; y0=-yStart; xs=xEnd-xStart;xs=1.0/xs; ys=yEnd-yStart;ys=1.0/ys; // here zvalue here is zcoord on Z axis, to be scaled between 0 and 1 for compatibility with call of gdlConvertT3DMatrixToPlplotRotationMatrix() zValue /= (zEnd - zStart); plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix(zValue, az, alt, ay, scale, axisExchangeCode); Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0 = x0; Data3d.y0 = y0; Data3d.xs = xs; Data3d.ys = ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } actStream->stransform(gdl3dTo2dTransform, &Data3d); } else { actStream->OnePageSaveLayout(); // do not use in projections actStream->NoSub( ); DDouble *sx, *sy; GetSFromPlotStructs( &sx, &sy ); DFloat *wx, *wy; GetWFromPlotStructs( &wx, &wy ); DDouble pxStart, pxEnd, pyStart, pyEnd; DataCoordLimits( sx, sy, wx, wy, &pxStart, &pxEnd, &pyStart, &pyEnd, true ); actStream->vpor( wx[0], wx[1], wy[0], wy[1] ); actStream->wind( pxStart, pxEnd, pyStart, pyEnd ); } gdlSetGraphicsForegroundColorFromKw( e, actStream ); for ( int i = 0; i < files.size( ); ++i ) { if ( i == countries && !kw_countries && !kw_usa ) continue; if ( i == rivers && !kw_rivers ) continue; if ( i == continents && !kw_continents ) continue; if ( i == coasts && !kw_coasts ) continue; do_fill = (kw_fill && i == continents); // TODO: coasts, continents FILE *fp = NULL; if ( (fp = fopen( files[i].c_str( ), "rb" )) == NULL ) { actStream->RestoreLayout(); e->Throw( "GSHHS: Could not open file: " + files[i] ); } FILEGuard fpGuard( fp, fclose ); struct GSHHS h; int n_read = fread( (void *) &h, (size_t)sizeof (struct GSHHS), (size_t) 1, fp ); int version = (h.flag >> 8) & 255; int flip = (version != GSHHS_DATA_RELEASE); /* Take as sign that byte-swapping is needed */ int max_east = 270000000; while ( n_read == 1 ) { if ( flip ) { h.id = swabi4( (unsigned int) h.id ); h.n = swabi4( (unsigned int) h.n ); h.west = swabi4( (unsigned int) h.west ); h.east = swabi4( (unsigned int) h.east ); h.south = swabi4( (unsigned int) h.south ); h.north = swabi4( (unsigned int) h.north ); h.area = swabi4( (unsigned int) h.area ); h.area_full = swabi4( (unsigned int) h.area_full ); h.flag = swabi4( (unsigned int) h.flag ); h.container = swabi4( (unsigned int) h.container ); h.ancestor = swabi4( (unsigned int) h.ancestor ); } int level = h.flag & 255; // Level is 1-4 version = (h.flag >> 8) & 255; // Version is 1-7 int greenwich = (h.flag >> 16) & 1; // Greenwich is 0 or 1 int src = (h.flag >> 24) & 1; // Greenwich is 0 (WDBII) or 1 (WVS) int river = (h.flag >> 25) & 1; // River is 0 (not river) or 1 (is river) double ww = h.west * GSHHS_SCL; // Convert from microdegrees to degrees double ee = h.east * GSHHS_SCL; double ss = h.south * GSHHS_SCL; double nn = h.north * GSHHS_SCL; char source = (src == 1) ? 'W' : 'C'; // Either WVS or CIA (WDBII) pedigree if ( river ) source = tolower( (int) source ); // Lower case c means river-lake int line = (h.area) ? 0 : 1; // Either Polygon (0) or Line (1) (if no area) double area = 0.1 * h.area; // Now im km^2 double f_area = 0.1 * h.area_full; // Now im km^2 bool skip = false; if ( i == continents && line ) skip = true; if ( do_fill && line ) skip = true; if ( i == continents && river ) skip = true; if ( i == continents && (level > 1) ) skip = true; if ( i == countries && (level > 2) ) skip = true; if ( i == countries && !kw_usa && (level > 1) ) skip = true; if ( i == countries && kw_usa && !kw_countries && (level < 2) ) skip = true; if ( i == coasts && level > 2 ) skip = true; if ( i == coasts && !kw_hires && area < 100.0 ) skip = true; if ( i == rivers && (level > 4) ) skip = true; if ( skip ) { if ( fseek( fp, (long) (h.n * sizeof (struct GSHHS_POINT)), SEEK_CUR ) != 0 ) { actStream->RestoreLayout(); e->Throw( "Error reading file" + files[i] + " for " + (line ? "line" : "polygon") + i2s( h.id ) ); } } else { DDoubleGDL *lons, *lats; lons = new DDoubleGDL( h.n, BaseGDL::NOZERO ); lats = new DDoubleGDL( h.n, BaseGDL::NOZERO ); for ( SizeT k = 0; k < h.n; k++ ) { if ( fread( (void *) &p, (size_t)sizeof (struct GSHHS_POINT), (size_t) 1, fp ) != 1 ) { actStream->RestoreLayout(); e->Throw( "Error reading file" + files[i] + " for " + (line ? "line" : "polygon") + i2s( h.id ) + ", point " + i2s( k ) ); } // byte order if ( flip ) { p.x = swabi4( (unsigned int) p.x ); p.y = swabi4( (unsigned int) p.y ); } (*lons)[k] = p.x * GSHHS_SCL; if ( (greenwich && p.x > max_east) || (h.west > 180000000) ) ( *lons )[k] -= 360.0; (*lats)[k] = p.y * GSHHS_SCL; } GDLgrProjectedPolygonPlot(actStream, ref, map, lons, lats, false, do_fill, NULL); max_east = 180000000; /* Only Eurasia needs 270 */ GDLDelete( lons ); GDLDelete( lats ); } n_read = fread( (void *) &h, (size_t)sizeof (struct GSHHS), (size_t) 1, fp ); } } actStream->lsty( 1 ); //reset linestyle // // reset the viewport and world coordinates to the original values if (!doT3d) actStream->RestoreLayout(); #endif } // old_body private: void call_plplot( EnvT* e, GDLGStream * actStream ) { } private: void post_call( EnvT* e, GDLGStream * actStream ) { if (doT3d) { plplot3d_guard.Reset(plplot3d); actStream->stransform(NULL,NULL); } } }; // class definition void map_continents( EnvT* e ) { #if defined(USE_LIBPROJ4) || defined(USE_LIBPROJ4_NEW) map_continents_call map_continents; map_continents.call( e, 0 ); #else Throw("GDL was compiled without Proj4 ou LibProj4 ... no cartography !"); #endif } } // namespace #endif gdl-0.9.9/src/gshhs.h000066400000000000000000000105531340051421000143450ustar00rootroot00000000000000/* $Id: gshhs.h,v 1.3 2014-09-19 15:43:59 gilles-duvert Exp $ * * Include file defining structures used in gshhs.c * * Paul Wessel, SOEST * * Copyright (c) 1996-2011 by P. Wessel and W. H. F. Smith * See LICENSE.TXT file for copying and redistribution conditions. * * 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; version 2 or 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. * * Contact info: www.soest.hawaii.edu/pwessel * * 14-SEP-2004. PW: Version 1.3. Header is now n * 8 bytes (n = 5) * For use with version 1.3 of GSHHS * 2-MAY-2006. PW: Version 1.4. Header is now 32 bytes (all int 4) * For use with version 1.4 of GSHHS * 31-MAR-2007. PW: Version 1.5. no format change * For use with version 1.5 of GSHHS * 28-AUG-2007. PW: Version 1.6. no format change * For use with version 1.6 of GSHHS which now has WDBII * borders and rivers. * 03-JUL-2008. PW: Version 1.11. New -I option to pull out a single pol * 27-MAY-2009. PW: Version 1.12. Now includes container polygon ID in header, * an ancestor ID, and area of the reduced polygon. Works on * GSHHS 2.0 data. * Header is now 44 bytes (all 4-byte integers) * 24-MAY-2010. PW: Data version is now 2.1.0. [no change to format] * 15-JUL-2011. PW: Data version is now 2.2.0. [Change in header format to store * area magnitude and let greenwich be 2-bit flag (0-3)]. Also * flag WDBII riverlakes with the river flag as used for GSHHS. */ /* * Modified by GDL team (renamed POINT to GSHHS_POINT to avoid conflict with a POINT structure present in Windows API (?) * Certainly there is a better way to handle this problem, but we are a bit at loss here... */ #ifndef _GSHHS #define _GSHHS #define _POSIX_SOURCE 1 /* GSHHS code is POSIX compliant */ #include #include #include #include #ifdef WIN32 #pragma warning( disable : 4996 ) #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef SEEK_CUR /* For really ancient systems */ #define SEEK_CUR 1 #endif #define GSHHS_DATA_RELEASE 9 /* For v2.2.0 data set */ #define GSHHS_DATA_VERSION "2.2.0" /* For v2.2.0 data set */ #define GSHHS_PROG_VERSION "1.13" #define GSHHS_SCL 1.0e-6 /* Convert micro-degrees to degrees */ /* For byte swapping on little-endian systems (GSHHS is defined to be bigendian) */ #define swabi4(i4) (((i4) >> 24) + (((i4) >> 8) & 65280) + (((i4) & 65280) << 8) + (((i4) & 255) << 24)) struct GSHHS { /* Global Self-consistent Hierarchical High-resolution Shorelines */ int id; /* Unique polygon id number, starting at 0 */ int n; /* Number of points in this polygon */ int flag; /* = level + version << 8 + greenwich << 16 + source << 24 + river << 25 + p << 26 */ /* flag contains 6 items, as follows: * low byte: level = flag & 255: Values: 1 land, 2 lake, 3 island_in_lake, 4 pond_in_island_in_lake * 2nd byte: version = (flag >> 8) & 255: Values: Should be 9 for GSHHS release 9 * 3rd byte: greenwich = (flag >> 16) & 3: Values: 0 if Greenwich nor Dateline are crossed, * 1 if Greenwich is crossed, 2 if Dateline is crossed, 3 if both is crossed. * 4th byte: source = (flag >> 24) & 1: Values: 0 = CIA WDBII, 1 = WVS * 4th byte: river = (flag >> 25) & 1: Values: 0 = not set, 1 = river-lake and GSHHS level = 2 (or WDBII level 0) * 4th byte: area magnitude scale p (as in 10^p) = flag >> 26. We divide area by 10^p. */ int west, east, south, north; /* min/max extent in micro-degrees */ int area; /* Area of polygon in km^2 * 10^p for this resolution file */ int area_full; /* Area of corresponding full-resolution polygon in km^2 * 10^p */ int container; /* Id of container polygon that encloses this polygon (-1 if none) */ int ancestor; /* Id of ancestor polygon in the full resolution set that was the source of this polygon (-1 if none) */ }; struct GSHHS_POINT { /* Each lon, lat pair is stored in micro-degrees in 4-byte integer format */ int x; int y; }; #endif /* _GSHHS */ gdl-0.9.9/src/gshhs.hpp000066400000000000000000000022421340051421000147010ustar00rootroot00000000000000/*************************************************************************** gshhs.hpp - GSHHS-related routines ------------------- begin : Apr 18 2010 copyright : (C) 2010 by Sylwester Arabas email : slayoo@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef GSHHS_HPP_ #define GSHHS_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { void map_continents(EnvT* e); } // namespace #endif gdl-0.9.9/src/gsl_fun.cpp000066400000000000000000004401221340051421000152200ustar00rootroot00000000000000/*************************************************************************** gsl_fun.cpp - GDL GSL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include //fx_root #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "gsl_fun.hpp" #include "dinterpreter.hpp" #ifdef _MSC_VER #include "gtdhelper.hpp" //for gettimeofday() #else #include #endif // ms: must not be inlcuded here //#include "libinit_ac.cpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // newton/broyden #include #include // numerical integration (alternative to Qromb) #include // constant #include #include #include #ifdef USE_UDUNITS # ifdef HAVE_UDUNITS2_UDUNITS2_H # include # else # include # endif #endif // binomialcoef #include // wtn #ifndef GSL_DISABLE_DEPRECATED # define GSL_DISABLE_DEPRECATED # include # undef GSL_DISABLE_DEPRECATED #else # include #endif #include // zeropoly #include // spher_harm #include //interpolate #include #include "interp_multid.h" #include "nullgdl.hpp" //#include "gsl_errorhandler.hpp" #define LOG10E 0.434294 #ifdef _MSC_VER #define isnan _isnan #define isfinite _finite #endif namespace lib { using namespace std; #ifndef _MSC_VER using std::isnan; #endif const int szdbl=sizeof(double); const int szflt=sizeof(float); class SetTemporaryGSLErrorHandlerT { gsl_error_handler_t* oldHandler; public: SetTemporaryGSLErrorHandlerT( gsl_error_handler_t* handler) { oldHandler = gsl_set_error_handler( handler); } ~SetTemporaryGSLErrorHandlerT() { gsl_set_error_handler( oldHandler); } }; void GDLGenericGSLErrorHandler(const char* reason, const char* file, int line, int gsl_errno) { throw GDLException( "GSL Error #" + i2s(gsl_errno) + ": " + string(reason));// + " file: " + file + " line: " + i2s(line)); } void SetGDLGenericGSLErrorHandler() { gsl_set_error_handler( GDLGenericGSLErrorHandler); } template< typename T1, typename T2> int cp2data2_template( BaseGDL* p0, T2* data, SizeT nEl, SizeT offset, SizeT stride_in, SizeT stride_out) { T1* p0c = static_cast( p0); for( SizeT i=0; i int cp2data_template( BaseGDL* p0, T* data, SizeT nEl, SizeT offset, SizeT stride_in, SizeT stride_out) { switch ( p0->Type()) { case GDL_DOUBLE: cp2data2_template< DDoubleGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; case GDL_FLOAT: cp2data2_template< DFloatGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; case GDL_LONG: cp2data2_template< DLongGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; case GDL_ULONG: cp2data2_template< DULongGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; case GDL_INT: cp2data2_template< DIntGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; case GDL_UINT: cp2data2_template< DUIntGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; case GDL_BYTE: cp2data2_template< DByteGDL, T>( p0, data, nEl, offset, stride_in, stride_out); break; default: std::cerr<<"internal error, please report."< int unpack_real_mxradix_template(T *dptr, SizeT nEl, double direct, SizeT offset, SizeT stride) { if (direct == -1) { for( SizeT i=0; i int real_fft_transform_template(BaseGDL* p0, T *dptr, SizeT nEl, double direct, SizeT offset, SizeT stride_in, SizeT stride_out, SizeT radix2, int (*complex_radix2_forward) (T[], const size_t, size_t), int (*complex_radix2_backward) (T[], const size_t, size_t), int (*real_transform) (T[], const size_t, size_t, const T1*, T2*), T1 *(*wavetable_alloc)(size_t), T2 *(*workspace_alloc)(size_t), void (*wavetable_free)(T1*), void (*workspace_free)(T2*)) { cp2data_template< T>( p0, dptr, nEl, offset, stride_in, stride_out); if (radix2) { if (direct == -1) { (*complex_radix2_forward) (&dptr[2*offset], stride_out, nEl); for( SizeT i=0; i &) dptr[2*(i*stride_out+offset)]) /= nEl; } else if (direct == +1) { (*complex_radix2_backward) (&dptr[2*offset], stride_out, nEl); } } else if (!radix2) { T1 *wave; T2 *work; work = (*workspace_alloc) (nEl); GDLGuard g1( work, workspace_free); wave = (*wavetable_alloc) (nEl); GDLGuard g2( wave, wavetable_free); (*real_transform) (&dptr[2*offset], 2*stride_out, nEl, wave, work); unpack_real_mxradix_template< T>( dptr, nEl, direct, offset, stride_out); // (*workspace_free) (work); // (*wavetable_free) (wave); } return 0; } template< typename T, typename T1, typename T2> int complex_fft_transform_template(BaseGDL* p0, T *dptr, SizeT nEl, double direct, SizeT offset, SizeT stride, SizeT radix2, int (*complex_radix2_forward) (T[], const size_t, size_t), int (*complex_radix2_backward) (T[], const size_t, size_t), int (*complex_forward_transform) (T[], const size_t, size_t, const T1*, T2*), int (*complex_backward_transform) (T[], const size_t, size_t, const T1*, T2*), T1 *(*wavetable_alloc)(size_t), T2 *(*workspace_alloc)(size_t), void (*wavetable_free)(T1*), void (*workspace_free)(T2*)) { if (radix2) { if (direct == -1) { (*complex_radix2_forward) (&dptr[2*offset], stride, nEl); for( SizeT i=0; i &) dptr[2*(i*stride+offset)]) /= nEl; } else if (direct == +1) { (*complex_radix2_backward) (&dptr[2*offset], stride, nEl); } } else if (!radix2) { T1 *wave; T2 *work; work = (*workspace_alloc) (nEl); GDLGuard g1( work, workspace_free); wave = (*wavetable_alloc) (nEl); GDLGuard g2( wave, wavetable_free); if (direct == -1) { (*complex_forward_transform) (&dptr[2*offset], stride, nEl, wave, work); for( SizeT i=0; i &) dptr[2*stride*i+2*offset]) /= nEl; } else if (direct == +1) { (*complex_backward_transform) (&dptr[2*offset], stride, nEl, wave, work); } // (*workspace_free) (work); // (*wavetable_free) (wave); } return 0; } template < typename T> T* fft_template(EnvT* e,BaseGDL* p0, SizeT nEl, SizeT dbl, SizeT overwrite, double direct, DLong dimension) { SizeT offset; SizeT stride=1; T* res; T* tabtemp=new T(p0->Dim()); Guard tabtempGuard( tabtemp); Guard resGuard; if (overwrite == 0) { res = new T( p0->Dim(), BaseGDL::ZERO); resGuard.Reset( res); } else { res = (T*) p0; if( e->GlobalPar(0)) e->SetPtrToReturnValue(&e->GetPar(0)); } DComplexGDL* tabfft = new DComplexGDL(p0->Dim()); Guard tabfftGuard( tabfft); DComplexGDL* p0C = static_cast (p0->Convert2( GDL_COMPLEX, BaseGDL::COPY)); Guard p0CGuard( p0C); int dec=0; int temp=0; int flag=0; int l=0; int tab[MAXRANK]; for (int y=0;yRank();y++) tab[y]=0; if(dimension >= 0) { // contact for this part (dim > 0) is Mathieu P. or Alain C. // Debut demontage tab l=0; for(int j=0;jDim(dimension);j++) { dec=0; flag=0; for(int n=0;nRank();n++) { if(tab[n]!=tabfft->Dim(n)-1 && flag==0 && n!=dimension && l!=0) { tab[n]++; //cout << "tab[" << n << "] = " << tab[n] << endl; flag=1; } else if(tab[n]==tabfft->Dim(n)-1 && flag==0 && n!=dimension && l!=0) tab[n]=0; temp=1; if(n!=0) { for(int m=n-1;m>=0;m--) { temp=temp*tabfft->Dim(m); } } //cout << "temp = " << temp << endl; dec=dec+tab[n]*temp; //cout << "dec = " << dec << endl; } temp=1; for(int y=dimension-1;y>=0;y--) { temp=temp*tabfft->Dim(y); } for(int i=0; iDim(dimension);i++) { (*tabfft)[l]=(*p0C)[dec+i*temp]; //cout << l << "=" << dec+i*temp << endl; l++; } } // Fin demontage tab - Debut res temp=1; for(int y=0;yRank();y++) { if(y!=dimension) temp=temp*tabfft->Dim(y); } for(int i=0;iDim(dimension); fft_1d(tabfft, &(*tabtemp)[0], tabfft->Dim(dimension), offset, stride, direct, dbl,1); } // Fin res - Debut remontage for (int y=0;yRank();y++) tab[y]=0; l=0; for(int j=0;jDim(dimension);j++) { dec=0; flag=0; for(int n=0;nRank();n++) { if(tab[n]!=tabfft->Dim(n)-1 && flag==0 && n!=dimension && l!=0) { tab[n]++; //cout << "tab[" << n << "] = " << tab[n] << endl; flag=1; } else if(tab[n]==tabfft->Dim(n)-1 && flag==0 && n!=dimension && l!=0) tab[n]=0; temp=1; if(n!=0) { for(int m=n-1;m>=0;m--) { temp=temp*tabfft->Dim(m); } } //cout << "temp = " << temp << endl; dec=dec+tab[n]*temp; //cout << "dec = " << dec << endl; } temp=1; for(int y=dimension-1;y>=0;y--) { temp=temp*tabfft->Dim(y); } for(int i=0; iDim(dimension);i++) { (*res)[dec+i*temp]=(*tabtemp)[l]; //cout << l << "=" << dec+i*temp << endl; l++; } } } else { dimension=0; if( p0->Rank() == 1) { offset=0; stride=1; fft_1d( p0, &(*res)[0], nEl, offset, stride, direct, dbl, dimension); } else if ( p0->Rank() == 2) { stride=p0->Dim(0); for( SizeT i=0; iDim(0); ++i) { fft_1d( p0, &(*res)[0], p0->Dim(1), i, stride, direct, dbl, dimension); } for( SizeT i=0; iDim(1); ++i) { fft_1d( res, &(*res)[0], p0->Dim(0), i*p0->Dim(0), 1, direct, dbl, dimension); } } else if( p0->Rank() >= 3) { unsigned char *used = new unsigned char [nEl]; ArrayGuard usedGuard( used); stride = nEl; for( SizeT i=p0->Rank(); iRank(); k>0; --k) { for( SizeT i=0; iDim(k-1); SizeT cnt=1; offset = 0; while(cnt <= nEl/p0->Dim(k-1)) { if (used[offset] != 1) { cnt++; for( SizeT i=0; iDim(k-1); ++i) used[offset+i*stride] = 1; if (k == p0->Rank()) fft_1d( p0, &(*res)[0], p0->Dim(k-1), offset, stride, direct, dbl, dimension); else fft_1d( res, &(*res)[0], p0->Dim(k-1), offset, stride, direct, dbl, dimension); } offset++; } } // delete used; } } resGuard.release(); return res; } BaseGDL* fft_fun( EnvT* e) { static bool warning_done=false; /* Program Flow ------------ fft_fun fft_template fft_1d (real/complex)_fft_transform_template cp2data_template (real only) cp2data_2_template (real only) */ SizeT nParam=e->NParam(); SizeT overwrite=0, dbl=0; SizeT stride; SizeT offset; double direct=-1.0; if( nParam == 0) e->Throw( "Incorrect number of arguments."); //BaseGDL* p0 = e->GetNumericArrayParDefined( 0); BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: "+e->GetParString(0)); if( nParam == 2) { BaseGDL* p1 = e->GetPar( 1); if (p1->N_Elements() > 1) e->Throw( "Expression must be a scalar or 1 element array: " +e->GetParString(1)); DDoubleGDL* direction = static_cast(p1->Convert2( GDL_DOUBLE, BaseGDL::COPY)); direct = GSL_SIGN((*direction)[0]); } if( e->KeywordSet(0)) dbl = 1; if( e->KeywordSet(1)) direct = +1.0; if( e->KeywordSet(2)) overwrite = 1; if( e->KeywordSet(4) && !warning_done) { warning_done=true; cerr<<"Warning, keyword CENTER ignored, fixme!"<KeywordIx("DIMENSION"); if (e->KeywordSet(DimEnvIx)) { BaseGDL* DimOfDim = e->GetKW(DimEnvIx); if (DimOfDim->N_Elements() > 1) e->Throw("Expression must be a scalar or 1 element array in this context:"); e->AssureLongScalarKW(DimEnvIx, dimension); if ((dimension < 0) || (dimension > p0->Rank())) { e->Throw("Illegal keyword value for DIMENSION."); } } // AC 07/09/2012: Mathieu did it like that and we checked ! // in fact, here dimension should always be >=0 dimension--; if( p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_DOUBLE || dbl) { //cout << "if 1" << endl; if( overwrite) e->StealLocalPar(0); // only steals if local par // e->StealLocalParUndefGlobal(0); // AC 10-09-2012: temporary fix dbl=1; return fft_template< DComplexDblGDL> (e, p0, nEl, dbl, overwrite, direct, dimension); } else if( p0->Type() == GDL_COMPLEX) { //cout << "if 2" << endl; DComplexGDL* res; if( overwrite) e->StealLocalPar(0); // only steals if local par // e->StealLocalParUndefGlobal(0); return fft_template< DComplexGDL> (e, p0, nEl, dbl, overwrite, direct, dimension); } else if (p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_INT || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { //cout << "if 3" << endl; overwrite = 0; return fft_template< DComplexGDL> (e, p0, nEl, dbl, overwrite, direct, dimension); } else { //cout << "else" << endl; overwrite = 0; DComplexGDL* p0C = static_cast (p0->Convert2( GDL_COMPLEX, BaseGDL::COPY)); Guard guard_p0C( p0C); return fft_template< DComplexGDL> (e, p0C, nEl, dbl, overwrite, direct,dimension); } } int fft_1d( BaseGDL* p0, void* data, SizeT nEl, SizeT offset, SizeT stride, double direct, SizeT dbl, DLong dimension) { float f32[2]; double f64[2]; // Determine if radix2 SizeT radix2 = 0; for( SizeT i=0; i<32; ++i) { if (nEl == (2 << i)) { radix2 = 1; break; } } // Determine input stride SizeT stride_in=1; if (dimension > 0) for( SizeT i=0; iDim(i); else stride_in = stride; if( p0->Type() == GDL_COMPLEX && dbl == 0) { DComplexGDL* p0C = static_cast( p0); float *dptr; dptr = (float*) data; if (dimension > 0) { for( SizeT i=0; i (p0, dptr, nEl, direct, offset, stride, radix2, gsl_fft_complex_float_radix2_forward, gsl_fft_complex_float_radix2_backward, gsl_fft_complex_float_forward, gsl_fft_complex_float_backward, gsl_fft_complex_wavetable_float_alloc, gsl_fft_complex_workspace_float_alloc, gsl_fft_complex_wavetable_float_free, gsl_fft_complex_workspace_float_free); return 0; } else if( p0->Type() == GDL_COMPLEXDBL || (p0->Type() == GDL_COMPLEX && dbl)) { DComplexDblGDL* p0C = static_cast( p0); DComplexGDL* p0CF = static_cast( p0); double *dptr; dptr = (double*) data; if( p0->Type() == GDL_COMPLEXDBL) { for( SizeT i=0; iType() == GDL_COMPLEX) { DComplexDbl c128; for( SizeT i=0; i (p0, dptr, nEl, direct, offset, stride, radix2, gsl_fft_complex_radix2_forward, gsl_fft_complex_radix2_backward, gsl_fft_complex_forward, gsl_fft_complex_backward, gsl_fft_complex_wavetable_alloc, gsl_fft_complex_workspace_alloc, gsl_fft_complex_wavetable_free, gsl_fft_complex_workspace_free); return 0; } else if( p0->Type() == GDL_DOUBLE || dbl) { double *dptr; dptr = (double*) data; real_fft_transform_template (p0, dptr, nEl, direct, offset, stride_in, stride, radix2, gsl_fft_complex_radix2_forward, gsl_fft_complex_radix2_backward, gsl_fft_real_transform, gsl_fft_real_wavetable_alloc, gsl_fft_real_workspace_alloc, gsl_fft_real_wavetable_free, gsl_fft_real_workspace_free); // printf("real_fft_transform_template\n"); return 0; } else if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_INT || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { float *dptr; dptr = (float*) data; real_fft_transform_template (p0, dptr, nEl, direct, offset, stride_in, stride, radix2, gsl_fft_complex_float_radix2_forward, gsl_fft_complex_float_radix2_backward, gsl_fft_real_float_transform, gsl_fft_real_wavetable_float_alloc, gsl_fft_real_workspace_float_alloc, gsl_fft_real_wavetable_float_free, gsl_fft_real_workspace_float_free); // printf("real_fft_transform_template (float)\n"); return 0; } assert(false); return 0; } /* following are modified codes taken from the GNU Scientific Library (gauss.c) * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2006, 2007 James Theiler, Brian Gough * Copyright (C) 2006 Charles Karney * * 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 of the License, 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; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ inline double high_prec_gsl_rng_uniform_pos_d(const gsl_rng * r) { unsigned long A, B; long double C; A = gsl_rng_uniform_pos(r)*0xFFFFFFFFUL; B = gsl_rng_uniform_pos(r)*0xFFFFFFFFUL; A = (A >> 5); B = (B >> 6); C = A * pow(2, 26) + B; return C * pow(2, -53); } float modified_gsl_ran_gaussian_f(const gsl_rng * r, const double sigma, bool reset = false) { //modified from GSL code to use the trick described in NumRec, that is, //use also the angle of the 'draw" as a no-cost random variable. //This trick is used by IDL. //The reset is used to start a new sequence (could probably be done looking at r contents) static int available = 0; if (reset) { available = 0; return std::numeric_limits::quiet_NaN(); //ensure not used. } static float other; float x, y, r2; if (available == 0) { do { /* choose x,y in uniform square (-1,-1) to (+1,+1) */ x = -1 + 2 * gsl_rng_uniform_pos(r); y = -1 + 2 * gsl_rng_uniform_pos(r); /* see if it is in the unit circle */ r2 = x * x + y * y; } while (r2 > 1.0 || r2 == 0); /* Box-Muller transform */ double fct = sqrt(-2.0 * log(r2) / r2); float current = sigma * y * fct; other = sigma * x * fct; available = 1; return current; } else { available = 0; return other; } } double modified_gsl_ran_gaussian_d(const gsl_rng * r, const double sigma, bool reset = false) { //modified from GSL code to use the trick described in NumRec, that is, //use also the angle of the 'draw" as a no-cost random variable. //This trick is used by IDL. //Moreover, IDL for doubles eats 2 single-precision numbers so that the result is // randomn_double = [(A >> 5)*226 + (B >> 6)]*2-53 where A and B are // 2 integer 32 bits random numbers. //The reset is used to start a new sequence (could probably be done looking at r contents) //GSL uses uniform_pos but the algo should permit x==0 or y==0 ? static int available = 0; if (reset) { available = 0; return std::numeric_limits::quiet_NaN(); //ensure not used. } static double other; double x, y, r2; if (available == 0) { do { /* choose x,y in uniform square (-1,-1) to (+1,+1) */ x = -1 + 2 * high_prec_gsl_rng_uniform_pos_d(r); y = -1 + 2 * high_prec_gsl_rng_uniform_pos_d(r); /* see if it is in the unit circle */ r2 = x * x + y * y; } while (r2 > 1.0 || r2 == 0); /* Box-Muller transform */ double fct = sqrt(-2.0 * log(r2) / r2); double current = sigma * y * fct; other = sigma * x * fct; available = 1; return current; } else { available = 0; return other; } } //template uses gsl, certified to give identical results to IDL8+. This is SLOW and not the default. template< typename T1, typename T2> int random_gamma(T1* res, gsl_rng *gsl_rng_mem, dimension dim, DLong n) { SizeT nEl = res->N_Elements(); for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (T2) gsl_ran_gamma_knuth(gsl_rng_mem, 1.0 * n, 1.0); //differs from idl above gamma=6. ?//IDL says it's the Knuth algo used. return 0; } template< typename T1, typename T2> int random_binomial(T1* res, gsl_rng *gsl_rng_mem, dimension dim, DDoubleGDL* binomialKey) { SizeT nEl = res->N_Elements(); //Note: Binomial values are not same IDL. DULong n = (DULong) (*binomialKey)[0]; DDouble p = (DDouble) (*binomialKey)[1]; for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (T2) gsl_ran_binomial_knuth(gsl_rng_mem, p, n); return 0; } template< typename T1, typename T2> int random_poisson(T1* res, gsl_rng *gsl_rng_mem, dimension dim, DDoubleGDL* poissonKey) { SizeT nEl = res->N_Elements(); //Removed old code that would return non-integer values for high mu values. DDouble mu = (DDouble) (*poissonKey)[0]; for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (T2) gsl_ran_poisson(gsl_rng_mem, mu); return 0; } template< typename T1, typename T2> int random_uniform(T1* res, gsl_rng *gsl_rng_mem, dimension dim) { SizeT nEl = res->N_Elements(); if (sizeof (T2) == sizeof (float)) { for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (T2) gsl_rng_uniform(gsl_rng_mem); return 0; } else { //as for IDL, make a more precise random number from 2 successive ones: unsigned long A, B; long double C; for (SizeT i = 0; i < nEl; ++i) { A = gsl_rng_uniform(gsl_rng_mem)*0xFFFFFFFFUL; B = gsl_rng_uniform(gsl_rng_mem)*0xFFFFFFFFUL; A = (A >> 5); B = (B >> 6); C = A * pow(2, 26) + B; C = C * pow(2, -53); (*res)[ i] = (T2) C; //gives the same as IDL 8 } return 0; } } template< typename T1, typename T2> int random_normal(T1* res, gsl_rng *gsl_rng_mem, dimension dim) { SizeT nEl = res->N_Elements(); if (sizeof (T2) == sizeof (float)) { for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (T2) modified_gsl_ran_gaussian_f(gsl_rng_mem, 1.0); //does reproduct IDL values. modified_gsl_ran_gaussian_f(gsl_rng_mem, 1.0, true); //reset use of internal cache in the modified_gsl_ran_gaussian function. return 0; } else { for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (T2) modified_gsl_ran_gaussian_d(gsl_rng_mem, 1.0); //does reproduct IDL values. modified_gsl_ran_gaussian_d(gsl_rng_mem, 1.0, true); //reset use of internal cache in the modified_gsl_ran_gaussian function. } return 0; } #define MERSENNE_GSL_N 624 /* Period parameters */ typedef struct { unsigned long mt[MERSENNE_GSL_N]; int mti; } mt_state_t; void set_random_state(gsl_rng* r, const unsigned long int* seed, const int pos, const int n) { assert(n == MERSENNE_GSL_N); mt_state_t *state = (mt_state_t *) (r->state); unsigned long * mt = state->mt; for (int i = 0; i < n; ++i) mt[i] = seed[i]; state->mti = pos; } void get_random_state(EnvT* e, const gsl_rng* r, const DULong seed) { if (e->GlobalPar(0)) { int pos; mt_state_t *mt_state = (mt_state_t *) (r->state); pos = mt_state->mti; unsigned long int* state= mt_state->mt; DULongGDL* ret = new DULongGDL(dimension(MERSENNE_GSL_N + 4), BaseGDL::ZERO); //ZERO as not all elements are initialized here DULong* newstate = (DULong*) (ret->DataAddr()); newstate[0] = seed; newstate[1] = pos; for (int i = 0; i < MERSENNE_GSL_N; ++i) newstate[i + 2] = state[i]; e->SetPar(0, ret); } } //GSL version of random_fun. See randomgenerators.cpp BaseGDL* random_fun_gsl(EnvT* e) { //used in RANDOMU and RANDOMN, which share the SAME KEYLIST. It is safe to speed up by using static ints KeywordIx. //Note: LONG or ULONG are obeyed irrespectively of the presence of GAMMA etc which are ignored. static int LONGIx = e->KeywordIx("LONG"); static int ULONGIx = e->KeywordIx("ULONG"); static int GAMMAIx = e->KeywordIx("GAMMA"); static int BINOMIALIx = e->KeywordIx("BINOMIAL"); static int NORMALIx = e->KeywordIx("NORMAL"); static int POISSONIx = e->KeywordIx("POISSON"); static int UNIFORMIx = e->KeywordIx("UNIFORM"); // testing Exclusive Keywords ... int exclusiveKW = e->KeywordPresent(GAMMAIx); exclusiveKW = exclusiveKW + e->KeywordPresent(BINOMIALIx); exclusiveKW = exclusiveKW + e->KeywordPresent(NORMALIx); exclusiveKW = exclusiveKW + e->KeywordPresent(POISSONIx); exclusiveKW = exclusiveKW + e->KeywordPresent(UNIFORMIx); if (exclusiveKW > 1) e->Throw("Conflicting keywords."); //idem for LONG and ULONG at the same time! exclusiveKW = e->KeywordPresent(LONGIx); exclusiveKW = exclusiveKW + e->KeywordPresent(ULONGIx); if (exclusiveKW > 1) e->Throw("Conflicting keywords."); // the generator structure static gsl_rng *gsl_rng_mem = gsl_rng_alloc(gsl_rng_mt19937); SizeT nParam = e->NParam(1); dimension dim; if (nParam > 1) arr(e, dim, 1); DULong seed; bool initialized=false; bool isAnull = NullGDL::IsNULLorNullGDL(e->GetPar(0)); if (!isAnull) { DULongGDL* p0L = e->IfDefGetParAs< DULongGDL>(0); if (p0L != NULL) // some non-null value passed -> can be a seed state, 628 integers, or use first value: { // IDL does not check that the seed sequence has been changed: as long as it is a 628 element Ulong, it takes it // and use it as the current sequence (try with "all zeroes"). if (p0L->N_Elements() == MERSENNE_GSL_N + 4 && p0L->Type() == GDL_ULONG ) { //a (valid?) seed sequence seed = (*p0L)[0]; int pos = (*p0L)[1]; int n = MERSENNE_GSL_N; unsigned long int sequence[n]; for (int i = 0; i < n; ++i) sequence[i] = (unsigned long int) (*p0L)[i + 2]; set_random_state(gsl_rng_mem, sequence, pos, n); //the seed initialized=true; } else { // not a seed sequence: take first (IDL does more than this...) if (p0L->N_Elements() >= 1) { seed = (*p0L)[0]; gsl_rng_set(gsl_rng_mem, seed); initialized=true; } } } } if (!initialized) { struct timeval tval; struct timezone tzone; gettimeofday(&tval, &tzone); long long int tt = tval.tv_sec * 1e6 + tval.tv_usec; // time in UTC microseconds seed = tt; gsl_rng_set(gsl_rng_mem, seed); initialized=true; } if (e->KeywordSet(LONGIx)) { DLongGDL* res = new DLongGDL(dim, BaseGDL::NOZERO); SizeT nEl = res->N_Elements(); for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (DLong) (gsl_rng_uniform(gsl_rng_mem) * 2147483646) + 1; //apparently IDL rounds up. get_random_state(e, gsl_rng_mem, seed); return res; } if (e->KeywordSet(ULONGIx)) { DULongGDL* res = new DULongGDL(dim, BaseGDL::NOZERO); SizeT nEl = res->N_Elements(); for (SizeT i = 0; i < nEl; ++i) (*res)[ i] = (DULong) (gsl_rng_uniform(gsl_rng_mem) * 0xFFFFFFFFUL) + 1; //apparently IDL rounds up. get_random_state(e, gsl_rng_mem, seed); return res; } if (e->KeywordPresent(GAMMAIx)) { DLong n = -1; //please initialize everything! e->AssureLongScalarKW(GAMMAIx, n); if (n == 0) { DDouble test_n; e->AssureDoubleScalarKW(GAMMAIx, test_n); if (test_n > 0.0) n = 1; } if (n <= 0) e->Throw("Value of (Int/Long) GAMMA is out of allowed range: Gamma = 1, 2, 3, ..."); if (!e->KeywordSet(0)) { //hence:float if (n >= 10000000) e->Throw("Value of GAMMA is out of allowed range: Try /DOUBLE."); } if (e->KeywordSet(0)) { // GDL_DOUBLE DDoubleGDL* res = new DDoubleGDL(dim, BaseGDL::NOZERO); random_gamma< DDoubleGDL, double>(res, gsl_rng_mem, dim, n); get_random_state(e, gsl_rng_mem, seed); return res; } else { DFloatGDL* res = new DFloatGDL(dim, BaseGDL::NOZERO); random_gamma< DFloatGDL, float>(res, gsl_rng_mem, dim, n); get_random_state(e, gsl_rng_mem, seed); return res; } } DDoubleGDL* binomialKey = e->IfDefGetKWAs(BINOMIALIx); if (binomialKey != NULL) { SizeT nBinomialKey = binomialKey->N_Elements(); if (nBinomialKey != 2) e->Throw("Keyword array parameter BINOMIAL must have 2 elements."); if ((*binomialKey)[0] < 1.0) e->Throw(" Value of BINOMIAL[0] is out of allowed range: n = 1, 2, 3, ..."); if (((*binomialKey)[1] < 0.0) || ((*binomialKey)[1] > 1.0)) e->Throw(" Value of BINOMIAL[1] is out of allowed range: 0.0 <= p <= 1.0"); if (e->KeywordSet(0)) { // GDL_DOUBLE DDoubleGDL* res = new DDoubleGDL(dim, BaseGDL::NOZERO); random_binomial< DDoubleGDL, double>(res, gsl_rng_mem, dim, binomialKey); get_random_state(e, gsl_rng_mem, seed); return res; } else { DFloatGDL* res = new DFloatGDL(dim, BaseGDL::NOZERO); random_binomial< DFloatGDL, float>(res, gsl_rng_mem, dim, binomialKey); get_random_state(e, gsl_rng_mem, seed); return res; } } DDoubleGDL* poissonKey = e->IfDefGetKWAs(POISSONIx); if (poissonKey != NULL) { SizeT nPoissonKey = poissonKey->N_Elements(); if (nPoissonKey != 1) e->Throw("Expression must be a scalar or 1 element array in this context: " + e->GetString(POISSONIx)); if (e->KeywordSet(0)) { // GDL_DOUBLE DDoubleGDL* res = new DDoubleGDL(dim, BaseGDL::NOZERO); random_poisson< DDoubleGDL, double>(res, gsl_rng_mem, dim, poissonKey); get_random_state(e, gsl_rng_mem, seed); return res; } else { DFloatGDL* res = new DFloatGDL(dim, BaseGDL::NOZERO); random_poisson< DFloatGDL, float>(res, gsl_rng_mem, dim, poissonKey); get_random_state(e, gsl_rng_mem, seed); return res; } } if (e->KeywordSet(UNIFORMIx) || ((e->GetProName() == "RANDOMU") && !e->KeywordSet(NORMALIx))) { if (e->KeywordSet(0)) { // GDL_DOUBLE DDoubleGDL* res = new DDoubleGDL(dim, BaseGDL::NOZERO); random_uniform< DDoubleGDL, double>(res, gsl_rng_mem, dim); get_random_state(e, gsl_rng_mem, seed); return res; } else { DFloatGDL* res = new DFloatGDL(dim, BaseGDL::NOZERO); random_uniform< DFloatGDL, float>(res, gsl_rng_mem, dim); get_random_state(e, gsl_rng_mem, seed); return res; } } if (e->KeywordSet(NORMALIx) || ((e->GetProName() == "RANDOMN") && !e->KeywordSet(UNIFORMIx))) { if (e->KeywordSet(0)) { // GDL_DOUBLE DDoubleGDL* res = new DDoubleGDL(dim, BaseGDL::NOZERO); random_normal< DDoubleGDL, double>(res, gsl_rng_mem, dim); get_random_state(e, gsl_rng_mem, seed); return res; } else { DFloatGDL* res = new DFloatGDL(dim, BaseGDL::NOZERO); random_normal< DFloatGDL, float>(res, gsl_rng_mem, dim); get_random_state(e, gsl_rng_mem, seed); return res; } } assert(false); return NULL; } #ifndef HAVE_NEXTTOWARD // SA: in C99 / C++TR1 / Boost there is the nextafter() function // the code below provides an alternative if needed // based on the nexttoward.c from mingw (mingw-runtime-3.8/mingwex/math) // by Danny Smith /* nexttoward.c Contributed by Danny Smith No copyright claimed, absolutely no warranties. 2005-05-10 */ double nexttoward(double x, long double y) { union { double d; unsigned long long ll; } u; long double xx = x; if (isnan (y) || isnan (x)) return x + y; /* nextafter (0.0, -O.0) should return -0.0. */ if (xx == y) return y; u.d = x; if (x == 0.0) { u.ll = 1; return y > 0.0L ? u.d : -u.d; } /* Non-extended encodings are lexicographically ordered, with implicit "normal" bit. */ if (((x > 0.0) ^ (y > xx)) == 0) u.ll++; else u.ll--; return u.d; } #endif // Alain C., 26 February 2013 // this is a temporary workaround of an in accuracy in the GSL (up to 1.15) // when working on 64b version and integer bin size ... // GDL bug report 618683 // http://sourceforge.net/tracker/?func=detail&aid=3602623&group_id=97659&atid=618683 // GSL bug report thread // http://lists.gnu.org/archive/html/bug-gsl/2013-02/msg00006.html static void gdl_make_uniform (gsl_histogram * h, size_t n, double xmin, double xmax) { size_t i; for (i = 0; i <= n; i++) h->range[i] = xmin + (double) i * (xmax-xmin)/((double) n); } BaseGDL* histogram_fun( EnvT* e) { double a; double b; DULong nri; SizeT nParam=e->NParam(1); BaseGDL* p0 = e->GetNumericParDefined( 0); if (p0->Rank() == 0) e->Throw( "Expression must be an array in this context: " + e->GetParString(0)); SizeT nEl = p0->N_Elements(); if( p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL) e->Throw( "Complex expression not allowed in this context: " +e->GetParString(0)); static int binsizeIx=e->KeywordIx("BINSIZE"); BaseGDL* binsizeKW = e->GetKW(binsizeIx); DDouble bsize = 1.0; if( binsizeKW != NULL) { e->AssureDoubleScalarKW( 0, bsize); if( bsize <= 0.0) e->Throw( "Illegal BINSIZE."); } static int maxIx=e->KeywordIx("MAX"); BaseGDL* maxKW = e->GetKW(maxIx); static int minIx=e->KeywordIx("MIN"); BaseGDL* minKW = e->GetKW(minIx); static int nbinsIx=e->KeywordIx("NBINS"); BaseGDL* nbinsKW = e->GetKW(nbinsIx); DLong nbins; if( nbinsKW != NULL) { e->AssureLongScalarKW(nbinsIx, nbins); if( nbins < 0) e->Throw( "Illegal NBINS (<0)."); if( nbins == 0) // NBINS=0 is ignored nbinsKW = NULL; } if( binsizeKW != NULL && nbinsKW != NULL && maxKW != NULL) e->Throw( "Conflicting keywords."); DDoubleGDL *p0D; Guard guard; if( p0->Type() != GDL_DOUBLE) { p0D = static_cast(p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard.Init( p0D); } else { p0D = static_cast(p0); } // get min max // use MinMax here when NAN will be supported DDouble minVal, maxVal; static int nanIx=e->KeywordIx("NAN"); if( e->KeywordSet(nanIx)) { DLong minEl, maxEl; p0D->MinMax( &minEl, &maxEl, NULL, NULL, true); minVal=(*p0D)[minEl]; maxVal=(*p0D)[maxEl]; } else { minVal = (*p0D)[0]; maxVal = minVal; for( SizeT i=1; iThrow("Array has too many elements (Infinite value encoutered)."); }; } if ((*p0D)[i] < minVal) minVal = (*p0D)[i]; else if ((*p0D)[i] > maxVal) maxVal = (*p0D)[i]; } } int debug=0; if (debug) cout << "min/max : " << minVal << " " << maxVal << endl; // min if (minKW == NULL) { if( p0->Type() == GDL_BYTE) a = 0.0; else a = minVal; } else e->AssureDoubleScalarKW(minIx, a); // max if (maxKW == NULL) { if( p0->Type() == GDL_BYTE) b = 255.0; // !MAX && BINSIZE && NBINS -> determine MAX else if (binsizeKW != NULL && nbinsKW != NULL) b = a + bsize * nbins; // SA: !MAX && !BINSIZE && NBINS -> binsize = (max - min) / (nbins - 1) else if (binsizeKW == NULL && nbinsKW != NULL) { bsize = (maxVal - minVal) / (nbins - 1); b = a + nbins * bsize; } else b = maxVal; } else { e->AssureDoubleScalarKW(maxIx, b); // MAX && !BINSIZE && NBINS -> determine BINSIZE if( binsizeKW == NULL && nbinsKW != NULL) bsize = (b - a) / (nbins - 1); } if( bsize < 0 || a > b || !isfinite(a) || !isfinite(b)) e->Throw( "Illegal binsize or max/min."); // gsl histogram needs this adjustment double aOri = a, bOri = b; a = nexttoward(a, -DBL_MAX); b = nexttoward(b, DBL_MAX); // -> NBINS if( nbinsKW == NULL) nbins = static_cast< DLong>( floor( (b - a) / bsize) + 1); // INPUT keyword static int inputIx = e->KeywordIx("INPUT"); DLongGDL* input = e->IfDefGetKWAs( inputIx); if (input != NULL) { if (input->N_Elements() < nbins) e->Throw("Expression " +e->GetString(inputIx) + " does not have enough elements."); else if (input->N_Elements() > nbins) nbins = input->N_Elements(); } // Adjust "b" if binsize specified otherwise gsl_histogram_set_ranges_uniform // will change bsize to (b-a)/nbins // SA: another case when it's needed: !MAX && !BINSIZE && NBINS if ( binsizeKW != NULL || (binsizeKW == NULL && maxKW == NULL && nbinsKW != NULL) ) b = a + nbins * bsize; // GSL error handling SetTemporaryGSLErrorHandlerT setTemporaryGSLErrorHandler( GDLGenericGSLErrorHandler); gsl_histogram* hh = gsl_histogram_alloc( nbins); GDLGuard hhGuard( hh, gsl_histogram_free); gsl_histogram_set_ranges_uniform( hh, a, b); // temporary revisited computation of bin values ... gdl_make_uniform (hh, hh->n, a, b); // Set maxVal from keyword if present if (maxKW != NULL) e->AssureDoubleScalarKW(maxIx, maxVal); // Generate histogram for( SizeT i=0; i( gsl_histogram_get(hh, i)); } // Add input to output if present if (input != NULL) for( SizeT i=0; iKeywordIx("OMAX"); if( e->KeywordPresent(omaxIx)) { // e->SetKW( 5, (new DDoubleGDL( gsl_histogram_max(hh)))->Convert2(p0->Type(), BaseGDL::CONVERT)); e->SetKW(omaxIx, (new DDoubleGDL( bOri))->Convert2(p0->Type(), BaseGDL::CONVERT)); } // OMIN static int ominIx=e->KeywordIx("OMIN"); if( e->KeywordPresent(ominIx)) { // e->SetKW( 6, (new DDoubleGDL( gsl_histogram_min(hh)))->Convert2(p0->Type(), BaseGDL::CONVERT)); e->SetKW(ominIx, (new DDoubleGDL( aOri))->Convert2(p0->Type(), BaseGDL::CONVERT)); } // REVERSE_INDICES static int reverse_indicesIx=e->KeywordIx("REVERSE_INDICES"); if( e->KeywordPresent(reverse_indicesIx)) { if (input != NULL) e->Throw("Conflicting keywords."); DULong k = 0; multimap< size_t, SizeT> bin_j; for( SizeT j=0; j= a && (*p0D)[j] <= b) { ++k; size_t bin; gsl_histogram_find (hh, (*p0D)[j], &bin); bin_j.insert( make_pair( bin, j)); } } nri = nbins + k + 1; DLongGDL* revindKW = new DLongGDL( dimension( nri), BaseGDL::NOZERO); k = 0; for( SizeT i=0; i::const_iterator mmI; pair< mmI, mmI> b = bin_j.equal_range( i); for( mmI j = b.first; j != b.second; ++j) { (*revindKW)[nbins+1+k] = j->second; k++; } } // for( SizeT i=nbins+1; i= a && (*p0D)[j] <= b) // { // size_t bin; // gsl_histogram_find (hh, (*p0D)[j], &bin); // if( bin == i) // { // (*revindKW)[nbins+1+k] = j; // k++; // } // } // } // } // for( SizeT i=nbins+1; iSetKW(reverse_indicesIx, revindKW); } // LOCATIONS static int locationsIx=e->KeywordIx("LOCATIONS"); if( e->KeywordPresent(locationsIx)) { BaseGDL** locationsKW = &e->GetKW(locationsIx); GDLDelete((*locationsKW)); dimension dim( nbins); if( p0->Type() == GDL_DOUBLE) { *locationsKW = new DDoubleGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_FLOAT) { *locationsKW = new DFloatGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_LONG) { *locationsKW = new DLongGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_ULONG) { *locationsKW = new DULongGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_LONG64) { *locationsKW = new DLong64GDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_ULONG64) { *locationsKW = new DULong64GDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_INT) { *locationsKW = new DIntGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_UINT) { *locationsKW = new DUIntGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } else if (p0->Type() == GDL_BYTE) { *locationsKW = new DByteGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i( *locationsKW))[i] = static_cast(aOri + bsize * i); } } //gsl_histogram_free (hh); return(res); } DDoubleGDL* interpolate_1dim(EnvT* e, const gdl_interp1d_type* interp_type, DDoubleGDL* array, DDoubleGDL* x, bool use_missing, DDouble missing, DDouble gamma) { SizeT nx = x->N_Elements(); // Determine number and value of input points along x-axis and y-axis if (array->Rank() < 1) e->Throw("Number of parameters must agree with dimensions of argument."); SizeT rankLeft = array->Rank()-1; //initialize output array with correct dimensions DLong dims[MAXRANK]; SizeT i = 0; for (; i < rankLeft; ++i) dims[i] = array->Dim(i); for (; i < MAXRANK; ++i) dims[i] = 0; SizeT resRank = rankLeft; SizeT chunksize; for (SizeT i = 0; i < x->Rank(); ++i) { dims[resRank++] = x->Dim(i); if (resRank>MAXRANK) e->Throw("Rank of resulting array is currently limited to " + i2s(MAXRANK) + "."); } chunksize=nx; dimension dim((DLong *)dims, resRank); DDoubleGDL *res; res = new DDoubleGDL(dim, BaseGDL::NOZERO); // Determine number of interpolations for remaining dimensions SizeT ninterp = 1; for (SizeT i = 0; i < rankLeft; ++i) ninterp *= array->Dim(i); //need to PAD the intermediate work array to satisfy the IDL requirement that //INTERPOLATE considers location points with values between zero and n, //where n is the number of values in the input array, to be valid. // Seems however to be the case only for 1D interpolation. SizeT nxa = array->Dim(rankLeft)+1; double *xa = new double[nxa]; ArrayGuard xaGuard(xa); for (SizeT i = 0; i < nxa; ++i) xa[i] = (double)i; // Setup interpolation arrays gsl_interp_accel *accx = gsl_interp_accel_alloc(); GDLGuard g1( accx, gsl_interp_accel_free); gdl_interp1d* interpolant = gdl_interp1d_alloc(interp_type, nxa); GDLGuard g2( interpolant, gdl_interp1d_free); // output locations tables: double *xval = new double[chunksize]; ArrayGuard xvalGuard(xval); for (SizeT count = 0; count < chunksize; ++count) { xval[count] = (*x)[count]; } //construct 1d intermediate array, subset of array with stride ninterp double *temp = new double[nxa]; ArrayGuard tempGuard(temp); // Interpolate iteratively ninterp times: // loop could be multihreaded easily for (SizeT iterate = 0; iterate < ninterp; ++iterate) { //here we use a padded temp array (1D only): for (SizeT k = 0; k < nxa-1; ++k) temp[k]=(*array)[k*ninterp+iterate]; temp[nxa-1]=temp[nxa-2]; //pad! gdl_interp1d_init(interpolant, xa, temp, nxa, use_missing?missing_GIVEN:missing_NEAREST, missing, gamma); #ifndef __PATHCC__ #pragma omp parallel if (chunksize >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= chunksize)) #pragma omp for #endif for (OMPInt i = 0; i < chunksize; ++i) { double x = xval[i]; (*res)[i*ninterp+iterate] = gdl_interp1d_eval(interpolant, xa, temp, x, accx); } } // gsl_interp_accel_free(accx); // gdl_interp1d_free(interpolant); return res; } DDoubleGDL* interpolate_2dim(EnvT* e, const gdl_interp2d_type* interp_type, DDoubleGDL* array, DDoubleGDL* x, DDoubleGDL* y, bool grid, bool use_missing, DDouble missing, DDouble gamma) { SizeT nx = x->N_Elements(); SizeT ny = y->N_Elements(); if (nx == 1 && ny == 1) grid = false; // Determine number and value of input points along x-axis and y-axis if (array->Rank() < 2) e->Throw("Number of parameters must agree with dimensions of argument."); SizeT rankLeft = array->Rank()-2; // If not GRID then check that rank and dims match if (!grid) { if (x->Rank() != y->Rank()) e->Throw("Coordinate arrays must have same rank if Grid not set."); else { for (SizeT i = 0; i < x->Rank(); ++i) { if (x->Dim(i) != y->Dim(i)) e->Throw("Coordinate arrays must have same shape if Grid not set."); } } } //initialize output array with correct dimensions DLong dims[MAXRANK]; SizeT i = 0; for (; i < rankLeft; ++i) dims[i] = array->Dim(i); for (; i < MAXRANK; ++i) dims[i] = 0; SizeT resRank = rankLeft; SizeT chunksize; if (grid) { dims[resRank++] = nx; if (resRank > MAXRANK - 1) e->Throw("Rank of resulting array is currently limited to " + i2s(MAXRANK) + "."); dims[resRank++] = ny; chunksize = nx*ny; } else { for (SizeT i = 0; i < x->Rank(); ++i) { dims[resRank++] = x->Dim(i); if (resRank > MAXRANK) e->Throw("Rank of resulting array is currently limited to " + i2s(MAXRANK) + "."); } chunksize = nx; } dimension dim((DLong *)dims, resRank); DDoubleGDL *res; res = new DDoubleGDL(dim, BaseGDL::NOZERO); // Determine number of interpolations for remaining dimensions SizeT ninterp = 1; for (SizeT i = 0; i < rankLeft; ++i) ninterp *= array->Dim(i); SizeT nxa = array->Dim(rankLeft); double *xa = new double[nxa]; ArrayGuard xaGuard( xa); for (SizeT i = 0; i < nxa; ++i) xa[i] = (double)i; SizeT nya = array->Dim(rankLeft+1); double *ya = new double[nya]; ArrayGuard yaGuard( ya); for (SizeT i = 0; i < nya; ++i) ya[i] = (double)i; // Setup interpolation arrays gsl_interp_accel *accx = gsl_interp_accel_alloc(); GDLGuard g1( accx, gsl_interp_accel_free); gsl_interp_accel *accy = gsl_interp_accel_alloc(); GDLGuard g2( accy, gsl_interp_accel_free); gdl_interp2d* interpolant = gdl_interp2d_alloc(interp_type, nxa, nya); GDLGuard g3( interpolant, gdl_interp2d_free); // output locations tables: double *xval = new double[chunksize]; ArrayGuard xvalGuard( xval); double *yval = new double[chunksize]; ArrayGuard yvalGuard( yval); if (grid) { for (SizeT j = 0, count=0; j < ny; j++) { for (SizeT i = 0, count = 0; i < nx; i++) { count = INDEX_2D(i, j, nx, ny); xval[count] = (*x)[i]; yval[count] = (*y)[j]; } } } else { for (SizeT count = 0; count < chunksize; ++count) { xval[count] = (*x)[count]; yval[count] = (*y)[count]; } } //construct 2d intermediate array, subset of array with stride ninterp double *temp = new double[nxa*nya]; ArrayGuard tempGuard( temp); // Interpolate iteratively ninterp times: // loop could be multihreaded easily for (SizeT iterate = 0; iterate < ninterp; ++iterate) { for (SizeT k = 0; k < nxa * nya; ++k) temp[k] = (*array)[k * ninterp + iterate]; gdl_interp2d_init(interpolant, xa, ya, temp, nxa, nya, use_missing ? missing_GIVEN : missing_NEAREST, missing, gamma); #ifndef __PATHCC__ #pragma omp parallel if (chunksize >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= chunksize)) #pragma omp for #endif for (OMPInt i = 0; i < chunksize; ++i) { double x = xval[i]; double y = yval[i]; (*res)[i * ninterp + iterate] = gdl_interp2d_eval(interpolant, xa, ya, temp, x, y, accx, accy); } } // gsl_interp_accel_free(accx); // gsl_interp_accel_free(accy); // gdl_interp2d_free(interpolant); return res; } DDoubleGDL* interpolate_3dim(EnvT* e, const gdl_interp3d_type* interp_type, DDoubleGDL* array, DDoubleGDL* x, DDoubleGDL* y, DDoubleGDL* z, bool grid, bool use_missing, DDouble missing) { SizeT nx = x->N_Elements(); SizeT ny = y->N_Elements(); SizeT nz = z->N_Elements(); if (nx == 1 && ny == 1 && nz == 1) grid = false; // Determine number and value of input points along x-axis and y-axis if (array->Rank() < 3) e->Throw("Number of parameters must agree with dimensions of argument."); SizeT rankLeft = array->Rank()-3; // If not GRID then check that rank and dims match if (!grid) { if (x->Rank() != y->Rank() || x->Rank() != z->Rank() ) e->Throw("Coordinate arrays must have same rank if Grid not set."); else { for (SizeT i = 0; i < x->Rank(); ++i) { if (x->Dim(i) != y->Dim(i) || x->Dim(i) != z->Dim(i)) e->Throw("Coordinate arrays must have same shape if Grid not set."); } } } //initialize output array with correct dimensions DLong dims[MAXRANK]; SizeT i = 0; for (; i < rankLeft; ++i) dims[i] = array->Dim(i); for (; i < MAXRANK; ++i) dims[i] = 0; SizeT resRank= rankLeft; SizeT chunksize; if (grid) { dims[resRank++] = nx; if (resRank>MAXRANK-2) e->Throw("Rank of resulting array is currently limited to " + i2s(MAXRANK) + "."); dims[resRank++] = ny; dims[resRank++] = nz; chunksize=nx*ny*nz; } else { for (SizeT i = 0; i < x->Rank(); ++i) { dims[resRank++] = x->Dim(i); if (resRank>MAXRANK) e->Throw("Rank of resulting array is currently limited to " + i2s(MAXRANK) + "."); } chunksize=nx; } dimension dim((DLong *)dims, resRank); DDoubleGDL *res; res = new DDoubleGDL(dim, BaseGDL::NOZERO); // Determine number of interpolations for remaining dimensions SizeT ninterp = 1; for (SizeT i = 0; i < rankLeft; ++i) ninterp *= array->Dim(i); SizeT nxa = array->Dim(rankLeft); double *xa = new double[nxa]; ArrayGuard xaGuard( xa); for (SizeT i = 0; i < nxa; ++i) xa[i] = (double)i; SizeT nya = array->Dim(rankLeft+1); double *ya = new double[nya]; ArrayGuard yaGuard( ya); for (SizeT i = 0; i < nya; ++i) ya[i] = (double)i; SizeT nza = array->Dim(rankLeft+2); double *za = new double[nza]; ArrayGuard zaGuard( za); for (SizeT i = 0; i < nza; ++i) za[i] = (double)i; // test if interp_type kernel trace is statisfied by nxa,nya,nza: if (nxaThrow("Array(s) dimensions too small for this interpolation type."); // Setup interpolation arrays gsl_interp_accel *accx = gsl_interp_accel_alloc(); GDLGuard g1( accx, gsl_interp_accel_free); gsl_interp_accel *accy = gsl_interp_accel_alloc(); GDLGuard g2( accy, gsl_interp_accel_free); gsl_interp_accel *accz = gsl_interp_accel_alloc(); GDLGuard g3( accz, gsl_interp_accel_free); gdl_interp3d* interpolant = gdl_interp3d_alloc(interp_type, nxa, nya, nza); GDLGuard g4( interpolant, gdl_interp3d_free); // output locations tables: double *xval = new double[chunksize]; ArrayGuard xvalGuard( xval); double *yval = new double[chunksize]; ArrayGuard yvalGuard( yval); double *zval = new double[chunksize]; ArrayGuard zvalGuard( zval); if (grid) { for (SizeT k = 0, count = 0; k < nz; ++k) { for (SizeT j = 0; j < ny; ++j) { for (SizeT i = 0; i < nx; ++i) { count = INDEX_3D(i, j, k, nx, ny, nz); xval[count] = (*x)[i]; yval[count] = (*y)[j]; zval[count] = (*z)[k]; } } } } else { for (SizeT count = 0; count < chunksize; ++count) { xval[count] = (*x)[count]; yval[count] = (*y)[count]; zval[count] = (*z)[count]; } } //construct 3d intermediate array, subset of array with stride ninterp double *temp = new double[nxa*nya*nza]; ArrayGuard tempGuard( temp); // Interpolate iteratively ninterp times: // this outer loop could be multihreaded easily for (SizeT iterate = 0; iterate < ninterp; ++iterate) { for (SizeT k = 0; k < nxa*nya*nza; ++k) temp[k]=(*array)[k*ninterp+iterate]; gdl_interp3d_init(interpolant, xa, ya, za, temp, nxa, nya, nza, use_missing?missing_GIVEN:missing_NEAREST, missing); #ifndef __PATHCC__ #pragma omp parallel if (chunksize >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= chunksize)) #pragma omp for #endif for (OMPInt i = 0; i < chunksize; ++i) { double x = xval[i]; double y = yval[i]; double z = zval[i]; (*res)[i*ninterp+iterate] = gdl_interp3d_eval(interpolant, xa, ya, za, temp, x, y, z, accx, accy, accz); } } // gsl_interp_accel_free(accx); // gsl_interp_accel_free(accy); // gsl_interp_accel_free(accz); // gdl_interp3d_free(interpolant); return res; } BaseGDL* interpolate_fun(EnvT* e){ SizeT nParam = e->NParam(); // options static int cubicIx = e->KeywordIx("CUBIC"); bool cubic = e->KeywordSet(cubicIx); DDouble gamma=-1.0; e->AssureDoubleScalarKWIfPresent(cubicIx, gamma); static int nnborIx = e->KeywordIx("NEAREST_NEIGHBOUR"); //usage restricted to GDL, undocumented, normally for CONGRID. bool nnbor = e->KeywordSet(nnborIx); if (nnbor && cubic) nnbor=false; //undocumented nearest neighbour give way wrt. other options. static int gridIx = e->KeywordIx("GRID"); bool grid = e->KeywordSet(gridIx); // AC 2018-feb-01 : NB !! Double Keyword is related to Grid Keyword // // due to our "bug" report to IDL, /Double was add in IDL since 8.2.3 // but we don't managed it (/double) in GDL because we always // compute Grid related stuffs in Double .... // // static int dblIx = e->KeywordIx("DOUBLE"); // bool dbl = e->KeywordSet(dblIx); static int missingIx = e->KeywordIx("MISSING"); bool use_missing = e->KeywordSet(missingIx); DDouble missing; e->AssureDoubleScalarKWIfPresent(missingIx, missing); DDoubleGDL* p0D[2]; DDoubleGDL* p1D; DDoubleGDL* p2D; DDoubleGDL* p3D; Guard guard00; Guard guard01; Guard guard1; Guard guard2; Guard guard3; int complexity=1; if (nParam < 2) e->Throw("Incorrect number of arguments."); // convert to internal double arrays. Special case for complex values, we separate R and I BaseGDL* p0 = e->GetParDefined(0); if (p0->Rank() < nParam - 1) e->Throw("Number of parameters must agree with dimensions of argument."); //Ok, Ranks are compatible, but check if last parameter(s) have dimension 1. //interpol is unable to interpolate on a zero-size dimension. We will downgrade the number //of dimensions to be interpolated, and duplicate the result to the size of the last parameter(s). SizeT lastDim=0; bool needsLastDims=false; dimension dimIni=p0->Dim(); dimension dimEnd=p0->Dim(); dimEnd.Purge(); SizeT RankDiff=dimIni.Rank()-dimEnd.Rank(); //number of 1-sized dimensions consecutive at end SizeT resDimInit[ MAXRANK]; SizeT iAddRank=0; for (iAddRank=0;iAddRank0) { for (SizeT i=RankDiff; i>=1; --i){ lastDim=(e->GetParDefined(nParam-i))->Dim(0); if (lastDim > 1) needsLastDims=true; //correct behaviour: last dim=1 is trimmed anyway. resDimInit[iAddRank]=(lastDim==0)?1:lastDim; iAddRank++; } nParam-=RankDiff; } if (p0->Type() == GDL_COMPLEX) { complexity=2; DComplexGDL* c0 = static_cast (p0); p0D[0] = new DDoubleGDL(c0->Dim(), BaseGDL::NOZERO); guard00.Init(p0D[0]); p0D[1] = new DDoubleGDL(c0->Dim(), BaseGDL::NOZERO); guard01.Init(p0D[1]); #pragma omp parallel if ( p0->N_Elements() >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= p0->N_Elements())) #pragma omp for for (OMPInt i = 0; i < c0->N_Elements(); ++i) { (*p0D[0])[i] = (*c0)[i].real(); (*p0D[1])[i] = (*c0)[i].imag(); } } else if( p0->Type() == GDL_COMPLEXDBL) { complexity=2; DComplexDblGDL* c0 = static_cast (p0); p0D[0] = new DDoubleGDL(c0->Dim(), BaseGDL::NOZERO); guard00.Init(p0D[0]); p0D[1] = new DDoubleGDL(c0->Dim(), BaseGDL::NOZERO); guard01.Init(p0D[1]); #pragma omp parallel if ( p0->N_Elements() >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= p0->N_Elements())) #pragma omp for for (OMPInt i = 0; i < c0->N_Elements(); ++i) { (*p0D[0])[i] = (*c0)[i].real(); (*p0D[1])[i] = (*c0)[i].imag(); } } else if (p0->Type() == GDL_DOUBLE) p0D[0] = static_cast(p0); else { p0D[0] = static_cast(p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard00.Init(p0D[0]); } BaseGDL* p1 = e->GetParDefined(1); if (p1->Type() == GDL_DOUBLE) p1D = static_cast(p1); else { p1D = static_cast(p1->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard1.Init(p1D); } BaseGDL* p2 = NULL; if (nParam >= 3) { p2 = e->GetParDefined(2); if (p2->Type() == GDL_DOUBLE) p2D = static_cast(p2); else { p2D = static_cast(p2->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard2.Init(p2D); } } BaseGDL* p3 = NULL; if (nParam >= 4) { p3 = e->GetParDefined(3); if (p3->Type() == GDL_DOUBLE) p3D = static_cast(p3); else { p3D = static_cast(p3->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard3.Init(p3D); } } DDoubleGDL* res[2]; for (int iloop=0; iloopDup(); // 1D Interpolation if (nParam == 2) { // res[iloop]=interpolate_1dim(e,p0D[iloop],p1D,cubic,use_missing,missing); if (nnbor) res[iloop]=interpolate_1dim(e,gdl_interp1d_nearest,p0D[iloop],p1D,use_missing,missing,0.0); else if (cubic) res[iloop]=interpolate_1dim(e,gdl_interp1d_cubic,p0D[iloop],p1D,use_missing,missing,gamma); else res[iloop]=interpolate_1dim(e,gdl_interp1d_linear,p0D[iloop],p1D,use_missing,missing,0.0); } // 2D Interpolation if (nParam == 3) { if (nnbor) res[iloop]=interpolate_2dim(e,gdl_interp2d_binearest,p0D[iloop],p1D,p2D,grid,use_missing,missing,0.0); else if (cubic) res[iloop]=interpolate_2dim(e,gdl_interp2d_bicubic,p0D[iloop],p1D,p2D,grid,use_missing,missing,gamma); else res[iloop]=interpolate_2dim(e,gdl_interp2d_bilinear,p0D[iloop],p1D,p2D,grid,use_missing,missing,0.0); } // 3D Interpolation if (nParam == 4) { res[iloop]=interpolate_3dim(e,gdl_interp3d_trilinear,p0D[iloop],p1D,p2D,p3D,grid,use_missing,missing); } //special case where last dimension of input was 1 if (needsLastDims){ dimension dim=(res[iloop])->Dim(); for (SizeT i=0; i<(res[iloop])->Rank(); ++i){ resDimInit[i]=dim[i]; //put back first dimensions of interpolated result } dimension resDim( resDimInit, iAddRank); //change as Dimension... res[iloop]= static_cast(res[iloop]->Rebin(resDim, true)); //Rebin to the extra number of dims. } } // AC 2018-feb-01 : don't put here a conversion with /Double : not need !! // in IDL since 8.2.3, /Double is related to grid keyword if (p0->Type() == GDL_DOUBLE) { return res[0]; } else if (p0->Type() == GDL_FLOAT) { DFloatGDL* res1 = static_cast (res[0]->Convert2(GDL_FLOAT, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_INT) { DIntGDL* res1 = static_cast (res[0]->Convert2(GDL_INT, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_UINT) { DUIntGDL* res1 = static_cast (res[0]->Convert2(GDL_UINT, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_LONG) { DLongGDL* res1 = static_cast (res[0]->Convert2(GDL_LONG, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_ULONG) { DULongGDL* res1 = static_cast (res[0]->Convert2(GDL_ULONG, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_LONG64) { DLong64GDL* res1 = static_cast (res[0]->Convert2(GDL_LONG64, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_ULONG64) { DULong64GDL* res1 = static_cast (res[0]->Convert2(GDL_ULONG64, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_BYTE) { DByteGDL* res1 = static_cast (res[0]->Convert2(GDL_BYTE, BaseGDL::COPY)); delete res[0]; return res1; } else if (p0->Type() == GDL_COMPLEX) { DComplexGDL* res1 = new DComplexGDL(res[0]->Dim(), BaseGDL::NOZERO); #pragma omp parallel if ( p0->N_Elements() >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= p0->N_Elements())) #pragma omp for for (OMPInt i = 0; i < res1->N_Elements(); ++i) { (*res1)[ i] = DComplex((*res[0])[i],(*res[1])[i]); // (*res1)[i].real() = (*res[0])[i]; // (*res1)[i].imag() = (*res[1])[i]; } delete res[0]; delete res[1]; return res1; } else if (p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* res1 = new DComplexDblGDL(res[0]->Dim(), BaseGDL::NOZERO); #pragma omp parallel if ( p0->N_Elements() >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= p0->N_Elements())) #pragma omp for for (OMPInt i = 0; i < res1->N_Elements(); ++i) { (*res1)[ i] = DComplexDbl((*res[0])[i],(*res[1])[i]); // (*res1)[i].real() = (*res[0])[i]; // (*res1)[i].imag() = (*res[1])[i]; } delete res[0]; delete res[1]; return res1; } else //? { return res[0]; } } void la_trired_pro( EnvT* e) { SizeT nParam=e->NParam(3); float f32; double f64; // if( nParam != 3) // e->Throw( // "LA_TRIRED: Incorrect number of arguments."); BaseGDL* p0 = e->GetNumericArrayParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw("Variable is undefined: "+ e->GetParString(0)); if (p0->Dim(0) != p0->Dim(1)) e->Throw("Input must be a square matrix: "+ e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); float f32_2[2]; double f64_2[2]; gsl_matrix_complex *mat = gsl_matrix_complex_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1( mat, gsl_matrix_complex_free); gsl_matrix_complex *Q = gsl_matrix_complex_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g2( Q, gsl_matrix_complex_free); gsl_vector_complex *tau = gsl_vector_complex_alloc(p0->Dim(0)-1); GDLGuard g3(tau, gsl_vector_complex_free); gsl_vector *diag = gsl_vector_alloc(p0->Dim(0)); GDLGuard g4( diag, gsl_vector_free); gsl_vector *subdiag = gsl_vector_alloc(p0->Dim(0)-1); GDLGuard g5( subdiag, gsl_vector_free); for( SizeT i=0; idata[2*i], &f64, szdbl); f64 = (double) f32_2[1]; memcpy(&mat->data[2*i+1], &f64, szdbl); } gsl_linalg_hermtd_decomp (mat, tau); gsl_linalg_hermtd_unpack (mat, tau, Q, diag, subdiag); SizeT dims[2] = {p0->Dim(0), p0->Dim(0)}; dimension dim0(dims, (SizeT) 2); BaseGDL** p0Co = &e->GetPar( 0); GDLDelete((*p0Co)); *p0Co = new DComplexGDL(dim0, BaseGDL::NOZERO); SizeT n = p0->Dim(0); dimension dim1(&n, (SizeT) 1); BaseGDL** p1F = &e->GetPar( 1); GDLDelete((*p1F)); *p1F = new DFloatGDL(dim1, BaseGDL::NOZERO); n--; dimension dim2(&n, (SizeT) 1); BaseGDL** p2F = &e->GetPar( 2); GDLDelete((*p2F)); *p2F = new DFloatGDL(dim2, BaseGDL::NOZERO); for( SizeT i=0; iDim(0)*p0->Dim(0); i++) { memcpy(&f64_2[0], &Q->data[2*i], 2*szdbl); f32_2[0] = (float) f64_2[0]; f32_2[1] = (float) f64_2[1]; memcpy(&(*(DComplexGDL*) *p0Co)[i], &f32_2, 2*szflt); } for( SizeT i=0; iDim(0); i++) { memcpy(&f64, &diag->data[i], szdbl); f32 = (float) f64; memcpy(&(*(DFloatGDL*) *p1F)[i], &f32, szflt); } for( SizeT i=0; iDim(0)-1; i++) { memcpy(&f64, &subdiag->data[i], szdbl); f32 = (float) f64; memcpy(&(*(DFloatGDL*) *p2F)[i], &f32, szflt); } // gsl_matrix_complex_free(mat); // gsl_matrix_complex_free(Q); // gsl_vector_complex_free(tau); // gsl_vector_free(diag); // gsl_vector_free(subdiag); } else if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); gsl_matrix_complex *mat = gsl_matrix_complex_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1( mat, gsl_matrix_complex_free); gsl_matrix_complex *Q = gsl_matrix_complex_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g2( Q, gsl_matrix_complex_free); gsl_vector_complex *tau = gsl_vector_complex_alloc(p0->Dim(0)-1); GDLGuard g3(tau, gsl_vector_complex_free); gsl_vector *diag = gsl_vector_alloc(p0->Dim(0)); GDLGuard g4( diag, gsl_vector_free); gsl_vector *subdiag = gsl_vector_alloc(p0->Dim(0)-1); GDLGuard g5( subdiag, gsl_vector_free); memcpy(mat->data, &(*p0C)[0], nEl*szdbl*2); gsl_linalg_hermtd_decomp (mat, tau); gsl_linalg_hermtd_unpack (mat, tau, Q, diag, subdiag); SizeT dims[2] = {p0->Dim(0), p0->Dim(0)}; dimension dim0(dims, (SizeT) 2); BaseGDL** p0Co = &e->GetPar( 0); GDLDelete((*p0Co)); *p0Co = new DComplexDblGDL(dim0, BaseGDL::NOZERO); SizeT n = p0->Dim(0); dimension dim1(&n, (SizeT) 1); BaseGDL** p1D = &e->GetPar( 1); GDLDelete((*p1D)); *p1D = new DDoubleGDL(dim1, BaseGDL::NOZERO); n--; dimension dim2(&n, (SizeT) 1); BaseGDL** p2D = &e->GetPar( 2); GDLDelete((*p2D)); *p2D = new DDoubleGDL(dim2, BaseGDL::NOZERO); memcpy(&(*(DComplexDblGDL*) *p0Co)[0], Q->data, p0->Dim(0)*p0->Dim(0)*szdbl*2); memcpy(&(*(DDoubleGDL*) *p1D)[0], diag->data, p0->Dim(0)*szdbl); memcpy(&(*(DDoubleGDL*) *p2D)[0], subdiag->data, (p0->Dim(0)-1)*szdbl); // gsl_matrix_complex_free(mat); // gsl_matrix_complex_free(Q); // gsl_vector_complex_free(tau); // gsl_vector_free(diag); // gsl_vector_free(subdiag); } else if( p0->Type() == GDL_DOUBLE) { DDoubleGDL* p0D = static_cast( p0); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1( mat, gsl_matrix_free); gsl_matrix *Q = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g2( Q, gsl_matrix_free); gsl_vector *tau = gsl_vector_alloc(p0->Dim(0)-1); GDLGuard g3( tau, gsl_vector_free); gsl_vector *diag = gsl_vector_alloc(p0->Dim(0)); GDLGuard g4( diag, gsl_vector_free); gsl_vector *subdiag = gsl_vector_alloc(p0->Dim(0)-1); GDLGuard g5( subdiag, gsl_vector_free); memcpy(mat->data, &(*p0D)[0], nEl*szdbl); gsl_linalg_symmtd_decomp (mat, tau); gsl_linalg_symmtd_unpack (mat, tau, Q, diag, subdiag); SizeT dims[2] = {p0->Dim(0), p0->Dim(0)}; dimension dim0(dims, (SizeT) 2); BaseGDL** p0Do = &e->GetPar( 0); GDLDelete((*p0Do)); *p0Do = new DDoubleGDL(dim0, BaseGDL::NOZERO); SizeT n = p0->Dim(0); dimension dim1(&n, (SizeT) 1); BaseGDL** p1D = &e->GetPar( 1); GDLDelete((*p1D)); *p1D = new DDoubleGDL(dim1, BaseGDL::NOZERO); n--; dimension dim2(&n, (SizeT) 1); BaseGDL** p2D = &e->GetPar( 2); GDLDelete((*p2D)); *p2D = new DDoubleGDL(dim2, BaseGDL::NOZERO); memcpy(&(*(DDoubleGDL*) *p0Do)[0], Q->data, p0->Dim(0)*p0->Dim(0)*szdbl); memcpy(&(*(DDoubleGDL*) *p1D)[0], diag->data, p0->Dim(0)*szdbl); memcpy(&(*(DDoubleGDL*) *p2D)[0], subdiag->data, (p0->Dim(0)-1)*szdbl); // gsl_matrix_free(mat); // gsl_matrix_free(Q); // gsl_vector_free(tau); // gsl_vector_free(diag); // gsl_vector_free(subdiag); } else if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_INT || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { DFloatGDL* p0F = static_cast( p0); DLongGDL* p0L = static_cast( p0); DULongGDL* p0UL = static_cast( p0); DIntGDL* p0I = static_cast( p0); DUIntGDL* p0UI = static_cast( p0); DByteGDL* p0B = static_cast( p0); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1( mat, gsl_matrix_free); gsl_matrix *Q = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g2( Q, gsl_matrix_free); gsl_vector *tau = gsl_vector_alloc(p0->Dim(0)-1); GDLGuard g3( tau, gsl_vector_free); gsl_vector *diag = gsl_vector_alloc(p0->Dim(0)); GDLGuard g4( diag, gsl_vector_free); gsl_vector *subdiag = gsl_vector_alloc(p0->Dim(0)-1); GDLGuard g5( subdiag, gsl_vector_free); for( SizeT i=0; iType()) { case GDL_FLOAT: f64 = (double) (*p0F)[i]; break; case GDL_LONG: f64 = (double) (*p0L)[i]; break; case GDL_ULONG: f64 = (double) (*p0UL)[i]; break; case GDL_INT: f64 = (double) (*p0I)[i]; break; case GDL_UINT: f64 = (double) (*p0UI)[i]; break; case GDL_BYTE: f64 = (double) (*p0B)[i]; break; default: break; //pacify -Wswitch. } memcpy(&mat->data[i], &f64, szdbl); } gsl_linalg_symmtd_decomp (mat, tau); gsl_linalg_symmtd_unpack (mat, tau, Q, diag, subdiag); SizeT dims[2] = {p0->Dim(0), p0->Dim(0)}; dimension dim0(dims, (SizeT) 2); BaseGDL** p0Fo = &e->GetPar( 0); GDLDelete((*p0Fo)); *p0Fo = new DFloatGDL(dim0, BaseGDL::NOZERO); SizeT n = p0->Dim(0); dimension dim1(&n, (SizeT) 1); BaseGDL** p1F = &e->GetPar( 1); GDLDelete((*p1F)); *p1F = new DFloatGDL(dim1, BaseGDL::NOZERO); n--; dimension dim2(&n, (SizeT) 1); BaseGDL** p2F = &e->GetPar( 2); GDLDelete((*p2F)); *p2F = new DFloatGDL(dim2, BaseGDL::NOZERO); for( SizeT i=0; iDim(0)*p0->Dim(0); i++) { memcpy(&f64, &Q->data[i], szdbl); f32 = (float) f64; memcpy(&(*(DFloatGDL*) *p0Fo)[i], &f32, szflt); } for( SizeT i=0; iDim(0); i++) { memcpy(&f64, &diag->data[i], szdbl); f32 = (float) f64; memcpy(&(*(DFloatGDL*) *p1F)[i], &f32, szflt); } for( SizeT i=0; iDim(0)-1; i++) { memcpy(&f64, &subdiag->data[i], szdbl); f32 = (float) f64; memcpy(&(*(DFloatGDL*) *p2F)[i], &f32, szflt); } // gsl_matrix_free(mat); // gsl_matrix_free(Q); // gsl_vector_free(tau); // gsl_vector_free(diag); // gsl_vector_free(subdiag); } else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); } } // gsl_multiroot_function-compatible function serving as a wrapper to the // user-defined function passed (by name) as the second arg. to NEWTON or BROYDEN class n_b_param { public: EnvT* envt; EnvUDT* nenvt; DDoubleGDL* arg; string errmsg; }; int n_b_function(const gsl_vector* x, void* params, gsl_vector* f) { n_b_param *p = static_cast (params); // copying from GSL to GDL for (size_t i = 0; i < x->size; i++) (*(p->arg))[i] = gsl_vector_get(x, i); // executing GDL code BaseGDL* res; res = p->envt->Interpreter()->call_fun( static_cast (p->nenvt->GetPro())->GetTree() ); // TODO: no guarding if res is an optimized constant // NO!!! the return value of call_fun() is always owned by the caller (constants are Dup()ed) // From 0.9.4 on, call_fun can return left and right values dependent on the call context // which is by default EnvUDT::RFUNCTION, hence the above is *here* correct. Guard res_guard(res); // sanity checks // if (res->Rank() != 1 || res->N_Elements() != x->size) //AC for iCosmo if (res->N_Elements() != x->size) { p->errmsg = "user-defined function must evaluate to a vector of the size of its argument"; return GSL_EBADFUNC; } DDoubleGDL* dres; try { // BUT: Convert2(...) with CONVERT already deletes 'res' here if the type is changed dres = static_cast ( res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT_THROWIOERROR) ); } catch (GDLIOException& ex) { p->errmsg = "failed to convert the result of the user-defined function to double"; return GSL_EBADFUNC; } if (res != dres) { // prevent 'res' from being deleted again res_guard.Release(); res_guard.Init(dres); } // copying from GDL to GSL for (size_t i = 0; i < x->size; i++) gsl_vector_set(f, i, (*dres)[i]); return GSL_SUCCESS; } // a simple error handler for GSL issuing GDL warning messages // an initial call (with file=NULL, line=-1 and gsl_errno=-1) sets a prefix to "reason: " void n_b_gslerrhandler(const char* reason, const char* file, int line, int gsl_errno) { static string prefix; if (line == -1 && gsl_errno == -1 && file == NULL) prefix = string(reason) + ": "; else Warning(prefix + "GSL: " + reason); } // a guard object ensuring freeing of GSL-allocated memory class n_b_gslguard { private: // gsl_vector* x; // gsl_multiroot_fsolver* solver; gsl_error_handler_t* old_handler; public: // n_b_gslguard(gsl_vector* x_, gsl_multiroot_fsolver* solver_, gsl_error_handler_t* old_handler_) n_b_gslguard(gsl_error_handler_t* old_handler_) { // x = x_; // solver = solver_; old_handler = old_handler_; } ~n_b_gslguard() { // gsl_multiroot_fsolver_free(solver); // gsl_vector_free(x); gsl_set_error_handler(old_handler); } }; // SA: the library routine registered in libinit.cpp both for newton(), // broyden() and used in imsl_zerosys.pro (/HYBRID keyword) BaseGDL* newton_broyden(EnvT* e) { // sanity check (for number of parameters) SizeT nParam = e->NParam(); // 1-st argument : initial guess vector BaseGDL* p0 = e->GetParDefined(0); //AC for iCosmo //if (p0->Rank() != 1) e->Throw("the first argument is expected to be a vector"); BaseGDL* par = p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard par_guard(par); // 2-nd argument : name of user function defining the system DString fun; e->AssureScalarPar(1, fun); fun = StrUpCase(fun); if (LibFunIx(fun) != -1) e->Throw("only user-defined functions allowed (library-routine name given)"); // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnv = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx(fun)], (DObjGDL**)NULL); newEnv->SetNextPar(&par); e->Interpreter()->CallStack().push_back(newEnv); // GSL function parameter initialization n_b_param param; param.envt = e; param.nenvt = newEnv; param.arg = static_cast(par); // GSL function initialization gsl_multiroot_function F; F.f = &n_b_function; F.n = p0->N_Elements(); F.params = ¶m; // GSL error handling gsl_error_handler_t* old_handler = gsl_set_error_handler(&n_b_gslerrhandler); // now: reinstall previous error handler (was: GSL ensuring memory de-allocation) n_b_gslguard gslguard = n_b_gslguard(old_handler); n_b_gslerrhandler(e->GetProName().c_str(), NULL, -1, -1); // GSL vector initialization gsl_vector *x = gsl_vector_alloc(F.n); GDLGuard g1( x, gsl_vector_free); for (size_t i = 0; i < F.n; i++) gsl_vector_set(x, i, (*(DDoubleGDL*) par)[i]); // GSL solver initialization gsl_multiroot_fsolver* solver; { const gsl_multiroot_fsolver_type* T; static int HYBRIDIx=e->KeywordIx("HYBRID"); //same place in both functions. if (e->KeywordSet(HYBRIDIx)) T = gsl_multiroot_fsolver_hybrid; //Not using static int KwIx since lists are different. else if (e->GetProName() == "NEWTON") T = gsl_multiroot_fsolver_dnewton; //id else if (e->GetProName() == "BROYDEN") T = gsl_multiroot_fsolver_broyden; //ibid else assert(false); solver = gsl_multiroot_fsolver_alloc(T, F.n); } GDLGuard g2( solver, gsl_multiroot_fsolver_free); gsl_multiroot_fsolver_set(solver, &F, x); // GDL handling fine-tuning keywords // (intentionally not making keyword indices static here (NEWTON vs. BROYDEN)) DLong iter_max = 200; static int ITMAXIx=e->KeywordIx("ITMAX"); //same place in both functions. e->AssureLongScalarKWIfPresent(ITMAXIx, iter_max); //ibid DDouble tolx = 1e-7, tolf = 1e-4; static int TOLXIx=e->KeywordIx("TOLX"); //same place in both functions. e->AssureDoubleScalarKWIfPresent(TOLXIx, tolx); //ibid static int TOLFIx=e->KeywordIx("TOLF"); //same place in both functions. e->AssureDoubleScalarKWIfPresent(TOLFIx, tolf); //ibid // GSL root-finding loop size_t iter = 0; int status; do { iter++; status = gsl_multiroot_fsolver_iterate(solver); if (status) break; { // TOLF check double test_tolf = 0; for (size_t i = 0; i < F.n; i++) test_tolf = max(test_tolf, abs(gsl_vector_get(solver->f, i))); if (test_tolf < tolf) break; } { // TOLX check double test_tolx = 0; for (size_t i = 0; i < F.n; i++) test_tolx = max(test_tolx, abs(gsl_vector_get(solver->dx, i))/max(abs(gsl_vector_get(solver->x, i)), 1.) ); if (test_tolx < tolx) break; } // a check from GSL doc // if (gsl_multiroot_test_residual(solver->f, 1e-7) != GSL_CONTINUE) break; } while (iter <= iter_max); // remembering the result for (size_t i = 0; i < F.n; i++) (*(DDoubleGDL*) par)[i] = gsl_vector_get(solver->x, i); // handling errors from GDL via GSL if (status == GSL_EBADFUNC) e->Throw(static_cast(F.params)->errmsg); // showing an error message if ITMAX reached if (iter > iter_max) e->Throw("maximum number of iterations reached"); // returning the result static int doubleIx=e->KeywordIx("DOUBLE"); //same place in both functions. par_guard.release(); // reusing par for the return value return par->Convert2( // converting to float if neccesarry e->KeywordSet(doubleIx) || p0->Type() == GDL_DOUBLE ? GDL_DOUBLE : GDL_FLOAT, BaseGDL::CONVERT ); } // gsl_multiroot_function-compatible function serving as a wrapper to the // user-defined function passed (by name) as the second arg. to NEWTON or BROYDEN class param_for_minim { public: EnvT* envt; EnvUDT* nenvt; string funcname; DDoubleGDL* arg; bool failed; string errmsg; }; double minim_function(const gsl_vector* x, void* params_minim) { param_for_minim *p = static_cast (params_minim); p->failed=false; // copying from GSL to GDL for (size_t i = 0; i < x->size; i++) (*(p->arg))[i] = gsl_vector_get(x, i); // executing GDL code BaseGDL* res; res = p->envt->Interpreter()->call_fun( static_cast (p->nenvt->GetPro())->GetTree() ); // TODO: no guarding if res is an optimized constant // NO!!! the return value of call_fun() is always owned by the caller (constants are Dup()ed) // From 0.9.4 on, call_fun can return left and right values dependent on the call context // which is by default EnvUDT::RFUNCTION, hence the above is *here* correct. Guard res_guard(res); if (res->N_Elements() != 1) { p->failed=true; p->errmsg = "user-defined function \""+p->funcname+"\" must return a single non-string value"; return std::numeric_limits::quiet_NaN(); } DDoubleGDL* dres; try { // BUT: Convert2(...) with CONVERT already deletes 'res' here if the type is changed dres = static_cast(res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT_THROWIOERROR)); } catch (GDLIOException& ex) { p->failed=true; p->errmsg = "failed to convert the result of the user-defined function \""+p->funcname+"\" to double"; dres=new DDoubleGDL(std::numeric_limits::quiet_NaN()); //we do not return, dres MUST exist! } if (res != dres) { // prevent 'res' from being deleted again res_guard.Release(); res_guard.Init(dres); } // copying from GDL to GSL return (*dres)[0]; } BaseGDL* amoeba(EnvT* e) { DDouble ftol = 1e-7; e->AssureDoubleScalarPar(0, ftol); BaseGDL* test; // name of user function defining the system static int fnameIx = e->KeywordIx("FUNCTION_NAME"); DString fun; if(e->KeywordPresent(fnameIx)) e->AssureScalarKW(fnameIx, fun); else fun="FUNC"; fun = StrUpCase(fun); if (LibFunIx(fun) != -1) e->Throw("only user-defined functions allowed (library-routine name given)"); static int P0Ix = e->KeywordIx("P0"); bool hasp0=false; if(e->KeywordPresent(P0Ix)){ test=e->GetKW(P0Ix); if (test != NULL) hasp0=true; } static int SCALEIx = e->KeywordIx("SCALE"); bool hasScale=false; if (e->KeywordPresent(SCALEIx)){ test=e->GetKW(SCALEIx); if (test != NULL) hasScale=true; } static int SIMPLEXIx = e->KeywordIx("SIMPLEX"); bool hasSimplex=false; if (e->KeywordPresent(SIMPLEXIx)){ test=e->GetKW(SIMPLEXIx); if (test != NULL) hasSimplex=true; } //scale implies p0 and fails reading p0 if it is not present //if p0 is present, and scale is not present, use Simplex if present, silently else throw. bool useSimplex=false; BaseGDL* par0; BaseGDL* p0; Guard p0_guard; BaseGDL* par1; BaseGDL* scale; Guard scale_guard; BaseGDL* par2; BaseGDL* simplex; Guard simplex_guard; if (hasScale) { //suppose p0 exist, and get both Scale and p0 if (hasp0) { par0 = e->GetKW(P0Ix); p0 = par0->Convert2(GDL_DOUBLE, BaseGDL::COPY); p0_guard.Reset(p0); } else e->Throw("Variable is undefined: P0."); //not exactly IDL. IDL throws on P0 not being defined. par1 = e->GetKW(SCALEIx); if (par1->N_Elements() != par0->N_Elements()) { scale=new DDoubleGDL(dimension(par0->N_Elements())); scale_guard.Reset(scale); DDoubleGDL* tmpscale=static_cast(par1->Convert2(GDL_DOUBLE, BaseGDL::COPY)); Guard tmpscale_guard(tmpscale); //deleted immediately when loop exits. SizeT n=tmpscale->N_Elements(); for (SizeT i=0; iN_Elements() ; ++i) (*(DDoubleGDL*)scale)[i]=(*tmpscale)[i%n]; } else { scale = par1->Convert2(GDL_DOUBLE, BaseGDL::COPY); scale_guard.Reset(scale); } //Now that we have p0 and Scale, create a simplex, useful in some cases below. SizeT dims[2]; dims[0] = p0->Dim(0); dims[1] = dims[0]+1; simplex = new DDoubleGDL(dimension(dims,2), BaseGDL::NOZERO); //guard this temporary simplex simplex_guard.Reset(simplex); //populate simplex as p0, p0 + [1,0,...,0] * scale, p0 + [0,1,0,...,0] * scale, ... for (SizeT j = 0; j < dims[0]; ++j) (*(DDoubleGDL*)simplex)[j] = (*(DDoubleGDL*)p0)[j]; //p0 for (SizeT i = 1; i < dims[1]; ++i) { DDouble sc=(*(DDoubleGDL*)scale)[i-1]; for (SizeT j = 0; j < dims[0]; ++j) { (*(DDoubleGDL*)simplex)[j+i*dims[0]] = (*(DDoubleGDL*)p0)[j]+((j==(i-1))?sc:0.0); //warnings about operator precedence solved. } } } else { if (hasSimplex) useSimplex=true; else e->Throw("Either (SCALE,P0) or SIMPLEX must be initialized"); } //if simplex, convert to p0 and scale if (useSimplex) { static int make_warning=true; if (make_warning) { Warning("AMOEBA% SIMPLEX values will be converted to P0 and SCALE, not used directly."); make_warning=false; } par2 = e->GetKW(SIMPLEXIx); //check dimensionality if (par2->Rank()!=2) e->Throw("Simplex is not a 2D array."); SizeT n=par2->Dim(0); if (par2->Dim(1) != n+1) e->Throw("Simplex has wrong dimensions."); simplex = par2->Convert2(GDL_DOUBLE, BaseGDL::COPY); //do not guard simplex, it will be given back //create (temporary) p0 and scale p0 = new DDoubleGDL(dimension(n)); p0_guard.Reset(p0); for (SizeT j=0; jKeywordIx("NMAX"); e->AssureLongScalarKWIfPresent(NMAXIx, nmax); static int NCALLSIx = e->KeywordIx("NCALLS"); bool returnNCalls=e->KeywordPresent(NCALLSIx); static int FUNVALIx = e->KeywordIx("FUNCTION_VALUE"); bool doFunVal=e->KeywordPresent(FUNVALIx); // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnv = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx(fun)], (DObjGDL**) NULL); newEnv->SetNextPar(&p0); e->Interpreter()->CallStack().push_back(newEnv); // GSL function parameter initialization param_for_minim param_minim; param_minim.envt = e; param_minim.nenvt = newEnv; param_minim.funcname = fun; param_minim.arg = static_cast (p0); // GSL function initialization gsl_multimin_function minex_func; minex_func.f = &minim_function; minex_func.n = p0->N_Elements(); minex_func.params = ¶m_minim; // GSL error handling gsl_error_handler_t* old_handler = gsl_set_error_handler(&n_b_gslerrhandler); // now: reinstall previous error handler (was: GSL ensuring memory de-allocation) n_b_gslguard gslguard = n_b_gslguard(old_handler); n_b_gslerrhandler(e->GetProName().c_str(), NULL, -1, -1); // solution values at start gsl_vector *x = gsl_vector_alloc(minex_func.n); GDLGuard g1(x, gsl_vector_free); for (SizeT i = 0; i < minex_func.n; ++i) gsl_vector_set(x, i, (*(DDoubleGDL*)p0)[i]); // initial step sizes gsl_vector *ss = gsl_vector_alloc(minex_func.n); for (SizeT i = 0; i < minex_func.n; ++i) gsl_vector_set(ss, i, (*(DDoubleGDL*)scale)[i]); GDLGuard g2(ss, gsl_vector_free); const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex2; gsl_multimin_fminimizer *s = NULL; size_t iter = 0; int status; double size; s = gsl_multimin_fminimizer_alloc(T, minex_func.n); gsl_multimin_fminimizer_set(s, &minex_func, x, ss); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; size = gsl_multimin_fminimizer_size(s); status = gsl_multimin_test_size(size, ftol); } while (status == GSL_CONTINUE && iter < nmax); // handling errors from GDL via GSL if (param_minim.failed) e->Throw(param_minim.errmsg); if (returnNCalls) e->SetKW(NCALLSIx, new DLongGDL(iter)); bool isDouble; //Caution par0 may not be defined if simplex. if (useSimplex) isDouble=par2->Type()==GDL_DOUBLE; else isDouble=(par0->Type() == GDL_DOUBLE); BaseGDL* ret; if (isDouble) { if (status == GSL_SUCCESS) { ret = new DDoubleGDL(dimension(minex_func.n)); for (SizeT i = 0; i < minex_func.n; ++i) (*(DDoubleGDL*)ret)[i] = gsl_vector_get(s->x, i); } else ret = new DDoubleGDL(-1); } else { if (status == GSL_SUCCESS) { ret = new DFloatGDL(dimension(minex_func.n)); for (SizeT i = 0; i < minex_func.n; ++i) (*(DFloatGDL*)ret)[i] = gsl_vector_get(s->x, i); } else ret = new DFloatGDL(-1); } //give back optimized simplex if (useSimplex) { SizeT n = simplex->Dim(0); //simplex always exist SizeT p = simplex->Dim(1); for (SizeT j = 0; j < n; ++j) (*(DDoubleGDL*)simplex)[j] = gsl_vector_get(s->x, j); for (SizeT i = 1; i < p; ++i) { for (SizeT j = 0; j < n; ++j) { (*(DDoubleGDL*)simplex)[j+i*n] = (*(DDoubleGDL*)simplex)[j]+((j==(i-1))?size:0.0); //warning about operator precedence solved. } } if (isDouble) e->SetKW(SIMPLEXIx, simplex); else { simplex_guard.Reset(simplex); e->SetKW(SIMPLEXIx, simplex->Convert2(GDL_FLOAT, BaseGDL::COPY)); } } // function_value for each simplex. Warning: Destroys ss. if (doFunVal) { gsl_vector_set_all(ss, 0.0); BaseGDL* funval; SizeT n = simplex->Dim(0); //simplex always exist SizeT p = simplex->Dim(1); if (isDouble) { funval = new DDoubleGDL(dimension(p), BaseGDL::NOZERO); for (SizeT i = 0; i < p; ++i) { for (SizeT j = 0; j < n; ++j) gsl_vector_set(x, j, (*(DDoubleGDL*) simplex)[j + i * n]); gsl_multimin_fminimizer_set(s, &minex_func, x, ss); (*(DDoubleGDL*) funval)[i] = s->fval; } } else { funval = new DFloatGDL(dimension(p), BaseGDL::NOZERO); for (SizeT i = 0; i < p; ++i) { for (SizeT j = 0; j < n; ++j) gsl_vector_set(x, j, (*(DDoubleGDL*) simplex)[j + i * n]); gsl_multimin_fminimizer_set(s, &minex_func, x, ss); (*(DFloatGDL*) funval)[i] = s->fval; } } e->SetKW(FUNVALIx, funval); } gsl_multimin_fminimizer_free(s); return ret; } class param_for_minim_fdf { public: EnvT* envt; EnvUDT* nenvt; string funcname_f; string funcname_df; DDoubleGDL* arg; DIntGDL* code; bool failed; string errmsg; }; double minim_function_f(const gsl_vector* x, void* params_minim) { param_for_minim_fdf *p = static_cast (params_minim); p->failed=false; // copying from GSL to GDL for (size_t i = 0; i < x->size; i++) (*(p->arg))[i] = gsl_vector_get(x, i); (*(p->code))[0]=0; // executing our wrapper function with code 0 BaseGDL* res; res = p->envt->Interpreter()->call_fun( static_cast (p->nenvt->GetPro())->GetTree() ); // TODO: no guarding if res is an optimized constant // NO!!! the return value of call_fun() is always owned by the caller (constants are Dup()ed) // From 0.9.4 on, call_fun can return left and right values dependent on the call context // which is by default EnvUDT::RFUNCTION, hence the above is *here* correct. Guard res_guard(res); if (res->N_Elements() != 1) { p->failed=true; p->errmsg = "user-defined function \""+p->funcname_f+"\" must return a single non-string value"; return std::numeric_limits::quiet_NaN(); } DDoubleGDL* dres; try { // BUT: Convert2(...) with CONVERT already deletes 'res' here if the type is changed dres = static_cast(res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT_THROWIOERROR)); } catch (GDLIOException& ex) { p->failed=true; p->errmsg = "failed to convert the result of the user-defined function \""+p->funcname_f+"\" to double"; dres=new DDoubleGDL(std::numeric_limits::quiet_NaN()); //we do not return, dres MUST exist! } if (res != dres) { // prevent 'res' from being deleted again res_guard.Release(); res_guard.Init(dres); } // copying from GDL to GSL return (*dres)[0]; } void minim_function_df(const gsl_vector* x, void* params_minim,gsl_vector * g) { param_for_minim_fdf *p = static_cast (params_minim); p->failed=false; // copying from GSL to GDL for (size_t i = 0; i < x->size; i++) (*(p->arg))[i] = gsl_vector_get(x, i); (*(p->code))[0]=1; // executing our wrapper function with code 0 BaseGDL* res; res = p->envt->Interpreter()->call_fun( static_cast (p->nenvt->GetPro())->GetTree() ); // TODO: no guarding if res is an optimized constant // NO!!! the return value of call_fun() is always owned by the caller (constants are Dup()ed) // From 0.9.4 on, call_fun can return left and right values dependent on the call context // which is by default EnvUDT::RFUNCTION, hence the above is *here* correct. Guard res_guard(res); if (res->N_Elements() != x->size) { p->failed=true; p->errmsg = "user-defined function \""+p->funcname_df+"\" must return "+i2s(x->size)+" value"; } DDoubleGDL* dres; try { // BUT: Convert2(...) with CONVERT already deletes 'res' here if the type is changed dres = static_cast(res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT_THROWIOERROR)); } catch (GDLIOException& ex) { p->failed=true; p->errmsg = "failed to convert the result of the user-defined function \""+p->funcname_df+"\" to double"; dres=new DDoubleGDL(dimension(x->size),BaseGDL::ZERO); //we do not return, dres MUST exist! } if (res != dres) { // prevent 'res' from being deleted again res_guard.Release(); res_guard.Init(dres); } // copying from GDL to GSL: for (SizeT i = 0; i < dres->N_Elements(); ++i) gsl_vector_set(g, i, (*(DDoubleGDL*)dres)[i]); } void minim_function_fdf(const gsl_vector* x, void* params_minim, double *f, gsl_vector * g) { param_for_minim_fdf *p = static_cast (params_minim); p->failed=false; // copying from GSL to GDL for (size_t i = 0; i < x->size; i++) (*(p->arg))[i] = gsl_vector_get(x, i); (*(p->code))[0]=2; // executing our wrapper function with code 0 BaseGDL* res; res = p->envt->Interpreter()->call_fun( static_cast (p->nenvt->GetPro())->GetTree() ); // TODO: no guarding if res is an optimized constant // NO!!! the return value of call_fun() is always owned by the caller (constants are Dup()ed) // From 0.9.4 on, call_fun can return left and right values dependent on the call context // which is by default EnvUDT::RFUNCTION, hence the above is *here* correct. Guard res_guard(res); if (res->N_Elements() != x->size+1) { p->failed=true; p->errmsg = "problem in \""+p->funcname_f+"\" or \""+p->funcname_df+"\"."; return; } DDoubleGDL* dres; try { // BUT: Convert2(...) with CONVERT already deletes 'res' here if the type is changed dres = static_cast(res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT_THROWIOERROR)); } catch (GDLIOException& ex) { p->failed=true; p->errmsg = "failed to convert the result of your function(s) to double"; dres=new DDoubleGDL(dimension(x->size),BaseGDL::ZERO); //we do not return, dres MUST exist! } if (res != dres) { // prevent 'res' from being deleted again res_guard.Release(); res_guard.Init(dres); } // copying from GDL to GSL: *f=(*(DDoubleGDL*)dres)[0]; for (SizeT i = 0; i < dres->N_Elements()-1; ++i) gsl_vector_set(g, i, (*(DDoubleGDL*)dres)[i+1]); } void dfpmin(EnvT* e) { // sanity check (for number of parameters) SizeT nParam = e->NParam(); if (nParam != 5) e->Throw("Incorrect number of arguments."); // 1-st argument : initial guess vector BaseGDL* p0 = e->GetParDefined(0); BaseGDL* xVal = p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); // 2nd argument : gtol DDouble gtol = 0; e->AssureDoubleScalarPar(1,gtol); // 3rd argument : fmin. will be set on exit. //4th argument: function BaseGDL* fun= e->GetParDefined(3); DString sfun = StrUpCase((*(DStringGDL*)fun)[0]); if (LibFunIx(sfun) != -1) e->Throw("only user-defined functions allowed (library-routine name "+sfun+" given)"); //5th argument: derivative function BaseGDL* dfun= e->GetParDefined(4); DString sdfun = StrUpCase((*(DStringGDL*)dfun)[0]); if (LibFunIx(sdfun) != -1) e->Throw("only user-defined functions allowed (library-routine name "+sdfun+" given)"); //but we will use only this special crafted function that accompanies GDL: DStringGDL* gdlFun=new DStringGDL("GDL_MULTIMIN_FDF"); static int DOUBLEIx = e->KeywordIx("DOUBLE"); bool isDouble=(p0->Type()==GDL_DOUBLE); if(e->KeywordSet(DOUBLEIx)) isDouble=true; static int EPSIx = e->KeywordIx("EPS"); DDouble eps=isDouble?3E-10:3E-8; if (e->KeywordPresent(EPSIx)) e->AssureDoubleScalarKW(EPSIx,eps); static int ITMAXIx = e->KeywordIx("ITMAX"); DLong itmax=200; if (e->KeywordPresent(ITMAXIx)) e->AssureLongScalarKW(ITMAXIx,itmax); static int TOLXIx = e->KeywordIx("TOLX"); DDouble tolx=4*eps; if (e->KeywordPresent(TOLXIx)) e->AssureDoubleScalarKW(TOLXIx,tolx); static int STEPMAXIx = e->KeywordIx("STEPMAX"); DDouble stepmax=100.0; if (e->KeywordPresent(STEPMAXIx)) e->AssureDoubleScalarKW(STEPMAXIx,stepmax); BaseGDL* code=new DIntGDL(0); // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnvfun = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx((*gdlFun)[0])], (DObjGDL**) NULL); newEnvfun->SetNextPar(&xVal); //x in function(x,'f','df',code) newEnvfun->SetNextPar(&fun); //f newEnvfun->SetNextPar(&dfun); //df newEnvfun->SetNextPar(&code); //code e->Interpreter()->CallStack().push_back(newEnvfun); // GSL function parameter initialization param_for_minim_fdf param_minim_fdf; param_minim_fdf.envt = e; param_minim_fdf.nenvt = newEnvfun; param_minim_fdf.funcname_f = sfun; param_minim_fdf.funcname_df = sdfun; param_minim_fdf.arg = static_cast (xVal); param_minim_fdf.code = static_cast(code); // GSL function initialization gsl_multimin_function_fdf minex_func_fdf; minex_func_fdf.f = &minim_function_f; minex_func_fdf.df = &minim_function_df; minex_func_fdf.fdf = &minim_function_fdf; minex_func_fdf.n = p0->N_Elements(); minex_func_fdf.params = ¶m_minim_fdf; // GSL error handling gsl_error_handler_t* old_handler = gsl_set_error_handler(&n_b_gslerrhandler); // now: reinstall previous error handler (was: GSL ensuring memory de-allocation) n_b_gslguard gslguard = n_b_gslguard(old_handler); n_b_gslerrhandler(e->GetProName().c_str(), NULL, -1, -1); // solution values at start gsl_vector *x = gsl_vector_alloc(minex_func_fdf.n); GDLGuard g1(x, gsl_vector_free); for (SizeT i = 0; i < minex_func_fdf.n; ++i) gsl_vector_set(x, i, (*(DDoubleGDL*)xVal)[i]); size_t iter = 0; int status; const gsl_multimin_fdfminimizer_type *T = gsl_multimin_fdfminimizer_vector_bfgs2; gsl_multimin_fdfminimizer *s = gsl_multimin_fdfminimizer_alloc(T, minex_func_fdf.n); gsl_multimin_fdfminimizer_set (s, &minex_func_fdf, x, stepmax, gtol); do { iter++; status = gsl_multimin_fdfminimizer_iterate(s); if (status) break; status = gsl_multimin_test_gradient(s->gradient, gtol); } while (status == GSL_CONTINUE && iter < itmax); // handling errors from GDL via GSL if (param_minim_fdf.failed) e->Throw(param_minim_fdf.errmsg); for (SizeT j = 0; j < p0->N_Elements(); ++j) (*(DDoubleGDL*)xVal)[j] = gsl_vector_get(s->x, j); if (isDouble) { e->SetPar(0, xVal); e->SetPar(2, new DDoubleGDL(s->f)); } else { Guard xval_guard(xVal); e->SetPar(0, xVal->Convert2(GDL_FLOAT, BaseGDL::COPY)); e->SetPar(2, new DFloatGDL(s->f)); } gsl_multimin_fdfminimizer_free(s); } // ------------------------------------------------------------------------- // GSL don't have implementations of QROMB and QROMO but alternatives // AC, 10 Jan 2011, to have it for iCosmos class qromb_param { public: EnvT* envt; EnvUDT* nenvt; DDoubleGDL* arg; string errmsg; }; double qromb_function(double x, void* params) { qromb_param *p = static_cast(params); (*(p->arg))[0]=x; BaseGDL* res; // marc: is this ok? call_fun will be executed within the actual (callStack.back()) environment res = p->envt->Interpreter()->call_fun(static_cast(p->nenvt->GetPro())->GetTree()); // res can be of any type! // return (*static_cast(res))[0]; DDoubleGDL* resDouble = static_cast(res->Convert2(GDL_DOUBLE, BaseGDL::CONVERT)); // Guard guard(resDouble); double retRes = (*resDouble)[0]; delete resDouble; // direct delete should be faster than setting up a guard return retRes; } // AC: the library routine is registered in libinit_ac.cpp BaseGDL* qromb_fun(EnvT* e) { int debug=0; // sanity check (for number of parameters) SizeT nParam = e->NParam(3); // 2-nd argument : initial bound BaseGDL* p1 = e->GetParDefined(1); BaseGDL* par1 = p1->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard par1_guard(par1); // 3-th argument : final bound BaseGDL* p2 = e->GetParDefined(2); BaseGDL* par2 = p2->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard par2_guard(par2); // 1-st argument : name of user function defining the system DString fun; e->AssureScalarPar(0, fun); fun = StrUpCase(fun); if (LibFunIx(fun) != -1) e->Throw("only user-defined functions allowed (library-routine name given)"); // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnv = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx(fun)], (DObjGDL**)NULL); newEnv->SetNextPar(&par1); e->Interpreter()->CallStack().push_back(newEnv); // GSL function parameter initialization qromb_param param; param.envt = e; param.nenvt = newEnv; param.arg = static_cast(par1); // GSL function initialization gsl_function F; F.function = &qromb_function; F.params = ¶m; double result, error; double first, last; SizeT nEl1=par1->N_Elements(); SizeT nEl2=par2->N_Elements(); SizeT nEl=nEl1; DDoubleGDL* res; if (nEl1 == 1 || nEl2 == 1) { if (nEl1 == 1) { nEl=nEl2; res=new DDoubleGDL(par2->Dim(), BaseGDL::NOZERO); } if (nEl2 == 1) { res=new DDoubleGDL(par1->Dim(), BaseGDL::NOZERO); nEl=nEl1; } } else { if (nEl1 <= nEl2) { res=new DDoubleGDL(par1->Dim(), BaseGDL::NOZERO); } else { res=new DDoubleGDL(par2->Dim(), BaseGDL::NOZERO); nEl=nEl2; } } // Definition of JMAX int pos; DLong wsize =static_cast(pow(2.0, (20-1))); static int JMAXIx=e->KeywordIx("JMAX"); //same place in both functions. if(e->KeywordSet(JMAXIx)) //ibid { e->AssureLongScalarKWIfPresent(JMAXIx, wsize); wsize=static_cast(pow(2.0, (wsize-1))); } // eps value: double eps, eps_default; static int doubleIx=e->KeywordIx("DOUBLE"); //same place in both functions. bool isDouble = e->KeywordSet(doubleIx) || p1->Type() == GDL_DOUBLE || p2->Type() == GDL_DOUBLE; if (isDouble) {eps_default=1.e-12;} else {eps_default=1.e-6;} static int EPSIx=e->KeywordIx("EPS"); //same place in both functions if (e->KeywordSet(EPSIx)) { e->AssureDoubleScalarKWIfPresent(EPSIx, eps); if (eps < 0.0) { Message(e->GetProName() + ": EPS must be positive ! Value set to Default."); eps=eps_default; } if(!isfinite(eps)) { Message(e->GetProName() + ": EPS must be finite ! Value set to Default."); eps=eps_default; } } else { eps=eps_default; } gsl_integration_workspace *w = gsl_integration_workspace_alloc (wsize); GDLGuard g1( w, gsl_integration_workspace_free); first=(*static_cast(par1))[0]; last =(*static_cast(par2))[0]; for( SizeT i=0; i 1) {first=(*static_cast(par1))[i];} if (nEl2 > 1) {last =(*static_cast(par2))[i];} if (debug) cout << "Boundaries : "<< first << " " << last <Convert2(GDL_FLOAT, BaseGDL::CONVERT); } } // AC: the library routine is registered in libinit_ac.cpp BaseGDL* qromo_fun(EnvT* e) { int debug=0; // sanity check (for number of parameters) // AC 2016/10/13 : we cannot test here 2 or 3 since both are possible SizeT nParam = e->NParam(); static int midexpIx=e->KeywordIx("MIDEXP"); bool do_midexp=e->KeywordSet(midexpIx); if (do_midexp) { if (nParam < 2) e->Throw("Incorrect number of arguments."); if (nParam > 2) e->Throw("Too many arguments."); } else { if (nParam < 3) e->Throw("Incorrect number of arguments."); } // 2-nd argument : initial bound BaseGDL* p1 = NULL; BaseGDL* par1 = NULL; p1 = e->GetParDefined(1); par1 = p1->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard par1_guard(par1); BaseGDL* p2 = NULL; BaseGDL* par2 = NULL; if (!do_midexp) { // 3-th argument : final bound p2 = e->GetParDefined(2); par2 = p2->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard par2_guard(par2); } // do we need to compute/return in double ? static int doubleIx=e->KeywordIx("DOUBLE"); bool isDouble = e->KeywordSet(doubleIx) || p1->Type() == GDL_DOUBLE; if (!do_midexp) if (p2->Type() == GDL_DOUBLE) isDouble=true; // 1-st argument : name of user function defining the system DString fun; e->AssureScalarPar(0, fun); fun = StrUpCase(fun); if (LibFunIx(fun) != -1) e->Throw("only user-defined functions allowed (library-routine name given)"); gsl_error_handler_t* old_handler = gsl_set_error_handler(&n_b_gslerrhandler); n_b_gslerrhandler(e->GetProName().c_str(), NULL, -1, -1); // Check for impossible case bool flag=0; for(SizeT i=4;i<=8;i++) { if(flag==1 && e->KeywordPresent(i)) { e->Throw("Incorrect number of arguments."); } else if (flag==0 && e->KeywordPresent(i)) flag=1; } // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnv = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx(fun)], (DObjGDL**)NULL); newEnv->SetNextPar(&par1); e->Interpreter()->CallStack().push_back(newEnv); // GSL function parameter initialization qromb_param param; param.envt = e; param.nenvt = newEnv; param.arg = static_cast(par1); // GSL function initialization gsl_function F; F.function = &qromb_function; F.params = ¶m; double result, error; double first, last; SizeT nEl1=par1->N_Elements(); SizeT nEl2=nEl1; if (!do_midexp) nEl2=par2->N_Elements(); SizeT nEl=nEl1; DDoubleGDL* res; if (!do_midexp) { if (nEl1 == 1 || nEl2 == 1) { if (nEl1 == 1) { nEl=nEl2; res=new DDoubleGDL(par2->Dim(), BaseGDL::NOZERO); } if (nEl2 == 1) { res=new DDoubleGDL(par1->Dim(), BaseGDL::NOZERO); nEl=nEl1; } } else { if (nEl1 <= nEl2) { res=new DDoubleGDL(par1->Dim(), BaseGDL::NOZERO); } else { res=new DDoubleGDL(par2->Dim(), BaseGDL::NOZERO); nEl=nEl2; } } } else res=new DDoubleGDL(par1->Dim(), BaseGDL::NOZERO); // managing eps value: double eps, eps_default; if (isDouble) {eps_default=1.e-12;} else {eps_default=1.e-6;} int pos; static int epsIx=e->KeywordIx("EPS"); if (e->KeywordSet(epsIx)) { e->AssureDoubleScalarKWIfPresent(epsIx, eps); if (eps < 0.0) { Message(e->GetProName() + ": EPS must be positive ! Value set to Default."); eps=eps_default; } if(!isfinite(eps)) { Message(e->GetProName() + ": EPS must be finite ! Value set to Default."); eps=eps_default; } } else { eps=eps_default; } // Definition of JMAX DLong wsize =static_cast(pow(2.0, (20-1))); static int jmaxIx=e->KeywordIx("JMAX"); if(e->KeywordSet(jmaxIx)) { e->AssureLongScalarKWIfPresent(jmaxIx, wsize); wsize=static_cast(pow(2.0, (wsize-1))); } gsl_integration_workspace *w = gsl_integration_workspace_alloc (wsize); GDLGuard g1( w, gsl_integration_workspace_free); first=(*static_cast(par1))[0]; if (!do_midexp) last =(*static_cast(par2))[0]; for( SizeT i=0; i 1) {first=(*static_cast(par1))[i];} if ((!do_midexp) && (nEl2 > 1)) {last =(*static_cast(par2))[i];} if (debug) cout << "Boundaries : "<< first << " " << last <KeywordIx("MIDINF"); static int midpntIx=e->KeywordIx("MIDPNT"); static int midsqlIx=e->KeywordIx("MIDSQL"); static int midsquIx=e->KeywordIx("MIDSQU"); static int jmaxIx=e->KeywordIx("JMAX"); // Mimic IDL behavior for K static int kkkIx=e->KeywordIx("K"); if (e->KeywordPresent(kkkIx)) { DLong k=0; DFloat kk; e->AssureFloatScalarKW(kkkIx, kk); k=(long) floor(kk); if (k < 1) e->Throw("K value must be >= 1 (not used)."); } // intregation on open range [first,+inf[ if (do_midexp) { gsl_integration_qagiu(&F, first, 0, eps, wsize, w, &result, &error); } else if (e->KeywordSet(midinfIx) || e->KeywordSet(midpntIx) || e->KeywordSet(midsqlIx) || e->KeywordSet(midsquIx) || e->KeywordSet(jmaxIx) || e->KeywordSet(kkkIx)) { gsl_integration_qag(&F, first, last, 0, eps, wsize, GSL_INTEG_GAUSS61, w, &result, &error); } else { // AC 2012-10-10: ToDo: checks on values at the boundaries. // if no problem, using QAG, else QAGS // intregation on open range ]first,last[ gsl_integration_qags(&F, first, last, 0, eps, wsize, w, &result, &error); } if (debug) cout << "Result : " << result << endl; (*res)[i]=result; } // gsl_integration_workspace_free (w); if (isDouble) return res; else return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); } //FZ_ROOT:compute polynomial roots BaseGDL* fz_roots_fun(EnvT* e) { static int doubleIx = e->KeywordIx("DOUBLE"); // Ascending coefficient array BaseGDL* p0 = e->GetNumericArrayParDefined(0); DDoubleGDL* coef = e->GetParAs(0); // GSL function if (ComplexType(p0->Type())) { e->Throw("Polynomials with complex coefficients not supported yet (FIXME!)"); } if (coef->N_Elements() < 2) { e->Throw("Degree of the polynomial must be strictly greather than zero"); } for (int i = 0; i N_Elements();i++) { if (!isfinite((*coef)[i])) e->Throw("Not a number and infinity are not supported"); } gsl_poly_complex_workspace* w = gsl_poly_complex_workspace_alloc (coef->N_Elements()); GDLGuard g1( w, gsl_poly_complex_workspace_free); SizeT resultSize = coef->N_Elements()-1; vector tmp(2 * resultSize); gsl_poly_complex_solve (&(*coef)[0],coef->N_Elements(),w, &(tmp[0])); // gsl_poly_complex_workspace_free (w); int debug =0; if (debug) { for (int i = 0; i < resultSize; i++) { printf ("z%d = %+.18f %+.18f\n", i, tmp[2*i], tmp[2*i+1]); } } DComplexDblGDL* result = new DComplexDblGDL(dimension(resultSize), BaseGDL::NOZERO); for (SizeT i = 0; i < resultSize; ++i) { (*result)[i] = complex(tmp[2 * i], tmp[2 * i + 1]); } return result->Convert2( e->KeywordSet(doubleIx) || p0->Type() == GDL_DOUBLE ? GDL_COMPLEXDBL : GDL_COMPLEX, BaseGDL::CONVERT); } //FX_ROOT class fx_root_param { public: EnvT* envt; EnvUDT* nenvt; DComplexDblGDL* arg; }; complex fx_root_function(complex x,void* params) { fx_root_param *p = static_cast(params); (*(p->arg))[0] = x; BaseGDL* res; res = p->envt->Interpreter()->call_fun(static_cast(p->nenvt->GetPro())->GetTree()); return (*static_cast(res))[0]; } BaseGDL* fx_root_fun(EnvT* e) { //Sanity check //SizeT nParam = e->NParam(); //cout << nParam << endl; //1-st argument: a 2-element real or complex initial guess array BaseGDL* p0 = e->GetNumericArrayParDefined(0); DComplexDblGDL* init = e->GetParAs(0); BaseGDL* par0 = p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY); Guard par0_guard(par0); if (init->N_Elements() != 3) { e->Throw("Initial guess vector must be a 3-element vector"); } // 2-nd argument : function name DString fun; e->AssureScalarPar(1, fun); fun = StrUpCase(fun); //cout<Throw("only user-defined functions allowed (library-routine name given)"); // GDL magick StackGuard guard(e->Interpreter()->CallStack()); EnvUDT* newEnv = new EnvUDT(e->CallingNode(), funList[GDLInterpreter::GetFunIx(fun)], (DObjGDL**)NULL); newEnv->SetNextPar(&par0); e->Interpreter()->CallStack().push_back(newEnv); // Function parameter initialization fx_root_param param; param.envt = e; param.nenvt = newEnv; param.arg = static_cast(par0); //3-rd argument : number of iteration DLong max_iter =100; static int itmaxIx = e->KeywordIx("ITMAX"); if (e->KeywordSet(itmaxIx)) { e->AssureLongScalarKWIfPresent(itmaxIx, max_iter); } //4-th argument : stopping criterion DLong stop = 0; static int stopIx = e->KeywordIx("STOP"); if (e->KeywordSet(stopIx)) { e->AssureLongScalarKWIfPresent(stopIx, stop); } if (stop != 0 || stop != 1 || isfinite(stop) == 0) { DLong stop = 0; } //5-th argument : tolerance criterion DDouble tol = 0.0001; static int tolIx = e->KeywordIx("TOL"); if (e->KeywordSet(tolIx)) { e->AssureDoubleScalarKWIfPresent(tolIx, tol); } if (isfinite(tol) == 0) { DDouble tol = 0.0001; } //Mueller method //Initialization and interpolation complex x0((*init)[0].real(),(*init)[0].imag()); complex x1((*init)[1].real(),(*init)[1].imag()); complex x2((*init)[2].real(),(*init)[2].imag()); //Security tests if ( (x0.real() == x1.real() && x0.imag() == x1.imag()) || (x0.real() == x2.real() && x0.imag() == x2.imag()) || (x1.real() == x2.real() && x1.imag() == x2.imag()) ) { e->Throw("Initial parameters must be different"); } if ((isfinite(x0.real()) == 0 || isfinite(x0.imag()) == 0) || (isfinite(x1.real()) == 0 || isfinite(x1.imag()) == 0) || (isfinite(x2.real()) == 0 || isfinite(x2.imag()) == 0)) { e->Throw("Not a number and Infinity are not supported"); } complex fx0 = fx_root_function(x0,¶m); complex fx1 = fx_root_function(x1,¶m); complex fx2 = fx_root_function(x2,¶m); complex den = (x0-x2)*(x1-x2)*(x0-x1); complex a = ((x1-x2)*(fx0-fx2)-(x0-x2)*(fx1-fx2))/den; complex b = (pow(x0-x2,2)*(fx1-fx2)-pow(x1-x2,2)*(fx0-fx2))/den; complex c = fx2; complex op; int iter = 0; double stopcri; DComplexDblGDL* res; res=new DComplexDblGDL(1, BaseGDL::NOZERO); // before going further, we check whether the "x_i" are roots ?! int done=0; if (abs(fx0) < tol) {(*res)[0] = x0; done=1;} if (abs(fx1) < tol) {(*res)[0] = x1; done=1;} if (abs(fx2) < tol) {(*res)[0] = x2; done=1;} if (done ==0) { complex tmpdisc; complex discm; complex discp; int debug=0; do { iter++; if (stop == 1) { stopcri =abs(fx_root_function(x2,¶m)); } else { stopcri = abs(x1-x2); } tmpdisc=sqrt(pow(b,2)-4.*a*c); if (debug) { cout << "Iteration " << iter << endl; cout << "x0: " << setprecision(15) << x0 << endl; cout << "x1: " << setprecision(15) << x1 << endl; cout << "x2: " << setprecision(15) << x2 << endl; cout << "tmpdisc "<< tmpdisc << endl; } discm=b-tmpdisc; discp=b+tmpdisc; if (abs(discm) < abs(discp)) {op = 2.*c/discp;} else {op = 2.*c/discm;} x0 = x1; x1 = x2; x2 = x2 - op; fx0 = fx1; fx1 = fx2; fx2 = fx_root_function(x2,¶m); den = (x0-x2)*(x1-x2)*(x0-x1); a = ((x1-x2)*(fx0-fx2)-(x0-x2)*(fx1-fx2))/den; b = (pow(x0-x2,2)*(fx1-fx2)-pow(x1-x2,2)*(fx0-fx2))/den; c = fx2; (*res)[0] = x1; } while (stopcri >= tol && (isfinite(x2.real()) == 1 && isfinite(x2.imag()) == 1) && iter < max_iter); } static int DOUBLEIx=e->KeywordIx("DOUBLE"); bool isdouble=e->KeywordSet(DOUBLEIx); if ((*res)[0].imag() == 0) { DDoubleGDL* resreal; resreal = new DDoubleGDL(1, BaseGDL::NOZERO); (*resreal)[0] = (*res)[0].real(); if (isdouble || p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_DOUBLE) { return resreal->Convert2(GDL_DOUBLE, BaseGDL::CONVERT); } else { return resreal->Convert2(GDL_FLOAT, BaseGDL::CONVERT); } } if (isdouble || p0->Type() == GDL_COMPLEXDBL) { return res->Convert2(GDL_COMPLEXDBL, BaseGDL::CONVERT); } else { return res->Convert2(GDL_COMPLEX, BaseGDL::CONVERT); } } /* * SA: TODO: * constants: Catalan * units: ounce, oz, AU, mill, Fahrenheit, stoke, Abcoulomb, ATM (atm works!) * prefixes: u (micro) */ BaseGDL* constant(EnvT* e) { string name; bool twoparams=false; if (e->NParam(1) == 2) twoparams=true; DStructGDL *Values = SysVar::Values(); //MUST NOT BE STATIC, due to .reset static double nan = (*static_cast(Values->GetTag(Values->Desc()->TagIndex("D_NAN"), 0)))[0]; #ifdef USE_UDUNITS string unit; #endif { #ifdef USE_UDUNITS DString tmpunit; #endif if (twoparams) { #ifdef USE_UDUNITS e->AssureScalarPar(1, tmpunit); unit.reserve(tmpunit.length()); for (string::iterator it = tmpunit.begin(); it < tmpunit.end(); it++) if (*it != ' ') unit.append(1, *it); #else e->Throw("GDL was compiled without support for UDUNITS"); #endif } DString tmpname; e->AssureScalarPar(0, tmpname); name.reserve(tmpname.length()); for (string::iterator it = tmpname.begin(); it < tmpname.end(); ++it) if (*it != ' ' && *it != '_') name.append(1, (char)std::tolower(*it)); } #ifdef USE_UDUNITS ut_set_error_message_handler(ut_ignore); // making the unit catalogue static to gain performace in the next call static ut_system* unitsys = ut_read_xml(NULL); if (unitsys == NULL) e->Throw("UDUNITS: failed to load the default unit database"); ut_unit* unit_from; #endif DDoubleGDL *res; if (name.compare("amu") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_UNIFIED_ATOMIC_MASS); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "kg", UT_ASCII); #endif } else if (name.compare("atm") == 0 || name.compare("standardpressure") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_STD_ATMOSPHERE); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "N/m2", UT_ASCII); #endif } else if (name.compare("au") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_ASTRONOMICAL_UNIT); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "m", UT_ASCII); #endif } else if (name.compare("avogadro") == 0) { res = new DDoubleGDL(GSL_CONST_NUM_AVOGADRO); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "1/mole", UT_ASCII); #endif } else if (name.compare("boltzman") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_BOLTZMANN); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "J/K", UT_ASCII); #endif } else if (name.compare("c") == 0 || name.compare("speedlight") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_SPEED_OF_LIGHT); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "m/s", UT_ASCII); #endif } // else if (name.compare("catalan") == 0) // { // res = new DDoubleGDL(); // TODO: Dirichlet Beta function! //#ifdef USE_UDUNITS // if (twoparams) unit_from = ut_parse(unitsys, "", UT_ASCII); //#endif // } else if (name.compare("e") == 0) { res = new DDoubleGDL(M_E); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_get_dimensionless_unit_one(unitsys); #endif } else if (name.compare("electroncharge") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_ELECTRON_CHARGE); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "C", UT_ASCII); #endif } else if (name.compare("electronmass") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_MASS_ELECTRON); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "kg", UT_ASCII); #endif } else if (name.compare("electronvolt") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_ELECTRON_VOLT); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "J", UT_ASCII); #endif } else if (name.compare("euler") == 0 || name.compare("gamma") == 0) { res = new DDoubleGDL(M_EULER); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_get_dimensionless_unit_one(unitsys); #endif } else if (name.compare("faraday") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_FARADAY); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "C/mole", UT_ASCII); #endif } else if (name.compare("finestructure") == 0) { res = new DDoubleGDL(GSL_CONST_NUM_FINE_STRUCTURE); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_get_dimensionless_unit_one(unitsys); #endif } else if (name.compare("gas") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_MOLAR_GAS); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "J/mole/K", UT_ASCII); #endif } else if (name.compare("gravity") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_GRAVITATIONAL_CONSTANT); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "N m2 kg-2", UT_ASCII); #endif } else if (name.compare("hbar") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_PLANCKS_CONSTANT_HBAR); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "J s", UT_ASCII); #endif } else if (name.compare("perfectgasvolume") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_STANDARD_GAS_VOLUME); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "m3/mole", UT_ASCII); #endif } else if (name.compare("pi") == 0) { res = new DDoubleGDL(M_PI); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_get_dimensionless_unit_one(unitsys); #endif } else if (name.compare("planck") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_PLANCKS_CONSTANT_H); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "J s", UT_ASCII); #endif } else if (name.compare("protonmass") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_MASS_PROTON); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "kg", UT_ASCII); #endif } else if (name.compare("rydberg") == 0) { res = new DDoubleGDL( GSL_CONST_MKSA_MASS_ELECTRON * pow(GSL_CONST_MKSA_ELECTRON_CHARGE, 4) / ( 8. * pow(GSL_CONST_MKSA_VACUUM_PERMITTIVITY, 2) * pow(GSL_CONST_MKSA_PLANCKS_CONSTANT_H, 3) * GSL_CONST_MKSA_SPEED_OF_LIGHT ) ); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "m-1", UT_ASCII); #endif } else if (name.compare("standardgravity") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_GRAV_ACCEL); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "m/s2", UT_ASCII); #endif } else if (name.compare("stefanboltzman") == 0) { res = new DDoubleGDL(GSL_CONST_MKSA_STEFAN_BOLTZMANN_CONSTANT); #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "W/K4/m2", UT_ASCII); #endif } else if (name.compare("watertriple") == 0) { res = new DDoubleGDL(273.16); // e.g. http://wtt-lite.nist.gov/cgi-bin/openindex.cgi?cid=7732185 #ifdef USE_UDUNITS if (twoparams) unit_from = ut_parse(unitsys, "K", UT_ASCII); #endif } else { Warning("IMSL_CONSTANT: unknown constant"); res = new DDoubleGDL(nan); twoparams = false; } // units #ifdef USE_UDUNITS if (twoparams) { assert(unit_from != NULL); ut_unit* unit_to = ut_parse(unitsys, unit.c_str(), UT_ASCII); if (unit_to == NULL) { Warning("IMSL_CONSTANT: UDUNITS: failed to parse unit"); (*res)[0] = nan; } else { cv_converter* converter = ut_get_converter(unit_from, unit_to); if (converter == NULL) { Warning("IMSL_CONSTANT: UDUNITS: units not convertible"); (*res)[0] = nan; } else { (*res)[0] = cv_convert_double(converter, (*res)[0]); cv_free(converter); } } ut_free(unit_from); // leaks? ut_free(unit_to); // leaks? //ut_free_system(unitsys); // (made static above) } #endif static int doubleIx = e->KeywordIx("DOUBLE"); return res->Convert2(e->KeywordSet(doubleIx) ? GDL_DOUBLE : GDL_FLOAT, BaseGDL::CONVERT); } BaseGDL* binomialcoef(EnvT* e) { SizeT nParam=e->NParam(2); if (!IntType(e->GetParDefined(0)->Type()) || !IntType(e->GetParDefined(1)->Type())) e->Throw("Arguments must not be floating point numbers"); DLong n, m; e->AssureLongScalarPar(0, n); e->AssureLongScalarPar(1, m); if (n < 0 || m < 0 || n < m) e->Throw("Arguments must fulfil n >= m >= 0"); BaseGDL* res = new DDoubleGDL(gsl_sf_choose(n, m)); static int doubleIx = e->KeywordIx("DOUBLE"); return res->Convert2(e->KeywordSet(doubleIx) ? GDL_DOUBLE : GDL_FLOAT, BaseGDL::CONVERT); } // // SA: helper routines/classes for WTN // // an auto_ptr-like class for guarding wavelets // class gsl_wavelet_guard // { // gsl_wavelet* wavelet; // public: // gsl_wavelet_guard(gsl_wavelet* wavelet_) { wavelet = wavelet_; } // ~gsl_wavelet_guard() { gsl_wavelet_free(wavelet); } // }; // // as auto_ptr-like class for guarding wavelet_workspaces // class gsl_wavelet_workspace_guard // { // gsl_wavelet_workspace* workspace; // public: // gsl_wavelet_workspace_guard(gsl_wavelet_workspace* workspace_) { workspace = workspace_; } // ~gsl_wavelet_workspace_guard() { gsl_wavelet_workspace_free(workspace); } // }; // a simple error handler for GSL issuing GDL warning messages // an initial call (with file=NULL, line=-1 and gsl_errno=-1) sets a prefix to "reason: " // TODO: merge with the code of NEWTON/BROYDEN/IMSL_HYBRID void gsl_err_2_gdl_warn(const char* reason, const char* file, int line, int gsl_errno) { static string prefix; if (line == -1 && gsl_errno == -1 && file == NULL) prefix = string(reason) + ": "; else Warning(prefix + "GSL: " + reason); } class gsl_err_2_gdl_warn_guard { gsl_error_handler_t* old_handler; public: gsl_err_2_gdl_warn_guard(gsl_error_handler_t* old_handler_) { old_handler = old_handler_; } ~gsl_err_2_gdl_warn_guard() { gsl_set_error_handler(old_handler); } }; // SA: 1. Numerical Recipes, and hence IDL as well, calculate the transform until there are // two smoothing coefficients left, while GSL leaves out just one, thus: // - IDL skips computations for four or less elements, while the limit of GSL is 2 // - plot, wtn([1,0,0,0,0,0,0,0],4,/inv) have different result in GDL and IDL // 2. As of version 1.13 GSL supports only two dimensions (checked at GDL level), and // square matrices in 2D case (left for the GSL error handler to report) BaseGDL* wtn(EnvT* e) { SizeT nParam=e->NParam(2); static int doubleIx = e->KeywordIx("DOUBLE"); static int overwriteIx = e->KeywordIx("OVERWRITE"); static int columnIx = e->KeywordIx("COLUMN"); static int inverseIx = e->KeywordIx("INVERSE"); // sanity checks for the first argument - array, each dimension of length of 2^n BaseGDL* p0 = e->GetNumericArrayParDefined(0); for (SizeT dim = 0; dim < p0->Rank(); dim++) if ((p0->Dim(dim) & (p0->Dim(dim) - 1)) != 0) e->Throw("Dimensions of array must be powers of 2: " + e->GetParString(0)); // sanity checks for the second argument // check for value will be done by GSL (supported numbers are 4, 6, 8, 10, 12, 14, 16, 18, 20) // (IDL supports 4, 12 and 20) DLong p1; e->AssureLongScalarPar(1, p1); // sanity checkf for GSL constraints if (p0->Rank() > 2) e->Throw("Only one- and two-dimensional transforms supported by GSL"); // preparing output (GSL always uses double precision and always works in-situ) DType inputType = p0->Type(); DDoubleGDL* ret; Guard ret_guard; if( !e->KeywordSet(overwriteIx)) { bool stolen = e->StealLocalPar(0); if( inputType == GDL_DOUBLE && stolen) { ret = static_cast(p0); ret_guard.Init(ret); } else { if( stolen) ret = static_cast(p0->Convert2( GDL_DOUBLE, BaseGDL::CONVERT )); else ret = static_cast(p0->Convert2( GDL_DOUBLE, BaseGDL::COPY )); ret_guard.Init(ret); } } else { bool stolen = e->StealLocalPar(0); if( stolen) { // was local par ret = static_cast(p0->Convert2( GDL_DOUBLE, BaseGDL::CONVERT )); ret_guard.Init(ret); } else { assert( e->GlobalPar(0)); if( inputType == GDL_DOUBLE) { ret = static_cast(p0); e->SetPtrToReturnValue( &e->GetPar(0)); } else { ret = static_cast(p0->Convert2( GDL_DOUBLE, BaseGDL::COPY )); ret_guard.Init(ret); } } } // GSL error handling gsl_error_handler_t* old_handler = gsl_set_error_handler(&gsl_err_2_gdl_warn); gsl_err_2_gdl_warn_guard old_handler_guard(old_handler); gsl_err_2_gdl_warn(e->GetProName().c_str(), NULL, -1, -1); // initializing wavelet ceofficients gsl_wavelet *wavelet = gsl_wavelet_alloc(gsl_wavelet_daubechies, p1); if (wavelet == NULL) e->Throw("Failed to initialize the wavelet filter coefficients"); GDLGuard wavelet_guard(wavelet, gsl_wavelet_free); //gsl_wavelet_guard wavelet_guard = gsl_wavelet_guard(wavelet); // initializing workspace (N -> N, NxN -> N, 1xN -> N) gsl_wavelet_workspace *workspace = gsl_wavelet_workspace_alloc(max(ret->Dim(0), ret->Dim(1))); if (workspace == NULL) e->Throw("Failed to allocate scratch memory"); GDLGuard workspace_guard( workspace, gsl_wavelet_workspace_free); //gsl_wavelet_workspace_guard workspace_guard = gsl_wavelet_workspace_guard(workspace); // 1D (or 1xN) case if (ret->Rank() == 1 || (ret->Rank() == 2 && ret->Dim(0) == 1)) { if (GSL_SUCCESS != gsl_wavelet_transform( wavelet, &(*ret)[0], 1, // stride ret->N_Elements(), e->KeywordSet(inverseIx) ? gsl_wavelet_backward : gsl_wavelet_forward, workspace )) e->Throw("Failed to compute the transform"); // transposing the result if /COLUMN was set if (e->KeywordSet(columnIx)) ret->SetDim(ret->Rank() == 1 ? dimension(1, ret->N_Elements()) : dimension(ret->N_Elements()) ); } // 2D case else { if (GSL_SUCCESS != gsl_wavelet2d_transform( wavelet, &((*ret)[0]), ret->Dim(0), // physical row length ret->Dim(0), // number of rows ret->Dim(1), // number of columns e->KeywordSet(inverseIx) ? gsl_wavelet_backward : gsl_wavelet_forward, workspace )) e->Throw("Failed to compute the transform"); // TODO: make a proper n-dimensional suuport! if (e->KeywordSet(columnIx)) { DDoubleGDL* tmp; tmp = ret; ret = static_cast(ret->Transpose(NULL)); GDLDelete(tmp); } } // returning ret_guard.release(); return ret->Convert2( e->KeywordSet(doubleIx) || inputType == GDL_DOUBLE ? GDL_DOUBLE : GDL_FLOAT, BaseGDL::CONVERT ); } // SA: helper class for zeropoly // an auto_ptr-like class for guarding the poly_complex_workspace // class gsl_poly_complex_workspace_guard // { // gsl_poly_complex_workspace* workspace; // public: // gsl_poly_complex_workspace_guard(gsl_poly_complex_workspace* workspace_) { workspace = workspace_; } // ~gsl_poly_complex_workspace_guard() { gsl_poly_complex_workspace_free(workspace); } // }; BaseGDL* zeropoly(EnvT* e) { static int doubleIx = e->KeywordIx("DOUBLE"); static int jenkisTraubIx = e->KeywordIx("JENKINS_TRAUB"); SizeT nParam=e->NParam(1); if (e->KeywordSet(jenkisTraubIx)) e->Throw("Jenkins-Traub method not supported yet (FIXME!)"); BaseGDL* p0 = e->GetNumericArrayParDefined(0); if (ComplexType(p0->Type())) e->Throw("Polynomials with complex coefficients not supported yet (FIXME!)"); if (p0->Rank() != 1) e->Throw("The first argument must be a column vector: " + e->GetParString(0)); DDoubleGDL* coef = e->GetParAs(0); // GSL error handling gsl_error_handler_t* old_handler = gsl_set_error_handler(&gsl_err_2_gdl_warn); gsl_err_2_gdl_warn_guard old_handler_guard(old_handler); gsl_err_2_gdl_warn(e->GetProName().c_str(), NULL, -1, -1); // initializing complex polynomial workspace gsl_poly_complex_workspace* w = gsl_poly_complex_workspace_alloc(coef->N_Elements()); GDLGuard g1( w, gsl_poly_complex_workspace_free); // gsl_poly_complex_workspace_guard w_guard(w); SizeT resultSize = coef->N_Elements()-1; vector tmp(2 * resultSize); if (GSL_SUCCESS != gsl_poly_complex_solve( &(*coef)[0], coef->N_Elements(), w, &(tmp[0])) ) e->Throw("Failed to compute the roots of the polynomial"); DComplexDblGDL* result = new DComplexDblGDL(dimension(resultSize), BaseGDL::NOZERO); for (SizeT i = 0; i < resultSize; ++i) (*result)[i] = complex(tmp[2 * i], tmp[2 * i + 1]); return result->Convert2( e->KeywordSet(doubleIx) || p0->Type() == GDL_DOUBLE ? GDL_COMPLEXDBL : GDL_COMPLEX, BaseGDL::CONVERT ); } // SA: GDL implementation of LEGENDRE uses gsl_sf_legendre_Plm, while SPHER_HARM implem. // below uses gsl_sf_legendre_sphPlm which is intended for use with sph. harms template void spher_harm_helper_helper_helper(EnvT *e, T_theta *theta, T_phi *phi, T_res *res, int l, int m, int step_theta, int step_phi, SizeT length) { double sign = (m < 0 && m % 2 == -1) ? -1. : 1.; // SA: I haven't found any L,M values which GSL would not accept... //gsl_sf_result sphPlm; for (SizeT j = 0; j < length; ++j) { /* if (GSL_SUCCESS != gsl_sf_legendre_sphPlm_e(l, abs(m), cos(theta[j * step_theta]), &sphPlm)) e->Throw("GSL refused to compute Legendre polynomial value for the given L,M pair"); res[j] = sign * sphPlm.val; */ res[j] = sign * gsl_sf_legendre_sphPlm(l, abs(m), cos(theta[j * step_theta])); res[j] *= T_res(std::exp(complex(0., m * phi[j * step_phi]))); } } template void spher_harm_helper_helper(EnvT* e, BaseGDL *theta, T_phi *phi, T_res *res, int l, int m, int step_theta, int step_phi, SizeT length) { if (theta->Type() == GDL_DOUBLE || theta->Type() == GDL_COMPLEXDBL) { DDoubleGDL *theta_ = e->GetParAs(0); spher_harm_helper_helper_helper(e, &((*theta_)[0]), phi, res, l, m, step_theta, step_phi, length); } else { DFloatGDL *theta_ = e->GetParAs(0); spher_harm_helper_helper_helper(e, &((*theta_)[0]), phi, res, l, m, step_theta, step_phi, length); } } template void spher_harm_helper(EnvT* e, BaseGDL *theta, BaseGDL *phi, T_res *res, int l, int m, int step_theta, int step_phi, SizeT length) { if (phi->Type() == GDL_DOUBLE || phi->Type() == GDL_COMPLEXDBL) { DDoubleGDL *phi_ = e->GetParAs(1); spher_harm_helper_helper(e, theta, &((*phi_)[0]), res, l, m, step_theta, step_phi, length); } else { DFloatGDL *phi_ = e->GetParAs(1); spher_harm_helper_helper(e, theta, &((*phi_)[0]), res, l, m, step_theta, step_phi, length); } } BaseGDL* spher_harm(EnvT* e) { // sanity checks etc SizeT nParam=e->NParam(4); BaseGDL *theta = e->GetNumericParDefined(0); BaseGDL *phi = e->GetNumericParDefined(1); int step_theta = 1, step_phi = 1; SizeT length = theta->N_Elements(); if (theta->N_Elements() != phi->N_Elements()) { if ( (theta->N_Elements() > 1 && phi->Rank() != 0) || (phi->N_Elements() > 1 && theta->Rank() != 0) ) e->Throw("Theta (1st arg.) or Phi (2nd arg.) must be scalar, or have the same number of values"); if (theta->N_Elements() > 1) step_phi = 0; else { step_theta = 0; length = phi->N_Elements(); } } DLong l; e->AssureLongScalarPar(2, l); if (l < 0) e->Throw("L (3rd arg.) must be greater than or equal to zero"); DLong m; e->AssureLongScalarPar(3, m); if (abs(m) > l) e->Throw("M (4th arg.) must be in the range [-L, L]"); // allocating (and guarding) memory BaseGDL *res; bool dbl = e->KeywordSet(0) || theta->Type() == GDL_DOUBLE || phi->Type() == GDL_DOUBLE; { dimension dim = dimension(length); if (phi->Rank() == 0 && theta->Rank() == 0) dim.Remove(0); if (dbl) res = new DComplexDblGDL(dim); else res = new DComplexGDL(dim); } Guard res_guard(res); // computing the result if (dbl) spher_harm_helper(e, theta, phi, &((*static_cast(res))[0]), l, m, step_theta, step_phi, length); else spher_harm_helper(e, theta, phi, &((*static_cast(res))[0]), l, m, step_theta, step_phi, length); // returning res_guard.release(); return res; } } // namespace gdl-0.9.9/src/gsl_fun.hpp000066400000000000000000000051641340051421000152300ustar00rootroot00000000000000/*************************************************************************** gsl_fun.hpp - GSL GDL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #if defined(HAVE_LIBGSL) && defined(HAVE_LIBGSLCBLAS) #ifndef GSL_FUN_HPP_ #define GSL_FUN_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { // BaseGDL* invert_fun( EnvT* e); BaseGDL* fft_fun( EnvT* e); BaseGDL* random_fun( EnvT* e); BaseGDL* histogram_fun( EnvT* e); BaseGDL* interpolate_fun( EnvT* e); void la_trired_pro( EnvT* e); // int fft_1d( BaseGDL*, void*, SizeT, SizeT, //SizeT, // double, SizeT); int fft_1d( BaseGDL* p0, void* data, SizeT nEl, SizeT offset, SizeT stride, double direct, SizeT dbl, DLong dimension); // int unpack_real_radix2(double*, SizeT); int unpack_real_mxradix(double*, SizeT); int unpack_real_mxradix_float(float*, SizeT); void inplacemxradixfft(double a[], double b[], int ntot, int n, int nspan, int isn); // the following by AC BaseGDL* qromb_fun(EnvT* e); BaseGDL* qromo_fun(EnvT* e); BaseGDL* fz_roots_fun(EnvT* e); BaseGDL* fx_root_fun(EnvT* e); // the following by SA BaseGDL* newton_broyden(EnvT* e); BaseGDL* amoeba(EnvT* e); void dfpmin(EnvT* e); BaseGDL* constant(EnvT* e); BaseGDL* binomialcoef(EnvT* e); BaseGDL* wtn(EnvT* e); BaseGDL* zeropoly(EnvT* e); BaseGDL* spher_harm(EnvT* e); template< typename T1, typename T2> int cp2data2_template( BaseGDL* p0, T2* data, SizeT nEl, SizeT offset, SizeT stride_in, SizeT stride_out); template< typename T> int cp2data_template( BaseGDL* p0, T* data, SizeT nEl, SizeT offset, SizeT stride_in, SizeT stride_out); BaseGDL* random_fun_gsl(EnvT* e); } // namespace #endif #endif gdl-0.9.9/src/gsl_matrix.cpp000066400000000000000000000324041340051421000157340ustar00rootroot00000000000000/*************************************************************************** gsl_matrix.cpp - GSL GDL library function ------------------- begin : Dec 9 2011 copyright : (C) 2011 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "gsl_fun.hpp" #include "dinterpreter.hpp" #include #include // constant #include //#define LOG10E 0.434294 namespace lib { using namespace std; const int szdbl=sizeof(DDouble); const int szflt=sizeof(DFloat); const int szlng=sizeof(DLong); const int szlng64=sizeof(DLong64); void ludc_pro( EnvT* e) { // cout << szdbl << " " <NParam(1); // if( nParam == 0) // e->Throw( "Incorrect number of arguments."); BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: " + e->GetParString(0)); if (p0->Rank() > 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); if (p0->Rank() > 1) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); } // status // check here, if not done, res would be pending in case of SetPar() throws // SetPar() only throws in AssureGlobalPar() if (nParam == 2) e->AssureGlobalPar( 1); // only one element matrix if (p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_COMPLEX){ e->Throw( "Input type cannot be COMPLEX, please use LA_LUDC (not ready)"); } //DDoubleGDL* p0D = static_cast( p0); DDoubleGDL *p0D = e->GetParAs(0); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1(mat,gsl_matrix_free); memcpy(mat->data, &(*p0D)[0], nEl*szdbl); gsl_permutation * p = gsl_permutation_alloc (p0->Dim(0)); GDLGuard g2( p, gsl_permutation_free); int s; gsl_linalg_LU_decomp (mat, p, &s); int debug=0; if (debug) { cout << "permutation order: " << s << endl; cout << "permutation vector:"<< endl; gsl_permutation_fprintf (stdout, p, " %u"); cout << endl; } // copying over p0 the updated matrix SizeT dims[2] = {p0->Dim(0), p0->Dim(0)}; dimension dim0(dims, (SizeT) 2); BaseGDL** p0Do = &e->GetPar( 0); GDLDelete((*p0Do)); *p0Do = new DDoubleGDL(dim0, BaseGDL::NOZERO); memcpy(&(*(DDoubleGDL*) *p0Do)[0], mat->data, p0->Dim(0)*p0->Dim(0)*szdbl); int double_flag=0; if (p0->Type() == GDL_DOUBLE) double_flag=1; static int doubleIx=e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx)) double_flag=1; // this code will always return GDL_DOUBLE because I don't know how to do :( // AC 13-Feb-2012 : this is not working and I don't know how to do :( // if (double_flag == 0) // { p0->Convert2(GDL_FLOAT, BaseGDL::CONVERT); } // copying over p1 the permutation vector SizeT n = p0->Dim(0); dimension dim1(&n, (SizeT) 1); BaseGDL** p1D = &e->GetPar( 1); GDLDelete((*p1D)); if (sizeof(size_t) == szlng) { *p1D = new DLongGDL(dim1, BaseGDL::NOZERO); memcpy(&(*(DLongGDL*) *p1D)[0], p->data, p0->Dim(0)*szlng); } else { *p1D = new DLong64GDL(dim1, BaseGDL::NOZERO); memcpy(&(*(DLong64GDL*) *p1D)[0], p->data, p0->Dim(0)*szlng64); } // gsl_matrix_free(mat); // gsl_permutation_free(p); } BaseGDL* lusol_fun( EnvT* e) { SizeT nParam=e->NParam(1); // int s; // if( nParam == 0) // e->Throw( "Incorrect number of arguments."); // managing first input: Square Matrix BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: " + e->GetParString(0)); if (p0->Rank() > 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); if (p0->Rank() > 1) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); } // status // check here, if not done, res would be pending in case of SetPar() throws // SetPar() only throws in AssureGlobalPar() if (nParam == 2) e->AssureGlobalPar( 1); // managing seconf input: Vector BaseGDL* p1 = e->GetParDefined(1); SizeT nEl1 = p1->N_Elements(); if( nEl1 == 0) e->Throw( "Variable is undefined: " + e->GetParString(1)); if (p1->Rank() > 2) e->Throw( "Input must be a Vector:" + e->GetParString(1)); // managing third input: Vector BaseGDL* p2 = e->GetParDefined(2); SizeT nEl2 = p2->N_Elements(); if( nEl2 == 0) e->Throw( "Variable is undefined: " + e->GetParString(2)); if (p2->Rank() > 2) e->Throw( "Input must be a Vector:" + e->GetParString(2)); if (p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_COMPLEX){ e->Throw( "Input type cannot be COMPLEX, please use LA_LUDC (not ready)"); } DDoubleGDL *p0D = e->GetParAs(0); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1(mat,gsl_matrix_free); memcpy(mat->data, &(*p0D)[0], nEl*szdbl); gsl_permutation *p = gsl_permutation_alloc (nEl1); GDLGuard g2(p,gsl_permutation_free); if (sizeof(size_t) == szlng) { DLongGDL* p1L =e->GetParAs(1); memcpy(p->data, &(*p1L)[0], nEl1*szlng); } else { DLong64GDL* p1L =e->GetParAs(1); memcpy(p->data, &(*p1L)[0], nEl1*szlng64); } DDoubleGDL *p2D = e->GetParAs(2); gsl_vector *b = gsl_vector_alloc(nEl2); GDLGuard g3(b,gsl_vector_free); // b was NOT freed before memcpy(b->data, &(*p2D)[0], nEl1*szdbl); gsl_vector *x = gsl_vector_alloc(nEl2); GDLGuard g4(x,gsl_vector_free); // computation by GSL gsl_linalg_LU_solve (mat, p, b, x); int debug=0; if (debug) { // cout << "permutation order: " << s << endl; cout << "permutation vector:"; gsl_permutation_fprintf (stdout, p, " %u"); cout << endl; cout << "input vector:"; gsl_vector_fprintf (stdout, b, " %g"); cout << endl; cout << "result vector:"; gsl_vector_fprintf (stdout, x, " %g"); cout << endl; } DDoubleGDL* res = new DDoubleGDL( p2->Dim(), BaseGDL::NOZERO); memcpy(&(*res)[0], x->data, nEl1*szdbl); // gsl_matrix_free(mat);Parameter // gsl_vector_free(x); // gsl_permutation_free(p); // b ??? int double_flag=0; if (p0->Type() == GDL_DOUBLE || p2->Type() == GDL_DOUBLE) double_flag=1; static int doubleIx=e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx)) double_flag=1; if (double_flag) { return res; } else { return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); } } BaseGDL* determ_fun( EnvT* e) { // managing first input: Square Matrix BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: " + e->GetParString(0)); if (p0->Rank() > 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); if (p0->Rank() > 1) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); } if (p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_COMPLEX){ e->Throw( "Input type cannot be COMPLEX, please use LA_DETERM (not ready)"); } DDoubleGDL *p0D = e->GetParAs(0); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(0)); GDLGuard g1(mat,gsl_matrix_free); memcpy(mat->data, &(*p0D)[0], nEl*szdbl); gsl_permutation *p = gsl_permutation_alloc(p0->Dim(0)); GDLGuard g2(p,gsl_permutation_free); int sign; double determ=0.0; // computation by GSL gsl_linalg_LU_decomp (mat, p, &sign); determ=gsl_linalg_LU_det (mat, sign); int debug=0; if (debug) { cout << "Determ : " << determ << endl; } // gsl_matrix_free(mat); // gsl_permutation_free(p); DDoubleGDL* res = new DDoubleGDL(1, BaseGDL::NOZERO); (*res)[0]=determ; int double_flag=0; if (p0->Type() == GDL_DOUBLE) double_flag=1; static int doubleIx=e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx)) double_flag=1; if (double_flag) { return res; } else { return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); } } BaseGDL* trisol_fun( EnvT* e) { // managing first input: Square Matrix BaseGDL* p0 = e->GetParDefined(0); // sub-diag elements BaseGDL* p1 = e->GetParDefined(1); // diagonal elements BaseGDL* p2 = e->GetParDefined(2); // sup-diag elements BaseGDL* p3 = e->GetParDefined(3); // right-hand side vector SizeT nEl0 = p0->N_Elements(); if( nEl0 == 0) e->Throw( "Variable is undefined: " + e->GetParString(0)); SizeT nEl1 = p1->N_Elements(); if( nEl1 == 0) e->Throw( "Variable is undefined: " + e->GetParString(1)); SizeT nEl2 = p2->N_Elements(); if( nEl2 == 0) e->Throw( "Variable is undefined: " + e->GetParString(2)); SizeT nEl3 = p3->N_Elements(); if( nEl3 == 0) e->Throw( "Variable is undefined: " + e->GetParString(3)); // cout << nEl0 << " " << nEl1 << " " << nEl2 << " " << nEl3 << " " << endl; SizeT nEl = nEl0; if (nEl1 != nEl) e->Throw( "Argument: " + e->GetParString(1)+" does not have correct size"); if (nEl2 != nEl) e->Throw( "Argument: " + e->GetParString(2)+" does not have correct size"); if (nEl3 != nEl) e->Throw( "Argument: " + e->GetParString(3)+" does not have correct size"); int complex_flag=0; if (p0->Type() == GDL_COMPLEXDBL || p0->Type() == GDL_COMPLEX) complex_flag=1; if (p1->Type() == GDL_COMPLEXDBL || p1->Type() == GDL_COMPLEX) complex_flag=1; if (p2->Type() == GDL_COMPLEXDBL || p2->Type() == GDL_COMPLEX) complex_flag=1; if (p3->Type() == GDL_COMPLEXDBL || p3->Type() == GDL_COMPLEX) complex_flag=1; if (complex_flag) { e->Throw( "Input type cannot be COMPLEX, please use LA_TRISOL (not ready)"); } // computations are done in Double type, conversion at the end DDoubleGDL *p0D = e->GetParAs(0); gsl_vector *subd = gsl_vector_alloc(nEl-1); GDLGuard g1(subd,gsl_vector_free); memcpy(subd->data, &(*p0D)[1], (nEl-1)*szdbl); DDoubleGDL *p1D= e->GetParAs(1);// = static_cast(p1); gsl_vector *diag = gsl_vector_alloc(nEl); GDLGuard g2(diag,gsl_vector_free); memcpy(diag->data, &(*p1D)[0], nEl*szdbl); DDoubleGDL *p2D= e->GetParAs(2); // = static_cast(p2); gsl_vector *supd = gsl_vector_alloc(nEl-1); GDLGuard g3(supd,gsl_vector_free); memcpy(supd->data, &(*p2D)[0], (nEl-1)*szdbl); DDoubleGDL *p3D= e->GetParAs(3);// = static_cast(p3); gsl_vector *rhs = gsl_vector_alloc(nEl); GDLGuard g4(rhs,gsl_vector_free); memcpy(rhs->data, &(*p3D)[0], nEl*szdbl); gsl_vector *x = gsl_vector_alloc(nEl); GDLGuard g5(x,gsl_vector_free); // x was NOT freed before // computation by GSL int error_code=-1; error_code=gsl_linalg_solve_tridiag (diag, supd, subd, rhs, x); if (error_code > 0) Message( e->GetProName() + ": GSL did return an error. Is realy the matrix Pos. Define ?"); int debug=0; if (debug) { gsl_vector_fprintf (stdout, diag, "diag: %g"); gsl_vector_fprintf (stdout, subd, "subd: %g"); gsl_vector_fprintf (stdout, supd, "supd: %g"); gsl_vector_fprintf (stdout, rhs, "rhs: %g"); gsl_vector_fprintf (stdout, x, "res: %g"); } // gsl_vector_free(diag); // gsl_vector_free(subd); // gsl_vector_free(supd); // gsl_vector_free(rhs); // x ??? int double_flag=0; if (p0->Type() == GDL_DOUBLE || p1->Type() == GDL_DOUBLE) double_flag=1; if (p2->Type() == GDL_DOUBLE || p3->Type() == GDL_DOUBLE) double_flag=1; static int doubleIx=e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx)) double_flag=1; DDoubleGDL* res = new DDoubleGDL(nEl, BaseGDL::NOZERO); memcpy(&(*res)[0], x->data, nEl*szdbl); if (double_flag) { return res; } else { return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); } } } gdl-0.9.9/src/gsl_matrix.hpp000066400000000000000000000023371340051421000157430ustar00rootroot00000000000000/*************************************************************************** gsl_matrix.hpp - GSL GDL library function ------------------- begin : Dec 9 2011 copyright : (C) 2011 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "datatypes.hpp" #include "envt.hpp" namespace lib { void ludc_pro( EnvT* e); BaseGDL* lusol_fun( EnvT* e); BaseGDL* determ_fun( EnvT* e); BaseGDL* trisol_fun( EnvT* e); } // namespace gdl-0.9.9/src/gtdhelper.cpp000066400000000000000000000016101340051421000155340ustar00rootroot00000000000000#include "gtdhelper.hpp" // gettimeofday in windows int gettimeofday(struct timeval *tv, struct timezone *tz) { FILETIME ft; union { struct { unsigned long Low; unsigned long High; } u; unsigned __int64 tmpres; }; static int tzflag; if (NULL != tv) { // Get system time GetSystemTimeAsFileTime(&ft); // Make it an unsigned 64 bit u.High = ft.dwHighDateTime; u.Low = ft.dwLowDateTime; // 100nano -> 1micro, // and convert into epoch time tmpres = tmpres/10UL - DELTA_EPOCH_IN_MICROSECS; // set sec, microsec tv->tv_sec = (tmpres / 1000000UL); tv->tv_usec = (tmpres % 1000000UL); } // timezone if (NULL != tz) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; } // source from http://spaurh.egloos.com/4569632gdl-0.9.9/src/gtdhelper.hpp000066400000000000000000000011551340051421000155450ustar00rootroot00000000000000#include #include #include // A conversion constant between epoch time and microsecs #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #else #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif /*! \brief gtdhelper.hpp for WIN32 or MINGW32 */ #ifndef _TIMEZONE_DEFINED /* also in sys/time.h */ #define _TIMEZONE_DEFINED struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif /* _TIMEZONE_DEFINED */ int gettimeofday(struct timeval *tv, struct timezone *tz); // Source from http://spaurh.egloos.com/4569632gdl-0.9.9/src/gzstream.hpp000066400000000000000000000124251340051421000154250ustar00rootroot00000000000000// ============================================================================ // gzstream, C++ iostream classes wrapping the zlib compression library. // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner // // This library 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 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ============================================================================ // // File : gzstream.h // Revision : $Revision: 1.4 $ // Revision_date : $Date: 2017-10-12 21:29:17 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner // // Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ #ifndef GZSTREAM_H #define GZSTREAM_H 1 // standard C++ with new header file names and std:: namespace #include #include #include #ifdef GZSTREAM_NAMESPACE namespace GZSTREAM_NAMESPACE { #endif // ---------------------------------------------------------------------------- // Internal classes to implement gzstream. See below for user classes. // ---------------------------------------------------------------------------- const int buf4 = 2; class gzstreambuf : public std::streambuf { private: static const int bufferSize = 47+256; // size of data buff // totals 512 bytes under g++ for igzstream at the end. gzFile file; // file handle for compressed file char buffer[bufferSize]; // data buffer char opened; // open/close state of stream int mode; // I/O mode std::streampos position; int flush_buffer(); public: gzstreambuf() : opened(0) { setp( buffer, buffer + (bufferSize-1)); setg( buffer + buf4, // beginning of putback area buffer + buf4, // read position buffer + buf4); // end position // ASSERT: both input & output capabilities will not be used together } int is_open() { return opened; } gzstreambuf* open( const char* name, int open_mode); gzstreambuf* close(); ~gzstreambuf() { close(); } virtual int overflow( int c = EOF); virtual int underflow(); virtual int sync(); std::streampos pubseekpos(std::streampos sp, std::ios_base::openmode which=std::ios_base::in|std::ios_base::out); std::streampos pubseekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which=std::ios_base::in|std::ios_base::out); //hacks for not being lost with input gzipped streams std::streampos getPosition(){return position;} void setPosition(long pos){position=pos;} void incrementPosition(long pos=1){position+=pos;} void decrementPosition(long pos=1){position-=pos;} }; class gzstreambase : virtual public std::ios { protected: gzstreambuf buf; public: gzstreambase() { init(&buf); } gzstreambase( const char* name, int open_mode); ~gzstreambase(); void open( const char* name, int open_mode); void close(); gzstreambuf* rdbuf() { return &buf; } }; // ---------------------------------------------------------------------------- // User classes. Use igzstream and ogzstream analogously to ifstream and // ofstream respectively. They read and write files based on the gz* // function interface of the zlib. Files are compatible with gzip compression. // ---------------------------------------------------------------------------- class igzstream : public gzstreambase, public std::istream { public: igzstream() : std::istream( &buf) {} igzstream( const char* name, int open_mode = std::ios::in) : gzstreambase( name, open_mode), std::istream( &buf) {} gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } void open( const char* name, int open_mode = std::ios::in) { gzstreambase::open( name, open_mode); } igzstream& seekg(std::streampos); igzstream& seekg(std::streamoff, std::ios_base::seekdir); }; class ogzstream : public gzstreambase, public std::ostream { public: ogzstream() : std::ostream( &buf) {} ogzstream( const char* name, int mode = std::ios::out) : gzstreambase( name, mode), std::ostream( &buf) {} gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } void open( const char* name, int open_mode = std::ios::out) { gzstreambase::open( name, open_mode); } ogzstream& seekp(std::streampos); ogzstream& seekp(std::streamoff, std::ios_base::seekdir); }; #ifdef GZSTREAM_NAMESPACE } // namespace GZSTREAM_NAMESPACE #endif #endif // GZSTREAM_H // ============================================================================ // EOF // gdl-0.9.9/src/hash.cpp000066400000000000000000003224601340051421000145120ustar00rootroot00000000000000/*************************************************************************** hash.cpp - for HASH objects ------------------- begin : July 22 2013 copyright : (C) 2013 by M. Schellens et al. email : m_schellens@users.sf.net * * April 11 2016: Greg Jung * - implemented EXTRACT, FOLD_CASE. * - hash__tostruct set up for RECURSIVE, NO_COPY implementations. * - ORDEREDHASH placeholder routines, flags only. * - [ and ] overloads revision to accomodate in-place array access * is implemented in list.cpp - same logic overhaul can be applied here. * ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #define GDL_LIST_STRUCT() \ static unsigned pHeadTag = structDesc::LIST->TagIndex( "PHEAD"); \ static unsigned pTailTag = structDesc::LIST->TagIndex( "PTAIL"); \ static unsigned nListTag = structDesc::LIST->TagIndex( "NLIST"); #define GDL_CONTAINER_NODE() \ static unsigned pNextTag = structDesc::GDL_CONTAINER_NODE->TagIndex( "PNEXT"); \ static unsigned pListDataTag = structDesc::GDL_CONTAINER_NODE->TagIndex( "PDATA"); #define GDL_HASH_STRUCT() \ static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); \ static unsigned pTableTag = structDesc::HASH->TagIndex( "TABLE_DATA"); \ static unsigned TableSizeTag = structDesc::HASH->TagIndex( "TABLE_SIZE"); \ static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); #define GDL_HASHTABLEENTRY() \ static unsigned pKeyTag = structDesc::GDL_HASHTABLEENTRY->TagIndex( "PKEY"); \ static unsigned pValueTag = structDesc::GDL_HASHTABLEENTRY->TagIndex( "PVALUE"); #define MAKE_LONGGDL(X, XLong) \ DLongGDL* XLong=0; \ Guard XLongGuard; \ if( X != 0) \ if( X->Type() == GDL_LONG) \ XLong = static_cast( X); \ else { \ try{ \ XLong = static_cast( X->Convert2( GDL_LONG, BaseGDL::COPY)); \ } \ catch( GDLException& ex) { \ ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); \ } \ XLongGuard.Init( XLong); \ } #include "includefirst.hpp" #include "nullgdl.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" static bool trace_me(false); namespace lib { // bool trace_arg(); void help_item( std::ostream& os, BaseGDL* par, DString parString, bool doIndentation); // void help_struct( std::ostream& os, BaseGDL* par, int indent , bool debug ); SizeT HASH_count( DStructGDL* hash) { static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); return (*static_cast( hash->GetTag( TableCountTag, 0)))[0]; } } std::string ValidTagName( const std::string& in) // (performance) Function parameter 'in' should be passed by reference. { if( in.length() == 0) return "_"; std::string result = StrUpCase( in); SizeT i = 0; if( result[0] >= '0' && result[0] <= '9') { result = "_" + result; ++i; } else if( result[0] == '!') { ++i; } for( ; i= 'A' && result[i] <= 'Z') || (result[i] >= '0' && result[i] <= '9') || result[i] == '$')) result[i] = '_'; } return result; } static DStructGDL* GetLISTStruct( EnvUDT* e, DPtr actP) // (copied from list.cpp) { // Get the GDL_CONTAINER_NODE struct {pNext, pData} from a list // From the heap pointer actP // the next pointer in list will be found in the struct. BaseGDL* actPHeap; try { actPHeap = BaseGDL::interpreter->GetHeap( actP); } catch( GDLInterpreter::HeapException& hEx) { if( e == NULL) throw GDLException( "LIST container node ID <" +i2s(actP)+"> not found."); ThrowFromInternalUDSub( e, "LIST container node ID <" +i2s(actP)+"> not found."); } if( actPHeap == NULL || actPHeap->Type() != GDL_STRUCT) { if( e == NULL) throw GDLException( "LIST node must be a STRUCT."); else ThrowFromInternalUDSub( e, "LIST node must be a STRUCT."); } DStructGDL* actPStruct = static_cast( actPHeap); return actPStruct; } static DPtr GetLISTNode( EnvUDT* e, DStructGDL* self, DLong targetIx) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DPtr actP; if( targetIx == -1) { actP = (*static_cast(self->GetTag( pHeadTag, 0)))[0]; } else { actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; for( SizeT elIx = 0; elIx < targetIx; ++elIx) { DStructGDL* actPStruct = GetLISTStruct(e, actP); actP = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; } } return actP; } static BaseGDL* GetNodeData(DPtr &Node) { GDL_CONTAINER_NODE() DStructGDL* act = GetLISTStruct( NULL, Node); DPtr ptrX = (*static_cast(act->GetTag( pListDataTag, 0)))[0]; Node = (*static_cast(act->GetTag( pNextTag, 0)))[0]; BaseGDL* result = new BaseGDL( ); Guard resultGuard( result); result = BaseGDL::interpreter->GetHeap( ptrX); if( result == NULL) result = NullGDL::GetSingleInstance(); // if(trace_me) lib::help_item(std::cout, result, " from GetNodeData", false); resultGuard.Release(); return result; } static BaseGDL* hash_create( EnvT* e, bool isordered ); static BaseGDL* structP_tohash( EnvT* e,BaseGDL* par, bool foldcasekw, bool extractkw, bool isordered ); static DStructGDL* GetOBJ( BaseGDL* Objptr, EnvUDT* e) { if( Objptr == NULL || Objptr->Type() != GDL_OBJ) { if( e == NULL) throw GDLException( "Objptr not of type OBJECT. Please report."); else ThrowFromInternalUDSub( e, "Objptr not of type OBJECT. Please report."); } if( !Objptr->Scalar()) { if( e == NULL) throw GDLException( "Objptr must be a scalar. Please report."); else ThrowFromInternalUDSub( e, "Objptr must be a scalar. Please report."); } DObjGDL* Object = static_cast( Objptr); DObj ID = (*Object)[0]; try { return BaseGDL::interpreter->GetObjHeap( ID); } catch( GDLInterpreter::HeapException& hEx) { if( e == NULL) throw GDLException( "Object ID <"+i2s(ID)+"> not found."); else ThrowFromInternalUDSub( e, "Object ID <"+i2s(ID)+"> not found."); } assert(false); return NULL; } // if not found returns -(pos +1) DLong HashIndex( DStructGDL* hashTable, BaseGDL* key, bool isfoldcase=false) { GDL_HASHTABLEENTRY() assert( key != NULL && key != NullGDL::GetSingleInstance()); DLong searchIxStart = 0; DLong searchIxEnd = hashTable->N_Elements(); bool dofoldcase = isfoldcase; if( key->Type() != GDL_STRING) dofoldcase = false; if(trace_me) std::cout << ". "; BaseGDL* keyfind = key; if(dofoldcase) { // this code bombs if key is not a string. DString keyval = (*static_cast(key))[0]; std::transform(keyval.begin(), keyval.end(), keyval.begin(), ::tolower); keyfind = static_cast(new DStringGDL(keyval)); } if(trace_me) std::cout << ". "; for(;;) { DLong searchIx = (searchIxStart + searchIxEnd) / 2; if( (*static_cast( hashTable->GetTag( pKeyTag, searchIx)))[0] == 0) { DLong checkIx = searchIx-1; while( checkIx >= searchIxStart && (*static_cast(hashTable->GetTag( pKeyTag, checkIx)))[0] == 0) --checkIx; if( checkIx < searchIxStart) { checkIx = searchIx+1; while( checkIx < searchIxEnd && (*static_cast(hashTable->GetTag( pKeyTag, checkIx)))[0] == 0) ++checkIx; if( checkIx == searchIxEnd) { // only empty elements found in interval return -(searchIx + 1); } } searchIx = checkIx; } DPtr kID = (*static_cast( hashTable->GetTag( pKeyTag, searchIx)))[0]; assert( kID != 0); BaseGDL* candidate = BaseGDL::interpreter->GetHeap( kID); if( dofoldcase and candidate->Type() == GDL_STRING) { DString keyval = (*static_cast(candidate))[0]; std::transform(keyval.begin(), keyval.end(), keyval.begin(), ::tolower); candidate = static_cast(new DStringGDL(keyval)); } int hashCompare = keyfind->HashCompare( candidate); if( hashCompare == 0) return searchIx; if( searchIxStart == searchIxEnd) { return -(searchIxStart + 1); } if( hashCompare == -1) // key < hashKey[searchIx] searchIxEnd = searchIx; else { // key > hashKey[searchIx] searchIxStart = searchIx+1; if( searchIxStart >= hashTable->N_Elements()) { return -(hashTable->N_Elements() + 1); } } if( searchIxStart == searchIxEnd && searchIx == searchIxStart) { return -(searchIxStart + 1); } } } bool Hashisfoldcase( DStructGDL* hashStruct) { static unsigned fold_case_mask = 0x00000001; static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); if(hashStruct == NULL) return false; DLong bits = (*static_cast( hashStruct->GetTag( TableBitsTag , 0)))[0]; // if(trace_me) std::cout << "isfold: bits=" << bits << std::endl; if ( (bits & fold_case_mask) == 0) return false; else return true; } static bool Hashisordered( DStructGDL* hashStruct) { static unsigned ordmask = 0x00000010; static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); if(hashStruct == NULL) return false; DLong bits = (*static_cast( hashStruct->GetTag( TableBitsTag , 0)))[0]; if ( (bits & ordmask) == 0) return false; else return true; } // copies all keys and values DStructGDL* CopyHashTable( DStructGDL* hashStruct, DStructGDL* hashTable, DLong nSizeNew) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() if(hashStruct == NULL) return NULL; DLong nSize = hashTable->N_Elements(); DLong nCount = (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0]; assert( nSizeNew >= nCount); DStructGDL* newHashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(nSizeNew)); // copy old table to new one, insert holes SizeT nAdd = 0; for( SizeT oldIx=0; oldIx(hashTable->GetTag( pKeyTag, oldIx)))[0] == 0) continue; SizeT newIx = nAdd * nSizeNew / nCount; assert( newIx >= nAdd); ++nAdd; DPtr keyP = (*static_cast(hashTable->GetTag( pKeyTag, oldIx)))[0]; // create new heap copy BaseGDL* key = BaseGDL::interpreter->GetHeap( keyP); assert( key != NULL); DPtr newKeyP = BaseGDL::interpreter->NewHeap( 1, key->Dup()); (*static_cast(newHashTable->GetTag( pKeyTag, newIx)))[0] = newKeyP; DPtr valP = (*static_cast(hashTable->GetTag( pValueTag, oldIx)))[0]; // create new heap copy BaseGDL* value = BaseGDL::interpreter->GetHeap( valP); if( value != NULL) value = value->Dup(); DPtr newValP = BaseGDL::interpreter->NewHeap( 1, value); (*static_cast(newHashTable->GetTag( pValueTag, newIx)))[0] = newValP; } // SizeT oldIx = 0; // for( SizeT nAdd=0; nAdd(hashTable->GetTag( pKeyTag, oldIx)))[0] == 0) // ++oldIx; // assert( oldIx < nSize); // // SizeT newIx = nAdd * nSizeNew / nCount; // assert( newIx >= nAdd); // // DPtr keyP = (*static_cast(hashTable->GetTag( pKeyTag, oldIx)))[0]; // // create new heap copy // BaseGDL* key = BaseGDL::interpreter->GetHeap( keyP); // assert( key != NULL); // DPtr newKeyP = BaseGDL::interpreter->NewHeap( 1, key->Dup()); // // (*static_cast(newHashTable->GetTag( pKeyTag, newIx)))[0] = newKeyP; // // // DPtr valP = (*static_cast(hashTable->GetTag( pValueTag, oldIx)))[0]; // // create new heap copy // BaseGDL* value = BaseGDL::interpreter->GetHeap( valP); // if( value != NULL) // value = value->Dup(); // DPtr newValP = BaseGDL::interpreter->NewHeap( 1, value); // (*static_cast(newHashTable->GetTag( pValueTag, newIx)))[0] = newValP; // // } return newHashTable; } // keeps the keys and values void GrowHashTable( DStructGDL* hashStruct, DStructGDL*& hashTable, DLong nSizeNew) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() if(hashStruct == NULL) return; DLong nSize = hashTable->N_Elements(); DLong nCount = (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0]; DStructGDL* newHashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(nSizeNew)); assert( nSizeNew > nCount); // copy old table to new one, insert holes SizeT nAdd = 0; for( SizeT oldIx=0; oldIx(hashTable->GetTag( pKeyTag, oldIx)))[0] == 0) continue; SizeT newIx = nAdd * nSizeNew / nCount; // +1 : keep bottom free assert( newIx >= nAdd); ++nAdd; (*static_cast(newHashTable->GetTag( pKeyTag, newIx)))[0] = (*static_cast(hashTable->GetTag( pKeyTag, oldIx)))[0]; // prevent ref-count cleanup (*static_cast(hashTable->GetTag( pKeyTag, oldIx)))[0] = 0; (*static_cast(newHashTable->GetTag( pValueTag, newIx)))[0] = (*static_cast(hashTable->GetTag( pValueTag, oldIx)))[0]; // prevent ref-count cleanup (*static_cast(hashTable->GetTag( pValueTag, oldIx)))[0] = 0; } // SizeT oldIx = 0; // for( SizeT nAdd=0; nAdd(hashTable->GetTag( pKeyTag, oldIx)))[0] == 0) // oldIx++; // assert( oldIx < nSize); // // SizeT newIx = nAdd * nSizeNew / nCount; // +1 : keep bottom free // assert( newIx >= nAdd); // // (*static_cast(newHashTable->GetTag( pKeyTag, newIx)))[0] = // (*static_cast(hashTable->GetTag( pKeyTag, oldIx)))[0]; // // prevent ref-count cleanup // (*static_cast(hashTable->GetTag( pKeyTag, oldIx)))[0] = 0; // // (*static_cast(newHashTable->GetTag( pValueTag, newIx)))[0] = // (*static_cast(hashTable->GetTag( pValueTag, oldIx)))[0]; // // prevent ref-count cleanup // (*static_cast(hashTable->GetTag( pValueTag, oldIx)))[0] = 0; // // } DPtr hashTableID = (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0]; assert( BaseGDL::interpreter->GetHeap( hashTableID) == hashTable); // delete old delete hashTable; // set new instead BaseGDL::interpreter->GetHeap( hashTableID) = newHashTable; // update nSize (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = newHashTable->N_Elements(); // return the new table hashTable = newHashTable; } BaseGDL* RemoveFromHashTable( EnvUDT* e, DStructGDL* hashStruct, BaseGDL* key) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() if(hashStruct == NULL) return NULL; bool isfoldcase = Hashisfoldcase( hashStruct); // our current table DPtr thisTableID = (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTable = static_cast(BaseGDL::interpreter->GetHeap( thisTableID)); DLong hashIndex = -1; if( key == NULL) // special case - remove random { // remove last element for( DLong h=hashTable->N_Elements()-1; h>=0; --h) { DPtr kID = (*static_cast(hashTable->GetTag( pKeyTag, h)))[0]; if( kID != 0) { hashIndex = h; break; } } if( hashIndex < 0) // nothing found - ok for empty table :-) return NullGDL::GetSingleInstance(); // ThrowFromInternalUDSub( e, "Internal error. Please report. Random hash index not found."); } else { hashIndex = HashIndex( hashTable, key, isfoldcase); if( hashIndex < 0) ThrowFromInternalUDSub( e, "Key does not exist."); } DPtr kID = (*static_cast(hashTable->GetTag( pKeyTag, hashIndex)))[0]; DPtr vID = (*static_cast(hashTable->GetTag( pValueTag, hashIndex)))[0]; BaseGDL* retValue = BaseGDL::interpreter->GetHeap( vID); BaseGDL::interpreter->GetHeap( vID) = NULL; BaseGDL::interpreter->FreeHeap( kID); BaseGDL::interpreter->FreeHeap( vID); (*static_cast(hashTable->GetTag( pKeyTag, hashIndex)))[0] = 0; (*static_cast(hashTable->GetTag( pValueTag, hashIndex)))[0] = 0; --((*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0]); return retValue; } // must pass hashTable as reference as it might be changed (GrowHashTable) void InsertIntoHashTable( DStructGDL* hashStruct, DStructGDL*& hashTable, BaseGDL* key, BaseGDL* value) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() // key is always copied into heap, value is taken as is. if(hashStruct == NULL) return; bool isfoldcase = Hashisfoldcase( hashStruct); DLong nSize = hashTable->N_Elements(); assert( nSize == (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0]); DLong nCount = (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0]; if( nCount == 0) { assert( nSize >= 1); DLong insertPos = nSize / 2; // std::cout << " at " << i2s(insertPos) << std::endl; DPtr pID = BaseGDL::interpreter->NewHeap(1,value); (*static_cast(hashTable->GetTag( pValueTag, insertPos)))[0] = pID; DPtr kID = BaseGDL::interpreter->NewHeap(1,key->Dup()); (*static_cast(hashTable->GetTag( pKeyTag, insertPos)))[0] = kID; (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0] = 1; return; } // must be done here, otherwise hashIndex will be not in sync if( nSize <= (nCount * 10 / 8)) // grow on 80% occupation. TODO: find optimal value { // std::cout << " grow table "<< i2s(nSize) << " -> " << i2s(nSize * 2) << std::endl; // deletes hashTable, replaces it by new one, updates nSize GrowHashTable( hashStruct, hashTable, nSize * 2); // grow to 50% occupation. TODO: find optimal value // nSize = (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0]; nSize = hashTable->N_Elements(); } DLong hashIndex = HashIndex( hashTable, key, isfoldcase); if( hashIndex >= 0) // hit -> overwrite { // std::cout << " (ovwrt) at "<< i2s(hashIndex) <(hashTable->GetTag( pValueTag, hashIndex)))[0]; GDLDelete( BaseGDL::interpreter->GetHeap( vID)); BaseGDL::interpreter->GetHeap( vID) = value; return; } // std::cout << " nSize = "<< i2s(nSize) < insert DLong insertPos = -(hashIndex + 1); // std::cout << " try "<< i2s(insertPos) << "... "; // make some space DLong nextFreeElementIx = insertPos; for( ; nextFreeElementIx < nSize; ++nextFreeElementIx) { // shuffle against top // insert at insertPos as old insertPos is shuffled up if( (*static_cast(hashTable->GetTag( pKeyTag, nextFreeElementIx)))[0] == 0) { // shuffle elements away to make space for new element // we could optimize this by using a new DStructGDL function for( DLong i=nextFreeElementIx; i>insertPos; --i) { (*static_cast(hashTable->GetTag( pKeyTag, i)))[0] = (*static_cast(hashTable->GetTag( pKeyTag, i-1)))[0]; (*static_cast(hashTable->GetTag( pValueTag, i)))[0] = (*static_cast(hashTable->GetTag( pValueTag, i-1)))[0]; // std::cout << i2s(i-1) << " -> " << i2s(i) << std::endl; } break; } } if( nextFreeElementIx >= nSize) { // shuffle against bottom // insert at insertPos-1 as old insertPos stays at insertPos --insertPos; nextFreeElementIx = insertPos; for( ; nextFreeElementIx >= 0; --nextFreeElementIx) { if( (*static_cast(hashTable->GetTag( pKeyTag, nextFreeElementIx)))[0] == 0) { for( DLong i=nextFreeElementIx; i " << i2s(i) << " kID:";//std::endl; // std::cout << (*static_cast(hashTable->GetTag( pKeyTag, i+1)))[0]; // std::cout << " vID:" << (*static_cast(hashTable->GetTag( pValueTag, i+1)))[0]; // std::cout << std::endl; (*static_cast(hashTable->GetTag( pKeyTag, i)))[0] = (*static_cast(hashTable->GetTag( pKeyTag, i+1)))[0]; (*static_cast(hashTable->GetTag( pValueTag, i)))[0] = (*static_cast(hashTable->GetTag( pValueTag, i+1)))[0]; // std::cout << i2s(i+1) << " -> " << i2s(i) << std::endl; } break; } } } assert( nextFreeElementIx >= 0 && nextFreeElementIx < nSize); // insert the element // overwrite, the (now overwritten) pointers are already moved or are NULL DPtr kID = BaseGDL::interpreter->NewHeap(1,key->Dup()); (*static_cast(hashTable->GetTag( pKeyTag, insertPos)))[0] = kID; DPtr pID = BaseGDL::interpreter->NewHeap(1,value); (*static_cast(hashTable->GetTag( pValueTag, insertPos)))[0] = pID; // std::cout << " at "<< i2s(insertPos) << "(" << i2s(kID) << "," << i2s(pID) << ")" <( hashStruct->GetTag( TableCountTag, 0)))[0] = ++nCount; } void HASH__ToStream( DStructGDL* oStructGDL, std::ostream& o, SizeT w, SizeT* actPosPtr) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() SizeT nCount = (*static_cast(oStructGDL->GetTag( TableCountTag, 0)))[0]; DPtr Ptr = (*static_cast( oStructGDL->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); DLong nSize = hashTable->N_Elements(); SizeT ix = 0; for( SizeT i=0; i(hashTable->GetTag( pKeyTag, ix)))[0] == 0) ++ix; assert( ix < nSize); DPtr pKey = (*static_cast(hashTable->GetTag( pKeyTag, ix)))[0]; DPtr pValue = (*static_cast(hashTable->GetTag( pValueTag, ix)))[0]; BaseGDL* key = BaseGDL::interpreter->GetHeap( pKey); assert( key != NULL); BaseGDL* value = BaseGDL::interpreter->GetHeap( pValue); if( value == NULL) value = NullGDL::GetSingleInstance(); // std::cout << "("<ToStream( o, w, actPosPtr); o << ":"; value->ToStream( o, w, actPosPtr); if( (i+1) < nCount) o << std::endl; } } DLong GetInitialTableSize( DLong nEntries) { DLong initialTableSize = 4; DLong minEntries = nEntries * 2; // initial min 50% filling. TODO: find optimal value while( initialTableSize < minEntries) initialTableSize <<= 1; //*= 2; return initialTableSize; } DObj new_hashStruct( DLong initialTableSize, DStructGDL*& hashTable, bool foldcasekw=false, bool isordered=false) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() static unsigned fold_case_mask = 0x00000001; static unsigned orderedmask = 0x00000010; // because of .RESET_SESSION, we cannot use static here DStructDesc* hashDesc=structDesc::HASH; DStructDesc* entryDesc=structDesc::GDL_HASHTABLEENTRY; assert( hashDesc != NULL && hashDesc->NTags() > 0); assert( entryDesc != NULL && entryDesc->NTags() > 0); DStructGDL* hashStruct= new DStructGDL( hashDesc, dimension()); DObj objID= BaseGDL::interpreter->NewObjHeap( 1, hashStruct); hashTable= new DStructGDL( entryDesc, dimension(initialTableSize)); DPtr hashTableID= BaseGDL::interpreter->NewHeap( 1, hashTable); (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = initialTableSize; unsigned long bitmask=0; // apply specialty bits to TABLE_BITS of hashStruct if( foldcasekw) bitmask = fold_case_mask; if( isordered) bitmask |= orderedmask; (*static_cast( hashStruct->GetTag( TableBitsTag, 0)))[0] = bitmask; return objID; } static BaseGDL* struct_tohash( EnvT* e,DStructGDL* parStruct, bool foldcasekw, bool extractkw, bool isordered=false) { static int kwLOWERCASEIx = e->KeywordIx("LOWERCASE"); bool keytolower = e->KeywordSet(kwLOWERCASEIx); DStructDesc* desc = parStruct->Desc(); DStructGDL* hashTable; DLong initialTableSize = GetInitialTableSize( desc->NTags()); DObj objID= new_hashStruct( initialTableSize, hashTable, foldcasekw, isordered); BaseGDL* newObj = new DObjGDL( objID); // the hash object Guard newObjGuard( newObj); DStructGDL* hashStruct = GetOBJ( newObj, 0); for( SizeT t=0; tNTags(); ++t) { DString validName = ValidTagName( desc->TagName(t)); // http://blog.fourthwoods.com/2013/12/10/convert-c-string-to-lower-case-or-upper-case/ if(keytolower) std::transform(validName.begin(), validName.end(), validName.begin(), ::tolower); DStringGDL *structKey = new DStringGDL( validName); BaseGDL* structData; BaseGDL* par = parStruct->GetTag(t,0); assert(par != NULL); if( extractkw and par->Type() == GDL_STRUCT and (par->N_Elements()==1)) structData = structP_tohash( e, par, foldcasekw, extractkw, isordered); else structData = par->Dup(); InsertIntoHashTable( hashStruct, hashTable, structKey, structData); } newObjGuard.Release(); return newObj; } static BaseGDL* structP_tohash( EnvT* e,BaseGDL* par, bool foldcasekw, bool extractkw, bool isordered=false) { if(par->N_Elements() != 1) e->Throw(" only a single struct may be hashed"); DStructGDL* parStruct = static_cast(par); return struct_tohash( e, parStruct, foldcasekw, extractkw, isordered); } BaseGDL* hash_tostruct( DStructGDL* self , BaseGDL* missing, BaseGDL** skipped, bool recursive, bool no_copy) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() DPtr Ptr = (*static_cast( self->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); DLong nSize = hashTable->N_Elements(); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DStructDesc* listDesc= structDesc::LIST; DStructDesc* containerDesc= structDesc::GDL_CONTAINER_NODE; DStructGDL* listStruct = NULL; BaseGDL* newObj = NULL; Guard newListObjGuard; if( skipped != NULL) { listStruct= new DStructGDL( listDesc, dimension()); DObj objID= BaseGDL::interpreter->NewObjHeap( 1, listStruct); // owns objStruct newObj = new DObjGDL( objID); // the list object newListObjGuard.Init( newObj); } DStructDesc* nStructDesc = new DStructDesc( "$truct"); // instance takes care of nStructDesc since it is unnamed // dimension dim( 1); // DStructGDL* instance = new DStructGDL( nStructDesc, dim); DStructGDL* instance = new DStructGDL( nStructDesc); Guard instance_guard(instance); DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; for( SizeT el=0; el(hashTable->GetTag( pKeyTag, el)))[0]; if( pKey == 0) continue; DPtr pValue = (*static_cast(hashTable->GetTag( pValueTag, el)))[0]; assert( pValue != 0); BaseGDL* key = BaseGDL::interpreter->GetHeap( pKey); assert( key != NULL); BaseGDL* value = BaseGDL::interpreter->GetHeap( pValue); if( value == NULL || value == NullGDL::GetSingleInstance()) { value = missing; } // we are not owner of value here bool added = false; if( key->Type() == GDL_STRING && value != NULL) { assert( key->N_Elements() == 1); DString keyString = (*static_cast(key))[0]; DString tagString = ValidTagName( keyString); if( nStructDesc->TagIndex( tagString) == -1) { if(value->Type() == GDL_OBJ and value->StrictScalar()) { if(recursive) { DStructGDL* theStruct = GetOBJ( value, NULL); if( (theStruct->Desc())->IsParent("HASH") ) { SizeT nhash = lib::HASH_count(theStruct); if( nhash > 0) { value = hash_tostruct( theStruct , missing, skipped, recursive, no_copy); } } } } //else if(trace_me) std::cout<<" value->Type() or StrictScalar()" << std::endl; //if(trace_me) lib::help_item(std::cout,value,tagString, false); instance->NewTag( tagString, value->Dup()); added = true; } //else if(trace_me) std::cout<<" TagIndex != -1" << std::endl; } if( !added && listStruct != NULL) // add key to skipped { key = key->Dup(); DPtr dID = BaseGDL::interpreter->NewHeap(1,key); cStruct = new DStructGDL( containerDesc, dimension()); cID = BaseGDL::interpreter->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pListDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; } } if( skipped != NULL) { GDLDelete( *skipped); newListObjGuard.Release(); *skipped = newObj; } instance_guard.Release(); if( instance->NTags() == 0) return NullGDL::GetSingleInstance(); return instance; } // checks wether referenced values are equal (recursively) bool PtrDerefEqual( DPtrGDL* l, DPtrGDL* r) { SizeT nEl = l->N_Elements(); if( nEl != r->N_Elements()) return false; for( SizeT i=0; iGetHeap( pL); BaseGDL* derefR = BaseGDL::interpreter->GetHeap( pR); if( derefL == NullGDL::GetSingleInstance()) derefL = NULL; if( derefR == NullGDL::GetSingleInstance()) derefR = NULL; if( derefL == NULL && derefR == NULL) continue; if( derefL == NULL || derefR == NULL) return false; if( derefL->Type() != derefR->Type()) return false; if( derefL->Type() == GDL_PTR) { // recursion here if( !PtrDerefEqual( static_cast( derefL), static_cast( derefR))) return false; } else if( !derefL->ArrayEqual( derefR)) return false; } return true; } namespace lib { SizeT LIST_count( DStructGDL* list); BaseGDL* list_rightextraction( EnvUDT* e, BaseGDL* theref, int iprm ); void list_leftinsertion( EnvUDT* e, BaseGDL* theref, int iprm ); BaseGDL* HASH___OverloadIsTrue( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() SizeT nParam = e->NParam(1); static int kwSELFIx = 0; DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; if( nCount == 0) return new DByteGDL(0); else return new DByteGDL(1); } BaseGDL* HASH___OverloadNEOp( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() SizeT nParam = e->NParam(); // number of parameters actually given // more precise error message if( nParam < 3) // consider SELF ThrowFromInternalUDSub( e, "Two parameters are needed: LEFT, RIGHT."); BaseGDL* l = e->GetKW(1); if( l == NullGDL::GetSingleInstance()) l = NULL; BaseGDL* r = e->GetKW(2); if( r == NullGDL::GetSingleInstance()) r = NULL; if( (l == NULL && r == NULL)) ThrowFromInternalUDSub( e, "At least one parameter must be defined and a HASH."); DStructGDL* leftStruct = NULL; DObj leftID = 0; if( l != NULL && l->Type() == GDL_OBJ) { DObjGDL* left = static_cast(l); leftID = (*left)[0]; if( leftID == 0) { // null object -> compare to !NULL l = NULL; } else { try { leftStruct = BaseGDL::interpreter->GetObjHeap( leftID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Left parameter object ID <"+i2s(leftID)+"> not found."); } if( !leftStruct->Desc()->IsParent("HASH")) leftStruct = NULL; } } DStructGDL* rightStruct = NULL; DObj rightID = 0; if( r != NULL && r->Type() == GDL_OBJ) { DObjGDL* right = static_cast(r); rightID = (*right)[0]; if( rightID == 0) { // null object -> compare to !NULL r = NULL; } else { try { rightStruct = BaseGDL::interpreter->GetObjHeap( rightID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Right parameter object ID <"+i2s(rightID)+"> not found."); } if( !rightStruct->Desc()->IsParent("HASH")) rightStruct = NULL; } } DStructGDL* hashStruct = NULL; DStructGDL* hashTable = NULL; DStructGDL* compareStruct = NULL; DStructGDL* compareTable = NULL; BaseGDL* compare = NULL; if( leftStruct != NULL) { hashStruct = leftStruct; DPtr Ptr = (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0]; hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); if( rightStruct != NULL) { compareStruct = rightStruct; DPtr Ptr = (*static_cast( compareStruct->GetTag( pTableTag, 0)))[0]; compareTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); } else { compare = r; } } else if( rightStruct != NULL) { hashStruct = rightStruct; DPtr Ptr = (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0]; hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); compare = l; } else ThrowFromInternalUDSub( e, "At least one parameter must be a HASH."); bool isfoldcase = Hashisfoldcase( hashStruct); DLong nSize = hashTable->N_Elements(); // DLong nCount = (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0]; GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // the result list DStructDesc* listDesc= structDesc::LIST; DStructDesc* containerDesc= structDesc::GDL_CONTAINER_NODE; DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct BaseGDL* newObj = new DObjGDL( objID); // the list object Guard newObjGuard( newObj); DLong nCountList = 0; DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; for( SizeT i=0; i(hashTable->GetTag( pKeyTag, i)))[0]; if( kID == 0) continue; BaseGDL* key = BaseGDL::interpreter->GetHeap( kID); assert( key != NULL); if( compareStruct == NULL) // against value { DPtr vID = (*static_cast(hashTable->GetTag( pValueTag, i)))[0]; BaseGDL* v = BaseGDL::interpreter->GetHeap( vID); BaseGDL* vCmp = compare; if( v == NULL || v == NullGDL::GetSingleInstance()) { if( vCmp == NULL /*&& vCmp == NullGDL::GetSingleInstance()*/) continue; } if( vCmp == NULL /*|| vCmp == NullGDL::GetSingleInstance()*/) { if( v == NULL && v == NullGDL::GetSingleInstance()) continue; } if( v != NULL && vCmp != NULL) { if( v->Type() == vCmp->Type()) { if( v->Type() == GDL_PTR) { if( PtrDerefEqual( static_cast(v), static_cast(vCmp))) continue; } else if( v->ArrayEqual( vCmp)) continue; } } } else // against other HASH { DLong insertIx = HashIndex(compareTable, key, isfoldcase); if( insertIx >= 0) // found { DPtr vID = (*static_cast(hashTable->GetTag( pValueTag, i)))[0]; BaseGDL* v = BaseGDL::interpreter->GetHeap( vID); DPtr vCmpID = (*static_cast(compareTable->GetTag( pValueTag, insertIx)))[0]; BaseGDL* vCmp = BaseGDL::interpreter->GetHeap( vCmpID); if( v == NULL || v == NullGDL::GetSingleInstance()) { if( vCmp == NULL || vCmp == NullGDL::GetSingleInstance()) continue; } if( vCmp == NULL || vCmp == NullGDL::GetSingleInstance()) { if( v == NULL || v == NullGDL::GetSingleInstance()) continue; } if( v != NULL && vCmp != NULL) { if( v->Type() == vCmp->Type()) { if( v->Type() == GDL_PTR) { if( PtrDerefEqual( static_cast(v), static_cast(vCmp))) continue; } else if( v->ArrayEqual( vCmp)) continue; } } } } // not equal or not found -> insert into LIST DPtr dID = e->Interpreter()->NewHeap(1,key->Dup()); cStruct = new DStructGDL( containerDesc, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pListDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; ++nCountList; } // for // now check other HASH (if it is a HASH) // add all keys not in first HASH if( compareStruct != NULL) { DLong nSizeCmp = compareTable->N_Elements(); for( SizeT i=0; i(compareTable->GetTag( pKeyTag, i)))[0]; if( kID == 0) continue; BaseGDL* key = BaseGDL::interpreter->GetHeap( kID); assert( key != NULL); DLong insertIx = HashIndex(hashTable, key, isfoldcase); if( insertIx >= 0) // found { // this key was already handled (inserted or not) during the first compare continue; } // not equal -> insert into LIST DPtr dID = e->Interpreter()->NewHeap(1,key->Dup()); cStruct = new DStructGDL( containerDesc, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pListDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; ++nCountList; } // for } (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = nCountList; newObjGuard.Release(); return newObj; } // HASH___OverloadNEOp BaseGDL* HASH___OverloadEQOp( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() SizeT nParam = e->NParam(); // number of parameters actually given // more precise error message if( nParam < 3) // consider SELF ThrowFromInternalUDSub( e, "Two parameters are needed: LEFT, RIGHT."); BaseGDL* l = e->GetKW(1); if( l == NullGDL::GetSingleInstance()) l = NULL; BaseGDL* r = e->GetKW(2); if( r == NullGDL::GetSingleInstance()) r = NULL; if( (l == NULL && r == NULL)) ThrowFromInternalUDSub( e, "At least one parameter must be defined and a HASH."); DStructGDL* leftStruct = NULL; DObj leftID = 0; if( l != NULL && l->Type() == GDL_OBJ) { DObjGDL* left = static_cast(l); leftID = (*left)[0]; if( leftID == 0) { // null object -> compare to !NULL l = NULL; } else { try { leftStruct = BaseGDL::interpreter->GetObjHeap( leftID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Left parameter object ID <"+i2s(leftID)+"> not found."); } if( !leftStruct->Desc()->IsParent("HASH")) leftStruct = NULL; } } DStructGDL* rightStruct = NULL; DObj rightID = 0; if( r != NULL && r->Type() == GDL_OBJ) { DObjGDL* right = static_cast(r); rightID = (*right)[0]; if( rightID == 0) { // null object -> compare to !NULL r = NULL; } else { try { rightStruct = BaseGDL::interpreter->GetObjHeap( rightID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Right parameter object ID <"+i2s(rightID)+"> not found."); } if( !rightStruct->Desc()->IsParent("HASH")) rightStruct = NULL; } } bool isfoldcase = Hashisfoldcase(leftStruct) or Hashisfoldcase(rightStruct); DStructGDL* hashStruct = NULL; DStructGDL* hashTable = NULL; DStructGDL* compareStruct = NULL; DStructGDL* compareTable = NULL; BaseGDL* compare = NULL; if( leftStruct != NULL) { hashStruct = leftStruct; DPtr Ptr = (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0]; hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); if( rightStruct != NULL) { compareStruct = rightStruct; DPtr Ptr = (*static_cast( compareStruct->GetTag( pTableTag, 0)))[0]; compareTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); } else { compare = r; } } else if( rightStruct != NULL) { hashStruct = rightStruct; DPtr Ptr = (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0]; hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); compare = l; } else ThrowFromInternalUDSub( e, "At least one parameter must be a HASH."); DLong nSize = hashTable->N_Elements(); DLong nCount = (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0]; GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // making the result list: DStructDesc* listDesc= structDesc::LIST; DStructDesc* containerDesc= structDesc::GDL_CONTAINER_NODE; DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct BaseGDL* newObj = new DObjGDL( objID); // the list object Guard newObjGuard( newObj); DLong nCountList = 0; DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; for( SizeT i=0; i(hashTable->GetTag( pKeyTag, i)))[0]; if( kID == 0) continue; BaseGDL* key = BaseGDL::interpreter->GetHeap( kID); assert( key != NULL); if( compareStruct == NULL) // against value { DPtr vID = (*static_cast(hashTable->GetTag( pValueTag, i)))[0]; BaseGDL* v = BaseGDL::interpreter->GetHeap( vID); BaseGDL* vCmp = compare; if( v == NULL || v == NullGDL::GetSingleInstance()) { if( vCmp != NULL /*&& vCmp != NullGDL::GetSingleInstance()*/) continue; } if( vCmp == NULL /*|| vCmp == NullGDL::GetSingleInstance()*/) { if( v != NULL && v != NullGDL::GetSingleInstance()) continue; } if( v != NULL) { if( v->Type() != vCmp->Type()) continue; if( v->Type() == GDL_PTR) { if( !PtrDerefEqual( static_cast(v), static_cast(vCmp))) continue; } else if( !v->ArrayEqual( vCmp)) continue; } } else // against other HASH { DLong insertIx = HashIndex(compareTable, key, isfoldcase); if( insertIx < 0) // not found continue; DPtr vID = (*static_cast(hashTable->GetTag( pValueTag, i)))[0]; BaseGDL* v = BaseGDL::interpreter->GetHeap( vID); DPtr vCmpID = (*static_cast(compareTable->GetTag( pValueTag, insertIx)))[0]; BaseGDL* vCmp = BaseGDL::interpreter->GetHeap( vCmpID); if( v == NULL || v == NullGDL::GetSingleInstance()) { if( vCmp != NULL && vCmp != NullGDL::GetSingleInstance()) continue; } if( vCmp == NULL || vCmp == NullGDL::GetSingleInstance()) { if( v != NULL && v != NullGDL::GetSingleInstance()) continue; } if( v != NULL) { if( v->Type() != vCmp->Type()) continue; if( v->Type() == GDL_PTR) { if( !PtrDerefEqual( static_cast(v), static_cast(vCmp))) continue; } else if( !v->ArrayEqual( vCmp)) continue; } } // equal -> insert into LIST DPtr dID = e->Interpreter()->NewHeap(1,key->Dup()); cStruct = new DStructGDL( containerDesc, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pListDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; ++nCountList; } // for (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = nCountList; newObjGuard.Release(); return newObj; } BaseGDL* HASH___OverloadPlus( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() SizeT nParam = e->NParam(); // number of parameters actually given // more precise error message if( nParam < 3) ThrowFromInternalUDSub( e, "Two parameters are needed: LEFT, RIGHT."); // default behavior: Exact like scalar indexing BaseGDL* l = e->GetKW(1); if(l == NULL || (l->Type() != GDL_OBJ && l->Type() != GDL_STRUCT)) ThrowFromInternalUDSub( e, "Left parameter must be a HASH or STRUCT."); BaseGDL* r = e->GetKW(2); if(r == NULL || (r->Type() != GDL_OBJ && r->Type() != GDL_STRUCT)) ThrowFromInternalUDSub( e, "Right parameter must be a HASH or STRUCT."); // new hash DStructGDL* hashStruct= new DStructGDL( structDesc::HASH, dimension()); DObj objID= e->NewObjHeap( 1, hashStruct); // owns hashStruct, sets ref count to 1 BaseGDL* newObj = new DObjGDL( objID); // the return HASH object Guard newObjGuard( newObj); DStructGDL* leftStruct = NULL; DObj leftID = 0; if( l->Type() == GDL_OBJ) { DObjGDL* left = static_cast(l); leftID = (*left)[0]; try { leftStruct = BaseGDL::interpreter->GetObjHeap( leftID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Left parameter object ID <"+i2s(leftID)+"> not found."); } if( !leftStruct->Desc()->IsParent("HASH")) ThrowFromInternalUDSub( e, "Left parameter object ("+leftStruct->Desc()->Name()+") must be a HASH."); } else { leftStruct = static_cast(l); } DStructGDL* rightStruct = NULL; DObj rightID = 0; if( r->Type() == GDL_OBJ) { DObjGDL* right = static_cast(r); rightID = (*right)[0]; try { rightStruct = BaseGDL::interpreter->GetObjHeap( rightID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Right parameter object ID <"+i2s(rightID)+"> not found."); } if( !rightStruct->Desc()->IsParent("HASH")) ThrowFromInternalUDSub( e, "Right parameter object ("+rightStruct->Desc()->Name()+") must be a HASH."); } else { rightStruct = static_cast(r); } if( leftID != 0 && rightID != 0) { // merge sort them together DLong nCountL = (*static_cast(leftStruct->GetTag( TableCountTag, 0)))[0]; DLong nCountR = (*static_cast(rightStruct->GetTag( TableCountTag, 0)))[0]; DPtr PtrL = (*static_cast( leftStruct->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTableL = static_cast(BaseGDL::interpreter->GetHeap( PtrL)); DPtr PtrR = (*static_cast( rightStruct->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTableR = static_cast(BaseGDL::interpreter->GetHeap( PtrR)); DLong nSizeL = hashTableL->N_Elements(); DLong nSizeR = hashTableR->N_Elements(); DLong nCountMax = nCountL + nCountR; // new hash table DLong initialTableSize = GetInitialTableSize( nCountMax); DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= e->NewHeap( 1, hashTable); // owns hashTable, sets ref count to 1 (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; DLong nSize = hashTable->N_Elements(); assert( nSize >= nCountMax); if( nCountMax == 0) // two empty HASH { (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = nSize; // nCount was set to zero at init newObjGuard.Release(); return newObj; } DLong leftIx = -1; DLong rightIx = -1; // advance both to 1st if( nCountL > 0) while( (*static_cast(hashTableL->GetTag( pKeyTag, ++leftIx)))[0] == 0); if( leftIx == -1) leftIx = nSizeL; if( nCountR > 0) while( (*static_cast(hashTableR->GetTag( pKeyTag, ++rightIx)))[0] == 0); if( rightIx == -1) rightIx = nSizeR; DLong nCount = nCountMax; for( SizeT el=0; el(hashTableL->GetTag( pKeyTag, leftIx)))[0]; keyL = BaseGDL::interpreter->GetHeap( kIDL); assert( keyL != NULL); if( rightIx < nSizeR) { DPtr kIDR = (*static_cast(hashTableR->GetTag( pKeyTag, rightIx)))[0]; keyR = BaseGDL::interpreter->GetHeap( kIDR); assert( keyR != NULL); // both valid -> compare hashCompare = keyL->HashCompare( keyR); if( hashCompare == 0) --nCount; } else { // right finish -> use left hashCompare = -1; } } else { // left finish -> use right if( rightIx >= nSizeR) assert( rightIx < nSizeR); DPtr kIDR = (*static_cast(hashTableR->GetTag( pKeyTag, rightIx)))[0]; keyR = BaseGDL::interpreter->GetHeap( kIDR); assert( keyR != NULL); hashCompare = 1; } DLong insertIx = el * nSize / nCountMax; if( hashCompare == -1) // keyL smaller -> use left { DPtr kID = BaseGDL::interpreter->NewHeap(1,keyL->Dup()); (*static_cast(hashTable->GetTag( pKeyTag, insertIx)))[0] = kID; DPtr vSrcID = (*static_cast(hashTableL->GetTag( pValueTag, leftIx)))[0]; BaseGDL* value = BaseGDL::interpreter->GetHeap( vSrcID); if( value != NULL) value = value->Dup(); DPtr vID = BaseGDL::interpreter->NewHeap(1,value); (*static_cast(hashTable->GetTag( pValueTag, insertIx)))[0] = vID; // advance l while( (++leftIx < nSizeL) && (*static_cast(hashTableL->GetTag( pKeyTag, leftIx)))[0] == 0); } else // keyL larger or equal -> use right { DPtr kID = BaseGDL::interpreter->NewHeap(1,keyR->Dup()); (*static_cast(hashTable->GetTag( pKeyTag, insertIx)))[0] = kID; DPtr vSrcID = (*static_cast(hashTableR->GetTag( pValueTag, rightIx)))[0]; BaseGDL* value = BaseGDL::interpreter->GetHeap( vSrcID); if( value != NULL) value = value->Dup(); DPtr vID = BaseGDL::interpreter->NewHeap(1,value); (*static_cast(hashTable->GetTag( pValueTag, insertIx)))[0] = vID; // advance r while( (++rightIx < nSizeR) && (*static_cast(hashTableR->GetTag( pKeyTag, rightIx)))[0] == 0); if( hashCompare == 0) // advance r also if equal keys while( (++leftIx < nSizeL) && (*static_cast(hashTableL->GetTag( pKeyTag, leftIx)))[0] == 0); } } (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = nSize; (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0] = nCount; newObjGuard.Release(); return newObj; } DStructGDL* newHashTable; // at least one is struct if( leftID != 0) // left is HASH { DLong nCountL = (*static_cast(leftStruct->GetTag( TableCountTag, 0)))[0]; DPtr PtrL = (*static_cast( leftStruct->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTableL = static_cast(BaseGDL::interpreter->GetHeap( PtrL)); // right must be struct DLong nCountR = rightStruct->NTags(); DLong nCount = nCountL + nCountR; DLong initialTableSize = GetInitialTableSize( nCount); newHashTable = CopyHashTable( leftStruct, hashTableL, initialTableSize); DPtr hashTableID= e->NewHeap( 1, newHashTable); // owns hashTable, sets ref count to 1 (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0] = nCountL; } else if( rightID != 0) // right is HASH { DLong nCountR = (*static_cast(rightStruct->GetTag( TableCountTag, 0)))[0]; DPtr PtrR = (*static_cast( rightStruct->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTableR = static_cast(BaseGDL::interpreter->GetHeap( PtrR)); // right must be struct DLong nCountL = leftStruct->NTags(); DLong nCount = nCountL + nCountR; DLong initialTableSize = GetInitialTableSize( nCount); newHashTable = CopyHashTable( rightStruct, hashTableR, initialTableSize); DPtr hashTableID= e->NewHeap( 1, newHashTable); // owns hashTable, sets ref count to 1 (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0] = nCountR; } else // both are struct { DLong nCountL = leftStruct->NTags(); DLong nCountR = rightStruct->NTags(); DLong nCount = nCountL + nCountR; DLong initialTableSize = GetInitialTableSize( nCount); newHashTable = new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= e->NewHeap( 1, newHashTable); // owns hashTable, sets ref count to 1 (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; // set to zero at init //(*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0] = 0; } (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = newHashTable->N_Elements(); if( leftID == 0) // add left struct { DStructDesc* desc = leftStruct->Desc(); for( SizeT t=0; tNTags(); ++t) { DStringGDL *structKey = new DStringGDL( desc->TagName(t)); BaseGDL* structData = leftStruct->GetTag(t,0); assert(structData != NULL); structData = structData->Dup(); InsertIntoHashTable( hashStruct, newHashTable, structKey, structData); } } if( rightID == 0) // add right struct { DStructDesc* desc = rightStruct->Desc(); for( SizeT t=0; tNTags(); ++t) { DStringGDL *structKey = new DStringGDL( desc->TagName(t)); BaseGDL* structData = rightStruct->GetTag(t,0); assert(structData != NULL); structData = structData->Dup(); InsertIntoHashTable( hashStruct, newHashTable, structKey, structData); } } newObjGuard.Release(); return newObj; } BaseGDL* hash__tostruct( EnvUDT* e) { static int kwSKIPPEDIx = e->GetKeywordIx("SKIPPED"); static int kwMISSINGIx = e->GetKeywordIx("MISSING"); static int kwRECURSIVEIx = e->GetKeywordIx("RECURSIVE"); static int kwNO_COPYIx = e->GetKeywordIx("NO_COPY"); BaseGDL* missing = e->GetKW( kwMISSINGIx); BaseGDL** skipped = NULL; if( e->GlobalKW( kwSKIPPEDIx)) skipped = &e->GetKW(kwSKIPPEDIx); bool recursive = e->KeywordSet(kwRECURSIVEIx); bool no_copy = e->KeywordSet( kwNO_COPYIx); static int kwSELFIx = kwSKIPPEDIx + 1; SizeT nParam = e->NParam(1); DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); return hash_tostruct( self, missing, skipped, recursive, no_copy); } BaseGDL* hash__isempty( EnvUDT* e) { static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); static int kwSELFIx = 0; BaseGDL* selfP = e->GetKW( kwSELFIx); DStructGDL* self = GetOBJ( selfP, e); DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; if (nCount > 0) return new DByteGDL( 0); else return new DByteGDL(1); } BaseGDL* hash__isordered( EnvUDT* e) { static unsigned ordmask = 0x00000010; static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); static int kwSELFIx = 0; BaseGDL* selfP = e->GetKW( kwSELFIx); DStructGDL* self = GetOBJ( selfP, e); DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; if(trace_me) std::cout << "isordered: nCount=" << nCount << std::endl; DLong bits = (*static_cast( self->GetTag( TableBitsTag , 0)))[0]; if(trace_me) std::cout << "isordered: bits=" << bits << std::endl; if ( (bits & ordmask) == 0) return new DByteGDL( 0); else return new DByteGDL(1); } BaseGDL* hash__isfoldcase( EnvUDT* e) { static unsigned fold_case_mask = 0x00000001; static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); if ( Hashisfoldcase( GetOBJ( e->GetKW( 0), e)) ) return new DByteGDL(1); else return new DByteGDL(0); } BaseGDL* hash__count( EnvUDT* e) { static int kwSELFIx = 0; static int kwVALUEIx = 1; static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); static unsigned nListTag = structDesc::LIST->TagIndex( "NLIST"); BaseGDL* selfP = e->GetKW( kwSELFIx); SizeT nParam = e->NParam(1); if( nParam == 1) return new DLongGDL( HASH_count( GetOBJ( selfP, e))); DObjGDL* selfObj = static_cast(selfP); // nParam > 1: BaseGDL* r = e->GetKW( kwVALUEIx); DObjGDL* listObj = static_cast( selfObj->EqOp( r)); Guard listObjGuard( listObj); DStructGDL* selfLIST = GetOBJ( listObj, e); DLong nList = (*static_cast( selfLIST->GetTag( nListTag, 0)))[0]; return new DLongGDL( nList); } BaseGDL* hash__where( EnvUDT* e) { static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); static unsigned nListTag = structDesc::LIST->TagIndex( "NLIST"); static int kwNCOMPLEMENTIx = e->GetKeywordIx("NCOMPLEMENT"); static int kwCOUNTIx = e->GetKeywordIx("COUNT"); static int kwCOMPLEMENTIx = e->GetKeywordIx("COMPLEMENT"); static int kwSELFIx = 3; static int kwVALUEIx = kwSELFIx + 1; SizeT nParam = e->NParam(2); // SELF, VALUE BaseGDL* selfP = e->GetKW( kwSELFIx); DStructGDL* self = GetOBJ( selfP, e); DObjGDL* selfObj = static_cast(selfP); BaseGDL* r = e->GetKW( kwVALUEIx); DObjGDL* listObj = static_cast( selfObj->EqOp( r)); Guard listObjGuard( listObj); DStructGDL* selfLIST = GetOBJ( listObj, e); DLong nList = (*static_cast( selfLIST->GetTag( nListTag, 0)))[0]; if( e->KeywordPresent( kwNCOMPLEMENTIx)) // NCOMPLEMENT { DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; e->SetKW( kwNCOMPLEMENTIx, new DLongGDL( nCount - nList)); } if( e->KeywordPresent( kwCOUNTIx)) // COUNT { e->SetKW( kwCOUNTIx, new DLongGDL( nList)); } if( e->KeywordPresent( kwCOMPLEMENTIx)) // COMPLEMENT { DObjGDL* compObj = static_cast( selfObj->NeOp( r)); e->SetKW( kwCOMPLEMENTIx, compObj); } listObjGuard.Release(); return listObj; } BaseGDL* hash__keysvalues( EnvUDT* e, bool keys); BaseGDL* hash__values( EnvUDT* e) { return hash__keysvalues( e, false); } BaseGDL* hash__keys( EnvUDT* e) { return hash__keysvalues( e, true); } BaseGDL* hash__keysvalues( EnvUDT* e, bool doKeys) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() static int kwSELFIx = 0; SizeT nParam = e->NParam(1); // SELF BaseGDL* selfP = e->GetKW( kwSELFIx); DStructGDL* self = GetOBJ( selfP, e); DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DStructDesc* listDesc= structDesc::LIST; DStructDesc* containerDesc= structDesc::GDL_CONTAINER_NODE; DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct BaseGDL* newObj = new DObjGDL( objID); // the list object Guard newObjGuard( newObj); DPtr Ptr = (*static_cast( self->GetTag( pTableTag, 0)))[0]; DStructGDL* hashTable = static_cast(BaseGDL::interpreter->GetHeap( Ptr)); DLong nSize = hashTable->N_Elements(); unsigned sourceTag; if( doKeys) { sourceTag = pKeyTag; } else // do values { sourceTag = pValueTag; } DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; SizeT ix = 0; for( SizeT i=0; i(hashTable->GetTag( pKeyTag, ix)))[0] == 0) ++ix; assert( ix < nSize); DPtr pSource = (*static_cast(hashTable->GetTag( sourceTag, ix)))[0]; BaseGDL* source = BaseGDL::interpreter->GetHeap( pSource); assert( !doKeys || source != NULL); if( source != NULL) // NULL is ok for values source = source->Dup(); DPtr dID = e->Interpreter()->NewHeap(1,source); cStruct = new DStructGDL( containerDesc, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pListDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; } (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = nCount; newObjGuard.Release(); return newObj; } BaseGDL* hash__haskey( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() // see overload.cpp static int kwSELFIx = 0; static int kwKEYIx = 1; SizeT nParam = e->NParam(2); // SELF, KEYLIST BaseGDL* selfP = e->GetKW( kwSELFIx); DStructGDL* self = GetOBJ( selfP, e); bool isfoldcase = Hashisfoldcase( self); BaseGDL* keyList = e->GetKW( kwKEYIx); if( keyList == NULL || keyList == NullGDL::GetSingleInstance()) ThrowFromInternalUDSub( e, "Key must be a scalar string or number."); if( keyList->Type() != GDL_STRING && !NumericType(keyList->Type())) ThrowFromInternalUDSub( e, "Key must be a scalar string or number."); DPtr Ptr = (*static_cast( self->GetTag( pTableTag, 0)))[0]; DStructGDL* thisHashTable = static_cast(e->Interpreter()->GetHeap( Ptr)); if( keyList->N_Elements() == 1) { DLong hashIndex = HashIndex( thisHashTable, keyList, isfoldcase); if( hashIndex >= 0) return new DIntGDL( 1); return new DIntGDL( 0); } SizeT keyListN_Elements = keyList->N_Elements(); DIntGDL* result = new DIntGDL( dimension(keyListN_Elements)); // zero Guard resultGuard( result); for( SizeT i=0; iNewIx( i); // Guard keyGuard( key); DLong hashIndex = HashIndex( thisHashTable, key, isfoldcase); if( hashIndex >= 0) (*result)[ i] = 1; } resultGuard.Release(); return result; } BaseGDL* hash__remove( EnvUDT* e, bool asFunction); BaseGDL* hash__remove_fun( EnvUDT* e) { return hash__remove( e, true); } void hash__remove_pro( EnvUDT* e) { hash__remove( e, false); } BaseGDL* hash__remove( EnvUDT* e, bool asFunction) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() // see overload.cpp static int kwALLIx = 0; static int kwSELFIx = 1; static int kwINDEXIx = 2; bool kwALL = false; if (e->KeywordSet(kwALLIx)){ kwALL = true;} SizeT nParam = e->NParam(1); DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); if( kwALL) { if( asFunction) { DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; DLong initialTableSize = GetInitialTableSize( 0); // our current table DPtr thisTableID = (*static_cast( self->GetTag( pTableTag, 0)))[0]; DStructGDL* thisHashTable = static_cast(e->Interpreter()->GetHeap( thisTableID)); DLong nSize = thisHashTable->N_Elements(); // new hash DStructGDL* hashStruct= new DStructGDL( structDesc::HASH, dimension()); DObj objID= e->NewObjHeap( 1, hashStruct); // owns hashStruct, sets ref count to 1 BaseGDL* newObj = new DObjGDL( objID); // the return HASH object Guard newObjGuard( newObj); // our new hash table DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= e->NewHeap( 1, hashTable); // owns hashTable, sets ref count to 1 // set our table to new empty table (*static_cast( self->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( self->GetTag( TableSizeTag, 0)))[0] = initialTableSize; (*static_cast( self->GetTag( TableCountTag, 0)))[0] = 0; // set our old table to new HASH (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = thisTableID; (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = nSize; (*static_cast( hashStruct->GetTag( TableCountTag, 0)))[0] = nCount; newObjGuard.Release(); return newObj; } else { DLong initialTableSize = GetInitialTableSize( 0); // our current table DPtr thisTableID = (*static_cast( self->GetTag( pTableTag, 0)))[0]; // DStructGDL* thisHashTable = static_cast(e->Interpreter()->GetHeap( thisTableID)); // our new hash table DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= e->NewHeap( 1, hashTable); // owns hashTable, sets ref count to 1 // set our table to new empty table (*static_cast( self->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( self->GetTag( TableSizeTag, 0)))[0] = initialTableSize; (*static_cast( self->GetTag( TableCountTag, 0)))[0] = 0; // trigger ref-count delete of all elements BaseGDL::interpreter->FreeHeap( thisTableID); return NULL; } } BaseGDL* index = NULL; if( nParam >= 2) index = e->GetKW(kwINDEXIx); if( index == NULL) { BaseGDL* removedElement = RemoveFromHashTable( e, self, NULL); if( !asFunction) { GDLDelete( removedElement); removedElement = NULL; } return removedElement; } if( index->N_Elements() == 1) { BaseGDL* removedElement = RemoveFromHashTable( e, self, index); if( !asFunction) { GDLDelete( removedElement); removedElement = NULL; } return removedElement; } if( asFunction) { // new hash DStructGDL* hashStruct= new DStructGDL( structDesc::HASH, dimension()); DObj objID= e->NewObjHeap( 1, hashStruct); // owns hashStruct, sets ref count to 1 BaseGDL* newObj = new DObjGDL( objID); // the return HASH object Guard newObjGuard( newObj); SizeT nRemove = index->N_Elements(); DLong initialTableSize = GetInitialTableSize( nRemove); // new hash table // our current table (for the descriptor) DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= e->NewHeap( 1, hashTable); // owns hashTable, sets ref count to 1 (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = initialTableSize; for( SizeT r=0; rNewIx( r); Guard removeKeyGuard( removeKey); BaseGDL* removedElement = RemoveFromHashTable( e, self, removeKey); InsertIntoHashTable( hashStruct, hashTable, removeKeyGuard.release(), removedElement); } newObjGuard.Release(); return newObj; } else { SizeT nRemove = index->N_Elements(); for( SizeT r=0; rNewIx( r); Guard removeKeyGuard( removeKey); BaseGDL* removedElement = RemoveFromHashTable( e, self, removeKey); GDLDelete( removedElement); } return NULL; } } BaseGDL* hash_subset(DStructGDL* thisTable, BaseGDL* index, bool isfoldcase); BaseGDL* hash_newhash(SizeT nEntries = 0, bool isfoldcase = false) { // new hash GDL_HASHTABLEENTRY() GDL_HASH_STRUCT() static unsigned fold_case_mask = 0x00000001; DLong initialTableSize = GetInitialTableSize(nEntries); DStructGDL* hashStruct= new DStructGDL( structDesc::HASH, dimension()); DObj objID= BaseGDL::interpreter->NewObjHeap( 1, hashStruct); if( isfoldcase) (*static_cast ( hashStruct->GetTag( TableBitsTag, 0)))[0] = fold_case_mask; BaseGDL* newObj = new DObjGDL( objID); Guard newObjGuard( newObj); DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= BaseGDL::interpreter->NewHeap( 1, hashTable); (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = initialTableSize; newObjGuard.Release(); return newObj; } void hash_leftinsertion( EnvUDT* e, DStructGDL* theStruct, int iprm ) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() static unsigned isRangeIx = 3; static unsigned prmbeg = isRangeIx+1; GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // handle DOT access bool dotAccess = false; BaseGDL** objRef = &e->GetKW(1); if( *objRef == NULL || *objRef == NullGDL::GetSingleInstance()) { if( !e->GlobalKW(1)) ThrowFromInternalUDSub( e, "Parameter 1 (OBJREF) is undefined."); dotAccess = true; } BaseGDL* rValue = e->GetKW(2); if( rValue == NULL) rValue = NullGDL::GetSingleInstance(); BaseGDL* parX = e->GetKW(iprm + prmbeg); if( parX == 0) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( iprm + prmbeg ))); bool stolen = e->StealLocalKW(iprm + prmbeg); if( !stolen) parX = parX->Dup(); // if called explicitely DType theType = parX->Type(); if(trace_me) { std::cout << " parX->Type() " << theType ; help_item(std::cout, parX, " hash-leftinsert ",false); } DStructGDL* ListHead; SizeT listSize = 0; DPtr keyNode; bool iskeylist = false;; if(theType == GDL_OBJ && parX->Rank() == 0) { DObj p=(*static_cast( parX))[0]; if(p != 0) { ListHead = GetOBJ( parX, e); DStructDesc* desc = ListHead->Desc(); iskeylist = desc->IsParent("LIST"); } if(iskeylist) { listSize = (*static_cast(ListHead->GetTag( nListTag, 0)))[0]; keyNode = GetLISTNode(e, ListHead, 0); if( listSize == 1) { // accidentally this will pass through an array embedded in a single-element list. parX = GetNodeData( keyNode); iskeylist = false; } // } } DPtr thisTableID = (*static_cast( theStruct->GetTag( pTableTag, 0)))[0]; DStructGDL* thisHashTable = static_cast(e->Interpreter()-> GetHeap( thisTableID)); bool isfoldcase = Hashisfoldcase( theStruct); // non-range (keyed) SizeT nKey = parX->N_Elements(); if(iskeylist) nKey = listSize; if( nKey == 1) // single key { if( dotAccess) // -> objRef is NULL (or !NULL) { if( rValue != NullGDL::GetSingleInstance()) { ThrowFromInternalUDSub( e, "For struct access (OBJREF is !NULL), RVALUE must be !NULL as well."); } DLong hashIndex = HashIndex( thisHashTable, parX, isfoldcase); if( hashIndex < 0) ThrowFromInternalUDSub( e, "Key not found."); *objRef = thisHashTable->GetTag( pValueTag, hashIndex)->Dup(); return; } InsertIntoHashTable( theStruct, thisHashTable, parX, rValue->Dup()); return; } if( dotAccess) ThrowFromInternalUDSub( e, "Only single value struct access is allowed."); bool isvalscalar = false; bool isvallist = false; if( rValue == NULL || rValue == NullGDL::GetSingleInstance()) isvalscalar = true; else if( rValue->StrictScalar() ) isvalscalar = true; if(trace_me) std::cout << " isvalscalar/ iskeylist? nKey:"<< isvalscalar<< iskeylist << nKey << std::endl; if( !isvalscalar && rValue->N_Elements() != nKey ) ThrowFromInternalUDSub( e, "Key and Value must have the same number of elements."); if( isvalscalar){ if( rValue->Type() == GDL_OBJ) { DObj p=(*static_cast( rValue))[0]; if(p != 0) { ListHead = GetOBJ( rValue, e); DStructDesc* desc = ListHead->Desc(); isvallist = desc->IsParent("LIST"); } } if(isvallist) { listSize = (*static_cast(ListHead->GetTag( nListTag, 0)))[0]; if(listSize != nKey) ThrowFromInternalUDSub( e, "Key and Value must have the same number of elements."); DPtr valNode = GetLISTNode(e, ListHead, 0); if(iskeylist) for( SizeT kIx=0; kIxDup()); else for( SizeT kIx=0; kIxNewIx(kIx), (GetNodeData(valNode))->Dup()); } else { if(iskeylist) for( SizeT kIx=0; kIxDup()); else for( SizeT kIx=0; kIxNewIx(kIx), rValue->Dup()); } } else { // rValue not a scalar. if(iskeylist) { for( SizeT kIx=0; kIxNewIx(kIx)); } else { for( SizeT kIx=0; kIxNewIx(kIx), rValue->NewIx(kIx)); } } } void HASH___OverloadBracketsLeftSide( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() // static unsigned par1Ix = 4; static unsigned isRangeIx = 3; static unsigned prmbeg = isRangeIx+1; // trace_me = lib::trace_arg(); std::string trcn = trace_me? "\n;" :";"; SizeT nParam = e->NParam(1); if( nParam < 5) ThrowFromInternalUDSub( e, "Four parameters are needed: OBJREF, RVALUE, ISRANGE, SUB1."); // handle DOT access bool dotAccess = false; BaseGDL** objRef = &e->GetKW(1); if( *objRef == NULL || *objRef == NullGDL::GetSingleInstance()) { if( !e->GlobalKW(1)) ThrowFromInternalUDSub( e, "Parameter 1 (OBJREF) is undefined."); dotAccess = true; } BaseGDL* rValue = e->GetKW(2); if( rValue == NULL) rValue = NullGDL::GetSingleInstance(); DLongGDL* isRange = static_cast( e->GetKW(isRangeIx)); SizeT nIsRange = isRange->N_Elements(); if(nIsRange == 0) { nIsRange = nParam - isRangeIx - 1; for (int i=0; i < nIsRange; i++) (*isRange)[i] = 0; if(trace_me) std::cout << " nIsRange was 0!" ; } // isRange is a series of 0 or 1 indicating if a range is present. // more comments in list__]/ if(trace_me) { std::cout << "Hash-OL left:nIsRange " << nIsRange << ",nParam " << nParam << " ,isRange:"; for (int i=0; i < nIsRange; i++) std::cout << " "<<(*isRange)[i]; std::cout << std::endl; } // hash[*] = ... (Decline the attempt.) BaseGDL* parX = e->GetKW( prmbeg); // implicit SELF, ISRANGE, par1..par8 if( parX == NULL) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( prmbeg))); if( (*isRange)[0]== 1) { if( parX->N_Elements() != 3) ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW(prmbeg))); MAKE_LONGGDL(parX, parXLong) if( (*parXLong)[0] != 0 || (*parXLong)[1] != -1 || (*parXLong)[2] != 1) ThrowFromInternalUDSub( e, "Subscript range is not allowed: [" + i2s((*parXLong)[0])+ ":"+ i2s((*parXLong)[1])+":"+i2s((*parXLong)[2])+"]"); // (Dead End) ThrowFromInternalUDSub( e, "Setting all [*] for hash is not allowed in GDL. \n" " (in IDL, kl=hash.keys(). for i=0,n_elements(kl)-1 do hash[kl[i]]= ...)\n" "Please report if you would appreciate this functionality."); } // Generalize from self to theStruct DStructGDL* self = GetOBJ( e->GetKW( 0), e); DStructGDL* theStruct = self; DPtr Ptr = (*static_cast( theStruct->GetTag( pTableTag, 0) ))[0]; DStructGDL* hashTable = static_cast( BaseGDL::interpreter->GetHeap( Ptr)); bool isfoldcase = Hashisfoldcase( theStruct); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // This section copied and slightly adapted from LIST_OVERLOADLEFT BaseGDL* theref = NULL; int iprm = 0; SizeT listSize = 0; bool islist= false; bool ishash = true; bool isstruct = false; bool finalprm = false; while( (*isRange)[iprm] == 0) { // && (iprm+3 < nParam) finalprm = (iprm+prmbeg+1 == nParam); BaseGDL* XX = e->GetKW( iprm + prmbeg); if( XX->Rank() != 0 ) break; // must be a scalar if( islist) { MAKE_LONGGDL( XX, XXLong) DLong Ixref = (*XXLong)[0]; listSize = (*static_cast(theStruct->GetTag( nListTag, 0)))[0]; if(Ixref >= listSize) // this is certainly common. ThrowFromInternalUDSub( e, "direct access index is too high" + i2s(Ixref) + " >= nList:"+i2s(listSize)); DStructGDL* Node = GetLISTStruct( e, GetLISTNode( e, theStruct, Ixref)); DPtr Ptr = (*static_cast( Node->GetTag( pListDataTag, 0)))[0]; if(trace_me) std::cout << " islist iprm="< or list[ix,iy] = if(trace_me) std::cout<<" - immediate Dup()"<GetHeap( Ptr) = rValue->Dup(); return; } theref = BaseGDL::interpreter->GetHeap( Ptr); if( theref == 0) ThrowFromInternalUDSub( e, " No data in list at index "+i2s(Ixref)); } else if( ishash ) { DPtr Ptr = (*static_cast( theStruct->GetTag( pTableTag, 0) ))[0]; hashTable = static_cast( BaseGDL::interpreter->GetHeap( Ptr)); if(trace_me) std::cout<< iprm << " =iprm, " ; isfoldcase = Hashisfoldcase( theStruct); DLong hashIndex = HashIndex( hashTable , XX, isfoldcase); if(trace_me) std::cout << " hashindex= "<= 0) { DPtr pValue = (*static_cast( hashTable->GetTag( pValueTag, hashIndex) ))[0]; if( finalprm ) { if(trace_me) std::cout<<" - immediate Dup()"<GetHeap( pValue) = rValue->Dup(); return; } else { theref = BaseGDL::interpreter->GetHeap( pValue); } } else { // hashIndex >= 0 if( finalprm ) { if(trace_me) std::cout<<" - insert rVal->Dup()"; hash_leftinsertion( e, theStruct, iprm); return; } else{ if(trace_me) std::cout<<" newhash(0)"; theref = hash_subset( hashTable, 0, isfoldcase); // theref = hash_newhash( 0, isfoldcase); // Now we must insert this new hash before proceeding down the nest. bool stolen = e->StealLocalKW(iprm + prmbeg); if( !stolen) XX = XX->Dup(); InsertIntoHashTable( theStruct, hashTable, XX, theref->Dup()); } } } else if( isstruct ) { // use XX to access struct. GDL extension, IDL doesn't do this. int ptagindex = 0; if(XX->Type() != GDL_STRING) { MAKE_LONGGDL( XX, XXLong) ptagindex = (*XXLong)[0]; if(ptagindex >= theStruct->Desc()->NTags() ) ptagindex = -1; } else { DString tag = (*static_cast( XX))[0]; StrUpCaseInplace(tag); ptagindex = theStruct->Desc()->TagIndex(tag); } if(ptagindex < 0) ThrowFromInternalUDSub( e, " struct tag not found "); theref = theStruct->Get( ptagindex); } else {break;} DType theType = theref->Type(); // Enhance (?) it by allowing pointers to lists to represent lists. // in order to turn this off, a ptr scalar must go in as a ptrarr[1]; // This is probably not IDL behavior. if( theType == GDL_PTR && theref->Rank() == 0) { theref = BaseGDL::interpreter->GetHeap( (*static_cast( theref))[0] ); theType = theref->Type(); // this is probably so odd itshould be advertised when it happens: std::cout<<" **p= "<Rank() == 0) { theStruct = GetOBJ( theref, e); DStructDesc* desc = theStruct->Desc(); islist = desc->IsParent("LIST"); ishash = desc->IsParent("HASH"); isstruct = !(islist or ishash); } else if( theType == GDL_STRUCT and theref->N_Elements() == 1) { theStruct = static_cast( theref); isstruct = true; } iprm++; if( gdl_type_lookup::IsConvertableType[theType] ) break; } // while if(trace_me) { std::cout << " HASH_OL[L]: iprm="<< i2s(iprm); // if(theref == NULL || theref == NullGDL::GetSingleInstance() ) std::cout <<" (theref == 0) "<< std::endl; else lib::help_item(std::cout, theref," theref",false);// } if(ishash) { // if we finish on a hash, make insertion and leave. // BaseGDL* parX = e->GetKW( iprm + prmbeg ); // if( parX == 0) ThrowFromInternalUDSub( e, "Parameter is undefined: " // + e->Caller()->GetString(e->GetKW( iprm + prmbeg ))); hash_leftinsertion( e, theStruct, iprm); return; } else if(islist || gdl_type_lookup::IsConvertableType[theref->Type()] ) { list_leftinsertion( e, theref, iprm); return; } else ThrowFromInternalUDSub( e, "Logic error in hash_overloadleft." "Please report this Occurence."); } BaseGDL* hash_subset(DStructGDL* thisTable, BaseGDL* index, bool isfoldcase) { GDL_LIST_STRUCT() DStructGDL* ListHead; SizeT listSize = 0; DPtr keyNode; bool iskeylist = false;; SizeT nEntries = 0; DType theType; if( index != NULL) { // use index==NULL to simply make a blank hash. nEntries = index->N_Elements(); theType = index->Type(); if(trace_me) std::cout << " hash_subset: index->Type() " << theType << std::endl; if(theType == GDL_OBJ && index->Rank() == 0) { DObj p=(*static_cast( index))[0]; if(p != 0) { ListHead = GetOBJ( index, 0); DStructDesc* desc = ListHead->Desc(); iskeylist = desc->IsParent("LIST"); } if(iskeylist) { listSize = (*static_cast(ListHead->GetTag( nListTag, 0)))[0]; keyNode = GetLISTNode( 0, ListHead, 0); if( listSize == 1) { index = GetNodeData( keyNode); iskeylist = false; } nEntries = listSize; } } } GDL_HASHTABLEENTRY() GDL_HASH_STRUCT() static unsigned fold_case_mask = 0x00000001; DLong initialTableSize = GetInitialTableSize( nEntries); // new hash DStructGDL* hashStruct= new DStructGDL( structDesc::HASH, dimension()); DObj objID= BaseGDL::interpreter->NewObjHeap( 1, hashStruct); if( isfoldcase) (*static_cast ( hashStruct->GetTag( TableBitsTag, 0)))[0] = fold_case_mask; BaseGDL* newObj = new DObjGDL( objID); Guard newObjGuard( newObj); DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= BaseGDL::interpreter->NewHeap( 1, hashTable); (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = initialTableSize; BaseGDL* actKey; for( SizeT eIx=0; eIxNewIx( eIx); DLong hashIndex = HashIndex( thisTable, actKey, isfoldcase); if( hashIndex < 0) continue; DPtr vID = (*static_cast(thisTable->GetTag( pValueTag, hashIndex)))[0]; BaseGDL* value = BaseGDL::interpreter->GetHeap( vID); if( value != NULL) value = value->Dup(); InsertIntoHashTable( hashStruct, hashTable, actKey->Dup(), value); } newObjGuard.Release(); return newObj; } BaseGDL* hash_duplicate(DStructGDL* self) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() DPtr thisTableID = (*static_cast( self->GetTag( pTableTag, 0)))[0]; DStructGDL* thisHashTable = static_cast(BaseGDL::interpreter->GetHeap( thisTableID)); DLong nCount = (*static_cast( self->GetTag( TableCountTag, 0)))[0]; SizeT nEntries = nCount; DLong initialTableSize = GetInitialTableSize( nEntries); // new hash DStructGDL* hashStruct= new DStructGDL( structDesc::HASH, dimension()); // unsigned long bitmask; (*static_cast( hashStruct->GetTag( TableBitsTag, 0)))[0] = (*static_cast( self->GetTag( TableBitsTag , 0)))[0]; DObj objID=BaseGDL::interpreter->NewObjHeap( 1, hashStruct); // owns hashStruct, sets ref count to 1 BaseGDL* newObj = new DObjGDL( objID); // the return HASH object Guard newObjGuard( newObj); // the return hash table DStructGDL* hashTable= new DStructGDL( structDesc::GDL_HASHTABLEENTRY, dimension(initialTableSize)); DPtr hashTableID= BaseGDL::interpreter->NewHeap( 1, hashTable); // owns hashTable, sets ref count to 1 (*static_cast( hashStruct->GetTag( pTableTag, 0)))[0] = hashTableID; (*static_cast( hashStruct->GetTag( TableSizeTag, 0)))[0] = initialTableSize; if(trace_me) std::cout << "hash_duplicate: nCount= " << nCount << " nEntries= " << nEntries ; SizeT sourceIx = 0; for( SizeT eIx=0; eIx( thisHashTable->GetTag( pKeyTag, sourceIx)))[0]; while( kID == 0) kID = (*static_cast( thisHashTable->GetTag( pKeyTag, ++sourceIx)))[0]; DPtr vID = (*static_cast(thisHashTable->GetTag( pValueTag, sourceIx++)))[0]; BaseGDL* key = BaseGDL::interpreter->GetHeap( kID); assert( key != NULL); BaseGDL* value = BaseGDL::interpreter->GetHeap( vID); if( value != NULL) { if( value->Type() == GDL_OBJ && value->Rank() == 0) { DObj p=(*static_cast( value))[0]; if(p != 0) { DStructGDL* theStruct = GetOBJ( value, 0); DStructDesc* desc = theStruct->Desc(); if( desc->IsParent("HASH")) value = hash_duplicate(theStruct); } } } InsertIntoHashTable( hashStruct, hashTable, key->Dup(), value->Dup()); } newObjGuard.Release(); return newObj; } BaseGDL* HASH___OverloadBracketsRightSide( EnvUDT* e) { GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() static unsigned fold_case_mask = 0x00000001; static unsigned isRangeIx = 1; static unsigned prmbeg = isRangeIx+1; // trace_me = lib::trace_arg(); SizeT nParam = e->NParam(1); if( nParam < 3) ThrowFromInternalUDSub( e, "Two parameters are needed: ISRANGE, SUB1 [, ...]."); DStructGDL* self = GetOBJ( e->GetKW( 0), e); DLongGDL* isRange = static_cast( e->GetKW(isRangeIx)); SizeT nIsRange = isRange->N_Elements(); if(nIsRange == 0) { // sometimes this comes in wrong - fix it. nIsRange = nParam - isRangeIx - 1; for (int i=0; i < nIsRange; i++) (*isRange)[i] = 0; } // isRange is a series of 0 or 1 indicating if a range is present. // more comments in list__]/ if(trace_me) { std::cout << "Hash-OL right:nIsRange " << nIsRange << ",nParam " << nParam << " ,isRange:"; for (int i=0; i < nIsRange; i++) std::cout << " "<<(*isRange)[i]; std::cout << std::endl; } bool isfoldcase = Hashisfoldcase( self); DPtr thisTableID = (*static_cast( self->GetTag( pTableTag, 0)))[0]; DStructGDL* thisHashTable = static_cast(e->Interpreter()->GetHeap( thisTableID)); BaseGDL* parX = e->GetKW( prmbeg); // implicit SELF, ISRANGE, par1..par8 if( parX == NULL) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( prmbeg))); if( (*isRange)[0] == 1) // r = hash[*] { if( parX->N_Elements() != 3) ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW( prmbeg))); MAKE_LONGGDL(parX, parXLong) if( (*parXLong)[0] != 0 || (*parXLong)[1] != -1 || (*parXLong)[2] != 1) ThrowFromInternalUDSub( e, "Subscript range is not allowed: [" + i2s((*parXLong)[0])+":"+i2s((*parXLong)[1])+":"+i2s((*parXLong)[2])+"]"); BaseGDL* cloned = hash_duplicate(self); if(trace_me) std::cout << " cloned " <GetKW( iprm + prmbeg); if( XX->Rank() != 0 ) break; // must be a scalar if( islist) { MAKE_LONGGDL( XX, XXLong) DLong Ixref = (*XXLong)[0]; listSize = (*static_cast(theStruct->GetTag( nListTag, 0)))[0]; if(Ixref >= listSize) // this is certainly common. ThrowFromInternalUDSub( e, "direct access index is too high" + i2s(Ixref) + " >= nList:"+i2s(listSize)); DStructGDL* Node = GetLISTStruct( e, GetLISTNode( e, theStruct, Ixref)); DPtr Ptr = (*static_cast( Node->GetTag( pListDataTag, 0)))[0]; theref = BaseGDL::interpreter->GetHeap( Ptr); if(trace_me) std::cout << " islist iprm="<Type() == GDL_OBJ) { DObj p=(*static_cast( XX))[0]; if(p != 0) { DStructGDL* ListHead = GetOBJ( XX, e); // DStructDesc* desc = ListHead->Desc(); if(ListHead->Desc()->IsParent("LIST")) { theref = hash_subset(hashTable, XX, isfoldcase); if( finalprm ) return theref; if(trace_me) std::cout << " ...[XX...]" ; } else ThrowFromInternalUDSub( e, " -XX- hash key an object not LIST"); } else ThrowFromInternalUDSub( e, " -XX- hash key an invalid object"); } else { DLong hashIndex = HashIndex( hashTable , XX, isfoldcase); if(trace_me) std::cout <<" pData:"<( hashTable->GetTag( pValueTag, hashIndex) ))[0]; theref = BaseGDL::interpreter->GetHeap( pValue); } } else if( isstruct ) { // use XX to access struct by naming the tag, or by its numerical index. int ptagindex = 0; if(XX->Type() != GDL_STRING) { MAKE_LONGGDL( XX, XXLong) ptagindex = (*XXLong)[0]; if(ptagindex >= theStruct->Desc()->NTags() ) ptagindex = -1; } else { DString tag = (*static_cast( XX))[0]; StrUpCaseInplace(tag); ptagindex = theStruct->Desc()->TagIndex(tag); } if(ptagindex < 0) ThrowFromInternalUDSub( e, " struct tag not found "); theref = theStruct->Get( ptagindex); } else { if(trace_me) std::cout << "isstruct || ishash || islist "<< iprm <Type(); if(trace_me) std::cout << " theType="<Rank() == 0) { DPtr p=(*static_cast( theref))[0]; if( p != 0) theref = BaseGDL::interpreter->GetHeap( p); theType = theref->Type(); } // right bracket, we are done if only 3 parameters left (?). if(finalprm) { if(trace_me) help_item(std::cout, theref, " ->Dup():",false); return theref->Dup(); } if(trace_me) help_item(std::cout, theref, " \n theref ",false); // otherwise, another dimension is involved and we need to process again. islist = false; ishash = false; isstruct = false; if(theType == GDL_OBJ && theref->Rank() == 0) { DObj p=(*static_cast( theref))[0]; if(p == 0) break; theStruct = GetOBJ( theref, e); DStructDesc* desc = theStruct->Desc(); islist = desc->IsParent("LIST"); ishash = desc->IsParent("HASH"); isstruct = !(islist or ishash); } else if( theType == GDL_STRUCT and theref->N_Elements() == 1) { theStruct = static_cast( theref); isstruct = true; } iprm++; if( gdl_type_lookup::IsConvertableType[theType] ) break; } // while /* */ if(trace_me) std::cout << " HASH_OL[R]: iprm="<< i2s(iprm); if(trace_me) lib::help_item(std::cout, theref," theref",false); if(!ishash) return list_rightextraction( e, theref, iprm); // rewind to a simpler time ... hashnew=hashold[ keys ] if( nParam > 3) ThrowFromInternalUDSub( e, "Only one dimensional access allowed."); // non-range BaseGDL* index = parX; // one element -> return value if( index->N_Elements() == 1) { DLong hashIndex = HashIndex( thisHashTable, index, isfoldcase); // if( hashIndex < 0) ThrowFromInternalUDSub( e, "Key is not present."); if( hashIndex < 0) return NullGDL::GetSingleInstance(); DPtr vID = (*static_cast(thisHashTable->GetTag( pValueTag, hashIndex)))[0]; BaseGDL* value = e->Interpreter()->GetHeap( vID); if(trace_me) lib::help_item(std::cout, value," value",false); if( value == NULL) return NullGDL::GetSingleInstance(); else return value->Dup(); } else return hash_subset(thisHashTable, index, isfoldcase); } BaseGDL* hash_fun( EnvT* e) { return hash_create( e , false); } BaseGDL* orderedhash_fun( EnvT* e) { BaseGDL* par = hash_create( e , true); static unsigned ordmask = 0x00000010; static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); DObj s = (*static_cast(par))[0]; // is StrictScalar() if( s == 0) e->Throw(" fail ( s == 0) in ordered hash! "); DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s); if( oStructGDL == NULL) e->Throw(" fail ( struct == NULL) in ordered hash! "); DStructDesc* desc = oStructGDL->Desc(); static unsigned TableBitsIx = desc->TagIndex("TABLE_BITS"); (*static_cast(oStructGDL->GetTag( TableBitsIx, 0)))[0] = ordmask; return par; } } // namespace lib static BaseGDL* hash_create( EnvT* e, bool isordered=false) { static int kwNO_COPYIx = e->KeywordIx("NO_COPY"); bool kwNO_COPY = false; if (e->KeywordSet(kwNO_COPYIx)){ kwNO_COPY = true;} static int kwFOLD_CASEIx = e->KeywordIx("FOLD_CASE"); static unsigned fold_case_mask = 0x00000001; static int kwEXTRACTIx = e->KeywordIx("EXTRACT"); // still new trace_me = false; // lib::trace_arg(); SizeT nParam = e->NParam(); ProgNodeP cN = e->CallingNode(); DInterpreter* ip = e->Interpreter(); GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() // because of .RESET_SESSION, we cannot use static here DStructDesc* hashDesc=structDesc::HASH; DStructDesc* entryDesc=structDesc::GDL_HASHTABLEENTRY; assert( hashDesc != NULL && hashDesc->NTags() > 0); assert( entryDesc != NULL && entryDesc->NTags() > 0); bool foldcasekw = e->KeywordSet( kwFOLD_CASEIx); bool extractkw = e->KeywordSet( kwEXTRACTIx); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() BaseGDL* key; SizeT nEntries = 0; if( nParam == 1) { key = e->GetPar( 0); if( key == NULL || key == NullGDL::GetSingleInstance()) e->Throw(" invalid 1st parameter "); if(trace_me) std::cout << " hash(nParam=1) "; if( key->Type() == GDL_STRUCT ) { if(trace_me) std::cout << " . " ; return structP_tohash( e, key, foldcasekw, extractkw, isordered); }// direct return for the case of struct --> hash else if ( key->Type() == GDL_OBJ and key->StrictScalar()) { // GDL extension: put object structure directly into a hash. DStructGDL* oStructGDL= GetOBJ( key, NULL); return struct_tohash( e, oStructGDL, foldcasekw, extractkw, isordered); } else { // key->Type() == GDL_STRUCT || key->Type() == GDL_OBJ // 1-element hash table, value=null); nEntries = key->N_Elements(); if(trace_me) std::cout << " nEntries= " << nEntries; } } // nParam==1 // Count the possible entries, no check for total correctness. for( SizeT eIx=0; eIx < nParam/2; ++eIx) { BaseGDL* key = e->GetPar( 2 * eIx); if( key == NULL || key == NullGDL::GetSingleInstance()) continue; if ( key->Type() == GDL_OBJ and key->StrictScalar()) { DStructGDL* theList = GetOBJ( key, NULL); DStructDesc* desc = theList->Desc(); if(desc->IsParent("LIST")) nEntries += (*static_cast( theList->GetTag( nListTag, 0)))[0]; } else if( key->Type() == GDL_STRUCT ) e->Throw("Only 1 argument is allowed with input of type STRUCT."); else nEntries += key->N_Elements(); } if(trace_me) std::cout << " hash_create: counted nEntries=" << nEntries << std::endl; DStructGDL* hashTable; DLong initialTableSize = GetInitialTableSize( nEntries); // DStructGDL* hashStruct = // create_hashStruct( initialTableSize, hashTable, foldcasekw, isordered); // DObj objID= e->NewObjHeap( 1, hashStruct); // owns hashStruct, sets ref count to 1 DObj objID= new_hashStruct( initialTableSize, hashTable, foldcasekw, isordered); BaseGDL* newObj = new DObjGDL( objID); // the hash object Guard newObjGuard( newObj); DStructGDL* hashStruct = GetOBJ( newObj, 0); if( nParam == 1) { if( key->N_Elements() == 1) { InsertIntoHashTable( hashStruct, hashTable, key, NULL); } else { for( SizeT kIx=0; kIx < nEntries; ++kIx) InsertIntoHashTable( hashStruct, hashTable, key->NewIx(kIx), NULL); } newObjGuard.Release(); return newObj; } for( SizeT eIx=0; eIx < nParam/2; ++eIx) { SizeT keyIx = 2 * eIx; SizeT valueIx = 2 * eIx + 1; BaseGDL* key = e->GetPar( keyIx); bool iskeylist=false; // !NULL keys are not inserted if( key == NULL || key == NullGDL::GetSingleInstance()) continue; // --- (to change) if(trace_me ) { std::cout << i2s(eIx) << " key:"; lib::help_item(std::cout , key, " key for hash", false); } SizeT nKey = key->N_Elements(); DPtr keyNode = 0; DPtr valNode = 0; if ( key->Type() == GDL_OBJ and key->StrictScalar()) { DStructGDL* keyList = GetOBJ( key, NULL); DStructDesc* desc = keyList->Desc(); iskeylist = desc->IsParent("LIST"); if(iskeylist) { nKey = (*static_cast( keyList->GetTag( nListTag, 0)))[0]; keyNode = GetLISTNode(NULL, keyList, 0); } else e->Throw("only objects allowed for keys or values are LISTs"); } else if( key->Type() == GDL_STRUCT ) e->Throw("Only 1 argument is allowed with input of type STRUCT."); BaseGDL* value = e->GetPar( valueIx); SizeT nValue = 1; bool isvallist = false; bool isvalscalar = false; if( value == NULL || value == NullGDL::GetSingleInstance()) isvalscalar = true; else nValue = value->N_Elements(); if ( value->Type() == GDL_OBJ and value->StrictScalar()) { isvalscalar = true; DStructGDL* valList = GetOBJ( value, NULL); DStructDesc* desc = valList->Desc(); isvallist = desc->IsParent("LIST"); if(isvallist) { nValue = (*static_cast( valList->GetTag( nListTag, 0)))[0]; valNode = GetLISTNode(NULL, valList, 0); isvalscalar = false; if(trace_me) std::cout <<"HASH: isvallist=true, nvalue="<StrictScalar else if( value->Type() == GDL_STRUCT ) e->Throw("Only 1 argument is allowed with input of type STRUCT."); else if( value->StrictScalar() ) isvalscalar = true;; if(trace_me) std::cout << " isvalscalar/ iskeylist? nkey:"<< isvalscalar<< iskeylist << nKey << std::endl; if( ( !isvalscalar) && ( nValue != 0 && nKey != 1 && nValue != nKey) ) e->Throw( "Key and Value must have the same number of elements."); // Allowing a list of key and/or a list of values // leaves an ambiguity for the case of a single addition if( nKey == 1) { if(isvallist && nValue == 1) value = GetNodeData(valNode); if(iskeylist) key = GetNodeData(keyNode); if( !kwNO_COPY && value != NULL) value = value->Dup(); InsertIntoHashTable( hashStruct, hashTable, key, value); } else // nkey > 1 { if( isvalscalar) { if(iskeylist) for( SizeT kIx=0; kIxDup()); else for( SizeT kIx=0; kIxNewIx(kIx), value->Dup()); } else { // value not a scalar. if(iskeylist) { if(isvallist) { for( SizeT kIx=0; kIxDup()); } else { for( SizeT kIx=0; kIxNewIx(kIx)); } } else { if(isvallist) { for( SizeT kIx=0; kIxNewIx(kIx), (GetNodeData(valNode))->Dup()); } else { for( SizeT kIx=0; kIxNewIx(kIx), value->NewIx(kIx)); } } } } if( kwNO_COPY) { bool stolen = e->StealLocalPar( valueIx); if( !stolen) e->GetPar(valueIx) = NULL; } } newObjGuard.Release(); return newObj; } gdl-0.9.9/src/hash.hpp000066400000000000000000000040271340051421000145130ustar00rootroot00000000000000/*************************************************************************** hash.hpp - for HASH objects ------------------- begin : July 22 2013 copyright : (C) 2013 by M. Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef HASH_HPP_ #define HASH_HPP_ void HASH__ToStream( DStructGDL* oStructGDL, std::ostream& o, SizeT w, SizeT* actPosPtr); DLong HashIndex( DStructGDL* hashTable, BaseGDL* key); namespace lib { BaseGDL* HASH___OverloadIsTrue( EnvUDT* e); BaseGDL* HASH___OverloadNEOp( EnvUDT* e); BaseGDL* HASH___OverloadEQOp( EnvUDT* e); BaseGDL* HASH___OverloadPlus( EnvUDT* e); BaseGDL* HASH___OverloadBracketsRightSide( EnvUDT* e); void HASH___OverloadBracketsLeftSide( EnvUDT* e); BaseGDL* hash__haskey( EnvUDT* e); BaseGDL* hash__remove_fun( EnvUDT* e); void hash__remove_pro( EnvUDT* e); BaseGDL* hash__values( EnvUDT* e); BaseGDL* hash__keys( EnvUDT* e); BaseGDL* hash__tostruct( EnvUDT* e); BaseGDL* hash__count( EnvUDT* e); SizeT HASH_count( DStructGDL* oStructGDL); BaseGDL* hash__isempty( EnvUDT* e); BaseGDL* hash__isordered( EnvUDT* e); BaseGDL* hash__isfoldcase( EnvUDT* e); BaseGDL* hash__where( EnvUDT* e); BaseGDL* hash_fun( EnvT* e); BaseGDL* orderedhash_fun( EnvT* e); } #endif gdl-0.9.9/src/hdf5_fun.cpp000066400000000000000000000665761340051421000153020ustar00rootroot00000000000000/*************************************************************************** hdf5_fun.cpp - HDF5 GDL library function ------------------- begin : Aug 02 2004 copyright : (C) 2004 by Peter Messmer email : messmer@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // the following stuff needs some cleanup in order to make it nicely fit // into the distribution. #ifdef HAVE_CONFIG_H #include #else // default: assume we have HDF5 #define USE_HDF5 1 #endif #ifdef USE_HDF5 #include "includefirst.hpp" #include "hdf5_fun.hpp" namespace lib { using namespace std; // SA: error-handling-realted helper routines / classes // -------------------------------------------------------------------- // helper routine for hdf5_error_message() herr_t hdf5_error_message_helper(int n, H5E_error_t *err_desc, void *msg) { // getting something better than "Inappropriate type" message #if (H5_VERS_MAJOR < 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR <= 6)) if (err_desc->min_num == H5E_BADTYPE) *static_cast(msg) = H5Eget_major(err_desc->maj_num); else *static_cast(msg) = H5Eget_minor(err_desc->min_num); #else char* tmp; if (err_desc->min_num == H5E_BADTYPE) tmp = H5Eget_major(err_desc->maj_num); else tmp = H5Eget_minor(err_desc->min_num); *static_cast(msg) = tmp; free(tmp); #endif return 0; } // returns a meaningful message describing last HDF5 error // usual usege: // if (H5X_xxx(...) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } string hdf5_error_message(string &msg) { H5Ewalk(H5E_WALK_UPWARD, hdf5_error_message_helper, &msg); return msg; } // auto_ptr-like class for guarding HDF5 spaces // usage: // hid_t h5s_id = H5Dget_space(h5d_id); // if (h5s_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } // hdf5_space_guard h5s_id_guard = hdf5_space_guard(h5s_id); class hdf5_space_guard { hid_t space; public: hdf5_space_guard(hid_t space_) { space = space_; } ~hdf5_space_guard() { H5Sclose(space); } }; // auto_ptr-like class for guarding HDF5 types // usage: // hid_t datatype = H5Dget_type(h5d_id); // if (datatype < 0) { string msg; e->Throw(hdf5_error_message(msg)); } // hdf5_type_guard datatype_guard = hdf5_type_guard(datatype); class hdf5_type_guard { hid_t type; public: hdf5_type_guard(hid_t type_) { type = type_; } ~hdf5_type_guard() { H5Tclose(type); } }; // -------------------------------------------------------------------- DLong mapH5DatatypesToGDL(DLong h5type){ //must be in order, from most complicated to simplest, string at end //not until LDOUBLE Is handled everywhere!! // if (H5Tequal(h5type , H5T_NATIVE_LDOUBLE )) return GDL_LDOUBLE; if (H5Tequal(h5type , H5T_NATIVE_DOUBLE )) return GDL_DOUBLE; if (H5Tequal(h5type , H5T_NATIVE_FLOAT )) return GDL_FLOAT; if (H5Tequal(h5type , H5T_NATIVE_ULLONG )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_ALPHA_U64 )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_INTEL_U64 )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_MIPS_U64 )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_NATIVE_UINT64 )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_NATIVE_UINT_FAST64 )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_NATIVE_UINT_LEAST64 )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_STD_U64BE )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_STD_U64LE )) return GDL_ULONG64; if (H5Tequal(h5type , H5T_NATIVE_LLONG )) return GDL_LONG64; if (H5Tequal(h5type , H5T_IEEE_F64BE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_IEEE_F64LE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_INTEL_B64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_INTEL_F64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_INTEL_I64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_MIPS_B64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_MIPS_F64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_MIPS_I64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_NATIVE_B64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_NATIVE_INT64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_NATIVE_INT_FAST64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_NATIVE_INT_LEAST64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_STD_B64BE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_STD_B64LE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_STD_I64BE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_STD_I64LE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_UNIX_D64BE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_UNIX_D64LE )) return GDL_LONG64; if (H5Tequal(h5type , H5T_ALPHA_B64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_ALPHA_F64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_ALPHA_I64 )) return GDL_LONG64; if (H5Tequal(h5type , H5T_NATIVE_ULONG )) return GDL_ULONG; if (H5Tequal(h5type , H5T_ALPHA_U32 )) return GDL_ULONG; if (H5Tequal(h5type , H5T_INTEL_U32 )) return GDL_ULONG; if (H5Tequal(h5type , H5T_MIPS_U32 )) return GDL_ULONG; if (H5Tequal(h5type , H5T_NATIVE_UINT32 )) return GDL_ULONG; if (H5Tequal(h5type , H5T_NATIVE_UINT_FAST32 )) return GDL_ULONG; if (H5Tequal(h5type , H5T_NATIVE_UINT_LEAST32 )) return GDL_ULONG; if (H5Tequal(h5type , H5T_STD_U32BE )) return GDL_ULONG; if (H5Tequal(h5type , H5T_STD_U32LE )) return GDL_ULONG; if (H5Tequal(h5type , H5T_NATIVE_HBOOL )) return GDL_LONG; if (H5Tequal(h5type , H5T_NATIVE_LONG )) return GDL_LONG; if (H5Tequal(h5type , H5T_ALPHA_B32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_ALPHA_F32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_ALPHA_I32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_IEEE_F32BE )) return GDL_LONG; if (H5Tequal(h5type , H5T_IEEE_F32LE )) return GDL_LONG; if (H5Tequal(h5type , H5T_INTEL_B32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_INTEL_F32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_INTEL_I32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_MIPS_B32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_MIPS_F32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_MIPS_I32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_NATIVE_B32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_NATIVE_INT32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_NATIVE_INT_FAST32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_NATIVE_INT_LEAST32 )) return GDL_LONG; if (H5Tequal(h5type , H5T_STD_B32BE )) return GDL_LONG; if (H5Tequal(h5type , H5T_STD_B32LE )) return GDL_LONG; if (H5Tequal(h5type , H5T_STD_I32BE )) return GDL_LONG; if (H5Tequal(h5type , H5T_STD_I32LE )) return GDL_LONG; if (H5Tequal(h5type , H5T_UNIX_D32BE )) return GDL_LONG; if (H5Tequal(h5type , H5T_UNIX_D32LE )) return GDL_LONG; if (H5Tequal(h5type , H5T_NATIVE_UINT )) return GDL_UINT; if (H5Tequal(h5type , H5T_NATIVE_UINT16 )) return GDL_UINT; if (H5Tequal(h5type , H5T_NATIVE_UINT_FAST16 )) return GDL_UINT; if (H5Tequal(h5type , H5T_NATIVE_UINT_LEAST16 )) return GDL_UINT; if (H5Tequal(h5type , H5T_STD_U16BE )) return GDL_UINT; if (H5Tequal(h5type , H5T_STD_U16LE )) return GDL_UINT; if (H5Tequal(h5type , H5T_ALPHA_U16 )) return GDL_UINT; if (H5Tequal(h5type , H5T_INTEL_U16 )) return GDL_UINT; if (H5Tequal(h5type , H5T_MIPS_U16 )) return GDL_UINT; if (H5Tequal(h5type , H5T_NATIVE_INT )) return GDL_INT; if (H5Tequal(h5type , H5T_NATIVE_INT16 )) return GDL_INT; if (H5Tequal(h5type , H5T_NATIVE_INT_FAST16 )) return GDL_INT; if (H5Tequal(h5type , H5T_NATIVE_INT_LEAST16 )) return GDL_INT; if (H5Tequal(h5type , H5T_STD_B16BE )) return GDL_INT; if (H5Tequal(h5type , H5T_STD_B16LE )) return GDL_INT; if (H5Tequal(h5type , H5T_STD_I16BE )) return GDL_INT; if (H5Tequal(h5type , H5T_STD_I16LE )) return GDL_INT; if (H5Tequal(h5type , H5T_ALPHA_B16 )) return GDL_INT; if (H5Tequal(h5type , H5T_ALPHA_I16 )) return GDL_INT; if (H5Tequal(h5type , H5T_INTEL_B16 )) return GDL_INT; if (H5Tequal(h5type , H5T_INTEL_I16 )) return GDL_INT; if (H5Tequal(h5type , H5T_MIPS_B16 )) return GDL_INT; if (H5Tequal(h5type , H5T_MIPS_I16 )) return GDL_INT; if (H5Tequal(h5type , H5T_NATIVE_B16 )) return GDL_INT; if (H5Tequal(h5type , H5T_ALPHA_U8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_MIPS_U8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_INTEL_U8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_UINT8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_UINT_FAST8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_UINT_LEAST8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_STD_U8BE )) return GDL_BYTE; if (H5Tequal(h5type , H5T_STD_U8LE )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_USHORT )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_INT8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_ALPHA_B8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_ALPHA_I8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_INTEL_B8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_INTEL_I8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_MIPS_I8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_B8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_INT_FAST8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_INT_LEAST8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_NATIVE_SHORT )) return GDL_BYTE; if (H5Tequal(h5type , H5T_MIPS_B8 )) return GDL_BYTE; if (H5Tequal(h5type , H5T_STD_B8BE )) return GDL_BYTE; if (H5Tequal(h5type , H5T_STD_B8LE )) return GDL_BYTE; if (H5Tequal(h5type , H5T_STD_I8BE )) return GDL_BYTE; if (H5Tequal(h5type , H5T_STD_I8LE )) return GDL_BYTE; if (H5Tequal(h5type , H5T_C_S1 )) return GDL_STRING; if (H5Tequal(h5type , H5T_FORTRAN_S1 )) return GDL_STRING; if (H5Tequal(h5type , H5T_STRING )) return GDL_STRING; if (H5Tequal(h5type , H5T_NATIVE_CHAR )) return GDL_STRING; if (H5Tequal(h5type , H5T_NATIVE_SCHAR )) return GDL_STRING; if (H5Tequal(h5type , H5T_NATIVE_UCHAR )) return GDL_STRING; return GDL_UNDEF; } BaseGDL* h5_get_libversion_fun( EnvT* e) { unsigned int majnum, minnum, relnum; if (H5get_libversion(&majnum, &minnum, &relnum) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DStringGDL(i2s(majnum) + "." + i2s(minnum) + "." + i2s(relnum)); } BaseGDL* h5f_is_hdf5_fun( EnvT* e) { DString h5fFilename; e->AssureScalarPar( 0, h5fFilename); WordExp( h5fFilename); htri_t code; code = H5Fis_hdf5(h5fFilename.c_str()); if (code <= 0) return new DLongGDL(0); else return new DLongGDL(1); } BaseGDL* h5f_create_fun( EnvT* e) { DLong h5f_id; DString h5fFilename; e->AssureScalarPar( 0, h5fFilename); WordExp( h5fFilename); h5f_id = H5Fcreate( h5fFilename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); // h5f_id = H5Fopen(h5fFilename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); if (h5f_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5f_id ); } BaseGDL* h5f_open_fun( EnvT* e) { DLong h5f_id; DString h5fFilename; e->AssureScalarPar( 0, h5fFilename); WordExp( h5fFilename); h5f_id = H5Fopen(h5fFilename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); if (h5f_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5f_id ); } BaseGDL* h5g_open_fun( EnvT* e) { SizeT nParam=e->NParam(2); DLong h5f_id; e->AssureLongScalarPar(0, h5f_id); DString h5gGroupname; e->AssureScalarPar( 1, h5gGroupname); DLong h5g_id; h5g_id = H5Gopen(h5f_id, h5gGroupname.c_str()); if (h5g_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5g_id ); } BaseGDL* h5d_open_fun( EnvT* e) { SizeT nParam=e->NParam(2); DLong h5f_id; e->AssureLongScalarPar(0, h5f_id); DString h5dDatasetname; e->AssureScalarPar( 1, h5dDatasetname); DLong h5d_id; h5d_id = H5Dopen(h5f_id, h5dDatasetname.c_str()); if (h5d_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5d_id ); } BaseGDL* h5a_open_idx_fun( EnvT* e) { SizeT nParam=e->NParam(2); DLong h5f_id, attr_idx; e->AssureLongScalarPar(0, h5f_id); e->AssureLongScalarPar(1, attr_idx); DLong h5a_id; h5a_id = H5Aopen_idx(h5f_id, attr_idx); if (h5a_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5a_id ); } BaseGDL* h5a_get_name_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5a_id; e->AssureLongScalarPar(0, h5a_id); // querying for the length of the name char tmp; ssize_t len = H5Aget_name(h5a_id, 1, &tmp); if (len < 0) { string msg; e->Throw(hdf5_error_message(msg)); } // acquiring the name len++; char* name = static_cast(malloc(len * sizeof(char))); if (name == NULL) e->Throw("Failed to allocate memory!"); if (H5Aget_name(h5a_id, len, name) < 0) { free(name); { string msg; e->Throw(hdf5_error_message(msg)); } return NULL; } DStringGDL* ret = new DStringGDL(name); free(name); return ret; } BaseGDL* h5a_get_type_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5a_id; e->AssureLongScalarPar(0, h5a_id); DLong h5a_type_id; h5a_type_id = H5Aget_type( h5a_id ); if (h5a_type_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5a_type_id ); } BaseGDL* h5a_open_name_fun( EnvT* e) { SizeT nParam=e->NParam(2); DLong h5f_id; e->AssureLongScalarPar(0, h5f_id); DString h5aAttrname; e->AssureScalarPar( 1, h5aAttrname); DLong h5a_id; h5a_id = H5Aopen_name(h5f_id, h5aAttrname.c_str()); if (h5a_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5a_id ); } BaseGDL* h5d_get_space_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5d_id; e->AssureLongScalarPar(0, h5d_id); DLong h5d_space_id; h5d_space_id = H5Dget_space( h5d_id ); if (h5d_space_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5d_space_id ); } BaseGDL* h5a_get_space_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5a_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5a_id); #else e->AssureLongScalarPar(0, h5a_id); #endif DLong h5a_space_id; h5a_space_id = H5Aget_space( h5a_id ); if (h5a_space_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5a_space_id ); } BaseGDL* h5a_get_num_attrs_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong loc_id; e->AssureLongScalarPar(0, loc_id); int num = H5Aget_num_attrs( loc_id ); if (num < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( num ); } BaseGDL* h5d_get_type_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5d_id; e->AssureLongScalarPar(0, h5d_id); DLong h5d_type_id; h5d_type_id = H5Dget_type( h5d_id ); if (h5d_type_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( h5d_type_id ); } BaseGDL* h5t_get_size_fun( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5t_id; e->AssureLongScalarPar(0, h5t_id); size_t size = H5Tget_size( h5t_id ); if (size == 0) { string msg; e->Throw(hdf5_error_message(msg)); } return new DLongGDL( size ); } BaseGDL* h5s_get_simple_extent_dims_fun( EnvT* e) { SizeT nParam=e->NParam(1); hsize_t dims_out[MAXRANK]; DLong h5s_id; e->AssureLongScalarPar(0, h5s_id); int rank = H5Sget_simple_extent_ndims(h5s_id); if (rank < 0) { string msg; e->Throw(hdf5_error_message(msg)); } if (H5Sget_simple_extent_dims(h5s_id, dims_out, NULL) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } dimension dim(rank); DLongGDL* d = new DLongGDL(dim); for(int i=0; iNParam(1); hsize_t dims_out[MAXRANK]; hid_t h5a_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5a_id); #else e->AssureLongScalarPar(0, h5a_id); #endif hid_t h5s_id = H5Aget_space(h5a_id); if (h5s_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } hdf5_space_guard h5s_id_guard = hdf5_space_guard(h5s_id); hid_t datatype = H5Aget_type(h5a_id); if (datatype < 0) { string msg; e->Throw(hdf5_error_message(msg)); } hdf5_type_guard datatype_guard = hdf5_type_guard(datatype); // determine the rank and dimension of the dataset int rank = H5Sget_simple_extent_ndims(h5s_id); if (rank < 0) { string msg; e->Throw(hdf5_error_message(msg)); } if (H5Sget_simple_extent_dims(h5s_id, dims_out, NULL) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } // need to reverse indices for column major format SizeT count_s[MAXRANK]; for(int i=0; iThrow(hdf5_error_message(msg)); } for (int i = 0; i < count_s[0]; i++) (*(static_cast (res)))[i] = rdata[i]; free (rdata); //but not rdata[0] status = H5Tclose (filetype); status = H5Tclose (memtype); return res; } else { e->Throw("Unsupported data format" + i2s(datatype)); } if (H5Aread(h5a_id, type, res->DataAddr()) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return res; return new DIntGDL(-1); } /** * h5d_read_fun * CAUTION: compatibility only fractional * - Does not allow to select hyperslabs */ BaseGDL* h5d_read_fun(EnvT* e) { SizeT nParam = e->NParam(1); hsize_t dims_out[MAXRANK]; hid_t h5d_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5d_id); #else e->AssureLongScalarPar(0, h5d_id); #endif hid_t h5s_id = H5Dget_space(h5d_id); if (h5s_id < 0) { string msg; e->Throw(hdf5_error_message(msg)); } hdf5_space_guard h5s_id_guard = hdf5_space_guard(h5s_id); hid_t datatype = H5Dget_type(h5d_id); if (datatype < 0) { string msg; e->Throw(hdf5_error_message(msg)); } hdf5_type_guard datatype_guard = hdf5_type_guard(datatype); // determine the rank and dimension of the dataset int rank = H5Sget_simple_extent_ndims(h5s_id); if (rank < 0) { string msg; e->Throw(hdf5_error_message(msg)); } if (H5Sget_simple_extent_dims(h5s_id, dims_out, NULL) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } // define hyperslab in dataset #if (H5_VERS_MAJOR < 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR < 6)) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR == 6) && (H5_VERS_RELEASE <= 3)) hssize_t offset[MAXRANK]; #else hsize_t offset[MAXRANK]; #endif hsize_t count[MAXRANK]; for (int i = 0; i < rank; i++) offset[i] = 0; for (int i = 0; i < rank; i++) count[i] = dims_out[i]; if (H5Sselect_hyperslab(h5s_id, H5S_SELECT_SET, offset, NULL, count, NULL) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } // define memory dataspace hid_t memspace = H5Screate_simple(rank, count, NULL); if (memspace < 0) { string msg; e->Throw(hdf5_error_message(msg)); } hdf5_space_guard memspace_guard = hdf5_space_guard(memspace); // define memory hyperslab #if (H5_VERS_MAJOR < 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR < 6)) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR == 6) && (H5_VERS_RELEASE <= 3)) hssize_t offset_out[MAXRANK]; #else hsize_t offset_out[MAXRANK]; #endif hsize_t count_out[MAXRANK]; for (int i = 0; i < rank; i++) offset_out[i] = 0; for (int i = 0; i < rank; i++) count_out[i] = dims_out[i]; if (H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL, count_out, NULL) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } SizeT count_s[MAXRANK]; SizeT rank_s; rank_s = (SizeT) rank; // need to reverse indices for column major format for (int i = 0; i < rank; i++) count_s[i] = (SizeT) count_out[rank - 1 - i ]; // create the IDL datatypes dimension dim(count_s, rank_s); //std::cout << dim << std::endl; BaseGDL *res; DLong ourType = mapH5DatatypesToGDL(datatype); hsize_t type; if (ourType == GDL_BYTE) { res = new DByteGDL(dim); type = H5T_NATIVE_UINT8; } else if (ourType == GDL_INT) { res = new DIntGDL(dim); type = H5T_NATIVE_INT16; } else if (ourType == GDL_UINT) { res = new DUIntGDL(dim); type = H5T_NATIVE_UINT16; } else if (ourType == GDL_LONG) { res = new DLongGDL(dim); type = H5T_NATIVE_INT32; } else if (ourType == GDL_ULONG) { res = new DULongGDL(dim); type = H5T_NATIVE_UINT32; } else if (ourType == GDL_LONG64) { res = new DLong64GDL(dim); type = H5T_NATIVE_INT64; } else if (ourType == GDL_LONG64) { res = new DULong64GDL(dim); type = H5T_NATIVE_UINT64; } else if (ourType == GDL_FLOAT) { res = new DFloatGDL(dim); type = H5T_NATIVE_FLOAT; } else if (ourType == GDL_DOUBLE) { res = new DDoubleGDL(dim); type = H5T_NATIVE_DOUBLE; } else if (ourType == GDL_STRING) { // a bit special, lets follow the example on h5 site: res = new DStringGDL(dim); type = H5T_C_S1; hid_t filetype = H5Dget_type(h5d_id); SizeT sdim = H5Tget_size(filetype); sdim++; /* Make room for null terminator */ char **rdata; /* * Allocate array of pointers to rows. */ rdata = (char **) malloc(count_s[0] * sizeof (char *)); /* * Allocate space for integer data. */ rdata[0] = (char *) malloc(count_s[0] * sdim * sizeof (char)); /* * Set the rest of the pointers to rows to the correct addresses. */ for (int i = 1; i < count_s[0]; i++) rdata[i] = rdata[0] + i * sdim; /* * Create the memory datatype. */ hid_t memtype = H5Tcopy(H5T_C_S1); hid_t status = H5Tset_size(memtype, sdim); status = H5Dread(h5d_id, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata[0]); if (status < 0) { string msg; e->Throw(hdf5_error_message(msg)); } for (int i = 0; i < count_s[0]; i++) (*(static_cast (res)))[i] = rdata[i]; free (rdata); //but not rdata[0] status = H5Tclose (filetype); status = H5Tclose (memtype); return res; } else { e->Throw("Unsupported data format" + i2s(datatype)); } if (H5Dread(h5d_id, type, memspace, h5s_id, H5P_DEFAULT, res->DataAddr()) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } return res; } void h5s_close_pro( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5s_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5s_id); #else e->AssureLongScalarPar(0, h5s_id); #endif if (H5Sclose(h5s_id) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } } void h5d_close_pro( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5d_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5d_id); #else e->AssureLongScalarPar(0, h5d_id); #endif if (H5Dclose(h5d_id) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } } void h5f_close_pro( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5f_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5f_id); #else e->AssureLongScalarPar(0, h5f_id); #endif if (H5Fclose(h5f_id) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } } void h5t_close_pro( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5t_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5t_id); #else e->AssureLongScalarPar(0, h5t_id); #endif if (H5Tclose(h5t_id) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } } void h5g_close_pro( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5g_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5g_id); #else e->AssureLongScalarPar(0, h5g_id); #endif if (H5Gclose(h5g_id) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } } void h5a_close_pro( EnvT* e) { SizeT nParam=e->NParam(1); DLong h5a_id; #if (H5_VERS_MAJOR>1)||((H5_VERS_MAJOR==1)&&(H5_VERS_MINOR>=10)) e->AssureLongScalarPar(0, (DLong64&)h5a_id); #else e->AssureLongScalarPar(0, h5a_id); #endif if (H5Aclose(h5a_id) < 0) { string msg; e->Throw(hdf5_error_message(msg)); } } } // namespace #endif gdl-0.9.9/src/hdf5_fun.hpp000066400000000000000000000045061340051421000152700ustar00rootroot00000000000000/*************************************************************************** hdf5_fun.hpp - HDF5 GDL library function ------------------- begin : Aug 02 2004 copyright : (C) 2004 by Peter Messmer email : messmer@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef HDF5_FUN_HPP_ #define HDF5_FUN_HPP_ #include "datatypes.hpp" #include "envt.hpp" /** * needs the hdf5 library, obtainable from http://hdf.ncsa.uiuc.edu/HDF5/ */ #define H5_USE_16_API 1 #include "hdf5.h" namespace lib { /** * wrapper routines for hdf5 function calls. Only minimal set currently * implemented in order to get things going. The rest is bare-bones work */ BaseGDL* h5f_create_fun( EnvT* e); BaseGDL* h5f_open_fun( EnvT* e); BaseGDL* h5d_open_fun( EnvT* e); BaseGDL* h5d_read_fun( EnvT* e); BaseGDL* h5d_get_space_fun( EnvT* e); BaseGDL* h5s_get_simple_extent_dims_fun( EnvT* e); void h5f_close_pro( EnvT* e); void h5d_close_pro( EnvT* e); void h5s_close_pro( EnvT* e); // SA: BaseGDL* h5f_is_hdf5_fun( EnvT* e); BaseGDL* h5_get_libversion_fun( EnvT* e); BaseGDL* h5d_get_type_fun( EnvT* e); BaseGDL* h5t_get_size_fun( EnvT* e); BaseGDL* h5a_open_name_fun( EnvT* e); BaseGDL* h5a_open_idx_fun( EnvT* e); BaseGDL* h5a_get_name_fun( EnvT* e); BaseGDL* h5a_get_space_fun( EnvT* e); BaseGDL* h5a_get_type_fun( EnvT* e); BaseGDL* h5a_get_num_attrs_fun( EnvT* e); BaseGDL* h5a_read_fun( EnvT* e); BaseGDL* h5g_open_fun( EnvT* e); void h5a_close_pro( EnvT* e ); void h5t_close_pro( EnvT* e ); void h5g_close_pro( EnvT* e ); } // namespace #endif gdl-0.9.9/src/hdf_fun.cpp000066400000000000000000000271321340051421000151760ustar00rootroot00000000000000/*************************************************************************** hdf_fun.cpp - HDF4 GDL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have HDF #define USE_HDF 1 #endif #ifdef USE_HDF #include "includefirst.hpp" #include "mfhdf.h" #include "hdf_fun.hpp" namespace lib { using namespace std; BaseGDL* hdf_open_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; DString hdfFilename; e->AssureScalarPar( 0, hdfFilename); WordExp( hdfFilename); static int allIx = e->KeywordIx("ALL"); static int createIx = e->KeywordIx("CREATE"); static int num_ddIx = e->KeywordIx("NUM_DD"); static int rdwrIx = e->KeywordIx("RDWR"); static int readIx = e->KeywordIx("READ"); static int writeIx = e->KeywordIx("WRITE"); intn access; if (e->KeywordSet(createIx) || e->KeywordSet(allIx)) access = DFACC_CREATE; else if (e->KeywordSet(writeIx) || e->KeywordSet(rdwrIx)) access = DFACC_RDWR; else access = DFACC_RDONLY; DLong n_adds = DEF_NDDS; e->AssureLongScalarKWIfPresent(num_ddIx, n_adds); hdf_id = Hopen(hdfFilename.c_str(), access, n_adds); Vstart(hdf_id); return new DLongGDL( hdf_id ); } BaseGDL* hdf_ishdf( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; DString hdfFilename; e->AssureScalarPar( 0, hdfFilename); WordExp( hdfFilename); intn access = DFACC_RDONLY; hdf_id = Hopen(hdfFilename.c_str(), access, 0); if (hdf_id==-1) return new DLongGDL(0); else return new DLongGDL( 1 ); } BaseGDL* hdf_vg_getid_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; e->AssureLongScalarPar( 0, hdf_id); DLong vg_ref; e->AssureLongScalarPar( 1, vg_ref); return new DLongGDL( Vgetid(hdf_id, vg_ref) ); } BaseGDL* hdf_vg_attach_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; e->AssureScalarPar( 0, hdf_id); DLong vg_ref; e->AssureScalarPar( 1, vg_ref); static int readIx=e->KeywordIx("READ"); static int writeIx=e->KeywordIx("WRITE"); if (e->KeywordSet( readIx )) return new DLongGDL( Vattach(hdf_id, vg_ref, "r")); return new DLongGDL( Vattach(hdf_id, vg_ref, "w")); //other cases. } BaseGDL* hdf_vd_attach_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; e->AssureScalarPar( 0, hdf_id); DLong vd_ref; e->AssureScalarPar( 1, vd_ref); static int readIx=e->KeywordIx("READ"); static int writeIx=e->KeywordIx("WRITE"); if (e->KeywordSet( writeIx ) || vd_ref == -1) return new DLongGDL( VSattach(hdf_id, vd_ref, "w")); if (e->KeywordSet(readIx )) return new DLongGDL( VSattach(hdf_id, vd_ref, "r")); return new DLongGDL( VSattach(hdf_id, vd_ref, "r")); } BaseGDL* hdf_vd_find_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; e->AssureScalarPar( 0, hdf_id); DString vdataname; e->AssureScalarPar( 1, vdataname); return new DLongGDL( VSfind(hdf_id, vdataname.c_str())); } template< typename T> void hdf_vd_read_template( EnvT* e, dimension dim, int32 vd_id, int32 *nRecs, int32 interlace) { int32 nread; T* data = new T( dim, BaseGDL::NOZERO); BaseGDL** p1 = &e->GetPar( 1); *p1 = data; nread = VSread(vd_id, (uint8 *) &(*data)[0], *nRecs, interlace); *nRecs = nread; } BaseGDL* hdf_vd_read_fun( EnvT* e) { SizeT nParam=e->NParam(); char *fields; char buffer[FIELDNAMELENMAX+2+1]; DLong dims[2]; DLong rank; DLong vd_id; e->AssureScalarPar( 0, vd_id); fields = (char *) malloc(VFnfields(vd_id)*(FIELDNAMELENMAX+1)+2); fields[0] = ','; DLong nRecs; DLong interlace_mode; DLong vdata_size; VSinquire(vd_id, (int32 *) &nRecs, (int32 *) &interlace_mode, &fields[1], (int32 *) &vdata_size, NULL); if(e->KeywordSet(0)) { DString Fields; e->AssureScalarKW< DStringGDL>( 0, Fields); strcpy(&fields[1], Fields.c_str()); } VSsetfields(vd_id, &fields[1]); DLong recsize; recsize = (int32) VSsizeof(vd_id, &fields[1]); // Determine active fields in read strcat(fields, ","); DByte fieldindex[VSFIELDMAX]; DLong nFlds = 0; for( SizeT i=0; iKeywordSet(1)) { e->AssureScalarKW< DLongGDL>( 1, nRecs); } // Determine type of first field to read DLong type; DByte diffType = 0; for( SizeT i=0; i( e, dim, vd_id, (int32 *) &nRecs, interlace_mode); } else if (type == DFNT_FLOAT64) { hdf_vd_read_template< DDoubleGDL>( e, dim, vd_id, (int32 *) &nRecs, interlace_mode); } else if (type == DFNT_FLOAT32) { hdf_vd_read_template< DFloatGDL>( e, dim, vd_id, (int32 *) &nRecs, interlace_mode); } else if (type == DFNT_INT32) { hdf_vd_read_template< DLongGDL>( e, dim, vd_id, (int32 *) &nRecs, interlace_mode); // int32 nread; //DLongGDL* data = new DLongGDL( dim, BaseGDL::NOZERO); //BaseGDL** p1 = &e->GetPar( 1); //*p1 = data; // nread = VSread(vd_id, (uint8 *) &(*data)[0], nRecs, interlace_mode); } else if (type == DFNT_INT16) { hdf_vd_read_template< DIntGDL>( e, dim, vd_id, (int32 *) &nRecs, interlace_mode); } free(fields); /* field_order = VFfieldorder(vdata_id, field_index); field_type = VFfieldtype(vdata_id, field_index); */ return new DLongGDL( nRecs ); } BaseGDL* hdf_sd_start_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong sd_id; DString hdfFilename; e->AssureScalarPar( 0, hdfFilename); WordExp( hdfFilename); static int createIx = e->KeywordIx("CREATE"); static int rdwrIx = e->KeywordIx("RDWR"); intn access = DFACC_RDONLY; if (e->KeywordSet(rdwrIx)) access = DFACC_RDWR; else if (e->KeywordSet(createIx)) access = DFACC_CREATE; sd_id = SDstart(hdfFilename.c_str(), access); return new DLongGDL( sd_id ); } BaseGDL* hdf_sd_create_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong sd_id; e->AssureScalarPar( 0, sd_id); DString sdsname; e->AssureScalarPar( 1, sdsname); BaseGDL* p2 = e->GetPar( 2); SizeT ndim = p2->N_Elements(); DLongGDL* dims = static_cast (p2->Convert2( GDL_LONG, BaseGDL::COPY)); static int hdftypeIx=e->KeywordIx("HDF_TYPE"); DLong hdfType=0; e->AssureLongScalarKWIfPresent( hdftypeIx , hdfType); DLong sds_id; // GDL_BYTE if (e->KeywordSet(0) || e->KeywordSet(1) || e->KeywordSet(2) || hdfType == DFNT_INT8 || hdfType == DFNT_UINT8) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_UINT8, ndim, (int32 *) &(*dims)[0]); //GDL_INT } else if (e->KeywordSet(3) || e->KeywordSet(4) || e->KeywordSet(5) || hdfType == DFNT_INT16) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_INT16, ndim, (int32 *) &(*dims)[0]); // GDL_UINT } else if (e->KeywordSet(6) || hdfType == DFNT_UINT16) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_UINT16, ndim, (int32 *) &(*dims)[0]); // GDL_LONG } else if (e->KeywordSet(7) || e->KeywordSet(8) || hdfType == DFNT_INT32) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_INT32, ndim, (int32 *) &(*dims)[0]); // GDL_ULONG } else if (e->KeywordSet(9) || hdfType == DFNT_UINT32) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_UINT32, ndim, (int32 *) &(*dims)[0]); // GDL_FLOAT } else if (e->KeywordSet(10) || hdfType == DFNT_FLOAT32) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_FLOAT32, ndim, (int32 *) &(*dims)[0]); // GDL_DOUBLE } else if (e->KeywordSet(11) || hdfType == DFNT_FLOAT64) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_FLOAT64, ndim, (int32 *) &(*dims)[0]); // GDL_STRING } else if (e->KeywordSet(12) || e->KeywordSet(13) || hdfType == DFNT_CHAR) { sds_id = SDcreate(sd_id, sdsname.c_str(), DFNT_CHAR, ndim, (int32 *) &(*dims)[0]); } return new DLongGDL( sds_id ); } BaseGDL* hdf_sd_nametoindex_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong sd_id; e->AssureLongScalarPar( 0, sd_id); DString sdsName; e->AssureScalarPar( 1, sdsName); DLong index = SDnametoindex(sd_id, sdsName.c_str()); return new DLongGDL( index ); } BaseGDL* hdf_sd_select_fun( EnvT* e) { SizeT nParam=e->NParam(); DLong sd_id; e->AssureScalarPar( 0, sd_id); DLong index; // SA: this makes it accept the argument both as a short and as a long integer (as IDL does) //e->AssureScalarPar( 1, index); e->AssureLongScalarPar(1, index); return new DLongGDL( SDselect(sd_id, index) ); } BaseGDL* hdf_sd_dimgetid_fun( EnvT* e) { DLong sds_id, dim_index, dim_id; int32 rank, status; e->AssureScalarPar( 0, sds_id); e->AssureLongScalarPar(1, dim_index); { char fieldname[256]; int32 null[MAXRANK]; status = SDgetinfo(sds_id, fieldname, &rank, null, null, null); } if (status != 0) e->Throw("Invalid SD dataset ID: " + i2s(sds_id)); // using reverse indices to reflect IDL behaviour dim_id = SDgetdimid(sds_id, rank - 1 - dim_index); if (dim_id == -1) e->Throw("Invalid dimension index: " + i2s(dim_index) + " (valid indices range from 0 to " + i2s(rank) + ")"); return new DLongGDL(dim_id); } BaseGDL* hdf_sd_attrfind_fun( EnvT* e) { DLong s_id; e->AssureLongScalarPar( 0, s_id); DString attrName; e->AssureScalarPar( 1, attrName); DLong index = SDfindattr(s_id, attrName.c_str()); return new DLongGDL( index ); } } // namespace #endif gdl-0.9.9/src/hdf_fun.hpp000066400000000000000000000032121340051421000151740ustar00rootroot00000000000000/*************************************************************************** hdf_fun.hpp - HDF4 GDL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef HDF_FUN_HPP_ #define HDF_FUN_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* hdf_ishdf( EnvT* e); BaseGDL* hdf_sd_create_fun( EnvT* e); BaseGDL* hdf_sd_start_fun( EnvT* e); BaseGDL* hdf_sd_nametoindex_fun( EnvT* e); BaseGDL* hdf_sd_attrfind_fun( EnvT* e); BaseGDL* hdf_sd_select_fun( EnvT* e); BaseGDL* hdf_sd_dimgetid_fun( EnvT* e); BaseGDL* hdf_open_fun( EnvT* e); BaseGDL* hdf_vg_getid_fun( EnvT* e); BaseGDL* hdf_vg_attach_fun( EnvT* e); BaseGDL* hdf_vd_attach_fun( EnvT* e); BaseGDL* hdf_vd_find_fun( EnvT* e); BaseGDL* hdf_vd_read_fun( EnvT* e); } // namespace #endif gdl-0.9.9/src/hdf_pro.cpp000066400000000000000000000422101340051421000152000ustar00rootroot00000000000000/*************************************************************************** hdf_pro.cpp - HDF4 GDL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have HDF #define USE_HDF 1 #endif #ifdef USE_HDF #include "includefirst.hpp" #include "mfhdf.h" #include "hdf_pro.hpp" namespace lib { using namespace std; template< typename T> void hdf_sd_getdata_template( EnvT* e, dimension dim, int32 sds_id, int32 start[], int32 edges[], int32 stride[], DLongGDL* strideKW) { T* data = new T( dim, BaseGDL::NOZERO); if (strideKW == NULL) SDreaddata(sds_id, start, NULL, edges, data->DataAddr()); else SDreaddata(sds_id, start, stride, edges, data->DataAddr()); BaseGDL** p1 = &e->GetPar( 1); *p1 = data; } void hdf_sd_getdata_pro( EnvT* e) { SizeT nParam=e->NParam(2); char fieldname[256]; int32 rank; int32 dims[MAXRANK]; int32 start[MAXRANK]; int32 edges[MAXRANK]; int32 stride[MAXRANK]; int32 dtype; int32 nattrs; int32 status; DLong sds_id; e->AssureScalarPar( 0, sds_id); DLongGDL* startKW = e->IfDefGetKWAs( 0); DLongGDL* strideKW = e->IfDefGetKWAs( 1); DLongGDL* countKW = e->IfDefGetKWAs( 2); status = SDgetinfo(sds_id, fieldname, &rank, dims, &dtype, &nattrs); if (status == FAIL) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Invalid SD dataset ID: " + i2s(sds_id)); for( SizeT i = 0; i < rank; i++) { start[i] = 0; stride[i] = 1; edges[i] = dims[i]; } if (startKW != NULL) { if (startKW->N_Elements() != rank) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Incorrect number of START dimensions:" +i2s(startKW->N_Elements())); memcpy(start, &(*startKW)[0], rank*sizeof(int32)); // Switch to C-ordering for( SizeT i = 0; i < rank/2; i++) { int32 temp = start[i]; start[i] = start[rank-1]; start[rank-1] = temp; } } if (countKW != NULL) { if (countKW->N_Elements() != rank) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Incorrect number of COUNT dimensions:" +i2s(countKW->N_Elements())); memcpy(edges, &(*countKW)[0], rank*sizeof(int32)); // Switch to C-ordering for( SizeT i = 0; i < rank/2; i++) { int32 temp = edges[i]; edges[i] = edges[rank-1]; edges[rank-1] = temp; } } if (strideKW != NULL) { if (strideKW->N_Elements() != rank) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Incorrect number of STRIDE dimensions:" +i2s(strideKW->N_Elements())); memcpy(stride, &(*strideKW)[0], rank*sizeof(int32)); // Switch to C-ordering for( SizeT i = 0; i < rank/2; i++) { int32 temp = stride[i]; stride[i] = stride[rank-1]; stride[rank-1] = temp; } } // Reverse order of edges for setting up GDL array( for( SizeT i = 0; i < rank/2; i++) { int32 tempedge = edges[i]; edges[i] = edges[rank-1]; edges[rank-1] = tempedge; } dimension dim((DLong *) edges, rank); // Return to original edge values for HDF read for( SizeT i = 0; i < rank/2; i++) { int32 tempedge = edges[i]; edges[i] = edges[rank-1]; edges[rank-1] = tempedge; } switch ( dtype) { case DFNT_FLOAT64: { hdf_sd_getdata_template< DDoubleGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } case DFNT_FLOAT32: { hdf_sd_getdata_template< DFloatGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } case DFNT_UINT32: { hdf_sd_getdata_template< DULongGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } case DFNT_INT32: { hdf_sd_getdata_template< DLongGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } case DFNT_UINT16: { hdf_sd_getdata_template< DUIntGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } case DFNT_INT16: { hdf_sd_getdata_template< DIntGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } case DFNT_UINT8: case DFNT_INT8: { hdf_sd_getdata_template< DByteGDL>( e, dim, sds_id, start, edges, stride, strideKW); break; } } } void hdf_sd_adddata_pro( EnvT* e) { SizeT nParam=e->NParam(); char fieldname[256]; int32 rank; int32 dims[MAXRANK]; int32 start[MAXRANK]; int32 edges[MAXRANK]; int32 stride[MAXRANK]; int32 dtype; int32 nattrs; int32 status; DLong sds_idAsDLong; e->AssureScalarPar( 0, sds_idAsDLong); int32 sds_id = sds_idAsDLong; DLongGDL* startKW = e->IfDefGetKWAs( 0); DLongGDL* strideKW = e->IfDefGetKWAs( 1); DLongGDL* countKW = e->IfDefGetKWAs( 2); status = SDgetinfo(sds_id, fieldname, &rank, dims, &dtype, &nattrs); if (status == FAIL) throw GDLException( e->CallingNode(), "HDF_SD_ADDDATA: Invalid SD dataset ID: " + i2s(sds_id)); for( SizeT i = 0; i < rank; i++) { start[i] = 0; stride[i] = 1; edges[i] = dims[i]; } if (startKW != NULL) { if (startKW->N_Elements() != rank) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Incorrect number of START dimensions:" +i2s(startKW->N_Elements())); memcpy(start, &(*startKW)[0], rank*sizeof(int32)); } if (countKW != NULL) { if (countKW->N_Elements() != rank) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Incorrect number of COUNT dimensions:" +i2s(countKW->N_Elements())); memcpy(edges, &(*countKW)[0], rank*sizeof(int32)); } if (strideKW != NULL) { if (strideKW->N_Elements() != rank) throw GDLException( e->CallingNode(), "HDF_SD_GETDATA: Incorrect number of STRIDE dimensions:" +i2s(strideKW->N_Elements())); memcpy(stride, &(*strideKW)[0], rank*sizeof(int32)); } BaseGDL* p1 = e->GetParDefined( 1); if (strideKW == NULL) SDwritedata(sds_id, start, NULL, edges, p1->DataAddr()); else SDwritedata(sds_id, start, stride, edges, p1->DataAddr()); } void hdf_sd_fileinfo_pro( EnvT* e) { SizeT nParam=e->NParam(); DLong sd_id; DLong num_datasets, num_global_attrs; e->AssureScalarPar( 0, sd_id); SDfileinfo(sd_id, (int32 *) &num_datasets, (int32 *) &num_global_attrs); if (nParam >= 2) { BaseGDL** p1L = &e->GetPar( 1); GDLDelete((*p1L)); *p1L = new DLongGDL( num_datasets); } if (nParam == 3) { BaseGDL** p2L = &e->GetPar( 2); GDLDelete((*p2L)); *p2L = new DLongGDL( num_global_attrs); } } void hdf_sd_getinfo_pro( EnvT* e) { SizeT nParam=e->NParam(); char fieldname[256]; int32 rank; int32 dims[MAXRANK]; int32 dtype; int32 nattrs; int32 status; DLong sds_id; e->AssureScalarPar( 0, sds_id); status = SDgetinfo(sds_id, fieldname, &rank, dims, &dtype, &nattrs); if (status == FAIL) throw GDLException( e->CallingNode(), "HDF_SD_GETINFO: Invalid SD dataset ID: " + i2s(sds_id)); // Write SDS dimensions array to KW if( e->KeywordPresent( 0)) { BaseGDL** dimKW = &e->GetKW( 0); GDLDelete((*dimKW)); dimension dim((DLong *) &rank, (SizeT) 1); *dimKW = new DLongGDL(dim, BaseGDL::NOZERO); // Reverse order of dimensions for( SizeT i = 0; i < rank/2; i++) { int32 tempdim = dims[i]; dims[i] = dims[rank-1]; dims[rank-1] = tempdim; } memcpy(&(*(DLongGDL*) *dimKW)[0], dims, sizeof(int32)*rank); } if( e->KeywordPresent( 1)) { BaseGDL** hdftypeKW = &e->GetKW( 1); GDLDelete((*hdftypeKW)); *hdftypeKW = new DLongGDL( dtype); } if( e->KeywordPresent( 2)) { BaseGDL** nameKW = &e->GetKW( 2); delete(*nameKW); *nameKW = new DStringGDL( fieldname); } if( e->KeywordPresent( 3)) { BaseGDL** nattrsKW = &e->GetKW( 3); GDLDelete((*nattrsKW)); *nattrsKW = new DLongGDL( nattrs); } if( e->KeywordPresent( 4)) { BaseGDL** ndimsKW = &e->GetKW( 4); GDLDelete((*ndimsKW)); *ndimsKW = new DLongGDL( rank); } if( e->KeywordPresent( 5)) { BaseGDL** typeKW = &e->GetKW( 5); delete(*typeKW); switch ( dtype) { case DFNT_FLOAT64: { *typeKW = new DStringGDL( "DOUBLE"); break; } case DFNT_FLOAT32: { *typeKW = new DStringGDL( "FLOAT"); break; } case DFNT_UINT32: { *typeKW = new DStringGDL( "ULONG"); break; } case DFNT_INT32: { *typeKW = new DStringGDL( "LONG"); break; } case DFNT_UINT16: { *typeKW = new DStringGDL( "UINT"); break; } case DFNT_INT16: { *typeKW = new DStringGDL( "INT"); break; } case DFNT_UINT8: case DFNT_INT8: { *typeKW = new DStringGDL( "BYTE"); break; } } } } void hdf_sd_attrinfo_pro( EnvT* e) { SizeT nParam=e->NParam(); char attrname[256]; int32 num_type; int32 count; int32 nattrs; int32 status; DLong s_id; e->AssureScalarPar( 0, s_id); DLong attrindex; // SA: this makes it accept both short and long integers as IDL does // e->AssureScalarPar( 1, attrindex); e->AssureLongScalarPar( 1, attrindex); status = SDattrinfo(s_id, attrindex, attrname, &num_type, &count); if( e->KeywordPresent( 0)) { BaseGDL** countKW = &e->GetKW( 0); GDLDelete((*countKW)); *countKW = new DLongGDL( count); } if( e->KeywordPresent( 1)) { dimension dim((DLong *) &count, 1); BaseGDL** dataKW = &e->GetKW( 1); GDLDelete((*dataKW)); switch ( num_type) { case DFNT_FLOAT64: { *dataKW = new DDoubleGDL(dim, BaseGDL::NOZERO); SDreadattr(s_id, attrindex, (*dataKW)->DataAddr()); break; } case DFNT_FLOAT32: { *dataKW = new DFloatGDL(dim, BaseGDL::NOZERO); SDreadattr(s_id, attrindex, (*dataKW)->DataAddr()); break; } case DFNT_INT32: { *dataKW = new DLongGDL(dim, BaseGDL::NOZERO); SDreadattr(s_id, attrindex, (*dataKW)->DataAddr()); break; } case DFNT_INT16: { *dataKW = new DIntGDL(dim, BaseGDL::NOZERO); SDreadattr(s_id, attrindex, (*dataKW)->DataAddr()); break; } case DFNT_UINT32: { *dataKW = new DULongGDL(dim, BaseGDL::NOZERO); SDreadattr(s_id, attrindex, (*dataKW)->DataAddr()); break; } case DFNT_UINT16: { *dataKW = new DUIntGDL(dim, BaseGDL::NOZERO); SDreadattr(s_id, attrindex, (*dataKW)->DataAddr()); break; } case DFNT_CHAR: { char* attrstr = new char[count+1]; memset(attrstr, 0, count+1); SDreadattr(s_id, attrindex, (VOIDP) attrstr); *dataKW = new DStringGDL( attrstr); delete[] attrstr; } } } if( e->KeywordPresent( 2)) { BaseGDL** hdftypeKW = &e->GetKW( 2); GDLDelete((*hdftypeKW)); *hdftypeKW = new DLongGDL( num_type); } if( e->KeywordPresent( 3)) { BaseGDL** nameKW = &e->GetKW( 3); delete(*nameKW); *nameKW = new DStringGDL( attrname); } } void hdf_vg_getinfo_pro( EnvT* e) { SizeT nParam=e->NParam(); char groupname[256]; char groupclass[256]; int32 nentries; DLong vg_id; e->AssureScalarPar( 0, vg_id); if( e->KeywordPresent( 0)) { Vgetclass(vg_id, groupclass); BaseGDL** classKW = &e->GetKW( 0); delete(*classKW); *classKW = new DStringGDL( groupclass); } if( e->KeywordPresent( 1)) { Vgetname(vg_id, groupname); BaseGDL** nameKW = &e->GetKW( 1); delete(*nameKW); *nameKW = new DStringGDL( groupname); } if( e->KeywordPresent( 2)) { Vinquire(vg_id, &nentries, groupname); BaseGDL** nentriesKW = &e->GetKW( 2); GDLDelete((*nentriesKW)); *nentriesKW = new DLongGDL( nentries); } } void hdf_vd_get_pro( EnvT* e) { SizeT nParam=e->NParam(); char vdataname[256]; char vdataclass[256]; int32 nentries; DLong vd_id; e->AssureScalarPar( 0, vd_id); if( e->KeywordPresent( 0)) { VSgetclass(vd_id, vdataclass); BaseGDL** classKW = &e->GetKW( 0); delete(*classKW); *classKW = new DStringGDL( vdataclass); } if( e->KeywordPresent( 1)) { VSgetname(vd_id, vdataname); BaseGDL** nameKW = &e->GetKW( 1); delete(*nameKW); *nameKW = new DStringGDL( vdataname); } if( e->KeywordPresent( 2)) { nentries = VSelts(vd_id); BaseGDL** nentriesKW = &e->GetKW( 2); GDLDelete((*nentriesKW)); *nentriesKW = new DLongGDL( nentries); } } void hdf_vg_gettrs_pro( EnvT* e) { SizeT nParam=e->NParam(3); char groupname[256]; int32 nentries; DLong vg_id; e->AssureScalarPar( 0, vg_id); Vinquire(vg_id, &nentries, groupname); dimension dim((DLong *) &nentries, (SizeT) 1); BaseGDL** p1L = &e->GetPar( 1); GDLDelete((*p1L)); *p1L = new DLongGDL(dim, BaseGDL::NOZERO); BaseGDL** p2L = &e->GetPar( 2); GDLDelete((*p2L)); *p2L = new DLongGDL(dim, BaseGDL::NOZERO); Vgettagrefs(vg_id, (int32 *) (*p1L)->DataAddr(), (int32 *) (*p2L)->DataAddr(), nentries); } void hdf_vg_detach_pro( EnvT* e) { SizeT nParam=e->NParam(); DLong vg_id; e->AssureScalarPar( 0, vg_id); Vdetach(vg_id); } void hdf_vd_detach_pro( EnvT* e) { SizeT nParam=e->NParam(); DLong vd_id; e->AssureScalarPar( 0, vd_id); VSdetach(vd_id); } void hdf_sd_endaccess_pro( EnvT* e) { SizeT nParam=e->NParam(); DLong sds_id; e->AssureScalarPar( 0, sds_id); SDendaccess(sds_id); } void hdf_sd_end_pro( EnvT* e) { SizeT nParam=e->NParam(); DLong sd_id; e->AssureScalarPar( 0, sd_id); SDend(sd_id); } void hdf_close_pro( EnvT* e) { SizeT nParam=e->NParam(); DLong hdf_id; e->AssureScalarPar( 0, hdf_id); Vend(hdf_id); Hclose(hdf_id); } template< typename T> void hdf_sd_getdscl_template(EnvT* e, DLong dim_size, int32 dim_id) { T* data = new T(dimension(dim_size), BaseGDL::NOZERO); SDgetdimscale(dim_id, data->DataAddr()); BaseGDL** scaleKW = &e->GetKW(2); *scaleKW = data; } void hdf_sd_dimget_pro( EnvT* e) { DLong dim_id, status; int32 n_attrs, data_type, dim_size; e->AssureScalarPar( 0, dim_id); // NAME keyword if (e->KeywordPresent(0)) { char dim_name[64]; status = SDdiminfo(dim_id, dim_name, &dim_size, &data_type, &n_attrs); if (status != FAIL) { BaseGDL** nameKW = &e->GetKW(0); delete(*nameKW); *nameKW = new DStringGDL(dim_name); } } else { status = SDdiminfo(dim_id, NULL, &dim_size, &data_type, &n_attrs); } if (status == FAIL) throw GDLException(e->CallingNode(), "HDF_SD_DIMGET: Invalid dimension ID: " + i2s(dim_id)); // ... or unselected SDS? // NATTR keyword if (e->KeywordPresent(1)) { BaseGDL** nattrKW = &e->GetKW(1); delete(*nattrKW); *nattrKW = new DLongGDL(n_attrs); } // SCALE keyword if (e->KeywordPresent(2)) { BaseGDL** scaleKW = &e->GetKW(2); delete(*scaleKW); // TODO: ? if dim_type == 0 scale not set switch (data_type) { case DFNT_FLOAT64: hdf_sd_getdscl_template< DDoubleGDL>( e, dim_size, dim_id); break; case DFNT_FLOAT32: hdf_sd_getdscl_template< DFloatGDL>( e, dim_size, dim_id); break; case DFNT_UINT32: hdf_sd_getdscl_template< DULongGDL>( e, dim_size, dim_id); break; case DFNT_INT32: hdf_sd_getdscl_template< DLongGDL>( e, dim_size, dim_id); break; case DFNT_UINT16: hdf_sd_getdscl_template< DUIntGDL>( e, dim_size, dim_id); break; case DFNT_INT16: hdf_sd_getdscl_template< DIntGDL>( e, dim_size, dim_id); break; case DFNT_UINT8: case DFNT_INT8: hdf_sd_getdscl_template< DByteGDL>( e, dim_size, dim_id); break; } } // SCALE keyword // COUNT keyword if (e->KeywordPresent(3)) { BaseGDL** countKW = &e->GetKW(3); delete(*countKW); *countKW = new DLongGDL(dim_size); } } } // namespace #endif gdl-0.9.9/src/hdf_pro.hpp000066400000000000000000000032071340051421000152100ustar00rootroot00000000000000/*************************************************************************** hdf_pro.hpp - HDF4 GDL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef HDF_PRO_HPP_ #define HDF_PRO_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { void hdf_sd_getdata_pro( EnvT* e); void hdf_sd_adddata_pro( EnvT* e); void hdf_sd_fileinfo_pro( EnvT* e); void hdf_sd_getinfo_pro( EnvT* e); void hdf_sd_attrinfo_pro( EnvT* e); void hdf_sd_dimget_pro( EnvT* e); void hdf_sd_endaccess_pro( EnvT* e); void hdf_sd_end_pro( EnvT* e); void hdf_close_pro( EnvT* e); void hdf_vg_getinfo_pro( EnvT* e); void hdf_vg_gettrs_pro( EnvT* e); void hdf_vg_detach_pro( EnvT* e); void hdf_vd_detach_pro( EnvT* e); void hdf_vd_get_pro( EnvT* e); } // namespace #endif gdl-0.9.9/src/ifmt.cpp000066400000000000000000000625711340051421000145320ustar00rootroot00000000000000/*************************************************************************** ifmt.cpp - formatted input ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_IFMT_CPP #include #include //#include "datatypes.hpp" //#include "dstructgdl.hpp" //#include "io.hpp" #include "real2int.hpp" using namespace std; // on input all format codes are the similar // only the default width is important // (dec, hex, oct are also supported) void ReadNext( istream& is, string& buf) { bool trail = false; char c; for(;;) { c = is.get(); // int cc = c; // cout << "c: " << cc << " ("< 0) { char *buf = new char[ w+1]; ArrayGuard guard( buf); is->get( buf, w+1); return Str2D( buf); } else if( w == 0) { string buf; ReadNext( *is, buf); return Str2D( buf.c_str()); } else { string buf; getline( *is, buf); return Str2D( buf.c_str()); } } // read long inline long int ReadL( istream* is, int w, int base=10) { if( w > 0) { char *buf = new char[ w+1]; ArrayGuard guard( buf); is->get( buf, w+1); return Str2L( buf, base); } else if( w == 0) { string buf; ReadNext( *is, buf); return Str2L( buf.c_str(), base); } else { string buf; getline( *is, buf); return Str2L( buf.c_str(), base); } } // read unsigned long inline unsigned long int ReadUL( istream* is, int w, int base=10) { if( w > 0) { char *buf = new char[ w+1]; ArrayGuard guard( buf); is->get( buf, w+1); return Str2UL( buf, base); } else if( w == 0) { string buf; ReadNext( *is, buf); return Str2UL( buf.c_str(), base); } else { string buf; getline( *is, buf); return Str2UL( buf.c_str(), base); } } // A code // string template<> SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; if( w <= 0) for( SizeT i=offs; i guard( buf); for( SizeT i=offs; iget( buf, w); (*this)[ i] = buf; //string( buf); if( is->eof()) // ignore if length is too short { if( i == (endEl-1)) is->clear(); assert( is->good()); } } } return tCount; } // int (long, ...) template<> SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { float re, im; if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadD( is, w); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { double re, im; if( w < 0) w = 0; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadD( is, w); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtI( istream* is, SizeT offs, SizeT r, int w, BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtI( istream* is, SizeT offs, SizeT r, int w, BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtI( istream* is, SizeT offs, SizeT r, int w, BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtI( istream* is, SizeT offs, SizeT r, int w, BaseGDL::IOMode oMode) { float re, im; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadL( is, w, oMode); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtI( istream* is, SizeT offs, SizeT r, int w, BaseGDL::IOMode oMode) { double re, im; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadL( is, w, oMode); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i(ReadD( is, w)); } return tCount; } // float template<> SizeT Data_:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { float re, im; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadD( is, w); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { double re, im; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadD( is, w); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; iToTransfer(); nB += tt; if( nB > firstOffs) { nB -= tt; break; } } firstIn = firstEl * NTags() + firstTag; firstOffs -= nB; } SizeT DStructGDL:: IFmtA( istream* is, SizeT offs, SizeT r, int w) { SizeT firstIn, firstOffs, tCount, tCountIn; IFmtAll( offs, r, firstIn, firstOffs, tCount, tCountIn); SizeT trans = (*this)[ firstIn]->IFmtA( is, firstOffs, tCount, w); if( trans >= tCount) return tCountIn; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstIn+1); i < ddSize; i++) { trans = (*this)[ i]->IFmtA( is, 0, tCount, w); if( trans >= tCount) return tCountIn; tCount -= trans; } return tCountIn; } SizeT DStructGDL:: IFmtI( istream* is, SizeT offs, SizeT r, int w, BaseGDL::IOMode oMode) { SizeT firstIn, firstOffs, tCount, tCountIn; IFmtAll( offs, r, firstIn, firstOffs, tCount, tCountIn); SizeT trans = (*this)[ firstIn]->IFmtI( is, firstOffs, tCount, w, oMode); if( trans >= tCount) return tCountIn; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstIn+1); i < ddSize; i++) { trans = (*this)[ i]->IFmtI( is, 0, tCount, w, oMode); if( trans >= tCount) return tCountIn; tCount -= trans; } return tCountIn; } SizeT DStructGDL:: IFmtF( istream* is, SizeT offs, SizeT r, int w) { SizeT firstIn, firstOffs, tCount, tCountIn; IFmtAll( offs, r, firstIn, firstOffs, tCount, tCountIn); SizeT trans = (*this)[ firstIn]->IFmtF( is, firstOffs, tCount, w); if( trans >= tCount) return tCountIn; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstIn+1); i < ddSize; i++) { trans = (*this)[ i]->IFmtF( is, 0, tCount, w); if( trans >= tCount) return tCountIn; tCount -= trans; } return tCountIn; } int getPosInStringArray(string *array, int nval, string what) { for (int i=0; i 31) throw GDLException("Unable to apply format code "+fmt+" to input: "+what.substr(8,2)+"."); iHour=Str2L( what.substr(11,2).c_str(), 10); if (iHour < 0 || iHour > 23) throw GDLException("Unable to apply format code "+fmt+" to input: "+what.substr(11,2)+"."); iMinute=Str2L( what.substr(14,2).c_str(), 10); if (iMinute < 0 || iMinute > 59) throw GDLException("Unable to apply format code "+fmt+" to input: "+what.substr(14,2)+"."); Second=Str2L( what.substr(17,2).c_str(), 10); //Str2D since it is in format integer (CSI2.2) if (Second < 0 || Second > 59.0) throw GDLException("Unable to apply format code "+fmt+" to input: "+what.substr(17,2)+"."); iYear=Str2L( what.substr(20,4).c_str(), 10); if (iYear < -4716 || iYear > 5000000 || iYear == 0) throw GDLException("Value of Julian date is out of allowed range."); break; case BaseGDL::CMOA: fmt="CMOA"; iMonth=getPosInStringArray(theMONTH, 12, what); if (iMonth == -1) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CMoA: fmt="CMoA"; iMonth=getPosInStringArray(theMONTH, 12, what); if (iMonth == -1) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CmoA: fmt="CmoA"; iMonth=getPosInStringArray(theMONTH, 12, what); if (iMonth == -1) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CDWA: case BaseGDL::CDwA: case BaseGDL::CdwA: //do nothing -- day of week is not useful. break; case BaseGDL::CapA: fmt="CapA"; //icap should modify date. FIXME. icap=getPosInStringArray(cAPa, 2, what); if (icap == -1) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CApA: fmt="CApA"; //icap should modify date. FIXME. icap=getPosInStringArray(cAPa, 2, what); if (icap == -1) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CAPA: fmt="CAPA"; //icap should modify date. FIXME. icap=getPosInStringArray(cAPa, 2, what); if (icap == -1) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CMOI: fmt="CMOI"; iMonth=Str2L( what.c_str(), 10); if (iMonth < 1 || iMonth > 12) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CYI: fmt="CYI"; iYear=Str2L( what.c_str(), 10); if (iYear < -4716 || iYear > 5000000 || iYear == 0) throw GDLException("Value of Julian date is out of allowed range."); break; case BaseGDL::ChI: fmt="ChI"; //AM-PM hour -- to be modified by CaPA. iHour=Str2L( what.c_str(), 10); if (iHour < 0 || iHour > 12) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CHI: fmt="CHI"; iHour=Str2L( what.c_str(), 10); if (iHour < 0 || iHour > 23) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CDI: fmt="CDI"; iDay=Str2L( what.c_str(), 10); if (iDay < 0 || iDay > 31) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CMI: fmt="CMI"; iMinute=Str2L( what.c_str(), 10); if (iMinute < 0 || iMinute > 59) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; case BaseGDL::CSI: fmt="CSI"; Second=Str2L( what.c_str(), 10); if (Second < 0 || Second > 59.0) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; //Float case BaseGDL::CSF: fmt="CSF"; Second=Str2D( what.c_str()); if (Second < 0.0 || Second > 60.0) throw GDLException("Unable to apply format code "+fmt+" to input: "+what+"."); break; default: std::cerr<<"unhandled switch statement, please report!"< 0) { char *buf = new char[ w+1]; ArrayGuard guard( buf); is->get( buf, w+1); what.assign(buf); } else if( w == 0) { ReadNext( *is, what); } else { getline( *is, what); } return what; } template<> SizeT Data_:: IFmtCal( istream* is, SizeT offs, SizeT r, int w, BaseGDL::Cal_IOMode cMode) { // ***NOT COMPLETE: Repeat count will mostly *NOT* Work ! FIXME (see ofmt.cpp solution!) DDouble val = ReadFmtCal( IFmtGetString(is, w), w, cMode); std::ostringstream s; s << setw( 16 ) << std::scientific<< val; (*this)[ offs] = s.str(); return 1; } template<> SizeT Data_:: IFmtCal( istream* is, SizeT offs, SizeT r, int w, BaseGDL::Cal_IOMode cMode) { // ***NOT COMPLETE: Repeat count will mostly *NOT* Work ! FIXME (see ofmt.cpp solution!) DFloat re, im; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadFmtCal( IFmtGetString(is, w), w, cMode); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtCal( istream* is, SizeT offs, SizeT r, int w, BaseGDL::Cal_IOMode cMode) { // ***NOT COMPLETE: Repeat count will mostly *NOT* Work ! FIXME (see ofmt.cpp solution!) DDouble re, im; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountIn = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { im = ReadFmtCal( IFmtGetString(is, w), w, cMode); (*this)[ firstEl] = Ty( (*this)[ firstEl].real(), im); firstEl++; tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: IFmtCal( istream* is, SizeT offs, SizeT r, int w, BaseGDL::Cal_IOMode cMode) { // ***NOT COMPLETE: Repeat count will mostly *NOT* Work ! FIXME (see ofmt.cpp solution!) (*this)[ offs] = ReadFmtCal( IFmtGetString(is, w), w, cMode); return 1; } SizeT DStructGDL:: IFmtCal( istream* is, SizeT offs, SizeT r, int w, BaseGDL::Cal_IOMode cMode) { // ***NOT COMPLETE: Repeat count will mostly *NOT* Work ! FIXME (see ofmt.cpp solution!) SizeT firstIn, firstOffs, tCount, tCountIn; IFmtAll( offs, 1, firstIn, firstOffs, tCount, tCountIn); SizeT trans = (*this)[ firstIn]->IFmtCal( is, firstOffs, r, w, cMode); if( trans >= tCount) return tCountIn; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstIn+1); i < ddSize; i++) { trans = (*this)[ i]->IFmtCal( is, 0, r, w, cMode); if( trans >= tCount) return tCountIn; tCount -= trans; } return tCountIn; } //#include "instantiate_templates.hpp" #endif gdl-0.9.9/src/image.cpp000066400000000000000000000226371340051421000146540ustar00rootroot00000000000000/*************************************************************************** image.cpp - GDL image routines ------------------- begin : Jul 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // PLplot is used for direct graphics #include "includefirst.hpp" #include "graphicsdevice.hpp" #include "image.hpp" #ifdef HAVE_LIBWXWIDGETS #include "gdlwxstream.hpp" #endif using namespace std; namespace lib { // BaseGDL* tvrd( EnvT* e) // { // // when !d.name == Null we do nothing ! // GDLGStream* actStream = GraphicsDevice::GetDevice()->GetStream(); // if (actStream == NULL) e->Throw("Unable to create window."); // //#ifdef HAVE_LIBWXWIDGETS // if (actStream->HasImage()) // return GetImage(e); // else //#endif // return GraphicsDevice::GetDevice()->TVRD( e); // } BaseGDL* tvrd( EnvT* e){ GDLGStream* actStream = GraphicsDevice::GetDevice()->GetStream(); if (actStream == NULL) e->Throw("Unable to create window."); static int wordsIx=e->KeywordIx("WORDS"); static int orderIx=e->KeywordIx("ORDER"); static int trueIx=e->KeywordIx("TRUE"); static int channelIx=e->KeywordIx("CHANNEL"); if (e->KeywordSet(wordsIx)) e->Throw( "WORDS keyword not yet supported."); DLong orderVal=SysVar::TV_ORDER(); e->AssureLongScalarKWIfPresent(orderIx, orderVal); DLong tru=0; e->AssureLongScalarKWIfPresent( trueIx, tru); if (tru > 3 || tru < 0) e->Throw("Value of TRUE keyword is out of allowed range."); //GetBitMapData is device-dependent and insures that image is by default ORDER=0 now. DByteGDL *bitmap = static_cast(actStream->GetBitmapData()); if (bitmap==NULL) e->Throw("Unable to read from current device: "+GraphicsDevice::GetDevice()->Name()+"."); //need to GDLDelete bitmap on exit after this line. long nx=bitmap->Dim(0); long ny=bitmap->Dim(1); long x_gdl=0; long y_gdl=0; long nx_gdl=nx; long ny_gdl=ny; bool error=false; bool hasXsize=false; bool hasYsize=false; int nParam = e->NParam(); if (nParam >= 4) { DLongGDL* Ny = e->GetParAs(3); ny_gdl=(*Ny)[0]; hasYsize=true; } if (nParam >= 3) { DLongGDL* Nx = e->GetParAs(2); nx_gdl=(*Nx)[0]; hasXsize=true; } if (nParam >= 2) { DLongGDL* y0 = e->GetParAs(1); y_gdl=(*y0)[0]; } if (nParam >= 1) { DLongGDL* x0 = e->GetParAs(0); x_gdl=(*x0)[0]; } DLong channel=-1; if (nParam == 5) { DLongGDL* ChannelGdl = e->GetParAs(4); channel=(*ChannelGdl)[0]; } e->AssureLongScalarKWIfPresent( channelIx, channel); if (channel > 3) {GDLDelete(bitmap); e->Throw("Value of Channel is out of allowed range.");} if (!(hasXsize))nx_gdl-=x_gdl; if (!(hasYsize))ny_gdl-=y_gdl; DLong xref,xval,xinc,yref,yval,yinc,xmax11,ymin11; int x_11=0; int y_11=0; xref=0;xval=0;xinc=1; yref=0;yval=0;yinc=1; x_11=xval+(x_gdl-xref)*xinc; y_11=yval+(y_gdl-yref)*yinc; xmax11=xval+(x_gdl+nx_gdl-1-xref)*xinc; ymin11=yval+(y_gdl+ny_gdl-1-yref)*yinc; if (y_11 < 0 || y_11 > ny-1) error=true; if (x_11 < 0 || x_11 > nx-1) error=true; if (xmax11 < 0 || xmax11 > nx-1) error=true; if (ymin11 < 0 || ymin11 > ny-1) error=true; if (error) {GDLDelete(bitmap); e->Throw("Value of Area is out of allowed range.");} SizeT dims[3]; DByteGDL* res; if ( tru == 0 ) { dims[0] = nx_gdl; dims[1] = ny_gdl; dimension dim( dims, (SizeT) 2 ); res = new DByteGDL( dim, BaseGDL::ZERO ); //set again dimension since tvrd does not want the 1-sized dimensions purged! (like in a=tvrd(0,0,1,1) a=Array[1,1] static_cast(res)->SetDim(dim); if ( channel <= 0 ) { //channel not given, return max of the 3 channels DByte mx, mx1; for ( SizeT i =0; i < nx_gdl ; ++i ) { for ( SizeT j = 0; j < ny_gdl ; ++j ) { mx = (*bitmap)[3 * ((j+y_11) * nx + (i+x_11)) + 0]; mx1 = (*bitmap)[3 * ((j+y_11) * nx + (i+x_11)) + 1]; if ( mx1 > mx ) mx = mx1; mx1 = (*bitmap)[3 * ((j+y_11) * nx + (i+x_11)) + 2]; if ( mx1 > mx ) mx = mx1; (*res)[j * nx_gdl + i] = mx; } } } else { for ( SizeT i =0; i < nx_gdl ; ++i ) { for ( SizeT j = 0; j < ny_gdl ; ++j ) { (*res)[j * nx_gdl + i] = (*bitmap)[3 * ((j+y_11) * nx + (i+x_11)) + channel]; } } } GDLDelete(bitmap); // Reflect about y-axis if ( orderVal == 1 ) res->Reverse( 1 ); return res; } else { dims[0] = 3; dims[1] = nx_gdl; dims[2] = ny_gdl; dimension dim( dims, (SizeT) 3 ); res = new DByteGDL( dim, BaseGDL::NOZERO ); //set again dimension since tvrd does not want the 1-sized dimensions purged! (like in a=tvrd(0,0,1,1,/tru) a=Array[3,1,1] static_cast(res)->SetDim(dim); for ( SizeT i =0; i < nx_gdl ; ++i ) { for ( SizeT j = 0; j < ny_gdl ; ++j ) { for ( SizeT k = 0 ; k < 3 ; ++k) (*res)[3 * (j * nx_gdl + i) + k] = (*bitmap)[3 * ((j+y_11) * nx + (i+x_11)) + k]; } } GDLDelete(bitmap); // Reflect about y-axis if ( orderVal == 1 ) res->Reverse( 2 ); if ( tru == 1 ) { return res; } else if ( tru == 2 ) { DUInt* perm = new DUInt[3]; perm[0] = 1; perm[1] = 0; perm[2] = 2; return res->Transpose( perm ); } else if ( tru == 3 ) { DUInt* perm = new DUInt[3]; perm[0] = 1; perm[1] = 2; perm[2] = 0; return res->Transpose( perm ); } } assert( false ); return NULL; } void loadct( EnvT* e) // = LOADCT_INTERNALGDL for exclusive use by LOADCT { SizeT nCT = GraphicsDevice::N_CT(); static int get_namesIx = e->KeywordIx( "GET_NAMES"); bool get_names = e->KeywordPresent( get_namesIx); if( get_names) { e->AssureGlobalKW( get_namesIx); DStringGDL* names = new DStringGDL( nCT, BaseGDL::NOZERO); for( SizeT i=0; iName(); e->SetKW( get_namesIx, names); return; //correct behaviour. } if( e->NParam() == 0) return; //FIXME should list tables names, promt for number and load it! DLong iCT; DByte r[ctSize], g[ctSize], b[ctSize]; PLINT rint[ctSize], gint[ctSize], bint[ctSize]; //load original table GDLCT* actCT = GraphicsDevice::GetCT(); actCT->Get(rint,gint,bint,ctSize); e->AssureLongScalarPar( 0, iCT); if( iCT < 0 || iCT >= nCT) e->Throw( "Table number must be from 0 to "+i2s(nCT-1)); GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); GDLGStream* actStream = actDevice->GetStream( false); // no open GraphicsDevice::LoadCT( iCT); //new table is: actCT = GraphicsDevice::GetCT(); //actually update colors in col0 if needed: DLong bottom=0; DLong ncolors=ctSize; static int bottomIx=e->KeywordIx("BOTTOM"); static int ncolorsIx=e->KeywordIx("NCOLORS"); if ( e->KeywordSet ( bottomIx ) ) e->AssureLongScalarKWIfPresent ( bottomIx, bottom ); if ( e->KeywordSet ( ncolorsIx ) ) e->AssureLongScalarKWIfPresent ( ncolorsIx, ncolors ); if (bottom < 0) bottom=0; if (bottom > ctSize-1) bottom=ctSize-1; if (ncolors < 1) ncolors=1; if (ncolors > ctSize) ncolors=ctSize; if (bottom+ncolors > ctSize) ncolors=ctSize-bottom; for( SizeT i=0, j=bottom ; jGet( i, r[ i], g[ i], b[ i]); //update section of colors rint[j] = (PLINT) r[i]; gint[j] = (PLINT) g[i]; bint[j] = (PLINT) b[i]; } static int rgbtableIx = e->KeywordIx( "RGB_TABLE"); if( e->KeywordPresent( rgbtableIx) ) { e->AssureGlobalKW( rgbtableIx); DByteGDL* rgbtable = new DByteGDL( dimension(ncolors, 3), BaseGDL::NOZERO); for( SizeT i=0, j=bottom ; jSetKW( rgbtableIx, rgbtable); return; //correct behaviour. } // GD: // new colormap must be given to *all* streams since plplot has a colormap PER STREAM. // (IDL has a colormap PER Device, i.e., all Windows of multiWindow devices.) // However plplot using the crazy old rw color scheme, uses heavily XAllocColor which is a killer for X11 speed. // SetColorMap0() is thus overloaded for X11 devices to *do nothing* (devicex do tricks behind plplot's back most of the time) int nbActiveStreams = actDevice->MaxWin(); for (int i = 0; i < nbActiveStreams; ++i) { actStream = actDevice->GetStreamAt(i); if (actStream != NULL) actStream->SetColorMap0(rint, gint, bint, ctSize); } } } // namespace gdl-0.9.9/src/image.hpp000066400000000000000000000023251340051421000146510ustar00rootroot00000000000000/*************************************************************************** image.hpp - GDL image routines ------------------- begin : Jul 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef IMAGE_HPP_ #define IMAGE_HPP_ #include "envt.hpp" #include "initsysvar.hpp" namespace lib { void loadct( EnvT* e); BaseGDL* tvrd( EnvT* e); BaseGDL* GetImage( EnvT* e); } // namespace #endif gdl-0.9.9/src/includefirst.hpp000066400000000000000000000063041340051421000162630ustar00rootroot00000000000000/*************************************************************************** includefirst.hpp - include this first ------------------- begin : Wed Apr 18 16:58:14 JST 2005 copyright : (C) 2002-2006 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef INCLUDEFIRST_HPP_ #define INCLUDEFIRST_HPP_ #ifdef __CYGWIN__ // std::cerr is broken in gcc/cygwin64 - for gdl, anyways. #define cerr cout #endif // #undef cerr if you want to try it. #ifdef WIN32 # define WIN32_LEAN_AND_MEAN 1 #endif #ifdef HAVE_CONFIG_H #include #endif #ifdef _MSC_VER #define NOMINMAX #define _WINSOCKAPI_ #pragma warning( disable : 4716 ) #endif // Python.h must be included before everything else #if defined(USE_PYTHON) || defined(PYTHON_MODULE) #ifndef HAVE_LIBREADLINE #define GDL_NOT_HAVE_READLINE #endif #include #ifdef GDL_NOT_HAVE_READLINE #undef HAVE_LIBREADLINE #endif #undef GDL_NOT_HAVE_READLINE #endif #include #include #if defined(USE_EIGEN) #include #endif #if defined(__sun__) // SA: CS is defined in /usr/include/sys/regset.h and used in an enum statement by ANTLR # include # undef CS # undef GS #endif //define globally a gdl method for allocating/deallocating/freeing data compatible with alignment needed by EIGEN. //This permits to create unallocated data varibale (BaseGDL* objects) and have them point to some // data adress that has been allocated in a c or c++ function. inline void* gdlAlignedMalloc(std::size_t size) { #if defined(USE_EIGEN) return Eigen::internal::aligned_malloc(size); #else return std::malloc(size); #endif } inline void* gdlAlignedRealloc(void *ptr, std::size_t new_size, std::size_t old_size=0) { //apparently Eigen does not use old_size anymore. Pfewh. #if defined(USE_EIGEN) return Eigen::internal::aligned_realloc(ptr,new_size,old_size); #else return std::realloc(ptr, new_size); #endif } inline void gdlAlignedFree(void* ptr) { #if defined(USE_EIGEN) return Eigen::internal::aligned_free(ptr); #else return free(ptr); #endif } #if defined _OPENMP inline int currentNumberOfThreads() { return omp_get_num_threads(); } inline int maxNumberOfThreads() { return omp_get_num_procs(); } inline int currentThreadNumber() { return omp_get_thread_num(); } #else inline int currentNumberOfThreads() { return 1; } inline int maxNumberOfThreads() { return 1; } inline int currentThreadNumber() { return 0; } #endif #endif gdl-0.9.9/src/initct.cpp000066400000000000000000004046241340051421000150640ustar00rootroot00000000000000// define the color tables #include "includefirst.hpp" #include "graphicsdevice.hpp" void GraphicsDevice::InitCT() { { // make r, g, b local identifiers DByte r[256]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; DByte g[256]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; DByte b[256]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; CT.push_back(GDLCT("B-W LINEAR",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 90, 94, 98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 7, 9, 10, 12, 13, 15, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 34, 36, 37, 39, 41, 42, 44, 45, 47, 49, 50, 52, 53, 55, 57, 58, 60, 61, 63, 65, 66, 68, 69, 71, 73, 74, 76, 77, 79, 81, 82, 84, 85, 87, 89, 90, 92, 94, 95, 97, 98,100,102,103,105,106,108,110,111,113,114,116,118,119,121,122,124,126,127,129,130,132,134,135,137,138,140,142,143,145,146,148,150,151,153,154,156,158,159,161,162,164,166,167,169,170,172,174,175,177,179,180,182,183,185,187,188,190,191,193,195,196,198,199,201,203,204,206,207,209,211,212,214,215,217,219,220,222,223,225,227,228,230,231,233,235,236,238,239,241,243,244,246,247,249,251,252,254,255}; DByte b[256]={ 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 23, 24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 46, 47, 48, 50, 51, 52, 54, 55, 56, 58, 59, 61, 62, 63, 65, 66, 67, 69, 70, 71, 73, 74, 75, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96, 97, 99,100,101,103,104,105,107,108,109,111,112,113,115,116,118,119,120,122,123,124,126,127,128,130,131,132,134,135,136,138,139,141,142,143,145,146,147,149,150,151,153,154,155,157,158,160,161,162,164,165,166,168,169,170,172,173,174,176,177,179,180,181,183,184,185,187,188,189,191,192,193,195,196,198,199,200,202,203,204,206,207,208,210,211,212,214,215,217,218,219,221,222,223,225,226,227,229,230,231,233,234,236,237,238,240,241,242,244,245,246,248,249,250,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; CT.push_back(GDLCT("BLUE/WHITE",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96,102,108,114,120,126,132,138,144,150,156,162,168,174,180,186,192,198,204,210,216,222,228,234,240,243,246,249,252,252,252,252,252,251,250,249,248,248,248,248,248,247,246,245,244,243,242,241,240,240,239,238,237,236,236,236,236,235,234,233,232,231,230,229,228,228,228,228,228,227,226,225,224,223,222,221,220,219,218,217,216,216,216,216,216,215,214,213,212,211,210,209,208,207,206,205,204,204,204,204,204,203,202,201,200,199,198,197,196,196,196,196,196,195,194,193,192,191,190,189,188,187,186,185,184,184,184,184,184,183,182,181,180,179,178,177,176,176,176,176,176,175,174,173,172,171,170,169,168,167,166,165,164,164,164,164,164,163,162,161,160,159,158,157,156,155,154,153,152,152,152,152,152,151,150,149,148,151,154,157,160,163,166,169,172,176,180,184,188,191,194,197,200,203,206,209,212,215,218,221,224,228,232,236,240,243,246,249,252,253,254,255}; DByte g[256]={ 0, 36, 72, 75, 79, 82, 86, 90, 93, 97,100,104,108,117,126,135,144,153,162,171,180,189,198,207,216,225,234,243,252,249,246,243,240,234,228,222,216,210,204,198,192,186,180,174,168,162,156,150,144,138,132,126,120,114,108,102, 96, 90, 84, 78, 72, 66, 60, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96,104,112,120,128,135,142,149,156,164,172,180,188,196,204,212,220,228,236,244,252,253,254,255}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 10, 12, 14, 16, 18, 20, 22, 25, 27, 29, 31, 34, 35, 37, 39, 41, 43, 45, 47, 50, 52, 54, 56, 59, 61, 63, 65, 67, 68, 70, 72, 74, 76, 78, 80, 83, 85, 87, 89, 92, 94, 96, 98,101,102,104,106,108,110,112,114,116,118,120,122,125,127,129,131,134,135,137,139,141,143,145,147,150,152,154,156,159,160,162,163,165,167,169,171,174,176,178,180,183,185,187,189,192,193,195,197,199,201,203,205,208,210,212,214,216,217,219,221,223,225,227,229,232,234,236,238,241,243,245,247,250,251,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; CT.push_back(GDLCT("GRN-RED-BLU-WHT",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 15, 17, 18, 20, 21, 23, 24, 26, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 57, 59, 60, 62, 63, 65, 66, 68, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99,101,102,104,105,107,108,110,111,113,114,115,117,118,120,121,123,124,126,127,128,130,131,133,134,136,137,139,140,141,143,144,146,147,149,150,152,153,155,156,157,159,160,162,163,165,166,168,169,170,172,173,175,176,178,179,181,182,184,185,186,188,189,191,192,194,195,197,198,199,201,202,204,205,207,208,210,211,212,214,215,217,218,220,221,223,224,226,227,228,230,231,233,234,236,237,239,240,241,243,244,246,247,249,250,252,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 35, 37, 39, 41, 43, 45, 47, 49, 51, 52, 54, 56, 58, 60, 62, 64, 66, 68, 69, 71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 94, 96, 98,100,102,103,105,107,109,111,113,115,117,119,120,122,124,126,128,130,132,134,136,137,139,141,143,145,147,149,151,153,154,156,158,160,162,164,166,168,170,171,173,175,177,179,181,183,185,187,188,190,192,194,196,198,200,202,204,205,207,209,211,213,215,217,219,221,222,224,226,228,230,232,234,236,238,239,241,243,245,247,249,251,253,255}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 54, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94, 98,102,105,109,113,117,121,125,129,133,137,141,145,149,153,156,160,164,168,172,176,180,184,188,192,196,200,204,207,211,215,219,223,227,231,235,239,243,247,251,255}; CT.push_back(GDLCT("RED TEMPERATURE",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 15, 22, 30, 37, 45, 52, 60, 67, 75, 82, 90, 97,105,112,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,200,201,201,202,202,203,203,204,204,205,205,206,206,207,207,208,208,209,209,210,210,211,211,212,212,213,213,214,214,215,215,216,216,217,217,218,218,219,219,220,220,221,221,222,222,223,223,224,224,225,225,226,226,227,227,228,228,229,229,230,230,231,231,232,232,233,233,234,234,235,235,236,236,237,237,238,238,239,239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 12, 15, 18, 21, 25, 28, 31, 34, 37, 40, 43, 46, 50, 53, 56, 59, 62, 65, 68, 71, 75, 78, 81, 84, 87, 90, 93, 96,100,103,106,109,112,115,118,121,125,128,131,134,137,140,143,146,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,149,148,148,147,146,146,145,145,144,143,143,142,141,141,140,140,137,135,132,130,127,125,122,120,117,115,112,110,107,105,102,100, 93, 87, 81, 75, 68, 62, 56, 50, 43, 37, 31, 25, 18, 12, 6, 0, 2, 4, 6, 9, 11, 13, 16, 18, 20, 23, 25, 27, 29, 32, 34, 36, 39, 41, 43, 46, 48, 50, 53, 55, 57, 59, 62, 64, 66, 69, 71, 73, 76, 78, 80, 83, 85, 87, 89, 92, 94, 96, 99,101,103,106,108,110,113,115,117,119,122,124,126,129,131,133,136,138,140,142,145,147,149,152,154,156,159,161,163,166,168,170,172,175,177,179,182,184,186,189,191,193,196,198,200,202,205,207,209,212,214,216,219,221,223,226,228,230,232,235,237,239,242,244,246,249,251,253,255}; DByte b[256]={ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, 96, 93, 90, 87, 84, 81, 78, 75, 71, 68, 65, 62, 59, 56, 53, 50, 46, 43, 40, 37, 34, 31, 28, 25, 21, 18, 15, 12, 9, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("BLUE/GREEN/RED/YELLOW",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 9, 14, 19, 23, 28, 33, 38, 42, 47, 52, 57, 61, 66, 71, 76, 81, 81, 81, 81, 81, 81, 81, 81, 80, 80, 80, 80, 80, 80, 80, 79, 84, 89, 94, 99,104,109,114,119,124,129,134,139,144,149,154,159,164,169,174,180,185,190,196,201,206,212,217,222,228,233,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,248,240,232,225,217,209,202,194,186,179,171,163,168,173,178,183,188,193,198,203,209,214,219,224,229,234,239,244,249,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 16, 21, 27, 32, 37, 43, 48, 54, 59, 64, 70, 75, 81, 85, 90, 95,100,105,109,114,119,124,129,134,138,143,148,153,158,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,169,175,181,187,193,199,205,212,218,224,230,236,242,248,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte b[256]={ 0, 5, 10, 15, 20, 26, 31, 36, 41, 46, 52, 57, 62, 67, 72, 78, 83, 88, 93, 98,104,109,114,119,124,130,135,140,145,150,156,161,166,171,176,182,187,192,197,202,208,213,218,223,228,234,239,244,249,255,250,245,239,234,228,223,218,212,207,201,196,190,185,180,174,169,163,158,152,147,142,136,131,125,120,114,109,104, 98, 93, 87, 82, 76, 71, 66, 60, 55, 49, 44, 38, 33, 28, 22, 17, 11, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 9, 14, 19, 24, 28, 33, 38, 43, 48, 53, 57, 62, 67, 72, 77, 82, 77, 71, 65, 59, 53, 47, 41, 36, 30, 24, 18, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 12, 16, 19, 22, 25, 29, 32, 35, 38, 41, 45, 48, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 83, 87, 90, 93, 96,100,103,106,109,112,116,119,122,125,129,132,135,138,142,145,148,151,154,158,161,164,167,171,174,177,180,183,187,190,193,196,200,203,206,209,213,216,219,222,225,229,232,235,238,242,245,248,251,255}; CT.push_back(GDLCT("STD GAMMA-II",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 3, 7, 11, 15, 19, 22, 26, 30, 34, 38, 41, 45, 49, 53, 57, 60, 64, 68, 72, 76, 79, 83, 87, 91, 95, 98,102,106,110,114,117,121,125,129,133,137,140,144,148,152,156,159,163,167,171,175,178,182,186,190,194,197,201,205,209,213,216,220,224,228,232,235,239,243,247,251,255,251,247,243,239,235,230,226,222,218,214,210,205,201,197,193,189,184,180,176,172,168,164,159,155,151,147,143,138,134,130,126,122,118,113,109,105,101, 97, 92, 88, 84, 80, 76, 72, 67, 63, 59, 55, 51, 46, 42, 38, 34, 30, 26, 21, 17, 13, 9, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255,251,247,243,239,235,231,227,223,219,215,211,207,203,199,195,191,187,183,179,175,170,166,162,158,154,150,146,142,138,134,130,126,122,118,114,110,106,102, 98, 94, 90, 85, 81, 77, 73, 69, 65, 61, 57, 53, 49, 45, 41, 37, 33, 29, 25, 21, 17, 13, 9, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 11, 15, 19, 23, 27, 30, 34, 38, 42, 46, 50, 54, 57, 61, 65, 69, 73, 77, 81, 85, 88, 92, 96,100,104,108,112,115,119,123,127,131,135,139,142,146,150,154,158,162,166,170,173,177,181,185,189,193,197,200,204,208,212,216,220,224,227,231,235,239,243,247,251,255,251,247,243,239,235,231,227,223,219,215,211,207,203,199,195,191,187,183,179,175,170,166,162,158,154,150,146,142,138,134,130,126,122,118,114,110,106,102, 98, 94, 90, 85, 81, 77, 73, 69, 65, 61, 57, 53, 49, 45, 41, 37, 33, 29, 25, 21, 17, 13, 9, 5, 0}; CT.push_back(GDLCT("PRISM",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 3, 6, 10, 13, 17, 20, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 85, 86, 87, 88, 90, 92, 94, 96, 97, 98, 99,100,102,104,106,108,109,110,111,112,114,116,118,120,121,122,123,124,126,128,130,132,133,134,135,136,138,140,142,144,145,146,147,148,150,152,154,156,157,158,159,160,162,164,166,168,169,170,171,172,174,176,178,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,198,200,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,224,226,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,246,248,250,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,253,254}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 20, 20, 20, 20, 20, 21, 22, 23, 24, 24, 24, 24, 24, 25, 26, 27, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 61, 62, 63, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98,100,102,104,107,110,113,116,119,122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,180,184,188,192,197,202,207,212,217,222,227,232,237,242,247,252,252,253,254}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 6, 7, 9, 9, 10, 11, 12, 13, 14, 15, 17, 17, 18, 18, 19, 20, 22, 23, 25, 25, 26, 26, 27, 28, 29, 30, 32, 32, 33, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41, 42, 43, 44, 46, 46, 47, 48, 49, 50, 51, 52, 54, 54, 53, 53, 52, 54, 56, 58, 60, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 82, 82, 83, 83, 84, 85, 86, 87, 89, 90, 91, 92, 94, 95, 96, 97, 98, 99,100,101,103,103,104,105,106,107,108,109,110,111,112,113,115,116,117,118,119,120,121,122,124,124,125,125,126,127,129,131,133,134,136,138,140,141,143,144,146,147,149,151,153,154,156,157,159,160,161,162,164,165,166,167,169,170,172,173,175,176,177,178,180,181,183,184,186,187,188,189,191,192,193,194,196,197,199,200,202,203,204,205,207,208,209,210,212,213,214,215,217,218,219,220,221,222,223,224,226,227,228,229,230,231,232,233,235,236,237,238,239,240,241,242,243,243,244,245,246,246,247,248,249,249,250,251,252,252,253,254}; CT.push_back(GDLCT("RED-PURPLE",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 24, 25, 27, 29, 30, 32, 33, 35, 37, 38, 40, 41, 43, 45, 46, 48, 50, 51, 53, 54, 56, 58, 59, 61, 62, 64, 66, 67, 69, 71, 72, 74, 75, 77, 79, 80, 82, 83, 85, 87, 88, 90, 91, 93, 95, 96, 98,100,101,103,104,106,108,109,111,112,114,116,117,119,121,122,124,125,127,129,130,132,133,135,137,138,140,142,143,145,146,148,150,151,153,154,156,158,159,161,163,164,166,167,169,171,172,174,175,177,179,180,182,183,185,187,188,190,192,193,195,196,198,200,201,203,204,206,208,209,211,213,214,216,217,219,221,222,224,225,227,229,230,232,234,235,237,238,240,242,243,245,246,248,250,251,253,255}; DByte g[256]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 10, 13, 17, 20, 24, 27, 31, 34, 37, 41, 44, 48, 51, 55, 58, 62, 65, 68, 72, 75, 79, 82, 86, 89, 93, 96, 99,103,106,110,113,117,120,124,127,130,134,137,141,144,148,151,155,158,161,165,168,172,175,179,182,186,189,192,196,199,203,206,210,213,217,220,223,227,230,234,237,241,244,248,251,255}; CT.push_back(GDLCT("GREEN/WHITE LINEAR",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 23, 23, 23, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 39, 39, 39, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 47, 47, 47, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 52, 52, 52, 54, 54, 55, 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 64, 64, 66, 68, 70, 71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 94, 96, 98, 99,101,103,105,107,109,111,113,114,116,118,120,122,124,126,127,129,131,133,135,137,139,141,142,144,146,148,150,152,154,156,157,159,161,163,165,167,169,170,172,174,176,178,180,182,184,185,187,189,191,193,195,197,198,200,202,204,206,208,210,212,213,215,217,219,221,223,225,226,228,230,232,234,236,238,240,241,243,245,247,249,251,253,255}; DByte g[256]={ 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 50, 51, 52, 52, 53, 54, 54, 55, 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75, 76, 76, 77, 78, 78, 79, 80, 80, 81, 82, 82, 83, 84, 84, 85, 86, 87, 88, 90, 91, 92, 94, 95, 96, 98, 99,100,102,103,104,106,107,108,110,111,112,114,115,116,118,119,120,122,123,124,126,127,128,130,131,132,134,135,136,138,139,140,142,143,145,146,147,149,150,151,153,154,155,157,158,159,161,162,163,165,166,167,169,170,171,173,174,175,177,178,179,181,182,183,185,186,187,189,190,191,193,194,195,197,198,200,201,202,204,205,206,208,209,210,212,213,214,216,217,218,220,221,222,224,225,226,228,229,230,232,233,234,236,237,238,240,241,242,244,245,246,248,249,250,252,253,255}; DByte b[256]={ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 48, 47, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 90, 93, 96, 99,102,105,108,111,114,117,120,123,126,129,131,134,137,140,143,146,149,152,155,158,161,164,167,170,172,175,178,181,184,187,190,193,196,199,202,205,208,211,213,216,219,222,225,228,231,234,237,240,243,246,249,252,255}; CT.push_back(GDLCT("GRN/WHT EXPONENTIAL",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 84, 88, 92, 96,101,106,111,116,121,126,131,136,141,146,151,156,159,162,165,168,171,174,177,180,183,186,189,192,195,198,201,204,207,210,213,216,219,222,225,228,231,234,237,240,243,246,249,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,253,254,255}; DByte g[256]={ 0, 0, 0, 0, 14, 28, 43, 57, 72, 81, 90, 99,108,117,126,135,144,153,162,171,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,154,152,150,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,126,124,122,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100, 99, 98, 97, 96, 94, 92, 90, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 66, 64, 62, 60, 59, 58, 57, 56, 54, 52, 50, 48, 47, 46, 45, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 18, 17, 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96,100,104,108,112,116,120,124,128,132,136,140,144,147,150,153,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,253,254,255}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 38, 40, 42, 44, 46, 48, 50, 53, 54, 56, 58, 60, 62, 64, 66, 68, 69, 71, 73, 75, 77, 79, 81, 83, 84, 86, 88, 90, 92, 94, 96, 99,100,102,104,106,108,110,112,114,116,118,120,122,123,125,127,129,131,133,135,137,138,140,142,144,146,148,150,153,154,156,158,160,162,164,166,168,170,172,174,176,177,179,181,183,185,187,189,191,193,195,197,199,199,198,197,196,196,196,196,195,195,194,193,192,192,191,191,190,190,190,190,190,190,190,190,189,189,188,187,186,186,185,185,184,184,185,186,187,187,187,187,187,187,187,187,188,188,188,188,189,189,189,189,189,189,189,189,190,190,190,190,191,191,191,191,191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; CT.push_back(GDLCT("GREEN-PINK",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 1, 2, 3, 4, 8, 12, 16, 21, 25, 29, 33, 38, 42, 46, 50, 55, 59, 63, 67, 72, 76, 80, 84, 89, 93, 97,101,106,110,114,118,123,127,131,135,140,144,148,152,157,161,165,169,174,178,182,186,191,195,199,203,208,212,216,220,225,229,233,237,242,246,250,255,255,251,247,243,239,235,231,227,223,219,215,211,207,203,199,195,191,187,183,179,175,170,166,162,158,154,150,146,142,138,134,130,126,122,118,114,110,106,102, 98, 94, 90, 85, 81, 77, 73, 69, 65, 61, 57, 53, 49, 45, 41, 37, 33, 29, 25, 21, 17, 13, 9, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={ 0, 1, 2, 3, 4, 8, 12, 16, 21, 25, 29, 33, 38, 42, 46, 50, 55, 59, 63, 67, 72, 76, 80, 84, 89, 93, 97,101,106,110,114,118,123,127,131,135,140,144,148,152,157,161,165,169,174,178,182,186,191,195,199,203,208,212,216,220,225,229,233,237,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,247,243,239,235,231,227,223,218,214,210,206,202,198,194,190,186,181,177,173,169,165,161,157,153,149,144,140,136,132,128,124,120,116,112,107,103, 99, 95, 91, 87, 83, 79, 75, 70, 66, 62, 58, 54, 50, 46, 42, 38, 33, 29, 25, 21, 17, 13, 9, 5, 0, 0}; CT.push_back(GDLCT("BLUE-RED",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,220,220,220,220,220,221,221,221,221,221,222,222,222,222,222,223,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; CT.push_back(GDLCT("16 LEVEL",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 45, 50, 54, 58, 61, 64, 68, 69, 72, 74, 77, 79, 80, 82, 83, 85, 84, 86, 87, 88, 86, 87, 87, 87, 85, 84, 84, 84, 83, 79, 78, 77, 76, 71, 70, 68, 66, 60, 58, 55, 53, 46, 43, 40, 36, 33, 25, 21, 16, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 21, 25, 29, 33, 42, 46, 51, 55, 63, 67, 72, 76, 80, 89, 93, 97,101,110,114,119,123,131,135,140,144,153,157,161,165,169,178,182,187,191,199,203,208,212,221,225,229,233,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 16, 21, 25, 29, 38, 42, 46, 51, 55, 63, 67, 72, 76, 84, 89, 93, 97,106,110,114,119,127,131,135,140,144,152,157,161,165,174,178,182,187,195,199,203,208,216,220,225,229,233,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,242,238,233,229,221,216,212,208,199,195,191,187,178,174,170,165,161,153,148,144,140,131,127,123,119,110,106,102, 97, 89, 85, 80, 76, 72, 63, 59, 55, 51, 42, 38, 34, 29, 21, 17, 12, 8, 0}; DByte b[256]={ 0, 3, 7, 10, 14, 19, 23, 28, 32, 38, 43, 48, 53, 59, 63, 68, 72, 77, 81, 86, 91, 95,100,104,109,113,118,122,127,132,136,141,145,150,154,159,163,168,173,177,182,186,191,195,200,204,209,214,218,223,227,232,236,241,245,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,242,238,233,225,220,216,212,203,199,195,191,187,178,174,170,165,157,152,148,144,135,131,127,123,114,110,106,102, 97, 89, 84, 80, 76, 67, 63, 59, 55, 46, 42, 38, 34, 25, 21, 16, 12, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("RAINBOW",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 15, 23, 31, 39, 47, 55, 63, 70, 78, 86, 94,102,110,118,126,134,142,151,159,168,176,184,193,201,210,218,226,235,243,252, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 23, 25, 27, 29, 32, 34, 36, 38, 41, 44, 47, 50, 53, 56, 59, 63, 66, 69, 72, 75, 78, 82, 85, 89, 93, 97,101,105,108,112,116,120,124,128,131,135,139,143,147,151,155,159,163,167,171,175,178,181,185,188,192,195,198,202,205,209,212,216,218,220,223,225,227,230,232,234,237,239,241,244,244,245,246,247,247,248,249,250,250,251,252,253,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 42, 85,127,170,212,255,246,236,226,216,206,197,187,177,167,157,148,138,128,118,108, 99, 89, 79, 69, 59, 50, 40, 30, 20, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 5, 8, 10, 12, 15, 17, 19, 22, 24, 26, 29, 31, 33, 36, 36, 38, 40, 42, 45, 48, 51, 54, 58, 61, 64, 67, 70, 73, 77, 82, 87, 92, 96,100,104,108,113,119,125,131,138,144,151,157,164,171,178,185,193,200,208,215,223,229,235,242,248,255}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98,106,115,123,131,139,148,156,164,172,180,189,197,205,213,222,230,238,246,255, 0, 5, 10, 15, 21, 26, 31, 37, 42, 47, 53, 58, 63, 69, 74, 79, 85, 89, 94, 98,103,108,112,117,121,126,131,135,140,144,149,154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 7, 9, 12, 14, 17, 20, 23, 27, 30, 34, 39, 44, 49, 55, 60, 65, 71, 76, 82, 89, 97,104,112,120,128,136,145,153,162,171,180,189,198,207,217,224,232,239,247,255}; CT.push_back(GDLCT("STEPS",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 18, 36, 54, 72, 90,108,127,145,163,181,199,217,235,254,249,244,239,234,229,223,218,213,208,203,197,192,187,182,177,172,166,161,156,151,146,140,135,130,125,120,115,109,104, 99, 94, 89, 83, 78, 73, 68, 63, 58, 52, 47, 42, 37, 32, 26, 21, 16, 11, 6, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; DByte g[256]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; DByte b[256]={ 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,251,247,243,238,234,230,226,221,217,213,209,204,200,196,192,187,183,179,175,170,166,162,158,153,149,145,141,136,132,128,124,119,115,111,107,102, 98, 94, 90, 85, 81, 77, 73, 68, 64, 60, 56, 51, 47, 43, 39, 34, 30, 26, 22, 17, 13, 9, 5, 0, 3, 7, 11, 15, 19, 22, 26, 30, 34, 38, 41, 45, 49, 53, 57, 60, 64, 68, 72, 76, 79, 83, 87, 91, 95, 98,102,106,110,114,117,121,125,129,133,137,140,144,148,152,156,159,163,167,171,175,178,182,186,190,194,197,201,205,209,213,216,220,224,228,232,235,239,243,247,251,255}; CT.push_back(GDLCT("BOW SPECIAL",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={167,167,255,254,249,247,245,243,242,240,238,236,234,232,230,228,226,224,222,220,218,216,214,212,210,208,206,204,202,200,198,196,194,192,190,188,186,184,182,180,178,176,174,172,170,168,166,164,162,160,158,156,154,152,150,148,146,144,142,141,139,137,135,133,131,129,127,125,123,121,119,117,115,113,111,109,107,105,103,101, 99, 97, 95, 93, 91, 89, 87, 85, 83, 81, 79, 77, 75, 73, 71, 69, 67, 65, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 13, 8, 6, 4, 4, 6, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,101,103,105,107,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,251}; DByte g[256]={112,112,213,212,210,209,208,206,205,203,202,200,199,198,196,195,193,192,191,189,188,186,185,183,182,181,179,178,176,175,174,172,171,169,168,166,165,164,162,161,159,158,157,155,154,152,151,150,148,147,145,144,142,141,140,138,137,135,134,133,131,130,128,127,125,124,123,121,120,118,117,116,114,113,111,110,109,107,106,104,103,101,100, 99, 97, 96, 94, 93, 92, 90, 89, 87, 86, 84, 83, 82, 80, 79, 77, 76, 75, 73, 72, 70, 69, 68, 66, 65, 63, 62, 60, 59, 58, 56, 55, 53, 52, 51, 49, 48, 46, 45, 43, 42, 41, 39, 38, 36, 35, 34, 32, 31, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64, 65, 66, 68, 69, 70, 72, 73, 75, 76, 77, 79, 80, 81, 83, 84, 85, 87, 88, 89, 91, 92, 93, 95, 96, 97, 99,100,101,103,104,105,107,108,109,111,112,113,115,116,117,119,120,121,123,124,125,127,128,129,131,132,133,135,136,137,139,140,141,143,144,145,147,148,149,151,152,153,155,156,157,159,160,161,163,164,165,167,168,169,171,172,173,175,176,177,179,180,181,183,184,185,187,188,189,191,192,193,195,195}; DByte b[256]={255,255,254,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 13, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0}; CT.push_back(GDLCT("Haze",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 33, 33, 32, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 13, 8, 7, 5, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 7, 8, 13, 11, 13, 14, 15, 17, 18, 19, 20, 21, 29, 36, 42, 48, 53, 58, 61, 65, 68, 70, 72, 73, 74, 74, 74, 75, 75, 76, 76, 76, 77, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, 91, 92, 91, 94, 96, 98,100,102,104,106,108,109,111,112,113,115,116,117,119,120,121,123,124,125,127,128,129,131,132,133,135,136,137,138,140,141,142,144,145,146,148,149,150,152,153,154,156,157,158,160,161,162,164,165,166,168,169,170,172,173,174,175,177,178,179,181,182,183,185,186,187,189,190,191,193,193}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 6, 8, 13, 12, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 46, 49, 51, 53, 56, 58, 60, 63, 65, 68, 71, 73, 76, 78, 81, 84, 87, 89, 92, 95, 98,101,104,107,110,113,116,119,122,125,128,131,134,138,141,144,148,151,154,158,161,165,168,172,175,179,182,186,190,193,197,201,205,209,212,216,220,224,228,232,234,235,236,238,239,240,241,243,244,245,246,247,249,249,246,244,241,237,232,227,223,218,214,209,205,201,196,192,188,184,180,175,171,167,163,160,156,152,148,144,141,137,133,130,126,123,119,116,116,115,113,112,110,109,104,104,103,102,101,100, 99, 98, 97, 96, 95, 94, 93, 92, 88, 88, 88, 87, 86, 85, 85, 84, 83, 82, 80, 79, 78, 76, 75, 74, 73, 71, 70, 69, 68, 67, 66, 64, 63, 61, 58, 56, 54, 52, 49, 47, 45, 43, 41, 40, 38, 36, 34, 33, 31, 29, 28, 26, 25, 23, 22, 21, 19, 18, 17, 16, 14, 13, 12, 11, 13, 9, 8, 7, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0}; DByte b[256]={ 96, 96, 97, 99,100,101,102,104,105,106,107,108,110,111,112,113,115,116,117,118,119,121,122,123,124,125,127,128,129,130,132,133,134,135,136,138,139,140,141,143,144,145,146,147,149,150,151,152,154,155,156,157,158,160,161,162,163,164,166,167,168,169,171,172,173,174,175,177,178,179,180,182,183,184,185,186,188,189,190,191,193,194,195,196,197,199,200,201,202,203,205,206,207,208,210,211,212,213,214,216,217,218,219,221,222,223,224,225,227,228,229,230,232,233,232,230,229,227,225,223,222,220,218,216,214,212,210,208,149,142,135,127,118,111,103, 95, 88, 81, 74, 67, 60, 53, 47, 40, 34, 28, 22, 22, 23, 24, 25, 26, 27, 28, 28, 29, 30, 30, 31, 31, 32, 32, 29, 28, 26, 25, 23, 22, 20, 18, 17, 16, 15, 14, 13, 12, 11, 13, 9, 8, 7, 6, 5, 5, 4, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Blue - Pastel - Red",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,251,249,247,245,243,241,239,237,235,233,231,229,227,225,223,221,219,217,216,214,212,210,208,206,204,202,200,198,196,194,192,190,188,186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 13, 19, 25, 30, 36, 42, 48, 53, 59, 65, 71, 76, 82, 88, 93, 99,105,111,116,122,128,133,139,145,151,156,162,168,173,179,185,191,196,202,208,214,219,225,231,236,242,248,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140,146,152,157,163,169,174,180,186,192,197,203,209,214,220,226,232,237,243,249,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,244,238,233,227,221,215,210,204,198,193,187,181,175,170,170}; DByte b[256]={ 72, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 91, 93, 95, 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,139,141,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,242,244,246,248,250,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,249,243,237,232,226,220,214,209,203,197,192,186,180,174,169,163,157,152,146,140,134,129,123,117,112,106,100, 94, 89, 83, 77, 71, 66, 60, 54, 49, 43, 37, 31, 26, 20, 14, 9, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Pastels",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={251,251,251,251,252,252,253,252,252,251,251,250,250,249,249,249,248,248,247,247,246,246,246,245,245,244,244,243,243,243,242,242,241,241,241,240,240,240,239,239,239,238,238,237,235,230,226,222,217,213,209,205,201,197,194,190,186,183,179,176,173,169,166,163,160,157,154,151,148,145,143,140,137,135,133,130,128,126,124,122,120,118,116,114,112,111,109,109,110,111,113,114,115,116,117,118,119,121,122,123,125,125,126,127,128,129,131,132,133,135,136,137,138,139,140,140,141,142,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,171,172,174,174,175,176,177,178,179,180,181,182,183,184,185,185,186,187,188,189,190,190,191,192,193,194,195,196,197,199,200,202,203,204,206,207,208,210,211,212,213,214,215,216,217,218,219,220,220,221,222,223,224,225,226,226,227,228,228,229,230,230,231,232,232,233,233,234,235,235,235,236,236,236,237,237,237,238,238,239,239,239,240,240,240,241,242,242,242,242,243,243,244,244,244,245,245,246,246,246,247,247,248,248,249,249,250,250,251,251}; DByte g[256]={ 0, 0, 0, 1, 1, 2, 2, 4, 5, 7, 8, 7, 9, 13, 8, 15, 17, 18, 20, 21, 23, 24, 26, 27, 28, 30, 31, 33, 34, 35, 37, 38, 40, 41, 42, 44, 45, 46, 48, 49, 50, 52, 53, 55, 56, 57, 59, 60, 61, 63, 64, 65, 66, 68, 69, 70, 72, 73, 74, 76, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 95, 96, 97, 98, 99,101,102,103,104,105,107,108,110,114,118,122,125,129,132,136,139,143,146,149,152,156,158,161,164,167,170,173,175,178,181,184,186,188,191,193,195,197,199,201,203,205,207,209,211,213,215,216,218,220,221,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,223,223,223,223,223,223,223,223,223,223,223,223,223,224,224,224,224,224,224,224,224,225,225,225,225,225,225,225,226,226,226,226,226,226,227,227,227,227,227,228,228,228,228,228,229,229,229,229,229,229,230,230,230,230,231,231,232,232,232,232,232,233,233,233,234,234,234,234,235,235,235,236,236,236,236,236,237,237,237,237,238,238,238,239,239,239,240,240,241,241,242,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,250}; DByte b[256]={ 3, 3, 9, 15, 22, 28, 34, 41, 48, 55, 62, 66, 73, 81, 84, 94,100,106,112,118,124,130,135,141,147,152,157,162,168,173,178,183,187,192,197,201,206,210,215,219,223,227,231,235,237,237,236,236,236,235,235,235,235,234,234,234,233,233,233,232,232,232,232,231,231,231,230,230,230,230,230,229,229,229,229,228,228,228,228,228,227,227,227,227,227,226,226,226,226,226,225,225,225,225,225,225,225,224,224,224,224,224,224,224,224,224,223,223,223,223,223,223,223,223,223,223,223,223,222,222,222,222,222,222,222,222,222,222,222,222,221,220,218,217,216,214,213,212,211,210,208,207,206,206,205,204,203,202,202,201,200,200,199,198,198,197,197,197,196,197,196,196,195,195,195,195,195,195,195,195,195,195,195,196,196,197,198,199,200,201,201,202,203,204,205,205,206,207,208,209,209,210,211,212,212,213,213,214,215,216,216,217,218,218,219,220,221,221,222,223,223,224,225,226,226,227,228,228,229,230,230,231,232,232,233,233,234,235,235,236,237,237,238,238,239,240,240,241,241,242,243,243,244,244,245,246,246,247,247,248,248,249,249,250,250,250}; CT.push_back(GDLCT("Hue Sat Lightness 1",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={253,253,251,250,250,249,249,248,248,247,247,246,246,246,245,245,244,244,244,243,243,242,242,242,241,241,240,240,240,239,239,239,238,238,238,237,237,236,236,236,235,235,235,235,234,233,233,232,232,231,231,230,229,229,228,227,226,226,225,224,223,223,222,221,220,219,218,217,216,215,214,213,212,211,210,208,207,206,205,204,202,200,199,198,196,195,194,192,192,191,191,190,189,188,187,185,185,184,183,183,182,181,180,179,178,177,176,175,174,173,172,172,171,170,169,168,167,166,165,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,149,148,147,146,145,144,143,142,140,139,138,138,137,136,135,134,132,131,130,129,128,127,126,125,124,122,121,120,119,118,118,116,114,113,112,111,111,109,108,109,111,114,115,117,118,120,123,125,127,129,131,134,137,139,141,144,147,150,152,155,158,161,164,167,171,174,177,181,184,188,192,195,199,203,207,211,216,220,224,228,233,237,238,239,239,240,240,240,241,241,241,242,242,243,243,243,244,244,245,245,245,246,246,247,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,254,254}; DByte g[256]={252,252,250,250,249,249,248,248,247,247,246,246,245,245,244,244,243,242,242,241,241,240,239,239,238,238,237,236,236,235,235,234,233,233,232,232,231,230,230,229,228,228,227,226,226,225,224,223,223,222,221,221,220,219,218,218,217,217,216,215,214,214,213,212,211,211,209,209,208,208,206,206,205,205,204,202,202,201,201,200,199,197,197,196,196,195,195,194,194,194,194,194,194,194,195,194,195,195,195,196,196,196,197,197,198,198,199,199,200,200,201,202,203,204,204,205,206,207,208,210,211,212,213,215,216,217,219,220,222,222,222,222,222,222,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,224,224,224,224,224,224,224,224,224,225,225,225,225,225,225,225,226,226,226,226,226,227,227,227,227,227,227,228,228,228,228,229,229,229,229,229,230,230,230,230,231,231,231,231,232,232,232,232,233,233,233,234,234,234,234,235,235,235,236,236,236,237,237,237,238,238,235,231,227,223,218,214,210,205,201,196,191,187,182,177,172,167,162,157,151,146,140,135,129,123,117,111,106, 99, 93, 85, 78, 74, 67, 61, 54, 47, 40, 33, 27, 27}; DByte b[256]={252,252,250,250,249,249,248,248,247,247,246,246,245,245,244,244,243,243,243,242,242,241,241,241,240,240,239,239,239,238,238,238,237,237,237,237,236,236,236,236,235,235,235,235,234,234,234,234,233,233,233,232,232,232,232,231,231,231,230,230,230,230,229,229,229,229,229,228,228,228,228,227,227,227,227,227,226,226,226,226,226,226,225,226,225,225,225,225,224,225,224,224,224,224,224,224,224,224,224,223,223,223,223,223,223,223,223,223,223,223,223,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,220,218,217,215,213,211,210,208,206,204,202,200,197,195,193,191,188,186,183,181,178,176,173,170,168,165,162,159,156,153,150,146,143,140,137,133,129,126,122,118,116,112,107,106,105,105,104,102,100, 99, 99, 97, 96, 94, 93, 93, 91, 90, 88, 88, 86, 85, 83, 83, 81, 80, 78, 78, 76, 75, 73, 72, 71, 70, 69, 67, 66, 65, 63, 62, 62, 59, 58, 58, 55, 54, 54, 51, 50, 49, 47, 46, 45, 43, 42, 41, 39, 38, 36, 35, 34, 32, 31, 30, 28, 27, 25, 24, 23, 22, 20, 18, 17, 15, 14, 13, 8, 13, 8, 7, 5, 4, 2, 1, 0, 0}; CT.push_back(GDLCT("Hue Sat Lightness 2",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,247,242,237,233,228,223,219,214,210,205,201,196,192,188,184,179,175,171,167,163,159,155,151,147,144,140,136,133,129,125,122,118,115,112,108,105,102, 99, 95, 92, 89, 86, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,172,175,177,180,183,186,188,191,194,196,199,201,203,206,208,210,213,215,217,219,221,223,225,227,229,230,232,234,236,237,239,240,242,243,245,246,247,248,250,251,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 87, 92, 97,102,107,111,116,121,125,130,134,139,143,147,152,156,160,164,168,172,176,180,184,188,192,196,199,203,207,210,214,217,221,224,228,231,234,238,241,244,247,250,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,251,251,250,249,249,248,247,247,246,246,246,245,245,245,245,244,244,244,244,244,244,245,245,245,245,246,246,246,247,247,248,249,249,250,251,251,251}; DByte b[256]={ 3, 3, 13, 17, 23, 30, 37, 44, 50, 57, 63, 70, 76, 82, 89, 95,101,107,114,120,126,132,138,144,149,155,161,167,172,178,184,189,195,200,205,211,216,221,227,232,237,242,247,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,250,247,244,242,239,236,234,231,229,226,224,221,219,217,214,212,210,208,206,204,202,200,198,196,194,192,191,189,187,186,184,183,181,180,179,177,176,175,174,173,172,171,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,251}; CT.push_back(GDLCT("Hue Sat Value 1",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,252,251,249,248,247,246,244,243,241,240,238,237,235,233,231,230,228,226,224,222,220,218,216,213,211,209,207,204,202,199,197,194,192,189,187,184,181,178,175,172,170,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 85, 84, 84, 88, 91, 94, 97,100,103,107,110,114,117,121,124,128,131,135,139,143,146,150,154,158,162,166,170,174,179,183,187,191,196,200,205,209,214,218,223,228,233,237,242,247,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={253,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,169,169,170,171,172,173,174,176,177,178,180,181,183,184,186,188,189,191,193,195,197,199,201,203,205,207,209,211,214,216,218,221,223,226,228,231,233,236,239,241,244,247,250,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,247,242,237,232,226,221,216,211,205,200,194,189,183,178,172,166,160,155,149,143,137,131,125,119,113,107,100, 94, 88, 81, 75, 69, 62, 56, 49, 42, 36, 29, 29}; DByte b[256]={253,253,252,251,250,249,248,248,247,247,246,246,245,245,244,244,244,244,243,243,243,243,243,243,243,243,244,244,244,244,245,245,246,246,247,247,248,249,250,250,251,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,250,247,244,241,237,234,231,227,224,220,217,213,210,206,203,199,195,191,187,183,179,175,171,167,163,159,155,150,146,142,137,133,128,124,119,114,110,105,100, 95, 90, 86, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 13, 9, 8, 7, 6, 5, 4, 3, 2, 2}; CT.push_back(GDLCT("Hue Sat Value 2",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0,127,191,188,186,184,182,179,177,140,138,170,168,165,163,161,158,156,154,121,119,147,145,142,140,138,135,133,131,103,101,124,122,119,117,115,112,110,108, 84, 82,101, 99, 96, 94, 92, 89, 87, 85, 66, 64, 78, 76, 73, 71, 69, 66, 64, 62, 47, 46, 55, 52, 50, 48, 46, 43, 41, 39, 29, 27, 32, 29, 27, 25, 23, 20, 18, 16, 11, 9, 9, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 12, 18, 24, 30, 36, 42, 48, 54, 48, 53, 72, 78, 85, 91, 97,103,109,115, 97,102,133,139,145,151,157,163,170,176,145,150,194,200,206,212,218,224,230,236,194,199,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255}; DByte g[256]={ 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 18, 19, 24, 36, 42, 48, 54, 60, 66, 72, 78, 68, 72, 97,103,109,115,121,127,133,139,116,121,157,163,170,176,182,188,194,200,165,170,218,224,230,236,242,248,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,248,242,235,229,223,216,210,163,158,191,184,178,172,165,159,153,146,112,107,127,121,115,110,104, 98, 92, 86, 64, 60, 69, 63, 57, 52, 46, 40, 34, 28, 18, 13, 11, 5, 0, 0}; DByte b[256]={ 0, 0,127,191,192,192,193,194,195,195,157,157,198,198,199,200,201,202,202,203,163,164,205,206,207,208,208,209,210,211,169,170,213,214,215,215,216,217,218,218,175,176,221,221,222,223,224,225,225,226,181,182,228,229,230,231,231,232,233,234,188,188,236,237,238,238,239,240,241,241,194,194,244,245,245,246,247,248,248,249,200,200,251,252,253,254,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,255,204,204,255,255,255,255,255,255,255,248,194,189,230,224,218,212,206,200,194,188,145,140,169,163,157,151,145,139,133,127, 97, 92,109,103, 97, 91, 84, 78, 72, 66, 48, 43, 48, 42, 36, 30, 24, 18, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 7, 10, 12, 15, 17, 16, 18, 25, 28, 30, 33, 35, 38, 40, 43, 36, 38, 51, 48, 46, 44, 41, 39, 37, 34, 25, 24, 27, 25, 23, 20, 18, 16, 13, 11, 7, 5, 4, 2, 0, 0}; CT.push_back(GDLCT("Purple-Red + Stripes",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 64, 68, 72, 76, 81, 85, 89, 93, 98,102,106,110,115,119,123,128,132,136,140, 76, 76, 76, 81, 85, 89, 93, 98,102,106,110,115,119,123,128,132,136,140,145,149,153,157,157,161,164,167,170,173,177,180,183,186,189,193,196,199,202,205,209,212,215,218,218,219,220,222,223,224,225,226,227,229,230,231,232,233,234,236,237,238,239,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte g[256]={251,251,249,247,245,243,241,238,236,234,232,230,228,226,224,221,219,217,215,213,211,209,206,204,202,200,198,196,194,192,189,187,185,183,181,179,177,174,172,170,168,166,164,162,160,157,155,153,151,149,147,145,142,140,138,136,134,132,130,128,128,129,131,133,134,136,138,139,141,143,145,146,148,150,151,153,155,157,158,160,162,163,165,167,168,170,172,174,175,177,179,180,182,182,177,171,165,160,154,149,143,138,132,126,121,115,110,104, 99, 93, 88, 82, 76, 71, 65, 60, 54, 49, 43, 37, 32, 26, 21, 15, 13, 4, 0, 0, 0, 4, 8, 12, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 64, 68, 72, 76, 81, 81, 85, 89, 93, 98,102,106,110,115,119,123,128,132,136,140,145,149,153,157,162,162,166,170,174,179,183,187,192,196,200,204,209,213,217,221,226,230,234,238,243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 64, 68, 72, 76, 81, 85, 89, 93, 98,102,106,110,115,119,123,128,132,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136, 76, 76, 76, 72, 68, 64, 60, 56, 52, 48, 44, 40, 36, 32, 28, 23, 19, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 17, 21, 25, 29, 34, 38, 42, 46, 51, 55, 59, 64, 68, 72, 76, 81, 81, 84, 88, 91, 95, 98,102,105,109,113,116,120,123,127,130,134,137,141,145,148,152,155,159,159,162,166,170,173,177,181,184,188,192,195,199,203,206,210,214,217,221,225,228,232,236,239, 0, 0, 0}; CT.push_back(GDLCT("Beach",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={124,124,120,115,111,106,102, 97, 93, 88, 84, 79, 75, 70, 66, 61, 57, 52, 48, 43, 39, 34, 30, 25, 21, 16, 12, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 13, 14, 19, 23, 28, 32, 37, 41, 46, 50, 55, 59, 64, 68, 73, 77, 82, 86, 91, 95,100,104,109,113,118,123,126,132,135,141,144,150,153,159,162,168,171,177,180,186,189,195,198,204,207,213,216,222,225,231,234,240,243,249,252,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 11, 15, 20, 24, 29, 33, 38, 42, 47, 51, 56, 60, 65, 69, 74, 78, 83, 87, 92, 96,101,105,110,114,119,122,128,131,137,140,146,149,155,158,164,167,173,176,182,185,191,194,200,203,209,212,218,221,227,230,236,240,245,249,254,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,252,247,243,238,234,229,225,220,216,211,207,202,198,193,189,184,180,175,171,166,162,157,153,148,144,139,135,131,126,122,117,113,108,104, 99, 95, 90, 86, 81, 77, 72, 68, 63, 59, 54, 50, 45, 41, 36, 32, 27, 23, 18, 14, 9, 5, 5}; DByte b[256]={255,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,254,255,250,247,241,238,232,229,223,220,214,211,205,202,196,193,187,184,178,175,169,166,160,157,151,148,142,139,133,130,125,121,116,112,107,103, 98, 94, 89, 85, 80, 76, 71, 67, 62, 58, 53, 49, 44, 40, 35, 31, 26, 22, 17, 13, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Mac Style",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0,127,123,119,114,110,106,102, 97, 84, 80, 76, 80, 76, 72, 67, 63, 59, 55, 45, 42, 38, 38, 33, 29, 25, 21, 16, 12, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 17, 25, 34, 42, 51, 59, 61, 68, 76, 93,102,110,119,127,136,144,137,145,153,178,187,195,204,212,221,229,214,221,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,253,251,249,248,246,244,242,217,215,213,236,234,232,230,229,227,225,201,200,198,218,217,215,213,211,210,208,186,184,182,201,199,198,196,194,192,191,170,169,167,184,182,180,179,177,175,174,155,153,151,167,165,163,161,160,158,156,139,138,136,149,148,146,144,143,141,139,124,122,120,132,130,130}; DByte g[256]={ 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 34, 51, 68, 85,102,119,122,137,153,187,204,221,238,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,255,255,229,229,229,250,246,242,238,233,229,225,198,195,191,208,204,199,195,191,187,182,160,156,152,165,161,157,153,148,144,140,122,118,114,125,123,121,119,116,114,112, 99, 97, 95,104,102, 99, 97, 95, 93, 91, 80, 78, 76, 82, 80, 78, 76, 74, 72, 70, 61, 59, 57, 61, 59, 57, 55, 53, 50, 48, 42, 40, 38, 40, 38, 36, 33, 31, 29, 27, 22, 21, 19, 19, 16, 14, 12, 13, 8, 6, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={ 0, 0,127,193,195,197,199,201,204,206,187,189,191,214,216,218,221,223,225,227,206,208,210,235,238,240,242,244,246,248,225,227,229,255,255,255,255,255,255,255,229,229,229,255,255,255,255,255,238,221,183,168,152,153,135,118,101, 84, 67, 50, 30, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Eos A",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={255,255,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 18, 27, 36, 45, 49, 57, 72, 81, 91,100,109,118,127,136,131,139,163,173,182,191,200,209,218,227,213,221,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,253,251,249,247,245,243,241,215,214,235,234,232,230,228,226,224,222,198,196,216,215,213,211,209,207,205,203,181,179,197,196,194,192,190,188,186,184,164,162,178,176,175,173,171,169,167,165,147,145,159,157,156,154,152,150,148,146,130,128,140,138,137,135,133,131,129,127,113,111,121,119,117,117}; DByte g[256]={255,255,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 15, 23, 31, 39, 47, 55, 57, 64, 79, 87, 95,103,111,119,127,135,129,136,159,167,175,183,191,199,207,215,200,207,239,247,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,250,246,242,238,233,229,225,198,195,212,208,204,199,195,191,187,182,160,156,169,165,161,157,153,148,144,140,122,118,127,125,123,121,119,116,114,112, 99, 97,106,104,102, 99, 97, 95, 93, 91, 80, 78, 84, 82, 80, 78, 76, 74, 72, 70, 61, 59, 63, 61, 59, 57, 55, 53, 50, 48, 42, 40, 42, 40, 38, 36, 33, 31, 29, 27, 22, 21, 21, 19, 16, 14, 12, 13, 8, 6, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={255,255,127,131,136,140,144,148,153,157,145,149,170,174,178,182,187,191,195,199,183,187,212,216,221,225,229,233,238,242,221,225,255,247,239,231,223,215,207,199,172,164,175,167,159,151,143,135,127,119,100, 93, 95, 87, 79, 71, 63, 55, 47, 39, 28, 21, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Eos B",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 4, 4, 5, 7, 9, 11, 12, 14, 15, 16, 17, 17, 18, 18, 18, 17, 16, 15, 14, 13, 11, 13, 8, 5, 3, 1, 0, 3, 5, 7, 13, 12, 13, 15, 17, 18, 19, 19, 19, 19, 19, 18, 16, 14, 12, 9, 5, 2, 2, 6, 11, 17, 23, 29, 36, 42, 49, 56, 64, 71, 78, 85, 93,100,106,113,119,125,130,135,139,143,146,149,150,151,152,151,150,148,145,142,138,133,127,121,114,107, 99, 90, 82, 73, 63, 54, 44, 35, 25, 16, 6, 1, 13, 18, 25, 32, 38, 44, 48, 52, 55, 56, 57, 57, 56, 53, 50, 45, 39, 33, 25, 16, 6, 3, 15, 27, 40, 53, 67, 81, 96,111,126,141,156,170,185,199,212,225,237,248,252,242,234,227,222,217,214,212,212,213,216,220,225,232,240,249,251,239,226,213,198,183,167,150,133,116, 98, 81, 64, 47, 30, 14, 1, 15, 29, 42, 54, 64, 73, 81, 87, 91, 94, 95, 95, 92, 88, 82, 75, 66, 55, 42, 28, 13, 3, 21, 40, 60, 81,103,125,147,170,193,216,239,249,228,207,187,168,151,134,119,106, 95, 85, 77, 71, 67, 65, 66, 68, 72, 79, 87, 98,110,124,140,158,177,197,219,241,245,221,196,171,145,120, 95, 70, 46, 23, 1, 19, 39, 57, 74, 89,102,112,121,127,127}; DByte g[256]={ 51, 51, 58, 65, 72, 79, 85, 92, 99,105,111,117,124,129,135,141,146,152,157,162,167,171,176,180,184,188,191,195,198,201,203,206,208,210,212,213,214,215,216,216,216,216,216,215,215,213,212,210,209,206,204,201,199,195,192,189,185,181,177,172,168,163,158,153,148,142,137,131,125,119,113,106,100, 93, 87, 80, 73, 67, 60, 53, 46, 39, 32, 25, 18, 11, 4, 2, 9, 16, 22, 29, 36, 42, 49, 55, 61, 68, 74, 79, 85, 91, 96,101,106,111,116,120,125,129,133,136,140,143,146,149,151,153,155,157,159,160,161,162,162,162,162,162,162,161,160,159,157,155,153,151,148,146,143,139,136,132,128,124,120,115,111,106,101, 95, 90, 84, 79, 73, 67, 61, 54, 48, 42, 35, 28, 22, 15, 8, 1, 5, 12, 19, 26, 33, 40, 47, 54, 61, 67, 74, 81, 88, 94,101,107,113,120,126,131,137,143,148,154,159,164,168,173,177,181,185,189,193,196,199,202,204,207,209,211,212,214,215,216,216,216,216,216,216,215,214,213,212,210,208,206,203,201,198,194,191,187,184,180,175,171,166,161,156,151,146,140,135,129,123,117,111,104, 98, 91, 85, 78, 71, 64, 57, 50, 44, 37, 30, 23, 23}; DByte b[256]={116,116,105, 94, 84, 74, 64, 55, 46, 38, 30, 24, 18, 12, 8, 5, 2, 0, 0, 0, 1, 3, 6, 13, 14, 20, 26, 33, 41, 50, 59, 68, 78, 88, 99,109,120,131,142,153,163,174,184,193,202,211,218,226,232,238,243,247,250,252,253,253,253,251,249,246,241,236,230,224,216,208,200,190,181,171,160,150,139,128,117,106, 96, 85, 75, 65, 56, 47, 39, 31, 24, 18, 13, 9, 5, 2, 0, 0, 0, 1, 3, 5, 9, 14, 19, 25, 32, 40, 48, 57, 67, 76, 87, 97,108,119,130,140,151,162,172,182,192,201,209,217,225,231,237,242,246,249,252,253,254,253,252,249,246,242,237,231,225,217,209,201,192,182,172,162,151,140,130,119,108, 97, 87, 76, 67, 57, 48, 40, 32, 25, 19, 14, 9, 5, 3, 1, 0, 0, 0, 2, 5, 9, 13, 18, 24, 31, 39, 47, 56, 65, 75, 85, 96,106,117,128,139,150,160,171,181,190,200,208,216,224,230,236,241,246,249,251,253,253,253,252,250,247,243,238,232,226,218,211,202,193,184,174,163,153,142,131,120,109, 99, 88, 78, 68, 59, 50, 41, 33, 26, 20, 14, 13, 6, 3, 1, 0, 0, 0, 2, 5, 8, 12, 18, 24, 30, 38, 46, 55, 64, 74, 84, 94,105,105}; CT.push_back(GDLCT("Hardcandy",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={105,105,105,105,105,105,105,105,105,110,114,123,127,131,135,143,147,150,157,160,163,165,170,172,174,176,179,180,180,181,182,181,181,180,179,177,174,172,170,168,163,160,157,154,147,143,139,131,127,123,119,110,105,100, 96, 87, 82, 77, 68, 63, 59, 54, 46, 42, 38, 30, 26, 23, 19, 13, 13, 8, 5, 1, 0, 2, 5, 6, 6, 7, 8, 7, 7, 6, 5, 3, 2, 1, 3, 5, 8, 13, 16, 19, 26, 30, 34, 38, 46, 50, 54, 59, 68, 73, 77, 86, 91, 96,100,110,114,119,127,131,135,139,147,150,154,157,163,165,168,172,174,176,177,180,180,181,182,181,181,180,179,177,176,174,170,168,165,160,157,154,150,143,139,135,127,123,119,114,105,100, 96, 91, 82, 77, 73, 63, 59, 54, 50, 42, 38, 34, 30, 23, 19, 16, 13, 8, 5, 3, 0, 2, 3, 6, 6, 7, 7, 7, 7, 6, 6, 3, 2, 0, 3, 5, 8, 13, 16, 19, 23, 30, 34, 38, 42, 50, 54, 59, 63, 73, 77, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0,255,255}; DByte g[256]={246,246,246,246,246,246,246,246,246,251,253,244,239,235,231,224,222,219,216,214,214,213,214,215,216,218,223,226,229,237,241,246,251,248,243,237,225,218,212,205,192,186,179,173,160,154,148,137,132,127,122,113,109,105,102, 96, 94, 92, 89, 88, 88, 88, 88, 89, 90, 93, 95, 97, 99,104,107,110,113,120,124,127,134,138,141,145,152,155,158,164,166,169,171,175,176,178,179,180,180,180,180,179,178,176,173,171,169,166,161,158,154,148,144,140,136,128,124,120,112,108,104,100, 92, 88, 85, 81, 74, 71, 68, 62, 60, 57, 55, 51, 50, 48, 46, 45, 44, 44, 43, 43, 43, 44, 44, 45, 46, 47, 48, 49, 51, 53, 54, 55, 57, 59, 60, 61, 63, 64, 64, 65, 66, 67, 67, 67, 67, 67, 67, 66, 66, 65, 64, 62, 61, 60, 58, 56, 55, 53, 50, 48, 46, 43, 41, 39, 37, 34, 32, 30, 28, 25, 23, 22, 19, 17, 16, 15, 12, 11, 13, 8, 7, 6, 6, 4, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255}; DByte b[256]={234,234,234,234,234,234,234,234,234,222,210,186,175,164,153,132,122,113, 95, 87, 79, 72, 59, 54, 49, 44, 37, 34, 32, 30, 29, 30, 31, 34, 37, 40, 49, 54, 59, 66, 79, 87, 95,104,122,132,142,164,175,186,198,222,234,246,251,227,214,202,177,165,153,141,118,107, 96, 75, 65, 56, 47, 30, 22, 15, 9, 2, 7, 12, 19, 22, 24, 25, 27, 26, 25, 22, 19, 16, 12, 2, 2, 9, 15, 30, 38, 47, 65, 75, 85, 96,118,129,141,153,177,189,202,226,239,251,246,222,210,198,175,164,153,142,122,113,104, 95, 79, 72, 66, 54, 49, 44, 40, 34, 32, 31, 29, 30, 31, 32, 37, 40, 44, 49, 59, 66, 72, 87, 95,104,113,132,142,153,175,186,198,210,234,246,251,239,214,202,189,165,153,141,129,107, 96, 85, 75, 56, 47, 38, 22, 15, 9, 2, 7, 12, 16, 22, 24, 25, 26, 26, 25, 24, 22, 16, 12, 7, 2, 9, 15, 22, 38, 47, 56, 75, 85, 96,107,129,141,153,165,189,202,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, 0,255,255}; CT.push_back(GDLCT("Nature",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 54, 54, 59, 63, 68, 73, 77, 82, 82, 87, 91, 96,100,105,110,114,119,123,127,131,135,139,143,143,147,150,154,157,160,163,165,168,170,172,174,176,177,177,179,180,180,181,181,182,181,181,180,180,179,177,176,174,174,172,170,168,165,163,160,157,154,150,147,143,139,135,131,131,127,123,119,114,110,105,100, 96, 91, 86, 82, 77, 73, 68, 68, 63, 59, 54, 50, 46, 42, 38, 34, 30, 26, 23, 19, 16, 13, 13, 13, 8, 5, 3, 1, 0, 2, 3, 5, 6, 6, 7, 7, 8, 8, 7, 7, 6, 6, 5, 3, 2, 0, 1, 3, 5, 8, 13, 13, 13, 16, 19, 23, 26, 30, 34, 38, 42, 46, 50, 54, 59, 63, 68, 68, 73, 77, 82, 87, 91, 96,100,105,110,114,119,123,127,131,131,135,139,143,147,150,154,157,160,163,165,168,170,172,172,174,176,177,179,180,180,181,181,182,181,181,180,180,179,179,177,176,174,172,170,168,165,163,160,157,154,150,147,143,143,139,135,131,127,123,119,114,110,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105, 0,255,255}; DByte g[256]={ 67, 67, 67, 67, 67, 67, 67, 66, 66, 66, 65, 64, 64, 63, 62, 61, 60, 59, 57, 56, 55, 54, 53, 53, 52, 51, 49, 48, 47, 47, 46, 45, 44, 44, 44, 43, 43, 43, 43, 43, 44, 44, 45, 46, 47, 48, 50, 51, 53, 55, 57, 60, 60, 62, 65, 68, 71, 74, 78, 81, 85, 88, 92, 96,100,104,108,108,112,116,120,124,128,132,136,140,144,148,151,154,158,161,161,164,166,169,171,173,175,176,178,179,180,180,180,180,180,180,179,179,178,176,175,173,171,169,166,164,161,158,155,152,152,148,145,141,138,134,131,127,124,120,117,113,110,107,104,104,101, 99, 97, 95, 93, 91, 90, 89, 88, 88, 88, 88, 88, 89, 89, 91, 92, 94, 96, 99,102,105,109,113,117,122,127,132,137,137,142,148,154,160,166,173,179,186,192,199,205,212,218,218,225,231,237,243,248,254,251,246,241,237,233,229,226,223,223,220,218,216,215,214,213,213,214,214,216,217,219,222,224,224,228,231,235,239,244,248,253,251,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246, 0,255,255}; DByte b[256]={141,141,153,165,177,189,202,214,214,227,239,251,246,234,222,210,198,186,175,164,153,142,132,132,122,113,104, 95, 87, 79, 72, 66, 59, 54, 49, 44, 40, 40, 37, 34, 32, 31, 30, 29, 30, 31, 32, 34, 37, 40, 44, 49, 49, 54, 59, 66, 72, 79, 87, 95,104,113,122,132,142,153,164,164,175,186,198,210,222,234,246,251,239,226,214,202,189,177,177,165,153,141,129,118,107, 96, 85, 75, 65, 56, 47, 38, 30, 30, 22, 15, 9, 2, 2, 7, 12, 16, 19, 22, 24, 25, 26, 27, 27, 26, 25, 24, 22, 19, 16, 12, 7, 2, 2, 9, 15, 22, 30, 30, 38, 47, 56, 65, 75, 85, 96,107,118,129,141,153,165,177,177,189,202,214,227,239,251,246,234,222,210,198,186,175,164,164,153,142,132,122,113,104, 95, 87, 79, 72, 66, 59, 54, 54, 49, 44, 40, 37, 34, 32, 31, 30, 29, 30, 31, 32, 34, 37, 37, 40, 44, 49, 54, 59, 66, 72, 79, 87, 95,104,113,122,132,132,142,153,164,175,186,198,210,222,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, 0,255,255}; CT.push_back(GDLCT("Ocean",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 81, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240, 0, 0, 0, 0, 80, 80, 80, 80,160,160,160,160,240,240,240,240}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,192,192,192,192,192,192,193,192,192,192,192,192,192,192,192,192,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240}; DByte b[256]={ 80, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,240, 0, 80,160,160}; CT.push_back(GDLCT("Peppermint",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 2, 2, 3, 4, 5, 6, 7, 8, 9, 13, 11, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 70, 71, 72, 74, 75, 77, 78, 79, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99,100,101,102,103,103,104,105,106,107,107,108,108,109,110,110,111,111,112,113,113,114,114,115,116,117,117,118,119,120,121,122,123,124,125,127,128,129,131,132,134,135,137,138,140,142,143,145,147,149,150,152,154,155,157,158,160,161,163,164,166,167,168,169,170,171,172,173,174,174,175,175,176,176,177,177,178,178,178,178,179,179,179,180,180,180,181,181,182,182,183,184,184,185,186,187,188,190,191,192,194,195,197,198,200,202,204,206,208,210,212,214,216,218,220,222,224,225,227,229,231,232,234,236,237,238,239,241,242,242,243,244,245,245,246,246,246,246,246,247,247,247,247,247,247,247,247,247,247,247,247,247,248,248,248,249,250,251,251,252,254,255,254,252,251,249,247,247}; DByte g[256]={ 19, 19, 20, 22, 25, 29, 33, 38, 44, 51, 58, 65, 73, 81, 89, 98,106,115,124,132,140,148,155,162,169,175,180,184,188,191,193,194,195,194,193,191,188,184,180,175,169,162,155,148,140,132,124,115,107, 98, 89, 81, 73, 65, 58, 51, 44, 38, 33, 29, 25, 22, 20, 19, 19, 19, 20, 22, 25, 29, 33, 38, 44, 51, 58, 65, 73, 81, 89, 98,107,115,124,132,140,148,155,162,169,175,180,184,188,191,193,194,195,194,193,191,188,184,180,175,169,162,155,148,140,132,124,115,106, 98, 89, 81, 73, 65, 58, 51, 44, 38, 33, 29, 25, 22, 20, 19, 19, 19, 20, 22, 25, 29, 33, 38, 44, 51, 58, 65, 73, 81, 89, 98,107,115,124,132,140,148,155,162,169,175,180,184,188,191,193,194,195,194,193,191,188,184,180,175,169,162,155,148,140,132,124,115,106, 98, 89, 81, 73, 65, 58, 51, 44, 38, 33, 29, 25, 22, 20, 19, 19, 19, 20, 22, 25, 29, 33, 38, 44, 51, 58, 65, 73, 81, 89, 98,107,115,124,132,140,148,155,162,169,175,180,184,188,191,193,194,195,194,193,191,188,184,180,175,169,162,155,148,140,132,124,115,106, 98, 89, 81, 73, 65, 58, 51, 44, 38, 33, 29, 25, 22, 20, 20}; DByte b[256]={ 7, 7, 11, 15, 19, 22, 26, 30, 34, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 93, 97,100,103,107,110,113,116,119,122,125,128,130,133,136,139,141,144,147,150,153,156,159,162,165,169,172,176,180,184,188,192,196,201,205,210,215,220,225,230,235,241,246,251,253,248,243,237,232,227,222,217,212,207,202,198,194,190,186,182,179,176,172,170,167,165,162,160,158,157,155,154,152,151,150,148,147,146,144,143,141,140,138,136,134,132,129,126,123,120,116,113,108,104, 99, 94, 89, 83, 78, 72, 65, 59, 53, 46, 39, 32, 25, 18, 11, 5,253,246,239,233,227,221,215,210,205,200,195,191,188,184,181,178,176,174,172,171,170,169,169,168,168,168,168,169,169,169,169,170,170,170,169,169,168,167,166,164,162,160,157,154,150,146,141,136,131,125,119,112,106, 98, 91, 83, 75, 67, 58, 50, 41, 33, 24, 16, 8,255,247,239,232,225,219,213,207,202,197,193,189,186,183,181,179,178,177,177,177,178,179,180,181,183,184,186,188,190,192,193,195,196,197,198,198,198,198,197,195,193,191,188,184,180,175,169,163,156,149,142,133,125,116,107, 97, 87, 87}; CT.push_back(GDLCT("Plasma",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,246,241,237,233,228,224,219,215,211,206,202,197,193,189,184,180,175,171,167,162,158,153,149,145,140,136,131,131}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95, 99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,247,243,239,235,231,227,223,219,215,211,207,203,199,195,191,187,183,179,175,171,167,163,159,155,151,147,143,139,135,131,127,123,119,115,111,107,103, 99, 95, 91, 87, 83, 79, 75, 71, 67, 63, 59, 55, 51, 47, 43, 39, 35, 31, 27, 23, 19, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={131,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,247,243,239,235,231,227,223,219,215,211,207,203,199,195,191,187,183,179,175,171,167,163,159,155,151,147,143,139,135,131,127,123,119,115,111,107,103, 99, 95, 91, 87, 83, 79, 75, 71, 67, 63, 59, 55, 51, 47, 43, 39, 35, 31, 27, 23, 19, 15, 11, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Blue-Red",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={124,124,120,115,111,106,102, 97, 93, 88, 84, 79, 75, 70, 66, 61, 57, 52, 48, 43, 39, 34, 30, 25, 21, 16, 12, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 13, 14, 19, 23, 28, 32, 37, 41, 46, 50, 55, 59, 64, 68, 73, 77, 82, 86, 91, 95,100,104,109,113,118,123,127,132,136,141,145,150,154,159,163,168,172,177,181,186,190,195,199,204,208,213,217,222,226,231,235,240,244,249,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 11, 15, 20, 24, 29, 33, 38, 42, 47, 51, 56, 60, 65, 69, 74, 78, 83, 87, 92, 96,101,105,110,114,119,123,128,132,137,141,146,150,155,159,164,168,173,177,182,186,191,195,200,204,209,213,218,222,227,231,236,241,245,250,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,252,248,243,239,234,230,225,221,216,212,207,203,198,194,189,185,180,176,171,167,162,158,153,149,144,140,135,131,126,122,117,113,108,104, 99, 95, 90, 86, 81, 77, 72, 68, 63, 59, 54, 50, 45, 41, 36, 32, 27, 23, 18, 14, 9, 5, 5}; DByte b[256]={255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,247,242,238,233,229,224,220,215,211,206,202,197,193,188,184,179,175,170,166,161,157,152,148,143,139,134,130,125,121,116,112,107,103, 98, 94, 89, 85, 80, 76, 71, 67, 62, 58, 53, 49, 44, 40, 35, 31, 26, 22, 17, 13, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Rainbow",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 82, 82, 77, 73, 68, 63, 59, 54, 50, 46, 42, 38, 34, 30, 26, 23, 19, 16, 13, 13, 8, 5, 3, 1, 0, 2, 3, 5, 6, 6, 7, 7, 8, 7, 7, 6, 6, 5, 3, 2, 0, 1, 3, 5, 8, 13, 13, 16, 19, 23, 26, 30, 34, 38, 42, 46, 50, 54, 59, 63, 68, 73, 77, 82, 87, 91, 96,100,105,110,114,119,123,127,131,135,139,143,147,150,154,157,160,163,165,168,170,172,174,176,177,179,180,180,181,181,182,181,181,180,180,179,177,176,174,172,170,168,165,163,160,157,154,150,147,143,139,135,131,127,123,119,114,110,105,100, 96, 91, 86, 82, 77, 73, 68, 63, 59, 54, 50, 46, 42, 38, 34, 30, 26, 23, 19, 16, 13, 13, 8, 5, 3, 1, 0, 2, 3, 5, 6, 6, 7, 7, 8, 7, 7, 6, 6, 5, 3, 2, 0, 1, 3, 5, 8, 13, 13, 16, 19, 23, 26, 30, 34, 38, 42, 46, 50, 54, 59, 63, 68, 73, 77, 82, 87, 91, 96,100,105,110,114,119,123,127,131,135,139,143,147,150,154,157,160,163,165,168,170,172,174,176,177,179,180,180,181,181,182,181,181,180,180,179,177,176,174,172,170,168,165,163,160,157,154,150,147,143,139,135,131,127,123,119,114,110,105,100, 96, 96}; DByte g[256]={ 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 9, 13, 11, 12, 13, 15, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 32, 34, 35, 37, 39, 41, 43, 45, 46, 48, 50, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 66, 66, 65, 64, 64, 63, 62, 61, 60, 59, 57, 56, 55, 54, 53, 52, 51, 49, 48, 47, 47, 46, 45, 44, 44, 44, 43, 43, 43, 43, 44, 44, 45, 46, 47, 48, 50, 51, 53, 55, 57, 60, 62, 65, 68, 71, 74, 78, 81, 85, 88, 92, 96,100,104,108,112,116,120,124,128,132,136,140,144,148,151,154,158,161,164,166,169,171,173,175,176,178,179,180,180,180,180,180,179,179,178,176,175,173,171,169,166,164,161,158,155,152,148,145,141,138,134,131,127,124,120,117,113,110,107,104,101, 99, 97, 95, 93, 91, 90, 89, 88, 88, 88, 88, 88, 89, 91, 92, 94, 96, 99,102,105,109,113,117,122,127,132,137,142,148,154,160,166,173,179,186,192,199,205,212,218,225,231,237,243,248,254,251,246,241,237,233,229,226,223,220,218,216,215,214,213,213,214,214,216,217,219,222,224,228,231,235,239,244,248,253,251,246,240,234,234}; DByte b[256]={214,214,202,189,177,165,153,141,129,118,107, 96, 85, 75, 65, 56, 47, 38, 30, 22, 15, 9, 2, 2, 7, 12, 16, 19, 22, 24, 25, 26, 27, 26, 25, 24, 22, 19, 16, 12, 7, 2, 2, 9, 15, 22, 30, 38, 47, 56, 65, 75, 85, 96,107,118,129,141,153,165,177,189,202,214,227,239,251,246,234,222,210,198,186,175,164,153,142,132,122,113,104, 95, 87, 79, 72, 66, 59, 54, 49, 44, 40, 37, 34, 32, 31, 30, 29, 30, 31, 32, 34, 37, 40, 44, 49, 54, 59, 66, 72, 79, 87, 95,104,113,122,132,142,153,164,175,186,198,210,222,234,246,251,239,226,214,202,189,177,165,153,141,129,118,107, 96, 85, 75, 65, 56, 47, 38, 30, 22, 15, 9, 2, 2, 7, 12, 16, 19, 22, 24, 25, 26, 27, 26, 25, 24, 22, 19, 16, 12, 7, 2, 2, 9, 15, 22, 30, 38, 47, 56, 65, 75, 85, 96,107,118,129,141,153,165,177,189,202,214,227,239,251,246,234,222,210,198,186,175,164,153,142,132,122,113,104, 95, 87, 79, 72, 66, 59, 54, 49, 44, 40, 37, 34, 32, 31, 30, 29, 30, 31, 32, 34, 37, 40, 44, 49, 54, 59, 66, 72, 79, 87, 95,104,113,122,132,142,153,164,175,186,198,210,222,234,246,251,251}; CT.push_back(GDLCT("Blue Waves",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 64, 64, 60, 57, 54, 51, 48, 45, 42, 40, 37, 35, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 12, 11, 13, 9, 9, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 13, 11, 12, 13, 14, 15, 17, 18, 20, 22, 23, 25, 27, 30, 32, 34, 37, 39, 42, 44, 47, 50, 53, 56, 59, 63, 66, 70, 73, 77, 80, 84, 88, 92, 96,100,104,109,113,117,122,126,131,136,140,145,150,155,160,165,170,175,180,186,191,196,201,207,212,218,223,229,234,240,246,251,253,247,241,236,230,224,218,213,207,201,195,189,183,178,172,166,160,154,148,143,137,131,125,120,114,108,103, 97, 92, 86, 80, 75, 70, 64, 59, 53, 48, 43, 38, 33, 28, 23, 18, 13, 8, 3, 1, 5, 13, 15, 19, 23, 28, 32, 36, 40, 44, 48, 52, 56, 60, 63, 67, 70, 73, 77, 80, 83, 86, 89, 92, 94, 97,100,102,104,107,109,111,113,114,116,118,119,121,122,123,124,125,126,127,128,128,129,129,129,129,129,129,129,129,129,128,127,127,126,125,124,123,122,120,119,117,116,114,112,110,108,106,103,101, 99, 96, 93, 91, 88, 85, 82, 79, 75, 72, 69, 65, 62, 58, 54, 50, 47, 43, 39, 34, 30, 26, 22, 17, 13, 8, 8}; DByte g[256]={ 35, 35, 40, 44, 49, 54, 58, 63, 67, 72, 76, 80, 84, 89, 93, 96,100,104,108,111,115,118,121,124,127,130,133,135,137,140,142,144,145,147,148,150,151,152,152,153,153,153,153,153,153,153,152,151,150,149,148,146,145,143,141,139,137,134,132,129,126,123,120,117,113,110,106,103, 99, 95, 91, 87, 83, 79, 74, 70, 66, 61, 57, 52, 47, 43, 38, 33, 29, 24, 19, 15, 13, 5, 1, 3, 7, 12, 16, 20, 25, 29, 33, 37, 41, 45, 49, 53, 56, 60, 63, 66, 69, 72, 75, 78, 80, 83, 85, 87, 89, 91, 92, 94, 95, 96, 97, 98, 99, 99, 99, 99, 99, 99, 99, 98, 97, 97, 95, 94, 93, 91, 89, 88, 86, 83, 81, 78, 76, 73, 70, 67, 64, 61, 57, 54, 50, 46, 42, 38, 34, 30, 26, 22, 17, 13, 9, 4, 0, 4, 9, 13, 18, 23, 27, 32, 37, 41, 46, 51, 55, 60, 64, 69, 73, 77, 82, 86, 90, 94, 98,102,105,109,112,116,119,122,125,128,131,133,136,138,140,142,144,146,147,149,150,151,152,152,153,153,153,153,153,153,152,152,151,150,149,147,146,144,142,140,138,136,133,131,128,125,122,119,116,112,109,105,101, 98, 94, 90, 86, 81, 77, 73, 68, 64, 60, 55, 50, 46, 41, 37, 32, 32}; DByte b[256]={116,116,105, 94, 84, 74, 64, 55, 46, 38, 30, 24, 18, 12, 8, 5, 2, 0, 0, 0, 1, 3, 6, 13, 14, 20, 26, 33, 41, 50, 59, 68, 78, 88, 99,109,120,131,142,153,163,174,184,193,202,211,218,226,232,238,243,247,250,252,253,253,253,251,249,246,241,236,230,224,216,208,200,190,181,171,160,150,139,128,117,106, 96, 85, 75, 65, 56, 47, 39, 31, 24, 18, 13, 9, 5, 2, 0, 0, 0, 1, 3, 5, 9, 14, 19, 25, 32, 40, 48, 57, 67, 76, 87, 97,108,119,130,140,151,162,172,182,192,201,209,217,225,231,237,242,246,249,252,253,254,253,252,249,246,242,237,231,225,217,209,201,192,182,172,162,151,140,130,119,108, 97, 87, 76, 67, 57, 48, 40, 32, 25, 19, 14, 9, 5, 3, 1, 0, 0, 0, 2, 5, 9, 13, 18, 24, 31, 39, 47, 56, 65, 75, 85, 96,106,117,128,139,150,160,171,181,190,200,208,216,224,230,236,241,246,249,251,253,253,253,252,250,247,243,238,232,226,218,211,202,193,184,174,163,153,142,131,120,109, 99, 88, 78, 68, 59, 50, 41, 33, 26, 20, 14, 13, 6, 3, 1, 0, 0, 0, 2, 5, 8, 12, 18, 24, 30, 38, 46, 55, 64, 74, 84, 94,105,105}; CT.push_back(GDLCT("Volcano",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={124,124,121,118,115,112,109,106,103,100, 97, 94, 91, 88, 85, 82, 79, 76, 73, 70, 68, 65, 62, 60, 57, 54, 52, 49, 47, 45, 42, 40, 38, 36, 33, 31, 29, 27, 25, 24, 22, 20, 19, 17, 15, 14, 13, 11, 13, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 13, 11, 13, 14, 15, 17, 19, 20, 22, 24, 25, 27, 29, 31, 33, 36, 38, 40, 42, 45, 47, 49, 52, 54, 57, 60, 62, 65, 68, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97,100,103,106,109,112,115,118,121,124,128,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,179,182,185,187,190,193,195,198,201,203,206,208,210,213,215,217,219,222,224,226,228,230,231,233,235,236,238,240,241,242,244,245,246,247,248,249,250,251,251,252,253,253,254,254,254,254,254,255,254,254,254,254,254,253,253,252,251,251,250,249,248,247,246,245,244,242,241,240,238,236,235,233,231,230,228,226,224,222,219,217,215,213,210,208,206,203,201,198,195,193,190,187,185,182,179,176,173,170,167,164,161,158,155,152,149,146,143,140,137,134,134}; DByte g[256]={121,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 97, 72, 52, 38, 34, 38, 52, 72, 96,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 72, 97,121,141,155,160,155,141,121, 96, 72, 52, 38, 34, 38, 52, 52}; DByte b[256]={131,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,179,182,185,187,190,193,195,198,201,203,206,208,210,213,215,217,219,222,224,226,228,230,231,233,235,236,238,240,241,242,244,245,246,247,248,249,250,251,251,252,253,253,254,254,254,254,254,255,254,254,254,254,254,253,253,252,251,251,250,249,248,247,246,245,244,242,241,240,238,236,235,233,231,230,228,226,224,222,219,217,215,213,210,208,206,203,201,198,195,193,190,187,185,182,179,176,173,170,167,164,161,158,155,152,149,146,143,140,137,134,131,127,124,121,118,115,112,109,106,103,100, 97, 94, 91, 88, 85, 82, 79, 76, 73, 70, 68, 65, 62, 60, 57, 54, 52, 49, 47, 45, 42, 40, 38, 36, 33, 31, 29, 27, 25, 24, 22, 20, 19, 17, 15, 14, 13, 11, 13, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 13, 11, 13, 14, 15, 17, 19, 20, 22, 24, 25, 27, 29, 31, 33, 36, 38, 40, 42, 45, 47, 49, 52, 54, 57, 60, 62, 65, 68, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97,100,103,106,109,112,115,118,121,121}; CT.push_back(GDLCT("Waves",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,175,175,175,175,175,175,175,175,175,175,175,175,175,175,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,255,255}; DByte b[256]={ 0,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,255,255}; CT.push_back(GDLCT("Rainbow18",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 45, 50, 58, 61, 64, 68, 69, 72, 74, 77, 79, 80, 82, 83, 84, 86, 87, 88, 86, 87, 87, 87, 85, 84, 84, 84, 79, 78, 77, 76, 71, 70, 68, 66, 60, 58, 55, 46, 43, 40, 36, 33, 25, 21, 16, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 21, 25, 29, 42, 46, 51, 55, 63, 67, 72, 76, 80, 89, 93, 97,110,114,119,123,131,135,140,144,153,157,161,165,178,182,187,191,199,203,208,212,221,225,229,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 16, 21, 25, 29, 38, 42, 46, 51, 55, 63, 67, 72, 84, 89, 93, 97,106,110,114,119,127,131,135,140,152,157,161,165,174,178,182,187,195,199,203,216,220,225,229,233,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,242,238,233,229,221,216,212,199,195,191,187,178,174,170,165,161,153,148,144,131,127,123,119,110,106,102, 97, 89, 85, 80, 76, 63, 59, 55, 51, 42, 38, 34, 29, 21, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255}; DByte b[256]={ 0, 3, 7, 10, 14, 19, 23, 28, 32, 38, 43, 48, 59, 63, 68, 72, 77, 81, 86, 91, 95,100,104,109,118,122,127,132,136,141,145,150,154,159,163,168,177,182,186,191,195,200,204,209,214,218,223,232,236,241,245,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,242,238,225,220,216,212,203,199,195,191,187,178,174,170,157,152,148,144,135,131,127,123,114,110,106,102, 89, 84, 80, 76, 67, 63, 59, 55, 46, 42, 38, 25, 21, 16, 12, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255}; CT.push_back(GDLCT("Rainbow + white",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers DByte r[256]={ 0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 45, 50, 58, 61, 64, 68, 69, 72, 74, 77, 79, 80, 82, 83, 84, 86, 87, 88, 86, 87, 87, 87, 85, 84, 84, 84, 79, 78, 77, 76, 71, 70, 68, 66, 60, 58, 55, 46, 43, 40, 36, 33, 25, 21, 16, 12, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 21, 25, 29, 42, 46, 51, 55, 63, 67, 72, 76, 80, 89, 93, 97,110,114,119,123,131,135,140,144,153,157,161,165,178,182,187,191,199,203,208,212,221,225,229,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0}; DByte g[256]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 16, 21, 25, 29, 38, 42, 46, 51, 55, 63, 67, 72, 84, 89, 93, 97,106,110,114,119,127,131,135,140,152,157,161,165,174,178,182,187,195,199,203,216,220,225,229,233,242,246,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,250,242,238,233,229,221,216,212,199,195,191,187,178,174,170,165,161,153,148,144,131,127,123,119,110,106,102, 97, 89, 85, 80, 76, 63, 59, 55, 51, 42, 38, 34, 29, 21, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DByte b[256]={ 0, 3, 7, 10, 14, 19, 23, 28, 32, 38, 43, 48, 59, 63, 68, 72, 77, 81, 86, 91, 95,100,104,109,118,122,127,132,136,141,145,150,154,159,163,168,177,182,186,191,195,200,204,209,214,218,223,232,236,241,245,250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,242,238,225,220,216,212,203,199,195,191,187,178,174,170,157,152,148,144,135,131,127,123,114,110,106,102, 89, 84, 80, 76, 67, 63, 59, 55, 46, 42, 38, 25, 21, 16, 12, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; CT.push_back(GDLCT("Rainbow + black",r,g,b,256)); } // local identifiers { // make r, g, b local identifiers // 0 2 4 6 8 10 12 14 DByte r[16] ={ 0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xf5, 0xbe, 0xa5, 0x00, 0x8a, 0x00, 0x40, 0xff, 0xfa, 0xff }; DByte g[16] ={ 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0, 0xde, 0xbe, 0x2a, 0x00, 0x2b, 0xff, 0xe0, 0x00, 0x80, 0xff }; DByte b[16] ={ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xcb, 0xb3, 0xbe, 0x2a, 0xff, 0xe2, 0xff, 0xd0, 0xff, 0x72, 0xff }; CT.push_back(GDLCT("Tektronix default",r,g,b,16)); } // local identifiers // init actCT to tektronix default,AKA "DEFAULT" of the constructor GDLCT. actCT = GDLCT(); } /* 0 black 0x00, 0x00, 0x00 1 red 0xff, 0x00, 0x00 2 yellow 0xff, 0xff, 0x00 3 green 0x00, 0xff, 0x00 4 aquamarine 0x7f, 0xff, 0xd4 5 pink 0xff, 0xC0, 0xCB 6 wheat 0xf5, 0xDE, 0xb3 7 grey 0xbe, 0xbe, 0xbe 8 brown 0xA5, 0x2A, 0x2a 9 blue 0x00, 0x00, 0xff 10 BlueViolet 0x8A, 0x2B, 0xe2 11 cyan 0x00, 0xff, 0xff 12 turquoise 0x40, 0xE0, 0xd0 13 magenta 0xff, 0x00, 0xff 14 salmon 0xfa, 0x80, 0x72 15 white 0xff, 0xff, 0xff */ gdl-0.9.9/src/initsysvar.cpp000066400000000000000000001130141340051421000157730ustar00rootroot00000000000000/*************************************************************************** initsysvar.cpp - definition of GDL system variables ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifndef _WIN32 #include #endif #include #include #ifdef _OPENMP #include // for !CPU #endif #include "nullgdl.hpp" #include "objects.hpp" #include "dstructgdl.hpp" #include "graphicsdevice.hpp" #include "file.hpp" #ifdef _MSC_VER #include "gtdhelper.hpp" #else #include #endif #ifndef BUILD_DATE #define BUILD_DATE __DATE__ #endif namespace SysVar { using namespace std; // the index of some system variables UInt nullIx, trueIx, falseIx, pathIx, promptIx, edit_inputIx, quietIx, dIx, pIx, xIx, yIx, zIx, vIx, gdlWarningIx, gdlIx, cIx, MouseIx, errorStateIx, errorIx, errIx, err_stringIx, valuesIx, journalIx, exceptIx, mapIx, cpuIx, dirIx, GshhsDirIx, stimeIx, warnIx, usersymIx, orderIx, MakeDllIx, colorIx; // !D structs const int nDevices = 5; DStructGDL* devices[ 5]; // NULL, PS, Z, SVG, (X or WIN or nothing) // !STIME const SizeT MAX_STIME_STRING_LENGTH=80; bool IsSTime( DVar* var) { // due to .RESET_SESSION we cannot use static here // but the effect will be minimal anyway // static DVar* varSTime = sysVarList[ stimeIx]; return var == sysVarList[ stimeIx]; } // bool IsD( DVar* var) // { // return var == sysVarList[ dIx]; // } void SetGDLPath( const DString& newPath) { FileListT sArr; #ifdef _WIN32 char pathsep[]=";"; #else char pathsep[]=":"; #endif SizeT d; long sPos=0; do { d=newPath.find(pathsep[0],sPos); string act = newPath.substr(sPos,d-sPos); lib::ExpandPath( sArr, act, "*.pro"); sPos=d+1; } while( d != newPath.npos); SizeT nArr = sArr.size(); if( nArr == 0) return; // get the path DVar& pathSysVar=*sysVarList[pathIx]; DString& path=static_cast(*pathSysVar.Data())[0]; // set the path path = sArr[0]; for( SizeT i=1; i( *dirSysVar.Data())[0]; } // updates !STIME (as a plain DString) void UpdateSTime() { DVar& stimeSysVar = *sysVarList[ stimeIx]; DString& stime=static_cast(*stimeSysVar.Data())[0]; struct timeval tval; struct timezone tzone; struct tm *tstruct; gettimeofday(&tval,&tzone); time_t ttime = tval.tv_sec; tstruct= localtime(&ttime); char st[MAX_STIME_STRING_LENGTH]; const char *format="%d-%h-%Y %T.00";// !STIME format. SizeT res=strftime( st, MAX_STIME_STRING_LENGTH, format, tstruct); stime = st; } DStructGDL* D() { DVar& var = *sysVarList[ dIx]; return static_cast(var.Data()); } // // updates !D in all modes (should insure correct update if Win, XWidgets ...) // void UpdateD() // { // DStructGDL* dD = D(); // // DLong windowIdx=(*static_cast(dD->GetTag(dD->Desc()->TagIndex("WINDOW"), 0)))[0]; // if( windowIdx <0) return; // // GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); // GDLGStream* actStream = actDevice->GetStream(); // // long xSizeGG,ySizeGG; // actStream->GetGeometry(xSizeGG,ySizeGG); // int debug=0; // if (debug) cout << "GetX11Geo in SysVar::UpdateD : " << xSizeGG <<" "<< ySizeGG << endl; // // (*static_cast(dD->GetTag(dD->Desc()->TagIndex("X_SIZE"), 0)))[0] = xSizeGG; // (*static_cast(dD->GetTag(dD->Desc()->TagIndex("Y_SIZE"), 0)))[0] = ySizeGG; // (*static_cast(dD->GetTag(dD->Desc()->TagIndex("X_VSIZE"), 0)))[0] = xSizeGG; // (*static_cast(dD->GetTag(dD->Desc()->TagIndex("Y_VSIZE"), 0)))[0] = ySizeGG; // } // returns array of path strings const StrArr& GDLPath() { static StrArr sArr; // clear whatever old value is stored sArr.clear(); // get the path DVar& pathSysVar=*sysVarList[pathIx]; DString& path=static_cast(*pathSysVar.Data())[0]; if( path == "") return sArr; SizeT d; long sPos=0; #ifdef _WIN32 char pathsep[]=";"; #else char pathsep[]=":"; #endif do { d=path.find(pathsep[0],sPos); sArr.push_back(path.substr(sPos,d-sPos)); sPos=d+1; } while( d != path.npos); return sArr; } const string& Prompt() { DVar& promptSysVar=*sysVarList[promptIx]; return static_cast(*promptSysVar.Data())[0]; } int Edit_Input() { DVar& eiSysVar=*sysVarList[edit_inputIx]; return static_cast(*eiSysVar.Data())[0]; } DLong Quiet() { DVar& qSysVar=*sysVarList[quietIx]; return static_cast(*qSysVar.Data())[0]; } DLong GDL_Warning() { DVar& gwSysVar=*sysVarList[gdlWarningIx]; return static_cast(*gwSysVar.Data())[0]; } void SetC( DLong cVal) { DVar& cSysVar=*sysVarList[cIx]; static_cast(*cSysVar.Data())[0] = cVal; } void SetD( BaseGDL* newD) { DVar& dSysVar = *sysVarList[ dIx]; dSysVar.Data() = newD; } void SetErr_String( const DString& eS) { DVar& eSSysVar = *sysVarList[ err_stringIx]; static_cast(*eSSysVar.Data())[0] = eS; } void SetErrError( DLong eC) { DVar& errSysVar = *sysVarList[ errIx]; DVar& errorSysVar = *sysVarList[ errorIx]; static_cast(*errSysVar.Data())[0] = eC; static_cast(*errorSysVar.Data())[0] = eC; } DStructGDL* P() { DVar& pSysVar = *sysVarList[ pIx]; return static_cast(pSysVar.Data()); } DLongGDL* GetPMulti() { DStructGDL* pStruct = SysVar::P(); //MUST NOT BE STATIC, due to .reset static int tag = pStruct->Desc()->TagIndex( "MULTI"); return static_cast( pStruct->GetTag( tag, 0)); } DLong GetPFont() { DStructGDL* pStruct = SysVar::P(); //MUST NOT BE STATIC, due to .reset static int tag = pStruct->Desc()->TagIndex( "FONT"); return (*static_cast( pStruct->GetTag( tag)))[0]; } const DString& GshhsDir() { DVar& var = *sysVarList[GshhsDirIx]; return static_cast(*var.Data())[0]; } DStringGDL* STime() { DVar& var = *sysVarList[ stimeIx]; return static_cast(var.Data()); } DStructGDL* X() { DVar& var = *sysVarList[ xIx]; return static_cast(var.Data()); } DStructGDL* Y() { DVar& var = *sysVarList[ yIx]; return static_cast(var.Data()); } DStructGDL* Z() { DVar& var = *sysVarList[ zIx]; return static_cast(var.Data()); } DStructGDL* Version() { DVar& var = *sysVarList[ vIx]; return static_cast(var.Data()); } void SetFakeRelease( DString release) { DVar& var = *sysVarList[ vIx]; DStructGDL *s=static_cast(var.Data()); static int tag = s->Desc()->TagIndex( "RELEASE"); (*static_cast( s->GetTag( tag)))[0] = release; } DStructGDL* Values() { DVar& var = *sysVarList[ valuesIx]; return static_cast(var.Data()); } DStructGDL* Error_State() { DVar& var = *sysVarList[ errorStateIx]; return static_cast(var.Data()); } DStructGDL* Map() { DVar& var = *sysVarList[ mapIx]; return static_cast(var.Data()); } DStructGDL* Mouse() { DVar& var = *sysVarList[ MouseIx]; return static_cast(var.Data()); } DStructGDL* Cpu() { DVar* sysVarList_cpuIx = sysVarList[ cpuIx]; return static_cast(sysVarList_cpuIx->Data()); } DStructGDL* Warn() { DVar* sysVarList_warnIx = sysVarList[ warnIx]; return static_cast(sysVarList_warnIx->Data()); } DString MsgPrefix() { DStructGDL* errorState = Error_State(); static unsigned msgTag = errorState->Desc()->TagIndex( "MSG_PREFIX"); return (*static_cast( errorState->GetTag( msgTag, 0)))[0]; } DLong JournalLUN() { DVar& jSysVar=*sysVarList[journalIx]; return static_cast(*jSysVar.Data())[0]; } void JournalLUN( DLong jLUN) { DVar& jSysVar=*sysVarList[journalIx]; static_cast(*jSysVar.Data())[0] = jLUN; } DLong TV_ORDER() { DVar& orderVar=*sysVarList[orderIx]; return static_cast(*orderVar.Data())[0]; } // call only once in main void InitSysVar() { // for very sensitive compilers (which need a SizeT for dimension()) const SizeT one=1; // !NULL NullGDL* nullInstance = NullGDL::GetSingleInstance(); DVar *nullVar = new DVar( "NULL", nullInstance); nullIx=sysVarList.size(); sysVarList.push_back(nullVar); // !TRUE DByteGDL* trueData = new DByteGDL(1); DVar *true_logical = new DVar( "TRUE", trueData ); trueIx=sysVarList.size(); sysVarList.push_back(true_logical); // !FALSE DByteGDL* falseData = new DByteGDL(0); DVar *false_logical = new DVar( "FALSE", falseData ); falseIx=sysVarList.size(); sysVarList.push_back(false_logical); // !PATH // DString initPath(""); // set here the initial path DStringGDL* pathData=new DStringGDL( ""); DVar *path=new DVar( "PATH", pathData); pathIx=sysVarList.size(); sysVarList.push_back(path); // !PROMPT DStringGDL* promptData=new DStringGDL( "GDL> "); DVar *prompt=new DVar( "PROMPT", promptData); promptIx=sysVarList.size(); sysVarList.push_back(prompt); // !EDIT_INPUT DIntGDL* edit_inputData=new DIntGDL( 1); DVar *edit_input=new DVar( "EDIT_INPUT", edit_inputData); edit_inputIx=sysVarList.size(); sysVarList.push_back(edit_input); // !QUIET DLongGDL* quietData=new DLongGDL( 0); DVar *quiet=new DVar( "QUIET", quietData); quietIx=sysVarList.size(); sysVarList.push_back(quiet); // !C DLongGDL* cData=new DLongGDL( 0); DVar *c=new DVar( "C", cData); cIx=sysVarList.size(); sysVarList.push_back(c); // !D defined in Graphics DVar *d=new DVar( "D", NULL); dIx=sysVarList.size(); sysVarList.push_back(d); sysVarRdOnlyList.push_back( d); // make it read only // plotting // !P SizeT clipDim = 6; // DLong p_clipInit[] = { 0, 0, 1024, 1024, 0, 1000}; DLong p_clipInit[] = { 0, 0, 639, 511, 0, 0}; DLongGDL* p_clip = new DLongGDL( dimension( &clipDim, one)); for( UInt i=0; iNewTag("BACKGROUND", new DLongGDL( 0)); plt->NewTag("CHARSIZE", new DFloatGDL( 0.0)); plt->NewTag("CHARTHICK", new DFloatGDL( 0.0)); plt->NewTag("CLIP", p_clip); plt->NewTag("COLOR", new DLongGDL( 255)); plt->NewTag("FONT", new DLongGDL( -1)); plt->NewTag("LINESTYLE", new DLongGDL( 0)); plt->NewTag("MULTI", new DLongGDL( dimension( &multiDim, one))); plt->NewTag("NOCLIP", new DLongGDL( 0)); plt->NewTag("NOERASE", new DLongGDL( 0)); plt->NewTag("NSUM", new DLongGDL( 0)); plt->NewTag("POSITION", new DFloatGDL( dimension( &positionDim, one))); plt->NewTag("PSYM", new DLongGDL( 0)); plt->NewTag("REGION", new DFloatGDL( dimension( ®ionDim, one))); plt->NewTag("SUBTITLE", new DStringGDL( "")); plt->NewTag("SYMSIZE", new DFloatGDL( 0.0)); { DDoubleGDL* tmp = new DDoubleGDL( dimension( tDim, 2)); (*tmp)[0] = (*tmp)[5] = (*tmp)[10] = (*tmp)[15] = 1; plt->NewTag("T", tmp); } plt->NewTag("T3D", new DLongGDL( 0)); plt->NewTag("THICK", new DFloatGDL( 0.0)); plt->NewTag("TITLE", new DStringGDL( "")); plt->NewTag("TICKLEN", new DFloatGDL( 0.02)); plt->NewTag("CHANNEL", new DLongGDL( 0)); DVar *p=new DVar( "P", plt); pIx=sysVarList.size(); sysVarList.push_back(p); // some constants // !ORDER DLongGDL *orderData = new DLongGDL( 0 ); DVar *order = new DVar( "ORDER", orderData); orderIx = sysVarList.size(); sysVarList.push_back( order); // !GDL_WARNING (to be used in VOIGT() and BeselIJKY() to warm on // different behaviour between IDL and GDL DLongGDL *gdlWarningData = new DLongGDL( 1 ); DVar *gdlWarning = new DVar( "GDL_WARNING", gdlWarningData); gdlWarningIx = sysVarList.size(); sysVarList.push_back( gdlWarning); // !GDL (to allow distinguish IDL/GDL with DEFSYSV, '!gdl', exists=exists ) DStructGDL* gdlStruct = new DStructGDL( "!GNUDATALANGUAGE"); gdlStruct->NewTag("RELEASE", new DStringGDL( VERSION)); // creating an explicit build date in !GDL (also exist in !version) gdlStruct->NewTag("BUILD_DATE", new DStringGDL(BUILD_DATE)); // creating and Epoch entry in order to have a simple incremental number int CompilationMonth =0, CompilationYear=0, CompilationDay=0; string MyDate= BUILD_DATE; string SCompilationYear; SCompilationYear=MyDate.substr(7,4); CompilationYear=atoi(SCompilationYear.c_str()); string SCompilationDay; SCompilationDay=MyDate.substr(4,2); CompilationDay=atoi(SCompilationDay.c_str()); // for the months, it is more difficult if (MyDate.find("Jan")!=string::npos) CompilationMonth=1; if (MyDate.find("Feb")!=string::npos) CompilationMonth=2; if (MyDate.find("Mar")!=string::npos) CompilationMonth=3; if (MyDate.find("Apr")!=string::npos) CompilationMonth=4; if (MyDate.find("May")!=string::npos) CompilationMonth=5; if (MyDate.find("Jun")!=string::npos) CompilationMonth=6; if (MyDate.find("Jul")!=string::npos) CompilationMonth=7; if (MyDate.find("Aug")!=string::npos) CompilationMonth=8; if (MyDate.find("Sep")!=string::npos) CompilationMonth=9; if (MyDate.find("Oct")!=string::npos) CompilationMonth=10; if (MyDate.find("Nov")!=string::npos) CompilationMonth=11; if (MyDate.find("Dec")!=string::npos) CompilationMonth=12; //cout << SCompilationYear << " "<< CompilationMonth <NewTag("EPOCH", new DLongGDL((long) t_of_day)); DVar *gdl = new DVar( "GDL", gdlStruct); sysVarList.push_back(gdl); sysVarRdOnlyList.push_back( gdl); // make it read only // !DPI DDoubleGDL *dpiData = new DDoubleGDL( (double)(4*atan(1.0)) ); DVar *dpi = new DVar( "DPI", dpiData); sysVarList.push_back( dpi); sysVarRdOnlyList.push_back( dpi); // make it read only // !PI DFloatGDL *piData = new DFloatGDL( (float)(4*atan(1.0)) ); DVar *pi = new DVar( "PI", piData); sysVarList.push_back( pi); sysVarRdOnlyList.push_back( pi); // make it read only // !DTOR DFloatGDL *dtorData = new DFloatGDL((*piData)[0] / 180.);// 0.0174533); DVar *dtor = new DVar( "DTOR", dtorData); sysVarList.push_back( dtor); sysVarRdOnlyList.push_back( dtor); // make it read only // !RADEG DFloatGDL *radegData = new DFloatGDL(180. / (*piData)[0]);// 57.2957764); DVar *radeg = new DVar( "RADEG", radegData); sysVarList.push_back( radeg); sysVarRdOnlyList.push_back( radeg); // make it read only // !CONST // source : http://physics.nist.gov/cgi-bin/cuu/Results?category=abbr_in DStructGDL *constantList = new DStructGDL( "!CONST"); // Fine structure constant constantList ->NewTag("ALPHA", new DDoubleGDL(7.2973525698e-3)); // Astronomical Unit [m] constantList ->NewTag("AU", new DDoubleGDL(1.49597870700e11)); // Speed of Light in Vacuum [m/s] constantList ->NewTag("C", new DDoubleGDL(299792458.)); // Degrees to radians constantList ->NewTag("DTOR", new DDoubleGDL((*dpiData)[0] / 180.)); // Elementary Charge [Coulon] constantList ->NewTag("E", new DDoubleGDL(1.602176565e-19)); // Electric Vacuum Permittivity [F/m] constantList ->NewTag("EPS0", new DDoubleGDL(8.854187817e-12)); // Euler's number constantList ->NewTag("EULER", new DDoubleGDL(2.7182818284590452)); // Faraday constant NAe [C/mol] constantList ->NewTag("F", new DDoubleGDL(96485.3365)); // Gravitation constant [m^3/kg/s^2] constantList ->NewTag("G", new DDoubleGDL(6.67384e-11)); // Earth standard gravity [m/s^2] constantList ->NewTag("GN", new DDoubleGDL(9.80665)); // Planck constant [Js] constantList ->NewTag("H", new DDoubleGDL(6.62606957e-34)); // h_bar (h/!pi) [Js] constantList ->NewTag("HBAR", new DDoubleGDL(1.054571726e-34)); //Imaginary number complex imaginary(0., 1.); constantList ->NewTag("I", new DComplexDblGDL(imaginary)); // Boltzmann constant (R/NA) [J/K] constantList ->NewTag("K", new DDoubleGDL(1.3806488e-23 )); // Light-Year distance [m] constantList ->NewTag("LY", new DDoubleGDL(9.4607304725808e15)); // Mass of the Earth [kg] constantList ->NewTag("M_EARTH", new DDoubleGDL(5.972186390e24)); // Mass of the Sun [kg] constantList ->NewTag("M_SUN", new DDoubleGDL(1.98841586057e30)); // electron mass [kg] constantList ->NewTag("ME", new DDoubleGDL(9.10938291e-31)); // neutron mass [kg] constantList ->NewTag("MN", new DDoubleGDL(1.674927351e-27)); // proton mass [kg] constantList ->NewTag("MP", new DDoubleGDL(1.672621777e-27)); // magnetic vacuum permeability [N/A^2] constantList ->NewTag("MU0", new DDoubleGDL(12.566370614e-7)); // Loschmidt's number NAp0/(RT0) [m-3] constantList ->NewTag("N0", new DDoubleGDL(2.6867805e25)); // Avogadro constant NA [mol-1] constantList ->NewTag("NA", new DDoubleGDL(6.02214129e23)); // Standard atmosphere Pression [Pa] constantList ->NewTag("P0", new DDoubleGDL(101325.)); // Parsec distance [m] constantList ->NewTag("PARSEC", new DDoubleGDL(3.0856775814671912e16)); //golden ratio ((1+sqrt(5))/2) constantList ->NewTag("PHI", new DDoubleGDL(1.6180339887498948)); // Pi constantList ->NewTag("PI", new DDoubleGDL((*dpiData)[0])); // molar gas constant [J/mol/K] constantList ->NewTag("R", new DDoubleGDL(8.3144621)); // Earth radius (assuming spherical) [m] constantList ->NewTag("R_EARTH", new DDoubleGDL(6378136.6)); // Radians to degrees constantList ->NewTag("RTOD", new DDoubleGDL(180./(*dpiData)[0])); // classical electron radius [m] constantList ->NewTag("RE", new DDoubleGDL(2.8179403267e-15)); // Rydberg constant R∞ [1/m] constantList ->NewTag("RYDBERG", new DDoubleGDL(10973731.568539)); // Stefan-Boltzmann constant [W/m^2/K^4] constantList ->NewTag("SIGMA", new DDoubleGDL(5.670373e-8)); // Standard temperature [K] constantList ->NewTag("T0", new DDoubleGDL(273.15)); // unified atomic mass unit [kg] constantList ->NewTag("U", new DDoubleGDL(1.660538921e-27)); // Molar volume, ideal gas at Standard temperature and Pression (STP) [m^3/mol] constantList ->NewTag("VM", new DDoubleGDL(22.413968e-3)); DVar *constant = new DVar("CONST",constantList); sysVarList.push_back(constant); sysVarRdOnlyList.push_back(constant); // make it read only // ![XYZ] SizeT dim2 = 2; SizeT dim60 = 60; SizeT dim10 = 10; DStructGDL* xAxis = new DStructGDL( "!AXIS"); xAxis->NewTag("TITLE", new DStringGDL( "")); xAxis->NewTag("TYPE", new DLongGDL( 0)); xAxis->NewTag("STYLE", new DLongGDL( 0)); xAxis->NewTag("TICKS", new DLongGDL( 0)); xAxis->NewTag("TICKLEN", new DFloatGDL( 0.0)); xAxis->NewTag("THICK", new DFloatGDL( 0.0)); xAxis->NewTag("RANGE", new DDoubleGDL( dimension( &dim2,one))); xAxis->NewTag("CRANGE", new DDoubleGDL( dimension( &dim2,one))); xAxis->NewTag("S", new DDoubleGDL( dimension( &dim2,one))); xAxis->NewTag("MARGIN", new DFloatGDL( dimension( &dim2,one))); xAxis->NewTag("OMARGIN", new DFloatGDL( dimension( &dim2,one))); xAxis->NewTag("WINDOW", new DFloatGDL( dimension( &dim2,one))); xAxis->NewTag("REGION", new DFloatGDL( dimension( &dim2,one))); xAxis->NewTag("CHARSIZE", new DFloatGDL( 0.0)); xAxis->NewTag("MINOR", new DLongGDL( 0)); xAxis->NewTag("TICKV", new DDoubleGDL( dimension( &dim60,one))); xAxis->NewTag("TICKNAME", new DStringGDL( dimension( &dim60,one))); xAxis->NewTag("GRIDSTYLE", new DLongGDL( 0)); xAxis->NewTag("TICKFORMAT", new DStringGDL( dimension( &dim10,one))); xAxis->NewTag("TICKINTERVAL", new DDoubleGDL( 0)); xAxis->NewTag("TICKLAYOUT", new DLongGDL( 0)); xAxis->NewTag("TICKUNITS", new DStringGDL( dimension( &dim10,one))); (*static_cast( xAxis->GetTag( 8, 0)))[1] = 1.0; (*static_cast( xAxis->GetTag( 9, 0)))[0] = 10.0; (*static_cast( xAxis->GetTag( 9, 0)))[1] = 3.0; DVar *x = new DVar( "X", xAxis); xIx = sysVarList.size(); sysVarList.push_back(x); DStructGDL* yAxis = new DStructGDL( "!AXIS"); (*static_cast( yAxis->GetTag( 8, 0)))[1] = 1.0; (*static_cast( yAxis->GetTag( 9, 0)))[0] = 4.0; (*static_cast( yAxis->GetTag( 9, 0)))[1] = 2.0; DVar* y = new DVar( "Y", yAxis); yIx = sysVarList.size(); sysVarList.push_back(y); DStructGDL* zAxis = new DStructGDL( "!AXIS"); (*static_cast( zAxis->GetTag( 8, 0)))[1] = 1.0; DVar* z = new DVar( "Z", zAxis); zIx = sysVarList.size(); sysVarList.push_back(z); // !VERSION DStructGDL* ver = new DStructGDL( "!VERSION"); #ifdef _WIN32 #ifdef __MINGW32__ typedef void (WINAPI *GetNativeSystemInfoFunc)(LPSYSTEM_INFO); HMODULE hModule = LoadLibraryW(L"kernel32.dll"); GetNativeSystemInfoFunc GetNativeSystemInfo =(GetNativeSystemInfoFunc) GetProcAddress(hModule, "GetNativeSystemInfo"); #endif const char* SysName = "Windows"; SYSTEM_INFO stInfo; GetNativeSystemInfo( &stInfo ); DStringGDL *arch; switch(stInfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: arch = new DStringGDL("x64"); break; case PROCESSOR_ARCHITECTURE_INTEL: arch = new DStringGDL("x86"); break; case PROCESSOR_ARCHITECTURE_ARM: arch = new DStringGDL("ARM"); break; default: arch = new DStringGDL("unknown"); } ver->NewTag("ARCH", arch); ver->NewTag("OS", new DStringGDL(SysName)); ver->NewTag("OS_FAMILY", new DStringGDL(SysName)); ver->NewTag("OS_NAME", new DStringGDL(SysName)); #else struct utsname uts; uname(&uts); ver->NewTag("ARCH", new DStringGDL( uts.machine)); const char *SysName=uts.sysname; if (strcmp(SysName,"Linux") ==0) SysName="linux"; if (strcmp(SysName,"Darwin") ==0) SysName="darwin"; ver->NewTag("OS", new DStringGDL(SysName)); //correct IDL order ver->NewTag("OS_FAMILY", new DStringGDL( "unix")); // AC 2018-sep-07 if (strcmp(SysName,"darwin") ==0) SysName="Mac OS X"; ver->NewTag("OS_NAME", new DStringGDL(SysName)); #endif ver->NewTag("RELEASE", new DStringGDL( "8.2")); //we are at least 6.4 ver->NewTag("BUILD_DATE", new DStringGDL(BUILD_DATE)); ver->NewTag("MEMORY_BITS", new DIntGDL( sizeof(BaseGDL*)*8)); ver->NewTag("FILE_OFFSET_BITS", new DIntGDL( sizeof(SizeT)*8)); DVar *v = new DVar( "VERSION", ver); vIx = sysVarList.size(); sysVarList.push_back(v); sysVarRdOnlyList.push_back(v); // !Mouse DStructGDL* MouseData = new DStructGDL( "!MOUSE"); MouseData->NewTag("X", new DLongGDL( 0)); MouseData->NewTag("Y", new DLongGDL( 0)); MouseData->NewTag("BUTTON", new DLongGDL( 0)); MouseData->NewTag("TIME", new DLongGDL( 0)); DVar *Mouse = new DVar( "MOUSE", MouseData); MouseIx = sysVarList.size(); sysVarList.push_back(Mouse); // !Make_dll DStructGDL* MakeDllData = new DStructGDL( "!MAKE_DLL"); MakeDllData->NewTag("COMPILE_DIRECTORY", new DStringGDL("/tmp/")); MakeDllData->NewTag("COMPILER_NAME", new DStringGDL("GCC")); MakeDllData->NewTag("CC", new DStringGDL("gcc %X -fPIC -I%Z -c -D_REENTRANT %C -o %O")); MakeDllData->NewTag("LD", new DStringGDL("ld -shared -o %L %O %X")); DVar *MakeDll = new DVar( "MAKE_DLL", MakeDllData); MakeDllIx = sysVarList.size(); sysVarList.push_back(MakeDll); // !ERROR_STATE DStructGDL* eStateData = new DStructGDL( "!ERROR_STATE"); eStateData->NewTag("NAME", new DStringGDL( "IDL_M_SUCCESS")); eStateData->NewTag("BLOCK", new DStringGDL( "IDL_MBLK_CORE")); eStateData->NewTag("CODE", new DLongGDL( 0)); eStateData->NewTag("SYS_CODE", new DLongGDL( dimension( &dim2,one))); //idl 8 eStateData->NewTag("SYS_CODE_TYPE", new DStringGDL( "")); eStateData->NewTag("MSG", new DStringGDL( "")); eStateData->NewTag("SYS_MSG", new DStringGDL( "")); eStateData->NewTag("MSG_PREFIX", new DStringGDL( "% ")); DVar *eState = new DVar( "ERROR_STATE", eStateData); errorStateIx = sysVarList.size(); sysVarList.push_back(eState); // sysVarRdOnlyList.push_back(eState); // !ERROR DLongGDL *errorData = new DLongGDL( 0 ); DVar *errorVar = new DVar( "ERROR", errorData ); errorIx = sysVarList.size(); sysVarList.push_back( errorVar); //sysVarRdOnlyList.push_back( errorVar); !error is (no more?) a readonly variable. // !ERR DLongGDL *errData = new DLongGDL( 0 ); DVar *errVar = new DVar( "ERR", errData ); errIx = sysVarList.size(); sysVarList.push_back( errVar ); // sysVarRdOnlyList.push_back( errVar); // !ERR_STRING DStringGDL *err_stringData = new DStringGDL( ""); DVar *err_stringVar = new DVar( "ERR_STRING", err_stringData ); err_stringIx = sysVarList.size(); sysVarList.push_back( err_stringVar ); sysVarRdOnlyList.push_back( err_stringVar); //!err_string IS a readonly variable! // !VALUES DStructGDL* valuesData = new DStructGDL( "!VALUES"); if( std::numeric_limits< DFloat>::has_infinity) { valuesData->NewTag("F_INFINITY", new DFloatGDL( std::numeric_limits< DFloat>::infinity())); } else { #ifndef _MSC_VER // Can be ignored, because the windows version of limit has infinity() valuesData->NewTag("F_INFINITY", new DFloatGDL((float)1.0/0.0)); #endif } #ifdef NAN valuesData->NewTag("F_NAN", new DFloatGDL(NAN)); #else valuesData->NewTag("F_NAN", new DFloatGDL(sqrt((float) -1.0))); //sign depends on the architecture, dangerous way to define a +Nan! #endif if( std::numeric_limits< DDouble>::has_infinity) { valuesData->NewTag("D_INFINITY", new DDoubleGDL( std::numeric_limits< DDouble>::infinity())); } else { #ifndef _MSC_VER // Can be ignored, because the windows version of limit has infinity() valuesData->NewTag("D_INFINITY", new DDoubleGDL( (double)1.0/0.0)); #endif } #ifdef NAN valuesData->NewTag("D_NAN", new DDoubleGDL(NAN)); #else valuesData->NewTag("D_NAN", new DDoubleGDL(-sqrt((double) -1.0))); //sign depends on the architecture, dangerous way to define a +Nan! #endif DVar *values = new DVar( "VALUES", valuesData); valuesIx = sysVarList.size(); sysVarList.push_back(values); sysVarRdOnlyList.push_back( values); // !JOURNAL hold journal file lun DLongGDL *journalData = new DLongGDL( 0); DVar *journal = new DVar( "JOURNAL", journalData); journalIx = sysVarList.size(); sysVarList.push_back( journal); sysVarRdOnlyList.push_back( journal); // !EXCEPT DIntGDL *exceptData = new DIntGDL( 1); DVar *except = new DVar( "EXCEPT", exceptData); exceptIx=sysVarList.size(); sysVarList.push_back( except); // !MAP DStructGDL* mapData = new DStructGDL( "!MAP"); mapData->NewTag("PROJECTION", new DLongGDL( 0)); mapData->NewTag("SIMPLE", new DLongGDL( 0)); mapData->NewTag("FILL_METHOD", new DLongGDL( 0)); mapData->NewTag("UP_FLAGS", new DLongGDL( 0)); mapData->NewTag("UP_NAME", new DStringGDL( "")); mapData->NewTag("P0LON", new DDoubleGDL( 0.0)); mapData->NewTag("P0LAT", new DDoubleGDL( 0.0)); mapData->NewTag("U0", new DDoubleGDL( 0.0)); mapData->NewTag("V0", new DDoubleGDL( 0.0)); mapData->NewTag("SINO", new DDoubleGDL( 0.0)); mapData->NewTag("COSO", new DDoubleGDL( 0.0)); mapData->NewTag("ROTATION", new DDoubleGDL( 0.0)); mapData->NewTag("SINR", new DDoubleGDL( 0.0)); mapData->NewTag("COSR", new DDoubleGDL( 0.0)); mapData->NewTag("A", new DDoubleGDL( 0.0)); mapData->NewTag("E2", new DDoubleGDL( 0.0)); mapData->NewTag("UV", new DDoubleGDL( dimension( 2))); mapData->NewTag("POLE", new DDoubleGDL( dimension( 7))); mapData->NewTag("UV_BOX", new DDoubleGDL( dimension( 4))); mapData->NewTag("LL_BOX", new DDoubleGDL( dimension( 4))); mapData->NewTag("SEGMENT_LENGTH", new DDoubleGDL( 0.0)); mapData->NewTag("P", new DDoubleGDL( dimension( 16))); mapData->NewTag("PIPELINE", new DDoubleGDL( dimension( 8, 12))); DVar *map=new DVar( "MAP", mapData); mapIx=sysVarList.size(); sysVarList.push_back( map); // !CPU // init independent of OpenMP usage #ifdef _OPENMP CpuTPOOL_NTHREADS = omp_get_num_procs(); omp_set_num_threads(CpuTPOOL_NTHREADS); #else CpuTPOOL_NTHREADS = 1; #endif CpuTPOOL_MIN_ELTS = DefaultTPOOL_MIN_ELTS; CpuTPOOL_MAX_ELTS = DefaultTPOOL_MAX_ELTS; DStructGDL* cpuData = new DStructGDL( "!CPU"); cpuData->NewTag("HW_VECTOR", new DLongGDL( 0)); cpuData->NewTag("VECTOR_ENABLE", new DLongGDL( 0)); #ifdef _OPENMP cpuData->NewTag("HW_NCPU", new DLongGDL( omp_get_num_procs())); #else cpuData->NewTag("HW_NCPU", new DLongGDL( 1)); #endif cpuData->NewTag("TPOOL_NTHREADS", new DLongGDL( CpuTPOOL_NTHREADS)); //if use DLong64 below, please update basic_pro.cpp (function cpu()) and //add an 'assureLong64Kw()' function in envt.cpp. Otherwise the program will //crash in cpu(). (should have been done on 2014 March 18 by AC (tested).) cpuData->NewTag("TPOOL_MIN_ELTS", new DLong64GDL( CpuTPOOL_MIN_ELTS)); cpuData->NewTag("TPOOL_MAX_ELTS", new DLong64GDL( CpuTPOOL_MAX_ELTS)); DVar *cpu=new DVar( "CPU", cpuData); cpuIx=sysVarList.size(); sysVarList.push_back( cpu); sysVarRdOnlyList.push_back( cpu); #ifdef _OPENMP if( omp_get_dynamic()) omp_set_dynamic( 1); #endif #if defined (_WIN32) #define realpath(N,R) _fullpath((R),(N),_MAX_PATH) // ref:http://sourceforge.net/p/mingw/patches/256/ Keith Marshall 2005-12-02 #endif // !DIR #ifndef EXEC_PREFIX #define EXEC_PREFIX "" #endif DStringGDL *dirData = new DStringGDL( EXEC_PREFIX); string gdlDir=GetEnvString("GDL_DIR"); if( gdlDir == "") gdlDir=GetEnvString("IDL_DIR"); if( gdlDir != "") { delete dirData; dirData = new DStringGDL( gdlDir); } DVar *dir = new DVar( "DIR", dirData); dirIx=sysVarList.size(); sysVarList.push_back( dir); // !GSHHS_DATA_DIR string tmpDir=GetEnvString("GSHHS_DATA_DIR"); if( tmpDir == "") tmpDir = string(GDLDATADIR) + "/../gshhs/"; // cout << "1 GSHHS data dir : " << tmpDir << endl; // is the path a true path ? char *symlinkpath =const_cast (tmpDir.c_str()); #ifdef _MSC_VER #define PATH_MAX MAX_PATH #endif //patch #90 #ifndef PATH_MAX #define PATH_MAX 4096 #endif char actualpath [PATH_MAX+1]; char *ptr; ptr = realpath(symlinkpath, actualpath); if( ptr != NULL ) tmpDir=string(ptr)+lib::PathSeparator(); else tmpDir=""; //cout << "2 GSHHS data dir : " << tmpDir << endl; DStringGDL *GshhsDataDir = new DStringGDL( tmpDir); DVar *GshhsDir = new DVar("GSHHS_DATA_DIR", GshhsDataDir); GshhsDirIx=sysVarList.size(); sysVarList.push_back(GshhsDir); // !STIME DStringGDL *stimeData = new DStringGDL( ""); DVar *stime = new DVar( "STIME", stimeData); stimeIx=sysVarList.size(); sysVarList.push_back( stime); sysVarRdOnlyList.push_back( stime); // make it read only // !WARN DStructGDL* warnData = new DStructGDL( "!WARN"); warnData->NewTag("OBS_ROUTINES", new DByteGDL( 0)); warnData->NewTag("OBS_SYSVARS", new DByteGDL( 0)); warnData->NewTag("PARENS", new DByteGDL( 0)); DVar *warn = new DVar( "WARN", warnData); warnIx = sysVarList.size(); sysVarList.push_back(warn); //!COLOR static const int col[]={240,248,255,250,235,215,0,255,255,127,255,212,240,255,255,245,245,220,255,228,196,0,0,0,255,235,205,0,0,255,138,43, 226,165,42,42,222,184,135,95,158,160,127,255,0,210,105,30,255,127,80,100,149,237,255,248,220,220,20,60,0,255,255,0, 0,139,0,139,139,184,134,11,169,169,169,0,100,0,169,169,169,189,183,107,139,0,139,85,107,47,255,140,0,153,50,204, 139,0,0,233,150,122,143,188,143,72,61,139,47,79,79,47,79,79,0,206,209,148,0,211,255,20,147,0,191,255,105,105, 105,105,105,105,30,144,255,178,34,34,255,250,240,34,139,34,255,0,255,220,220,220,248,248,255,255,215,0,218,165,32,127, 127,127,0,127,0,173,255,47,127,127,127,240,255,240,255,105,180,205,92,92,75,0,130,255,255,240,240,230,140,230,230,250, 255,240,245,124,252,0,255,250,205,173,216,230,240,128,128,224,255,255,250,250,210,144,238,144,211,211,211,211,211,211,255,182, 193,255,160,122,32,178,170,135,206,250,119,136,153,119,136,153,176,196,222,255,255,224,0,255,0,50,205,50,250,240,230,255, 0,255,127,0,0,102,205,170,0,0,205,186,85,211,147,112,219,60,179,113,123,104,238,0,250,154,72,209,204,199,21,133, 025,25,112,245,255,250,255,228,225,255,228,181,255,222,173,0,0,128,253,245,230,128,128,0,107,142,35,255,165,0,255,69, 0,218,112,214,238,232,170,152,251,152,175,238,238,219,112,147,255,239,213,255,218,185,205,133,63,255,192,203,221,160,221,176, 224,230,127,0,127,255,0,0,188,143,143,65,105,225,139,69,19,250,128,114,244,164,96,46,139,87,255,245,238,160,82,45, 192,192,192,135,206,235,106,90,205,112,128,144,112,128,144,255,250,250,0,255,127,70,130,180,210,180,140,0,128,128,216,191, 216,255,99,71,64,224,208,238,130,238,245,222,179,255,255,255,245,245,245,255,255,0,154,205,50}; static const string coln[]={"ALICE_BLUE","ANTIQUE_WHITE","AQUA","AQUAMARINE","AZURE","BEIGE","BISQUE","BLACK","BLANCHED_ALMOND", "BLUE","BLUE_VIOLET","BROWN","BURLYWOOD","CADET_BLUE","CHARTREUSE","CHOCOLATE","CORAL","CORNFLOWER","CORNSILK", "CRIMSON","CYAN","DARK_BLUE","DARK_CYAN","DARK_GOLDENROD","DARK_GRAY","DARK_GREEN","DARK_GREY","DARK_KHAKI", "DARK_MAGENTA","DARK_OLIVE_GREEN","DARK_ORANGE","DARK_ORCHID","DARK_RED","DARK_SALMON","DARK_SEA_GREEN", "DARK_SLATE_BLUE","DARK_SLATE_GRAY","DARK_SLATE_GREY","DARK_TURQUOISE","DARK_VIOLET","DEEP_PINK","DEEP_SKY_BLUE", "DIM_GRAY","DIM_GREY","DODGER_BLUE","FIREBRICK","FLORAL_WHITE","FOREST_GREEN","FUCHSIA","GAINSBORO","GHOST_WHITE", "GOLD","GOLDENROD","GRAY","GREEN","GREEN_YELLOW","GREY","HONEYDEW","HOT_PINK","INDIAN_RED","INDIGO","IVORY","KHAKI", "LAVENDER","LAVENDER_BLUSH","LAWN_GREEN","LEMON_CHIFFON","LIGHT_BLUE","LIGHT_CORAL","LIGHT_CYAN","LIGHT_GOLDENROD", "LIGHT_GREEN","LIGHT_GRAY","LIGHT_GREY","LIGHT_PINK","LIGHT_SALMON","LIGHT_SEA_GREEN","LIGHT_SKY_BLUE","LIGHT_SLATE_GRAY", "LIGHT_SLATE_GREY","LIGHT_STEEL_BLUE","LIGHT_YELLOW","LIME","LIME_GREEN","LINEN","MAGENTA","MAROON","MEDIUM_AQUAMARINE", "MEDIUM_BLUE","MEDIUM_ORCHID","MEDIUM_PURPLE","MEDIUM_SEA_GREEN","MEDIUM_SLATE_BLUE","MEDIUM_SPRING_GREEN","MEDIUM_TURQUOISE", "MEDIUM_VIOLET_RED","MIDNIGHT_BLUE","MINT_CREAM","MISTY_ROSE","MOCCASIN","NAVAJO_WHITE","NAVY","OLD_LACE","OLIVE", "OLIVE_DRAB","ORANGE","ORANGE_RED","ORCHID","PALE_GOLDENROD","PALE_GREEN","PALE_TURQUOISE","PALE_VIOLET_RED","PAPAYA_WHIP", "PEACH_PUFF","PERU","PINK","PLUM","POWDER_BLUE","PURPLE","RED","ROSY_BROWN","ROYAL_BLUE","SADDLE_BROWN","SALMON", "SANDY_BROWN","SEA_GREEN","SEASHELL","SIENNA","SILVER","SKY_BLUE","SLATE_BLUE","SLATE_GRAY","SLATE_GREY","SNOW","SPRING_GREEN", "STEEL_BLUE","TAN","TEAL","THISTLE","TOMATO","TURQUOISE","VIOLET","WHEAT","WHITE","WHITE_SMOKE","YELLOW","YELLOW_GREEN"}; int ncol=147; int i,k; DStructGDL* colorData = new DStructGDL( "!COLOR"); for (i=0, k=0; iNewTag(coln[i], new DByteGDL( dimension(3))); for (int j=0; j<3; ++j) (*static_cast( colorData->GetTag( i, 0)))[j] = col[k++]; } DVar *color = new DVar( "COLOR", colorData); colorIx = sysVarList.size(); sysVarList.push_back(color); sysVarRdOnlyList.push_back( color); //Is Readonly. } } gdl-0.9.9/src/initsysvar.hpp000066400000000000000000000050241340051421000160010ustar00rootroot00000000000000/*************************************************************************** initsysvar.hpp - system variable access ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef INITSYSVAR_HPP_ #define INITSYSVAR_HPP_ #include "objects.hpp" namespace SysVar { // extern unsigned int pathIx, dIx; // returns a StrArr with the path to search const StrArr& GDLPath(); void SetGDLPath( const DString& newPath); // returns !P DStructGDL* P(); DLongGDL* GetPMulti(); DLong GetPFont(); // returns ![XYZ] DStructGDL* X(); DStructGDL* Y(); DStructGDL* Z(); // returns !DIR const DString& Dir(); const DString& GshhsDir(); // updates !STIME void UpdateSTime(); // updates !D // void UpdateD();//long &xSize, long &ySize); DStructGDL* Version(); DStructGDL* Values(); // return !Mouse DStructGDL* Mouse(); DStructGDL* Error_State(); DString MsgPrefix(); void SetErr_String( const DString& eS); void SetErrError( DLong eC); // set !C void SetC( DLong newC); // set !D void SetD( BaseGDL* newD); // returns !MAP DStructGDL* Map(); // returns !CPU DStructGDL* Cpu(); // void CPUChanged(); // returns !D DStructGDL* D(); // returns !STIME DStringGDL* STime(); // returns !WARN DStructGDL* Warn(); const std::string& Prompt(); int Edit_Input(); DLong Quiet(); DLong GDL_Warning(); // get and set !JOURNAL (journal file LUN) DLong JournalLUN(); void JournalLUN( DLong jLUN); // get and set USERSYM DStructGDL* USYM(); // get the !ORDER variable DLong TV_ORDER(); // initialize the predefined system variables (!IDNAME) void InitSysVar(); void SetFakeRelease( DString str); } #endif gdl-0.9.9/src/interp_multid.h000066400000000000000000000634351340051421000161170ustar00rootroot00000000000000#ifndef __INTERP_MULTID_H__ #define __INTERP_MULTID_H__ #include #include #ifdef __cplusplus extern "C" { #endif enum missing_mode { missing_NONE = 0, missing_NEAREST, missing_GIVEN }; /* Gamma value for cubic interpolation and means to change it*/ static double gdl_cubic_gamma=-1.0; void gdl_update_cubic_interpolation_coeff(double gammaValue) { gdl_cubic_gamma=-1; if (gammaValue <=0 && gammaValue >= -1.0) gdl_cubic_gamma=gammaValue; } /* convolutions available */ inline double linConv(double d, double x0, double x1) { return (1. - d)*x0 + d*x1; } //idem cubConvParam but with param=-1.0 - replaced by cubConv Below // double cubConv(double d, double x0, double x1, double x2, double x3) { // return (-x0 + x1 - x2 + x3)*pow(d, 3) +(2 * x0 - 2 * x1 + x2 - x3) * pow(d, 2) + (-x0 + x2) * d + x1; // } // without inlining, speed x 2; without use of pow(), speed x10! inline double cubConv(double d, double x0, double x1, double x2, double x3) { double g=gdl_cubic_gamma; return ((g + 2) * d*d*d - (g + 3) * d*d + 1)*x1 + ((g + 2) * (1 - d)*(1-d)*(1-d) - (g + 3) * (1 - d)*(1-d) + 1) * x2 + (g * (1 + d)*(1+d)*(1+d) -5 * g * (1 + d)*(1+d) + 8 * g * (1 + d) - 4 * g) * x0 + (g * (2 - d)*(2-d)*(2-d) -5 * g * (2 - d)*(2-d) + 8 * g * (2 - d) - 4 * g) * x3; } /* 1D */ typedef struct { const char* name; unsigned int min_size; void* (*alloc)(size_t size); int (*init)(void*, const double xa[], const double ta[], size_t xsize); int (*eval)(const void*, const double xa[], const double ta[], size_t xsize, double x, gsl_interp_accel*, double* t); void (*free)(void*); } gdl_interp1d_type; typedef struct { const gdl_interp1d_type* type; double xmin; double xmax; size_t xsize; missing_mode mode; double missing; void* state; } gdl_interp1d; size_t gdl_interp1d_type_min_size(const gdl_interp1d_type* T) { return T->min_size; } size_t gdl_interp1d_min_size(const gdl_interp1d* interp) { return interp->type->min_size; } const char* gdl_interp1d_name(const gdl_interp1d* interp) { return interp->type->name; } GSL_VAR const gdl_interp1d_type* gdl_interp1d_linear; GSL_VAR const gdl_interp1d_type* gdl_interp1d_nearest; GSL_VAR const gdl_interp1d_type* gdl_interp1d_cubic; double gdl_interp1d_eval(const gdl_interp1d* interp, const double xarr[], const double tarr[], const double x, gsl_interp_accel* xa); gdl_interp1d* gdl_interp1d_alloc(const gdl_interp1d_type* T, size_t xsize) { gdl_interp1d* interp; // protection removed since interpolators are protected against index overflow. Mimics IDL. // if (xsize < T->min_size) { // GSL_ERROR_NULL("insufficient number of points for interpolation type", GSL_EINVAL); // } interp = (gdl_interp1d*) malloc(sizeof (gdl_interp1d)); if (interp == NULL) { GSL_ERROR_NULL("failed to allocate space for gdl_interp1d struct", GSL_ENOMEM); } interp->type = T; interp->xsize = xsize; if (interp->type->alloc == NULL) { interp->state = NULL; return interp; } interp->state = interp->type->alloc(xsize); if (interp->state == NULL) { free(interp); GSL_ERROR_NULL("failed to allocate space for gdl_interp1d state", GSL_ENOMEM); } return interp; } int gdl_interp1d_init(gdl_interp1d* interp, const double xarr[], const double tarr[], size_t xsize, missing_mode mode, double missing, double gammaValue) { size_t i; if (xsize != interp->xsize) { GSL_ERROR("data must match size of interpolation object", GSL_EINVAL); } for (i = 1; i < xsize; i++) { if (xarr[i - 1] >= xarr[i]) { GSL_ERROR("x values must be strictly increasing", GSL_EINVAL); } } interp->xmin = xarr[0]; interp->xmax = xarr[xsize - 1]; interp->mode = mode; interp->missing = missing; gdl_update_cubic_interpolation_coeff(gammaValue); { int status = interp->type->init(interp->state, xarr, tarr, xsize); return status; } } void gdl_interp1d_free(gdl_interp1d* interp) { if (!interp) { return; } if (interp->type->free) { interp->type->free(interp->state); } free(interp); } double gdl_interp1d_eval(const gdl_interp1d* interp, const double xarr[], const double tarr[], const double x, gsl_interp_accel* xa) { double xx, t; xx = x; int status; switch (interp->mode) { case missing_NONE: if (xx < interp->xmin || xx >= interp->xmax) { GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN); } break; case missing_NEAREST: if (xx < interp->xmin) xx = interp->xmin; if (xx >= interp->xmax) xx = interp->xmax; break; case missing_GIVEN: if ((xx < interp->xmin) || (xx >= interp->xmax)) { return interp->missing; } break; } status = interp->type->eval(interp->state, xarr, tarr, interp->xsize, xx, xa, &t); if ((status) != GSL_SUCCESS) GSL_ERROR_VAL("interpolation error", (status), GSL_NAN); return t; } static int linear_init(void* state, const double xa[], const double ta[], size_t xsize) { return GSL_SUCCESS; } static int nearest_init(void* state, const double xa[], const double ta[], size_t xsize) { return GSL_SUCCESS; } static int cubic_init(void* state, const double xa[], const double ta[], size_t xsize) { return GSL_SUCCESS; } static int cubic_eval(const void* state, const double xarr[], const double tarr[], size_t xsize, double x, gsl_interp_accel* xa, double* t) { double xmin, xmax; double dx; double u; size_t xm, xi, xp, xp2; double kern[4]; if (xa != NULL) { xi = gsl_interp_accel_find(xa, xarr, xsize, x); } else { xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1); } xm = (xi > 0) ? xi - 1 : xi; xp = (xi + 1 < xsize) ? xi + 1 : xi; xp2 = (xp + 1 < xsize) ? xp + 1 : xp; kern[0] = tarr[xm]; kern[1] = tarr[xi]; kern[2] = tarr[xp]; kern[3] = tarr[xp2]; xmin = xarr[xi]; xmax = xarr[xp]; dx = xmax - xmin; u = (dx > 0.0) ? (x - xmin) / dx : 0.0; *t = cubConv(u, kern[0], kern[1], kern[2], kern[3]); return GSL_SUCCESS; } static int linear_eval(const void* state, const double xarr[], const double tarr[], size_t xsize, double x, gsl_interp_accel* xa, double* t) { double xmin, xmax; double dx; double u; size_t xi, xp; double kern[2]; if (xa != NULL) { xi = gsl_interp_accel_find(xa, xarr, xsize, x); } else { xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1); } xp = (xi + 1 < xsize) ? xi + 1 : xi; kern[0] = tarr[xi]; kern[1] = tarr[xp]; xmin = xarr[xi]; xmax = xarr[xp]; dx = xmax - xmin; u = (dx > 0.0) ? (x - xmin) / dx : 0.0; *t = linConv(u, kern[0], kern[1]); return GSL_SUCCESS; } static int nearest_eval(const void* state, const double xarr[], const double tarr[], size_t xsize, double x, gsl_interp_accel* xa, double* t) { size_t xmin; xmin = (x < 0) ? 0 : x; xmin = (xmin > xsize - 1) ? xsize - 1 : xmin; *t = tarr[xmin]; return GSL_SUCCESS; } static const gdl_interp1d_type cubic_type = { "cubic", 4, NULL, &cubic_init, &cubic_eval }; static const gdl_interp1d_type linear_type = { "linear", 2, NULL, &linear_init, &linear_eval }; static const gdl_interp1d_type nearest_type = { "nearest", 1, NULL, &nearest_init, &nearest_eval }; const gdl_interp1d_type* gdl_interp1d_linear = &linear_type; const gdl_interp1d_type* gdl_interp1d_nearest = &nearest_type; const gdl_interp1d_type* gdl_interp1d_cubic = &cubic_type; /* 2D */ /* column-major index (FORTRAN, IDL) */ #define INDEX_2D(xi, yi, xsize, ysize) (yi) * (xsize) + (xi) /* row-major index (C, C++) */ //#define INDEX_2D(xi, yi, xsize, ysize) (xi) * (ysize) + (yi) typedef struct { const char* name; unsigned int min_size; void* (*alloc)(size_t size); int (*init)(void*, const double xa[], const double ya[], const double ta[], size_t xsize, size_t ysize); int (*eval)(const void*, const double xa[], const double ya[], const double ta[], size_t xsize, size_t ysize, double x, double y, gsl_interp_accel*, gsl_interp_accel*, double* z); void (*free)(void*); } gdl_interp2d_type; typedef struct { const gdl_interp2d_type* type; double xmin; double xmax; double ymin; double ymax; size_t xsize; size_t ysize; missing_mode mode; double missing; void* state; } gdl_interp2d; size_t gdl_interp2d_type_min_size(const gdl_interp2d_type* T) { return T->min_size; } size_t gdl_interp2d_min_size(const gdl_interp2d* interp) { return interp->type->min_size; } const char* gdl_interp2d_name(const gdl_interp2d* interp) { return interp->type->name; } GSL_VAR const gdl_interp2d_type* gdl_interp2d_bilinear; GSL_VAR const gdl_interp2d_type* gdl_interp2d_binearest; GSL_VAR const gdl_interp2d_type* gdl_interp2d_bicubic; double gdl_interp2d_eval(const gdl_interp2d* interp, const double xarr[], const double yarr[], const double tarr[], const double x, const double y, gsl_interp_accel* xa, gsl_interp_accel* ya); gdl_interp2d* gdl_interp2d_alloc(const gdl_interp2d_type* T, size_t xsize, size_t ysize) { gdl_interp2d* interp; // protection removed since interpolators are protected against index overflow. Mimics IDL. // if (xsize < T->min_size || ysize < T->min_size) { // GSL_ERROR_NULL("insufficient number of points for interpolation type", GSL_EINVAL); // } interp = (gdl_interp2d*) malloc(sizeof (gdl_interp2d)); if (interp == NULL) { GSL_ERROR_NULL("failed to allocate space for gdl_interp2d struct", GSL_ENOMEM); } interp->type = T; interp->xsize = xsize; interp->ysize = ysize; if (interp->type->alloc == NULL) { interp->state = NULL; return interp; } interp->state = interp->type->alloc(xsize); if (interp->state == NULL) { free(interp); GSL_ERROR_NULL("failed to allocate space for gdl_interp2d state", GSL_ENOMEM); } return interp; } int gdl_interp2d_init(gdl_interp2d* interp, const double xarr[], const double yarr[], const double tarr[], size_t xsize, size_t ysize, missing_mode mode, double missing, double gammaValue) { size_t i; if (xsize != interp->xsize || ysize != interp->ysize) { GSL_ERROR("data must match size of interpolation object", GSL_EINVAL); } for (i = 1; i < xsize; i++) { if (xarr[i - 1] >= xarr[i]) { GSL_ERROR("x values must be strictly increasing", GSL_EINVAL); } } for (i = 1; i < ysize; i++) { if (yarr[i - 1] >= yarr[i]) { GSL_ERROR("y values must be strictly increasing", GSL_EINVAL); } } interp->xmin = xarr[0]; interp->xmax = xarr[xsize - 1]; interp->ymin = yarr[0]; interp->ymax = yarr[ysize - 1]; interp->mode = mode; interp->missing = missing; gdl_update_cubic_interpolation_coeff(gammaValue); { int status = interp->type->init(interp->state, xarr, yarr, tarr, xsize, ysize); return status; } } void gdl_interp2d_free(gdl_interp2d* interp) { if (!interp) { return; } if (interp->type->free) { interp->type->free(interp->state); } free(interp); } double gdl_interp2d_eval(const gdl_interp2d* interp, const double xarr[], const double yarr[], const double tarr[], const double x, const double y, gsl_interp_accel* xa, gsl_interp_accel* ya) { double xx, yy, t; xx = x; yy = y; int status; switch (interp->mode) { case missing_NONE: if (xx < interp->xmin || xx > interp->xmax) { GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN); } if (yy < interp->ymin || yy > interp->ymax) { GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN); } break; case missing_NEAREST: if (xx < interp->xmin) xx = interp->xmin; if (xx > interp->xmax) xx = interp->xmax; if (yy < interp->ymin) yy = interp->ymin; if (yy > interp->ymax) yy = interp->ymax; break; case missing_GIVEN: if ((xx < interp->xmin) || (xx > interp->xmax) || (yy < interp->ymin) || (yy > interp->ymax)) { return interp->missing; } } status = interp->type->eval(interp->state, xarr, yarr, tarr, interp->xsize, interp->ysize, xx, yy, xa, ya, &t); if ((status) != GSL_SUCCESS) GSL_ERROR_VAL("interpolation error", (status), GSL_NAN); return t; } static int bilinear_init(void* state, const double xa[], const double ya[], const double ta[], size_t xsize, size_t ysize) { return GSL_SUCCESS; } static int binearest_init(void* state, const double xa[], const double ya[], const double ta[], size_t xsize, size_t ysize) { return GSL_SUCCESS; } static int bicubic_init(void* state, const double xa[], const double ya[], const double ta[], size_t xsize, size_t ysize) { return GSL_SUCCESS; } static int bicubic_eval(const void* state, const double xarr[], const double yarr[], const double tarr[], size_t xsize, size_t ysize, double x, double y, gsl_interp_accel* xa, gsl_interp_accel* ya, double* t) { double xmin, xmax, ymin, ymax; double dx, dy; double v, u; size_t xm, ym, xi, yi, xp, yp, xp2, yp2; double kern[4][4]; double t1, t2, t3, t4; if (xa != NULL) { xi = gsl_interp_accel_find(xa, xarr, xsize, x); } else { xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1); } xm = (xi > 0) ? xi - 1 : xi; xp = (xi + 1 < xsize) ? xi + 1 : xi; xp2 = (xp + 1 < xsize) ? xp + 1 : xp; if (ya != NULL) { yi = gsl_interp_accel_find(ya, yarr, ysize, y); } else { yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1); } ym = (yi > 0) ? yi - 1 : yi; yp = (yi + 1 < ysize) ? yi + 1 : yi; yp2 = (yp + 1 < ysize) ? yp + 1 : yp; kern[0][0] = tarr[INDEX_2D(xm, ym, xsize, ysize)]; kern[0][1] = tarr[INDEX_2D(xm, yi, xsize, ysize)]; kern[0][2] = tarr[INDEX_2D(xm, yp, xsize, ysize)]; kern[0][3] = tarr[INDEX_2D(xm, yp2, xsize, ysize)]; kern[1][0] = tarr[INDEX_2D(xi, ym, xsize, ysize)]; kern[1][1] = tarr[INDEX_2D(xi, yi, xsize, ysize)]; kern[1][2] = tarr[INDEX_2D(xi, yp, xsize, ysize)]; kern[1][3] = tarr[INDEX_2D(xi, yp2, xsize, ysize)]; kern[2][0] = tarr[INDEX_2D(xp, ym, xsize, ysize)]; kern[2][1] = tarr[INDEX_2D(xp, yi, xsize, ysize)]; kern[2][2] = tarr[INDEX_2D(xp, yp, xsize, ysize)]; kern[2][3] = tarr[INDEX_2D(xp, yp2, xsize, ysize)]; kern[3][0] = tarr[INDEX_2D(xp2, ym, xsize, ysize)]; kern[3][1] = tarr[INDEX_2D(xp2, yi, xsize, ysize)]; kern[3][2] = tarr[INDEX_2D(xp2, yp, xsize, ysize)]; kern[3][3] = tarr[INDEX_2D(xp2, yp2, xsize, ysize)]; xmin = xarr[xi]; xmax = xarr[xp]; ymin = yarr[yi]; ymax = yarr[yp]; dx = xmax - xmin; dy = ymax - ymin; u = (dx > 0.0) ? (x - xmin) / dx : 0.0; v = (dy > 0.0) ? (y - ymin) / dy : 0.0; t1 = cubConv(u, kern[0][0], kern[1][0], kern[2][0], kern[3][0]); t2 = cubConv(u, kern[0][1], kern[1][1], kern[2][1], kern[3][1]); t3 = cubConv(u, kern[0][2], kern[1][2], kern[2][2], kern[3][2]); t4 = cubConv(u, kern[0][3], kern[1][3], kern[2][3], kern[3][3]); *t = cubConv(v, t1, t2, t3, t4); return GSL_SUCCESS; } static int bilinear_eval(const void* state, const double xarr[], const double yarr[], const double tarr[], size_t xsize, size_t ysize, double x, double y, gsl_interp_accel* xa, gsl_interp_accel* ya, double* t) { double xmin, xmax, ymin, ymax; double dx, dy; double v, u; size_t xi, yi, xp, yp; double kern[2][2]; double t1, t2; if (xa != NULL) { xi = gsl_interp_accel_find(xa, xarr, xsize, x); } else { xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1); } xp = (xi + 1 < xsize) ? xi + 1 : xi; if (ya != NULL) { yi = gsl_interp_accel_find(ya, yarr, ysize, y); } else { yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1); } yp = (yi + 1 < ysize) ? yi + 1 : yi; kern[0][0] = tarr[INDEX_2D(xi, yi, xsize, ysize)]; kern[0][1] = tarr[INDEX_2D(xi, yp, xsize, ysize)]; kern[1][0] = tarr[INDEX_2D(xp, yi, xsize, ysize)]; kern[1][1] = tarr[INDEX_2D(xp, yp, xsize, ysize)]; xmin = xarr[xi]; xmax = xarr[xp]; ymin = yarr[yi]; ymax = yarr[yp]; dx = xmax - xmin; dy = ymax - ymin; u = (dx > 0.0) ? (x - xmin) / dx : 0.0; v = (dy > 0.0) ? (y - ymin) / dy : 0.0; t1 = linConv(u, kern[0][0], kern[1][0]); t2 = linConv(u, kern[0][1], kern[1][1]); *t = linConv(v, t1, t2); return GSL_SUCCESS; } static int binearest_eval(const void* state, const double xarr[], const double yarr[], const double tarr[], size_t xsize, size_t ysize, double x, double y, gsl_interp_accel* xa, gsl_interp_accel* ya, double* t) { size_t xmin, ymin; xmin = (x < 0) ? 0 : x; xmin = (xmin > xsize - 1) ? xsize - 1 : xmin; ymin = (y < 0) ? 0 : y; ymin = (ymin > ysize - 1) ? ysize - 1 : ymin; *t = tarr[INDEX_2D(xmin, ymin, xsize, ysize)]; return GSL_SUCCESS; } static const gdl_interp2d_type bicubic_type = { "cubic", 4, NULL, &bicubic_init, &bicubic_eval }; static const gdl_interp2d_type bilinear_type = { "linear", 2, NULL, &bilinear_init, &bilinear_eval }; static const gdl_interp2d_type binearest_type = { "nearest", 1, NULL, &binearest_init, &binearest_eval }; const gdl_interp2d_type* gdl_interp2d_bilinear = &bilinear_type; const gdl_interp2d_type* gdl_interp2d_binearest = &binearest_type; const gdl_interp2d_type* gdl_interp2d_bicubic = &bicubic_type; /* 3D */ /*column-major index (idl, fortran). Beware to keep all the parenthesis!*/ #define INDEX_3D(xi, yi, zi, xsize, ysize, zsize) ((zi) * (ysize) + (yi)) * (xsize) + (xi) /* row-major index (C, C++) */ /* #define INDEX_3D(xi, yi, zi, xsize, ysize, zsize) ((xi) * (ysize) + (yi) ) * (zsize) + (zi) */ typedef struct { const char* name; unsigned int min_size; void* (*alloc)(size_t size); int (*init)(void*, const double xa[], const double ya[], const double za[], const double ta[], size_t xsize, size_t ysize, size_t zsize); int (*eval)(const void*, const double xa[], const double ya[], const double za[], const double ta[], size_t xsize, size_t ysize, size_t zsize, double x, double y, double z, gsl_interp_accel*, gsl_interp_accel*, gsl_interp_accel*, double* t); void (*free)(void*); } gdl_interp3d_type; typedef struct { const gdl_interp3d_type* type; double xmin; double xmax; double ymin; double ymax; double zmin; double zmax; size_t xsize; size_t ysize; size_t zsize; missing_mode mode; double missing; void* state; } gdl_interp3d; size_t gdl_interp3d_type_min_size(const gdl_interp3d_type* T) { return T->min_size; } size_t gdl_interp3d_min_size(const gdl_interp3d* interp) { return interp->type->min_size; } const char* gdl_interp3d_name(const gdl_interp3d* interp) { return interp->type->name; } GSL_VAR const gdl_interp3d_type* gdl_interp3d_trilinear; double gdl_interp3d_eval(const gdl_interp3d* interp, const double xarr[], const double yarr[], const double zarr[], const double tarr[], const double x, const double y, const double z, gsl_interp_accel* xa, gsl_interp_accel* ya, gsl_interp_accel* za); gdl_interp3d* gdl_interp3d_alloc(const gdl_interp3d_type* T, size_t xsize, size_t ysize, size_t zsize) { gdl_interp3d* interp; // if (xsize < T->min_size || ysize < T->min_size || zsize < T->min_size) { // GSL_ERROR_NULL("insufficient number of points for interpolation type", GSL_EINVAL); // } interp = (gdl_interp3d*) malloc(sizeof (gdl_interp3d)); if (interp == NULL) { GSL_ERROR_NULL("failed to allocate space for gdl_interp3d struct", GSL_ENOMEM); } interp->type = T; interp->xsize = xsize; interp->ysize = ysize; interp->zsize = zsize; if (interp->type->alloc == NULL) { interp->state = NULL; return interp; } interp->state = interp->type->alloc(xsize); if (interp->state == NULL) { free(interp); GSL_ERROR_NULL("failed to allocate space for gdl_interp3d state", GSL_ENOMEM); } return interp; } int gdl_interp3d_init(gdl_interp3d* interp, const double xarr[], const double yarr[], const double zarr[], const double tarr[], size_t xsize, size_t ysize, size_t zsize, missing_mode mode, double missing) { size_t i; if (xsize != interp->xsize || ysize != interp->ysize || zsize != interp->zsize) { GSL_ERROR("data must match size of interpolation object", GSL_EINVAL); } for (i = 1; i < xsize; i++) { if (xarr[i - 1] >= xarr[i]) { GSL_ERROR("x values must be strictly increasing", GSL_EINVAL); } } for (i = 1; i < ysize; i++) { if (yarr[i - 1] >= yarr[i]) { GSL_ERROR("y values must be strictly increasing", GSL_EINVAL); } } for (i = 1; i < zsize; i++) { if (zarr[i - 1] >= zarr[i]) { GSL_ERROR("z values must be strictly increasing", GSL_EINVAL); } } interp->xmin = xarr[0 ]; interp->xmax = xarr[xsize - 1]; interp->ymin = yarr[0]; interp->ymax = yarr[ysize - 1]; interp->zmin = zarr[0]; interp->zmax = zarr[zsize - 1]; interp->mode = mode; interp->missing = missing; { int status = interp->type->init(interp->state, xarr, yarr, zarr, tarr, xsize, ysize, zsize); return status; } } void gdl_interp3d_free(gdl_interp3d* interp) { if (!interp) { return; } if (interp->type->free) { interp->type->free(interp->state); } free(interp); } double gdl_interp3d_eval(const gdl_interp3d* interp, const double xarr[], const double yarr[], const double zarr[], const double tarr[], const double x, const double y, const double z, gsl_interp_accel* xa, gsl_interp_accel* ya, gsl_interp_accel* za) { double xx, yy, zz, t; xx = x; yy = y; zz = z; int status; switch (interp->mode) { case missing_NONE: if (xx < interp->xmin || xx > interp->xmax) { GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN); } if (yy < interp->ymin || yy > interp->ymax) { GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN); } if (zz < interp->zmin || zz > interp->zmax) { GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN); } break; case missing_NEAREST: if (xx < interp->xmin) xx = interp->xmin; if (xx > interp->xmax) xx = interp->xmax; if (yy < interp->ymin) yy = interp->ymin; if (yy > interp->ymax) yy = interp->ymax; if (zz < interp->zmin) zz = interp->zmin; if (zz > interp->zmax) zz = interp->zmax; break; case missing_GIVEN: if ((xx < interp->xmin) || (xx > interp->xmax) || (yy < interp->ymin) || (yy > interp->ymax) || (zz < interp->zmin) || (zz > interp->zmax)) { t = interp->missing; return t; } } status = interp->type->eval(interp->state, xarr, yarr, zarr, tarr, interp->xsize, interp->ysize, interp->zsize, xx, yy, zz, xa, ya, za, &t); if ((status) != GSL_SUCCESS) GSL_ERROR_VAL("interpolation error", (status), GSL_NAN); return t; } static int trilinear_init(void* state, const double xa[], const double ya[], const double za[], const double ta[], size_t xsize, size_t ysize, size_t zsize) { return GSL_SUCCESS; } static int trilinear_eval(const void* state, const double xarr[], const double yarr[], const double zarr[], const double tarr[], size_t xsize, size_t ysize, size_t zsize, double x, double y, double z, gsl_interp_accel* xa, gsl_interp_accel* ya, gsl_interp_accel* za, double* t) { double xmin, xmax, ymin, ymax, zmin, zmax; double dx, dy, dz; double u, v, w; size_t xi, xp, yi, yp, zi, zp; double kern[2][2]; double t1, t2, t12, t21; if (xa != NULL) { xi = gsl_interp_accel_find(xa, xarr, xsize, x); } else { xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1); } xp = (xi + 1 < xsize) ? xi + 1 : xi; if (ya != NULL) { yi = gsl_interp_accel_find(ya, yarr, ysize, y); } else { yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1); } yp = (yi + 1 < ysize) ? yi + 1 : yi; if (za != NULL) { zi = gsl_interp_accel_find(za, zarr, zsize, z); } else { zi = gsl_interp_bsearch(zarr, z, 0, zsize - 1); } zp = (zi + 1 < zsize) ? zi + 1 : zi; xmin = xarr[xi]; xmax = xarr[xp]; ymin = yarr[yi]; ymax = yarr[yp]; zmin = zarr[zi]; zmax = zarr[zp]; dx = xmax - xmin; dy = ymax - ymin; dz = zmax - zmin; u = (dx > 0.0) ? (x - xmin) / dx : 0.0; v = (dy > 0.0) ? (y - ymin) / dy : 0.0; w = (dz > 0.0) ? (z - zmin) / dz : 0.0; kern[0][0] = tarr[INDEX_3D(xi, yi, zi, xsize, ysize, zsize)]; kern[1][0] = tarr[INDEX_3D(xp, yi, zi, xsize, ysize, zsize)]; kern[0][1] = tarr[INDEX_3D(xi, yp, zi, xsize, ysize, zsize)]; kern[1][1] = tarr[INDEX_3D(xp, yp, zi, xsize, ysize, zsize)]; t1 = linConv(u, kern[0][0], kern[1][0]); t2 = linConv(u, kern[0][1], kern[1][1]); t12 = linConv(v, t1, t2); kern[0][0] = tarr[INDEX_3D(xi, yi, zp, xsize, ysize, zsize)]; kern[1][0] = tarr[INDEX_3D(xp, yi, zp, xsize, ysize, zsize)]; kern[0][1] = tarr[INDEX_3D(xi, yp, zp, xsize, ysize, zsize)]; kern[1][1] = tarr[INDEX_3D(xp, yp, zp, xsize, ysize, zsize)]; t1 = linConv(u, kern[0][0], kern[1][0]); t2 = linConv(u, kern[0][1], kern[1][1]); t21 = linConv(v, t1, t2); *t = linConv(w, t12, t21); return GSL_SUCCESS; } static const gdl_interp3d_type trilinear_type = { "linear", 2, NULL, &trilinear_init, &trilinear_eval }; const gdl_interp3d_type* gdl_interp3d_trilinear = &trilinear_type; #ifdef __cplusplus } #endif #endif gdl-0.9.9/src/io.cpp000066400000000000000000000615361340051421000142020ustar00rootroot00000000000000/*************************************************************************** io.cpp - GDL classes for file io ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include // std::remove(...) #include "objects.hpp" #include "io.hpp" #ifdef __MINGW32__ #include // for close() #endif #if defined(_WIN32) && !defined(__CYGWIN__) #define NS_INT16SZ 2 #define NS_INADDRSZ 4 #define NS_IN6ADDRSZ 16 #ifndef EAFNOSUPPORT #define EAFNOSUPPORT 9901 #endif static int inet_pton4( const char *src, unsigned char *dst ) { static const char digits[] = "0123456789"; int saw_digit, octets, ch; unsigned char tmp[NS_INADDRSZ], *tp; saw_digit = 0; octets = 0; *(tp = tmp) = 0; while( (ch = *src++) != ' ' ) { const char *pch; if( (pch = strchr(digits, ch)) != NULL ) { unsigned int iNew = (unsigned int)(*tp * 10 + (pch - digits)); if( iNew > 255 ) return (0); *tp = iNew; if( !saw_digit ) { if( ++octets > 4 ) return (0); saw_digit = 1; } } else if( ch == '.' && saw_digit ) { if( octets == 4 ) return (0); *++tp = 0; saw_digit = 0; } else { return (0); } } if( octets < 4 ) return (0); memcpy( dst, tmp, NS_INADDRSZ ); return (1); } static int inet_pton6( const char *src, unsigned char * dst ) { static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF"; unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; const char *xdigits, *curtok; int ch, saw_xdigit; unsigned int val; memset((tp = tmp), ' ', NS_IN6ADDRSZ); endp = tp + NS_IN6ADDRSZ; colonp = NULL; // Leading :: requires some special handling. if( *src == ':' && *++src != ':' ) return (0); curtok = src; saw_xdigit = 0; val = 0; while( ( ch = *src++ ) != ' ' ) { const char *pch; if( ( pch = strchr( ( xdigits = xdigits_l ), ch ) ) == NULL ) pch = strchr( (xdigits = xdigits_u), ch ); if( pch != NULL ) { val <<= 4; val |= (pch - xdigits); if( val > 0xffff ) return (0); saw_xdigit = 1; continue; } if( ch == ':' ) { curtok = src; if( !saw_xdigit ) { if( colonp ) return (0); colonp = tp; continue; } if( tp + NS_INT16SZ > endp ) return (0); *tp++ = (unsigned char) (val >> 8) & 0xff; *tp++ = (unsigned char) val & 0xff; saw_xdigit = 0; val = 0; continue; } if( ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0 ) { tp += NS_INADDRSZ; saw_xdigit = 0; break; /* ' ' was seen by inet_pton4(). */ } return (0); } if( saw_xdigit ) { if( tp + NS_INT16SZ > endp ) return (0); *tp++ = (unsigned char) (val >> 8) & 0xff; *tp++ = (unsigned char) val & 0xff; } if( colonp != NULL ) { // Since some memmove()'s erroneously fail to handle overlapping regions, we'll do the shift by hand. const int n = (int)(tp - colonp); int i; for( i = 1; i <= n; i++ ) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if( tp != endp ) return (0); memcpy(dst, tmp, NS_IN6ADDRSZ); return (1); } int inet_pton( int af, const char *src, void *dst ) { switch (af) { case AF_INET: return inet_pton4( src, (unsigned char *)dst ); case AF_INET6: return inet_pton6( src, (unsigned char *)dst ); default: errno = EAFNOSUPPORT; return (-1); } } // This source code is from http://blog.naver.com/PostView.nhn?blogId=websearch&logNo=70089324416&parentCategoryNo=4&viewDate=¤tPage=1&listtype=0 #endif using namespace std; const string StreamInfo( ios* searchStream) { if( dynamic_cast( searchStream) != NULL) return "Unit: 0, (redirected)"; if( searchStream == &cin) return "Unit: 0, "; if( searchStream == &cout) return "Unit: -1, "; if( searchStream == &cerr) return "Unit: -2, "; for( SizeT i=0; iFStream() == searchStream) { return "Unit: "+i2s(i+1)+", File: "+fileUnits[ i].Name(); } } return "Internal error: Stream not found."; } void AnyStream::Close() { if( fStream != NULL && fStream->is_open()) { fStream->close(); fStream->clear(); } if( igzStream != NULL && igzStream->rdbuf()->is_open()) { igzStream->close(); igzStream->clear(); } if( ogzStream != NULL && ogzStream->rdbuf()->is_open()) { ogzStream->close(); ogzStream->clear(); } } void AnyStream::Open(const std::string& name_, ios_base::openmode mode_ , bool compress_) { if (compress_) { delete fStream; fStream = NULL; if( (mode_ & std::ios::out)) { if( ogzStream == NULL) ogzStream = new ogzstream(); ogzStream->open( name_.c_str(), mode_ & ~std::ios::in); if( ogzStream->fail()) { delete ogzStream; ogzStream = NULL; throw GDLIOException("Error opening compressed file for output."); } } else { delete ogzStream; ogzStream = NULL; } if( (mode_ & std::ios::in) && !(mode_ & std::ios::out)) { if( igzStream == NULL) igzStream = new igzstream(); igzStream->open( name_.c_str(), mode_ & ~std::ios::out); if( igzStream->fail()) { delete igzStream; igzStream = NULL; throw GDLIOException("Error opening compressed file for input."); } } else { delete igzStream; igzStream = NULL; } } else { delete igzStream; igzStream = NULL; delete ogzStream; ogzStream = NULL; if( fStream == NULL) fStream = new fstream(); fStream->open( name_.c_str(), mode_); if( fStream->fail()) { delete fStream; fStream = NULL; if( ((mode_ | ios_base::in) != 0) && ((mode_ | ios_base::out) == 0)) throw GDLIOException(-265,"Error opening file for reading."); throw GDLIOException(-1,"Error opening file."); } } } void GDLStream::Open( const string& name_, ios_base::openmode mode_, bool swapEndian_, bool dOC, bool xdr_, SizeT width_, bool f77_, bool compress_) { string expName = name_; WordExp( expName); f77 = f77_; // if( f77_) // throw GDLException("F77_UNFORMATTED format not supported."); // if( (fStream != NULL && fStream->is_open()) || (igzStream != NULL && igzStream->rdbuf()->is_open()) || (ogzStream != NULL && ogzStream->rdbuf()->is_open())) if( anyStream != NULL && anyStream->IsOpen()) throw GDLIOException("File unit is already open."); if( anyStream == NULL) anyStream = new AnyStream(); name=expName; mode=mode_; compress = compress_; anyStream->Open(expName,mode_,compress_); swapEndian = swapEndian_; deleteOnClose = dOC; if( xdr_) xdrs = new XDR; lastSeekPos = 0; lastRecord = 0; lastRecordStart = 0; width = width_; } void GDLStream::Socket( const string& host, DUInt port, bool swapEndian_, DDouble c_timeout_, DDouble r_timeout_, DDouble w_timeout_) { if( iSocketStream == NULL) iSocketStream = new istringstream; if( recvBuf == NULL) recvBuf = new string; name=host; sockNum = socket( AF_INET, SOCK_STREAM, 0); c_timeout = c_timeout_; r_timeout = r_timeout_; w_timeout = w_timeout_; int on = 1; if (setsockopt( sockNum, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof (on)) == -1) { throw GDLIOException("Error opening file."); } sockaddr_in m_addr; m_addr.sin_family = AF_INET; m_addr.sin_port = htons ( port); // Convert host to IPv4 format struct hostent *h; if ((h=gethostbyname( host.c_str())) == NULL) { // get the host info throw GDLIOException("Unable to lookup host."); } // cout << inet_ntoa(*((struct in_addr *)h->h_addr)) << endl; int status = inet_pton( AF_INET, inet_ntoa(*((struct in_addr *)h->h_addr)), &m_addr.sin_addr ); status = connect( sockNum, ( sockaddr * ) &m_addr, sizeof (m_addr)); swapEndian = swapEndian_; // BIG limit on socket send width to avoid leading \n in CheckNL width = 32768; } void AnyStream::Flush() { if( fStream != NULL) { fStream->flush(); } if( ogzStream != NULL) { ogzStream->flush(); } } void GDLStream::Flush() { if( anyStream != NULL) { anyStream->Flush(); } } void GDLStream::Close() { if( anyStream != NULL) { anyStream->Close(); if( deleteOnClose) std::remove(name.c_str()); } name=""; f77=false; swapEndian=false; compress=false; deleteOnClose=false; delete xdrs; xdrs = NULL; width = defaultStreamWidth; sockNum = -1; c_timeout = 0.0; r_timeout = 0.0; w_timeout = 0.0; #ifdef HAVE_EXT_STDIO_FILEBUF_H // GGH: ggh hack to implement SPAWN keyword UNIT // Do housekeeping before closure if (readbuf_frb_destroy_on_close_p != NULL) { readbuf_frb_destroy_on_close_p->~stdio_filebuf(); readbuf_frb_destroy_on_close_p = NULL; } if (readbuf_bsrb_destroy_on_close_p != NULL) { readbuf_bsrb_destroy_on_close_p->~basic_streambuf(); readbuf_bsrb_destroy_on_close_p = NULL; } if (fd_close_on_close != -1) { close(fd_close_on_close); fd_close_on_close = -1; } #endif } void GDLStream::Free() { Close(); delete anyStream; anyStream = NULL; delete iSocketStream; iSocketStream = NULL; delete recvBuf; recvBuf = NULL; getLunLock = false; } igzstream& GDLStream::IgzStream() { if( anyStream == NULL || anyStream->IgzStream() == NULL || !anyStream->IsOpen()) throw GDLIOException("File unit is not open for compressed reading or writing."); if( !(mode & ios::in)) throw GDLIOException("File unit is not open for reading."); return *anyStream->IgzStream(); } ogzstream& GDLStream::OgzStream() { if( anyStream == NULL || anyStream->OgzStream() == NULL || !anyStream->IsOpen()) throw GDLIOException("File unit is not open for compressed reading or writing."); if( !(mode & ios::out)) throw GDLIOException("File unit is not open for compressed writing."); return *anyStream->OgzStream(); } fstream& GDLStream::IStream() { if( anyStream == NULL || anyStream->FStream() == NULL || !anyStream->IsOpen()) throw GDLIOException("File unit is not open."); if( !(mode & ios::in)) throw GDLIOException("File unit is not open for reading."); return *anyStream->FStream(); } fstream& GDLStream::OStream() { if( anyStream == NULL || anyStream->FStream() == NULL || !anyStream->IsOpen()) throw GDLIOException("File unit is not open."); if( !(mode & ios::out)) throw GDLIOException("File unit is not open for writing."); return *anyStream->FStream(); } istringstream& GDLStream::ISocketStream() { if( iSocketStream == NULL) throw GDLIOException("Socket unit is not open."); return *iSocketStream; } void GDLStream::Pad( std::streamsize nBytes) { if( anyStream != NULL) anyStream->Pad( nBytes); } void AnyStream::Pad( std::streamsize nBytes) { const std::streamsize bufSize = 1024; static char buf[ bufSize]; SizeT nBuf = nBytes / bufSize; std::streamsize lastBytes = nBytes % bufSize; if( fStream != NULL) { for( SizeT i=0; iwrite( buf, bufSize); if( lastBytes > 0) fStream->write( buf, lastBytes); } else if( ogzStream != NULL) { for( SizeT i=0; iwrite( buf, bufSize); if( lastBytes > 0) ogzStream->write( buf, lastBytes); } } void GDLStream::F77Write( DULong tCount) { anyStream->ClearEof(); assert( sizeof( DULong) == 4); if( swapEndian) { char swapTCount[ sizeof( DULong)]; for( SizeT i=0; i(&tCount)[ sizeof( DULong)-1-i]; anyStream->Write(swapTCount,sizeof( DULong)); } else { anyStream->Write(reinterpret_cast(&tCount),sizeof( DULong)); } if( !anyStream->Good()) { throw GDLIOException("Error writing F77_UNFORMATTED record data."); } } DULong GDLStream::F77ReadStart() { if( anyStream->EofRaw()) throw GDLIOException("End of file encountered."); assert( sizeof( DULong) == 4); DULong tCountRd; if( swapEndian) { char swapTCount[ sizeof( DULong)]; anyStream->Read( swapTCount, sizeof( DULong)); for( SizeT i=0; i(&tCountRd)[ sizeof( DULong)-1-i] = swapTCount[i]; } else { anyStream->Read(reinterpret_cast(&tCountRd),sizeof( DULong)); } if( anyStream->EofRaw()) throw GDLIOException("End of file encountered."); if( !anyStream->Good()) { throw GDLIOException("Error reading F77_UNFORMATTED record data."); } lastRecord = tCountRd; lastRecordStart = Tell(); return tCountRd; } void GDLStream::F77ReadEnd() { if( anyStream->EofRaw()) throw GDLIOException("End of file encountered."); std::streampos actPos = Tell(); if( actPos > (lastRecordStart+lastRecord)) throw GDLIOException( "Read past end of Record of F77_UNFORAMTTED file."); if( actPos < (lastRecordStart+lastRecord)) Seek( lastRecordStart+lastRecord); DULong tCountRd; if( swapEndian) { char swapTCount[ sizeof( DULong)]; anyStream->Read( swapTCount, sizeof( DULong)); for( SizeT i=0; i(&tCountRd)[ sizeof( DULong)-1-i] = swapTCount[i]; } else { anyStream->Read(reinterpret_cast(&tCountRd),sizeof( DULong)); } if( anyStream->EofRaw()) throw GDLIOException("End of file encountered."); if( !anyStream->Good()) { throw GDLIOException("Error reading F77_UNFORMATTED record data."); } if( lastRecord !=static_cast( tCountRd)) throw GDLIOException( "Logical error in F77_UNFORAMTTED file."); } // ============================================================================ #ifdef HAVE_EXT_STDIO_FILEBUF_H // GGH ggh hack to implement SPAWN keyword UNIT std::basic_streambuf *GDLStream::get_stream_readbuf_bsrb() { return anyStream->fStream->std::ios::rdbuf(); } int GDLStream::set_stream_readbuf_bsrb_from_frb(__gnu_cxx::stdio_filebuf *frb_p) { anyStream->fStream->std::ios::rdbuf(frb_p); return 0; } int GDLStream::set_readbuf_frb_destroy_on_close(__gnu_cxx::stdio_filebuf *frb_p) { readbuf_frb_destroy_on_close_p = frb_p; return 0; } int GDLStream::set_readbuf_bsrb_destroy_on_close(std::basic_streambuf *bsrb_p) { readbuf_bsrb_destroy_on_close_p = bsrb_p; return 0; } int GDLStream::set_fd_close_on_close(int fd) { fd_close_on_close = fd; return 0; } #endif // gzstream, C++ iostream classes wrapping the zlib compression library. // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner // // This library 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 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ============================================================================ // // File : gzstream.C // Author(s) : Deepak Bandyopadhyay, Lutz Kettner // // Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ #ifdef GZSTREAM_NAMESPACE namespace GZSTREAM_NAMESPACE { #endif // ---------------------------------------------------------------------------- // Internal classes to implement gzstream. See header file for user classes. // ---------------------------------------------------------------------------- // -------------------------------------- // class gzstreambuf: // -------------------------------------- gzstreambuf* gzstreambuf::open( const char* name, int open_mode) { if ( is_open()) return (gzstreambuf*)0; position = 0; mode = open_mode; // no append nor read/write mode if ((mode & std::ios::ate) || (mode & std::ios::app) || ((mode & std::ios::in) && (mode & std::ios::out))) return (gzstreambuf*)0; char fmode[10]; char* fmodeptr = fmode; if ( mode & std::ios::in) *fmodeptr++ = 'r'; else if ( mode & std::ios::out) *fmodeptr++ = 'w'; *fmodeptr++ = 'b'; *fmodeptr = '\0'; file = gzopen( name, fmode); if (file == 0) return (gzstreambuf*)0; opened = 1; return this; } gzstreambuf * gzstreambuf::close() { if ( is_open()) { //reset buf to 0 position: solves bug #724 setg( buffer + buf4, // beginning of putback area buffer + buf4, // read position buffer + buf4); // end position sync(); opened = 0; position=0; if ( gzclose( file) == Z_OK) return this; } return (gzstreambuf*)0; } int gzstreambuf::underflow() { // used for input buffer only if ( gptr() && ( gptr() < egptr())) return * reinterpret_cast( gptr()); if ( ! (mode & std::ios::in) || ! opened) return EOF; // Josuttis' implementation of inbuf int n_putback = gptr() - eback(); if ( n_putback > buf4) n_putback = buf4; memcpy( buffer + (buf4 - n_putback), gptr() - n_putback, n_putback); int num = gzread( file, buffer+buf4, bufferSize-buf4); if (num <= 0) // ERROR or EOF return EOF; // reset buffer pointers setg( buffer + (buf4 - n_putback), // beginning of putback area buffer + buf4, // read position buffer + buf4 + num); // end of buffer // return next character return * reinterpret_cast( gptr()); } int gzstreambuf::flush_buffer() { // Separate the writing of the buffer from overflow() and // sync() operation. int w = pptr() - pbase(); if ( gzwrite( file, pbase(), w) != w) return EOF; pbump( -w); return w; } int gzstreambuf::overflow( int c) { // used for output buffer only if ( ! ( mode & std::ios::out) || ! opened) return EOF; if (c != EOF) { *pptr() = c; pbump(1); } if ( flush_buffer() == EOF) return EOF; return c; } int gzstreambuf::sync() { // Changed to use flush_buffer() instead of overflow( EOF) // which caused improper behavior with std::endl and flush(), // bug reported by Vincent Ricard. if ( pptr() && pptr() > pbase()) { if ( flush_buffer() == EOF) return -1; } return 0; } std::streampos gzstreambuf::pubseekpos(std::streampos sp, std::ios_base::openmode which) { if (is_open()) { // cerr<<"seeking "<file)<mode & std::ios::in) || /* read mode : ok */ (which == std::ios_base::out && this->mode & std::ios::out && static_cast (sp) >= gztell(this->file))) /* write mode : seek forward only */ { z_off_t off = gzseek(this->file, static_cast (0), SEEK_SET); //absolutely necessary to rewind!!! position = 0; setg(buffer + buf4, buffer + buf4, buffer + buf4); if (sp != 0) off = gzseek(this->file, static_cast (sp), SEEK_SET); // fprintf(stderr, "Seek: %d=pubseekpos(sp=%d)\n", off, static_cast (sp)); // GD. seems reset of buffer is needed only when rewinded at 0. if (which == std::ios_base::in && off == 0) setg(buffer + buf4, buffer + buf4, buffer + buf4); position = off; return off; } else { z_off_t off=static_cast(gztell(this->file)); /* Just don't Seek, no error */ // fprintf(stderr, "Tell: %d=pubseekpos(sp=%d)\n", off, static_cast (sp)); position = off; return off; } } // fprintf(stderr, "EOF: -1=pubseekpos(sp=%d)\n", static_cast (sp)); return -1; } std::streampos gzstreambuf::pubseekoff(std::streamoff offIn, std::ios_base::seekdir way, std::ios_base::openmode which) { // debug aid // string str; // switch(way) // { // case std::ios_base::beg: // str="beg"; break; // case std::ios_base::cur: // str="cur"; break; // case std::ios_base::end: // str="end"; break; // } if (is_open() && way != std::ios_base::end) /* No seek with SEEK_END */ { if ((which == std::ios_base::in && this->mode & std::ios::in) || /* read mode : ok */ (which == std::ios_base::out && this->mode & std::ios::out && /* write mode : ok if */ ((way == std::ios_base::cur && offIn >= 0) || /* SEEK_CUR with positive offset */ (way == std::ios_base::beg && static_cast (offIn) >= gztell(this->file))))) /* or SEEK_SET which go forward */ { z_off_t off = gzseek(this->file, static_cast (offIn), (way == std::ios_base::beg ? SEEK_SET : SEEK_CUR)); // fprintf(stderr, "WRONG? Seek: %d=pubseekoff(offIn=%d,way=%s)\n", off, static_cast (offIn), str.c_str()); // GD. seems reset of buffer is needed only when rewinded at 0. if (which == std::ios_base::in && off == 0) setg(buffer + buf4, buffer + buf4, buffer + buf4); position = off; return off; } else { z_off_t off=static_cast(gztell(this->file)); /* Just don't Seek, no error */ // fprintf(stderr, "WRONG? Tell: %d=pubseekoff(offIn=%d,way=%s)\n", off, static_cast (offIn), str.c_str()); position = off; return off; } } // fprintf(stderr, "EOF: -1=pubseekoff(offIn=%d,way=%s)\n", static_cast (offIn), str.c_str()); return -1; } // -------------------------------------- // class gzstreambase: // -------------------------------------- gzstreambase::gzstreambase( const char* name, int mode) { init( &buf); open( name, mode); } gzstreambase::~gzstreambase() { buf.close(); } void gzstreambase::open( const char* name, int open_mode) { if ( ! buf.open( name, open_mode)) clear( rdstate() | std::ios::badbit); } void gzstreambase::close() { if ( buf.is_open()) if ( ! buf.close()) clear( rdstate() | std::ios::badbit); } // -------------------------------------- // class igzstream: // -------------------------------------- igzstream& igzstream::seekg(std::streampos pos) { if(rdbuf()->pubseekpos(pos,ios_base::in)==std::streampos(-1)) this->setstate(std::ios_base::badbit); else this->setstate(std::ios_base::goodbit); return *this; } igzstream& igzstream::seekg(std::streamoff off, std::ios_base::seekdir dir) { if(rdbuf()->pubseekoff(off,dir,ios_base::in)==std::streampos(-1)) this->setstate(std::ios_base::badbit); else this->setstate(std::ios_base::goodbit); return *this; } // -------------------------------------- // class ogzstream: // -------------------------------------- ogzstream& ogzstream::seekp(std::streampos pos) { if(rdbuf()->pubseekpos(pos,ios_base::out)==std::streampos(-1)) this->setstate(std::ios_base::badbit); else this->setstate(std::ios_base::goodbit); return *this; } ogzstream& ogzstream::seekp(std::streamoff off, std::ios_base::seekdir dir) { if(rdbuf()->pubseekoff(off,dir,ios_base::out)==std::streampos(-1)) this->setstate(std::ios_base::badbit); else this->setstate(std::ios_base::goodbit); return *this; } #ifdef GZSTREAM_NAMESPACE } // namespace GZSTREAM_NAMESPACE #endif // ============================================================================ // EOF // gdl-0.9.9/src/io.hpp000066400000000000000000000270461340051421000142050ustar00rootroot00000000000000/* ************************************************************************* io.hpp - GDL classes for file io ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef IO_HPP_ #define IO_HPP_ #include "includefirst.hpp" #include #include #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #else #include #include #include #include #include #endif #include // for memcpy #include "gzstream.hpp" #include "gdlexception.hpp" // GGH ggh hack to implement SPAWN keyword UNIT #ifdef HAVE_EXT_STDIO_FILEBUF_H # include #endif //#include // the file IO system consists of 128 GDLStream objects const int maxLun=128; // within GDL, internal max LUN is 127 const int maxUserLun=99; // within GDL, internal always lun-1 is used const std::string StreamInfo( std::ios* searchStream); const SizeT defaultStreamWidth = 80; // used by open_lun class AnyStream { // GGH ggh made all these public public: std::fstream* fStream; igzstream* igzStream; // for gzip compressed input ogzstream* ogzStream; // for gzip compressed output //public: AnyStream() : fStream(NULL) , igzStream(NULL) , ogzStream(NULL) {} void Flush() ; void Close(); void Open(const std::string& name_, std::ios_base::openmode mode_ , bool compress_); std::fstream* FStream(){return fStream;} igzstream* IgzStream(){return igzStream;} // for gzip compressed input ogzstream* OgzStream(){return ogzStream;} // for gzip compressed output void ClearEof() { if( fStream&&fStream->eof()) fStream->clear(); if( igzStream&&igzStream->eof()) igzStream->clear(); if( ogzStream&&ogzStream->eof()) ogzStream->clear(); } void Write( char* buf, std::streamsize nBytes) { if( fStream != NULL) { fStream->write(buf,nBytes); } else if( ogzStream != NULL) { ogzStream->write(buf,nBytes); } else assert( 0); } void Read( char* buf, std::streamsize nBytes) { if( fStream != NULL) { fStream->read(buf,nBytes); } else if( igzStream != NULL) { igzStream->read(buf,nBytes); } else assert( 0); } bool Good() { if( fStream != NULL) return fStream->good(); else if( igzStream != NULL && ogzStream != NULL) return igzStream->good() && ogzStream->good(); else if( igzStream != NULL) return igzStream->good(); else if( ogzStream != NULL) return ogzStream->good(); else { assert(false); throw; // getting rid of compiler warning } } bool EofRaw() { if( fStream != NULL) { return fStream->eof(); } if( igzStream != NULL) { return igzStream->eof(); } return true; } bool Eof() { if( fStream == NULL && igzStream == NULL && ogzStream == NULL) throw GDLException("Inner file unit is not open."); if( fStream != NULL) { fStream->clear(); // clear old EOF fStream->peek(); // trigger EOF if at EOF return fStream->eof(); } if( igzStream != NULL) { igzStream->clear(); // clear old EOF igzStream->peek(); // trigger EOF if at EOF return igzStream->eof(); } return true; } void Seek( std::streampos pos) { if (fStream == NULL && igzStream == NULL && ogzStream == NULL) throw GDLException("inner file unit is not open."); if (fStream != NULL) { if (fStream->eof()) fStream->clear(); fStream->rdbuf()->pubseekpos(pos, std::ios_base::in | std::ios_base::out); } if (igzStream != NULL) { if (igzStream->eof()) igzStream->clear(); igzStream->seekg(pos); // igzStream->rdbuf()->pubseekpos( pos, std::ios_base::in); } if (ogzStream != NULL) { if (ogzStream->eof()) ogzStream->clear(); ogzStream->seekp(pos); // ogzStream->rdbuf()->pubseekpos( pos, std::ios_base::out); } } std::streampos Size() { if( fStream != NULL) { std::streampos cur = Tell(); std::streampos end = fStream->rdbuf()->pubseekoff( 0, std::ios_base::end); fStream->rdbuf()->pubseekpos( cur, std::ios_base::in | std::ios_base::out); return end; } else { if( igzStream != NULL) { std::streampos cur = igzStream->rdbuf()->pubseekoff( 0, std::ios_base::cur); std::streampos end = igzStream->rdbuf()->pubseekoff( 0, std::ios_base::end); igzStream->rdbuf()->pubseekpos( cur, std::ios_base::in); return end; } if( ogzStream != NULL) { std::streampos cur = ogzStream->rdbuf()->pubseekoff( 0, std::ios_base::cur); std::streampos end = ogzStream->rdbuf()->pubseekoff( 0, std::ios_base::end); ogzStream->rdbuf()->pubseekpos( cur, std::ios_base::out); return end; } else { assert(false); throw; // getting rid of compiler warning } } } std::streampos Tell() { if (fStream != NULL) return( fStream->tellg()); else if(igzStream != NULL) return igzStream->rdbuf()->getPosition(); //igzStream->rdbuf()->pubseekoff( 0, std::ios_base::cur); else if( ogzStream != NULL) return ogzStream->rdbuf()->pubseekoff( 0, std::ios_base::cur); else { assert(false); throw; // getting rid of compiler warning } } void SeekPad( std::streampos pos) { if( fStream == NULL && ogzStream == NULL) throw GDLException("File unit is not open."); if( fStream != NULL) { if( fStream->eof()) fStream->clear(); std::streampos fSize = Size(); if( pos > fSize) Pad( pos - fSize); fStream->rdbuf()->pubseekpos( pos, std::ios_base::in | std::ios_base::out); } else { if( ogzStream->eof()) ogzStream->clear(); std::streampos fSize = Size(); if( pos > fSize) Pad( pos - fSize); ogzStream->rdbuf()->pubseekpos( pos, std::ios_base::in | std::ios_base::out); } } bool InUse() { return (fStream != NULL || igzStream != NULL || ogzStream != NULL);} bool IsOpen() { return (fStream != NULL && fStream->is_open()) || (igzStream != NULL && igzStream->rdbuf()->is_open()) || (ogzStream != NULL && ogzStream->rdbuf()->is_open());} void Pad( std::streamsize nBytes); void Clear() { } }; class GDLStream { bool getLunLock; std::string name; std::ios_base::openmode mode; AnyStream* anyStream; // std::fstream* fStream; // igzstream* igzStream; // for gzip compressed input // ogzstream* ogzStream; // for gzip compressed output bool f77; // FORTRAN unformatted bool swapEndian; bool deleteOnClose; bool varlenVMS; bool compress; XDR *xdrs; std::istringstream* iSocketStream; int sockNum; std::string* recvBuf; DDouble c_timeout; DDouble r_timeout; DDouble w_timeout; #ifdef HAVE_EXT_STDIO_FILEBUF_H // GGH ggh hack to implement SPAWN keyword UNIT __gnu_cxx::stdio_filebuf *readbuf_frb_destroy_on_close_p; std::basic_streambuf *readbuf_bsrb_destroy_on_close_p; int fd_close_on_close; #endif SizeT width; std::streampos lastSeekPos; // for F77 std::streampos lastRecord; std::streampos lastRecordStart; void Pad( std::streamsize nBytes); // puts out nBytes zero bytes public: GDLStream(): getLunLock(false), name(), mode(), anyStream(NULL), /* fStream(NULL), igzStream(NULL), ogzStream(NULL), */ f77(false), swapEndian(false), deleteOnClose(false), varlenVMS(false), compress(false), xdrs(NULL), iSocketStream(NULL), sockNum( -1), recvBuf(NULL), c_timeout(0.0), r_timeout(0.0), w_timeout(0.0), width( defaultStreamWidth), lastSeekPos( 0), lastRecord( 0), lastRecordStart( 0) { #ifdef HAVE_EXT_STDIO_FILEBUF_H readbuf_frb_destroy_on_close_p = NULL; readbuf_bsrb_destroy_on_close_p = NULL; fd_close_on_close = -1; #endif } ~GDLStream() { delete xdrs; delete anyStream; /* delete fStream; delete igzStream; delete ogzStream;*/ delete iSocketStream; } void Open( const std::string& name_, std::ios_base::openmode, bool swapEndian_, bool deleteOnClose_, bool xdr_, SizeT width, bool f77, bool compress); void Socket( const std::string& host, DUInt port, bool swapEndian_, DDouble c_timeout, DDouble r_timeout, DDouble w_timeout); void Flush(); void Close(); bool Eof() { if( anyStream == NULL) throw GDLException("File unit is not open."); return anyStream->Eof(); } void Seek( std::streampos pos) { if( anyStream == NULL) throw GDLException("File unit is not open."); anyStream->Seek(pos); lastSeekPos = pos; } std::streampos Size() { return anyStream->Size(); } std::streampos Tell() { return anyStream->Tell(); } SizeT Width() { return width; } void SeekPad( std::streampos pos) { if( anyStream == NULL) throw GDLException("File unit is not open."); anyStream->SeekPad( pos); lastSeekPos = pos; } bool InUse() { return (anyStream != NULL && anyStream->InUse());} bool IsOpen() { return (anyStream != NULL && anyStream->IsOpen());} bool IsReadable() { return (IsOpen() && (mode & std::ios::in));} bool IsWriteable() { return (IsOpen() && (mode & std::ios::out));} void Free(); void SetGetLunLock( bool b) { getLunLock = b;} bool GetGetLunLock() { return getLunLock;} const std::string& Name() { return name;} bool SwapEndian() { return swapEndian;} bool VarLenVMS() { return varlenVMS;} void PutVarLenVMS( bool varlenVMS_) { varlenVMS = varlenVMS_;} bool Compress() { return compress;} /* void PutCompress( bool compress_) { compress = compress_;}*/ igzstream& IgzStream(); ogzstream& OgzStream(); XDR *Xdr() { return xdrs;} std::fstream& IStream(); std::fstream& OStream(); int SockNum() { return sockNum;} std::istringstream& ISocketStream(); std::string& RecvBuf() { return *recvBuf;} DDouble cTimeout() { return c_timeout;} DDouble rTimeout() { return r_timeout;} DDouble wTimeout() { return w_timeout;} // friend const std::string StreamInfo( AnyStream* searchStream); friend const std::string StreamInfo( std::ios* searchStream); // F77_UNFORMATTED stuff bool F77() { return f77;} void F77Write( DULong tCount); DULong F77ReadStart(); void F77ReadEnd(); #ifdef HAVE_EXT_STDIO_FILEBUF_H // GGH ggh hack to implement SPAWN keyword UNIT std::basic_streambuf *get_stream_readbuf_bsrb(); int set_stream_readbuf_bsrb_from_frb(__gnu_cxx::stdio_filebuf *frb_p); int set_readbuf_frb_destroy_on_close(__gnu_cxx::stdio_filebuf *frb_p); int set_readbuf_bsrb_destroy_on_close(std::basic_streambuf *bsrb_p); int set_fd_close_on_close(int fd); #endif }; typedef std::vector GDLFileListT; #endif gdl-0.9.9/src/lapack.cpp000066400000000000000000000020331340051421000150110ustar00rootroot00000000000000/*************************************************************************** lapack.cpp - lapack routines ------------------- begin : January 31 2010 copyright : (C) 2010y Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //#include gdl-0.9.9/src/least_squares.cpp000066400000000000000000000134171340051421000164410ustar00rootroot00000000000000/*************************************************************************** la_least_squares.cpp - GDL library function ------------------- begin : Jul 2 2015 copyright : (C) 2015 by NATCHKEBIA Ilia email contact : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include //#include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "dinterpreter.hpp" #if defined(USE_EIGEN) #include #include #include #endif namespace lib { using namespace std; #ifndef _MSC_VER using std::isnan; #endif //const int szdbl=sizeof(double); //const int szflt=sizeof(float); #if defined(USE_EIGEN) using namespace Eigen; /*********************************************************** ********************la_least_squares_Solution*************** ************************************************************/ BaseGDL* la_least_squares_fun( EnvT* e) { static int method = 3; //default Method is 3 that give identic result as idl static int isDouble = 0; //default double is 0 static int methodIx=e->KeywordIx("METHOD"); e->AssureLongScalarKWIfPresent(methodIx , method); static int doubleIx=e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx)) isDouble = methodIx; BaseGDL* p0 = e->GetParDefined( 0); BaseGDL* p1 = e->GetParDefined( 1); /***************Checking_if_arguments_are_OK***********/ if (p0->N_Elements()==0) e->Throw( "Variable A is undefined: " + e->GetParString(0)); if (p1->N_Elements()==0) e->Throw( "Variable B is undefined: " + e->GetParString(1)); if (p0->Rank() != 2){ e->Throw( "Argument A must be a 2 dimensional matrix:" + e->GetParString(0)); } if (p1->Rank() > 2) { e->Throw( "Argument B must be a vector or 2 dimensional array:" + e->GetParString(1)); } if(p1->Rank() == 1) { if(p1->N_Elements()!=p0->Dim(1)) e->Throw("Number of elements in B does not match number of rows in A"); }else if (p1->Dim(1)!=p0->Dim(1)){ e->Throw("Number of rows in B does not match number of rows in A"); } if(0 > method || method > 3) { e->Throw("Method must be 0,1,2 or 3"); } long NbCol1,NbRow1,NbCol2,NbRow2; /**********************Variables************************/ DDoubleGDL* p0D = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); DDoubleGDL* p2D = static_cast (p1->Convert2( GDL_DOUBLE, BaseGDL::COPY)); NbCol1=p0->Dim(1); NbRow1=p0->Dim(0); NbCol2=p1->Dim(1); NbRow2=p1->Dim(0); Map > m0(&(*p0D)[0], NbCol1,NbRow1); Map > m2(&(*p2D)[0], NbCol2,NbRow2); // LLTsolver; //solver is not USED! and... Map m3(&(*p2D)[0], NbRow2); //for one B when it's vector MatrixXd tmp_res; /**************Methods******************/ if (method == 0 && p1->Dim(1)) tmp_res = m0.colPivHouseholderQr().solve(m2) ; else if (method == 0 && !p1->Dim(1)) tmp_res = m0.colPivHouseholderQr().solve(m3) ; else if (method == 1 && p1->Dim(1)) tmp_res = (m0.transpose() * m0).ldlt().solve(m0.transpose() * m2) ; else if (method == 1 && !p1->Dim(1)) tmp_res = (m0.transpose() * m0).ldlt().solve(m0.transpose() * m3) ; else if (method >= 2 && p1->Dim(1)) //method 2 and method 3 is the same tmp_res = m0.jacobiSvd(ComputeThinU | ComputeThinV).solve(m2) ; else if (method >= 2 && !p1->Dim(1)) tmp_res = m0.jacobiSvd(ComputeThinU | ComputeThinV).solve(m3) ; // AND if SOLVER is not USED, The following crash on an assertion in debug mode!!! // if(solver.info()==NumericalIssue) // { // e->Throw( "Array is not positive definite: " + e->GetParString(0)); // return 0; // } // if(solver.info()!=Success) // { // e->Throw( "Decomposition has failed: " + e->GetParString(0)); // return 0; // } /***********************Return Values******************/ if(p1->Dim(1)) { SizeT dims[3]; dims[1] = NbRow1; dims[0] = NbRow2; dimension dim( dims, (SizeT) 2 ); if(( p0->Type() == GDL_DOUBLE) || isDouble) { DDoubleGDL* resD =new DDoubleGDL(dim, BaseGDL::NOZERO); Map(&(*resD)[0], NbRow2,NbRow1) = tmp_res.transpose().cast(); return resD; } else { DFloatGDL* resF = new DFloatGDL(dim, BaseGDL::NOZERO); Map(&(*resF)[0], NbRow2,NbRow1) = tmp_res.transpose().cast(); return resF; } } else { //when B is a vector if(( p0->Type() == GDL_DOUBLE) || isDouble) { DDoubleGDL* resD =new DDoubleGDL(NbRow1, BaseGDL::NOZERO); Map(&(*resD)[0], NbRow1) = tmp_res.cast(); return resD; } else { DFloatGDL* resF = new DFloatGDL(NbRow1, BaseGDL::NOZERO); Map(&(*resF)[0], NbRow1) = tmp_res.cast(); return resF; } } } #endif } //namespace lib gdl-0.9.9/src/least_squares.hpp000066400000000000000000000023421340051421000164410ustar00rootroot00000000000000/*************************************************************************** least_squares.hpp - GDL library function ------------------- begin : July 2015 copyright : (C) 2015 by NATCHKEBIA Ilia email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif // this code needs Eigen3 #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* la_least_squares_fun( EnvT* e); } // namespace //#endif gdl-0.9.9/src/libinit.cpp000066400000000000000000001322471340051421000152230ustar00rootroot00000000000000/*************************************************************************** libinit.cpp - initialization of GDL library routines ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include "envt.hpp" #include "dpro.hpp" #include "objects.hpp" #include "basic_fun.hpp" #include "basic_pro.hpp" #include "gdlhelp.hpp" #include "list.hpp" #include "hash.hpp" #include "math_fun.hpp" #include "math_fun_ac.hpp" #include "math_fun_gm.hpp" #include "math_fun_ng.hpp" #include "plotting.hpp" #include "file.hpp" #include "gsl_fun.hpp" #include "where.hpp" #include "convol.hpp" #include "smooth.hpp" #include "brent.hpp" #include "linearprogramming.hpp" #include "saverestore.hpp" #ifdef USE_PYTHON # include "gdlpython.hpp" #endif #include "grib.hpp" #include "semshm.hpp" // for extensions #include "new.hpp" using namespace std; // declare here other library init functions void LibInit_jmg(); // libinit_jmg.cpp void LibInit_cl(); // libinit_cl.cpp void LibInit_mes(); // libinit_mes.cpp void LibInit_ac(); // libinit_ac.cpp void LibInit_gm(); // libinit_gm.cpp void LibInit_ng(); // libinit_ng.cpp void LibInit_jp(); // libinit_jp.cpp void LibInit_exists(); // libinit_exists.cpp void LibInit() { // call other library init functions LibInit_jmg(); LibInit_cl(); LibInit_mes(); LibInit_ac(); LibInit_gm(); LibInit_ng(); LibInit_jp(); LibInit_exists(); const char KLISTEND[] = ""; const string restoreKey[]={ "FILENAME","DESCRIPTION","VERBOSE", KLISTEND}; const string restoreWarnKey[]={"NO_COMPILE", "RELAXED_STRUCTURE_ASSIGNMENT", "RESTORED_OBJECTS" , KLISTEND}; new DLibPro(lib::gdl_restore,string("RESTORE"),1,restoreKey,restoreWarnKey); const string saveKey[]={ "FILENAME","DESCRIPTION","VERBOSE","VARIABLES", "ALL", "COMM", "COMPRESS", "SYSTEM_VARIABLES",KLISTEND}; const string saveWarnKey[]={"EMBEDDED","ROUTINES", KLISTEND}; new DLibPro(lib::gdl_save,string("SAVE"),-1,saveKey,saveWarnKey); const string listKey[]={"EXTRACT", "LENGTH", "NO_COPY", KLISTEND}; new DLibFunRetNew(lib::list_fun,string("LIST"),-1,listKey); const string hashKey[]={"EXTRACT", "LOWERCASE", "NO_COPY", "FOLD_CASE", KLISTEND}; new DLibFunRetNew(lib::hash_fun,string("HASH"),-1,hashKey); new DLibFunRetNew(lib::orderedhash_fun,string("ORDEREDHASH"),-1,hashKey); new DLibFun(lib::scope_level,string("SCOPE_LEVEL"),0); const string scope_varfetchKey[]={"LEVEL","ENTER", KLISTEND}; const string scope_varfetchWarnKey[]={"COMMON","REF_EXTRA", KLISTEND}; new DLibFun(lib::scope_varfetch_value,string("SCOPE_VARFETCH"),-1,scope_varfetchKey,scope_varfetchWarnKey); const string scope_tracebackKey[]={"STRUCTURE","SYSTEM", KLISTEND}; new DLibFunRetNew(lib::scope_traceback,string("SCOPE_TRACEBACK"),0,scope_tracebackKey); const string cpuKey[]={ "RESET","RESTORE","TPOOL_MAX_ELTS", "TPOOL_MIN_ELTS", "TPOOL_NTHREADS","VECTOR_ENABLE",KLISTEND}; new DLibPro(lib::cpu,string("CPU"),0,cpuKey); const string get_kbrdKey[]={"ESCAPE","KEY_NAME",KLISTEND}; new DLibFunRetNew(lib::get_kbrd,string("GET_KBRD"),1,NULL,get_kbrdKey); const string svdcKey[]={"COLUMN","ITMAX","DOUBLE",KLISTEND}; new DLibPro(lib::svdc,string("SVDC"),4,svdcKey); new DLibFunRetNew(lib::temporary,string("TEMPORARY"),1); const string routine_infoKey[]={"FUNCTIONS","SYSTEM","DISABLED","ENABLED", "PARAMETERS","SOURCE", KLISTEND}; new DLibFunRetNew(lib::routine_info,string("ROUTINE_INFO"),1,routine_infoKey); #ifdef _WIN32 //Please note that NOWAIT and HIDE are WINDOWS-Reserved Keywords. const string spawnKey[] = { "COUNT", "EXIT_STATUS", "PID", "SH", "NOSHELL", "UNIT", "HIDE", "NOWAIT", KLISTEND }; #else const string spawnKey[]={ "COUNT","EXIT_STATUS","PID", "SH","NOSHELL","UNIT",KLISTEND}; #endif new DLibPro(lib::spawn_pro,string("SPAWN"),3,spawnKey); const string bytsclKey[]={"MIN","MAX","TOP","NAN",KLISTEND}; new DLibFunRetNew(lib::bytscl,string("BYTSCL"),3,bytsclKey); const string n_tagsKey[]={"DATA_LENGTH","LENGTH",KLISTEND}; new DLibFunRetNew(lib::n_tags,string("N_TAGS"),1,n_tagsKey); const string byteorderKey[]={"SSWAP","LSWAP","L64SWAP", "SWAP_IF_BIG_ENDIAN", "SWAP_IF_LITTLE_ENDIAN", "NTOHL","NTOHS","HTONL","HTONS", "FTOXDR","DTOXDR","XDRTOF","XDRTOD", KLISTEND}; new DLibPro(lib::byteorder,string("BYTEORDER"),-1,byteorderKey); const string obj_classKey[]={"COUNT","SUPERCLASS",KLISTEND}; new DLibFunRetNew(lib::obj_class,string("OBJ_CLASS"),1,obj_classKey); new DLibFunRetNew(lib::obj_isa,string("OBJ_ISA"),2,NULL,NULL,false,2); new DLibFunRetNew(lib::obj_hasmethod,string("OBJ_HASMETHOD"),2); const string rebinKey[]={"SAMPLE",KLISTEND}; new DLibFunRetNew(lib::rebin_fun,string("REBIN"),9,rebinKey); const string convolKey[]={"CENTER","EDGE_TRUNCATE","EDGE_WRAP","EDGE_ZERO", "EDGE_MIRROR", "BIAS","NORMALIZE","NAN", "INVALID", "MISSING",KLISTEND}; new DLibFunRetNew(lib::convol_fun,string("CONVOL"),3,convolKey); const string smoothKey[]={"NAN", "EDGE_MIRROR", "EDGE_WRAP","EDGE_TRUNCATE", "EDGE_ZERO", "MISSING", KLISTEND}; new DLibFunRetNew(lib::smooth_fun,string("SMOOTH"),2,smoothKey); const string file_searchKey[]={"COUNT","EXPAND_ENVIRONMENT","EXPAND_TILDE", "FOLD_CASE","ISSUE_ACCESS_ERROR", "MARK_DIRECTORY","NOSORT","QUOTE", "MATCH_INITIAL_DOT", "MATCH_ALL_INITIAL_DOT","FULLY_QUALIFY_PATH", "TEST_DIRECTORY", "TEST_EXECUTABLE", "TEST_READ", "TEST_REGULAR", "TEST_WRITE", "TEST_ZERO_LENGTH", "TEST_SYMLINK", "DIRECTORY","SYMLINK","REGULAR","ZERO_LENGTH", KLISTEND}; new DLibFunRetNew(lib::file_search,string("FILE_SEARCH"),3,file_searchKey); const string file_expand_pathKey[]={KLISTEND}; new DLibFunRetNew(lib::file_expand_path,string("FILE_EXPAND_PATH"),1,file_expand_pathKey); const string file_readlinkKey[]={"ALLOW_NONEXISTENT","ALLOW_NONSYMLINK","NOEXPAND_PATH",KLISTEND}; new DLibFunRetNew(lib::file_readlink,string("FILE_READLINK"),1,file_readlinkKey); const string expand_pathKey[]={"ARRAY","ALL_DIRS","COUNT","PATTERN",KLISTEND}; new DLibFunRetNew(lib::expand_path,string("EXPAND_PATH"),1,expand_pathKey); const string strjoinKey[]={"SINGLE",KLISTEND}; new DLibFunRetNew(lib::strjoin,string("STRJOIN"),2,strjoinKey,NULL,true/*retConstant*/); const string strcmpKey[]={"FOLD_CASE",KLISTEND}; new DLibFunRetNew(lib::strcmp_fun,string("STRCMP"),3,strcmpKey,NULL,true); new DLibFunRetNew(lib::eof_fun,string("EOF"),1); new DLibFunRetNew(lib::arg_present,string("ARG_PRESENT"),1); const string messageKey[]={"CONTINUE","INFORMATIONAL","IOERROR","LEVEL", "NONAME","NOPREFIX","NOPRINT", "RESET","REISSUE_LAST","TRACEBACK", KLISTEND}; //TRACEBACK is in MESSAGE but obsolete since 5.0. it is used widely in CMSVlib ! const string messageWarnKey[]={"NAME", "BLOCK",KLISTEND}; new DLibPro(lib::message_pro,string("MESSAGE"),-1,messageKey,messageWarnKey); const string cdKey[]={"CURRENT",KLISTEND}; new DLibPro(lib::cd_pro,string("CD"),1,cdKey); const string file_testKey[]={"DIRECTORY","EXECUTABLE","READ", "REGULAR","WRITE","ZERO_LENGTH", "GET_MODE", "BLOCK_SPECIAL","CHARACTER_SPECIAL", "NAMED_PIPE","SOCKET","SYMLINK","NOEXPAND_PATH","DANGLING_SYMLINK",KLISTEND}; new DLibFunRetNew(lib::file_test,string("FILE_TEST"),1,file_testKey); const string file_basenameKey[]={"FOLD_CASE",KLISTEND}; new DLibFunRetNew(lib::file_basename,string("FILE_BASENAME"),2,file_basenameKey); const string file_dirnameKey[]={"MARK_DIRECTORY",KLISTEND}; new DLibFunRetNew(lib::file_dirname,string("FILE_DIRNAME"),1,file_dirnameKey); const string file_moveKey[]={"ALLOW_SAME", "OVERWRITE", "REQUIRE_DIRECTORY", "VERBOSE", "NOEXPAND_PATH",KLISTEND}; new DLibPro(lib::file_move,string("FILE_MOVE"),2,file_moveKey); //exists as stub procedure for _WIN32 #ifndef _WIN32 const string file_linkKey[]={"ALLOW_SAME", "HARDLINK", "VERBOSE", "NOEXPAND_PATH",KLISTEND}; new DLibPro(lib::file_link,string("FILE_LINK"),2,file_linkKey); #endif const string file_copyKey[]={"ALLOW_SAME", "OVERWRITE","FORCE", "REQUIRE_DIRECTORY", "VERBOSE", "NOEXPAND_PATH","RECURSIVE","COPY_SYMLINK",KLISTEND}; new DLibPro(lib::file_copy,string("FILE_COPY"),2,file_copyKey); const string file_deleteKey[]={"ALLOW_NONEXISTENT","NOEXPAND_PATH","RECURSIVE", "QUIET","VERBOSE",KLISTEND}; new DLibPro(lib::file_delete,string("FILE_DELETE"),-1,file_deleteKey); const string file_sameKey[]={"NOEXPAND_PATH",KLISTEND}; new DLibFunRetNew(lib::file_same,string("FILE_SAME"),2,file_sameKey); const string file_infoKey[]={"NOEXPAND_PATH",KLISTEND}; new DLibFunRetNew(lib::file_info,string("FILE_INFO"),2,file_infoKey); const string file_linesKey[]={"NOEXPAND_PATH","COMPRESS",KLISTEND}; new DLibFunRetNew(lib::file_lines,string("FILE_LINES"),1,file_linesKey); const string file_mkdirKey[]={"NOEXPAND_PATH",KLISTEND}; new DLibPro(lib::file_mkdir,string("FILE_MKDIR"),-1,file_mkdirKey); new DLibFunRetNew(lib::shift_fun,string("SHIFT"),9,NULL,NULL,true); new DLibFunRetNew(lib::ishft_fun,string("ISHFT"),2,NULL,NULL,true); const string sortKey[]={"L64",KLISTEND}; new DLibFunRetNew(lib::sort_fun,string("SORT"),1,sortKey,NULL,true); const string medianKey[]={"EVEN","DOUBLE","DIMENSION",KLISTEND}; new DLibFunRetNew(lib::median,string("MEDIAN"),2,medianKey); const string meanKey[]={"DOUBLE","DIMENSION","NAN",KLISTEND}; new DLibFunRetNew(lib::mean_fun,string("MEAN"),1,meanKey); const string momentKey[]={"DOUBLE","DIMENSION","NAN","KURTOSIS","MAXMOMENT","MDEV","MEAN","SDEV","SKEWNESS","VARIANCE",KLISTEND}; new DLibFunRetNew(lib::moment_fun,string("MOMENT"),1,momentKey); new DLibFunRetNew(lib::transpose,string("TRANSPOSE"),2,NULL,NULL,true); new DLibPro(lib::retall,string("RETALL")); const string catchKey[]={"CANCEL",KLISTEND}; new DLibPro(lib::catch_pro,string("CATCH"),1,catchKey); new DLibPro(lib::on_error,string("ON_ERROR"),1); new DLibFunRetNew(lib::recall_commands,string("RECALL_COMMANDS"),0); const string exitKey[]={"NO_CONFIRM","STATUS",KLISTEND}; new DLibPro(lib::exitgdl,string("EXIT"),0,exitKey); const string helpKey[]={"ALL_KEYS","BRIEF","FULL","CALLS", "DEBUG","DEVICE","FUNCTIONS","HEAP_VARIABLES","HELP","INFO","FILES", "INTERNAL_LIB_GDL","KEYS","LAST_MESSAGE","LIB","MEMORY","NAMES", "OBJECTS","OUTPUT","PATH_CACHE","PREFERENCES","PROCEDURES", "RECALL_COMMANDS","ROUTINES","SOURCE_FILES","STRUCTURES", "SYSTEM_VARIABLES","TRACEBACK", "COMMON","LEVEL", KLISTEND}; const string helpWarnKey[]={"BREAKPOINTS","DLM", "MESSAGES", "SHARED_MEMORY", KLISTEND}; new DLibPro(lib::help_pro,string("HELP"),-1,helpKey,helpWarnKey); new DLibPro(lib::delvar_pro,string("DELVAR"),-1,NULL,NULL); DLibPro* hide = new DLibPro(lib::findvar_pro,string("FINDVAR"),-1,NULL,NULL); hide->SetHideHelp(true); //stub to avoid setting errors on pref_set. One may want to really write pref_set, // but this function is just here to prevent setting !ERR=-1 when stumbling on a pref_set command, // since !ERR=-1 is frequently checked by legacy procedures. const string pref_setKey[] = {"FILENAME","COMMIT","DEFAULT", KLISTEND }; new DLibPro(lib::pref_set_pro, string("PREF_SET"), -1, pref_setKey); const string memoryKey[]={"CURRENT","HIGHWATER","NUM_ALLOC", "NUM_FREE","STRUCTURE","L64",KLISTEND}; new DLibFunRetNew(lib::memory, string("MEMORY"), 1, memoryKey, NULL); // printKey, readKey and stringKey are closely associated // as the same functions are called "FORMAT" till "MONTH" // must be the first four keywords. The inner print_os function is BASED on this ORDER! //NOTE THAT AM_PM, DAYS_OF_WEEK and MONTHS are silently ignored!!! //implied print is a feature introduced in idl8.3 and shared by print/printf, string and fix(type=7) #define COMMONKEYWORDSFORSTRINGFORMATTING "FORMAT","AM_PM","DAYS_OF_WEEK","MONTHS" const string printKey[]={COMMONKEYWORDSFORSTRINGFORMATTING, "STDIO_NON_FINITE",KLISTEND}; const string impliedprintKey[]={COMMONKEYWORDSFORSTRINGFORMATTING, "STDIO_NON_FINITE","IMPLIED_PRINT",KLISTEND}; //At the moment, print accepts silently "IMPLIED_PRINT" as this is used in autoprint feature. new DLibPro(lib::print,string("PRINT"),-1,impliedprintKey); //but PRINTF issues a warning, as it is not yet supported const string printfWarnKey[]={"IMPLIED_PRINT",KLISTEND}; new DLibPro(lib::printf,string("PRINTF"),-1,printKey,printfWarnKey); // allow printing (of expressions) with all keywords // (easier to implement this way) new DLibPro(lib::stop,string("STOP"),-1,printKey); const string readKey[]={COMMONKEYWORDSFORSTRINGFORMATTING,"PROMPT",KLISTEND}; new DLibPro(lib::read,string("READ"),-1,readKey); new DLibPro(lib::readf,string("READF"),-1,readKey); const string readsKey[]={COMMONKEYWORDSFORSTRINGFORMATTING, KLISTEND}; // no PROMPT new DLibPro(lib::reads,string("READS"),-1,readsKey); const string stringKey[]={COMMONKEYWORDSFORSTRINGFORMATTING,"PRINT",KLISTEND}; const string stringWarnKey[]={"IMPLIED_PRINT",KLISTEND}; new DLibFun(lib::string_fun,string("STRING"),-1,stringKey,stringWarnKey); const string defsysvKey[]={"EXISTS",KLISTEND}; new DLibPro(lib::defsysv,string("DEFSYSV"),3,defsysvKey); const string heap_gcKey[]={"PTR","OBJ","VERBOSE",KLISTEND}; new DLibPro(lib::heap_gc,string("HEAP_GC"),0,heap_gcKey); new DLibPro(lib::heap_free,string("HEAP_FREE"),1,heap_gcKey); const string heap_refcount[]={"DISABLE","ENABLE","IS_ENABLED",KLISTEND}; new DLibFunRetNew(lib::heap_refcount,string("HEAP_REFCOUNT"),1,heap_refcount); new DLibPro(lib::ptr_free,string("PTR_FREE"),-1); const string arrKey[]={"NOZERO",KLISTEND}; new DLibFunRetNew(lib::bytarr,string("BYTARR"),MAXRANK,arrKey,NULL,true/*retConstant*/); new DLibFunRetNew(lib::intarr,string("INTARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::uintarr,string("UINTARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::lonarr,string("LONARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::ulonarr,string("ULONARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::lon64arr,string("LON64ARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::ulon64arr,string("ULON64ARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::fltarr,string("FLTARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::dblarr,string("DBLARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::strarr,string("STRARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::complexarr,string("COMPLEXARR"),MAXRANK,arrKey,NULL,true); new DLibFunRetNew(lib::dcomplexarr,string("DCOMPLEXARR"),MAXRANK,arrKey,NULL,true); const string ptrArrKey[]={"NOZERO","ALLOCATE_HEAP",KLISTEND}; new DLibFunRetNew(lib::ptrarr,string("PTRARR"),MAXRANK,ptrArrKey); new DLibFunRetNew(lib::objarr,string("OBJARR"),MAXRANK,arrKey); const string ptr_newKey[]={"NO_COPY","ALLOCATE_HEAP",KLISTEND}; new DLibFunRetNew(lib::ptr_new,string("PTR_NEW"),1,ptr_newKey); const string obj_validKey[]={"CAST","COUNT","GET_HEAP_IDENTIFIER",KLISTEND}; new DLibFunRetNew(lib::ptr_valid,string("PTR_VALID"),1,obj_validKey); new DLibFunRetNew(lib::obj_valid,string("OBJ_VALID"),1,obj_validKey); const string obj_newKey[]={"_REF_EXTRA",KLISTEND}; new DLibFunRetNew(lib::obj_new,string("OBJ_NEW"),-1,obj_newKey); new DLibPro(lib::obj_destroy,string("OBJ_DESTROY"),-1,obj_newKey); // call... fun/pro new DLibFun(lib::call_function,string("CALL_FUNCTION"),-1,obj_newKey); new DLibPro(lib::call_procedure,string("CALL_PROCEDURE"),-1,obj_newKey); new DLibFun(lib::call_method_function, string("CALL_METHOD"),-1,obj_newKey); new DLibPro(lib::call_method_procedure,string("CALL_METHOD"),-1,obj_newKey); const string indKey[]={"TYPE","BYTE","COMPLEX","DCOMPLEX", "DOUBLE","FLOAT","L64","LONG", "STRING","UINT","UL64","ULONG", "START", "INCREMENT", KLISTEND}; const string xindKey[]={"START", "INCREMENT", KLISTEND}; new DLibFunRetNew(lib::bindgen,string("BINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::indgen,string("INDGEN"),MAXRANK,indKey,NULL,true); new DLibFunRetNew(lib::uindgen,string("UINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::sindgen,string("SINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::lindgen,string("LINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::ulindgen,string("ULINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::l64indgen,string("L64INDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::ul64indgen,string("UL64INDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::findgen,string("FINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::dindgen,string("DINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::cindgen,string("CINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::dcindgen,string("DCINDGEN"),MAXRANK,xindKey,NULL,true); new DLibFunRetNew(lib::n_elements,string("N_ELEMENTS"),1,NULL,NULL,true,1); new DLibFun(lib::execute_fun,string("EXECUTE"),3); const string openKey[]={"APPEND","COMPRESS","BUFSIZE", "DELETE","ERROR","F77_UNFORMATTED", "GET_LUN" /*7*/,"MORE","STDIO", "SWAP_ENDIAN","SWAP_IF_BIG_ENDIAN", "SWAP_IF_LITTLE_ENDIAN" /*12*/, "VAX_FLOAT","WIDTH","XDR", "BLOCK", "NOAUTOMODE","BINARY","STREAM", KLISTEND}; const string openWarnKey[]={"INITIALSIZE","EXTENDSIZE",KLISTEND}; // VAX only new DLibPro(lib::openr,string("OPENR"),3,openKey,openWarnKey); new DLibPro(lib::openw,string("OPENW"),3,openKey,openWarnKey); new DLibPro(lib::openu,string("OPENU"),3,openKey,openWarnKey); new DLibPro(lib::get_lun,string("GET_LUN"),1); const string socketKey[]={"ERROR","GET_LUN","STDIO", "SWAP_ENDIAN","SWAP_IF_BIG_ENDIAN", "SWAP_IF_LITTLE_ENDIAN","WIDTH", "CONNECT_TIMEOUT","READ_TIMEOUT", "WRITE_TIMEOUT", KLISTEND}; new DLibPro(lib::socket,string("SOCKET"),3,socketKey); new DLibPro(lib::flush_lun,string("FLUSH"),-1); const string close_lunKey[]={"FORCE","FILE","ALL",KLISTEND}; const string close_lunWarnKey[]={"EXIT_STATUS",KLISTEND}; new DLibPro(lib::close_lun,string("CLOSE"),-1,close_lunKey,close_lunWarnKey); const string free_lunKey[]={"FORCE",KLISTEND}; const string free_lunWarnKey[]={"EXIT_STATUS",KLISTEND}; new DLibPro(lib::free_lun,string("FREE_LUN"),-1,free_lunKey,free_lunWarnKey); const string writeuKey[]={"TRANSFER_COUNT",KLISTEND}; new DLibPro(lib::writeu,string("WRITEU"),-1,writeuKey); new DLibPro(lib::readu,string("READU"),-1,writeuKey); const string resolve_routineWarnKey[]={"SKIP_EXISTING",KLISTEND}; const string resolve_routineKey[]={"NO_RECOMPILE","IS_FUNCTION","EITHER","COMPILE_FULL_FILE","QUIET",KLISTEND}; new DLibPro(lib::resolve_routine,string("RESOLVE_ROUTINE"),1, resolve_routineKey,resolve_routineWarnKey); const string routine_filepathKey[]={"EITHER","IS_FUNCTION", KLISTEND}; new DLibFunRetNew(lib::routine_filepath,string("ROUTINE_FILEPATH"),1, routine_filepathKey); const string assocKey[]={"PACKED",KLISTEND}; new DLibFunRetNew(lib::assoc,string("ASSOC"),3,assocKey); new DLibFun(lib::byte_fun,string("BYTE"),10,NULL,NULL); /* new DLibFunRetNew(lib::fix_fun,string("FIX"),10,fixKey,NULL,true); new DLibFunRetNew(lib::uint_fun,string("UINT"),10,NULL,NULL,true); new DLibFunRetNew(lib::long_fun,string("LONG"),10,NULL,NULL,true); new DLibFunRetNew(lib::ulong_fun,string("ULONG"),10,NULL,NULL,true); new DLibFunRetNew(lib::long64_fun,string("LONG64"),10,NULL,NULL,true); new DLibFunRetNew(lib::ulong64_fun,string("ULONG64"),10,NULL,NULL,true); new DLibFunRetNew(lib::float_fun,string("FLOAT"),10,NULL,NULL,true); new DLibFunRetNew(lib::double_fun,string("DOUBLE"),10,NULL,NULL,true); new DLibFunRetNew(lib::complex_fun,string("COMPLEX"),MAXRANK+2,NULL,NULL,true); new DLibFunRetNew(lib::dcomplex_fun,string("DCOMPLEX"),MAXRANK+2,NULL,NULL,true); */ // that's apparently the desired bahaviour, see bug no. 3151760 const string fixKey[]={"TYPE","PRINT",KLISTEND}; const string fixWarnKey[]={"IMPLIED_PRINT",KLISTEND}; new DLibFun(lib::fix_fun,string("FIX"),10,fixKey,fixWarnKey); new DLibFun(lib::uint_fun,string("UINT"),10,NULL,NULL); new DLibFun(lib::long_fun,string("LONG"),10,NULL,NULL); new DLibFun(lib::ulong_fun,string("ULONG"),10,NULL,NULL); new DLibFun(lib::long64_fun,string("LONG64"),10,NULL,NULL); new DLibFun(lib::ulong64_fun,string("ULONG64"),10,NULL,NULL); new DLibFun(lib::float_fun,string("FLOAT"),10,NULL,NULL); new DLibFun(lib::double_fun,string("DOUBLE"),10,NULL,NULL); const string complexKey[]={"DOUBLE",KLISTEND}; new DLibFun(lib::complex_fun,string("COMPLEX"),MAXRANK+2,complexKey,NULL); new DLibFun(lib::dcomplex_fun,string("DCOMPLEX"),MAXRANK+2,NULL,NULL); new DLibFunRetNew(lib::gdl_logical_and,string("LOGICAL_AND"),2,NULL,NULL,true); new DLibFunRetNew(lib::gdl_logical_or,string("LOGICAL_OR"),2,NULL,NULL,true); new DLibFunDirect(lib::logical_true,string("LOGICAL_TRUE")); new DLibFunRetNew(lib::replicate,string("REPLICATE"),9,NULL,NULL,true); new DLibPro(lib::replicate_inplace_pro,string("REPLICATE_INPLACE"),6); new DLibFunDirect(lib::sin_fun,string("SIN")); new DLibFunDirect(lib::cos_fun,string("COS")); new DLibFunDirect(lib::tan_fun,string("TAN"));//,1,NULL,NULL,true); new DLibFunDirect(lib::sinh_fun,string("SINH"));//,1,NULL,NULL,true); new DLibFunDirect(lib::cosh_fun,string("COSH"));//,1,NULL,NULL,true); new DLibFunDirect(lib::tanh_fun,string("TANH"));//,1,NULL,NULL,true); new DLibFunDirect(lib::asin_fun,string("ASIN")); new DLibFunDirect(lib::acos_fun,string("ACOS")); const string atanKey[] = {"PHASE", KLISTEND}; new DLibFunRetNew(lib::atan_fun,string("ATAN"),2,atanKey,NULL,true); new DLibFunDirect(lib::alog_fun,string("ALOG")); new DLibFunDirect(lib::alog10_fun,string("ALOG10")); // new DLibFunRetNew(lib::alog_fun,string("ALOG"),1,NULL,NULL,true,1); // new DLibFunRetNew(lib::alog10_fun,string("ALOG10"),1,NULL,NULL,true,1); new DLibFunDirect(lib::sqrt_fun,string("SQRT")); new DLibFunDirect(lib::abs_fun,string("ABS")); new DLibFunDirect(lib::exp_fun,string("EXP")); const string roundKey[]={"L64",KLISTEND}; // retConstant: check definition of the rounding functions if they depend // from some sys var (defining a round mode) // (probably nobody rounds a constant anyway) new DLibFunRetNew(lib::round_fun,string("ROUND"),1,roundKey); const string ceilfloorKey[]={"L64",KLISTEND}; new DLibFunRetNew(lib::ceil_fun,string("CEIL"),1,ceilfloorKey); new DLibFunRetNew(lib::floor_fun,string("FLOOR"),1,ceilfloorKey); new DLibFunDirect(lib::conj_fun,string("CONJ")); new DLibFunDirect(lib::imaginary_fun,string("IMAGINARY")); const string strcompressKey[]={"REMOVE_ALL",KLISTEND}; new DLibFunRetNew(lib::strcompress,string("STRCOMPRESS"),1,strcompressKey,NULL,true); new DLibFunDirect(lib::strlowcase,string("STRLOWCASE")); new DLibFunDirect(lib::strupcase,string("STRUPCASE")); new DLibFunDirect(lib::strlen,string("STRLEN")); const string strmidKey[]={"REVERSE_OFFSET",KLISTEND}; new DLibFunRetNew(lib::strmid,string("STRMID"),3,strmidKey,NULL,true); new DLibFunRetNew(lib::strtrim,string("STRTRIM"),2,NULL,NULL,true); const string strposKey[]={"REVERSE_OFFSET","REVERSE_SEARCH",KLISTEND}; new DLibFunRetNew(lib::strpos,string("STRPOS"),3,strposKey,NULL,true,2); new DLibPro(lib::strput,string("STRPUT"),3,NULL,NULL,2); const string whereKey[]={"COMPLEMENT","NCOMPLEMENT","NULL","L64",KLISTEND}; new DLibFunRetNew(lib::where_fun,string("WHERE"),2,whereKey); const string totalKey[]={"CUMULATIVE","DOUBLE","NAN","INTEGER","PRESERVE_TYPE",KLISTEND}; new DLibFunRetNew(lib::total_fun,string("TOTAL"),2,totalKey,NULL,true); const string productKey[]={"CUMULATIVE","NAN","INTEGER","PRESERVE_TYPE",KLISTEND}; new DLibFunRetNew(lib::product_fun,string("PRODUCT"),2,productKey,NULL,true); new DLibFunRetNew(lib::n_params,string("N_PARAMS"),1); // IDL allows one parameter new DLibFunRetNew(lib::keyword_set,string("KEYWORD_SET"),1); const string array_equalKey[]={"NO_TYPECONV","NOT_EQUAL","QUIET",KLISTEND}; new DLibFunRetNew(lib::array_equal,string("ARRAY_EQUAL"),2,array_equalKey,NULL,true); const string minKey[]={"MAX","NAN","SUBSCRIPT_MAX","DIMENSION","ABSOLUTE",KLISTEND}; new DLibFunRetNew(lib::min_fun,string("MIN"),2,minKey,NULL,true); const string maxKey[]={"MIN","NAN","SUBSCRIPT_MIN","DIMENSION","ABSOLUTE",KLISTEND}; new DLibFunRetNew(lib::max_fun,string("MAX"),2,maxKey,NULL,true); // retConstant: structs are tricky: struct resolution depends from !PATH // and this might change during runtime, but if treated as retConstant // the struct would be already defined at compile time. const string create_structKey[]={"NAME",KLISTEND}; new DLibFunRetNew(lib::create_struct,string("CREATE_STRUCT"),-1,create_structKey/*,true*/); new DLibFunRetNew(lib::rotate,string("ROTATE"),2,NULL,NULL,true); const string reverseKey[] = {"OVERWRITE", KLISTEND}; new DLibFun(lib::reverse, string("REVERSE"), 2, reverseKey, NULL, true); // const string minKey[]={"MAX",KLISTEND}; // new DLibFun(lib::min_fun,string("MIN"),2,minKey); // const string maxKey[]={"MIN",KLISTEND}; // new DLibFun(lib::max_fun,string("MAX"),2,maxKey); #ifdef USE_PYTHON const string python_funKey[]={"ARGV","DEFAULTRETURNVALUE",KLISTEND}; new DLibFun(lib::gdlpython_fun,string("PYTHON"),-1,python_funKey); const string python_proKey[]={"ARGV",KLISTEND}; new DLibPro(lib::gdlpython_pro,string("PYTHON"),-1,python_proKey); #endif // graphics ******************************************************* const string windowKey[]={"COLORS","FREE","PIXMAP","RETAIN","TITLE", "XPOS","YPOS","XSIZE","YSIZE",KLISTEND}; new DLibPro(lib::window,string("WINDOW"),1,windowKey); new DLibPro(lib::wdelete,string("WDELETE"),-1); new DLibPro(lib::wset,string("WSET"),1); const string wshowKey[]={"ICONIC", KLISTEND}; new DLibPro(lib::wshow,string("WSHOW"),2,wshowKey); const string cursorKey[]={"CHANGE","DOWN","NOWAIT","UP","WAIT", "DATA","DEVICE","NORMAL",KLISTEND}; new DLibPro(lib::cursor,string("CURSOR"),3,cursorKey); const string set_plotKey[]={"COPY","INTERPOLATE",KLISTEND}; new DLibPro(lib::set_plot,string("SET_PLOT"),1,set_plotKey); const string get_screen_sizeKey[]={"RESOLUTION","DISPLAY_NAME",KLISTEND}; new DLibFunRetNew(lib::get_screen_size,string("GET_SCREEN_SIZE"),1,get_screen_sizeKey); const string tvlctKey[]={"GET","HLS","HSV",KLISTEND}; new DLibPro(lib::tvlct,string("TVLCT"),4,tvlctKey); const string tvcrsKey[]={"DATA","DEVICE","NORMAL",KLISTEND}; const string tvcrsWarnKey[]={"CENTIMETERS","INCHES","HIDE_CURSOR","T3D","Z",KLISTEND}; new DLibPro(lib::tvcrs,string("TVCRS"),2,tvcrsKey,tvcrsWarnKey); new DLibPro(lib::empty,string("EMPTY"),-1); const string deviceKey[]= { "CLOSE_FILE", "FILENAME", "LANDSCAPE", "PORTRAIT", //there is a "CLOSE" for device Z defined... and a CLOSE_DOCUMENT for printer "DECOMPOSED","GET_DECOMPOSED","Z_BUFFERING","SET_RESOLUTION", "XSIZE","YSIZE", "COLOR","GET_PAGE_SIZE","GET_SCREEN_SIZE","INCHES","WINDOW_STATE","SCALE_FACTOR", "XOFFSET", "YOFFSET", "ENCAPSULATED", "GET_GRAPHICS_FUNCTION", "SET_GRAPHICS_FUNCTION", "CURSOR_STANDARD", "CURSOR_ORIGINAL", "CURSOR_CROSSHAIR","RETAIN", "BITS_PER_PIXEL", "GET_WINDOW_POSITION","GET_PIXEL_DEPTH","GET_VISUAL_DEPTH","GET_VISUAL_NAME", "GET_WRITE_MASK", "COPY","GET_FONTNAMES","SET_FONT","GET_CURRENT_FONT","GET_FONTNUM", "SET_PIXEL_DEPTH", //Z "SET_CHARACTER_SIZE", //(all) KLISTEND }; const string deviceWarnKey[] = { "AVANTGARDE","BKMAN","COURIER","HELVETICA","ISOLATIN","PALATINO","SCHOOLBOOK","SYMBOL","TIMES","ZAPFCHANCERY","ZAPFDINGBATS", //PS //"AVERAGE_LINES", (REGIS) //"BINARY","NCAR","TEXT", (CGM) "BOLD", //PS "BOOK", //PS "BYPASS_TRANSLATION", //(WIN,X) "CMYK", //PS "CURSOR_IMAGE", //WIN,X "CURSOR_MASK", //WIN,X "CURSOR_XY", //WIN,X "DIRECT_COLOR", //X //"EJECT", (HP) //"ENCODING", (CGM) "FLOYD", //(PCL,X) "FONT_INDEX", //PS "FONT_SIZE", //PS //"GIN_CHARS", (TEX) "GLYPH_CACHE", //PRINTER,PS,WIN,Z,METAFILE //"INDEX_COLOR", (METAFILE, PRINTER) "ITALIC", //PS "LANGUAGE_LEVEL" //PS, "DEMI","LIGHT","MEDIUM","NARROW","OBLIQUE", //PS //"OPTIMIZE", (PCL) "ORDERED", //(PCL,X) "OUTPUT", //(HP,PS) //"PIXELS", (PCL) //"PLOT_TO", (REGIS,TEK) //"PLOTTER_ON_OFF", "POLYFILL", (HP) "PRE_DEPTH","PRE_XSIZE","PRE_YSIZE","PREVIEW", //PS "PRINT_FILE",// WIN "PSEUDO_COLOR",//X //"RESET_STRING", (TEK) //"RESOLUTION", (PCL) //"SET_COLORMAP",(PCL) "SET_COLORS", //Z //"SET_STRING", (TEK) "SET_TRANSLATION", //X "SET_WRITE_MASK", //(X,Z) "STATIC_COLOR",//X "STATIC_GRAY",//X //"TEK4014","TEK4100", (TEK) "THRESHOLD", //X "TRANSLATION", //(WIN,X) "TRUE_COLOR", //(METAFILE, PRINTER, X) "TT_FONT", //(METAFILE, PRINTER, X, PS, WIN, Z) //"TTY", (REGIS, TEK) //"VT240","VT241","VT340","VT341",(REGIS) //"XON_XOFF" (HP) KLISTEND}; new DLibPro(lib::device,string("DEVICE"),0, deviceKey, deviceWarnKey); const string usersymKey[]= { "FILL", "COLOR","THICK", KLISTEND }; new DLibPro(lib::usersym,string("USERSYM"),2, usersymKey); const string plotKey[]= { "BACKGROUND","CHARSIZE","CHARTHICK","CLIP", "COLOR", "DATA", "DEVICE", "ISOTROPIC", "LINESTYLE", "NOCLIP", "NODATA", "NOERASE", "NORMAL", "POSITION","PSYM", "SUBTITLE", "SYMSIZE", "THICK", "TICKLEN", "TITLE", "MAX_VALUE", "MIN_VALUE", "XLOG", "YLOG", "YNOZERO", "XTYPE", "YTYPE", "POLAR", "NSUM", //XTYPE and YTYPE are oldies, equivalent to XLOG when value is odd. "XCHARSIZE", "YCHARSIZE", "XGRIDSTYLE", "YGRIDSTYLE", "XMARGIN", "YMARGIN", "XMINOR", "YMINOR", "XRANGE", "YRANGE", "XSTYLE", "YSTYLE", "XTHICK", "YTHICK", "XTICK_GET", "YTICK_GET", "XTICKFORMAT", "YTICKFORMAT", "XTICKINTERVAL", "YTICKINTERVAL", "XTICKLAYOUT", "YTICKLAYOUT", "XTICKLEN", "YTICKLEN", "XTICKNAME", "YTICKNAME", "XTICKS", "YTICKS", "XTICKUNITS", "YTICKUNITS", "XTICKV", "YTICKV", "XTITLE", "YTITLE", "ZCHARSIZE", "ZGRIDSTYLE", "ZMARGIN", "ZMINOR", "ZRANGE", "ZSTYLE", "ZTHICK", "ZTICK_GET", "ZTICKFORMAT", "ZTICKINTERVAL", "ZTICKLAYOUT", "ZTICKLEN", "ZTICKNAME", "ZTICKS", "ZTICKUNITS", "ZTICKV", "ZTITLE", "T3D", "ZVALUE", "FONT", "CHANNEL", KLISTEND }; // // const string plotWarnKey[]= { "FONT","CHANNEL", KLISTEND }; new DLibPro(lib::plot,string("PLOT"),2,plotKey);//,plotWarnKey); new DLibPro(lib::plot_io,string("PLOT_IO"),2,plotKey);//,plotWarnKey); new DLibPro(lib::plot_oo,string("PLOT_OO"),2,plotKey);//,plotWarnKey); new DLibPro(lib::plot_oi,string("PLOT_OI"),2,plotKey);//,plotWarnKey); const string axisKey[]= { "CHARSIZE", "CHARTHICK", "COLOR", "DATA", "DEVICE", "FONT", "NODATA", "NOERASE", "NORMAL", "SUBTITLE", "T3D", "TICKLEN", "SAVE", "XAXIS", "YAXIS", "XLOG", "YLOG", "XTYPE", "YTYPE", "YNOZERO", "THICK", "XCHARSIZE", "YCHARSIZE", "XGRIDSTYLE", "YGRIDSTYLE", "XMARGIN", "YMARGIN", "XMINOR", "YMINOR", "XRANGE", "YRANGE", "XSTYLE", "YSTYLE", "XTHICK", "YTHICK", "XTICK_GET", "YTICK_GET", "XTICKFORMAT", "YTICKFORMAT", "XTICKINTERVAL", "YTICKINTERVAL", "XTICKLAYOUT", "YTICKLAYOUT", "XTICKLEN", "YTICKLEN", "XTICKNAME", "YTICKNAME", "XTICKS", "YTICKS", "XTICKUNITS", "YTICKUNITS", "XTICKV", "YTICKV", "XTITLE", "YTITLE", "ZAXIS", "ZLOG", "ZVALUE", "ZCHARSIZE", "ZGRIDSTYLE", "ZMARGIN", "ZMINOR", "ZRANGE", "ZSTYLE", "ZTHICK", "ZTICK_GET", "ZTICKFORMAT", "ZTICKINTERVAL", "ZTICKLAYOUT", "ZTICKLEN", "ZTICKNAME", "ZTICKS", "ZTICKUNITS", "ZTICKV", "ZTITLE", "CHANNEL", KLISTEND }; new DLibPro(lib::axis,string("AXIS"),3,axisKey); const string oplotKey[]= { // GRAPHIC KEYWORDS // 0 "CLIP","COLOR", "LINESTYLE", "NOCLIP", // 4 "PSYM", "SYMSIZE", "T3D", "ZVALUE", "THICK", // 8 "MAX_VALUE", "MIN_VALUE", "NSUM", "POLAR", "CHANNEL", KLISTEND }; new DLibPro(lib::oplot, string("OPLOT"),2,oplotKey); const string plotsKey[]= { "CLIP","COLOR", "LINESTYLE", "NOCLIP", "PSYM", "SYMSIZE", "T3D", "Z", "THICK", "DATA","DEVICE","NORMAL","CONTINUE", KLISTEND }; new DLibPro(lib::plots, string("PLOTS"), 3, plotsKey); const string set_shadingKey[]= { "LIGHT", KLISTEND }; const string set_shadingWarnKey[]= { "GOURAUD","REJECT","VALUES",KLISTEND }; new DLibPro(lib::set_shading, string("SET_SHADING"), 0, set_shadingKey, set_shadingWarnKey); const string shade_surfKey[]= { "AX", "AZ", "MAX_VALUE", "MIN_VALUE", "SHADES", "HORIZONTAL", "LOWER_ONLY", "UPPER_ONLY", "BOTTOM", // ([xyz]type undocumented but still existing in SHADE_SURF ...) "XLOG", "YLOG", "ZLOG", "XTYPE", "YTYPE", "ZTYPE", //General Graphics KW "BACKGROUND", "NOERASE", "CLIP", "NOCLIP", "CHARSIZE", "CHARTHICK", "COLOR", "DATA", "DEVICE", "NORMAL", "FONT", "NODATA", "POSITION", "SUBTITLE", "THICK", "TICKLEN", "TITLE", //Axis KW "ZCHARSIZE", "YCHARSIZE", "XCHARSIZE", "ZGRIDSTYLE", "YGRIDSTYLE", "XGRIDSTYLE", "ZMARGIN", "YMARGIN", "XMARGIN", "ZMINOR", "YMINOR", "XMINOR", "ZRANGE", "YRANGE", "XRANGE", "ZSTYLE", "YSTYLE", "XSTYLE", "ZTHICK", "YTHICK", "XTHICK", "ZTICKFORMAT", "YTICKFORMAT", "XTICKFORMAT", "ZTICKINTERVAL", "YTICKINTERVAL", "XTICKINTERVAL", "ZTICKLAYOUT", "YTICKLAYOUT", "XTICKLAYOUT", "ZTICKLEN", "YTICKLEN", "XTICKLEN", "ZTICKNAME", "YTICKNAME", "XTICKNAME", "ZTICKS", "YTICKS", "XTICKS", "ZTICKUNITS", "YTICKUNITS", "XTICKUNITS", "ZTICKV", "YTICKV", "XTICKV", "ZTICK_GET", "YTICK_GET", "XTICK_GET", "ZTITLE", "YTITLE", "XTITLE", //3D KW "ZVALUE","T3D", "SAVE", "SKIRT", "ZAXIS", "CHANNEL", KLISTEND }; const string shade_surfWarnKey[]= { "IMAGE", "PIXELS", KLISTEND }; new DLibPro(lib::shade_surf,string("SHADE_SURF"),3,shade_surfKey, shade_surfWarnKey); const string surfaceKey[]= { // GRAPHIC KEYWORDS "BACKGROUND","CHARSIZE","CHARTHICK","CLIP", "COLOR", "DATA", "DEVICE", "FONT", "LINESTYLE", "NOCLIP", "NODATA", "NOERASE", "NORMAL", "POSITION", "SUBTITLE", "THICK", "TICKLEN", "TITLE", "XCHARSIZE", "XGRIDSTYLE", "XMARGIN", "XMINOR", "XRANGE", "XSTYLE", "XTHICK", "XTICKFORMAT", "XTICKINTERVAL","XTICKLAYOUT","XTICKLEN","XTICKNAME", "XTICKS", "XTICKUNITS", "XTICKV", "XTICK_GET", "XTITLE", "YCHARSIZE", "YGRIDSTYLE", "YMARGIN", "YMINOR", "YRANGE", "YSTYLE", "YTHICK", "YTICKFORMAT", "YTICKINTERVAL","YTICKLAYOUT","YTICKLEN","YTICKNAME", "YTICKS", "YTICKUNITS", "YTICKV", "YTICK_GET", "YTITLE", "ZCHARSIZE", "ZGRIDSTYLE", "ZMARGIN", "ZMINOR", "ZRANGE", "ZSTYLE", "ZTHICK", "ZTICKFORMAT", "ZTICKINTERVAL","ZTICKLAYOUT","ZTICKLEN","ZTICKNAME", "ZTICKS", "ZTICKUNITS", "ZTICKV", "ZTICK_GET", "ZTITLE", // SURFACE keywords "MAX_VALUE", "MIN_VALUE", "AX", "AZ", // ([xyz]type undocumented but still existing in SURFACE ...) "XLOG", "YLOG", "ZLOG", "XTYPE", "YTYPE", "ZTYPE", "HORIZONTAL", "LOWER_ONLY", "UPPER_ONLY", "SHADES", "ZAXIS", "BOTTOM", "SKIRT", "SAVE", "T3D", "ZVALUE", "CHANNEL", KLISTEND }; const string surfaceWarnKey[]= { "LEGO", KLISTEND }; new DLibPro(lib::surface,string("SURFACE"),3,surfaceKey, surfaceWarnKey); const string contourKey[]= { "BACKGROUND","CHARSIZE","CHARTHICK","CLIP", "COLOR", "DATA", "DEVICE", "NOCLIP", "NODATA", "NOERASE", "NORMAL", "POSITION", "SUBTITLE", "T3D", "THICK", "TICKLEN", "TITLE" , "LEVELS", "NLEVELS", "MAX_VALUE", "MIN_VALUE", // ([xy]type undocumented but still existing in CONTOUR ...) "XLOG", "YLOG", "XTYPE", "YTYPE", "FILL", "ISOTROPIC", "FOLLOW", "XCHARSIZE", "YCHARSIZE", "ZCHARSIZE", "XGRIDSTYLE", "YGRIDSTYLE", "ZGRIDSTYLE", "XMARGIN", "YMARGIN", "ZMARGIN", "XMINOR", "YMINOR", "ZMINOR", "XRANGE", "YRANGE", "ZRANGE", "XSTYLE", "YSTYLE", "ZSTYLE", "XTHICK", "YTHICK", "ZTHICK", "XTICK_GET", "YTICK_GET", "ZTICK_GET", "XTICKFORMAT", "YTICKFORMAT", "ZTICKFORMAT", "XTICKINTERVAL", "YTICKINTERVAL", "ZTICKINTERVAL", "XTICKLAYOUT", "YTICKLAYOUT", "ZTICKLAYOUT", "XTICKLEN", "YTICKLEN", "ZTICKLEN", "XTICKNAME", "YTICKNAME", "ZTICKNAME", "XTICKS", "YTICKS", "ZTICKS", "XTICKUNITS", "YTICKUNITS", "ZTICKUNITS", "XTICKV", "YTICKV","ZTICKV", "XTITLE", "YTITLE", "ZTITLE", "ZVALUE", "ZAXIS", "C_CHARSIZE","OVERPLOT","C_COLORS","C_LINESTYLE", "C_LABELS", "C_CHARTHICK", "C_ORIENTATION", "C_SPACING", "C_THICK", "PATH_INFO","PATH_XY", "ZLOG","IRREGULAR", "CHANNEL", "FONT", //ZLOG is an addition for GDL only & FONT is not permitted apparently KLISTEND }; // NO SUPPORT AT ALL for:,"CLOSED","DOWNHILL","IRREGULAR","PATH_DATA_COORDS","PATH_FILENAME", // "PATH_INFO","PATH_XY","TRIANGULATION","PATH_DOUBLE","ZAXIS" // "CHANNEL" is supposed to be passed from CONTOUR, PLOT, OPLOT, SHADE_SURF etc to ERASE const string contourWarnKey[]= { "CELL_FILL","C_ANNOTATIONS","CLOSED","DOWNHILL", "PATH_DATA_COORDS","PATH_FILENAME", "PATH_INFO","PATH_XY","TRIANGULATION","PATH_DOUBLE",KLISTEND }; new DLibPro(lib::contour,string("CONTOUR"),3,contourKey,contourWarnKey); // note that although SIZE is not in IDL6+ documentation, it is widely used // in place of CHARSIZE.... const string xyoutsKey[]= { "COLOR","DATA","NORMAL","DEVICE","CLIP", "ORIENTATION","ALIGNMENT","CHARSIZE","SIZE","CHARTHICK", //note SIZE is not in doc but in XYOUTS demo! "NOCLIP","T3D","Z","TEXT_AXES","WIDTH","FONT",KLISTEND }; new DLibPro(lib::xyouts, string("XYOUTS"), 3, xyoutsKey);//, xyoutsWarnKey); const string polyfillKey[]= { "CLIP", "COLOR","DATA","DEVICE","NORMAL","LINESTYLE","NOCLIP", //supported graphic KW "ORIENTATION","THICK", //supported graphic KW "LINE_FILL", "SPACING", "T3D","Z", //polyfill specifics KLISTEND }; const string polyfillWarnKey[]= { "IMAGE_COORD","IMAGE_INTERP", "PATTERN", "TRANSPARENT",KLISTEND }; new DLibPro(lib::polyfill, string("POLYFILL"), 3, polyfillKey,polyfillWarnKey); const string scale3Key[]= { "AX", "AZ", "XRANGE", "YRANGE", "ZRANGE", KLISTEND }; new DLibPro(lib::scale3_pro, string("SCALE3"), 0, scale3Key); //in plotting_convert_coord.cpp const string t3dKey[]= { "RESET", "MATRIX", "OBLIQUE", "PERSPECTIVE", "ROTATE", "SCALE", "TRANSLATE", "XYEXCH", "XZEXCH", "YZEXCH", KLISTEND }; new DLibPro(lib::t3d_pro, string("T3D"), 1, t3dKey); //in plotting_convert_coord.cpp const string eraseKey[]= {"CHANNEL","COLOR",KLISTEND}; new DLibPro(lib::erase,string("ERASE"),1, eraseKey); new DLibFunRetNew(lib::format_axis_values,string("FORMAT_AXIS_VALUES"),1); const string laguerreKey[]={"DOUBLE","COEFFICIENTS",KLISTEND}; new DLibFunRetNew(lib::laguerre,string("LAGUERRE"),3,laguerreKey); new DLibFunRetNew(lib::gauss_pdf,string("GAUSS_PDF"),1); new DLibFunRetNew(lib::gauss_cvf,string("GAUSS_CVF"),1); new DLibFunRetNew(lib::t_pdf,string("T_PDF"),2); new DLibPro(lib::caldat, string("CALDAT"), 7); new DLibFunRetNew(lib::julday, string("JULDAY"), 6); // SA: the HYBRID key is used in imsl_zerosys.pro to switch to the modif. brent algo. const string newtonKey[] = {"DOUBLE", "ITMAX", "TOLF", "TOLX", "HYBRID", KLISTEND }; const string newtonWarnKey[] = {"CHECK", "STEPMAX", "TOLMIN", KLISTEND}; new DLibFunRetNew(lib::newton_broyden, string("NEWTON"), 2, newtonKey, newtonWarnKey); //WARNING: THESE FUNCTIONS MUST HAVE THE SAME OPTION LIST. NOTE THAT /HYBRID is not part of either functions, //it is used by imsl_zerosys.pro const string broydenKey[] = {"DOUBLE", "ITMAX", "TOLF", "TOLX", "HYBRID", KLISTEND }; const string broydenWarnKey[] = {"CHECK", "STEPMAX", "TOLMIN", "EPS", KLISTEND}; new DLibFunRetNew(lib::newton_broyden, string("BROYDEN"), 2, broydenKey, broydenWarnKey); const string amoebaKey[] = {"FUNCTION_NAME", "FUNCTION_VALUE", "NCALLS", "NMAX", "P0", "SCALE" , "SIMPLEX", KLISTEND }; new DLibFunRetNew(lib::amoeba, string("AMOEBA"), 1, amoebaKey); const string dfpminKey[] = { "DOUBLE", "EPS", "ITER", "ITMAX", "STEPMAX", "TOLX", KLISTEND }; new DLibPro(lib::dfpmin, string("DFPMIN"), 5, dfpminKey); const string brentKey[] = { "DOUBLE", "ITER", "ITMAX", KLISTEND }; new DLibPro(lib::brent, string("POWELL"), 5, brentKey); //#ifdef USE_GLPK const string simplexKey[] = { "DOUBLE", "EPS", "STATUS", KLISTEND }; new DLibFunRetNew(lib::simplex, string("SIMPLEX"), 8, simplexKey); //#endif new DLibFunRetNew(lib::parse_url, string("PARSE_URL"), 1); new DLibFunRetNew(lib::locale_get, string("LOCALE_GET"), 0); new DLibFunRetNew(lib::get_login_info, string("GET_LOGIN_INFO"), 0); new DLibFunRetNew(lib::idl_base64, string("IDL_BASE64"), 1); const string ll_arc_distanceKey[] = {"DEGREES", KLISTEND }; new DLibFunRetNew(lib::ll_arc_distance, string("LL_ARC_DISTANCE"), 3, ll_arc_distanceKey); const string command_line_argsKey[] = {"COUNT","RESET","SET", KLISTEND }; //note: reset and set are unsupported extensions. // original const string command_line_argsKey[] = {"COUNT", KLISTEND }; new DLibFunRetNew(lib::command_line_args_fun, string("COMMAND_LINE_ARGS"), 0, command_line_argsKey); const string pmKey[] = {"FORMAT", "TITLE", KLISTEND }; new DLibPro(lib::pm, string("PM"), -1, pmKey); const string constantKey[] = {"DOUBLE", KLISTEND }; new DLibFunRetNew(lib::constant, string("IMSL_CONSTANT"), 2, constantKey); const string get_drive_listKey[] = {"COUNT", KLISTEND }; new DLibFunRetNew(lib::get_drive_list, string("GET_DRIVE_LIST"), 0, get_drive_listKey); const string binomialcoefKey[] = {"DOUBLE", KLISTEND }; new DLibFunRetNew(lib::binomialcoef, string("IMSL_BINOMIALCOEF"), 2, binomialcoefKey); // SA: GRIB format support based on the ECMWF GRIB_API package (IDL does not support it yet) // GRIBAPI_ prefix is used in order to (hopefully) prevent future incompatibilities with IDL // ----------------------------------------------------------------------------------------- // GRIB: file related new DLibFunRetNew(lib::grib_open_file_fun, string("GRIBAPI_OPEN_FILE"), 1); new DLibFunRetNew(lib::grib_count_in_file_fun, string("GRIBAPI_COUNT_IN_FILE"), 1); new DLibPro(lib::grib_close_file_pro, string("GRIBAPI_CLOSE_FILE"), 1); // GRIB: message related new DLibFunRetNew(lib::grib_new_from_file_fun, string("GRIBAPI_NEW_FROM_FILE"), 1); new DLibPro(lib::grib_release_pro, string("GRIBAPI_RELEASE"), 1); // see comment in grib.cpp //new DLibFunRetNew(lib::grib_get_message_size_fun, string("GRIBAPI_GET_MESSAGE_SIZE"), 1); new DLibFunRetNew(lib::grib_clone_fun, string("GRIBAPI_CLONE"), 1); // GRIB: data related new DLibFunRetNew(lib::grib_get_size_fun, string("GRIBAPI_GET_SIZE"), 2); new DLibPro(lib::grib_get_pro, string("GRIBAPI_GET"), 3); new DLibPro(lib::grib_get_data_pro, string("GRIBAPI_GET_DATA"), 4); // ----------------------------------------------------------------------------------------- new DLibFunRetNew(lib::crossp, string("CROSSP"), 2); //const string hanningKey[] = {"DOUBLE", "ALPHA", KLISTEND }; //new DLibFunRetNew(lib::hanning, string("HANNING"), 2, hanningKey); const string wtnKey[] = {"COLUMN", "DOUBLE", "INVERSE", "OVERWRITE", KLISTEND }; new DLibFun(lib::wtn, string("WTN"), 2, wtnKey); const string zeropolyKey[] = {"DOUBLE", "COMPANION", "JENKINS_TRAUB", KLISTEND }; new DLibFunRetNew(lib::zeropoly, string("IMSL_ZEROPOLY"), 1, zeropolyKey); const string spher_harmKey[] = {"DOUBLE", KLISTEND }; new DLibFunRetNew(lib::spher_harm, string("SPHER_HARM"), 4, spher_harmKey); const string gdl_erfinvKey[] = {"DOUBLE", KLISTEND }; new DLibFunRetNew(lib::gdl_erfinv_fun, string("GDL_ERFINV"), 1, gdl_erfinvKey); // by Mateusz Turcza const string sem_createKey[] = {"DESTROY_SEMAPHORE", KLISTEND }; new DLibFunRetNew(lib::sem_create, string("SEM_CREATE"), 1, sem_createKey); new DLibPro(lib::sem_delete, string("SEM_DELETE"), 1); new DLibFunRetNew(lib::sem_lock, string("SEM_LOCK"), 1); new DLibPro(lib::sem_release, string("SEM_RELEASE"), 1); } gdl-0.9.9/src/libinit_ac.cpp000066400000000000000000000116531340051421000156630ustar00rootroot00000000000000/*************************************************************************** libinit_ac.cpp - initialization of GDL library routines ------------------- begin : 20 April 2007 copyright : (C) 2007 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #if defined(HAVE_LIBGSL) #include #endif #include "math_fun_ac.hpp" #include "gsl_matrix.hpp" #include "gsl_fun.hpp" #include "smooth.hpp" using namespace std; void LibInit_ac() { const char KLISTEND[] = ""; #if defined(HAVE_LIBGSL) // Besel functions family const string beseliKey[]={"DOUBLE","ITER","HELP",KLISTEND}; new DLibFunRetNew(lib::beseli_fun,string("BESELI"),2,beseliKey); const string beseljKey[]={"DOUBLE","ITER","HELP",KLISTEND}; new DLibFunRetNew(lib::beselj_fun,string("BESELJ"),2,beseljKey); const string beselkKey[]={"DOUBLE","ITER","HELP",KLISTEND}; new DLibFunRetNew(lib::beselk_fun,string("BESELK"),2,beselkKey); const string beselyKey[]={"DOUBLE","ITER","HELP",KLISTEND}; new DLibFunRetNew(lib::besely_fun,string("BESELY"),2,beselyKey); // Matrix functions family const string ludcKey[]={"COLUMN","DOUBLE","INTERCHANGES",KLISTEND}; new DLibPro(lib::ludc_pro,string("LUDC"),2,ludcKey); const string lusolKey[]={"COLUMN","DOUBLE",KLISTEND}; new DLibFunRetNew(lib::lusol_fun,string("LUSOL"),3,lusolKey); const string determKey[]={"DOUBLE","CHECK","ZERO",KLISTEND}; new DLibFunRetNew(lib::determ_fun,string("DETERM"),1,determKey); const string trisolKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::trisol_fun,string("TRISOL"),4,trisolKey); // QSIMP/QROMB (we share code for QSIMP and QROMB) const string qsimpKey[]={"DOUBLE","EPS","JMAX",KLISTEND}; const string qsimpWarnKey[]={"K",KLISTEND}; //RSIMP has no 'K' new DLibFunRetNew(lib::qromb_fun,string("QSIMP"),3,qsimpKey,qsimpWarnKey); const string qrombKey[]={"DOUBLE","EPS","JMAX",KLISTEND}; const string qrombWarnKey[]={"K",KLISTEND}; //QROMB code does not make use of 'K' key new DLibFunRetNew(lib::qromb_fun,string("QROMB"),3,qrombKey,qrombWarnKey); //QROMO const string qromoKey[]={"DOUBLE","EPS","JMAX","K","MIDEXP", "MIDINF","MIDPNT","MIDSQL","MIDSQU",KLISTEND}; new DLibFunRetNew(lib::qromo_fun,string("QROMO"),3,qromoKey); const string fz_rootsKey[]={"DOUBLE","EPS","NO_POLISH",KLISTEND}; new DLibFunRetNew(lib::fz_roots_fun,string("FZ_ROOTS"),3,fz_rootsKey); const string fx_rootKey[]={"DOUBLE","ITMAX","STOP","TOL",KLISTEND}; new DLibFunRetNew(lib::fx_root_fun,string("FX_ROOT"),2,fx_rootKey); #endif const string spl1Key[]={"YP0","YPN_1","DOUBLE","HELP",KLISTEND}; new DLibFunRetNew(lib::spl_init_fun,string("SPL_INIT"),2,spl1Key); const string spl2Key[]={"DOUBLE","HELP",KLISTEND}; new DLibFunRetNew(lib::spl_interp_fun,string("SPL_INTERP"),4,spl2Key); const string helpKey[]={"HELP",KLISTEND}; new DLibFunRetNew(lib::roberts_fun,string("ROBERTS"),1,helpKey); new DLibFunRetNew(lib::sobel_fun,string("SOBEL"),1,helpKey); new DLibFunRetNew(lib::prewitt_fun,string("PREWITT"),1,helpKey); /* NOTE: 2018-09-07 by rexso (remi.solaas at edinsights dot no) * * ERODE and DILATE currently implemented in IDL, * available in pro/erode.pro and pro/dilate.pro * with grayscale support. Uncomment when the C++ * implementation is complete. */ const string erodeKey[]={"HELP","GRAY","PRESERVE_TYPE","UINT","ULONG","VALUES",KLISTEND}; new DLibFunRetNew(lib::erode_fun,string("ERODE_INTERNALGDL"),5,erodeKey); const string dilateKey[]={"HELP","GRAY","PRESERVE_TYPE","UINT","ULONG","VALUES", "CONSTRAINED","BACKGROUND",KLISTEND}; new DLibFunRetNew(lib::dilate_fun,string("DILATE_INTERNALGDL"),5,dilateKey); const string matrix_multiplyKey[]={"ATRANSPOSE","BTRANSPOSE",KLISTEND}; new DLibFunRetNew(lib::matrix_multiply,string("MATRIX_MULTIPLY"),2,matrix_multiplyKey); // Levan Loria and Alain Coulais, September 2014 : to be extensively tested // please replace smooth with one of these functions only when thoroughly tested. // const string smoothKey[]={"NAN",KLISTEND}; // new DLibFunRetNew(lib::smooth2_fun,string("SMOOTH2"),2,smoothKey); // new DLibFunRetNew(lib::smooth3_fun,string("SMOOTH3"),2,smoothKey); } gdl-0.9.9/src/libinit_cl.cpp000066400000000000000000000230411340051421000156700ustar00rootroot00000000000000/*************************************************************************** libinit_cl.cpp - initialization of GDL library routines ------------------- begin : March 18 2004 copyright : (C) 2004 by Christopher Lee, : Original by Marc Schellens(2002(C)) email : chrislee0@hotmail.com ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H # include #else # define USE_NETCDF 1 # define USE_MAGICK 1 #endif #include "includefirst.hpp" #include #include #include "envt.hpp" #include "dpro.hpp" #include "gdljournal.hpp" #include "basic_fun_cl.hpp" #ifdef USE_MAGICK # include "magick_cl.hpp" #endif #ifdef USE_NETCDF # include "ncdf_cl.hpp" #endif #ifdef USE_TIFF # include "tiff.hxx" #endif using namespace std; void LibInit_cl() { const char KLISTEND[] = ""; new DLibPro(lib::journal,string("JOURNAL"),1); const string systimeKey[]={"JULIAN","SECONDS","UTC",KLISTEND}; new DLibFunRetNew(lib::systime,string("SYSTIME"),2,systimeKey); const string legendreKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::legendre,string("LEGENDRE"),3,legendreKey); new DLibFunRetNew(lib::gsl_exp, string("GSL_EXP"),1); #ifdef USE_NETCDF //open NetCDF const string ncdf_openKey[]={"WRITE","NOWRITE",KLISTEND}; new DLibFunRetNew(lib::ncdf_open,string("NCDF_OPEN"),1,ncdf_openKey); //create NetCDF const string ncdf_createKey[]={"CLOBBER","NOCLOBBER","NETCDF3_64BIT","NETCDF4_FORMAT",KLISTEND}; new DLibFunRetNew(lib::ncdf_create,string("NCDF_CREATE"),1,ncdf_createKey); //close NetCDF new DLibPro(lib::ncdf_close,string("NCDF_CLOSE"),1); //reading NetCDF #ifdef USE_NETCDF4 // NetCDF 4 extension // Group Inquire new DLibFunRetNew(lib::ncdf_groupsinq,string("NCDF_GROUPSINQ"),1); // Group Name new DLibFunRetNew(lib::ncdf_groupname,string("NCDF_GROUPNAME"),1); // Full Group Name new DLibFunRetNew(lib::ncdf_fullgroupname,string("NCDF_FULLGROUPNAME"),1); // Group Parent new DLibFunRetNew(lib::ncdf_groupparent,string("NCDF_GROUPPARENT"),1); // Group Def new DLibFunRetNew(lib::ncdf_groupdef,string("NCDF_GROUPDEF"),2); // array of dimension IDs const string ncdf_dimidsinqKey[]={"INCLUDE_PARENTS",KLISTEND}; new DLibFunRetNew(lib::ncdf_dimidsinq,string("NCDF_DIMIDSINQ"),1,ncdf_dimidsinqKey); // returns the ID of a group new DLibFunRetNew(lib::ncdf_ncidinq,string("NCDF_NCIDINQ"),2); // returns a group’s variable IDs. new DLibFunRetNew(lib::ncdf_varidsinq,string("NCDF_VARIDSINQ"),1); // returns the identifiers of the unlimited dimensions in a group. const string ncdf_unlimdimsinqKey[]={"COUNT",KLISTEND}; new DLibFunRetNew(lib::ncdf_unlimdimsinq,string("NCDF_UNLIMDIMSINQ"),1,ncdf_unlimdimsinqKey); #endif // USE_NETCDF4 //Inquire new DLibFunRetNew(lib::ncdf_inquire,string("NCDF_INQUIRE"),1); //Variable Inquire new DLibFunRetNew(lib::ncdf_varinq,string("NCDF_VARINQ"),2); //Varget 1 const string ncdf_varget1Key[]={"OFFSET",KLISTEND}; new DLibPro(lib::ncdf_varget1,string("NCDF_VARGET1"),3,ncdf_varget1Key); //Varget const string ncdf_vargetKey[]={"COUNT","OFFSET", "STRIDE",KLISTEND}; new DLibPro(lib::ncdf_varget,string("NCDF_VARGET"),3,ncdf_vargetKey); //Variable ID new DLibFunRetNew(lib::ncdf_varid,string("NCDF_VARID"),2); //Dimension Inquire new DLibPro(lib::ncdf_diminq,string("NCDF_DIMINQ"),4); //Dimension ID new DLibFunRetNew(lib::ncdf_dimid,string("NCDF_DIMID"),2); //Get attribute name const string ncdf_attnameKey[]={"GLOBAL",KLISTEND}; new DLibFunRetNew(lib::ncdf_attname,string("NCDF_ATTNAME"),3,ncdf_attnameKey); //Get attribute const string ncdf_attgetKey[]={"GLOBAL",KLISTEND}; new DLibPro(lib::ncdf_attget,string("NCDF_ATTGET"),4,ncdf_attgetKey); //Inquire attribute (datatype, size?) const string ncdf_attinqKey[]={"GLOBAL",KLISTEND}; new DLibFunRetNew(lib::ncdf_attinq,string("NCDF_ATTINQ"),3,ncdf_attinqKey); //Control functions, define mode etc. const string ncdf_controlKey[]={"ABORT","ENDEF","FILL","NOFILL", "VERBOSE", "NOVERBOSE","OLDFILL","REDEF","SYNC", KLISTEND}; new DLibPro(lib::ncdf_control,string("NCDF_CONTROL"),1,ncdf_controlKey); //writing NetCDF //Put attribute into file const string ncdf_attputKey[]={"GLOBAL","LENGTH","BYTE","CHAR","DOUBLE","FLOAT","LONG","SHORT",KLISTEND}; new DLibPro(lib::ncdf_attput, string("NCDF_ATTPUT"), 4,ncdf_attputKey); //copy attribute between files const string ncdf_attcopyKey[]={"IN_GLOBAL","OUT_GLOBAL",KLISTEND}; new DLibFunRetNew(lib::ncdf_attcopy, string("NCDF_ATTCOPY"), 5,ncdf_attcopyKey); //delete attribute const string ncdf_attdelKey[]={"GLOBAL",KLISTEND}; new DLibPro(lib::ncdf_attdel, string("NCDF_ATTDEL"), 3,ncdf_attdelKey); //rename attribute const string ncdf_attrenameKey[]={"GLOBAL",KLISTEND}; new DLibPro(lib::ncdf_attrename, string("NCDF_ATTRENAME"), 4, ncdf_attrenameKey); //define dimension const string ncdf_dimdefKey[]={"UNLIMITED",KLISTEND}; new DLibFunRetNew(lib::ncdf_dimdef, string("NCDF_DIMDEF"), 3,ncdf_dimdefKey); //rename dimension new DLibPro(lib::ncdf_dimrename, string("NCDF_DIMRENAME"), 3); //define variable const string ncdf_vardefKey[]={"BYTE","CHAR","DOUBLE","FLOAT","LONG","SHORT", KLISTEND}; new DLibFunRetNew(lib::ncdf_vardef, string("NCDF_VARDEF"), 3,ncdf_vardefKey); //rename variable new DLibPro(lib::ncdf_varrename, string("NCDF_VARRENAME"), 3); //put variable const string ncdf_varputKey[]={"COUNT","OFFSET", "STRIDE",KLISTEND}; new DLibPro(lib::ncdf_varput, string("NCDF_VARPUT"), 3,ncdf_varputKey); //epoch time conversion (a draft of the code existed in CVS version before January 2014 // in "ncdf_cl.cpp" but is was wrong !) // const string cdf_epochKey[]={"BREAKDOWN_EPOCH","COMPUTE_EPOCH",KLISTEND}; // new DLibPro(lib::cdf_epoch, string("CDF_EPOCH"),8,cdf_epochKey); #endif #ifdef USE_MAGICK new DLibFunRetNew(lib::magick_open,string("MAGICK_OPEN"),1); new DLibFunRetNew(lib::magick_create,string("MAGICK_CREATE"),3); new DLibPro(lib::magick_close,string("MAGICK_CLOSE"),1); const string magick_readKey[]={"RGB","SUB_RECT","MAP",KLISTEND}; new DLibFunRetNew(lib::magick_read,string("MAGICK_READ"),1,magick_readKey); new DLibFunRetNew(lib::magick_readindexes,string("MAGICK_READINDEXES"),1); new DLibPro(lib::magick_readcolormapRGB,string("MAGICK_READCOLORMAPRGB"),4); const string magick_writeKey[]={"RGB",KLISTEND}; new DLibPro(lib::magick_write,string("MAGICK_WRITE"),2,magick_writeKey); new DLibPro(lib::magick_writefile,string("MAGICK_WRITEFILE"),3); //attributes new DLibFunRetNew(lib::magick_IndexedColor,string("MAGICK_INDEXEDCOLOR"),1); new DLibFunRetNew(lib::magick_rows,string("MAGICK_ROWS"),1); new DLibFunRetNew(lib::magick_columns,string("MAGICK_COLUMNS"),1); new DLibFunRetNew(lib::magick_colormapsize,string("MAGICK_COLORMAPSIZE"),2); new DLibFunRetNew(lib::magick_magick,string("MAGICK_MAGICK"),2); new DLibPro(lib::magick_quality,string("MAGICK_QUALITY"),2); const string magick_quantizeKey[]={"TRUECOLOR","YUV","GRAYSCALE","DITHER",KLISTEND}; new DLibPro(lib::magick_quantize,string("MAGICK_QUANTIZE"),2,magick_quantizeKey); new DLibPro(lib::magick_writeIndexes, string("MAGICK_WRITEINDEXES"),2); new DLibPro(lib::magick_writeColorTable, string("MAGICK_WRITECOLORTABLE"),4); //manipulation new DLibPro(lib::magick_flip,string("MAGICK_FLIP"),1); new DLibPro(lib::magick_matte,string("MAGICK_MATTE"),1); new DLibPro(lib::magick_mattecolor,string("MAGICK_MATTECOLOR"),2); const string magick_interlaceKey[]={"NOINTERLACE","LINEINTERLACE","PLANEINTERLACE",KLISTEND}; new DLibPro(lib::magick_interlace,string("MAGICK_INTERLACE"),1,magick_interlaceKey); const string magick_addnoiseKey[]={"UNIFORMNOISE","GAUSSIANNOISE","MULTIPLICATIVEGAUSSIANNOISE","IMPULSENOISE","LAPLACIANNOISE","POISSONNOISE","NOISE",KLISTEND}; new DLibPro(lib::magick_addNoise,string("MAGICK_ADDNOISE"),1,magick_addnoiseKey); //hmm new DLibPro(lib::magick_display,string("MAGICK_DISPLAY"),1); // SA: support fot query/ping routines const string magick_pingKey[] = {"INFO", "CHANNELS", "DIMENSIONS", "HAS_PALETTE", "IMAGE_INDEX", "NUM_IMAGES", "PIXEL_TYPE",/* "SUPPORTED_READ", "SUPPORTED_WRITE", */"TYPE",KLISTEND}; new DLibFunRetNew(lib::magick_ping, string("MAGICK_PING"), 2, magick_pingKey); // see bug no. 3376577 // Magick::InitializeMagick(NULL); #endif #ifdef USE_TIFF const string tiff_queryKey[] = {"INFO", "GEOTIFF", "IMAGE_INDEX", KLISTEND}; new DLibFunRetNew(lib::tiff_query, string("TIFF_QUERY"), 1, tiff_queryKey); const string tiff_readKey[] = {"RED", "GREEN", "BLUE", "CHANNELS", "DOT_RANGE", "GEOTIFF", "ICC_PROFILE", "IMAGE_INDEX", "INTERLEAVE", "ORIENTATION", "PHOTOSHOP", "PLANARCONFIG", "SUB_RECT", "VERBOSE", KLISTEND}; new DLibFunRetNew(lib::tiff_read, string("TIFF_READ"), 1, tiff_readKey); #endif // USE_TIFF } gdl-0.9.9/src/libinit_exists.cpp000066400000000000000000000055651340051421000166240ustar00rootroot00000000000000/*************************************************************************** libinit_exists.cpp - initialization of GDL library routines ------------------- begin : 25 December 2017 copyright : (C) 2017 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 #define USE_MAGICK 1 #endif #include "includefirst.hpp" #include #include #include "envt.hpp" #include "dpro.hpp" /* #include "gdljournal.hpp" #include "basic_fun_cl.hpp" #ifdef USE_MAGICK #include "magick_cl.hpp" #endif #ifdef USE_NETCDF #include "ncdf_cl.hpp" #endif */ #include "exists_fun.hpp" #include "dialog.hpp" using namespace std; void LibInit_exists() { new DLibFunRetNew(lib::eigen_exists,string("EIGEN_EXISTS")); new DLibFunRetNew(lib::fftw_exists,string("FFTW_EXISTS")); new DLibFunRetNew(lib::glpk_exists,string("GLPK_EXISTS")); new DLibFunRetNew(lib::grib_exists,string("GRIB_EXISTS")); new DLibFunRetNew(lib::gshhg_exists,string("GSHHG_EXISTS")); new DLibFunRetNew(lib::hdf5_exists,string("HDF5_EXISTS")); new DLibFunRetNew(lib::hdf_exists,string("HDF_EXISTS")); new DLibFunRetNew(lib::magick_exists,string("MAGICK_EXISTS")); new DLibFunRetNew(lib::ncdf_exists,string("NCDF_EXISTS")); new DLibFunRetNew(lib::ncdf4_exists,string("NCDF4_EXISTS")); new DLibFunRetNew(lib::openmp_exists,string("OPENMP_EXISTS")); new DLibFunRetNew(lib::pnglib_exists,string("PNGLIB_EXISTS")); new DLibFunRetNew(lib::proj4_exists,string("PROJ4_EXISTS")); new DLibFunRetNew(lib::proj4new_exists,string("PROJ4NEW_EXISTS")); new DLibFunRetNew(lib::pslib_exists,string("PSLIB_EXISTS")); new DLibFunRetNew(lib::python_exists,string("PYTHON_EXISTS")); new DLibFunRetNew(lib::tiff_exists,string("TIFF_EXISTS")); new DLibFunRetNew(lib::geotiff_exists,string("GEOTIFF_EXISTS")); new DLibFunRetNew(lib::udunits_exists,string("UDUNITS_EXISTS")); new DLibFunRetNew(lib::wxwidgets_exists, string("WXWIDGETS_EXISTS")); new DLibFunRetNew(lib::x11_exists, string("X11_EXISTS")); new DLibFunRetNew(lib::dsfmt_exists, string("DSFMT_EXISTS")); } gdl-0.9.9/src/libinit_gm.cpp000066400000000000000000000053151340051421000157010ustar00rootroot00000000000000/*************************************************************************** math_fun_gm.cpp - math GDL library function (GM) ------------------- begin : 03 May 2007 copyright : (C) 2007 by Gregory Marchal email : gregory.marchal_at_obspm.fr website : http://format.obspm.fr/~m1/gmarchal/ ****************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #if defined(HAVE_LIBGSL) #include #include #endif #include "math_fun_gm.hpp" using namespace std; void LibInit_gm() { const char KLISTEND[] = ""; #if defined(HAVE_LIBGSL) const string erfKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::erf_fun,string("ERF"),1,erfKey); const string errorfKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::errorf_fun,string("ERRORF"),1,errorfKey); const string erfcKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::erfc_fun,string("ERFC"),1,erfcKey); const string gammaKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::gamma_fun,string("GAMMA"),1,gammaKey); // undocumented function ... new DLibFunRetNew(lib::gamma_fun,string("NR_GAMMA"),1,gammaKey); const string lngammaKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::lngamma_fun,string("LNGAMMA"),1,lngammaKey); // const string igammaKey[]={"DOUBLE","EPS","ITER","ITMAX","METHOD",KLISTEND}; const string igammaKey[]={"DOUBLE","METHOD",KLISTEND}; const string igammaWarnKey[]={"EPS","ITER","ITMAX",KLISTEND}; new DLibFunRetNew(lib::igamma_fun,string("IGAMMA"),2,igammaKey,igammaWarnKey); // undocumented function ... new DLibFunRetNew(lib::igamma_fun,string("IDL_IGAMMA"),2,igammaKey); const string betaKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::beta_fun,string("BETA"),2,betaKey); const string expintKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::expint_fun,string("EXPINT"),2,expintKey); const string gaussintKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::gaussint_fun,string("GAUSSINT"),2,gaussintKey); #endif } gdl-0.9.9/src/libinit_jmg.cpp000066400000000000000000000604441340051421000160570ustar00rootroot00000000000000/*************************************************************************** libinit_jmg.cpp - initialization of GDL library routines ------------------- begin : 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // the following is already done in "includefirst.hpp" // #ifdef HAVE_CONFIG_H // #include // #else // // default: assume we have HDF // #define USE_HDF 1 // #define USE_FFTW 1 // #endif #include "includefirst.hpp" #include #include #include "envt.hpp" #include "basic_fun_jmg.hpp" #include "math_fun_jmg.hpp" #include "basic_pro_jmg.hpp" #include "gsl_fun.hpp" #include "image.hpp" #include "plotting.hpp" #include "widget.hpp" #if defined(USE_HDF) #include "hdf_fun.hpp" #include "hdf_pro.hpp" #endif #if defined(USE_FFTW) #include "fftw.hpp" #endif #if defined(USE_EIGEN) #include "matrix_cholesky.hpp" #include "least_squares.hpp" #endif #include "matrix_invert.hpp" #if defined(USE_LIBPROJ4)||defined(USE_LIBPROJ4_NEW) #include "gshhs.hpp" #endif #include "triangulation.hpp" using namespace std; void LibInit_jmg() { const char KLISTEND[] = ""; // the following by Joel Gales const string sizeKey[]={"L64","DIMENSIONS","FILE_LUN","FILE_OFFSET", "N_DIMENSIONS","N_ELEMENTS", "SNAME","STRUCTURE","TNAME","TYPE",KLISTEND}; new DLibFunRetNew(lib::size_fun,string("SIZE"),1,sizeKey); new DLibFunRetNew(lib::fstat_fun,string("FSTAT"),1); const string routine_namesKey[]={"LEVEL","VARIABLES","FETCH","ARG_NAME", "STORE","S_FUNCTIONS","S_PROCEDURES", KLISTEND}; new DLibFun(lib::routine_names_value,string("ROUTINE_NAMES"),-1,routine_namesKey); // the 2 following by Alain C. and Levan L., Summer 2014 const string isaKey[]={"ARRAY","FILE","NULL","NUMBER","SCALAR","BOOLEAN", "COMPLEX","FLOAT","INTEGER","STRING",KLISTEND}; new DLibFunRetNew(lib::isa_fun,string("ISA"),2,isaKey); new DLibFunRetNew(lib::typename_fun,string("TYPENAME"),1); // the following (Chol and Invert) by Alain C. and Nodar K., Summer 2013 // Since we have a difference between the IDL way and the Eigen way // we (temporary) remove these 2 codes in the CVS of GDL // Help welcome. #if defined(USE_EIGEN) const string cholKey[]={"DOUBLE",KLISTEND}; new DLibPro(lib::choldc_pro,string("CHOLDC"),2,cholKey); new DLibFunRetNew(lib::cholsol_fun,string("CHOLSOL"),3,cholKey); // const string lacholdcKey[]={"DOUBLE","STATUS","UPPER",KLISTEND}; new DLibPro(lib::la_choldc_pro,string("LA_CHOLDC"),1,lacholdcKey); const string lacholsolKey[]={"DOUBLE","STATUS",KLISTEND}; new DLibFunRetNew(lib::la_cholsol_fun,string("LA_CHOLSOL"),2,lacholsolKey); // Ilia N. & Alain C., Summer 2015 const string laleastsquaresKey[]={"DOUBLE","METHOD","RANK","RCONDITION","RESIDUAL","STATUS",KLISTEND}; new DLibFunRetNew(lib::la_least_squares_fun,string("LA_LEAST_SQUARES"),2,laleastsquaresKey); #endif #if defined(HAVE_LIBGSL) && defined(HAVE_LIBGSLCBLAS) const string invertKey[]={"DOUBLE","GSL","EIGEN",KLISTEND}; new DLibFunRetNew(lib::AC_invert_fun,string("INVERT"),2,invertKey); // if FFTw not available, FFT in the GSL used (slower) const string fftKey[]={"DOUBLE","INVERSE","OVERWRITE","DIMENSION","CENTER",KLISTEND}; #if defined(USE_FFTW) new DLibFun(lib::fftw_fun,string("FFT"),2,fftKey); #else new DLibFun(lib::fft_fun,string("FFT"),2,fftKey); #endif const string randomKey[]={"DOUBLE","GAMMA","LONG","NORMAL", "BINOMIAL","POISSON","UNIFORM","ULONG","RAN1",KLISTEND}; //note WARNING: RAN1 has a special meaning for GDL, see code. new DLibFunRetNew(lib::random_fun,string("RANDOMU"),MAXRANK+1,randomKey); new DLibFunRetNew(lib::random_fun,string("RANDOMN"),MAXRANK+1,randomKey); const string checkmathKey[]={"MASK","NOCLEAR","PRINT",KLISTEND}; new DLibFunRetNew(lib::check_math_fun,string("CHECK_MATH"),2,checkmathKey); const string histogramKey[]={"BINSIZE","INPUT","MAX","MIN","NBINS", "OMAX","OMIN","REVERSE_INDICES", "LOCATIONS","NAN",KLISTEND}; const string histogramWarnKey[]={"L64",KLISTEND}; new DLibFunRetNew(lib::histogram_fun,string("HISTOGRAM"),1,histogramKey,histogramWarnKey); const string interpolateKey[]={"CUBIC","DOUBLE","GRID","MISSING","NEAREST_NEIGHBOUR",KLISTEND}; new DLibFunRetNew(lib::interpolate_fun,string("INTERPOLATE"),4,interpolateKey); const string la_triredKey[]={"DOUBLE","UPPER",KLISTEND}; new DLibPro(lib::la_trired_pro,string("LA_TRIRED"),3,la_triredKey); #endif const string macharKey[]={"DOUBLE",KLISTEND}; new DLibFunRetNew(lib::machar_fun,string("MACHAR"),0,macharKey); #if defined(USE_LIBPROJ4)||defined(USE_LIBPROJ4_NEW) const string map_proj_forwardKey[]={"MAP_STRUCTURE","RADIANS","POLYGONS","POLYLINES","CONNECTIVITY","FILL",KLISTEND}; //WARNING FIXED ORDER for GetMapAsMapStructureKeyword() new DLibFunRetNew(lib::map_proj_forward_fun, string("MAP_PROJ_FORWARD"),2,map_proj_forwardKey,NULL); const string map_proj_inverseKey[]={"MAP_STRUCTURE","RADIANS",KLISTEND}; //WARNING FIXED ORDER for GetMapAsMapStructureKeyword() new DLibFunRetNew(lib::map_proj_inverse_fun, string("MAP_PROJ_INVERSE"),2,map_proj_inverseKey); //dummy functions for compatibility support of GCTP projections new DLibPro(lib::map_proj_gctp_forinit,string("MAP_PROJ_GCTP_FORINIT"),4); new DLibPro(lib::map_proj_gctp_revinit,string("MAP_PROJ_GCTP_REVINIT"),4); // SA: GSHHS dataset // TODO: USA, ORIENTATION, LIMIT, MLINESTYLE, MLINETHICK, SPACING, T3D, ZVALUE const string map_continentsKey[] = { "MAP_STRUCTURE", "COLOR", "RIVERS", "COUNTRIES", "COASTS", "CONTINENTS", "USA", "HIRES", "FILL_CONTINENTS",KLISTEND};//WARNING FIXED ORDER for GetMapAsMapStructureKeyword() const string map_continentsWarnKey[] = {"ORIENTATION", "LIMIT", "MLINESTYLE", "MLINETHICK", "SPACING", "T3D", "ZVALUE", KLISTEND}; new DLibPro(lib::map_continents, string("MAP_CONTINENTS"), 0, map_continentsKey, map_continentsWarnKey); #endif const string convert_coordKey[]={"DATA","DEVICE","NORMAL","T3D","DOUBLE", "TO_DATA","TO_DEVICE","TO_NORMAL",KLISTEND}; new DLibFunRetNew(lib::convert_coord,string("CONVERT_COORD"),3,convert_coordKey); const string finiteKey[]={"INFINITY","NAN","SIGN",KLISTEND}; new DLibFunRetNew(lib::finite_fun,string("FINITE"),1,finiteKey); const string radonKey[]={"BACKPROJECT","DOUBLE","DRHO","DX","DY", "GRAY","LINEAR","NRHO","NTHETA","NX","NY", "RHO","RMIN","THETA","XMIN","YMIN",KLISTEND}; new DLibFunRetNew(lib::radon_fun,string("RADON"),1,radonKey); const string grid_inputKey[]={"SPHERE", "POLAR", "DEGREES", "DUPLICATES", "EPSILON", "EXCLUDE", KLISTEND}; new DLibPro(lib::grid_input,string("GRID_INPUT"),6,grid_inputKey); const string triangulateKey[]={"CONNECTIVITY", "SPHERE", "DEGREES", "FVALUE",KLISTEND}; const string triangulateWarnKey[]={"REPEATS", "TOLERANCE",KLISTEND}; new DLibPro(lib::GDL_Triangulate,string("TRIANGULATE"),4,triangulateKey,triangulateWarnKey); //to be written and do not forget to uncomment QHULL in CMakeLists and config.h.cmake #ifdef HAVE_QHULL const string qhullKey[]={"BOUNDS", "CONNECTIVITY", "DELAUNAY", "SPHERE", "VDIAGRAM" ,"VNORMALS", "VVERTICES", KLISTEND}; new DLibPro(lib::qhull,string("QHULL"),8,qhullKey); const string qgrid3Key[]={"DELTA", "DIMENSION", "MISSING", "START", KLISTEND}; new DLibFunRetNew(lib::qgrid3_fun,string("QGRID3"),5,qgrid3Key); #endif const string trigridKey[]={"DEGREES","NX","NY","SPHERE","XGRID","XOUT","YGRID","YOUT","MAX_VALUE","MIN_VALUE","MISSING","INPUT",KLISTEND}; const string trigridWarnKey[]={"EXTRAPOLATE","QUINTIC",KLISTEND}; new DLibFunRetNew(lib::trigrid_fun,string("TRIGRID"),6,trigridKey,trigridWarnKey); const string poly_2dKey[]={"CUBIC","MISSING",KLISTEND}; new DLibFunRetNew(lib::poly_2d_fun,string("POLY_2D"),6,poly_2dKey); const string make_arrayKey[]={"DIMENSION", "INCREMENT", "INDEX", "NOZERO", "SIZE", "START", "TYPE", "VALUE", "BOOLEAN", "BYTE", "COMPLEX", "DCOMPLEX", "DOUBLE", "FLOAT", "INTEGER", "L64", "LONG", "OBJ", "PTR", "STRING", "UINT", "UL64", "ULONG", KLISTEND}; new DLibFunRetNew(lib::make_array,string("MAKE_ARRAY"),MAXRANK,make_arrayKey); const string reformKey[]={"OVERWRITE",KLISTEND}; new DLibFun(lib::reform,string("REFORM"),MAXRANK+1,reformKey); new DLibPro(lib::point_lun,string("POINT_LUN"),2); new DLibPro(lib::linkimage,string("LINKIMAGE"),4); new DLibPro(lib::wait_pro,string("WAIT"),1); #if defined(USE_HDF) new DLibFunRetNew(lib::hdf_ishdf,string("HDF_ISHDF"),1); const string hdf_openKey[]={"READ","RDWR","CREATE","ALL","NUM_DD","WRITE",KLISTEND}; new DLibFunRetNew(lib::hdf_open_fun,string("HDF_OPEN"),2,hdf_openKey); new DLibFunRetNew(lib::hdf_vg_getid_fun,string("HDF_VG_GETID"),2); const string hdf_vg_attachKey[]={"READ","WRITE",KLISTEND}; new DLibFunRetNew(lib::hdf_vg_attach_fun,string("HDF_VG_ATTACH"),2, hdf_vg_attachKey); const string hdf_vd_attachKey[]={"READ","WRITE",KLISTEND}; new DLibFunRetNew(lib::hdf_vd_attach_fun,string("HDF_VD_ATTACH"),2, hdf_vd_attachKey); new DLibFunRetNew(lib::hdf_vd_find_fun,string("HDF_VD_FIND"),2); const string hdf_vd_readKey[]={"FIELDS","NRECORDS","FULL_INTERLACE", "NO_INTERLACE",KLISTEND}; new DLibFunRetNew(lib::hdf_vd_read_fun,string("HDF_VD_READ"),2,hdf_vd_readKey); const string hdf_vg_getinfoKey[]={"CLASS","NAME","NENTRIES","REF","TAG", KLISTEND}; new DLibPro(lib::hdf_vg_getinfo_pro,string("HDF_VG_GETINFO"),1, hdf_vg_getinfoKey); const string hdf_vd_getKey[]={"CLASS","NAME","COUNT","REF","TAG",KLISTEND}; new DLibPro(lib::hdf_vd_get_pro,string("HDF_VD_GET"),1, hdf_vd_getKey); new DLibPro(lib::hdf_vg_gettrs_pro,string("HDF_VG_GETTRS"),3); new DLibPro(lib::hdf_vg_detach_pro,string("HDF_VG_DETACH"),1); new DLibPro(lib::hdf_vd_detach_pro,string("HDF_VD_DETACH"),1); const string hdf_sd_createKey[]={"BYTE","DFNT_INT8","DFNT_UINT8", "SHORT","INT","DFNT_INT16","DFNT_UINT16", "LONG","DFNT_INT32","DFNT_UINT32", "FLOAT","DFNT_FLOAT32", "DOUBLE","DFNT_FLOAT64", "STRING","DFNT_CHAR","HDF_TYPE",KLISTEND}; new DLibFunRetNew(lib::hdf_sd_create_fun,string("HDF_SD_CREATE"),3, hdf_sd_createKey); const string hdf_sd_startKey[]={"READ","RDWR","CREATE",KLISTEND}; new DLibFunRetNew(lib::hdf_sd_start_fun,string("HDF_SD_START"),2,hdf_sd_startKey); new DLibFunRetNew(lib::hdf_sd_nametoindex_fun,string("HDF_SD_NAMETOINDEX"),2); new DLibFunRetNew(lib::hdf_sd_attrfind_fun,string("HDF_SD_ATTRFIND"),2); new DLibFunRetNew(lib::hdf_sd_select_fun,string("HDF_SD_SELECT"),2); const string hdf_sd_getdataKey[]={"START","STRIDE","COUNT",KLISTEND}; new DLibPro(lib::hdf_sd_getdata_pro,string("HDF_SD_GETDATA"),2, hdf_sd_getdataKey); const string hdf_sd_adddataKey[]={"START","STRIDE","COUNT",KLISTEND}; new DLibPro(lib::hdf_sd_adddata_pro,string("HDF_SD_ADDDATA"),2, hdf_sd_adddataKey); new DLibPro(lib::hdf_sd_fileinfo_pro,string("HDF_SD_FILEINFO"),3); const string hdf_sd_getinfoKey[]={"DIMS","HDF_TYPE","NAME", "NATTS","NDIMS","TYPE", "LABEL","UNIT","FORMAT","COORDSYS", KLISTEND}; new DLibPro(lib::hdf_sd_getinfo_pro,string("HDF_SD_GETINFO"),1, hdf_sd_getinfoKey); const string hdf_sd_attrinfoKey[]={"COUNT","DATA","HDF_TYPE","NAME", "TYPE",KLISTEND}; new DLibPro(lib::hdf_sd_attrinfo_pro,string("HDF_SD_ATTRINFO"),2, hdf_sd_attrinfoKey); new DLibPro(lib::hdf_sd_endaccess_pro,string("HDF_SD_ENDACCESS"),1); new DLibPro(lib::hdf_sd_end_pro,string("HDF_SD_END"),1); new DLibPro(lib::hdf_close_pro,string("HDF_CLOSE"),1); new DLibFunRetNew(lib::hdf_sd_dimgetid_fun, string("HDF_SD_DIMGETID"), 2); const string hdf_sd_dimgetKey[] = { "NAME", "NATTR", "SCALE", "COUNT", KLISTEND }; const string hdf_sd_dimgetWarnKey[] = { "COMPATIBILITY", "FORMAT", "LABEL", "TYPE", "UNIT", KLISTEND }; new DLibPro(lib::hdf_sd_dimget_pro, string("HDF_SD_DIMGET"), 1, hdf_sd_dimgetKey, hdf_sd_dimgetWarnKey); #endif const string tvKey[]={"TRUE","NORMAL","CHANNEL","XSIZE","YSIZE","ORDER","DEVICE","DATA","T3D","Z","CENTIMETERS","INCHES",KLISTEND}; const string tvWarnKey[]={"WORDS",KLISTEND}; new DLibPro(lib::tv_image,string("TV"),4,tvKey,tvWarnKey); const string tvrdKey[]={"CHANNEL","ORDER","TRUE","WORDS",KLISTEND}; new DLibFunRetNew(lib::tvrd,string("TVRD"),5,tvrdKey); const string loadctKey[]={"GET_NAMES","BOTTOM","NCOLORS","RGB_TABLE","SILENT",KLISTEND}; const string loadctWarnKey[]={"FILE",KLISTEND}; new DLibPro(lib::loadct,string("LOADCT_INTERNALGDL"),1,loadctKey,loadctWarnKey); // call_external (by Christoph Fuchs) const string call_externalKey[] = {"VALUE", "ALL_VALUE", "RETURN_TYPE", "B_VALUE", "I_VALUE", "L_VALUE", "F_VALUE", "D_VALUE", "UI_VALUE", "UL_VALUE", "L64_VALUE", "UL64_VALUE", "S_VALUE", "UNLOAD", "ALL_GDL", "STRUCT_ALIGN_BYTES", KLISTEND }; new DLibFunRetNew(lib::call_external, string("CALL_EXTERNAL"), -1, call_externalKey); // WIDGET_ functions new DLibPro(lib::widget_displaycontextmenu,string("WIDGET_DISPLAYCONTEXTMENU"),4); #define WIDGET_COMMON_KEYWORDS "EVENT_FUNC", "EVENT_PRO", "FUNC_GET_VALUE", "KILL_NOTIFY" \ , "NOTIFY_REALIZE" , "PRO_SET_VALUE" , "NO_COPY" , "GROUP_LEADER"\ , "SCR_XSIZE" , "SCR_YSIZE" , "SCROLL" , "SENSITIVE" \ , "UNAME" , "UNITS" , "UVALUE" , "XOFFSET" \ , "XSIZE" , "YOFFSET" , "YSIZE" , "FRAME" \ , "ALIGN_LEFT", "ALIGN_RIGHT", "ALIGN_CENTER", "ALIGN_BOTTOM", "ALIGN_TOP", "FONT","RESOURCE_NAME" //ACTIVEX //BASE const string widget_baseKey[] = {WIDGET_COMMON_KEYWORDS,"MBAR","APP_MBAR","MODAL","COLUMN","ROW", "EXCLUSIVE","NONEXCLUSIVE","FLOATING","MAP","TITLE","XPAD","X_SCROLL_SIZE","YPAD","Y_SCROLL_SIZE","DISPLAY_NAME", "RNAME_MBAR","TAB_MODE","CONTEXT_EVENTS","KBRD_FOCUS_EVENTS","TLB_ICONIFY_EVENTS","TLB_KILL_REQUEST_EVENTS", "TLB_MOVE_EVENTS","TLB_SIZE_EVENTS","TRACKING_EVENTS","GRID_LAYOUT", "BASE_ALIGN_CENTER","BASE_ALIGN_LEFT","BASE_ALIGN_RIGHT","BASE_ALIGN_BOTTOM","BASE_ALIGN_TOP","SPACE","CONTEXT_MENU",KLISTEND}; const string widget_baseWarnKey[] = {"TLB_FRAME_ATTR", "TOOLBAR", "BITMAP", KLISTEND}; new DLibFunRetNew(lib::widget_base,string("WIDGET_BASE"),1,widget_baseKey,widget_baseWarnKey); //BUTTON const string widget_buttonKey[] = {WIDGET_COMMON_KEYWORDS,"MENU","VALUE","HELP","SEPARATOR","INPUT_FOCUS","BITMAP","TOOLTIP", "TRACKING_EVENTS","DYNAMIC_RESIZE","X_BITMAP_EXTRA",KLISTEND}; const string widget_buttonWarnKey[] ={"ACCELERATOR","CHECKED_MENU", "TAB_MODE","NO_RELEASE",KLISTEND}; new DLibFunRetNew(lib::widget_button,string("WIDGET_BUTTON"),1,widget_buttonKey,widget_buttonWarnKey); //COMBOBOX const string widget_comboboxKey[] = {WIDGET_COMMON_KEYWORDS,"EDITABLE","TITLE","VALUE","TRACKING_EVENTS","DYNAMIC_RESIZE",KLISTEND}; // const string widget_comboboxWarnKey[] = {"TAB_MODE",KLISTEND}; new DLibFunRetNew(lib::widget_combobox,string("WIDGET_COMBOBOX"),1,widget_comboboxKey);//,widget_comboboxWarnKey); //CONTROL const string widget_ControlKey[] = {"REALIZE","MANAGED","EVENT_FUNC","EVENT_PRO", "XMANAGER_ACTIVE_COMMAND","DESTROY", "GET_UVALUE","SET_UVALUE","SET_VALUE", "MAP","FUNC_GET_VALUE","PRO_SET_VALUE", "SET_UNAME","NO_COPY","SET_BUTTON", "SET_DROPLIST_SELECT","SET_LIST_SELECT","SET_COMBOBOX_SELECT", "SENSITIVE","XOFFSET","YOFFSET", "GET_VALUE","NO_NEWLINE","TLB_GET_SIZE", "HOURGLASS","TLB_SET_TITLE","INPUT_FOCUS", "CLEAR_EVENTS","TLB_SET_XOFFSET","TLB_SET_YOFFSET","TLB_GET_OFFSET", "DRAW_BUTTON_EVENTS","DRAW_EXPOSE_EVENTS","DRAW_KEYBOARD_EVENTS", "DRAW_MOTION_EVENTS","DRAW_WHEEL_EVENTS","TRACKING_EVENTS","DRAW_VIEWPORT_EVENTS", "SET_DROP_EVENTS","KILL_NOTIFY","SHOW","APPEND","USE_TEXT_SELECT","SET_TEXT_SELECT", "XSIZE","YSIZE","SCR_XSIZE","SCR_YSIZE","DRAW_XSIZE","DRAW_YSIZE","FRAME","SCROLL", "BITMAP","TIMER","NOTIFY_REALIZE","ALL_TABLE_EVENTS","ALL_TEXT_EVENTS", "TLB_KILL_REQUEST_EVENTS","TLB_MOVE_EVENTS","TLB_SIZE_EVENTS","TLB_ICONIFY_EVENTS", "CONTEXT_EVENTS","KBRD_FOCUS_EVENTS","ALIGNMENT", "BACKGROUND_COLOR","FOREGROUND_COLOR","ROW_LABELS","COLUMN_LABELS", "COLUMN_WIDTHS","ROW_HEIGHTS","TABLE_DISJOINT_SELECTION","USE_TABLE_SELECT", "INSERT_COLUMNS","INSERT_ROWS","DELETE_COLUMNS","DELETE_ROWS", "AM_PM", "DAYS_OF_WEEK", "MONTHS", "SET_TABLE_SELECT","SET_TABLE_VIEW", "UPDATE","FORMAT","EDIT_CELL", "TABLE_XSIZE","TABLE_YSIZE","SEND_EVENT","BAD_ID", "GROUP_LEADER", "COMBOBOX_ADDITEM" ,"COMBOBOX_DELETEITEM" ,"COMBOBOX_INDEX", "GET_DRAW_VIEW","SET_TAB_CURRENT", "UNITS","DYNAMIC_RESIZE","SET_SLIDER_MIN","SET_SLIDER_MAX", "X_BITMAP_EXTRA",KLISTEND}; const string widget_WarnControlKey[] ={"SET_TREE_SELECT","SET_TREE_EXPANDED","SET_TREE_INDEX", "SET_TREE_BITMAP","DELAY_DESTROY", "DEFAULT_FONT", "PUSHBUTTON_EVENTS","TABLE_BLANK","TAB_MODE","SET_TAB_MULTILINE",KLISTEND}; //LIST NOT CLOSE!!! //IMPORTANT : new DLibPro(lib::widget_control,string("WIDGET_CONTROL"),1, widget_ControlKey,widget_WarnControlKey); //DISPLAYCONTEXTMENU //DRAW const string widget_drawKey[] = { WIDGET_COMMON_KEYWORDS, "X_SCROLL_SIZE", "Y_SCROLL_SIZE" , "MOTION_EVENTS" , "BUTTON_EVENTS" , "DROP_EVENTS" , "EXPOSE_EVENTS" , "KEYBOARD_EVENTS" , "TRACKING_EVENTS" , "WHEEL_EVENTS" , "VIEWPORT_EVENTS" , "INPUT_FOCUS" , "APP_SCROLL" , "TOOLTIP" , "RETAIN" //not taken into account, but not useful, too. , KLISTEND}; const string widget_drawWarnKey[] = { "CLASSNAME" , "COLOR_MODEL" , "COLORS" // , "DRAG_NOTIFY" //should be implemented , "GRAPHICS_LEVEL" , "IGNORE_ACCELERATORS" , "RENDERER" ,KLISTEND}; new DLibFunRetNew(lib::widget_draw,string("WIDGET_DRAW"),1,widget_drawKey,widget_drawWarnKey); //DROPLIST const string widget_droplistKey[] = {WIDGET_COMMON_KEYWORDS,"TITLE","VALUE","TRACKING_EVENTS","DYNAMIC_RESIZE",KLISTEND}; // const string widget_droplistWarnKey[] = {"TAB_MODE",KLISTEND}; new DLibFunRetNew(lib::widget_droplist,string("WIDGET_DROPLIST"),1,widget_droplistKey);//,widget_droplistWarnKey); //EVENT const string widget_eventKey[] = {"XMANAGER_BLOCK","DESTROY","SAVE_HOURGLASS","NOWAIT","BAD_ID",KLISTEND}; new DLibFunRetNew(lib::widget_event,string("WIDGET_EVENT"),1,widget_eventKey); //complete!! //INFO const string widget_infoKey[] = { "DEBUG","ACTIVE","VALID_ID","MODAL","MANAGED", "XMANAGER_BLOCK", //only GDL, used in xmanager.pro , may even not be useful now. "CHILD","VERSION","GEOMETRY","UNAME", "FONTNAME",//not really supported - returns "". "BUTTON_SET","PARENT","TEXT_SELECT","FIND_BY_UNAME","TYPE","NAME", "TABLE_DISJOINT_SELECTION","TABLE_SELECT","COLUMN_WIDTHS","ROW_HEIGHTS","USE_TABLE_SELECT","SYSTEM_COLORS", "TREE_ROOT","TREE_SELECT","TREE_EXPANDED","TREE_FOLDER","TREE_INDEX","TREE_BITMAP","DROP_EVENTS","DRAGGABLE","DRAG_NOTIFY","MASK", "LIST_SELECT","DROPLIST_SELECT","COMBOBOX_GETTEXT", "TAB_NUMBER","TAB_MULTILINE","TAB_CURRENT","UPDATE", "TLB_KILL_REQUEST_EVENTS","TLB_MOVE_EVENTS","TLB_SIZE_EVENTS","TLB_ICONIFY_EVENTS", "EVENT_FUNC","EVENT_PRO","N_CHILDREN","ALL_CHILDREN","REALIZED", "UNITS",KLISTEND}; const string widget_infoWarnKey[]={ // "COLUMN_WIDTHS", // "COMBOBOX_NUMBER","COMPONENT","CONTEXT_EVENTS", // "DRAW_BUTTON_EVENTS","DRAW_EXPOSE_EVENTS","DRAW_KEYBOARD_EVENTS","DRAW_MOTION_EVENTS", // "DRAW_VIEWPORT_EVENTS","DRAW_WHEEL_EVENTS","DROPLIST_NUMBER","DROPLIST_SELECT", // "DYNAMIC_RESIZE","EVENT_FUNC","EVENT_PRO","FIND_BY_UNAME","KBRD_FOCUS_EVENTS", // "LIST_MULTIPLE","LIST_NUMBER","LIST_NUM_VISIBLE","LIST_TOP","MAP",, // "MULTIPLE_PROPERTIES",,"PROPERTYSHEET_NSELECTED","PROPERTYSHEET_SELECTED", // "PROPERTY_VALID","PROPERTY_VALUE","PUSHBUTTON_EVENTS","ROW_HEIGHTS","SENSITIVE","SIBLING", // "SLIDER_MIN_MAX","STRING_SIZE","TABLE_ALL_EVENTS","TABLE_BACKGROUND_COLOR", // "TABLE_EDITABLE","TABLE_EDIT_CELL","TABLE_FONT","TABLE_FOREGROUND_COLOR","TABLE_VIEW", // "TAB_MODE","TEXT_ALL_EVENTS","TEXT_EDITABLE","TEXT_NUMBER","TEXT_OFFSET_TO_XY", // "TEXT_TOP_LINE","TEXT_XY_TO_OFFSET", // "TOOLTIP","TRACKING_EVENTS","TREE_DRAG_SELECT","UPDATE","USE_TABLE_SELECT","VISIBLE", "TAB_MODE",KLISTEND}; new DLibFunRetNew(lib::widget_info,string("WIDGET_INFO"),1,widget_infoKey,widget_infoWarnKey); //LABEL const string widget_labelKey[] = {WIDGET_COMMON_KEYWORDS,"VALUE","SUNKEN_FRAME","TRACKING_EVENTS","DYNAMIC_RESIZE",KLISTEND}; new DLibFunRetNew(lib::widget_label,string("WIDGET_LABEL"),1,widget_labelKey); //LIST const string widget_listKey[] = {WIDGET_COMMON_KEYWORDS,"MULTIPLE","VALUE","CONTEXT_EVENTS","TRACKING_EVENTS",KLISTEND}; const string widget_listWarnKey[] = {"TAB_MODE",KLISTEND}; new DLibFunRetNew(lib::widget_list,string("WIDGET_LIST"),1,widget_listKey,widget_listWarnKey); //MESSAGE //PROPERTYSHEET (2-columns TABLE) #ifdef HAVE_WXWIDGETS_PROPERTYGRID const string widget_propertyKey[] = {WIDGET_COMMON_KEYWORDS,KLISTEND} //to be finished... new DLibFunRetNew(lib::widget_property,string("WIDGET_PROPERTYSHEET"),1,widget_propertyKey); #endif //SLIDER const string widget_sliderKey[] = {WIDGET_COMMON_KEYWORDS,"TITLE","DRAG","VALUE","MINIMUM","MAXIMUM","VERTICAL", "SUPPRESS_VALUE", "TRACKING_EVENTS", KLISTEND}; const string widget_sliderWarnKey[] = {"TAB_MODE",KLISTEND}; new DLibFunRetNew(lib::widget_slider,string("WIDGET_SLIDER"),1,widget_sliderKey,widget_sliderWarnKey); //STUB //TAB const string widget_tabKey[] = {WIDGET_COMMON_KEYWORDS,"MULTILINE","LOCATION","TRACKING_EVENTS", KLISTEND}; // const string widget_tabWarnKey[] = {WIDGET_COMMON_KEYWORDS,"TAB_MODE", KLISTEND}; new DLibFunRetNew(lib::widget_tab,string("WIDGET_TAB"),1,widget_tabKey); //,widget_tabWarnKey); //TABLE const string widget_tableKey[] = {WIDGET_COMMON_KEYWORDS , "ALIGNMENT" , "ALL_EVENTS" , "BACKGROUND_COLOR" , "COLUMN_LABELS" , "COLUMN_WIDTHS" , "CONTEXT_EVENTS" , "DISJOINT_SELECTION" , "EDITABLE" , "FOREGROUND_COLOR" , "FORMAT" , "KBRD_FOCUS_EVENTS" , "RESIZEABLE_COLUMNS" , "RESIZEABLE_ROWS" , "ROW_HEIGHTS" , "ROW_LABELS" , "TRACKING_EVENTS" , "VALUE" , "X_SCROLL_SIZE" , "Y_SCROLL_SIZE" , "NO_COLUMN_HEADERS" , "NO_HEADERS" , "NO_ROW_HEADERS" , "COLUMN_MAJOR" , "ROW_MAJOR" , "AM_PM" , "DAYS_OF_WEEK" , "MONTHS" , KLISTEND}; const string widget_tableWarnKey[] = { "IGNORE_ACCELERATORS" , "TAB_MODE" , KLISTEND}; new DLibFunRetNew(lib::widget_table,string("WIDGET_TABLE"),1,widget_tableKey,widget_tableWarnKey); //TEXT const string widget_textKey[] = {WIDGET_COMMON_KEYWORDS,"EDITABLE","NO_NEWLINE","VALUE", "INPUT_FOCUS","ALL_EVENTS","CONTEXT_EVENTS","KBRD_FOCUS_EVENTS","TRACKING_EVENTS",KLISTEND}; const string widget_textWarnKey[] = {"IGNORE_ACCELERATORS","TAB_MODE","WRAP",KLISTEND}; new DLibFunRetNew(lib::widget_text,string("WIDGET_TEXT"),1,widget_textKey,widget_textWarnKey); //TREE const string widget_treeWarnKey[] = { "DRAG_NOTIFY" , "MASK" , "MULTIPLE" , "TAB_MODE" , KLISTEND}; const string widget_treeKey[] = {WIDGET_COMMON_KEYWORDS , "BITMAP" , "FOLDER" , "EXPANDED" , "VALUE" , "CONTEXT_EVENTS" , "TRACKING_EVENTS" , "DROP_EVENTS" , "DRAGGABLE" , "INDEX" , KLISTEND}; new DLibFunRetNew(lib::widget_tree,string("WIDGET_TREE"),1,widget_treeKey,widget_treeWarnKey); //TREE_MOVE // const string widget_bgroupKey[] = // {"BUTTON_UVALUE","COLUMN","EVENT_FUNC","EXCLUSIVE","NONEXCLUSIVE","SPACE","XPAD","YPAD","FRAME","IDS","LABEL_LEFT","LABEL_TOP","MAP","NO_RELEASE","RETURN_ID","RETURN_INDEX","RETURN_NAME","ROW","SCROLL","SET_VALUE","TAB_MODE","X_SCROLL_SIZE","Y_SCROLL_SIZE","SET_VALUE","UNAME","UVALUE","XOFFSET","XSIZE","YOFFSET","YSIZE",KLISTEND}; // new DLibFunRetNew(lib::widget_bgroup,string("CW_BGROUP"),2,widget_bgroupKey); } gdl-0.9.9/src/libinit_jp.cpp000066400000000000000000000035701340051421000157100ustar00rootroot00000000000000/*************************************************************************** libinit_jp.cpp - initialization of GDL library routines ------------------- begin : 2015 copyright : (C) 2015 by Jeongbin Park email : pjb7687@gmail.com ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "dialog.hpp" using namespace std; void LibInit_jp() { const char KLISTEND[] = ""; const string dialog_pickFile_wxwidgetsKey[] = { "DEFAULT_EXTENSION", "DIRECTORY", "DIALOG_PARENT", "DISPLAY_NAME", "FILE", "FILTER", "FIX_FILTER", "GET_PATH", "GROUP", "MULTIPLE_FILES", "MUST_EXIST", "OVERWRITE_PROMPT", "PATH", "READ", "WRITE", "RESOURCE_NAME", "TITLE", KLISTEND }; new DLibFunRetNew(lib::dialog_pickfile_wxwidgets, string("DIALOG_PICKFILE_WXWIDGETS"), 0, dialog_pickFile_wxwidgetsKey); const string dialog_message_wxwidgetsKey[] = { "CANCEL", "CENTER", "DEFAULT_CANCEL", "DEFAULT_NO", "DIALOG_PARENT", "DISPLAY_NAME", "ERROR", "INFORMATION", "QUESTION", "RESOURCE_NAME", "TITLE", KLISTEND }; new DLibFunRetNew(lib::dialog_message_wxwidgets, string("DIALOG_MESSAGE_WXWIDGETS"), 1, dialog_message_wxwidgetsKey); } gdl-0.9.9/src/libinit_mes.cpp000066400000000000000000000116711340051421000160640ustar00rootroot00000000000000/*************************************************************************** libinit_mes.cpp - initialization of GDL library routines ------------------- begin : Aug 02 2004 copyright : (C) 2004 by Peter Messmer email : messmer@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have HDF5 #define USE_HDF5 1 #endif #include "includefirst.hpp" #include #include #include "envt.hpp" #include "dpro.hpp" #include "basic_fun.hpp" #include "basic_pro.hpp" #ifdef USE_HDF5 #include "hdf5_fun.hpp" #endif #include "mpi.hpp" using namespace std; void LibInit_mes() { const char KLISTEND[] = ""; // general procedures/functions const string strtokKey[]={"EXTRACT","ESCAPE","LENGTH", "PRESERVE_NULL","REGEX","COUNT","FOLD_CASE",KLISTEND}; new DLibFunRetNew(lib::strtok_fun, string("STRTOK"), 2, strtokKey); new DLibPro(lib::setenv_pro, string("SETENV"), 1); const string getenvKey[]={"ENVIRONMENT", KLISTEND}; new DLibFunRetNew(lib::getenv_fun, string("GETENV"), 1, getenvKey); const string tagNamesKey[] = {"STRUCTURE_NAME", KLISTEND}; new DLibFunRetNew(lib::tag_names_fun, string("TAG_NAMES"), 1, tagNamesKey); const string stregexKey[] = {"BOOLEAN", "EXTRACT", "LENGTH", "SUBEXPR", "FOLD_CASE", KLISTEND}; new DLibFunRetNew(lib::stregex_fun, string("STREGEX"), 2, stregexKey); const string structAssignKey[] = {"NOZERO", "VERBOSE", KLISTEND}; new DLibPro(lib::struct_assign_pro, string("STRUCT_ASSIGN"), 2, structAssignKey); // new DLibPro(lib::wait_pro, string("WAIT"), 1); // new DLibFunRetNew(lib::clock_fun, string("CLOCK"),0); #ifdef USE_MPI // MPI Functions/Procedures const string mpiSendKey[] = {"DEST", "TAG", KLISTEND}; new DLibPro(lib::mpi_send_pro, string("MPIDL_SEND"), 1, mpiSendKey); const string mpiRecvKey[] = {"SOURCE", "TAG", "COUNT", KLISTEND}; new DLibFunRetNew(lib::mpi_recv_fun, string("MPIDL_RECV"), 0, mpiRecvKey); const string mpiAllreduceKey[] = {"SUM", "PRODUCT", "COUNT", KLISTEND}; new DLibFunRetNew(lib::mpi_allreduce_fun, string("MPIDL_ALLREDUCE"), 1, mpiAllreduceKey); new DLibFunRetNew(lib::mpi_comm_rank_fun, string("MPIDL_COMM_RANK"), 0); new DLibFunRetNew(lib::mpi_comm_size_fun, string("MPIDL_COMM_SIZE"), 0); new DLibPro(lib::mpi_finalize_pro, string("MPIDL_FINALIZE"), 0); #endif #ifdef USE_HDF5 // hdf5 procedures/functions new DLibFunRetNew(lib::h5f_create_fun, string("H5F_CREATE"), 1); new DLibFunRetNew(lib::h5f_open_fun, string("H5F_OPEN"), 1); new DLibFunRetNew(lib::h5d_open_fun, string("H5D_OPEN"), 2); new DLibFunRetNew(lib::h5d_read_fun, string("H5D_READ"), 1); // TODO: 2nd argument & keywords new DLibFunRetNew(lib::h5d_get_space_fun, string("H5D_GET_SPACE"), 1); new DLibFunRetNew(lib::h5s_get_simple_extent_dims_fun, string("H5S_GET_SIMPLE_EXTENT_DIMS"), 1); new DLibPro(lib::h5f_close_pro,string("H5F_CLOSE"),1); new DLibPro(lib::h5d_close_pro,string("H5D_CLOSE"),1); new DLibPro(lib::h5s_close_pro,string("H5S_CLOSE"),1); // SA: new DLibFunRetNew(lib::h5f_is_hdf5_fun, string("H5F_IS_HDF5"), 1); new DLibFunRetNew(lib::h5_get_libversion_fun, string("H5_GET_LIBVERSION"), 0); new DLibFunRetNew(lib::h5d_get_type_fun, string("H5D_GET_TYPE"), 1); new DLibFunRetNew(lib::h5t_get_size_fun, string("H5T_GET_SIZE"), 1); new DLibFunRetNew(lib::h5a_open_name_fun, string("H5A_OPEN_NAME"), 2); new DLibFunRetNew(lib::h5a_open_idx_fun, string("H5A_OPEN_IDX"), 2); new DLibFunRetNew(lib::h5a_get_name_fun, string("H5A_GET_NAME"), 1); new DLibFunRetNew(lib::h5a_get_space_fun, string("H5A_GET_SPACE"), 1); new DLibFunRetNew(lib::h5a_get_type_fun, string("H5A_GET_TYPE"), 1); new DLibFunRetNew(lib::h5a_get_num_attrs_fun, string("H5A_GET_NUM_ATTRS"), 1); new DLibFunRetNew(lib::h5a_read_fun, string("H5A_READ"), 1); // TODO: 2nd argument new DLibPro(lib::h5a_close_pro, string("H5A_CLOSE"), 1); new DLibPro(lib::h5t_close_pro, string("H5T_CLOSE"), 1); new DLibPro(lib::h5g_close_pro, string("H5G_CLOSE"), 1); new DLibFunRetNew(lib::h5g_open_fun, string("H5G_OPEN"), 2); // SA: disabling the default HDF5 error handler (error handling in hdf5_fun.cpp) H5Eset_auto(NULL, NULL); #endif } gdl-0.9.9/src/libinit_ng.cpp000066400000000000000000000025751340051421000157070ustar00rootroot00000000000000/*************************************************************************** libinit_ng.cpp - initialization of GDL library routines ------------------- begin : 26 May 2008 copyright : (C) 2008 by Nicolas Galmiche email : n.galmiche@gmail.com ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "math_fun_ng.hpp" using namespace std; void LibInit_ng() { const char KLISTEND[] = ""; const string rk4Key[]={"DOUBLE","ITER",KLISTEND}; new DLibFunRetNew(lib::rk4_fun,string("RK4"),5,rk4Key); const string voigtKey[]={"DOUBLE","ITER",KLISTEND}; new DLibFunRetNew(lib::voigt_fun,string("VOIGT"),2,voigtKey); } gdl-0.9.9/src/linearprogramming.cpp000066400000000000000000000153461340051421000173060ustar00rootroot00000000000000/*************************************************************************** linearprogramming.cpp - GDL library function ------------------- begin : Jul 12 2017 copyright : (C) 2017 by Gilles Duvert as interface to GLPK lib. ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dinterpreter.hpp" //#if defined(HAVE_GLPK) namespace lib { using namespace std; //#ifdef HAVE_GLPK #ifdef USE_GLPK //#define USE_GLPK 1 #include //#else //#define USE_GLPK 0 #endif BaseGDL* simplex(EnvT* e) { #ifndef USE_GLPK e->Throw("GDL was compiled without support for GLPK"); return NULL; #else // sanity check (for number of parameters) SizeT nParam = e->NParam(); if (nParam < 5) e->Throw("Incorrect number of arguments."); // 1-st argument : equation parameters; N parameters BaseGDL* p0 = e->GetParDefined(0); DDoubleGDL* zEquation = (DDoubleGDL*) p0->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard zEquation_guard(zEquation); DLong n = zEquation->N_Elements(); // 2nd argument : constraints: a N+1 cols by M rows table BaseGDL* p1 = e->GetParDefined(1); DDoubleGDL* constraints = (DDoubleGDL*) p1->Convert2(GDL_DOUBLE, BaseGDL::COPY); Guard constraints_guard(constraints); if (constraints->Rank() != 2) e->Throw("Constraints must be a Rank 2 matrix."); if (constraints->Dim(0) != n + 1) e->Throw("Constraints's first dimension must be " + i2s(n + 1)); DLong m = constraints->Dim(1); //3rd argument: m1, the number of less-than constraints (first m1 lines) DLong m1 = 0; e->AssureLongScalarPar(2, m1); //idem for m2 and m3, resp. greater-than and equal-to DLong m2 = 0; e->AssureLongScalarPar(3, m2); DLong m3 = 0; e->AssureLongScalarPar(4, m3); if (m1 + m2 + m3 != m) e->Throw("Sum of m1, m2 a,d m3 must be equal to " + i2s(m)); static int DOUBLEIx = e->KeywordIx("DOUBLE"); bool isDouble = (p0->Type() == GDL_DOUBLE); if (e->KeywordSet(DOUBLEIx)) isDouble = true; // We do not neeed eps at all. // static int EPSIx = e->KeywordIx("EPS"); // DDouble eps = isDouble ? 3E-10 : 3E-8; // bool doEps=false; // if (e->KeywordPresent(EPSIx)) { // e->AssureDoubleScalarKW(EPSIx, eps); // doEps=true; // } glp_prob *theProblem; theProblem = glp_create_prob(); glp_set_prob_name(theProblem, "GDL"); glp_set_obj_dir(theProblem, GLP_MAX); glp_add_rows(theProblem, m1 + m2 + m3); for (int i = 1; i < m1+1; ++i) //their numbering starts at 1 { string tmp = "up" + i2s(i); glp_set_row_name(theProblem, i, tmp.c_str()); glp_set_row_bnds(theProblem, i, GLP_UP, 0.0, (*constraints)[(i-1) * (n + 1)]); } for (int i = m1+1; i < m1 + m2 +1; ++i) //their numbering starts at 1 { string tmp = "lo" + i2s(i); glp_set_row_name(theProblem, i, tmp.c_str()); glp_set_row_bnds(theProblem, i, GLP_LO, (*constraints)[(i-1) * (n + 1)], 0.0); } for (int i = m1 + m2 +1 ; i < m+1 ; ++i) //their numbering starts at 1 { string tmp = "eq" + i2s(i); glp_set_row_name(theProblem, i, tmp.c_str()); glp_set_row_bnds(theProblem, i, GLP_FX, (*constraints)[(i-1) * (n + 1)], (*constraints)[(i-1) * (n + 1)]); } glp_add_cols(theProblem, n); for (int i = 1; i < n+1; ++i) //their numbering starts at 1 { string tmp = "X" + i2s(i); glp_set_col_name(theProblem, i, tmp.c_str()); glp_set_obj_coef(theProblem, i, (*zEquation)[i-1]); //their numbering starts at 1 glp_set_col_bnds(theProblem, i, GLP_LO, 0.0, 0.0); } int ia[n * m], ja[n * m]; double ar[n * m], z, x1, x2, x3; int k = 1; //their numbering starts at 1 for (int j = 0; j < m; ++j) { for (int i = 0; i < n; ++i) { ia[k] = j+1; ja[k] = i+1; ar[k] = -1.0*(*constraints)[1 + i + j * (n + 1)]; //sign is inverse from IDL k++; } } glp_load_matrix(theProblem, n*m, ia, ja, ar); glp_smcp parm; glp_init_smcp(&parm); parm.msg_lev=GLP_MSG_OFF; int returned=glp_simplex(theProblem, &parm); DLong status=0; static int STATUSIx = e->KeywordIx("STATUS"); bool returnStatus=e->KeywordPresent(STATUSIx); switch (glp_get_status(theProblem)) { case GLP_OPT: case GLP_FEAS: status=0; break; case GLP_UNBND: status=1; break; case GLP_INFEAS: case GLP_NOFEAS: case GLP_UNDEF: status=2; } if (returnStatus) { if (returned==0) e->SetKW(STATUSIx, new DLongGDL(status)); else e->SetKW(STATUSIx, new DLongGDL(3)); } //tableau etc not yet ready. // if (nParam >= 6) { // SizeT dims[2]; // dims[0] = n; // dims[1] = m + 2; // if (isDouble) // { // DDoubleGDL* tab = new DDoubleGDL(dimension(dims,2)); // e->SetPar(5, tab); // } else { // DFloatGDL* tab = new DFloatGDL(dimension(dims,2)); // e->SetPar(5, tab); // } // } // if (nParam >= 7) { // if (isDouble) // { // DDoubleGDL* izrov = new DDoubleGDL(dimension(n)); // e->SetPar(6, izrov); // } else { // DFloatGDL* izrov = new DFloatGDL(dimension(n)); // e->SetPar(6, izrov); // } // } // if (nParam == 8) { // if (isDouble) // { // DDoubleGDL* iposv = new DDoubleGDL(dimension(n)); // e->SetPar(7, iposv); // } else { // DFloatGDL* iposv = new DFloatGDL(dimension(n)); // e->SetPar(7, iposv); // } // } BaseGDL* ret; if (isDouble) { ret = new DDoubleGDL(dimension(n+1)); (*(DDoubleGDL*)ret)[0] = glp_get_obj_val(theProblem); for (int i = 1; i < n+1; ++i) (*(DDoubleGDL*)ret)[i] = glp_get_col_prim(theProblem, i); } else { ret = new DFloatGDL(dimension(n+1)); (*(DFloatGDL*)ret)[0] = glp_get_obj_val(theProblem); for (int i = 1; i < n+1; ++i) (*(DFloatGDL*)ret)[i] = glp_get_col_prim(theProblem, i); } return ret; #endif } } gdl-0.9.9/src/linearprogramming.hpp000066400000000000000000000023131340051421000173010ustar00rootroot00000000000000/*************************************************************************** linearprogramming.hpp - GDL header ------------------- begin : Jul 12 2017 copyright : (C) 2017 by Gilles Duvert as interface to GLPK lib. ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #ifndef GDLGLPK_HPP_ #define GDLGLPK_HPP_ //#ifdef USE_GLPK #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* simplex(EnvT* e); } //#endif #endif gdl-0.9.9/src/list.cpp000066400000000000000000004126241340051421000145440ustar00rootroot00000000000000/*************************************************************************** list.cpp - for LIST objects ------------------- begin : July 22 2013 copyright : (C) 2013 by M. Schellens et al. email : m_schellens@users.sf.net ******************************* * 2018 Apr 19: maintaining legacy LIST, introduce some of the new code * LIST_count - will be used externally * HASH_count - similarly * modifications particularly related to the re-definition * of N_elements() function for lists and hashes (To be redefined * to the usual usage, as for any other object array. * For scalar list parameters, N_ELEMENTS( ) give the number * of entries (LIST.count()). lib:: routine LIST_count is provided for that purpose. ***** * For the features it attempts, old list ("legacy list) does ok. * However for instance the usage ; alist[3] = fltarr(8) generates an error. * ********** * April 4 2016: Greg Jung * - fully implement TOARRAY, including DIMENSION and NO_COPY keywords. * - list.MOVE, list.SWAP methods. * - [ and ] overloads revised to accomodate in-place array access to hashes * and arrays contained, including nested lists and hashes. * * Additional goodies: * list.help(MAXITEM) - produce help lines for items within the list. * MAXITEM - maximum # of items to print help on ( default=4, -1 = no max) * items are identified as "list item " xxx. * sub-lists are expanded recursively. * ::GET - used by both LIST and by GDL_CONTAINER * LIST_Count(DstructGDL* Lstruct) - for use externally to get * #items in the list. This replaces the re-definition of N_Elements * for lists (and hashes) which confuses the issue. * macros used to declare static tag items * GDL_CONTAINER_STRUCT() * GDL_LIST_STRUCT() * GDL_CONTAINER_MODE() * Also * #define MAKE_LONGGDL(X, XLong) * Used to get a guarded long from parameter X, possibly converted. * GDL_HASH_STRUCT() \ * GDL_HASHTABLEENTRY() * For access to a hash embedded in a list. * This is a stage1 list.cpp, so most of the new functionality is NOT * included. **************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // These macros are used in the new container-related routines #define GDL_CONTAINER_STRUCT() \ static unsigned GDLContainerVersionTag = \ structDesc::GDL_CONTAINER->TagIndex( "GDLCONTAINERVERSION"); \ static unsigned pHeadTag = structDesc::GDL_CONTAINER->TagIndex( "PHEAD"); \ static unsigned pTailTag = structDesc::GDL_CONTAINER->TagIndex( "PTAIL"); \ static unsigned nListTag = structDesc::GDL_CONTAINER->TagIndex( "NLIST"); #define GDL_LIST_STRUCT() \ static unsigned GDLContainerVersionTag = \ structDesc::GDL_CONTAINER->TagIndex( "GDLCONTAINERVERSION"); \ static unsigned pHeadTag = structDesc::LIST->TagIndex( "PHEAD"); \ static unsigned pTailTag = structDesc::LIST->TagIndex( "PTAIL"); \ static unsigned nListTag = structDesc::LIST->TagIndex( "NLIST"); #define GDL_CONTAINER_NODE() \ static unsigned pNextTag = structDesc::GDL_CONTAINER_NODE->TagIndex( "PNEXT"); \ static unsigned pDataTag = structDesc::GDL_CONTAINER_NODE->TagIndex( "PDATA"); #define GDL_HASH_STRUCT() \ static unsigned TableBitsTag = structDesc::HASH->TagIndex( "TABLE_BITS"); \ static unsigned pTableTag = structDesc::HASH->TagIndex( "TABLE_DATA"); \ static unsigned TableSizeTag = structDesc::HASH->TagIndex( "TABLE_SIZE"); \ static unsigned TableCountTag = structDesc::HASH->TagIndex( "TABLE_COUNT"); #define GDL_HASHTABLEENTRY() \ static unsigned pKeyTag = structDesc::GDL_HASHTABLEENTRY->TagIndex( "PKEY"); \ static unsigned pValueTag = structDesc::GDL_HASHTABLEENTRY->TagIndex( "PVALUE"); #define MAKE_LONGGDL(X, XLong) \ DLongGDL* XLong=0; \ Guard XLongGuard; \ if(X != 0) { \ if(X->Type() == GDL_LONG) \ XLong = static_cast( X); \ else { \ try { \ XLong = static_cast( X->Convert2( GDL_LONG, BaseGDL::COPY)); \ } \ catch( GDLException& ex) { \ ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); \ } \ XLongGuard.Init( XLong); \ } \ } #include "includefirst.hpp" #include "nullgdl.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" bool Hashisfoldcase( DStructGDL* hashStruct); DLong HashIndex( DStructGDL* hashTable, BaseGDL* key, bool isfoldcase); void InsertIntoHashTable( DStructGDL* hashStruct, DStructGDL*& hashTable, BaseGDL* key, BaseGDL* value); static bool trace_me(false); static bool doIncDec(true); // In order to experiment with IncRef and DecRef namespace lib { // bool trace_arg(); bool array_equal_bool( BaseGDL* p0, BaseGDL* p1, bool notypeconv=false, bool not_equal=false, bool quiet=true); void help_item( std::ostream& os, BaseGDL* par, DString parString, bool doIndentation); void help_struct( std::ostream& os, BaseGDL* par, int indent , bool debug ); void hash_leftinsertion( EnvUDT* e, DStructGDL* theStruct, int iprm); BaseGDL* hash_subset(DStructGDL* thisTable, BaseGDL* index, bool isfoldcase); } template< typename IndexT> void MergeSortDescending( IndexT* hhS, IndexT* h1, IndexT* h2, SizeT len) { if( len <= 1) return; SizeT h1N = len / 2; SizeT h2N = len - h1N; // 1st half MergeSortDescending(hhS, h1, h2, h1N); // 2nd half IndexT* hhM = &hhS[h1N]; MergeSortDescending(hhM, h1, h2, h2N); SizeT i; for(i=0; iType() != GDL_OBJ) ThrowFromInternalUDSub( e, "Objptr not of type OBJECT. Please report."); if( !Objptr->Scalar()) ThrowFromInternalUDSub( e, "Objptr must be a scalar. Please report."); DObjGDL* Object = static_cast( Objptr); DObj ID = (*Object)[0]; try { return BaseGDL::interpreter->GetObjHeap( ID); } catch( GDLInterpreter::HeapException& hEx) { ThrowFromInternalUDSub( e, "Object ID <"+i2s(ID)+"> not found."); } assert(false); return NULL; } DStructGDL* GetLISTStruct( EnvUDT* e, DPtr actP) { // Get the GDL_CONTAINER_NODE struct {pNext, pData} from a list // From the heap pointer actP // the next pointer in list will be found in the struct. BaseGDL* actPHeap; try { actPHeap = BaseGDL::interpreter->GetHeap( actP); } catch( GDLInterpreter::HeapException& hEx) { if( e == NULL) throw GDLException( "LIST container node ID <" +i2s(actP)+"> not found."); ThrowFromInternalUDSub( e, "LIST container node ID <" +i2s(actP)+"> not found."); } if( actPHeap == NULL || actPHeap->Type() != GDL_STRUCT) { if( e == NULL) throw GDLException( "LIST node must be a STRUCT."); else ThrowFromInternalUDSub( e, "LIST node must be a STRUCT."); } DStructGDL* actPStruct = static_cast( actPHeap); return actPStruct; } static BaseGDL* GetNodeData(DPtr &Node) { GDL_CONTAINER_NODE() DStructGDL* act = GetLISTStruct( NULL, Node); DPtr ptrX = (*static_cast(act->GetTag( pDataTag, 0)))[0]; Node = (*static_cast(act->GetTag( pNextTag, 0)))[0]; BaseGDL* result = new BaseGDL( ); Guard resultGuard( result); result = BaseGDL::interpreter->GetHeap( ptrX); if( result == NULL) result = NullGDL::GetSingleInstance(); // if(trace_me) lib::help_item(std::cout, result, " from GetNodeData", false); resultGuard.Release(); return result; } void FreeLISTNode( EnvUDT* e, DPtr pRemoveNode, bool deleteData = true) { GDL_CONTAINER_NODE() DStructGDL* removeNode = GetLISTStruct( e, pRemoveNode); DPtr pData = (*static_cast( removeNode->GetTag( pDataTag, 0)))[0]; if( deleteData) BaseGDL::interpreter->FreeHeap( pData); // delete else BaseGDL::interpreter->HeapErase( pData); // no delete // prevent cleanup due to ref-counting (*static_cast( removeNode->GetTag( pNextTag, 0)))[0] = 0; BaseGDL::interpreter->FreeHeap( pRemoveNode); // delete return; } DPtr GetLISTNode( EnvUDT* e, DStructGDL* self, DLong targetIx) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DPtr actP; if( targetIx == -1) { actP = (*static_cast(self->GetTag( pHeadTag, 0)))[0]; } else { actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; for( SizeT elIx = 0; elIx < targetIx; ++elIx) { DStructGDL* actPStruct = GetLISTStruct(e, actP); actP = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; } } return actP; } void LIST__ToStream( DStructGDL* oStructGDL, std::ostream& o, SizeT w, SizeT* actPosPtr) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() SizeT nList = (*static_cast(oStructGDL->GetTag( nListTag, 0)))[0]; DPtr pActNode = GetLISTNode( NULL, oStructGDL, 0); for( SizeT i=0; i(actNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( pData); if( data == NULL) data = NullGDL::GetSingleInstance(); data->ToStream( o, w, actPosPtr); if( (i+1) < nList) o << std::endl; pActNode = (*static_cast(actNode->GetTag( pNextTag, 0)))[0]; } } // for HEAP_GC void EnvBaseT::AddLIST( DPtrListT& ptrAccessible, DPtrListT& objAccessible, DStructGDL* listStruct) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DStructGDL* self = listStruct; DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; // vector listElementsID; // listElementsID.reserve( nList); DPtr actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; for( SizeT elIx = 0; elIx < nList; ++elIx) { // no recursion here // PNEXT is handled within this loop instead ptrAccessible.insert( actP); DStructGDL* actPStruct = GetLISTStruct(NULL, actP); DPtr actPData = (*static_cast( actPStruct->GetTag( pDataTag, 0)))[0]; // the LIST is corrupted if this check fails, // but we quietly ignore it, as this is only about heap consistency if( actPData != 0 && interpreter->PtrValid( actPData)) { ptrAccessible.insert( actPData); Add( ptrAccessible, objAccessible, interpreter->GetHeap( actPData)); } actP = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; } } void LISTCleanup( EnvUDT* e, DStructGDL* self) { GDL_CONTAINER_NODE() GDL_LIST_STRUCT() DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; DPtr actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; // swipe head and tail pointer (*static_cast( self->GetTag( pTailTag, 0)))[0] = 0; (*static_cast( self->GetTag( pHeadTag, 0)))[0] = 0; for( SizeT elIx = 0; elIx < nList; ++elIx) { // DStructGDL* actPStruct = GetLISTStruct(e, actP); BaseGDL* actPHeap; try { actPHeap = BaseGDL::interpreter->GetHeap( actP); } catch( GDLInterpreter::HeapException& hEx) { std::cout << "LIST::cleanup - container node ID <" +i2s(actP)+"> not found." << " Returning w/o error " << std::endl; return; } if( actPHeap == NULL || actPHeap->Type() != GDL_STRUCT) ThrowFromInternalUDSub( e, "container node must be a STRUCT."); DStructGDL* actPStruct = static_cast( actPHeap); DPtr actPNext = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; // the key here: break the chain (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0] = 0; //==// DPtr pData = (*static_cast(actPStruct ->GetTag( pDataTag, 0)))[0]; if( trace_me) std::printf("pData=%llu.",pData); if(doIncDec) { BaseGDL* data = BaseGDL::interpreter->GetHeapNoThrow( pData); if( data == NULL || data == NullGDL::GetSingleInstance()) ; else if( (data->Type() == GDL_PTR) && e->Interpreter()->PtrValid( pData)) e->Interpreter()->DecRef( pData); else if( (data->Type() == GDL_OBJ) && e->Interpreter()->ObjValid( pData)) e->Interpreter()->DecRefObj( pData); else e->Interpreter()->FreeHeap( pData); } //==// GDLInterpreter::FreeHeap( actP); // deletes also PDATA (?) actP = actPNext; } (*static_cast( self->GetTag( nListTag, 0)))[0] = 0; } void CONTAINERCleanup( EnvUDT* e, DStructGDL* self) { GDL_CONTAINER_STRUCT() GDL_CONTAINER_NODE() enum {POINTERS=1, OBJECTS}; DInt GDLContainerVersion = (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0]; bool isPtr = (GDLContainerVersion == POINTERS); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList == 0) return; DPtr actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; if( actP == 0) ThrowFromInternalUDSub( e, " Invalid Node reference at tail end of container"); // swipe head and tail pointer, reset nlist. (*static_cast( self->GetTag( pTailTag, 0)))[0] = 0; (*static_cast( self->GetTag( pHeadTag, 0)))[0] = 0; (*static_cast( self->GetTag( nListTag, 0)))[0] = 0; if( trace_me) std::cout << " Top of deallocation loop: " ; for( SizeT elIx = 0; elIx < nList; ++elIx) { if( trace_me) std::printf(" #%llu %llu:",elIx,actP); // DStructGDL* Node = GetLISTStruct(e, actP); BaseGDL* actPHeap; try { actPHeap = BaseGDL::interpreter->GetHeap( actP); } catch( GDLInterpreter::HeapException& hEx) { // ThrowFromInternalUDSub( e, " container node ID <" // +i2s(actP)+"> not found."); std::cout << "Container::cleanup - container node ID <" +i2s(actP)+"> not found." << " Returning w/o error " << std::endl; return; } if( actPHeap == NULL || actPHeap->Type() != GDL_STRUCT) ThrowFromInternalUDSub( e, "container node must be a STRUCT."); DStructGDL* Node = static_cast( actPHeap); DPtr pNext = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; DPtr pData = (*static_cast( Node->GetTag( pDataTag, 0)))[0]; if( trace_me) std::printf("pData=%llu.",pData); if(doIncDec) { if( isPtr && e->Interpreter()->PtrValid( pData)) e->Interpreter()->DecRef( pData); else if(!isPtr && e->Interpreter()->ObjValid( pData)) e->Interpreter()->DecRefObj( pData); } // prevent cleanup due to ref-counting (*static_cast( Node->GetTag( pNextTag, 0)))[0] = 0; BaseGDL::interpreter->FreeHeap( actP); actP = pNext; } if(trace_me) std::cout << std::endl; } namespace lib { BaseGDL* list_rightextraction( EnvUDT* e, BaseGDL* theref, int iprm ); void list_insertion( BaseGDL* theref, BaseGDL* rVal, ArrayIndexListT* ixList) { DType destTy = theref->Type(); ixList->SetVariable( theref); dimension dim = ixList->GetDim(); if( rVal->Type() != destTy) rVal = rVal->Convert2( destTy, BaseGDL::COPY); switch( destTy) { case GDL_BYTE: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break;} case GDL_INT: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break;} case GDL_UINT: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_LONG: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_ULONG: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_LONG64: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_ULONG64: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_FLOAT: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_DOUBLE: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_STRING: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_COMPLEX: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_COMPLEXDBL: { Data_* dest= static_cast* >(theref); dest->AssignAt( rVal, ixList); break; } case GDL_STRUCT: { DStructGDL* dest=static_cast(theref); dest->AssignAt( rVal, ixList); break;} case GDL_PTR: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break;} case GDL_OBJ: { Data_* dest=static_cast* >(theref); dest->AssignAt( rVal, ixList); break;} } return; } BaseGDL* list_extraction( BaseGDL* theref, ArrayIndexListT* ixList) { DType destTy = theref->Type(); ixList->SetVariable( theref); dimension dim = ixList->GetDim(); switch( destTy) { case GDL_BYTE: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest) ;} case GDL_INT: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest) ;} case GDL_UINT: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_LONG: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_ULONG: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_LONG64: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_ULONG64: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_FLOAT: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_DOUBLE: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_STRING: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_COMPLEX: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_COMPLEXDBL: {Data_* dest= new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest); } case GDL_PTR: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest) ;} case GDL_OBJ: {Data_* dest=new Data_( dim, BaseGDL::NOZERO); dest->InsertAt( 0, theref, ixList); return static_cast(dest) ;} case GDL_STRUCT: {DStructGDL* dest=new DStructGDL((static_cast(theref))->Desc(), dim); dest->InsertAt( 0, theref, ixList); return static_cast(dest) ;} } // Guard resultGuard( result); } void list__cleanup( EnvUDT* e) { DStructGDL* self = GetOBJ( e->GetKW( 0), e); if( trace_me) std::cout << " List::CLEANUP" << std::endl; LISTCleanup( e, self); } BaseGDL* LIST___OverloadIsTrue( EnvUDT* e) { SizeT nParam = e->NParam(1); // SELF DStructGDL* self = GetOBJ( e->GetKW( 0), e); // here static is fine static unsigned nListTag = structDesc::LIST->TagIndex( "NLIST"); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList == 0) return new DByteGDL(0); else return new DByteGDL(1); } BaseGDL* LIST___OverloadEQOp( EnvUDT* e); BaseGDL* LIST___OverloadNEOp( EnvUDT* e) { DByteGDL* result = static_cast(LIST___OverloadEQOp( e)); for( SizeT i=0; iN_Elements(); ++i) { if( (*result)[i] == 0) (*result)[i] = 1; else (*result)[i] = 0; } return result; } BaseGDL* LIST___OverloadEQOp( EnvUDT* e) { SizeT nParam = e->NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined if( nParam < 3) // consider implicit SELF ThrowFromInternalUDSub( e, "Two parameters are needed: LEFT, RIGHT."); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // default behavior: Exact like scalar indexing DStructGDL* leftStruct = NULL; DStructGDL* rightStruct = NULL; BaseGDL* l = e->GetKW(1); if( l == NULL) l = NullGDL::GetSingleInstance(); else if( l->Type() == GDL_OBJ) leftStruct = GetOBJ( l, e); BaseGDL* r = e->GetKW(2); if( r == NULL) r = NullGDL::GetSingleInstance(); else if( r->Type() == GDL_OBJ) rightStruct = GetOBJ( r, e); if( rightStruct == NULL && leftStruct == NULL){ ThrowFromInternalUDSub( e, "At least one parameter must be a LIST."); } if( leftStruct == NULL) { leftStruct = rightStruct; rightStruct = NULL; r = l; } if( leftStruct->Desc() != structDesc::LIST) ThrowFromInternalUDSub( e, "Parameter must be a LIST."); if( rightStruct != NULL && rightStruct->Desc() != structDesc::LIST) ThrowFromInternalUDSub( e, "Right parameter must be a LIST."); SizeT nListLeft = (*static_cast(leftStruct->GetTag( nListTag, 0)))[0]; SizeT nListRight = 0; if( rightStruct != NULL) { nListRight = (*static_cast(rightStruct->GetTag( nListTag, 0)))[0]; if( nListRight == 0) { if( nListLeft == 0) return new DByteGDL(1); else return new DByteGDL(0); } } assert( rightStruct == NULL || nListRight > 0); if( nListLeft == 0) { return new DByteGDL(0); } if( rightStruct != NULL) { SizeT nEl = (nListLeft < nListRight) ? nListLeft : nListRight; DByteGDL* result = new DByteGDL( dimension( nEl)); Guard resultGuard( result); if(trace_me) std::cout << "OverloadEQOp: left and right: nEl=" << nEl; DPtr pActLNode = GetLISTNode( e, leftStruct, 0); DPtr pActRNode = GetLISTNode( e, rightStruct, 0); for( SizeT i=0; i(actLNode->GetTag( pDataTag, 0)))[0]; BaseGDL* dataL = BaseGDL::interpreter->GetHeap( pDataL); DPtr pDataR = (*static_cast(actRNode->GetTag( pDataTag, 0)))[0]; BaseGDL* dataR = BaseGDL::interpreter->GetHeap( pDataR); if( dataL == NULL || dataL == NullGDL::GetSingleInstance()) { if( dataR == NULL || dataR == NullGDL::GetSingleInstance()) (*result)[ i] = 1; } else if( dataR != NULL && dataR != NullGDL::GetSingleInstance()) { if( dataL->N_Elements() != dataR->N_Elements() ) (*result)[ i] = 0; // same number of elements else if( ( gdl_type_lookup::IsNumericType[dataL->Type()] and !gdl_type_lookup::IsNumericType[dataR->Type()] ) or ( gdl_type_lookup::IsNumericType[dataR->Type()] and !gdl_type_lookup::IsNumericType[dataL->Type()] ) ) (*result)[ i] = 0; else { if(trace_me) std::cout << " ."<< i ; if ( !gdl_type_lookup::IsConvertableType[dataR->Type()] or !gdl_type_lookup::IsConvertableType[dataL->Type()] ) { (*result)[ i] = 0; continue; } BaseGDL* rConvert = dataR; if( !(dataL->EqType(dataR)) ) rConvert = dataR->Convert2(dataL->Type(),BaseGDL::COPY); Guard rConvertGuard( rConvert); BaseGDL* eqRes = dataL->EqOp( rConvert); rConvertGuard.Release(); if( eqRes->Type() != GDL_BYTE) eqRes = eqRes->Convert2( GDL_BYTE, BaseGDL::CONVERT); Guard eqResGuard( eqRes); DByteGDL* eqResByte = static_cast(eqRes); SizeT c = 0; for( c=0; cN_Elements(); ++c) if( !((*eqResByte)[ c])) break; if( c == eqResByte->N_Elements()) (*result)[ i] = 1; eqResGuard.Release(); } } // advance to next node pActLNode = (*static_cast(actLNode->GetTag( pNextTag, 0)))[0]; pActRNode = (*static_cast(actRNode->GetTag( pNextTag, 0)))[0]; } if(trace_me) std::cout << " >>" < resultGuard( result); if(trace_me) std::cout << "OverloadEQOp: left only: nEl=" << nEl ; DPtr pActLNode = GetLISTNode( e, leftStruct, 0); BaseGDL* dataR = r; for( SizeT i=0; i(actLNode->GetTag( pDataTag, 0)))[0]; BaseGDL* dataL = BaseGDL::interpreter->GetHeap( pDataL); if( dataL == NULL || dataL == NullGDL::GetSingleInstance()) { if( dataR == NULL || dataR == NullGDL::GetSingleInstance()) (*result)[ i] = 1; } else if( dataR != NULL && dataR != NullGDL::GetSingleInstance()) { if( dataL->N_Elements() != dataR->N_Elements() ) (*result)[ i] = 0; // same number of elements else if( dataL->EqType(dataR)) { // same type if(trace_me) std::cout << " ?"<< i ; BaseGDL* eqRes = dataL->EqOp( dataR); if( eqRes->Type() != GDL_BYTE) { Guard eqResGuardTmp( eqRes); eqRes = eqRes->Convert2( GDL_BYTE, BaseGDL::CONVERT); eqResGuardTmp.Release(); } Guard eqResGuard( eqRes); DByteGDL* eqResByte = static_cast(eqRes); SizeT c = 0; for( c=0; cN_Elements(); ++c) if( !((*eqResByte)[ c])) break; if( c == eqResByte->N_Elements()) (*result)[ i] = 1; } else if( ( gdl_type_lookup::IsNumericType[dataL->Type()] and !gdl_type_lookup::IsNumericType[dataR->Type()] ) or ( gdl_type_lookup::IsNumericType[dataR->Type()] and !gdl_type_lookup::IsNumericType[dataL->Type()] ) ) (*result)[ i] = 0; else { // convertable, first convert. if(trace_me) std::cout << " ."<< i ; BaseGDL* eqRes = NULL; DType aTy=dataL->Type(); DType bTy=dataR->Type(); if( DTypeOrder[aTy] > DTypeOrder[bTy]) { // convert b to a BaseGDL* rConvert = dataR->Convert2(dataL->Type(),BaseGDL::COPY); Guard rConvertGuard(rConvert); eqRes = dataL->EqOp( rConvert); } else { // convert a to b BaseGDL* lConvert = dataL->Convert2(dataR->Type(),BaseGDL::COPY); Guard lConvertGuard(lConvert); eqRes = dataR->EqOp( lConvert); } if( eqRes->Type() != GDL_BYTE) { Guard eqResGuardTmp( eqRes); eqRes = eqRes->Convert2( GDL_BYTE, BaseGDL::CONVERT); eqResGuardTmp.Release(); } Guard eqResGuard( eqRes); DByteGDL* eqResByte = static_cast(eqRes); SizeT c = 0; for( c=0; cN_Elements(); ++c) if( !((*eqResByte)[ c])) break; if( c == eqResByte->N_Elements()) (*result)[ i] = 1; } } // advance to next node pActLNode = (*static_cast(actLNode->GetTag( pNextTag, 0)))[0]; } if(trace_me) std::cout << " >>" <NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined // if(trace_arg()) std::printf(" list___OverloadPlus \n"); if( nParam < 3) ThrowFromInternalUDSub( e, "Two parameters are needed: LEFT, RIGHT."); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DStructGDL* leftStruct; DStructGDL* rightStruct; // default behavior: Exact like scalar indexing BaseGDL* l = e->GetKW(1); if(l == NULL || l->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, "Left parameter must be a LIST."); else leftStruct = GetOBJ( l, e); BaseGDL* r = e->GetKW(2); if(r == NULL || r->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, "Right parameter must be a LIST."); else rightStruct = GetOBJ( r, e); // define the standard listDesc from global: DStructDesc* listDesc = structDesc::LIST; if( leftStruct->Desc() != listDesc ) ThrowFromInternalUDSub( e, "Left parameter must be a LIST."); if( rightStruct->Desc() != listDesc) ThrowFromInternalUDSub( e, "Right parameter must be a LIST."); SizeT nListLeft = (*static_cast(leftStruct->GetTag( nListTag, 0)))[0]; SizeT nListRight = (*static_cast(rightStruct->GetTag( nListTag, 0)))[0]; DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct BaseGDL* newObj = new DObjGDL( objID); // the list object if( nListLeft == 0 && nListRight == 0) return newObj; Guard newObjGuard( newObj); // because of .RESET_SESSION, we cannot use static here DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; DPtr pActNode = GetLISTNode( e, (nListLeft > 0) ? leftStruct : rightStruct, 0); for( SizeT i=0; i(actNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( pData); if( data != NULL) data = data->Dup(); DPtr dID = e->Interpreter()->NewHeap(1,data); cStruct = new DStructGDL( containerDesc, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; if( (i+1) == nListLeft && nListRight > 0) pActNode = GetLISTNode( e, rightStruct, 0); else pActNode = (*static_cast(actNode->GetTag( pNextTag, 0)))[0]; } (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = nListLeft+nListRight; newObjGuard.Release(); return newObj; } /* * In this example, we create a list that contains another list (which contains an array) and a hash: list = LIST( 'Sensor Data', 'April 2', $ LIST('MyData', DIST(20, 30)), $ HASH('LINESTYLE', 3, 'THICK', 2) ) ; Extract the entire array from the sub-list help, list[2, 1] FLOAT = Array[20, 30] ; Extract a subset of the array within the sub-list help, list[2, 1, 10:15, [20,21,22] ] FLOAT = Array[6, 3] ; Add a new key-value to the hash within the list list[3, 'COLOR'] = 'blue' ; Extract a value from the hash help, list[3, 'COLOR' ] STRING = 'blue' * */ BaseGDL* LIST___OverloadBracketsRightSide( EnvUDT* e) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() static unsigned isRangeIx = 1; static unsigned prmbeg = isRangeIx+1; SizeT nParam = e->NParam(1); std::string trcn = trace_me? "\n;" :";"; if(trace_me) std::cout << "LIST__] #:" << e->GetKW( 0)->N_Elements(); DLongGDL* isRange = static_cast( e->GetKW(isRangeIx)); SizeT nIsRange = isRange->N_Elements(); // 2016 Mar 28 check-throws on above gets removed because Interpreter // will send the right stuff, or nothing at all. // = list[4,5,6] // What's passed from the interpreter is a GDL variable // isRange followed by the entries within the brackets (par1, par2 , ...) if(nIsRange == 0) { nIsRange = nParam - prmbeg; for (int i=0; i < nIsRange; i++) (*isRange)[i] = 0; if(trace_me) std::cout << " nIsRange was 0!" ; } // isRange is a series of 0 or 1 indicating if a range is present. // may not have N_Elements() properly set. // This occurs when a range is not in the list of parameters. // in that case the preparation of isRange is neglected. if(trace_me) { std::cout << ",nIsRange " << nIsRange << ",nParam " << nParam << " ,isRange:"; for (int i=0; i < nIsRange; i++) std::cout << " "<<(*isRange)[i]; std::cout << std::endl; } // Generalize from self to theStruct BaseGDL* theref = e->GetKW( 0); DStructGDL* self = GetOBJ( theref , e); DStructGDL* theStruct = self; int iprm = 0; SizeT listSize = (*static_cast(self->GetTag( nListTag, 0)))[0]; bool islist=true; bool ishash = false; bool isstruct = false; //--------------------- // Drill down until either a range is encountered or parameter list ends. // /* mxlist = LIST( 'Sensor Data', 'April 2', $ LIST('integers', indgen(20, 30)), $ HASH('LINESTYLE', 3, 'THICK', 2, 'LIST', LIST('this','is','another','list') ) ) */ // If mylist[index, points to LIST or to HASH // mylist[2, Ix] Ix indexes the internally kept list. // mylist[3,'THICK'] will pull thick from the hash // mylist[3,'LIST',2] will result in "another" // mylist[3,'LIST',*] will result in LIST('this','is','another','list') //--------------------- while( (*isRange)[iprm] == 0) { // && (iprm+3 < nParam) BaseGDL* XX = e->GetKW( iprm + prmbeg); if( islist) { MAKE_LONGGDL( XX, XXLong) if( !XX->StrictScalar()) break; // must be a scalar DLong Ixref = (*XXLong)[0]; listSize = (*static_cast(theStruct->GetTag( nListTag, 0)))[0]; if(Ixref >= listSize) // this is certainly common. ThrowFromInternalUDSub( e, "direct access index is too high" + i2s(Ixref) + " >= nList:"+i2s(listSize)); DStructGDL* Node = GetLISTStruct( e, GetLISTNode( e, theStruct, Ixref)); DPtr Ptr = (*static_cast( Node->GetTag( pDataTag, 0)))[0]; theref = BaseGDL::interpreter->GetHeap( Ptr); if(trace_me) std::cout << " (islist) Ixref=" << i2s(Ixref) << ", iprm="<( theStruct->GetTag( pTableTag, 0) ))[0]; DStructGDL* hashTable = static_cast( BaseGDL::interpreter->GetHeap( Ptr)); bool isfoldcase = Hashisfoldcase( theStruct); if(trace_me) std::cout<< " embedded hash:"; if(XX->Type() == GDL_OBJ && XX->StrictScalar()) { DObj p=(*static_cast( XX))[0]; if(p != 0) { DStructGDL* ListHead = GetOBJ( XX, e); if(ListHead->Desc()->IsParent("LIST")) { theref = hash_subset(hashTable, XX, isfoldcase); if(iprm+prmbeg+1 == nParam) return theref; if(trace_me) std::cout << " ...[XX...]" ; } else ThrowFromInternalUDSub( e, " -XX- hash key an object not LIST"); } else ThrowFromInternalUDSub( e, " -XX- hash key an invalid object"); } else { if( XX->N_Elements() == 1){ DLong hashIndex = HashIndex( hashTable, XX, isfoldcase); if( hashIndex < 0) return NullGDL::GetSingleInstance(); DPtr vID = (*static_cast(hashTable->GetTag( pValueTag, hashIndex)))[0]; BaseGDL* value = e->Interpreter()->GetHeap( vID); if(trace_me) lib::help_item(std::cout, value," [...XX]value",false); if( value == NULL) return NullGDL::GetSingleInstance(); else return value->Dup(); } else return hash_subset(hashTable, XX, isfoldcase); } } else if( isstruct ) { // use XX to access struct. if( !XX->StrictScalar()) break; // must be a scalar int ptagindex = 0; if(XX->Type() != GDL_STRING) { MAKE_LONGGDL( XX, XXLong) ptagindex = (*XXLong)[0]; if(ptagindex >= theStruct->Desc()->NTags() ) ptagindex = -1; } else { DString tag = (*static_cast( XX))[0]; StrUpCaseInplace(tag); ptagindex = theStruct->Desc()->TagIndex(tag); } if(ptagindex < 0) ThrowFromInternalUDSub( e, " struct tag not found "); theref = theStruct->Get( ptagindex); } else { if(trace_me) std::cout << "isstruct || ishash || islist "<< iprm <Type(); if(trace_me) std::cout << " theType="<Rank() == 0) { DPtr p=(*static_cast( theref))[0]; if( p != 0) theref = BaseGDL::interpreter->GetHeap( p); theType = theref->Type(); } if(trace_me) help_item(std::cout, theref, trcn+"theref ",false); islist = false; ishash = false; isstruct = false; if(theType == GDL_OBJ && theref->Rank() == 0) { DObj p=(*static_cast( theref))[0]; if(p == 0) break; theStruct = GetOBJ( theref, e); DStructDesc* desc = theStruct->Desc(); islist = desc->IsParent("LIST"); ishash = desc->IsParent("HASH"); isstruct = !(islist or ishash); } // else if( theType == GDL_STRUCT and // theref->N_Elements() == 1) { else if( theType == GDL_STRUCT) { theStruct = static_cast( theref); isstruct = true; } if(iprm+3 == nParam) return theref->Dup(); iprm++; if( gdl_type_lookup::IsConvertableType[theType] ) break; } // while if(trace_me) std::cout << " LIST_OL[R]: iprm="<< i2s(iprm); if(trace_me) lib::help_item(std::cout, theref," theref",false); return list_rightextraction( e, theref, iprm); // e, theref, iprm } BaseGDL* list_rightextraction( EnvUDT* e, BaseGDL* theref, int iprm ) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() SizeT nParam = e->NParam(1); static unsigned isRangeIx = 1; static unsigned prmbeg = isRangeIx+1; DLongGDL* isRange = static_cast( e->GetKW(isRangeIx)); SizeT nIsRange = isRange->N_Elements(); if(nIsRange == 0) { nIsRange = nParam - prmbeg; for (int i=0; i < nIsRange; i++) (*isRange)[i] = 0; } DType theType = theref->Type(); bool islist = false; bool ishash = false; bool isstruct = false; DStructGDL* theStruct; if(theType == GDL_OBJ && theref->Rank() == 0) { DObj p=(*static_cast( theref))[0]; if(p != 0) { theStruct = GetOBJ( theref, e); DStructDesc* desc = theStruct->Desc(); islist = desc->IsParent("LIST"); ishash = desc->IsParent("HASH"); isstruct = !(islist or ishash); } } else if( theType == GDL_STRUCT) { theStruct = static_cast( theref); isstruct = true; } // ArrayIndexVectorT ixList; try { for( int p=iprm; pGetKW( p + prmbeg); // implicit SELF, ISRANGE, par1..par8 if( parX == 0) // programming error. ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( p + prmbeg))); MAKE_LONGGDL(parX, parXLong) DLong isRangeX = (*isRange)[p]; if( isRangeX != 0 && isRangeX != 1) // programming error. ThrowFromInternalUDSub( e, "Value of parameter 1 (ISRANGE[" +i2s(p)+"]) is out of allowed range."); if( isRangeX == 1) { if( parX->N_Elements() != 3) // programming error. ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW( p + prmbeg))); if(trace_me) { std::cout << "; p:"<

CArrayIndexRangeS can handle [b:*:s] ([b,-1,s]) ixList.push_back(nCA); } else // non-range { if(trace_me) std::cout << "; p:"<

Rank() == 0) ixList.push_back( new CArrayIndexScalar( parX->Dup())); else ixList.push_back( new CArrayIndexIndexed( parX->Dup())); } } // for } catch( ...) { ixList.Destruct(); // ixList is not valid afterwards, but as we throw this is ok throw; } if( trace_me) std::cout << " done, iprm="< aLGuard( aL); if(!islist) { if( trace_me && theref != 0) std::cout <<", theref->N_El() "<N_Elements() <<", theref->Type() "<Type(); if(isstruct and trace_me) std::cout <<" isstruct !!"; if(trace_me) std::cout << " ixList: " << ixList.size() << " dim:" << aL->GetDim() << std::endl; // if(ishash || isstruct){ if(ishash ){ ThrowFromInternalUDSub( e, " hashes or structs cannot be accessed this way."); } else return list_extraction( theref , aL); } SizeT listSize = (*static_cast(theStruct->GetTag( nListTag, 0)))[0]; SpDLong t = SpDLong( dimension(listSize)); aL->SetVariable( &t); AllIxBaseT* allIx = aL->BuildIx(); aLGuard.Release(); Guard< AllIxBaseT> allIxGuard( allIx); if(trace_me) std::cout << " listSize:" << listSize; if(trace_me) std::cout << " allIx->size()=" << allIx->size() <size() == 1 && ( ((*isRange)[0] == 0) && (e->GetKW( prmbeg))->StrictScalar() )) { DLong targetIx = allIx->operator[](0); if( targetIx == (listSize-1)) targetIx = -1; DPtr actP = GetLISTNode( e, theStruct, targetIx); // ?? theStruct? if(trace_me) std::cout << " ?? theStruct?" ; DStructGDL* actPStruct = GetLISTStruct( e, actP); actP = (*static_cast(actPStruct->GetTag( pDataTag, 0)))[0]; BaseGDL* listitem = e->Interpreter()->GetHeap( actP); allIxGuard.Release(); if( listitem == 0) return NullGDL::GetSingleInstance(); if(trace_me) std::cout << " itemdim: " << listitem->Dim(); return listitem->Dup(); } if(trace_me) std::cout << " newObj "; DStructDesc* listDesc= structDesc::LIST; DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct BaseGDL* newObj = new DObjGDL( objID); // the list object Guard newObjGuard( newObj); DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; for( SizeT i=0; isize(); ++i) { DLong actIx = allIx->operator[](i); if( actIx == (listSize-1)) actIx = -1; DPtr pActNode = GetLISTNode( e, theStruct, actIx);// theStruct from theref (islist !!) DStructGDL* actNode = GetLISTStruct( e, pActNode); DPtr Ptr = (*static_cast(actNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( Ptr); if( data != 0 && data != NullGDL::GetSingleInstance()) data = data->Dup(); DPtr dID = e->Interpreter()->NewHeap(1,data); cStruct = new DStructGDL( containerDesc, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; } (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = allIx->size(); // At this point we have created and populated listStruct as a subset of self. if(trace_me) std::cout << allIx->size() << std::endl; allIxGuard.Release(); newObjGuard.Release(); return newObj; } void list_leftinsertion( EnvUDT* e, BaseGDL* theref, int iprm ) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() static unsigned isRangeIx = 3; static unsigned prmbeg = isRangeIx+1; SizeT nParam = e->NParam(1); // number of parameters actually given // handle DOT access bool dotAccess = false; SizeT listSize = 0; BaseGDL** objRef = &e->GetKW(1); if( *objRef == NULL || *objRef == NullGDL::GetSingleInstance()){ if( !e->GlobalKW(1)) ThrowFromInternalUDSub( e, "Parameter 1 (OBJREF) is undefined."); dotAccess = true; } BaseGDL* rValue = e->GetKW(2); if( rValue == NULL) rValue = NullGDL::GetSingleInstance(); DLongGDL* isRange = static_cast( e->GetKW(isRangeIx)); SizeT nIsRange = isRange->N_Elements(); if(nIsRange == 0) { nIsRange = nParam - prmbeg; for (int i=0; i < nIsRange; i++) (*isRange)[i] = 0; if(trace_me) std::cout << " nIsRange was 0!" ; } DStructGDL* theStruct; bool islist = false; bool ishash = false; // although normally, ishash case is already handled. bool isstruct = false; DType theType = theref->Type(); if(theType == GDL_OBJ && theref->Rank() == 0) { theStruct = GetOBJ( theref, e); DStructDesc* desc = theStruct->Desc(); islist = desc->IsParent("LIST"); ishash = desc->IsParent("HASH"); // isstruct = !(islist or ishash); } // else if( theType == GDL_STRUCT and theref->N_Elements() == 1) { else if( theType == GDL_STRUCT) { // theStruct = static_cast( theref); isstruct = true; } if(islist) listSize = (*static_cast(theStruct->GetTag( nListTag, 0)))[0]; ArrayIndexVectorT ixList; // IxExprListT exprList; try { for( int p=iprm; pGetKW( p + prmbeg ); // implicit SELF, ISRANGE, par1..par8 if( parX == 0) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( p + prmbeg ))); DLong isRangeX = (*isRange)[p]; if( isRangeX != 0 && isRangeX != 1) ThrowFromInternalUDSub( e, "Value of parameter 1 (ISRANGE["+i2s(p)+"]) is out of allowed range."); if(trace_me) std::printf(" p:%d isRangeX = %ld", p, isRangeX ); if( isRangeX == 1) { if( parX->N_Elements() != 3) ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW( p + prmbeg ))); MAKE_LONGGDL(parX, parXLong) if(trace_me) std::printf(" (isRangeX =1) (*parXLong)[0-2]: %d %d %d \n", (*parXLong)[0], (*parXLong)[1], (*parXLong)[2]); ixList.push_back(new CArrayIndexRangeS( (*parXLong)[0], (*parXLong)[1], (*parXLong)[2])); } else { if(trace_me) help_item(std::cout, parX, " parX", false); if( parX->Rank() == 0) ixList.push_back( new CArrayIndexScalar( parX->Dup())); else ixList.push_back( new CArrayIndexIndexed( parX->Dup())); } } // for } catch( GDLException& ex) { ixList.Destruct(); // ixList is not valid afterwards, but as we throw this is ok throw ex; } ArrayIndexListT* aL; MakeArrayIndex( &ixList, &aL, NULL); // important to get the non-NoAssoc ArrayIndexListT // because only they clean up ixList on destruction Guard< ArrayIndexListT> aLGuard( aL); if(!islist) { if(trace_me) std::cout << " ixList: " << ixList.size() << " dim:" << aL->GetDim() << std::endl; list_insertion( theref , rValue, aL); return; } SpDLong t = SpDLong( dimension(listSize)); aL->SetVariable( &t); AllIxBaseT* allIx = aL->BuildIx(); SizeT allIxSize = allIx->size(); if(trace_me) std::cout << " listSize:" << listSize << " allIxSize = " << allIxSize; if( dotAccess) // -> objRef is NULL (or !NULL) { if(trace_me) std::cout << " dotAccess..."; if( rValue != NullGDL::GetSingleInstance()) ThrowFromInternalUDSub( e, "For struct access (OBJREF is !NULL), RVALUE must be !NULL as well."); if( allIxSize != 1) ThrowFromInternalUDSub( e, "Only single value struct access is allowed."); SizeT actIx = allIx->operator[](0); DPtr pActNode = GetLISTNode( e, theStruct, actIx); DStructGDL* actNode = GetLISTStruct( e, pActNode); *objRef = actNode->GetTag( pDataTag, 0)->Dup(); return; } bool rValislist = false; DStructGDL* rValStruct = NULL; SizeT rValueSize= rValue->Size(); if( rValue->Type() != GDL_OBJ ) { if (rValueSize <= 0) // should never occur; ThrowFromInternalUDSub( e, " right-hand value (not GDL_OBJ) is ill-formed "); } else if( rValue->Rank() == 0) { rValStruct = GetOBJ( rValue, e); DStructDesc* desc = rValStruct->Desc(); rValislist = desc->IsParent("LIST"); } DPtr rValNode; if(rValislist) { rValueSize= (*static_cast(rValStruct->GetTag( nListTag, 0)))[0]; rValNode = GetLISTNode( e, rValStruct, 0); } if(trace_me) std::cout << " rValueSize: " << rValueSize << std::endl; if( rValueSize != allIxSize && (rValueSize > 1)) ThrowFromInternalUDSub( e, "Incorrect number of elements for Values ("+ i2s(allIxSize)+" NE "+i2s(rValueSize)+")."); if( rValueSize <= 1 || allIxSize == 1 ) { // if list has size of one, it will get extracted before insertion. if(rValislist && (rValueSize == 1)) rValue = GetNodeData(rValNode); for( SizeT i=0; ioperator[](i); DPtr pActNode = GetLISTNode( e, theStruct, actIx); DStructGDL* actNode = GetLISTStruct( e, pActNode); DPtr Ptr = (*static_cast(actNode->GetTag( pDataTag, 0)))[0]; BaseGDL::interpreter->GetHeap( Ptr) = rValue->Dup(); } } else { for( SizeT i=0; ioperator[](i); DPtr pActNode = GetLISTNode( e, theStruct, actIx); DStructGDL* actNode = GetLISTStruct( e, pActNode); DPtr Ptr = (*static_cast(actNode->GetTag( pDataTag, 0)))[0]; if( rValislist) BaseGDL::interpreter->GetHeap( Ptr) = GetNodeData(rValNode)->Dup(); else BaseGDL::interpreter->GetHeap( Ptr) = rValue->NewIx( i); } } return; } void LIST___OverloadBracketsLeftSide( EnvUDT* e) { // SELF //->AddPar("OBJREF")->AddPar("RVALUE")->AddPar("ISRANGE"); //->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); //->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() GDL_HASH_STRUCT() GDL_HASHTABLEENTRY() static unsigned isRangeIx = 3; static unsigned prmbeg = isRangeIx+1; SizeT nParam = e->NParam(1); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined std::string trcn = trace_me? "\n;" :";"; if( nParam < 5) // consider implicit SELF ThrowFromInternalUDSub( e, "Four parameters are needed: OBJREF, RVALUE, ISRANGE, SUB1."); // handle DOT access bool dotAccess = false; BaseGDL** objRef = &e->GetKW(1); if( *objRef == NULL || *objRef == NullGDL::GetSingleInstance()) { if( !e->GlobalKW(1)) ThrowFromInternalUDSub( e, "Parameter 1 (OBJREF) is undefined."); dotAccess = true; } BaseGDL* rValue = e->GetKW(2); if( rValue == NULL) rValue = NullGDL::GetSingleInstance(); // default behavior: Exact like scalar indexing DLongGDL* isRange = static_cast( e->GetKW(isRangeIx)); SizeT nIsRange = isRange->N_Elements(); if(nIsRange == 0) { nIsRange = nParam - prmbeg; for (int i=0; i < nIsRange; i++) (*isRange)[i] = 0; if(trace_me) std::cout << " nIsRange was 0!" ; } // isRange is a series of 0 or 1 indicating if a range is present. // more comments in list__]/ if(trace_me) { std::cout << ",nIsRange " << nIsRange << ",nParam " << nParam << " ,isRange:"; for (int i=0; i < nIsRange; i++) std::cout << " "<<(*isRange)[i]; std::cout << std::endl; } // Generalize from self to theStruct BaseGDL* theref = e->GetKW( 0); DStructGDL* self = GetOBJ( theref , e); DStructGDL* theStruct = self; int iprm = 0; SizeT listSize = (*static_cast(self->GetTag( nListTag, 0)))[0]; bool islist=true; bool ishash = false; bool isstruct = false; while( (*isRange)[iprm] == 0) { // && (iprm+3 < nParam) BaseGDL* XX = e->GetKW( iprm + prmbeg); if( XX->Rank() != 0 ) break; // must be a scalar if( islist) { MAKE_LONGGDL( XX, XXLong) DLong Ixref = (*XXLong)[0]; listSize = (*static_cast(theStruct->GetTag( nListTag, 0)))[0]; if(Ixref >= listSize) // this is certainly common. ThrowFromInternalUDSub( e, "direct access index is too high" + i2s(Ixref) + " >= nList:"+i2s(listSize)); DStructGDL* Node = GetLISTStruct( e, GetLISTNode( e, theStruct, Ixref)); DPtr Ptr = (*static_cast( Node->GetTag( pDataTag, 0)))[0]; if(trace_me) std::cout << " islist iprm="< or list[ix,iy] = if(trace_me) std::cout<<" - immediate Dup()"<GetHeap( Ptr) = rValue->Dup(); return; } theref = BaseGDL::interpreter->GetHeap( Ptr); if( theref == 0) ThrowFromInternalUDSub( e, " No data in list at index "+i2s(Ixref)); } else if( ishash ) { DPtr Ptr = (*static_cast( theStruct->GetTag( pTableTag, 0) ))[0]; DStructGDL* hashTable = static_cast( BaseGDL::interpreter->GetHeap( Ptr)); if(trace_me) std::cout<< " hash key:" << XX; bool isfoldcase = Hashisfoldcase( theStruct); DLong hashIndex = HashIndex( hashTable , XX, isfoldcase); if(trace_me) std::cout << " hashindex"<= 0) { DPtr pValue = (*static_cast( hashTable->GetTag( pValueTag, hashIndex) ))[0]; if( iprm+prmbeg+1 == nParam) { if(trace_me) std::cout<<" - immediate Dup()"<GetHeap( pValue) = rValue->Dup(); return; } else theref = BaseGDL::interpreter->GetHeap( pValue); } else { // hashIndex >= 0 if( iprm+prmbeg != nParam) { if(trace_me) std::cout<<" - insert rVal->Dup()"<StealLocalKW( iprm + prmbeg); if( !stolen) XX = XX->Dup(); InsertIntoHashTable( theStruct, hashTable, XX, rValue->Dup()); return; } else ThrowFromInternalUDSub( e, " hash key not found "); } } else if( isstruct ) { // use XX to access struct. GDL extension, IDL doesn't do this. // should instead be utilized as index into the structure array. int ptagindex = 0; if(XX->Type() != GDL_STRING) { if(trace_me) std::cout << " struct[XX!=STRING] ..."; list_leftinsertion( e, theref, iprm); return; } else { DString tag = (*static_cast( XX))[0]; StrUpCaseInplace(tag); ptagindex = theStruct->Desc()->TagIndex(tag); } if(ptagindex < 0) ThrowFromInternalUDSub( e, " struct tag not found "); //;lt0[5,'background',0]=-1 works for scalar struct. // if(theref->N_Elements() == 1) // theref = theStruct->Get( ptagindex); // else ThrowFromInternalUDSub( e, " struct tags inaccessible"); } else {break;} DType theType = theref->Type(); // Enhance (?) it by allowing pointers to lists to represent lists. // in order to turn this off, a ptr scalar must go in as a ptrarr[1]; // This is probably not IDL behavior. if( theType == GDL_PTR && theref->Rank() == 0) { theref = BaseGDL::interpreter->GetHeap( (*static_cast( theref))[0] ); theType = theref->Type(); // this is probably so odd itshould be advertised when it happens: std::cout<<" **p= "<Dup(); if( iprm + prmbeg == nParam) break;//( no prms left) if(trace_me) help_item(std::cout, theref, trcn+"theref ",false); islist = false; ishash = false; isstruct = false; if(theType == GDL_OBJ && theref->Rank() == 0) { theStruct = GetOBJ( theref, e); DStructDesc* desc = theStruct->Desc(); islist = desc->IsParent("LIST"); ishash = desc->IsParent("HASH"); // isstruct = !(islist or ishash); } // else if( theType == GDL_STRUCT and theref->N_Elements() == 1) { else if( theType == GDL_STRUCT ) { theStruct = static_cast( theref); isstruct = true; } iprm++; if( gdl_type_lookup::IsConvertableType[theType] ) break; } // while if(trace_me) { std::cout << " LIST_OL[L]: iprm="<< i2s(iprm); //*/ if(theref == NULL || theref == NullGDL::GetSingleInstance() ) std::cout <<" (theref == 0) "<< std::endl; else lib::help_item(std::cout, theref," theref",false);//*/ } if(ishash) { hash_leftinsertion( e, theStruct, iprm); return; } list_leftinsertion( e, theref, iprm); } template< typename DTypeGDL> BaseGDL* LIST__ToArray( EnvUDT* e, dimension& newdim) { // // "resultype" == DtypeGDL::t // GDL_LIST_STRUCT() GDL_CONTAINER_NODE() if(trace_me) std::cout << " ToArray."; static int kwTYPEIx = e->GetKeywordIx("TYPE"); static int kwSELFIx = kwTYPEIx + 1; static int kwMISSINGIx = e->GetKeywordIx("MISSING"); static int kwDIMENSIONIx = e->GetKeywordIx("DIMENSION"); static int kwNO_COPYIx = e->GetKeywordIx("NO_COPY"); static int kwTRANSPOSEIx = e->GetKeywordIx("TRANSPOSE"); DTypeGDL* missingT = NULL; Guard missingTGuard; /* * DIMENSION Set this keyword to the dimension over which to concatenate the arrays contained within the list. * For this keyword to work correctly, each element of the list must have the same number of elements in each dimension except for the dimension given by DIMENSION. For example, assume your list contains three arrays and you wish to concatenate over the second dimension: l = LIST(FLTARR(3,10,5), FLTARR(3,12,5), FLTARR(3,7,5)) result = l.ToArray(DIMENSION=2) help, result IDL prints: RESULT FLOAT = Array[3, 29, 5] Note: If the DIMENSION keyword is specified, the MISSING and TRANSPOSE keywords are ignored. */ DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; DPtr pNext = pTail; BaseGDL* dimensionKW = e->GetKW( kwDIMENSIONIx); BaseGDL* missingKW = (dimensionKW != 0)? 0:e->GetKW( kwMISSINGIx); BaseGDL* transposeKW = (dimensionKW != 0)? 0:e->GetKW( kwTRANSPOSEIx); SizeT dimkw=0; MAKE_LONGGDL(dimensionKW, dimkwLong) if(dimensionKW != 0) dimkw = (*dimkwLong)[0]; SizeT Rank = newdim.Rank(); SizeT Stride = newdim.Stride(Rank-1); if(dimkw > 0) Stride = newdim.Stride(dimkw-1); if(missingKW != 0 && missingKW->Rank() != 0 && (Stride != missingKW->N_Elements()) ) ThrowFromInternalUDSub( e, " 'missing' keyword array does not match elements' structure"); DTypeGDL* result = new DTypeGDL( newdim, BaseGDL::NOZERO); Guard resultGuard( result); bool transposekw = (transposeKW != 0) || (dimensionKW != 0) ; if(trace_me) { std::cout << " newdim stride 0...Rank-1 = " << Rank-1 << ": " ; for (int i=0; i < Rank; i++) std::cout << "["<GetHeap( (*static_cast( Node->GetTag( pDataTag, 0)))[0]); pNext = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; if( data == 0 || data == NullGDL::GetSingleInstance()) { if(missingKW == 0 || missingKW == NullGDL::GetSingleInstance()) continue; if( missingT == 0) { missingT = new DTypeGDL( dimension(Stride) , BaseGDL::NOZERO); missingTGuard.Init( missingT); BaseGDL* fill = missingKW->Convert2( result->Type() ,BaseGDL::COPY); missingT->AssignAt( fill, NULL, 0); } result->InsertAt( Stride*inlist , missingT, NULL); ++inlist; continue; } else { DTypeGDL* src = static_cast(data); DType theType = data->Type(); // if( ( theType == resultType) || !ConvertableType( theType) ) continue; if( data->Type() != DTypeGDL::t ) src = static_cast(data->Convert2( DTypeGDL::t , BaseGDL::COPY)); // inlist will be incremented in CatInsert and gaps, strides are all good. result->CatInsert(src, catrankIx, inlist); } // ( data == NULL) } // for i KeywordSet( kwNO_COPYIx)) LISTCleanup( e, self); // For NO_COPY keyword resultGuard.Release(); if( transposekw) return result; else { // The result is composed (via CatInsert) in transposed form. // If keyword TRANSPOSE not set, need to transpose back. DUInt* perm = new DUInt[Rank]; ArrayGuard perm_guard( perm); perm[0] = Rank - 1; for( SizeT i=1; i< Rank; ++i) perm[i] = i-1; return result->Transpose( perm); } } #if 0 // currently a void, Standard GDLobject help provided in gdlhelp. void list__help( EnvUDT* e) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() static int kwMAXITEMIx = e->GetKeywordIx("MAXITEM"); static int kwSELFIx = kwMAXITEMIx + 1; // trace_me = false; // lib::trace_arg(); SizeT nParam = e->NParam(1); // SELF DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); if(trace_me) std::cout << " list.help():"; } #endif BaseGDL* list__toarray( EnvUDT* e) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() static int kwTYPEIx = e->GetKeywordIx("TYPE"); static int kwSELFIx = kwTYPEIx + 1; static int kwMISSINGIx = e->GetKeywordIx("MISSING"); static int kwDIMENSIONIx = e->GetKeywordIx("DIMENSION"); static int kwNO_COPYIx = e->GetKeywordIx("NO_COPY"); static int kwTRANSPOSEIx = e->GetKeywordIx("TRANSPOSE"); static int kwPROMOTE_TYPEIx = e->GetKeywordIx("PROMOTE_TYPE"); trace_me = false; // lib::trace_arg(); SizeT nParam = e->NParam(1); // SELF DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); if(trace_me) std::cout << " list.toarray():"; // define the standard LIST struct = listDesc: DStructDesc* listDesc = structDesc::LIST; DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList == 0) return NullGDL::GetSingleInstance(); DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; DPtr pNext = pTail; int inlist = 0; BaseGDL* data; do { DStructGDL* Node = GetLISTStruct(e, pNext); DPtr Ptr = (*static_cast( Node->GetTag( pDataTag, 0)))[0]; data = BaseGDL::interpreter->GetHeap( Ptr); pNext = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; } while ( data == NULL and ++inlist != nList ); if( data == NULL ) ThrowFromInternalUDSub( e, " no data in list to make array"); BaseGDL* typeKW = e->GetKW( kwTYPEIx); BaseGDL* promote_typeKW = e->GetKW( kwPROMOTE_TYPEIx); bool promote_type = e->KeywordSet(kwPROMOTE_TYPEIx); BaseGDL* dimensionKW = e->GetKW( kwDIMENSIONIx); BaseGDL* missingKW = (dimensionKW != NULL)? NULL:e->GetKW( kwMISSINGIx); Guard missingKWGuard(missingKW); // value_guard.Reset(value);//e->Guard( value); DType resultType = GDL_UNDEF; if( typeKW == NULL) { if( missingKW != NULL) resultType = missingKW->Type(); else resultType = data->Type(); } else { promote_type = false; if( typeKW->Type() == GDL_STRING) { DString typeStr = StrUpCase( (*static_cast(typeKW))[0]); if( SpDByte().TypeStr() == typeStr) resultType = GDL_BYTE; else if( SpDInt().TypeStr() == typeStr) resultType = GDL_INT; else if( SpDLong().TypeStr() == typeStr) resultType = GDL_LONG; else if( SpDFloat().TypeStr() == typeStr) resultType = GDL_FLOAT; else if( SpDDouble().TypeStr() == typeStr) resultType = GDL_DOUBLE; else if( SpDComplex().TypeStr() == typeStr) resultType = GDL_COMPLEX; else if( SpDString().TypeStr() == typeStr) resultType = GDL_STRING; else if( SpDComplexDbl().TypeStr() == typeStr) resultType = GDL_COMPLEXDBL; else if( SpDUInt().TypeStr() == typeStr) resultType = GDL_UINT; else if( SpDULong().TypeStr() == typeStr) resultType = GDL_ULONG; else if( SpDLong64().TypeStr() == typeStr) resultType = GDL_LONG64; else if( SpDULong64().TypeStr() == typeStr) resultType = GDL_ULONG64; else ThrowFromInternalUDSub( e, "Unknown or unable to convert to type " + typeStr); } else { // MAKE_LONGGDL(typeKW, typeCodeKW) DLongGDL* typeCodeKW; Guard typeCodeGuard; if( typeKW->Type() == GDL_LONG) { typeCodeKW = static_cast(typeKW); } else { try{ typeCodeKW = static_cast(typeKW->Convert2(GDL_LONG,BaseGDL::COPY)); typeCodeGuard.Init(typeCodeKW); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } } // MAKE_LONGGDL(typeKW, typeCodeKW) DLong typeCode = (*typeCodeKW)[0]; if( typeCode < GDL_BYTE || typeCode > GDL_ULONG64) ThrowFromInternalUDSub( e, "Illegal value for TYPE: " + i2s(typeCode)); resultType = static_cast(typeCode); } } if( resultType == GDL_UNDEF) ThrowFromInternalUDSub( e, "Result type is UNDEF. Please report."); DLong dimkw=0; MAKE_LONGGDL(dimensionKW, dimkwLong) if(dimensionKW != NULL) dimkw = (*dimkwLong)[0]; if(dimkw > 8) ThrowFromInternalUDSub( e, " DIMENSION keyword can only go up to 8" ); SizeT nel0 = data->N_Elements(); dimension refdim(data->Dim()); if( dimkw == refdim.Rank() +1) refdim << 1; // one-time deal SizeT Rank0 = refdim.Rank(); SizeT Rank0Ix = RankIx(Rank0); if( dimkw > Rank0) ThrowFromInternalUDSub( e, " DIMENSION keyword exceeds plausible rank of first element" ); SizeT newSize = 0; pNext = pTail; for( SizeT inlist=0; inlistGetHeap( (*static_cast( Node->GetTag( pDataTag, 0)))[0]); pNext = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; if( data == NULL) { if( dimkw > 0 || missingKW == NULL) continue; // will be quietly bypassed. ++newSize; continue; } if(Rank0 != 0) { dimension thedim(data->Dim()); if( thedim.Rank() != Rank0 ) { // kick with one exception if(dimkw == 0 ) ThrowFromInternalUDSub( e, " all elements must be Rank "+i2s( (long) Rank0) ); if( !((dimkw == Rank0) and ( thedim.Rank() == Rank0-1)) ) ThrowFromInternalUDSub( e, " all elements must be Rank "+i2s( (long) Rank0) ); thedim << 1; } for(int i=0; i < Rank0; ++i) { if(trace_me) std::cout << thedim[i]; if( dimkw == (i+1)) continue; if(thedim[i] != refdim[i]) ThrowFromInternalUDSub(e, " dimensions dont agree " +i2s(i+1)+" List item #"+i2s(inlist)+"\n " +i2s(thedim[i]) +" # "+i2s(refdim[i])); } if( dimkw > 0) newSize += thedim[dimkw-1]; else ++newSize; } // 1-d arrays an mix with scalars by defining array[10] = array[1,10] else // (Rank0Ix != 0) { if( (data->N_Elements() != nel0) && (dimkw != 1) ) ThrowFromInternalUDSub(e, " 1-d Sizes don't agree " +i2s(nel0)+" List item #"+i2s(inlist)); else newSize += data->N_Elements(); } // Dimensionality seems ok. Now check for type. DType theType = data->Type(); if( ( theType == resultType) || !ConvertableType( theType) ) continue; if( promote_type ) { if( theType == GDL_STRING) resultType = GDL_STRING; if( NumericType( theType) && (resultType != GDL_STRING)) { if ( theType == GDL_COMPLEXDBL) resultType = GDL_COMPLEXDBL; else if (resultType == GDL_COMPLEXDBL) continue; else if (( theType == GDL_COMPLEX) && (resultType == GDL_DOUBLE) || ( theType == GDL_DOUBLE) && (resultType == GDL_COMPLEX) ) resultType = GDL_COMPLEXDBL; else if (resultType == GDL_COMPLEX ) continue; else if (theType == GDL_DOUBLE ) resultType = GDL_DOUBLE; else if (theType == GDL_COMPLEX ) resultType = GDL_COMPLEX; else if ( ( theType > resultType) && (DTypeOrder[ theType] >= DTypeOrder[ resultType]) ) resultType = theType; } } } dimension newdim = refdim; if( dimkw > 0) { newdim.SetOneDim( dimkw-1, newSize); } else { newdim << newSize; } SizeT catrankIx = (dimkw ==0) ? RankIx(newdim.Rank()) : dimkw-1 ; if(trace_me) std::cout <<" catrankIx, newdim.Rank()"<< catrankIx<( e, newdim); else if( resultType == GDL_INT) return LIST__ToArray( e, newdim); else if( resultType == GDL_LONG) return LIST__ToArray( e, newdim); else if( resultType == GDL_FLOAT) return LIST__ToArray( e, newdim); else if( resultType == GDL_DOUBLE) return LIST__ToArray( e, newdim); else if( resultType == GDL_COMPLEX) return LIST__ToArray( e, newdim); else if( resultType == GDL_STRING) return LIST__ToArray( e, newdim); else if( resultType == GDL_COMPLEXDBL) return LIST__ToArray( e, newdim); else if( resultType == GDL_UINT) return LIST__ToArray( e, newdim); else if( resultType == GDL_ULONG) return LIST__ToArray( e, newdim); else if( resultType == GDL_LONG64) return LIST__ToArray( e, newdim); else if( resultType == GDL_ULONG64) return LIST__ToArray( e, newdim); else if( resultType == GDL_STRUCT) throw GDLException( " unable to extract arrays of GDL_STRUCT"); else throw GDLException( "Unknown or unable to convert to type code: " + i2s(resultType)); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } assert(false); return NULL; } } BaseGDL* list__isempty( EnvUDT* e) { GDL_LIST_STRUCT() static int kwSELFIx = 0; DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if (nList > 0) return new DByteGDL(0); else return new DByteGDL(1); } SizeT LIST_count( DStructGDL* list) {// straight through, no checks static unsigned nListTag = structDesc::LIST->TagIndex( "NLIST"); return (*static_cast( list->GetTag( nListTag, 0)))[0]; } BaseGDL* list__count( EnvUDT* e) { static int kwSELFIx = 0; // no keywords static int kwVALUEIx = 1; // DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); SizeT nParam = e->NParam(1); if( nParam == 1) return new DLongGDL( LIST_count( GetOBJ( e->GetKW( kwSELFIx), e))); // nParam > 1: BaseGDL* r = e->GetKW( kwVALUEIx); DObjGDL* selfObj = static_cast(e->GetKW( kwSELFIx)); DByteGDL* result = static_cast(selfObj->EqOp( r)); Guard newObjGuard( result); DLong nList = 0; for( SizeT i=0; iN_Elements(); ++i) if( (*result)[i] != 0) ++nList; return new DLongGDL( nList); } void list__move( EnvUDT* e) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() SizeT nParam = e->NParam(3); // minimum SELF, SOURCE, DESTINATION static int kwSELFIx = 0; // no keywords DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; trace_me = false; // trace_arg(); DLong index1, index2; // (allowing negative index references) e->AssureLongScalarPar( 1, index1); if(index1 < 0) index1 += nList; e->AssureLongScalarPar( 2, index2); if(index2 < 0) index2 += nList; if( index1 >= nList or index2 >= nList or index1 < 0 or index2 < 0) ThrowFromInternalUDSub( e," index out of range - listsize=: " +i2s(nList)+" indeces: "+i2s(index1)+","+i2s(index2)); DStructDesc* selfDesc= self->Desc(); DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; assert( selfDesc != NULL && selfDesc->NTags() > 0); assert( containerDesc != NULL && containerDesc->NTags() > 0); DPtrGDL* Tail = static_cast( self->GetTag( pTailTag, 0)); DPtrGDL* Head = static_cast( self->GetTag( pHeadTag, 0)); DPtr pTail = (*Tail)[0]; DPtr pHead = (*Head)[0]; if(trace_me or ((index1 ==0) and (index2==0))) { DPtr p0 = (*Tail)[0]; std::printf(" list: TAIL=%llu", p0); for( int i=0; i < nList ; i++) { DStructGDL* Node=GetLISTStruct(NULL, p0); p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; DPtr pdata = (*static_cast( Node->GetTag( pDataTag, 0)))[0]; std::printf("->%llu<%llu>:", p0, pdata);} std::printf("->HEAD= %llu (list.move:%d,%d) \n", pHead, index1, index2); } if(index1 == index2) return; // trivial case DPtr ptrg, predptr; DPtr p0 = pTail; DStructGDL* Node = GetLISTStruct(NULL, p0); DStructGDL* predNode = Node; if(index2 < index1) for( int i=0; i < index1 ; i++) { if(i == index2-1) ptrg = p0; predptr = p0; p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; predNode = Node; Node = GetLISTStruct(NULL, p0); } else for( int i=0; i < index1 ; i++) { predptr = p0; p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; predNode = Node; Node = GetLISTStruct(NULL, p0); } DPtr psrc = p0; DPtrGDL* ptrnxt = static_cast( Node->GetTag( pNextTag, 0)); if(index1 == 0) (*Tail)[0] = (*ptrnxt)[0]; else if( index1 == nList-1) { (*Head)[0] = predptr; (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = 0; } else (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = (*ptrnxt)[0]; (*ptrnxt)[0] = 0; if( index2 == 0) { (*Tail)[0] = psrc; (*ptrnxt)[0] = pTail; } else if( index2 == nList-1) { Node = GetLISTStruct(NULL, (*Head)[0]); (*static_cast( Node->GetTag( pNextTag, 0)))[0] = psrc; (*Head)[0] = psrc; } else { if( index1 == 0) p0 =(*Tail)[0]; else if(index2 > index1) p0 = (*static_cast( predNode->GetTag( pNextTag, 0)))[0]; else p0 = ptrg; for(int i = index1; i < index2 - 1 ; i++) { Node = GetLISTStruct(NULL, p0); p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; } Node = GetLISTStruct(NULL, p0); ptrnxt = static_cast( Node->GetTag( pNextTag, 0)); p0 = (*ptrnxt)[0]; (*ptrnxt)[0] = psrc; Node = GetLISTStruct(NULL, psrc); (*static_cast( Node->GetTag( pNextTag, 0)))[0] = p0; } if(trace_me) { p0 = (*Tail)[0]; std::printf(" from list.move : TAIL=%llu" , p0); for( int i=0; i < nList ; i++) { DStructGDL* Node=GetLISTStruct(NULL, p0); p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; std::printf("->%llu", p0); } p0 = (*Head)[0]; std::printf(" : HEAD= %llu \n", p0); } return; // victorious } void list__swap( EnvUDT* e) { GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // trace_me = false; // lib::trace_arg(); if(trace_me) std::printf(" list__swap "); SizeT nParam = e->NParam(3); // minimum SELF, INDEX1, INDEX2 static int kwSELFIx = 0; // no keywords DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; DLong index1, index2; e->AssureLongScalarPar( 1, index1); e->AssureLongScalarPar( 2, index2); if(index1 < 0 or index1 >= nList) ThrowFromInternalUDSub( e," index1 out of range: "+i2s(index1)); if(index2 < 0 or index2 >= nList) ThrowFromInternalUDSub( e," index2 out of range: "+i2s(index2)); if(index1 < index2) { DLong swap = index1; index1 = index2; index2 = swap; } else if(index1 == index2) return; // define the standard LIST struct = listDesc: DStructDesc* listDesc = structDesc::LIST; DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; DPtrGDL* Tail = static_cast( self->GetTag( pTailTag, 0)); DPtrGDL* Head = static_cast( self->GetTag( pHeadTag, 0)); DStructGDL* Node = NULL; DStructGDL* predNsrc = Node; DStructGDL* Ntrg; DStructGDL* predNtrg; DPtr pNext, ptrg, psrc; //--- . .... index2 ,,,,, ... index1 // tail[0]> ptrg ..... predsrc->pNext .. psrc // predtrg->pNext DPtr p0 = (*Tail)[0]; Node = GetLISTStruct(NULL, p0); for( int i=0; i < index1 ; i++) { if(i == index2) { ptrg = p0; predNtrg=predNsrc; Ntrg=Node;} p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; predNsrc = Node; Node = GetLISTStruct(NULL, p0); } psrc=p0; DStructGDL* Nsrc = Node; if(trace_me) { std::printf(" ptrg %llu -> %llu , psrc %llu-> %llu ", ptrg,(*static_cast( Ntrg->GetTag( pNextTag, 0)))[0], psrc,(*static_cast( Nsrc->GetTag( pNextTag, 0)))[0]); std::printf(" : Tail=%llu Head=%llu list.swap:%d,%d \n", (*Tail)[0], (*Head)[0], index1, index2); } // swap contents of pNextTag DPtr swap = (*static_cast( Ntrg->GetTag( pNextTag, 0)))[0]; if(swap == psrc) { swap = ptrg; // correction for swapping adjacent nodes. predNsrc = Nsrc; } (*static_cast( Ntrg->GetTag( pNextTag, 0)))[0] = (*static_cast( Nsrc->GetTag( pNextTag, 0)))[0]; (*static_cast( Nsrc->GetTag( pNextTag, 0)))[0] = swap; if( index1 == nList-1) { (*Head)[0] = ptrg; (*static_cast( Ntrg->GetTag( pNextTag, 0)))[0] = 0; } (*static_cast( predNsrc->GetTag( pNextTag, 0)))[0] = ptrg; if(index2 == 0) (*Tail)[0] = psrc; else { (*static_cast( predNtrg->GetTag( pNextTag, 0)))[0] = psrc; } //--- . .... index2 ,,,,, ... index1 // tail[0]> psrc ..... predsrc->pNext .. ptrg return; } BaseGDL* list__where( EnvUDT* e) { static int kwNCOMPLEMENTIx = e->GetKeywordIx("NCOMPLEMENT"); static int kwCOUNTIx = e->GetKeywordIx("COUNT"); static int kwCOMPLEMENTIx = e->GetKeywordIx("COMPLEMENT"); static int kwSELFIx = 3; static int kwVALUEIx = kwSELFIx + 1; SizeT nParam = e->NParam(2); // SELF, VALUE DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); // checks BaseGDL* r = e->GetKW( kwVALUEIx); DObjGDL* selfObj = static_cast(e->GetKW( kwSELFIx)); BaseGDL* result = selfObj->EqOp( r); Guard resultGuard( result); DLong nEl = result->N_Elements(); SizeT count; DLong* ret=NULL; DLong* comp_ret=NULL; result->Where(ret, count, e->KeywordPresent(kwCOMPLEMENTIx), comp_ret); SizeT nCount = nEl - count; if (e->KeywordPresent(kwCOMPLEMENTIx)) // COMPLEMENT { if (nCount == 0) { e->SetKW(kwCOMPLEMENTIx, NullGDL::GetSingleInstance()); } else { DLongGDL* cRet=new DLongGDL(dimension(nCount),BaseGDL::NOALLOC); cRet->SetBuffer((void*)comp_ret); cRet->SetBufferSize(nCount); cRet->SetDim(dimension(nCount)); e->SetKW(kwCOMPLEMENTIx, cRet); } } if (e->KeywordPresent(kwNCOMPLEMENTIx)) // NCOMPLEMENT { e->SetKW(kwCOMPLEMENTIx, new DLongGDL(nCount)); } if( e->KeywordPresent( kwCOUNTIx)) { // COUNT e->SetKW(kwCOUNTIx, new DLongGDL(count)); } // The system variable !ERR is set to the number of nonzero elements for compatibility with old versions of IDL DVar *err = FindInVarList(sysVarList, "ERR"); (static_cast (err->Data()))[0] = count; if (count == 0) { return NullGDL::GetSingleInstance(); } DLongGDL* res=new DLongGDL(dimension(count),BaseGDL::NOALLOC); res->SetBuffer((void*)ret); res->SetBufferSize(count); res->SetDim(dimension(count)); return res; } BaseGDL* list__remove( EnvUDT* e, bool asFunction); BaseGDL* list__remove_fun( EnvUDT* e) { return list__remove( e, true); } void list__remove_pro( EnvUDT* e) { list__remove( e, false); } BaseGDL* list__remove( EnvUDT* e, bool asFunction) { // see overload.cpp; ALL is only keyword. static int kwALLIx = 0; static int kwSELFIx = 1; static int kwINDEXIx = 2; bool kwALL = false; if (e->KeywordSet(kwALLIx)){ kwALL = true;} SizeT nParam = e->NParam(1); // minimum SELF DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); // define the standard LIST struct = listDesc: DStructDesc* listDesc = structDesc::LIST; // DStructDesc* containerDesc= structDesc::GDL_CONTAINER_NODE; GDL_LIST_STRUCT() GDL_CONTAINER_NODE() if( kwALL) { if( asFunction) { DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct, inits ref count BaseGDL* newObj = new DObjGDL( objID); // the list object Guard newObjGuard( newObj); (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; (*static_cast( self->GetTag( pHeadTag, 0)))[0] = 0; (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = (*static_cast( self->GetTag( pTailTag, 0)))[0]; (*static_cast( self->GetTag( pTailTag, 0)))[0] = 0; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = (*static_cast( self->GetTag( nListTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = 0; newObjGuard.Release(); return newObj; } else { LISTCleanup( e, self); return NULL; } } DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList == 0) ThrowFromInternalUDSub( e, "LIST is empty."); BaseGDL* index = ( nParam >= 2) ? e->GetKW(kwINDEXIx) : NULL; DLongGDL* indexLong = NULL; Guard indexLongGuard; if( index != NULL) { if( index->Type() != GDL_LONG) { indexLong = static_cast(index->Convert2(GDL_LONG,BaseGDL::COPY)); indexLongGuard.Init( indexLong); } else indexLong = static_cast(index); } // using macro to make BaseGDL* indexLong doesn't work when we need indexLongGuard.Get() DLong removePos = -1; if( indexLong != NULL) { if( indexLong->N_Elements() == 1) { removePos = (*indexLong)[0]; if( removePos < 0) removePos += nList; if( removePos < 0) ThrowFromInternalUDSub( e, "Index too small."); if( removePos >= nList) ThrowFromInternalUDSub( e, "Index out of range."); } } if( indexLong == NULL || removePos == nList-1) // remove head { DPtr pHead = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; DStructGDL* headNode = GetLISTStruct(e, pHead); DPtr pData = (*static_cast( headNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( pData); if( nList == 1) { (*static_cast( self->GetTag( pHeadTag, 0)))[0] = 0; (*static_cast( self->GetTag( pTailTag, 0)))[0] = 0; (*static_cast( self->GetTag( nListTag, 0)))[0] = 0; } else if( nList == 2) { (*static_cast( self->GetTag( pHeadTag, 0)))[0] = (*static_cast( self->GetTag( pTailTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = 1; } else // nList > 2 { DPtr pPredHead = GetLISTNode( e, self, nList-2); (*static_cast( self->GetTag( pHeadTag, 0)))[0] = pPredHead; (*static_cast( self->GetTag( nListTag, 0)))[0] = nList - 1; } // e->Interpreter()->HeapErase( pData); // no delete // e->Interpreter()->FreeHeap( pHead); // delete FreeLISTNode( e, pHead, !asFunction); if( data == NULL) return NullGDL::GetSingleInstance(); return data; } if( removePos == 0) // remove tail { // implicit: nList > 1 DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; DStructGDL* tailNode = GetLISTStruct(e, pTail); DPtr pData = (*static_cast( tailNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( pData); if( nList == 2) { (*static_cast( self->GetTag( pTailTag, 0)))[0] = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = 1; } else // nList > 2 { (*static_cast( self->GetTag( pTailTag, 0)))[0] = (*static_cast( tailNode->GetTag( pNextTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = nList - 1; } // e->Interpreter()->HeapErase( pData); // no delete // e->Interpreter()->FreeHeap( pTail); // delete FreeLISTNode( e, pTail, !asFunction); if( data == NULL) return NullGDL::GetSingleInstance(); return data; } if( removePos != -1) // single element { // implicit: nList > 2 DPtr pPredNode = GetLISTNode( e, self, removePos-1); DStructGDL* predNode = GetLISTStruct( e, pPredNode); DPtr pRemoveNode = (*static_cast( predNode->GetTag( pNextTag, 0)))[0]; DStructGDL* removeNode = GetLISTStruct( e, pRemoveNode); DPtr pData = (*static_cast( removeNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( pData); (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = (*static_cast( removeNode->GetTag( pNextTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = nList - 1; // e->Interpreter()->HeapErase( pData); // no delete // e->Interpreter()->FreeHeap( pRemoveNode); // no delete FreeLISTNode( e, pRemoveNode, !asFunction); if( data == NULL) return NullGDL::GetSingleInstance(); return data; } // remove all indexed elements // 1st build return LIST BaseGDL* newObj = NULL; // the list object Guard newObjGuard; SizeT indexN_Elements = indexLong->N_Elements(); if( asFunction) { DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct newObj = new DObjGDL( objID); // the list object newObjGuard.Init( newObj); // we need ref counting here as the LIST (newObj) is a regular return value // e->Interpreter()->IncRefObj( objID); DStructGDL* cStructLast = NULL; DStructGDL* cStruct = NULL; DPtr cID = 0; for( SizeT i=0; i= nList) ThrowFromInternalUDSub( e, "Index out of range."); DPtr pActNode = GetLISTNode( e, self, actIx); DStructGDL* actNode = GetLISTStruct( e, pActNode); DPtr pData = (*static_cast(actNode->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeap( pData); if( data != NULL) data = data->Dup(); DPtr dID = e->Interpreter()->NewHeap(1,data); cStruct = new DStructGDL( structDesc::GDL_CONTAINER_NODE, dimension()); cID = e->Interpreter()->NewHeap(1,cStruct); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = dID; if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; } (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = indexN_Elements; } // if( asFunction) // 2nd: remove the indexed elements if( indexLongGuard.Get() == NULL) { // we need to sort the index indexLong = indexLong->Dup(); indexLongGuard.Init(indexLong); } DLong *hh = static_cast(indexLong->DataAddr()); // massage the indeces so that < 0 are back in range for( DLong i=0; i < indexN_Elements; ++i) if( hh[i] < 0) hh[i] += nList; // This needed for the tail->head removall. DLong* h1 = new DLong[ indexN_Elements/2]; DLong* h2 = new DLong[ (indexN_Elements+1)/2]; // call the sort routine MergeSortDescending( hh, h1, h2, indexN_Elements); delete[] h1; delete[] h2; // See notes on doomed code block since 2018-May DPtrGDL* Tail = static_cast( self->GetTag( pTailTag, 0)); DPtrGDL* Head = static_cast( self->GetTag( pHeadTag, 0)); if(trace_me) { DPtr p0 = (*Tail)[0]; std::printf(" tracing list.remove : TAIL=%llu", p0); for( int i=0; i < nList ; i++) { DStructGDL* Node=GetLISTStruct(NULL, p0); p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; std::printf("->%llu", p0);} std::printf(" : HEAD= %llu (incoming) \n", (*Head)[0]); } if(trace_me) { std::cout << "list.Remove() "+i2s(indexN_Elements)+" indeces "; for( DLong i=0; i < indexN_Elements; ++i) std::cout << hh[ indexN_Elements - i - 1] <<": "; std::cout << std::endl; } SizeT nListStart = nList; DLong prvfetch = -1; // repeated indeces need to be skipped!! #if 1 // alternative one-way removal. DPtr pTail = (*Tail)[0]; DPtr predptr; DPtr p0 = pTail; DLong inlist = 0; DStructGDL* Node; DStructGDL* predNode; for( DLong i=0; i < indexN_Elements; ++i) { // get the next index targetted for removal. DLong removeIndex = hh[ indexN_Elements - i - 1]; if( removeIndex < 0) ThrowFromInternalUDSub( e, "Index too small:"+i2s(removeIndex) ); if( removeIndex >= nListStart) ThrowFromInternalUDSub( e, "Index out of range: "+i2s(removeIndex) ); if( removeIndex == prvfetch) continue; // (ignore repeats) // if(trace_me) std::cout << i2s(removeIndex) << " p0="<= 1); Node = GetLISTStruct(NULL, p0); for( DLong j=0; j < removeIndex - prvfetch - 1; j++) { inlist++; predptr = p0; // if(trace_me) std::cout <<" ^" << p0; p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; predNode = Node; Node = GetLISTStruct(NULL, p0); } DPtrGDL* ptrnxt = static_cast( Node->GetTag( pNextTag, 0)); if(inlist == 0) { (*Tail)[0] = (*ptrnxt)[0]; } else if( inlist == nList -1 ) { (*Head)[0] = predptr; (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = 0; } else (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = (*ptrnxt)[0]; DPtr Ptr = (*static_cast( Node->GetTag( pDataTag, 0)))[0]; BaseGDL::interpreter->FreeHeap( Ptr); /* if(trace_me) { std::printf(" pdata=%llu", Ptr); std::printf(" pTail=%llu",(*Tail)[0]); std::printf(" ptrnxt=%llu", (*ptrnxt)[0]);} */ DPtr pNext = (*ptrnxt)[0]; // delete p0 from heap (*static_cast( Node->GetTag( pNextTag, 0)))[0] = 0; BaseGDL::interpreter->FreeHeap( p0); p0 = pNext; // & get ready for next item. (*static_cast( self->GetTag( nListTag, 0)))[0] = --nList; prvfetch = removeIndex; } #elif 0 // doomed code block: was bookended by #elif 0 ... #endif // old way (works,but traverses list for each deletion.) for( DLong i=0; i < indexN_Elements; ++i) { DLong removeIndex = hh[ i]; if( removeIndex < 0) removeIndex += nListStart; if( removeIndex < 0) ThrowFromInternalUDSub( e, "Index too small."); if( removeIndex >= nList) ThrowFromInternalUDSub( e, "Index out of range."); if( removeIndex == prvfetch) continue; if( removeIndex == nList-1) // remove head { // std::cout << " Removing index: nList-1" << std::endl; DPtr pHead = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; DStructGDL* headNode = GetLISTStruct(e, pHead); if( nList == 1) { (*static_cast( self->GetTag( pHeadTag, 0)))[0] = 0; (*static_cast( self->GetTag( pTailTag, 0)))[0] = 0; (*static_cast( self->GetTag( nListTag, 0)))[0] = 0; } else if( nList == 2) { (*static_cast( self->GetTag( pHeadTag, 0)))[0] = (*static_cast( self->GetTag( pTailTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = 1; } else // nList > 2 { DPtr pPredHead = GetLISTNode( e, self, nList-2); (*static_cast( self->GetTag( pHeadTag, 0)))[0] = pPredHead; (*static_cast( self->GetTag( nListTag, 0)))[0] = nList - 1; } // prevent (ref-count) cleanup of next node (*static_cast( headNode->GetTag( pNextTag, 0)))[0] = 0; // e->Interpreter()->FreeHeap( pData); // e->Interpreter()->FreeHeap( pHead); FreeLISTNode( e, pHead, true); } else if( removeIndex == 0) // remove tail { // implicit: nList > 1 DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; DStructGDL* tailNode = GetLISTStruct(e, pTail); if( nList == 2) { (*static_cast( self->GetTag( pTailTag, 0)))[0] = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = 1; } else // nList > 2 { (*static_cast( self->GetTag( pTailTag, 0)))[0] = (*static_cast( tailNode->GetTag( pNextTag, 0)))[0]; (*static_cast( self->GetTag( nListTag, 0)))[0] = nList - 1; } // prevent (ref-count) cleanup of next node (*static_cast( tailNode->GetTag( pNextTag, 0)))[0] = 0; // e->Interpreter()->FreeHeap( pData); // e->Interpreter()->FreeHeap( pTail); FreeLISTNode( e, pTail, true); } else { // implicit: nList > 2 DPtr pPredNode = GetLISTNode( e, self, removeIndex-1); DStructGDL* predNode = GetLISTStruct( e, pPredNode); DPtr pRemoveNode = (*static_cast( predNode->GetTag( pNextTag, 0)))[0]; DStructGDL* removeNode = GetLISTStruct( e, pRemoveNode); (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = (*static_cast( removeNode->GetTag( pNextTag, 0)))[0]; // prevent (ref-count) cleanup of next node (*static_cast( removeNode->GetTag( pNextTag, 0)))[0] = 0; // e->Interpreter()->FreeHeap( pData); // e->Interpreter()->FreeHeap( pRemoveNode); FreeLISTNode( e, pRemoveNode, true); } assert( nList >= 1); // keep LIST consistent (*static_cast( self->GetTag( nListTag, 0)))[0] = --nList; prvfetch = removeIndex; } // end of doomed code block. #endif if(trace_me) { std::cout<< std::endl; DPtrGDL* Tail = static_cast( self->GetTag( pTailTag, 0)); DPtrGDL* Head = static_cast( self->GetTag( pHeadTag, 0)); DPtr p0 = (*Tail)[0]; std::printf(" tracing: TAIL=%llu", p0); for( int i=0; i < nList-1 ; i++) { DStructGDL* Node=GetLISTStruct(NULL, p0); p0 = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; std::printf("->%llu", p0);} std::printf(" : HEAD= %llu (outgoing) \n", (*Head)[0]); } newObjGuard.Release(); return newObj; } void list__reverse( EnvUDT* e) { // no args no kwords (but SELF parameter) SizeT nParam = e->NParam(1); // SELF DStructGDL* self = GetOBJ( e->GetKW( 0), e); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList <= 1) // no change for empty or one-element return; DPtr actPrevP = 0; DPtr actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; for( SizeT elIx = 0; elIx < nList; ++elIx) { DStructGDL* actPStruct = GetLISTStruct(e, actP); DPtr actPNext = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0] = actPrevP; actPrevP = actP; actP = actPNext; } // swap head and tail pointer DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; (*static_cast( self->GetTag( pTailTag, 0)))[0] = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; (*static_cast( self->GetTag( pHeadTag, 0)))[0] = pTail; } BaseGDL* list__init( EnvUDT* e) { // if( trace_me) std::cout << " List Init!" << std::endl; return new DByteGDL(1); // if we reach here, defaul is to return 'TRUE' } // list__get and list__add are shared by the LIST oand the GDL_CONTAINER objects. // "bool listmode" adapts LIST::GET to GDL (NOT an IDL feature, useful for debug) // BaseGDL* list__get( EnvUDT* e) { // see overload.cpp // DFunLIST__ADD->AddKey("ALL","ALL")->AddKey("ISA","ISA")->AddKey("NULL","NULL"); // DFunLIST__ADD->AddPar("VALUE")->AddPar("INDEX"); // res=List.get([/all] [, isa=(names)] [. position=index] [, count=variable] [/null][) GDL_LIST_STRUCT() GDL_CONTAINER_NODE() enum { POINTERS=1, OBJECTS}; SizeT nParam = e->NParam(1); trace_me = false;//trace_arg(); static int kwALLIx = e->GetKeywordIx("ALL"); static int kwISAIx = e->GetKeywordIx("ISA"); static int kwNULLIx = e->GetKeywordIx("NULL"); static int kwPOSITIONIx = e->GetKeywordIx("POSITION"); static int kwCOUNTIx = e->GetKeywordIx("COUNT"); static int kwSELFIx = kwALLIx + 1; DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); // IDL_CONTAINER began as an object container and was later extended to // include Heap variable pointers. Both cases are handled with the same // GDL_CONTAINER link-list, as for LIST. DStructDesc* selfDesc= self->Desc(); bool listmode = ( selfDesc == structDesc::LIST); if(trace_me) { if(listmode) std::printf(" list__get -nprm= %llu ", nParam); else std::printf(" container::get -nprm= %llu ", nParam); } DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; bool nullKW = e->KeywordSet(kwNULLIx); if( nList == 0) { if(nullKW) return NullGDL::GetSingleInstance(); else return new DLongGDL(-1); } DInt GDLContainerVersion = (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0]; bool isPtr = (GDLContainerVersion == POINTERS) or listmode; bool allKW = e->KeywordSet(kwALLIx); BaseGDL* isaKW = NULL; if( allKW) { isaKW = e->GetKW( kwISAIx); if( isPtr && isaKW != NULL) { if(nullKW) return NullGDL::GetSingleInstance(); else return new DLongGDL(-1); } } BaseGDL** countKW = NULL; if( e->GetKW( kwCOUNTIx) != NULL) countKW = &e->GetKW( kwCOUNTIx); // // an IDL_CONTAINER is supposed to be only of one type or another: // either it is holding objects or it is holding heapvar pointers. // pDataTag is always just a pointer, either a DPtr or DObj. // If ::GET was to be used on a real LIST then pData would point to // the data item(s) in the list. // BaseGDL* index = e->GetKW(kwPOSITIONIx); MAKE_LONGGDL(index, indexLong) if( indexLong == NULL) indexLong = new DLongGDL(0); std::vector testisa; if( isaKW != NULL) { if( isaKW->Type() != GDL_STRING) ThrowFromInternalUDSub( e, "Object Classes can be referenced only with names (strings)"); for(SizeT i=0; i < isaKW->N_Elements(); ++i) testisa.push_back(StrUpCase( (*static_cast( isaKW))[i])); } DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; DPtr pNext = pTail; DStructGDL* Node = GetLISTStruct(e, pTail); BaseGDL* NodePtr = Node->GetTag( pDataTag, 0); DPtr pointer = (*static_cast( NodePtr))[0]; DObj ObjID = static_cast(pointer); if(trace_me and !listmode) { if(isPtr) std::printf(" Tail.pDataTag: %llu \n", pointer); else std::printf(" Tail.pDataTag (OBJ): %llu \n", ObjID); } std::vector pointers; if(allKW) { int inlist = 0; do { if(pNext == 0) ThrowFromInternalUDSub( e, "Invalid container node"); DStructGDL* Node = GetLISTStruct(e, pNext); BaseGDL* NodePtr = Node->GetTag( pDataTag, 0); DPtr pointer = (*static_cast( NodePtr))[0]; DObj ObjID = static_cast(pointer); if(isPtr && e->Interpreter()->PtrValid( pointer)) { pointers.push_back( pointer); if(trace_me) std::printf(" (ptr)++: %d %llu",inlist, pointer); } else if(!isPtr && e->Interpreter()->ObjValid( ObjID)) { bool accept = true; if( isaKW != NULL) { accept = false; DStructGDL* oStruct = e->GetObjHeap( ObjID); for(SizeT i =0; i < testisa.size(); ++i) if( oStruct->Desc()->IsParent( testisa[i])) { accept = true; break;} } if(accept) { pointers.push_back( ObjID); if(trace_me) std::printf(" (obj)++: %d %llu",inlist, ObjID); } } else if(trace_me) std::printf(" invalid: %d %llu", inlist, pointer); pNext = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; if(trace_me) std::printf(" pNext:%llu", pNext); } while ( ++inlist != nList ); if(countKW != NULL) *countKW = new DLongGDL(pointers.size()); if(pointers.size() == 0){ if(nullKW) return NullGDL::GetSingleInstance(); else return new DLongGDL(-1); } } else { // allKW if( index == NULL) { if(trace_me) std::printf(" 1-shot %llu\n" , pointer); if(isPtr && e->Interpreter()->PtrValid( pointer)) { if(doIncDec) e->Interpreter()->IncRef( pointer); if(countKW != NULL) *countKW = new DLongGDL(1); return new DPtrGDL( pointer); } else if(!isPtr && e->Interpreter()->ObjValid( ObjID)) { if(doIncDec) e->Interpreter()->IncRefObj( ObjID); if(countKW != NULL) *countKW = new DLongGDL(1); return new DObjGDL( ObjID); } else { if(countKW != NULL) *countKW = new DLongGDL(0); if(nullKW) return NullGDL::GetSingleInstance(); else return new DLongGDL(-1); } } int inlist = 0; SizeT nEl = indexLong->N_Elements(); do { if(pNext == 0) ThrowFromInternalUDSub( e, "Invalid container node"); DStructGDL* Node = GetLISTStruct(e, pNext); BaseGDL* NodePtr = Node->GetTag( pDataTag, 0); DPtr pointer = (*static_cast( NodePtr))[0]; DObj ObjID = static_cast(pointer); if( (isPtr && e->Interpreter()->PtrValid( pointer)) || (!isPtr && e->Interpreter()->ObjValid( ObjID)) ) { for( SizeT i=0; i < nEl; ++i) { int ix = (*indexLong)[i]; if (ix < 0) ix += nList; if(inlist == ix) pointers.push_back( pointer); } } else if(trace_me) std::printf(" invalid: %d %llu", inlist, pointer); if(trace_me) std::printf(" pNext:%llu", pNext); pNext = (*static_cast( Node->GetTag( pNextTag, 0)))[0]; } while ( ++inlist != nList ); if(trace_me) std::cout << std::endl; } SizeT nfetch = pointers.size(); if(countKW != NULL) *countKW = new DLongGDL(nfetch); if(nfetch == 0) { if(nullKW) return NullGDL::GetSingleInstance(); else return new DLongGDL(-1); } if(trace_me) printf(" fetch: #%llu isPtr? %d",nfetch,isPtr); if( isPtr) { if( nfetch ==1) { if(doIncDec) e->Interpreter()->IncRef(pointers[0]); return new DPtrGDL(pointers[0]); } DPtrGDL* ret; ret = new DPtrGDL( dimension(nfetch)); Guard retGuard( ret); for(SizeT i=0; i < nfetch; ++i) { if(doIncDec) e->Interpreter()->IncRef(pointers[i]); (*ret)[i] = pointers[i]; } retGuard.Release(); return ret; } else { if( nfetch ==1) { if(doIncDec) e->Interpreter()->IncRefObj(static_cast(pointers[0])); return new DObjGDL(static_cast(pointers[0])); } DObjGDL* ret; ret = new DObjGDL( dimension(nfetch)); Guard retGuard( ret); for(SizeT i=0; i < nfetch; ++i) { if(doIncDec) e->Interpreter()->IncRefObj( static_cast(pointers[i])); (*ret)[i] = static_cast(pointers[i]); } retGuard.Release(); return ret; } } void list__add( EnvUDT* e) { // see overload.cpp // DFunLIST__ADD->AddKey("EXTRACT","EXTRACT")->AddKey("NO_COPY","NO_COPY"); // DFunLIST__ADD->AddPar("VALUE")->AddPar("INDEX"); // List.Add, Value [,Index], [, /EXTRACT] [, /NO_COPY] GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // trace_me = false; //lib::trace_arg(); static int kwEXTRACTIx = e->GetKeywordIx("EXTRACT"); static int kwNO_COPYIx = e->GetKeywordIx("NO_COPY"); static int kwPOSITIONIx = e->GetKeywordIx("POSITION"); static int kwSELFIx = kwEXTRACTIx + 1; static int kwVALUEIx = kwSELFIx+1; static int kwINDEXIx = kwSELFIx+2; SizeT nParam = e->NParam(1); DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; DInt GDLContainerVersion = 0; DStructDesc* selfDesc= self->Desc(); bool listmode = ( selfDesc == structDesc::LIST); BaseGDL* value = NULL; DType valType; if( nParam >= 2) value = e->GetKW(kwVALUEIx); bool isvalscalar = false; if( value == NULL || value == NullGDL::GetSingleInstance()) isvalscalar = true; else { if( value->StrictScalar() ) isvalscalar = true; valType = value->Type(); } DLong listSize; DStructGDL* ListHead; bool isvallist = false; bool kwEXTRACT = false; bool kwNO_COPY = false; BaseGDL* index = NULL; if(listmode) { if( nParam >= 3) index = e->GetKW(kwINDEXIx); if (e->KeywordSet(kwEXTRACTIx)) kwEXTRACT = true; if (e->KeywordSet(kwNO_COPYIx)) kwNO_COPY = true; if (e->KeywordPresent(kwPOSITIONIx)) ThrowFromInternalUDSub( e, "list::add - POSITION cannot be used"); if( isvalscalar && kwEXTRACT && valType == GDL_OBJ) { DObj p=(*static_cast( value))[0]; if(p != 0) { ListHead = GetOBJ( value, e); DStructDesc* desc = ListHead->Desc(); isvallist = desc->IsParent("LIST"); } } } else { if (e->KeywordPresent(kwPOSITIONIx)) index = e->GetKW( kwPOSITIONIx); if (e->KeywordSet(kwEXTRACTIx)) ThrowFromInternalUDSub( e, " EXTRACT cannot be used"); if (e->KeywordSet(kwNO_COPYIx)) ThrowFromInternalUDSub( e, " NOCOPY cannot be used"); } MAKE_LONGGDL(index, indexLong) DLong insertPos = -1; if( index != NULL) { insertPos = (*indexLong)[0]; // Currently only scalars accepted. if(insertPos < 0) insertPos += nList; if( insertPos < 0) ThrowFromInternalUDSub( e, "INDEX out of range ("+i2s(insertPos)+" (<0))"); if( insertPos > nList) ThrowFromInternalUDSub( e, "INDEX out of range ("+i2s(insertPos)+" (>"+i2s(nList)+"))"); } // InsertPos: 0-nList, or -1 (equiv nList) // // 1. Form chain representing additional members. // sequence of {PNEXT, PDATA} with final PNEXT = NULL // VALUE may be singular (chain has one member) or need extraction. // process may involve NO_COPY // 2. Attach chain to the list at insertPos if(trace_me) { if(listmode) std::printf(" list__add "); else std::printf(" container::add "); } DStructGDL* cStruct = NULL; DPtr cID = 0; DPtr firstID = 0; SizeT valueN_Elements = 1; if( kwEXTRACT && value != NULL) { DStructGDL* cStructLast = NULL; DPtr valNode; DPtr pID; valueN_Elements = value->N_Elements(); if(trace_me) std::printf(" (kwEXTRACT && value != NULL) #: %llu" , valueN_Elements ); if(isvallist) { valueN_Elements = (*static_cast(ListHead->GetTag( nListTag, 0)))[0]; valNode = GetLISTNode(e, ListHead, 0); } for( SizeT eIx=0; eIxInterpreter()->NewHeap(1,GetNodeData(valNode)->Dup()); else if(valType != GDL_PTR or isvalscalar ) pID = e->Interpreter()->NewHeap(1,value->NewIx(eIx)); else { // when a ptrarr is added & extracted, make ptrarr(1) DPtrGDL* pHeap = new DPtrGDL( dimension(1)); (*pHeap)[0] = (*static_cast(value))[eIx]; pID = e->Interpreter()->NewHeap(1, pHeap); } if(trace_me) std::printf(" (%llu)", pID); // container to accomodate the data cStruct= new DStructGDL( containerDesc, dimension()); // attach pID to cstruct (as data) (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = pID; // create pointer for cstruct cID cID = e->Interpreter()->NewHeap(1,cStruct); // assign pointer cID if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else firstID = cID; cStructLast = cStruct; } } else if( !listmode) { if(valType != GDL_PTR and valType != GDL_OBJ) ThrowFromInternalUDSub( e, " Must be pointers or Objects"); DStructGDL* cStructLast = NULL; valueN_Elements = value->N_Elements(); // because objects do not get another pointer GDLContainerVersion = (valType == GDL_PTR) ? 1 : 2; if(nList == 0) (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0] = GDLContainerVersion; else if( GDLContainerVersion != (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0]) ThrowFromInternalUDSub( e, " Mixed pointers/Objects attempted"); for( SizeT eIx=0; eIxInterpreter()->NewHeap(1,cStruct); if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else firstID = cID; // Container::ADD. IncRef(pID) // IncRefObj calls are essential, so no option offered. if(valType == GDL_PTR) { DPtr pID = (*static_cast(value))[eIx]; e->Interpreter()->IncRef(pID); if(trace_me) std::printf(" (%llu)", pID); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = pID; } else { DObj ID = (*static_cast(value))[eIx]; e->Interpreter()->IncRefObj(ID); if(trace_me) std::printf(" (%llu)", ID); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = ID; } cStructLast = cStruct; } } else { // kwEXTRACT && value != NULL ... !listmode DPtr pID; if( value == NULL || kwNO_COPY) pID = e->Interpreter()->NewHeap(1,value); else pID = e->Interpreter()->NewHeap(1,value->Dup()); valueN_Elements = 1; // pID properly set (ptr to data) cStruct= new DStructGDL( containerDesc, dimension()); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = pID; cID = e->Interpreter()->NewHeap(1,cStruct); if(trace_me) std::printf(" cID %llu",cID); firstID = cID; } // kwEXTRACT && value != NULL if( kwNO_COPY) { bool stolen = e->StealLocalKW( kwVALUEIx); if( !stolen) e->GetKW(kwVALUEIx) = NULL; GDLDelete(value); } if(trace_me) std::printf(" nList %d \n",nList); if( nList == 0) // empty LIST { (*static_cast( self->GetTag( pTailTag, 0)))[0] = firstID; (*static_cast( self->GetTag( pHeadTag, 0)))[0] = cID; } else if( insertPos == -1 || insertPos == nList) // head { DPtr pHead = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; DStructGDL* headNode = GetLISTStruct( e, pHead); (*static_cast( headNode->GetTag( pNextTag, 0)))[0] = firstID; (*static_cast( self->GetTag( pHeadTag, 0)))[0] = cID; } else if( insertPos == 0) // tail { DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; (*static_cast( cStruct->GetTag( pNextTag, 0)))[0] = pTail; (*static_cast( self->GetTag( pTailTag, 0)))[0] = firstID; } else { DPtr pPredNode = GetLISTNode( e, self, insertPos-1); DStructGDL* predNode = GetLISTStruct( e, pPredNode); (*static_cast( cStruct->GetTag( pNextTag, 0)))[0] = (*static_cast( predNode->GetTag( pNextTag, 0)))[0]; (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = firstID; } (*static_cast( self->GetTag( nListTag, 0)))[0] = nList+valueN_Elements; } BaseGDL* list_fun( EnvT* e) { static int kwEXTRACTIx = e->KeywordIx("EXTRACT"); static int kwLENGTHIx = e->KeywordIx("LENGTH"); static int kwNO_COPYIx = e->KeywordIx("NO_COPY"); bool kwEXTRACT = false; bool kwNO_COPY = false; if (e->KeywordSet(kwEXTRACTIx)){ kwEXTRACT = true;} if (e->KeywordSet(kwNO_COPYIx)){ kwNO_COPY = true;} SizeT nParam = e->NParam(); DLong listLength = 0; DLongGDL* lengthKW = e->IfDefGetKWAs(kwLENGTHIx); if( lengthKW != NULL) { listLength = (*lengthKW)[0]; if( listLength < 0) listLength = 0; } DInterpreter* ip = e->Interpreter(); GDL_LIST_STRUCT() GDL_CONTAINER_NODE() // because of .RESET_SESSION, we cannot use static here DStructDesc* listDesc=structDesc::LIST; DStructDesc* containerDesc=structDesc::GDL_CONTAINER_NODE; assert( listDesc != NULL && listDesc->NTags() > 0); assert( containerDesc != NULL && containerDesc->NTags() > 0); DStructGDL* listStruct= new DStructGDL( listDesc, dimension()); DObj objID= e->NewObjHeap( 1, listStruct); // owns objStruct, sets ref count to 1 BaseGDL* newObj = new DObjGDL( objID); // the list object Guard newObjGuard( newObj); SizeT added = 0; DStructGDL* cStruct = NULL; DPtr cID = 0; (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; if( nParam > 0 || listLength > 0) { DStructGDL* cStructLast = NULL; for( SizeT pIx=0; pIxGetPar(pIx); if( kwEXTRACT && p != NULL && p->N_Elements() > 1) { for( SizeT eIx=0; eIxN_Elements(); ++eIx) { DPtr pID; // pID = ip->NewHeap(1,p->NewIx(eIx)); // sets ref count to 1 if(p->Type() != GDL_PTR or (p->StrictScalar()) ){ pID = ip->NewHeap(1,p->NewIx(eIx)); } else { // when a ptrarr is added & extracted, make ptrarr(1) DPtrGDL* pHeap = new DPtrGDL( dimension(1)); (*pHeap)[0] = (*static_cast(p))[eIx]; pID = ip->NewHeap(1, // scalar PTRs are treated different in [, ]. pHeap); } cStruct= new DStructGDL( containerDesc, dimension()); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = pID; cID = ip->NewHeap(1,cStruct); // sets ref count to 1 if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; if( ++added == listLength) break; } if( kwNO_COPY) { bool stolen = e->StealLocalPar( pIx); if( !stolen) e->GetPar(pIx) = NULL; GDLDelete(p); } assert( added > 0); if( added == listLength) break; } else { SizeT pID; if( p == NULL || kwNO_COPY) { pID = ip->NewHeap(1,p); // sets ref count bool stolen = e->StealLocalPar( pIx); if( !stolen) e->GetPar(pIx) = NULL; } else { pID = ip->NewHeap(1,p->Dup()); } cStruct= new DStructGDL( containerDesc, dimension()); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = pID; cID = ip->NewHeap(1,cStruct); // sets ref count if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; if( ++added == listLength) break; } } if( listLength != 0 && added < listLength) { for( ; addedNewHeap(1,NULL); cStruct= new DStructGDL( containerDesc, dimension()); (*static_cast( cStruct->GetTag( pDataTag, 0)))[0] = pID; cID = ip->NewHeap(1,cStruct); if( cStructLast != NULL) (*static_cast( cStructLast->GetTag( pNextTag, 0)))[0] = cID; else { // 1st element (*static_cast( listStruct->GetTag( pTailTag, 0)))[0] = cID; } cStructLast = cStruct; } } } // if( cStruct != NULL) // (*static_cast( cStruct->GetTag( pNextTag, 0)))[0] = 0; (*static_cast( listStruct->GetTag( pHeadTag, 0)))[0] = cID; (*static_cast( listStruct->GetTag( nListTag, 0)))[0] = added; newObjGuard.Release(); return newObj; } BaseGDL* container__init( EnvUDT* e) { // container is parented by GDL_OBJECT which can handle INIT: return new DByteGDL(1); // if we reach here, defaul is to return 'TRUE' } void container__cleanup( EnvUDT* e) { DStructGDL* self = GetOBJ( e->GetKW( 0), e); if( trace_me) std::cout << " CONTAINER::CLEANUP:" ; CONTAINERCleanup( e, self); } BaseGDL* container__iscontained( EnvUDT* e) { GDL_CONTAINER_STRUCT() GDL_CONTAINER_NODE() static int kwPOSITIONIx = e->GetKeywordIx("POSITION"); static int kwSELFIx = kwPOSITIONIx + 1; // no keywords static int kwVALUEIx = kwSELFIx + 1; // Keyword DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList == 0) return NullGDL::GetSingleInstance(); SizeT nParam = e->NParam(1); BaseGDL* values = e->GetKW( kwVALUEIx); if( nParam == 0 or values== 0) return NullGDL::GetSingleInstance(); DInt GDLContainerVersion = (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0]; if( GDLContainerVersion == 0) ThrowFromInternalUDSub( e, " only pointers or objects shall be placed in such containers"); if( GDLContainerVersion == 1 and values->Type() != GDL_PTR) ThrowFromInternalUDSub( e, " only pointers can be found in this container"); if( GDLContainerVersion == 2 and values->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, " only objects can be found in this container"); DPtr actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; if( ! BaseGDL::interpreter->PtrValid(actP)) // return NullGDL::GetSingleInstance(); DLongGDL* pos = new DLongGDL( dimension(values->N_Elements()) ); Guard posGuard( pos); DByteGDL* result = new DByteGDL( dimension(nList)); Guard resultGuard( result); for( SizeT elIx = 0; elIx < nList; ++elIx) { DStructGDL* actPStruct = GetLISTStruct(e, actP); DPtr Ptr = (*static_cast(actPStruct->GetTag( pDataTag, 0)))[0]; for( SizeT k=0; k < values->N_Elements(); k++ ) if( Ptr == (*static_cast(values))[k] ) { (*result)[k] = 1; (*pos)[k] = elIx; break; } actP = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; } for( SizeT k=0; k < values->N_Elements(); k++ ) if( (*result)[k] == 0 ) (*pos)[k] = -1; if( e->KeywordPresent( kwPOSITIONIx)) { BaseGDL** posKW = &e->GetKW( kwPOSITIONIx); posGuard.Release(); *posKW = pos; } resultGuard.Release(); if(!values->StrictScalar()) return result; else return new DByteGDL( (*result)[0]); } BaseGDL* container__equals( EnvUDT* e) { GDL_CONTAINER_STRUCT() GDL_CONTAINER_NODE() static int kwSELFIx = 0; // no keywords static int kwVALUEIx = 1; // no Keywords DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; if( nList == 0) return NullGDL::GetSingleInstance(); SizeT nParam = e->NParam(1); BaseGDL* value = e->GetKW( kwVALUEIx); if( nParam == 0 or value== 0) return NullGDL::GetSingleInstance(); DByteGDL* result = new DByteGDL( dimension(nList)); Guard resultGuard( result); DInt GDLContainerVersion = (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0]; if( GDLContainerVersion != 1) // should be throwing exception here ThrowFromInternalUDSub( e, " only containers of pointers are allowed"); DPtr actP = (*static_cast(self->GetTag( pTailTag, 0)))[0]; if( ! BaseGDL::interpreter->PtrValid(actP)) // return NullGDL::GetSingleInstance(); for( SizeT elIx = 0; elIx < nList; ++elIx) { DStructGDL* actPStruct = GetLISTStruct(e, actP); DPtr Ptr = (*static_cast(actPStruct->GetTag( pDataTag, 0)))[0]; BaseGDL* data = BaseGDL::interpreter->GetHeapNoThrow( Ptr); if( data == NULL || data == NullGDL::GetSingleInstance()) (*result)[elIx] = 0; else (*result)[elIx] = lib::array_equal_bool(data, value) ? 1 : 0; actP = (*static_cast( actPStruct->GetTag( pNextTag, 0)))[0]; } resultGuard.Release(); return result; } void container__remove( EnvUDT* e) { GDL_CONTAINER_STRUCT() GDL_CONTAINER_NODE() enum { POINTERS=1, OBJECTS}; SizeT nParam = e->NParam(1); // sALL, POSITION are keyword. static int kwALLIx = e->GetKeywordIx("ALL"); static int kwPOSITIONIx = e->GetKeywordIx("POSITION"); static int kwSELFIx = kwALLIx + 1; DStructGDL* self = GetOBJ( e->GetKW( kwSELFIx), e); DLong nList = (*static_cast( self->GetTag( nListTag, 0)))[0]; // Is this correct behavior? Not from the LIST example. // if( nList == 0) ThrowFromInternalUDSub( e, "Container is empty."); if(nList == 0) return; DInt GDLContainerVersion = (*static_cast( self->GetTag( GDLContainerVersionTag, 0)))[0]; DPtr pTail = (*static_cast( self->GetTag( pTailTag, 0)))[0]; bool isPtr = (GDLContainerVersion == POINTERS); bool allKW = e->KeywordSet(kwALLIx); if(allKW) { CONTAINERCleanup(e, self); return; } if( nParam == 2) { static int kwVALUEIx = kwSELFIx + 1; BaseGDL* value = e->GetKW(kwVALUEIx); if( value == NULL) return; DType valType = value->Type(); if( valType != GDL_PTR and isPtr) ThrowFromInternalUDSub( e, " Heapvars not pointers"); else if( valType != GDL_OBJ and !isPtr) ThrowFromInternalUDSub( e, " Heapvars not Objects"); DPtr pNext = pTail; DPtr pHead = (*static_cast( self->GetTag( pHeadTag, 0)))[0] ; DPtr predPtr = 0; DLong newnList = nList; SizeT valueN_Elements = value->N_Elements(); for (SizeT k=0; k < nList; ++k) { DPtr pRemove=pNext; DStructGDL* removeNode = GetLISTStruct( e, pRemove); pNext = (*static_cast( removeNode->GetTag( pNextTag, 0)))[0]; DPtr pData = (*static_cast( removeNode->GetTag( pDataTag, 0)))[0]; bool release = false; for (SizeT eIx=0; eIx < valueN_Elements; ++eIx) { DPtr valtest = (*static_cast(value))[eIx]; if( pData == valtest) {release = true; break;} } if( release) { if(doIncDec) { if( isPtr && e->Interpreter()->PtrValid( pData)) e->Interpreter()->DecRef( pData); else if(!isPtr && e->Interpreter()->ObjValid( pData)) e->Interpreter()->DecRefObj( pData); // else std::cout << " removing an invalid obj/ptr " << std::endl; } (*static_cast( removeNode->GetTag( pNextTag, 0)))[0] = 0; e->Interpreter()->FreeHeap( pRemove); //==== Now patch up the container for the hole we created. --newnList; if( predPtr == 0) (*static_cast( self->GetTag( pTailTag, 0)))[0] = pNext; else { DStructGDL* predNode = GetLISTStruct( e, predPtr); (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = pNext; } if( pRemove == pHead) (*static_cast( self->GetTag( pHeadTag, 0)))[0] = predPtr; } else { // release predPtr = pRemove; } } (*static_cast( self->GetTag( nListTag, 0)))[0] = newnList; return; } BaseGDL* index = NULL; if( e->KeywordPresent(kwPOSITIONIx)) index = e->GetKW(kwPOSITIONIx); MAKE_LONGGDL(index, indexLong) DLong removePos = -1; if( indexLong != NULL) { if( indexLong->N_Elements() == 1) { removePos = (*indexLong)[0]; if( removePos < 0) removePos += nList; if( (removePos < 0) or ( removePos >= nList) ) ThrowFromInternalUDSub( e, "Index out of range."); } } if(trace_me) std::printf(" c-r.remove: %d ",removePos); DPtr pNext = pTail; DPtr pHead = (*static_cast( self->GetTag( pHeadTag, 0)))[0]; DPtr predPtr = 0; for (SizeT k=0; k < nList; ++k) { DPtr pRemove=pNext; DStructGDL* removeNode = GetLISTStruct( e, pRemove); bool release = (k == removePos); pNext = (*static_cast( removeNode->GetTag( pNextTag, 0)))[0]; if( release) { DPtr pData = (*static_cast( removeNode->GetTag( pDataTag, 0)))[0]; if(doIncDec) { if( isPtr && e->Interpreter()->PtrValid( pData)) e->Interpreter()->DecRef( pData); else if(!isPtr && e->Interpreter()->ObjValid( pData)) e->Interpreter()->DecRefObj( pData); // else std::cout << " removing an invalid obj/ptr " << std::endl; } (*static_cast( removeNode->GetTag( pNextTag, 0)))[0] = 0; e->Interpreter()->HeapErase( pRemove); if( predPtr == 0) (*static_cast( self->GetTag( pTailTag, 0)))[0] = pNext; else { DStructGDL* predNode = GetLISTStruct( e, predPtr); (*static_cast( predNode->GetTag( pNextTag, 0)))[0] = pNext; } if( pRemove == pHead) (*static_cast( self->GetTag( pHeadTag, 0)))[0] = predPtr; (*static_cast( self->GetTag( nListTag, 0)))[0] = nList - 1; break; } predPtr = pRemove; if( trace_me) std::printf(" %llu ", k); } if(trace_me) std::cout << std::endl; return; } } // namespace lib gdl-0.9.9/src/list.hpp000066400000000000000000000045231340051421000145440ustar00rootroot00000000000000/*************************************************************************** list.hpp - for LIST objects ------------------- begin : July 22 2013 copyright : (C) 2013 by M. Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef LIST_HPP_ #define LIST_HPP_ // #include void LIST__ToStream( DStructGDL* oStructGDL, std::ostream& o, SizeT w, SizeT* actPosPtr); DStructGDL*GetOBJ( BaseGDL* selfP, EnvUDT* e); DStructGDL*GetSELF( BaseGDL* selfP, EnvUDT* e); namespace lib { BaseGDL* list_fun( EnvT* e); void list__cleanup( EnvUDT* e); BaseGDL* LIST___OverloadIsTrue( EnvUDT* e); BaseGDL* LIST___OverloadBracketsRightSide( EnvUDT* e); void LIST___OverloadBracketsLeftSide( EnvUDT* e); BaseGDL* LIST___OverloadPlus( EnvUDT* e); BaseGDL* LIST___OverloadEQOp( EnvUDT* e); BaseGDL* LIST___OverloadNEOp( EnvUDT* e); void list__add( EnvUDT* e); void container__cleanup( EnvUDT* e); BaseGDL* container__iscontained( EnvUDT* e); BaseGDL* container__equals( EnvUDT* e); void container__remove( EnvUDT* e); void list__remove_pro( EnvUDT* e); void list__reverse( EnvUDT* e); void list__swap( EnvUDT* e); void list__move( EnvUDT* e); BaseGDL* list__remove_fun( EnvUDT* e); BaseGDL* list__toarray( EnvUDT* e); BaseGDL* list__isempty( EnvUDT* e); SizeT LIST_count( DStructGDL* oStructGDL); BaseGDL* list__count( EnvUDT* e); BaseGDL* list__where( EnvUDT* e); // these added in order to accomodate being an IDL_CONTAINER: BaseGDL* list__get( EnvUDT* e); BaseGDL* list__init( EnvUDT* e); } #endif gdl-0.9.9/src/magick_cl.cpp000066400000000000000000001021311340051421000154670ustar00rootroot00000000000000/*************************************************************************** magick_fun_cl.cpp - basic GDL library function ------------------- begin : May 7 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #ifndef HAVE_CONFIG_H // #include // #else // default: assume we have ImageMagick #define USE_MAGICK 1 #define USE_MAGICK6 1 #endif #ifdef USE_MAGICK #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" #include "basic_fun_cl.hpp" #include "terminfo.hpp" #include "typedefs.hpp" #include "magick_cl.hpp" #include "graphicsdevice.hpp" #define GDL_DEBUG //#undef GDL_DEBUG // If Magick has not been initialized, do it here, instead of initilizing it in the main program (speedup and avoid strange backtraces) // Also warn about limitations due to local implementation of Magick library. //We should do more, by example hat octave people do in their code (they circumvent some other limitations) #define START_MAGICK \ if (notInitialized ) { \ notInitialized = false; \ Magick::InitializeMagick(NULL); \ if ( QuantumDepth < 32) fprintf(stderr, "%% WARNING: your version of the %s library will truncate images to %d bits per pixel\n", \ MagickPackageName, QuantumDepth); \ } namespace lib { using namespace std; using namespace antlr; using namespace Magick; Image gImage[40]; unsigned int gValid[40]; unsigned int gCount = 0; static bool notInitialized = true; void magick_setup() { int i; for (i = 0; i < 40; ++i) gValid[i] = 0; } Image& magick_image(EnvT *e, unsigned int mid) { if (gValid[mid] == 0) e->Throw("invalid ID."); return gImage[mid]; } unsigned int magick_image(EnvT* e, Image &imImage) { unsigned int mid = magick_id(); gImage[mid] = imImage; return mid; } void magick_replace(EnvT* e, unsigned int mid, Image &imImage) { gImage[mid] = imImage; } unsigned int magick_id(void) { unsigned int i, val; val = gCount; if (gCount == 0) magick_setup(); for (i = 0; i < 40; ++i) if (gValid[i] == 0 && val > i) val = i; // if(gCount==40) ERROR if (val >= gCount) gCount++; gValid[val] = 1; return val; } // magic_id=OPEN("Filename") BaseGDL* magick_open(EnvT* e) { START_MAGICK; try { DString filename; e->AssureScalarPar(0, filename); WordExp(filename); if (filename.length() == 0) e->Throw("Void file Name"); Image a; try { a.read(filename); } catch (WarningCoder &warning_) { cerr << warning_.what() << endl; } if ((a.rows() * a.columns()) == 0) e->Throw("Error reading image dimensions!"); a.flip(); unsigned int mid; mid = magick_image(e, a); return new DUIntGDL(mid); } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } BaseGDL * magick_ping(EnvT* e) { // TODO! //if (e->KeywordPresent("SUPPORTED_READ") || e->KeywordPresent("SUPPORTED_WRITE")) // e->Warning("SUPPORTED_READ and SUPPORTED_WRITE keywords not supported yet"); // TODO: JPEG2000- and TIFF-related additional fields in the INFO structure START_MAGICK; SizeT nParam = e->NParam(1); try { DString filename; e->AssureScalarPar(0, filename); if (filename.length() == 0) return new DLongGDL(0); WordExp(filename); Image a; try { a.ping(filename); //a.read(filename); } catch (WarningCoder &warning_) { cerr << warning_.what() << endl; } if (nParam == 2) { DString magick; e->AssureScalarPar(1, magick); if (a.magick() != magick) return new DLongGDL(0); } int debug = 0; if (debug == 1) { cout << "a.type() :" << a.type() << endl; cout << "a.classType() :" << a.classType() << endl; cout << "a.matte() :" << a.matte() << endl; // no useful info here:cout << "a.colorSpace() :" << a.colorSpace() << endl; // Always 8:cout << "a.depth() :" << a.depth() << endl; // Always 1: cout << "a.colorSpace() :" << a.colorSpace() << endl; } // AC 2012-May-10 // http://www.graphicsmagick.org/Magick++/Image.html#type // relevant information that, in some cases, is provided after pinging: // a.matte(), a.classType() [and a.type() for Palette info only] DLong channels = 0; if (a.classType() == 1) channels = 3; // DirectColor if (a.classType() == 2) channels = 1; // PseudoColor if (channels == 0) cout << "no ClassType found for current Image" << endl; // AC 2012-May-10 this is NOT working with only a a.ping() // a.type() is FULLY reliable if and only if a.read() was done before !!! //http://www.graphicsmagick.org/Magick++/Image.html#type // (should be OK with a a.read()) /* channels = a.classType() == PseudoClass ? 1 // color palette : a.type() == GrayscaleType ? 1 // greyscale : a.type() == ColorSeparationType ? 4 // CMYK : 3; // RGB */ // AC 2012-May-10 this is OK (reliable), see exemple "589 Lavandula mono" if (a.matte()) channels += 1; // TODO! multiple images (using the Magick++ STL interface) DLong image_index, num_images; image_index = 0; num_images = 1; DInt pixel_type; pixel_type = a.depth() == 16 ? 2 : 1; // AC 2012-May-10 Palette only if type == 4 OR 5 // Despite Type is NOT useful without a a.read(), it is OK for Palette ! // This should be reliable (OK with ImageMagick AND GraphicsMagick) DInt has_palette = 0; if (a.type() == PaletteType | a.type() == PaletteMatteType) has_palette = 1; // TODO: // - JP2->JPEG2000 ? DString type; type = a.magick() == "PNM" ? "PPM" : a.magick() == "DCM" ? "DICOM" : a.magick(); if (debug == 1) cout << "Type (via a.magick()) : " << type << endl; static int infoIx = e->KeywordIx("INFO"); if (e->KeywordPresent(infoIx)) { e->AssureGlobalKW(infoIx); // creating the output anonymous structure DStructDesc* info_desc = new DStructDesc("$truct"); SpDString aString; SpDLong aLong; SpDInt aInt; SpDLong aLongArr2(dimension(2)); info_desc->AddTag("CHANNELS", &aLong); info_desc->AddTag("DIMENSIONS", &aLongArr2); info_desc->AddTag("HAS_PALETTE", &aInt); info_desc->AddTag("IMAGE_INDEX", &aLong); info_desc->AddTag("NUM_IMAGES", &aLong); info_desc->AddTag("PIXEL_TYPE", &aInt); info_desc->AddTag("TYPE", &aString); DStructGDL* info = new DStructGDL(info_desc, dimension()); // filling the info struct with data info->InitTag("CHANNELS", DLongGDL(channels)); { DLongGDL dims(dimension(2)); dims[0] = a.columns(); dims[1] = a.rows(); info->InitTag("DIMENSIONS", dims); } info->InitTag("HAS_PALETTE", DIntGDL(has_palette)); info->InitTag("IMAGE_INDEX", DLongGDL(image_index)); info->InitTag("NUM_IMAGES", DLongGDL(num_images)); info->InitTag("PIXEL_TYPE", DIntGDL(pixel_type)); info->InitTag("TYPE", DStringGDL(type)); e->SetKW(infoIx, info); } static int channelsIx = e->KeywordIx("CHANNELS"); if (e->KeywordPresent(channelsIx)) { e->AssureGlobalKW(channelsIx); e->SetKW(channelsIx, new DLongGDL(channels)); } static int dimensionsIx = e->KeywordIx("DIMENSIONS"); if (e->KeywordPresent(dimensionsIx)) { e->AssureGlobalKW(dimensionsIx); DLongGDL *dims = new DLongGDL(dimension(2)); (*dims)[0] = a.columns(); (*dims)[1] = a.rows(); e->SetKW(dimensionsIx, dims); } static int has_paletteIx = e->KeywordIx("HAS_PALETTE"); if (e->KeywordPresent(has_paletteIx)) { e->AssureGlobalKW(has_paletteIx); e->SetKW(has_paletteIx, new DIntGDL(has_palette)); } static int image_indexIx = e->KeywordIx("IMAGE_INDEX"); if (e->KeywordPresent(image_indexIx)) { e->AssureGlobalKW(image_indexIx); e->SetKW(image_indexIx, new DLongGDL(image_index)); } static int num_imagesIx = e->KeywordIx("NUM_IMAGES"); if (e->KeywordPresent(num_imagesIx)) { e->AssureGlobalKW(num_imagesIx); e->SetKW(num_imagesIx, new DLongGDL(num_images)); } static int pixel_typeIx = e->KeywordIx("PIXEL_TYPE"); if (e->KeywordPresent(pixel_typeIx)) { e->AssureGlobalKW(pixel_typeIx); e->SetKW(pixel_typeIx, new DIntGDL(pixel_type)); } static int typeIx = e->KeywordIx("TYPE"); if (e->KeywordPresent(typeIx)) { e->AssureGlobalKW(typeIx); e->SetKW(typeIx, new DStringGDL(type)); } return new DLongGDL(1); } catch (Exception &error_) { return new DLongGDL(0); } } // magic_id=CREATE (columns, rows [, "colorname"]) BaseGDL* magick_create(EnvT* e) { START_MAGICK; try { size_t nParam = e->NParam(2); DString col; DLong columns, rows; Geometry g; e->AssureScalarPar(0, columns); g.width(columns); e->AssureScalarPar(1, rows); g.height(rows); if (nParam == 3) { //truecolor e->AssureScalarPar(2, col); Image a(g, Color(col)); unsigned int mid; a.matte(false); mid = magick_image(e, a); return new DUIntGDL(mid); } else { Image a(g, Color("black")); unsigned int mid; a.matte(false); mid = magick_image(e, a); return new DUIntGDL(mid); } } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //CLOSE, magic_id void magick_close(EnvT *e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); if (mid > gCount - 1) e->Throw("Invalid ID"); else if (gValid[mid] == 0) e->Throw("ID not used"); gValid[mid] = 0; gImage[mid] = NULL; if (gCount - 1 == mid) gCount--; } catch (Exception &error_) { e->Throw(error_.what()); } } //image=MAGICK_READINDEXES(mid) //read an indexed image. BaseGDL* magick_readindexes(EnvT *e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); unsigned int columns, rows; Image image = magick_image(e, mid); if (image.classType() == DirectClass) e->Throw("Not an indexed image: " + e->GetParString(0)); columns = image.columns(); rows = image.rows(); if (image.matte() == 0) { SizeT c[2]; c[0] = columns; c[1] = rows; dimension dim(c, 2); DByteGDL *bImage = new DByteGDL(dim, BaseGDL::NOZERO); const PixelPacket* pixel; const IndexPacket* index; pixel = image.getPixels(0, 0, columns, rows); index = image.getIndexes(); if (index == NULL) { string txt = "Warning -- Magick's getIndexes() returned NULL for: "; string txt2 = ", using unsafe patch."; //PATCH to get something until we understand what's going on cerr << (txt + e->GetParString(0) + txt2) << endl; string map = "R"; image.write(0, 0, columns, rows, map, CharPixel, &(*bImage)[0]); return bImage; } unsigned int cx, cy; for (cy = 0; cy < rows; ++cy) for (cx = 0; cx < columns; ++cx) // note by AC, 07Feb2012: why this transpose here ?? // (*bImage)[cx+(rows-cy-1)*columns]= index[cx+(cy)*columns]; (*bImage)[cx + cy * columns] = index[cx + cy * columns]; return bImage; } else { // we do have to manage an extra channel for transparency string map = "RA"; SizeT c[3]; c[0] = map.length(); // see code "magick_read" below c[1] = columns; c[2] = rows; dimension dim(c, 3); DByteGDL *bImage = new DByteGDL(dim, BaseGDL::NOZERO); image.write(0, 0, columns, rows, map, CharPixel, &(*bImage)[0]); return bImage; } } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //MAGICK_READCOLORMAPRGB, mid, red, green, blue void magick_readcolormapRGB(EnvT* e) { START_MAGICK; try { size_t nParam = e->NParam(1); DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); if (image.classType() == DirectClass) e->Throw("Not an indexed image: " + e->GetParString(0)); if (image.classType() == PseudoClass) { unsigned int Quant, scale, i; if (QuantumDepth == 16) Quant = 65535; if (QuantumDepth == 8) Quant = 255; unsigned int cmapsize = image.colorMapSize(); dimension cmap(cmapsize, 1); Color col; #ifdef USE_MAGICK6 if (image.modulusDepth() <= 8) #else if (image.depth() <= 8) #endif { scale = 255; DByteGDL *R, *G, *B; R = new DByteGDL(cmap, BaseGDL::NOZERO); G = new DByteGDL(cmap, BaseGDL::NOZERO); B = new DByteGDL(cmap, BaseGDL::NOZERO); for (i = 0; i < cmapsize; ++i) { col = image.colorMap(i); (*R)[i] = (col.redQuantum()) * scale / Quant; (*G)[i] = (col.greenQuantum()) * scale / Quant; (*B)[i] = (col.blueQuantum()) * scale / Quant; } if (nParam > 1) e->SetPar(1, R); if (nParam > 2) e->SetPar(2, G); if (nParam > 3) e->SetPar(3, B); } #ifdef USE_MAGICK6 else if (image.modulusDepth() <= 16) #else else if (image.depth() <= 16) #endif { scale = 65536; DUIntGDL *R, *G, *B; R = new DUIntGDL(cmap, BaseGDL::NOZERO); G = new DUIntGDL(cmap, BaseGDL::NOZERO); B = new DUIntGDL(cmap, BaseGDL::NOZERO); for (i = 0; i < cmapsize; ++i) { col = image.colorMap(i); (*R)[i] = (col.redQuantum()) * scale / Quant; (*G)[i] = (col.greenQuantum()) * scale / Quant; (*B)[i] = (col.blueQuantum()) * scale / Quant; } if (nParam > 1) e->SetPar(1, R); if (nParam > 2) e->SetPar(2, G); if (nParam > 3) e->SetPar(3, B); } else { e->Throw("Uknown Image type, too many colors"); } } else { e->Throw("Not an indexed image: " + e->GetParString(0)); } } catch (Exception &error_) { e->Throw(error_.what()); } } // iImage = MAGIC_READ(magic_id [,RGB=rgb_code] [,SUB_RECT=[a,b,c,d]] [,MAP=map_code]) // rgb_code is 0="BGR", 1="RGB", 2="RBG", 3="BRG", 4="GRB", 5="GBR" // map_code is any of combination or order of R = red, G = green, B = blue, A = alpha, C = cyan, Y = yellow M = magenta, and K = black. // The ordering reflects the order of the pixels in the supplied pixel array. BaseGDL* magick_read(EnvT *e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); unsigned int columns, rows, lx, ly, wx, wy; Image image = magick_image(e, mid); columns = image.columns(); rows = image.rows(); if ((rows * columns) == 0) e->Throw("Error reading image dimensions!"); string map = "BGR"; if (e->GetKW(0) != NULL)//RGB { DInt rgb; e->AssureScalarKW(0, rgb); if (rgb == 0) map = "BGR"; else if (rgb == 1) map = "RGB"; else if (rgb == 2) map = "RBG"; else if (rgb == 3) map = "BRG"; else if (rgb == 4) map = "GRB"; else if (rgb == 5) map = "GBR"; else { string s = "MAGICK_READ: RGB order type not supported ("; s += i2s(rgb); s += "), using BGR ordering."; Message(s); map = "BGR"; } } if (image.matte()) map = map + "A"; if (e->KeywordSet(2)) //MAP e->AssureScalarPar(0, map); lx = 0; ly = 0; wx = columns; wy = rows; if (e->GetKW(1) != NULL)//SUB_RECT { BaseGDL* sr = e->GetKW(1); DULongGDL * subrect = static_cast (sr->Convert2(GDL_ULONG, BaseGDL::COPY)); if (subrect->N_Elements() != 4) e->Throw("Not enough elements in SUB_RECT, expected 4."); lx = (*subrect)[0]; //guaranteed to be >0 ly = (*subrect)[1]; wx = (*subrect)[2]; wy = (*subrect)[3]; if (wx > columns) e->Throw("Requested width exceeds number of columns, Either reduce the width or the X origin."); if (ly + wy > rows) e->Throw("Requested height exceeds number of rows. Either reduce the height or the Y origin."); } SizeT c[3]; c[0] = map.length(); c[1] = wx; c[2] = wy; dimension dim(c, 3); if (image.depth() == 8) { DByteGDL *bImage = new DByteGDL(dim, BaseGDL::NOZERO); image.write(lx, ly, wx, wy, map, CharPixel, &(*bImage)[0]); return bImage; } else if (image.depth() == 16) { DUIntGDL* iImage = new DUIntGDL(dim, BaseGDL::NOZERO); image.write(lx, ly, wx, wy, map, ShortPixel, &(*iImage)[0]); return iImage; } else { e->Throw("Unsupported bit depth"); } } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } // MAGICK_WRITE, mid, gdlImageArray, rgb=rgb //general purpose writing array of pixels to internal format at magic number mid. void magick_write(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); int columns, rows, planes; // StorageType ty; // ty=CharPixel; BaseGDL* GDLimage = e->GetParDefined(1); string map = "BGR"; if (GDLimage->Rank() == 3) { planes = GDLimage->Dim(0); columns = GDLimage->Dim(1); rows = GDLimage->Dim(2); if (planes == 2) { map = "IA"; } else { if (e->GetKW(0) != NULL)//RGB { DInt rgb; e->AssureScalarKW(0, rgb); if (rgb == 0) map = "BGR"; else if (rgb == 1) map = "RGB"; else if (rgb == 2) map = "RBG"; else if (rgb == 3) map = "BRG"; else if (rgb == 4) map = "GRB"; else if (rgb == 5) map = "GBR"; else { string s = "MAGICK_WRITE: RGB order type not supported ("; s += i2s(rgb); s += "), using BGR ordering."; Message(s); map = "BGR"; } if (image.matte()) map = map + "A"; } } DByteGDL * bImage = static_cast (GDLimage->Convert2(GDL_BYTE, BaseGDL::COPY)); Guard bImageGuard(bImage); image.read(columns, rows, map, CharPixel, &(*bImage)[0]); /* } else if(image.depth() == 16) { DUIntGDL * iImage= static_cast(GDLimage->Convert2(GDL_UINT,BaseGDL::COPY)); image.read(columns,rows,map, ShortPixel,&(*iImage)[0]); } else { e->Throw("Unsupported bit depth"); }*/ } else { columns = GDLimage->Dim(0); rows = GDLimage->Dim(1); DByteGDL * bImage = static_cast (GDLimage->Convert2(GDL_BYTE, BaseGDL::COPY)); Guard bImageGuard(bImage); // Ensure that there are no other references to this image. image.modifyImage(); // Set the image type to Palette. image.type(PaletteType); // if (image.colorMapSize() < 1) e->Throw("GDL internal: destination image has no colormap!"); image.size(Geometry(columns, rows)); image.setPixels(0,0,columns, rows); image.readPixels(IndexQuantum,(unsigned char*)bImage->DataAddr()); image.syncPixels(); } image.flip(); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_WRITEFILE, mid, filename, imageType void magick_writefile(EnvT* e) { START_MAGICK; try { size_t nParam = e->NParam(2); DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); DString filename; e->AssureScalarPar(1, filename); WordExp(filename); if (nParam == 3) { DString imagetype; e->AssureScalarPar(2, imagetype); image.magick(imagetype); } image.write(filename); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //Attributes //ncolors=MAGICK_COLORMAPSIZE(mid) BaseGDL* magick_colormapsize(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); size_t nParam = e->NParam(1); if (nParam == 2) { DUInt ncol; e->AssureScalarPar(1, ncol); image.colorMapSize(ncol); magick_replace(e, mid, image); } return new DLongGDL(image.colorMapSize()); } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //magickNumber=MAGICK_MAGICK(mid [, "imageType"]) BaseGDL* magick_magick(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); size_t nParam = e->NParam(1); if (nParam == 2) { DString format; e->AssureScalarPar(1, format); image.magick(format); magick_replace(e, mid, image); } return new DStringGDL(image.magick()); } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //nrows=MAGICK_ROWS(mid) BaseGDL* magick_rows(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); return new DLongGDL(image.rows()); } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //ncols=MAGICK_COLUMNS(mid) BaseGDL* magick_columns(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); return new DLongGDL(image.columns()); } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //bool=MAGICK_INDEXEDCOLOR(mid) BaseGDL* magick_IndexedColor(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); if (image.classType() == DirectClass) return new DIntGDL(0); if (image.classType() == PseudoClass) return new DIntGDL(1); } catch (Exception &error_) { e->Throw(error_.what()); } return NULL; //pacify -Wreturn-type } //MAGICK_QUALITY, mid, quality void magick_quality(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); DUInt q; size_t nParam = e->NParam(2); if (nParam == 2) e->AssureScalarPar(1, q); if (nParam == 2) q = 75; //check before we do anything. Image image = magick_image(e, mid); image.quality(q); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //manipulations //MAGIC_FLIP,mid void magick_flip(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); image.flip(); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_MATTE, mid void magick_matte(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); image.matte(true); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_MATTECOLOR, mid, index void magick_mattecolor(EnvT* e) { START_MAGICK; try { DUInt mid, index; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); e->AssureScalarPar(1, index); if (index >= 0 && index < image.colorMapSize()) { image.transparent(image.colorMap(index)); magick_replace(e, mid, image); } } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_INTERLACE, mid, /NOINTERLACE, /LINEINTERLACE, /PLANEINTERLACE void magick_interlace(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); //NoInterlace.......Don't interlace image (RGBRGBRGBRGBRGBRGB...) //LineInterlace.....Use scanline interlacing (RRR...GGG...BBB...RRR...GGG...BBB...) //PlaneInterlace....Use plane interlacing (RRRRRR...GGGGGG...BBBBBB...) if (e->KeywordSet(0))//NoInterlace image.interlaceType(NoInterlace); else if (e->KeywordSet(1))//LineInterlace image.interlaceType(LineInterlace); else if (e->KeywordSet(2))//PlaneInterlace image.interlaceType(PlaneInterlace); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_ADDNOISE,mid, /UNIFORMNOISE, /GAUSSIANNOISE, /MULTIPLICATIVEGAUSSIANNOISE, /IMPULSENOISE, /LAPLACIANNOISE", // /POISSONNOISE, NOISE=value void magick_addNoise(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); if (e->KeywordSet(0))//Uniform noise image.addNoise(UniformNoise); else if (e->KeywordSet(1))//Gaussian noise image.addNoise(GaussianNoise); else if (e->KeywordSet(2))//Multiplicative Gaussian noise image.addNoise(MultiplicativeGaussianNoise); else if (e->KeywordSet(3))//Impulse noise image.addNoise(ImpulseNoise); else if (e->KeywordSet(4))//Laplacian noise image.addNoise(LaplacianNoise); else if (e->KeywordSet(5))//Poisson noise image.addNoise(PoissonNoise); else if (e->GetKW(6) != NULL) { DInt noise; e->AssureScalarKW(6, noise); if (noise == 0)//Uniform noise image.addNoise(UniformNoise); else if (noise == 1)//Gaussian noise image.addNoise(GaussianNoise); else if (noise == 2)//Multiplicative Gaussian noise image.addNoise(MultiplicativeGaussianNoise); else if (noise == 3)//Impulse noise image.addNoise(ImpulseNoise); else if (noise == 4)//Laplacian noise image.addNoise(LaplacianNoise); else if (noise == 5)//Poisson noise image.addNoise(PoissonNoise); else e->Throw("Unknown noise type requested."); } else//no keyword image.addNoise(UniformNoise); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_QUANTIZE, mid [, ncolors] [,/TRUECOLOR] [,/YUV] [,/GRAYSCALE] [,/DITHER] void magick_quantize(EnvT* e) { START_MAGICK; try { size_t nParam = e->NParam(); DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); //set the number of colors; DLong ncol = 256; if (nParam > 1) e->AssureLongScalarPar(1, ncol); image.quantizeColors(ncol); static int TRUECOLORIx = e->KeywordIx("TRUECOLOR"); static int DITHERIx = e->KeywordIx("DITHER"); static int YUVIx = e->KeywordIx("YUV"); static int GRAYSCALEIx = e->KeywordIx("GRAYSCALE"); if (e->KeywordSet(TRUECOLORIx)) { image.quantizeColorSpace(RGBColorspace); image.quantizeColors((long) 256 * (long) 256 * (long) 256 - 1); if (e->KeywordSet(DITHERIx)) image.quantizeDither(true); image.quantize(); image.classType(DirectClass); } else { if (e->KeywordSet(YUVIx)) //YUV image.quantizeColorSpace(YUVColorspace); else if (e->KeywordSet(GRAYSCALEIx)) //Grayscale image.quantizeColorSpace(GRAYColorspace); else image.quantizeColorSpace(RGBColorspace); if (e->KeywordSet(DITHERIx)) image.quantizeDither(true); image.quantize(); image.classType(PseudoClass); } magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_DISPLAY,mid void magick_display(EnvT* e) { START_MAGICK; DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); image.display(); } void magick_writeIndexes(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); BaseGDL* GDLimage = e->GetParDefined(1); DByteGDL * bImage = static_cast (GDLimage->Convert2(GDL_BYTE, BaseGDL::COPY)); Image image = magick_image(e, mid); const PixelPacket* pixels; IndexPacket* index; unsigned int columns, rows; columns = image.columns(); rows = image.rows(); pixels = image.setPixels(0, 0, columns, rows); index = image.getIndexes(); SizeT nEl = columns*rows; // #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { // #pragma omp for for (SizeT cx = 0; cx < nEl; ++cx) { index[cx] = static_cast ((*bImage)[cx]); /* *index=(unsigned int)(*bImage)[cx]; index++;*/ } } image.syncPixels(); magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } //MAGICK_WRITECOLORTABLE,mid[,r,g,b] void magick_writeColorTable(EnvT* e) { START_MAGICK; try { DUInt mid; e->AssureScalarPar(0, mid); Image image = magick_image(e, mid); SizeT nparam = e->NParam(); if (nparam != 1 && nparam != 4) e->Throw("invalid number of parameters for MAGICK_WRITECOLORTABLE Procedure."); unsigned int scale; scale = 255; //these would be Palette type images I bet. image.type(PaletteType); if (nparam == 4) { //get passed LUT BaseGDL* GDLCol = e->GetParDefined(1); DByteGDL * Red = static_cast (GDLCol->Convert2(GDL_BYTE, BaseGDL::COPY)); //e->Guard( Red); Guard r_guard(Red); GDLCol = e->GetParDefined(2); DByteGDL * Green = static_cast (GDLCol->Convert2(GDL_BYTE, BaseGDL::COPY)); //e->Guard( Green); Guard g_guard(Green); GDLCol = e->GetParDefined(3); DByteGDL *Blue = static_cast (GDLCol->Convert2(GDL_BYTE, BaseGDL::COPY)); //e->Guard( Blue); Guard b_guard(Blue); if (Red->N_Elements() == Green->N_Elements() && Red->N_Elements() == Blue->N_Elements()) { unsigned long n = Red->N_Elements(); image.colorSpace(RGBColorspace); image.colorMapSize(n); image.quantize(n); for (unsigned long c = 0; c < n; ++c) image.colorMap(c, ColorRGB((double)(*Red)[c] / 255., (double)(*Green)[c] / 255., (double)(*Blue)[c] / 255.)); } } else { //GET current LOADCT LUT PLINT r[ctSize], g[ctSize], b[ctSize]; GraphicsDevice::GetDevice()->GetCT()->Get(r, g, b); unsigned long n = ctSize; image.colorSpace(RGBColorspace); image.colorMapSize(n); image.quantize(n); for (unsigned long c = 0; c < n; ++c) image.colorMap(c, ColorRGB((double)r[c] / 255., (double)g[c] / 255., (double)b[c] / 255.)); } magick_replace(e, mid, image); } catch (Exception &error_) { e->Throw(error_.what()); } } /* void magick_template(EnvT* e) { try{ DUInt mid; e->AssureScalarPar(0,mid); Image image=magick_image(e,mid); magick_replace(e,mid,image); } catch (Exception &error_ ) { e->Throw(error_.what()); } } */ } #endif gdl-0.9.9/src/magick_cl.hpp000066400000000000000000000046121340051421000155010ustar00rootroot00000000000000/*************************************************************************** image_fun_cl.hpp - basic GDL library functions ------------------- begin : May 7 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef MAGICK_HPP_CL #define MAGICK_HPP_CL #include namespace lib { using namespace Magick; using namespace std; using namespace antlr; //internal string GDLitos(int i); string GDLutos(unsigned int i); void magick_setup(void); unsigned int magick_id(void); Image& magick_image(EnvT * e,unsigned int mid); unsigned int magick_image(EnvT* e,Image &imImage); void magick_replace(EnvT* e, unsigned int mid, Image &imImage); //interface BaseGDL* magick_open(EnvT *e); BaseGDL* magick_create(EnvT *e); void magick_close(EnvT *e); BaseGDL* magick_read(EnvT *e); BaseGDL* magick_readindexes(EnvT *e); void magick_readcolormapRGB(EnvT *e); void magick_write(EnvT *e); void magick_writefile(EnvT *e); //Attributes BaseGDL * magick_IndexedColor(EnvT* e); BaseGDL * magick_rows(EnvT* e); BaseGDL * magick_columns(EnvT* e); BaseGDL * magick_colormapsize(EnvT* e); BaseGDL * magick_magick(EnvT* e); //manipulations void magick_flip(EnvT* e); void magick_matte(EnvT* e); void magick_mattecolor(EnvT* e); void magick_interlace(EnvT* e); void magick_addNoise(EnvT* e); void magick_quantize(EnvT* e); void magick_writeIndexes(EnvT* e); void magick_writeColorTable(EnvT* e); void magick_quality(EnvT* e); //hmm void magick_display(EnvT* e); // SA: query/ping routines support BaseGDL * magick_ping(EnvT* e); } #endif gdl-0.9.9/src/math_fun.cpp000066400000000000000000002206121340051421000153640ustar00rootroot00000000000000/*************************************************************************** math_fun.cpp - mathematical GDL library function ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include #include #include #include #include #include "objects.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "math_utl.hpp" #include "math_fun.hpp" //#define GDL_DEBUG #undef GDL_DEBUG #ifdef _MSC_VER #define round(f) floor(f+0.5) #endif namespace lib { using namespace std; template< typename srcT, typename destT> void TransposeFromToGSL( srcT* src, destT* dest, SizeT srcStride1, SizeT nEl) { for( SizeT d = 0, ix = 0, srcDim0 = 0; d= nEl) ix = ++srcDim0; } } template< typename srcT, typename destT> void FromToGSL( srcT* src, destT* dest, SizeT nEl) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( SizeT d = 0; dNParam( 4); static int doubleKWIx = e->KeywordIx( "DOUBLE"); bool doubleKW = e->KeywordSet( doubleKWIx); BaseGDL* A = e->GetParDefined( 0); doubleKW = doubleKW || (A->Type() == GDL_DOUBLE) || (A->Type() == GDL_COMPLEXDBL); if( doubleKW) { A = e->GetParAs< DDoubleGDL>( 0); } else { A = e->GetParAs< DFloatGDL>( 0); } if( A->Rank() != 2) e->Throw( "Argument must be a 2-D matrix: "+e->GetParString(0)); e->AssureGlobalPar( 1); // W e->AssureGlobalPar( 2); // U e->AssureGlobalPar( 3); // V static int columnKWIx = e->KeywordIx( "COLUMN"); bool columnKW = e->KeywordSet( columnKWIx); static int itmaxKWIx = e->KeywordIx( "ITMAX"); DLong itMax = 30; e->AssureLongScalarKWIfPresent( itmaxKWIx, itMax); DLong n; DLong m; if( columnKW) { n = A->Dim( 1); m = A->Dim( 0); } else { n = A->Dim( 0); m = A->Dim( 1); } if( m < n) e->Throw( "SVD of NxM matrix with N>M is not implemented yet."); DLong nEl = A->N_Elements(); if( doubleKW) { DDoubleGDL* AA = static_cast( A); gsl_matrix *aGSL = gsl_matrix_alloc( m, n); GDLGuard g1( aGSL, gsl_matrix_free); if( !columnKW) memcpy(aGSL->data, &(*AA)[0], nEl*sizeof( DDouble)); else TransposeFromToGSL< DDouble, double>( &(*AA)[0], aGSL->data, AA->Dim( 0), nEl); gsl_matrix *vGSL = gsl_matrix_alloc( n, n); GDLGuard g2( vGSL, gsl_matrix_free); gsl_vector *wGSL = gsl_vector_alloc( n); GDLGuard g3( wGSL, gsl_vector_free); gsl_vector *work = gsl_vector_alloc( n); GDLGuard g4( work, gsl_vector_free); gsl_linalg_SV_decomp( aGSL, vGSL, wGSL, work); // gsl_vector_free( work); // aGSL -> uGSL gsl_matrix *uGSL = aGSL; // why? // U DDoubleGDL* U = new DDoubleGDL( AA->Dim(), BaseGDL::NOZERO); if( !columnKW) memcpy( &(*U)[0], uGSL->data, nEl*sizeof( DDouble)); else TransposeFromToGSL< double, DDouble>( uGSL->data, &(*U)[0], U->Dim( 1), nEl); // gsl_matrix_free( uGSL); e->SetPar( 2, U); // V DDoubleGDL* V = new DDoubleGDL( dimension( n, n), BaseGDL::NOZERO); if( !columnKW) memcpy( &(*V)[0], vGSL->data, n*n*sizeof( DDouble)); else TransposeFromToGSL< double, DDouble>( vGSL->data, &(*V)[0], n, n*n); // gsl_matrix_free( vGSL); e->SetPar( 3, V); // W DDoubleGDL* W = new DDoubleGDL( dimension( n), BaseGDL::NOZERO); memcpy( &(*W)[0], wGSL->data, n*sizeof( DDouble)); // gsl_vector_free( wGSL); e->SetPar( 1, W); } else // float { DFloatGDL* AA = static_cast( A); gsl_matrix *aGSL = gsl_matrix_alloc( m, n); GDLGuard g1( aGSL, gsl_matrix_free); if( !columnKW) FromToGSL< DFloat, double>( &(*AA)[0], aGSL->data, nEl); else TransposeFromToGSL< DFloat, double>( &(*AA)[0], aGSL->data, AA->Dim( 0), nEl); gsl_matrix *vGSL = gsl_matrix_alloc( n, n); GDLGuard g2( vGSL, gsl_matrix_free); gsl_vector *wGSL = gsl_vector_alloc( n); GDLGuard g3( wGSL, gsl_vector_free); gsl_vector *work = gsl_vector_alloc( n); GDLGuard g4( work, gsl_vector_free); gsl_linalg_SV_decomp( aGSL, vGSL, wGSL, work); // gsl_vector_free( work); // aGSL -> uGSL gsl_matrix *uGSL = aGSL; // why? // U DFloatGDL* U = new DFloatGDL( AA->Dim(), BaseGDL::NOZERO); if( !columnKW) FromToGSL< double, DFloat>( uGSL->data, &(*U)[0], nEl); else TransposeFromToGSL< double, DFloat>( uGSL->data, &(*U)[0], U->Dim( 1), nEl); // gsl_matrix_free( uGSL); e->SetPar( 2, U); // V DFloatGDL* V = new DFloatGDL( dimension( n, n), BaseGDL::NOZERO); if( !columnKW) FromToGSL< double, DFloat>( vGSL->data, &(*V)[0], n*n); else TransposeFromToGSL< double, DFloat>( vGSL->data, &(*V)[0], n, n*n); // gsl_matrix_free( vGSL); e->SetPar( 3, V); // W DFloatGDL* W = new DFloatGDL( dimension( n), BaseGDL::NOZERO); FromToGSL< double, DFloat>( wGSL->data, &(*W)[0], n); // gsl_vector_free( wGSL); e->SetPar( 1, W); } } template< typename T> BaseGDL* sin_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); // eigen is not faster here // #ifdef USE_EIGEN // // Eigen::Map ,Eigen::Aligned> m1(&(*p0C)[0], nEl); // Eigen::Map ,Eigen::Aligned> m2(&(*res)[0], nEl); // m2 = m1.sin(); // return res; // #else if( nEl == 1) { (*res)[0] = sin( (*p0C)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1);//, "SIN"); // // BaseGDL* p0 = e->GetParDefined( 0);//, "SIN"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); DType p0Type = p0->Type(); if( p0Type == GDL_COMPLEX) return sin_fun_template< DComplexGDL>( p0); else if( p0Type == GDL_COMPLEXDBL) return sin_fun_template< DComplexDblGDL>( p0); else if( p0Type == GDL_DOUBLE) return sin_fun_template< DDoubleGDL>( p0); else if( p0Type == GDL_FLOAT) return sin_fun_template< DFloatGDL>( p0); else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* cos_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[0] = cos( (*p0C)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // SizeT nParam=e->NParam(); // // if( nParam == 0) // e->Throw( // "Incorrect number of arguments."); // // BaseGDL* p0 = e->GetParDefined( 0);//, "COS"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) return cos_fun_template< DComplexGDL>( p0); else if( p0->Type() == GDL_COMPLEXDBL) return cos_fun_template< DComplexDblGDL>( p0); else if( p0->Type() == GDL_DOUBLE) return cos_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return cos_fun_template< DFloatGDL>( p0); else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* tan_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[0] = tan( (*p0C)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* tan_fun_template< DComplexGDL>( BaseGDL* p0) { typedef DComplexGDL T; T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[0] = tan( static_cast((*p0C)[0])); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i((*p0C)[ i])); } } return res; } BaseGDL* tan_fun( BaseGDL* p0, bool isReference) { assert( p0 != NULL); assert( p0->N_Elements() > 0); // SizeT nParam=e->NParam(); // // if( nParam == 0) // e->Throw( // "Incorrect number of arguments."); // // BaseGDL* p0 = e->GetParDefined( 0);//, "TAN"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) return tan_fun_template< DComplexGDL>( p0); else if( p0->Type() == GDL_COMPLEXDBL) return tan_fun_template< DComplexDblGDL>( p0); else if( p0->Type() == GDL_DOUBLE) return tan_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return tan_fun_template< DFloatGDL>( p0); else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* sinh_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[0] = sinh( (*p0C)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // SizeT nParam=e->NParam(); // // if( nParam == 0) // e->Throw( // "Incorrect number of arguments."); // // BaseGDL* p0 = e->GetParDefined( 0);//, "SINH"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) return sinh_fun_template< DComplexGDL>( p0); else if( p0->Type() == GDL_COMPLEXDBL) return sinh_fun_template< DComplexDblGDL>( p0); else if( p0->Type() == GDL_DOUBLE) return sinh_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return sinh_fun_template< DFloatGDL>( p0); else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* cosh_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[0] = cosh( (*p0C)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // SizeT nParam=e->NParam(); // // if( nParam == 0) // e->Throw( // "Incorrect number of arguments."); // // BaseGDL* p0 = e->GetParDefined( 0);//, "COSH"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) return cosh_fun_template< DComplexGDL>( p0); else if( p0->Type() == GDL_COMPLEXDBL) return cosh_fun_template< DComplexDblGDL>( p0); else if( p0->Type() == GDL_DOUBLE) return cosh_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return cosh_fun_template< DFloatGDL>( p0); else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* tanh_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[0] = tanh( (*p0C)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // SizeT nParam=e->NParam(); // // if( nParam == 0) // e->Throw( // "Incorrect number of arguments."); // // BaseGDL* p0 = e->GetParDefined( 0);//, "TANH"); // // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) return tanh_fun_template< DComplexGDL>( p0); else if( p0->Type() == GDL_COMPLEXDBL) return tanh_fun_template< DComplexDblGDL>( p0); else if( p0->Type() == GDL_DOUBLE) return tanh_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return tanh_fun_template< DFloatGDL>( p0); else { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); SizeT nEl = p0->N_Elements(); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1);//, "ASIN"); // // BaseGDL* p0 = e->GetParDefined( 0);//, "ASIN"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL) { throw GDLException( "Operation illegal with complex type."); } else if( p0->Type() == GDL_DOUBLE) { DDoubleGDL* p0D = static_cast( p0); DDoubleGDL* res = new DDoubleGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = asin( (*p0D)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_FLOAT) { DFloatGDL* p0F = static_cast( p0); DFloatGDL* res = new DFloatGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = asin( (*p0F)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if( nEl == 1) { (*res)[0] = asin( (*res)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1);//, "ACOS"); // // BaseGDL* p0 = e->GetParDefined( 0);//, "ACOS"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( // "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL) { throw GDLException( "Operation illegal with complex type."); } else if( p0->Type() == GDL_DOUBLE) { DDoubleGDL* p0D = static_cast( p0); DDoubleGDL* res = new DDoubleGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = acos( (*p0D)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_FLOAT) { DFloatGDL* p0F = static_cast( p0); DFloatGDL* res = new DFloatGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = acos( (*p0F)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if( nEl == 1) { (*res)[0] = acos( (*res)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i inline C atanC(const C& c) { // double x = c.real(); // double x2 = x * x; // double y = c.imag(); // return C(0.5 * atan2(2.0*x, 1.0 - x2 - y*y), 0.25 * log( (x2 + (y+1)*(y+1)) / (x2 + (y-1)*(y-1)) )); const C i(0.0,1.0); const C one(1.0,0.0); return log( (one + i * c) / (one - i * c)) / (C(2.0,0.0)*i); } template< typename C> inline C atanC(const C& c1, const C& c2) { const C i(0.0,1.0); //const C one(1.0,0.0); // return -i * log((c2 + i * c1) / (sqrt(pow(c2, 2) + pow(c1, 2)))); return -i * log((c2 + i * c1) / sqrt((c2 * c2) + (c1 * c1))); } BaseGDL* atan_fun( EnvT* e) { SizeT nParam=e->NParam( 1);//, "ATAN"); BaseGDL* p0 = e->GetParDefined( 0);//, "ATAN"); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: "+e->GetParString(0)); if( nParam == 2) { BaseGDL* p1 = e->GetPar( 1); if( p1 == NULL) e->Throw( "Variable is undefined: "+e->GetParString(1)); SizeT nEl1 = p1->N_Elements(); if( nEl1 == 0) e->Throw( "Variable is undefined: "+e->GetParString(1)); DType t = (DTypeOrder[ p0->Type()] > DTypeOrder[ p1->Type()])? p0->Type() : p1->Type(); bool p0dim; if (p0->Rank() == 0 && p1->Rank() != 0) p0dim = false; else if (p0->Rank() != 0 && p1->Rank() == 0) p0dim = true; else if (nEl <= nEl1) p0dim = true; else p0dim = false; const dimension& dim = p0dim ? p0->Dim() : p1->Dim(); SizeT nElMin = p0dim ? nEl : nEl1; SizeT i, zero = 0, *i0, *i1; i0 = p0->Rank() == 0 ? &zero : &i, i1 = p1->Rank() == 0 ? &zero : &i; if( t == GDL_COMPLEX) { Guard< DComplexGDL> guard0; Guard< DComplexGDL> guard1; DComplexGDL* p0F = static_cast(p0->Convert2( GDL_COMPLEX, BaseGDL::COPY)); guard0.Init( p0F); DComplexGDL* p1F = static_cast(p1->Convert2( GDL_COMPLEX, BaseGDL::COPY)); guard1.Init( p1F); DComplexGDL* res = new DComplexGDL( dim, BaseGDL::NOZERO); for (i = 0; i < nElMin; ++i) (*res)[i] = atanC((*p0F)[*i0], (*p1F)[*i1]); return res; } else if( t == GDL_COMPLEXDBL) { Guard< DComplexDblGDL> guard0; Guard< DComplexDblGDL> guard1; DComplexDblGDL* p0F = static_cast(p0->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY)); guard0.Init( p0F); DComplexDblGDL* p1F = static_cast(p1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY)); guard1.Init( p1F); DComplexDblGDL* res = new DComplexDblGDL( dim, BaseGDL::NOZERO); for (i = 0; i < nElMin; ++i) (*res)[i] = atanC((*p0F)[*i0], (*p1F)[*i1]); return res; } else if( t == GDL_DOUBLE) { Guard< DDoubleGDL> guard; DDoubleGDL* p0D; if( p0->Type() != GDL_DOUBLE) { p0D = static_cast( p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard.Reset( p0D); } else { p0D = static_cast( p0); } DDoubleGDL* p1D; if( p1->Type() != GDL_DOUBLE) { p1D = static_cast( p1->Convert2( GDL_DOUBLE, BaseGDL::COPY)); guard.Reset( p1D); } else { p1D = static_cast( p1); } DDoubleGDL* res = new DDoubleGDL( dim, BaseGDL::NOZERO); for (i = 0; i < nElMin; ++i) (*res)[i] = atan2((*p0D)[*i0], (*p1D)[*i1]); return res; } else if( t == GDL_FLOAT) { Guard< DFloatGDL> guard; DFloatGDL* p0F; if( p0->Type() != GDL_FLOAT) { p0F = static_cast( p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); guard.Reset( p0F); } else { p0F = static_cast( p0); } DFloatGDL* p1F; if( p1->Type() != GDL_FLOAT) { p1F = static_cast( p1->Convert2( GDL_FLOAT, BaseGDL::COPY)); guard.Reset( p1F); } else { p1F = static_cast( p1); } DFloatGDL* res = new DFloatGDL( dim, BaseGDL::NOZERO); for (i = 0; i < nElMin; ++i) (*res)[i] = (float)atan2((double)(*p0F)[*i0], (double)(*p1F)[*i1]); return res; } else { Guard< DFloatGDL> guard0; Guard< DFloatGDL> guard1; DFloatGDL* p0F = static_cast(p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); guard0.Init( p0F); DFloatGDL* p1F = static_cast(p1->Convert2( GDL_FLOAT, BaseGDL::COPY)); guard1.Init( p1F); DFloatGDL* res = new DFloatGDL( dim, BaseGDL::NOZERO); for (i = 0; i < nElMin; ++i) (*res)[i] = (float)atan2((double)(*p0F)[*i0], (double)(*p1F)[*i1]); return res; } } else { static int phaseIx = e->KeywordIx("PHASE"); static float half_pi_f = .5 * atan((float(1))); static double half_pi_d = .5 * atan(double(1)); if( p0->Type() == GDL_COMPLEX && e->KeywordSet(phaseIx)) { DComplexGDL* p0C = static_cast( p0); DFloatGDL* res = new DFloatGDL( p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (float)atan2((double)C.imag(), (double)C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); DComplexGDL* res = new DComplexGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = atanC((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL && e->KeywordSet(phaseIx)) { DComplexDblGDL* p0C = static_cast( p0); DDoubleGDL* res = new DDoubleGDL( p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = atan2( C.imag(), C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); DComplexDblGDL* res = new DComplexDblGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = atanC((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_DOUBLE) { DDoubleGDL* p0D = static_cast( p0); DDoubleGDL* res = new DDoubleGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = atan((*p0D)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_FLOAT) { DFloatGDL* p0F = static_cast( p0); DFloatGDL* res = new DFloatGDL( p0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = atan((*p0F)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if( nEl == 1) { (*res)[ 0] = atan((*res)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i // BaseGDL* alog_fun_template( BaseGDL* p0) // { // T* p0C = static_cast( p0); // T* res = new T( p0C->Dim(), BaseGDL::NOZERO); // SizeT nEl = p0->N_Elements(); // for( SizeT i=0; iN_Elements() > 0); if( !isReference) //e->StealLocalPar( 0)) { return p0->LogThis(); } return p0->Log(); // if( FloatType( p0->Type()) || ComplexType( p0->Type())) // if( !isReference) //e->StealLocalPar( 0)) // { // p0->LogThis(); // return p0; // } // else // return p0->Log(); // else // { // DFloatGDL* res = static_cast // (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); // res->LogThis(); // return res; // } } // BaseGDL* alog10_fun( EnvT* e) BaseGDL* alog10_fun( BaseGDL* p0, bool isReference) { assert( p0 != NULL); assert( p0->N_Elements() > 0); if( !isReference) //e->StealLocalPar( 0)) { return p0->Log10This(); } return p0->Log10(); // if( FloatType( p0->Type()) || ComplexType( p0->Type())) // if( !isReference) //e->StealLocalPar( 0)) // { // p0->Log10This(); // return p0; // } // else // return p0->Log10(); // else // { // DFloatGDL* res = static_cast // (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); // res->Log10This(); // return res; // } } // original by joel gales template< typename T> BaseGDL* sqrt_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = sqrt((*p0C)[ 0]); return res; } // eigen is not faster here //#ifdef USE_EIGEN // // Eigen::Map ,Eigen::Aligned> mP0C(&(*p0C)[0], nEl); // Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); // mRes = mP0C.sqrt(); // return res; //#else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* sqrt_fun_template_grab( BaseGDL* p0) { T* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*p0C)[ 0] = sqrt((*p0C)[ 0]); return p0C; } // eigen is not faster here //#ifdef USE_EIGEN // // Eigen::Map ,Eigen::Aligned> mP0C(&(*p0C)[0], nEl); // mP0C = mP0C.sqrt(); // return p0C; //#else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); DType p0Type = p0->Type(); if( isReference) { if( p0Type == GDL_COMPLEX) return sqrt_fun_template< DComplexGDL>( p0); else if( p0Type == GDL_COMPLEXDBL) return sqrt_fun_template< DComplexDblGDL>( p0); else if( p0Type == GDL_DOUBLE) return sqrt_fun_template< DDoubleGDL>( p0); else if( p0Type == GDL_FLOAT) return sqrt_fun_template< DFloatGDL>( p0); } else { if( p0Type == GDL_COMPLEX) return sqrt_fun_template_grab< DComplexGDL>( p0); else if( p0Type == GDL_COMPLEXDBL) return sqrt_fun_template_grab< DComplexDblGDL>( p0); else if( p0Type == GDL_DOUBLE) return sqrt_fun_template_grab< DDoubleGDL>( p0); else if( p0Type == GDL_FLOAT) return sqrt_fun_template_grab< DFloatGDL>( p0); } { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = sqrt( (*res)[ 0]); return res; } // eigen is not faster here //#ifdef USE_EIGEN // // Eigen::Map ,Eigen::Aligned> mRes(&(*res)[0], nEl); // mRes = mRes.sqrt(); // return res; //#else TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* abs_fun_template( BaseGDL* p0) { T* p0C = static_cast( p0); T* res = new T( p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = abs((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1); // // BaseGDL* p0 = e->GetParDefined( 0); // // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); DFloatGDL* res = new DFloatGDL(p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = abs((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); DDoubleGDL* res = new DDoubleGDL(p0C->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = abs((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_DOUBLE) return abs_fun_template< DDoubleGDL>( p0); else if( p0->Type() == GDL_FLOAT) return abs_fun_template< DFloatGDL>( p0); else if( p0->Type() == GDL_LONG64) return abs_fun_template< DLong64GDL>( p0); else if( p0->Type() == GDL_LONG) return abs_fun_template< DLongGDL>( p0); else if( p0->Type() == GDL_INT) return abs_fun_template< DIntGDL>( p0); else if( isReference) { if( p0->Type() == GDL_ULONG64) return p0->Dup(); else if( p0->Type() == GDL_ULONG) return p0->Dup(); else if( p0->Type() == GDL_UINT) return p0->Dup(); else if( p0->Type() == GDL_BYTE) return p0->Dup(); } else { if( p0->Type() == GDL_ULONG64) return p0; else if( p0->Type() == GDL_ULONG) return p0; else if( p0->Type() == GDL_UINT) return p0; else if( p0->Type() == GDL_BYTE) return p0; } DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = abs((*res)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* round_fun_template( BaseGDL* p0, bool isKWSetL64) { T* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = static_cast( round((*p0C)[ 0])); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i( round((*p0C)[ i])); } } return res; } else { DLongGDL* res = new DLongGDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = static_cast( round((*p0C)[ 0])); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i( round((*p0C)[ i])); } } return res; } } BaseGDL* round_fun( EnvT* e) { e->NParam( 1);//, "ROUND"); BaseGDL* p0 = e->GetParDefined( 0);//, "ROUND"); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "ROUND: Variable is undefined: "+e->GetParString(0)); static SizeT l64Ix = e->KeywordIx( "L64"); bool isKWSetL64 = e->KeywordSet( l64Ix); if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (DLong64) round(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (int) round(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = (DLong64) round(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = (int) round(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_DOUBLE) return round_fun_template< DDoubleGDL>( p0, isKWSetL64); else if( p0->Type() == GDL_FLOAT) return round_fun_template< DFloatGDL>( p0, isKWSetL64); else if( p0->Type() == GDL_LONG64) return p0->Dup(); else if( p0->Type() == GDL_LONG) return p0->Dup(); else if( p0->Type() == GDL_INT) return p0->Dup(); else if( p0->Type() == GDL_ULONG64) return p0->Dup(); else if( p0->Type() == GDL_ULONG) return p0->Dup(); else if( p0->Type() == GDL_UINT) return p0->Dup(); else if( p0->Type() == GDL_BYTE) return p0->Dup(); else { DFloatGDL* p0F = e->GetParAs( 0); DLongGDL* res = new DLongGDL(p0->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = (int) round((double) (*p0F)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* ceil_fun_template( BaseGDL* p0, bool isKWSetL64) { T* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = (DLong64) ceil((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = (int) ceil((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iNParam( 1);//, "CEIL"); BaseGDL* p0 = e->GetParDefined( 0);//, "CEIL"); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: "+e->GetParString(0)); bool isKWSetL64 = e->KeywordSet(0); //L64, same place in ceil and floor. if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (DLong64) ceil(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (int) ceil(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = (DLong64) ceil(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = (int) ceil(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_DOUBLE) return ceil_fun_template< DDoubleGDL>( p0, isKWSetL64); else if( p0->Type() == GDL_FLOAT) return ceil_fun_template< DFloatGDL>( p0, isKWSetL64); else if( p0->Type() == GDL_LONG64) return p0->Dup(); else if( p0->Type() == GDL_LONG) return p0->Dup(); else if( p0->Type() == GDL_INT) return p0->Dup(); else if( p0->Type() == GDL_ULONG64) return p0->Dup(); else if( p0->Type() == GDL_ULONG) return p0->Dup(); else if( p0->Type() == GDL_UINT) return p0->Dup(); else if( p0->Type() == GDL_BYTE) return p0->Dup(); else { DFloatGDL* p0F = e->GetParAs( 0); DLongGDL* res = new DLongGDL(p0->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = (int) ceil((double) (*p0F)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i BaseGDL* floor_fun_template( BaseGDL* p0, bool isKWSetL64) { T* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = (DLong64) floor((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = (int) floor((*p0C)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iNParam( 1);//, "FLOOR"); BaseGDL* p0 = e->GetParDefined( 0);//, "FLOOR"); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: "+e->GetParString(0)); bool isKWSetL64 = e->KeywordSet( 0 ); //L64, same place in ceil and floor. if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (DLong64) floor(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { DComplex& C = (*p0C)[ 0]; (*res)[ 0] = (int) floor(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); SizeT nEl = p0->N_Elements(); // L64 keyword support if (isKWSetL64) { DLong64GDL* res = new DLong64GDL(p0C->Dim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = (DLong64) floor(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iDim(), BaseGDL::NOZERO); if( nEl == 1) { DComplexDbl& C = (*p0C)[ 0]; (*res)[ 0] = (int) floor(C.real()); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_DOUBLE) return floor_fun_template< DDoubleGDL>( p0, isKWSetL64); else if( p0->Type() == GDL_FLOAT) return floor_fun_template< DFloatGDL>( p0, isKWSetL64); else if( p0->Type() == GDL_LONG64) return p0->Dup(); else if( p0->Type() == GDL_LONG) return p0->Dup(); else if( p0->Type() == GDL_INT) return p0->Dup(); else if( p0->Type() == GDL_ULONG64) return p0->Dup(); else if( p0->Type() == GDL_ULONG) return p0->Dup(); else if( p0->Type() == GDL_UINT) return p0->Dup(); else if( p0->Type() == GDL_BYTE) return p0->Dup(); else { DFloatGDL* p0F = e->GetParAs( 0); DLongGDL* res = new DLongGDL(p0->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); if( nEl == 1) { (*res)[ 0] = (int) floor((double) (*p0F)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iN_Elements() > 0); // e->NParam( 1); // BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( "Variable is undefined: "+e->GetParString(0)); if( p0->Type() == GDL_COMPLEX) { DComplexGDL* res = static_cast(p0)->NewResult();// static_cast(p0->Dup()); DComplexGDL* p0C = static_cast(p0); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* res = static_cast(p0)->NewResult();//static_cast(p0->Dup()); DComplexDblGDL* p0C = static_cast(p0); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iType() == GDL_DOUBLE || p0->Type() == GDL_LONG64 || p0->Type() == GDL_ULONG64) { DComplexDblGDL* res = static_cast (p0->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY)); return res; } // all other types DComplexGDL* res = static_cast( p0->Convert2( GDL_COMPLEX, BaseGDL::COPY)); return res; } BaseGDL* imaginary_fun( BaseGDL* p0, bool isReference)//( EnvT* e) { assert( p0 != NULL); assert( p0->N_Elements() > 0); // e->NParam( 1); // BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( "Variable is undefined: "+e->GetParString(0)); // complex types, return imaginary part if( p0->Type() == GDL_COMPLEX) { DComplexGDL* c0 = static_cast(p0); DFloatGDL* res = new DFloatGDL( c0->Dim(), BaseGDL::NOZERO); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( SizeT i=0; iType() == GDL_COMPLEXDBL) { DComplexDblGDL* c0 = static_cast(p0); DDoubleGDL* res = new DDoubleGDL( c0->Dim(), BaseGDL::NOZERO); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( SizeT i=0; iType(); if( t == GDL_STRING) throw GDLException( "String expression not allowed in this context."); if( t == GDL_STRUCT) throw GDLException( "Struct expression not allowed in this context."); if( t == GDL_PTR) throw GDLException( "Pointer expression not allowed in this context."); if( t == GDL_OBJ) throw GDLException( "Object reference not allowed in this context."); // all other types (return array of zeros) DFloatGDL* res = new DFloatGDL( p0->Dim()); // ZERO return res; } BaseGDL* exp_fun( BaseGDL* p0, bool isReference) { assert( p0 != NULL); assert( p0->N_Elements() > 0); // e->NParam( 1); // BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); DType t = p0->Type(); if( t == GDL_COMPLEXDBL) { DComplexDblGDL *c0 = static_cast< DComplexDblGDL*>( p0); DComplexDblGDL *res = c0->New( c0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = exp( (*c0)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i( p0); DComplexGDL *res = c0->New( c0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = exp( (*c0)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i( p0); DDoubleGDL *res = c0->New( c0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = exp( (*c0)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i( p0); DFloatGDL *res = c0->New( c0->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[ 0] = exp( (*c0)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i( p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if( nEl == 1) { (*res)[ 0] = exp( (*res)[ 0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; iNParam(1); DDoubleGDL* v = static_cast(e->GetParDefined(0)-> Convert2(GDL_DOUBLE,BaseGDL::COPY)); SizeT nv = v->N_Elements(); for (int count = 0;count < nv;++count) (*v)[count] = gsl_cdf_ugaussian_P((*v)[count]); if (e->GetParDefined(0)->Type() == GDL_DOUBLE) return v; else return v->Convert2(GDL_FLOAT,BaseGDL::CONVERT); return new DByteGDL(0); } // by medericboquien@users.sourceforge.net BaseGDL* gauss_cvf(EnvT* e) { SizeT nParam = e->NParam(1); DDoubleGDL* p = static_cast(e->GetParDefined(0)-> Convert2(GDL_DOUBLE,BaseGDL::COPY)); if (p->N_Elements() != 1) e->Throw("Parameter must be scalar or one element array: "+ e->GetParString(0)); if ((*p)[0] < 0. || (*p)[0] > 1.) e->Throw("Parameter must be in [0,1]: "+e->GetParString(0)); (*p)[0] = gsl_cdf_ugaussian_Qinv((*p)[0]); if (e->GetParDefined(0)->Type() == GDL_DOUBLE) return p; else return p->Convert2(GDL_FLOAT,BaseGDL::CONVERT); return new DByteGDL(0); } // by medericboquien@users.sourceforge.net BaseGDL* t_pdf(EnvT* e) { SizeT nParam = e->NParam(2); DDoubleGDL* v = e->GetParAs(0); DDoubleGDL* df = e->GetParAs(1); DDoubleGDL* res; SizeT nv = v->N_Elements(); SizeT ndf = df->N_Elements(); for (int i=0;iThrow("Degrees of freedom must be positive."); if (nv == 1 && ndf == 1) { res = new DDoubleGDL(dimension(1), BaseGDL::NOZERO); (*res)[0] = gsl_cdf_tdist_P((*v)[0],(*df)[0]); } else if (nv > 1 && ndf == 1) { res = new DDoubleGDL(dimension(nv), BaseGDL::NOZERO); for (SizeT count = 0; count < nv; ++count) (*res)[count] = gsl_cdf_tdist_P((*v)[count],(*df)[0]); } else if (nv == 1 && ndf > 1) { res = new DDoubleGDL(dimension(ndf), BaseGDL::NOZERO); for (SizeT count = 0; count < ndf; ++count) (*res)[count] = gsl_cdf_tdist_P((*v)[0],(*df)[count]); } else { SizeT nreturn = nv>ndf?ndf:nv; res = new DDoubleGDL(dimension(nreturn), BaseGDL::NOZERO); for (SizeT count = 0; count < nreturn; ++count) (*res)[count] = gsl_cdf_tdist_P((*v)[count],(*df)[count]); } if (e->GetParDefined(0)->Type() != GDL_DOUBLE && e->GetParDefined(0)->Type() != GDL_DOUBLE) return res->Convert2(GDL_FLOAT,BaseGDL::CONVERT); else return res; return new DByteGDL(0); } // by medericboquien@users.sourceforge.net BaseGDL* laguerre(EnvT* e) { SizeT nParam = e->NParam(2); DDoubleGDL* xvals = e->GetParAs(0); if(e->GetParDefined(0)->Type() == GDL_COMPLEX || e->GetParDefined(0)->Type() == GDL_COMPLEXDBL) e->Throw("Complex Laguerre not implemented: "); DIntGDL* nval = e->GetParAs(1); if (nval->N_Elements() != 1) e->Throw("N and K must be scalars."); if ((*nval)[0] < 0) e->Throw("Argument N must be greater than or equal to zero."); DDoubleGDL* kval; Guard kval_guard; if (nParam>2) { kval = e->GetParAs(2); if(kval->N_Elements() != 1) e->Throw("N and K must be scalars."); if ((*kval)[0] < 0.) e->Throw("Argument K must be greater than or equal to zero."); } else { kval = new DDoubleGDL(0); kval_guard.Reset(kval); } DDoubleGDL* res = new DDoubleGDL(xvals->Dim(),BaseGDL::NOZERO); DDouble k = (*kval)[0]; DInt n = (*nval)[0]; SizeT nEx = xvals->N_Elements(); OMPInt count; TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEx >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEx)) { #pragma omp for for (count = 0;countKeywordIx("DOUBLE"); static DInt coefKWIx = e->KeywordIx("COEFFICIENTS"); if(e->KeywordPresent(coefKWIx)) { double gamma_kn1 = gsl_sf_gamma(k+n+1.); DDoubleGDL* coefKW = new DDoubleGDL(dimension(n+1) , BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (n >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= n)) { #pragma omp for for(count = 0;count<=n;++count) { double dcount = static_cast(count); (*coefKW)[count] = ((count & 0x0001)?-1.0:1.0)*gamma_kn1/ (gsl_sf_gamma(n-dcount+1.)*gsl_sf_gamma(k+dcount+1.)* gsl_sf_gamma(dcount+1.)); } } if(e->GetParDefined(0)->Type() != GDL_DOUBLE && !e->KeywordSet(doubleKWIx)) coefKW = static_cast(coefKW-> Convert2(GDL_FLOAT,BaseGDL::CONVERT)); e->SetKW(coefKWIx, coefKW); } //convert things back if(e->GetParDefined(0)->Type() != GDL_DOUBLE && !e->KeywordSet(doubleKWIx)) return res->Convert2(GDL_FLOAT,BaseGDL::CONVERT); else return res; } // SA: based on equations 5-5 & 5-6 from Snyder (1987) USGS report no 1395 (page 31) // available for download at: http://pubs.er.usgs.gov/djvu/PP/pp_1395.djvu template inline void ll_arc_distance_helper( T c, T Az, T phi1, T l0, T& phi, T& l, bool degrees) { // temporary variables T pi = 4 * atan((T)1.), dtor = degrees ? pi / 180. : 1, sin_c = sin(c), cos_c = cos(c), cos_Az = cos(Az * dtor), sin_phi1 = sin(phi1 * dtor), cos_phi1 = cos(phi1 * dtor); // computing the results phi = asin(sin_phi1 * cos_c + cos_phi1 * sin_c * cos_Az) / dtor; l = l0 * dtor + atan2( sin_c * sin(Az * dtor), (cos_phi1 * cos_c - sin_phi1 * sin_c * cos_Az) ); // placing the result in (-pi, pi) while (l < -pi) l += 2 * pi; while (l > pi) l -= 2 * pi; // converting to degrees if needed l /= dtor; } BaseGDL* ll_arc_distance(EnvT* e) { // sanity check (for number of parameters) SizeT nParam = e->NParam(); // 1-st argument : longitude/latitude values pair (in radians unless DEGREE kw. present) BaseGDL* p0 = e->GetNumericParDefined(0); // 2-nd argument : arc distance (in radians regardless of DEGREE kw. presence) BaseGDL* p1 = e->GetNumericParDefined(1); if (p1->N_Elements() != 1) e->Throw("second argument is expected to be a scalar or 1-element array"); // 3-rd argument : azimuth (in radians unless DEGREE kw. present) BaseGDL* p2 = e->GetNumericParDefined(2); if (p2->N_Elements() != 1) e->Throw("third argument is expected to be a scalar or 1-element array"); // chosing a type for the return value bool args_complexdbl = (p0->Type() == GDL_COMPLEXDBL || p1->Type() == GDL_COMPLEXDBL || p2->Type() == GDL_COMPLEXDBL); bool args_complex = args_complexdbl ? false : (p0->Type() == GDL_COMPLEX || p1->Type() == GDL_COMPLEX || p2->Type() == GDL_COMPLEX); DType type = ( p0->Type() == GDL_DOUBLE || p1->Type() == GDL_DOUBLE || p2->Type() == GDL_DOUBLE || args_complexdbl ) ? GDL_DOUBLE : GDL_FLOAT; // converting datatypes if neccesarry if (p0->Type() != type) p0 = p0->Convert2(type, BaseGDL::COPY); if (p1->Type() != type) p1 = p1->Convert2(type, BaseGDL::COPY); if (p2->Type() != type) p2 = p2->Convert2(type, BaseGDL::COPY); // calculating (by calling a helper template function for float/double versions) BaseGDL* rt = p0->New(dimension(2, BaseGDL::NOZERO)); if (type == GDL_FLOAT) { ll_arc_distance_helper( (*static_cast(p1))[0], (*static_cast(p2))[0], (*static_cast(p0))[1], (*static_cast(p0))[0], (*static_cast(rt))[1], (*static_cast(rt))[0], e->KeywordSet(0) //DEGREES (sole option) ); } else { ll_arc_distance_helper( (*static_cast(p1))[0], (*static_cast(p2))[0], (*static_cast(p0))[1], (*static_cast(p0))[0], (*static_cast(rt))[1], (*static_cast(rt))[0], e->KeywordSet(0) ); } // handling complex/dcomplex conversion return rt->Convert2( args_complexdbl ? GDL_COMPLEXDBL : args_complex ? GDL_COMPLEX : type, BaseGDL::CONVERT ); } BaseGDL* crossp(EnvT* e) { BaseGDL* p0 = e->GetNumericParDefined(0); BaseGDL* p1 = e->GetNumericParDefined(1); if (p0->N_Elements() != 3 || p1->N_Elements() != 3) e->Throw("Both arguments must have 3 elements"); BaseGDL *a, *b, *c; a = (DTypeOrder[p0->Type()] >= DTypeOrder[p1->Type()] ? p0 : p1)->New(dimension(3), BaseGDL::ZERO); // a = 0 // .--mem: new a (with the type and shape of the result) b = p0->CShift(-1)->Convert2(a->Type(), BaseGDL::CONVERT); // | .--mem: new b a->Add(b); // | | a = shift(p0, -1) delete b; // | `--mem: del b b = p1->CShift(-2)->Convert2(a->Type(), BaseGDL::CONVERT); // | .--mem: new b a->Mult(b); // | | a = shift(p0, -1) * shift(p1, -2) b->Sub(b); // | | b = 0 c = p0->CShift(1)->Convert2(a->Type(), BaseGDL::CONVERT); // | | .--mem: new c b->Sub(c); // | | | b = - shift(p0, 1) delete c; // | | `--mem: del c c = p1->CShift(2)->Convert2(a->Type(), BaseGDL::CONVERT); // | | .--mem: new c b->Mult(c); // | | | b = - shift(p0, 1) * shift(p1, 2) delete c; // | | `--mem: del c a->Add(b); // | | a = shift(p0, -1) * shift(p1, -2) - shift(p0, 1) * shift(p1, 2) delete b; // | `--mem: del b return a; // `---> } // SA: adapted from the GPL-licensed GNU plotutils (plotutils-2.5/ode/specfun.c) // ----------------------------------------------------------------------------- template T inverf (T p) /* Inverse Error Function */ { /* * Source: This routine was derived (using f2c) from the Fortran * subroutine MERFI found in ACM Algorithm 602, obtained from netlib. * * MDNRIS code is copyright 1978 by IMSL, Inc. Since MERFI has been * submitted to netlib, it may be used with the restrictions that it may * only be used for noncommercial purposes, and that IMSL be acknowledged * as the copyright-holder of the code. */ /* Initialized data */ static T a1 = -.5751703, a2 = -1.896513, a3 = -.05496261, b0 = -.113773, b1 = -3.293474, b2 = -2.374996, b3 = -1.187515, c0 = -.1146666, c1 = -.1314774, c2 = -.2368201, c3 = .05073975, d0 = -44.27977, d1 = 21.98546, d2 = -7.586103, e0 = -.05668422, e1 = .3937021, e2 = -.3166501, e3 = .06208963, f0 = -6.266786, f1 = 4.666263, f2 = -2.962883, g0 = 1.851159e-4, g1 = -.002028152, g2 = -.1498384, g3 = .01078639, h0 = .09952975, h1 = .5211733, h2 = -.06888301; /* Local variables */ static T a, b, f, w, x, y, z, sigma, z2, sd, wi, sn; x = p; /* determine sign of x */ sigma = (x > 0 ? 1.0 : -1.0); /* Note: -1.0 < x < 1.0 */ z = abs(x); /* z between 0.0 and 0.85, approx. f by a rational function in z */ if (z <= 0.85) { z2 = z * z; f = z + z * (b0 + a1 * z2 / (b1 + z2 + a2 / (b2 + z2 + a3 / (b3 + z2)))); } else /* z greater than 0.85 */ { a = 1.0 - z; b = z; /* reduced argument is in (0.85,1.0), obtain the transformed variable */ w = sqrt(-(T)log(a + a * b)); if (w >= 4.0) /* w greater than 4.0, approx. f by a rational function in 1.0 / w */ { wi = 1.0 / w; sn = ((g3 * wi + g2) * wi + g1) * wi; sd = ((wi + h2) * wi + h1) * wi + h0; f = w + w * (g0 + sn / sd); } else if (w < 4.0 && w > 2.5) /* w between 2.5 and 4.0, approx. f by a rational function in w */ { sn = ((e3 * w + e2) * w + e1) * w; sd = ((w + f2) * w + f1) * w + f0; f = w + w * (e0 + sn / sd); /* w between 1.13222 and 2.5, approx. f by a rational function in w */ } else if (w <= 2.5 && w > 1.13222) { sn = ((c3 * w + c2) * w + c1) * w; sd = ((w + d2) * w + d1) * w + d0; f = w + w * (c0 + sn / sd); } } y = sigma * f; return y; } // ----------------------------------------------------------------------------- BaseGDL* gdl_erfinv_fun(EnvT* e) { BaseGDL* p0 = e->GetNumericParDefined(0); SizeT n = p0->N_Elements(); static int doubleIx = e->KeywordIx("DOUBLE"); if (e->KeywordSet(doubleIx) || p0->Type() == GDL_DOUBLE) { DDoubleGDL *ret = new DDoubleGDL(dimension(n)), *p0d = e->GetParAs(0); while (n != 0) --n, (*ret)[n] = inverf((*p0d)[n]); return ret; } else { DFloatGDL *ret = new DFloatGDL(dimension(n)), *p0f = e->GetParAs(0); while (n != 0) --n, (*ret)[n] = inverf((*p0f)[n]); return ret; } } } // namespace gdl-0.9.9/src/math_fun.hpp000066400000000000000000000050731340051421000153730ustar00rootroot00000000000000/*************************************************************************** math_fun.hpp - mathematical GDL library function ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef MATH_FUN_HPP_ #define MATH_FUN_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { void svdc( EnvT* e); BaseGDL* sin_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* cos_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* tan_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* sinh_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* cosh_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* tanh_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* asin_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* acos_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* atan_fun( EnvT* e); BaseGDL* alog_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* alog10_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* sqrt_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* abs_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* round_fun( EnvT* e); BaseGDL* floor_fun( EnvT* e); BaseGDL* ceil_fun( EnvT* e); BaseGDL* conj_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* imaginary_fun( BaseGDL* p0, bool isReference);//( EnvT* e); BaseGDL* exp_fun( BaseGDL* p0, bool isReference);//( EnvT* e); // by medericboquien@users.sourceforge.net BaseGDL* gauss_pdf(EnvT* e); BaseGDL* gauss_cvf(EnvT* e); BaseGDL* t_pdf(EnvT* e); BaseGDL* laguerre(EnvT* e); // by Sylwester Arabas BaseGDL* ll_arc_distance(EnvT* e); BaseGDL* crossp(EnvT* e); BaseGDL* gdl_erfinv_fun(EnvT* e); } // namespace #endif gdl-0.9.9/src/math_fun_ac.cpp000066400000000000000000001147011340051421000160300ustar00rootroot00000000000000/*************************************************************************** math_fun_ac.cpp - math GDL library function (AC) ------------------- begin : 20 April 2007 copyright : (C) 2007 by Alain Coulais email : alaingdl@users.sourceforge.net ****************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* using the Besel functions provided by GSL http://www.physics.ohio-state.edu/~ntg/780/gsl_examples/J0_test.cpp http://www.gnu.org/software/gsl/manual/html_node/Bessel-Functions.html ----------------------- Warning ------------- (obsolete) As is on 20/April/2007: Warning : GSL allows only INTEGER type for order Thibaut contributes to extend to REAL in July 2009 Important information: since bad formating issue in IDL (only first field in BESEL*([1], [1,2,3.]) is OK, doc said IDL must return a [1elem] array but return a [3elem] (see converse case BESELI( [1,2,3.], [1]))) WE decided to follow IDL but to compute all the cases ... Note on 28/July/2009: when called with only X elements in IDL, Besel* functions are computed with implicit N==0, we don't follow this undocumented feature ... ----------------------- Warning ------------- Since functions are clones derivated from the first one, please propagates bugs' correction and improvments. Don't know how to symplified :-( ----------------------- Warning ------------- some codes here (macro) are common with "math_fun_gm.cpp" and "math_fun_ng.cpp" */ #define GM_EPS 1.0e-6 #define GM_ITER 50 #define GM_TINY 1.0e-18 #define GM_MIN(a, b) ((a) < (b) ? (a) : (b)) #define GM_5P0(a) \ e->NParam(a); \ \ DDoubleGDL* p0 = e->GetParAs(0); \ SizeT nElp0 = p0->N_Elements(); \ if (nElp0 == 0) \ throw GDLException(e->CallingNode(), "Variable is undefined: "+e->GetParString(0)); \ \ DType t0 = e->GetParDefined(0)->Type(); \ //no "//" comments in macro !!!! //if (t0 == GDL_COMPLEX || t0 == GDL_COMPLEXDBL) \ // e->Throw("Complex not implemented (GSL limitation). "); #define AC_2P1() \ SizeT nElp1; \ DIntGDL* p1; \ DFloatGDL* p1_float; \ DType t1; \ \ if (e->NParam() == 1) \ { \ p1 = new DIntGDL(1, BaseGDL::NOZERO); \ (*p1)[0]=0; \ nElp1=1; \ t1 = GDL_INT; \ p1_float = new DFloatGDL(1, BaseGDL::NOZERO); \ (*p1_float)[0]=0.000; \ } \ else \ { \ p1 = e->GetParAs(1); \ nElp1 = p1->N_Elements(); \ t1 = e->GetParDefined(1)->Type(); \ p1_float = e->GetParAs(1); \ } \ \ const double dzero = 0.0000000000000000000 ; \ \ // throw GDLException(e->CallingNode(), "Variable is undefined: "+e->GetParString(1)); \ \ // DType t1 = e->GetParDefined(1)->Type(); \ // if (t1 == GDL_COMPLEX || t1 == GDL_COMPLEXDBL) \ // e->Throw("Complex not implemented (GSL limitation). "); // change by Alain C., June 1st 2015 : IDL 8.4 behavior #define GM_DF2() \ \ DDoubleGDL* res; \ /*/ cout << p0->Rank() << " " <Dim() <<" " <N_Elements() <Rank() << " " << p1->Dim()<<" " <N_Elements() <Rank() == 0) \ res = new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); \ else if (p1->Rank() == 0) \ res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); \ else if (p0->N_Elements() > p1->N_Elements()) \ res = new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); \ else \ res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); \ \ /* cout << res->Rank() << " " << res->Dim()<<" " << res->N_Elements() <N_Elements(); \ #define GM_DF2_OLD() \ \ DDoubleGDL* res; \ cout << p0->Rank() << " " << p0->Dim() <<" " <N_Elements() <Rank() << " " << p1->Dim() <<" " <N_Elements() < 1 && nElp1 == 1) \ res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); \ else if (nElp0 == 1 && nElp1 > 1) \ res = new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); \ else if (nElp0 <= nElp1) \ res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); \ else \ res = new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); \ \ SizeT nElp = res->N_Elements(); \ #define GM_CV0() \ static DInt doubleKWIx = e->KeywordIx("DOUBLE"); \ \ if (e->KeywordSet(doubleKWIx)) \ return res; \ else \ return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); #define GM_CV1() \ static DInt doubleKWIx = e->KeywordIx("DOUBLE"); \ \ if (t0 != GDL_DOUBLE && t0 != GDL_COMPLEXDBL && \ !e->KeywordSet(doubleKWIx)) \ return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); \ else \ return res; #define GM_CV2() \ static DInt doubleKWIx = e->KeywordIx("DOUBLE"); \ \ /*cout << t0 << t1 << endl; */ \ if (t0 != GDL_DOUBLE && t0 != GDL_COMPLEXDBL && \ t1 != GDL_DOUBLE && t1 != GDL_COMPLEXDBL && \ !e->KeywordSet(doubleKWIx)) \ return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); \ else \ return res; #define GM_CC1() \ static DInt coefKWIx = e->KeywordIx("ITER"); \ if(e->KeywordPresent(coefKWIx)) \ { \ cout << "ITER keyword not used, always return -1)" << endl; \ e->SetKW( coefKWIx, new DLongGDL( -1)); \ } #define AC_HELP() \ static int HELPIx=e->KeywordIx("HELP"); \ if (e->KeywordSet(HELPIx)) { \ string inline_help[]={ \ "Usage: res="+e->GetProName()+"(x, [n,] double=double)", \ " -- x is a number or an array", \ " -- n is a number or an array (if missing, set to 0)", \ " If x and n dimensions differ, reasonable rules applied"}; \ int size_of_s = sizeof(inline_help) / sizeof(inline_help[0]); \ e->Help(inline_help, size_of_s); \ } #include "includefirst.hpp" #include "initsysvar.hpp" // Used to define Double Infinity and Double NaN #include "math_fun_ac.hpp" #include #ifdef _MSC_VER #define isfinite _finite #define isinf !_finite #endif namespace lib { using namespace std; #ifndef _MSC_VER using std::isinf; #endif #if defined(USE_EIGEN) using namespace Eigen; #endif BaseGDL* beseli_fun(EnvT* e) { AC_HELP(); GM_5P0(1); AC_2P1(); GM_DF2(); SizeT count; // GSL Limitation for X : must be lower than ~708 for (count = 0;count 708.) e->Throw("Value of X is out of allowed range."); // we need to check if N values (array) are Integer or not int test=0; for (count = 0;count 0.000001) // don't know if a "machar" value exists test=1; if (test==0) { if(nElp0==1) { for (count = 0;countThrow("Value of X is out of allowed range (Only positive values when N is non integer)."); // we need to check if N values (array) are positives for (count = 0;countThrow("Value of N is out of allowed range (Only positive values when N is non integer)."); if(nElp0==1) { for (count = 0;count 0.000001) // don't know if a "machar" value exists test=1; if (test==0) { if(nElp0==1) { for (count = 0;countThrow("Value of X is out of allowed range (Only positive values when N is non integer)."); // we need to check if N values (array) are positives for (count = 0;countThrow("Value of N is out of allowed range (Only positive values when N is non integer)."); if(nElp0==1) { for (count = 0;countThrow("Value of X is out of allowed range (Only positive values)."); int test=0; for (count = 0;count 0.000001) // don't know if a "machar" value exists test=1; if (test==0) { // when X value is below ~1e-20 --> return -Inf (we use log(0.) which gives -Inf) const double smallVal = 1e-38 ; if(nElp0==1) { for (count = 0;countThrow("Value of N is out of allowed range (Only positive values when N is non integer)."); // when X value is below ~1e-20 --> return -Inf (we use log(0.) which gives -Inf) const double smallVal = 1e-38 ; if(nElp0==1) { for (count = 0;countThrow("Value of X is out of allowed range (Only positive values)."); int test=0; for (count = 0;count 0.000001) // don't know if a "machar" value exists test=1; if (test==0) { // when X value is below ~1e-20 --> return -Inf (we use log(0.) which gives -Inf) const double smallVal = 1e-38 ; if(nElp0==1) { for (count = 0;countThrow("Value of N is out of allowed range (Only positive values when N is non integer)."); // when X value is below ~1e-20 --> return -Inf (we use log(0.) which gives -Inf) const double smallVal = 1e-38 ; if(nElp0==1) { for (count = 0;countKeywordIx("HELP"); if (e->KeywordSet(HELPIx)) { string inline_help[]={ "Usage: y2a=SPL_INIT(xa, ya, yp0=yp0, ypn_1= ypn_1, double=double)", " -- xa is a N elements *ordered* array", " -- ya is a N elements array containing values of the function", " -- yp0 is the value of derivate of YA function at first point", " -- ypN_1 is the value of derivate of YA function at last point", "If X or Y contain NaN or Inf, output is NaN"}; int size_of_s = sizeof(inline_help) / sizeof(inline_help[0]); e->Help(inline_help, size_of_s); } DDoubleGDL* Xpos = e->GetParAs(0); SizeT nElpXpos = Xpos->N_Elements(); DDoubleGDL* Ypos = e->GetParAs(1); SizeT nElpYpos = Ypos->N_Elements(); // we only issue a message if (nElpXpos != nElpYpos) { cout << "SPL_INIT (warning): X and Y arrays do not have same lengths !" << endl; // all next computations to be done on MIN(nElpXpos,nElpYpos) (except NaN/Inf checks) if (nElpXpos > nElpYpos) nElpXpos=nElpYpos; } // creating result array DDoubleGDL* res; // the "res" array; res = new DDoubleGDL(nElpXpos, BaseGDL::NOZERO); SizeT count, count1; // before all, we check wether inputs arrays does contains NaN or Inf DStructGDL *Values = SysVar::Values(); //MUST NOT BE STATIC, due to .reset DDouble d_nan=(*static_cast(Values->GetTag(Values->Desc()->TagIndex("D_NAN"), 0)))[0]; for (count = 0; count < nElpXpos; ++count) { if (!isfinite((*Xpos)[count])) { cout << "SPL_INIT (fatal): at least one value in X input array is NaN or Inf ..." << endl; for (count1 = 0; count1 < nElpXpos; ++count1) (*res)[count1] =d_nan; return res; } } for (count = 0; count < nElpYpos; ++count) { if (!isfinite((*Ypos)[count])) { cout << "SPL_INIT (fatal): at least one value in Y input array is NaN or Inf ..." << endl; for (count1 = 0; count1 < nElpXpos; ++count1) (*res)[count1] =d_nan; return res; } } // we also check wether X input array is well ordered ... double step; int flag_skip=0; for (count = 1; count < nElpXpos; ++count) { step=(*Xpos)[count]-(*Xpos)[count-1]; if (step < 0.0) { if (flag_skip == 0) { cout << "SPL_INIT (warning): at least one x[n+1]-x[n] step is negative: X is assumed to be ordered" << endl; flag_skip = 1; } } if (abs(step) == 0.0) { cout << "SPL_INIT (fatal): at least two consecutive X values are identical" << endl; for (count1 = 0; count1 < nElpXpos; ++count1) (*res)[count1] =d_nan; return res; } } Guard U_guard; DDoubleGDL* U; U = new DDoubleGDL(nElpXpos, BaseGDL::NOZERO); U_guard.Reset(U); // delete upon exit // may be we will have to check the size of these arrays ? static int yp0Ix=e->KeywordIx("YP0"); BaseGDL* Yderiv0=e->GetKW(yp0Ix); DDoubleGDL* YP0; if(Yderiv0 !=NULL && !isinf((*(YP0=e->GetKWAs(yp0Ix)))[0] )){ // first derivative at the point X0 is defined and different to Inf (*res)[0]=-0.5; (*U)[0] = ( 3. / ((*Xpos)[1]-(*Xpos)[0])) * (((*Ypos)[1]-(*Ypos)[0]) / ((*Xpos)[1]-(*Xpos)[0]) - (*YP0)[0] ); }else{ // YP0 is omitted or equal to Inf (*res)[0]=0.; (*U)[0]=0.; } double psig, pu, x, xm, xp, y, ym, yp, p, dx, qn; for (count = 1; count < nElpXpos-1; ++count) { x=(*Xpos)[count]; xm=(*Xpos)[count-1]; xp=(*Xpos)[count+1]; psig=(x-xm)/(xp-xm); y=(*Ypos)[count]; ym=(*Ypos)[count-1]; yp=(*Ypos)[count+1]; pu=((ym-y)/(xm-x)-(y-yp)/(x-xp))/(xm-xp); p=psig*(*res)[count-1]+2.; (*res)[count]=(psig-1.)/p; (*U)[count]=(6.00*pu-psig*(*U)[count-1])/p; } static int ypn_1Ix=e->KeywordIx("YPN_1"); BaseGDL* YderivN=e->GetKW(ypn_1Ix); DDoubleGDL* YPN; if(YderivN !=NULL && !isinf((*(YPN=e->GetKWAs(ypn_1Ix)))[0] )){ // first derivative at the point XN-1 is defined and different to Inf (*res)[nElpXpos-1] =0.; qn=0.5; dx=((*Xpos)[nElpXpos-1]-(*Xpos)[nElpXpos-2]); (*U)[nElpXpos-1]= (3./dx)*((*YPN)[0]-((*Ypos)[nElpXpos-1]-(*Ypos)[nElpXpos-2])/dx); }else{ // YPN_1 is omitted or equal to Inf qn=0.; (*U)[nElpXpos-1]=0.; } (*res)[nElpXpos-1] =((*U)[nElpXpos-1]-qn*(*U)[nElpXpos-2])/(qn*(*res)[nElpXpos-2]+ 1.); for (count = nElpXpos-2; count != -1; --count){ (*res)[count] =(*res)[count]*(*res)[count+1]+(*U)[count]; } GM_CV0(); } BaseGDL* spl_interp_fun( EnvT* e) { static int HELPIx=e->KeywordIx("HELP"); if (e->KeywordSet(HELPIx)) { // string inline_help[]={}; // e->Help(inline_help, 0); string inline_help[]={ "Usage: res=SPL_INTERP(xa, ya, y2a, new_x, double=double)", " -- xa is a N elements *ordered* array", " -- ya is a N elements array containing values of the function", " -- y2a is the value of derivate of YA function at first point", " -- new_x is an array for new X positions where we want to compute SPLINE", "This function should be called only after use of SPL_INIT() !"}; int size_of_s = sizeof(inline_help) / sizeof(inline_help[0]); e->Help(inline_help, size_of_s); } DDoubleGDL* Xpos = e->GetParAs(0); SizeT nElpXpos = Xpos->N_Elements(); DType t0 = e->GetParDefined(0)->Type(); DDoubleGDL* Ypos = e->GetParAs(1); SizeT nElpYpos = Ypos->N_Elements(); DDoubleGDL* Yderiv2 = e->GetParAs(2); SizeT nElpYderiv2 = Yderiv2->N_Elements(); // Do the 3 arrays have same lengths ? if ((nElpXpos != nElpYpos) || (nElpXpos != nElpYderiv2)) e->Throw("Arguments XA, YA, and Y2A must have the same number of elements."); DDoubleGDL* Xnew = e->GetParAs(3); SizeT nElpXnew = Xnew->N_Elements(); DDoubleGDL* res; res = new DDoubleGDL(nElpXnew, BaseGDL::NOZERO); int debug =0; SizeT ilo, ihi, imiddle; double xcur, xposcur, h, aa, bb; for (SizeT count = 0; count < nElpXnew; ++count) { xcur=(*Xnew)[count]; ilo=0; ihi=nElpXpos-1; while ((ihi-ilo) > 1){ imiddle=(ilo+ihi)/2; xposcur=(*Xpos)[imiddle]; if (xposcur > xcur) ihi=imiddle; else ilo=imiddle; } h=(*Xpos)[ihi]-(*Xpos)[ilo]; if (abs(h) == 0.0) e->Throw("SPL_INTERP: Bad XA input (XA not ordered or zero step in XA)."); if (debug == 1) cout << "h " << h << " lo/hi" << ilo << " " < T2* Sobel_Template(T* p0,T3 a) { SizeT nbX = p0->Dim(0); SizeT nbY = p0->Dim(1); T2* res = new T2(p0->Dim(), BaseGDL::NOZERO); //DDoubleGDL z = new DDoubleGDL[nbX,nbY]; for( SizeT k=0; k<=nbY-1; k++) { (*res)[0+nbX*k]=0; (*res)[nbX-1+nbX*k]=0; } for( SizeT j=0; j<= nbX-1; j++) { (*res)[j+0]=0; (*res)[j+nbX*(nbY-1)]=0; } for( SizeT k=1; k<=nbY-2; k++) { for( SizeT j=1; j<= nbX-2; j++) { a = labs ((*p0)[j+1+nbX*(k+1)]+2*(*p0)[j+1+nbX*k]+(*p0)[j+1+nbX*(k-1)] - ((*p0)[j-1+nbX*(k+1)]+2*(*p0)[j-1+nbX*k]+(*p0)[j-1+nbX*(k-1)])) + labs ((*p0)[j-1+nbX*(k-1)]+2*(*p0)[j+nbX*(k-1)]+(*p0)[j+1+nbX*(k-1)] - ((*p0)[j-1+nbX*(k+1)]+2*(*p0)[j+nbX*(k+1)]+(*p0)[j+1+nbX*(k+1)])); (*res)[j+nbX*k]=a; } } return res; } BaseGDL* sobel_fun( EnvT* e) { BaseGDL* p0 = e->GetParDefined(0); string txt=" expression not allowed in this context: "; if (p0->Type() == GDL_STRING) e->Throw("String"+txt+ e->GetParString(0)); if (p0->Type() == GDL_PTR) e->Throw("Pointer"+txt+ e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("Structure"+txt+ e->GetParString(0)); if (p0->Type() == GDL_OBJ) e->Throw("Object"+txt+ e->GetParString(0)); if( p0->Rank() != 2) e->Throw( "Array must have 2 dimensions: "+ e->GetParString(0)); switch (p0->Type()) { case GDL_BYTE:{ long int a; return Sobel_Template(static_cast(p0),a); } case GDL_INT: {long int a; return Sobel_Template(static_cast (p0),a); } case GDL_UINT:{long int a; return Sobel_Template(static_cast (p0),a); } case GDL_LONG:{long int a; return Sobel_Template(static_cast (p0),a); } case GDL_ULONG:{long int a; return Sobel_Template(static_cast (p0),a); } case GDL_LONG64:{long int a; return Sobel_Template(static_cast (p0),a); } case GDL_ULONG64:{long int a; return Sobel_Template(static_cast (p0),a); } case GDL_FLOAT:{long double a; return Sobel_Template(static_cast (p0),a); } case GDL_DOUBLE: {long double a; return Sobel_Template(static_cast (p0),a); } case GDL_COMPLEX: { long int a; DDoubleGDL* p0 = e->GetParAs(0); return Sobel_Template(static_cast (p0),a); } case GDL_COMPLEXDBL:{long double a; DDoubleGDL* p0 = e->GetParAs(0); return Sobel_Template(static_cast (p0),a); } default: e->Throw( "Should not reach this point, please report"); } return NULL; } BaseGDL* roberts_fun( EnvT* e){ // BaseGDL* p0 = e->GetParDefined(0); int type=e->GetParDefined(0)->Type(); string txt=" expression not allowed in this context: "; if (type == GDL_STRING) e->Throw("String"+txt+ e->GetParString(0)); if (type == GDL_PTR) e->Throw("Pointer"+txt+ e->GetParString(0)); if (type == GDL_STRUCT) e->Throw("Structure"+txt+ e->GetParString(0)); if (type == GDL_OBJ) e->Throw("Object"+txt+ e->GetParString(0)); // DDoubleGDL* p0 = e->GetParAs(0); if (e->GetParDefined(0)->Rank() != 2) e->Throw( "Array must have 2 dimensions: "+ e->GetParString(0)); DDoubleGDL* p0 = e->GetParAs(0); DDoubleGDL* res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); SizeT nbX = p0->Dim(0); SizeT nbY = p0->Dim(1); bool debug=false; if (debug) { cout << "nbX : " << nbX << endl; cout << "nbY : " << nbY << endl; } for( SizeT k=0; k<=nbY-1; k++) { (*res)[nbX-1+nbX*k]=0; } for( SizeT j=0; j<= nbX-1; j++) { (*res)[j+nbX*(nbY-1)]=0; } //DDoubleGDL z = new DDoubleGDL[nbX,nbY]; for( SizeT k=0; k T2* Prewitt_Template(T* p0,T3 a) { SizeT nbX = p0->Dim(0); SizeT nbY = p0->Dim(1); T2* res = new T2(p0->Dim(), BaseGDL::NOZERO); bool debug=false; //DDoubleGDL z = new DDoubleGDL[nbX,nbY]; for( SizeT k=0; k<=nbY-1; k++) { (*res)[0+nbX*k]=0; (*res)[nbX-1+nbX*k]=0; } for( SizeT j=0; j<= nbX-1; j++) { (*res)[j+0]=0; (*res)[j+nbX*(nbY-1)]=0; } T3 Gx=0,Gy=0; double r=0; for( SizeT k=1; k<=nbY-2; k++) { for( SizeT j=1; j<= nbX-2; j++) { Gx= ((*p0)[j+1+nbX*(k+1)]+(*p0)[j+1+nbX*k]+(*p0)[j+1+nbX*(k-1)] - ((*p0)[j-1+nbX*(k+1)]+(*p0)[j-1+nbX*k]+(*p0)[j-1+nbX*(k-1)])); Gy= ((*p0)[j-1+nbX*(k-1)]+(*p0)[j+nbX*(k-1)]+(*p0)[j+1+nbX*(k-1)] - ((*p0)[j-1+nbX*(k+1)]+(*p0)[j+nbX*(k+1)]+(*p0)[j+1+nbX*(k+1)])); if (debug) cout<GetParDefined(0); string txt=" expression not allowed in this context: "; if (p0->Type() == GDL_STRING) e->Throw("String"+txt+ e->GetParString(0)); if (p0->Type() == GDL_PTR) e->Throw("Pointer"+txt+ e->GetParString(0)); if (p0->Type() == GDL_STRUCT) e->Throw("Structure"+txt+ e->GetParString(0)); if (p0->Type() == GDL_OBJ) e->Throw("Object"+txt+ e->GetParString(0)); if( p0->Rank() != 2) e->Throw( "Array must have 2 dimensions: "+ e->GetParString(0)); switch (p0->Type()) { case GDL_BYTE:{ long int a; return Prewitt_Template(static_cast(p0),a); } case GDL_INT: {long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_UINT:{long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_LONG:{long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_ULONG:{long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_LONG64:{long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_ULONG64:{long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_FLOAT:{long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_DOUBLE: {long int a; return Prewitt_Template(static_cast (p0),a); } case GDL_COMPLEX: { long int a; DDoubleGDL* p0 = e->GetParAs(0); return Prewitt_Template(static_cast (p0),a); } case GDL_COMPLEXDBL:{long int a; DDoubleGDL* p0 = e->GetParAs(0); return Prewitt_Template(static_cast (p0),a); } default: e->Throw( "Should not reach this point, please report"); } return NULL; } BaseGDL* erode_fun( EnvT* e){ SizeT nParam = e->NParam(1); DIntGDL* p0 = e->GetParAs(0); DIntGDL* p1 = e->GetParAs(1); static int preserveix = e->KeywordIx("PRESERVE_TYPE"); static int grayix = e->KeywordIx("GRAY"); switch ( p0->Rank()) { case 1:{if(p1->Rank()!=1){e->Throw( "Array must have 1 dimensions: "+ e->GetParString(1));}break;} case 2:{if(p1->Rank()!=2){e->Throw( "Array must have 2 dimensions: "+ e->GetParString(1));}break;} case 3:{if(p1->Rank()!=3){e->Throw( "Array must have 3 dimensions: "+ e->GetParString(1));}break;} default:{e->Throw( "Array must have 2 or 3 dimensions: "+ e->GetParString(0)); break;} } if (e->GetKW(grayix) != NULL) { e->Throw( "/GRAY not yet programmed."); } DByteGDL* res = new DByteGDL(p0->Dim(), BaseGDL::NOZERO); if (e->GetKW(preserveix) != NULL) { switch (p0->Type()) { case GDL_BYTE:{ DByteGDL* res = new DByteGDL(p0->Dim(), BaseGDL::NOZERO); break; } case GDL_UINT:{ DUIntGDL* res = new DUIntGDL(p0->Dim(), BaseGDL::NOZERO); break; } case GDL_ULONG:{ DULongGDL* res = new DULongGDL(p0->Dim(), BaseGDL::NOZERO); break; } default:{ e->Throw( "PRESERVE_TYPE valid only with BYTE, UINT, and ULONG."); break; } } } long int nbX = p0->Dim(0); long int nbY = p0->Dim(1); long int nbZ = p0->Dim(2); long int mX = p1->Dim(0); long int mY = p1->Dim(1); long int mZ = p1->Dim(2); long int midx= ceil(mX/2); long int midy= ceil(mY/2); long int midz= ceil(mZ/2); if (p0->Rank()==2) { nbZ = 1; mZ = 1; } if (p0->Rank()==1) { nbZ = 1; mZ = 1; nbY = 1; mY = 1; } if (nParam>=3) { DIntGDL* p2 = e->GetParAs(2); midx=(*p2)[0]; } if (nParam>=4) { DIntGDL* p2 = e->GetParAs(3); midy=(*p2)[0]; } if (nParam>=5) { DIntGDL* p2 = e->GetParAs(4); midz=(*p2)[0]; } bool debug=false; if (debug) { cout <<"midx= " <=nbZ)|((l+z)<0)) { bo=true; break; } if ((*p1)[x+mX*y+z*(mX*mY)]==1) if ((*p0)[(j+x)+nbX*(k+y)+(l+z)*(nbX*nbY)] !=(*p1)[x+mX*y+z*(mX*mY)]) { bo=true; break; } } } } if (bo==true) { if ((j+midxNParam(1); DIntGDL* p0 = e->GetParAs(0); DIntGDL* p1 = e->GetParAs(1); static int preserveix = e->KeywordIx("PRESERVE_TYPE"); static int grayix = e->KeywordIx("GRAY"); switch ( p0->Rank()) { case 1:{if(p1->Rank()!=1){e->Throw( "Array must have 1 dimensions: "+ e->GetParString(1));}break;} case 2:{if(p1->Rank()!=2){e->Throw( "Array must have 2 dimensions: "+ e->GetParString(1));}break;} case 3:{if(p1->Rank()!=3){e->Throw( "Array must have 3 dimensions: "+ e->GetParString(1));}break;} default:{e->Throw( "Array must have 2 or 3 dimensions: "+ e->GetParString(0)); break;} } if (e->GetKW(grayix) != NULL) { e->Throw( "/GRAY not yet programmed."); } DByteGDL* res = new DByteGDL(p0->Dim(), BaseGDL::NOZERO); if (e->GetKW(preserveix) != NULL) { switch (p0->Type()) { case GDL_BYTE:{ DByteGDL* res = new DByteGDL(p0->Dim(), BaseGDL::NOZERO); break; } case GDL_UINT:{ DUIntGDL* res = new DUIntGDL(p0->Dim(), BaseGDL::NOZERO); break; } case GDL_ULONG:{ DULongGDL* res = new DULongGDL(p0->Dim(), BaseGDL::NOZERO); break; } default:{ e->Throw( "PRESERVE_TYPE valid only with BYTE, UINT, and ULONG."); break; } } } long int nbX = p0->Dim(0); long int nbY = p0->Dim(1); long int nbZ = p0->Dim(2); long int mX = p1->Dim(0); long int mY = p1->Dim(1); long int mZ = p1->Dim(2); long int midx= ceil(mX/2); long int midy= ceil(mY/2); long int midz= ceil(mZ/2); if (p0->Rank()==2) { nbZ = 1; mZ = 1; } if (p0->Rank()==1) { nbZ = 1; mZ = 1; nbY = 1; mY = 1; } if (nParam>=3) { DIntGDL* p2 = e->GetParAs(2); midx=(*p2)[0]; } if (nParam>=4) { DIntGDL* p2 = e->GetParAs(3); midy=(*p2)[0]; } if (nParam>=5) { DIntGDL* p2 = e->GetParAs(4); midz=(*p2)[0]; } bool debug=false; if (debug) { cout <<"midx= " <=0)) { if ((*p1)[x+mX*y+z*(mX*mY)]==1) if ((*p0)[(j+x)+nbX*(k+y)+(l+z)*(nbX*nbY)] ==(*p1)[x+mX*y+z*(mX*mY)]) { bo=true; break; } } } } } } } if (bo==true) { if ((j+midxGetParDefined(0); BaseGDL* b = e->GetParDefined(1); DType aTy = a->Type(); if (!NumericType(aTy)) e->Throw("Array type cannot be " + a->TypeStr() + " here: " + e->GetParString(0)); DType bTy = b->Type(); if (!NumericType(bTy)) e->Throw("Array type cannot be " + b->TypeStr() + " here: " + e->GetParString(1)); static int atIx = e->KeywordIx("ATRANSPOSE"); static int btIx = e->KeywordIx("BTRANSPOSE"); bool at = e->KeywordSet(atIx); bool bt = e->KeywordSet(btIx); if (a->Rank() > 2) { e->Throw("Array must have 1 or 2 dimensions: " + e->GetParString(0)); } if (b->Rank() > 2) { e->Throw("Array must have 1 or 2 dimensions: " + e->GetParString(1)); } // code from ProgNode::AdjustTypes() Guard aGuard; Guard bGuard; // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL DType cxTy = PromoteComplexOperand( aTy, bTy); if( cxTy != GDL_UNDEF) { a = a->Convert2( cxTy, BaseGDL::COPY); aGuard.Init( a); b = b->Convert2( cxTy, BaseGDL::COPY); bGuard.Init( b); } else { DType cTy = PromoteMatrixOperands( aTy, bTy); if( aTy != cTy) { a = a->Convert2( cTy, BaseGDL::COPY); aGuard.Init( a); } if( bTy != cTy) { b = b->Convert2( cTy, BaseGDL::COPY); bGuard.Init( b); } } // might use eigen3 return a->MatrixOp( b, at, bt); } } // namespace gdl-0.9.9/src/math_fun_ac.hpp000066400000000000000000000031631340051421000160340ustar00rootroot00000000000000/*************************************************************************** math_fun_ac.hpp - mathematical GDL library function ------------------- begin : 20 April 2007 copyright : (C) 2007 by Alain Coulais email : alaingdl@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "datatypes.hpp" #include "envt.hpp" #if defined(USE_EIGEN) #include //using namespace Eigen; // never in header files! #endif namespace lib { BaseGDL* beseli_fun( EnvT* e); BaseGDL* beselj_fun( EnvT* e); BaseGDL* beselk_fun( EnvT* e); BaseGDL* besely_fun( EnvT* e); BaseGDL* spl_init_fun( EnvT* e); BaseGDL* spl_interp_fun( EnvT* e); BaseGDL* sobel_fun( EnvT* e); BaseGDL* roberts_fun( EnvT* e); BaseGDL* prewitt_fun( EnvT* e); BaseGDL* erode_fun( EnvT* e); BaseGDL* dilate_fun( EnvT* e); BaseGDL* matrix_multiply( EnvT* e); } // namespace gdl-0.9.9/src/math_fun_gm.cpp000066400000000000000000000500641340051421000160510ustar00rootroot00000000000000/*************************************************************************** math_fun_gm.cpp - math GDL library function (GM) ------------------- begin : 03 May 2007 copyright : (C) 2007 by Gregory Marchal email : gregory.marchal_at_obspm.fr website : http://format.obspm.fr/~m1/gmarchal/ ****************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Using the Erfs functions and Gammas function provides by GSL ----------------------- Warning ------------- Since Erfs and Gammas functions are clones derivated from the first one, please propagates bugs' correction and improvements. Do not know how to simplified :-( ----------------------- Note ------------- See http://www.netlib.org/specfun/erf for further details on how processing Erfcx. ----------------------- Note ---------------- Variables are double because of the GSL. ----------------------- Note ---------------- ExpInt code is partially adapted from Numerical Recipes in C, section 6.3. See http://www.nrbook.com/b/bookcpdf/c6-3.pdf */ // Constants ----------------------------------------------------------------- #define GM_EPS 1.0e-6 #define GM_ITER 50 #define GM_TINY 1.0e-18 // Macros -------------------------------------------------------------------- #define GM_MIN(a, b) ((a) < (b) ? (a) : (b)) /* Table 3-115: IDL Type Codes and Names (IDL Help) ================================================ Type Code | Type Name | Data Type ------------------------------------------------- 0 | UNDEFINED | Undefined 1 | GDL_BYTE | Byte 2 | GDL_INT | Integer 3 | GDL_LONG | Longword integer 4 | GDL_FLOAT | Floating point 5 | GDL_DOUBLE | Double-precision floating 6 | GDL_COMPLEX | Complex floating 7 | GDL_STRING | String 8 | GDL_STRUCT | Structure 9 | DCOMPLEX | Double-precision complex 10 | POINTER | Pointer 11 | OBJREF | Object reference 12 | GDL_UINT | Unsigned Integer 13 | GDL_ULONG | Unsigned Longword Integer 14 | GDL_LONG64 | 64-bit Integer 15 | GDL_ULONG64 | Unsigned 64-bit Integer */ // Macros GM_xPy(a): - x must be replaced by the desired type code in the table above (set it to 2 if you want to get an int, etc.); // - P means parameter, don't replace it; // - y must be replaced by the number of the parameter you want to get (it starts at 0); // - a, when you define the 0th parameter, must be replaced by the total number of parameters. // // Note that macros suite is incomplete. // See below for examples. #define GM_2P0(a) \ e->NParam(a); \ \ DIntGDL* p0 = e->GetParAs(0); \ SizeT nElp0 = p0->N_Elements(); \ \ if (nElp0 == 0) \ throw GDLException(e->CallingNode(), "Variable is undefined: "+e->GetParString(0)); \ #define GM_5P0(a) \ e->NParam(a); \ \ DDoubleGDL* p0 = e->GetParAs(0); \ SizeT nElp0 = p0->N_Elements(); \ \ if (nElp0 == 0) \ throw GDLException(e->CallingNode(), "Variable is undefined: "+e->GetParString(0)); \ #define GM_5P1() \ DDoubleGDL* p1 = e->GetParAs(1); \ SizeT nElp1 = p1->N_Elements(); \ \ if (nElp1 == 0) \ throw GDLException(e->CallingNode(), "Variable is undefined: "+e->GetParString(1)); \ #define GM_CheckComplex_P0(flag) \ DType t0 = e->GetParDefined(0)->Type(); \ if (flag == 1 && (t0 == GDL_COMPLEX || t0 == GDL_COMPLEXDBL)) \ e->Throw("Complex not implemented (GSL limitation). "); \ #define GM_CheckComplex_P1(flag) \ DType t1 = e->GetParDefined(1)->Type(); \ if (flag == 1 && (t1 == GDL_COMPLEX || t1 == GDL_COMPLEXDBL)) \ e->Throw("Complex not implemented (GSL limitation). "); \ // Use this macro to define Inf and NaN, number of elements and result in a function with one parameter. // Note no STATIC for SysVar::, due to .reset #define GM_NaN_Inf() \ DStructGDL *Values = SysVar::Values(); \ DDouble d_infinity=(*static_cast(Values->GetTag(Values->Desc()->TagIndex("D_INFINITY"), 0)))[0]; \ DDouble d_nan=(*static_cast(Values->GetTag(Values->Desc()->TagIndex("D_NAN"), 0)))[0]; \ #define GM_DF1() \ DDoubleGDL* res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); // Use this macro to define Inf and NaN, number of elements and result in a function with two parameters. #define GM_DF2() \ DDoubleGDL* res; \ \ if (p0->Rank() == 0) \ res = new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); \ else if (p1->Rank() == 0) \ res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); \ else if (p0->N_Elements() > p1->N_Elements()) \ res = new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); \ else \ res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); \ SizeT nElp = res->N_Elements(); \ \ //cout << "nElp0 : " << nElp0 << std::endl; \ //cout << "nElp1 : " << nElp1 << std::endl; \ //cout << "nElp : " << nElp << std::endl; // Use this macro to convert result in a function with one parameter. #define GM_CV1() \ static DInt doubleKWIx = e->KeywordIx("DOUBLE"); \ \ if (t0 != GDL_DOUBLE && t0 != GDL_COMPLEXDBL && \ !e->KeywordSet(doubleKWIx)) \ return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); \ else \ return res; \ \ // AC2018 why do we had that ?? return new DByteGDL(0); // Use this macro to convert result in a function with two parameters. #define GM_CV2() \ static DInt doubleKWIx = e->KeywordIx("DOUBLE"); \ \ if (t0 != GDL_DOUBLE && t0 != GDL_COMPLEXDBL && \ t1 != GDL_DOUBLE && t1 != GDL_COMPLEXDBL && \ !e->KeywordSet(doubleKWIx)) \ return res->Convert2(GDL_FLOAT, BaseGDL::CONVERT); \ else \ return res; \ \ // AC2018 why do we had that ?? return new DByteGDL(0); #include "includefirst.hpp" #include "initsysvar.hpp" // Used to define Double Infinity and Double NaN #include "math_fun_gm.hpp" #include #include #include #include #include #ifdef _MSC_VER #define isnan _isnan #define isfinite _finite #endif namespace lib { using namespace std; #ifndef _MSC_VER using std::isnan; #endif double gm_expint(int n, double x); double gm_lentz(double a[], double b[], double tiny, int n, double eps); BaseGDL* erf_fun(EnvT* e) { GM_CheckComplex_P0(1); GM_5P0(1); GM_DF1(); GM_NaN_Inf(); for (SizeT c = 0; c < nElp0; ++c) { if ((*p0)[c] == d_infinity) (*res)[c] = 1.0; else if ((*p0)[c] == -d_infinity) (*res)[c] = -1.0; else if (isnan((*p0)[c]) == 1) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_erf((*p0)[c]); } GM_CV1(); } // erf_fun // ERRORF is the IDL old name of the ERF function. It is implemented to keep old syntax active. BaseGDL* errorf_fun(EnvT* e) { return erf_fun(e); } // errorf_fun // this a separable function : GAUSSINT(a,b)=GAUSSINT(a)*GAUSSINT(b) BaseGDL* gaussint_fun(EnvT* e) { GM_NaN_Inf(); SizeT nParam = e->NParam(); // cout << nParam << endl; // real part of Complex inputs are used GM_CheckComplex_P0(0); GM_5P0(); DDoubleGDL* tmp0; tmp0=new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); DType t1 = GDL_LONG; DDoubleGDL* tmp1; DDoubleGDL* p1 = e->GetParAs(1); SizeT nElp1 = p1->N_Elements(); DType t1bis; if (nParam == 2) { GM_CheckComplex_P1(0); p1 = e->GetParAs(1); SizeT nElp1 = p1->N_Elements(); tmp1=new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); t1bis = e->GetParDefined(1)->Type(); //cout << "type : "<< t1 << endl; } else { nElp1=1; tmp1=new DDoubleGDL(1.); // DType t1bis = GDL_FLOAT; } t1=t1bis; // cout << "type : "<< t1bis << endl; // cout << "type : "<< t1 << endl; // computation for X input for (SizeT c = 0; c < nElp0; ++c) { if ((*p0)[c] == d_infinity) (*tmp0)[c] = 1.0; else if ((*p0)[c] == -d_infinity) (*tmp0)[c] = 0.0; else if (isnan((*p0)[c]) == 1) (*tmp0)[c] = d_nan; else (*tmp0)[c] = 0.5*(1.+gsl_sf_erf((*p0)[c]/sqrt(2.))); } if (nParam == 2) { // computation for Y input for (SizeT c = 0; c < nElp1; ++c) { if ((*p1)[c] == d_infinity) (*tmp1)[c] = 1.0; else if ((*p1)[c] == -d_infinity) (*tmp1)[c] = 0.0; else if (isnan((*p1)[c]) == 1) (*tmp1)[c] = d_nan; else (*tmp1)[c] = 0.5*(1.+gsl_sf_erf((*p1)[c]/sqrt(2.))); } } DDoubleGDL* res; if (p0->Rank() == 0) { res =new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); for (SizeT c = 0; c < nElp1; ++c) (*res)[c] =(*tmp1)[c]*(*tmp0)[0]; } else { if (p1->Rank() == 0) { res =new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); for (SizeT c = 0; c < nElp0; ++c) (*res)[c] =(*tmp0)[c]*(*tmp1)[0]; } else { SizeT nbp; if (nElp0 > nElp1) { nbp=nElp1; res =new DDoubleGDL(p1->Dim(), BaseGDL::NOZERO); } else { nbp=nElp0; res =new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); } for (SizeT c = 0; c < nbp; ++c) (*res)[c] =(*tmp0)[c]*(*tmp1)[c]; } } GM_CV2(); } // gaussint_fun BaseGDL* erfc_fun(EnvT* e) { GM_CheckComplex_P0(1); GM_5P0(1); GM_DF1(); GM_NaN_Inf(); for (SizeT c = 0; c < nElp0; ++c) { if ((*p0)[c] == d_infinity) (*res)[c] = 0.0; else if ((*p0)[c] == -d_infinity) (*res)[c] = 2.0; else if (isnan((*p0)[c]) == 1) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_erfc((*p0)[c]); } GM_CV1(); } // erfc_fun BaseGDL* gamma_fun(EnvT* e) { GM_CheckComplex_P0(1); GM_5P0(1); GM_DF1(); GM_NaN_Inf(); for (SizeT c = 0; c < nElp0; ++c) if (((*p0)[c] == 0.0) || (((*p0)[c] < 0.0) && ((int)(*p0)[c] == (*p0)[c])) || (*p0)[c] >= GSL_SF_GAMMA_XMAX) (*res)[c] = d_infinity; else if (isnan((*p0)[c]) == 1 || (*p0)[c] == -d_infinity) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_gamma((*p0)[c]); GM_CV1(); } // gamma_fun BaseGDL* lngamma_fun(EnvT* e) { GM_CheckComplex_P0(1); GM_5P0(1); GM_DF1(); GM_NaN_Inf(); for (SizeT c = 0; c < nElp0; ++c) if ((*p0)[c] == 0.0 || (*p0)[c] < 0.0) (*res)[c] = d_infinity; else if (isnan((*p0)[c])) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_lngamma((*p0)[c]); GM_CV1(); } // lngamma_fun BaseGDL* igamma_fun(EnvT* e) { GM_CheckComplex_P0(1); GM_CheckComplex_P1(1); GM_5P0(2); GM_5P1(); GM_DF2(); GM_NaN_Inf(); if (nElp0 == 1) { if ((*p0)[0] <= 0.0) e->Throw("First argument must be greater than zero (GSL limitation)! "); for (SizeT c = 0; c < nElp; ++c) { if ((*p1)[c] < 0.0) e->Throw("Second argument must be greater than or equal to zero! "); } } else if (nElp1 == 1) { for (SizeT c = 0; c < nElp; ++c) { if ((*p0)[c] <= 0.0) e->Throw("First argument must be greater than zero (GSL limitation)! "); } if ((*p1)[0] < 0.0) e->Throw("Second argument must be greater than or equal to zero! "); } else { for (SizeT c = 0; c < nElp; ++c) { if ((*p0)[c] <= 0.0) e->Throw("First argument must be greater than zero (GSL limitation)! "); else if ((*p1)[c] < 0.0) e->Throw("Second argument must be greater than or equal to zero! "); } } if (nElp0 == 1) for (SizeT c = 0; c < nElp; ++c) if ((*p0)[0] == d_infinity && (*p1)[c] == d_infinity) (*res)[c] = 1.0; else if (isnan((*p0)[0]) == 1 || isnan((*p1)[c])) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_gamma_inc_P((*p0)[0], (*p1)[c]); else if (nElp1 == 1) for (SizeT c = 0; c < nElp; ++c) if ((*p0)[c] == d_infinity && (*p1)[0] == d_infinity) (*res)[c] = 1.0; else if (isnan((*p0)[c]) == 1 || isnan((*p1)[0])) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_gamma_inc_P((*p0)[c], (*p1)[0]); else for (SizeT c = 0; c < nElp; ++c) if ((*p0)[c] == d_infinity && (*p1)[c] == d_infinity) (*res)[c] = 1.0; else if (isnan((*p0)[c]) == 1 || isnan((*p1)[c])) (*res)[c] = d_nan; else (*res)[c] = gsl_sf_gamma_inc_P((*p0)[c], (*p1)[c]); static int methodIx = e->KeywordIx("METHOD"); if (e->KeywordPresent(methodIx)) { DIntGDL* IxMethod = new DIntGDL(nElp, BaseGDL::NOZERO); for( SizeT i=0; iSetKW( methodIx, IxMethod); } GM_CV2(); } // igamma_fun BaseGDL* beta_fun(EnvT* e) { GM_CheckComplex_P0(1); GM_CheckComplex_P1(1); GM_5P0(2); GM_5P1(); GM_DF2(); GM_NaN_Inf(); if (nElp0 == 1) { bool flag0 = false; bool flag1 = false; if (isfinite((*p0)[0]) == 0) flag0 = true; if ((int)(*p0)[0] == (*p0)[0] && (*p0)[0] <= 0.0) flag1 = true; for (SizeT c = 0; c < nElp; ++c) { if (flag0 == true || isfinite((*p1)[c]) == 0) (*res)[c] = d_nan; else if (flag1 == true || ((int)(*p1)[c] == (*p1)[c] && (*p1)[c] <= 0.0)) (*res)[c] = d_infinity; else (*res)[c] = gsl_sf_beta((*p0)[0], (*p1)[c]); } } else if (nElp1 == 1) { bool flag0 = false; bool flag1 = false; if (isfinite((*p1)[0]) == 0) flag0 = true; if ((int)(*p1)[0] == (*p1)[0] && (*p1)[0] <= 0.0) flag1 = true; for (SizeT c = 0; c < nElp; ++c) { if (isfinite((*p0)[c]) == 0 || flag0 == true) (*res)[c] = d_nan; else if (((int)(*p0)[c] == (*p0)[c] && (*p0)[c] <= 0.0) || flag1 == true) (*res)[c] = d_infinity; else (*res)[c] = gsl_sf_beta((*p0)[c], (*p1)[0]); } } else { for (SizeT c = 0; c < nElp; ++c) { if (isfinite((*p0)[c]) == 0 || isfinite((*p1)[c]) == 0) (*res)[c] = d_nan; else if (((int)(*p0)[c] == (*p0)[c] && (*p0)[c] <= 0.0) || ((int)(*p1)[c] == (*p1)[c] && (*p1)[c] <= 0.0)) (*res)[c] = d_infinity; else (*res)[c] = gsl_sf_beta((*p0)[c], (*p1)[c]); } } GM_CV2(); } // beta_fun BaseGDL* expint_fun(EnvT* e) { // real part of Complex inputs are used GM_CheckComplex_P0(0); GM_CheckComplex_P1(0); GM_2P0(2); GM_5P1(); GM_DF2(); GM_NaN_Inf(); //Tests ----------------- if (nElp0 == 1) { if ((*p0)[0] < 0) e->Throw("Arguments must be greater than or equal to zero. "); for (SizeT c = 0; c < nElp; ++c) { if ((*p1)[c] < 0.0) e->Throw("Arguments must be greater than or equal to zero. "); } } else if (nElp1 == 1) { for (SizeT c = 0; c < nElp; ++c) { if ((*p0)[c] < 0) e->Throw("Arguments must be greater than or equal to zero. "); } if ((*p1)[0] < 0.0) e->Throw("Arguments must be greater than or equal to zero. "); } else { for (SizeT c = 0; c < nElp; ++c) { if ((*p0)[c] < 0 || (*p1)[c] < 0.0) e->Throw("Arguments must be greater than or equal to zero. "); } } // Calculus -------------- if (nElp0 == 1) { for (SizeT c = 0; c < nElp; ++c) { if ((*p1)[c] == d_infinity) (*res)[c] = 0.0; // initially was: // else if (isnan((*p0)[0]) == 1 || isnan((*p1)[c]) == 1 || (*p1)[c] < 0.0) // but (*p0) is an Int (see GM_2P0) , and insnan() does not work on Ints. Error on some compilers. else if (isnan((*p1)[c]) == 1 || (*p1)[c] < 0.0) (*res)[c] = d_nan; else (*res)[c] = gm_expint((*p0)[0], (*p1)[c]); } } else if (nElp1 == 1) { for (SizeT c = 0; c < nElp; ++c) { if ((*p1)[0] == d_infinity) (*res)[c] = 0.0; //same comment as above else if (isnan((*p1)[0]) == 1 || (*p1)[0] < 0.0) (*res)[c] = d_nan; else (*res)[c] = gm_expint((*p0)[c], (*p1)[0]); } } else { for (SizeT c = 0; c < nElp; ++c) { if ((*p1)[c] == d_infinity) (*res)[c] = 0.0; //same comment as above else if (isnan((*p1)[c]) == 1 || (*p1)[c] < 0.0) (*res)[c] = d_nan; else (*res)[c] = gm_expint((*p0)[c], (*p1)[c]); } } GM_CV2(); } // expint_fun /* Modified Lentz's algorithm, as described in Numerical Recipes in C, section 5.2. See http://www.nrbook.com/b/bookcpdf/c5-2.pdf I strictly used the notation of the book. This algorithm is used to evaluate continued fractions. */ double gm_lentz(double a[], double b[], double tiny, int n, double eps) { double f, C, D, Delta; f = b[0]; if (b[0] == 0.0) { f = tiny; } C = f; D = 0.0; for (int j = 1; j <= n; j++) { D = b[j]+a[j]*D; if (D == 0.0) { D = tiny; } C = b[j]+a[j]/C; if (C == 0.0) { C = tiny; } D = 1.0/D; Delta = C*D; f = f*Delta; if (fabs(Delta-1.0) < eps) { return f; } } assert(false); return 0.0; } // gm_lentz double gm_expint(int n, double x) { int m; double res; m = n-1; if (n == 0) { res = exp(-x)/x; } else if (x == 0.0) { res = 1.0/m; } else if (x <= 1.0) // Series, used for 0 < x <= 1 { double c, Delta; res = m != 0 ? 1.0/m : -log(x)-M_EULER; c = 1.0; for (int i = 1; i <= GM_ITER; i++) { c *= -x/i; if (i != m) { Delta = -c/(i-m); } else { Delta = c*(-log(x)+gsl_sf_psi_int(n)); } res += Delta; if (fabs(Delta) < fabs(res)*GM_EPS) { return res; } } } else // Modified Lentz's algorithm, used for x > 1 { double a[GM_ITER+1], b[GM_ITER+1]; b[0] = 0.0; a[1] = 1.0; b[1] = x+n; for (int i = 2; i <= GM_ITER; i++) { a[i] = (1-i)*(n+i-2); b[i] = b[i-1]+2.0; } res = exp(-x)*gm_lentz(a, b, GM_TINY, GM_ITER, GM_EPS); return res; } return res; } // gm_expint } // namespace gdl-0.9.9/src/math_fun_gm.hpp000066400000000000000000000027161340051421000160570ustar00rootroot00000000000000/*************************************************************************** math_fun_gm.cpp - math GDL library function (GM) ------------------- begin : 03 May 2007 copyright : (C) 2007 by Gregory Marchal email : gregory.marchal_at_obspm.fr website : http://format.obspm.fr/~m1/gmarchal/ ****************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* erf_fun( EnvT* e); BaseGDL* errorf_fun( EnvT* e); BaseGDL* erfc_fun( EnvT* e); BaseGDL* gamma_fun( EnvT* e); BaseGDL* lngamma_fun( EnvT* e); BaseGDL* igamma_fun( EnvT* e); BaseGDL* beta_fun( EnvT* e); BaseGDL* expint_fun( EnvT* e); BaseGDL* gaussint_fun( EnvT* e); } // namespace gdl-0.9.9/src/math_fun_jmg.cpp000066400000000000000000001702111340051421000162200ustar00rootroot00000000000000/*************************************************************************** math_fun_jmg.cpp - math GDL library function (JMG) ------------------- begin : March 03 2004 copyright : (C) 2002 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "dinterpreter.hpp" #include "initsysvar.hpp" #include "math_utl.hpp" #include "math_fun_jmg.hpp" #include "graphicsdevice.hpp" //#define GDL_DEBUG #undef GDL_DEBUG #define COMPLEX2 GDL_COMPLEX #if defined(_MSC_VER) && _MSC_VER < 1800 #define FE_DIVBYZERO #define FE_UNDERFLOW #define FE_OVERFLOW #define FE_INVALID #define round(f) floor(f+0.5) #define isnan _isnan #define isinf !_finite #define isfinite _finite #define signbit(d) (d < 0.0)? 1:0 #endif namespace lib { using namespace std; #ifndef _MSC_VER using std::isinf; using std::isnan; #endif BaseGDL* machar_fun( EnvT* e) { long int ibeta, it, irnd, ngrd, machep, negep, iexp, minexp, maxexp; float eps, epsneg, xmin, xmax; double epsD, epsnegD, xminD, xmaxD; if( e->KeywordSet(0)) //DOUBLE { machar_d(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, &epsD, &epsnegD, &xminD, &xmaxD ); DStructGDL* machar = new DStructGDL( "DMACHAR"); machar->InitTag("IBETA", DLongGDL(ibeta)); machar->InitTag("IT", DLongGDL(it)); machar->InitTag("IRND", DLongGDL(irnd)); machar->InitTag("NGRD", DLongGDL(ngrd)); machar->InitTag("MACHEP", DLongGDL(machep)); machar->InitTag("NEGEP", DLongGDL(negep)); machar->InitTag("IEXP", DLongGDL(iexp)); machar->InitTag("MINEXP", DLongGDL(minexp)); machar->InitTag("MAXEXP", DLongGDL(maxexp)); machar->InitTag("EPS", DDoubleGDL(epsD)); machar->InitTag("EPSNEG", DDoubleGDL(epsnegD)); machar->InitTag("XMIN", DDoubleGDL(xminD)); machar->InitTag("XMAX", DDoubleGDL(xmaxD)); return machar; } else { machar_s(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, &eps, &epsneg, &xmin, &xmax ); DStructGDL* machar = new DStructGDL( "MACHAR"); machar->InitTag("IBETA", DLongGDL(ibeta)); machar->InitTag("IT", DLongGDL(it)); machar->InitTag("IRND", DLongGDL(irnd)); machar->InitTag("NGRD", DLongGDL(ngrd)); machar->InitTag("MACHEP", DLongGDL(machep)); machar->InitTag("NEGEP", DLongGDL(negep)); machar->InitTag("IEXP", DLongGDL(iexp)); machar->InitTag("MINEXP", DLongGDL(minexp)); machar->InitTag("MAXEXP", DLongGDL(maxexp)); machar->InitTag("EPS", DFloatGDL(eps)); machar->InitTag("EPSNEG", DFloatGDL(epsneg)); machar->InitTag("XMIN", DFloatGDL(xmin)); machar->InitTag("XMAX", DFloatGDL(xmax)); return machar; } } // #if 0 // template< typename T> // BaseGDL* finite_fun_template( BaseGDL* p0) // { // T* p0C = static_cast( p0); // DByteGDL* res = new DByteGDL( p0C->Dim(), BaseGDL::NOZERO); // SizeT nEl = p0->N_Elements(); // for( SizeT i=0; iType() == GDL_COMPLEX) { // float* dptr = (float*) &(*p0C)[0]; // } else if( p0->Type() == GDL_COMPLEXDBL) { // int a=0; // } else { // int out = isfinite((*p0C)[ i]); // if (out == 0) // (*res)[ i] = 0; // else // (*res)[ i] = 1; // } // } // return res; // } // #endif // BaseGDL* finite_fun( EnvT* e) // { // e->NParam( 1);//, "FINITE"); // BaseGDL* p0 = e->GetParDefined( 0);//, "FINITE"); // SizeT nEl = p0->N_Elements(); // if( nEl == 0) // e->Throw( "Variable is undefined: "+e->GetParString(0)); // DByteGDL* res = new DByteGDL( p0->Dim(), BaseGDL::NOZERO); // if( p0->Type() == GDL_COMPLEX) { // DComplexGDL* p0C = static_cast( p0); // for( SizeT i=0; iType() == GDL_COMPLEXDBL) { // DComplexDblGDL* p0C = static_cast( p0); // for( SizeT i=0; iType() == GDL_DOUBLE) { // DDoubleGDL* p0D = static_cast( p0); // for( SizeT i=0; iType() == GDL_FLOAT) { // DFloatGDL* p0F = static_cast( p0); // for( SizeT i=0; i // (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); // for( SizeT i=0; i struct finite_helper { inline static BaseGDL* do_it(T* src, bool kwNaN, bool kwInfinity) { DByteGDL* res = new DByteGDL( src->Dim(), BaseGDL::NOZERO); SizeT nEl = src->N_Elements(); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { if (kwNaN){ #pragma omp for for ( SizeT i=0; i struct finite_helper { inline static BaseGDL* do_it(T* src, bool kwNaN, bool kwInfinity) { DByteGDL* res = new DByteGDL( src->Dim(), BaseGDL::NOZERO); SizeT nEl = src->N_Elements(); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { if (kwNaN){ #pragma omp for for ( SizeT i=0; i inline BaseGDL* finite_template( BaseGDL* src, bool kwNaN, bool kwInfinity) { return finite_helper:: do_it(static_cast(src), kwNaN, kwInfinity); }; //general signed template template< typename T, bool> struct finite_helper_sign { inline static BaseGDL* do_it(T* src, bool kwNaN, bool kwInfinity, DLong kwSign) { DByteGDL* res = new DByteGDL( src->Dim(), BaseGDL::ZERO); // ::ZERO is not working SizeT nEl = src->N_Elements(); if (kwInfinity || kwNaN) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { if (kwInfinity) { if (kwSign > 0) { #pragma omp for for ( SizeT i=0; i 0) { #pragma omp for for ( SizeT i=0; i struct finite_helper_sign { inline static BaseGDL* do_it(T* src, bool kwNaN, bool kwInfinity, DLong kwSign) { DByteGDL* res = new DByteGDL( src->Dim(), BaseGDL::ZERO); SizeT nEl = src->N_Elements(); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for ( SizeT i=0; i 0) (*res)[i]=1; else if ((kwInfinity && isinf((*src)[ i].imag()) || kwNaN && isnan((*src)[ i].imag())) && signbit((*src)[ i].imag())==0 && kwSign > 0) (*res)[i]=1; else if ((kwInfinity && isinf((*src)[ i].real()) || kwNaN && isnan((*src)[ i].real())) && signbit((*src)[ i].real())!=0 && kwSign < 0) (*res)[i]=1; else if ((kwInfinity && isinf((*src)[ i].imag()) || kwNaN && isnan((*src)[ i].imag())) && signbit((*src)[ i].imag())!=0 && kwSign < 0) (*res)[i]=1; } } return res; } }; template< typename T, bool IS_COMPLEX> inline BaseGDL* finite_template( BaseGDL* src, bool kwNaN, bool kwInfinity, DLong kwSign) { return finite_helper_sign:: do_it(static_cast(src), kwNaN, kwInfinity, kwSign); }; BaseGDL* finite_fun( EnvT* e) { e->NParam( 1); BaseGDL* p0 = e->GetParDefined( 0); Guard guard; static int nanIx = e->KeywordIx( "NAN"); bool kwNaN = e->KeywordSet( nanIx); static int infinityIx = e->KeywordIx( "INFINITY"); bool kwInfinity = e->KeywordSet( infinityIx); static int signIx = e->KeywordIx( "SIGN"); DLong kwSign = 0; e->AssureLongScalarKWIfPresent( signIx, kwSign); if( kwNaN && kwInfinity) e->Throw("Conflicting keywords."); if(kwSign==0 || (kwInfinity==0 && kwNaN==0)) { switch (p0->Type()) { case GDL_FLOAT: { return finite_template(p0, kwNaN, kwInfinity); } case GDL_DOUBLE: { return finite_template(p0, kwNaN, kwInfinity); } case GDL_COMPLEX: { return finite_template(p0, kwNaN, kwInfinity); } case GDL_COMPLEXDBL: { return finite_template(p0, kwNaN, kwInfinity); } case GDL_STRING: { DFloatGDL* p0F = static_cast(p0->Convert2(GDL_FLOAT,BaseGDL::COPY)); guard.Reset( p0F); return finite_template(p0F, kwNaN, kwInfinity); } case GDL_STRUCT: case GDL_PTR: case GDL_OBJ: { e->Throw( p0->TypeStr() + " not allowed in this context: " + e->GetParString( 0)); } default: // integer types { if( kwNaN || kwInfinity) return new DByteGDL( p0->Dim()); // zero DByteGDL* res = new DByteGDL( p0->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); for (SizeT i=0; iType()) { case GDL_FLOAT: { return finite_template(p0, kwNaN, kwInfinity, kwSign); } case GDL_DOUBLE: { return finite_template(p0, kwNaN, kwInfinity, kwSign); } case GDL_COMPLEX: { return finite_template(p0, kwNaN, kwInfinity, kwSign); } case GDL_COMPLEXDBL: { return finite_template(p0, kwNaN, kwInfinity, kwSign); } case GDL_STRING: { DFloatGDL* p0F = static_cast(p0->Convert2(GDL_FLOAT,BaseGDL::COPY)); guard.Reset( p0F); return finite_template(p0F, kwNaN, kwInfinity, kwSign); } case GDL_STRUCT: case GDL_PTR: case GDL_OBJ: { e->Throw( p0->TypeStr() + " not allowed in this context: " + e->GetParString( 0)); } default: // integer types { if( kwNaN || kwInfinity) return new DByteGDL( p0->Dim()); // zero DByteGDL* res = new DByteGDL( p0->Dim(), BaseGDL::NOZERO); SizeT nEl = p0->N_Elements(); for (SizeT i=0; iNParam(); DLong flag_print=0, flag_noclear=0, flag_clear=1; DLong value=0; static DLong cumul_value; // auto init to 0 DLong mask=255; // static int printKwIx = e->KeywordIx("PRINT"); static int noClearKwIx = e->KeywordIx("NOCLEAR"); static int maskKwIx = e->KeywordIx("MASK"); flag_print = e->KeywordSet( printKwIx); flag_noclear = e->KeywordSet( noClearKwIx); // // if Params are provides (first: print, second: noclear) // they do overwrite the same provided by Keyword // if (nParam >= 1) { e->AssureLongScalarPar( 0, flag_print); } if (nParam == 2) { e->AssureLongScalarPar( 1, flag_noclear); } if (flag_noclear > 0) flag_clear=0; const int debug=0; if (debug) { cout << "Flag Print : " << flag_print << endl; cout << "Flag NoClear: " << flag_noclear << endl; cout << "Flag Clear: " << flag_clear << endl; } if( e->KeywordSet( maskKwIx)) e->AssureLongScalarKWIfPresent( maskKwIx, mask); if (mask & 16) { #if defined(_MSC_VER) && _MSC_VER < 1800 if (_statusfp() & _SW_ZERODIVIDE == _SW_ZERODIVIDE) { #else if (fetestexcept(FE_DIVBYZERO)) { #endif value = value | 16; if ( flag_print) cout << "% Program caused arithmetic error: Floating divide by 0" << endl; if ( flag_clear) feclearexcept(FE_DIVBYZERO); } } if (mask & 32) { #if defined(_MSC_VER) && _MSC_VER < 1800 if (_statusfp() & _SW_UNDERFLOW == _SW_UNDERFLOW) { #else if (fetestexcept(FE_UNDERFLOW)) { #endif value = value | 32; if ( flag_print) cout << "% Program caused arithmetic error: Floating underflow" << endl; if ( flag_clear) feclearexcept(FE_UNDERFLOW); } } if (mask & 64) { #if defined(_MSC_VER) && _MSC_VER < 1800 if (_statusfp() & _SW_OVERFLOW == _SW_OVERFLOW) { #else if (fetestexcept(FE_OVERFLOW)) { #endif value = value | 64; if ( flag_print) cout << "% Program caused arithmetic error: Floating overflow" << endl; if ( flag_clear) feclearexcept(FE_OVERFLOW); } } if (mask & 128) {// && value == 0) { #if defined(_MSC_VER) && _MSC_VER < 1800 if (_statusfp() & _SW_INVALID == _SW_INVALID) { #else if (fetestexcept(FE_INVALID)) { #endif value = value | 128; if ( flag_print) // avoid double message cout << "% Program caused arithmetic error: Floating illegal operand" << endl; if ( flag_clear) feclearexcept(FE_INVALID); } } if (debug) { cout << " value " <GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: "+e->GetParString(0)); if (p0->Rank() != 2) e->Throw( "Array must have 2 dimensions: "+e->GetParString(0)); DFloatGDL* p0F = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); DFloat fpi=4*atan(1.0); DFloat dx=1, dy=1; DFloat drho = 0.5 * sqrt(dx*dx + dy*dy); static int DXIx=e->KeywordIx("DX"); static int DYIx=e->KeywordIx("DY"); static int DRHOIx=e->KeywordIx("DRHO"); static int NXIx=e->KeywordIx("NX"); static int NYIx=e->KeywordIx("NY"); static int XMINIx=e->KeywordIx("XMIN"); static int YMINIx=e->KeywordIx("YMIN"); static int NTHETAIx=e->KeywordIx("NTHETA"); static int NRHOIx=e->KeywordIx("NRHO"); static int RMINIx=e->KeywordIx("RMIN"); static int BACKPROJECTIx=e->KeywordIx("BACKPROJECT"); if( e->KeywordSet( DXIx)) e->AssureFloatScalarKWIfPresent( DXIx, dx); if( e->KeywordSet( DYIx)) e->AssureFloatScalarKWIfPresent( DYIx, dy); if( e->KeywordSet( DRHOIx)) e->AssureFloatScalarKWIfPresent( DRHOIx, drho); DLong dims[2]; if( e->KeywordSet( BACKPROJECTIx)) { DLong ntheta=p0->Dim(0); DLong nrho=p0->Dim(1); DFloat dtheta=fpi/ntheta; DLong nx=(DLong) floor(2*((drho*nrho/2)/sqrt(dx*dx + dy*dy))+1); DLong ny=nx; if( e->KeywordSet( NXIx)) e->AssureLongScalarKWIfPresent( NXIx, nx); if( e->KeywordSet( NYIx)) e->AssureLongScalarKWIfPresent( NYIx, ny); dims[0] = nx; dims[1] = ny; dimension dim((DLong *) dims, 2); DFloat xmin = -0.5 * (nx-1); DFloat ymin = -0.5 * (ny-1); DFloat xmax = +0.5 * (nx-1); DFloat ymax = +0.5 * (ny-1); if( e->KeywordSet( YMINIx)) e->AssureFloatScalarKWIfPresent( XMINIx, xmin); if( e->KeywordSet( YMINIx)) e->AssureFloatScalarKWIfPresent( YMINIx, ymin); DFloatGDL* res = new DFloatGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; i 0 && indx < nrho) (*res)[m+n*nx] += dtheta * (*p0F)[itheta+ntheta*indx]; theta += dtheta; } } } return res; } else { // "Forward Radon Transform" DFloat maxr2[4], mrho2; DFloat xmin = -0.5 * (p0->Dim(0)-1); DFloat ymin = -0.5 * (p0->Dim(1)-1); DFloat xmax = +0.5 * (p0->Dim(0)-1); DFloat ymax = +0.5 * (p0->Dim(1)-1); if( e->KeywordSet( XMINIx)) e->AssureFloatScalarKWIfPresent( XMINIx, xmin); if( e->KeywordSet( YMINIx)) e->AssureFloatScalarKWIfPresent( YMINIx, xmin); maxr2[0] = xmin*xmin + ymin*ymin; maxr2[1] = xmin*xmin + ymax*ymax; maxr2[2] = xmax*xmax + ymin*ymin; maxr2[3] = xmax*xmax + ymax*ymax; mrho2 = maxr2[0]; if (maxr2[1] > mrho2) mrho2 = maxr2[1]; if (maxr2[2] > mrho2) mrho2 = maxr2[2]; if (maxr2[3] > mrho2) mrho2 = maxr2[3]; dims[0] = (DLong) ceil(fpi * sqrt(0.5*(p0->Dim(0)*p0->Dim(0) + p0->Dim(1)*p0->Dim(1)))); dims[1] = 2 * (DLong) ceil(sqrt(mrho2)/drho) + 1; if( e->KeywordSet( NTHETAIx)) e->AssureLongScalarKWIfPresent( NTHETAIx, dims[0]); if( e->KeywordSet( NRHOIx)) e->AssureLongScalarKWIfPresent( NRHOIx, dims[1]); static int thetaIx = e->KeywordIx( "THETA"); if( e->KeywordPresent( thetaIx)) { DFloatGDL* thetaKW = e->IfDefGetKWAs( thetaIx); if (thetaKW != NULL) dims[0] = thetaKW->N_Elements(); } DLong ntheta = dims[0]; DLong nrho = dims[1]; dimension dim((DLong *) dims, 2); DFloatGDL* res = new DFloatGDL( dim, BaseGDL::NOZERO); for( SizeT i=0; iKeywordSet( RMINIx)) e->AssureFloatScalarKWIfPresent( RMINIx, rmin); for( SizeT itheta=0; itheta 1/sqrt(2.0)) { DFloat a = -(dx/dy) * (cs/sn); DFloat den = dy * sn; DFloat num1 = xmin*cs + ymin*sn; rho = rmin; for( SizeT irho=0; irhoDim(0); ++m) { DLong indx = (DLong) round(a*m+b); if (indx < 0 || indx > (p0->Dim(1)-1)) continue; (*res)[itheta+irho*ntheta] += (*p0F)[m+(p0->Dim(0))*indx]; } rho += drho; (*res)[itheta+irho*ntheta] *= dx/abs(sn); } // irho loop } else { DFloat a = -(dy/dx) * (sn/cs); DFloat den = dx * cs; DFloat num1 = xmin*cs + ymin*sn; rho = rmin; for( SizeT irho=0; irhoDim(1); ++n) { DLong indx = (DLong) round(a*n+b); if (indx < 0 || indx > (p0->Dim(0)-1)) continue; // printf("indx: %d n: %d b: %f rho: %f\n",indx,n,b,rho); (*res)[itheta+irho*ntheta] += (*p0F)[n*(p0->Dim(0))+indx]; } rho += drho; (*res)[itheta+irho*ntheta] *= dy/abs(cs); } // irho loop } theta += dtheta; } // itheta loop // Write rho array to KW static int rhoIx = e->KeywordIx( "RHO"); if( e->KeywordPresent( rhoIx)) { BaseGDL** rhoKW = &e->GetKW( rhoIx); delete (*rhoKW); dimension dim((DLong *) &nrho, (SizeT) 1); *rhoKW = new DFloatGDL(dim, BaseGDL::NOZERO); for( SizeT irho=0; irhoKeywordPresent( thetaIx)) { if (e->IfDefGetKWAs( thetaIx) == NULL) { dimension dim((DLong *) &ntheta, (SizeT) 1); BaseGDL** thetaKW = &e->GetKW( thetaIx); delete (*thetaKW); *thetaKW = new DFloatGDL(dim, BaseGDL::NOZERO); for( SizeT itheta=0; itheta BaseGDL* warp_linear0( SizeT nCols, SizeT nRows, BaseGDL* data_, DDouble *P, DDouble *Q, DDouble initvalue_, bool doMissing) { DLong lx = data_->Dim(0); DLong ly = data_->Dim(1); dimension dim(nCols, nRows); T1* res_ = new T1(dim, BaseGDL::NOZERO); T2 initvalue = initvalue_; DLong nEl = nCols*nRows; T2* res = (T2*) res_->DataAddr(); T2* data = (T2*) data_->DataAddr(); if (doMissing) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (DLong i = 0; i < nCols * nRows; ++i) res[i] = initvalue; } } /* Double loop on the output image */ #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for collapse(2) for (DLong j = 0; j < nRows; ++j) { for (DLong i = 0; i < nCols; ++i) { // Compute the original source for this pixel, note order of j and i in P and Q definition of IDL doc. DLong px = (DLong) (P[0] + P[1] * (DDouble) j + P[2] * (DDouble) i); DLong py = (DLong) (Q[0] + Q[1] * (DDouble) j + Q[2] * (DDouble) i); if (doMissing && ((px < 0) || (px > (lx - 1)) || (py < 0) || (py > (ly - 1)))) { continue; // already initialised to 'missing' value. } else { if (px < 0) px = 0; if (px > (lx - 1)) px = (lx - 1); if (py < 0) py = 0; if (py > (ly - 1)) py = (ly - 1); res[i + j * nCols] = data[px + py * lx]; } } } } return res_; } template< typename T1, typename T2> BaseGDL* warp_linear2( SizeT nCols, SizeT nRows, BaseGDL* data_, DDouble *P, DDouble *Q, DDouble cubicParameter, DDouble missingValue, bool doMissing) { DLong lx = data_->Dim(0); DLong ly = data_->Dim(1); dimension dim(nCols, nRows); T1* res_ = new T1(dim, BaseGDL::NOZERO); T2 initvalue = missingValue; DLong nEl = nCols*nRows; T2* res = (T2*) res_->DataAddr(); T2* data = (T2*) data_->DataAddr(); int leaps[16]; DDouble * kernel = generate_interpolation_kernel(2, cubicParameter); /* Pre compute leaps for 16 closest neighbors positions */ leaps[0] = -1 - lx; leaps[1] = -lx; leaps[2] = 1 - lx; leaps[3] = 2 - lx; leaps[4] = -1; leaps[5] = 0; leaps[6] = 1; leaps[7] = 2; leaps[8] = -1 + lx; leaps[9] = lx; leaps[10] = 1 + lx; leaps[11] = 2 + lx; leaps[12] = -1 + 2 * lx; leaps[13] = 2 * lx; leaps[14] = 1 + 2 * lx; leaps[15] = 2 + 2 * lx; if (doMissing) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (DLong i = 0; i < nCols * nRows; ++i) res[i] = initvalue; } } /* Double loop on the output image */ #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for collapse(2) for (DLong j = 0; j < nRows; ++j) { for (DLong i = 0; i < nCols; ++i) { // Compute the original source for this pixel, note order of j and i in P and Q definition of IDL doc. DDouble x = (P[0] + P[1] * (DDouble) j + P[2] * (DDouble) i); DLong px = (DLong) x; DDouble y = (Q[0] + Q[1] * (DDouble) j + Q[2] * (DDouble) i); DLong py = (DLong) y; if (doMissing && ((px < 0) || (px > (lx - 1)) || (py < 0) || (py > (ly - 1)))) { continue; // already initialised to 'missing' value. } else { if (px < 1) px = 0; if (px > (lx - 1)) px = (lx - 1); if (py < 1) py = 0; if (py > (ly - 1)) py = (ly - 1); if ((px < 1) || (px > (lx - 3)) || (py < 1) || (py > (ly - 3))) res[i + j * nCols] = data[px + py * lx]; else { DDouble cur; DDouble neighbors[16]; DDouble rsc[8], sumrs; // Feed the positions for the closest 16 neighbors for (SizeT k = 0; k < 16; ++k) neighbors[k] = data[px + py * lx + leaps[k]]; DDouble dpx = (DDouble) px; DDouble dpy = (DDouble) py; // Which tabulated value index shall we use? DLong tabx = (DLong) ((x - dpx) * (DDouble) (TABSPERPIX)); DLong taby = (DLong) ((y - dpy) * (DDouble) (TABSPERPIX)); /* Compute resampling coefficients */ /* rsc[0..3] in x, rsc[4..7] in y */ rsc[0] = kernel[TABSPERPIX + tabx]; rsc[1] = kernel[tabx]; rsc[2] = kernel[TABSPERPIX - tabx]; rsc[3] = kernel[2 * TABSPERPIX - tabx]; rsc[4] = kernel[TABSPERPIX + taby]; rsc[5] = kernel[taby]; rsc[6] = kernel[TABSPERPIX - taby]; rsc[7] = kernel[2 * TABSPERPIX - taby]; sumrs = (rsc[0] + rsc[1] + rsc[2] + rsc[3]) * (rsc[4] + rsc[5] + rsc[6] + rsc[7]); /* Compute interpolated pixel now */ cur = rsc[4] * (rsc[0] * neighbors[0] + rsc[1] * neighbors[1] + rsc[2] * neighbors[2] + rsc[3] * neighbors[3]) + rsc[5] * (rsc[0] * neighbors[4] + rsc[1] * neighbors[5] + rsc[2] * neighbors[6] + rsc[3] * neighbors[7]) + rsc[6] * (rsc[0] * neighbors[8] + rsc[1] * neighbors[9] + rsc[2] * neighbors[10] + rsc[3] * neighbors[11]) + rsc[7] * (rsc[0] * neighbors[12] + rsc[1] * neighbors[13] + rsc[2] * neighbors[14] + rsc[3] * neighbors[15]); /* Affect the value to the output image */ res[i + j * nCols] = (cur / sumrs); /* done ! */ } } } } } free(kernel); return res_; } template< typename T1, typename T2> BaseGDL* warp_linear1( SizeT nCols, SizeT nRows, BaseGDL* data_, DDouble *P, DDouble *Q, DDouble missingValue, bool doMissing) { DLong lx = data_->Dim(0); DLong ly = data_->Dim(1); dimension dim(nCols, nRows); T1* res_ = new T1(dim, BaseGDL::NOZERO); T2 initvalue = missingValue; DLong nEl = nCols*nRows; T2* res = (T2*) res_->DataAddr(); T2* data = (T2*) data_->DataAddr(); int leaps[9]; DDouble * kernel = generate_interpolation_kernel(1, 0.0); /* Pre compute leaps for 9 closest neighbors positions */ leaps[0] = -1 - lx; leaps[1] = -lx; leaps[2] = 1 - lx; leaps[3] = -1; leaps[4] = 0; leaps[5] = 1; leaps[6] = -1 + lx; leaps[7] = lx; leaps[8] = 1 + lx; if (doMissing) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (DLong i = 0; i < nCols * nRows; ++i) res[i] = initvalue; } } /* Double loop on the output image */ #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for collapse(2) for (DLong j = 0; j < nRows; ++j) { for (DLong i = 0; i < nCols; ++i) { // Compute the original source for this pixel, note order of j and i in P and Q definition of IDL doc. DDouble x = (P[0] + P[1] * (DDouble) j + P[2] * (DDouble) i); DLong px = (DLong) x; DDouble y = (Q[0] + Q[1] * (DDouble) j + Q[2] * (DDouble) i); DLong py = (DLong) y; if (doMissing && ((px < 0) || (px > (lx - 1)) || (py < 0) || (py > (ly - 1)))) { continue; // already initialised to 'missing' value. } else { if (px < 1) px = 0; if (px > (lx - 1)) px = (lx - 1); if (py < 1) py = 0; if (py > (ly - 1)) py = (ly - 1); if ((px < 1) || (px > (lx - 2)) || (py < 1) || (py > (ly - 2))) res[i + j * nCols] = data[px + py * lx]; else { DDouble cur; DDouble neighbors[9]; DDouble rsc[6], sumrs; // Feed the positions for the closest 16 neighbors for (SizeT k = 0; k < 9; ++k) neighbors[k] = data[px + py * lx + leaps[k]]; DDouble dpx = (DDouble) px; DDouble dpy = (DDouble) py; // Which tabulated value index shall we use? DLong tabx = (DLong) ((x - dpx) * (DDouble) (TABSPERPIX)); DLong taby = (DLong) ((y - dpy) * (DDouble) (TABSPERPIX)); /* Compute resampling coefficients */ /* rsc[0..3] in x, rsc[4..7] in y */ rsc[0] = kernel[TABSPERPIX + tabx]; rsc[1] = kernel[tabx]; rsc[2] = kernel[TABSPERPIX - tabx]; rsc[3] = kernel[TABSPERPIX + taby]; rsc[4] = kernel[taby]; rsc[5] = kernel[TABSPERPIX - taby]; sumrs = (rsc[0] + rsc[1] + rsc[2]) * (rsc[3] + rsc[4] + rsc[5]); /* Compute interpolated pixel now */ cur = rsc[3] * (rsc[0] * neighbors[0] + rsc[1] * neighbors[1] + rsc[2] * neighbors[2]) + rsc[4] * (rsc[0] * neighbors[3] + rsc[1] * neighbors[4] + rsc[2] * neighbors[5]) + rsc[5] * (rsc[0] * neighbors[6] + rsc[1] * neighbors[7] + rsc[2] * neighbors[8]); /* Affect the value to the output image */ res[i + j * nCols] = (cur / sumrs); /* done ! */ } } } } } free(kernel); return res_; } template< typename T1, typename T2> BaseGDL* warp0( SizeT nCols, SizeT nRows, BaseGDL* data_, poly2d* poly_u, poly2d* poly_v, DDouble initvalue_, bool doMissing) { DLong lx = data_->Dim(0); DLong ly = data_->Dim(1); dimension dim(nCols, nRows); T1* res_ = new T1(dim, BaseGDL::NOZERO); T2 initvalue = initvalue_; DLong nEl = nCols*nRows; T2* res = (T2*) res_->DataAddr(); T2* data = (T2*) data_->DataAddr(); if (doMissing) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (DLong i = 0; i < nCols * nRows; ++i) res[i] = initvalue; } } /* Double loop on the output image */ #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for collapse(2) for (DLong j = 0; j < nRows; ++j) { for (DLong i = 0; i < nCols; ++i) { // Compute the original source for this pixel, note order of j and i. DDouble x = poly2d_compute(poly_u, (DDouble) j, (DDouble) i); DDouble y = poly2d_compute(poly_v, (DDouble) j, (DDouble) i); DLong px = (DLong) x; DLong py = (DLong) y; if (doMissing && ((px < 0) || (px > (lx - 1)) || (py < 0) || (py > (ly - 1)))) { continue; // already initialised to 'missing' value. } else { if (px < 0) px = 0; if (px > (lx - 1)) px = (lx - 1); if (py < 0) py = 0; if (py > (ly - 1)) py = (ly - 1); res[i + j * nCols] = data[px + py * lx]; } } } } free(poly_u->px); free(poly_u->py); free(poly_u->c); free(poly_u); free(poly_v->px); free(poly_v->py); free(poly_v->c); free(poly_v); return res_; } template< typename T1, typename T2> BaseGDL* warp2( SizeT nCols, SizeT nRows, BaseGDL* data_, DDouble cubicParameter, poly2d* poly_u, poly2d* poly_v, DDouble missingValue, bool doMissing) { DLong lx = data_->Dim(0); DLong ly = data_->Dim(1); dimension dim(nCols, nRows); T1* res_ = new T1(dim, BaseGDL::NOZERO); T2 initvalue = missingValue; DLong nEl = nCols*nRows; T2* res = (T2*) res_->DataAddr(); T2* data = (T2*) data_->DataAddr(); int leaps[16]; DDouble * kernel = generate_interpolation_kernel(2, cubicParameter); /* Pre compute leaps for 16 closest neighbors positions */ leaps[0] = -1 - lx; leaps[1] = -lx; leaps[2] = 1 - lx; leaps[3] = 2 - lx; leaps[4] = -1; leaps[5] = 0; leaps[6] = 1; leaps[7] = 2; leaps[8] = -1 + lx; leaps[9] = lx; leaps[10] = 1 + lx; leaps[11] = 2 + lx; leaps[12] = -1 + 2 * lx; leaps[13] = 2 * lx; leaps[14] = 1 + 2 * lx; leaps[15] = 2 + 2 * lx; if (doMissing) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (DLong i = 0; i < nCols * nRows; ++i) res[i] = initvalue; } } /* Double loop on the output image */ #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for collapse(2) for (DLong j = 0; j < nRows; ++j) { for (DLong i = 0; i < nCols; ++i) { // Compute the original source for this pixel, note order of j and i. DDouble x = poly2d_compute(poly_u, (DDouble) j, (DDouble) i); DDouble y = poly2d_compute(poly_v, (DDouble) j, (DDouble) i); DLong px = (DLong) x; DLong py = (DLong) y; if (doMissing && ((px < 0) || (px > (lx - 1)) || (py < 0) || (py > (ly - 1)))) { continue; // already initialised to 'missing' value. } else { if (px < 1) px = 0; if (px > (lx - 1)) px = (lx - 1); if (py < 1) py = 0; if (py > (ly - 1)) py = (ly - 1); if ((px < 1) || (px > (lx - 3)) || (py < 1) || (py > (ly - 3))) res[i + j * nCols] = data[px + py * lx]; else { DDouble cur; DDouble neighbors[16]; DDouble rsc[8], sumrs; // Feed the positions for the closest 16 neighbors for (SizeT k = 0; k < 16; ++k) neighbors[k] = data[px + py * lx + leaps[k]]; DDouble dpx = (DDouble) px; DDouble dpy = (DDouble) py; // Which tabulated value index shall we use? DLong tabx = (DLong) ((x - dpx) * (DDouble) (TABSPERPIX)); DLong taby = (DLong) ((y - dpy) * (DDouble) (TABSPERPIX)); /* Compute resampling coefficients */ /* rsc[0..3] in x, rsc[4..7] in y */ rsc[0] = kernel[TABSPERPIX + tabx]; rsc[1] = kernel[tabx]; rsc[2] = kernel[TABSPERPIX - tabx]; rsc[3] = kernel[2 * TABSPERPIX - tabx]; rsc[4] = kernel[TABSPERPIX + taby]; rsc[5] = kernel[taby]; rsc[6] = kernel[TABSPERPIX - taby]; rsc[7] = kernel[2 * TABSPERPIX - taby]; sumrs = (rsc[0] + rsc[1] + rsc[2] + rsc[3]) * (rsc[4] + rsc[5] + rsc[6] + rsc[7]); /* Compute interpolated pixel now */ cur = rsc[4] * (rsc[0] * neighbors[0] + rsc[1] * neighbors[1] + rsc[2] * neighbors[2] + rsc[3] * neighbors[3]) + rsc[5] * (rsc[0] * neighbors[4] + rsc[1] * neighbors[5] + rsc[2] * neighbors[6] + rsc[3] * neighbors[7]) + rsc[6] * (rsc[0] * neighbors[8] + rsc[1] * neighbors[9] + rsc[2] * neighbors[10] + rsc[3] * neighbors[11]) + rsc[7] * (rsc[0] * neighbors[12] + rsc[1] * neighbors[13] + rsc[2] * neighbors[14] + rsc[3] * neighbors[15]); /* Affect the value to the output image */ res[i + j * nCols] = (cur / sumrs); /* done ! */ } } } } } free(kernel); free(poly_u->px); free(poly_u->py); free(poly_u->c); free(poly_u); free(poly_v->px); free(poly_v->py); free(poly_v->c); free(poly_v); return res_; } template< typename T1, typename T2> BaseGDL* warp1( SizeT nCols, SizeT nRows, BaseGDL* data_, poly2d* poly_u, poly2d* poly_v, DDouble missingValue, bool doMissing) { DLong lx = data_->Dim(0); DLong ly = data_->Dim(1); dimension dim(nCols, nRows); T1* res_ = new T1(dim, BaseGDL::NOZERO); T2 initvalue = missingValue; DLong nEl = nCols*nRows; T2* res = (T2*) res_->DataAddr(); T2* data = (T2*) data_->DataAddr(); int leaps[9]; DDouble * kernel = generate_interpolation_kernel(1, 0.0); /* Pre compute leaps for 9 closest neighbors positions */ leaps[0] = -1 - lx; leaps[1] = -lx; leaps[2] = 1 - lx; leaps[3] = -1; leaps[4] = 0; leaps[5] = 1; leaps[6] = -1 + lx; leaps[7] = lx; leaps[8] = 1 + lx; if (doMissing) { #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (DLong i = 0; i < nCols * nRows; ++i) res[i] = initvalue; } } /* Double loop on the output image */ #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for collapse(2) for (DLong j = 0; j < nRows; ++j) { for (DLong i = 0; i < nCols; ++i) { // Compute the original source for this pixel, note order of j and i. DDouble x = poly2d_compute(poly_u, (DDouble) j, (DDouble) i); DDouble y = poly2d_compute(poly_v, (DDouble) j, (DDouble) i); DLong px = (DLong) x; DLong py = (DLong) y; if (doMissing && ((px < 0) || (px > (lx - 1)) || (py < 0) || (py > (ly - 1)))) { continue; // already initialised to 'missing' value. } else { if (px < 1) px = 0; if (px > (lx - 1)) px = (lx - 1); if (py < 1) py = 0; if (py > (ly - 1)) py = (ly - 1); if ((px < 1) || (px > (lx - 2)) || (py < 1) || (py > (ly - 2))) res[i + j * nCols] = data[px + py * lx]; else { DDouble cur; DDouble neighbors[9]; DDouble rsc[6], sumrs; // Feed the positions for the closest 16 neighbors for (SizeT k = 0; k < 9; ++k) neighbors[k] = data[px + py * lx + leaps[k]]; DDouble dpx = (DDouble) px; DDouble dpy = (DDouble) py; // Which tabulated value index shall we use? DLong tabx = (DLong) ((x - dpx) * (DDouble) (TABSPERPIX)); DLong taby = (DLong) ((y - dpy) * (DDouble) (TABSPERPIX)); /* Compute resampling coefficients */ /* rsc[0..3] in x, rsc[4..7] in y */ rsc[0] = kernel[TABSPERPIX + tabx]; rsc[1] = kernel[tabx]; rsc[2] = kernel[TABSPERPIX - tabx]; rsc[3] = kernel[TABSPERPIX + taby]; rsc[4] = kernel[taby]; rsc[5] = kernel[TABSPERPIX - taby]; sumrs = (rsc[0] + rsc[1] + rsc[2]) * (rsc[3] + rsc[4] + rsc[5]); /* Compute interpolated pixel now */ cur = rsc[3] * (rsc[0] * neighbors[0] + rsc[1] * neighbors[1] + rsc[2] * neighbors[2]) + rsc[4] * (rsc[0] * neighbors[3] + rsc[1] * neighbors[4] + rsc[2] * neighbors[5]) + rsc[5] * (rsc[0] * neighbors[6] + rsc[1] * neighbors[7] + rsc[2] * neighbors[8]); /* Affect the value to the output image */ res[i + j * nCols] = (cur / sumrs); /* done ! */ } } } } } free(kernel); free(poly_u->px); free(poly_u->py); free(poly_u->c); free(poly_u); free(poly_v->px); free(poly_v->py); free(poly_v->c); free(poly_v); return res_; } BaseGDL* poly_2d_fun(EnvT* e) { /* The poly_2d code is inspired by "ECLIPSE", the ESO C Library for an Image Processing Software Environment N. Devillard, "The eclipse software", The messenger No 87 - March 1997 http://www.eso.org/projects/aot/eclipse/ */ SizeT nParam = e->NParam(); if (nParam < 3) e->Throw("Incorrect number of arguments."); BaseGDL* p0 = e->GetParDefined(0); if (p0->Type() == GDL_COMPLEX || p0->Type() == GDL_COMPLEXDBL) e->Throw("Complex values not supported (FIXME)"); if (p0->Rank() != 2) e->Throw("Array must have 2 dimensions: " + e->GetParString(0)); BaseGDL* p1 = e->GetParDefined(1); BaseGDL* p2 = e->GetParDefined(2); DLong interp = 0; if (nParam >= 4) e->AssureLongScalarPar(3, interp); if (interp < 0 || interp > 2) e->Throw("Value of Interpolation type is out of allowed range."); if (nParam == 5) e->Throw("Incorrect number of arguments."); DLong nCol = p0->Dim(0); DLong nRow = p0->Dim(1); if (nParam >= 6) { e->AssureLongScalarPar(4, nCol); e->AssureLongScalarPar(5, nRow); if (nCol <1 || nRow <1) e->Throw("Array dimensions must be greater than 0."); } static int CUBICIx = e->KeywordIx("CUBIC"); DDouble cubicParameter = -0.5; if (e->KeywordSet(CUBICIx)) { e->AssureDoubleScalarKWIfPresent(CUBICIx, cubicParameter); interp = 2; } static int MISSINGIx = e->KeywordIx("MISSING"); DDouble missing = 0.0; bool doMissing = (e->KeywordPresent(MISSINGIx)); if (doMissing) { e->AssureDoubleScalarKWIfPresent(MISSINGIx, missing); } // check P dimension first DLong Psize=p1->N_Elements(); if (Psize < 4) e->Throw("Value of Polynomial degree is out of allowed range."); DDouble dPdim = sqrt((DDouble) Psize); DLong nDegree = (DLong) dPdim -1; DLong nc=(nDegree + 1) * (nDegree + 1); if ( p2->N_Elements() < nc ) e->Throw("Coefficient arrays must have (degree+1)^2 elements"); DDoubleGDL* P = static_cast (p1->Convert2(GDL_DOUBLE, BaseGDL::COPY)); DDoubleGDL* Q = static_cast (p2->Convert2(GDL_DOUBLE, BaseGDL::COPY)); if (nDegree == 1 && (*P)[3] == 0 && (*Q)[3] == 0 ) { //LINEAR CASE //return p0 if identity. if ((*P)[0] == 0 && (*P)[1] == 0 && (*P)[2] == 1 && (*P)[3] == 0 && (*Q)[0] == 0 && (*Q)[1] == 1 && (*Q)[2] == 0 && (*Q)[3] == 0) { return p0->Dup(); } if (interp==0) { if (p0->Type() == GDL_BYTE) { return warp_linear0< DByteGDL, DByte>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_INT) { return warp_linear0< DIntGDL, DInt>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_UINT) { return warp_linear0< DUIntGDL, DUInt>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_LONG) { return warp_linear0< DLongGDL, DLong>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_ULONG) { return warp_linear0< DULongGDL, DULong>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_LONG64) { return warp_linear0< DLong64GDL, DLong64>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_ULONG64) { return warp_linear0< DULong64GDL, DULong64>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_FLOAT) { return warp_linear0< DFloatGDL, DFloat>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_DOUBLE) { return warp_linear0< DDoubleGDL, DDouble>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } } else if (interp==1) { if (p0->Type() == GDL_BYTE) { return warp_linear1< DByteGDL, DByte>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_INT) { return warp_linear1< DIntGDL, DInt>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_UINT) { return warp_linear1< DUIntGDL, DUInt>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_LONG) { return warp_linear1< DLongGDL, DLong>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_ULONG) { return warp_linear1< DULongGDL, DULong>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_LONG64) { return warp_linear1< DLong64GDL, DLong64>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_ULONG64) { return warp_linear1< DULong64GDL, DULong64>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_FLOAT) { return warp_linear1< DFloatGDL, DFloat>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } else if (p0->Type() == GDL_DOUBLE) { return warp_linear1< DDoubleGDL, DDouble>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), missing, doMissing); } } else if (interp==2) { if (p0->Type() == GDL_BYTE) { return warp_linear2< DByteGDL, DByte>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_INT) { return warp_linear2< DIntGDL, DInt>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_UINT) { return warp_linear2< DUIntGDL, DUInt>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_LONG) { return warp_linear2< DLongGDL, DLong>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_ULONG) { return warp_linear2< DULongGDL, DULong>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_LONG64) { return warp_linear2< DLong64GDL, DLong64>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_ULONG64) { return warp_linear2< DULong64GDL, DULong64>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_FLOAT) { return warp_linear2< DFloatGDL, DFloat>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } else if (p0->Type() == GDL_DOUBLE) { return warp_linear2< DDoubleGDL, DDouble>(nCol, nRow, p0, (DDouble*) P->DataAddr(),(DDouble*) Q->DataAddr(), cubicParameter, missing, doMissing); } } } else { //NON-LINEAR Polynomial poly2d* poly_u; poly2d* poly_v; poly_u = (poly2d *) malloc(sizeof (poly2d)); poly_u->nc = nc; poly_u->px = (DLong *) malloc(nc * sizeof (DLong)); poly_u->py = (DLong *) malloc(nc * sizeof (DLong)); poly_u->c = (DDouble *) malloc(nc * sizeof (DDouble)); for (SizeT i = 0; i < (nDegree + 1)*(nDegree + 1); ++i) { poly_u->px[i] = i / (nDegree + 1); poly_u->py[i] = i - (poly_u->px[i] * (nDegree + 1)); poly_u->c[i] = (*P)[poly_u->px[i]+(nDegree + 1) * poly_u->py[i]]; } poly_v = (poly2d *) malloc(sizeof (poly2d)); poly_v->nc = nc; poly_v->px = (DLong *) malloc(nc * sizeof (DLong)); poly_v->py = (DLong *) malloc(nc * sizeof (DLong)); poly_v->c = (DDouble *) malloc(nc * sizeof (DDouble)); for (SizeT i = 0; i < (nDegree + 1)*(nDegree + 1); ++i) { poly_v->px[i] = i / (nDegree + 1); poly_v->py[i] = i - (poly_v->px[i] * (nDegree + 1)); poly_v->c[i] = (*Q)[poly_v->px[i]+(nDegree + 1) * poly_v->py[i]]; } if (interp==0) { if (p0->Type() == GDL_BYTE) { return warp0< DByteGDL, DByte>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_INT) { return warp0< DIntGDL, DInt>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_UINT) { return warp0< DUIntGDL, DUInt>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_LONG) { return warp0< DLongGDL, DLong>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_ULONG) { return warp0< DULongGDL, DULong>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_LONG64) { return warp0< DLong64GDL, DLong64>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_ULONG64) { return warp0< DULong64GDL, DULong64>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_FLOAT) { return warp0< DFloatGDL, DFloat>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_DOUBLE) { return warp0< DDoubleGDL, DDouble>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } } else if (interp==1) { if (p0->Type() == GDL_BYTE) { return warp1< DByteGDL, DByte>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_INT) { return warp1< DIntGDL, DInt>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_UINT) { return warp1< DUIntGDL, DUInt>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_LONG) { return warp1< DLongGDL, DLong>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_ULONG) { return warp1< DULongGDL, DULong>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_LONG64) { return warp1< DLong64GDL, DLong64>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_ULONG64) { return warp1< DULong64GDL, DULong64>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_FLOAT) { return warp1< DFloatGDL, DFloat>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_DOUBLE) { return warp1< DDoubleGDL, DDouble>(nCol, nRow, p0, poly_u, poly_v, missing, doMissing); } } else if (interp==2) { if (p0->Type() == GDL_BYTE) { return warp2< DByteGDL, DByte>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_INT) { return warp2< DIntGDL, DInt>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_UINT) { return warp2< DUIntGDL, DUInt>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_LONG) { return warp2< DLongGDL, DLong>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_ULONG) { return warp2< DULongGDL, DULong>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_LONG64) { return warp2< DLong64GDL, DLong64>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_ULONG64) { return warp2< DULong64GDL, DULong64>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_FLOAT) { return warp2< DFloatGDL, DFloat>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } else if (p0->Type() == GDL_DOUBLE) { return warp2< DDoubleGDL, DDouble>(nCol, nRow, p0, cubicParameter, poly_u, poly_v, missing, doMissing); } } } return NULL; } /*-------------------------------------------------------------------------*/ /** @brief Same as pow(x,y) but for integer values of y only (faster). @param x A double number. @param p An integer power. @return x to the power p. This is much faster than the math function due to the integer. Some compilers make this optimization already, some do not. p can be positive, negative or null. */ /*--------------------------------------------------------------------------*/ double ipow(double x, int p) { double r, recip ; /* Get rid of trivial cases */ switch (p) { case 0: return 1.00 ; case 1: return x ; case 2: return x*x ; case 3: return x*x*x ; case -1: return 1.00 / x ; case -2: return (1.00 / x) * (1.00 / x) ; } if (p>0) { r = x ; while (--p) r *= x ; } else { r = recip = 1.00 / x ; while (++p) r *= recip ; } return r; } /*-------------------------------------------------------------------------*/ /** @brief Compute the value of a poly2d at a given point. @param p Poly2d object. @param x x coordinate. @param y y coordinate. @return The value of the 2d polynomial at (x,y) as a double. This computes the value of a poly2d in a single point. To compute many values in a row, see poly2d_compute_array(). */ /*--------------------------------------------------------------------------*/ double poly2d_compute( poly2d * p, double x, double y) { double z ; int i ; z = 0.00 ; for (i=0 ; inc ; i++) { z += p->c[i] * ipow(x, p->px[i]) * ipow(y, p->py[i]) ; } return z ; } ///*-------------------------------------------------------------------------*/ ///** // @brief Cardinal sine. // @param x double value. // @return 1 double. // // Compute the value of the function sinc(x)=sin(pi*x)/(pi*x) at the // requested x. // */ ///*--------------------------------------------------------------------------*/ //double sinc(double x) //{ // if (fabs(x)<1e-4) // return (double)1.00 ; // else // return ((sin(x * (double)PI_NUMB)) / (x * (double)PI_NUMB)) ; //} /*-------------------------------------------------------------------------*/ /** @brief Generate an interpolation kernel to use in this module. @param kernel_type (integer) 1:linear 2:cubic 3 quintic @param cubic (DDouble) cubic parameter [0..1[ for cubic kernel. @return 1 newly allocated array of doubles. The returned array of doubles must be deallocated using free(). */ /*--------------------------------------------------------------------------*/ DDouble * generate_interpolation_kernel(int kernel_type, DDouble cubicParameter) { double * tab ; int i ; double x ; int samples = KERNEL_SAMPLES ; /* Taken from "Image Reconstruction By Piecewise Polynomial Kernels", Meijering et al */ if (kernel_type == 1) { tab = (double *) calloc(samples , sizeof(double)) ; tab[0] = 1.0 ; for (i=1 ; i= 1) tab[i] = 0; } } else if (kernel_type == 2) { //uses cubic tab = (double *) calloc(samples , sizeof(double)) ; tab[0] = 1.0 ; for (i=1 ; iNParam(); if (nParam !=2) e->Throw(" function VOIGT takes 2 params: 'Result = VOIGT(A,U)' "); DFloatGDL* A = e->GetParAs(0); //AC2018 if(e->GetParDefined(0)->Type() == GDL_COMPLEX || e->GetParDefined(0)->Type() == GDL_COMPLEXDBL) // e->Throw(" no complex : "); DFloatGDL* U = e->GetParAs(1); //AC2018 if(e->GetParDefined(1)->Type() == GDL_COMPLEX || e->GetParDefined(1)->Type() == GDL_COMPLEXDBL) //e->Throw(" no complex : "); // Use to define NaN which is returned if one parameter of humlik function is Not A Number DStructGDL *Values = SysVar::Values(); //MUST NOT BE STATIC, due to .reset DDouble d_nan=(*static_cast(Values->GetTag(Values->Desc()->TagIndex("D_NAN"), 0)))[0]; DDouble d_infinity= (*static_cast(Values->GetTag(Values->Desc()->TagIndex("D_INFINITY"), 0)))[0]; // we don't use Gregory formalism (see macros in "math_fun_gm.cpp") // but we follow him notations ... just in case ... // Assign dimension(s) to "res" SizeT nElp0 = A->N_Elements(); SizeT nElp1 = U->N_Elements(); DFloatGDL* res ; if (A->Rank() == 0) \ res = new DFloatGDL(U->Dim(), BaseGDL::NOZERO); \ else if (U->Rank() == 0) \ res = new DFloatGDL(A->Dim(), BaseGDL::NOZERO); \ else if (A->N_Elements() > U->N_Elements()) \ res = new DFloatGDL(U->Dim(), BaseGDL::NOZERO); \ else \ res = new DFloatGDL(A->Dim(), BaseGDL::NOZERO); \ /* the obsolete version (before idl 8.4) if (nElp0 == 1 && nElp1 == 1) { if (A->Rank() > U->Rank()) res = new DFloatGDL(A->Dim(), BaseGDL::NOZERO); else res = new DFloatGDL(U->Dim(), BaseGDL::NOZERO); } else if (nElp0 > 1 && nElp1 == 1) res = new DFloatGDL(A->Dim(), BaseGDL::NOZERO); else if (nElp0 == 1 && nElp1 > 1) res = new DFloatGDL(U->Dim(), BaseGDL::NOZERO); else if (nElp0 <= nElp1) res = new DFloatGDL(A->Dim(), BaseGDL::NOZERO); else res = new DFloatGDL(U->Dim(), BaseGDL::NOZERO); */ SizeT nElp = res->N_Elements(); float InitA = (*A)[0]; float InitU = (*U)[0]; SizeT i; // Here also, we follow Nicolas choices, but can be simplified ... // Voigt ( scalar , scalar ) if (nElp0 == 1 && nElp1 == 1) { if (isfinite(InitA)==0 || isfinite(InitU)==0) { if ((InitU == d_infinity || InitU == -d_infinity ) && isfinite(InitA) != 0) (*res)[0] = 0.0000; else (*res)[0] = d_nan; } else if(InitA<0) (*res)[0] = -(humlik( InitU,-(InitA ))); else (*res)[0] = humlik( InitU,InitA ); } // Voigt ( array , array ) if (nElp0 > 1 && nElp1 > 1) { for (i=0;i 1) { /* obsolete !! if ((A->Rank() > 0) && (SysVar::GDL_Warning())) { Warning ( "You are using a case where IDL and GDL don't work similarly:"); Warning ( "in Voigt(A,U), A is a singleton array and U a true array: check your code !"); Warning ( "in GDL: Voigt(1,[0,1,2]) == Voigt([1],[0,1,2]) == Voigt([1,1,1],[0,1,2])."); Warning ( "You can turn OFF this warning changing !GDL_WARNING to 0."); } */ for (i=0;i 1 && nElp1 == 1) { /* obsolete !! if ((U->Rank() > 0) && (SysVar::GDL_Warning())) { Warning ( "You are using a case where IDL and GDL don't work similarly:"); Warning ( "in Voigt(A,U), U is a singleton array and A a true array: check your code !"); Warning ( "in GDL: Voigt([0,1,2], 1) == Voigt([0,1,2],[1]) == Voigt([0,1,2],[1,1,1])."); Warning ( "You can turn OFF this warning changing !GDL_WARNING to 0."); } */ for (i=0;iGetParDefined(0)->Type(); DType t1=e->GetParDefined(1)->Type(); static DInt doubleKWIx = e->KeywordIx("DOUBLE"); if (t0 == GDL_DOUBLE || t0 == GDL_COMPLEXDBL || t1 == GDL_DOUBLE || t1 == GDL_COMPLEXDBL || e->KeywordSet(doubleKWIx)) return res->Convert2(GDL_DOUBLE,BaseGDL::CONVERT); return res; } //end of voigt_fun //--------------------------------------------------------------------------// // static DInterpreter* interpreter; void PushNewEnvRK( EnvT*e, DSubUD* newPro, BaseGDL** a,BaseGDL** b) { EnvUDT* newEnv= new EnvUDT( e->CallingNode(), newPro, (DObjGDL**)NULL); newEnv->SetNextPar(a); // pass as global newEnv->SetNextPar(b); // pass as global e->Interpreter()->CallStack().push_back(newEnv); } //*********************************** RK4 FUNCTION **************************// BaseGDL* rk4_fun(EnvT* e) { SizeT nParam = e->NParam(); if( nParam != 5) e->Throw(" Invalid Number of arguments in RK4 "); //----------------------------- ACQUISITION DES PARAMETRES ------------------// //"Y" input array a vector of values for Y at X value //DDoubleGDL* Yvals = new DDoubleGDL(e->GetParAs(0)->N_Elements(),BaseGDL::NOZERO); DDoubleGDL* Yvals = e->GetParAs(0); if(e->GetParDefined(0)->Type() == GDL_COMPLEX || e->GetParDefined(0)->Type() == GDL_COMPLEXDBL) cout<<" If RK4 is complex then only the real part is used for the computation "<< endl; //"dydx" input value or array //DDoubleGDL* dydxvals = new DDoubleGDL(e->GetParAs(1)->N_Elements(),BaseGDL::NOZERO); DDoubleGDL* dydxvals = e->GetParAs(1); if(e->GetParDefined(1)->Type() == GDL_COMPLEX || e->GetParDefined(1)->Type() == GDL_COMPLEXDBL) cout<<" If RK4 is complex then only the real part is used for the computation "<< endl; if(dydxvals->N_Elements()!=Yvals->N_Elements())e->Throw(" Y and DYDX dimensions have to match "); // "X" input value DDoubleGDL* X = e->GetParAs(2); if(e->GetParDefined(2)->Type() == GDL_COMPLEX || e->GetParDefined(2)->Type() == GDL_COMPLEXDBL) cout<<" If RK4 is complex then only the real part is used for the computation "<< endl; // "H" input value DDoubleGDL* H = e->GetParAs(3); if(e->GetParDefined(3)->Type() == GDL_COMPLEX || e->GetParDefined(3)->Type() == GDL_COMPLEXDBL) cout<<" If RK4 is complex then only the real part is used for the computation "<< endl; // Differentiate User's Function string name DStringGDL* init = e->GetParAs(4); if(e->GetParDefined(4)->Type() != GDL_STRING ) e->Throw(" Fifth value must be a function name string "); //-------------------------------- Allocation -----------------------------------// BaseGDL *Steptwo,*Stepthree,*Stepfour; DDoubleGDL *HH,*H6,*XplusH,*Ytampon,*XH,*Yout,*dym,*dyt; Ytampon = new DDoubleGDL(Yvals->Dim(),BaseGDL::NOZERO); Yout = new DDoubleGDL(Yvals->Dim(),BaseGDL::NOZERO); HH = new DDoubleGDL(H->Dim(),BaseGDL::NOZERO); H6 = new DDoubleGDL(H->Dim(),BaseGDL::NOZERO); XH = new DDoubleGDL(H->Dim(),BaseGDL::NOZERO); BaseGDL* XHO=static_cast(XH); XplusH = new DDoubleGDL(H->Dim(),BaseGDL::NOZERO); BaseGDL* XplusHO=static_cast(XplusH); dym= new DDoubleGDL(Yvals->Dim(),BaseGDL::NOZERO); dyt= new DDoubleGDL(Yvals->Dim(),BaseGDL::NOZERO); //-------------------------------- Init FIRST STEP -----------------------------------// (*HH)[0]=(*H)[0]*0.50000; (*H6)[0]=(*H)[0]/6.00000; (*XH)[0] = (*X)[0] + (*HH)[0]; // marc: probably an error // XplusH[0] = (*X)[0] + (*H)[0]; (*XplusH)[0] = (*X)[0] + (*H)[0]; //dym=static_cast(dymO); //dyt=static_cast(dytO); //---------------------------- Init Call function -------------------------------------// DString RK_Diff; e->AssureScalarPar( 4, RK_Diff); // this is a function name -> convert to UPPERCASE RK_Diff = StrUpCase( RK_Diff); // first search library funcedures int funIx=LibFunIx( RK_Diff); StackGuard guard( e->Interpreter()->CallStack()); if( funIx != -1) { e->Throw(" String function name is intrinsic function name please change it "); } else { // Search in user proc and function funIx = GDLInterpreter::GetFunIx(RK_Diff ); //-----------------FIRST STEP-------------------// for (SizeT i=0;iN_Elements();++i) (*Ytampon)[i]=(*Yvals)[i]+(*HH)[0]*(*dydxvals)[i]; BaseGDL* Ytmp=static_cast(Ytampon); // 1st CALL to user function "differentiate" PushNewEnvRK(e, funList[ funIx],&XHO,&Ytmp); EnvUDT* newEnv = static_cast(e->Interpreter()->CallStack().back()); StackGuard guard1 ( e->Interpreter()->CallStack()); BaseGDL* Steptwo = e->Interpreter()->call_fun(static_cast(newEnv->GetPro())->GetTree()); //Conversion BaseGDL*-> DDoubleGDL* in order to use the RK_Diff function result. dyt= static_cast(Steptwo->Convert2(GDL_DOUBLE,BaseGDL::CONVERT)); //-------------SECOND STEP-------------------// for (SizeT i=0;iN_Elements();++i) (*Ytampon)[i]=(*Yvals)[i]+(*HH)[0]*(*dyt)[i]; // 2nd CALL to user function "differentiate" PushNewEnvRK(e, funList[ funIx],&XHO,&Ytmp); StackGuard guard2 ( newEnv->Interpreter()->CallStack()); BaseGDL* Stepthree = e->Interpreter()->call_fun(static_cast(newEnv->GetPro())->GetTree()); //Conversion BaseGDL*-> DDoubleGDL* in order to use the RK_Diff function result. dym = static_cast(Stepthree->Convert2(GDL_DOUBLE,BaseGDL::CONVERT)); //--------------THIRD STEP-------------------// for (SizeT i=0;iN_Elements();++i) { (*Ytampon)[i]=(*Yvals)[i]+ (*H)[0]*(*dym)[i]; (*dym)[i] += (*dyt)[i]; } // 3rd CALL to user function "differentiate" PushNewEnvRK(e, funList[ funIx],&XplusHO,&Ytmp); StackGuard guard3 ( newEnv->Interpreter()->CallStack()); BaseGDL* Stepfour = e->Interpreter()->call_fun(static_cast(newEnv->GetPro())->GetTree()); dyt= static_cast(Stepfour->Convert2(GDL_DOUBLE,BaseGDL::CONVERT)); //--------------FOURTH STEP-------------------// for (SizeT i=0;iN_Elements();++i) (*Yout)[i]= (*Yvals)[i] + (*H6)[0] * ( (*dydxvals)[i]+(*dyt)[i]+ 2.00000*(*dym)[i] ); static int doubleKWIx = e->KeywordIx("DOUBLE"); //if need, convert things back if( !e->KeywordSet(doubleKWIx)) return Yout->Convert2(GDL_FLOAT,BaseGDL::CONVERT); else return Yout; } assert( false); }// RK4_fun }//namespace gdl-0.9.9/src/math_fun_ng.hpp000066400000000000000000000023051340051421000160520ustar00rootroot00000000000000/*************************************************************************** math_fun_ng.hpp - mathematical GDL library function ------------------- begin : 26 May 2008 copyright : (C) 2007 by Nicolas Galmiche email : n.galmiche AT gmail.com ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "datatypes.hpp" #include "dinterpreter.hpp" namespace lib { BaseGDL* rk4_fun( EnvT* e); BaseGDL* voigt_fun( EnvT* e); float humlik( float A, float U); } // namespace gdl-0.9.9/src/math_utl.cpp000066400000000000000000000415051340051421000154020ustar00rootroot00000000000000/*************************************************************************** math_utl.cpp - math utilities GDL library function ------------------- begin : Feb 11 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include "math_utl.hpp" #include "dimension.hpp" #include "initsysvar.hpp" //#define GDL_DEBUG #undef GDL_DEBUG namespace lib { //********************************************************************** // special pragma to prevent optimization by the zealous compiler icc. (when optimized, loops forever on the 'while') #pragma GCC push_options #pragma GCC optimize ("O0") #pragma optimize("", off) #if defined(__clang__) # pragma clang optimize off #endif void machar_s ( long int *ibeta, long int *it, long int *irnd, long int *ngrd, long int *machep, long int *negep, long int *iexp, long int *minexp, long int *maxexp, float *eps, float *epsneg, float *xmin, float *xmax ) //********************************************************************** // // Purpose: // // MACHAR_S computes machine constants for floating point arithmetic. // // Discussion: // // This routine determines the parameters of the floating-point // arithmetic system specified below. The determination of the first // three uses an extension of an algorithm due to Malcolm, // incorporating some of the improvements suggested by Gentleman and // Marovich. // // A FORTRAN version of this routine appeared as ACM algorithm 665. // // This routine is a C translation of the FORTRAN code, and appeared // as part of ACM algorithm 722. // // An earlier version of this program was published in Cody and Waite. // // Reference: // // W J Cody, // ACM Algorithm 665, MACHAR, a subroutine to dynamically determine // machine parameters, // ACM Transactions on Mathematical Software, // Volume 14, Number 4, pages 303-311, 1988. // // W J Cody and W Waite, // Software Manual for the Elementary Functions, // Prentice Hall, 1980. // // M Gentleman and S Marovich, // Communications of the ACM, // Volume 17, pages 276-277, 1974. // // M. Malcolm, // Communications of the ACM, // Volume 15, pages 949-951, 1972. // // Author: // // W. J. Cody // Argonne National Laboratory // // Parameters: // // Output, long int* IBETA, the radix for the floating-point representation. // // Output, long int* IT, the number of base IBETA digits in the floating-point // significand. // // Output, long int* IRND: // 0, if floating-point addition chops. /// 1, if floating-point addition rounds, but not in the IEEE style. // 2, if floating-point addition rounds in the IEEE style. // 3, if floating-point addition chops, and there is partial underflow. // 4, if floating-point addition rounds, but not in the IEEE style, and // there is partial underflow. // 5, if floating-point addition rounds in the IEEE style, and there is // partial underflow. // // Output, long int* NGRD, the number of guard digits for multiplication with // truncating arithmetic. It is // 0, if floating-point arithmetic rounds, or if it truncates and only // IT base IBETA digits participate in the post-normalization shift of the // floating-point significand in multiplication; // 1, if floating-point arithmetic truncates and more than IT base IBETA // digits participate in the post-normalization shift of the floating-point // significand in multiplication. // // Output, long int* MACHEP, the largest negative integer such that // 1.0 + ( float ) IBETA ^ MACHEP != 1.0, // except that MACHEP is bounded below by - ( IT + 3 ). // // Output, long int* NEGEPS, the largest negative integer such that // 1.0 - ( float ) IBETA ) ^ NEGEPS != 1.0, // except that NEGEPS is bounded below by - ( IT + 3 ). // // Output, long int* IEXP, the number of bits (decimal places if IBETA = 10) // reserved for the representation of the exponent (including the bias or // sign) of a floating-point number. // // Output, long int* MINEXP, the largest in magnitude negative integer such // that // ( float ) IBETA ^ MINEXP // is positive and normalized. // // Output, long int* MAXEXP, the smallest positive power of BETA that overflows. // // Output, float* EPS, the smallest positive floating-point number such // that // 1.0 + EPS != 1.0. // in particular, if either IBETA = 2 or IRND = 0, // EPS = ( float ) IBETA ^ MACHEP. // Otherwise, // EPS = ( ( float ) IBETA ^ MACHEP ) / 2. // // Output, float* EPSNEG, a small positive floating-point number such that // 1.0 - EPSNEG != 1.0. // In particular, if IBETA = 2 or IRND = 0, // EPSNEG = ( float ) IBETA ^ NEGEPS. // Otherwise, // EPSNEG = ( float ) IBETA ^ NEGEPS ) / 2. // Because NEGEPS is bounded below by - ( IT + 3 ), EPSNEG might not be the // smallest number that can alter 1.0 by subtraction. // // Output, float* XMIN, the smallest non-vanishing normalized floating-point // power of the radix: // XMIN = ( float ) IBETA ^ MINEXP // // Output, float* XMAX, the largest finite floating-point number. In // particular, // XMAX = ( 1.0 - EPSNEG ) * ( float ) IBETA ^ MAXEXP // On some machines, the computed value of XMAX will be only the second, // or perhaps third, largest number, being too small by 1 or 2 units in // the last digit of the significand. // { float a; float b; float beta; float betah; float betain; int i; int itmp; int iz; int j; int k; int mx; int nxres; float one; float t; float tmp; float tmp1; float tmpa; float two; float y; float z; float zero; (*irnd) = 1; one = (float) (*irnd); two = one + one; a = two; b = a; zero = 0.0e0; // // Determine IBETA and BETA ala Malcolm. // tmp = ( ( a + one ) - a ) - one; while ( tmp == zero ) { a = a + a; tmp = a + one; tmp1 = tmp - a; tmp = tmp1 - one; } tmp = a + b; itmp = ( int ) ( tmp - a ); while ( itmp == 0 ) { b = b + b; tmp = a + b; itmp = ( int ) ( tmp - a ); } *ibeta = itmp; beta = ( float ) ( *ibeta ); // // Determine IRND, IT. // ( *it ) = 0; b = one; tmp = ( ( b + one ) - b ) - one; while ( tmp == zero ) { *it = *it + 1; b = b * beta; tmp = b + one; tmp1 = tmp - b; tmp = tmp1 - one; } *irnd = 0; betah = beta / two; tmp = a + betah; tmp1 = tmp - a; if ( tmp1 != zero ) { *irnd = 1; } tmpa = a + beta; tmp = tmpa + betah; if ( ( *irnd == 0 ) && ( tmp - tmpa != zero ) ) { *irnd = 2; } // // Determine NEGEP, EPSNEG. // (*negep) = (*it) + 3; betain = one / beta; a = one; for ( i = 1; i <= (*negep); i++ ) { a = a * betain; } b = a; tmp = ( one - a ); tmp = tmp - one; while ( tmp == zero ) { a = a * beta; *negep = *negep - 1; tmp1 = one - a; tmp = tmp1 - one; } (*negep) = -(*negep); (*epsneg) = a; // // Determine MACHEP, EPS. // (*machep) = -(*it) - 3; a = b; tmp = one + a; while ( tmp - one == zero) { a = a * beta; *machep = *machep + 1; tmp = one + a; } *eps = a; // // Determine NGRD. // (*ngrd) = 0; tmp = one + *eps; tmp = tmp * one; if ( ( (*irnd) == 0 ) && ( tmp - one ) != zero ) { (*ngrd) = 1; } // // Determine IEXP, MINEXP and XMIN. // // Loop to determine largest I such that (1/BETA) ** (2**(I)) // does not underflow. Exit from loop is signaled by an underflow. // i = 0; k = 1; z = betain; t = one + *eps; nxres = 0; for ( ; ; ) { y = z; z = y * y; // // Check for underflow // a = z * one; tmp = z * t; if ( ( a + a == zero ) || ( abs( z ) > y ) ) { break; } tmp1 = tmp * betain; if ( tmp1 * beta == z ) { break; } i = i + 1; k = k + k; } // // Determine K such that (1/BETA)**K does not underflow. // First set K = 2 ** I. // (*iexp) = i + 1; mx = k + k; if ( *ibeta == 10 ) { // // For decimal machines only // (*iexp) = 2; iz = *ibeta; while ( k >= iz ) { iz = iz * ( *ibeta ); (*iexp) = (*iexp) + 1; } mx = iz + iz - 1; } // // Loop to determine MINEXP, XMIN. // Exit from loop is signaled by an underflow. // for ( ; ; ) { (*xmin) = y; y = y * betain; a = y * one; tmp = y * t; tmp1 = a + a; if ( ( tmp1 == zero ) || ( abs( y ) >= ( *xmin ) ) ) { break; } k = k + 1; tmp1 = tmp * betain; tmp1 = tmp1 * beta; if ( ( tmp1 == y ) && ( tmp != y ) ) { nxres = 3; *xmin = y; break; } } (*minexp) = -k; // // Determine MAXEXP, XMAX. // if ( ( mx <= k + k - 3 ) && ( ( *ibeta ) != 10 ) ) { mx = mx + mx; (*iexp) = (*iexp) + 1; } (*maxexp) = mx + (*minexp); // // Adjust IRND to reflect partial underflow. // (*irnd) = (*irnd) + nxres; // // Adjust for IEEE style machines. // if ( ( *irnd) >= 2 ) { (*maxexp) = (*maxexp) - 2; } // // Adjust for machines with implicit leading bit in binary // significand and machines with radix point at extreme // right of significand. // i = (*maxexp) + (*minexp); if ( ( ( *ibeta ) == 2 ) && ( i == 0 ) ) { (*maxexp) = (*maxexp) - 1; } if ( i > 20 ) { (*maxexp) = (*maxexp) - 1; } if ( a != y ) { (*maxexp) = (*maxexp) - 2; } (*xmax) = one - (*epsneg); tmp = (*xmax) * one; if ( tmp != (*xmax) ) { (*xmax) = one - beta * (*epsneg); } (*xmax) = (*xmax) / ( beta * beta * beta * (*xmin) ); i = (*maxexp) + (*minexp) + 3; if ( i > 0 ) { for ( j = 1; j <= i; j++ ) { if ( (*ibeta) == 2 ) { (*xmax) = (*xmax) + (*xmax); } if ( (*ibeta) != 2 ) { (*xmax) = (*xmax) * beta; } } } return; } #pragma GCC pop_options #if defined(__clang__) # pragma clang optimize on #endif // special pragma to prevent optimization by the zealous compiler icc. (when optimized, loops forever on the 'while') #pragma GCC push_options #pragma GCC optimize ("O0") #pragma optimize("", off) #if defined(__clang__) # pragma clang optimize off #endif void machar_d ( long int *ibeta, long int *it, long int *irnd, long int *ngrd, long int *machep, long int *negep, long int *iexp, long int *minexp, long int *maxexp, double *eps, double *epsneg, double *xmin, double *xmax ) { double a; double b; double beta; double betah; double betain; int i; int itmp; int iz; int j; int k; int mx; int nxres; double one; double t; double tmp; double tmp1; double tmpa; double two; double y; double z; double zero; (*irnd) = 1; one = (double) (*irnd); two = one + one; a = two; b = a; zero = 0.0e0; // // Determine IBETA and BETA ala Malcolm. // tmp = ( ( a + one ) - a ) - one; while ( tmp == zero ) { a = a + a; tmp = a + one; tmp1 = tmp - a; tmp = tmp1 - one; } tmp = a + b; itmp = ( int ) ( tmp - a ); while ( itmp == 0 ) { b = b + b; tmp = a + b; itmp = ( int ) ( tmp - a ); } *ibeta = itmp; beta = ( double ) ( *ibeta ); // // Determine IRND, IT. // ( *it ) = 0; b = one; tmp = ( ( b + one ) - b ) - one; while ( tmp == zero ) { *it = *it + 1; b = b * beta; tmp = b + one; tmp1 = tmp - b; tmp = tmp1 - one; } *irnd = 0; betah = beta / two; tmp = a + betah; tmp1 = tmp - a; if ( tmp1 != zero ) { *irnd = 1; } tmpa = a + beta; tmp = tmpa + betah; if ( ( *irnd == 0 ) && ( tmp - tmpa != zero ) ) { *irnd = 2; } // // Determine NEGEP, EPSNEG. // (*negep) = (*it) + 3; betain = one / beta; a = one; for ( i = 1; i <= (*negep); i++ ) { a = a * betain; } b = a; tmp = ( one - a ); tmp = tmp - one; while ( tmp == zero ) { a = a * beta; *negep = *negep - 1; tmp1 = one - a; tmp = tmp1 - one; } (*negep) = -(*negep); (*epsneg) = a; // // Determine MACHEP, EPS. // (*machep) = -(*it) - 3; a = b; tmp = one + a; while ( tmp - one == zero) { a = a * beta; *machep = *machep + 1; tmp = one + a; } *eps = a; // // Determine NGRD. // (*ngrd) = 0; tmp = one + *eps; tmp = tmp * one; if ( ( (*irnd) == 0 ) && ( tmp - one ) != zero ) { (*ngrd) = 1; } // // Determine IEXP, MINEXP and XMIN. // // Loop to determine largest I such that (1/BETA) ** (2**(I)) // does not underflow. Exit from loop is signaled by an underflow. // i = 0; k = 1; z = betain; t = one + *eps; nxres = 0; for ( ; ; ) { y = z; z = y * y; // // Check for underflow // a = z * one; tmp = z * t; if ( ( a + a == zero ) || ( abs( z ) > y ) ) { break; } tmp1 = tmp * betain; if ( tmp1 * beta == z ) { break; } i = i + 1; k = k + k; } // // Determine K such that (1/BETA)**K does not underflow. // First set K = 2 ** I. // (*iexp) = i + 1; mx = k + k; if ( *ibeta == 10 ) { // // For decimal machines only // (*iexp) = 2; iz = *ibeta; while ( k >= iz ) { iz = iz * ( *ibeta ); (*iexp) = (*iexp) + 1; } mx = iz + iz - 1; } // // Loop to determine MINEXP, XMIN. // Exit from loop is signaled by an underflow. // for ( ; ; ) { (*xmin) = y; y = y * betain; a = y * one; tmp = y * t; tmp1 = a + a; if ( ( tmp1 == zero ) || ( abs( y ) >= ( *xmin ) ) ) { break; } k = k + 1; tmp1 = tmp * betain; tmp1 = tmp1 * beta; if ( ( tmp1 == y ) && ( tmp != y ) ) { nxres = 3; *xmin = y; break; } } (*minexp) = -k; // // Determine MAXEXP, XMAX. // if ( ( mx <= k + k - 3 ) && ( ( *ibeta ) != 10 ) ) { mx = mx + mx; (*iexp) = (*iexp) + 1; } (*maxexp) = mx + (*minexp); // // Adjust IRND to reflect partial underflow. // (*irnd) = (*irnd) + nxres; // // Adjust for IEEE style machines. // if ( ( *irnd) >= 2 ) { (*maxexp) = (*maxexp) - 2; } // // Adjust for machines with implicit leading bit in binary // significand and machines with radix point at extreme // right of significand. // i = (*maxexp) + (*minexp); if ( ( ( *ibeta ) == 2 ) && ( i == 0 ) ) { (*maxexp) = (*maxexp) - 1; } if ( i > 20 ) { (*maxexp) = (*maxexp) - 1; } if ( a != y ) { (*maxexp) = (*maxexp) - 2; } (*xmax) = one - (*epsneg); tmp = (*xmax) * one; if ( tmp != (*xmax) ) { (*xmax) = one - beta * (*epsneg); } (*xmax) = (*xmax) / ( beta * beta * beta * (*xmin) ); i = (*maxexp) + (*minexp) + 3; if ( i > 0 ) { for ( j = 1; j <= i; j++ ) { if ( (*ibeta) == 2 ) { (*xmax) = (*xmax) + (*xmax); } if ( (*ibeta) != 2 ) { (*xmax) = (*xmax) * beta; } } } return; } #pragma GCC pop_options #if defined(__clang__) # pragma clang optimize on #endif } // namespace gdl-0.9.9/src/math_utl.hpp000066400000000000000000000043641340051421000154110ustar00rootroot00000000000000/*************************************************************************** math_utl.hpp - math utilities GDL library function ------------------- begin : Feb 11 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef MATH_UTL_HPP_ #define MATH_UTL_HPP_ #include "basegdl.hpp" //#define ABS(xxx) (( xxx > -xxx)?(xxx):(-xxx)) // This caused a compiler error on g++ 4.5, see: // http://sourceforge.net/tracker/index.php?func=detail&aid=2949808&group_id=97659&atid=618683 // template< typename T> // inline T abs( T a) { return (a>=T(0))?a:-a;} namespace lib { // SA: needs to be inside a namespace for GCC 4.5 template< typename T> inline T abs( T a) { return (a>=T(0))?a:-a;} // int trans513(char *, int, int, int, DType); // int transpose(char *, SizeT, SizeT [], SizeT, DType); // int transpose_perm(char *, SizeT, SizeT [], SizeT, DType, long []); void machar_s ( long int *ibeta, long int *it, long int *irnd, long int *ngrd, long int *machep, long int *negep, long int *iexp, long int *minexp, long int *maxexp, float *eps, float *epsneg, float *xmin, float *xmax ); void machar_d ( long int *ibeta, long int *it, long int *irnd, long int *ngrd, long int *machep, long int *negep, long int *iexp, long int *minexp, long int *maxexp, double *eps, double *epsneg, double *xmin, double *xmax ); #ifdef _MSC_VER # define isinf !_finite # define isfinite _finite # define isnan _isnan #endif } // namespace #endif gdl-0.9.9/src/matrix_cholesky.cpp000066400000000000000000000557551340051421000170060ustar00rootroot00000000000000/*************************************************************************** gsl_fun.cpp - GDL GSL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include #include //#include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "dinterpreter.hpp" #include "gsl_fun.hpp" #if defined(USE_EIGEN) #include #include #include #endif namespace lib { using namespace std; #ifndef _MSC_VER using std::isnan; #endif //const int szdbl=sizeof(double); //const int szflt=sizeof(float); #if defined(USE_EIGEN) using namespace Eigen; /*********************************************************** ********************LA_Cholesky_Solution*********************** ************************************************************/ BaseGDL* la_cholsol_fun ( EnvT* e) { Message("We have troubles related to LA_CHOLDC/LA_CHOLSOL and Eigen"); Message("Help and contributions very welcome"); Message(" "); // set_num_threads(); SizeT nParam=e->NParam(2); BaseGDL* p0 = e->GetParDefined( 0); BaseGDL* p1 = e->GetParDefined( 1); /*********************************Checking_if_arguments_are_OK*********************/ if (p0->N_Elements()==0) e->Throw( "Variable A is undefined: " + e->GetParString(0)); if (p1->N_Elements()==0) e->Throw( "Variable B is undefined: " + e->GetParString(1)); if (p0->Rank() == 2){ if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Argument A must be a square matrix:" + e->GetParString(0)); } else e->Throw( "Argument A must be a square matrix:" + e->GetParString(0)); if(p1->Rank()==1){ if(p1->N_Elements()!=p0->Dim(0)) e->Throw("Arguments sizes mismatch"); } else if(p1->Rank()==2){ if(p1->Dim(1)!=p0->Dim(0)) e->Throw("Arguments sizes mismatch"); } else e->Throw( "Argument B must be a vector or a matrix:" + e->GetParString(0)); long NbCol,NbRow; /*************************Double**************************************/ static int DOUBLEIx=e->KeywordIx("DOUBLE"); if(( p0->Type() == GDL_DOUBLE) || e->KeywordSet(DOUBLEIx)) { DDoubleGDL* p0D = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); DDoubleGDL* p2D = static_cast (p1->Convert2( GDL_DOUBLE, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0D)[0], NbCol,NbRow); Map m2(&(*p2D)[0], NbCol); LLTsolver; VectorXd tmp_res = solver.compute(m0).solve(m2); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return 0; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return 0; } DDoubleGDL* res =new DDoubleGDL(NbCol, BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.cast(); return res; } return p0; } /*********************************************************** ********************Cholesky_Solution*********************** ************************************************************/ BaseGDL* cholsol_fun ( EnvT* e) { // set_num_threads(); SizeT nParam=e->NParam(3); BaseGDL* p0 = e->GetNumericParDefined( 0); BaseGDL* p1 = e->GetNumericParDefined( 1); BaseGDL* p2 = e->GetNumericParDefined( 2); /*********************************Checking_if_arguments_are_OK*********************/ if (p0->N_Elements()==0) e->Throw( "Variable A is undefined: " + e->GetParString(0)); if (p1->N_Elements()==0) e->Throw( "Variable P is undefined: " + e->GetParString(1)); if (p2->N_Elements()==0) e->Throw( "Variable B is undefined: " + e->GetParString(2)); if (p0->Rank() == 2) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Argument A must be a square matrix:" + e->GetParString(0)); } else e->Throw( "Argument A must be a square matrix:" + e->GetParString(0)); if (p1->Rank() != 1 ) e->Throw( "Argument P must be a column vector: " + e->GetParString(1)); if (p2->Rank() != 1 ) e->Throw( "Argument B must be a column vector: " + e->GetParString(1)); // else // if (p2->N_Elements()<2) if( p2->N_Elements()!=p1->N_Elements() || p1->N_Elements()!=p0->Dim(0) || p2->N_Elements()!=p0->Dim(0) ) e->Throw("Arguments sizes mismatch"); long NbCol,NbRow; /*************************Double**************************************/ static int DOUBLEIx=e->KeywordIx("DOUBLE"); if(( p0->Type() == GDL_DOUBLE) || e->KeywordSet(DOUBLEIx)) { DDoubleGDL* p0D = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); DDoubleGDL* p2D = static_cast (p2->Convert2( GDL_DOUBLE, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0D)[0], NbCol,NbRow); Map m2(&(*p2D)[0], NbCol); LLTsolver; VectorXd tmp_res = solver.compute(m0).solve(m2); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return 0; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return 0; } DDoubleGDL* res =new DDoubleGDL(NbCol, BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.cast(); return res; } /*************************Complex**************************************/ if( p0->Type() == GDL_COMPLEX && !e->KeywordSet(DOUBLEIx)) { DComplexGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEX , BaseGDL::COPY)); DComplexGDL* p2C = static_cast (p2->Convert2(GDL_COMPLEX , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map,Dynamic,Dynamic,RowMajor> > m0(&(*p0C)[0], NbCol,NbRow); Map m2(&(*p2C)[0], NbCol); LLTsolver; MatrixXf tmp_res = solver.compute(m0.real()).solve(m2.real()); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return 0; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return 0; } DFloatGDL* res = new DFloatGDL(NbCol, BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.cast(); return res; } /*************************Complex_Double**************************************/ else if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEXDBL , BaseGDL::COPY)); DComplexDblGDL* p2C = static_cast (p2->Convert2(GDL_COMPLEXDBL , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map,Dynamic,Dynamic,RowMajor> > m0(&(*p0C)[0], NbCol,NbRow); Map m2(&(*p2C)[0], NbCol); LLTsolver; MatrixXd tmp_res = solver.compute(m0.real()).solve(m2.real()); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return 0; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return 0; } DDoubleGDL* res = new DDoubleGDL(NbCol, BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.cast(); return res; } /*************************All_Other**************************************/ if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_LONG64 || p0->Type() == GDL_ULONG64 || p0->Type() == GDL_INT || p0->Type() == GDL_STRING || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { DFloatGDL* p0SS = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); DFloatGDL* p2SS = static_cast (p2->Convert2( GDL_FLOAT, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0SS)[0], NbCol,NbRow); Map m2(&(*p2SS)[0], NbCol); LLTsolver; VectorXf tmp_res = solver.compute(m0).solve(m2); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return 0; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return 0; } DFloatGDL* res =new DFloatGDL(NbCol, BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.cast(); return res; } //****************************Bug************************** else { cout << "Should never reach this point ! Please report it !" << endl; DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); return res; } } /*********************************************************** ********************error_checker_LA_CHOLDC***************** ************************************************************/ bool error_check(EnvT* e,int status) { static int statusIx = e->KeywordIx("STATUS"); bool statusKeyword = e->KeywordPresent( statusIx ); if ( statusKeyword ) e->AssureGlobalKW( statusIx ); if(status==NumericalIssue) { if(statusKeyword) { e->SetKW(statusIx,new DLongGDL(1)); return 0; } e->Throw( "Array is not positive definite: " + e->GetParString(0)); return 0; } if(status!=Success) { e->SetKW(statusIx,new DLongGDL(2)); e->Throw( "Decomposition has failed: " + e->GetParString(0)); return 0; } if(statusKeyword) e->SetKW(statusIx,new DLongGDL(0)); return 1; } /*********************************************************** ********************LA_CHOLDC-procedure********************* ************************************************************/ void la_choldc_pro( EnvT* e) { Message("We have troubles related to LA_CHOLDC/LA_CHOLSOL and Eigen"); Message("Help and contributions very welcome"); Message(" "); SizeT nParam = e->NParam(1); BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: " + e->GetParString(0)); if (p0->Rank() > 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); if (p0->Rank() > 1) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); } if (p0->Rank() < 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); long NbCol,NbRow; static int DOUBLEIx=e->KeywordIx("DOUBLE"); static int UPPERIx=e->KeywordIx("UPPER"); /*************************Complex_Double**************************************/ if( p0->Type() == GDL_COMPLEXDBL || (p0->Type() == GDL_COMPLEX && e->KeywordSet(DOUBLEIx))) { DComplexDblGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEXDBL , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map,Dynamic,Dynamic> > m0(&(*p0C)[0], NbCol,NbRow); MatrixXcd tmp_res; if(e->KeywordSet(UPPERIx)) { LLTsolver; solver.compute(m0); if ( !error_check(e,solver.info()) ) return ; tmp_res=solver.matrixLLT(); } else { LLTsolver; solver.compute(m0); if ( !error_check(e,solver.info()) ) return ; tmp_res=solver.matrixLLT(); } // DComplexDblGDL* res2 = new DComplexDblGDL(p0->Dim(), BaseGDL::NOZERO); Map(&(*p0C)[0], NbCol, NbRow) = tmp_res.transpose().cast >(); e->SetPar(0,p0C); return ; } /*************************Complex**************************************/ else if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEX , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map,Dynamic,Dynamic> > m0(&(*p0C)[0], NbCol,NbRow); MatrixXcf tmp_res; if(e->KeywordSet(UPPERIx)) { LLTsolver; solver.compute(m0); if( !error_check(e,solver.info())) return ; tmp_res=solver.matrixLLT(); } else { LLTsolver; solver.compute(m0); if( !error_check(e,solver.info())) return ; tmp_res=solver.matrixLLT(); } // DComplexGDL* res2 = new DComplexGDL(p0->Dim(), BaseGDL::NOZERO); Map(&(*p0C)[0], NbCol, NbRow) = tmp_res.transpose().cast >(); e->SetPar(0,p0C); return ; } /*************************Double**************************************/ else if(( p0->Type() == GDL_DOUBLE) || e->KeywordSet(DOUBLEIx)) { DDoubleGDL* p0D = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0D)[0], NbCol,NbRow); MatrixXd tmp_res; if(e->KeywordSet(UPPERIx)) { LLTsolver; solver.compute(m0); if( !error_check(e,solver.info())) return ; tmp_res=solver.matrixLLT(); } else { LLTsolver; solver.compute(m0); if( !error_check(e,solver.info())) return ; tmp_res=solver.matrixLLT(); } Map >(&(*p0D)[0], NbCol, NbRow) = tmp_res.cast(); e->SetPar(0,p0D); return ; } /*************************All_Other**************************************/ else if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_LONG64 || p0->Type() == GDL_ULONG64 || p0->Type() == GDL_INT || p0->Type() == GDL_STRING || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { DFloatGDL* p0SS = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0SS)[0], NbCol,NbRow); MatrixXf tmp_res; if(e->KeywordSet(UPPERIx)) { LLTsolver; solver.compute(m0); if( !error_check(e,solver.info())) return ; tmp_res=solver.matrixLLT(); } else { LLTsolver; solver.compute(m0); if( !error_check(e,solver.info())) return ; tmp_res=solver.matrixLLT(); } Map(&(*p0SS)[0], NbCol, NbRow) = tmp_res.transpose().cast(); e->SetPar(0,p0SS); return ; } //****************************Bug************************** else { cout << "Should never reach this point ! Please report it !" << endl; return ; } } /*********************************************************** ********************Cholesky_Decomposition****************** ************************************************************/ void choldc_pro( EnvT* e) { BaseGDL* p0 = e->GetNumericParDefined( 0); //BaseGDL* p0 = e->GetParDefined( 0); SizeT nParam=e->NParam(2); long singular=0; SizeT nEl = p0->N_Elements(); //cout<<"rank is"<Rank()<Throw( "Variable is undefined: " + e->GetParString(0)); if (p0->Rank() > 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); if (p0->Rank() > 1) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); } if (p0->Rank() < 2) e->Throw( "Input must be a square matrix:" + e->GetParString(0)); long NbCol,NbRow; // cout << p0->Type() << endl; static int DOUBLEIx=e->KeywordIx("DOUBLE"); /*************************Complex**************************************/ if( p0->Type() == GDL_COMPLEX && !e->KeywordSet(DOUBLEIx)) { DComplexGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEX , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map,Dynamic,Dynamic,RowMajor> > m0(&(*p0C)[0], NbCol,NbRow); LLTsolver; MatrixXf tmp_res = solver.compute(m0.real()).matrixL(); DFloatGDL* res = new DFloatGDL(p0->Dim(0), BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.diagonal().cast(); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return ; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return; } e->SetPar(1,res); m0=m0.triangularView(); tmp_res=tmp_res.triangularView(); tmp_res=tmp_res+m0.real(); DFloatGDL* res2 = new DFloatGDL(p0->Dim(), BaseGDL::NOZERO); Map >(&(*res2)[0], NbCol, NbRow) = tmp_res.cast(); e->SetPar(0,res2); return ; } /*************************Complex_Double**************************************/ else if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEXDBL , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map,Dynamic,Dynamic,RowMajor> > m0(&(*p0C)[0], NbCol,NbRow); LLTsolver; MatrixXd tmp_res = solver.compute(m0.real()).matrixL(); DDoubleGDL* res = new DDoubleGDL(p0->Dim(0), BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.diagonal().cast(); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return ; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return; } e->SetPar(1,res); m0=m0.triangularView(); tmp_res=tmp_res.triangularView(); tmp_res=tmp_res+m0.real(); DDoubleGDL* res2 = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); Map >(&(*res2)[0], NbCol, NbRow) = tmp_res.cast(); e->SetPar(0,res2); return ; } /*************************Double**************************************/ else if(( p0->Type() == GDL_DOUBLE) || e->KeywordSet(DOUBLEIx)) { DDoubleGDL* p0D = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0D)[0], NbCol,NbRow); LLTsolver; MatrixXd tmp_res = solver.compute(m0).matrixL(); DDoubleGDL* res = new DDoubleGDL(p0->Dim(0), BaseGDL::NOZERO); Map(&(*res)[0], NbCol) = tmp_res.diagonal().cast(); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return ; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return; } e->SetPar(1,res); m0=m0.triangularView(); tmp_res=tmp_res.triangularView(); tmp_res=tmp_res+m0; Map >(&(*p0D)[0], NbCol, NbRow) = tmp_res.cast(); e->SetPar(0,p0D); return ; } /*************************All_Other**************************************/ else if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_LONG64 || p0->Type() == GDL_ULONG64 || p0->Type() == GDL_INT || p0->Type() == GDL_STRING || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { DFloatGDL* p0SS = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); Map > m0(&(*p0SS)[0], NbCol,NbRow); LLTsolver; MatrixXf tmp_res = solver.compute(m0).matrixL(); // cout<<"matrix"<(&(*res)[0], NbCol) = tmp_res.diagonal().cast(); if(solver.info()==NumericalIssue) { e->Throw( "Array is not positive definite: " + e->GetParString(0)); return ; } if(solver.info()!=Success) { e->Throw( "Decomposition has failed: " + e->GetParString(0)); return; } e->SetPar(1,res); m0 = m0.triangularView(); tmp_res = tmp_res.triangularView(); tmp_res = tmp_res + m0; Map >(&(*p0SS)[0], NbCol, NbRow) = tmp_res.cast(); e->SetPar(0,p0SS); return ; } //****************************Bug************************** else { cout << "Should never reach this point ! Please report it !" << endl; return ; } return ; } // UNUSED, copy of gsl_fun: bad habit! // template< typename T> // int cp2data_template( BaseGDL* p0, T* data, SizeT nEl, // SizeT offset, SizeT stride_in, SizeT stride_out) // { // switch ( p0->Type()) { // case GDL_DOUBLE: // cp2data2_template< DDoubleGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // case GDL_FLOAT: // cp2data2_template< DFloatGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // case GDL_LONG: // cp2data2_template< DLongGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // case GDL_ULONG: // cp2data2_template< DULongGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // case GDL_INT: // cp2data2_template< DIntGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // case GDL_UINT: // cp2data2_template< DUIntGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // case GDL_BYTE: // cp2data2_template< DByteGDL, T>( p0, data, nEl, offset, // stride_in, stride_out); // break; // } // return 0; // } #endif } //namespace lib gdl-0.9.9/src/matrix_cholesky.hpp000066400000000000000000000026561340051421000170030ustar00rootroot00000000000000/*************************************************************************** gsl_fun.hpp - GSL GDL library function ------------------- begin : Jan 20 2004 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif // current versions are based on Eigen3 // #if defined(HAVE_LIBGSL) && defined(HAVE_LIBGSLCBLAS) //#ifndef GSL_FUN_HPP_ //#define GSL_FUN_HPP_ #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* cholsol_fun( EnvT* e); BaseGDL* la_cholsol_fun( EnvT* e); void choldc_pro( EnvT* e); void la_choldc_pro( EnvT* e); } // namespace //#endif gdl-0.9.9/src/matrix_invert.cpp000066400000000000000000000443561340051421000164670ustar00rootroot00000000000000/*************************************************************************** matrix_invert.cpp ------------------- begin : May 17 2013 copyright : (C) 2004 by Joel Gales email : jomoga@users.sourceforge.net ***************************************************************************/ /* history: At the beginning, this code was only available using the GSL library. At that time, it was included in the "gsl_fun.hpp/cpp" code In 2013 we start to use Eigen3 in conjonction with the GSL. The GSL is mandatory. Eigen3 is not mandatory. */ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //#ifdef HAVE_CONFIG_H //#include //#endif // current versions are based on Eigen3 // #if defined(HAVE_LIBGSL) && defined(HAVE_LIBGSLCBLAS) #include "includefirst.hpp" #include #include #include #include //#include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "basic_fun.hpp" #include "gsl_fun.hpp" #include "dinterpreter.hpp" #include #include #include "matrix_invert.hpp" //#include "gsl_errorhandler.hpp" #define LOG10E 0.434294 #if defined(USE_EIGEN) #include #include #include #endif namespace lib { #if defined(USE_EIGEN) using namespace Eigen; #endif using namespace std; //void SetGDLGenericGSLErrorHandler(); const int szdbl=sizeof(double); const int szflt=sizeof(float); void matrix_input_check_dims( EnvT* e) { BaseGDL* p0 = e->GetNumericParDefined( 0); //cout << p0->Rank() << endl; SizeT nEl = p0->N_Elements(); if( nEl == 0) e->Throw( "Variable is undefined: " + e->GetParString(0)); if (p0->Rank() > 2) e->Throw( "Input must be a square matrix: " + e->GetParString(0)); if (p0->Rank() == 2) { if (p0->Dim(0) != p0->Dim(1)) e->Throw( "Input must be a square matrix: " + e->GetParString(0)); } // array singleton OK (e.g. [1]), vector not if ((p0->Rank() == 1) && (nEl > 1)) { e->Throw( "Input must be a square matrix: " + e->GetParString(0)); } if (p0->Rank() == 0) e->Throw( "Expression must be an array in this context: " + e->GetParString(0)); } BaseGDL* AC_invert_fun( EnvT* e) { static int GSLIx=e->KeywordIx("GSL"); static int EIGENIx=e->KeywordIx("EIGEN"); if (e->KeywordSet(GSLIx) && e->KeywordSet(EIGENIx)) e->Throw("Conflicting keywords"); static int DOUBLEIx=e->KeywordIx("DOUBLE"); bool hasDouble=e->KeywordSet(DOUBLEIx); matrix_input_check_dims(e); #if defined(USE_EIGEN) bool Eigen_flag=TRUE; #else bool Eigen_flag=FALSE; #endif if (e->KeywordSet(EIGENIx) && (!Eigen_flag)) Warning("Eigen Invert not available, GSL used"); if (e->KeywordSet(GSLIx) || (!Eigen_flag)) { return invert_gsl_fun(e, hasDouble); } else { // if /Eigen, we want to use Eigen, // then we don't check the status and return ... if (e->KeywordSet(EIGENIx)) return invert_eigen_fun(e, hasDouble); // AC 2014-08-10 : during tests of Chianti Code, // we discovered that the GSL code was less sensitive // to very high range in matrix ... // If status used, if Eigen fails, we try GSL BaseGDL* tmp; tmp=invert_eigen_fun(e, hasDouble); SizeT nParam=e->NParam(1); if (nParam == 2) { BaseGDL* p1 = e->GetParDefined(1); DLongGDL* res = static_cast (p1->Convert2(GDL_LONG, BaseGDL::COPY)); DLong status; status=(*res)[0]; if (status > 0) tmp=invert_gsl_fun(e, hasDouble); } return tmp; } } BaseGDL* invert_gsl_fun( EnvT* e, bool hasDouble) { BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); // related to "status" param // check here, if not done, res would be pending in case of SetPar() throws // SetPar() only throws in AssureGlobalPar() SizeT nParam=e->NParam(1); if (nParam == 2) e->AssureGlobalPar( 1); long singular=0; int s; float f32; double f64; double det; // only one element matrix if( nEl == 1) { if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* res = static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); double a, b, deno; a=real((*res)[0]); b=imag((*res)[0]); deno=a*a+b*b; if (deno == 0.0) { singular=1; (*res)[0]= DComplexDbl(0., 0.); } else { (*res)[0]= DComplexDbl(a/deno, -b/deno); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } if( p0->Type() == GDL_COMPLEX) { DComplexGDL* res = static_cast (p0->Convert2(GDL_COMPLEX, BaseGDL::COPY)); float a, b, deno; a=real((*res)[0]); b=imag((*res)[0]); deno=a*a+b*b; if (deno == 0.0) { singular=1; (*res)[0]= DComplex(0., 0.); } else { (*res)[0]= DComplex(a/deno, -b/deno); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } if(( p0->Type() == GDL_DOUBLE) || hasDouble) { DDoubleGDL* res = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); if ((*res)[0] == 0.0) { singular=1; } else { double unity=1.0 ; (*res)[0]= unity / ((*res)[0]); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } // all other cases (including GDL_STRING, Float, Int, ... ) // if( p0->Type() == GDL_STRING) { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if ((*res)[0] == 0.0) { singular=1; } else { (*res)[0]= 1.0 / ((*res)[0]); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } // more than one element matrix // GSL error handling // SetTemporaryGSLErrorHandlerT lib::setTemporaryGSLErrorHandler( GDLGenericGSLErrorHandler); if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast( p0); DComplexGDL* res = new DComplexGDL( p0C->Dim(), BaseGDL::NOZERO); Guard resGuard( res); float f32_2[2]; double f64_2[2]; gsl_matrix_complex *mat = gsl_matrix_complex_alloc(p0->Dim(0), p0->Dim(1)); GDLGuard g1( mat, gsl_matrix_complex_free); gsl_matrix_complex *inverse = gsl_matrix_complex_calloc(p0->Dim(0), p0->Dim(1)); GDLGuard g2( inverse, gsl_matrix_complex_free); gsl_permutation *perm = gsl_permutation_alloc(p0->Dim(0)); GDLGuard g3( perm, gsl_permutation_free); for( SizeT i=0; idata[2*i], &f64, szdbl); f64 = (double) f32_2[1]; memcpy(&mat->data[2*i+1], &f64, szdbl); } gsl_linalg_complex_LU_decomp (mat, perm, &s); det = gsl_linalg_complex_LU_lndet(mat); if (gsl_isinf(det) == 0) { gsl_linalg_complex_LU_invert (mat, perm, inverse); if (abs(det) * LOG10E < 1e-5) singular = 2; } else singular = 1; for( SizeT i=0; idata[2*i], szdbl*2); f32_2[0] = (float) f64_2[0]; f32_2[1] = (float) f64_2[1]; memcpy(&(*res)[i], &f32_2[0], szflt*2); } // gsl_permutation_free(perm); // gsl_matrix_complex_free(mat); // gsl_matrix_complex_free(inverse); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); resGuard.release(); return res; } else if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast( p0); DComplexDblGDL* res = new DComplexDblGDL( p0C->Dim(), BaseGDL::NOZERO); Guard resGuard( res); gsl_matrix_complex *mat = gsl_matrix_complex_alloc(p0->Dim(0), p0->Dim(1)); GDLGuard g1( mat, gsl_matrix_complex_free); gsl_matrix_complex *inverse = gsl_matrix_complex_calloc(p0->Dim(0), p0->Dim(1)); GDLGuard g2( inverse, gsl_matrix_complex_free); gsl_permutation *perm = gsl_permutation_alloc(p0->Dim(0)); GDLGuard g3( perm, gsl_permutation_free); memcpy(mat->data, &(*p0C)[0], nEl*szdbl*2); gsl_linalg_complex_LU_decomp (mat, perm, &s); det = gsl_linalg_complex_LU_lndet(mat); if (gsl_isinf(det) == 0) { gsl_linalg_complex_LU_invert (mat, perm, inverse); if (abs(det) * LOG10E < 1e-5) singular = 2; } else singular = 1; memcpy(&(*res)[0], inverse->data, nEl*szdbl*2); // gsl_permutation_free(perm); // gsl_matrix_complex_free(mat); // gsl_matrix_complex_free(inverse); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); resGuard.release(); return res; } else if (( p0->Type() == GDL_DOUBLE) || hasDouble) { DDoubleGDL* p0D = static_cast (p0->Convert2(GDL_DOUBLE,BaseGDL::COPY)); // DDoubleGDL* p0D = static_cast( p0); DDoubleGDL* res = new DDoubleGDL( p0->Dim(), BaseGDL::NOZERO); Guard resGuard( res); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(1)); GDLGuard g1( mat, gsl_matrix_free); gsl_matrix *inverse = gsl_matrix_calloc(p0->Dim(0), p0->Dim(1)); GDLGuard g2( inverse, gsl_matrix_free); gsl_permutation *perm = gsl_permutation_alloc(p0->Dim(0)); GDLGuard g3( perm, gsl_permutation_free); memcpy(mat->data, &(*p0D)[0], nEl*szdbl); gsl_linalg_LU_decomp (mat, perm, &s); det = gsl_linalg_LU_lndet(mat); if (gsl_isinf(det) == 0) { gsl_linalg_LU_invert (mat, perm, inverse); if (abs(det) * LOG10E < 1e-5) singular = 2; } else singular = 1; memcpy(&(*res)[0], inverse->data, nEl*szdbl); // gsl_permutation_free(perm); // gsl_matrix_free(mat); // gsl_matrix_free(inverse); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); resGuard.release(); return res; } else if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_ULONG || p0->Type() == GDL_INT || p0->Type() == GDL_STRING || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { DFloatGDL* p0F = static_cast( p0); DLongGDL* p0L = static_cast( p0); DULongGDL* p0UL = static_cast( p0); DIntGDL* p0I = static_cast( p0); // DStringGDL* p0S = static_cast( p0); DUIntGDL* p0UI = static_cast( p0); DByteGDL* p0B = static_cast( p0); // if (p0->Type() == STRING) { DFloatGDL* p0SS = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); Guard p0SSGuard( p0SS); //} DFloatGDL* res = new DFloatGDL( p0->Dim(), BaseGDL::NOZERO); Guard resGuard( res); gsl_matrix *mat = gsl_matrix_alloc(p0->Dim(0), p0->Dim(1)); GDLGuard g1( mat, gsl_matrix_free); gsl_matrix *inverse = gsl_matrix_calloc(p0->Dim(0), p0->Dim(1)); GDLGuard g2( inverse, gsl_matrix_free); gsl_permutation *perm = gsl_permutation_alloc(p0->Dim(0)); GDLGuard g3( perm, gsl_permutation_free); for( SizeT i=0; iType()) { case GDL_FLOAT: f64 = (double) (*p0F)[i]; break; case GDL_LONG: f64 = (double) (*p0L)[i]; break; case GDL_ULONG: f64 = (double) (*p0UL)[i]; break; case GDL_INT: f64 = (double) (*p0I)[i]; break; case GDL_STRING:f64 = (double) (*p0SS)[i]; break; case GDL_UINT: f64 = (double) (*p0UI)[i]; break; case GDL_BYTE: f64 = (double) (*p0B)[i]; break; default: break; //not reached. pacifies compilers. } memcpy(&mat->data[i], &f64, szdbl); } gsl_linalg_LU_decomp (mat, perm, &s); det = gsl_linalg_LU_lndet(mat); if (gsl_isinf(det) == 0) { gsl_linalg_LU_invert (mat, perm, inverse); if (abs(det) * LOG10E < 1e-5) singular = 2; } else singular = 1; for( SizeT i=0; idata[i]; memcpy(&(*res)[i], &f32, 4); } // gsl_permutation_free(perm); // gsl_matrix_free(mat); // gsl_matrix_free(inverse); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); resGuard.release(); return res; } else { cout << "Should never reach this point ! Please report it !" << endl; DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } } #if defined(USE_EIGEN) BaseGDL* invert_eigen_fun( EnvT* e, bool hasDouble) { BaseGDL* p0 = e->GetParDefined( 0); SizeT nEl = p0->N_Elements(); // related to "status" param : see comment in "invert_gsl_fun" SizeT nParam=e->NParam(1); if (nParam == 2) e->AssureGlobalPar( 1); long singular=0; // only one element matrix if( nEl == 1) { if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* res = static_cast (p0->Convert2(GDL_COMPLEXDBL, BaseGDL::COPY)); double a, b, deno; a=real((*res)[0]); b=imag((*res)[0]); deno=a*a+b*b; if (deno == 0.0) { singular=1; (*res)[0]= DComplexDbl(0., 0.); } else { (*res)[0]= DComplexDbl(a/deno, -b/deno); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } if( p0->Type() == GDL_COMPLEX) { DComplexGDL* res = static_cast (p0->Convert2(GDL_COMPLEX, BaseGDL::COPY)); float a, b, deno; a=real((*res)[0]); b=imag((*res)[0]); deno=a*a+b*b; if (deno == 0.0) { singular=1; (*res)[0]= DComplex(0., 0.); } else { (*res)[0]= DComplex(a/deno, -b/deno); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } if(( p0->Type() == GDL_DOUBLE) || hasDouble) { DDoubleGDL* res = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); if ((*res)[0] == 0.0) { singular=1; } else { double unity=1.0 ; (*res)[0]= unity / ((*res)[0]); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } // all other cases (including GDL_STRING, Float, Int, ... ) // if( p0->Type() == GDL_STRING) { DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if ((*res)[0] == 0.0) { singular=1; } else { (*res)[0]= 1.0 / ((*res)[0]); } if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } // more than one element matrix long NbCol, NbRow; if( p0->Type() == GDL_COMPLEX) { DComplexGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEX , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); MatrixXcf tmp_res (NbCol,NbRow); Map,Dynamic,Dynamic> > m0(&(*p0C)[0], NbCol,NbRow); FullPivLU lu(m0); if(lu.isInvertible()) { tmp_res=lu.inverse(); if (abs(lu.determinant().real())* LOG10E < 1e-5) singular = 2; } else singular=1; DComplexGDL* res = new DComplexGDL(p0->Dim(), BaseGDL::NOZERO); Map(&(*res)[0], NbCol, NbRow) = tmp_res.cast >(); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } else if( p0->Type() == GDL_COMPLEXDBL) { DComplexDblGDL* p0C = static_cast (p0->Convert2(GDL_COMPLEXDBL , BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); MatrixXcd tmp_res (NbCol,NbRow); Map,Dynamic,Dynamic> > m0(&(*p0C)[0], NbCol,NbRow); FullPivLU lu(m0); if(lu.isInvertible()) { tmp_res=lu.inverse(); if (abs(lu.determinant().real())* LOG10E < 1e-5) singular = 2; } else singular=1; DComplexDblGDL* res = new DComplexDblGDL(p0->Dim(), BaseGDL::NOZERO); Map(&(*res)[0], NbCol, NbRow) = tmp_res.cast >(); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } else if(( p0->Type() == GDL_DOUBLE) || hasDouble) { DDoubleGDL* p0D = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); MatrixXd tmp_res (NbCol,NbRow); Map > m0(&(*p0D)[0], NbCol,NbRow); Eigen::FullPivLU lu(m0); // cout << lu.determinant() << endl; //cout << lu.isInvertible() << endl; if(lu.isInvertible()) { tmp_res=lu.inverse(); if (abs(lu.determinant()) * LOG10E < 1e-5) singular = 2; } else singular=1; DDoubleGDL* res = new DDoubleGDL(p0->Dim(), BaseGDL::NOZERO); Map(&(*res)[0], NbCol, NbRow) = tmp_res.cast(); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } // all other cases (including GDL_STRING, Float, Int, ... ) // if( p0->Type() == GDL_STRING) { else if( p0->Type() == GDL_FLOAT || p0->Type() == GDL_LONG || p0->Type() == GDL_LONG64 || p0->Type() == GDL_ULONG64 || p0->Type() == GDL_ULONG || p0->Type() == GDL_INT || p0->Type() == GDL_STRING || p0->Type() == GDL_UINT || p0->Type() == GDL_BYTE) { DFloatGDL* p0SS = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); NbCol=p0->Dim(0); NbRow=p0->Dim(1); MatrixXf tmp_res(NbCol,NbRow); Map > m0(&(*p0SS)[0], NbCol,NbRow); FullPivLU lu(m0); if(lu.isInvertible()) { tmp_res=lu.inverse(); if (abs(lu.determinant()) * LOG10E < 1e-5) singular = 2; } else singular=1; DFloatGDL* res =new DFloatGDL(p0->Dim(), BaseGDL::NOZERO); Map(&(*res)[0], NbCol, NbRow) = tmp_res.cast(); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } else { cout << "Should never reach this point ! Please report it !" << endl; DFloatGDL* res = static_cast (p0->Convert2( GDL_FLOAT, BaseGDL::COPY)); if (nParam == 2) e->SetPar(1,new DLongGDL( singular)); return res; } } #else BaseGDL* invert_eigen_fun( EnvT* e, bool hasDouble){ e->Throw( "sorry, INVERT with Eigen not available. GDL must be compiled with Eigen lib."); return NULL; } #endif } gdl-0.9.9/src/matrix_invert.hpp000066400000000000000000000031671340051421000164670ustar00rootroot00000000000000/*************************************************************************** matrix_invert.hpp ------------------- begin : May 17 2013 copyright : (C) 2004 by Joel Gales, 2013: Nodar K. and Alain C. email : jomoga@users.sourceforge.net ***************************************************************************/ /* history: At the beginning, this code was only available using the GSL library. At that time, it was included in the "gsl_fun.hpp/cpp" code In 2013 we start to use Eigen3 in conjonction with the GSL. The GSL is mandatory. Eigen3 is not mandatory. */ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif // current versions are based on Eigen3 // #if defined(HAVE_LIBGSL) && defined(HAVE_LIBGSLCBLAS) #include "datatypes.hpp" #include "envt.hpp" namespace lib { BaseGDL* invert_eigen_fun( EnvT* e, bool hasDouble); BaseGDL* invert_gsl_fun( EnvT* e, bool hasDouble); BaseGDL* AC_invert_fun( EnvT* e); } gdl-0.9.9/src/medianfilter.cpp000066400000000000000000001043641340051421000162330ustar00rootroot00000000000000// Copyright (c) 2014, Jukka Suomela. // // You can distribute and use this software under the MIT license: http://opensource.org/licenses/MIT // 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. // To contact the author, see http://users.ics.aalto.fi/suomela/ // modified by GD to mimic the /EVEN switch of IDL. Note that modifying these optimized algorithms for non-odd sizes is tricky. namespace fastmedian{ //make it apart from the rest... #include #include #include #include #include #include const uint64_t ONE64 = 1; // Reasonable values based on benchmarks inline int choose_blocksize_1d(int h) { return 8*(h + 2); } inline int choose_blocksize_2d(int h) { return 4*(h + 2); } // Find nth bit that is set and return its index // (no such bit: output undefined) inline int findnth64(uint64_t x, int n) { #ifdef __AVX2__ x = _pdep_u64(ONE64 << n, x); #else for (int i = 0; i < n; ++i) { x &= x - 1; } #endif return __builtin_ctzll(x); } inline int popcnt64(uint64_t x) { return __builtin_popcountll(x); } // Grid dimensions. class Dim { public: Dim(int b_, int size_, int h_) : size(size_), h(h_), step(calc_step(b_, h_)), count(calc_count(b_, size_, h_)) { assert(2 * h + 1 < b_); assert(count >= 1); assert(2 * h + count * step >= size); assert(2 * h + (count - 1) * step < size || count == 1); } const int size; const int h; const int step; const int count; private: inline static int calc_step(int b, int h) { return b - 2*h; } inline static int calc_count(int b, int size, int h) { if (size <= b) { return 1; } else { int interior = size - 2 * h; int step = calc_step(b, h); return (interior + step - 1) / step; } } }; // Slot i in the grid. struct BDim { BDim(Dim dim_) : dim(dim_) { set(0); } inline void set(int i) { bool is_first = (i == 0); bool is_last = (i + 1 == dim.count); start = dim.step * i; int end; if (is_last) { end = dim.size; } else { end = 2 * dim.h + (i + 1) * dim.step; } size = end - start; b0 = is_first ? 0 : dim.h; b1 = is_last ? size : size - dim.h; } // The window around point v is [w0(v), w1(v)). // 0 <= w0(v) <= v < w1(v) <= size inline int w0(int v) const { assert(b0 <= v); assert(v < b1); return std::max(0, v - dim.h); } inline int w1(int v) const { assert(b0 <= v); assert(v < b1); return std::min(v + 1 + dim.h, size); } // Block i is located at coordinates [start, end) in the image. // Within the block, median is needed for coordinates [b0, b1). // 0 <= start < end < dim.size // 0 <= b0 < b1 < size <= dim.b const Dim dim; int start; int size; int b0; int b1; }; // Data structure for the sliding window. class Window { public: Window(int bb) : words(get_words(bb)), buf(new uint64_t[words]) {} ~Window() { delete[] buf; } inline void clear() { for (int i = 0; i < words; ++i) { buf[i] = 0; } half[0] = 0; half[1] = 0; p = words / 2; } inline void update(int op, int s) { assert(op == -1 || op == +1); int i = s >> WORD_SHIFT; int j = s & WORD_MASK; if (op == +1) { assert(!(buf[i] & (ONE64 << j))); } else { assert(buf[i] & (ONE64 << j)); } buf[i] ^= (ONE64 << j); half[i >= p] += op; } inline int size() const { return half[0] + half[1]; } inline int find(int goal) { while (half[0] > goal) { --p; half[0] -= popcnt64(buf[p]); half[1] += popcnt64(buf[p]); } while (half[0] + popcnt64(buf[p]) <= goal) { half[0] += popcnt64(buf[p]); half[1] -= popcnt64(buf[p]); ++p; } int n = goal - half[0]; assert(0 <= n && n < popcnt64(buf[p])); int j = findnth64(buf[p], n); return (p << WORD_SHIFT) | j; } private: static inline int get_words(int bb) { assert(bb >= 1); return (bb + WORD_SIZE - 1) / WORD_SIZE; } static const int WORD_SHIFT = 6; static const int WORD_SIZE = 1 << WORD_SHIFT; static const int WORD_MASK = WORD_SIZE - 1; // Size of buf. const int words; // Bit number s is on iff element s is inside the window. uint64_t * const buf; // half[0] = popcount of buf[0] ... buf[p-1] // half[1] = popcount of buf[p] ... buf[words-1] int half[2]; // The current guess is that the median is in buf[p]. int p; }; template class WindowRank { public: WindowRank(int bb_) : sorted(new std::pair[bb_]), rank(new int[bb_]), window(bb_), bb(bb_) {} ~WindowRank() { delete[] sorted; delete[] rank; } void init_start() { size = 0; } inline void init_feed(T value, int slot) { if (std::isnan(value)) { rank[slot] = NAN_MARKER; } else { sorted[size] = std::make_pair(value, slot); ++size; } } void init_finish() { std::sort(sorted, sorted + size); for (int i = 0; i < size; ++i) { rank[sorted[i].second] = i; } } inline void clear() { window.clear(); } inline void update(int op, int slot) { int s = rank[slot]; if (s != NAN_MARKER) { window.update(op, s); } } inline T get_med() { int total = window.size(); if (total == 0) { return std::numeric_limits::quiet_NaN(); } else { int goal1 = (total - 1) / 2; int goal2 = (total - 0) / 2; int med1 = window.find(goal1); T value = sorted[med1].first; if (goal2 != goal1) { int med2 = window.find(goal2); assert(med2 > med1); value += sorted[med2].first; value /= 2; } return value; } } private: std::pair* const sorted; int* const rank; Window window; const int bb; int size; static const int NAN_MARKER = -1; }; // MedCalc2D.run(i,j) calculates medians for block (i,j). template class MedCalc2D { public: MedCalc2D(int b_, Dim dimx_, Dim dimy_, const T* in_, T* out_) : wr(b_ * b_), bx(dimx_), by(dimy_), in(in_), out(out_) {} void run(int bx_, int by_) { bx.set(bx_); by.set(by_); calc_rank(); medians(); } private: void calc_rank() { wr.init_start(); for (int y = 0; y < by.size; ++y) { for (int x = 0; x < bx.size; ++x) { wr.init_feed(in[coord(x, y)], pack(x, y)); } } wr.init_finish(); } void medians() { #ifdef NAIVE for (int y = by.b0; y < by.b1; ++y) { for (int x = bx.b0; x < bx.b1; ++x) { wr.clear(); update_block(+1, bx.w0(x), bx.w1(x), by.w0(y), by.w1(y)); set_med(x, y); } } #else wr.clear(); int x = bx.b0; int y = by.b0; update_block(+1, bx.w0(x), bx.w1(x), by.w0(y), by.w1(y)); set_med(x, y); bool down = true; while (true) { bool right = false; if (down) { if (y + 1 == by.b1) { right = true; down = false; } } else { if (y == by.b0) { right = true; down = true; } } if (right) { if (x + 1 == bx.b1) { break; } } if (right) { update_block(-1, bx.w0(x), bx.w0(x+1), by.w0(y), by.w1(y)); ++x; update_block(+1, bx.w1(x-1), bx.w1(x), by.w0(y), by.w1(y)); } else if (down) { update_block(-1, bx.w0(x), bx.w1(x), by.w0(y), by.w0(y+1)); ++y; update_block(+1, bx.w0(x), bx.w1(x), by.w1(y-1), by.w1(y)); } else { update_block(-1, bx.w0(x), bx.w1(x), by.w1(y-1), by.w1(y)); --y; update_block(+1, bx.w0(x), bx.w1(x), by.w0(y), by.w0(y+1)); } set_med(x, y); } #endif } inline void update_block(int op, int x0, int x1, int y0, int y1) { for (int y = y0; y < y1; ++y) { for (int x = x0; x < x1; ++x) { wr.update(op, pack(x, y)); } } } inline void set_med(int x, int y) { out[coord(x, y)] = wr.get_med(); } inline int pack(int x, int y) const { return y * bx.size + x; } inline int coord(int x, int y) const { return (y + by.start) * bx.dim.size + (x + bx.start); } WindowRank wr; BDim bx; BDim by; const T* const in; T* const out; }; template class MedCalc1D { public: MedCalc1D(int b_, Dim dimx_, const T* in_, T* out_) : wr(b_), bx(dimx_), in(in_), out(out_) {} void run(int bx_) { bx.set(bx_); calc_rank(); medians(); } private: void calc_rank() { wr.init_start(); for (int x = 0; x < bx.size; ++x) { wr.init_feed(in[coord(x)], pack(x)); } wr.init_finish(); } void medians() { #ifdef NAIVE for (int x = bx.b0; x < bx.b1; ++x) { wr.clear(); update_block(+1, bx.w0(x), bx.w1(x)); set_med(x); } #else wr.clear(); int x = bx.b0; update_block(+1, bx.w0(x), bx.w1(x)); set_med(x); while (x + 1 < bx.b1) { if (x >= bx.dim.h) { wr.update(-1, pack(x - bx.dim.h)); } ++x; if (x + bx.dim.h < bx.size) { wr.update(+1, pack(x + bx.dim.h)); } set_med(x); } #endif } inline void update_block(int op, int x0, int x1) { for (int x = x0; x < x1; ++x) { wr.update(op, pack(x)); } } inline void set_med(int x) { out[coord(x)] = wr.get_med(); } inline int pack(int x) const { return x; } inline int coord(int x) const { return x + bx.start; } WindowRank wr; BDim bx; const T* const in; T* const out; }; template void median_filter_impl_2d(int x, int y, int hx, int hy, int b, const T* in, T* out) { if (2 * hx + 1 > b || 2 * hy + 1 > b) { throw std::invalid_argument("window too large for this block size"); } Dim dimx(b, x, hx); Dim dimy(b, y, hy); #pragma omp parallel { MedCalc2D mc(b, dimx, dimy, in, out); #pragma omp for collapse(2) for (int by = 0; by < dimy.count; ++by) { for (int bx = 0; bx < dimx.count; ++bx) { mc.run(bx, by); } } } } template void median_filter_impl_1d(int x, int hx, int b, const T* in, T* out) { if (2 * hx + 1 > b) { throw std::invalid_argument("window too large for this block size"); } Dim dimx(b, x, hx); #pragma omp parallel { MedCalc1D mc(b, dimx, in, out); #pragma omp for for (int bx = 0; bx < dimx.count; ++bx) { mc.run(bx); } } } template void median_filter_2d(int x, int y, int hx, int hy, int blockhint, const T* in, T* out) { int h = std::max(hx, hy); int blocksize = blockhint ? blockhint : choose_blocksize_2d(h); median_filter_impl_2d(x, y, hx, hy, blocksize, in, out); } template void median_filter_1d(int x, int hx, int blockhint, const T* in, T* out) { int blocksize = blockhint ? blockhint : choose_blocksize_1d(hx); median_filter_impl_1d(x, hx, blocksize, in, out); } template void median_filter_2d(int x, int y, int hx, int hy, int blockhint, const float* in, float* out); template void median_filter_2d(int x, int y, int hx, int hy, int blockhint, const double* in, double* out); template void median_filter_1d(int x, int hx, int blockhint, const float* in, float* out); template void median_filter_1d(int x, int hx, int blockhint, const double* in, double* out); /* * ctmf.c - Constant-time median filtering * Copyright (C) 2006 Simon Perreault * * Reference: S. Perreault and P. Halbert, "Median Filtering in Constant Time", * IEEE Transactions on Image Processing, September 2007. * * This program has been obtained from http://nomis80.org/ctmf.html. No patent * covers this program, although it is subject to the following license: * * 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 of the License, 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. If not, see . * * Contact: * Laboratoire de vision et systemes numeriques * Pavillon Adrien-Pouliot * Universite Laval * Sainte-Foy, Quebec, Canada * G1K 7P4 * * perreaul@gel.ulaval.ca */ /* Standard C includes */ #include #include #include #include /* Type declarations */ #ifdef _MSC_VER #include typedef UINT8 uint8_t; typedef UINT16 uint16_t; typedef UINT32 uint32_t; #pragma warning( disable: 4799 ) #else #include #endif /* Intrinsic declarations */ #if defined(__SSE2__) || defined(__MMX__) #if defined(__SSE2__) #include #elif defined(__MMX__) #include #endif #if defined(__GNUC__) #include #elif defined(_MSC_VER) #include #endif #elif defined(__ALTIVEC__) #include #endif /* Compiler peculiarities */ #if defined(__GNUC__) #include #define inline __inline__ #define align(x) __attribute__ ((aligned (x))) #elif defined(_MSC_VER) #define inline __inline #define align(x) __declspec(align(x)) #else #define inline #define align(x) #endif #ifndef MIN #define MIN(a,b) ((a) > (b) ? (b) : (a)) #endif #ifndef MAX #define MAX(a,b) ((a) < (b) ? (b) : (a)) #endif /** * This structure represents a two-tier histogram. The first tier (known as the * "coarse" level) is 4 bit wide and the second tier (known as the "fine" level) * is 8 bit wide. Pixels inserted in the fine level also get inserted into the * coarse bucket designated by the 4 MSBs of the fine bucket value. * * The structure is aligned on 16 bytes, which is a prerequisite for SIMD * instructions. Each bucket is 16 bit wide, which means that extra care must be * taken to prevent overflow. */ typedef struct align(16) { uint16_t coarse[16]; uint16_t fine[16][16]; } Histogram; /** * HOP is short for Histogram OPeration. This macro makes an operation \a op on * histogram \a h for pixel value \a x. It takes care of handling both levels. */ #define HOP(h,x,op) \ h.coarse[x>>4] op; \ *((uint16_t*) h.fine + x) op; #define COP(c,j,x,op) \ h_coarse[ 16*(n*c+j) + (x>>4) ] op; \ h_fine[ 16 * (n*(16*c+(x>>4)) + j) + (x & 0xF) ] op; /** * Adds histograms \a x and \a y and stores the result in \a y. Makes use of * SSE2, MMX or Altivec, if available. */ #if defined(__SSE2__) static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) { *(__m128i*) &y[0] = _mm_add_epi16( *(__m128i*) &y[0], *(__m128i*) &x[0] ); *(__m128i*) &y[8] = _mm_add_epi16( *(__m128i*) &y[8], *(__m128i*) &x[8] ); } #elif defined(__MMX__) static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) { *(__m64*) &y[0] = _mm_add_pi16( *(__m64*) &y[0], *(__m64*) &x[0] ); *(__m64*) &y[4] = _mm_add_pi16( *(__m64*) &y[4], *(__m64*) &x[4] ); *(__m64*) &y[8] = _mm_add_pi16( *(__m64*) &y[8], *(__m64*) &x[8] ); *(__m64*) &y[12] = _mm_add_pi16( *(__m64*) &y[12], *(__m64*) &x[12] ); } #elif defined(__ALTIVEC__) static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) { *(__vector unsigned short*) &y[0] = vec_add( *(__vector unsigned short*) &y[0], *(__vector unsigned short*) &x[0] ); *(__vector unsigned short*) &y[8] = vec_add( *(__vector unsigned short*) &y[8], *(__vector unsigned short*) &x[8] ); } #else static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) { int i; for ( i = 0; i < 16; ++i ) { y[i] += x[i]; } } #endif /** * Subtracts histogram \a x from \a y and stores the result in \a y. Makes use * of SSE2, MMX or Altivec, if available. */ #if defined(__SSE2__) static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) { *(__m128i*) &y[0] = _mm_sub_epi16( *(__m128i*) &y[0], *(__m128i*) &x[0] ); *(__m128i*) &y[8] = _mm_sub_epi16( *(__m128i*) &y[8], *(__m128i*) &x[8] ); } #elif defined(__MMX__) static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) { *(__m64*) &y[0] = _mm_sub_pi16( *(__m64*) &y[0], *(__m64*) &x[0] ); *(__m64*) &y[4] = _mm_sub_pi16( *(__m64*) &y[4], *(__m64*) &x[4] ); *(__m64*) &y[8] = _mm_sub_pi16( *(__m64*) &y[8], *(__m64*) &x[8] ); *(__m64*) &y[12] = _mm_sub_pi16( *(__m64*) &y[12], *(__m64*) &x[12] ); } #elif defined(__ALTIVEC__) static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) { *(__vector unsigned short*) &y[0] = vec_sub( *(__vector unsigned short*) &y[0], *(__vector unsigned short*) &x[0] ); *(__vector unsigned short*) &y[8] = vec_sub( *(__vector unsigned short*) &y[8], *(__vector unsigned short*) &x[8] ); } #else static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) { int i; for ( i = 0; i < 16; ++i ) { y[i] -= x[i]; } } #endif static inline void histogram_muladd( const uint16_t a, const uint16_t x[16], uint16_t y[16] ) { int i; for ( i = 0; i < 16; ++i ) { y[i] += a * x[i]; } } static void ctmf_helper( const unsigned char* const src, unsigned char* const dst, const int width, const int height, const int src_step, const int dst_step, const int r, const int cn, const int pad_left, const int pad_right ) { const int m = height, n = width; int i, j, k, c; const unsigned char *p, *q; Histogram H[4]; uint16_t *h_coarse, *h_fine, luc[4][16]; assert( src ); assert( dst ); assert( r >= 0 ); assert( width >= 2*r+1 ); assert( height >= 2*r+1 ); assert( src_step != 0 ); assert( dst_step != 0 ); /* SSE2 and MMX need aligned memory, provided by _mm_malloc(). */ #if defined(__SSE2__) || defined(__MMX__) h_coarse = (uint16_t*) _mm_malloc( 1 * 16 * n * cn * sizeof(uint16_t), 16 ); h_fine = (uint16_t*) _mm_malloc( 16 * 16 * n * cn * sizeof(uint16_t), 16 ); memset( h_coarse, 0, 1 * 16 * n * cn * sizeof(uint16_t) ); memset( h_fine, 0, 16 * 16 * n * cn * sizeof(uint16_t) ); #else h_coarse = (uint16_t*) calloc( 1 * 16 * n * cn, sizeof(uint16_t) ); h_fine = (uint16_t*) calloc( 16 * 16 * n * cn, sizeof(uint16_t) ); #endif /* First row initialization */ for ( j = 0; j < n; ++j ) { for ( c = 0; c < cn; ++c ) { COP( c, j, src[cn*j+c], += r+1 ); } } for ( i = 0; i < r; ++i ) { for ( j = 0; j < n; ++j ) { for ( c = 0; c < cn; ++c ) { COP( c, j, src[src_step*i+cn*j+c], ++ ); } } } for ( i = 0; i < m; ++i ) { /* Update column histograms for entire row. */ p = src + src_step * MAX( 0, i-r-1 ); q = p + cn * n; for ( j = 0; p != q; ++j ) { for ( c = 0; c < cn; ++c, ++p ) { COP( c, j, *p, -- ); } } p = src + src_step * MIN( m-1, i+r ); q = p + cn * n; for ( j = 0; p != q; ++j ) { for ( c = 0; c < cn; ++c, ++p ) { COP( c, j, *p, ++ ); } } /* First column initialization */ memset( H, 0, cn*sizeof(H[0]) ); memset( luc, 0, cn*sizeof(luc[0]) ); if ( pad_left ) { for ( c = 0; c < cn; ++c ) { histogram_muladd( r, &h_coarse[16*n*c], H[c].coarse ); } } for ( j = 0; j < (pad_left ? r : 2*r); ++j ) { for ( c = 0; c < cn; ++c ) { histogram_add( &h_coarse[16*(n*c+j)], H[c].coarse ); } } for ( c = 0; c < cn; ++c ) { for ( k = 0; k < 16; ++k ) { histogram_muladd( 2*r+1, &h_fine[16*n*(16*c+k)], &H[c].fine[k][0] ); } } for ( j = pad_left ? 0 : r; j < (pad_right ? n : n-r); ++j ) { for ( c = 0; c < cn; ++c ) { const uint16_t t = 2*r*r + 2*r; uint16_t sum = 0, *segment; int b; histogram_add( &h_coarse[16*(n*c + MIN(j+r,n-1))], H[c].coarse ); /* Find median at coarse level */ for ( k = 0; k < 16 ; ++k ) { sum += H[c].coarse[k]; if ( sum > t ) { sum -= H[c].coarse[k]; break; } } assert( k < 16 ); /* Update corresponding histogram segment */ if ( luc[c][k] <= j-r ) { memset( &H[c].fine[k], 0, 16 * sizeof(uint16_t) ); for ( luc[c][k] = j-r; luc[c][k] < MIN(j+r+1,n); ++luc[c][k] ) { histogram_add( &h_fine[16*(n*(16*c+k)+luc[c][k])], H[c].fine[k] ); } if ( luc[c][k] < j+r+1 ) { histogram_muladd( j+r+1 - n, &h_fine[16*(n*(16*c+k)+(n-1))], &H[c].fine[k][0] ); luc[c][k] = j+r+1; } } else { for ( ; luc[c][k] < j+r+1; ++luc[c][k] ) { histogram_sub( &h_fine[16*(n*(16*c+k)+MAX(luc[c][k]-2*r-1,0))], H[c].fine[k] ); histogram_add( &h_fine[16*(n*(16*c+k)+MIN(luc[c][k],n-1))], H[c].fine[k] ); } } histogram_sub( &h_coarse[16*(n*c+MAX(j-r,0))], H[c].coarse ); /* Find median in segment */ segment = H[c].fine[k]; for ( b = 0; b < 16 ; ++b ) { sum += segment[b]; if ( sum > t ) { dst[dst_step*i+cn*j+c] = 16*k + b; break; } } assert( b < 16 ); } } } #if defined(__SSE2__) || defined(__MMX__) _mm_empty(); _mm_free(h_coarse); _mm_free(h_fine); #else free(h_coarse); free(h_fine); #endif } /** * \brief Constant-time median filtering * * This function does a median filtering of an 8-bit image. The source image is * processed as if it was padded with zeros. The median kernel is square with * odd dimensions. Images of arbitrary size may be processed. * * To process multi-channel images, you must call this function multiple times, * changing the source and destination adresses and steps such that each channel * is processed as an independent single-channel image. * * Processing images of arbitrary bit depth is not supported. * * The computing time is O(1) per pixel, independent of the radius of the * filter. The algorithm's initialization is O(r*width), but it is negligible. * Memory usage is simple: it will be as big as the cache size, or smaller if * the image is small. For efficiency, the histograms' bins are 16-bit wide. * This may become too small and lead to overflow as \a r increases. * * \param src Source image data. * \param dst Destination image data. Must be preallocated. * \param width Image width, in pixels. * \param height Image height, in pixels. * \param src_step Distance between adjacent pixels on the same column in * the source image, in bytes. * \param dst_step Distance between adjacent pixels on the same column in * the destination image, in bytes. * \param r Median filter radius. The kernel will be a 2*r+1 by * 2*r+1 square. * \param cn Number of channels. For example, a grayscale image would * have cn=1 while an RGB image would have cn=3. * \param memsize Maximum amount of memory to use, in bytes. Set this to * the size of the L2 cache, then vary it slightly and * measure the processing time to find the optimal value. * For example, a 512 kB L2 cache would have * memsize=512*1024 initially. */ void ctmf( const unsigned char* const src, unsigned char* const dst, const int width, const int height, const int src_step, const int dst_step, const int r, const int cn, const long unsigned int memsize ) { /* * Processing the image in vertical stripes is an optimization made * necessary by the limited size of the CPU cache. Each histogram is 544 * bytes big and therefore I can fit a limited number of them in the cache. * That number may sometimes be smaller than the image width, which would be * the number of histograms I would need without stripes. * * I need to keep histograms in the cache so that they are available * quickly when processing a new row. Each row needs access to the previous * row's histograms. If there are too many histograms to fit in the cache, * thrashing to RAM happens. * * To solve this problem, I figure out the maximum number of histograms * that can fit in cache. From this is determined the number of stripes in * an image. The formulas below make the stripes all the same size and use * as few stripes as possible. * * Note that each stripe causes an overlap on the neighboring stripes, as * when mowing the lawn. That overlap is proportional to r. When the overlap * is a significant size in comparison with the stripe size, then we are not * O(1) anymore, but O(r). In fact, we have been O(r) all along, but the * initialization term was neglected, as it has been (and rightly so) in B. * Weiss, "Fast Median and Bilateral Filtering", SIGGRAPH, 2006. Processing * by stripes only makes that initialization term bigger. * * Also, note that the leftmost and rightmost stripes don't need overlap. * A flag is passed to ctmf_helper() so that it treats these cases as if the * image was zero-padded. */ int stripes = (int) ceil( (double) (width - 2*r) / (memsize / sizeof(Histogram) - 2*r) ); int stripe_size = (int) ceil( (double) ( width + stripes*2*r - 2*r ) / stripes ); int i; for ( i = 0; i < width; i += stripe_size - 2*r ) { int stripe = stripe_size; /* Make sure that the filter kernel fits into one stripe. */ if ( i + stripe_size - 2*r >= width || width - (i + stripe_size - 2*r) < 2*r+1 ) { stripe = width - i; } ctmf_helper( src + cn*i, dst + cn*i, stripe, height, src_step, dst_step, r, cn, i == 0, stripe == width - i ); if ( stripe == width - i ) { break; } } } //unused for the time being: #if 1 #ifndef SIMPLE_H #define SIMPLE_H // Sliding median filter // Created 2012 by Colin Raffel // Portions Copyright (c) 2011 ashelly.myopenid.com under // see https://github.com/craffel/median-filter #ifndef MEDIATOR_H #define MEDIATOR_H template class Mediator { public: Mediator(int nItems, bool iseven):N(nItems),even(iseven) { data = new Item[nItems]; pos = new int[nItems]; allocatedHeap = new int[nItems]; heap = allocatedHeap + (nItems/2); minCt = maxCt = idx = 0; // Set up initial heap fill pattern: median, max, min, max, ... while (nItems--) { pos[nItems] = ((nItems + 1)/2)*((nItems & 1) ? -1 : 1); heap[pos[nItems]] = nItems; } }; ~Mediator() { delete[] data; delete[] pos; delete[] allocatedHeap; }; // Inserts item, maintains median in O(lg nItems) void insert(const Item& v ) { const int p = pos[idx]; const Item old = data[idx]; data[idx] = v; idx = (idx+1) % N; // New item is in minheap if (p>0) { if (minCt < (N-1)/2) { ++minCt; } else if (v > old) { minSortDown( p ); return; } if (minSortUp( p ) && mmCmpExch( 0, -1 )) { maxSortDown( -1 ); } } // New item is in maxheap else if (p<0) { if (maxCt < N/2) { ++maxCt; } else if (v < old) { maxSortDown( p ); return; } if (maxSortUp( p ) && minCt && mmCmpExch( 1, 0 )) { minSortDown( 1 ); } } // New item is at median else { if (maxCt && maxSortUp( -1 )) { maxSortDown( -1 ); } if (minCt && minSortUp( 1 )) { minSortDown( 1 ); } } }; // Returns median item (or average of 2 when item count is even) Item getMedian() { Item v = data[heap[0]]; if (even && (minCt= -maxCt; i*=2) { if (i > -maxCt && mmless( i, i-1 )) { --i; } if (!mmCmpExch( i/2, i )) { break; } } }; // Returns 1 if heap[i] < heap[j] inline int mmless(const int i,const int j ) { return (data[heap[i]] < data[heap[j]]); }; // Swaps items i&j if i 0 && mmCmpExch( i, i/2 )) { i /= 2; } return (i == 0); }; // Maintains maxheap property for all items above i, including median // Returns true if median changed inline int maxSortUp( int i ) { while (i < 0 && mmCmpExch( i/2, i )) { i /= 2; } return ( i==0 ); }; // Allocated size const int N; // even /odd correction const bool even; // Circular queue of values Item* data; // Index into `heap` for each value int* pos; // Max/median/min heap holding indexes into `data`. int* heap; // heap holds a pointer to the middle of its data; this is where the data is allocated. int* allocatedHeap; // Position in circular queue int idx; // Count of items in min heap int minCt; // Count of items in max heap int maxCt; }; #endif void filter( double* array, int n, int filterSize, bool even=false ); void filter( float* array, int n, int filterSize, bool even=false ); #endif void filter( double* array, int n, int filterSize , bool even) { Mediator mediator( filterSize, even ); for (int i = 0; i < filterSize/2; ++i) { mediator.insert( array[0] ); array[i] = mediator.getMedian(); } int offset = filterSize/2 + (filterSize % 2); for (int i = 0; i < offset; ++i) { mediator.insert( array[i] ); } for (int i = 0; i < n - offset; ++i) { array[i] = mediator.getMedian(); mediator.insert( array[i + offset] ); } for (int i = n - offset; i < n; ++i) { array[i] = mediator.getMedian(); mediator.insert( array[n - 1] ); } } void filter( float* array, int n, int filterSize, bool even ) { Mediator mediator( filterSize, even ); for (int i = 0; i < filterSize/2; ++i) { mediator.insert( array[0] ); array[i] = mediator.getMedian(); } int offset = filterSize/2 + (filterSize % 2); for (int i = 0; i < offset; ++i) { mediator.insert( array[i] ); } for (int i = 0; i < n - offset; ++i) { array[i] = mediator.getMedian(); mediator.insert( array[i + offset] ); } for (int i = n - offset; i < n; ++i) { array[i] = mediator.getMedian(); mediator.insert( array[n - 1] ); } } #endif } //namespace gdl-0.9.9/src/minmax_include.cpp000066400000000000000000000336241340051421000165640ustar00rootroot00000000000000/*************************************************************************** minmax_include.cpp - include for minmax() ------------------- begin : March 30 2018 copyright : (C) 2004 by Marc Schellens, 2018 by G. Duvert email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // for all variants of MinMax(), to be included from datatypes.cpp // default: start = 0, stop = 0, step = 1, valIx = -1 if (stop == 0) stop = dd.size(); #ifdef _OPENMP #define MINMAX_THREAD_NUM omp_get_thread_num() #else #define MINMAX_THREAD_NUM 0 #endif //permits to treat the complex types by ading .Real() to (*this)[i] #ifdef MINMAX_IS_COMPLEX #define REAL_PART(x) (x).real() #define COMPLEX_ABS(x) std::abs((x)) #else #define REAL_PART(x) (x) #define COMPLEX_ABS(x) (x) #endif //permits to filter NaNs and Infs if the Type needs it AND if the context (omitNaN=true) needs it. #ifdef MINMAX_HAS_OMITNAN #define AVOID_INF if (omitNaN && !std::isfinite(COMPLEX_ABS((*this)[i]))) continue; #else #define AVOID_INF #endif SizeT nElem = (stop - start) / step; //trap existence of ABSFUNC and create something that stands cppchekck useage (needed by contiunous integration scripts!) #ifndef ABSFUNC #define FUNCABS useAbs=false; #else #define FUNCABS ABSFUNC #endif #ifdef MINMAX_HAS_OMITNAN if (omitNaN) //get first not-nan. Rest of processing will ignore nans since logical expressions must be true. { SizeT j = start; for (; j < stop; j += step) { if (std::isfinite(COMPLEX_ABS((*this)[j]))) break; } start = j; nElem = (stop - start) / step; if (nElem == 0) { if (minE != NULL) *minE = 0; if (maxE != NULL) *maxE = 0; if (minVal != NULL) { if (valIx == -1) *minVal = new Data_((*this)[j]); else (*static_cast (*minVal))[valIx] = (*this)[j]; } if (maxVal != NULL) { if (valIx == -1) *maxVal = new Data_((*this)[j]); else (*static_cast (*maxVal))[valIx] = (*this)[j]; } return; } } #endif if (minE == NULL && minVal == NULL) { DLong maxEl = start; Ty maxV = (*this)[maxEl]; if (nElem < CpuTPOOL_MIN_ELTS || nElem < CpuTPOOL_NTHREADS || CpuTPOOL_NTHREADS == 1) { if (!useAbs) { for (SizeT i = start+step ; i < stop; i += step) { AVOID_INF if (REAL_PART((*this)[i]) > REAL_PART(maxV)) maxV = (*this)[maxEl = i]; } } #ifdef ABSFUNC else { for (SizeT i = start+step; i < stop; i += step) { AVOID_INF if (FUNCABS((*this)[i]) > FUNCABS(maxV)) maxV = (*this)[maxEl = i]; } } #endif } else { Ty* maxVArray= new Ty[CpuTPOOL_NTHREADS]; SizeT maxElArray[CpuTPOOL_NTHREADS]; //precaution:initialize to something realistic: for (int i = 0; i < CpuTPOOL_NTHREADS; ++i) {maxVArray[i]=maxV;maxElArray[i]=maxEl;} SizeT chunksize = nElem / (CpuTPOOL_NTHREADS); if (!useAbs) { #pragma omp parallel { int thread_id = MINMAX_THREAD_NUM; SizeT start_index, stop_index; start_index = start + thread_id * chunksize*step; if (thread_id != (CpuTPOOL_NTHREADS - 1)) { stop_index = start_index + chunksize*step; } else { stop_index = stop; } SizeT local_pos = maxEl; Ty local_max = maxV; //maxV is a sure non-infinite value when omitNaN is in use. for (SizeT i = start_index; i < stop_index; i += step) { AVOID_INF if (REAL_PART((*this)[i]) > REAL_PART(local_max)) local_max = (*this)[local_pos = i]; } maxElArray[thread_id] = local_pos; maxVArray[thread_id] = local_max; } } #ifdef ABSFUNC else { #pragma omp parallel { int thread_id = MINMAX_THREAD_NUM; SizeT start_index, stop_index; start_index = start + thread_id * chunksize*step; if (thread_id != (CpuTPOOL_NTHREADS - 1)) { stop_index = start_index + chunksize*step; } else { stop_index = stop; } SizeT local_pos = maxEl; Ty local_max = maxV;//maxV is a sure non-infinite value when omitNaN is in use. for (SizeT i = start_index; i < stop_index; i += step) { AVOID_INF if (FUNCABS((*this)[i]) > FUNCABS(local_max)) local_max = (*this)[local_pos = i]; } maxElArray[thread_id] = local_pos; maxVArray[thread_id] = local_max; } } #endif maxV = maxVArray[0]; maxEl = maxElArray[0]; #ifdef ABSFUNC if (useAbs) { for (int i = 1; i < CpuTPOOL_NTHREADS; ++i) if (FUNCABS(maxVArray[i]) > FUNCABS(maxV)) { maxV = maxVArray[i]; maxEl = maxElArray[i]; } } else #endif { for (int i = 1; i < CpuTPOOL_NTHREADS; ++i) if (REAL_PART(maxVArray[i]) > REAL_PART(maxV)) { maxV = maxVArray[i]; maxEl = maxElArray[i]; } } } if (maxE != NULL) *maxE = maxEl; if (maxVal != NULL) { if (valIx == -1) *maxVal = new Data_(maxV); else (*static_cast (*maxVal))[valIx] = maxV; } return; } if (maxE == NULL && maxVal == NULL) { DLong minEl = start; Ty minV = (*this)[minEl]; if (nElem < CpuTPOOL_MIN_ELTS || nElem < CpuTPOOL_NTHREADS || CpuTPOOL_NTHREADS == 1) { if (!useAbs) { for (SizeT i = start+step; i < stop; i += step) { AVOID_INF if (REAL_PART((*this)[i]) < REAL_PART(minV)) minV = (*this)[minEl = i]; } } #ifdef ABSFUNC else { for (SizeT i = start+step; i < stop; i += step) { AVOID_INF if (FUNCABS((*this)[i]) < FUNCABS(minV)) minV = (*this)[minEl = i]; } } #endif } else { Ty* minVArray=new Ty[CpuTPOOL_NTHREADS]; SizeT minElArray[CpuTPOOL_NTHREADS]; //precaution:initialize to something realistic: for (int i = 0; i < CpuTPOOL_NTHREADS; ++i) {minVArray[i]=minV;minElArray[i]=minEl;} SizeT chunksize = nElem / (CpuTPOOL_NTHREADS); if (!useAbs) { #pragma omp parallel { int thread_id = MINMAX_THREAD_NUM; SizeT start_index, stop_index; start_index = start + thread_id * chunksize*step; if (thread_id != (CpuTPOOL_NTHREADS - 1)) { stop_index = start_index + chunksize*step; } else { stop_index = stop; } SizeT local_pos = minEl; Ty local_min = minV; // start with a sure non-infinite value, not (*this)[local_pos]; for (SizeT i = start_index; i < stop_index; i += step) { AVOID_INF if (REAL_PART((*this)[i]) < REAL_PART(local_min)) local_min = (*this)[local_pos = i]; } minElArray[thread_id] = local_pos; minVArray[thread_id] = local_min; } } #ifdef ABSFUNC else { #pragma omp parallel { int thread_id = MINMAX_THREAD_NUM; SizeT start_index, stop_index; start_index = start + thread_id * chunksize*step; if (thread_id != (CpuTPOOL_NTHREADS - 1)) { stop_index = start_index + chunksize*step; } else { stop_index = stop; } SizeT local_pos = minEl; Ty local_min = minV; for (SizeT i = start_index; i < stop_index; i += step) { AVOID_INF if (FUNCABS((*this)[i]) < FUNCABS(local_min)) local_min = (*this)[local_pos = i]; } minElArray[thread_id] = local_pos; minVArray[thread_id] = local_min; } } #endif minV = minVArray[0]; minEl = minElArray[0]; #ifdef ABSFUNC if (useAbs) { for (int i = 1; i < CpuTPOOL_NTHREADS; ++i) if (FUNCABS(minVArray[i]) < FUNCABS(minV)) { minV = minVArray[i]; minEl = minElArray[i]; } } else #endif { for (int i = 1; i < CpuTPOOL_NTHREADS; ++i) if (REAL_PART(minVArray[i]) < REAL_PART(minV)) { minV = minVArray[i]; minEl = minElArray[i]; } } } if (minE != NULL) *minE = minEl; if (minVal != NULL) { if (valIx == -1) *minVal = new Data_(minV); else (*static_cast (*minVal))[valIx] = minV; } return; } //note: a slightly faster minmax is done by pairs, not done here. DLong minEl = start; Ty minV = (*this)[minEl]; DLong maxEl = start; Ty maxV = (*this)[maxEl]; if (nElem < CpuTPOOL_MIN_ELTS || nElem < CpuTPOOL_NTHREADS || CpuTPOOL_NTHREADS == 1) { if (!useAbs) { for (SizeT i = start+step; i < stop; i += step) { AVOID_INF if (REAL_PART((*this)[i]) < REAL_PART(minV)) minV = (*this)[minEl = i]; if (REAL_PART((*this)[i]) > REAL_PART(maxV)) maxV = (*this)[maxEl = i]; } } #ifdef ABSFUNC else { for (SizeT i = start+step; i < stop; i += step) { AVOID_INF if (FUNCABS((*this)[i]) < FUNCABS(minV)) minV = (*this)[minEl = i]; if (FUNCABS((*this)[i]) > FUNCABS(maxV)) maxV = (*this)[maxEl = i]; } } #endif } else { Ty* maxVArray=new Ty[CpuTPOOL_NTHREADS]; SizeT maxElArray[CpuTPOOL_NTHREADS]; Ty* minVArray=new Ty[CpuTPOOL_NTHREADS]; SizeT minElArray[CpuTPOOL_NTHREADS]; //precaution:initialize to something realistic: for (int i = 0; i < CpuTPOOL_NTHREADS; ++i) {maxVArray[i]=maxV;maxElArray[i]=maxEl;} for (int i = 0; i < CpuTPOOL_NTHREADS; ++i) {minVArray[i]=minV;minElArray[i]=minEl;} SizeT chunksize = nElem / (CpuTPOOL_NTHREADS); if (!useAbs) { #pragma omp parallel { int thread_id = MINMAX_THREAD_NUM; SizeT start_index, stop_index; start_index = start + thread_id * chunksize*step; if (thread_id != (CpuTPOOL_NTHREADS - 1)) { stop_index = start_index + chunksize*step; } else { stop_index = stop; } SizeT local_pos_min = minEl; SizeT local_pos_max = maxEl; Ty local_min = minV; Ty local_max = maxV; for (SizeT i = start_index; i < stop_index; i += step) { AVOID_INF if (REAL_PART((*this)[i]) < REAL_PART(local_min)) local_min = (*this)[local_pos_min = i]; if (REAL_PART((*this)[i]) > REAL_PART(local_max)) local_max = (*this)[local_pos_max = i]; } minElArray[thread_id] = local_pos_min; minVArray[thread_id] = local_min; maxElArray[thread_id] = local_pos_max; maxVArray[thread_id] = local_max; } } #ifdef ABSFUNC else { #pragma omp parallel { int thread_id = MINMAX_THREAD_NUM; SizeT start_index, stop_index; start_index = start + thread_id * chunksize*step; if (thread_id != (CpuTPOOL_NTHREADS - 1)) { stop_index = start_index + chunksize*step; } else { stop_index = stop; } SizeT local_pos_min = minEl; SizeT local_pos_max = maxEl; Ty local_min = minV; Ty local_max = maxV; for (SizeT i = start_index; i < stop_index; i += step) { AVOID_INF if (FUNCABS((*this)[i]) < FUNCABS(local_min)) local_min = (*this)[local_pos_min = i]; if (FUNCABS((*this)[i]) > FUNCABS(local_max)) local_max = (*this)[local_pos_max = i]; } minElArray[thread_id] = local_pos_min; minVArray[thread_id] = local_min; maxElArray[thread_id] = local_pos_max; maxVArray[thread_id] = local_max; } } #endif minV = minVArray[0]; maxV = maxVArray[0]; minEl = minElArray[0]; maxEl = maxElArray[0]; #ifdef ABSFUNC if (useAbs) { for (int i = 1; i < CpuTPOOL_NTHREADS; ++i) { if (FUNCABS(minVArray[i]) < FUNCABS(minV)) { minV = minVArray[i]; minEl = minElArray[i]; } if (FUNCABS(maxVArray[i]) > FUNCABS(maxV)) { maxV = maxVArray[i]; maxEl = maxElArray[i]; } } } else #endif { for (int i = 1; i < CpuTPOOL_NTHREADS; ++i) { if (REAL_PART(minVArray[i]) < REAL_PART(minV)) { minV = minVArray[i]; minEl = minElArray[i]; } if (REAL_PART(maxVArray[i]) > REAL_PART(maxV)) { maxV = maxVArray[i]; maxEl = maxElArray[i]; } } } } if (maxE != NULL) *maxE = maxEl; if (maxVal != NULL) { if (valIx == -1) *maxVal = new Data_(maxV); else (*static_cast (*maxVal))[valIx] = maxV; } if (minE != NULL) *minE = minEl; if (minVal != NULL) { if (valIx == -1) *minVal = new Data_(minV); else (*static_cast (*minVal))[valIx] = minV; } #undef AVOID_INF #undef REAL_PART #undef COMPLEX_ABS #undef FUNCABS #undef MINMAX_THREAD_NUMgdl-0.9.9/src/mpi.cpp000066400000000000000000000123531340051421000143510ustar00rootroot00000000000000/*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //#include #include "includefirst.hpp" #include "envt.hpp" #include "mpi.hpp" #ifdef USE_MPI #include "mpi.h" namespace lib { using namespace std; BaseGDL* mpi_comm_rank_fun( EnvT* e) { SizeT nParam=e->NParam(); if(nParam != 0) throw GDLException( e->CallingNode(), "MPI_COMM_RANK: Incorrect number of arguments."); int rank; int err = MPI_Comm_rank(MPI_COMM_WORLD, &rank); return new DIntGDL( rank); } BaseGDL* mpi_comm_size_fun( EnvT* e) { SizeT nParam=e->NParam(); if(nParam != 0) throw GDLException( e->CallingNode(), "MPI_COMM_SIZE: Incorrect number of arguments."); int size; int err = MPI_Comm_size(MPI_COMM_WORLD, &size); return new DIntGDL( size); } void mpi_finalize_pro( EnvT* e) { SizeT nParam=e->NParam(); if(nParam != 0) throw GDLException( e->CallingNode(), "MPI_COMM_SIZE: Incorrect number of arguments."); int err = MPI_Finalize(); exit(0); } void mpi_send_pro( EnvT* e) { SizeT nParam=e->NParam(); if(nParam != 1) throw GDLException( e->CallingNode(), "MPI_SEND: Incorrect number of agruments."); DDoubleGDL* p0 = e->GetParAs( 0); int nElem = p0->N_Elements(); int tag = 0; static int tagIx = e->KeywordIx("TAG"); bool tagKW = e->KeywordSet( tagIx); if( tagKW){ DLong tagLong = 0; e->AssureLongScalarKW(tagIx, tagLong); tag = (int) tagLong; } int dest = 0; static int destIx = e->KeywordIx("DEST"); bool destKW = e->KeywordSet( destIx); if( destKW){ DLong destLong = 0; e->AssureLongScalarKW( destIx, destLong); dest = (int) destLong; } MPI_Datatype mpi_type = MPI_DOUBLE; //cout << "Before gdl send" << (*p0)[0] << " nelem="<< nElem << endl; MPI_Send( (*p0).DataAddr(), nElem, mpi_type, dest, tag, MPI_COMM_WORLD); //cout << "after gdl send" << endl; } BaseGDL* mpi_recv_fun( EnvT* e) { SizeT nParam=e->NParam(); if(nParam != 0) throw GDLException( e->CallingNode(), "MPI_RECV: Incorrect number of agruments."); int tag = 0; static int tagIx = e->KeywordIx("TAG"); bool tagKW = e->KeywordSet( tagIx); if( tagKW){ DLong tagLong = 0; e->AssureLongScalarKW(tagIx, tagLong); tag = (int) tagLong; } int source = 0; static int sourceIx = e->KeywordIx("SOURCE"); bool sourceKW = e->KeywordSet( sourceIx); if( sourceKW){ DLong sourceLong = 0; e->AssureLongScalarKW( sourceIx, sourceLong); source = (int) sourceLong; } int count = 0; static int countIx = e->KeywordIx("COUNT"); bool countKW = e->KeywordSet( countIx); if( countKW){ DLong countLong = 0; e->AssureLongScalarKW( countIx, countLong); count = (int) countLong; } MPI_Datatype mpi_type = MPI_DOUBLE; dimension dim(count); DDoubleGDL* result = new DDoubleGDL(dim); MPI_Status status; // MPI_Recv( &((*result)[0]), count, mpi_type, source, tag, MPI_COMM_WORLD, &status); MPI_Recv( (*result).DataAddr(), count, mpi_type, source, tag, MPI_COMM_WORLD, &status); return result; } BaseGDL* mpi_allreduce_fun( EnvT* e) { SizeT nParam=e->NParam(); if(nParam != 1) throw GDLException( e->CallingNode(), "MPI_ALLREDUCE: Incorrect number of agruments."); // get the send buffer DDoubleGDL* p0 = e->GetParAs( 0); int nElem = p0->N_Elements(); // determine the reduction operation // int mpi_op = 0; Patch by Takeshi 2016/08/03 MPI_Op mpi_op = 0; static int opSumIx = e->KeywordIx("SUM"); if( e->KeywordSet( opSumIx)) mpi_op = MPI_SUM; static int opProdIx = e->KeywordIx("PRODUCT"); if( e->KeywordSet( opProdIx)) { if( mpi_op != 0) throw GDLException( e->CallingNode(), "MPI_ALLREDUCE: Conflicing operators."); else mpi_op = MPI_PROD; } int count = 0; static int countIx = e->KeywordIx("COUNT"); bool countKW = e->KeywordSet( countIx); if( countKW){ DLong countLong = 0; e->AssureLongScalarKW( countIx, countLong); count = (int) countLong; } else count = nElem; MPI_Datatype mpi_type = MPI_DOUBLE; dimension dim(count); DDoubleGDL* result = new DDoubleGDL(dim); MPI_Status status; // MPI_Recv( &((*result)[0]), count, mpi_type, source, tag, MPI_COMM_WORLD, &status); MPI_Allreduce( (*p0).DataAddr(), (*result).DataAddr(), count, mpi_type, mpi_op, MPI_COMM_WORLD); return result; } } #endif gdl-0.9.9/src/mpi.hpp000066400000000000000000000006051340051421000143530ustar00rootroot00000000000000 //#include "datatypes.hpp" //#include "envt.hpp" #include namespace lib { void wait_pro( EnvT* e); BaseGDL* clock_fun( EnvT* e); void mpi_send_pro( EnvT* e); BaseGDL* mpi_recv_fun( EnvT* e); BaseGDL* mpi_allreduce_fun( EnvT* e); BaseGDL* mpi_comm_rank_fun( EnvT* e); BaseGDL* mpi_comm_size_fun( EnvT* e); void mpi_finalize_pro( EnvT* e); } // namespace gdl-0.9.9/src/ncdf4_group.cpp000066400000000000000000000167521340051421000160050ustar00rootroot00000000000000/*************************************************************************** ncdf4_group.cpp - NetCDF GDL library function ------------------- begin : January 8 2014 copyright : (C) 2014 by Alain Coulais email : purpose : this file contains some extensions provided by NetCDF-4, e.g. group ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 #endif #ifdef USE_NETCDF #include "includefirst.hpp" #include "datatypes.hpp" #include "envt.hpp" #include "ncdf_cl.hpp" #define GDL_DEBUG //#undef GDL_DEBUG #ifdef USE_NETCDF4 namespace lib { using namespace std; using namespace antlr; BaseGDL* ncdf_groupsinq(EnvT* e) { size_t nParam=e->NParam(1); DLong grpid; e->AssureLongScalarPar( 0, grpid); int status; int numgrps; int ncids[NC_MAX_VAR_DIMS]; status=nc_inq_grps(grpid, &numgrps, (int *) &ncids); ncdf_handle_error(e, status,"NCDF_GROUPSINQ"); int debug=0; if (debug) { cout << "NCDF_GROUPSINQ : " << status < 0) { dimension dim(numgrps); DLongGDL *res = new DLongGDL(dim,BaseGDL::NOZERO); for (size_t i=0; iNParam(2); DLong grpid; e->AssureLongScalarPar( 0, grpid); DString s; e->AssureScalarPar(1, s); int status; int new_grpid; status=nc_def_grp(grpid, s.c_str(), &new_grpid); ncdf_handle_error(e, status,"NCDF_GROUPDEF"); return new DLongGDL(new_grpid); } BaseGDL* ncdf_groupname(EnvT* e) { size_t nParam=e->NParam(1); DLong grpid; e->AssureLongScalarPar( 0, grpid); int status; char groupname[NC_MAX_NAME]; status=nc_inq_grpname(grpid, groupname); ncdf_handle_error(e, status,"NCDF_GROUPNAME"); return new DStringGDL(groupname); } BaseGDL* ncdf_fullgroupname(EnvT* e) { size_t nParam=e->NParam(1); DLong grpid; e->AssureLongScalarPar( 0, grpid); int status; char fullgroupname[NC_MAX_NAME]; size_t lenp; status=nc_inq_grpname_full(grpid, &lenp, fullgroupname); ncdf_handle_error(e, status,"NCDF_GROUPFULLNAME"); return new DStringGDL(fullgroupname); } BaseGDL* ncdf_groupparent(EnvT* e) { size_t nParam=e->NParam(1); DLong grpid; e->AssureLongScalarPar( 0, grpid); int status; int new_grpid; status=nc_inq_grp_parent(grpid, &new_grpid); ncdf_handle_error(e, status,"NCDF_GROUPPARENT"); return new DLongGDL(new_grpid); } BaseGDL* ncdf_dimidsinq(EnvT* e) { DLong grpid; e->AssureLongScalarPar( 0, grpid); int include_parents=0; if (e->KeywordSet(0)) {include_parents=1;} //"INCLUDE_PARENTS" int status; int ndims; int dimids[NC_MAX_VAR_DIMS]; status=nc_inq_dimids(grpid, &ndims, (int *) &dimids, include_parents); ncdf_handle_error(e, status,"NCDF_DIMIDSINQ"); dimension dim(ndims); DLongGDL *res = new DLongGDL(dim,BaseGDL::NOZERO); for (size_t i=0; iNParam(2); // in fact, we can use the "grpid" to check the file format it-self. DLong grpid; e->AssureLongScalarPar( 0, grpid); DString s; e->AssureScalarPar(1, s); // before going further we have to chech the file format, must be NetCDF-4 int status; int fileformat; status=nc_inq_format(grpid, &fileformat); ncdf_handle_error(e, status,"NCDF_NCIDINQ"); if (fileformat == NC_FORMAT_CLASSIC) Warning("NCDF_NCIDINQ: NetCDF 3 Classic format found. not OK"); if (fileformat == NC_FORMAT_64BIT) Warning("NCDF_NCIDINQ: NetCDF 3 64-BIT format found. not OK"); if ((fileformat == NC_FORMAT_64BIT) || (fileformat == NC_FORMAT_CLASSIC)) { return new DLongGDL(-1); } int sub_grpid; status=nc_inq_ncid(grpid, s.c_str(), &sub_grpid); if (status != 0) { if (status == -125) { Warning("NCDF_NCIDINQ: No group found. (NC_ERROR=-125)"); return new DLongGDL(-1); } else { ncdf_handle_error(e, status,"NCDF_NCIDINQ"); } } return new DLongGDL(sub_grpid); } BaseGDL* ncdf_varidsinq(EnvT* e) { //size_t nParam=e->NParam(1); DLong grpid; e->AssureLongScalarPar( 0, grpid); int status; int nvars, varids[NC_MAX_VAR_DIMS]; status=nc_inq_varids(grpid, &nvars, (int *) &varids); int debug=0; if (debug) { cout << "NCDF_VARIDSINQ: status : " << status << endl; cout << "NCDF_VARIDSINQ: nvars : " << nvars << endl; cout << "NCDF_VARIDSINQ: *varId : "; for (size_t i=0; i 0) { dimension dim(nvars); DLongGDL *res = new DLongGDL(dim,BaseGDL::NOZERO); for (size_t i=0; iAssureLongScalarPar( 0, grpid); // first of all, we check whether the Group ID is a good one int status; char groupname[NC_MAX_NAME]; status=nc_inq_grpname(grpid, groupname); ncdf_handle_error(e, status,"NCDF_GROUPNAME"); int nunlimdimsp, unlimdimidsp[NC_MAX_VAR_DIMS]; status=nc_inq_unlimdims(grpid, &nunlimdimsp, (int *) &unlimdimidsp); ncdf_handle_error(e, status,"NCDF_UNLIMDIMSINQ"); int debug=0; if (debug) { cout << "NCDF_UNLIMDIMSINQ: status : " << status << endl; cout << "NCDF_UNLIMDIMSINQ: nunlimdimsp : " << nunlimdimsp << endl; cout << "NCDF_UNLIMDIMSINQ: *unlimdimidsp : "; for (size_t i=0; iKeywordIx("COUNT"); if (e->KeywordPresent(countIx)) { int count=0; if (nunlimdimsp > 0) count=nunlimdimsp; e->SetKW(countIx, new DLongGDL(count)); } if (nunlimdimsp > 0) { dimension dim(nunlimdimsp); DLongGDL *res = new DLongGDL(dim,BaseGDL::NOZERO); for (size_t i=0; i #else // default: assume we have netCDF # define USE_NETCDF 1 #endif #ifdef USE_NETCDF # include "includefirst.hpp" # define HDF 1 # include # include "datatypes.hpp" # include "envt.hpp" //# include "dpro.hpp" //# include "dinterpreter.hpp" # include "ncdf_cl.hpp" //# define GDL_DEBUG # undef GDL_DEBUG namespace lib { using namespace std; using namespace antlr; template void ncdf_att_handle_error(EnvT *e, int status, const char *function,T* data) // {{{ { if (data != NULL and status != NC_NOERR) delete[] data; ncdf_handle_error(e, status, function); } // }}} BaseGDL* ncdf_attname(EnvT* e) // {{{ { size_t nParam=e->NParam(2); if (nParam ==3 && e->KeywordSet(0)) e->Throw("Specifying both GLOBAL keyword an variable id not allowed"); int status; char att_name[NC_MAX_NAME]; DLong cdfid, varid,attnum; varid=0; attnum=0; DString attname; e->AssureLongScalarPar(0, cdfid); if (e->KeywordSet(0)) { e->AssureLongScalarPar(1, attnum); varid = NC_GLOBAL; } else { // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_ATTNAME"); } e->AssureLongScalarPar(2, attnum); } //get the att_name variable. status=nc_inq_attname(cdfid, varid, attnum, att_name); if (status == NC_ENOTATT) { Warning("NCDF_ATTNAME: Attribute " + i2s(attnum) + " not found."); return new DStringGDL(""); } //handle the error ncdf_handle_error(e,status,"NCDF_ATTNAME"); return new DStringGDL(att_name); } // }}} BaseGDL* ncdf_attinq(EnvT* e) // {{{ { size_t nParam=e->NParam(2); if(nParam ==3 && e->KeywordSet(0)) { throw GDLException(e->CallingNode(), "NCDF_ATTINQ: The error is Global + varid, not allowed, proper text to come."); } else{ int status; nc_type att_type; size_t length; DString attname; DLong cdfid, varid; varid=0; e->AssureLongScalarPar(0, cdfid); if(e->KeywordSet(0)) { e->AssureStringScalarPar(1, attname); varid=NC_GLOBAL; } else { // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_ATTNAME"); } e->AssureStringScalarPar(2, attname); } //get the attinq data status=nc_inq_att(cdfid, varid, attname.c_str(), &att_type, &length); //handle the error ncdf_handle_error(e,status,"NCDF_ATTNAME"); // $ is necessary here (see dstructgdl.cpp) DStructDesc* ncdf_attinq=new DStructDesc("$truct"); SpDLong aLong; SpDString aString; ncdf_attinq->AddTag("DATATYPE", &aString); ncdf_attinq->AddTag("LENGTH", &aLong); // never for unnamed structs: //structList.push_back(ncdf_attinq); DStructGDL* inq=new DStructGDL(ncdf_attinq,dimension()); inq->InitTag("DATATYPE",ncdf_gdl_typename(att_type)); inq->InitTag("LENGTH", DLongGDL(length)); return inq; } } // }}} void ncdf_attget(EnvT* e) // {{{ { size_t nParam=e->NParam(2); if (nParam >3 && e->KeywordSet(0)) e->Throw("The error is Global + varid, not allowed, proper text to come."); int status; nc_type att_type; size_t length; DString attname; DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); if (e->KeywordSet(0)) { e->AssureStringScalarPar(1, attname); varid = NC_GLOBAL; } else { // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_ATTGET"); } e->AssureStringScalarPar(2, attname); } //attname, varid, cdfid are set up //get the attinq data status=nc_inq_att(cdfid, varid, attname.c_str(), &att_type, &length); //handle the error ncdf_handle_error(e,status,"NCDF_ATTGET"); if (att_type == NC_CHAR) { DByteGDL* temp = new DByteGDL(dimension(length)); status = nc_get_att_text(cdfid, varid, attname.c_str(), (char*)(&((*temp)[0]))); ncdf_handle_error(e, status, "NCDF_ATTGET"); delete e->GetParGlobal(nParam-1); e->GetParGlobal(nParam-1)=temp; } else { dimension dim(length); BaseGDL* temp; switch (att_type) { case NC_INT : { int *ip = new int[length]; status=nc_get_att_int(cdfid, varid, attname.c_str(), ip); ncdf_att_handle_error(e, status, "NCDF_ATTGET", ip); temp = length == 1 ? new DLongGDL(BaseGDL::NOZERO) : new DLongGDL(dim, BaseGDL::NOZERO); memcpy(&(*static_cast(temp))[0], &(*ip), length * sizeof(int)); delete[] ip; break; } case NC_SHORT : { short *sp = new short[length]; status = nc_get_att_short(cdfid, varid, attname.c_str(), sp); ncdf_att_handle_error(e, status, "NCDF_ATTGET", sp); temp = length == 1 ? new DIntGDL(BaseGDL::NOZERO) : new DIntGDL(dim, BaseGDL::NOZERO); memcpy(&(*static_cast(temp))[0], &(*sp), length * sizeof(DInt)); delete[] sp; break; } case NC_FLOAT : { float *fp = new float[length]; status=nc_get_att_float(cdfid, varid, attname.c_str(), fp); ncdf_att_handle_error(e,status,"NCDF_ATTGET",fp); temp = length == 1 ? new DFloatGDL(BaseGDL::NOZERO) : new DFloatGDL(dim, BaseGDL::NOZERO); memcpy(&(*static_cast(temp))[0], &(*fp), length * sizeof(DFloat)); delete[] fp; break; } case NC_DOUBLE : { double *dp = new double[length]; status = nc_get_att_double(cdfid, varid, attname.c_str(), dp); ncdf_att_handle_error(e, status, "NCDF_ATTGET", dp); temp = length == 1 ? new DDoubleGDL(BaseGDL::NOZERO) : new DDoubleGDL(dim, BaseGDL::NOZERO); memcpy(&(*static_cast(temp))[0], &(*dp), length * sizeof(DDouble)); delete[] dp; break; } case NC_BYTE : { unsigned char *bp = new unsigned char[length]; status = nc_get_att_uchar(cdfid, varid, attname.c_str(), bp); ncdf_att_handle_error(e, status, "NCDF_ATTGET", bp); temp = length == 1 ? new DByteGDL(BaseGDL::NOZERO) : new DByteGDL(dim, BaseGDL::NOZERO); memcpy(&(*static_cast(temp))[0], &(*bp), length * sizeof(DByte)); delete[] bp; break; } } GDLDelete(e->GetParGlobal(nParam - 1)); e->GetParGlobal(nParam - 1) = temp; } } // }}} void ncdf_attput(EnvT* e) // {{{ { size_t N_Params=e->NParam(3); int status, val_num; nc_type xtype; BaseGDL* at;//name DString attname; BaseGDL* val;//value; //get the cdfid, which must be given. DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); varid=0; if(e->KeywordSet(0)) { e->AssureStringScalarPar(1, attname); val=e->GetParDefined(2); val_num=2; varid=NC_GLOBAL; } else { // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_ATTPUT"); } e->AssureStringScalarPar(2, attname); val=e->GetParDefined(3); val_num=3; } //we have the cdfid, varid, attname, attval here //determine default data type xtype = NC_FLOAT; if (val->Type() == GDL_BYTE) xtype=NC_BYTE; if (val->Type() == GDL_STRING) xtype=NC_CHAR; if (val->Type() == GDL_INT) xtype=NC_SHORT; if (val->Type() == GDL_LONG) xtype=NC_INT; if (val->Type() == GDL_FLOAT) xtype=NC_FLOAT; if (val->Type() == GDL_DOUBLE) xtype=NC_DOUBLE; // SA: TODO: GDL_UINT, GDL_ULONG, GDL_COMPLEX, GDL_PTR... if(e->KeywordSet(2)) //GDL_BYTE xtype=NC_BYTE; else if(e->KeywordSet(3)) //CHAR xtype=NC_CHAR; else if(e->KeywordSet(4)) //GDL_DOUBLE xtype=NC_DOUBLE; else if(e->KeywordSet(5)) //GDL_FLOAT xtype=NC_FLOAT; else if(e->KeywordSet(6)) //GDL_LONG xtype=NC_INT; else if(e->KeywordSet(7)) //SHORT xtype=NC_SHORT; // LENGTH keyword support DLong length; if (val->Type() != GDL_STRING) { length = val->N_Elements(); e->AssureLongScalarKWIfPresent(1, length); if (length > val->N_Elements()) e->Throw("LENGTH keyword value (" + i2s(length) + ") exceedes the data length (" + i2s(val->N_Elements()) + ")"); } if(val->Type() == GDL_BYTE) { DByteGDL * bvar=static_cast(val); status=nc_put_att_uchar(cdfid,varid, attname.c_str(),xtype, (size_t)length, (const unsigned char *)&(*bvar)[0]); } else if(val->Type() == GDL_STRING) { DString cvar; e->AssureScalarPar(val_num,cvar); length = cvar.length(); e->AssureLongScalarKWIfPresent(1, length); if (length > cvar.length()) e->Throw("LENGTH keyword value (" + i2s(length) + ") exceedes the data length (" + i2s(cvar.length()) + ")"); if (length < cvar.length()) cvar.resize(length); status=nc_put_att_text(cdfid,varid, attname.c_str(), cvar.length(), (char *)cvar.c_str()); } else if(val->Type() == GDL_INT) { DIntGDL * ivar=static_cast(val); status=nc_put_att_short(cdfid,varid, attname.c_str(), xtype, (size_t)length, &(*ivar)[0]); } else if(val->Type() == GDL_LONG) { DLongGDL * lvar=static_cast(val); status=nc_put_att_int(cdfid,varid, attname.c_str(),xtype, (size_t)length, &(*lvar)[0]); } else if(val->Type() == GDL_FLOAT) { DFloatGDL * fvar=static_cast(val); status=nc_put_att_float(cdfid,varid, attname.c_str(),xtype, (size_t)length, &(*fvar)[0]); } else if(val->Type() == GDL_DOUBLE) { DDoubleGDL * dvar=static_cast(val); status=nc_put_att_double(cdfid,varid, attname.c_str(),xtype, (size_t)length, &(*dvar)[0]); } ncdf_handle_error(e, status,"NCDF_ATTPUT"); return; } // }}} BaseGDL* ncdf_attcopy(EnvT* e) // {{{ { size_t nParam=e->NParam(3); int status,add; //incdf DLong integer,incdf,outcdf,invar,outvar; e->AssureLongScalarPar(0, incdf); add=0; if(e->KeywordSet(0)) //in_global invar=NC_GLOBAL; if(e->KeywordSet(1)) //out_global outvar=NC_GLOBAL; if(e->KeywordSet(0) && e->KeywordSet(1) && nParam > 3) { throw GDLException(e->CallingNode(), "NCDF_ATTCOPY: Too many variables error 1"); } else if((e->KeywordSet(0) || e->KeywordSet(1)) && nParam > 4) { throw GDLException(e->CallingNode(), "NCDF_ATTCOPY: Too many variables error 2"); } else if(e->KeywordSet(0) && !e->KeywordSet(1) && nParam == 4) { e->AssureLongScalarPar(2, outcdf); // Check type of varid BaseGDL* p3 = e->GetParDefined( 3); if (p3->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(3, outvar); } else { // String DString var_name; e->AssureScalarPar(3, var_name); status=nc_inq_varid(outcdf, var_name.c_str(), &outvar); ncdf_handle_error(e,status,"NCDF_ATTCOPY"); } } else if(!e->KeywordSet(0) && e->KeywordSet(1) && nParam == 4) { // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, invar); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(incdf, var_name.c_str(), &invar); ncdf_handle_error(e,status,"NCDF_ATTCOPY"); } } else if(!e->KeywordSet(0) && !e->KeywordSet(1) && nParam == 5) { e->AssureLongScalarPar(3, outcdf); // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, invar); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(incdf, var_name.c_str(), &invar); ncdf_handle_error(e,status,"NCDF_ATTCOPY"); } // Check type of varid BaseGDL* p4 = e->GetParDefined( 4); if (p4->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(4, outvar); } else { // String DString var_name; e->AssureScalarPar(4, var_name); status=nc_inq_varid(outcdf, var_name.c_str(), &outvar); ncdf_handle_error(e,status,"NCDF_ATTCOPY"); } } //Here, //we have, incdf, invar, outvar DString name; if(!e->KeywordSet(0)) add=1; e->AssureStringScalarPar(1+add, name); //name //outcdf e->AssureLongScalarPar(2+add, outcdf); //All variables are done. status=nc_copy_att(incdf,invar, name.c_str(), outcdf,outvar); ncdf_handle_error(e, status,"NCDF_ATTCOPY"); if(status == NC_NOERR) return new DIntGDL(outvar); return new DIntGDL(-1); } // }}} void ncdf_attdel(EnvT* e) // {{{ { size_t nParam=e->NParam(2); int status; BaseGDL* at;//name DString attname; BaseGDL* val;//value; //get the cdfid, which must be given. DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); varid=0; if(e->KeywordSet(0) && nParam == 3) { throw GDLException(e->CallingNode(), "NCDF_ATTDEL: Too many variables error 1"); } else if(!e->KeywordSet(0) && nParam == 2) { throw GDLException(e->CallingNode(), "NCDF_ATTDEL: Not enough variables error 2"); } else if(e->KeywordSet(0)) //global { e->AssureStringScalarPar(1, attname); varid=NC_GLOBAL; } else { BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_ATTNAME"); } e->AssureStringScalarPar(2, attname); } //we have the cdfid, varid, attname status=nc_del_att(cdfid,varid,attname.c_str()); ncdf_handle_error(e, status,"NCDF_ATTDEL"); return; } // }}} void ncdf_attrename(EnvT* e) // {{{ { size_t nParam=e->NParam(3); int status; BaseGDL* at;//name DString attname; DString newname; BaseGDL* val;//value; //get the cdfid, which must be given. DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); varid=0; if(e->KeywordSet(0) && nParam == 4) { throw GDLException(e->CallingNode(), "NCDF_ATTRENAME: Too many variables error 1"); } else if(!e->KeywordSet(0) && nParam == 3) { throw GDLException(e->CallingNode(), "NCDF_ATTRENAME: Not enough variables error 2"); } else if(e->KeywordSet(0)) //global { e->AssureStringScalarPar(1, attname); e->AssureStringScalarPar(2, newname); varid=NC_GLOBAL; } else { // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_ATTNAME"); } e->AssureStringScalarPar(2, attname); e->AssureStringScalarPar(3, newname); } //we have the cdfid, varid, attname,newname status=nc_rename_att(cdfid,varid, attname.c_str(), newname.c_str()); ncdf_handle_error(e, status,"NCDF_ATTRENAME"); return; } // }}} } #endif gdl-0.9.9/src/ncdf_cl.cpp000066400000000000000000000324541340051421000151600ustar00rootroot00000000000000/*************************************************************************** ncdf_cl.cpp - NetCDF GDL library function ------------------- begin : March 24 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 #endif #ifdef USE_NETCDF #include "includefirst.hpp" #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" #include "ncdf_cl.hpp" #define GDL_DEBUG //#undef GDL_DEBUG namespace lib { using namespace std; using namespace antlr; bool ncdf_verbose=true; DStringGDL ncdf_gdl_typename(nc_type vartype) { switch (vartype) { case NC_BYTE: return DStringGDL("BYTE");//8 bit case NC_CHAR: return DStringGDL("CHAR");//8 bit as string case NC_SHORT: return DStringGDL("INT");//16 bit case NC_INT: return DStringGDL("LONG");//32 bit case NC_FLOAT: return DStringGDL("FLOAT");//32 bit float case NC_DOUBLE:return DStringGDL("DOUBLE");//64 bit double } return DStringGDL("UNKNOWN"); } void ncdf_handle_error(EnvT *e, int status, const char *function) { // function is no more used ... can we used it for extra informational purpose ?? // cout << function << endl; if(status != NC_NOERR) { string error; //error=function; //error+=": "; DString s; if(status==NC_EBADID) /* Not a netcdf id */ { DLong id; e->AssureLongScalarPar( 0, id); error += i2s(id); error += " is not a valid cdfid. "; error+="(NC_ERROR=-33)"; } else if(status==NC_ENFILE) /* Too many netcdfs open */ { error+="Too many NetCDF files open. (NC_ERROR=-34)"; } else if(status==NC_EEXIST) /* netcdf file exists && NC_NOCLOBBER */ { e->AssureScalarPar(0, s); error+="Unable to create the file \"" + s + "\". "; error+="(NC_ERROR=-35)"; } else if(status==NC_EINVAL) /* Invalid Argument */ { error+="(NC_ERROR=-36)"; } else if(status==NC_EPERM) /* Write to read only */ { error+="Write permission not enabled. "; error+="(NC_ERROR=-37)"; } else if(status==NC_ENOTINDEFINE) /* Operation not allowed in data mode */ { error+=" Unable to define variable, not in define mode. "; error+="(NC_ERROR=-38)"; } else if(status== NC_EINDEFINE) /* Operation not allowed in define mode */ { error+=" Cannot acces data in DEFINE mode. "; error+="(NC_ERROR=-39)"; } else if(status==NC_EINVALCOORDS) /* Index exceeds dimension bound */ { //this error should never be triggered error+="GDL INTERNAL ERROR, PLEASE REPORT TO CODE MAINTAINER "; error+="(NC_ERROR=-40)"; } else if(status==NC_EMAXDIMS) /* NC_MAX_DIMS exceeded */ { error+="Unable to define variable, maximum number of attributes exceeded. "; error+="(NC_ERROR=-41)"; } else if(status==NC_ENAMEINUSE) /* String match to name in use */ { error+="(NC_ERROR=-42)"; } else if(status==NC_ENOTATT) /* Attribute not found */ { error+="Attribute enquiry failed. "; error+="(NC_ERROR=-43)"; } else if(status==NC_EMAXATTS) /* NC_MAX_ATTRS exceeded */ { error+="Attribute write failed, maximum number of attributes exceeded. "; error+="(NC_ERROR=-44)"; } else if(status==NC_EBADTYPE) /* Not a netcdf data type */ { error+="(NC_ERROR=-45)"; } else if(status==NC_EBADDIM) /* Invalid dimension id or name */ { size_t nParam=e->NParam(); if(nParam >= 3) { BaseGDL* v=e->GetParDefined(2); DIntGDL* dim_in=static_cast(v->Convert2(GDL_INT, BaseGDL::COPY)); Guard dim_in_guard( dim_in); int var_ndims=dim_in->N_Elements(); if(var_ndims > NC_MAX_VAR_DIMS) e->Throw("NCDF internal error in error handler (too many dimension IDs)."); error += "No Dimension with ID = "; for (int i=0; iAssureLongScalarPar( 0, id); error += "Invalid dimension or name. ID = "; error += i2s(id) + " "; } error+="(NC_ERROR=-46)"; } else if(status==NC_EUNLIMPOS) /* NC_UNLIMITED in the wrong index */ { error+="(NC_ERROR=-47)"; } else if(status==NC_EMAXVARS) /* NC_MAX_VARS exceeded */ { error+="Unable to define variable, maximum number of attributes exceeded. "; error+="(NC_ERROR=-48)"; } else if(status==NC_ENOTVAR) /* Variable not found */ { error += "Variable enquiry failed, "; if (e->GetPar(1)->Type() == GDL_STRING) { DString id; e->AssureStringScalarPar( 1, id); error += "\"" + id + "\""; } else { DLong id; e->AssureLongScalarPar( 1, id); error += i2s(id); } error += " is not a valid variable id. "; error += "(NC_ERROR=-49)"; } else if(status==NC_EGLOBAL) /* Action prohibited on NC_GLOBAL varid */ { error+="(NC_ERROR=-50)"; } else if(status==NC_ENOTNC) /* Not a netcdf file */ { e->AssureScalarPar(0, s); error+="Unable to open the file \""+s+ "\". "; error+="(NC_ERROR=-51)"; } else if(status==NC_ESTS) /* In Fortran, string too short */ { error+="(NC_ERROR=-52)"; } else if(status==NC_EMAXNAME) /* NC_MAX_NAME exceeded */ { error+="(NC_ERROR=-53)"; } else if(status==NC_EUNLIMIT) /* NC_UNLIMITED size already in use */ { error+="Unable to create dimension, NC_UNLIMITED dimension alread in use. "; error+="(NC_ERROR=-54)"; } else if(status==NC_ENORECVARS) /* nc_rec op when there are no record vars */ { error+="(NC_ERROR=-55)"; } else if(status==NC_ECHAR) /* Attempt to convert between text & numbers */ { error+="(NC_ERROR=-56)"; } else if(status==NC_EEDGE) /* Edge+start exceeds dimension bound */ { error+="Dimension bound exceeded. "; error+="(NC_ERROR=-57)"; } else if(status==NC_ESTRIDE) /* Illegal stride */ { error+="(NC_ERROR=-58)"; } else if(status==NC_EBADNAME) /* Attribute or variable name contains illegal characters */ { error+="(NC_ERROR=-59)"; } else if(status==NC_ERANGE) /* Math result not representable */ { error+="(NC_ERROR=-60)"; } else if(status==NC_ENOMEM) /* Memory allocation (malloc) failure */ { error+="(NC_ERROR=-61)"; } else if(status==2) { e->AssureScalarPar(0, s); error+="Unable to open the file \""+s+ "\". (NC_ERROR = 2)"; } else { /*unknown error*/ error+=nc_strerror(status); error+=" (NC_ERROR="+i2s(status)+")"; } e->Throw(error); } } // a way to test status of local file bool is_readable( const std::string & file ) { std::ifstream fichier( file.c_str() ); return !fichier.fail(); } //open the ncdf file of given filename OR an URL+filename BaseGDL * ncdf_open(EnvT * e) { size_t nParam=e->NParam(1); if(nParam != 1) e->Throw("Wrong number of arguments."); DString s; e->AssureScalarPar(0, s); WordExp(s); int cdfid,status; if(e->KeywordSet(0) //"WRITE" &&!e->KeywordSet(1)) //NOWRITE { status=nc_open(s.c_str(), NC_WRITE, &cdfid); } else { status=nc_open(s.c_str(), NC_NOWRITE, &cdfid); } bool debug=FALSE; if (debug) { cout << "NCDF_OPEN: filename (or url) : " << s << endl; cout << "NCDF_OPEN: status : " << status << endl; } // we try to add few extra informations to help to understand why the // file or link was not opened if (status != 0) { if ((status == -31) | (status == 2)) { // before any NetCDF stuff, we check whether the file exists ... if (!is_readable(s)) { Warning("NCDF_OPEN: file not found or not readable"); e->Throw("Unable to open the file \""+s+"\". (NC_ERROR="+i2s(status)+")"); } } if (status == -51) { Warning("NCDF_OPEN: file exists but not in NetCDF format(s)"); #ifndef USE_NETCDF4 Warning("NCDF_OPEN: GDL was compiled without support to new NetCDF-4 format(s)"); #endif e->Throw("Unable to open the file \""+s+"\". (NC_ERROR=-51)"); } ncdf_handle_error(e,status,"NCDF_OPEN"); } return new DLongGDL(cdfid); } //close the NetCDF file void ncdf_close(EnvT* e) { size_t nParam=e->NParam(1); DLong cdfid; e->AssureLongScalarPar( 0, cdfid); int status = nc_close(cdfid); ncdf_handle_error(e, status, "NCDF_CLOSE"); } //ncdf inquire, returns the struct {NDIMS: 0L,NVARS:0L,NGATTS:0L, RECDIM:0L} BaseGDL* ncdf_inquire(EnvT* e) { size_t nParam=e->NParam(1); int status, ndims,nvars,ngatts,unlimdimid; DLong cdfid; e->AssureLongScalarPar( 0, cdfid); status = nc_inq(cdfid, &ndims, &nvars, &ngatts, &unlimdimid); ncdf_handle_error(e,status,"NCDF_INQUIRE"); DStructDesc* ncdf_inq=new DStructDesc( "NCDF_INQ"); SpDLong aLong; ncdf_inq->AddTag("NDIMS", &aLong); ncdf_inq->AddTag("NVARS", &aLong); ncdf_inq->AddTag("NGATTS", &aLong); ncdf_inq->AddTag("RECDIM", &aLong); structList.push_back(ncdf_inq); DStructGDL* inq=new DStructGDL( "NCDF_INQ"); inq->InitTag("NDIMS",DLongGDL(ndims)); inq->InitTag("NVARS",DLongGDL(nvars)); inq->InitTag("NGATTS",DLongGDL(ngatts)); inq->InitTag("RECDIM",DLongGDL(unlimdimid)); return inq; } //Create the ncdf file of given filename BaseGDL * ncdf_create(EnvT * e) { size_t nParam=e->NParam(1); DString s; e->AssureScalarPar(0, s); int format; format = NC_FORMAT_CLASSIC; enum { CLOBBER, NOCLOBBER,NETCDF3_64BIT,NETCDF4_FORMAT }; if (e->KeywordSet(NETCDF3_64BIT)) { Warning("keyword NETCDF3_64BIT not ready."); format= NC_FORMAT_64BIT; } if (e->KeywordSet(NETCDF4_FORMAT)) { #ifndef USE_NETCDF4 e->Throw("GDL was compiled without support to new NetCDF-4 format(s)"); #endif Warning("keyword NETCDF4_FORMAT experimental."); format=NC_FORMAT_NETCDF4; } int cdfid,status; status=nc_set_default_format(format, NULL); if(e->KeywordSet(CLOBBER) &&!e->KeywordSet(NOCLOBBER)) { status=nc_create(s.c_str(), NC_CLOBBER, &cdfid); } else { status=nc_create(s.c_str(), NC_NOCLOBBER, &cdfid); if (status == -35) { Warning("NCDF_CREATE: the file already exists, use /CLOBBER to (try to) overwrite !"); } } ncdf_handle_error(e,status,"NCDF_CREATE"); return new DLongGDL(cdfid); } void ncdf_control(EnvT* e) { /*keywords 0 ABORT = restores or deletes file 1 ENDEF = ends define mode, starts data mode 2 FILL = fills the netcdf file with certain values 3 NOFILL = opposite of FILL 4 VERBOSE = verbose error messages, hmm 5 NOVERBOSE = opposite of verbose 6 OLDFILL=variable ->result of last fill 7 REDEF = puts file into define mode 8 SYNC = update the file on disk */ size_t nParam=e->NParam(1); int status,omode; DLong cdfid; e->AssureLongScalarPar( 0, cdfid); int total=e->KeywordSet(0)+ e->KeywordSet(1)+ e->KeywordSet(2)+ e->KeywordSet(3)+ e->KeywordSet(4)+ e->KeywordSet(5)+ e->KeywordSet(7)+ e->KeywordSet(8); if (total == 0) return; if (total != 1) e->Throw("Only one control may be selected per call."); status=NC_NOERR; if(e->KeywordSet(0))//ABORT status=nc_abort(cdfid); else if(e->KeywordSet(1))//ENDEF status=nc_enddef(cdfid); else if(e->KeywordSet(2))//FILL status=nc_set_fill(cdfid,NC_FILL,&omode); else if(e->KeywordSet(3))//NOFILL status=nc_set_fill(cdfid,NC_NOFILL,&omode); else if(e->KeywordSet(4))//VERBOSE ncdf_verbose=true; else if(e->KeywordSet(5))//NOVERBOSE ncdf_verbose=false; else if(e->KeywordSet(7))//REDEF status=nc_redef(cdfid); else if(e->KeywordSet(8))//SYNC status=nc_sync(cdfid); if(e->KeywordSet(7) && status==NC_EPERM) throw GDLException(e->CallingNode(),"NCDF_CONTROL: Attempt to reenter define mode (REDEF) failed, no write permission to the file."); else ncdf_handle_error(e, status, "NCDF_CONTROL"); if((e->KeywordSet(2) || e->KeywordSet(3)) &&e->KeywordPresent(6)) { e->AssureGlobalKW(6); GDLDelete(e->GetKW(6)); e->GetKW(6)=new DLongGDL(omode); } } } #endif gdl-0.9.9/src/ncdf_cl.hpp000066400000000000000000000064371340051421000151670ustar00rootroot00000000000000/*************************************************************************** ncdf_cl.hpp - NetCDF GDL library functions ------------------- begin : March 14 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef NCDF_HPP_CL_ #define NCDF_HPP_CL_ #include #include namespace lib { using namespace std; using namespace antlr; void ncdf_handle_error(EnvT* e, int status, const char * function); template void ncdf_handle_error(EnvT* e, int status, const char * function, T* data); DStringGDL ncdf_gdl_typename(nc_type type); void negzero_message(const char * name, int index, int set); void exceed_message(const char * name, int index, int set); string _ncdf_itos(int i); BaseGDL* ncdf_open(EnvT* e);/*IDL seems to segfault after ~40 files,GDL does 1024 with no segfault :)*/ BaseGDL* ncdf_create(EnvT* e); void ncdf_close(EnvT* e); BaseGDL* ncdf_inquire(EnvT* e); void ncdf_control(EnvT* e); //------------------ //----------------- dim relative func/pro void ncdf_diminq(EnvT* e); void ncdf_dimrename(EnvT* e); BaseGDL* ncdf_dimid(EnvT* e); BaseGDL* ncdf_dimdef(EnvT* e); //--------------------------- //----------------- variable relative func/pro void ncdf_varget1(EnvT* e); void ncdf_varget(EnvT* e); void ncdf_varrename(EnvT* e); void ncdf_varput(EnvT* e); BaseGDL* ncdf_varinq(EnvT* e); BaseGDL* ncdf_varid(EnvT* e); BaseGDL* ncdf_vardef(EnvT* e); template void ncdf_var_handle_error(EnvT *e, int status, const char *function, T* data); //----------------- attribute relative func/pro void ncdf_attput(EnvT* e); void ncdf_attget(EnvT* e); void ncdf_attdel(EnvT* e); void ncdf_attrename(EnvT* e); BaseGDL* ncdf_attinq(EnvT* e); BaseGDL* ncdf_attname(EnvT* e); BaseGDL* ncdf_attcopy(EnvT* e); template void ncdf_att_handle_error(EnvT *e, int status, const char *function, T* data); // --- groups were introduced in netcdf4 BaseGDL* ncdf_groupsinq(EnvT* e); BaseGDL* ncdf_groupname(EnvT* e); BaseGDL* ncdf_groupdef(EnvT* e); BaseGDL* ncdf_fullgroupname(EnvT* e); BaseGDL* ncdf_groupparent(EnvT* e); BaseGDL* ncdf_dimidsinq(EnvT* e); BaseGDL* ncdf_ncidinq(EnvT* e); BaseGDL* ncdf_varidsinq(EnvT* e); BaseGDL* ncdf_unlimdimsinq(EnvT* e); template void ncdf_grp_handle_error(EnvT *e, int status, const char *function, T* data); } // namespace #endif gdl-0.9.9/src/ncdf_dim_cl.cpp000066400000000000000000000127031340051421000160040ustar00rootroot00000000000000/*************************************************************************** ncdf_cl.cpp - NetCDF GDL library function ------------------- begin : March 24 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 #endif #ifdef USE_NETCDF #include "includefirst.hpp" #include #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" #include "ncdf_cl.hpp" #include "terminfo.hpp" #include "typedefs.hpp" #define MAX_DATE_STRING_LENGTH 80 #define GDL_DEBUG //#undef GDL_DEBUG namespace lib { using namespace std; using namespace antlr; void ncdf_diminq(EnvT* e) { size_t nParam=e->NParam(4); int status; size_t dim_size; char dim_name[NC_MAX_NAME]; DLong cdfid, dimid; e->AssureLongScalarPar(0, cdfid); BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, dimid); } else { // String DString dim_name; e->AssureScalarPar(1, dim_name); status=nc_inq_dimid(cdfid, dim_name.c_str(), &dimid); ncdf_handle_error(e, status, "NCDF_DIMRENAME"); } //call the ncdf library status=nc_inq_dim(cdfid, dimid,dim_name,&dim_size); //handle the error ncdf_handle_error(e,status,"NCDF_DIMINQ"); //fill in the return variables //name GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=new DStringGDL(dim_name); //size GDLDelete(e->GetParGlobal(3)); e->GetParGlobal(3)=new DLongGDL(dim_size); return; } BaseGDL* ncdf_dimid(EnvT* e) { size_t nParam=e->NParam(2); int status, dim_id; DLong cdfid; DString dim_name; e->AssureLongScalarPar(0, cdfid); e->AssureStringScalarPar(1,dim_name); status=nc_inq_dimid(cdfid, dim_name.c_str(),&dim_id); ncdf_handle_error(e,status,"NCDF_DIMID"); return new DLongGDL(dim_id); } BaseGDL* ncdf_dimdef(EnvT* e) { size_t nParam=e->NParam(2); int status, dim_id; DString in_string; DLong cdfid; e->AssureLongScalarPar(0, cdfid); DString dim_name; e->AssureStringScalarPar(1,dim_name); if(nParam == 3 && e->KeywordSet(0)) e->Throw("Dimension cannot have a specific size and UNLIMITED size."); else if (nParam == 2 && !e->KeywordSet(0)) e->Throw("No dimension size specified."); else if(nParam == 2 && e->KeywordSet(0)) //unlimited { //umlimited is set status=nc_def_dim(cdfid, dim_name.c_str(), NC_UNLIMITED, &dim_id); ncdf_handle_error(e,status,"NCDF_DIMDEF"); } else if(nParam == 3 && !e->KeywordSet(0)) { BaseGDL* s=e->GetParDefined(2); size_t ds; if(s->Type() == GDL_LONG) { DLong lvar; e->AssureScalarPar(2, lvar); ds=static_cast(lvar); } else if(s->Type() == GDL_INT) { DInt ivar; e->AssureScalarPar(2, ivar); ds=static_cast(ivar); } else if(s->Type() == GDL_FLOAT) { DFloat fvar; e->AssureScalarPar(2, fvar); ds=static_cast(fvar); } else if(s->Type() == GDL_DOUBLE) { DDouble dvar; e->AssureScalarPar(2, dvar); ds=static_cast(dvar); } else if(s->Type() == GDL_BYTE) { DByte bvar; e->AssureScalarPar(2, bvar); ds=static_cast(bvar); } else if(s->Type() == GDL_STRING) { DLongGDL* lsvar; DString sv; e->AssureScalarPar(2, sv); lsvar=static_cast(s->Convert2(GDL_LONG,BaseGDL::COPY)); ds=static_cast((*lsvar)[0]); } status=nc_def_dim(cdfid, dim_name.c_str(), ds, &dim_id); ncdf_handle_error(e,status,"NCDF_DIMDEF"); } return new DLongGDL(dim_id); } void ncdf_dimrename(EnvT* e) { size_t nParam=e->NParam(3); int status; //get the cdfid, which must be given. DString newname; DLong cdfid, dimid; e->AssureLongScalarPar(0, cdfid); BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, dimid); } else { // String DString dim_name; e->AssureScalarPar(1, dim_name); status=nc_inq_dimid(cdfid, dim_name.c_str(),&dimid); ncdf_handle_error(e,status,"NCDF_DIMRENAME"); } e->AssureStringScalarPar(2, newname); //we have the cdfid, dimid, newname status=nc_rename_dim(cdfid,dimid, newname.c_str()); ncdf_handle_error(e, status,"NCDF_DIMRENAME"); return; } } #endif gdl-0.9.9/src/ncdf_var_cl.cpp000066400000000000000000000734411340051421000160310ustar00rootroot00000000000000/*************************************************************************** ncdf_cl.cpp - NetCDF GDL library function ------------------- begin : March 24 2004 copyright : (C) 2004 by Christopher Lee email : leec_gdl@publius.co.uk ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #else // default: assume we have netCDF #define USE_NETCDF 1 #endif #ifdef USE_NETCDF #include "includefirst.hpp" #include #include #include #include #include #include "datatypes.hpp" #include "envt.hpp" #include "dpro.hpp" #include "dinterpreter.hpp" #include "ncdf_cl.hpp" //#include "terminfo.hpp" //#include "typedefs.hpp" #define GDL_DEBUG //#undef GDL_DEBUG namespace lib { using namespace std; using namespace antlr; extern bool ncdf_verbose; void exceed_message(const char * name,int index, int set) { string mess; mess=name; mess+="Limit exceeded on index "+i2s(index); mess+=", setting to "+i2s(set)+"."; Message(mess); } void negzero_message(const char * name,int index, int set) { int mema=3; string mess; mess=name; mess+="Value of index "+i2s(index); if(set > 0) mess+=" is negative or zero, setting to "; else if(set == 0) mess+=" is negative , setting to "; else mess+=" INTERNAL ERROR NCDF_VAR_CL.CPP negzero_message"; mess+=i2s(set); mess+="."; Message(mess); } template void ncdf_var_handle_error(EnvT *e, int status, const char *function, T *data) { // cout << function << endl; if (data != NULL and status != NC_NOERR) GDLDelete(data); ncdf_handle_error(e, status, function); } BaseGDL* ncdf_varinq(EnvT* e) { size_t nParam=e->NParam(2); int status,var_ndims,var_dims[NC_MAX_VAR_DIMS],var_natts; nc_type var_type; char var_name[NC_MAX_NAME]; BaseGDL* n; DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_VARINQ"); } //call the ncdf library status=nc_inq_var(cdfid,varid,var_name,&var_type,&var_ndims, var_dims,&var_natts); //handle the error ncdf_handle_error(e,status,"NCDF_VARINQ"); //build the structure template DStructDesc* ncdf_varinq=new DStructDesc("$truct"); SpDLong aLong; SpDString aString; SpDLong aLongArr(dimension(var_ndims == 0 ? 1 : var_ndims)); ncdf_varinq->AddTag("NAME", &aString); ncdf_varinq->AddTag("DATATYPE", &aString); ncdf_varinq->AddTag("NDIMS", &aLong); ncdf_varinq->AddTag("NATTS", &aLong); if (var_ndims == 0) ncdf_varinq->AddTag("DIM", &aLong); else ncdf_varinq->AddTag("DIM", &aLongArr); //fill the structure DStructGDL* inq=new DStructGDL(ncdf_varinq, dimension()); inq->InitTag("NAME",DStringGDL(var_name)); DLongGDL* dims_res; if (var_ndims == 0) dims_res = new DLongGDL(0); else { dims_res = new DLongGDL(dimension(var_ndims)); for( size_t i=0; iInitTag("DATATYPE",ncdf_gdl_typename(var_type)); inq->InitTag("NDIMS",DLongGDL(var_ndims)); inq->InitTag("NATTS",DLongGDL(var_natts)); inq->InitTag("DIM",*dims_res); return inq; } BaseGDL* ncdf_varid(EnvT* e) { size_t nParam=e->NParam(2); int status, var_id; DLong cdfid; e->AssureLongScalarPar(0, cdfid); DString dim_name; e->AssureScalarPar(1, dim_name); status=nc_inq_varid(cdfid, dim_name.c_str(),&var_id); if (status == NC_ENOTVAR) { Warning("NCDF_VARID: Variable not found \"" + dim_name + "\""); return new DLongGDL(-1); } ncdf_handle_error(e,status,"NCDF_VARID"); return new DLongGDL(var_id); } void ncdf_varget1(EnvT* e) { size_t nParam=e->NParam(3); int status,var_ndims,var_dims[NC_MAX_VAR_DIMS],var_natts; size_t index[NC_MAX_VAR_DIMS]; size_t reverse_index[NC_MAX_VAR_DIMS]; size_t dim_length[NC_MAX_VAR_DIMS]; nc_type var_type; char var_name[NC_MAX_NAME], *n; size_t i,mema; DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_VARGET1"); } //inquire status=nc_inq_var(cdfid,varid,var_name, &var_type,&var_ndims, var_dims,&var_natts); //handle the error ncdf_handle_error(e,status,"NCDF_VARGET1"); //get the dimension lengths for (i=0;iGetKW(0)!=NULL)//OFFSET { DLongGDL *o=e->GetKWAs(0); int nEl=o->N_Elements(); for (i=0;iGetParGlobal(2)); e->GetParGlobal(2)=new DDoubleGDL(dvar); } else if(var_type == NC_FLOAT){ float fvar; status=nc_get_var1_float(cdfid, varid, index, &fvar); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=new DFloatGDL(fvar); } /* This shouldn't get called? else if(var_type == NC_LONG) { long lvar; status=nc_get_var1_long(cdfid, varid, index, &lvar); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = new DLongGDL((lvar)); }*/ else if(var_type == NC_INT) { int ivar; status=nc_get_var1_int(cdfid, varid, index, &ivar); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = new DLongGDL((ivar)); } else if(var_type == NC_SHORT) { short svar; status=nc_get_var1_short(cdfid, varid, index, &svar); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = new DIntGDL((svar)); } else if(var_type == NC_CHAR) { char cvar; status=nc_get_var1_text(cdfid, varid, index, &cvar); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = new DByteGDL(cvar); } else if(var_type == NC_BYTE){ unsigned char bvar; status=nc_get_var1_uchar(cdfid, varid, index, &bvar); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = new DByteGDL((bvar)); } ncdf_handle_error(e,status,"NCDF_VARGET1"); } void ncdf_varget(EnvT* e) { size_t nParam=e->NParam(3); int status,var_ndims,var_dims[NC_MAX_VAR_DIMS],var_natts; size_t index[NC_MAX_VAR_DIMS], dim_length[NC_MAX_VAR_DIMS]; DLong transposed_dim_length[NC_MAX_VAR_DIMS]; long trans[NC_MAX_VAR_DIMS]; nc_type var_type; char var_name[NC_MAX_NAME]; DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_VARGET"); } //inquire status = nc_inq_var(cdfid, varid, var_name, &var_type, &var_ndims, var_dims, &var_natts); ncdf_handle_error(e, status, "NCDF_VARGET"); //get the dimension lengths if (var_ndims == 0) trans[0] = 0; else for (int i=0; i < var_ndims; ++i) { status = nc_inq_dimlen(cdfid,var_dims[i],&dim_length[i]); trans[i] = var_ndims - i - 1; transposed_dim_length[trans[i]] = dim_length[i]; ncdf_handle_error(e, status, "NCDF_VARGET"); } for (int i = 0; i < var_ndims; ++i) index[i]=0;//defaults /*Here we have the minimum required details for getting any kind of data We now have 4 cases to handle case 1: Get all the data (no keywords) case 2: Get all the data from the OFFSET case 3: get COUNT data from the OFFSET case 4: get COUNT DATA from OFFSET with STRIDE for case 4, we really have 3 subcases subcase 1: OFFSET is undefined (0,0,0,0..) subcase 2: COUNT is undefined (all,all,all...) subcase 3: All keywords are DEFINED subcase 4(==case 3): STRIDE is undefined (1,1,1,1)... case 1 we can do seperately, the rest can be handled generically, filling in COUNT, OFFSET and STRIDE as needed. */ //OFFSET = 0 //COUNT = 1 //STRIDE = 2 if (e->GetKW(0) == NULL && e->GetKW(1) == NULL && e->GetKW(2) == NULL) { //get all the data size_t array_size = 1; for (int i = 0; i < var_ndims; ++i) array_size = array_size * dim_length[i]; dimension dim(transposed_dim_length, (SizeT) var_ndims); if (var_type == NC_DOUBLE) { DDoubleGDL *temp = new DDoubleGDL(dim,BaseGDL::NOZERO); status=nc_get_var_double(cdfid, varid, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=temp; } else if (var_type == NC_FLOAT) { DFloatGDL *temp = new DFloatGDL(dim, BaseGDL::NOZERO); status = nc_get_var_float(cdfid, varid, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=temp; } else if (var_type == NC_SHORT) { DIntGDL * temp=new DIntGDL(dim,BaseGDL::NOZERO); status=nc_get_var_short(cdfid, varid,&(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=temp; } else if (var_type == NC_INT) { DLongGDL* temp=new DLongGDL(dim,BaseGDL::NOZERO); status=nc_get_var_int(cdfid, varid,&(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=temp; } else if (var_type == NC_BYTE) { DByteGDL* temp=new DByteGDL(dim,BaseGDL::NOZERO); status=nc_get_var_uchar(cdfid, varid, &(*temp)[0]); if (status != NC_ERANGE) { ncdf_var_handle_error(e,status,"NCDF_VARGET (ici)", temp); } else { Warning("Warning in NCDF_VARGET: NC_ERANGE during BYTE reading"); ncdf_var_handle_error(e,status,"NCDF_VARGET (ici)", temp); } GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2)=temp; } else if (var_type == NC_CHAR) { DByteGDL* temp = new DByteGDL(dim, BaseGDL::NOZERO); status = nc_get_var_text(cdfid, varid, (char*) &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } //done read all. } else { //OFFSET AND/OR COUNT and NOT/ STRIDE BaseGDL *offset,*count; size_t off[NC_MAX_VAR_DIMS], cou[NC_MAX_VAR_DIMS]; for (int i = 0; i < NC_MAX_VAR_DIMS; ++i) { off[i]=0; cou[i]=1; } size_t array_size = 1; for (int i = 0; i < var_ndims; ++i) off[i] = 0; if (e->GetKW(1) !=NULL) { DLongGDL *o=e->GetKWAs(1); int noff=o->N_Elements(); for (int i = 0; i < noff; ++i) { if ((*o)[i] < dim_length[var_ndims-(i+1)]) { off[var_ndims-(i+1)]=(*o)[i]; } else if ((*o)[i] <= 0) { off[trans[i]]=0; negzero_message("NCDF_VARGET: Offset on",i,0); } else { off[trans[i]]=dim_length[trans[i]]-1; exceed_message("NCDF_VARGET",i,dim_length[trans[i]]-1); } } } for (int i = 0; i < var_ndims; ++i) cou[i]=dim_length[i]-off[i]; if (e->GetKW(0) !=NULL) { DLongGDL *c=e->GetKWAs(0); int ncou=c->N_Elements(); for (int i = 0; i < ncou; ++i) { if ((*c)[i] < dim_length[trans[i]]-off[trans[i]]+1) { cou[trans[i]]=(*c)[i]; } else if ((*c)[i] <= 0) { cou[trans[i]]=1; negzero_message("NCDF_VARGET: Count on",i,1); } else { cou[trans[i]]=dim_length[trans[i]]-off[trans[i]]+1; exceed_message("NCDF_VARGET", i, dim_length[trans[i]]-off[trans[i]]+1); } } } if (e->GetKW(2) == NULL) { //NO STRIDE array_size = 1; for (int i = 0; i < var_ndims; ++i) { transposed_dim_length[trans[i]] = cou[i]; array_size = array_size * cou[i]; } dimension dim(transposed_dim_length, (SizeT) var_ndims); if (var_type == NC_DOUBLE) { DDoubleGDL *temp = new DDoubleGDL(dim, BaseGDL::NOZERO); status=nc_get_vara_double(cdfid, varid, off, cou, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if (var_type == NC_FLOAT) { DFloatGDL *temp = new DFloatGDL(dim, BaseGDL::NOZERO); status = nc_get_vara_float(cdfid, varid, off,cou,&(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if (var_type == NC_SHORT) { DIntGDL *temp = new DIntGDL(dim, BaseGDL::NOZERO); status = nc_get_vara_short(cdfid, varid, off, cou, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if(var_type == NC_INT) { DLongGDL *temp = new DLongGDL(dim,BaseGDL::NOZERO); status = nc_get_vara_int(cdfid, varid, off, cou, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if (var_type == NC_BYTE) { DByteGDL *temp=new DByteGDL(dim,BaseGDL::NOZERO); status = nc_get_vara_uchar(cdfid, varid, off, cou, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if (var_type == NC_CHAR) { DByteGDL *temp = new DByteGDL(dim, BaseGDL::NOZERO); status = nc_get_vara_text(cdfid, varid, off, cou, (char*) &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } } else { //STRIDE ptrdiff_t stri[NC_MAX_VAR_DIMS]; BaseGDL * stride; DIntGDL *s=e->GetKWAs(2); for (int i = 0; i < var_ndims; ++i) stri[i]=1; int nstri=s->N_Elements(); for (int i = 0; i < nstri; ++i) { if ((*s)[i]*cou[trans[i]] < dim_length[trans[i]]-off[trans[i]]+1) { //stride * count < length-offset stri[trans[i]]=(*s)[i]; } else if ((*s)[i] <= 0) { // stride<0, stop it now. stri[trans[i]]=1; e->Throw("STRIDE array cannot have negative elements" +e->GetParString(0)); } else { //cou*stride> length-offset //reduce count stri[trans[i]]=(*s)[i]; cou[trans[i]]=(dim_length[trans[i]]-off[trans[i]])/ stri[trans[i]]; //silent if there is no COUNT keyword if(e->GetKW(0) !=NULL) { int mema=3; string mess; mess = "NCDF_VARGET: Requested read is larget than data in dimension "; mess+=i2s(i); mess+=". Reducing COUNT to "; mess+=i2s(cou[trans[i]]); mess+="."; Message(mess); } } } //now we can get the damn data array_size=1; for (int i = 0; i < var_ndims; ++i) { transposed_dim_length[trans[i]]=cou[i]; array_size=array_size*cou[i]; } dimension dim(transposed_dim_length, (SizeT) var_ndims); if (var_type == NC_DOUBLE) { DDoubleGDL *temp = new DDoubleGDL(dim, BaseGDL::NOZERO); status=nc_get_vars_double(cdfid, varid, off, cou, stri, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if(var_type == NC_FLOAT) { DFloatGDL *temp = new DFloatGDL(dim,BaseGDL::NOZERO); status = nc_get_vars_float(cdfid, varid, off, cou, stri, &(*temp)[0]); ncdf_var_handle_error(e,status,"NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if (var_type == NC_SHORT) { DIntGDL *temp = new DIntGDL(dim, BaseGDL::NOZERO); status = nc_get_vars_short(cdfid, varid, off, cou, stri, &(*temp)[0]); ncdf_var_handle_error(e,status,"NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if(var_type == NC_INT) { DLongGDL *temp = new DLongGDL(dim, BaseGDL::NOZERO); status = nc_get_vars_int(cdfid, varid, off,cou, stri, &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if(var_type == NC_BYTE) { DByteGDL *temp=new DByteGDL(dim, BaseGDL::NOZERO); status = nc_get_vars_uchar(cdfid, varid, off, cou, stri, &(*temp)[0]); ncdf_var_handle_error(e,status,"NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } else if (var_type == NC_CHAR) { DByteGDL *temp = new DByteGDL(dim, BaseGDL::NOZERO); status = nc_get_vars_text(cdfid, varid, off, cou, stri, (char*) &(*temp)[0]); ncdf_var_handle_error(e, status, "NCDF_VARGET", temp); GDLDelete(e->GetParGlobal(2)); e->GetParGlobal(2) = temp; } } } } BaseGDL* ncdf_vardef(EnvT* e) { size_t nParam=e->NParam(2); int dims[NC_MAX_VAR_DIMS], status, var_id,i,var_ndims; nc_type type; DLong cdfid; e->AssureLongScalarPar(0, cdfid); BaseGDL* v=e->GetParDefined(1); DString var_name; e->AssureStringScalarPar(1,var_name); for (i=0;iGetParDefined(2); DIntGDL* dim_in=static_cast(v->Convert2(GDL_INT, BaseGDL::COPY)); Guard dim_in_guard( dim_in); var_ndims=dim_in->N_Elements(); if(var_ndims > NC_MAX_VAR_DIMS) { throw GDLException(e->CallingNode(), "Too many elements error 1 in array"+e->GetParString(0)); } for (i=0; iKeywordSet(0))//GDL_BYTE type=NC_BYTE; else if(e->KeywordSet(1))//CHAR type=NC_CHAR; else if(e->KeywordSet(2))//GDL_DOUBLE type=NC_DOUBLE; else if(e->KeywordSet(4))//GDL_LONG type=NC_INT; else if(e->KeywordSet(5))//SHORT type=NC_SHORT; else type=NC_FLOAT; status=nc_def_var(cdfid, var_name.c_str(), type, var_ndims, dims, &var_id); if(status==NC_ENAMEINUSE) throw GDLException(e->CallingNode(), "Unable to define variable, name in use by another variable ("+var_name+")"); else ncdf_handle_error(e,status,"NCDF_VARDEF"); return new DIntGDL(var_id); } void ncdf_varrename(EnvT* e) { size_t nParam=e->NParam(3); int status; //get the cdfid, which must be given. BaseGDL* n; DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status=nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e,status,"NCDF_VARRENAME"); } DString newname; e->AssureStringScalarPar(2, newname); //we have the cdfid, varid, newname status=nc_rename_var(cdfid,varid, newname.c_str()); ncdf_handle_error(e, status,"NCDF_VARRENAME"); return; } void ncdf_varput(EnvT* e) { //definitions int status, status_tr; size_t value_nelem, dim_length[MAXRANK]; long trans[NC_MAX_VAR_DIMS], retrans[NC_MAX_VAR_DIMS]; int var_dims[NC_MAX_VAR_DIMS], var_natts; char var_name[NC_MAX_NAME]; nc_type var_type; //get the cdfid BaseGDL* v; DLong cdfid, varid; e->AssureLongScalarPar(0, cdfid); // Check type of varid BaseGDL* p1 = e->GetParDefined( 1); if (p1->Type() != GDL_STRING) { // Numeric e->AssureLongScalarPar(1, varid); } else { // String DString var_name; e->AssureScalarPar(1, var_name); status = nc_inq_varid(cdfid, var_name.c_str(), &varid); ncdf_handle_error(e, status, "NCDF_VARPUT"); } int var_ndims; status = nc_inq_var(cdfid, varid, var_name, &var_type, (int *) &var_ndims, var_dims, &var_natts); //get the value v = e->GetParDefined(2); value_nelem = v->N_Elements(); for (int i = 0; i < var_ndims; ++i) { if (v->Type() != GDL_STRING) dim_length[i] = max(int(v->Dim(i)), 1); else dim_length[i] = (*static_cast(v))[0].length(); } //do offset first if (var_ndims == 0)//scalar { trans[0] = 0; retrans[0] = 0; } else { for (int i=0; i < var_ndims; ++i) { trans[i] = var_ndims - i - 1; retrans[i] = i; } } // SA: no-keyword-arguments case handled by nc_put_var_* removed as // * it relied on correctness of input data shape/length (segfaults), // * it did not allow to insert a new record (in an unlimited dimension), // * it is handled by the code below anyhow. //count, offset or stride size_t count[NC_MAX_VAR_DIMS], offset[NC_MAX_VAR_DIMS]; int noff, ncou, nstri; ptrdiff_t stride[NC_MAX_VAR_DIMS]; //setup for (int i = NC_MAX_VAR_DIMS; i--;) stride[i] = count[i] = offset[i] = 0; // not needed? if (var_ndims <= 1) { offset[0] = 0; count[0] = value_nelem; stride[0] = 1; } else { for (int i = 0; i < var_ndims; ++i) { offset[i] = 0; count[trans[i]] = dim_length[i]; stride[i] = 1; } } if (e->GetKW(1) != NULL) { //offset DLongGDL *o = e->GetKWAs(1); noff = o->N_Elements(); if (noff < var_ndims) e->Throw("Insufficient number of indices in OFFSET array (" + i2s(noff) + ", should be " + i2s(var_ndims) + ")"); // offset[0]=0; for (int i = 0; i < noff; ++i) { if ((*o)[i] > 0) offset[trans[i]] = (*o)[i]; else if ((*o)[i] < 0) { offset[trans[i]] = 0; negzero_message("NCDF_VARPUT: Offset", i, 0); } } } long total = 1; if (e->GetKW(0) != NULL) { DLongGDL *c = e->GetKWAs(0); ncou = c->N_Elements(); for (int i = 0; i < ncou; ++i) { if ((*c)[i] > 0) count[trans[i]] = (*c)[i]; else if ((*c)[i] <= 0) { count[trans[i]] = 1; negzero_message("NCDF_VARPUT: Count ", i, 1); } total = total * count[trans[i]]; } } else { if (var_ndims == 0) total = value_nelem; else for (int i = 0; i < var_ndims; ++i) total = total * count[i]; } if (total > value_nelem) e->Throw("Not enough elements (" + i2s(total) + ">" + i2s(value_nelem) + ")"); if (e->GetKW(2) != NULL) { //stride DIntGDL *s = e->GetKWAs(2); nstri=s->N_Elements(); for (int i = 0; i < nstri; ++i) { // stride * count < length-offset if ((*s)[i] > 0) stride[trans[i]] = (*s)[i]; // stride < 0, stop it now. else if ((*s)[i] <= 0) { // stride[trans[i]] = 1; throw GDLException(e->CallingNode(), "NCDF_VARPUT: STRIDE array cannot have negative elements" +e->GetParString(0)); } } } // TODO netCDF-4 has new data types switch (v->Type()) { // using netCDF API functions data type convertion case GDL_DOUBLE : status = nc_put_vars_double(cdfid, varid, offset, count, stride, &((*static_cast(v))[0])); break; case GDL_FLOAT : status = nc_put_vars_float(cdfid, varid, offset, count, stride, &((*static_cast(v))[0])); break; case GDL_INT : status = nc_put_vars_short(cdfid, varid, offset, count, stride, &((*static_cast(v))[0])); break; case GDL_LONG : status = nc_put_vars_int(cdfid, varid, offset, count, stride, &((*static_cast(v))[0])); break; case GDL_BYTE : status = nc_put_vars_uchar(cdfid, varid, offset, count, stride, &((*static_cast(v))[0])); break; // initially using GDL methods for data type convertion case GDL_COMPLEXDBL : case GDL_COMPLEX : case GDL_UINT : case GDL_ULONG : case GDL_LONG64: case GDL_ULONG64 : { BaseGDL* val; Guard val_guard; switch (var_type) { case NC_BYTE : // 8-bit signed integer case NC_SHORT : // 16-bit signed integer val = v->Convert2(GDL_INT, BaseGDL::COPY); val_guard.Init(val); status = nc_put_vars_short(cdfid, varid, offset, count, stride, &((*static_cast(val))[0])); break; case NC_CHAR : // 8-bit unsigned integer val = v->Convert2(GDL_BYTE, BaseGDL::COPY); val_guard.Init(val); status = nc_put_vars_uchar(cdfid, varid, offset, count, stride, &((*static_cast(val))[0])); break; case NC_INT : // 32-bit signed integer val = v->Convert2(GDL_LONG, BaseGDL::COPY); val_guard.Init(val); status = nc_put_vars_int(cdfid, varid, offset, count, stride, &((*static_cast(val))[0])); break; case NC_FLOAT : // 32-bit floating point val = v->Convert2(GDL_FLOAT, BaseGDL::COPY); val_guard.Init(val); status = nc_put_vars_float(cdfid, varid, offset, count, stride, &((*static_cast(val))[0])); break; case NC_DOUBLE : // 64-bit floating point val = v->Convert2(GDL_DOUBLE, BaseGDL::COPY); val_guard.Init(val); status = nc_put_vars_double(cdfid, varid, offset, count, stride, &((*static_cast(val))[0])); break; } break; } case GDL_STRING : status = nc_put_vars_text(cdfid, varid, offset, count, stride, (*static_cast(v))[0].c_str()); break; // reporting illegal types (could be done before...) case GDL_STRUCT : e->Throw("Struct expression not allowed in this context: " + e->GetParString(2)); case GDL_PTR : e->Throw("Pointer expression not allowed in this context: " + e->GetParString(2)); case GDL_OBJ : e->Throw("Object reference expression not allowed in this context: " + e->GetParString(2)); default: e->Throw("GDL internal error, please report!" + e->GetParString(2)); } ncdf_handle_error(e, status, "NCDF_VARPUT"); } } #endif gdl-0.9.9/src/new.cpp000066400000000000000000000022231340051421000143500ustar00rootroot00000000000000/*************************************************************************** |FILENAME| - description ------------------- begin : |DATE| copyright : (C) |YEAR| by |AUTHOR| email : |EMAIL| ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include "datatypes.hpp" #include "envt.hpp" #include "dinterpreter.hpp" namespace lib { } gdl-0.9.9/src/new.hpp000066400000000000000000000020031340051421000143510ustar00rootroot00000000000000/*************************************************************************** |FILENAME| - description ------------------- begin : |DATE| copyright : (C) |YEAR| by |AUTHOR| email : |EMAIL| ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ namespace lib { } // namespace gdl-0.9.9/src/newprognode.cpp000066400000000000000000000565171340051421000161250ustar00rootroot00000000000000/*************************************************************************** newprognode.cpp - translation from DNodes to ProgNode (our final 'code') ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include "dinterpreter.hpp" #include "prognodeexpr.hpp" #include "basegdl.hpp" #include "arrayindexlistt.hpp" #include "envt.hpp" #include "gdlexception.hpp" // print out AST tree #define GDL_DEBUG //#undef GDL_DEBUG #ifdef GDL_DEBUG #include "print_tree.hpp" #endif using namespace std; // helper function for NewProgNode( const RefDNode& refNode) // checks if parameterlist is all constant // used for constant evaluation at compile time bool ConstantPar( ProgNodeP _t) { while(_t != NULL) { switch ( _t->getType()) { case GDLTokenTypes::KEYDEF_REF: { return false; } case GDLTokenTypes::KEYDEF_REF_EXPR: { return false; } case GDLTokenTypes::KEYDEF: { // ProgNodeP __t162 = _t; // match(antlr::RefAST(_t),KEYDEF); // _t = _t->getFirstChild(); // match(antlr::RefAST(_t),IDENTIFIER); // _t = _t->getNextSibling(); if( !_t->getFirstChild()->getNextSibling()->ConstantNode()) return false; // _t = __t162; _t = _t->getNextSibling(); break; } case GDLTokenTypes::REF: { return false; } case GDLTokenTypes::REF_EXPR: { return false; } case GDLTokenTypes::KEYDEF_REF_CHECK: { return false; } case GDLTokenTypes::REF_CHECK: { return false; } default: { // expr if( !_t->ConstantNode()) return false; _t = _t->getNextSibling(); break; } } // switch } // while return true; } // here the transcription from DNode to ProgNode takes place // references are resolved ProgNodeP ProgNode::NewProgNode( const RefDNode& refNode) { // this can happen in case of a subroutine with only common blocks if( refNode == RefDNode(antlr::nullAST)) return NULL; bool nonCopy = false; bool nonCopy12 = false; if( refNode->GetFirstChild() != RefDNode(antlr::nullAST)) { if( NonCopyNode( refNode->GetFirstChild()->getType())) nonCopy = true; if( refNode->GetFirstChild()->GetNextSibling() != RefDNode(antlr::nullAST)) if( NonCopyNode( refNode->GetFirstChild()->GetNextSibling()->getType())) { if( nonCopy) nonCopy12 = true; else nonCopy = true; } } // note: constant expressions are always nonCopy // but expressions of constant expressions are not if( nonCopy) // VAR, VARPTR,... { UnaryExpr* newUnary = NULL; BinaryExpr* newNode = NULL; switch( refNode->getType()) { // case GDLTokenTypes::QUESTION: // { // return new QUESTIONNode( refNode); // } // // unary case GDLTokenTypes::UMINUS: { // // optimize constant unary minus away // // CONSTANT is a non-copy node // if( refNode->GetFirstChild()->getType() == GDLTokenTypes::CONSTANT) // { // const RefDNode& child = refNode->GetFirstChild(); // child->ResetCData( child->CData()->UMinus()); // return NewProgNode( child); // } // else newUnary = new UMINUSNode( refNode); break; } case GDLTokenTypes::LOG_NEG: { newUnary = new LOG_NEGNode( refNode); break; } case GDLTokenTypes::NOT_OP: { newUnary = new NOT_OPNode( refNode); break; } // binary case GDLTokenTypes::AND_OP: { if( nonCopy12) newNode = new AND_OPNCNode( refNode); else newNode = new AND_OPNCNode( refNode); break; } case GDLTokenTypes::OR_OP: { if( nonCopy12) newNode = new OR_OPNCNode( refNode); else newNode = new OR_OPNCNode( refNode); break; } case GDLTokenTypes::XOR_OP: { if( nonCopy12) newNode = new XOR_OPNCNode( refNode); else newNode = new XOR_OPNCNode( refNode); break; } case GDLTokenTypes::LOG_AND: { if( nonCopy12) newNode = new LOG_ANDNCNode( refNode); else newNode = new LOG_ANDNCNode( refNode); break; } case GDLTokenTypes::LOG_OR: { if( nonCopy12) newNode = new LOG_ORNCNode( refNode); else newNode = new LOG_ORNCNode( refNode); break; } case GDLTokenTypes::EQ_OP: { if( nonCopy12) newNode = new EQ_OPNCNode( refNode); else newNode = new EQ_OPNCNode( refNode); break; } case GDLTokenTypes::NE_OP: { if( nonCopy12) newNode = new NE_OPNCNode( refNode); else newNode = new NE_OPNCNode( refNode); break; } case GDLTokenTypes::LE_OP: { if( nonCopy12) newNode = new LE_OPNCNode( refNode); else newNode = new LE_OPNCNode( refNode); break; } case GDLTokenTypes::LT_OP: { if( nonCopy12) newNode = new LT_OPNCNode( refNode); else newNode = new LT_OPNCNode( refNode); break; } case GDLTokenTypes::GE_OP: { if( nonCopy12) newNode = new GE_OPNCNode( refNode); else newNode = new GE_OPNCNode( refNode); break; } case GDLTokenTypes::GT_OP: { if( nonCopy12) newNode = new GT_OPNCNode( refNode); else newNode = new GT_OPNCNode( refNode); break; } case GDLTokenTypes::PLUS: { if( nonCopy12) newNode = new PLUSNC12Node( refNode); else newNode = new PLUSNCNode( refNode); break; } case GDLTokenTypes::MINUS: { if( nonCopy12) newNode = new MINUSNC12Node( refNode); else newNode = new MINUSNCNode( refNode); break; } case GDLTokenTypes::LTMARK: { if( nonCopy12) newNode = new LTMARKNCNode( refNode); else newNode = new LTMARKNCNode( refNode); break; } case GDLTokenTypes::GTMARK: { if( nonCopy12) newNode = new GTMARKNCNode( refNode); else newNode = new GTMARKNCNode( refNode); break; } case GDLTokenTypes::ASTERIX: { if( nonCopy12) newNode = new ASTERIXNC12Node( refNode); else newNode = new ASTERIXNCNode( refNode); break; } case GDLTokenTypes::MATRIX_OP1: { if( nonCopy12) newNode = new MATRIX_OP1NCNode( refNode); else newNode = new MATRIX_OP1NCNode( refNode); break; } case GDLTokenTypes::MATRIX_OP2: { if( nonCopy12) newNode = new MATRIX_OP2NCNode( refNode); else newNode = new MATRIX_OP2NCNode( refNode); break; } case GDLTokenTypes::SLASH: { if( nonCopy12) newNode = new SLASHNC12Node( refNode); else newNode = new SLASHNCNode( refNode); break; } case GDLTokenTypes::MOD_OP: { if( nonCopy12) newNode = new MOD_OPNCNode( refNode); else newNode = new MOD_OPNCNode( refNode); break; } case GDLTokenTypes::POW: { if( nonCopy12) newNode = new POWNCNode( refNode); else newNode = new POWNCNode( refNode); break; } // case GDLTokenTypes::DEC: // { // return new DECNCNode( refNode); // } // case GDLTokenTypes::INC: // { // return new INCNCNode( refNode); // } // case GDLTokenTypes::POSTDEC: // { // return new POSTDECNCNode( refNode); // } // case GDLTokenTypes::POSTINC: // { // return new POSTINCNCNode( refNode); // } // default: // return new DefaultNode( refNode); } if( newNode != NULL) { if( !newNode->ConstantExpr()) return newNode; Guard guard( newNode); BaseGDL* cData = newNode->Eval(); ProgNodeP cN = new CONSTANTNode( newNode->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C" + refNode->getText()); return cN; } else if( newUnary != NULL) { if( !newUnary->ConstantExpr()) return newUnary; Guard guard( newUnary); BaseGDL* cData = newUnary->Eval(); ProgNodeP cN = new CONSTANTNode( newUnary->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C" + refNode->getText()); return cN; } } else // !nonCopy { UnaryExpr* newUnary = NULL; BinaryExpr* newNode = NULL; switch( refNode->getType()) { // case GDLTokenTypes::QUESTION: // { // return new QUESTIONNode( refNode); // } // // unary case GDLTokenTypes::UMINUS: { newUnary = new UMINUSNode( refNode); break; } case GDLTokenTypes::LOG_NEG: { newUnary = new LOG_NEGNode( refNode); break; } case GDLTokenTypes::NOT_OP: { newUnary = new NOT_OPNode( refNode); break; } // binary case GDLTokenTypes::AND_OP: { newNode = new AND_OPNode( refNode); break; } case GDLTokenTypes::OR_OP: { newNode = new OR_OPNode( refNode); break; } case GDLTokenTypes::XOR_OP: { newNode = new XOR_OPNode( refNode); break; } case GDLTokenTypes::LOG_AND: { newNode = new LOG_ANDNode( refNode); break; } case GDLTokenTypes::LOG_OR: { newNode = new LOG_ORNode( refNode); break; } case GDLTokenTypes::EQ_OP: { newNode = new EQ_OPNode( refNode); break; } case GDLTokenTypes::NE_OP: { newNode = new NE_OPNode( refNode); break; } case GDLTokenTypes::LE_OP: { newNode = new LE_OPNode( refNode); break; } case GDLTokenTypes::LT_OP: { newNode = new LT_OPNode( refNode); break; } case GDLTokenTypes::GE_OP: { newNode = new GE_OPNode( refNode); break; } case GDLTokenTypes::GT_OP: { newNode = new GT_OPNode( refNode); break; } case GDLTokenTypes::PLUS: { newNode = new PLUSNode( refNode); break; } case GDLTokenTypes::MINUS: { newNode = new MINUSNode( refNode); break; } case GDLTokenTypes::LTMARK: { newNode = new LTMARKNode( refNode); break; } case GDLTokenTypes::GTMARK: { newNode = new GTMARKNode( refNode); break; } case GDLTokenTypes::ASTERIX: { newNode = new ASTERIXNode( refNode); break; } case GDLTokenTypes::MATRIX_OP1: { newNode = new MATRIX_OP1Node( refNode); break; } case GDLTokenTypes::MATRIX_OP2: { newNode = new MATRIX_OP2Node( refNode); break; } case GDLTokenTypes::SLASH: { newNode = new SLASHNode( refNode); break; } case GDLTokenTypes::MOD_OP: { newNode = new MOD_OPNode( refNode); break; } case GDLTokenTypes::POW: { newNode = new POWNode( refNode); break; } // case GDLTokenTypes::DEC: // { // return new DECNode( refNode); // } // case GDLTokenTypes::INC: // { // return new INCNode( refNode); // } // case GDLTokenTypes::POSTDEC: // { // return new POSTDECNode( refNode); // } // case GDLTokenTypes::POSTINC: // { // return new POSTINCNode( refNode); // } // default: } if( newNode != NULL) { if( !newNode->ConstantExpr()) return newNode; Guard guard( newNode); BaseGDL* cData = newNode->Eval(); ProgNodeP cN = new CONSTANTNode( newNode->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C" + refNode->getText()); return cN; } else if( newUnary != NULL) { if( !newUnary->ConstantExpr()) return newUnary; Guard guard( newUnary); BaseGDL* cData = newUnary->Eval(); ProgNodeP cN = new CONSTANTNode( newUnary->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C" + refNode->getText()); return cN; } } // independed of nonCopy: switch( refNode->getType()) { case GDLTokenTypes::QUESTION: { return new QUESTIONNode( refNode); } case GDLTokenTypes::FCALL_LIB_RETNEW: { ProgNodeP c = new FCALL_LIB_RETNEWNode( refNode); if( !static_cast(c->libFun)->RetConstant() || !ConstantPar( c->getFirstChild())) return c; Guard< ProgNode> guard( c); BaseGDL* cData = c->Eval(); ProgNodeP cN = new CONSTANTNode( c->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C()"); return cN; } case GDLTokenTypes::FCALL_LIB_DIRECT: { ProgNodeP c = new FCALL_LIB_DIRECTNode( refNode); if( !static_cast(c->libFun)->RetConstant() || !ConstantPar( c->getFirstChild())) return c; Guard< ProgNode> guard( c); BaseGDL* cData = c->Eval(); ProgNodeP cN = new CONSTANTNode( c->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C()"); return cN; } case GDLTokenTypes::FCALL_LIB_N_ELEMENTS: { ProgNodeP c = new FCALL_LIB_N_ELEMENTSNode( refNode); if( !static_cast(c->libFun)->RetConstant() || !ConstantPar( c->getFirstChild())) return c; Guard< ProgNode> guard( c); BaseGDL* cData = c->Eval(); ProgNodeP cN = new CONSTANTNode( c->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "C()"); return cN; } case GDLTokenTypes::FCALL_LIB: { return new FCALL_LIBNode( refNode); } case GDLTokenTypes::MFCALL: { return new MFCALLNode( refNode); } case GDLTokenTypes::MFCALL_PARENT: { return new MFCALL_PARENTNode( refNode); } case GDLTokenTypes::FCALL: { return new FCALLNode( refNode); } case GDLTokenTypes::ARRAYEXPR_FCALL: { return new ARRAYEXPR_FCALLNode( refNode); } case GDLTokenTypes::ARRAYEXPR_MFCALL: { return new ARRAYEXPR_MFCALLNode( refNode); } case GDLTokenTypes::ARRAYEXPR: { return new ARRAYEXPRNode( refNode); } case GDLTokenTypes::EXPR: { return new EXPRNode( refNode); } case GDLTokenTypes::DOT: { return new DOTNode( refNode); } case GDLTokenTypes::VAR: { return new VARNode( refNode); } case GDLTokenTypes::VARPTR: { return new VARPTRNode( refNode); } case GDLTokenTypes::SYSVAR: { return new SYSVARNode( refNode); } case GDLTokenTypes::DEREF: { return new DEREFNode( refNode); } case GDLTokenTypes::CONSTANT: { // cout << "CONSTANT RefDNode:" << endl; // antlr::print_tree pt; // pt.pr_tree(static_cast( refNode)); // cout << "1st cData: " << refNode->getType() << " "<< refNode->getText() << " " << refNode->CData() << endl; // cout << endl; // // ProgNodeP c = new CONSTANTNode( refNode); // // cout << "CONSTANT ProgNodeP:" << endl; // pt.pr_tree(c); // cout << endl; // // return c; return new CONSTANTNode( refNode); } case GDLTokenTypes::ARRAYDEF_GENERALIZED_INDGEN: { ARRAYDEF_GENERALIZED_INDGENNode* c = new ARRAYDEF_GENERALIZED_INDGENNode( refNode); if( !c->ConstantArray()) return c; Guard< ARRAYDEF_GENERALIZED_INDGENNode> guard( c); BaseGDL* cData = c->Eval(); ProgNodeP cN = new CONSTANTNode( c->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "[c1:c2:c3]"); return cN; } case GDLTokenTypes::ARRAYDEF: { ARRAYDEFNode* c = new ARRAYDEFNode( refNode); if( !c->ConstantArray()) return c; Guard< ARRAYDEFNode> guard( c); BaseGDL* cData = c->Eval(); ProgNodeP cN = new CONSTANTNode( c->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "[c]"); return cN; } case GDLTokenTypes::ARRAYDEF_CONST: { // cout << "ARRAYDEF_CONST RefDNode:" << endl; // antlr::print_tree pt; // pt.pr_tree(static_cast( refNode)); // cout << endl; ARRAYDEFNode* c = new ARRAYDEFNode( refNode); // cout << "ARRAYDEF_CONST ProgNodeP:" << endl; // pt.pr_tree(c); // cout << endl; assert( c->ConstantArray()); Guard< ProgNode> guard( c); BaseGDL* cData = c->Eval(); ProgNodeP cN = new CONSTANTNode( c->StealNextSibling(), cData); cN->lineNumber = refNode->getLine(); cN->setText( "[C]"); return cN; // DNode* cN = new DNode(); // cN->setType(GDLTokenTypes::CONSTANT); // cN->setText("[CONSTANT]"); // cN->setNextSibling( refNode->getNextSibling()); // refNode->setNextSibling(antlr::nullAST); // ProgNodeP c = new ARRAYDEFNode( refNode); // Guard< ProgNode> guard( c); // //c->setType( GDLTokenTypes::ARRAYDEF); // // evaluate constant // BaseGDL* res = c->Eval(); // cN->ResetCData( res); // return new CONSTANTNode( RefDNode( cN)); } case GDLTokenTypes::STRUC: { return new STRUCNode( refNode); } case GDLTokenTypes::NSTRUC: { return new NSTRUCNode( refNode); } case GDLTokenTypes::NSTRUC_REF: { return new NSTRUC_REFNode( refNode); } case GDLTokenTypes::ASSIGN: { return new ASSIGNNode( refNode); } case GDLTokenTypes::ASSIGN_ARRAYEXPR_MFCALL: { return new ASSIGN_ARRAYEXPR_MFCALLNode( refNode); } case GDLTokenTypes::ASSIGN_REPLACE: { return new ASSIGN_REPLACENode( refNode); } case GDLTokenTypes::GOTO: { return new GOTONode( refNode); } case GDLTokenTypes::BREAK: { return new BREAKNode( refNode); } case GDLTokenTypes::CONTINUE: { return new CONTINUENode( refNode); } case GDLTokenTypes::LABEL: { return new LABELNode( refNode); } case GDLTokenTypes::ON_IOERROR: { return new ON_IOERRORNode( refNode); } case GDLTokenTypes::ON_IOERROR_NULL: { return new ON_IOERROR_NULLNode( refNode); } case GDLTokenTypes::RETF: { return new RETFNode( refNode); } case GDLTokenTypes::RETP: { return new RETPNode( refNode); } case GDLTokenTypes::FOR: { return new FORNode( refNode); } case GDLTokenTypes::FOR_STEP: { return new FOR_STEPNode( refNode); } case GDLTokenTypes::FOREACH: { return new FOREACHNode( refNode); } case GDLTokenTypes::FOREACH_INDEX: { return new FOREACH_INDEXNode( refNode); } case GDLTokenTypes::WHILE: { return new WHILENode( refNode); } case GDLTokenTypes::REPEAT: { return new REPEATNode( refNode); } case GDLTokenTypes::CASE: { return new CASENode( refNode); } case GDLTokenTypes::SWITCH: { return new SWITCHNode( refNode); } case GDLTokenTypes::BLOCK: { return new BLOCKNode( refNode); } case GDLTokenTypes::IF: { return new IFNode( refNode); } case GDLTokenTypes::IF_ELSE: { return new IF_ELSENode( refNode); } case GDLTokenTypes::PCALL_LIB: { return new PCALL_LIBNode( refNode); } case GDLTokenTypes::MPCALL: { return new MPCALLNode( refNode); } case GDLTokenTypes::MPCALL_PARENT: { return new MPCALL_PARENTNode( refNode); } case GDLTokenTypes::PCALL: { return new PCALLNode( refNode); } case GDLTokenTypes::POSTDEC: { return new POSTDECNode( refNode); } case GDLTokenTypes::POSTINC: { return new POSTINCNode( refNode); } case GDLTokenTypes::DEC: { return new DECNode( refNode); } case GDLTokenTypes::INC: { return new INCNode( refNode); } // the following must change their type if precalculation strikes case GDLTokenTypes::KEYDEF_REF: { ProgNodeP nn = new KEYDEF_REFNode( refNode); if( !nn->getFirstChild()->getNextSibling()->ConstantNode()) return nn; // nn->setType( GDLTokenTypes::KEYDEF); delete nn; nn = new KEYDEFNode( refNode); return nn; } case GDLTokenTypes::KEYDEF_REF_EXPR: { ProgNodeP nn = new KEYDEF_REF_EXPRNode( refNode); if( !nn->getFirstChild()->getNextSibling()->ConstantNode()) return nn; delete nn; nn = new KEYDEFNode( refNode); // nn->setType( GDLTokenTypes::KEYDEF); return nn; } case GDLTokenTypes::PARAEXPR: { ProgNodeP firstChild = new ParameterNode( refNode); return firstChild; } case GDLTokenTypes::PARAEXPR_VN: { ProgNodeP firstChild = new ParameterVNNode( refNode); return firstChild; } case GDLTokenTypes::KEYDEF: { ProgNodeP nn = new KEYDEFNode( refNode); return nn; } case GDLTokenTypes::REF: { ProgNodeP nn = new REFNode( refNode); if( !nn->getFirstChild()->ConstantNode()) return nn; delete nn; ProgNodeP firstChild = new ParameterNode( refNode);//->GetFirstChild()); return firstChild; } case GDLTokenTypes::REF_VN: { ProgNodeP nn = new REFVNNode( refNode); if( !nn->getFirstChild()->ConstantNode()) return nn; delete nn; ProgNodeP firstChild = new ParameterNode( refNode);//->GetFirstChild()); return firstChild; } case GDLTokenTypes::REF_EXPR: { ProgNodeP nn = new REF_EXPRNode( refNode); if( !nn->getFirstChild()->ConstantNode()) return nn; delete nn; ProgNodeP firstChild = new ParameterNode( refNode);//->GetFirstChild()); return firstChild; // Guard guard(nn); // return nn->StealFirstChild(); } case GDLTokenTypes::REF_EXPR_VN: { ProgNodeP nn = new REF_EXPRVNNode( refNode); if( !nn->getFirstChild()->ConstantNode()) return nn; delete nn; ProgNodeP firstChild = new ParameterNode( refNode);//->GetFirstChild()); return firstChild; // Guard guard(nn); // return nn->StealFirstChild(); } case GDLTokenTypes::KEYDEF_REF_CHECK: { ProgNodeP nn = new KEYDEF_REF_CHECKNode( refNode); if( nn->getFirstChild()->getNextSibling()->getType() != GDLTokenTypes::CONSTANT) return nn; delete nn; nn = new KEYDEFNode( refNode); return nn; } case GDLTokenTypes::REF_CHECK: { ProgNodeP nn = new REF_CHECKNode( refNode); if( !nn->getFirstChild()->ConstantNode()) return nn; delete nn; ProgNodeP firstChild = new ParameterNode( refNode); return firstChild; // Guard guard(nn); // ProgNodeP firstChild = nn->StealFirstChild(); // firstChild->SetNextSibling( nn->StealNextSibling()); // return firstChild; } case GDLTokenTypes::REF_CHECK_VN: { ProgNodeP nn = new REF_CHECKVNNode( refNode); if( !nn->getFirstChild()->ConstantNode()) return nn; delete nn; ProgNodeP firstChild = new ParameterNode( refNode); return firstChild; // Guard guard(nn); // ProgNodeP firstChild = nn->StealFirstChild(); // firstChild->SetNextSibling( nn->StealNextSibling()); // return firstChild; } } // default return new DefaultNode( refNode); } gdl-0.9.9/src/nullgdl.cpp000066400000000000000000000561401340051421000152270ustar00rootroot00000000000000/*************************************************************************** nullgdl.cpp - class for GDL !NULL ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "nullgdl.hpp" #include "datatypes.hpp" using namespace std; char NullGDL::buf[sizeof(NullGDL)]; NullGDL* NullGDL::instance = NULL; NullGDL::~NullGDL() { // it would be the fastest way, to just ignore it. // but ~BaseGDL() is called as well. And this must not be cerr << "Internal error: !NULL destructor called.\n" "Save your work and restart GDL (GDL is still functional, but !NULL will not work anymore).\n" "Please report at https://github.com/gnudatalanguage/gdl/issues" << endl; } bool NullGDL::IsAssoc() const { return false;} BaseGDL* NullGDL::AssocVar( int, SizeT) { throw GDLException("NullGDL::AssocVar(...) called."); } SizeT NullGDL::N_Elements() const { return 0; } SizeT NullGDL::Size() const { return 0;} SizeT NullGDL::ToTransfer() const { return 0;} SizeT NullGDL::Sizeof() const { return 0;} SizeT NullGDL::NBytes() const { return 0;} // for assoc function BaseGDL& NullGDL::operator=(const BaseGDL& right) { return *this; } void NullGDL::InitFrom(const BaseGDL& right) { throw GDLException("NullGDL::InitFrom(const BaseGDL& right) called."); } // BaseGDL* NullGDL::Abs() const // { // throw GDLException("NullGDL::Abs() called."); // } bool NullGDL::Greater(SizeT i1, SizeT i2) const { throw GDLException("NullGDL::Greater(SizeT,SizeT) called."); } bool NullGDL::Equal(SizeT i1, SizeT i2) const { throw GDLException("NullGDL::Equal(SizeT,SizeT) called."); } BaseGDL* NullGDL::CShift( DLong d) const { throw GDLException("NullGDL::CShift(...) called."); } BaseGDL* NullGDL::CShift( DLong d[MAXRANK]) const { throw GDLException("NullGDL::CShift( DLong d[MAXRANK]) called."); } BaseGDL* NullGDL::Transpose( DUInt* perm) { throw GDLException("NullGDL::Transpose(...) called."); } void NullGDL::MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start, SizeT stop, SizeT step, DLong valIx, bool useAbs) { throw GDLException("NullGDL::MinMax(...) called."); } void NullGDL::Clear() { throw GDLException("NullGDL::Clear() called."); } void NullGDL::Construct() { throw GDLException("NullGDL::Construct() called."); } void NullGDL::ConstructTo0() { throw GDLException("NullGDL::ConstructTo0() called."); } void NullGDL::Destruct() { throw GDLException("NullGDL::Destruct() called."); } void NullGDL::Assign( BaseGDL* src, SizeT nEl) { throw GDLException("NullGDL::Assign(...) called."); } std::ostream& NullGDL::Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs) { throw GDLException("NullGDL::Write(...) called."); } std::istream& NullGDL::Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs) { throw GDLException("NullGDL::Read(...) called."); } std::ostream& NullGDL::ToStream(std::ostream& o, SizeT width, SizeT* actPosPtr ) { o << "!NULL"; return o; } std::istream& NullGDL::FromStream(std::istream& i) { i >> *this; return i; } bool NullGDL::Scalar() const { return false;} bool NullGDL::StrictScalar() const { return false;} DType NullGDL::Type() const { return GDL_UNDEF;} const std::string& NullGDL::TypeStr() const { static const std::string s("UNDEFINED"); return s;} bool NullGDL::EqType( const BaseGDL*) const { throw GDLException("NullGDL::EqType(...) called."); } void* NullGDL::DataAddr()// SizeT elem) { throw GDLException("NullGDL::DataAddr(...) called."); } // make same type on the heap BaseGDL* NullGDL::New( const dimension& dim_, InitType noZero) const { return NullGDL::GetSingleInstance(); } BaseGDL* NullGDL::NewResult() const { return NullGDL::GetSingleInstance(); } BaseGDL* NullGDL::Dup() const { return NullGDL::GetSingleInstance(); } // BaseGDL* NullGDL::Dup( void*) const // { // throw GDLException("NullGDL::Dup(...) called."); // } BaseGDL* NullGDL::Convert2( DType destTy, Convert2Mode mode) { if( destTy == GDL_STRING) return new DStringGDL( "!NULL"); throw GDLException("Variable is undefined: !NULL"); } BaseGDL* NullGDL::GetTag() const { throw GDLException("!NULL not allowed in tag definition."); } BaseGDL* NullGDL::GetInstance() const { throw GDLException("NullGDL::GetInstance(...) called."); } BaseGDL* NullGDL::GetEmptyInstance() const { throw GDLException("NullGDL::GetEmptyInstance(...) called."); } BaseGDL* NullGDL::SetBuffer( const void* b) { throw GDLException("NullGDL::SetBuffer called."); } void NullGDL::SetBufferSize( SizeT s) { throw GDLException("NullGDL::SetBufferSize called."); } int NullGDL::Scalar2Index(SizeT& ret) const { throw GDLException("Operation not defined for !NULL 1."); } int NullGDL::Scalar2RangeT(RangeT& ret) const { throw GDLException("Operation not defined for !NULL 1a."); } SizeT NullGDL::GetAsIndex( SizeT i) const { throw GDLException("NullGDL::GetAsIndex called."); } SizeT NullGDL::GetAsIndexStrict( SizeT i) const { throw GDLException("NullGDL::GetAsIndexStrict called."); } #ifdef _MSC_VER bool NullGDL::True() #else bool NullGDL::NullGDL::True() #endif { throw GDLException("Operation not defined for !NULL 3."); } #ifdef _MSC_VER bool NullGDL::False() #else bool NullGDL::NullGDL::False() #endif { throw GDLException("Operation not defined for !NULL 4."); } bool NullGDL::LogTrue() { throw GDLException("Operation not defined for !NULL 4a."); } bool NullGDL::LogTrue( SizeT ix) { throw GDLException("Operation not defined for !NULL 4b."); } void NullGDL::Where(DLong* &ret, SizeT &passed_count, bool comp, DLong* &comp_ret) { throw GDLException("Operation not defined for !NULL 4b."); } void NullGDL::Where(DLong64* &ret, SizeT &passed_count, bool comp, DLong64* &comp_ret) { throw GDLException("Operation not defined for !NULL 4b."); } BaseGDL* NullGDL::LogNeg() { throw GDLException("Operation not defined for !NULL 4c."); } int NullGDL::Sgn() // -1,0,1 { throw GDLException("Operation not defined for !NULL 5."); } bool NullGDL::Equal( BaseGDL*) const { throw GDLException("Operation not defined for !NULL 6."); } bool NullGDL::EqualNoDelete( const BaseGDL*) const { throw GDLException("Operation not defined for !NULL 6a."); } bool NullGDL::ArrayEqual( BaseGDL*) { throw GDLException("Operation not defined for !NULL 6b."); } // for statement compliance (int types , float types scalar only) void NullGDL::ForCheck( BaseGDL**, BaseGDL**) { throw GDLException("Operation not defined for !NULL 7."); } bool NullGDL::ForCondUp( BaseGDL*) { throw GDLException("Operation not defined for !NULL 8."); } bool NullGDL::ForAddCondUp( BaseGDL* loopInfo) // bool NullGDL::ForAddCondUp( ForLoopInfoT& loopInfo) { throw GDLException("Operation not defined for !NULL 8a."); } bool NullGDL::ForCondDown( BaseGDL*) { throw GDLException("Operation not defined for !NULL 9."); } // bool NullGDL::ForCondUpDown( BaseGDL*) // { // throw GDLException("Operation not defined for !NULL 9a."); // } void NullGDL::ForAdd( BaseGDL* add) { throw GDLException("Operation not defined for !NULL 10."); } BaseGDL* NullGDL::CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank) { throw GDLException("NullGDL::CatArray(...) called."); } BaseGDL* NullGDL::Index( ArrayIndexListT* ixList) { throw GDLException("NullGDL::Index(...) called."); } // used in r_expr BaseGDL* NullGDL::UMinus() { throw GDLException("Operation not defined for !NULL 11."); } BaseGDL* NullGDL::NotOp() { throw GDLException("Operation not defined for !NULL 12."); } BaseGDL* NullGDL::AndOp( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 13."); } BaseGDL* NullGDL::AndOpInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 14."); } BaseGDL* NullGDL::OrOp( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 13."); } BaseGDL* NullGDL::OrOpInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 14."); } BaseGDL* NullGDL::XorOp( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 13."); } BaseGDL* NullGDL::XorOpS( BaseGDL* r) { throw GDLException("XOR: Operation not defined for !NULL."); } BaseGDL* NullGDL::EqOp( BaseGDL* r) { if( (r == NULL) || (r == NullGDL::GetSingleInstance())) { return new Data_( 1); } // check for null opject and pointer DType rTy= r->Type(); if( rTy == GDL_PTR) { DPtrGDL* rP = static_cast(r); DPtr pVal; if( rP->Scalar( pVal) && pVal == 0) return new Data_( 1); } else if( rTy == GDL_OBJ) { DObjGDL* rP = static_cast(r); DObj pVal; if( rP->Scalar( pVal) && pVal == 0) return new Data_( 1); } return new Data_( 0); } BaseGDL* NullGDL::NeOp( BaseGDL* r) { if( (r == NULL) || (r == NullGDL::GetSingleInstance())) { return new Data_( 0); } // check for null opject and pointer DType rTy= r->Type(); if( rTy == GDL_PTR) { DPtrGDL* rP = static_cast(r); DPtr pVal; if( rP->Scalar( pVal) && pVal == 0) return new Data_( 0); } else if( rTy == GDL_OBJ) { DObjGDL* rP = static_cast(r); DObj pVal; if( rP->Scalar( pVal) && pVal == 0) return new Data_( 0); } return new Data_( 1); } BaseGDL* NullGDL::LeOp( BaseGDL* r) { throw GDLException("LE: Operation not defined for !NULL."); } BaseGDL* NullGDL::GeOp( BaseGDL* r) { throw GDLException("GE: Operation not defined for !NULL."); } BaseGDL* NullGDL::LtOp( BaseGDL* r) { throw GDLException("LT: Operation not defined for !NULL."); } BaseGDL* NullGDL::GtOp( BaseGDL* r) { throw GDLException("GT: Operation not defined for !NULL."); } BaseGDL* NullGDL::Add( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 15."); } BaseGDL* NullGDL::AddInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 15."); } BaseGDL* NullGDL::Sub( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::SubInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::LtMark( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 18."); } BaseGDL* NullGDL::GtMark( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 19."); } BaseGDL* NullGDL::Mult( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 19a."); } BaseGDL* NullGDL::Div( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::DivInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::Mod( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::ModInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::Pow( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::PowInv( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::PowInt( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 170."); } BaseGDL* NullGDL::MatrixOp( BaseGDL* r, bool atranspose, bool btranspose) { throw GDLException("Operation not defined for !NULL 18."); } void NullGDL::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset) { throw GDLException("NullGDL::AssignAt(...) called."); } void NullGDL::AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList) { throw GDLException("NullGDL::AssignAt(..) called."); } void NullGDL::AssignAt( BaseGDL* srcIn) { throw GDLException("NullGDL::AssignAt(.) called."); } void NullGDL::DecAt( ArrayIndexListT* ixList) { throw GDLException("NullGDL::DecAt(...) called."); } void NullGDL::IncAt( ArrayIndexListT* ixList) { throw GDLException("NullGDL::IncAt(...) called."); } void NullGDL::Dec() { throw GDLException("NullGDL::Dec(...) called."); } void NullGDL::Inc() { throw GDLException("NullGDL::Inc(...) called."); } void NullGDL::InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList) { throw GDLException("NullGDL::InsertAt( SizeT, ...) called."); } // formatting output functions SizeT NullGDL::OFmtA( std::ostream* os, SizeT offset, SizeT num, int width) {throw GDLException("NullGDL::OFmtA(...) called.");} SizeT NullGDL::OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code, const BaseGDL::IOMode oM) {throw GDLException("NullGDL::OFmtF(...) called.");} SizeT NullGDL::OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code, BaseGDL::IOMode oM) {throw GDLException("NullGDL::OFmtI(...) called.");} SizeT NullGDL::IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode) {throw GDLException("NullGDL::IFmtCal(...) called.");} SizeT NullGDL::OFmtCal( std::ostream* os, SizeT offs, SizeT num, int width, int minN, char *f, NullGDL::Cal_IOMode cM) {throw GDLException("NullGDL::OFmtCal(...) called.");} SizeT NullGDL::IFmtA( std::istream* is, SizeT offset, SizeT num, int width) {throw GDLException("NullGDL::IFmtA(...) called.");} SizeT NullGDL::IFmtF( std::istream* is, SizeT offs, SizeT num, int width) {throw GDLException("NullGDL::IFmtF(...) called.");} SizeT NullGDL::IFmtI( std::istream* is, SizeT offs, SizeT num, int width, NullGDL::IOMode oM) {throw GDLException("NullGDL::IFmtI(...) called.");} BaseGDL* NullGDL::Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid) { throw GDLException("NullGDL::Convol(...) called."); } BaseGDL* NullGDL::Smooth( DLong* width, int edgeMode, bool doNan, BaseGDL* missing) { throw GDLException("NullGDL::Smooth(...) called."); } BaseGDL* NullGDL::Rebin( const dimension& newDim, bool sample) { throw GDLException("NullGDL::Rebin(...) called."); } #ifdef USE_PYTHON PyObject* NullGDL::ToPython() {throw GDLException("NullGDL::ToPython(...) called.");} #endif BaseGDL* NullGDL::AndOpS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 13."); } BaseGDL* NullGDL::AndOpInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 14."); } BaseGDL* NullGDL::OrOpS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 13."); } BaseGDL* NullGDL::OrOpInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 14."); } BaseGDL* NullGDL::AddS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 15."); } BaseGDL* NullGDL::AddInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 15."); } BaseGDL* NullGDL::SubS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::SubInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::LtMarkS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 18."); } BaseGDL* NullGDL::GtMarkS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 19."); } BaseGDL* NullGDL::MultS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 19a."); } BaseGDL* NullGDL::DivS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::DivInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::ModS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::ModInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::PowS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 16."); } BaseGDL* NullGDL::PowInvS( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 17."); } BaseGDL* NullGDL::NewIx( SizeT ix) { throw GDLException("Operation not defined for !NULL 20."); } BaseGDL* NullGDL::NewIx( BaseGDL* ix, bool strict) { throw GDLException("Operation not defined for !NULL 21."); } BaseGDL* NullGDL::NewIx( AllIxBaseT* ix, const dimension* dIn) { throw GDLException("Operation not defined for !NULL 22."); } BaseGDL* NullGDL::NewIxFrom( SizeT s) { throw GDLException("Operation not defined for !NULL 23."); } BaseGDL* NullGDL::NewIxFrom( SizeT s, SizeT e) { throw GDLException("Operation not defined for !NULL 24."); } BaseGDL* NullGDL::NewIxFromStride( SizeT s, SizeT stride) { throw GDLException("Operation not defined for !NULL 25."); } BaseGDL* NullGDL::NewIxFromStride( SizeT s, SizeT e, SizeT stride) { throw GDLException("Operation not defined for !NULL 26."); } BaseGDL* NullGDL::Log() { throw GDLException("Operation not defined for !NULL 27a."); } BaseGDL* NullGDL::LogThis() { throw GDLException("Operation not defined for !NULL 27b."); } BaseGDL* NullGDL::Log10() { throw GDLException("Operation not defined for !NULL 27c."); } BaseGDL* NullGDL::Log10This() { throw GDLException("Operation not defined for !NULL 27d."); } void NullGDL::AssignAtIx( RangeT ix, BaseGDL* srcIn) { throw GDLException("Operation not defined for !NULL 28."); } RangeT NullGDL::LoopIndex() const { throw GDLException("Operation not defined for !NULL 29."); } DDouble NullGDL::HashValue() const { throw GDLException("Operation not defined for !NULL 29a."); } BaseGDL* NullGDL::Rotate( DLong dir) { throw GDLException("Operation not defined for !NULL 30."); } void NullGDL::Reverse( DLong dim) { throw GDLException("Operation not defined for !NULL 31."); } BaseGDL* NullGDL::DupReverse( DLong dim) { throw GDLException("Operation not defined for !NULL 32."); } BaseGDL* NullGDL::AndOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 40.");} BaseGDL* NullGDL::AndOpInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 41.");} BaseGDL* NullGDL::OrOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 42.");} BaseGDL* NullGDL::OrOpInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 43.");} BaseGDL* NullGDL::XorOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 44.");} // BaseGDL* NullGDL::EqOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 45.");} // BaseGDL* NullGDL::NeOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 46.");} // BaseGDL* NullGDL::LeOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 47.");} // BaseGDL* NullGDL::GeOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 48.");} // BaseGDL* NullGDL::LtOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 49.");} // BaseGDL* NullGDL::GtOpNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 50.");} BaseGDL* NullGDL::AddNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 51.");} // implemented BaseGDL* NullGDL::AddInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 52.");} // implemented BaseGDL* NullGDL::SubNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 53.");} BaseGDL* NullGDL::SubInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 54.");} BaseGDL* NullGDL::LtMarkNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 55.");} BaseGDL* NullGDL::GtMarkNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 56.");} BaseGDL* NullGDL::MultNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 57.");} // implemented BaseGDL* NullGDL::DivNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 58.");} BaseGDL* NullGDL::DivInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 59.");} BaseGDL* NullGDL::ModNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 60.");} BaseGDL* NullGDL::ModInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 61.");} BaseGDL* NullGDL::PowNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 62.");} BaseGDL* NullGDL::PowInvNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 63.");} BaseGDL* NullGDL::PowIntNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 64.");} // implemented BaseGDL* NullGDL::AndOpSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 65.");} BaseGDL* NullGDL::AndOpInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 66.");} BaseGDL* NullGDL::OrOpSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 67.");} BaseGDL* NullGDL::OrOpInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 68.");} BaseGDL* NullGDL::XorOpSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 69.");} BaseGDL* NullGDL::AddSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 70.");} // implemented BaseGDL* NullGDL::AddInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 71.");} // implemented BaseGDL* NullGDL::SubSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 73.");} BaseGDL* NullGDL::SubInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 74.");} BaseGDL* NullGDL::LtMarkSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 75.");} BaseGDL* NullGDL::GtMarkSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 76.");} BaseGDL* NullGDL::MultSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 77.");} // implemented BaseGDL* NullGDL::DivSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 78.");} BaseGDL* NullGDL::DivInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 79.");} BaseGDL* NullGDL::ModSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 80.");} BaseGDL* NullGDL::ModInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 81.");} BaseGDL* NullGDL::PowSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 82.");} BaseGDL* NullGDL::PowInvSNew( BaseGDL* r) { throw GDLException("Operation not defined for !NULL 83.");} gdl-0.9.9/src/nullgdl.hpp000066400000000000000000000322231340051421000152300ustar00rootroot00000000000000/*************************************************************************** nullgdl.hpp - class for !NULL object ------------------- begin : July 22 2012 copyright : (C) 2012 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef NULLGDL_HPP_ #define NULLGDL_HPP_ #include "basegdl.hpp" // !NULL is a singleton class NullGDL: public BaseGDL { private: static NullGDL* instance; static char buf[]; NullGDL(): BaseGDL() {} ~NullGDL(); // virtual due to base class -> can be called nevertheless (but this would be an error here) public: void* operator new( size_t bytes, char* cP) { assert( bytes == sizeof( NullGDL)); return NullGDL::buf; } void* operator new( size_t bytes) { assert( bytes == sizeof( NullGDL)); return NullGDL::buf; } void operator delete( void *ptr) { // do nothing } static NullGDL* GetSingleInstance() { if( instance == NULL) instance = new (NullGDL::buf) NullGDL(); return instance; } static bool IsNULLorNullGDL( BaseGDL* p) { // works for uninitialized !NULL as well // if not instantiated yet, instance is NULL // if p is !NULL, instance must be initialized // even then we save one comparison (for instance == NULL) return (p == NULL) || (p == instance); } // private: /*virtual*/ BaseGDL& operator=(const BaseGDL& right); // public: /*virtual*/ void InitFrom(const BaseGDL& right); // for structs // /*virtual*/ functions /*virtual*/ bool IsAssoc() const; /*virtual*/ BaseGDL* AssocVar( int, SizeT); /*virtual*/ SizeT N_Elements() const; // number of elements /*virtual*/ SizeT Size() const; // size (= N_Elements, but 0 for BaseGDL) /*virtual*/ SizeT NBytes() const; // total bytes of data /*virtual*/ SizeT ToTransfer() const; // elements to transfer /*virtual*/ SizeT Sizeof() const; // size of scalar data /*virtual*/ BaseGDL* Transpose( DUInt* perm); /*virtual*/ BaseGDL* Rotate( DLong dir); /*virtual*/ void Reverse( DLong dim); /*virtual*/ BaseGDL* DupReverse( DLong dim); /*virtual*/ void MinMax( DLong* minE, DLong* maxE, BaseGDL** minVal, BaseGDL** maxVal, bool omitNaN, SizeT start = 0, SizeT stop = 0, SizeT step = 1, DLong valIx = -1, bool useAbs = false); /*virtual*/ void Clear(); /*virtual*/ void Construct(); /*virtual*/ void ConstructTo0(); /*virtual*/ void Destruct(); /*virtual*/ std::ostream& Write( std::ostream& os, bool swapEndian, bool compress, XDR *xdrs); /*virtual*/ std::istream& Read( std::istream& os, bool swapEndian, bool compress, XDR *xdrs); /*virtual*/ std::ostream& ToStream(std::ostream& o, SizeT width = 0, SizeT* actPosPtr = NULL); /*virtual*/ std::istream& FromStream(std::istream& i); /*virtual*/ bool Greater(SizeT i1, SizeT i2) const; // comp 2 elements /*virtual*/ bool Equal(SizeT i1, SizeT i2) const; // comp 2 elements /*virtual*/ BaseGDL* CShift( DLong d) const; // circular shift /*virtual*/ BaseGDL* CShift( DLong d[MAXRANK]) const; // circular shift multi dim /*virtual*/ bool Scalar() const; /*virtual*/ bool StrictScalar() const; /*virtual*/ DType Type() const; /*virtual*/ const std::string& TypeStr() const; /*virtual*/ bool EqType( const BaseGDL*) const; /*virtual*/ void* DataAddr();// SizeT elem=0); /*virtual*/ BaseGDL* New( const dimension& dim_, InitType noZero=ZERO) const; /*virtual*/ BaseGDL* NewResult() const; /*virtual*/ BaseGDL* Dup() const; // /*virtual*/ BaseGDL* Dup( char*) const; /*virtual*/ BaseGDL* Convert2( DType destTy, Convert2Mode mode=CONVERT); /*virtual*/ BaseGDL* GetTag() const; /*virtual*/ BaseGDL* GetInstance() const; /*virtual*/ BaseGDL* GetEmptyInstance() const; /*virtual*/ BaseGDL* SetBuffer( const void* b); /*virtual*/ void SetBufferSize( SizeT s); /*virtual*/ int Scalar2Index(SizeT& ret) const; /*virtual*/ int Scalar2RangeT(RangeT& ret) const; /*virtual*/ SizeT GetAsIndex( SizeT i) const; /*virtual*/ SizeT GetAsIndexStrict( SizeT i) const; /*virtual*/ RangeT LoopIndex() const; /*virtual*/ DDouble HashValue() const; /*virtual*/ bool True(); /*virtual*/ bool False(); /*virtual*/ bool LogTrue(); /*virtual*/ bool LogTrue( SizeT ix); /*virtual*/ void Where(DLong* &ret, SizeT &passed_count, bool comp, DLong* &comp_ret); /*virtual*/ void Where(DLong64* &ret, SizeT &passed_count, bool comp, DLong64* &comp_ret); /*virtual*/ BaseGDL* LogNeg(); /*virtual*/ int Sgn(); // -1,0,1 /*virtual*/ bool Equal( BaseGDL*) const; /*virtual*/ bool EqualNoDelete( const BaseGDL*) const; /*virtual*/ bool ArrayEqual( BaseGDL*); // for statement compliance (int types , float types scalar only) /*virtual*/ void ForCheck( BaseGDL**, BaseGDL** = NULL); /*virtual*/ bool ForCondUp( BaseGDL*); /*virtual*/ bool ForCondDown( BaseGDL*); /*virtual*/ bool ForAddCondUp( BaseGDL* loopInfo); // /*virtual*/ bool ForAddCondUp( ForLoopInfoT& loopInfo); // /*virtual*/ bool ForAddCondDown( ForLoopInfoT& loopInfo); // /*virtual*/ bool ForCondUpDown( BaseGDL*); /*virtual*/ void ForAdd( BaseGDL* add=NULL); /*virtual*/ BaseGDL* CatArray( ExprListT& exprList, const SizeT catRank, const SizeT rank); /*virtual*/ BaseGDL* Index( ArrayIndexListT* ixList); // /*virtual*/ BaseGDL* Abs() const; // return a new type of itself /*virtual*/ BaseGDL* NewIx( SizeT ix); /*virtual*/ BaseGDL* NewIx( BaseGDL* ix, bool strict); /*virtual*/ BaseGDL* NewIx( AllIxBaseT* ix, const dimension* dIn); /*virtual*/ BaseGDL* NewIxFrom( SizeT s); /*virtual*/ BaseGDL* NewIxFrom( SizeT s, SizeT e); /*virtual*/ BaseGDL* NewIxFromStride( SizeT s, SizeT stride); /*virtual*/ BaseGDL* NewIxFromStride( SizeT s, SizeT e, SizeT stride); // library functions /*virtual*/ BaseGDL* Convol( BaseGDL* kIn, BaseGDL* scaleIn, BaseGDL* bias, bool center, bool normalize, int edgeMode, bool doNan, BaseGDL* missing, bool doMissing, BaseGDL* invalid, bool doInvalid); /*virtual*/ BaseGDL* Smooth( DLong* width, int edgeMode, bool doNan, BaseGDL* missing); /*virtual*/ BaseGDL* Rebin( const dimension& newDim, bool sample); // for STRUCT_ASSIGN /*virtual*/ void Assign( BaseGDL* src, SizeT nEl); /*virtual*/ BaseGDL* Log(); /*virtual*/ BaseGDL* LogThis(); /*virtual*/ BaseGDL* Log10(); /*virtual*/ BaseGDL* Log10This(); // defined in basic_op.cpp // used in r_expr /*virtual*/ BaseGDL* UMinus(); /*virtual*/ BaseGDL* NotOp(); /*virtual*/ BaseGDL* AndOp( BaseGDL* r); /*virtual*/ BaseGDL* AndOpInv( BaseGDL* r); /*virtual*/ BaseGDL* OrOp( BaseGDL* r); /*virtual*/ BaseGDL* OrOpInv( BaseGDL* r); /*virtual*/ BaseGDL* XorOp( BaseGDL* r); /*virtual*/ BaseGDL* EqOp( BaseGDL* r); /*virtual*/ BaseGDL* NeOp( BaseGDL* r); /*virtual*/ BaseGDL* LeOp( BaseGDL* r); /*virtual*/ BaseGDL* GeOp( BaseGDL* r); /*virtual*/ BaseGDL* LtOp( BaseGDL* r); /*virtual*/ BaseGDL* GtOp( BaseGDL* r); /*virtual*/ BaseGDL* Add( BaseGDL* r); /*virtual*/ BaseGDL* AddInv( BaseGDL* r); /*virtual*/ BaseGDL* Sub( BaseGDL* r); /*virtual*/ BaseGDL* SubInv( BaseGDL* r); /*virtual*/ BaseGDL* LtMark( BaseGDL* r); /*virtual*/ BaseGDL* GtMark( BaseGDL* r); /*virtual*/ BaseGDL* Mult( BaseGDL* r); /*virtual*/ BaseGDL* Div( BaseGDL* r); /*virtual*/ BaseGDL* DivInv( BaseGDL* r); /*virtual*/ BaseGDL* Mod( BaseGDL* r); /*virtual*/ BaseGDL* ModInv( BaseGDL* r); /*virtual*/ BaseGDL* Pow( BaseGDL* r); /*virtual*/ BaseGDL* PowInv( BaseGDL* r); /*virtual*/ BaseGDL* PowInt( BaseGDL* r); /*virtual*/ BaseGDL* AndOpS( BaseGDL* r); /*virtual*/ BaseGDL* AndOpInvS( BaseGDL* r); /*virtual*/ BaseGDL* OrOpS( BaseGDL* r); /*virtual*/ BaseGDL* OrOpInvS( BaseGDL* r); /*virtual*/ BaseGDL* XorOpS( BaseGDL* r); /*virtual*/ BaseGDL* AddS( BaseGDL* r); /*virtual*/ BaseGDL* AddInvS( BaseGDL* r); /*virtual*/ BaseGDL* SubS( BaseGDL* r); /*virtual*/ BaseGDL* SubInvS( BaseGDL* r); /*virtual*/ BaseGDL* LtMarkS( BaseGDL* r); /*virtual*/ BaseGDL* GtMarkS( BaseGDL* r); /*virtual*/ BaseGDL* MultS( BaseGDL* r); /*virtual*/ BaseGDL* DivS( BaseGDL* r); /*virtual*/ BaseGDL* DivInvS( BaseGDL* r); /*virtual*/ BaseGDL* ModS( BaseGDL* r); /*virtual*/ BaseGDL* ModInvS( BaseGDL* r); /*virtual*/ BaseGDL* PowS( BaseGDL* r); /*virtual*/ BaseGDL* PowInvS( BaseGDL* r); // the New functions // defined in basic_op_new.cpp // results go into a new DataT /*virtual*/ BaseGDL* AndOpNew( BaseGDL* r); /*virtual*/ BaseGDL* AndOpInvNew( BaseGDL* r); /*virtual*/ BaseGDL* OrOpNew( BaseGDL* r); /*virtual*/ BaseGDL* OrOpInvNew( BaseGDL* r); /*virtual*/ BaseGDL* XorOpNew( BaseGDL* r); // /*virtual*/ BaseGDL* EqOpNew( BaseGDL* r); // /*virtual*/ BaseGDL* NeOpNew( BaseGDL* r); // /*virtual*/ BaseGDL* LeOpNew( BaseGDL* r); // /*virtual*/ BaseGDL* GeOpNew( BaseGDL* r); // /*virtual*/ BaseGDL* LtOpNew( BaseGDL* r); // /*virtual*/ BaseGDL* GtOpNew( BaseGDL* r); /*virtual*/ BaseGDL* AddNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* AddInvNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* SubNew( BaseGDL* r); /*virtual*/ BaseGDL* SubInvNew( BaseGDL* r); /*virtual*/ BaseGDL* LtMarkNew( BaseGDL* r); /*virtual*/ BaseGDL* GtMarkNew( BaseGDL* r); /*virtual*/ BaseGDL* MultNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* DivNew( BaseGDL* r); /*virtual*/ BaseGDL* DivInvNew( BaseGDL* r); /*virtual*/ BaseGDL* ModNew( BaseGDL* r); /*virtual*/ BaseGDL* ModInvNew( BaseGDL* r); /*virtual*/ BaseGDL* PowNew( BaseGDL* r); /*virtual*/ BaseGDL* PowInvNew( BaseGDL* r); /*virtual*/ BaseGDL* PowIntNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* AndOpSNew( BaseGDL* r); /*virtual*/ BaseGDL* AndOpInvSNew( BaseGDL* r); /*virtual*/ BaseGDL* OrOpSNew( BaseGDL* r); /*virtual*/ BaseGDL* OrOpInvSNew( BaseGDL* r); /*virtual*/ BaseGDL* XorOpSNew( BaseGDL* r); /*virtual*/ BaseGDL* AddSNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* AddInvSNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* SubSNew( BaseGDL* r); /*virtual*/ BaseGDL* SubInvSNew( BaseGDL* r); /*virtual*/ BaseGDL* LtMarkSNew( BaseGDL* r); /*virtual*/ BaseGDL* GtMarkSNew( BaseGDL* r); /*virtual*/ BaseGDL* MultSNew( BaseGDL* r); // implemented /*virtual*/ BaseGDL* DivSNew( BaseGDL* r); /*virtual*/ BaseGDL* DivInvSNew( BaseGDL* r); /*virtual*/ BaseGDL* ModSNew( BaseGDL* r); /*virtual*/ BaseGDL* ModInvSNew( BaseGDL* r); /*virtual*/ BaseGDL* PowSNew( BaseGDL* r); /*virtual*/ BaseGDL* PowInvSNew( BaseGDL* r); // /*virtual*/ BaseGDL* PowInvNew( BaseGDL* r); /*virtual*/ BaseGDL* MatrixOp( BaseGDL* r, bool atranspose, bool btranspose); /*virtual*/ void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList, SizeT offset); /*virtual*/ void AssignAt( BaseGDL* srcIn, ArrayIndexListT* ixList); /*virtual*/ void AssignAt( BaseGDL* srcIn); /*virtual*/ void AssignAtIx( RangeT ix, BaseGDL* srcIn); /*virtual*/ void DecAt( ArrayIndexListT* ixList); /*virtual*/ void IncAt( ArrayIndexListT* ixList); /*virtual*/ void Dec(); /*virtual*/ void Inc(); /*virtual*/ void InsertAt( SizeT offset, BaseGDL* srcIn, ArrayIndexListT* ixList); // /*virtual*/ formatting output functions /*virtual*/ SizeT OFmtA( std::ostream* os, SizeT offset, SizeT num, int width); /*virtual*/ SizeT OFmtF( std::ostream* os, SizeT offs, SizeT num, int width, int prec, const int code, BaseGDL::IOMode oM = FIXED); /*virtual*/ SizeT OFmtI( std::ostream* os, SizeT offs, SizeT num, int width, int minN, int code, BaseGDL::IOMode oM = DEC); /*virtual*/ SizeT OFmtCal( std::ostream* os, SizeT offs, SizeT num, int width, int minN, char *fill, BaseGDL::Cal_IOMode oM = BaseGDL::DEFAULT); /*virtual*/ SizeT IFmtA( std::istream* is, SizeT offset, SizeT num, int width); /*virtual*/ SizeT IFmtF( std::istream* is, SizeT offs, SizeT num, int width); /*virtual*/ SizeT IFmtI( std::istream* is, SizeT offs, SizeT num, int width, BaseGDL::IOMode oM = DEC); /*virtual*/ SizeT IFmtCal( std::istream* is, SizeT offs, SizeT r, int width, BaseGDL::Cal_IOMode cMode); #if defined(USE_PYTHON) || defined(PYTHON_MODULE) /*virtual*/ PyObject* ToPython(); #endif }; // class NullGDL #endif gdl-0.9.9/src/objects.cpp000066400000000000000000001041621340051421000152150ustar00rootroot00000000000000/*************************************************************************** objects.cpp - global structures ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include #include "str.hpp" #include "gdlexception.hpp" #include "initsysvar.hpp" #include "dnodefactory.hpp" #include "objects.hpp" #include "graphicsdevice.hpp" #include "overload.hpp" //#include "dinterpreter.hpp" #ifdef _OPENMP #include #endif #ifdef HAVE_LIBWXWIDGETS #include "gdlwidget.hpp" #endif #ifdef USE_PYTHON #include "gdlpython.hpp" #endif using namespace std; // DInterpreter* interpreter = NULL; // instantiate the global lists VarListT sysVarList; VarListT sysVarRdOnlyList; FunListT funList; ProListT proList; LibFunListT libFunList; LibProListT libProList; CommonListT commonList; StructListT structList; GDLFileListT fileUnits; // flag for control-c volatile bool sigControlC; int debugMode; bool strictInterpreter; // global garbage collection flag in support of HEAP_REFCOUNT: static bool enabled_GC=true; bool IsEnabledGC() // Referenced from GDLInterpreter.hpp { return enabled_GC; } void EnableGC( bool set=true) // same names, many contexts. { enabled_GC = set; } namespace structDesc { // set in InitStructs() DStructDesc* LIST = NULL; DStructDesc* HASH = NULL; DStructDesc* GDL_CONTAINER = NULL; DStructDesc* GDL_CONTAINER_NODE = NULL; DStructDesc* GDL_HASHTABLEENTRY = NULL; } // for OpenMP DLong CpuTPOOL_NTHREADS; DLong64 CpuTPOOL_MIN_ELTS; DLong64 CpuTPOOL_MAX_ELTS; const DLong64 CpuTPOOL_MAX_ELTS_max = numeric_limits::max(); // instantiate own AST factory //_DNodeFactory DNodeFactory; antlr::ASTFactory DNodeFactory("DNode",DNode::factory); //do we use WxWidgets for graphics? volatile bool useWxWidgetsForGraphics; //do we favor SIMD-accelerated random number generation? volatile bool useDSFMTAcceleration; void ResetObjects() { #ifdef HAVE_LIBWXWIDGETS // un-initialize widget system GDLWidget::UnInit(); #endif GraphicsDevice::DestroyDevices(); fileUnits.clear(); cerr << flush; cout << flush; clog << flush; PurgeContainer(sysVarList); // sysVarRdOnlyList.clear(); // data is owned by sysVarList PurgeContainer(funList); PurgeContainer(proList); // delete common block data (which might be of type STRUCT) CommonListT::iterator i; for(i = commonList.begin(); i != commonList.end(); ++i) { (*i)->DeleteData();} PurgeContainer(structList); // now deletes member subroutines (and they in turn common block references) // hence delete common blocks after structList // should be ok now as data is already deleted //avoid purging commonlist-->crash (probably some COMMON structures already destroyed) PurgeContainer(commonList); // don't purge library here // PurgeContainer(libFunList); // PurgeContainer(libProList); #ifdef USE_PYTHON PythonEnd(); #endif } // initialize struct descriptors which are not system variables void InitStructs() { SpDInt aInt; SpDLong aLong; SpDString aString; SpDByte aByte; SpDULong aULong; SpDLong64 aLong64; SpDFloat aFloat; SpDDouble aDouble; SpDComplex aComplex; SpDComplexDbl aComplexDbl; // SpDStruct aStruct; //protected, we cannot use? SpDInt aColor( dimension(3)); SpDLong aLongArr8( dimension(8)); SpDLong64 aLong64Arr8( dimension(8)); SpDPtr aPtrRef; SpDObj aObjRef; SpDUInt auInt; SpDULong auLong; SpDULong64 auLong64; // OBJECTS ================================================= //A structure where objects are in the order of GDL Typecodes. Useful. DStructDesc* gdltypecodes = new DStructDesc("GDL_TYPECODES_AS_STRUCT"); gdltypecodes->AddTag("GDL_UNDEF", &aInt ); //Danger! // 0 Undefined value, the default for new symbols gdltypecodes->AddTag("GDL_BYTE", &aByte ); // 1 byte gdltypecodes->AddTag("GDL_INT", &aInt ); // 2 Integer scalar gdltypecodes->AddTag("GDL_LONG", &aLong ); // 3 long Integer scalar gdltypecodes->AddTag("GDL_FLOAT", &aFloat ); // 4 Real scalar gdltypecodes->AddTag("GDL_DOUBLE", &aDouble ); // 5 Double scalar gdltypecodes->AddTag("GDL_COMPLEX", &aComplex ); // 6 Complex scalar gdltypecodes->AddTag("GDL_STRING", &aString ); // 7 String gdltypecodes->AddTag("GDL_STRUCT", &aInt ); //Danger // 8 Struct gdltypecodes->AddTag("GDL_COMPLEXDBL", &aComplexDbl ); // 9 Complex double gdltypecodes->AddTag("GDL_PTR", &aPtrRef ); // 10 Pointer gdltypecodes->AddTag("GDL_OBJ", &aObjRef ); // 11 Object reference gdltypecodes->AddTag("GDL_UINT", &auInt ); // 12 unsigned int gdltypecodes->AddTag("GDL_ULONG", &auLong ); // 13 unsigned long int gdltypecodes->AddTag("GDL_LONG64", &aLong64 ); // 14 64 bit integer gdltypecodes->AddTag("GDL_ULONG64", &auLong64 ); // 15 unsigned 64 bit integer // insert into structList structList.push_back(gdltypecodes); DStructDesc* gdl_object = new DStructDesc( GDL_OBJECT_NAME); gdl_object->AddTag("GDL_OBJ_TOP", &aLong64); gdl_object->AddTag("__OBJ__", &aObjRef); gdl_object->AddTag("GDL_OBJ_BOTTOM", &aLong64); // special for GDL_OBJECT ony gdl_object->InitOperatorList(); // insert into structList structList.push_back(gdl_object); DStructDesc* gdlList = new DStructDesc( "LIST"); gdlList->AddTag("GDL_CONTAINER_TOP", &aLong64); gdlList->AddTag("GDLCONTAINERVERSION", &aInt); gdlList->AddTag("PHEAD", &aPtrRef); gdlList->AddTag("PTAIL", &aPtrRef); gdlList->AddTag("NLIST", &aLong); gdlList->AddTag("GDL_CONTAINER_BOTTOM", &aLong64); // use operator overloading (note: gdl_object's operators are not set yet) gdlList->AddParent(gdl_object); // insert into structList structList.push_back(gdlList); structDesc::LIST = gdlList; DStructDesc* gdlContainerNode = new DStructDesc( "GDL_CONTAINER_NODE"); gdlContainerNode->AddTag("PNEXT", &aPtrRef); gdlContainerNode->AddTag("PDATA", &aPtrRef); // gdlContainerNode->AddTag("OOBJ", &aObjRef); // gdlContainerNode->AddTag("FLAGS", &aLong); // insert into structList structList.push_back(gdlContainerNode); structDesc::GDL_CONTAINER_NODE = gdlContainerNode; DStructDesc* gdlContainer = new DStructDesc( GDL_CONTAINER_NAME); gdlContainer->AddTag("GDL_CONTAINER_TOP", &aLong64); gdlContainer->AddTag("GDLCONTAINERVERSION", &aInt); gdlContainer->AddTag("PHEAD", &aPtrRef); gdlContainer->AddTag("PTAIL", &aPtrRef); gdlContainer->AddTag("NLIST", &aLong); gdlContainer->AddTag("GDL_CONTAINER_BOTTOM", &aLong64); // gdlContainer->AddParent(gdl_object);// no operator overloading structList.push_back(gdlContainer); structDesc::GDL_CONTAINER = gdlContainer; DStructDesc* gdlHash = new DStructDesc( "HASH"); gdlHash->AddTag("TABLE_BITS", &aULong); gdlHash->AddTag("TABLE_SIZE", &aULong); gdlHash->AddTag("TABLE_COUNT", &aULong); gdlHash->AddTag("TABLE_REMOVE", &aULong); gdlHash->AddTag("TABLE_FOREACH", &aULong); gdlHash->AddTag("TABLE_DATA", &aPtrRef); // use operator overloading (note: gdl_object's operators are not set yet) gdlHash->AddParent(gdl_object); // insert into structList structList.push_back(gdlHash); structDesc::HASH = gdlHash; DStructDesc* gdlHashTE = new DStructDesc( "GDL_HASHTABLEENTRY"); gdlHashTE->AddTag("PKEY", &aPtrRef); gdlHashTE->AddTag("PVALUE", &aPtrRef); // insert into structList structList.push_back(gdlHashTE); structDesc::GDL_HASHTABLEENTRY = gdlHashTE; // OBJECTS END ======================================================= for (int big = 1; big >= 0; --big) { DStructDesc* gdl_size = new DStructDesc( big ? "IDL_SIZE64" : "IDL_SIZE"); gdl_size->AddTag("TYPE_NAME", &aString); gdl_size->AddTag("STRUCTURE_NAME", &aString); gdl_size->AddTag("TYPE", &aInt); gdl_size->AddTag("FILE_LUN", &aInt); if (big) { gdl_size->AddTag("FILE_OFFSET", &aLong64); gdl_size->AddTag("N_ELEMENTS", &aLong64); } else { gdl_size->AddTag("FILE_OFFSET", &aLong); gdl_size->AddTag("N_ELEMENTS", &aLong); } gdl_size->AddTag("N_DIMENSIONS", &aLong); if (big) { gdl_size->AddTag("DIMENSIONS", &aLong64Arr8); } else { gdl_size->AddTag("DIMENSIONS", &aLongArr8); } // insert into structList structList.push_back(gdl_size); } for (int big = 1; big >= 0; --big) { DStructDesc* fstat = new DStructDesc( big ? "FSTAT64" : "FSTAT"); fstat->AddTag("UNIT", &aLong); fstat->AddTag("NAME", &aString); fstat->AddTag("OPEN", &aByte); fstat->AddTag("ISATTY", &aByte); fstat->AddTag("ISAGUI", &aByte); fstat->AddTag("INTERACTIVE", &aByte); fstat->AddTag("XDR", &aByte); fstat->AddTag("COMPRESS", &aByte); fstat->AddTag("READ", &aByte); fstat->AddTag("WRITE", &aByte); fstat->AddTag("ATIME", &aLong64); fstat->AddTag("CTIME", &aLong64); fstat->AddTag("MTIME", &aLong64); if (big) { fstat->AddTag("TRANSFER_COUNT", &aLong64); fstat->AddTag("CUR_PTR", &aLong64); fstat->AddTag("SIZE", &aLong64); fstat->AddTag("REC_LEN", &aLong64); } else { fstat->AddTag("TRANSFER_COUNT", &aLong); fstat->AddTag("CUR_PTR", &aLong); fstat->AddTag("SIZE", &aLong); fstat->AddTag("REC_LEN", &aLong); } // insert into structList structList.push_back( fstat); } DStructDesc* finfo = new DStructDesc("FILE_INFO"); finfo->AddTag("NAME", &aString); finfo->AddTag("EXISTS", &aByte); finfo->AddTag("READ", &aByte); finfo->AddTag("WRITE", &aByte); finfo->AddTag("EXECUTE", &aByte); finfo->AddTag("REGULAR", &aByte); finfo->AddTag("DIRECTORY", &aByte); finfo->AddTag("BLOCK_SPECIAL", &aByte); finfo->AddTag("CHARACTER_SPECIAL", &aByte); finfo->AddTag("NAMED_PIPE", &aByte); finfo->AddTag("SETUID", &aByte); finfo->AddTag("SETGID", &aByte); finfo->AddTag("SOCKET", &aByte); finfo->AddTag("STICKY_BIT", &aByte); finfo->AddTag("SYMLINK", &aByte); finfo->AddTag("DANGLING_SYMLINK", &aByte); finfo->AddTag("MODE", &aLong); finfo->AddTag("ATIME", &aLong64); finfo->AddTag("CTIME", &aLong64); finfo->AddTag("MTIME", &aLong64); finfo->AddTag("SIZE", &aLong64); // insert into structList structList.push_back( finfo); DStructDesc* memory = new DStructDesc("IDL_MEMORY"); memory->AddTag("CURRENT", &aLong); memory->AddTag("NUM_ALLOC", &aLong); memory->AddTag("NUM_FREE", &aLong); memory->AddTag("HIGHWATER", &aLong); // insert into structList structList.push_back(memory); DStructDesc* memory64 = new DStructDesc("IDL_MEMORY64"); memory64->AddTag("CURRENT", &aLong64); memory64->AddTag("NUM_ALLOC", &aLong64); memory64->AddTag("NUM_FREE", &aLong64); memory64->AddTag("HIGHWATER", &aLong64); // insert into structList structList.push_back(memory64); DStructDesc* machar = new DStructDesc( "MACHAR"); machar->AddTag("IBETA", &aLong); machar->AddTag("IT", &aLong); machar->AddTag("IRND", &aLong); machar->AddTag("NGRD", &aLong); machar->AddTag("MACHEP", &aLong); machar->AddTag("NEGEP", &aLong); machar->AddTag("IEXP", &aLong); machar->AddTag("MINEXP", &aLong); machar->AddTag("MAXEXP", &aLong); machar->AddTag("EPS", &aFloat); machar->AddTag("EPSNEG", &aFloat); machar->AddTag("XMIN", &aFloat); machar->AddTag("XMAX", &aFloat); // insert into structList structList.push_back( machar); DStructDesc* dmachar = new DStructDesc( "DMACHAR"); dmachar->AddTag("IBETA", &aLong); dmachar->AddTag("IT", &aLong); dmachar->AddTag("IRND", &aLong); dmachar->AddTag("NGRD", &aLong); dmachar->AddTag("MACHEP", &aLong); dmachar->AddTag("NEGEP", &aLong); dmachar->AddTag("IEXP", &aLong); dmachar->AddTag("MINEXP", &aLong); dmachar->AddTag("MAXEXP", &aLong); dmachar->AddTag("EPS", &aDouble); dmachar->AddTag("EPSNEG", &aDouble); dmachar->AddTag("XMIN", &aDouble); dmachar->AddTag("XMAX", &aDouble); // insert into structList structList.push_back( dmachar); // for internal usage. make event handler destroy the TLB widget // attention: $WIDGET_DESTROY would identify this as an unnamed struct // see DStructDesc constructor DStructDesc* widgdestroy = new DStructDesc( "*WIDGET_DESTROY*"); widgdestroy->AddTag("ID", &aLong); widgdestroy->AddTag("TOP", &aLong); widgdestroy->AddTag("HANDLER", &aLong); widgdestroy->AddTag("MESSAGE", &aLong); // insert into structList structList.push_back( widgdestroy); // for internal usage. make event handler exit form event loop on TLB destruction without destroying (again) the TLB widget DStructDesc* toplevelISdestroyed = new DStructDesc( "*TOPLEVEL_DESTROYED*"); toplevelISdestroyed->AddTag("ID", &aLong); toplevelISdestroyed->AddTag("TOP", &aLong); toplevelISdestroyed->AddTag("HANDLER", &aLong); toplevelISdestroyed->AddTag("MESSAGE", &aLong); // insert into structList structList.push_back( toplevelISdestroyed); DStructDesc* widgbut = new DStructDesc( "WIDGET_BUTTON"); widgbut->AddTag("ID", &aLong); widgbut->AddTag("TOP", &aLong); widgbut->AddTag("HANDLER", &aLong); widgbut->AddTag("SELECT", &aLong); // insert into structList structList.push_back( widgbut); DStructDesc* widgdlist = new DStructDesc( "WIDGET_DROPLIST"); widgdlist->AddTag("ID", &aLong); widgdlist->AddTag("TOP", &aLong); widgdlist->AddTag("HANDLER", &aLong); widgdlist->AddTag("INDEX", &aLong); // insert into structList structList.push_back( widgdlist); DStructDesc* widgcbox = new DStructDesc( "WIDGET_COMBOBOX"); widgcbox->AddTag("ID", &aLong); widgcbox->AddTag("TOP", &aLong); widgcbox->AddTag("HANDLER", &aLong); widgcbox->AddTag("INDEX", &aLong); widgcbox->AddTag("STR", &aString); // insert into structList structList.push_back( widgcbox); DStructDesc* widglist = new DStructDesc( "WIDGET_LIST"); widglist->AddTag("ID", &aLong); widglist->AddTag("TOP", &aLong); widglist->AddTag("HANDLER", &aLong); widglist->AddTag("INDEX", &aLong); widglist->AddTag("CLICKS", &aLong); // insert into structList structList.push_back( widglist); DStructDesc* widgdtab = new DStructDesc( "WIDGET_TAB"); widgdtab->AddTag("ID", &aLong); widgdtab->AddTag("TOP", &aLong); widgdtab->AddTag("HANDLER", &aLong); widgdtab->AddTag("TAB", &aLong); // insert into structList structList.push_back( widgdtab); DStructDesc* widgdsl = new DStructDesc( "WIDGET_SLIDER"); widgdsl->AddTag("ID", &aLong); widgdsl->AddTag("TOP", &aLong); widgdsl->AddTag("HANDLER", &aLong); widgdsl->AddTag("VALUE", &aLong); widgdsl->AddTag("DRAG", &aInt); // insert into structList structList.push_back( widgdsl); DStructDesc* widgbgroup = new DStructDesc( "WIDGET_BGROUP"); widgbgroup->AddTag("ID", &aLong); widgbgroup->AddTag("TOP", &aLong); widgbgroup->AddTag("HANDLER", &aLong); widgbgroup->AddTag("SELECT", &aLong); widgbgroup->AddTag("VALUE", &aLong); // insert into structList structList.push_back(widgbgroup); DStructDesc* widgtxtc = new DStructDesc( "WIDGET_TEXT_CH"); widgtxtc->AddTag("ID", &aLong); widgtxtc->AddTag("TOP", &aLong); widgtxtc->AddTag("HANDLER", &aLong); widgtxtc->AddTag("TYPE", &aInt); // 0 widgtxtc->AddTag("OFFSET", &aLong); widgtxtc->AddTag("CH", &aByte); // insert into structList structList.push_back( widgtxtc); DStructDesc* widgtablec = new DStructDesc( "WIDGET_TABLE_CH"); widgtablec->AddTag("ID", &aLong); widgtablec->AddTag("TOP", &aLong); widgtablec->AddTag("HANDLER", &aLong); widgtablec->AddTag("TYPE", &aInt); // 0 widgtablec->AddTag("OFFSET", &aLong); widgtablec->AddTag("CH", &aByte); widgtablec->AddTag("X", &aLong); widgtablec->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtablec); DStructDesc* widgtxtst = new DStructDesc( "WIDGET_TEXT_STR"); widgtxtst->AddTag("ID", &aLong); widgtxtst->AddTag("TOP", &aLong); widgtxtst->AddTag("HANDLER", &aLong); widgtxtst->AddTag("TYPE", &aInt); // 1 widgtxtst->AddTag("OFFSET", &aLong); widgtxtst->AddTag("STR", &aString); // insert into structList structList.push_back( widgtxtst); DStructDesc* widgtablest = new DStructDesc( "WIDGET_TABLE_STR"); widgtablest->AddTag("ID", &aLong); widgtablest->AddTag("TOP", &aLong); widgtablest->AddTag("HANDLER", &aLong); widgtablest->AddTag("TYPE", &aInt); // 1 widgtablest->AddTag("OFFSET", &aLong); widgtablest->AddTag("STR", &aString); widgtablest->AddTag("X", &aLong); widgtablest->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtablest); DStructDesc* widgtxts = new DStructDesc( "WIDGET_TEXT_SEL"); widgtxts->AddTag("ID", &aLong); widgtxts->AddTag("TOP", &aLong); widgtxts->AddTag("HANDLER", &aLong); widgtxts->AddTag("TYPE", &aInt); // 3 widgtxts->AddTag("OFFSET", &aLong); widgtxts->AddTag("LENGTH", &aLong); // insert into structList structList.push_back( widgtxts); DStructDesc* widgtablesel = new DStructDesc( "WIDGET_TABLE_TEXT_SEL"); widgtablesel->AddTag("ID", &aLong); widgtablesel->AddTag("TOP", &aLong); widgtablesel->AddTag("HANDLER", &aLong); widgtablesel->AddTag("TYPE", &aInt); // 3 widgtablesel->AddTag("OFFSET", &aLong); widgtablesel->AddTag("LENGTH", &aLong); widgtablesel->AddTag("X", &aLong); widgtablesel->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtablesel); DStructDesc* widgtablecelsel = new DStructDesc( "WIDGET_TABLE_CELL_SEL"); widgtablecelsel->AddTag("ID", &aLong); widgtablecelsel->AddTag("TOP", &aLong); widgtablecelsel->AddTag("HANDLER", &aLong); widgtablecelsel->AddTag("TYPE", &aInt); // 4 widgtablecelsel->AddTag("SEL_LEFT", &aLong); widgtablecelsel->AddTag("SEL_TOP", &aLong); widgtablecelsel->AddTag("SEL_RIGHT", &aLong); widgtablecelsel->AddTag("SEL_BOTTOM", &aLong); // insert into structList structList.push_back( widgtablecelsel); DStructDesc* widgtableceldesel = new DStructDesc( "WIDGET_TABLE_CELL_DESEL"); widgtableceldesel->AddTag("ID", &aLong); widgtableceldesel->AddTag("TOP", &aLong); widgtableceldesel->AddTag("HANDLER", &aLong); widgtableceldesel->AddTag("TYPE", &aInt); // 9 widgtableceldesel->AddTag("SEL_LEFT", &aLong); widgtableceldesel->AddTag("SEL_TOP", &aLong); widgtableceldesel->AddTag("SEL_RIGHT", &aLong); widgtableceldesel->AddTag("SEL_BOTTOM", &aLong); // insert into structList structList.push_back( widgtableceldesel); DStructDesc* widgtxtd = new DStructDesc( "WIDGET_TEXT_DEL"); widgtxtd->AddTag("ID", &aLong); widgtxtd->AddTag("TOP", &aLong); widgtxtd->AddTag("HANDLER", &aLong); widgtxtd->AddTag("TYPE", &aInt); // 2 widgtxtd->AddTag("OFFSET", &aLong); widgtxtd->AddTag("LENGTH", &aLong); // insert into structList structList.push_back( widgtxtd); DStructDesc* widgtabled = new DStructDesc( "WIDGET_TABLE_DEL"); widgtabled->AddTag("ID", &aLong); widgtabled->AddTag("TOP", &aLong); widgtabled->AddTag("HANDLER", &aLong); widgtabled->AddTag("TYPE", &aInt); // 2 widgtabled->AddTag("OFFSET", &aLong); widgtabled->AddTag("LENGTH", &aLong); widgtabled->AddTag("X", &aLong); widgtabled->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtabled); DStructDesc* widgtablerowheight = new DStructDesc( "WIDGET_TABLE_ROW_HEIGHT"); widgtablerowheight->AddTag("ID", &aLong); widgtablerowheight->AddTag("TOP", &aLong); widgtablerowheight->AddTag("HANDLER", &aLong); widgtablerowheight->AddTag("TYPE", &aInt); // 6 widgtablerowheight->AddTag("ROW", &aLong); widgtablerowheight->AddTag("HEIGHT", &aLong); // insert into structList structList.push_back( widgtablerowheight); DStructDesc* widgtablecolwidth = new DStructDesc( "WIDGET_TABLE_COL_WIDTH"); widgtablecolwidth->AddTag("ID", &aLong); widgtablecolwidth->AddTag("TOP", &aLong); widgtablecolwidth->AddTag("HANDLER", &aLong); widgtablecolwidth->AddTag("TYPE", &aInt); // 7 widgtablecolwidth->AddTag("COL", &aLong); widgtablecolwidth->AddTag("WIDTH", &aLong); // insert into structList structList.push_back( widgtablecolwidth); DStructDesc* widgtableinvalidentry = new DStructDesc( "WIDGET_TABLE_INVALID_ENTRY"); widgtableinvalidentry->AddTag("ID", &aLong); widgtableinvalidentry->AddTag("TOP", &aLong); widgtableinvalidentry->AddTag("HANDLER", &aLong); widgtableinvalidentry->AddTag("TYPE", &aInt); // 8 widgtableinvalidentry->AddTag("STR", &aString); widgtableinvalidentry->AddTag("X", &aLong); widgtableinvalidentry->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtableinvalidentry); DStructDesc* widgnoevent = new DStructDesc( "WIDGET_NOEVENT"); widgnoevent->AddTag("ID", &aLong); widgnoevent->AddTag("TOP", &aLong); widgnoevent->AddTag("HANDLER", &aLong); // insert into structList structList.push_back( widgnoevent); DStructDesc* widgver = new DStructDesc( "WIDGET_VERSION"); widgver->AddTag("STYLE", &aString); widgver->AddTag("TOOLKIT", &aString); widgver->AddTag("RELEASE", &aString); // insert into structList structList.push_back( widgver); DStructDesc* widggeom = new DStructDesc( "WIDGET_GEOMETRY"); widggeom->AddTag("XOFFSET",&aFloat); widggeom->AddTag("YOFFSET",&aFloat); widggeom->AddTag("XSIZE",&aFloat); widggeom->AddTag("YSIZE",&aFloat); widggeom->AddTag("SCR_XSIZE",&aFloat); widggeom->AddTag("SCR_YSIZE",&aFloat); widggeom->AddTag("DRAW_XSIZE",&aFloat); widggeom->AddTag("DRAW_YSIZE",&aFloat); widggeom->AddTag("MARGIN",&aFloat); widggeom->AddTag("XPAD",&aFloat); widggeom->AddTag("YPAD",&aFloat); widggeom->AddTag("SPACE",&aFloat); // insert into structList structList.push_back( widggeom); DStructDesc* widgdraw = new DStructDesc( "WIDGET_DRAW"); widgdraw->AddTag("ID", &aLong); widgdraw->AddTag("TOP", &aLong); widgdraw->AddTag("HANDLER", &aLong); widgdraw->AddTag("TYPE", &aInt); widgdraw->AddTag("X", &aLong); widgdraw->AddTag("Y", &aLong); widgdraw->AddTag("PRESS", &aByte); widgdraw->AddTag("RELEASE", &aByte); widgdraw->AddTag("CLICKS", &aLong); widgdraw->AddTag("MODIFIERS", &aLong); widgdraw->AddTag("CH", &aByte); widgdraw->AddTag("KEY", &aLong); // insert into structList structList.push_back( widgdraw); DStructDesc* widgkbrdfocus = new DStructDesc( "WIDGET_KBRD_FOCUS"); widgkbrdfocus->AddTag("ID", &aLong); widgkbrdfocus->AddTag("TOP", &aLong); widgkbrdfocus->AddTag("HANDLER", &aLong); widgkbrdfocus->AddTag("ENTER", &aInt); structList.push_back( widgkbrdfocus); DStructDesc* widgcontext = new DStructDesc( "WIDGET_CONTEXT"); widgcontext->AddTag("ID", &aLong); widgcontext->AddTag("TOP", &aLong); widgcontext->AddTag("HANDLER", &aLong); widgcontext->AddTag("X", &aLong); widgcontext->AddTag("Y", &aLong); widgcontext->AddTag("ROW", &aLong); widgcontext->AddTag("COL", &aLong); // insert into structList structList.push_back( widgcontext); DStructDesc* widgtlb_size_events = new DStructDesc( "WIDGET_BASE"); widgtlb_size_events->AddTag("ID", &aLong); widgtlb_size_events->AddTag("TOP", &aLong); widgtlb_size_events->AddTag("HANDLER", &aLong); widgtlb_size_events->AddTag("X", &aLong); widgtlb_size_events->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtlb_size_events); DStructDesc* widgtlb_move_events = new DStructDesc( "WIDGET_TLB_MOVE"); widgtlb_move_events->AddTag("ID", &aLong); widgtlb_move_events->AddTag("TOP", &aLong); widgtlb_move_events->AddTag("HANDLER", &aLong); widgtlb_move_events->AddTag("X", &aLong); widgtlb_move_events->AddTag("Y", &aLong); // insert into structList structList.push_back( widgtlb_move_events); DStructDesc* widgtlb_iconify_events = new DStructDesc( "WIDGET_TLB_ICONIFY"); widgtlb_iconify_events->AddTag("ID", &aLong); widgtlb_iconify_events->AddTag("TOP", &aLong); widgtlb_iconify_events->AddTag("HANDLER", &aLong); widgtlb_iconify_events->AddTag("ICONIFIED", &aInt); // insert into structList structList.push_back( widgtlb_iconify_events); DStructDesc* widgtlb_kill_request_events = new DStructDesc( "WIDGET_KILL_REQUEST"); widgtlb_kill_request_events->AddTag("ID", &aLong); widgtlb_kill_request_events->AddTag("TOP", &aLong); widgtlb_kill_request_events->AddTag("HANDLER", &aLong); // insert into structList structList.push_back( widgtlb_kill_request_events); DStructDesc* widgtracking = new DStructDesc( "WIDGET_TRACKING"); widgtracking->AddTag("ID", &aLong); widgtracking->AddTag("TOP", &aLong); widgtracking->AddTag("HANDLER", &aLong); widgtracking->AddTag("ENTER", &aInt); // insert into structList structList.push_back( widgtracking); DStructDesc* widgtimer = new DStructDesc( "WIDGET_TIMER"); widgtimer->AddTag("ID", &aLong); widgtimer->AddTag("TOP", &aLong); widgtimer->AddTag("HANDLER", &aLong); // insert into structList structList.push_back( widgtimer); DStructDesc* colo = new DStructDesc( "WIDGET_SYSTEM_COLORS"); colo->AddTag("DARK_SHADOW_3D", &aColor); colo->AddTag("FACE_3D", &aColor); colo->AddTag("LIGHT_EDGE_3D", &aColor); colo->AddTag("LIGHT_3D", &aColor); colo->AddTag("SHADOW_3D", &aColor); colo->AddTag("ACTIVE_BORDER", &aColor); colo->AddTag("ACTIVE_CAPTION", &aColor); colo->AddTag("APP_WORKSPACE", &aColor); colo->AddTag("DESKTOP", &aColor); colo->AddTag("BUTTON_TEXT", &aColor); colo->AddTag("CAPTION_TEXT", &aColor); colo->AddTag("GRAY_TEXT", &aColor); colo->AddTag("HIGHLIGHT", &aColor); colo->AddTag("HIGHLIGHT_TEXT", &aColor); colo->AddTag("INACTIVE_BORDER", &aColor); colo->AddTag("INACTIVE_CAPTION", &aColor); colo->AddTag("INACTIVE_CAPTION_TEXT", &aColor); colo->AddTag("TOOLTIP_BK", &aColor); colo->AddTag("TOOLTIP_TEXT", &aColor); colo->AddTag("MENU", &aColor); colo->AddTag("MENU_TEXT", &aColor); colo->AddTag("SCROLLBAR", &aColor); colo->AddTag("WINDOW_BK", &aColor); colo->AddTag("WINDOW_FRAME", &aColor); colo->AddTag("WINDOW_TEXT", &aColor); // insert into structList structList.push_back( colo); DStructDesc* dropstruct = new DStructDesc( "WIDGET_DROP"); dropstruct->AddTag("ID", &aLong); dropstruct->AddTag("TOP", &aLong); dropstruct->AddTag("HANDLER", &aLong); dropstruct->AddTag("DRAG_ID", &aLong); dropstruct->AddTag("POSITION", &aInt); dropstruct->AddTag("X", &aLong); dropstruct->AddTag("Y", &aLong); dropstruct->AddTag("MODIFIERS", &aInt); // insert into structList structList.push_back( dropstruct); DStructDesc* treeselstruct = new DStructDesc( "WIDGET_TREE_SEL"); treeselstruct->AddTag("ID", &aLong); treeselstruct->AddTag("TOP", &aLong); treeselstruct->AddTag("HANDLER", &aLong); treeselstruct->AddTag("TYPE", &aInt); treeselstruct->AddTag("CLICKS", &aLong); // insert into structList structList.push_back( treeselstruct); DStructDesc* treeexpandstruct = new DStructDesc( "WIDGET_TREE_EXPAND"); treeexpandstruct->AddTag("ID", &aLong); treeexpandstruct->AddTag("TOP", &aLong); treeexpandstruct->AddTag("HANDLER", &aLong); treeexpandstruct->AddTag("TYPE", &aInt); treeexpandstruct->AddTag("EXPAND", &aLong); // insert into structList structList.push_back( treeexpandstruct); DStructDesc* idltracebackstruct = new DStructDesc( "IDL_TRACEBACK"); idltracebackstruct->AddTag("ROUTINE", &aString); idltracebackstruct->AddTag("FILENAME", &aString); idltracebackstruct->AddTag("LINE", &aLong); idltracebackstruct->AddTag("LEVEL", &aLong); idltracebackstruct->AddTag("IS_FUNCTION", &aByte); idltracebackstruct->AddTag("METHOD", &aByte); idltracebackstruct->AddTag("RESTORED", &aByte); idltracebackstruct->AddTag("SYSTEM", &aByte); // insert into structList structList.push_back( idltracebackstruct); //template for future uses: // DStructDesc* struct = new DStructDesc( "WIDGET_DROP"); // struct->AddTag("ID", &aLong); // struct->AddTag("TOP", &aLong); // struct->AddTag("HANDLER", &aLong); // // insert into structList // structList.push_back( struct); } void InitObjects() { sigControlC = false; debugMode = 0; fileUnits.resize( maxLun); // 0-127 -> 1-128 within GDL for files // initialize GDL system variables SysVar::InitSysVar(); // initialize struct descriptors which are not system variables InitStructs(); // add internal memeber subroutines SetupOverloadSubroutines(); // graphic devices must be initialized after system variables. // !D must already exist // We need to initialize the multi-device object that inherits from the single-device object. GraphicsMultiDevice::Init(); string gdlPath=GetEnvString("GDL_PATH"); if( gdlPath == "") gdlPath=GetEnvString("IDL_PATH"); if( gdlPath == "") gdlPath = "+" GDLDATADIR "/lib"; SysVar::SetGDLPath( gdlPath); } // returns GDL lun, 0 on failure DLong GetLUN() { for( DLong lun=maxUserLun+1; lun <= fileUnits.size(); lun++) if( !fileUnits[ lun-1].InUse() && !fileUnits[ lun-1].GetGetLunLock()) { fileUnits[ lun-1].SetGetLunLock( true); return lun; } return 0; } bool IsRelaxed(){return !strictInterpreter;} void SetStrict(bool value){strictInterpreter=value;} // for semantic predicate bool IsFun(antlr::RefToken rT1) { antlr::Token& T1=*rT1; // search for T1.getText() in function table and path string searchName=StrUpCase(T1.getText()); // cout << "IsFun: Searching for: " << searchName << endl; // Speeds up the process of finding (in gdlc.g) if a syntax like foo(bar) is a call to the function 'foo' // or the 'bar' element of array 'foo'. LibFunListT::iterator p=find_if(libFunList.begin(),libFunList.end(), Is_eq(searchName)); if( p != libFunList.end()) if( *p != NULL) return true; FunListT::iterator q=find_if(funList.begin(),funList.end(), Is_eq(searchName)); if( q != funList.end()) if( *q != NULL) return true; // cout << "Not found: " << searchName << endl; return false; } int ProIx(const string& n) { SizeT nF=proList.size(); for( SizeT i=0; i(n)(proList[i])) return (int)i; return -1; } int FunIx(const string& n) { SizeT nF=funList.size(); for( SizeT i=0; i(n)(funList[i])) return (int)i; return -1; } int LibProIx(const string& n) { SizeT nF=libProList.size(); for( SizeT i=0; i(n)(libProList[i])) return (int)i; } return -1; } int LibFunIx(const string& n) { SizeT nF=libFunList.size(); for( SizeT i=0; i(n)(libFunList[i])) return (int)i; } return -1; } // returns the endian of the current machine bool BigEndian() { // a long should at least have two bytes // big endian -> msb first (msb is 0 here) static const unsigned long int s = 0x0001; static const bool bigEndian = !(*reinterpret_cast( &s)); return bigEndian; } // test--------------- void breakpoint() { static SizeT num=1; cout << "objects.cpp: at breakpoint(): " << num << endl; num++; } #ifndef _OPENMP int get_suggested_omp_num_threads() { return 1; } #endif #if defined _OPENMP int get_suggested_omp_num_threads() { int default_num_threads=1, suggested_num_threads=1; char* env_var_c; env_var_c = getenv ("OMP_NUM_THREADS"); if(env_var_c) { return atoi(env_var_c); } // cout<<"OMP_NUM_THREADS is not defined"</dev/null|cut -d\" \" -f3", "r"); if (!iff) { return default_num_threads; } #elif defined(_WIN32) #if 0 //cout<<"get_suggested_omp_num_threads(): is windows"< #include #include "datatypes.hpp" #include "dvar.hpp" #include "dpro.hpp" #include "dcommon.hpp" #include "envt.hpp" #include "io.hpp" #ifdef USE_PYTHON #include "gdlpython.hpp" #endif // class DInterpreter; // extern DInterpreter* interpreter; const std::string GDL_OBJECT_NAME("GDL_OBJECT"); const std::string GDL_CONTAINER_NAME("GDL_CONTAINER"); extern VarListT sysVarList; extern VarListT sysVarRdOnlyList; extern FunListT funList; extern ProListT proList; extern LibFunListT libFunList; extern LibProListT libProList; extern CommonListT commonList; // common blocks extern StructListT structList; extern GDLFileListT fileUnits; // for OpenMP const SizeT DefaultTPOOL_MIN_ELTS = 100000; const SizeT DefaultTPOOL_MAX_ELTS = 0; extern DLong CpuTPOOL_NTHREADS; extern DLong64 CpuTPOOL_MIN_ELTS; extern DLong64 CpuTPOOL_MAX_ELTS; //extern DeviceListT deviceList; //extern Graphics* actDevice; // signals if control-c was pressed extern volatile bool sigControlC; // tells if wxwidgets backend for graphics is to be used... extern volatile bool useWxWidgetsForGraphics; //do we favor SIMD-accelerated random number generation? extern volatile bool useDSFMTAcceleration; extern int debugMode; enum DebugCode { DEBUG_CLEAR=0, DEBUG_STOP = 1, DEBUG_PROCESS_STOP = 2, DEBUG_STEP = 3, DEBUG_STEPOVER= 4 }; template< class Container> void PurgeContainer( Container& s) { typename Container::iterator i; for(i = s.begin(); i != s.end(); ++i) { delete *i;}// *i = NULL;} s.clear(); } void InitGDL(); // defined in gdl.cpp void InitObjects(); void ResetObjects(); DLong GetLUN(); int ProIx(const std::string& n); int FunIx(const std::string& n); int LibProIx(const std::string& n); int LibFunIx(const std::string& n); bool IsFun(antlr::RefToken); // used by Lexer and Parser bool IsRelaxed(); //tells if syntax is not strict (i.e. parenthesis for array indexes). void SetStrict(bool value); bool BigEndian(); int get_suggested_omp_num_threads(); int currentNumberOfThreads(); int currentThreadNumber(); template class RefHeap { private: T* ptr; SizeT count; // 2016.05.13 GJ: bool doSave; // IDL 6.1 flag whether to include in a SAVE operation (HEAP_SAVE) // access via HEAP_SAVE( Heapvars) and HEAP_NOSAVE( Heapvars [,SET=[0/1]]) bool enableGC; // IDL 8.0 flag whether to perform automatic garbage collection // access via HEAP_REFCOUNT([,/ENABLE] [,/DISABLE] [,IS_ENABLED=]) // prevent usage RefHeap& operator=(const RefHeap& other) { return *this;} template operator RefHeap() {return RefHeap(ptr);} public: SizeT Count() const { return count;} bool IsEnabledGC() const { return enableGC; } void EnableGC( bool set=true) { enableGC = set; } bool IsEnabledSave() const { return doSave; } void EnableSave( bool set=true) { doSave = set; } void Inc() {++count;} void Add( SizeT add) {count += add;} bool Dec() {assert(count > 0); return (--count==0);} RefHeap(T* p = 0) : ptr(p), count(1), doSave(false), enableGC(true) {} RefHeap( const RefHeap& other) : ptr( other.ptr), count( other.count), doSave( other.doSave), enableGC( other.enableGC) {} ~RefHeap() {} operator T* () const { return ptr; } T* operator->() const { return ptr; } T*& get() { return ptr; } }; namespace structDesc { // these are used mainly in list.cpp and hash.cpp // as for .RESET_SESSION the pointers change // one can still use these as they get updated on every new creation in InitStructs() extern DStructDesc* LIST; extern DStructDesc* HASH; extern DStructDesc* GDL_CONTAINER; extern DStructDesc* GDL_CONTAINER_NODE; extern DStructDesc* GDL_HASHTABLEENTRY; } #endif gdl-0.9.9/src/ofmt.cpp000066400000000000000000001002151340051421000145240ustar00rootroot00000000000000/*************************************************************************** ofmt.cpp - formatted input/output ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // to be included from datatypes.cpp #ifdef INCLUDE_OFMT_CPP static const std::string allstars="****************************************************************************************************************************"; template< typename Ty> std::string binstr( const Ty v, int w, int d, int code) { bool dofill=( ( (code & fmtPAD) > 0 ) ); SizeT bitsetsize=sizeof(Ty)*8; if ( v==Ty(0.0) ) { if ( w<=0 ) return "0"; if ( (code & fmtALIGN_LEFT) > 0 ) { return "0"; } else { if (d>0) { if (d<=w) { std::string z(d,'0'); std::string s(w-d,' '); s+=z; return s; } else { std::string s(w+10,' '); //overfill to get *** return s; } } else { std::string s(w-1,dofill?'0':' '); s+='0'; return s; } } } if (w==0) w=bitsetsize; SizeT first=0; if (bitsetsize == 8) { std::bitset<8> me(v); for (SizeT i=0; i<8; ++i) if (me.test(7-i)) {first=i; break;} if (8-first > w) return allstars.substr(0,w); else return me.to_string,allocator >().substr(first); } else if (bitsetsize == 16) { std::bitset<16> me(v); for (SizeT i=0; i<16; ++i) if (me.test(15-i)) {first=i; break;} if (16-first > w) return allstars.substr(0,w); else return me.to_string,allocator >().substr(first); } else if (bitsetsize == 32) { std::bitset<32> me(v); for (SizeT i=0; i<32; ++i) if (me.test(31-i)) {first=i; break;} if (32-first > w) return allstars.substr(0,w); else return me.to_string,allocator >().substr(first); } else { std::bitset<64> me(v); for (SizeT i=0; i<64; ++i) if (me.test(63-i)) {first=i; break;} if (64-first > w) return allstars.substr(0,w); else return me.to_string,allocator >().substr(first); } } #include "ofmt.hpp" template void OutInteger(std::ostream& os, const T &val, const int w, const int d, int code, const BaseGDL::IOMode oMode) { std::ostringstream oss; if (d > 0) { std::ostringstream ossI; if (code & fmtSHOWPOS) ossI << std::showpos; if (oMode == BaseGDL::DEC) ossI << val; else if (oMode == BaseGDL::OCT) ossI << std::oct << val; else if (oMode == BaseGDL::BIN) ossI << binstr(val, w, d, code); else if (oMode == BaseGDL::HEX) ossI << std::uppercase << std::hex << val; else ossI << std::nouppercase << std::hex << val; // HEXL //force PADDING code |= fmtPAD; OutAdjustFill(oss, ossI.str(), d, code); //remove PAD for next treatment ---> must be blanks code &= (~fmtPAD); } else { if (code & fmtSHOWPOS) oss << std::showpos; if (d > 0) oss << std::setw(d) << std::setfill('0'); if (oMode == BaseGDL::DEC) oss << val; else if (oMode == BaseGDL::OCT) oss << std::oct << val; else if (oMode == BaseGDL::BIN) oss << binstr(val, w, d, code); else if (oMode == BaseGDL::HEX) oss << std::uppercase << std::hex << val; else oss << std::nouppercase << std::hex << val; // HEXL } if (w == 0) os << oss.str(); else if (oss.tellp() > w) OutStars(os, w); else if (code & fmtALIGN_LEFT) { os << std::left; os << std::setw(w); os << oss.str(); os << std::right; } else OutFixFill(os, oss.str(), w, code); } template <> void OutFixed(ostream& os, const DComplex &val, const int w, const int d, const int code) { OutFixed(os, val.real(), w, d, code); OutFixed(os, val.imag(), w, d, code); } template <> void OutFixed( ostream& os, const DComplexDbl &val, const int w, const int d, const int code) { OutFixed(os, val.real(), w, d, code); OutFixed(os, val.imag(), w, d, code); } template <> void OutScientific( ostream& os, const DComplex &val, const int w, const int d, const int code) { OutScientific( os, val.real(), w, d, code); OutScientific( os, val.imag(), w, d, code); } template <> void OutScientific( ostream& os, const DComplexDbl &val, const int w, const int d, const int code) { OutScientific( os, val.real(), w, d, code); OutScientific( os, val.imag(), w, d, code); } template <> void OutAuto( ostream& os, const DComplex &val, const int w, const int d, const int code) { OutAuto( os, val.real(), w, d, code); OutAuto( os, val.imag(), w, d, code); } template <> void OutAuto( ostream& os, const DComplexDbl &val, const int w, const int d, const int code) { OutAuto( os, val.real(), w, d, code); OutAuto( os, val.imag(), w, d, code); } void SetDefaultFieldLengths( int& w, int& d, const SizeT defPrec, const SizeT maxPrec, const SizeT wDef) { if( w == -1) // (X) { d = maxPrec; w = wDef; } else if( w == 0) // (X0) { if( d <= 0) d = defPrec; } else if( d < 0) //should never happen now. d = maxPrec; } void DStructGDL::OFmtAll( SizeT offs, SizeT r, SizeT& firstOut, SizeT& firstOffs, SizeT& tCount, SizeT& tCountOut) { SizeT nTrans = ToTransfer(); // transfer count tCount = nTrans - offs; if( r < tCount) tCount = r; tCountOut = tCount; // find first Element SizeT oneElTr = nTrans / N_Elements(); SizeT firstEl = offs / oneElTr; firstOffs = offs % oneElTr; // find first tag SizeT nB = 0; SizeT nTags=NTags(); SizeT firstTag = 0; for( firstTag=0; firstTag < nTags; firstTag++) { SizeT tt=(*this)[firstTag]->ToTransfer(); nB += tt; if( nB > firstOffs) { nB -= tt; break; } } firstOut = firstEl * NTags() + firstTag; firstOffs -= nB; } // A code **************************************************** // other template SizeT Data_::OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code) { DStringGDL* stringVal = static_cast ( this->Convert2( GDL_STRING, BaseGDL::COPY_BYTE_AS_INT)); SizeT retVal = stringVal->OFmtA( os, offs, r, w, code); delete stringVal; return retVal; } // string template<> SizeT Data_:: OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; if( w <= 0) { (*os) << left; for( SizeT i=offs; i SizeT Data_:: OFmtA(ostream* os, SizeT offs, SizeT r, int w, const int code) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if (r < tCount) tCount = r; SizeT tCountOut = tCount; SizeT firstEl = offs / 2; (*os) << right; if (offs & 0x01) { if (w <= 0) (*os) << float2string((*this)[ firstEl++].imag()); else { if (code & fmtALIGN_LEFT) (*os) << left; else (*os) << right; (*os) << setw(w) << float2string((*this)[ firstEl++].imag()).substr(0,w); } tCount--; } SizeT endEl = firstEl + tCount / 2; if (w <= 0) for (SizeT i = firstEl; i < endEl; ++i) { (*os) << float2string((*this)[ firstEl++].real()); (*os) << float2string((*this)[ firstEl++].imag()); } else { if (code & fmtALIGN_LEFT) (*os) << left; else (*os) << right; for (SizeT i = firstEl; i < endEl; ++i) { (*os) << setw(w) << float2string((*this)[ firstEl++].real()).substr(0,w); (*os) << setw(w) << float2string((*this)[ firstEl++].imag()).substr(0,w); } } if (tCount & 0x01) { if (w <= 0) (*os) << float2string((*this)[ firstEl++].real()); else { if (code & fmtALIGN_LEFT) (*os) << left; else (*os) << right; (*os) << setw(w) << float2string((*this)[ firstEl++].real()).substr(0,w); } } return tCountOut; } template<> SizeT Data_:: OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if (r < tCount) tCount = r; SizeT tCountOut = tCount; SizeT firstEl = offs / 2; (*os) << right; if (offs & 0x01) { if (w <= 0) (*os) << double2string((*this)[ firstEl++].imag()); else { if (code & fmtALIGN_LEFT) (*os) << left; else (*os) << right; (*os) << setw(w) << double2string((*this)[ firstEl++].imag()).substr(0,w); } tCount--; } SizeT endEl = firstEl + tCount / 2; if (w <= 0) for (SizeT i = firstEl; i < endEl; ++i) { (*os) << double2string((*this)[ firstEl++].real()); (*os) << double2string((*this)[ firstEl++].imag()); } else { if (code & fmtALIGN_LEFT) (*os) << left; else (*os) << right; for (SizeT i = firstEl; i < endEl; ++i) { (*os) << setw(w) << double2string((*this)[ firstEl++].real()).substr(0,w); (*os) << setw(w) << double2string((*this)[ firstEl++].imag()).substr(0,w); } } if (tCount & 0x01) { if (w <= 0) (*os) << double2string((*this)[ firstEl++].real()); else { if (code & fmtALIGN_LEFT) (*os) << left; else (*os) << right; (*os) << setw(w) << double2string((*this)[ firstEl++].real()).substr(0,w); } } return tCountOut; } // struct SizeT DStructGDL:: OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code) { SizeT firstOut, firstOffs, tCount, tCountOut; OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut); SizeT trans = (*this)[ firstOut]->OFmtA( os, firstOffs, tCount, w, code); if( trans >= tCount) return tCountOut; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstOut+1); i < ddSize; ++i) { trans = (*this)[ i]->OFmtA( os, 0, tCount, w, code); if( trans >= tCount) return tCountOut; tCount -= trans; } return tCountOut; } // F code **************************************************** // other template SizeT Data_:: OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode) { DDoubleGDL* cVal = static_cast ( this->Convert2( GDL_DOUBLE, BaseGDL::COPY)); SizeT retVal = cVal->OFmtF( os, offs, r, w, d, code, oMode); delete cVal; return retVal; } // double template<> SizeT Data_:: OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; SetDefaultFieldLengths( w, d, 6, 16, 25); if( oMode == AUTO) // G { for( SizeT i=offs; i SizeT Data_:: OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; SetDefaultFieldLengths( w, d, 6, 7, 15); if( oMode == AUTO) // G { for( SizeT i=offs; i SizeT Data_:: OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountOut = tCount; SizeT firstEl = offs / 2; SetDefaultFieldLengths( w, d, 6, 7, 15); if( oMode == AUTO) { if( offs & 0x01) { OutAuto( *os, (*this)[ firstEl++].imag(), w, d, code); tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; i SizeT Data_:: OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode) { SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountOut = tCount; SizeT firstEl = offs / 2; SetDefaultFieldLengths( w, d, 6, 16, 25); if( oMode == AUTO) { if( offs & 0x01) { OutAuto( *os, (*this)[ firstEl++].imag(), w, d, code); tCount--; } SizeT endEl = firstEl + tCount / 2; for( SizeT i= firstEl; iOFmtF( os, firstOffs, tCount, w, d, code, oMode); if( trans >= tCount) return tCountOut; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstOut+1); i < ddSize; ++i) { trans = (*this)[ i]->OFmtF( os, 0, tCount, w, d, code, oMode); if( trans >= tCount) return tCountOut; tCount -= trans; } return tCountOut; } // I code **************************************************** // other // undf byte int lint real dbl cplx str strct dcplx ptr obj uint ulon int64 uint64 const int iFmtWidth[] = { -1, 7, 7, 12, 12, 12, 12, 12, -1, 12, -1, -1, 7, 12, 22, 22}; const int iFmtWidthBIN[] = { -1, 8, 16, 32, 32, 32, 32, 32, -1, 64, -1, -1, 16, 32, 64, 64}; // GDL_STRUCT-GDL_ULONG64 template SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if ( this->Sizeof()==2 ) { DIntGDL* cVal = static_cast (this->Convert2( GDL_INT, BaseGDL::COPY )); if ( w < 0 ) w = (oMode == BaseGDL::BIN ? iFmtWidthBIN[ this->t] : iFmtWidth[ this->t]); SizeT retVal = cVal->OFmtI( os, offs, r, w, d, code, oMode); delete cVal; return retVal; //FIXME THIS MAY DEPEND ON THE MACHINE NATURAL SIZE. ON 64 BITS it is promoted to 64 bits. // } else if ( this->Sizeof()==4 ) { // DLongGDL* cVal = static_cast // (this->Convert2( GDL_LONG, BaseGDL::COPY )); // if ( w < 0 ) w = (oMode == BaseGDL::BIN ? iFmtWidthBIN[ this->t] : iFmtWidth[ this->t]); // SizeT retVal = cVal->OFmtI( os, offs, r, w, d, code, oMode); // delete cVal; // return retVal; } else { DLong64GDL* cVal = static_cast (this->Convert2( GDL_LONG64, BaseGDL::COPY )); if ( w < 0 ) w = (oMode == BaseGDL::BIN ? iFmtWidthBIN[ this->t] : iFmtWidth[ this->t]); SizeT retVal = cVal->OFmtI( os, offs, r, w, d, code, oMode); delete cVal; return retVal; } } template<> SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 8 : 7); SizeT nTrans = ToTransfer(); DIntGDL* cVal = static_cast (this->Convert2( GDL_INT, BaseGDL::COPY )); //necessary for non-b formats. // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 16 : 7); SizeT nTrans = ToTransfer(); DLongGDL* cVal = static_cast (this->Convert2( GDL_LONG, BaseGDL::COPY )); //necessary as IDL affixes the '+' when format="+". //meaning it does not pass an unsigned int! // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 16 : 7); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 32 : 12); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 32 : 12); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: OFmtI(ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if (w < 0) w = (oMode == BIN ? 64 : 22); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if (r < tCount) tCount = r; SizeT endEl = offs + tCount; for (SizeT i = offs; i < endEl; ++i) OutInteger(*os, (*this)[ i], w, d, code, oMode); return tCount; } // GDL_ULONG64 template<> SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 64 : 22); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT endEl = offs + tCount; for( SizeT i=offs; i SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 32 : 12); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountOut = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { OutInteger( *os, static_cast((*this)[ firstEl++].imag()), w, d, code, oMode); tCount--; } SizeT endEl = firstEl + tCount / 2; for ( SizeT i = firstEl; i < endEl; ++i ) { OutInteger( *os, static_cast((*this)[ i].real()), w, d, code, oMode); OutInteger( *os, static_cast((*this)[ i].imag()), w, d, code, oMode); } if( tCount & 0x01) { OutInteger( *os, static_cast((*this)[ endEl++].real()), w, d, code, oMode); } return tCountOut; } template<> SizeT Data_:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { if( w < 0) w = (oMode == BIN ? 32 : 12); SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; if( r < tCount) tCount = r; SizeT tCountOut = tCount; SizeT firstEl = offs / 2; if( offs & 0x01) { OutInteger( *os, static_cast((*this)[ firstEl++].imag()), w, d, code, oMode); tCount--; } SizeT endEl = firstEl + tCount / 2; for ( SizeT i = firstEl; i < endEl; ++i ) { OutInteger( *os, static_cast((*this)[ i].real()), w, d, code, oMode); OutInteger( *os, static_cast((*this)[ i].imag()), w, d, code, oMode); } if( tCount & 0x01) { OutInteger( *os, static_cast((*this)[ endEl++].real()), w, d, code, oMode); } return tCountOut; } SizeT DStructGDL:: OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code, BaseGDL::IOMode oMode) { SizeT firstOut, firstOffs, tCount, tCountOut; OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut); SizeT trans = (*this)[ firstOut]->OFmtI( os, firstOffs, tCount, w, d, code, oMode); if( trans >= tCount) return tCountOut; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstOut+1); i < ddSize; ++i) { trans = (*this)[ i]->OFmtI( os, 0, tCount, w, d, code, oMode); if( trans >= tCount) return tCountOut; tCount -= trans; } return tCountOut; } void outA( ostream* os, string s, int w, const int code) { if (w <= 0) { (*os) << left; (*os) << s; } else { if (code & fmtALIGN_LEFT) { (*os) << setw(w) << s.substr(0, w); } else { (*os) << right; (*os) << setw(w) << s.substr(0, w); } } } // struct SizeT DStructGDL:: OFmtCal( ostream* os, SizeT offs, SizeT r, int w, int d, char *f, int code, BaseGDL::Cal_IOMode cMode) { SizeT firstOut, firstOffs, tCount, tCountOut; OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut); SizeT trans = (*this)[ firstOut]->OFmtCal( os, firstOffs, tCount, w, d, f, code, cMode); if( trans >= tCount) return tCountOut; tCount -= trans; SizeT ddSize = dd.size(); for( SizeT i = (firstOut+1); i < ddSize; ++i) { trans = (*this)[ i]->OFmtCal( os, 0, tCount, w, d, f, code, cMode); if( trans >= tCount) return tCountOut; tCount -= trans; } return tCountOut; } template SizeT Data_:: OFmtCal( ostream* os, SizeT offs, SizeT repeat, int w, int d, char *fill, int code, BaseGDL::Cal_IOMode cMode) { static string theMonth[12]={"January","February","March","April","May","June", "July","August","September","October","November","December"}; static string theMONTH[12]={"JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE", "JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"}; static string themonth[12]={"january","february","march","april","may","june", "july","august","september","october","november","december"}; static string theDAY[7]={"MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"}; static string theDay[7]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}; static string theday[7]={"monday","tuesday","wednesday","thursday","friday","saturday","sunday"}; static string capa[2]={"am","pm"}; static string cApa[2]={"Am","Pm"}; static string cAPa[2]={"AM","PM"}; static DLong *iMonth, *iDay, *iYear, *iHour, *iMinute, *dow, *icap; static DDouble *Second; static ostringstream **local_os; bool cmplx=FALSE; SizeT nTrans = ToTransfer(); // transfer count SizeT tCount = nTrans - offs; SizeT r=tCount; if ( Data_::IS_COMPLEX ) { cmplx=TRUE;} //tCount in this case is twice the size of the complex array switch ( cMode ) { case BaseGDL::WRITE: for (SizeT i=0, j=0; j= repeat) {i=0; (*os)<str()).c_str(); i++; delete local_os[j]; } delete local_os; delete iMonth; delete iDay ; delete iYear; delete iHour; delete iMinute; delete dow; delete icap; delete Second; break; case BaseGDL::COMPUTE: iMonth=(DLong*)calloc(r,sizeof(DLong)); iDay=(DLong*)calloc(r,sizeof(DLong)); iYear=(DLong*)calloc(r,sizeof(DLong)); iHour=(DLong*)calloc(r,sizeof(DLong)); iMinute=(DLong*)calloc(r,sizeof(DLong)); dow=(DLong*)calloc(r,sizeof(DLong)); icap=(DLong*)calloc(r,sizeof(DLong)); Second=(DDouble*)calloc(r,sizeof(DDouble)); local_os=(ostringstream**)calloc(r,sizeof(ostringstream*)); if ( cmplx ) { DComplexDblGDL* cVal = static_cast (this->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY )); for( SizeT i=0, j=0; j<(r/2); ++j) { local_os[i]=new ostringstream(); if (!j2ymdhms( (*cVal)[offs +j].real(), iMonth[i], iDay[i], iYear[i], iHour[i], iMinute[i], Second[i], dow[i], icap[i] )) throw GDLException("Value of Julian date is out of allowed range."); i++; local_os[i]=new ostringstream(); if (!j2ymdhms( (*cVal)[offs+j].imag(), iMonth[i], iDay[i], iYear[i], iHour[i], iMinute[i], Second[i], dow[i], icap[i] )) throw GDLException("Value of Julian date is out of allowed range."); i++; } delete cVal; } else { for ( SizeT i = 0; i < r; i++ ) { local_os[i]=new ostringstream(); DDoubleGDL* cVal = static_cast (this->Convert2( GDL_DOUBLE, BaseGDL::COPY )); if (!j2ymdhms( (*cVal)[offs + i], iMonth[i], iDay[i], iYear[i], iHour[i], iMinute[i], Second[i], dow[i], icap[i] )) throw GDLException("Value of Julian date is out of allowed range."); delete cVal; // cerr<<"Dow="< #include #include #include #include // for binary output //using namespace std; #include "datatypes.hpp" #include "dstructgdl.hpp" #ifdef _MSC_VER #define finite _finite #define isnan _isnan #endif typedef enum codeFlags_ { fmtALIGN_LEFT = 1 ,fmtSHOWPOS = 2 ,fmtPAD = 4 ,fmtUPPER = 8 } codeFlags; // for auto formatting of float types // code in ofmt.cpp template< typename T> class AsComplex { #ifdef _MSC_VER public: // MSC cannot handle friend template specialization properly #endif T flt; int width; int prec; int code; public: AsComplex( const T val, const int w, const int p, const int c=0): flt( val), width( w), prec( p), code( c) {} template< typename T2> friend std::ostream& operator<<(std::ostream& os, const AsComplex& a); }; class CheckNL { #ifdef _MSC_VER public: // MSC cannot handle friend template specialization properly #endif SizeT width; SizeT* actPosPtr; SizeT nextW; public: CheckNL( const SizeT w, SizeT* const a, const SizeT n): width( w), actPosPtr( a), nextW( n) {} friend std::ostream& operator<<(std::ostream& os, const CheckNL& cc); }; // code in default_io.cpp std::ostream& operator<<(std::ostream& os, const CheckNL& c); // formatted output functions inline void OutStars( std::ostream& os, const int n) { for( int i=0; i inline void OutFixedNan( std::ostream& os, const T val, const int w, const int code) //d is ignored for Nan/Inf { static std::string symbol="NaN"; char s=(std::signbit(val))?'-':'+'; OutFixedStringVal(os, symbol, s, w, code); } template inline void OutFixedInf( std::ostream& os, const T val, const int w, const int code) //d is ignored for Nan/Inf { static std::string symbol="Inf"; char s=(std::signbit(val))?'-':'+'; OutFixedStringVal(os, symbol, s, w, code); } template <> inline void OutFixedInf( std::ostream& os, const DDouble val, const int w, const int code) //d is ignored for Nan/Inf { static std::string symbol="Infinity"; char s=(std::signbit(val))?'-':'+'; OutFixedStringVal(os, symbol,s, w, code); } inline void OutFixFill(std::ostream& os, const std::string &s, const int w, const int code) { if ( code & fmtPAD ) os << std::setfill('0'); if ( ( code & fmtPAD ) && ((s.substr( 0, 1) == "-" ) || ( s.substr(0, 1) == "+" )) ) { // preventing "00-1.00" or "00+1.00" os << s.substr(0, 1) << std::right << std::setw(w - 1) << s.substr(1); } else os << std::setw(w) << std::right << s; if ( code & fmtPAD ) os << std::setfill(' '); //which is '0' or blank at this point. } inline void OutAdjustFill(std::ostream& os, const std::string &s, const int w, const int code) { if ( code & fmtPAD ) os << std::setfill('0'); if ( ( code & fmtPAD ) && ((s.substr( 0, 1) == "-" ) || ( s.substr(0, 1) == "+" )) ) { // preventing "00-1.00" or "00+1.00" os << s.substr(0, 1) << std::right << std::setw(w) << s.substr(1); } else os << std::setw(w) << std::right << s; if ( code & fmtPAD ) os << std::setfill(' '); //which is '0' or blank at this point. } template void OutFixed(std::ostream& os, const T &val, const int w, const int d, const int code) { if (std::isfinite(val)) { std::ostringstream oss; if ( code & fmtSHOWPOS ) oss << std::showpos; oss << std::fixed << std::setprecision(d) << val; if (d==0) oss << "."; if( w <= 0) os << oss.str(); else if( oss.tellp() > w) OutStars( os, w); else if (code & fmtALIGN_LEFT) { os << std::left; os << std::setw(w); os << oss.str(); os << std::right; } else OutFixFill(os, oss.str(), w, code); } else if (std::isnan(val)) OutFixedNan( os, val, w, code); else OutFixedInf( os, val, w, code); } template <> void OutFixed(std::ostream& os, const DComplex &val, const int w, const int d, const int code); template <> void OutFixed(std::ostream& os, const DComplexDbl &val, const int w, const int d, const int code); template void OutScientific(std::ostream& os, const T &val, const int w, const int d, const int code) { if (std::isfinite(val)) { std::ostringstream oss; // TODO: IDL handles both lower and upper case "E" (tracker item no. 3147155) if ( code & fmtSHOWPOS ) oss << std::showpos; if ( code & fmtUPPER ) oss << std::uppercase ; oss << std::scientific << std::setprecision(d) << val; if (w == 0 ) os << oss.str(); else if (oss.tellp() > w) OutStars(os, w); else if (code & fmtALIGN_LEFT) { os << std::left; os << std::setw(w); os << oss.str(); os << std::right; } else OutFixFill(os, oss.str(), w, code); } else if (std::isnan(val)) OutFixedNan(os, val, w, code); else OutFixedInf(os, val, w, code); } template <> void OutScientific( std::ostream& os, const DComplex &val, const int w, const int d, const int code); template <> void OutScientific( std::ostream& os, const DComplexDbl &val, const int w, const int d, const int code); template void OutAuto(std::ostream& os, const T &val, const int w, const int d, const int code=0) { if (std::isfinite(val)) { std::ostringstream ossF; int fixLen=1; if (val == T(0.0)) // handle 0.0 { if (w <= 0) { if ( code & fmtSHOWPOS ) os<<"+0"; else os<<"0"; return; } //0 is FIXED if (code & fmtSHOWPOS) ossF << std::showpos ; if (code & fmtALIGN_LEFT) ossF << std::left; else ossF << std::right; ossF << std::fixed << std::setprecision(d-1) << val; } else { int powTen = static_cast(std::floor( std::log10( std::abs( val)))); fixLen = powTen > 0 ? powTen+1 : 1; // number of digits before '.' // as its used now, if w == 0 -> d != 0 (SetField()) // static cast here is needed for OS X, without we get a *linker* error // (but only if GDL is compiled with Magick) if (code & fmtSHOWPOS) ossF << std::showpos ; if (code & fmtALIGN_LEFT) ossF << std::left; else ossF << std::right; if( w == 0 && (powTen < d && powTen > -d) && (val - std::floor( val) < std::pow( 10.0, static_cast(-d)))) ossF << std::fixed << std::setprecision(0) << val; else if( powTen == 0 || (powTen < d && powTen > -d+1)) //just like that. { //format for values between -1 and 1 adapts to the width as to show as many digits as possible ossF << std::fixed << std::setprecision(d>fixLen?d-fixLen+((powTen<0)?-powTen:0):0) << val; if( d <= fixLen && w>0) ossF << "."; } else fixLen = 0; // marker to force scientific output } //get the scientific string std::ostringstream ossS; if (code & fmtSHOWPOS) ossS << std::showpos ; if (code & fmtALIGN_LEFT) ossS << std::left; else ossS << std::right; if ( code & fmtUPPER ) ossS << std::uppercase ; if (w==0) ossS << std::setprecision(d>6?d:6) << val; //Auto w=0 special format: does not use "scientific" but default field-point notation. else ossS << std::scientific << std::setprecision(d>0?d-1:0) << val; // compare merits if( fixLen == 0 || ossF.tellp() > ossS.tellp()) { if( w == 0) os << ossS.str(); else if( ossS.tellp() > w) OutStars( os, w); else if (code & fmtALIGN_LEFT) { os << std::left; os << std::setw(w); os << ossS.str(); os << std::right; } else OutFixFill(os, ossS.str(), w, code); } else { if( w == 0) os << ossF.str(); else if( ossF.tellp() > w) OutStars( os, w); else if (code & fmtALIGN_LEFT) { os << std::left; os << std::setw(w); os << ossF.str(); os << std::right; } else OutFixFill(os, ossF.str(), w, code); } } else if (std::isnan(val)) OutFixedNan(os, val, w, code); else OutFixedInf(os, val, w, code); } template <> void OutAuto( std::ostream& os, const DComplex &val, const int w, const int d, const int code); template <> void OutAuto( std::ostream& os, const DComplexDbl &val, const int w, const int d, const int code); template std::ostream& operator<<(std::ostream& os, const AsComplex& a) { os << "("; OutAuto( os, a.flt.real(), a.width, a.prec, a.code); os << ","; OutAuto( os, a.flt.imag(), a.width, a.prec, a.code); os << ")"; return os; } #endif gdl-0.9.9/src/overload.cpp000066400000000000000000001032421340051421000153750ustar00rootroot00000000000000/*************************************************************************** overload.cpp - GDL operator overloading for objects ------------------- begin : November 29 2012 copyright : (C) 2012 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "objects.hpp" #include "overload.hpp" #include "prognodeexpr.hpp" #include "dinterpreter.hpp" // #include "basic_pro.hpp" #include "nullgdl.hpp" #include "list.hpp" #include "hash.hpp" using namespace std; std::string overloadOperatorNames[] = { "_OVERLOADBRACKETSLEFTSIDE" , "_OVERLOADBRACKETSRIGHTSIDE" , "_OVERLOADMINUSUNARY" , "_OVERLOADNOT" , "_OVERLOADTILDE" , "_OVERLOADPLUS" , "_OVERLOADMINUS" , "_OVERLOADASTERISK" , "_OVERLOADSLASH" , "_OVERLOADCARET" , "_OVERLOADMOD" , "_OVERLOADLESSTHAN" , "_OVERLOADGREATERTHAN" , "_OVERLOADAND" , "_OVERLOADOR" , "_OVERLOADXOR" , "_OVERLOADEQ" , "_OVERLOADNE" , "_OVERLOADGE" , "_OVERLOADGT" , "_OVERLOADLE" , "_OVERLOADLT" , "_OVERLOADPOUND" , "_OVERLOADPOUNDPOUND" , "_OVERLOADISTRUE" , "_OVERLOADFOREACH" , "_OVERLOADHELP" , "_OVERLOADPRINT" , "_OVERLOADSIZE" }; // except _OVERLOADBRACKETSLEFTSIDE all are functions int OverloadOperatorIndexFun( std::string subName) { assert( !subName.empty()); if( subName[0] != '_') // optimization, true in most cases return -1; for( int i=1; i < NumberOfOverloadOperators; ++i) if( subName == overloadOperatorNames[ i]) return i; return -1; } int OverloadOperatorIndexPro( std::string subName) { if( subName == overloadOperatorNames[ 0]) return 0; else return -1; } // for proper error reporting we need to unwind the stack void ThrowFromInternalUDSub( EnvUDT* e, const string& s) { ProgNodeP callingNode = e->CallingNode(); string objectName =e->GetPro()->ObjectName(); delete e; GDLException::Interpreter()->CallStack().pop_back(); throw GDLException( callingNode, objectName+" (internal): " + s, false, false); } BaseGDL* _GDL_OBJECT_OverloadIsTrue( EnvUDT* e) { // default behavior: Implict: Another object cannot be the null object return new DIntGDL(1); // if we reach here, defaul is to return 'TRUE' } BaseGDL* _GDL_OBJECT_Init( EnvUDT* e) { // std::cout << " gdl_OBJECT_Init!" << std::endl; return new DIntGDL(1); // if we reach here, defaul is to return 'TRUE' } void _GDL_OBJECT_OverloadBracketsLeftSide( EnvUDT* e) { // // debug/check // std::cout << "_GDL_OBJECT_OverloadBracketsLeftSide called" << std::endl; // this is only called on scalar object references // IDL's default behavior is to just replace SELF (via OBJREF) by RVALUE // no index checking is done. SizeT nParam = e->NParam(); if( nParam < 3) // consider implicit SELF return; // RVALUE not given -> ignore // BaseGDL** objRef = e->GetKW(1); // BaseGDL** objRefP = e->GetPtrTo( objRef); if( !e->GlobalKW(1)) { ThrowFromInternalUDSub( e, "Parameter 1 (OBJREF) must be a passed as reference in this context."); } BaseGDL** objRefP = &e->GetKW(1); BaseGDL* objRef = *objRefP; BaseGDL* rValue = e->GetKW(2); if( rValue == NULL) { ThrowFromInternalUDSub( e, "Parameter 2 (RVALUE) is undefined."); } if( rValue->Type() != GDL_OBJ) { ThrowFromInternalUDSub( e, "Parameter 2 (RVALUE) must be an OBJECT in this context."); } GDLDelete( *objRefP); *objRefP = rValue->Dup(); } BaseGDL* _GDL_OBJECT_OverloadBracketsRightSide( EnvUDT* e) { // // debug/check // std::cout << "_GDL_OBJECT_OverloadBracketsRightSide called" << std::endl; SizeT nParam = e->NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined if( nParam < 3) // consider implicit SELF ThrowFromInternalUDSub( e, "At least 2 parameters are needed: ISRANGE, SUB1 [, ...]."); // default behavior: Exact like scalar indexing BaseGDL* isRange = e->GetKW(1); if( isRange == NULL) ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) is undefined."); if( isRange->Rank() == 0) ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) must be an array in this context: " + e->Caller()->GetString(e->GetKW(1))); SizeT nIsRange = isRange->N_Elements(); if( nIsRange > (nParam - 2)) //- SELF and ISRANGE ThrowFromInternalUDSub( e, "Parameter 1 (ISRANGE) must have "+i2s(nParam-2)+" elements."); Guard isRangeLongGuard; DLongGDL* isRangeLong; if( isRange->Type() == GDL_LONG) isRangeLong = static_cast( isRange); else { try{ isRangeLong = static_cast( isRange->Convert2( GDL_LONG, BaseGDL::COPY)); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } isRangeLongGuard.Reset( isRangeLong); } ArrayIndexVectorT ixList; // IxExprListT exprList; try { for( int p=0; pGetKW( p + 2); // implicit SELF, ISRANGE, par1..par8 if( parX == NULL) ThrowFromInternalUDSub( e, "Parameter is undefined: " + e->Caller()->GetString(e->GetKW( p + 2))); DLong isRangeX = (*isRangeLong)[p]; if( isRangeX != 0 && isRangeX != 1) ThrowFromInternalUDSub( e, "Value of parameter 1 (ISRANGE["+i2s(p)+"]) is out of allowed range."); if( isRangeX == 1) { if( parX->N_Elements() != 3) ThrowFromInternalUDSub( e, "Range vector must have 3 elements: " + e->Caller()->GetString(e->GetKW( p + 2))); Guard parXLongGuard; DLongGDL* parXLong; if( parX->Type() == GDL_LONG) parXLong = static_cast( parX); else { try{ parXLong = static_cast( parX->Convert2( GDL_LONG, BaseGDL::COPY)); } catch( GDLException& ex) { ThrowFromInternalUDSub( e, ex.ANTLRException::getMessage()); } parXLongGuard.Reset( parXLong); } // negative end ix is fine -> CArrayIndexRangeS can handle [b:*:s] ([b,-1,s]) ixList.push_back(new CArrayIndexRangeS( (*parXLong)[0], (*parXLong)[1], (*parXLong)[2])); } else // non-range { // ATTENTION: These two grab c1 (all others don't) // a bit unclean, but for maximum efficiency if( parX->Rank() == 0) ixList.push_back( new CArrayIndexScalar( parX->Dup())); else ixList.push_back( new CArrayIndexIndexed( parX->Dup())); } } // for } catch( GDLException& ex) { ixList.Destruct(); // ixList is not valid afterwards, but as we throw this is ok throw ex; } ArrayIndexListT* aL; MakeArrayIndex( &ixList, &aL, NULL); // important to get the non-NoAssoc ArrayIndexListT // because only they clean up ixList on destruction Guard< ArrayIndexListT> aLGuard( aL); IxExprListT ixL; return aL->Index( e->GetKW( 0), ixL); // index SELF } BaseGDL* _GDL_OBJECT_OverloadEQOp( EnvUDT* e) { SizeT nParam = e->NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined if( nParam < 2) // consider implicit SELF ThrowFromInternalUDSub( e, "2 parameters are needed: LEFT, RIGHT."); // default behavior: Exact like scalar indexing BaseGDL* l = e->GetKW(1); if( l->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, "Unable to convert parameter #1 to type object reference."); BaseGDL* r = e->GetKW(2); if( r->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, "Unable to convert parameter #2 to type object reference."); DObjGDL* left = static_cast(l); DObjGDL* right = static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=left->N_Elements(); // if( nEl == 0) // nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; DObj s; if( right->StrictScalar(s)) { res= new Data_( left->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = (s == (*left)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*left)[i] == s); } } else if( left->StrictScalar(s)) { res= new Data_( right->Dim(), BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] == s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] == s); } } else if( rEl < nEl) { res= new Data_( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] == (*left)[i]); } } else // ( rEl >= nEl) { res= new Data_( left->Dim(), BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] == (*left)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] == (*left)[i]); } } return res; } BaseGDL* _GDL_OBJECT_OverloadNEOp( EnvUDT* e) { SizeT nParam = e->NParam(); // number of parameters actually given // int envSize = e->EnvSize(); // number of parameters + keywords 'e' (pro) has defined if( nParam < 3) // consider implicit SELF ThrowFromInternalUDSub( e, "Two parameters are needed: LEFT, RIGHT."); // default behavior: Exact like scalar indexing BaseGDL* l = e->GetKW(1); if( l->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, "Unable to convert parameter #1 to type object reference."); BaseGDL* r = e->GetKW(2); if( r->Type() != GDL_OBJ) ThrowFromInternalUDSub( e, "Unable to convert parameter #2 to type object reference."); DObjGDL* left = static_cast(l); DObjGDL* right = static_cast(r); ULong rEl=right->N_Elements(); ULong nEl=left->N_Elements(); // if( nEl == 0) // nEl=N_Elements(); assert( rEl); assert( nEl); // if( !rEl || !nEl) throw GDLException("Variable is undefined."); Data_* res; DObj s; if( right->StrictScalar(s)) { res= new Data_( left->Dim(), BaseGDL::NOZERO); if( nEl == 1) { (*res)[0] = (s != (*left)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*left)[i] != s); } } else if( left->StrictScalar(s)) { res= new Data_( right->Dim(), BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] != s); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] != s); } } else if( rEl < nEl) { res= new Data_( right->Dim(), BaseGDL::NOZERO); TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (rEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= rEl)) { #pragma omp for for( OMPInt i=0; i < rEl; ++i) (*res)[i] = ((*right)[i] != (*left)[i]); } } else // ( rEl >= nEl) { res= new Data_( left->Dim(), BaseGDL::NOZERO); if( rEl == 1) { (*res)[0] = ((*right)[0] != (*left)[0]); return res; } TRACEOMP( __FILE__, __LINE__) #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for( OMPInt i=0; i < nEl; ++i) (*res)[i] = ((*right)[i] != (*left)[i]); } } return res; } // for GDL_OBJECT all other overloads are illegal operations as default // however, they need to be accessible for (nonsense) parent method calls. // But we can use just this one function for all of them BaseGDL* _GDL_OBJECT_OverloadReportIllegalOperation( EnvUDT* e) { ThrowFromInternalUDSub( e, "Operation illegal with object reference types."); return 0; } // set up the _overload... subroutines for GDL_OBJECT void SetupOverloadSubroutines() { // // The call // BaseGDL* res=interpreter->call_fun(static_cast(newEnv->GetPro())->GetTree()); // in call_fun eventually (in GDLInterpreter::statement) tree->Run() is called DStructDesc* gdlObjectDesc = FindInStructList(structList, GDL_OBJECT_NAME); assert( gdlObjectDesc != NULL); DStructDesc* gdlContainerDesc = FindInStructList(structList, "GDL_CONTAINER"); assert( gdlObjectDesc != NULL); DStructDesc* listDesc = FindInStructList(structList, "LIST"); assert( listDesc != NULL); DStructDesc* hashDesc = FindInStructList(structList, "HASH"); assert( hashDesc != NULL); WRAPPED_FUNNode *tree; WRAPPED_FUNNode *treeFun; WRAPPED_PRONode *treePro; // automatically adds "SELF" parameter (object name is != "") DFun *_overloadIsTrue = new DFun("_OVERLOADISTRUE",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_OverloadIsTrue); _overloadIsTrue->SetTree( treeFun); // we are NOT setting the operator to have (faster) default behavior // the functions must be there nevertheless for expicit callingNode // that's why we add them to the functions list gdlObjectDesc->FunList().push_back(_overloadIsTrue); // gdlObjectDesc->SetOperator(OOIsTrue,_overloadIsTrue); // GDL_OBJECT:: [ DPro *_overloadBracketsLeftSide = new DPro("_OVERLOADBRACKETSLEFTSIDE",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); _overloadBracketsLeftSide->AddPar("OBJREF")->AddPar("RVALUE")->AddPar("ISRANGE"); _overloadBracketsLeftSide->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); _overloadBracketsLeftSide->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); treePro = new WRAPPED_PRONode(_GDL_OBJECT_OverloadBracketsLeftSide); _overloadBracketsLeftSide->SetTree( treePro); gdlObjectDesc->ProList().push_back(_overloadBracketsLeftSide); // gdlObjectDesc->SetOperator(OOBracketsLeftSide,_overloadBracketsLeftSide); // GDL_OBJECT::INIT() DFun *_init = new DFun("INIT",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_Init); _init->SetTree( treeFun); gdlObjectDesc->FunList().push_back(_init); // GDL_OBJECT:: ] DFun *_overloadBracketsRightSide = new DFun("_OVERLOADBRACKETSRIGHTSIDE",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); _overloadBracketsRightSide->AddPar("ISRANGE"); _overloadBracketsRightSide->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); _overloadBracketsRightSide->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_OverloadBracketsRightSide); _overloadBracketsRightSide->SetTree( treeFun); gdlObjectDesc->FunList().push_back(_overloadBracketsRightSide); // gdlObjectDesc->SetOperator(OOBracketsRightSide,_overloadBracketsRightSide); // GDL_OBJECT:: = DFun *_overloadEQ = new DFun("_OVERLOADEQ",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); _overloadEQ->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_OverloadEQOp); _overloadEQ->SetTree( treeFun); gdlObjectDesc->FunList().push_back(_overloadEQ); // gdlObjectDesc->SetOperator(OOEQ,_overloadEQ); // GDL_OBJECT:: != DFun *_overloadNE = new DFun("_OVERLOADNE",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); _overloadNE->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_OverloadNEOp); _overloadNE->SetTree( treeFun); gdlObjectDesc->FunList().push_back(_overloadNE); // gdlObjectDesc->SetOperator(OONE,_overloadNE); // GDL_OBJECT:: + DFun *_overloadPlus = new DFun("_OVERLOADPLUS",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); _overloadPlus->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_OverloadReportIllegalOperation); _overloadPlus->SetTree( treeFun); gdlObjectDesc->FunList().push_back(_overloadPlus); // gdlObjectDesc->SetOperator(OOPlus,_overloadPlus); // GDL_OBJECT:: - DFun *_overloadMinus = new DFun("_OVERLOADMINUS",GDL_OBJECT_NAME,INTERNAL_LIBRARY_STR); _overloadMinus->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(_GDL_OBJECT_OverloadReportIllegalOperation); _overloadMinus->SetTree( treeFun); gdlObjectDesc->FunList().push_back(_overloadMinus); // gdlObjectDesc->SetOperator(OOMINUS,_overloadMinus); // LIST:: ] DFun *DFunLIST__overloadBracketsRightSide = new DFun("_OVERLOADBRACKETSRIGHTSIDE","LIST",INTERNAL_LIBRARY_STR); DFunLIST__overloadBracketsRightSide->AddPar("ISRANGE"); DFunLIST__overloadBracketsRightSide->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); DFunLIST__overloadBracketsRightSide->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); treeFun = new WRAPPED_FUNNode( lib::LIST___OverloadBracketsRightSide); DFunLIST__overloadBracketsRightSide->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__overloadBracketsRightSide); listDesc->SetOperator(OOBracketsRightSide,DFunLIST__overloadBracketsRightSide); // LIST:: [ DPro *DFunPro_overloadBracketsLeftSide = new DPro("_OVERLOADBRACKETSLEFTSIDE","LIST",INTERNAL_LIBRARY_STR); DFunPro_overloadBracketsLeftSide->AddPar("OBJREF")->AddPar("RVALUE")->AddPar("ISRANGE"); DFunPro_overloadBracketsLeftSide->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); DFunPro_overloadBracketsLeftSide->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); treePro = new WRAPPED_PRONode(lib::LIST___OverloadBracketsLeftSide); DFunPro_overloadBracketsLeftSide->SetTree( treePro); listDesc->ProList().push_back(DFunPro_overloadBracketsLeftSide); listDesc->SetOperator(OOBracketsLeftSide,DFunPro_overloadBracketsLeftSide); // LIST:: + DFun *LIST_overloadPlus = new DFun("_OVERLOADPLUS","LIST",INTERNAL_LIBRARY_STR); LIST_overloadPlus->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(lib::LIST___OverloadPlus); LIST_overloadPlus->SetTree( treeFun); listDesc->FunList().push_back(LIST_overloadPlus); listDesc->SetOperator(OOPlus,LIST_overloadPlus); // LIST:: = DFun *LIST_overloadEQ = new DFun("_OVERLOADEQ","LIST",INTERNAL_LIBRARY_STR); LIST_overloadEQ->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(lib::LIST___OverloadEQOp); LIST_overloadEQ->SetTree( treeFun); listDesc->FunList().push_back(LIST_overloadEQ); listDesc->SetOperator(OOEQ,LIST_overloadEQ); // LIST:: != DFun *LIST_overloadNE = new DFun("_OVERLOADNE","LIST",INTERNAL_LIBRARY_STR); LIST_overloadNE->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(lib::LIST___OverloadNEOp); LIST_overloadNE->SetTree( treeFun); listDesc->FunList().push_back(LIST_overloadNE); listDesc->SetOperator(OONE,LIST_overloadNE); // LIST:: DFun *LIST_overloadIsTrue = new DFun("_OVERLOADISTRUE","LIST",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode(lib::LIST___OverloadIsTrue); LIST_overloadIsTrue->SetTree( treeFun); listDesc->FunList().push_back(LIST_overloadIsTrue); listDesc->SetOperator(OOIsTrue,LIST_overloadIsTrue); // LIST::ADD DPro *DProLIST__ADD = new DPro("ADD","LIST",INTERNAL_LIBRARY_STR); DProLIST__ADD->AddKey("EXTRACT","EXTRACT")->AddKey("NO_COPY","NO_COPY"); DProLIST__ADD->AddKey("POSITION","POSITION"); DProLIST__ADD->AddPar("VALUE")->AddPar("INDEX"); treePro = new WRAPPED_PRONode( lib::list__add); DProLIST__ADD->SetTree( treePro); listDesc->ProList().push_back(DProLIST__ADD); // LIST::REMOVE() DFun *DFunLIST__REMOVE = new DFun("REMOVE","LIST",INTERNAL_LIBRARY_STR); DFunLIST__REMOVE->AddKey("ALL","ALL"); DFunLIST__REMOVE->AddPar("INDEX"); treeFun = new WRAPPED_FUNNode( lib::list__remove_fun); DFunLIST__REMOVE->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__REMOVE); // LIST::REMOVE PRO DPro *DProLIST__REMOVE = new DPro("REMOVE","LIST",INTERNAL_LIBRARY_STR); DProLIST__REMOVE->AddKey("ALL","ALL"); DProLIST__REMOVE->AddPar("INDEX"); treePro = new WRAPPED_PRONode( lib::list__remove_pro); DProLIST__REMOVE->SetTree( treePro); listDesc->ProList().push_back(DProLIST__REMOVE); // LIST::REVERSE PRO DPro *DProLIST__REVERSE = new DPro("REVERSE","LIST",INTERNAL_LIBRARY_STR); treePro = new WRAPPED_PRONode( lib::list__reverse); DProLIST__REVERSE->SetTree( treePro); listDesc->ProList().push_back(DProLIST__REVERSE); // LIST::ToArray() DFun *DFunLIST__TOARRAY = new DFun("TOARRAY","LIST",INTERNAL_LIBRARY_STR); DFunLIST__TOARRAY->AddKey("TYPE","TYPE")->AddKey("MISSING","MISSING"); DFunLIST__TOARRAY->AddKey("DIMENSION","DIMENSION")->AddKey("NO_COPY","NO_COPY"); DFunLIST__TOARRAY->AddKey("PROMOTE_TYPE","PROMOTE_TYPE")->AddKey("TRANSPOSE","TRANSPOSE"); treeFun = new WRAPPED_FUNNode( lib::list__toarray); DFunLIST__TOARRAY->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__TOARRAY); #if 0 // LIST::HELP() DFun *DFunLIST__HELP = new DFun("HELP","LIST",INTERNAL_LIBRARY_STR); DFunLIST__TOHELP->AddKey("MAXITEM","MAXITEM"); treeFun = new WRAPPED_FUNNode( lib::list__help); DFunLIST__TOHELP->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__TOHELP); #endif #if 0 // LIST::HELP DPro *DProLIST__HELP = new DPro("HELP","LIST",INTERNAL_LIBRARY_STR); DProLIST__HELP->AddKey("MAXITEM","MAXITEM"); treePro = new WRAPPED_PRONode( lib::list__help); DProLIST__HELP->SetTree( treePro); listDesc->ProList().push_back(DProLIST__HELP); #endif // LIST::CLEANUP DPro *DProLIST__CLEANUP = new DPro("CLEANUP","LIST",INTERNAL_LIBRARY_STR); treePro = new WRAPPED_PRONode( lib::list__cleanup); DProLIST__CLEANUP->SetTree( treePro); listDesc->ProList().push_back(DProLIST__CLEANUP); // LIST::MOVE DPro *DProLIST__MOVE = new DPro("MOVE","LIST",INTERNAL_LIBRARY_STR); DProLIST__MOVE->AddPar("SOURCE")->AddPar("DESTINATION"); treePro = new WRAPPED_PRONode( lib::list__move); DProLIST__MOVE->SetTree( treePro); listDesc->ProList().push_back(DProLIST__MOVE); // LIST::SWAP DPro *DProLIST__SWAP = new DPro("SWAP","LIST",INTERNAL_LIBRARY_STR); DProLIST__SWAP->AddPar("INDEX1")->AddPar("INDEX2"); treePro = new WRAPPED_PRONode( lib::list__swap); DProLIST__SWAP->SetTree( treePro); listDesc->ProList().push_back(DProLIST__SWAP); // LIST::COUNT() DFun *DFunLIST__COUNT = new DFun("COUNT","LIST",INTERNAL_LIBRARY_STR); DFunLIST__COUNT->AddPar("VALUE"); treeFun = new WRAPPED_FUNNode( lib::list__count); DFunLIST__COUNT->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__COUNT); // LIST::ISEMPTY() DFun *DFunLIST__ISEMPTY = new DFun("ISEMPTY","LIST",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::list__isempty); DFunLIST__ISEMPTY->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__ISEMPTY); // LIST::WHERE() DFun *DFunLIST__WHERE = new DFun("WHERE","LIST",INTERNAL_LIBRARY_STR); DFunLIST__WHERE->AddKey("COMPLEMENT","COMPLEMENT"); DFunLIST__WHERE->AddKey("COUNT","COUNT"); DFunLIST__WHERE->AddKey("NCOMPLEMENT","NCOMPLEMENT"); DFunLIST__WHERE->AddPar("VALUE"); treeFun = new WRAPPED_FUNNode( lib::list__where); DFunLIST__WHERE->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__WHERE); // LIST::GET() // here to make up for IDL_CONTAINER lack. // res=List.get([/all] [, isa=(names)] [. position=index] [, count=variable] [/null][) DFun *DFunLIST__GET = new DFun("GET","LIST",INTERNAL_LIBRARY_STR); DFunLIST__GET->AddKey("ALL","ALL")->AddKey("ISA","ISA")->AddKey("NULL","NULL"); DFunLIST__GET->AddKey("COUNT","COUNT"); DFunLIST__GET->AddKey("POSITION","POSITION"); treeFun = new WRAPPED_FUNNode( lib::list__get); DFunLIST__GET->SetTree( treeFun); listDesc->FunList().push_back(DFunLIST__GET); // LIST::INIT() // here to make up for IDL_CONTAINER lack. // list is parented by GDL_OBJECT which can handled INIT: // DFun *DFunLIST__INIT = new DFun("INIT","LIST",INTERNAL_LIBRARY_STR); // treeFun = new WRAPPED_FUNNode( lib::list__init); // DFunLIST__INIT->SetTree( treeFun); // listDesc->FunList().push_back(DFunLIST__INIT); // HASH DFun *DFunHASH__overloadBracketsRightSide = new DFun("_OVERLOADBRACKETSRIGHTSIDE","HASH",INTERNAL_LIBRARY_STR); DFunHASH__overloadBracketsRightSide->AddPar("ISRANGE"); DFunHASH__overloadBracketsRightSide->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); DFunHASH__overloadBracketsRightSide->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); treeFun = new WRAPPED_FUNNode( lib::HASH___OverloadBracketsRightSide); DFunHASH__overloadBracketsRightSide->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__overloadBracketsRightSide); hashDesc->SetOperator(OOBracketsRightSide,DFunHASH__overloadBracketsRightSide); DPro *DProHASH_overloadBracketsLeftSide = new DPro("_OVERLOADBRACKETSLEFTSIDE","HASH",INTERNAL_LIBRARY_STR); DProHASH_overloadBracketsLeftSide->AddPar("OBJREF")->AddPar("RVALUE")->AddPar("ISRANGE"); DProHASH_overloadBracketsLeftSide->AddPar("SUB1")->AddPar("SUB2")->AddPar("SUB3")->AddPar("SUB4"); DProHASH_overloadBracketsLeftSide->AddPar("SUB5")->AddPar("SUB6")->AddPar("SUB7")->AddPar("SUB8"); treePro = new WRAPPED_PRONode(lib::HASH___OverloadBracketsLeftSide); DProHASH_overloadBracketsLeftSide->SetTree( treePro); hashDesc->ProList().push_back(DProHASH_overloadBracketsLeftSide); hashDesc->SetOperator(OOBracketsLeftSide,DProHASH_overloadBracketsLeftSide); DFun *HASH_overloadPlus = new DFun("_OVERLOADPLUS","HASH",INTERNAL_LIBRARY_STR); HASH_overloadPlus->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(lib::HASH___OverloadPlus); HASH_overloadPlus->SetTree( treeFun); hashDesc->FunList().push_back(HASH_overloadPlus); hashDesc->SetOperator(OOPlus,HASH_overloadPlus); DFun *HASH_overloadEQ = new DFun("_OVERLOADEQ","HASH",INTERNAL_LIBRARY_STR); HASH_overloadEQ->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(lib::HASH___OverloadEQOp); HASH_overloadEQ->SetTree( treeFun); hashDesc->FunList().push_back(HASH_overloadEQ); hashDesc->SetOperator(OOEQ,HASH_overloadEQ); DFun *HASH_overloadNE = new DFun("_OVERLOADNE","HASH",INTERNAL_LIBRARY_STR); HASH_overloadNE->AddPar("LEFT")->AddPar("RIGHT"); treeFun = new WRAPPED_FUNNode(lib::HASH___OverloadNEOp); HASH_overloadNE->SetTree( treeFun); hashDesc->FunList().push_back(HASH_overloadNE); hashDesc->SetOperator(OONE,HASH_overloadNE); DFun *HASH_overloadIsTrue = new DFun("_OVERLOADISTRUE","HASH",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode(lib::HASH___OverloadIsTrue); HASH_overloadIsTrue->SetTree( treeFun); hashDesc->FunList().push_back(HASH_overloadIsTrue); hashDesc->SetOperator(OOIsTrue,HASH_overloadIsTrue); // HASH::REMOVE() DFun *DFunHASH__REMOVE = new DFun("REMOVE","HASH",INTERNAL_LIBRARY_STR); DFunHASH__REMOVE->AddKey("ALL","ALL"); DFunHASH__REMOVE->AddPar("INDEX"); treeFun = new WRAPPED_FUNNode( lib::hash__remove_fun); DFunHASH__REMOVE->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__REMOVE); // HASH::REMOVE PRO DPro *DProHASH__REMOVE = new DPro("REMOVE","HASH",INTERNAL_LIBRARY_STR); DProHASH__REMOVE->AddKey("ALL","ALL"); DProHASH__REMOVE->AddPar("INDEX"); treePro = new WRAPPED_PRONode( lib::hash__remove_pro); DProHASH__REMOVE->SetTree( treePro); hashDesc->ProList().push_back(DProHASH__REMOVE); // HASH::HASKEY() DFun *DFunHASH__HASKEY = new DFun("HASKEY","HASH",INTERNAL_LIBRARY_STR); DFunHASH__HASKEY->AddPar("KEYLIST"); treeFun = new WRAPPED_FUNNode( lib::hash__haskey); DFunHASH__HASKEY->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__HASKEY); // HASH::KEYS() DFun *DFunHASH__KEYS = new DFun("KEYS","HASH",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::hash__keys); DFunHASH__KEYS->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__KEYS); // HASH::VALUES() DFun *DFunHASH__VALUES = new DFun("VALUES","HASH",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::hash__values); DFunHASH__VALUES->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__VALUES); // HASH::TOSTRUCT() DFun *DFunHASH__TOSTRUCT = new DFun("TOSTRUCT","HASH",INTERNAL_LIBRARY_STR); DFunHASH__TOSTRUCT->AddKey("SKIPPED","SKIPPED")->AddKey("MISSING","MISSING"); DFunHASH__TOSTRUCT->AddKey("NO_COPY","NO_COPY")->AddKey("RECURSIVE","RECURSIVE"); treeFun = new WRAPPED_FUNNode( lib::hash__tostruct); DFunHASH__TOSTRUCT->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__TOSTRUCT); // HASH::COUNT() DFun *DFunHASH__COUNT = new DFun("COUNT","HASH",INTERNAL_LIBRARY_STR); DFunHASH__COUNT->AddPar("VALUE"); treeFun = new WRAPPED_FUNNode( lib::hash__count); DFunHASH__COUNT->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__COUNT); // HASH::ISEMPTY() DFun *DFunHASH__ISEMPTY = new DFun("ISEMPTY","HASH",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::hash__isempty); DFunHASH__ISEMPTY->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__ISEMPTY); // HASH::ISORDERED() DFun *DFunHASH__ISORDERED = new DFun("ISORDERED","HASH",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::hash__isordered); DFunHASH__ISORDERED->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__ISORDERED); // HASH::ISFOLDCASE() DFun *DFunHASH__ISFOLDCASE = new DFun("ISFOLDCASE","HASH",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::hash__isfoldcase); DFunHASH__ISFOLDCASE->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__ISFOLDCASE); // HASH::WHERE() DFun *DFunHASH__WHERE = new DFun("WHERE","HASH",INTERNAL_LIBRARY_STR); DFunHASH__WHERE->AddKey("COMPLEMENT","COMPLEMENT"); DFunHASH__WHERE->AddKey("COUNT","COUNT"); DFunHASH__WHERE->AddKey("NCOMPLEMENT","NCOMPLEMENT"); DFunHASH__WHERE->AddPar("VALUE"); treeFun = new WRAPPED_FUNNode( lib::hash__where); DFunHASH__WHERE->SetTree( treeFun); hashDesc->FunList().push_back(DFunHASH__WHERE); // GDL_CONTAINER - references list procedures because, we can. // res=GDL_CONTAINER.get([/all] [, isa=(names)] [. position=index] [, count=variable] [/null][) DFun* DFunlist = new DFun("GET","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DFunlist->AddKey("ALL","ALL")->AddKey("ISA","ISA")->AddKey("NULL","NULL"); DFunlist->AddKey("COUNT","COUNT"); DFunlist->AddKey("POSITION","POSITION"); treeFun = new WRAPPED_FUNNode( lib::list__get); DFunlist->SetTree( treeFun); gdlContainerDesc->FunList().push_back(DFunlist); // GDL_CONTAINER::INIT() // DFunlist = new DFun("INIT","GDL_CONTAINER",INTERNAL_LIBRARY_STR); // treeFun = new WRAPPED_FUNNode( lib::list__init); // DFunlist->SetTree( treeFun); // gdlContainerDesc->FunList().push_back(DFunlist); // GDL_CONTAINER::COUNT() DFunlist = new DFun("COUNT","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DFunlist->AddPar("VALUE"); treeFun = new WRAPPED_FUNNode( lib::list__count); DFunlist->SetTree( treeFun); gdlContainerDesc->FunList().push_back(DFunlist); // GDL_CONTAINER::ADD DPro* DProlist = new DPro("ADD","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DProlist->AddKey("EXTRACT","EXTRACT")->AddKey("NO_COPY","NO_COPY"); DProlist->AddKey("POSITION","POSITION"); DProlist->AddPar("VALUE")->AddPar("INDEX"); treePro = new WRAPPED_PRONode( lib::list__add); DProlist->SetTree( treePro); gdlContainerDesc->ProList().push_back(DProlist); #if 0 // GDL_CONTAINER::HELP DProlist = new DPro("HELP","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DProlist->AddKey("MAXITEM","MAXITEM"); treePro = new WRAPPED_PRONode( lib::list__help); DProlist->SetTree( treePro); gdlContainerDesc->ProList().push_back(DProlist); #endif // GDL_CONTAINER::CLEANUP DProlist = new DPro("CLEANUP","GDL_CONTAINER",INTERNAL_LIBRARY_STR); treePro = new WRAPPED_PRONode( lib::container__cleanup); DProlist->SetTree( treePro); gdlContainerDesc->ProList().push_back(DProlist);//*/ // GDL_CONTAINER::MOVE DProlist = new DPro("MOVE","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DProlist->AddPar("SOURCE")->AddPar("DESTINATION"); treePro = new WRAPPED_PRONode( lib::list__move); DProlist->SetTree( treePro); gdlContainerDesc->ProList().push_back(DProlist); // GDL_CONTAINER::REMOVE() DProlist = new DPro("REMOVE","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DProlist->AddKey("ALL","ALL"); DProlist->AddKey("POSITION","POSITION"); DProlist->AddPar("HEAPVAR"); treePro = new WRAPPED_PRONode( lib::container__remove); DProlist->SetTree( treePro); gdlContainerDesc->ProList().push_back(DProlist); // GDL_CONTAINER::EQUALS() DFunlist = new DFun("EQUALS","GDL_CONTAINER",INTERNAL_LIBRARY_STR); treeFun = new WRAPPED_FUNNode( lib::container__equals); DFunlist->SetTree( treeFun); gdlContainerDesc->FunList().push_back( DFunlist); // GDL_CONTAINER::ISCONTAINED() DFunlist = new DFun("ISCONTAINED","GDL_CONTAINER",INTERNAL_LIBRARY_STR); DFunlist->AddKey("POSITION","POSITION"); DFunlist->AddPar("VALUE"); treeFun = new WRAPPED_FUNNode( lib::container__iscontained); DFunlist->SetTree( treeFun); gdlContainerDesc->FunList().push_back( DFunlist); } gdl-0.9.9/src/overload.hpp000066400000000000000000000047101340051421000154020ustar00rootroot00000000000000/*************************************************************************** overload.hpp - GDL operator overloading for objects ------------------- begin : November 29 2012 copyright : (C) 2012 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef OVERLOAD_HPP_ #define OVERLOAD_HPP_ #include #include "dpro.hpp" // changes here must be reflected in std::string overloadOperatorNames[] (overload.cpp) enum OverloadOperators { OOBracketsLeftSide , OOBracketsRightSide , OOMinusUnary , OONOT , OOTilde , OOPlus , OOMinus , OOAsterisk , OOSlash , OOCaret , OOMOD , OOLessThan , OOGreaterThan , OOAND , OOOR , OOXOR , OOEQ , OONE , OOGE , OOGT , OOLE , OOLT , OOPound , OOPoundPound , OOIsTrue , OOForeach , OOHelp , OOPrint , OOSize , NumberOfOverloadOperators }; int OverloadOperatorIndexFun( std::string subName); int OverloadOperatorIndexPro( std::string subName); void SetupOverloadSubroutines(); class OperatorList { private: DSubUD* operators[ NumberOfOverloadOperators]; public: OperatorList() { for( int i=0; i < NumberOfOverloadOperators; ++i) operators[ i] = NULL; } OperatorList( const OperatorList& cp) { for( int i=0; i < NumberOfOverloadOperators; ++i) operators[ i] = cp[ i]; } ~OperatorList() { // as operators are added to funList/proList as well, they are not owned by OperatorList // for( int i=0; i < NumberOfOverloadOperators; ++i) // delete operators[ i]; } DSubUD* operator[]( SizeT i) const { return operators[i];} void SetOperator( SizeT op, DSubUD* opSub) { operators[op] = opSub;} }; void ThrowFromInternalUDSub( EnvUDT* e, const std::string& s); #endif gdl-0.9.9/src/plotting.cpp000066400000000000000000002612771340051421000154370ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "dinterpreter.hpp" #include "plotting.hpp" #include #ifdef _MSC_VER #define snprintf _snprintf #endif #define DEBUG_CONTOURS 0 #define GDL_PI double(3.1415926535897932384626433832795) #define GDL_HALFPI 0.5*GDL_PI namespace lib { using namespace std; // using std::isinf; #ifdef _MSC_VER #define finite _finite #else using std::isnan; #endif //static values static DDouble savedPointX=0.0; static DDouble savedPointY=0.0; static gdlSavebox saveBox; static DFloat sym1x[5]={1, -1, 0, 0, 0}; // + static DFloat sym1y[5]={0, 0, 0, -1, 1}; // + static DFloat sym2x[11]= {1, -1, 0, 0, 0, 0,1,-1,0,1,-1}; //* static DFloat sym2y[11]= {0, 0, 0, -1, 1,0,1,-1,0,-1,1}; // * static DFloat sym3x[2]={0,0}; // . static DFloat sym3y[2]={0,0}; // . static DFloat sym4x[5]={ 0, 1, 0, -1, 0 }; //diamond. static DFloat sym4y[5]={ 1, 0, -1, 0, 1 }; //diamond. static DFloat sym5x[4]={ -1, 0, 1, -1 }; // triangle up. static DFloat sym5y[4]={ -1, 1, -1, -1 }; // triangle up. static DFloat sym6x[5]={ -1, 1, 1, -1, -1 }; //square static DFloat sym6y[5]={ 1, 1, -1, -1, 1 }; //square static DFloat sym7x[5]= {1,-1,0,1,-1}; //x static DFloat sym7y[5]= {1,-1,0,-1,1}; //x DLong syml[7]={5,11,2,5,4,5,5}; struct LOCALUSYM { DLong nusym; DInt fill; DFloat usymx[49]; DFloat usymy[49]; bool hasColor; DLong color; bool hasThick; DFloat thick; }; static LOCALUSYM localusym; gdlSavebox* getSaveBox(){return &saveBox;} void gdlDoRangeExtrema(DDoubleGDL *xVal, DDoubleGDL *yVal, DDouble &min, DDouble &max, DDouble xmin, DDouble xmax, bool doMinMax, DDouble minVal, DDouble maxVal) { DDouble valx, valy; SizeT i,k; DLong n=xVal->N_Elements(); if(n!=yVal->N_Elements()) return; for (i=0,k=0 ; ixmax || isnan(valx))) continue; else { //min and max of y if not NaN and in range [minVal, maxVal] if doMinMax=yes (min_value, max_value keywords) valy=(*yVal)[i]; if ((doMinMax && (valymaxVal )) || isnan(valy)) continue; else {if(k==0) {min=valy; max=valy;} else {min=gdlPlot_Min(min,valy); max=gdlPlot_Max(max,valy);}} } k++; } } void GetMinMaxVal(DDoubleGDL* val, double* minVal, double* maxVal) { #define UNDEF_RANGE_VALUE 1E-12 DLong minE, maxE; const bool omitNaN=true; val->MinMax(&minE, &maxE, NULL, NULL, omitNaN); if ( minVal!=NULL ) { *minVal=(*val)[ minE]; if (isnan(*minVal)) *minVal = UNDEF_RANGE_VALUE; } if ( maxVal!=NULL ) { *maxVal=(*val)[ maxE]; if (isnan(*maxVal)) *maxVal = 1.0; } if ((*maxVal)==(*minVal)) *maxVal=*minVal+1.0; #undef UNDEF_RANGE_VALUE } void GetMinMaxValuesForSubset(DDoubleGDL* val, DDouble &minVal, DDouble &maxVal, SizeT FinalElement) { #define UNDEF_RANGE_VALUE 1E-12 DLong minE, maxE; const bool omitNaN=true; val->MinMax(&minE, &maxE, NULL, NULL, omitNaN, 0, FinalElement); minVal=(*val)[ minE]; if (isnan(minVal)) minVal = UNDEF_RANGE_VALUE; maxVal=(*val)[ maxE]; if (isnan(maxVal)) maxVal = 1.0; if (maxVal==minVal) maxVal=minVal+1.0; #undef UNDEF_RANGE_VALUE } PLFLT AutoTick(DDouble x) { if ( x==0.0 ) return 1.0; DLong n=static_cast(floor(log10(x/3.5))); DDouble y=(x/(3.5*pow(10., static_cast(n)))); DLong m=0; if ( y>=1&&y<2 ) m=1; else if ( y>=2&&y<5 ) m=2; else if ( y>=5 ) m=5; PLFLT intv=(PLFLT)(m*pow(10., static_cast(n))); return intv; } PLFLT AutoIntv(DDouble x) { if ( x==0.0 ) { // cout << "zero"<(floor(log10(x/2.82))); DDouble y=(x/(2.82*pow(10., static_cast(n)))); DLong m=0; if ( y>=1&&y<2 ) m=1; else if ( y>=2&&y<4.47 ) m=2; else if ( y>=4.47 ) m=5; // cout << "AutoIntv" << x << " " << y << endl; PLFLT intv=(PLFLT)(m*pow(10., static_cast(n))); return intv; } #define EXTENDED_DEFAULT_LOGRANGE 12 //protect from (inverted, strange) axis log values void gdlHandleUnwantedAxisValue(DDouble &min, DDouble &max, bool log) { bool invert=FALSE; DDouble val_min, val_max; if (!log) return; if(max-min >= 0) { val_min=min; val_max=max; invert=FALSE; } else { val_min=max; val_max=min; invert=TRUE; } if ( val_min<=0. ) { if ( val_max<=0. ) { val_min=-EXTENDED_DEFAULT_LOGRANGE; val_max=0.0; } else { val_min=log10(val_max)-EXTENDED_DEFAULT_LOGRANGE; val_max=log10(val_max); } } else { val_min=log10(val_min); val_max=log10(val_max); } if (invert) { min=pow(10.,val_max); max=pow(10.,val_min); } else { min=pow(10.,val_min); max=pow(10.,val_max); } } #undef EXTENDED_DEFAULT_LOGRANGE //improved version of "AutoIntv" for: // 1/ better managing ranges when all the data have same value // 2/ mimic IDL behavior when data are all positive // please notice that (val_min, val_max) will be changed // and "epsilon" is a coefficient if "extended range" is expected // input: linear min and max, output: linear min and max. // NOTE GD: this function should be rewritten, documented and tested correctly. Most often, the // plots are not exactly what IDL does in the same conditions. The reasons for the choices should be // clearly described in the code, to be checked by others. PLFLT gdlAdjustAxisRange(EnvT* e, string axis, DDouble &start, DDouble &end, bool log /* = false */, int code /* = 0 */) { gdlHandleUnwantedAxisValue(start, end, log); DDouble min, max; bool invert = FALSE; if (end - start >= 0) { min = start; max = end; invert = FALSE; } else { //never happens by construction!!!!!!!!!!!!!!!!!!!!!!! min = end; max = start; invert = TRUE; } PLFLT intv = 1.; int cas = 0; DDouble x; bool debug = false; if (debug) { cout << "init: " << min << " " << max << endl; } // case "all below ABS((MACHAR()).xmin)" //needs example. // if (!log && (abs(max) <= -std::numeric_limits::max())) { // min = DDouble(0.); // max = DDouble(1.); // intv = (PLFLT) (2.); // cas = 1; // } if (log) { min = log10(min); max = log10(max); } // case "all values are equal" if (cas == 0) { x = max - min; if (abs(x) <= std::numeric_limits::min()) { DDouble val_ref; val_ref = max; if (0.98 * min < val_ref) { // positive case max = 1.02 * val_ref; min = 0.98 * val_ref; } else { // negative case max = 0.98 * val_ref; min = 1.02 * val_ref; } if (debug) { cout << "Rescale : " << min << " " << max << endl; } } } // general case (only negative OR negative and positive) if (cas == 0) //rounding is not aka idl due to use of ceil and floor. TBD. { x = max - min; //correct this for calendar values (round to nearest year, month, etc) if ( code > 0) { if (code ==7 ) { if(x>=366) code=1; else if(x>=32) code=2; else if(x>=1.1) code=3; else if(x*24>=1.1) code=4; else if(x*24*60>=1.1) code=5; else code=6; } static int monthSize[]={31,28,31,30,31,30,31,31,30,31,30,31}; DLong Day1,Day2 , Year1,Year2 , Hour1,Hour2 , Minute1,Minute2, MonthNum1,MonthNum2; DLong idow1,icap1,idow2,icap2; DDouble Seconde1,Seconde2; j2ymdhms(min, MonthNum1 , Day1 , Year1 , Hour1 , Minute1, Seconde1, idow1, icap1); MonthNum1++; //j2ymdhms gives back Month number in the [0-11] range for indexing month name tables. pity. j2ymdhms(max, MonthNum2 , Day2 , Year2 , Hour2 , Minute2, Seconde2, idow2, icap2); MonthNum2++; switch(code){ case 1: // day mon year h m s.s dateToJD(min, 1, 1, Year1, 0, 0, 0.0); dateToJD(max, 1, 1, Year2+1, 0, 0, 0.0); break; case 2: dateToJD(min, 1, MonthNum1, Year1, 0, 0, 0.0); MonthNum2++; if (MonthNum2 > 12) {MonthNum2-=12; Year2+=1;} dateToJD(max, 1, MonthNum2, Year2, 0, 0, 0.0); break; case 3: dateToJD(min, Day1, MonthNum1, Year1, 0, 0, 0.0); Day2++; if (Day2 > monthSize[MonthNum2]) {Day2-=monthSize[MonthNum2]; MonthNum2+=1;} if (MonthNum2 > 12) {MonthNum2-=12; Year2+=1;} dateToJD(max, Day2, MonthNum2, Year2, 0, 0, 0.0); break; case 4: dateToJD(min, Day1, MonthNum1, Year1, Hour1, 0, 0.0); Hour2++; if (Hour2 > 23) {Hour2-=24; Day2+=1;} if (Day2 > monthSize[MonthNum2]) {Day2-=monthSize[MonthNum2]; MonthNum2+=1;} if (MonthNum2 > 12) {MonthNum2-=12; Year2+=1;} dateToJD(max, Day2, MonthNum2, Year2, Hour2, 0, 0.0); break; case 5: dateToJD(min, Day1, MonthNum1, Year1, Hour1, Minute1, 0.0); Minute2++; if (Minute2 > 59) {Minute2-=60; Hour2+=1;} if (Hour2 > 23) {Hour2-=24; Day2+=1;} if (Day2 > monthSize[MonthNum2]) {Day2-=monthSize[MonthNum2]; MonthNum2+=1;} if (MonthNum2 > 12) {MonthNum2-=12; Year2+=1;} dateToJD(max, Day2, MonthNum2, Year2, Hour2, Minute2, 0.0); break; case 6: dateToJD(min, Day1, MonthNum1, Year1, Hour1, Minute1, Seconde1); Seconde2++; if (Seconde2 > 59) {Seconde2-=60; Minute2+=1;} if (Minute2 > 59) {Minute2-=60; Hour2+=1;} if (Hour2 > 23) {Hour2-=24; Day2+=1;} if (Day2 > monthSize[MonthNum2]) {Day2-=monthSize[MonthNum2]; MonthNum2+=1;} if (MonthNum2 > 12) {MonthNum2-=12; Year2+=1;} dateToJD(max, Day2, MonthNum2, Year2, Hour2, Minute2, Seconde2); break; default: break; } } else { intv = AutoIntv(x); if (log) { max = ceil((max / intv) * intv); min = floor((min / intv) * intv); } else { max = ceil(max / intv) * intv; min = floor(min / intv) * intv; } } } if (debug) { cout << "cas: " << cas << " new range: " << min << " " << max << endl; } //give back non-log values if (log) { min = pow(10, min); max = pow(10, max); } //check if tickinterval would make more than 59 ticks (IDL apparent limit). In which case, IDL plots only the first 59 intervals: DDouble TickInterval; gdlGetDesiredAxisTickInterval(e, axis, TickInterval); if ( TickInterval > 0.0 ) if ((max-min)/TickInterval > 59) max=min+59.0*TickInterval; if (invert) { start = max; end = min; } else { start = min; end = max; } return intv; } void CheckMargin(GDLGStream* actStream, DFloat xMarginL, DFloat xMarginR, DFloat yMarginB, DFloat yMarginT, PLFLT& xMR, PLFLT& xML, PLFLT& yMB, PLFLT& yMT) { PLFLT sclx=actStream->dCharLength()/actStream->xSubPageSize(); //current char length/subpage size xML=xMarginL*sclx; //margin as percentage of subpage xMR=xMarginR*sclx; PLFLT scly=actStream->dLineSpacing()/actStream->ySubPageSize(); //current char length/subpage size yMB=(yMarginB)*scly; yMT=(yMarginT)*scly; //to allow subscripts and superscripts (as in IDL) if ( xML+xMR>=1.0 ) { Message("XMARGIN to large (adjusted)."); PLFLT xMMult=xML+xMR; xML/=xMMult*1.5; xMR/=xMMult*1.5; } if ( yMB+yMT>=1.0 ) { Message("YMARGIN to large (adjusted)."); PLFLT yMMult=yMB+yMT; yMB/=yMMult*1.5; yMT/=yMMult*1.5; } } void setIsoPort(GDLGStream* actStream, PLFLT x1, PLFLT x2, PLFLT y1, PLFLT y2, PLFLT aspect) { PLFLT X1, X2, Y1, Y2, X1s, X2s, Y1s, Y2s, displacx, displacy, scalex, scaley, offsetx, offsety; if ( aspect<=0.0 ) { actStream->vpor(x1, x2, y1, y2); return; } // here we need too compensate for the change of aspect due to eventual !P.MULTI plots actStream->vpor(x1, x2, y1, y2); //ask for non-iso window actStream->gvpd(X1, X2, Y1, Y2); //get viewport values //compute relation desiredViewport-page viewport x=scalex*X+offsetx: scalex=(x2-x1)/(X2-X1); offsetx=(x1*X2-x2*X1)/(X2-X1); scaley=(y2-y1)/(Y2-Y1); offsety=(y1*Y2-y2*Y1)/(Y2-Y1); //ask for wiewport scaled to isotropic by plplot actStream->vpas(x1, x2, y1, y2, aspect); //retrieve values actStream->gvpd(X1s, X2s, Y1s, Y2s); //measure displacement displacx=X1s-X1; displacy=Y1s-Y1; //set wiewport scaled by plplot, displaced, as vpor using above linear transformation x1=(X1s-displacx)*scalex+offsetx; x2=(X2s-displacx)*scalex+offsetx; y1=(Y1s-displacy)*scaley+offsety; y2=(Y2s-displacy)*scaley+offsety; actStream->vpor(x1, x2, y1, y2); } void GetSFromPlotStructs(DDouble **sx, DDouble **sy, DDouble **sz) { DStructGDL* xStruct=SysVar::X(); //MUST NOT BE STATIC, due to .reset DStructGDL* yStruct=SysVar::Y(); //MUST NOT BE STATIC, due to .reset DStructGDL* zStruct=SysVar::Z(); //MUST NOT BE STATIC, due to .reset unsigned sxTag=xStruct->Desc()->TagIndex("S"); unsigned syTag=yStruct->Desc()->TagIndex("S"); unsigned szTag=zStruct->Desc()->TagIndex("S"); if (sx != NULL) *sx= &(*static_cast(xStruct->GetTag(sxTag, 0)))[0]; if (sy != NULL) *sy= &(*static_cast(yStruct->GetTag(syTag, 0)))[0]; if (sz != NULL) *sz= &(*static_cast(zStruct->GetTag(szTag, 0)))[0]; } void GetWFromPlotStructs(DFloat **wx, DFloat **wy) { DStructGDL* xStruct=SysVar::X(); //MUST NOT BE STATIC, due to .reset DStructGDL* yStruct=SysVar::Y(); //MUST NOT BE STATIC, due to .reset unsigned xwindowTag=xStruct->Desc()->TagIndex("WINDOW"); unsigned ywindowTag=yStruct->Desc()->TagIndex("WINDOW"); *wx= &(*static_cast(xStruct->GetTag(xwindowTag, 0)))[0]; *wy= &(*static_cast(yStruct->GetTag(ywindowTag, 0)))[0]; } void setPlplotScale(GDLGStream* a) { DDouble *sx, *sy; GetSFromPlotStructs( &sx, &sy ); DDouble xStart, xEnd, yStart, yEnd; xStart=-sx[0]/sx[1]; xEnd=(1-sx[0])/sx[1]; yStart=-sy[0]/sy[1]; yEnd=(1-sy[0])/sy[1]; a->wind(xStart, xEnd, yStart, yEnd); } void DataCoordLimits(DDouble *sx, DDouble *sy, DFloat *wx, DFloat *wy, DDouble *xStart, DDouble *xEnd, DDouble *yStart, DDouble *yEnd, bool clip_by_default) { *xStart=(wx[0]-sx[0])/sx[1]; *xEnd=(wx[1]-sx[0])/sx[1]; *yStart=(wy[0]-sy[0])/sy[1]; *yEnd=(wy[1]-sy[0])/sy[1]; // patch from Joanna (tracker item no. 3029409, see test_clip.pro) if ( !clip_by_default ) { // cout << "joanna" << endl; DFloat wxlen=wx[1]-wx[0]; DFloat wylen=wy[1]-wy[0]; DFloat xlen= *xEnd- *xStart; DFloat ylen= *yEnd- *yStart; *xStart= *xStart-xlen/wxlen*wx[0]; *xEnd= *xEnd+xlen/wxlen*(1-wx[1]); *yStart= *yStart-ylen/wylen*wy[0]; *yEnd= *yEnd+ylen/wylen*(1-wy[1]); } // cout << *xStart <<" "<< *xEnd << " "<< *yStart <<" "<< *yEnd << ""<< endl; } void GetUsym(DLong **n, DInt **do_fill, DFloat **x, DFloat **y, bool **do_color, DLong **usymColor , bool **do_thick, DFloat **usymThick) { *n= &(localusym.nusym); *do_fill= &(localusym.fill); *do_color= &(localusym.hasColor); *do_thick= &(localusym.hasThick); *usymColor=&(localusym.color); *usymThick=&(localusym.thick); *x=localusym.usymx; *y=localusym.usymy; } void SetUsym(DLong n, DInt do_fill, DFloat *x, DFloat *y, bool usersymhascolor, DLong usymColor , bool usersymhasthick, DFloat usymThick ) { localusym.nusym=n; localusym.fill=do_fill; for ( int i=0; ijoin(x1, y1, val, y1); a->join(val, y1, val, y); a->join(val, y, x, y); } } void stopClipping(GDLGStream *a) { if (saveBox.initialized) { a->vpor(saveBox.nx1, saveBox.nx2, saveBox.ny1, saveBox.ny2); //restore norm of current box a->wind(saveBox.wx1, saveBox.wx2, saveBox.wy1, saveBox.wy2); //give back world of current box } else cerr<<"plot \"savebox\" not initialized, please report" <WorldToNormedDevice(wx, wy, savedPointX, savedPointY); if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"saveLastPoint as %lf %lf\n", savedPointX, savedPointY); } void getLastPoint(GDLGStream *a, DDouble& wx, DDouble& wy) { a->NormedDeviceToWorld(savedPointX, savedPointY, wx, wy); if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"getLastPoint: Got dev: %lf %lf giving %lf %lf world\n", savedPointX, savedPointY, wx, wy); } /// /// Draws a line along xVal, yVal /// @param general environnement pointer /// @param graphic stream /// @param xVal pointer on DDoubleGDL x values /// @param yVal pointer on DDoubleGDL y values /// @param minVal DDouble min value to plot. /// @param maxVal DDouble max value to plot. /// @param doMinMax bool do we use minval & maxval above? /// @param xLog bool scale is log in x /// @param yLog bool scale is log in y /// @param psym DLong plotting symbol code /// @param append bool values must be drawn starting from last plotted value /// @param color DLongGDL* pointer to color list (NULL if no use) /// void draw_polyline(GDLGStream *a, DDoubleGDL *xVal, DDoubleGDL *yVal, DDouble minVal, DDouble maxVal, bool doMinMax, bool xLog, bool yLog, //end non-implicit parameters DLong psym, bool useProjInfo, bool append, DLongGDL *color) { bool docolor=(color != NULL); // Get decomposed value for colors DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); //if docolor, do we really have more than one color? if (docolor) if (color->N_Elements() == 1) { //do the job once and forget it after. a->Color ( ( *color )[0], decomposed); docolor=false; } if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"draw_polyline()\n"); SizeT plotIndex=0; bool line=false; DLong psym_=0; if ( psym<0 ) { line=true; psym_= -psym; } else if ( psym==0 ) { line=true; psym_=psym; } else { psym_=psym; } //usersym and other syms as well! DFloat *userSymX, *userSymY; DLong *userSymArrayDim; //initialize symbol vertex list static PLFLT xSym[49]; static PLFLT ySym[49]; DInt *do_fill; bool *usersymhascolor; bool *usersymhasthick; DLong *usymColor; DFloat *usymThick; static DInt nofill=0; if ( psym_==8 ) { GetUsym(&userSymArrayDim, &do_fill, &userSymX, &userSymY, &usersymhascolor, &usymColor , &usersymhasthick, &usymThick ); if ( *userSymArrayDim==0 ) { ThrowGDLException("No user symbol defined."); } } else if ( (psym_>0&&psym_<8)) { do_fill=&nofill; userSymArrayDim=&(syml[psym_-1]); switch(psym_) { case 1: userSymX=sym1x; userSymY=sym1y; break; case 2: userSymX=sym2x; userSymY=sym2y; break; case 3: userSymX=sym3x; userSymY=sym3y; break; case 4: userSymX=sym4x; userSymY=sym4y; break; case 5: userSymX=sym5x; userSymY=sym5y; break; case 6: userSymX=sym6x; userSymY=sym6y; break; case 7: userSymX=sym7x; userSymY=sym7y; break; } } DLong minEl=(xVal->N_Elements()N_Elements())? xVal->N_Elements():yVal->N_Elements(); // if scalar x if ( xVal->N_Elements()==1&&xVal->Rank()==0 ) minEl=yVal->N_Elements(); // if scalar y if ( yVal->N_Elements()==1&&yVal->Rank()==0 ) minEl=xVal->N_Elements(); bool mapSet=false; #ifdef USE_LIBPROJ4 LPTYPE idata; XYTYPE odata; if (useProjInfo) { //special case for psyms, line and fills use GDLgrProjectedPolygonPlot() get_mapset(mapSet); if ( mapSet ) { ref=map_init(); if ( ref==NULL ) { ThrowGDLException("Projection initialization failed."); } } } #endif // is one of the 2 "arrays" a singleton or not ? PLFLT y, yMapBefore, y_ref; int flag_y_const=0; y_ref=static_cast((*yVal)[0]); if ( yVal->N_Elements()==1&&yVal->Rank()==0 ) flag_y_const=1; PLFLT x, x1, xMapBefore, x_ref; int flag_x_const=0; x_ref=static_cast((*xVal)[0]); if ( xVal->N_Elements()==1&&xVal->Rank()==0 ) flag_x_const=1; // AC 070601 we use a buffer to use the fast ->line method // instead of the slow ->join one. // 2 tricks: // trick 1/ size of buffer is limited to 1e4 (compromize syze/speed) in order to be able to manage very // large amount of data whitout duplicating all the arrays // trick 2/ when we have a NaN or and Inf, we realize the plot, then reset. int GDL_POLYLINE_BUFFSIZE=500000; // idl default seems to be more than 2e6 !! if ( minEl((*xVal)[i]); else x=x_ref; if ( !flag_y_const ) y=static_cast((*yVal)[i]); else y=y_ref; } #ifdef USE_LIBPROJ4 if ( mapSet ) { idata.u=x * DEG_TO_RAD; idata.v=y * DEG_TO_RAD; if ( i>0 ) { xMapBefore=odata.u; yMapBefore=odata.v; } odata=PJ_FWD(idata, ref); x=odata.u; y=odata.v; } #endif //note: here y is in minVal maxVal if ( doMinMax ) isBad=((ymaxVal)); if ( xLog ) x=log10(x); if ( yLog ) y=log10(y); isBad=(isBad||!isfinite(x)|| !isfinite(y)||isnan(x)||isnan(y)); if ( isBad ) { if ( i_buff>0 ) { if ( line ) { if (docolor) for (SizeT jj=0; jj< i_buff-1 ; ++jj) { a->Color ( ( *color )[plotIndex%color->N_Elements ( )], decomposed); a->line(2, &(x_buff[jj]), &(y_buff[jj])); plotIndex++; } else a->line(i_buff, x_buff, y_buff); } if (psym_>0&&psym_<8) { a->styl(0, NULL, NULL); //symbols drawn in continuous lines for ( int j=0; jgetPsymConvX(); ySym[kk]=y_buff[j]+userSymY[kk]*a->getPsymConvY(); } if (docolor) { a->Color ( ( *color )[plotIndex%color->N_Elements ( )], decomposed); plotIndex++; } if ( *do_fill==1 ) { a->fill(*userSymArrayDim, xSym, ySym); } else { a->line(*userSymArrayDim, xSym, ySym); } } } else if ( psym_==8 ) { a->styl(0, NULL, NULL); //symbols drawn in continuous lines if (*usersymhascolor) { a->Color(*usymColor, decomposed); } if (*usersymhasthick) { a->Thick(*usymThick); } for (int j = 0; j < i_buff; ++j) { for (int kk = 0; kk < *userSymArrayDim; kk++) { xSym[kk] = x_buff[j] + userSymX[kk] * a->getPsymConvX(); ySym[kk] = y_buff[j] + userSymY[kk] * a->getPsymConvY(); } if (*do_fill == 1) { a->fill(*userSymArrayDim, xSym, ySym); } else { a->line(*userSymArrayDim, xSym, ySym); } } } else if ( psym_==10 ) { ac_histo(a, i_buff, x_buff, y_buff, xLog); } i_buff=0; } continue; } x_buff[i_buff]=x; y_buff[i_buff]=y; i_buff=i_buff+1; // cout << "nbuf: " << i << " " << i_buff << " "<< n_buff_max-1 << " " << minEl-1 << endl; if ( (i_buff==GDL_POLYLINE_BUFFSIZE)||((i==minEl-1)&& !append)||((i==minEl)&&append) ) { if ( line ) { if (docolor) for (SizeT jj=0; jj< i_buff-1 ; ++jj) { a->Color ( ( *color )[plotIndex%color->N_Elements ( )], decomposed); a->line(2, &(x_buff[jj]), &(y_buff[jj])); plotIndex++; } else a->line(i_buff, x_buff, y_buff); } if ( psym_>0&&psym_<8 ) { a->styl(0, NULL, NULL); //symbols drawn in continuous lines for ( int j=0; jgetPsymConvX(); ySym[kk]=y_buff[j]+userSymY[kk]*a->getPsymConvY(); } if (docolor) { a->Color ( ( *color )[plotIndex%color->N_Elements ( )], decomposed); plotIndex++; } if ( *do_fill==1 ) { a->fill(*userSymArrayDim, xSym, ySym); } else { a->line(*userSymArrayDim, xSym, ySym); } } } else if ( psym_==8 ) { a->styl(0, NULL, NULL); //symbols drawn in continuous lines if (*usersymhascolor) { a->Color(*usymColor, decomposed); } if (*usersymhasthick) { a->Thick(*usymThick); } for (int j = 0; j < i_buff; ++j) { for (int kk = 0; kk < *userSymArrayDim; kk++) { xSym[kk] = x_buff[j] + userSymX[kk] * a->getPsymConvX(); ySym[kk] = y_buff[j] + userSymY[kk] * a->getPsymConvY(); } if (*do_fill == 1) { a->fill(*userSymArrayDim, xSym, ySym); } else { a->line(*userSymArrayDim, xSym, ySym); } } } else if ( psym_==10 ) { ac_histo(a, i_buff, x_buff, y_buff, xLog); } // we must recopy the last point since the line must continue (tested via small buffer ...) x_buff[0]=x_buff[i_buff-1]; y_buff[0]=y_buff[i_buff-1]; i_buff=1; } } delete[] x_buff; delete[] y_buff; //save last point saveLastPoint(a, x, y); } //BACKGROUND COLOR //Very special usage only in plotting surface void gdlSetGraphicsPenColorToBackground(GDLGStream *a) { a->plstream::col0( 0); } //COLOR // helper for NOERASE //PSYM //SYMSIZE //CHARSIZE //THICK //LINESTYLE void gdlLineStyle(GDLGStream *a, DLong style) { static PLINT mark1[]={75}; static PLINT space1[]={1500}; static PLINT mark2[]={1500}; static PLINT space2[]={1500}; static PLINT mark3[]={1500, 100}; static PLINT space3[]={1000, 1000}; static PLINT mark4[]={1500, 100, 100, 100}; static PLINT space4[]={1000, 1000, 1000, 1000}; static PLINT mark5[]={3000}; static PLINT space5[]={1500}; // see plplot-5.5.3/examples/c++/x09.cc switch(style) { case 0: a->styl(0, mark1, space1); return; case 1: a->styl(1, mark1, space1); return; case 2: a->styl(1, mark2, space2); return; case 3: a->styl(2, mark3, space3); return; case 4: a->styl(4, mark4, space4); return; case 5: a->styl(1, mark5, space5); return; default: a->styl(0, NULL, NULL); return; } } //crange to struct void gdlStoreAxisCRANGE(string axis, DDouble Start, DDouble End, bool log) { DStructGDL* Struct=NULL; if ( axis=="X" ) Struct=SysVar::X(); if ( axis=="Y" ) Struct=SysVar::Y(); if ( axis=="Z" ) Struct=SysVar::Z(); if ( Struct!=NULL ) { int debug=0; if ( debug ) cout<<"Set :"<Desc()->TagIndex("CRANGE"); if ( log ) { (*static_cast(Struct->GetTag(crangeTag, 0)))[0]=log10(Start); (*static_cast(Struct->GetTag(crangeTag, 0)))[1]=log10(End); if ( debug ) cout<<"set log"<(Struct->GetTag(crangeTag, 0)))[0]=Start; (*static_cast(Struct->GetTag(crangeTag, 0)))[1]=End; } } } //CRANGE from struct void gdlGetCurrentAxisRange(string axis, DDouble &Start, DDouble &End, bool checkMapset) { DStructGDL* Struct=NULL; if ( axis=="X" ) Struct=SysVar::X(); if ( axis=="Y" ) Struct=SysVar::Y(); if ( axis=="Z" ) Struct=SysVar::Z(); Start=0; End=0; if ( Struct!=NULL ) { int debug=0; if ( debug ) cout<<"Get :"<Desc()->TagIndex("UV_BOX"); static DDoubleGDL *uvbox; uvbox=static_cast(mapStruct->GetTag(uvboxTag, 0)); if (axis=="X") { Start=(*uvbox)[0]; End=(*uvbox)[2]; } else { Start=(*uvbox)[1]; End=(*uvbox)[3]; } } else { static unsigned crangeTag=Struct->Desc()->TagIndex("CRANGE"); Start=(*static_cast(Struct->GetTag(crangeTag, 0)))[0]; End=(*static_cast(Struct->GetTag(crangeTag, 0)))[1]; static unsigned typeTag=Struct->Desc()->TagIndex("TYPE"); if ( (*static_cast(Struct->GetTag(typeTag, 0)))[0]==1 ) { Start=pow(10., Start); End=pow(10., End); if ( debug ) cout<<"Get log :"<Desc()->TagIndex("WINDOW"); wStart=(*static_cast(Struct->GetTag(windowTag, 0)))[0]; wEnd=(*static_cast(Struct->GetTag(windowTag, 0)))[1]; } } //Stores [XYZ].WINDOW, .REGION and .S void gdlStoreAxisSandWINDOW(GDLGStream* actStream, string axis, DDouble Start, DDouble End, bool log) { PLFLT p_xmin, p_xmax, p_ymin, p_ymax, norm_min, norm_max, charDim; actStream->gvpd(p_xmin, p_xmax, p_ymin, p_ymax); //viewport normalized coords DStructGDL* Struct=NULL; if ( axis=="X" ) {Struct=SysVar::X(); norm_min=p_xmin; norm_max=p_xmax; charDim=actStream->nCharLength();} if ( axis=="Y" ) {Struct=SysVar::Y(); norm_min=p_ymin; norm_max=p_ymax; charDim=actStream->nCharHeight();} if ( axis=="Z" ) {Struct=SysVar::Z(); norm_min=0; norm_max=1; charDim=actStream->nCharLength();} if ( Struct!=NULL ) { unsigned marginTag=Struct->Desc()->TagIndex("MARGIN"); DFloat m1=(*static_cast(Struct->GetTag(marginTag, 0)))[0]; DFloat m2=(*static_cast(Struct->GetTag(marginTag, 0)))[1]; static unsigned regionTag=Struct->Desc()->TagIndex("REGION"); (*static_cast(Struct->GetTag(regionTag, 0)))[0]=max(0.0,norm_min-m1*charDim); (*static_cast(Struct->GetTag(regionTag, 0)))[1]=min(1.0,norm_max+m2*charDim); // if ( log ) {Start=log10(Start); End=log10(End);} static unsigned windowTag=Struct->Desc()->TagIndex("WINDOW"); (*static_cast(Struct->GetTag(windowTag, 0)))[0]=norm_min; (*static_cast(Struct->GetTag(windowTag, 0)))[1]=norm_max; static unsigned sTag=Struct->Desc()->TagIndex("S"); (*static_cast(Struct->GetTag(sTag, 0)))[0]= (norm_min*End-norm_max*Start)/(End-Start); (*static_cast(Struct->GetTag(sTag, 0)))[1]= (norm_max-norm_min)/(End-Start); } } void gdlStoreCLIP(DLongGDL* clipBox) { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset int i; static unsigned clipTag=pStruct->Desc()->TagIndex("CLIP"); for ( i=0; iN_Elements(); ++i ) (*static_cast(pStruct->GetTag(clipTag, 0)))[i]=(*clipBox)[i]; } void gdlGetAxisType(string axis, bool &log) { DStructGDL* Struct; if ( axis=="X" ) Struct=SysVar::X(); if ( axis=="Y" ) Struct=SysVar::Y(); if ( axis=="Z" ) Struct=SysVar::Z(); if ( Struct!=NULL ) { static unsigned typeTag=Struct->Desc()->TagIndex("TYPE"); if ( (*static_cast(Struct->GetTag(typeTag, 0)))[0]==1 ) log=true; else log=false; } } void get_mapset(bool &mapset) { DStructGDL* Struct=SysVar::X(); //MUST NOT BE STATIC, due to .reset if ( Struct!=NULL ) { static unsigned typeTag=Struct->Desc()->TagIndex("TYPE"); if ( (*static_cast(Struct->GetTag(typeTag, 0)))[0]==3 ) mapset=true; else mapset=false; } } void set_mapset(bool mapset) { DStructGDL* Struct=SysVar::X(); //MUST NOT BE STATIC, due to .reset if ( Struct!=NULL ) { static unsigned typeTag=Struct->Desc()->TagIndex("TYPE"); (*static_cast(Struct->GetTag(typeTag, 0)))[0]=(mapset)?3:0; } } //axis type (log..) void gdlStoreAxisType(string axis, bool Type) { DStructGDL* Struct=NULL; if ( axis=="X" ) Struct=SysVar::X(); if ( axis=="Y" ) Struct=SysVar::Y(); if ( axis=="Z" ) Struct=SysVar::Z(); if ( Struct!=NULL ) { static unsigned typeTag=Struct->Desc()->TagIndex("TYPE"); (*static_cast(Struct->GetTag(typeTag, 0)))[0]=Type; } } void doOurOwnFormat(PLINT axisNotUsed, PLFLT value, char *label, PLINT length, PLPointer data) { struct GDL_TICKDATA *ptr = (GDL_TICKDATA* )data; //was: // static string normalfmt[7]={"%1.0fx10#u%d#d","%2.1fx10#u%d#d","%3.2fx10#u%d#d","%4.2fx10#u%d#d","%5.4fx10#u%d#d","%6.5fx10#u%d#d","%7.6fx10#u%d#d"}; // static string specialfmt="10#u%d#d"; // static string specialfmtlog="10#u%s#d"; //we need !3x!X to insure the x sign is always written in single roman. static string normalfmt[7]={"%1.0f!3x!X10!E%d!N","%2.1f!3x!X10!E%d!N","%3.2f!3x!X10!E%d!N","%4.2f!3x!X10!E%d!N","%5.4f!3x!X10!E%d!N","%6.5f!3x!X10!E%d!N","%7.6f!3x!X10!E%d!N"}; static string specialfmt="10!E%d!N"; static string specialfmtlog="10!E%s!N"; PLFLT z; int ns; char *i; int sgn=(value<0)?-1:1; //special cases, since plplot gives approximate zero values, not strict zeros. if (!(ptr->isLog) && (sgn*valueaxisrange*1e-6)) { snprintf(label, length, "0"); return; } //in log, plplot gives correctly rounded "integer" values but 10^0 needs a bit of help. if ((ptr->isLog) && (sgn*value<1e-6)) //i.e. 0 { snprintf(label, length, "1"); return; } int e=floor(log10(value*sgn)); char *test=(char*)calloc(2*length, sizeof(char)); //be safe if (!isfinite(log10(value*sgn))||(e<4 && e>-4)) { snprintf(test, length, "%f",value); ns=strlen(test); i=strrchr (test,'0'); while (i==(test+ns-1)) //remove trailing zeros... { *i='\0'; i=strrchr(test,'0'); ns--; } i=strrchr(test,'.'); //remove trailing '.' if (i==(test+ns-1)) {*i='\0'; ns--;} if (ptr->isLog) { snprintf( label, length, specialfmtlog.c_str(),test); } else { strcpy(label, test); } } else { z=value*sgn/pow(10.,e); snprintf(test,20,"%7.6f",z); ns=strlen(test); i=strrchr(test,'0'); while (i==(test+ns-1)) { *i='\0'; i=strrchr(test,'0'); ns--; } ns-=2;ns=(ns>6)?6:ns; if (floor(sgn*z)==1 && ns==0) { snprintf( label, length, specialfmt.c_str(),e); } else { snprintf( label, length, normalfmt[ns].c_str(),sgn*z,e); } } free(test); } void doFormatAxisValue(DDouble value, string &label) { static string normalfmt[7]={"%1.0fx10^%d","%2.1fx10^%d","%3.2fx10^%d","%4.2fx10^%d","%5.4fx10^%d","%6.5fx10^%d","%7.6fx10^%d"}; static string specialfmt="10^%d"; static const int length=20; PLFLT z; int ns; char *i; int sgn=(value<0)?-1:1; //special cases, since plplot gives approximate zero values, not strict zeros. if (sgn*value< std::numeric_limits::min()) { label="0"; return; } int e=floor(log10(value*sgn)); char *test=(char*)calloc(2*length, sizeof(char)); //be safe if (!isfinite(e)||(e<4 && e>-4)) { snprintf(test, length, "%f",value); ns=strlen(test); i=strrchr (test,'0'); while (i==(test+ns-1)) //remove trailing zeros... { *i='\0'; i=strrchr(test,'0'); ns--; } i=strrchr(test,'.'); //remove trailing '.' if (i==(test+ns-1)) {*i='\0'; ns--;} } else { z=value*sgn/pow(10.,e); snprintf(test,20,"%7.6f",z); ns=strlen(test); i=strrchr(test,'0'); while (i==(test+ns-1)) { *i='\0'; i=strrchr(test,'0'); ns--; } ns-=2;ns=(ns>6)?6:ns; if (floor(sgn*z)==1 && ns==0) snprintf( test, length, specialfmt.c_str(),e); else snprintf( test, length, normalfmt[ns].c_str(),sgn*z,e); } label=test; free(test); } BaseGDL* format_axis_values(EnvT *e){ DDoubleGDL* p0D = e->GetParAs( 0); DStringGDL* res = new DStringGDL( p0D->Dim(), BaseGDL::NOZERO); SizeT nEl = p0D->N_Elements(); for( SizeT i=0; ia->TranslateFormatCodes(label, &nchars); ptr->nchars=max(ptr->nchars,nchars); strcpy(label,out.c_str()); } void gdlMultiAxisTickFunc(PLINT axis, PLFLT value, char *label, PLINT length, PLPointer multiaxisdata) { static GDL_TICKDATA tdata; static SizeT internalIndex=0; static DLong lastUnits=0; static string theMonth[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; PLINT Month, Day , Year , Hour , Minute, dow, cap; PLFLT Second; struct GDL_MULTIAXISTICKDATA *ptr = (GDL_MULTIAXISTICKDATA* )multiaxisdata; tdata.a=ptr->a; tdata.isLog=ptr->isLog; if (ptr->counter != lastUnits) { lastUnits=ptr->counter; internalIndex=0; } if (ptr->what==GDL_TICKFORMAT || (ptr->what==GDL_TICKFORMAT_AND_UNITS && ptr->counter < ptr->nTickFormat) ) { if (ptr->counter > ptr->nTickFormat-1) { doOurOwnFormat(axis, value, label, length, &tdata); } else { if (((*ptr->TickFormat)[ptr->counter]).substr(0,1) == "(") { //internal format, call internal func "STRING" EnvT *e=ptr->e; static int stringIx = LibFunIx("STRING"); assert( stringIx >= 0); EnvT* newEnv= new EnvT(e, libFunList[stringIx], NULL); Guard guard( newEnv); // add parameters newEnv->SetNextPar( new DDoubleGDL(value)); newEnv->SetNextPar( new DStringGDL(((*ptr->TickFormat)[ptr->counter]).c_str())); // make the call BaseGDL* res = static_cast(newEnv->GetPro())->Fun()(newEnv); strncpy(label,(*static_cast(res))[0].c_str(),1000); } else // external function: if tickunits not specified, pass Axis (int), Index(int),Value(Double) // else pass also Level(int) // Thanks to Marc for code snippet! // NOTE: this encompasses the 'LABEL_DATE' format, an existing procedure in the IDL library. { EnvT *e=ptr->e; DString callF=(*ptr->TickFormat)[ptr->counter]; // this is a function name -> convert to UPPERCASE callF = StrUpCase( callF); // Search in user proc and function SizeT funIx = GDLInterpreter::GetFunIx( callF); EnvUDT* newEnv = new EnvUDT( e->CallingNode(), funList[ funIx], (DObjGDL**)NULL); Guard< EnvUDT> guard( newEnv); // add parameters newEnv->SetNextPar( new DLongGDL(axis)); newEnv->SetNextPar( new DLongGDL(internalIndex)); newEnv->SetNextPar( new DDoubleGDL(value)); if (ptr->what==GDL_TICKFORMAT_AND_UNITS) newEnv->SetNextPar( new DLongGDL(ptr->counter)); // guard *before* pushing new env StackGuard guard1 ( e->Interpreter()->CallStack()); e->Interpreter()->CallStack().push_back(newEnv); guard.release(); BaseGDL* retValGDL = e->Interpreter()->call_fun(static_cast(newEnv->GetPro())->GetTree()); // we are the owner of the returned value Guard retGuard( retValGDL); strncpy(label,(*static_cast(retValGDL))[0].c_str(),1000); } } } else if (ptr->what==GDL_TICKUNITS || (ptr->what==GDL_TICKFORMAT_AND_UNITS && ptr->counter >= ptr->nTickFormat)) { if (ptr->counter > ptr->nTickUnits-1 ) { doOurOwnFormat(axis, value, label, length, &tdata); } else { DString what=StrUpCase((*ptr->TickUnits)[ptr->counter]); if (what.length()<1) { doOurOwnFormat(axis, value, label, length, &tdata); } else if (what.substr(0,7)=="NUMERIC") { doOurOwnFormat(axis, value, label, length, &tdata); } else { j2ymdhms(value, Month , Day , Year , Hour , Minute, Second, dow, cap); int convcode=0; if (what.length()<1) convcode=7; else if (what.substr(0,4)=="YEAR") convcode=1; else if (what.substr(0,5)=="MONTH") convcode=2; else if (what.substr(0,3)=="DAY") convcode=3; else if (what.substr(0,4)=="HOUR") convcode=4; else if (what.substr(0,6)=="MINUTE") convcode=5; else if (what.substr(0,6)=="SECOND") convcode=6; else if (what.substr(0,4)=="TIME") { if(ptr->axisrange>=366) convcode=1; else if(ptr->axisrange>=32) convcode=2; else if(ptr->axisrange>=1.1) convcode=3; else if(ptr->axisrange*24>=1.1) convcode=4; else if(ptr->axisrange*24*60>=1.1) convcode=5; else convcode=6; } else convcode=7; switch(convcode){ case 1: snprintf( label, length, "%d", Year); break; case 2: snprintf( label, length, "%s", theMonth[Month].c_str()); break; case 3: snprintf( label, length, "%d", Day); break; case 4: snprintf( label, length, "%02d", Hour); break; case 5: snprintf( label, length, "%02d", Minute); break; case 6: snprintf( label, length, "%05.2f", Second); break; case 7: doOurOwnFormat(axis, value, label, length, &tdata); break; } } } } //translate format codes (as in mtex). double nchars; std::string out = ptr->a->TranslateFormatCodes(label, &nchars); ptr->nchars=max(ptr->nchars,nchars); strcpy(label,out.c_str()); internalIndex++; } void gdlSingleAxisTickNamedFunc( PLINT axis, PLFLT value, char *label, PLINT length, PLPointer data) { static GDL_TICKDATA tdata; struct GDL_TICKNAMEDATA *ptr = (GDL_TICKNAMEDATA* )data; tdata.isLog=ptr->isLog; tdata.axisrange=ptr->axisrange; if (ptr->counter > ptr->nTickName-1) { doOurOwnFormat(axis, value, label, length, &tdata); } else { snprintf( label, length, "%s", ((*ptr->TickName)[ptr->counter]).c_str() ); } //translate format codes (as in mtex). double nchars; std::string out = ptr->a->TranslateFormatCodes(label, &nchars); ptr->nchars=max(ptr->nchars,nchars); strcpy(label,out.c_str()); ptr->counter++; } bool T3Denabled() { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DLong ok4t3d=(*static_cast(pStruct->GetTag(pStruct->Desc()->TagIndex("T3D"), 0)))[0]; if (ok4t3d==0) return false; else return true; } void usersym(EnvT *e) { DFloatGDL *xyVal, *xVal, *yVal; Guard p0_guard; DLong n; DInt do_fill; bool do_color; bool do_thick; DFloat thethick; DLong thecolor; DFloat *x, *y; SizeT nParam=e->NParam(); if (nParam==0) e->Throw("Incorrect number of arguments."); if ( nParam==1 ) { BaseGDL* p0=e->GetNumericArrayParDefined(0)->Transpose(NULL); //hence [49,2] xyVal=static_cast (p0->Convert2(GDL_FLOAT, BaseGDL::COPY)); p0_guard.Reset(p0); // delete upon exit if ( xyVal->Rank()!=2||xyVal->Dim(1)!=2 ) e->Throw(e->GetParString(0)+" must be a 2-dim array of type [2,N] in this context."); if ( xyVal->Dim(0)>49 ) { e->Throw("Max array size for USERSYM is 49"); } n=xyVal->Dim(0); // array is in the good order for direct C assignement x=&(*xyVal)[0]; y=&(*xyVal)[n]; } else { xVal=e->GetParAs< DFloatGDL>(0); if ( xVal->Rank()!=1 ) e->Throw(e->GetParString(0)+" must be a 1D array in this context: "); yVal=e->GetParAs< DFloatGDL>(1); if ( yVal->Rank()!=1 ) e->Throw("Expression must be a 1D array in this context: "+e->GetParString(1)); if ( xVal->Dim(0)!=yVal->Dim(0) ) { e->Throw("Arrays must have same size "); } if ( xVal->Dim(0)>49 ) { e->Throw("Max array size for USERSYM is 49"); } n=xVal->Dim(0); x=&(*xVal)[0]; y=&(*yVal)[0]; } do_fill=0; static int FILLIx = e->KeywordIx("FILL"); if ( e->KeywordSet(FILLIx) ) { do_fill=1; } //IDL does not complain if color is undefined. do_color=false; thecolor=0; static int COLORIx = e->KeywordIx("COLOR"); if ( e->KeywordPresent(COLORIx)) { if (e->IfDefGetKWAs( COLORIx )) { e->AssureLongScalarKW(COLORIx, thecolor); do_color=true; } } //IDL does not complain if thick is undefined. do_thick=false; thethick=0; static int THICKIx = e->KeywordIx("THICK"); if ( e->KeywordPresent(THICKIx)) { if (e->IfDefGetKWAs( THICKIx )) { e->AssureFloatScalarKW(THICKIx, thethick); do_thick=true; } } SetUsym(n, do_fill, x, y, do_color, thecolor, do_thick, thethick); } static DDouble bad=sqrt(-1); struct Vertex { DDouble lon; //lon DDouble lat; //lat }; struct Point3d { DDouble x; DDouble y; DDouble z; }; inline DDouble norm3d(const Point3d* p) { return sqrt(p->x*p->x+p->y*p->y+p->z*p->z); } inline DDouble norm3d(DDouble x, DDouble y, DDouble z) { return sqrt(x*x+y*y+z*z); } inline void normalize3d(Point3d* p){ DDouble norm=norm3d(p); p->x/=norm; p->y/=norm; p->z/=norm; } Point3d* toNormPoint3d(const Point3d* p){ DDouble norm=norm3d(p); Point3d* normed=new Point3d; normed->x=p->x/norm; normed->y=p->y/norm; normed->z=p->z/norm; return normed; } Point3d* toPoint3d(DDouble x, DDouble y, DDouble z) { Point3d* p = new Point3d; DDouble norm=norm3d(x,y,z); p->x = x/norm; p->y = y/norm; p->z = z/norm; return p; } Point3d* toPoint3d(const Vertex* v) { Point3d* p = new Point3d; p->x = cos(v->lon) * cos(v->lat); p->y = sin(v->lon) * cos(v->lat); p->z = sin(v->lat); return p; } Point3d* diff3d(const Point3d* p1, const Point3d* p2) { return toPoint3d((p2->x-p1->x),(p2->y-p1->y),(p2->z-p1->z)); } Vertex* toVertex(const Point3d* dirty_p) { //vertex is on a sphere, normalize Point3d Point3d* p=toNormPoint3d(dirty_p); Vertex* v = new Vertex; v->lon = atan2(p->y, p->x); v->lat = atan2(p->z, sqrt(p->x * p->x + p->y * p->y)); delete p; return v; } Point3d* crossP(const Point3d* p1, const Point3d *p2){ Point3d* p = new Point3d; p->x=(p1->y*p2->z-p1->z*p2->y); p->y=(p1->z*p2->x-p1->x*p2->z); p->z=(p1->x*p2->y-p1->y*p2->x); return p; } Point3d* normedCrossP(const Point3d* p1, const Point3d *p2){ Point3d* p = new Point3d; p->x=(p1->y*p2->z-p1->z*p2->y); p->y=(p1->z*p2->x-p1->x*p2->z); p->z=(p1->x*p2->y-p1->y*p2->x); normalize3d(p); return p; } //norm of cross product of two vectors DDouble normOfCrossP(const Point3d* p1, const Point3d *p2){ Point3d* p = new Point3d; p->x=(p1->y*p2->z-p1->z*p2->y); p->y=(p1->z*p2->x-p1->x*p2->z); p->z=(p1->x*p2->y-p1->y*p2->x); return norm3d(p); } inline DDouble dotP(const Point3d* p1, const Point3d *p2){ return p1->x*p2->x+p1->y*p2->y+p1->z*p2->z; } inline DDouble DistanceOnSphere(const Point3d* p1, const Point3d *p2) { return atan2(normOfCrossP(p1,p2),dotP(p1,p2)); } inline DDouble DistanceOnSphere(DDouble x, DDouble y, DDouble z, DDouble px, DDouble py, DDouble pz) { DDouble dotp=x*px+y*py+z*pz; DDouble crossp=sqrt((y*pz-z*py)*(y*pz-z*py) + (z*px-x*pz)*(z*px-x*pz) + (x*py-y*px)*(x*py-y*px)) ; return atan2(crossp,dotp); } inline DDouble DistanceOnSphere(const Vertex* v1, const Vertex* v2) { return DistanceOnSphere(toPoint3d(v1), toPoint3d(v2)); } // // vector normal to great circle defined by point3d and a bearing angle // Point3d* greatCircle(const Point3d* p, DDouble b){ // DDouble lon,lat; // lon = atan2(p->y, p->x); // lat = atan2(p->z, sqrt(p->x * p->x + p->y * p->y)); // DDouble x,y,z; // x = sin(lon) * cos(b) - sin(lat) * cos(lon) * sin(b); // y = -cos(lon) * cos(b) - sin(lat) * sin(lon) * sin(b); // z = cos(lat) * sin(b); // return toPoint3d(x,y,z); // } // inline DDouble OrientedAngleOfTwoPlanes(const Point3d* p1, const Point3d *p2, const Point3d *p){ // DDouble sint,cost; // Point3d* c=crossP(p1,p2); // DDouble sign=dotP(c,p); //orients the angle // sint=normCrossP(p1,p2)*(sign < 0)?-1:1; // cost=dotP(p1,p2); // return atan2(sint,cost); // } // DDouble bearing(const Point3d* p1, const Point3d* p2) { // static Point3d* northPole = toPoint3d(0.0, 0.0, 1.0); // Point3d* c1 = crossP(p1, p2); // Point3d* c2 = crossP(p1, northPole); // // bearing is (signed) angle between great circle p1p2 & and great circle p1 north pole // return OrientedAngleOfTwoPlanes(c1, c2, p1); // }; Point3d* CutPosition(const Point3d* p1, const Point3d* p2, DDouble u,DDouble v,DDouble w){ // p1 p2 define a plane--> perpendicular vector Point3d* p1p2=crossP(p1,p2); // u,v,w define the 2nd vector Point3d* cutplane=toPoint3d(u,v,w); // intersection of the 2 planes give two opposite points on sphere. We must choose. Point3d* cut1=crossP(p1p2,cutplane); Point3d* cut2=crossP(cutplane,p1p2); //general case: we choose depending on the direction we travel from p1 to p2. delete p1p2; if (dotP(crossP(cutplane,p2),cut1) > 0) {delete cut1;return cut2;} else {delete cut2; return cut1;} } inline Vertex* CutPosition(const Vertex* v1, const Vertex* v2, DDouble u,DDouble v,DDouble w){ return toVertex(CutPosition( toPoint3d(v1), toPoint3d(v2), u, v, w ) ); } inline DDouble distToCutplane(const Vertex* v, DDouble a,DDouble b,DDouble c){ Point3d* p=toPoint3d(v); return (p->x*a+p->y*b+p->z*c); } // inline DDouble CutPosition(DDouble x1,DDouble y1,DDouble z1, // DDouble x2,DDouble y2,DDouble z2, // DDouble u,DDouble v,DDouble w, // DDouble &x, DDouble &y, DDouble &z) // { // //vector perpendicular to plane containing p1 & p2: cross product of p1,p2 // DDouble a=(y1*z2-z1*y2); // DDouble b=(z1*x2-x1*z2); // DDouble c=(x1*y2-y1*x2); // //point id cross product of this vector with the cut plane defining vector. there are two of them: // DDouble xplus,yplus,zplus,xmoins,ymoins,zmoins; // x=(b*w-c*v); // y=(c*u-a*w); // z=(a*v-b*u); // DDouble norm=sqrt((x*x)+(y*y)+(z*z)); // x/=norm; // y/=norm; // z/=norm; // } #define avoidance 2E-10 //1 arc minute! //plane-vector intersection. Problem is: we cannot afford (x1,y1,z1) or (x2,y2,z2) to be exactly on the plane. //in this case, the result, within the numerical error, can be on the "wrong" side. inline void OnSphereVectorPlaneIntersection(DDouble x1,DDouble y1,DDouble z1,DDouble x2,DDouble y2, DDouble z2,DDouble u,DDouble v,DDouble w,DDouble h, DDouble &x, DDouble &y, DDouble &z){ //compute exact point of crossing the plane, following a great circle (3d vectors=> we follow great circles.) Point3d* p1=toPoint3d(x1,y1,z1); Point3d* p2=toPoint3d(x2,y2,z2); Point3d* p=CutPosition(p1,p2,u,v, w); x=p->x; y=p->y; z=p->z; delete p1; delete p2; delete p; return; } //Must be static and in plotting.hpp if one changes the position of "MAP_STRUCTURE". DStructGDL *GetMapAsMapStructureKeyword(EnvT *e, bool &externalmap) { externalmap = e->KeywordSet( 0 ); //MAP_STRUCTURE DStructGDL* map = NULL; if ( externalmap ) { map = e->GetKWAs( 0 ); //MAP_STRUCTURE if ( map->Desc( ) != SysVar::Map( )->Desc( ) ) e->Throw( "Conflicting data structures: MAP_STRUCTURE,!MAP." ); unsigned projectionTag = map->Desc( )->TagIndex( "PROJECTION" ); DLong map_projection = (*static_cast (map->GetTag( projectionTag, 0 )))[0]; if ( map_projection < 1 ) e->Throw( "Map transform not established." ); } else { map = SysVar::Map( ); unsigned projectionTag = map->Desc( )->TagIndex( "PROJECTION" ); DLong map_projection = (*static_cast (map->GetTag( projectionTag, 0 )))[0]; if ( map_projection < 1 ) e->Throw( "Map transform not established." ); } return map; } #define DELTA (double)(0.5*DEG_TO_RAD) //0.5 degree for increment between stitch vertexes. struct Polygon { std::list VertexList; int type; //+1 before cut, -1 after cut int index; //keep cut index int inside; // number of polygons inside int outside; // number of polygons outside DDouble xcut; //x coord for 1st cut DDouble ycut; //y coord .. DDouble zcut; //z .. DDouble cutDistAtStart; //cut distance for reordering DDouble cutDistAtEnd; //cut distance for reordering bool valid; //to be ignored (polygon has been transferred to another polygon list }; DDouble distFromCut(const Polygon& p, DDouble x, DDouble y, DDouble z) { return DistanceOnSphere(p.xcut, p.ycut, p.zcut, x, y, z ); } DDouble distFromEnd(const Polygon * p, const Polygon * q) { return fabs(p->cutDistAtEnd-q->cutDistAtStart); } bool OrderPolygonsAfter(const Polygon& first, const Polygon & second){ return (first.cutDistAtStart < second.cutDistAtStart); } bool OrderPolygonsBefore(const Polygon& first, const Polygon & second){ return (first.cutDistAtEnd < second.cutDistAtEnd); } bool IsPolygonInside(const Polygon * first, const Polygon * second){ //is second inside first? if (DEBUG_CONTOURS) cerr<<"("<cutDistAtStart/DEG_TO_RAD<<" < "<< second->cutDistAtStart/DEG_TO_RAD<<"? && " <cutDistAtEnd/DEG_TO_RAD<<" > "<cutDistAtEnd/DEG_TO_RAD<<"? "; bool ret = (first->cutDistAtStart < second->cutDistAtStart && first->cutDistAtEnd > second->cutDistAtEnd); if (DEBUG_CONTOURS) { if (ret) cerr<<"YES"<VertexList.back():p->VertexList.front()); xs = cos( start->lon ) * cos( start->lat ); ys = sin( start->lon ) * cos( start->lat); zs = sin( start->lat ); Vertex *end=new Vertex (invert?p->VertexList.front():p->VertexList.back()); xe = cos( end->lon ) * cos( end->lat ); ye = sin( end->lon ) * cos( end->lat ); ze = sin( end->lat ); // DDouble dist=DistanceOnSphere( xs, ys, zs, xe, ye, ze); DDouble dist=DistanceOnSphere(start, end); int nvertex=abs(dist/DELTA); if (nvertex > 0) { DDouble dx=(xe-xs)/nvertex; DDouble dy=(ye-ys)/nvertex; DDouble dz=(ze-zs)/nvertex; for (int k=0; klon=atan2( y, x ); stitch->lat=atan2(z,sqrt(x*x+y*y)); //asin( z ); p->VertexList.push_back(*stitch); } } p->VertexList.push_back(*start); //close contour delete end; } void StitchTwoPolygonsOnGreatCircle(Polygon *p, Polygon *q){ //stich end of p to start of q DDouble x, y, z, xs, ys, zs, xe, ye, ze; Vertex *start=new Vertex; start->lat=(p->VertexList.back()).lat; //end of p start->lon=(p->VertexList.back()).lon; //end of p xs = cos( start->lon ) * cos( start->lat ); ys = sin( start->lon ) * cos( start->lat); zs = sin( start->lat ); Vertex *end=new Vertex; end->lat=(q->VertexList.front()).lat; end->lon=(q->VertexList.front()).lon; xe = cos( end->lon ) * cos( end->lat ); ye = sin( end->lon ) * cos( end->lat ); ze = sin( end->lat ); // DDouble dist=DistanceOnSphere( xs, ys, zs, xe, ye, ze); DDouble dist=DistanceOnSphere( start, end); int nvertex=abs(dist/DELTA); if (nvertex > 0) { DDouble dx=(xe-xs)/nvertex; DDouble dy=(ye-ys)/nvertex; DDouble dz=(ze-zs)/nvertex; for (int k=0; klon=atan2( y, x ); stitch->lat=atan2(z,sqrt(x*x+y*y)); //asin( z ); p->VertexList.push_back(*stitch); //add all supplementary vertices to p } } if (p==q) { p->VertexList.push_back(*start); //stick p to start of q } else { //add all of q at end of p; delete start; p->VertexList.splice(p->VertexList.end(),q->VertexList); p->cutDistAtEnd=q->cutDistAtEnd; } delete end; } DDoubleGDL* gdlProjForward(PROJTYPE ref, DStructGDL* map, DDoubleGDL *lonsIn, DDoubleGDL *latsIn, DLongGDL *connIn, bool doConn, DLongGDL *&gonsOut, bool doGons, DLongGDL *&linesOut, bool doLines, bool const doFill) { //DATA MUST BE IN RADIANS #ifdef USE_LIBPROJ4 LPTYPE idata; XYTYPE odata; #endif unsigned pTag = map->Desc()->TagIndex("PIPELINE"); DDoubleGDL* pipeline = (static_cast (map->GetTag(pTag, 0))->Dup()); DLong dims[2]; enum { EXIT = 0, SPLIT, CLIP_PLANE, TRANSFORM, CLIP_UV }; dims[0] = pipeline->Dim(0); dims[1] = pipeline->Dim(1); int line = 0; //if pipeline is void, a TRANSFORM will be applied anyway.This test is just for that. bool PerformTransform = (pipeline->Sum() == 0); if (PerformTransform) (*pipeline)[0] = TRANSFORM; //just change value of pipeline (which is a copy) bool fill = (doFill || doGons); int icode = (*pipeline)[dims[0] * line + 0]; DDouble a = (*pipeline)[dims[0] * line + 1]; //plane a,b,c,d DDouble b = (*pipeline)[dims[0] * line + 2]; DDouble c = (*pipeline)[dims[0] * line + 3]; DDouble d = (*pipeline)[dims[0] * line + 4]; DDouble px = (*pipeline)[dims[0] * line + 5]; //pole x,y,z DDouble py = (*pipeline)[dims[0] * line + 6]; DDouble pz = (*pipeline)[dims[0] * line + 7]; DDouble x, y, z, before, after, xs, ys, zs, xe, ye, ze, xcut, ycut, zcut; DDouble CorrectionForAvoidance; OMPInt in; DDoubleGDL *lons; DDoubleGDL *lats; DLongGDL *currentConn; bool isVisible; //interpolations for GONS on cuts is every 2.5 degrees. //Gons takes precedence on Lines SizeT nEl = lonsIn->N_Elements(); //if connectivity does not exist, fake a simple one if (!doConn) { currentConn = new DLongGDL(dimension(nEl + 1), BaseGDL::INDGEN); currentConn->Dec(); (*currentConn)[0] = nEl; //[nEl,0,1...nEl] very important! } else { //just copy currentConn = connIn->Dup(); } //copy Input lons = lonsIn->Dup(); lats = latsIn->Dup(); //convert to lists SizeT index; SizeT size; SizeT start; SizeT k; std::list PolygonList; //explore conn and construct polygon list index = 0; SizeT num = 0; while (index < currentConn->N_Elements()) { size = (*currentConn)[index]; if (size > 0) { Polygon currentPol; start = index + 1; //start new chunk... num++; std::list currentVertexList; k = (*currentConn)[start + 0]; Vertex currstart; currstart.lon = (*lons)[k]; currstart.lat = (*lats)[k]; currentVertexList.push_back(currstart); for (in = 1; in < size; in++) { k = (*currentConn)[start + in]; //conn is a list of indexes... Vertex curr; curr.lon = (*lons)[k]; curr.lat = (*lats)[k]; currentVertexList.push_back(curr); } if (fill) { Vertex last = currentVertexList.back(); if (!((last.lon - currstart.lon == 0.0) && (last.lat - currstart.lat == 0.0))) {//close polygon. Vertex curr; curr.lon = currstart.lon; curr.lat = currstart.lat; currentVertexList.push_back(curr); } } currentPol.VertexList = currentVertexList; currentPol.type = 1; //before cut currentPol.xcut = sqrt(-1); //just to have a frank effect if following code is not correct. currentPol.ycut = sqrt(-1); currentPol.zcut = sqrt(-1); PolygonList.push_back(currentPol); } else break; index += (size + 1); } GDLDelete(lons); GDLDelete(lats); GDLDelete(currentConn); std::list newPolygonList; std::list tmpPolygonList; while (icode > 0) { switch (icode) { case SPLIT: if (PolygonList.empty()) break; for (std::list::iterator p = PolygonList.begin(); p != PolygonList.end(); ++p) { //cut current polygon, copy in a new polygon list the cuts Polygon * currentPol; index = 0; std::list * currentVertexList; Vertex* curr; std::list::iterator v = p->VertexList.begin(); xs = cos(v->lon) * cos(v->lat); ys = sin(v->lon) * cos(v->lat); zs = sin(v->lat); before = a * xs + b * ys + c * zs + d; //Let's start correctly: if the first point is on the cut plane, we MUST displace it by several epsilons in //the direction of the next point, to put them on the same 'side' (and avoid unnecessary cuts). Of course if the //second point, etc are on the cut, one must shift them all together as long we have found a 'good' vertex not on the cut. //of course if no such vertex is found we end by ignoring the contour using a dirty jump I'm not happy with. if (abs(before) < avoidance) { DDouble measure = before; std::list::iterator w = v; //find first ok point or ignore all: while (abs(measure) < avoidance) { ++w; if (w == (*p).VertexList.end()) { before = -before; break; } xs = cos(w->lon) * cos(w->lat); ys = sin(w->lon) * cos(w->lat); zs = sin(w->lat); measure = a * xs + b * ys + c * zs + d; } //here w is the first OK. Displace all between v and w-1 in the same direction: if (before < 0) CorrectionForAvoidance = 10 * avoidance; else CorrectionForAvoidance = -10 * avoidance; for (std::list::iterator t = v; t != w; ++t) { t->lon += CorrectionForAvoidance; } //recompute 'before': xs = cos(v->lon) * cos(v->lat); ys = sin(v->lon) * cos(v->lat); zs = sin(v->lat); before = a * xs + b * ys + c * zs + d; } if (abs(before) < avoidance) if (DEBUG_CONTOURS) cerr << "trouble 1" << endl; currentPol = new Polygon; currentPol->type = (*p).type; //inherit type at start currentPol->index = index; currentPol->valid = true; currentVertexList = new std::list; curr = new Vertex; curr->lon = v->lon; curr->lat = v->lat; currentVertexList->push_back(*curr); delete curr; for (++v; v != (*p).VertexList.end(); ++v) { xe = cos(v->lon) * cos(v->lat); ye = sin(v->lon) * cos(v->lat); ze = sin(v->lat); after = a * xe + b * ye + c * ze + d; if (abs(after) < avoidance) { //we are here, so 'before' is out of avoidance. Just push this point out of the zone, in the same side as 'before' if (before > 0) CorrectionForAvoidance = 10 * avoidance; else CorrectionForAvoidance = -10 * avoidance; v->lon += CorrectionForAvoidance; xe = cos(v->lon) * cos(v->lat); ye = sin(v->lon) * cos(v->lat); ze = sin(v->lat); after = a * xe + b * ye + c * ze + d; } if (abs(after) < avoidance) { if (DEBUG_CONTOURS) cerr << "trouble 2" << endl; if (DEBUG_CONTOURS) cerr << "culprit:" << after << "," << v->lon / DEG_TO_RAD << ", ys=" << v->lat / DEG_TO_RAD << endl; } if (before * after < 0.0) { //cut and start a new polygon //find intersection OnSphereVectorPlaneIntersection(xs, ys, zs, xe, ye, ze, a, b, c, d, xcut, ycut, zcut); if (1) {//fill || fmod(DistanceOnSphere( x, y, z, px, py, pz)+2*GDL_PI, GDL_PI) > (GDL_HALFPI-epsilon)) { //need to cut everywhere for current dumb(?) polygon filling curr = new Vertex; x = xs + (1. - 0.5)*(xcut - xs); y = ys + (1. - 0.5)*(ycut - ys); z = zs + (1. - 0.5)*(zcut - zs); curr->lon = atan2(y, x); curr->lat = atan2(z, sqrt(x * x + y * y)); currentVertexList->push_back(*curr); delete curr; //end of current Pol. Memorize cut position of first cut for cut ordering if filling occurs: currentPol->VertexList = (*currentVertexList); //save first cut position currentPol->xcut = x; currentPol->ycut = y; currentPol->zcut = z; int newtype = -1 * currentPol->type; tmpPolygonList.push_back(*currentPol); delete currentPol; //create a new polygon list currentPol = new Polygon; index++; currentPol->type = newtype; //inherit type at start currentPol->index = index; currentPol->valid = true; currentVertexList = new std::list; curr = new Vertex; x = xcut + (1. - 0.5)*(xe - xcut); y = ycut + (1. - 0.5)*(ye - ycut); z = zcut + (1. - 0.5)*(ze - zcut); currentPol->xcut = x; currentPol->ycut = y; currentPol->zcut = z; curr->lon = atan2(y, x); curr->lat = atan2(z, sqrt(x * x + y * y)); currentVertexList->push_back(*curr); delete curr; } } curr = new Vertex; curr->lon = v->lon; curr->lat = v->lat; currentVertexList->push_back(*curr); delete curr; before = after; xs = xe; ys = ye; zs = ze; } currentPol->VertexList = (*currentVertexList); tmpPolygonList.push_back(*currentPol); delete currentPol; //tmpPolygonList contains the current polygon, splitted. It must be stitched if filling occurs. //level-0 filling consist in adding last portion at beginning of first one if (fill && tmpPolygonList.size() > 1) { std::list::iterator beg = tmpPolygonList.begin(); std::list::reverse_iterator end = tmpPolygonList.rbegin(); (*beg).VertexList.splice((*beg).VertexList.begin(), (*end).VertexList); //concatenate // (*end).type=1; tmpPolygonList.pop_back(); } if (fill && tmpPolygonList.size() > 1) { // else already stitched! //stitch polygons. "West" are the polygons on the side of the first polygon. East on the other side; //polygons are 1 2 3 4 .. N. 1..N is sorted relatively with distance from (nearest?) pole . //all polygons are closed on themselves following an arc of meridian sampled every 1 degree. //a) compute distances from first cut, start & end: for (std::list::iterator p = tmpPolygonList.begin(); p != tmpPolygonList.end(); ++p) { Vertex v = (*p).VertexList.front(); x = cos(v.lon) * cos(v.lat); y = sin(v.lon) * cos(v.lat); z = sin(v.lat); (*p).cutDistAtStart = distFromCut((*p), x, y, z); // (*p).cutDistAtStart=v.y; v = (*p).VertexList.back(); x = cos(v.lon) * cos(v.lat); y = sin(v.lon) * cos(v.lat); z = sin(v.lat); (*p).cutDistAtEnd = distFromCut((*p), x, y, z); } //c) now produce 2 lists: before and after cut std::list beforePolygonList; std::list afterPolygonList; for (std::list::iterator p = tmpPolygonList.begin(); p != tmpPolygonList.end(); ++p) { if ((*p).type == 1) { beforePolygonList.push_back((*p)); //on side of first vertex. } else { afterPolygonList.push_back((*p)); //on other side. } } tmpPolygonList.clear(); //d) sort each list by increasing distance from first cut position, and remove each polygon after stiching. // Stitching alog uses a complexity number: number of polygons surrounding the polygon. std::list *aliasList; std::list* theTwoLists[] = {&beforePolygonList, &afterPolygonList}; int maxloop = 0; for (int jj = 0; jj < 2; jj++) { aliasList = theTwoLists[jj]; maxloop = 0; do { if (DEBUG_CONTOURS) cerr << "NEW LOOP: \n"; //treat in sequence each polygon, remove it if it can be stitched simply for (std::list::iterator q = aliasList->begin(); q != aliasList->end(); ++q) { if ((*q).valid) { if (DEBUG_CONTOURS) cerr << "LOOKING AT: " << &(*q) << endl; //zero inside & outside here. for (std::list::iterator p = aliasList->begin(); p != aliasList->end(); ++p) { if ((*p).valid) { if (DEBUG_CONTOURS) cerr << "ZERO:" << &(*p) << endl; (*p).inside = 0; (*p).outside = 0; } } Polygon * cur = &(*q); //establish its complexity number: either the polygon does not contain others, nor it is contained, and we stitch it alone // or it is contained and we pass, // or it is not contained and we stitch with the first it contains, then the complexity decreases and the process continues at the // next iteration for (std::list::iterator t = aliasList->begin(); t != aliasList->end(); ++t) { Polygon * pt = &(*t); if (!(pt == cur) && pt->valid) { //consider only others than current && valids if (IsPolygonInside(cur, pt)) cur->inside += 1; if (IsPolygonInside(pt, cur)) cur->outside += 1; } } if (cur->inside == 0 && cur->outside == 0) { //if the polygon is alone, stitch it and pop it if (DEBUG_CONTOURS) cerr << "CLOSING 1: " << cur << endl; StitchOnePolygonOnGreatCircle(cur); //add closed polygon to end of newPolygonList newPolygonList.push_back(*q); (*q).valid = false; } else if (cur->inside == 1 && cur->outside == 0) { std::list::iterator next; DDouble distref = 1E6; //very large dist DDouble dist; for (std::list::iterator t = aliasList->begin(); t != aliasList->end(); ++t) { Polygon * pt = &(*t); if (!(pt == cur) && pt->valid && IsPolygonInside(cur, pt)) { dist = distFromEnd(cur, pt); if (dist < distref) { distref = dist; next = t; } } } if (DEBUG_CONTOURS) cerr << "STITCHING: " << cur << " with " << &(*next) << endl; StitchTwoPolygonsOnGreatCircle(cur, &(*next)); //add closed polygon to end of newPolygonList newPolygonList.push_back(*q); (*q).valid = false; (*next).valid = false; } else { if (DEBUG_CONTOURS) cerr << "OTHER: " << cur << ":" << cur->inside << "," << cur->outside << endl; //if the polygon contains other (complexity >1), find the one with starting point closest to end of current //stitch the two. --> complexity decreases. // aliasList->erase( q ); //temporary remove } } } //will break on empty list int erase_all = 1; for (std::list::iterator q = aliasList->begin(); q != aliasList->end(); ++q) { if ((*q).valid) erase_all *= 0; } maxloop++; if (maxloop > 20) { erase_all = 1; if (DEBUG_CONTOURS) cerr << "MAX ITER REACHED"; } if (erase_all == 1 || maxloop > 20) aliasList->clear(); } while (!aliasList->empty()); } } else { //just add tmpPolygonList content to end of newPolygonList newPolygonList.splice(newPolygonList.end(), tmpPolygonList); //clear tmp (normally should be empty!) tmpPolygonList.clear(); } } //end of all the input list of polygons, newPolygonList contains cut and stitched polygons: //exchange new & old contents and void new PolygonList.swap(newPolygonList); newPolygonList.clear(); //Should remove empty polygons: TODO break; case CLIP_PLANE: if (PolygonList.empty()) break; //copy & cut... for (std::list::iterator p = PolygonList.begin(); p != PolygonList.end(); ++p) { Polygon * currentPol; std::list * currentVertexList; Vertex *curr; std::list::iterator v = (*p).VertexList.begin(); xs = cos(v->lon) * cos(v->lat); ys = sin(v->lon) * cos(v->lat); zs = sin(v->lat); before = a * xs + b * ys + c * zs + d; isVisible = (before >= 0.0); if (isVisible) { currentPol = new Polygon; currentVertexList = new std::list; curr = new Vertex; curr->lon = v->lon; curr->lat = v->lat; currentVertexList->push_back(*curr); delete curr; } for (++v; v != (*p).VertexList.end(); ++v) { xe = cos(v->lon) * cos(v->lat); ye = sin(v->lon) * cos(v->lat); ze = sin(v->lat); after = a * xe + b * ye + c * ze + d; if (before * after < 0.0) { //cut and start a new polygon //find intersection epsilon before OnSphereVectorPlaneIntersection(xs, ys, zs, xe, ye, ze, a, b, c, d, xcut, ycut, zcut); //, -avoidance); if (isVisible) { x = xs + (1. - 0.5)*(xcut - xs); y = ys + (1. - 0.5)*(ycut - ys); z = zs + (1. - 0.5)*(zcut - zs); curr = new Vertex; curr->lon = atan2(y, x); curr->lat = atan2(z, sqrt(x * x + y * y)); currentVertexList->push_back(*curr); delete curr; //end of current Pol. currentPol->VertexList = (*currentVertexList); newPolygonList.push_back(*currentPol); delete currentPol; } isVisible = !isVisible; if (isVisible) { //create a new polygon list currentPol = new Polygon; currentVertexList = new std::list; curr = new Vertex; x = xcut + (1. - 0.5)*(xe - xcut); y = ycut + (1. - 0.5)*(ye - ycut); z = zcut + (1. - 0.5)*(ze - zcut); curr->lon = atan2(y, x); curr->lat = atan2(z, sqrt(x * x + y * y)); //asin( z ); currentVertexList->push_back(*curr); delete curr; } } if (isVisible) { curr = new Vertex; curr->lon = v->lon; curr->lat = v->lat; currentVertexList->push_back(*curr); delete curr; } before = after; xs = xe; ys = ye; zs = ze; } if (isVisible) { currentPol->VertexList = (*currentVertexList); newPolygonList.push_back(*currentPol); delete currentPol; } } //exchange new & old contents and void new if (newPolygonList.empty()) PolygonList.clear(); else PolygonList.swap(newPolygonList); newPolygonList.clear(); break; case TRANSFORM: if (PolygonList.empty()) break; #ifdef USE_LIBPROJ4 for (std::list::iterator p = PolygonList.begin(); p != PolygonList.end(); ++p) { for (std::list::iterator v = (*p).VertexList.begin(); v != (*p).VertexList.end(); ++v) { idata.u = v->lon; idata.v = v->lat; odata = PJ_FWD(idata, ref); v->lon = odata.u; v->lat = odata.v; } } #endif //USE_LIBPROJ4 break; case CLIP_UV: if (PolygonList.empty()) break; //NO NO NO you must interpolate from outside to inside box! for (std::list::iterator p = PolygonList.begin(); p != PolygonList.end(); ++p) { for (std::list::iterator v = (*p).VertexList.begin(); v != (*p).VertexList.end(); ++v) { if (isfinite(v->lon * v->lat)) if (v->lon < a - avoidance || v->lon > c + avoidance || v->lat < b - avoidance || v->lat > d + avoidance) { v->lon = bad; v->lat = bad; } } } break; default: continue; } line++; icode = (*pipeline)[dims[0] * line + 0]; a = (*pipeline)[dims[0] * line + 1]; //plane a,b,c,d b = (*pipeline)[dims[0] * line + 2]; c = (*pipeline)[dims[0] * line + 3]; d = (*pipeline)[dims[0] * line + 4]; px = (*pipeline)[dims[0] * line + 5]; //pole x,y,z py = (*pipeline)[dims[0] * line + 6]; pz = (*pipeline)[dims[0] * line + 7]; } //recreate lons, lats, gons, .. if (PolygonList.empty()) { if (doGons) gonsOut = new DLongGDL(-1); else linesOut = new DLongGDL(-1); return new DDoubleGDL(-1); } //size SizeT nelem = 0; SizeT ngons = 0; for (std::list::iterator p = PolygonList.begin(); p != PolygonList.end(); ++p) { if ((*p).VertexList.size() > 0) { ngons++; ngons += (*p).VertexList.size(); nelem += (*p).VertexList.size(); } } lons = new DDoubleGDL(nelem, BaseGDL::NOZERO); lats = new DDoubleGDL(nelem, BaseGDL::NOZERO); currentConn = new DLongGDL(ngons, BaseGDL::NOZERO); SizeT i = 0; SizeT j = 0; for (std::list::iterator p = PolygonList.begin(); p != PolygonList.end(); ++p) { if ((*p).VertexList.size() > 0) { (*currentConn)[j++] = (*p).VertexList.size(); for (std::list::iterator v = (*p).VertexList.begin(); v != (*p).VertexList.end(); ++v, i++) { (*lons)[i] = v->lon; (*lats)[i] = v->lat; (*currentConn)[j++] = i; } } } nEl = lons->N_Elements(); DLong odims[2]; odims[0] = 2; odims[1] = nEl; dimension dim(odims, 2); DDoubleGDL *res = new DDoubleGDL(dim, BaseGDL::NOZERO); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for (OMPInt i = 0; i < nEl; ++i) { (*res)[2 * i] = (*lons)[i]; (*res)[2 * i + 1] = (*lats)[i]; } } //cleanup GDLDelete(lons); GDLDelete(lats); if (doGons || doLines) { if (doGons) gonsOut = currentConn; else linesOut = currentConn; } else GDLDelete(currentConn); return res; } void GDLgrProjectedPolygonPlot( GDLGStream * a, PROJTYPE ref, DStructGDL* map, DDoubleGDL *lons_donottouch, DDoubleGDL *lats_donottouch, bool isRadians, bool const doFill, DLongGDL *conn ) { DDoubleGDL *lons,*lats; lons=lons_donottouch->Dup(); lats=lats_donottouch->Dup(); DStructGDL* localMap = map; if (localMap==NULL) localMap=SysVar::Map( ); bool mapSet; get_mapset(mapSet); //if mapSet, output will be converted to normalized coordinates as this seems to be the way to do it. bool doConn = (conn != NULL); DLongGDL *gons, *lines; if (!isRadians) { SizeT nin = lons->N_Elements( ); #pragma omp parallel if (nin >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nin)) { #pragma omp for for ( OMPInt in = 0; in < nin; in++ ) { //pass in radians for gdlProjForward (*lons)[in] *= DEG_TO_RAD; (*lats)[in] *= DEG_TO_RAD; } } } DDoubleGDL *res = gdlProjForward( ref, localMap, lons, lats, conn, doConn, gons, doFill, lines, !doFill, false ); SizeT nout = res->N_Elements( ) / 2; if (nout < 1) {GDLDelete(res); return;} //projection clipped totally these values. res = static_cast (static_cast (res)->Transpose( NULL )); int minpoly; if ( doFill ) { conn = gons; minpoly = 3; } else { conn = lines; minpoly = 2; } SizeT index = 0; SizeT size; SizeT start; while ( index < conn->N_Elements( ) ) { size = (*conn)[index]; if ( size == 0 ) break; //cannot be negative! start = (*conn)[index + 1]; if ( size >= minpoly ) { if ( doFill ) { a->fill( size, (PLFLT*) &((*res)[start]), (PLFLT*) &((*res)[start + nout]) ); } else { a->line( size, (PLFLT*) &((*res)[start]), (PLFLT*) &((*res)[start + nout]) ); } } index += (size + 1); } GDLDelete( res ); if ( doFill ) GDLDelete( gons ); else GDLDelete( lines ); } } // namespace gdl-0.9.9/src/plotting.hpp000066400000000000000000002534721340051421000154420ustar00rootroot00000000000000/* ************************************************************************* plotting.hpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /* ************************************************************************* * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef PLOTTING_HPP_ #define PLOTTING_HPP_ #define gdlPlot_Min(a, b) ((a) < (b) ? (a) : (b)) #define gdlPlot_Max(a, b) ((a) > (b) ? (a) : (b)) //To debug Affine 3D homogenous projections matrices. //IDL define a matrix as M[ncol,mrow] and print as such. However col_major and //row_major refer to the math notation M[row,col] where row=dim(0) and col=dim(1). //Matrices are stored COL Major in IDL/Fortran and ROW Major in C,C++ etc. //so element at (i,j) is computed as (j*dim0 + i) for ColMajor/IDL //and (i*dim1 + j) for RowMajor/C #define TRACEMATRIX_C(var__) \ {int dim0__=(var__)->Dim(0), dim1__=(var__)->Dim(1); \ fprintf(stderr,"c matrix[%d,%d]\n",dim0__,dim1__); \ for (int row=0; row < dim0__ ; row++) \ { \ for (int col=0; col < dim1__-1; col++) \ { \ fprintf(stderr,"%g, ",(*var__)[row*dim1__ + col]); \ } \ fprintf(stderr,"%g\n",(*var__)[row*dim1__ + dim1__ -1]); \ } \ fprintf(stderr,"\n"); \ } //The following abbrevs should output the C matrix as IDL would do (ie,transposed): #define TRACEMATRIX_IDL(var__) \ {int dim0__=(var__)->Dim(0), dim1__=(var__)->Dim(1); \ fprintf(stderr,"idl matrix[%d,%d]\n[",dim0__,dim1__); \ for (int col=0; col < dim1__; col++) \ { \ fprintf(stderr,"["); \ for (int row=0; row < dim0__; row++) \ { \ fprintf(stderr,"%g",(*var__)[row*dim1__ + col]); \ if (row struct GDL_3DTRANSFORMDATA { DDoubleGDL* Matrix; DDouble zValue; int* code; DDouble x0; DDouble xs; DDouble y0; DDouble ys; DDouble z0; DDouble zs; bool xlog; bool ylog; bool zlog; }; static GDL_3DTRANSFORMDATA Data3d; static int code012[3] = {0, 1, 2}; static int code102[3] = {1, 0, 2}; static int code120[3] = {1, 2, 0}; static int code210[3] = {2, 1, 0}; static int code201[3] = {2, 0, 1}; static int code021[3] = {0, 2, 1}; enum ORIENTATION3D { NORMAL3D=0, XY, XZ, YZ, XZYZ, XZXY }; #define GDL_NONE -1 #define GDL_TICKFORMAT 0 #define GDL_TICKUNITS 1 #define GDL_TICKFORMAT_AND_UNITS 2 struct GDL_TICKDATA { GDLGStream *a; bool isLog; DDouble axisrange; //to circumvent plplot passing a non-zero value instead of strict 0.0 double nchars; //length of string *returned* after formatting. Can be non-integer. }; struct GDL_TICKNAMEDATA { GDLGStream *a; SizeT counter; SizeT nTickName; DStringGDL* TickName; bool isLog; DDouble axisrange; //to circumvent plplot passing a non-zero value instead of strict 0.0 double nchars; //length of string *returned* after formatting. Can be non-integer. }; struct GDL_MULTIAXISTICKDATA { EnvT *e; GDLGStream *a; SizeT counter; int what; SizeT nTickFormat; DDouble axismin; DDouble axismax; DStringGDL* TickFormat; SizeT nTickUnits; DStringGDL* TickUnits; bool isLog; DDouble axisrange; //to circumvent plplot passing a non-zero value instead of strict 0.0 double nchars; //length of string *returned* after formatting. Can be non-integer. }; typedef struct GDL_SAVEBOX { bool initialized; PLFLT wx1; //world coord of x min PLFLT wx2; PLFLT wy1; PLFLT wy2; PLFLT nx1; PLFLT nx2; PLFLT ny1; PLFLT ny2; } gdlSavebox ; namespace lib { using namespace std; // main plotting routine (all defined using the plotting_routine_call class) void plot( EnvT* e); void plot_io( EnvT* e); void plot_oo( EnvT* e); void plot_oi( EnvT* e); void oplot( EnvT* e); void plots( EnvT* e); void surface( EnvT* e); void shade_surf( EnvT* e); void contour( EnvT* e); void xyouts( EnvT* e); void axis( EnvT* e); void polyfill( EnvT* e); void tv_image( EnvT* e); void usersym( EnvT* e); void set_shading( EnvT* e); // other plotting routines void erase( EnvT* e); void tvlct( EnvT* e); void wshow( EnvT* e); void wdelete( EnvT* e); void wset( EnvT* e); void window( EnvT* e); void set_plot( EnvT* e); BaseGDL* get_screen_size( EnvT* e); void device( EnvT* e); void cursor( EnvT* e); void tvcrs( EnvT* e); void empty(EnvT* e); BaseGDL* format_axis_values(EnvT *e); void scale3_pro(EnvT* e); void t3d_pro( EnvT* e); // Map stuff void get_mapset(bool &mapset); void set_mapset(bool mapset); BaseGDL* map_proj_forward_fun( EnvT* e); BaseGDL* map_proj_inverse_fun( EnvT* e); BaseGDL* convert_coord( EnvT* e); //dummy functions for compatibility support of GCTP projections void map_proj_gctp_forinit (EnvT* e); void map_proj_gctp_revinit (EnvT* e); #if defined(USE_LIBPROJ4) || defined(USE_LIBPROJ4_NEW) #define GDL_COMPLEX COMPLEX2 #ifdef USE_LIBPROJ4_NEW extern "C" { //#include "projects.h" #include "proj_api.h" } #define LPTYPE projLP #define XYTYPE projXY #define PROJTYPE projPJ #define PROJDATA projUV #define PJ_INIT pj_init PROJDATA protect_proj_fwd (PROJDATA idata, PROJTYPE proj); PROJDATA protect_proj_inv (PROJDATA idata, PROJTYPE proj); #define PJ_FWD protect_proj_fwd #define LIB_PJ_FWD pj_fwd #define PJ_INV protect_proj_inv #define LIB_PJ_INV pj_inv PROJTYPE map_init(DStructGDL *map=SysVar::Map()); static volatile PROJTYPE ref; static volatile PROJTYPE prev_ref; static PROJDATA badProj={sqrt(-1),sqrt(-1)}; #else extern "C" { //adding this removes the problem with lam,phi vs. x,y and make no diffs between old an new lib proj.4 #define PROJ_UV_TYPE 1 #include "lib_proj.h" } #define LPTYPE PROJ_LP #define XYTYPE PROJ_XY #define PROJTYPE PROJ* #define PROJDATA PROJ_UV #define PJ_INIT proj_init PROJDATA protect_proj_fwd (PROJDATA idata, PROJTYPE proj); PROJDATA protect_proj_inv (PROJDATA idata, PROJTYPE proj); #define PJ_FWD protect_proj_fwd #define LIB_PJ_FWD proj_fwd #define PJ_INV protect_proj_inv #define LIB_PJ_INV proj_inv PROJTYPE map_init(DStructGDL *map=SysVar::Map()); static PROJTYPE ref; static PROJTYPE prev_ref; static PROJDATA badProj={sqrt(-1),sqrt(-1)}; //general reprojecting function #endif //general reprojecting function DDoubleGDL* gdlProjForward(PROJTYPE ref, DStructGDL* map, DDoubleGDL* lon, DDoubleGDL *lat, DLongGDL* connectivity, bool doConn, DLongGDL* &gons, bool doGons, DLongGDL* &lines, bool doLines, bool doFill); void GDLgrProjectedPolygonPlot(GDLGStream * a, PROJTYPE ref, DStructGDL* map, DDoubleGDL *lons, DDoubleGDL *lats, bool isRadians, bool const doFill, DLongGDL *conn=NULL); DStructGDL *GetMapAsMapStructureKeyword(EnvT *e, bool &externalMap); //not static since KW is at same place for all uses. #define COMPLEX2 GDL_COMPLEX #else //NOT USE_LIBPROJ4 : define some more or less dummy values: #define PROJTYPE void* #define DEG_TO_RAD 0.017453292 #endif //USE_LIBPROJ4 //3D conversions void SelfTranspose3d(DDoubleGDL* me); void SelfReset3d(DDoubleGDL* me); void SelfTranslate3d(DDoubleGDL* me, DDouble *trans); void SelfScale3d(DDoubleGDL* me, DDouble *scale); void SelfRotate3d(DDoubleGDL* me, DDouble *rot); void SelfPerspective3d(DDoubleGDL* me, DDouble zdist); void SelfOblique3d(DDoubleGDL* me, DDouble dist, DDouble angle); void SelfExch3d(DDoubleGDL* me, DLong code); void gdl3dTo2dTransformContour(PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data); void gdl3dTo2dTransform(PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data); void gdlProject3dCoordinatesIn2d( DDoubleGDL* Matrix, DDoubleGDL *xVal, DDouble *sx, DDoubleGDL *yVal, DDouble *sy, DDoubleGDL* zVal, DDouble *sz, DDoubleGDL *xValou, DDoubleGDL *yValou); DDoubleGDL* gdlComputePlplotRotationMatrix(DDouble az, DDouble alt, DDouble zValue, DDouble scale=1.0); DDoubleGDL* gdlConvertT3DMatrixToPlplotRotationMatrix(DDouble zValue, DDouble &az, DDouble &alt, DDouble &ay, DDouble &scale, ORIENTATION3D &code); DDoubleGDL* gdlGetScaledNormalizedT3DMatrix(DDoubleGDL* Matrix=NULL); DDoubleGDL* gdlGetT3DMatrix(); void gdlNormed3dToWorld3d(DDoubleGDL *xVal, DDoubleGDL *yVal, DDoubleGDL* zVal, DDoubleGDL* xValou, DDoubleGDL *yValou, DDoubleGDL *zValou); void gdl3dto2dProjectDDouble(DDoubleGDL* t3dMatrix, DDoubleGDL *xVal, DDoubleGDL *yVal, DDoubleGDL* zVal, DDoubleGDL *xValou, DDoubleGDL *yValou, int* code); bool T3Denabled(); class plotting_routine_call { // ensure execution of child-class destructors public: virtual ~plotting_routine_call() {}; // private fields private: SizeT _nParam; private: bool overplot; private: bool isDB; //see below why commented. // common helper methods protected: inline SizeT nParam() { return _nParam; } // prototypes for methods defining various steps private: virtual bool handle_args(EnvT*) = 0; // return value = overplot private: virtual void old_body(EnvT*, GDLGStream*) = 0; private: virtual void call_plplot(EnvT*, GDLGStream*) = 0; private: virtual void post_call(EnvT*, GDLGStream*) = 0; // all steps combined (virtual methods cannot be called from ctor) public: void call(EnvT* e, SizeT n_params_required) { // when !d.name == Null we do nothing ! DString name = (*static_cast(SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("NAME"), 0)))[0]; if (name == "NULL") return; _nParam = e->NParam(n_params_required); overplot = handle_args(e); GDLGStream* actStream = GraphicsDevice::GetDevice()->GetStream(); if (actStream == NULL) e->Throw("Unable to create window."); //ALL THE DoubleBuffering and Flush() code below introduces terrible slowness in remote X displays, as well as a lot of time lost //for displays on the same server. They are completely removed now. // //double buffering kills the logic and operation of XOR modes. Use HasSafeDoubleBuffering() that tests this feature.) // isDB = actStream->HasSafeDoubleBuffering(); // if (isDB) actStream->SetDoubleBuffering(); if (name == "X" || name == "MAC" || name == "WIN" ) actStream->updatePageInfo(); //since window size can change old_body(e, actStream); // TODO: to be removed! call_plplot(e, actStream); post_call(e, actStream); // IDEM: SLOW // if (isDB) actStream->eop(); else actStream->flush(); // if (isDB) actStream->UnSetDoubleBuffering(); //this is absolutely necessary for widgets as for windows. However the virtual Update function //i.e., calling plstream::cmd(PLESC_EXPOSE, NULL) is very slow. // See how to overload it by a faster function such as in GDLXStream::Update() . actStream->Update(); } }; void gdlDoRangeExtrema(DDoubleGDL *xVal, DDoubleGDL *yVal, DDouble &min, DDouble &max, DDouble xmin, DDouble xmax, bool doMinMax=FALSE, DDouble minVal=0, DDouble maxVal=0); void draw_polyline(GDLGStream *a, DDoubleGDL *xVal, DDoubleGDL *yVal, DDouble minVal, DDouble maxVal, bool doMinMax, bool xLog, bool yLog, //end non-default values DLong psym=0, bool useProjectionInfo=false, bool append=FALSE, DLongGDL *color=NULL); //protect from (inverted, strange) axis log values void gdlHandleUnwantedAxisValue(DDouble &min, DDouble &max, bool log); void gdlSetGraphicsPenColorToBackground(GDLGStream *a); void gdlLineStyle(GDLGStream *a, DLong style); void gdlStoreAxisCRANGE(string axis, DDouble Start, DDouble End, bool log); void gdlStoreAxisSandWINDOW(GDLGStream* actStream, string axis, DDouble Start, DDouble End, bool log=false); void gdlGetAxisType(string axis, bool &log); void gdlGetCurrentAxisRange(string axis, DDouble &Start, DDouble &End, bool checkMapset=FALSE); void gdlGetCurrentAxisWindow(string axis, DDouble &wStart, DDouble &wEnd); void gdlStoreAxisType(string axis, bool type); void gdlGetCharSizes(GDLGStream *a, PLFLT &nsx, PLFLT &nsy, DDouble &wsx, DDouble &wsy, DDouble &dsx, DDouble &dsy, DDouble &lsx, DDouble &lsy); void GetSFromPlotStructs(DDouble **sx, DDouble **sy, DDouble **sz=NULL); void GetWFromPlotStructs(DFloat **wx, DFloat **wy); void setPlplotScale(GDLGStream* a); void DataCoordLimits(DDouble *sx, DDouble *sy, DFloat *wx, DFloat *wy, DDouble *xStart, DDouble *xEnd, DDouble *yStart, DDouble *yEnd, bool); void stopClipping(GDLGStream *a); void gdlStoreCLIP(DLongGDL* clipBox); void GetCurrentUserLimits(GDLGStream *a, DDouble &xStart, DDouble &xEnd, DDouble &yStart, DDouble &yEnd); PLFLT gdlAdjustAxisRange(EnvT* e, string axis, DDouble &val_min, DDouble &val_max, bool log = false, int calendarcode = 0); PLFLT AutoTick(DDouble x); void setIsoPort(GDLGStream* actStream,PLFLT x1,PLFLT x2,PLFLT y1,PLFLT y2,PLFLT aspect); void GetMinMaxVal( DDoubleGDL* val, double* minVal, double* maxVal); void GetMinMaxValuesForSubset( DDoubleGDL* val, DDouble &minVal, DDouble &maxVal, SizeT endElement); void CheckMargin( GDLGStream* actStream, DFloat xMarginL, DFloat xMarginR, DFloat yMarginB, DFloat yMarginT, PLFLT& xMR, PLFLT& xML, PLFLT& yMB, PLFLT& yMT); void UpdateSWPlotStructs(GDLGStream* actStream, DDouble xStart, DDouble xEnd, DDouble yStart, DDouble yEnd, bool xLog, bool yLog); gdlSavebox* getSaveBox(); gdlSavebox* getTempBox(); void gdlSimpleAxisTickFunc( PLINT axis, PLFLT value, char *label, PLINT length, PLPointer data); void gdlSingleAxisTickNamedFunc( PLINT axis, PLFLT value, char *label, PLINT length, PLPointer data); void gdlMultiAxisTickFunc(PLINT axis, PLFLT value, char *label, PLINT length, PLPointer data); void doOurOwnFormat(PLINT axisNotUsed, PLFLT value, char *label, PLINT length, PLPointer data); // //--------------FOLLOWING ARE STATIC FUNCTIONS----------------------------------------------- //This because static pointers to options indexes are needed to speed up process, but these indexes vary between //the definition of the caller functions (e.g. "CHARSIZE" is 1 for CONTOUR but 7 for XYOUTS). So they need to be kept //static (for speed) but private for each graphic command. static void gdlSetGraphicsBackgroundColorFromKw(EnvT *e, GDLGStream *a, bool kw=true) { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DLong background= (*static_cast (pStruct->GetTag(pStruct->Desc()->TagIndex("BACKGROUND"), 0)))[0]; if ( kw ) { static int BACKGROUNDIx=e->KeywordIx("BACKGROUND"); e->AssureLongScalarKWIfPresent(BACKGROUNDIx, background); } DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); a->Background(background,decomposed); } static void gdlSetGraphicsForegroundColorFromKw(EnvT *e, GDLGStream *a, string OtherColorKw="") { // Get COLOR from PLOT system variable DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DLong color= (*static_cast (pStruct->GetTag(pStruct->Desc()->TagIndex("COLOR"), 0)))[0]; DLongGDL *colorVect; static int colorIx=e->KeywordIx ( "COLOR" ); int realcolorIx=colorIx; //eventually do not get color from standard "COLOR" keyword but from another... if (OtherColorKw != "") realcolorIx=e->KeywordIx (OtherColorKw); if ( e->GetKW ( realcolorIx )!=NULL ) { colorVect=e->GetKWAs( realcolorIx ); //color can be vectorial, but... color=(*colorVect)[0]; //this function only sets color to 1st arg in list! } // Get decomposed value for colors DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); a->Color(color, decomposed); } static void gdlGetPsym(EnvT *e, DLong &psym) { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset psym=(*static_cast (pStruct->GetTag(pStruct->Desc()->TagIndex("PSYM"), 0)))[0]; static int PSYMIx=e->KeywordIx("PSYM"); e->AssureLongScalarKWIfPresent(PSYMIx, psym); if ( psym>10||psym < -8||psym==9 ) e->Throw( "PSYM (plotting symbol) out of range."); } static void gdlSetSymsize(EnvT *e, GDLGStream *a) { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DFloat symsize=(*static_cast (pStruct->GetTag(pStruct->Desc()->TagIndex("SYMSIZE"), 0)))[0]; //NOTE THAT AS OF IDL 8.2 !P.SYMSIZE, HOWEVER EXISTING, IS NOT TAKEN INTO ACCOUNT. We however do not want //to reproduce this feature. static int SYMSIZEIx=e->KeywordIx("SYMSIZE"); e->AssureFloatScalarKWIfPresent(SYMSIZEIx, symsize); if ( symsize<=0.0 ) symsize=1.0; a->setSymbolSize(symsize); } // static void GetUserSymSize(EnvT *e, GDLGStream *a, DDouble& UsymConvX, DDouble& UsymConvY) // { // //get symsize // DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset // DFloat symsize=(*static_cast // (pStruct->GetTag(pStruct->Desc()->TagIndex("SYMSIZE"), 0)))[0]; // static int SYMSIZEIx = e->KeywordIx("SYMSIZE"); // e->AssureFloatScalarKWIfPresent(SYMSIZEIx, symsize); // if ( symsize<=0.0 ) symsize=1.0; // // UsymConvX=(0.5*symsize*(a->wCharLength()/a->charScale())); //be dependent only on symsize! // UsymConvY=(0.5*symsize*(a->wCharHeight()/a->charScale())); // PLFLT wun, wdeux, wtrois, wquatre; //take care of axes world orientation! // a->pageWorldCoordinates(wun, wdeux, wtrois, wquatre); // if ((wdeux-wun)<0) UsymConvX*=-1.0; // if ((wquatre-wtrois)<0) UsymConvY*=-1.0; // if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"GetUserSymSize(%f,%f), charlen=%f, charheight=%f, charscale=%f\n", // UsymConvX, UsymConvY,a->wCharLength(),a->wCharHeight(),a->charScale()); // } static void gdlSetPlotCharsize(EnvT *e, GDLGStream *a, bool accept_sizeKw=false) { PLFLT charsize; DDouble pmultiscale=1.0; // get !P preference DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset charsize=(*static_cast (pStruct->GetTag (pStruct->Desc()->TagIndex("CHARSIZE"), 0)))[0]; //overload with command preference. Charsize may be a vector now in some gdl commands, take care of it: if (accept_sizeKw) //XYOUTS specials! { static int SIZEIx=e->KeywordIx("SIZE"); //define here only (else trig an assert() ) DFloat fcharsize; fcharsize=charsize; e->AssureFloatScalarKWIfPresent(SIZEIx, fcharsize); charsize=fcharsize; } static int charsizeIx=e->KeywordIx ( "CHARSIZE" ); if ( e->GetKW ( charsizeIx )!=NULL ) { DFloatGDL* charsizeVect=e->GetKWAs( charsizeIx ); charsize=(*charsizeVect)[0]; } if ( charsize<=0.0 ) charsize=1.0; // adjust if MULTI: DLongGDL* pMulti=SysVar::GetPMulti(); if ( (*pMulti)[1]>2||(*pMulti)[2]>2 ) pmultiscale=0.5; a->sizeChar(charsize*pmultiscale); } static void gdlSetPlotCharthick(EnvT *e, GDLGStream *a) { // get !P preference DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DFloat charthick=(*static_cast (pStruct->GetTag (pStruct->Desc()->TagIndex("CHARTHICK"), 0)))[0]; static int charthickIx=e->KeywordIx ( "CHARTHICK" ); //Charthick values may be vector in GDL, not in IDL! if ( e->GetKW ( charthickIx )!=NULL ) { DFloatGDL* charthickVect=e->GetKWAs( charthickIx ); charthick=(*charthickVect)[0]; } if ( charthick <= 0.0 ) charthick=1.0; a->Thick(charthick); } static PLFLT gdlComputeTickInterval(EnvT *e, string axis, DDouble &min, DDouble &max, bool log) { DLong nticks=0; static int XTICKSIx = e->KeywordIx("XTICKS"); static int YTICKSIx = e->KeywordIx("YTICKS"); static int ZTICKSIx = e->KeywordIx("ZTICKS"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKSIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKSIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKSIx; } if ( Struct!=NULL ) { unsigned tickTag=Struct->Desc()->TagIndex("TICKS"); nticks=(*static_cast(Struct->GetTag(tickTag, 0)))[0]; } e->AssureLongScalarKWIfPresent(choosenIx, nticks); PLFLT intv; if (nticks == 0) { intv = (log)? AutoTick(log10(max-min)): AutoTick(max-min); } else { intv = (log)? log10(max-min)/nticks: (max-min)/nticks; } return intv; } static void gdlGetDesiredAxisCharsize(EnvT* e, string axis, DFloat &charsize) { //default: charsize=1.0; // get !P preference. Even if [xyz]charsize is absent, presence of charsize or !P.charsize must be taken into account. DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset charsize=(*static_cast (pStruct->GetTag (pStruct->Desc()->TagIndex("CHARSIZE"), 0)))[0]; static int CharsizeIx= e->KeywordIx( "CHARSIZE"); //cerr<<" CHARSIZE: "<< CharsizeIx<<" ("<< &CharsizeIx<<")"<AssureFloatScalarKWIfPresent(CharsizeIx, charsize); // option charsize overloads P.CHARSIZE if (charsize==0) charsize=1.0; // Axis Preference. Is a Multiplier! static int XCharsizeIx = e->KeywordIx("XCHARSIZE"); static int YCharsizeIx = e->KeywordIx("YCHARSIZE"); static int ZCharsizeIx = e->KeywordIx("ZCHARSIZE"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XCharsizeIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YCharsizeIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZCharsizeIx; } if ( Struct!=NULL ) { unsigned charsizeTag=Struct->Desc()->TagIndex("CHARSIZE"); //[XYZ].CHARSIZE DFloat axisCharsizeMultiplier=(*static_cast(Struct->GetTag(charsizeTag, 0)))[0]; e->AssureFloatScalarKWIfPresent(choosenIx, axisCharsizeMultiplier); //option [XYZ]CHARSIZE overloads ![XYZ].CHARSIZE if (axisCharsizeMultiplier>0.0) charsize*=axisCharsizeMultiplier; //IDL Behaviour... } } static void gdlSetAxisCharsize(EnvT *e, GDLGStream *a, string axis) { DFloat charsize=0.0; DDouble pmultiscale=1.0; gdlGetDesiredAxisCharsize(e, axis, charsize); // adjust if MULTI: DLongGDL* pMulti=SysVar::GetPMulti(); if ( (*pMulti)[1]>2||(*pMulti)[2]>2 ) pmultiscale=0.5; //IDL behaviour // scale default value (which depends on number of subpages) // a->schr(0.0, charsize*pmultiscale); a->sizeChar(charsize*pmultiscale); } static void gdlGetDesiredAxisGridStyle(EnvT* e, string axis, DLong &axisGridstyle) { axisGridstyle=0; DStructGDL* Struct=NULL; static int XGRIDSTYLEIx = e->KeywordIx("XGRIDSTYLE"); static int YGRIDSTYLEIx = e->KeywordIx("YGRIDSTYLE"); static int ZGRIDSTYLEIx = e->KeywordIx("ZGRIDSTYLE"); int choosenIx; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XGRIDSTYLEIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YGRIDSTYLEIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZGRIDSTYLEIx; } if ( Struct!=NULL ) { unsigned gridstyleTag=Struct->Desc()->TagIndex("GRIDSTYLE"); axisGridstyle=(*static_cast(Struct->GetTag(gridstyleTag, 0)))[0]; e->AssureLongScalarKWIfPresent(choosenIx, axisGridstyle); } } static void gdlGetDesiredAxisMargin(EnvT *e, string axis, DFloat &start, DFloat &end) { static int XMARGINIx = e->KeywordIx("XMARGIN"); static int YMARGINIx = e->KeywordIx("YMARGIN"); static int ZMARGINIx = e->KeywordIx("ZMARGIN"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XMARGINIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YMARGINIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZMARGINIx; } if ( Struct!=NULL ) { unsigned marginTag=Struct->Desc()->TagIndex("MARGIN"); start= (*static_cast(Struct->GetTag(marginTag, 0)))[0]; end = (*static_cast(Struct->GetTag(marginTag, 0)))[1]; } BaseGDL* Margin=e->GetKW(choosenIx); if ( Margin!=NULL ) { if ( Margin->N_Elements()>2 ) e->Throw("Keyword array parameter "+axis+"MARGIN must have from 1 to 2 elements."); Guard guard; DFloatGDL* MarginF=static_cast (Margin->Convert2(GDL_FLOAT, BaseGDL::COPY)); guard.Reset(MarginF); start=(*MarginF)[0]; if ( MarginF->N_Elements()>1 ) end=(*MarginF)[1]; } } static void gdlGetDesiredAxisMinor(EnvT* e, string axis, DLong &axisMinor) { axisMinor=0; static int XMINORIx = e->KeywordIx("XMINOR"); static int YMINORIx = e->KeywordIx("YMINOR"); static int ZMINORIx = e->KeywordIx("ZMINOR"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XMINORIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YMINORIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZMINORIx; } if ( Struct!=NULL ) { unsigned AxisMinorTag=Struct->Desc()->TagIndex("MINOR"); axisMinor=(*static_cast(Struct->GetTag(AxisMinorTag,0)))[0]; } e->AssureLongScalarKWIfPresent(choosenIx, axisMinor); } static bool gdlGetDesiredAxisRange(EnvT *e, string axis, DDouble &start, DDouble &end) { bool set=FALSE; static int XRANGEIx = e->KeywordIx("XRANGE"); static int YRANGEIx = e->KeywordIx("YRANGE"); static int ZRANGEIx = e->KeywordIx("ZRANGE"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XRANGEIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YRANGEIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZRANGEIx; } if ( Struct!=NULL ) { DDouble test1, test2; unsigned rangeTag=Struct->Desc()->TagIndex("RANGE"); test1=(*static_cast(Struct->GetTag(rangeTag, 0)))[0]; test2=(*static_cast(Struct->GetTag(rangeTag, 0)))[1]; if ( !((test1-test2)==0.0) ) { start=test1; end=test2; set=true; } } BaseGDL* Range=e->GetKW(choosenIx); if ( Range!=NULL ) { if ( Range->N_Elements()!=2 ) e->Throw("Keyword array parameter "+axis+"RANGE must have 2 elements."); Guard guard; DDoubleGDL* RangeF=static_cast(Range->Convert2(GDL_DOUBLE, BaseGDL::COPY)); guard.Reset(RangeF); if (!(((*RangeF)[0]-(*RangeF)[1])==0.0)) { start=(*RangeF)[0]; end=(*RangeF)[1]; set=true; } } return set; } static void gdlGetDesiredAxisStyle(EnvT *e, string axis, DLong &style) { static int XSTYLEIx = e->KeywordIx("XSTYLE"); static int YSTYLEIx = e->KeywordIx("YSTYLE"); static int ZSTYLEIx = e->KeywordIx("ZSTYLE"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XSTYLEIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YSTYLEIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZSTYLEIx; } if ( Struct!=NULL ) { int styleTag=Struct->Desc()->TagIndex("STYLE"); style= (*static_cast(Struct->GetTag(styleTag, 0)))[0]; } e->AssureLongScalarKWIfPresent( choosenIx, style); } static void gdlGetDesiredAxisThick(EnvT *e, string axis, DFloat &thick) { thick=1.0; static int XTHICKIx = e->KeywordIx("XTHICK"); static int YTHICKIx = e->KeywordIx("YTHICK"); static int ZTHICKIx = e->KeywordIx("ZTHICK"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTHICKIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTHICKIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTHICKIx; } if ( Struct!=NULL ) { //not static! int thickTag=Struct->Desc()->TagIndex("THICK"); thick = (*static_cast(Struct->GetTag(thickTag, 0)))[0]; } e->AssureFloatScalarKWIfPresent(choosenIx, thick); if ( thick <= 0.0 ) thick=1.0; } static void gdlGetDesiredAxisTickget(EnvT *e, string axis, DDoubleGDL *Axistickget) { //TODO! } static void gdlGetDesiredAxisTickFormat(EnvT* e, string axis, DStringGDL* &axisTickformatVect) { static int XTICKFORMATIx = e->KeywordIx("XTICKFORMAT"); static int YTICKFORMATIx = e->KeywordIx("YTICKFORMAT"); static int ZTICKFORMATIx = e->KeywordIx("ZTICKFORMAT"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKFORMATIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKFORMATIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKFORMATIx; } if ( Struct!=NULL ) { unsigned AxisTickformatTag=Struct->Desc()->TagIndex("TICKFORMAT"); axisTickformatVect = static_cast(Struct->GetTag(AxisTickformatTag,0)); } if ( e->GetKW ( choosenIx )!=NULL ) { axisTickformatVect=e->GetKWAs( choosenIx ); } } static void gdlGetDesiredAxisTickInterval(EnvT* e, string axis, DDouble &axisTickinterval) { axisTickinterval=0; static int XTICKINTERVALIx = e->KeywordIx("XTICKINTERVAL"); static int YTICKINTERVALIx = e->KeywordIx("YTICKINTERVAL"); static int ZTICKINTERVALIx = e->KeywordIx("ZTICKINTERVAL"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKINTERVALIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKINTERVALIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKINTERVALIx; } if ( Struct!=NULL ) { axisTickinterval=(*static_cast (Struct->GetTag (Struct->Desc()->TagIndex("TICKINTERVAL"), 0)))[0]; } e->AssureDoubleScalarKWIfPresent(choosenIx, axisTickinterval); } static void gdlGetDesiredAxisTickLayout(EnvT* e, string axis, DLong &axisTicklayout) { axisTicklayout=0; static int XTICKLAYOUTIx = e->KeywordIx("XTICKLAYOUT"); static int YTICKLAYOUTIx = e->KeywordIx("YTICKLAYOUT"); static int ZTICKLAYOUTIx = e->KeywordIx("ZTICKLAYOUT"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKLAYOUTIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKLAYOUTIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKLAYOUTIx; } if ( Struct!=NULL ) { axisTicklayout=(*static_cast (Struct->GetTag (Struct->Desc()->TagIndex("TICKLAYOUT"), 0)))[0]; } e->AssureLongScalarKWIfPresent(choosenIx, axisTicklayout); } static void gdlGetDesiredAxisTickLen(EnvT* e, string axis, DFloat &ticklen) { // order: !P.TICKLEN, TICKLEN, !X.TICKLEN, /XTICKLEN // get !P preference DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset ticklen=(*static_cast (pStruct->GetTag (pStruct->Desc()->TagIndex("TICKLEN"), 0)))[0]; //!P.TICKLEN, always exist, may be 0 static int TICKLENIx = e->KeywordIx("TICKLEN"); e->AssureFloatScalarKWIfPresent(TICKLENIx, ticklen); //overwritten by TICKLEN option static int XTICKLENIx = e->KeywordIx("XTICKLEN"); static int YTICKLENIx = e->KeywordIx("YTICKLEN"); static int ZTICKLENIx = e->KeywordIx("ZTICKLEN"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKLENIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKLENIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKLENIx; } if ( Struct!=NULL ) { unsigned ticklenTag=Struct->Desc()->TagIndex("TICKLEN"); DFloat axisTicklen=(*static_cast(Struct->GetTag(ticklenTag, 0)))[0]; //![XYZ].TICKLEN (exist) e->AssureFloatScalarKWIfPresent(choosenIx, axisTicklen); //overriden by kw if (axisTicklen!=0.0) ticklen=axisTicklen; } } static void gdlGetDesiredAxisTickName(EnvT* e, GDLGStream* a, string axis, DStringGDL* &axisTicknameVect) { static int XTICKNAMEIx = e->KeywordIx("XTICKNAME"); static int YTICKNAMEIx = e->KeywordIx("YTICKNAME"); static int ZTICKNAMEIx = e->KeywordIx("ZTICKNAME"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKNAMEIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKNAMEIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKNAMEIx; } if ( Struct!=NULL ) { unsigned AxisTicknameTag=Struct->Desc()->TagIndex("TICKNAME"); axisTicknameVect=static_cast(Struct->GetTag(AxisTicknameTag,0)); } if ( e->GetKW ( choosenIx )!=NULL ) { axisTicknameVect=e->GetKWAs( choosenIx ); //translate format codes here: // for (SizeT iname=0; iname < axisTicknameVect->N_Elements(); ++iname) { // std::string out = std::string(""); // a->TranslateFormatCodes(((*axisTicknameVect)[iname]).c_str(),out); ////TBD: not finished, see cases not treated in TransmateFormatCodes (gdlgstream.cpp) // (*axisTicknameVect)[iname]=out; // } } } static void gdlGetDesiredAxisTicks(EnvT* e, string axis, DLong &axisTicks) { axisTicks=0; static int XTICKSIx = e->KeywordIx("XTICKS"); static int YTICKSIx = e->KeywordIx("YTICKS"); static int ZTICKSIx = e->KeywordIx("ZTICKS"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKSIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKSIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKSIx; } if ( Struct!=NULL ) { axisTicks=(*static_cast (Struct->GetTag (Struct->Desc()->TagIndex("TICKS"), 0)))[0]; } e->AssureLongScalarKWIfPresent(choosenIx, axisTicks); if (axisTicks > 59) e->Throw("Value of number of ticks is out of allowed range."); } //if axis tick units is specified, first tickunit determines how the automatic limits are computed. // for example, if tickunits=['year','day'] the limits will be on a round nuber of years. // This is conveyed by the code static int gdlGetCalendarCode(EnvT* e, string axis) { static int XTICKUNITSIx = e->KeywordIx("XTICKUNITS"); static int YTICKUNITSIx = e->KeywordIx("YTICKUNITS"); static int ZTICKUNITSIx = e->KeywordIx("ZTICKUNITS"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKUNITSIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKUNITSIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKUNITSIx; } DStringGDL* axisTickunitsVect=NULL; if ( Struct!=NULL ) { unsigned AxisTickunitsTag=Struct->Desc()->TagIndex("TICKUNITS"); axisTickunitsVect=static_cast(Struct->GetTag(AxisTickunitsTag,0)); } if ( e->GetKW ( choosenIx )!=NULL ) { axisTickunitsVect=e->GetKWAs( choosenIx ); } int code=0; DString what=StrUpCase((*axisTickunitsVect)[0]); if (what.substr(0,4)=="YEAR") code=1; else if (what.substr(0,5)=="MONTH") code=2; else if (what.substr(0,3)=="DAY") code=3; else if (what.substr(0,7)=="NUMERIC") code=3; else if (what.substr(0,4)=="HOUR") code=4; else if (what.substr(0,6)=="MINUTE") code=5; else if (what.substr(0,6)=="SECOND") code=6; else if (what.substr(0,4)=="TIME") code=7; return code; } static void gdlGetDesiredAxisTickUnits(EnvT* e, string axis, DStringGDL* &axisTickunitsVect) { static int XTICKUNITSIx = e->KeywordIx("XTICKUNITS"); static int YTICKUNITSIx = e->KeywordIx("YTICKUNITS"); static int ZTICKUNITSIx = e->KeywordIx("ZTICKUNITS"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKUNITSIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKUNITSIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKUNITSIx; } if ( Struct!=NULL ) { unsigned AxisTickunitsTag=Struct->Desc()->TagIndex("TICKUNITS"); axisTickunitsVect=static_cast(Struct->GetTag(AxisTickunitsTag,0)); } if ( e->GetKW ( choosenIx )!=NULL ) { axisTickunitsVect=e->GetKWAs( choosenIx ); } } static void gdlGetDesiredAxisTickv(EnvT* e, string axis, DDoubleGDL* axisTickvVect) { static int XTICKVIx = e->KeywordIx("XTICKV"); static int YTICKVIx = e->KeywordIx("YTICKV"); static int ZTICKVIx = e->KeywordIx("ZTICKV"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTICKVIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTICKVIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTICKVIx; } if ( Struct!=NULL ) { unsigned AxisTickvTag=Struct->Desc()->TagIndex("TICKV"); axisTickvVect=static_cast(Struct->GetTag(AxisTickvTag,0)); } if ( e->GetKW ( choosenIx )!=NULL ) { axisTickvVect=e->GetKWAs( choosenIx ); } } static void gdlGetDesiredAxisTitle(EnvT *e, string axis, DString &title) { static int XTITLEIx = e->KeywordIx("XTITLE"); static int YTITLEIx = e->KeywordIx("YTITLE"); static int ZTITLEIx = e->KeywordIx("ZTITLE"); int choosenIx; DStructGDL* Struct=NULL; if ( axis=="X" ) { Struct=SysVar::X(); choosenIx=XTITLEIx; } if ( axis=="Y" ) { Struct=SysVar::Y(); choosenIx=YTITLEIx; } if ( axis=="Z" ) { Struct=SysVar::Z(); choosenIx=ZTITLEIx; } if ( Struct!=NULL ) { unsigned titleTag=Struct->Desc()->TagIndex("TITLE"); title= (*static_cast(Struct->GetTag(titleTag, 0)))[0]; } e->AssureStringScalarKWIfPresent(choosenIx, title); } static void gdlSetLineStyle(EnvT *e, GDLGStream *a) { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DLong linestyle= (*static_cast (pStruct->GetTag(pStruct->Desc()->TagIndex("LINESTYLE"), 0)))[0]; // if the LINESTYLE keyword is present, the value will be change DLong linestyleNew=-1111; static int linestyleIx = e->KeywordIx("LINESTYLE"); if (e->KeywordSet(linestyleIx)) e->AssureLongScalarKWIfPresent(linestyleIx, linestyleNew); bool debug=false; if ( debug ) { cout<<"temp_linestyle "<5 ) { linestyle=5; } gdlLineStyle(a, linestyle); } static DFloat gdlGetPenThickness(EnvT *e, GDLGStream *a) { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset DFloat thick=(*static_cast (pStruct->GetTag(pStruct->Desc()->TagIndex("THICK"), 0)))[0]; static int THICKIx = e->KeywordIx("THICK"); e->AssureFloatScalarKWIfPresent(THICKIx, thick); if ( thick <= 0.0 ) thick=1.0; return thick; } static void gdlSetPenThickness(EnvT *e, GDLGStream *a) { a->Thick(gdlGetPenThickness(e, a)); } static void gdlWriteTitleAndSubtitle(EnvT* e, GDLGStream *a) { unsigned titleTag=SysVar::P()->Desc()->TagIndex("TITLE"); unsigned subTitleTag=SysVar::P()->Desc()->TagIndex("SUBTITLE"); DString title=(*static_cast(SysVar::P()->GetTag(titleTag, 0)))[0]; DString subTitle=(*static_cast(SysVar::P()->GetTag(subTitleTag, 0)))[0]; static int TITLEIx = e->KeywordIx("TITLE"); static int SUBTITLEIx = e->KeywordIx("SUBTITLE"); e->AssureStringScalarKWIfPresent(TITLEIx, title); e->AssureStringScalarKWIfPresent(SUBTITLEIx, subTitle); if (title.empty() && subTitle.empty()) return; gdlSetPlotCharsize(e, a); if (!title.empty()) { e->AssureStringScalarKWIfPresent(TITLEIx, title); gdlSetPlotCharthick(e, a); a->sizeChar(1.25*a->charScale()); a->mtex("t", 1.5, 0.5, 0.5, title.c_str()); //position is in units of current char height. baseline at half-height a->sizeChar(a->charScale()/1.25); } if (!subTitle.empty()) { e->AssureStringScalarKWIfPresent(SUBTITLEIx, subTitle); DFloat step=a->mmLineSpacing()/a->mmCharHeight(); a->mtex("b", 5*step, 0.5, 0.5, subTitle.c_str()); } } //call this function if Y data is strictly >0. //set yStart to 0 only if gdlYaxisNoZero is false. static bool gdlYaxisNoZero(EnvT* e) { //no explict range given? DDouble test1, test2; unsigned rangeTag=SysVar::Y()->Desc()->TagIndex("RANGE"); test1=(*static_cast(SysVar::Y()->GetTag(rangeTag, 0)))[0]; test2=(*static_cast(SysVar::Y()->GetTag(rangeTag, 0)))[1]; if(!(test1==0.0 && test2==0.0)) return TRUE; static int YRANGEIx=e->KeywordIx( "YRANGE"); if ( e->KeywordSet( YRANGEIx)) return TRUE; //Style contains 1? DLong ystyle; gdlGetDesiredAxisStyle(e, "Y", ystyle); if (ystyle&1) return TRUE; DLong nozero=0; if (ystyle&16) nozero=1; static int YNOZEROIx=e->KeywordIx( "YNOZERO"); if ( e->KeywordSet(YNOZEROIx)) nozero = 1; return (nozero==1); } //advance to next plot unless the noerase flag is set // function declared static (local to each function using it) to avoid messing the NOERASEIx index which is not the same. static void gdlNextPlotHandlingNoEraseOption(EnvT *e, GDLGStream *a, bool noe=0) { bool noErase=FALSE; DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset if ( !noe ) { DLong LnoErase=(*static_cast (pStruct-> GetTag(pStruct->Desc()->TagIndex("NOERASE"), 0)))[0]; noErase=(LnoErase==1); static int NOERASEIx = e->KeywordIx("NOERASE"); if ( e->KeywordSet(NOERASEIx) ) { noErase=TRUE; } } else { noErase=TRUE; } a->NextPlot(!noErase); // all but the first element of !P.MULTI are ignored if POSITION kw or !P.POSITION or !P.REGION is specified // TODO: !P.REGION! DFloatGDL* pos=NULL; // system variable !P.REGION first ?? TODO pos=static_cast(pStruct-> GetTag(pStruct->Desc()->TagIndex("POSITION"), 0)); if ( (*pos)[0]==(*pos)[2] ) pos=NULL; //ignored // keyword if ( pos==NULL ) { static int positionIx=e->KeywordIx("POSITION"); if ( e->GetKW ( positionIx )!=NULL ) { pos=e->GetKWAs(positionIx); } } if ( pos!=NULL ) a->NoSub(); } static bool gdlSet3DViewPortAndWorldCoordinates(EnvT* e, GDLGStream* actStream, DDoubleGDL* Matrix, bool xLog, bool yLog, DDouble xStart, DDouble xEnd, DDouble yStart, DDouble yEnd, DDouble zStart=0.0, DDouble zEnd=1.0, bool zLog=false) { // set ![XY].CRANGE Before doing anything relative to 3D. gdlStoreAxisCRANGE("X", xStart, xEnd, xLog); gdlStoreAxisCRANGE("Y", yStart, yEnd, yLog); gdlStoreAxisCRANGE("Z", zStart, zEnd, zLog); //set ![XY].type gdlStoreAxisType("X",xLog); gdlStoreAxisType("Y",yLog); gdlStoreAxisType("Z",zLog); //set ![XY].WINDOW and ![XY].S gdlStoreAxisSandWINDOW(actStream, "X", xStart, xEnd, xLog); gdlStoreAxisSandWINDOW(actStream, "Y", yStart, yEnd, yLog); gdlStoreAxisSandWINDOW(actStream, "Z", zStart, zEnd, zLog); //3D work enum{ DATA=0, NORMAL, DEVICE } coordinateSystem=DATA; //To center plot, compute projected corners of 1 unit box static DDouble zz[8]={0,0,0,0,1,1,1,1}; static DDouble yy[8]={0,0,1,1,0,0,1,1}; static DDouble xx[8]={0,1,0,1,0,1,0,1}; static DDouble ww[8]={1,1,1,1,1,1,1,1}; DDoubleGDL* V=(new DDoubleGDL(dimension(8,4))); memcpy(&((*V)[0]),xx,8*sizeof(double)); memcpy(&((*V)[8]),yy,8*sizeof(double)); memcpy(&((*V)[16]),zz,8*sizeof(double)); memcpy(&((*V)[24]),ww,8*sizeof(double)); DDoubleGDL* pV=(Matrix->MatrixOp(V,false,true)); DDouble xmin,xmax,ymin,ymax; DLong iMin,iMax; pV->MinMax(&iMin,&iMax,NULL,NULL,false,0,0,4); xmin=(*pV)[iMin]; xmax=(*pV)[iMax]; pV->MinMax(&iMin,&iMax,NULL,NULL,false,1,0,4); ymin=(*pV)[iMin]; ymax=(*pV)[iMax]; PLFLT xMR, xML, yMB, yMT; DFloat xMarginL, xMarginR, yMarginB, yMarginT; gdlGetDesiredAxisMargin(e, "X", xMarginL, xMarginR); gdlGetDesiredAxisMargin(e, "Y", yMarginB, yMarginT); PLFLT scl=actStream->nCharLength(); //current char width xML=xMarginL*scl; //margin as percentage of subpage xMR=xMarginR*scl; scl=actStream->nCharHeight(); //current char height yMB=(yMarginB)*scl; yMT=(yMarginT)*scl; if ( xML+xMR>=1.0 ) { PLFLT xMMult=xML+xMR; xML/=xMMult*1.5; xMR/=xMMult*1.5; } if ( yMB+yMT>=1.0 ) { PLFLT yMMult=yMB+yMT; yMB/=yMMult*1.5; yMT/=yMMult*1.5; } static PLFLT positionP[4]={0, 0, 0, 0}; static PLFLT regionP[4]={0, 0, 0, 0}; static PLFLT position[4]={0,0,1,1}; DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset // Get !P.position values. !P.REGION is superseded by !P.POSITION if ( pStruct!=NULL ) { unsigned regionTag=pStruct->Desc()->TagIndex("REGION"); for ( SizeT i=0; i<4; ++i ) regionP[i]=(PLFLT)(*static_cast(pStruct->GetTag(regionTag, 0)))[i]; unsigned positionTag=pStruct->Desc()->TagIndex("POSITION"); for ( SizeT i=0; i<4; ++i ) positionP[i]=(PLFLT)(*static_cast(pStruct->GetTag(positionTag, 0)))[i]; } if (regionP[0]!=regionP[2] && positionP[0]==positionP[2]) //if not ignored, and will be used, as //a surrogate of !P.Position: { //compute position removing margins positionP[0]=regionP[0]+xMarginL*actStream->nCharLength(); positionP[1]=regionP[1]+yMarginB*actStream->nCharHeight(); positionP[2]=regionP[2]-xMarginR*actStream->nCharLength(); positionP[3]=regionP[3]-yMarginT*actStream->nCharHeight(); } //compatibility: Position NEVER outside [0,1]: positionP[0]=max(0.0,positionP[0]); positionP[1]=max(0.0,positionP[1]); positionP[2]=min(1.0,positionP[2]); positionP[3]=min(1.0,positionP[3]); //check presence of DATA,DEVICE and NORMAL options static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; // if (coordinateSystem==DATA && !actStream->validWorldBox()) e->Throw("PLOT: Data coordinate system not established."); // read boxPosition if needed static int positionIx = e->KeywordIx( "POSITION"); DFloatGDL* boxPosition = e->IfDefGetKWAs( positionIx); if (boxPosition == NULL) boxPosition = (DFloatGDL*) 0xF; if ( boxPosition!=(DFloatGDL*)0xF) { for ( SizeT i=0; i<4&&iN_Elements(); ++i ) position[i]=(*boxPosition)[i]; } // modify positionP and/or boxPosition to NORMAL if DEVICE is present if (coordinateSystem==DEVICE) { PLFLT normx; PLFLT normy; actStream->DeviceToNormedDevice(positionP[0], positionP[1], normx, normy); positionP[0]=normx; positionP[1]=normy; actStream->DeviceToNormedDevice(positionP[2], positionP[3], normx, normy); positionP[2]=normx; positionP[3]=normy; if ( boxPosition!=(DFloatGDL*)0xF) { actStream->DeviceToNormedDevice(position[0], position[1], normx, normy); position[0]=normx; position[1]=normy; actStream->DeviceToNormedDevice(position[2], position[3], normx, normy); position[2]=normx; position[3]=normy; } } if ( boxPosition!=(DFloatGDL*)0xF) { //compatibility again: Position NEVER outside [0,1]: position[0]=max(0.0,position[0]); position[1]=max(0.0,position[1]); position[2]=min(1.0,position[2]); position[3]=min(1.0,position[3]); } // New plot without POSITION=[] as argument if ( boxPosition==(DFloatGDL*)0xF ) { // If !P.position not set use default values. coordinatesSystem not used even if present! if ( positionP[0]==0&&positionP[1]==0&& positionP[2]==0&&positionP[3]==0 ) { // Set to (smart?) default values position[0]=0; position[1]=0+2*(yMB/yMarginB); //subtitle position[2]=1.0; position[3]=1.0-2*(yMT/yMarginT); //title actStream->vpor(position[0], position[2], position[1], position[3]); } else { // Use !P.position values. actStream->vpor(positionP[0], positionP[2], positionP[1], positionP[3]); } } else // Position keyword set { actStream->vpor(position[0], position[2], position[1], position[3]); } //adjust 'world' values to give room to axis labels. Could be better if we take //into account projection angles // fix word values without labels: actStream->wind(xmin, xmax, ymin, ymax); //compute world Charsize PLFLT xb, xe, yb, ye; xb=xmin-xMarginL*actStream->wCharLength(); xe=xmax+xMarginR*actStream->wCharLength(); yb=ymin-yMarginB*actStream->wCharHeight(); ye=ymax-yMarginT*actStream->wCharHeight(); actStream->wind(xb, xe, yb, ye); //Clipping is false in 3D... //set P.CLIP (done by PLOT, CONTOUR, SHADE_SURF, and SURFACE) Guard clipbox_guard; DLongGDL* clipBox= new DLongGDL(4, BaseGDL::ZERO); clipbox_guard.Reset(clipBox); PLFLT x,y; actStream->gvpd(xmin, xmax, ymin, ymax); actStream->NormedDeviceToDevice(xmin, ymin, x,y); (*clipBox)[0]=x; (*clipBox)[1]=y; actStream->NormedDeviceToDevice(xmax, ymax,x,y); (*clipBox)[2]=x; (*clipBox)[3]=y; gdlStoreCLIP(clipBox); return true; } //TODO: put margin discovery in gdlSetViewPortAndWorldCoordinates (simplify call list) //also, solve the proble of passing back xStart etc if they are changed by unwantedaxisvalue()) static bool gdlSetViewPortAndWorldCoordinates(EnvT* e, GDLGStream* actStream, bool xLog, bool yLog, DFloat xMarginL, DFloat xMarginR, DFloat yMarginB, DFloat yMarginT, DDouble xStart, DDouble xEnd, DDouble yStart, DDouble yEnd, DLong iso) { PLFLT xMR; PLFLT xML; PLFLT yMB; PLFLT yMT; enum{ DATA=0, NORMAL, DEVICE } coordinateSystem=DATA; CheckMargin(actStream, xMarginL, xMarginR, yMarginB, yMarginT, xMR, xML, yMB, yMT); // viewport - POSITION overrides static bool kwP=FALSE; static bool do_iso=FALSE; static PLFLT aspect=0.0; static PLFLT positionP[4]={0, 0, 0, 0}; static PLFLT regionP[4]={0, 0, 0, 0}; static PLFLT position[4]={0,0,1,1}; DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset // Get !P.position values. !P.REGION is superseded by !P.POSITION if ( pStruct!=NULL ) { unsigned regionTag=pStruct->Desc()->TagIndex("REGION"); for ( SizeT i=0; i<4; ++i ) regionP[i]=(PLFLT)(*static_cast(pStruct->GetTag(regionTag, 0)))[i]; unsigned positionTag=pStruct->Desc()->TagIndex("POSITION"); for ( SizeT i=0; i<4; ++i ) positionP[i]=(PLFLT)(*static_cast(pStruct->GetTag(positionTag, 0)))[i]; } if (regionP[0]!=regionP[2] && positionP[0]==positionP[2]) //if not ignored, and will be used, as //a surrogate of !P.Position: { //compute position removing margins positionP[0]=regionP[0]+xMarginL*actStream->nCharLength(); positionP[1]=regionP[1]+yMarginB*actStream->nLineSpacing(); positionP[2]=regionP[2]-xMarginR*actStream->nCharLength(); positionP[3]=regionP[3]-yMarginT*actStream->nLineSpacing(); } //compatibility: Position NEVER outside [0,1]: positionP[0]=max(0.0,positionP[0]); positionP[1]=max(0.0,positionP[1]); positionP[2]=min(1.0,positionP[2]); positionP[3]=min(1.0,positionP[3]); //check presence of DATA,DEVICE and NORMAL options static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; // if (coordinateSystem==DATA && !actStream->validWorldBox()) e->Throw("PLOT: Data coordinate system not established."); // read boxPosition if needed static int positionIx = e->KeywordIx( "POSITION"); DFloatGDL* boxPosition = e->IfDefGetKWAs( positionIx); if (boxPosition == NULL) boxPosition = (DFloatGDL*) 0xF; if ( boxPosition!=NULL && boxPosition!=(DFloatGDL*)0xF ) { for ( SizeT i=0; i<4&&iN_Elements(); ++i ) position[i]=(*boxPosition)[i]; } // modify positionP and/or boxPosition to NORMAL if DEVICE is present if (coordinateSystem==DEVICE) { PLFLT normx; PLFLT normy; actStream->DeviceToNormedDevice(positionP[0], positionP[1], normx, normy); positionP[0]=normx; positionP[1]=normy; actStream->DeviceToNormedDevice(positionP[2], positionP[3], normx, normy); positionP[2]=normx; positionP[3]=normy; if ( boxPosition!=NULL && boxPosition!=(DFloatGDL*)0xF ) { actStream->DeviceToNormedDevice(position[0], position[1], normx, normy); position[0]=normx; position[1]=normy; actStream->DeviceToNormedDevice(position[2], position[3], normx, normy); position[2]=normx; position[3]=normy; } } if ( boxPosition!=NULL && boxPosition!=(DFloatGDL*)0xF ) { //compatibility again: Position NEVER outside [0,1]: position[0]=max(0.0,position[0]); position[1]=max(0.0,position[1]); position[2]=min(1.0,position[2]); position[3]=min(1.0,position[3]); } // Adjust Start and End for Log (convert to log) if ( boxPosition!=NULL ) //new box { if ( xLog ) { gdlHandleUnwantedAxisValue(xStart, xEnd, xLog); xStart=log10(xStart); xEnd=log10(xEnd); } if ( yLog ) { gdlHandleUnwantedAxisValue(yStart, yEnd, yLog); yStart=log10(yStart); yEnd=log10(yEnd); } } // If pos == NULL (oplot, /OVERPLOT etc: Reuse previous values) if ( boxPosition==NULL ) { // If position keyword previously set if ( kwP ) { // Creates a viewport with the specified normalized subpage coordinates. if ( do_iso ) setIsoPort(actStream, position[0], position[2], position[1], position[3], aspect); else actStream->vpor(position[0], position[2], position[1], position[3]); } else { // If !P.position not set if ( positionP[0]==0&&positionP[1]==0&& positionP[2]==0&&positionP[3]==0 ) { if ( do_iso ) setIsoPort(actStream, position[0], position[2], position[1], position[3], aspect); else actStream->vpor(position[0], position[2], position[1], position[3]); } else { // !P.position set if ( do_iso ) setIsoPort(actStream, positionP[0], positionP[2], positionP[1], positionP[3], aspect); else actStream->vpor(positionP[0], positionP[2], positionP[1], positionP[3]); } } } else //New Plot { if ( iso==1 ) // Check ISOTROPIC first { do_iso=TRUE; aspect=abs((yEnd-yStart)/(xEnd-xStart)); //log-log or lin-log } else { do_iso=FALSE; aspect=0.0; // vpas with aspect=0.0 equals vpor. } // New plot without POSITION=[] as argument if ( boxPosition==(DFloatGDL*)0xF ) { kwP=false; // If !P.position not set use default values. coordinatesSystem not used even if present! if ( positionP[0]==0&&positionP[1]==0&& positionP[2]==0&&positionP[3]==0 ) { // Set to default values position[0]=xML; position[1]=yMB; position[2]=1.0-xMR; position[3]=1.0-yMT; if ( do_iso ) setIsoPort(actStream, position[0], position[2], position[1], position[3], aspect); else actStream->vpor(position[0], position[2], position[1], position[3]); } else { // Use !P.position values. if ( do_iso ) setIsoPort(actStream, positionP[0], positionP[2], positionP[1], positionP[3], aspect); else actStream->vpor(positionP[0], positionP[2], positionP[1], positionP[3]); } } else // Position keyword set { kwP=true; if ( do_iso ) setIsoPort(actStream, position[0], position[2], position[1], position[3], aspect); else actStream->vpor(position[0], position[2], position[1], position[3]); } } // for OPLOT start and end values are already log // SA: changing only local variables! //cout << "VP wind: "<GetProName()+"Coordinate system in error, please report to authors."); xStart=0.0; xEnd=1.0; } if (yStart==yEnd) { Message(e->GetProName()+"Coordinate system in error, please report to authors."); yStart=0.0; yEnd=1.0; } actStream->wind(xStart, xEnd, yStart, yEnd); // cout << "xStart " << xStart << " xEnd "< clipbox_guard; DLongGDL* clipBox= new DLongGDL(4, BaseGDL::ZERO); clipbox_guard.Reset(clipBox); PLFLT xmin, xmax, ymin, ymax, x,y; actStream->gvpd(xmin, xmax, ymin, ymax); actStream->NormedDeviceToDevice(xmin, ymin, x,y); (*clipBox)[0]=x; (*clipBox)[1]=y; actStream->NormedDeviceToDevice(xmax, ymax,x,y); (*clipBox)[2]=x; (*clipBox)[3]=y; gdlStoreCLIP(clipBox); return true; } static bool startClipping(EnvT *e, GDLGStream *a, bool canUsePClip=false) { if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"startClipping\n"); //function to be called when clipping must be actived, i.e., if the combination of CLIP= and NOCLIP= necessitate it //the function retrieves the pertinent information in keywords enum { DATA=0, NORMAL, DEVICE } coordinateSystem=DATA; bool xinverted=FALSE; bool yinverted=FALSE; //for inverted DATA coordinates static int clippingix=e->KeywordIx("CLIP"); DFloatGDL* clipBox=NULL; clipBox=e->IfDefGetKWAs(clippingix); //Get saveBox gdlSavebox* saveBox=getSaveBox(); //Save current box a->gvpd(saveBox->nx1, saveBox->nx2, saveBox->ny1, saveBox->ny2); //save norm of current box a->gvpw(saveBox->wx1, saveBox->wx2, saveBox->wy1, saveBox->wy2); //save world of current box saveBox->initialized=true; //mark as initialized (debug complicated clipping algo) //test axis inversion xinverted=(saveBox->wx1>saveBox->wx2); yinverted=(saveBox->wy1>saveBox->wy2); //GET CLIPPING PLFLT dClipBox[4]={0, 0, 0, 0}; PLFLT tempbox[4]={0, 0, 0, 0}; DDouble un, deux, trois, quatre; static int NOCLIPIx=e->KeywordIx("NOCLIP"); static string proname=e->GetProName(); static bool invertedMeaning=(proname=="PLOTS"||proname=="POLYFILL"||proname=="XYOUTS"); int noclipvalue=1; e->AssureLongScalarKWIfPresent( NOCLIPIx, noclipvalue); bool willNotClip; //eliminate simple cases if (invertedMeaning) willNotClip=(noclipvalue==1); else willNotClip=(e->KeywordSet(NOCLIPIx)); if (willNotClip) return false; if ( !canUsePClip && clipBox==NULL ) return false; if ( !canUsePClip && clipBox->N_Elements()<4) return false; //now we can start checking more deeply if (proname != "OPLOT") { //OPLOT has no /DEVICE /NORM and is already /DATA static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; } if ( clipBox==NULL && canUsePClip ) //get !P.CLIP. Coordinates are always DEVICE { DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset unsigned clipTag=pStruct->Desc()->TagIndex("CLIP"); //is in device coordinates for ( int i=0; i<4; ++i ) tempbox[i]=dClipBox[i]=(*static_cast(pStruct->GetTag(clipTag, 0)))[i]; coordinateSystem = DEVICE; //is in device coordinates if (GDL_DEBUG_PLSTREAM) fprintf(stderr, "using !P.CLIP=[%f,%f,%f,%f]\n", dClipBox[0], dClipBox[1], dClipBox[2], dClipBox[3]); } else //get units, convert to world coords for plplot, take care of axis direction { if ( (*clipBox)[0]>=(*clipBox)[2] ||(*clipBox)[1]>=(*clipBox)[3] ) { coordinateSystem=NORMAL; tempbox[0]=0.0; tempbox[1]=0.0; tempbox[2]=0.00001; //ridiculous but works. tempbox[3]=0.00001; } else for ( int i=0; i<4&&iN_Elements(); ++i ) tempbox[i]=dClipBox[i]=(*clipBox)[i]; if (GDL_DEBUG_PLSTREAM) fprintf(stderr, "using given CLIP=[%f,%f,%f,%f]\n", dClipBox[0], dClipBox[1], dClipBox[2], dClipBox[3]); if ( coordinateSystem==DATA ) { int *tx,*ty; int txn[2]={0,2}; int txr[2]={2,0}; int tyn[2]={1,3}; int tyr[2]={3,1}; if(tempbox[0]WorldToDevice(un, deux, trois, quatre); dClipBox[0]=trois; dClipBox[1]=quatre; un=tempbox[tx[1]]; deux=tempbox[ty[1]]; a->WorldToDevice(un, deux, trois, quatre); dClipBox[2]=trois; dClipBox[3]=quatre; } else if ( coordinateSystem==NORMAL ) { a->NormToDevice(tempbox[0], tempbox[1], dClipBox[0], dClipBox[1]); a->NormToDevice(tempbox[2], tempbox[3], dClipBox[2], dClipBox[3]); } } // we are now in DEVICE Coords // } //if new box is in error, return it: if (dClipBox[0]>=dClipBox[2]||dClipBox[1]>=dClipBox[3]) return false; //compute and set corresponding world coords before using whole page: a->DeviceToWorld(dClipBox[0], dClipBox[1],tempbox[0], tempbox[1]); a->DeviceToWorld(dClipBox[2], dClipBox[3],tempbox[2], tempbox[3]); a->NoSub(); // set full page viewport for the clip box boundaries: PLFLT xmin,xmax,ymin,ymax; a->DeviceToNormedDevice(dClipBox[0], dClipBox[1],xmin, ymin); a->DeviceToNormedDevice(dClipBox[2], dClipBox[3],xmax, ymax); a->vpor(xmin, xmax,ymin, ymax); a->wind(tempbox[0], tempbox[2], tempbox[1], tempbox[3]); // a->box( "bc", 0, 0, "bc", 0.0, 0); return TRUE; } static bool gdlAxis(EnvT *e, GDLGStream *a, string axis, DDouble Start, DDouble End, bool Log, DLong modifierCode=0, DDouble NormedLength=0) { static GDL_TICKNAMEDATA data; static GDL_MULTIAXISTICKDATA muaxdata; static GDL_TICKDATA tdata; tdata.a=a; tdata.isLog=Log; tdata.axisrange=abs(End-Start); data.a=a; data.nTickName=0; data.axisrange=abs(End-Start); muaxdata.e=e; muaxdata.a=a; muaxdata.what=GDL_NONE; muaxdata.nTickFormat=0; muaxdata.nTickUnits=0; muaxdata.axismin=Start; muaxdata.axismax=End; muaxdata.axisrange=abs(End-Start); //special values PLFLT OtherAxisSizeInMm; if (axis=="X") OtherAxisSizeInMm=a->mmyPageSize()*(a->boxnYSize()); if (axis=="Y") OtherAxisSizeInMm=a->mmxPageSize()*(a->boxnXSize()); //special for AXIS who change the requested box size! if (axis=="axisX") {axis="X"; OtherAxisSizeInMm=a->mmyPageSize()*(NormedLength);} if (axis=="axisY") {axis="Y"; OtherAxisSizeInMm=a->mmxPageSize()*(NormedLength);} DLong GridStyle; gdlGetDesiredAxisGridStyle(e, axis, GridStyle); DLong Minor; gdlGetDesiredAxisMinor(e, axis, Minor); DLong Style; gdlGetDesiredAxisStyle(e, axis, Style); DFloat Thick; gdlGetDesiredAxisThick(e, axis, Thick); DStringGDL* TickFormat; gdlGetDesiredAxisTickFormat(e, axis, TickFormat); DDouble TickInterval; gdlGetDesiredAxisTickInterval(e, axis, TickInterval); DLong TickLayout; gdlGetDesiredAxisTickLayout(e, axis, TickLayout); DFloat TickLen; gdlGetDesiredAxisTickLen(e, axis, TickLen); DStringGDL* TickName; gdlGetDesiredAxisTickName(e, a, axis, TickName); DLong Ticks; gdlGetDesiredAxisTicks(e, axis, Ticks); DStringGDL* TickUnits; gdlGetDesiredAxisTickUnits(e, axis, TickUnits); // DDoubleGDL *Tickv; // gdlGetDesiredAxisTickv(e, axis, Tickv); DString Title; gdlGetDesiredAxisTitle(e, axis, Title); bool hasTickUnitDefined = (TickUnits->NBytes()>0); int tickUnitArraySize=(hasTickUnitDefined)?TickUnits->N_Elements():0; //For labels we need ticklen in current character size, for ticks we need it in mm DFloat ticklen_in_mm= TickLen; if (TickLen<0) ticklen_in_mm*=-1; //ticklen in a percentage of box x or y size, to be expressed in mm if (axis=="X") ticklen_in_mm=a->mmyPageSize()*(a->boxnYSize())*ticklen_in_mm; if (axis=="Y") ticklen_in_mm=a->mmxPageSize()*(a->boxnXSize())*ticklen_in_mm; DFloat ticklen_as_norm=(axis=="X")?a->mm2ndy(ticklen_in_mm):a->mm2ndx(ticklen_in_mm); //in normed coord //eventually, each succesive X or Y axis is separated from previous by interligne + ticklen in adequate units. DFloat interligne_as_char; DFloat interligne_as_norm; DFloat typical_char_size_mm= (axis=="X")?a->mmCharHeight():a->mmCharLength(); interligne_as_char=(axis=="X")?a->mmLineSpacing()/typical_char_size_mm:a->mmCharLength()/typical_char_size_mm; //in normed coord interligne_as_norm=(axis=="X")?a->nLineSpacing():a->nCharLength(); //in normed coord DFloat displacement_of_new_axis_as_norm=2*interligne_as_norm+ticklen_as_norm; DFloat current_displacement=0; DFloat title_position=0; if ( (Style&4)!=4 ) //if we write the axis... { double nchars; //max number of chars written in label of axis. string Opt; string otherOpt; if (TickInterval==0) { if (Ticks<=0) TickInterval=gdlComputeTickInterval(e, axis, Start, End, Log); else if (Ticks>1) TickInterval=(End-Start)/Ticks; else TickInterval=(End-Start); } else { //check that tickinterval does not make more than 59 ticks: if (abs((End-Start)/TickInterval) > 59) TickInterval=(End-Start)/59; } //first write labels only: gdlSetAxisCharsize(e, a, axis); gdlSetPlotCharthick(e, a); //axis, 1st time: labels Opt="tvx";otherOpt="tv"; //draw major ticks "t" + v:values perp to Y axis + x: // the x option is in plplot 5.9.8 but not before. It permits // to avoid writing tick marks here (they will be written after) // I hope old plplots were clever enough to ignore 'x' // if they did not understand 'x' if ( Log ) Opt+="l"; //"l" for log; otherOpt is never in log I believe if (TickName->NBytes()>0) // /TICKNAME=[array] { data.counter=0; data.nchars=0; data.TickName=TickName; data.nTickName=TickName->N_Elements(); a->slabelfunc( gdlSingleAxisTickNamedFunc, &data ); Opt+="o"; if (modifierCode==2) Opt+="m"; else Opt+="n"; if (axis=="X") a->box(Opt.c_str(), TickInterval, Minor, "", 0.0, 0); else if (axis=="Y") a->box("", 0.0 ,0.0, Opt.c_str(), TickInterval, Minor); nchars=data.nchars; if (axis=="Y") title_position=nchars+2.5; else title_position=3.5; a->slabelfunc( NULL, NULL ); } //care Tickunits size is 10 if not defined because it is the size of !X.TICKUNITS. else if (hasTickUnitDefined) // /TICKUNITS=[several types of axes written below each other] { muaxdata.counter=0; muaxdata.what=GDL_TICKUNITS; if (TickFormat->NBytes()>0) // with also TICKFORMAT option.. { muaxdata.what=GDL_TICKFORMAT_AND_UNITS; muaxdata.TickFormat=TickFormat; muaxdata.nTickFormat=TickFormat->N_Elements(); } muaxdata.TickUnits=TickUnits; muaxdata.nTickUnits=tickUnitArraySize; a->slabelfunc( gdlMultiAxisTickFunc, &muaxdata ); Opt+="o";otherOpt+="o"; //use external func custom labeling if (modifierCode==2) {Opt+="m"; otherOpt+="m";} else {Opt+="n"; otherOpt+="n";} //m: write numerical/right above, n: below/left (normal) PLFLT un,deux,trois,quatre,xun,xdeux,xtrois,xquatre; a->getCurrentNormBox(un,deux,trois,quatre); a->getCurrentWorldBox(xun,xdeux,xtrois,xquatre); a->smaj(ticklen_in_mm, 1.0 ); for (SizeT i=0; i< muaxdata.nTickUnits; ++i) //loop on TICKUNITS axis { muaxdata.nchars=0; //set nchars to 0, at the end nchars will be the maximum size. if (i>0) Opt=otherOpt+"b"; //supplementary axes are to be wwritten with ticks, no smallticks; if (axis=="X") { a->vpor(un,deux,trois-current_displacement,quatre); a->wind(xun,xdeux,xtrois,xquatre); a->box(Opt.c_str(), TickInterval, Minor, "", 0.0, 0); //to avoid plplot crashes: do not use tickinterval. or recompute it correctly (no too small!) title_position=current_displacement/a->nCharHeight()+3.5; current_displacement+=displacement_of_new_axis_as_norm; //and the spacing plus the ticklengths } else if (axis=="Y") { a->vpor(un-current_displacement,deux,trois,quatre); a->wind(xun,xdeux,xtrois,xquatre); a->box("", 0.0 ,0.0, Opt.c_str(), TickInterval, Minor); //to avoid plplot crashes: do not use tickinterval. or recompute it correctly (no too small!) nchars=muaxdata.nchars; title_position=current_displacement/a->nCharLength()+nchars+2.5; current_displacement+=(nchars-1)*a->nCharLength(); //we'll skip what was written current_displacement+=displacement_of_new_axis_as_norm; //and the spacing plus the ticklengths } muaxdata.counter++; } a->vpor(un,deux,trois,quatre); a->wind(xun,xdeux,xtrois,xquatre); a->slabelfunc( NULL, NULL ); } else if (TickFormat->NBytes()>0) //no /TICKUNITS=> only 1 value taken into account { muaxdata.counter=0; muaxdata.nchars=0; muaxdata.what=GDL_TICKFORMAT; muaxdata.TickFormat=TickFormat; muaxdata.nTickFormat=1; a->slabelfunc( gdlMultiAxisTickFunc, &muaxdata ); Opt+="o"; if (modifierCode==2) Opt+="m"; else Opt+="n"; if (axis=="X") a->box(Opt.c_str(), TickInterval, Minor, "", 0.0, 0); else if (axis=="Y") a->box("", 0.0 ,0.0, Opt.c_str(), TickInterval, Minor); nchars=muaxdata.nchars; if (axis=="Y") title_position=nchars+2; else title_position=3.5; a->slabelfunc( NULL, NULL ); } else { tdata.nchars=0; a->slabelfunc( gdlSimpleAxisTickFunc, &tdata ); Opt+="o"; if (modifierCode==2) Opt+="m"; else Opt+="n"; if (axis=="X") a->box(Opt.c_str(), TickInterval, Minor, "", 0.0, 0); else if (axis=="Y") a->box("", 0.0 ,0.0, Opt.c_str(), TickInterval, Minor); nchars=tdata.nchars; if (axis=="Y") title_position=nchars+2; else title_position=3.5; a->slabelfunc( NULL, NULL ); } if (modifierCode==0 ||modifierCode==1) { if (axis=="X") a->mtex("b",title_position, 0.5, 0.5, Title.c_str()); else if (axis=="Y") a->mtex("l",title_position,0.5,0.5,Title.c_str()); } else if (modifierCode==2) { if (axis=="X") a->mtex("t", title_position, 0.5, 0.5, Title.c_str()); else if (axis=="Y") a->mtex("r",title_position,0.5,0.5,Title.c_str()); } if (TickLayout==0) { a->smaj(ticklen_in_mm, 1.0); //set base ticks to default 0.02 viewport converted to mm. a->smin(ticklen_in_mm/2.0,1.0); //idem min (plplt defaults) //thick for box and ticks. a->Thick(Thick); //ticks or grid eventually with style and length: if (abs(TickLen)<1e-6) Opt=""; else Opt="st"; //remove ticks if ticklen=0 if (TickLen<0) {Opt+="i"; TickLen=-TickLen;} switch(modifierCode) { case 2: Opt+="c"; break; case 1: Opt+="b"; break; case 0: if ( (Style&8)==8 ) Opt+="b"; else Opt+="bc"; } //gridstyle applies here: gdlLineStyle(a,GridStyle); if ( Log ) Opt+="l"; if (axis=="X") a->box(Opt.c_str(), TickInterval, Minor, "", 0.0, 0); else if (axis=="Y") a->box("", 0.0, 0, Opt.c_str(), TickInterval, Minor); //reset gridstyle gdlLineStyle(a,0); // pass over with outer box, with thick. No style applied, only ticks Opt=" "; switch(modifierCode) { case 2: Opt+="c"; break; case 1: Opt+="b"; break; case 0: if ( (Style&8)==8 ) Opt+="b"; else Opt+="bc"; } if (axis=="X") a->box(Opt.c_str(), 0.0, 0, "", 0.0, 0); else if (axis=="Y") a->box("", 0.0, 0 , Opt.c_str(), 0.0, 0); } //reset charsize & thick a->Thick(1.0); a->sizeChar(1.0); } return 0; } static bool gdlBox(EnvT *e, GDLGStream *a, DDouble xStart, DDouble xEnd, DDouble yStart, DDouble yEnd, bool xLog, bool yLog) { gdlWriteTitleAndSubtitle(e, a); gdlAxis(e, a, "X", xStart, xEnd, xLog); gdlAxis(e, a, "Y", yStart, yEnd, yLog); // title and sub title return true; } static bool gdlAxis3(EnvT *e, GDLGStream *a, string axis, DDouble Start, DDouble End, bool Log, DLong zAxisCode=0, DDouble NormedLength=0) { string addCode="b"; //for X and Y, and some Z if(zAxisCode==1 || zAxisCode==4) addCode="cm"; bool doZ=(zAxisCode>=0); // static GDL_TICKNAMEDATA data; static GDL_MULTIAXISTICKDATA muaxdata; static GDL_TICKDATA tdata; tdata.a=a; tdata.isLog=Log; tdata.axisrange=abs(End-Start); data.a=a; data.nTickName=0; data.axisrange=abs(End-Start); muaxdata.e=e; muaxdata.a=a; muaxdata.what=GDL_NONE; muaxdata.nTickFormat=0; muaxdata.nTickUnits=0; muaxdata.axismin=Start; muaxdata.axismax=End; muaxdata.axisrange=abs(End-Start); //special values PLFLT OtherAxisSizeInMm; if (axis=="X") OtherAxisSizeInMm=a->mmyPageSize()*(a->boxnYSize()); if (axis=="Y") OtherAxisSizeInMm=a->mmxPageSize()*(a->boxnXSize()); if (axis=="Z") OtherAxisSizeInMm=a->mmxPageSize()*(a->boxnXSize()); //not always correct //special for AXIS who change the requested box size! if (axis=="axisX") {axis="X"; OtherAxisSizeInMm=a->mmyPageSize()*(NormedLength);} if (axis=="axisY") {axis="Y"; OtherAxisSizeInMm=a->mmxPageSize()*(NormedLength);} if (axis=="axisZ") {axis="Y"; OtherAxisSizeInMm=a->mmxPageSize()*(NormedLength);} //not always correct // DFloat Charsize;//done in gdlSetAxisCharsize() below // gdlGetDesiredAxisCharsize(e, axis, Charsize); DLong GridStyle; gdlGetDesiredAxisGridStyle(e, axis, GridStyle); // DFloat MarginL, MarginR; //unused yet (fixme) // gdlGetDesiredAxisMargin(e, axis, MarginL, MarginR); DLong Minor; gdlGetDesiredAxisMinor(e, axis, Minor); DLong Style; gdlGetDesiredAxisStyle(e, axis, Style); DFloat Thick; gdlGetDesiredAxisThick(e, axis, Thick); DStringGDL* TickFormat; gdlGetDesiredAxisTickFormat(e, axis, TickFormat); DDouble TickInterval; gdlGetDesiredAxisTickInterval(e, axis, TickInterval); DLong TickLayout; gdlGetDesiredAxisTickLayout(e, axis, TickLayout); DFloat TickLen; gdlGetDesiredAxisTickLen(e, axis, TickLen); DStringGDL* TickName; gdlGetDesiredAxisTickName(e, a, axis, TickName); DLong Ticks; gdlGetDesiredAxisTicks(e, axis, Ticks); DStringGDL* TickUnits; gdlGetDesiredAxisTickUnits(e, axis, TickUnits); // DDoubleGDL* Tickv; // gdlGetDesiredAxisTickv(e, axis, Tickv); DString Title; gdlGetDesiredAxisTitle(e, axis, Title); bool hasTickUnitDefined = (TickUnits->NBytes()>0); int tickUnitArraySize=(hasTickUnitDefined)?TickUnits->N_Elements():0; //For labels we need ticklen in current character size, for ticks we need it in mm DFloat ticklen_in_mm= TickLen; if (TickLen<0) ticklen_in_mm*=-1; //ticklen in a percentage of box x or y size, to be expressed in mm if (axis=="X") ticklen_in_mm=a->mmyPageSize()*(a->boxnYSize())*ticklen_in_mm; if (axis=="Y") ticklen_in_mm=a->mmyPageSize()*(a->boxnXSize())*ticklen_in_mm; //eventually, each succesive X or Y axis is separated from previous by interligne + ticklen in adequate units. DFloat interligne; if (axis=="X") interligne=a->mmLineSpacing()/a->mmCharHeight(); //in units of character size if (axis=="Y") interligne=a->mmLineSpacing()/a->mmCharLength(); //in units of character size if ( (Style&4)!=4 ) //if we write the axis... { if (TickInterval==0) { if (Ticks<=0) TickInterval=gdlComputeTickInterval(e, axis, Start, End, Log); else if (Ticks>1) TickInterval=(End-Start)/Ticks; else TickInterval=(End-Start); } //Following hopefully corrects a bug in plplot when TickInterval is very very tiny. The only solution // is to avoid plotting the axis! if (TickInterval < 10*std::numeric_limits::epsilon()) { return 0; } string Opt; //first write labels only: gdlSetAxisCharsize(e, a, axis); gdlSetPlotCharthick(e, a); // axis legend if box style, else do not draw. Take care writing BELOW/ABOVE all axis if tickunits present:actStream->wCharHeight() DDouble displacement=(tickUnitArraySize>1)?2.5*tickUnitArraySize:0; //no option to care of placement of Z axis??? if (axis=="X") a->mtex3("xp",3.5+displacement, 0.5, 0.5, Title.c_str()); else if (axis=="Y") a->mtex3("yp",5.0+displacement,0.5,0.5,Title.c_str()); else if (doZ) a->mtex3("zp",5.0+displacement,0.5,0.5,Title.c_str()); //axis, 1st time: labels Opt=addCode+"nst"; //will write labels beside the left hand axis (u) at major ticks (n) if ( Log ) Opt+="l"; if (TickName->NBytes()>0) // /TICKNAME=[array] { data.counter=0; data.TickName=TickName; data.nTickName=TickName->N_Elements(); a->slabelfunc( gdlSingleAxisTickNamedFunc, &data ); Opt+="o"; if (axis=="X") a->box3(Opt.c_str(), "" , TickInterval, Minor, "", "", 0.0, 0, "", "", 0.0, 0); else if (axis=="Y") a->box3("", "", 0.0 ,0.0, Opt.c_str(),"", TickInterval, Minor, "", "", 0.0, 0); else if (doZ) if (axis=="Z") a->box3("", "", 0.0, 0, "", "", 0.0, 0, Opt.c_str(), "", TickInterval, Minor); a->slabelfunc( NULL, NULL ); } //care Tickunits size is 10 if not defined because it is the size of !X.TICKUNITS. else if (hasTickUnitDefined) // /TICKUNITS=[several types of axes written below each other] { muaxdata.counter=0; muaxdata.what=GDL_TICKUNITS; if (TickFormat->NBytes()>0) // with also TICKFORMAT option.. { muaxdata.what=GDL_TICKFORMAT_AND_UNITS; muaxdata.TickFormat=TickFormat; muaxdata.nTickFormat=TickFormat->N_Elements(); } muaxdata.TickUnits=TickUnits; muaxdata.nTickUnits=tickUnitArraySize; a->slabelfunc( gdlMultiAxisTickFunc, &muaxdata ); Opt+="o"; for (SizeT i=0; i< muaxdata.nTickUnits; ++i) //loop on TICKUNITS axis { // no equivalent in 3d yet... // PLFLT un,deux,trois,quatre,xun,xdeux,xtrois,xquatre; // a->plstream::gvpd(un,deux,trois,quatre); // a->plstream::gvpw(xun,xdeux,xtrois,xquatre); if (axis=="X") a->box3(Opt.c_str(), "", TickInterval, Minor, "", "", 0.0, 0, "", "", 0.0, 0); else if (axis=="Y") a->box3("", "", 0.0 ,0.0, Opt.c_str(),"", TickInterval, Minor, "", "", 0.0, 0); else if (doZ) if (axis=="Z") a->box3("", "", 0.0, 0, "", "", 0.0, 0, Opt.c_str(), "", TickInterval, Minor); // a->plstream::vpor(un,deux,trois,quatre); // a->plstream::wind(xun,xdeux,xtrois,xquatre); muaxdata.counter++; } a->slabelfunc( NULL, NULL ); } else if (TickFormat->NBytes()>0) //no /TICKUNITS=> only 1 value taken into account { muaxdata.counter=0; muaxdata.what=GDL_TICKFORMAT; muaxdata.TickFormat=TickFormat; muaxdata.nTickFormat=1; a->slabelfunc( gdlMultiAxisTickFunc, &muaxdata ); Opt+="o"; if (axis=="X") a->box3(Opt.c_str(), "", TickInterval, Minor, "", "", 0.0, 0, "", "", 0.0, 0); else if (axis=="Y") a->box3("", "", 0.0 ,0.0, Opt.c_str(),"", TickInterval, Minor, "", "", 0.0, 0); else if (doZ) if (axis=="Z") a->box3("", "", 0.0, 0, "", "", 0.0, 0, Opt.c_str(), "", TickInterval, Minor); a->slabelfunc( NULL, NULL ); } else { a->slabelfunc( gdlSimpleAxisTickFunc, &tdata ); Opt+="o"; if (axis=="X") a->box3(Opt.c_str(), "", TickInterval, Minor, "", "", 0.0, 0, "", "", 0.0, 0); else if (axis=="Y") a->box3("", "", 0.0 ,0.0, Opt.c_str(),"", TickInterval, Minor, "", "", 0.0, 0); else if (doZ) if (axis=="Z") a->box3("", "", 0.0, 0, "", "", 0.0, 0, Opt.c_str(), "", TickInterval, Minor); a->slabelfunc( NULL, NULL ); } if (TickLayout==0) { a->smaj(ticklen_in_mm, 1.0); //set base ticks to default 0.02 viewport converted to mm. a->smin(ticklen_in_mm/2.0,1.0); //idem min (plplt defaults) //thick for box and ticks. a->Thick(Thick); //ticks or grid eventually with style and length: if (abs(TickLen)<1e-6) Opt=""; else Opt="st"; //remove ticks if ticklen=0 if (TickLen<0) {Opt+="i"; TickLen=-TickLen;} //gridstyle applies here: gdlLineStyle(a,GridStyle); if ( Log ) Opt+="l"; if (axis=="X") a->box3(Opt.c_str(), "", TickInterval, Minor, "", "", 0.0, 0, "", "", 0.0, 0); else if (axis=="Y") a->box3("", "", 0.0 ,0.0, Opt.c_str(),"", TickInterval, Minor, "", "", 0.0, 0); else if (doZ) if (axis=="Z") a->box3("", "", 0.0, 0, "", "", 0.0, 0, Opt.c_str(), "", TickInterval, Minor); //reset ticks to default plplot value... //reset gridstyle gdlLineStyle(a,0); // pass over with outer box, with thick. No style applied, only ticks Opt="b"; if (axis=="X") a->box3(Opt.c_str(), "", TickInterval, Minor, "","",0,0,"","",0,0); else if (axis=="Y") a->box3("","",0,0, Opt.c_str(), "", TickInterval, Minor, "","",0,0); else if (doZ) if (axis=="Z") a->box3("","",0,0,"","",0,0, Opt.c_str(), "", TickInterval, Minor); } //reset charsize & thick a->Thick(1.0); a->sizeChar(1.0); } return 0; } static bool gdlBox3(EnvT *e, GDLGStream *a, DDouble xStart, DDouble xEnd, DDouble yStart, DDouble yEnd, DDouble zStart, DDouble zEnd, bool xLog, bool yLog, bool zLog, bool doSpecialZAxisPlacement=0) { DLong zAxisCode=0; static int ZAXISIx=e->KeywordIx("ZAXIS"); if (doSpecialZAxisPlacement) e->AssureLongScalarKWIfPresent(ZAXISIx, zAxisCode); gdlAxis3(e, a, "X", xStart, xEnd, xLog, 0); gdlAxis3(e, a, "Y", yStart, yEnd, yLog, 0); gdlAxis3(e, a, "Z", zStart, zEnd, zLog, zAxisCode); // title and sub title gdlWriteTitleAndSubtitle(e, a); return true; } } // namespace #endif gdl-0.9.9/src/plotting_axis.cpp000066400000000000000000000261321340051421000164500ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; class axis_call : public plotting_routine_call { private: bool handle_args(EnvT* e) { return true; } private: void old_body( EnvT* e, GDLGStream* actStream) { bool doT3d, real3d; DDouble zValue; //note: Z (VALUE) will be used uniquely if Z is not effectively defined. static int zvIx = e->KeywordIx( "Z"); zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); //T3D static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx) || T3Denabled()); DFloat xMarginL, xMarginR, yMarginB, yMarginT; bool xAxis=false, yAxis=false, zAxis=false; static int xaxisIx = e->KeywordIx( "XAXIS"); static int yaxisIx = e->KeywordIx( "YAXIS"); static int zaxisIx = e->KeywordIx( "ZAXIS"); PLINT xaxis_value, yaxis_value, zaxis_value; bool standardNumPos; //IDL behaviour for XAXIS and YAXIS and ZAXIS options: only one option is considered, and ZAXIS above YAXIS above XAXIS if( (e->GetKW( xaxisIx) != NULL) ) { xAxis = true; e->AssureLongScalarKWIfPresent(xaxisIx, xaxis_value); if (xaxis_value == 0) {standardNumPos = true;} else {standardNumPos = false;} } if( e->GetKW( yaxisIx) != NULL) { yAxis = true; xAxis = false; // like in IDL, yaxis overrides xaxis e->AssureLongScalarKWIfPresent( yaxisIx, yaxis_value); if (yaxis_value == 0) {standardNumPos = true;} else {standardNumPos = false;} } if( e->GetKW( zaxisIx) != NULL) { zAxis = true; xAxis = false; yAxis=false; // like in IDL, zaxis overrides all e->AssureLongScalarKWIfPresent( zaxisIx, zaxis_value); } if( (e->GetKW( xaxisIx) == NULL) && (e->GetKW( yaxisIx) == NULL ) && ((e->GetKW( zaxisIx) == NULL )||!doT3d)) { xAxis = true; standardNumPos = true; } // MARGIN gdlGetDesiredAxisMargin(e, "X",xMarginL, xMarginR); gdlGetDesiredAxisMargin(e, "Y",yMarginB, yMarginT); // will handle axis logness.. bool xLog, yLog, zLog; // is current box log or not? bool xAxisWasLog, yAxisWasLog, zAxisWasLog; gdlGetAxisType("X", xAxisWasLog); gdlGetAxisType("Y", yAxisWasLog); gdlGetAxisType("Z", zAxisWasLog); xLog=xAxisWasLog; yLog=yAxisWasLog; //by default logness is similar until another option is set zLog=zAxisWasLog; enum { DATA=0, NORMAL, DEVICE } coordinateSystem=DATA; static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); static int SAVEIx=e->KeywordIx("SAVE"); //check presence of DATA,DEVICE and NORMAL options if ( e->KeywordSet(DATAIx) ) coordinateSystem=DATA; if ( e->KeywordSet(DEVICEIx) ) coordinateSystem=DEVICE; if ( e->KeywordSet(NORMALIx) ) coordinateSystem=NORMAL; // get viewport coordinates in normalised units PLFLT ovpXL, ovpXR, ovpYB, ovpYT; gdlGetCurrentAxisWindow("X", ovpXL, ovpXR); gdlGetCurrentAxisWindow("Y", ovpYB, ovpYT); //undefined or null previous viewport, seems IDL returns without complain: if ((ovpXL==ovpXR) || (ovpYB==ovpYT)) return; // old x and y range DDouble oxStart, oxEnd; DDouble oyStart, oyEnd; // get ![XY].CRANGE gdlGetCurrentAxisRange("X", oxStart, oxEnd, FALSE); //ignore projection limits, convert to linear values if necessary. gdlGetCurrentAxisRange("Y", oyStart, oyEnd, FALSE); if ((oyStart == oyEnd) || (oxStart == oxEnd)) { if (oyStart != 0.0 && oyStart == oyEnd){ oyStart = 0; oyEnd = 1; } if (oxStart != 0.0 && oxStart == oxEnd){ oxStart = 0; oxEnd = 1; } } PLFLT ovpSizeX, ovpSizeY; ovpSizeX=ovpXR-ovpXL; ovpSizeY=ovpYT-ovpYB; // new x and y range, real values (not log) DDouble xStart=oxStart; DDouble xEnd=oxEnd; DDouble yStart=oyStart; DDouble yEnd=oyEnd; // handle Log options passing via Keywords // note: undocumented keywords [xyz]type still exist and // have priority on [xyz]log ! static int xTypeIx = e->KeywordIx( "XTYPE" ); static int yTypeIx = e->KeywordIx( "YTYPE" ); static int xLogIx = e->KeywordIx( "XLOG" ); static int yLogIx = e->KeywordIx( "YLOG" ); static int xTickunitsIx = e->KeywordIx( "XTICKUNITS" ); static int yTickunitsIx = e->KeywordIx( "YTICKUNITS" ); if ( e->KeywordPresent( xTypeIx ) ) xLog = e->KeywordSet( xTypeIx ); else xLog = e->KeywordSet( xLogIx ); if ( e->KeywordPresent( yTypeIx ) ) yLog = e->KeywordSet( yTypeIx ); else yLog = e->KeywordSet( yLogIx ); if ( xLog && e->KeywordSet( xTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); xLog = FALSE; } if ( yLog && e->KeywordSet( yTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); yLog = FALSE; } //XRANGE and YRANGE overrides all that, but Start/End should be recomputed accordingly DDouble xAxisStart, xAxisEnd, yAxisStart, yAxisEnd; bool setx=gdlGetDesiredAxisRange(e, "X", xAxisStart, xAxisEnd); bool sety=gdlGetDesiredAxisRange(e, "Y", yAxisStart, yAxisEnd); if (sety) { yStart=yAxisStart; yEnd=yAxisEnd; } if (setx) { xStart=xAxisStart; xEnd=xAxisEnd; } //handle Nozero option after all that! if(!gdlYaxisNoZero(e) && yStart >0 && !yLog ) yStart=0.0; gdlHandleUnwantedAxisValue(xStart, xEnd, xLog); gdlHandleUnwantedAxisValue(yStart, yEnd, yLog); // [XY]STYLE DLong xStyle=0, yStyle=0; gdlGetDesiredAxisStyle(e, "X", xStyle); gdlGetDesiredAxisStyle(e, "Y", yStyle); //xStyle and yStyle apply on range values if ((xStyle & 1) != 1) { PLFLT intv = gdlAdjustAxisRange(e, "X", xStart, xEnd, xLog); } if ((yStyle & 1) != 1) { PLFLT intv = gdlAdjustAxisRange(e, "Y", yStart, yEnd, yLog); } DDouble yVal, xVal; //in absence of arguments we will have: yVal=(standardNumPos)?oyStart:oyEnd; xVal=(standardNumPos)?oxStart:oxEnd; //read arguments if (nParam() == 1) { e->AssureDoubleScalarPar( 0, xVal); } if (nParam() == 2) { e->AssureDoubleScalarPar( 0, xVal); e->AssureDoubleScalarPar( 1, yVal); } if (nParam() == 3) { e->Throw( "Sorry, we do not yet support the 3D case"); } // *** start drawing gdlSetGraphicsForegroundColorFromKw(e, actStream); //COLOR // contrary to the documentation axis does not erase the plot (fortunately!) // gdlNextPlotHandlingNoEraseOption(e, actStream, true); //NOERASE -- not supported PLFLT vpXL, vpXR, vpYB, vpYT; //define new viewport in relative units // where is point of world coords xVal, yVal in viewport relative coords? DDouble vpX,vpY; if ( coordinateSystem==DEVICE ) { actStream->DeviceToNormedDevice(xVal, yVal, vpX, vpY); } else if ( coordinateSystem==NORMAL ) { vpX=xVal; vpY=yVal; } else //DATA { #ifdef USE_LIBPROJ4 // Map Stuff (xtype = 3) LPTYPE idata; XYTYPE odata; bool mapSet=false; get_mapset(mapSet); mapSet=(mapSet && coordinateSystem==DATA); if ( mapSet ) { ref=map_init(); if ( ref==NULL ) { e->Throw("Projection initialization failed."); } idata.u=xVal * DEG_TO_RAD; idata.v=yVal * DEG_TO_RAD; odata=PJ_FWD(idata, ref); xVal=odata.u; yVal=odata.v; DDouble *sx, *sy; GetSFromPlotStructs( &sx, &sy ); DFloat *wx, *wy; GetWFromPlotStructs( &wx, &wy ); DDouble pxStart, pxEnd, pyStart, pyEnd; DataCoordLimits( sx, sy, wx, wy, &pxStart, &pxEnd, &pyStart, &pyEnd, true ); actStream->vpor( wx[0], wx[1], wy[0], wy[1] ); actStream->wind( pxStart, pxEnd, pyStart, pyEnd ); } #endif if (xAxisWasLog) xVal=log10(xVal); if (yAxisWasLog) yVal=log10(yVal); if ( !isfinite(xVal)|| !isfinite(yVal) ) return; //no plot actStream->WorldToNormedDevice(xVal, yVal, vpX, vpY); } //compute new temporary viewport in relative coords #define ADDEPSILON 0.1 if ( standardNumPos ) { vpXL=(xAxis)?ovpXL :vpX; vpXR=(xAxis)?ovpXR :vpX+ovpSizeY; vpYB=(xAxis)?vpY :ovpYB; vpYT=(xAxis)?vpY+ovpSizeX:ovpYT; } else { vpXL=(xAxis)?ovpXL:vpX-ovpSizeY; vpXR=(xAxis)?ovpXR:vpX; vpYB=(xAxis)?vpY-ovpSizeX:ovpYB; vpYT=(xAxis)?vpY:ovpYT; } actStream->OnePageSaveLayout(); // one page actStream->vpor(vpXL, vpXR, vpYB, vpYT); if (xLog) {xStart=log10(xStart);xEnd=log10(xEnd);} if (yLog) {yStart=log10(yStart);yEnd=log10(yEnd);} actStream->wind(xStart, xEnd, yStart, yEnd); if ( xAxis ) { //special name "axisX" needed because we artificially changed size of box gdlAxis(e, actStream, "axisX", xStart, xEnd, xLog, standardNumPos?1:2, ovpSizeY); if ( e->KeywordSet(SAVEIx) ) { gdlStoreAxisCRANGE("X", xStart, xEnd, xLog); gdlStoreAxisType("X", xLog); gdlStoreAxisSandWINDOW(actStream, "X", xStart, xEnd, xLog); } } if ( yAxis ) {//special name "axisY" needed because we artificially changed size of box gdlAxis(e, actStream, "axisY", yStart, yEnd, yLog, standardNumPos?1:2, ovpSizeX); if ( e->KeywordSet(SAVEIx) ) { gdlStoreAxisCRANGE("Y", yStart, yEnd, yLog); gdlStoreAxisType("Y", yLog); gdlStoreAxisSandWINDOW(actStream, "Y", yStart, yEnd, yLog); } } // reset the viewport and world coordinates to the original values actStream->RestoreLayout(); // if save, update world coordinates to the new values if ( e->KeywordSet(SAVEIx) ) { actStream->wind(xStart, xEnd, yStart, yEnd); } } private: void call_plplot(EnvT* e, GDLGStream* actStream) { } private: virtual void post_call(EnvT* e, GDLGStream* actStream) { actStream->sizeChar(1.0); } }; void axis(EnvT* e) { axis_call axis; axis.call(e, 0); } } // namespace gdl-0.9.9/src/plotting_contour.cpp000066400000000000000000001145601340051421000172000ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #include "math_utl.hpp" #define LABELOFFSET 0.003 #define LABELSPACING 0.1 // sometime after 10/14 the tr0,tr1 moved from plstream:: to plcallback:: #undef PLCALLBACK #ifdef PLPLOT_HAS_PLCALLBACK #define PLCALLBACK plcallback #else #define PLCALLBACK plstream #endif namespace lib { using namespace std; // shared parameter bool xLog; bool yLog; void myrecordingfunction(PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data) { *xt=x; *yt=y; fprintf(stderr,"x=%f,y=%f\n",x,y); } PLINT doIt( PLFLT x, PLFLT y ) { if (xLog && x<=0 ) return 0; if (yLog && y<=0 ) return 0; return 1; } class contour_call: public plotting_routine_call { DDoubleGDL *zVal, *yVal, *xVal; Guard xval_guard, yval_guard, zval_guard, p0_guard; DDoubleGDL *yValTemp, *xValTemp; Guard xval_temp_guard, yval_temp_guard; SizeT xEl, yEl, zEl, ixEl, iyEl; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd, datamax, datamin; bool zLog, isLog; bool overplot, make2dBox, make3dBox, nodata; DLongGDL *colors,*labels,*style; PLINT defaultColor; DFloatGDL* thick; Guard colors_guard,thick_guard,labels_guard,style_guard; DFloatGDL *spacing,*orientation; Guard spacing_guard,orientation_guard; bool doT3d; bool irregular; bool setZrange; bool restorelayout; //PATH_XY etc: use actStream->stransform with a crafted recording function per level [lev-maxmax]. //disentangle positive and negative contours with their rotation signature. private: bool handle_args (EnvT* e) { static int irregIx = e->KeywordIx( "IRREGULAR"); irregular=e->KeywordSet(irregIx); // in all cases, we have to exit here if ( nParam()==2 || nParam()>3 ) { e->Throw ( "Incorrect number of arguments." ); } if ( nParam ( ) > 0 ) { // By testing here using EquivalentRank() we avoid computing zval if there was a problem. // AC 2018/04/24 // a sub-array like: a=RANDOMU(seed, 3,4,5) & (this procedure name), a[1,*,*] // should be OK ... if ( (e->GetNumericArrayParDefined ( 0 ))->EquivalentRank ( )!=2 ) e->Throw ( "Array must have 2 dimensions: "+e->GetParString ( 0 ) ); } if (nParam()==1) { if (irregular) { e->Throw ( "Incorrect number of arguments." ); } else { BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init ( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xEl=zVal->Dim ( 1 ); yEl=zVal->Dim ( 0 ); xVal=new DDoubleGDL ( dimension ( xEl ), BaseGDL::INDGEN ); xval_guard.Init ( xVal ); // delete upon exit yVal=new DDoubleGDL ( dimension ( yEl ), BaseGDL::INDGEN ); yval_guard.Init ( yVal ); // delete upon exit } } if ( nParam()==3) { if (irregular) { //ZVal will be treated as 1 dim array and X and Y must have the same number of elements. BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xValTemp=e->GetParAs< DDoubleGDL>( 1 ); yValTemp=e->GetParAs< DDoubleGDL>( 2 ); if (xValTemp->N_Elements() != zVal->N_Elements() ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if (yValTemp->N_Elements() != zVal->N_Elements() ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); xEl=xValTemp->N_Elements(); yEl=yValTemp->N_Elements(); //all points inside xVal=xValTemp; yVal=yValTemp;//for the time being, will be update later } else { BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xVal=e->GetParAs< DDoubleGDL>( 1 ); yVal=e->GetParAs< DDoubleGDL>( 2 ); if ( xVal->Rank ( )>2 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( yVal->Rank ( )>2 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( xVal->Rank ( )==0 || yVal->Rank ( )==0 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( xVal->Rank ( )==1 ) { xEl=xVal->Dim ( 0 ); if ( xEl!=zVal->Dim ( 1 ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( yVal->Rank ( )==1 ) { yEl=yVal->Dim ( 0 ); if ( yEl!=zVal->Dim ( 0 ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( xVal->Rank ( )==2 ) { xEl=xVal->Dim ( 0 ); if ( ( xVal->Dim ( 0 )!=zVal->Dim ( 1 ) )&&( xVal->Dim ( 1 )!=zVal->Dim ( 0 ) ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( yVal->Rank ( )==2 ) { yEl=yVal->Dim ( 1 ); if ( ( yVal->Dim ( 0 )!=zVal->Dim ( 1 ) )&&( yVal->Dim ( 1 )!=zVal->Dim ( 0 ) ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } } } GetMinMaxVal ( xVal, &xStart, &xEnd ); GetMinMaxVal ( yVal, &yStart, &yEnd ); //XRANGE and YRANGE overrides all that, but Start/End should be recomputed accordingly DDouble xAxisStart, xAxisEnd, yAxisStart, yAxisEnd; bool setx=gdlGetDesiredAxisRange(e, "X", xAxisStart, xAxisEnd); bool sety=gdlGetDesiredAxisRange(e, "Y", yAxisStart, yAxisEnd); if (setx) { xStart = xAxisStart; xEnd = xAxisEnd; } if (sety) { yStart = yAxisStart; yEnd = yAxisEnd; } // z range datamax=0.0; datamin=0.0; GetMinMaxVal ( zVal, &datamin, &datamax ); zStart=datamin; zEnd=datamax; setZrange = gdlGetDesiredAxisRange(e, "Z", zStart, zEnd); return false; } private: void old_body (EnvT* e, GDLGStream* actStream) // {{{ { // we need to define the NaN value DStructGDL *Values=SysVar::Values ( ); //MUST NOT BE STATIC, due to .reset static DDouble d_nan=( *static_cast ( Values->GetTag ( Values->Desc ( )->TagIndex ( "D_NAN" ), 0 ) ) )[0]; static DDouble minmin=std::numeric_limits::min(); static DDouble maxmax=std::numeric_limits::max(); //for 3D DDoubleGDL* plplot3d; DDouble az, alt, ay, scale; ORIENTATION3D axisExchangeCode; restorelayout=false; //T3D static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //ZVALUE static int zvIx = e->KeywordIx( "ZVALUE"); DDouble zValue=0.0; bool hasZvalue=false; if (e->GetKW(zvIx) !=NULL) { e->AssureDoubleScalarKW( zvIx, zValue ); zValue=min(zValue,0.999999); //to avoid problems with plplot zValue=max(zValue,0.0); hasZvalue=true; } //NODATA static int nodataIx = e->KeywordIx( "NODATA"); nodata=e->KeywordSet(nodataIx); //We could RECORD PATH this way. Not developed since PATH_INFO seems not to be used bool recordPath; static int pathinfoIx = e->KeywordIx( "PATH_INFO"); static int pathxyIx= e->KeywordIx( "PATH_XY"); recordPath=(e->KeywordSet(pathinfoIx)||e->KeywordSet(pathxyIx)); if (recordPath) { //recordPath--> use actStream->stransform(myrecordingfunction, &data); // actStream->stransform(myrecordingfunction, NULL); Warning( "PATH_INFO, PATH_XY not yet supported, (FIXME)"); recordPath=false; } // else actStream->stransform(NULL, NULL); //ISOTROPIC DLong iso=0; static int ISOTROPIC=e->KeywordIx("ISOTROPIC"); e->AssureLongScalarKWIfPresent( ISOTROPIC, iso); // [XY]STYLE DLong xStyle=0, yStyle=0, zStyle=0; ; gdlGetDesiredAxisStyle(e, "X", xStyle); gdlGetDesiredAxisStyle(e, "Y", yStyle); gdlGetDesiredAxisStyle(e, "Z", zStyle); // MARGIN DFloat xMarginL, xMarginR, yMarginB, yMarginT, zMarginF, zMarginB; gdlGetDesiredAxisMargin(e, "X", xMarginL, xMarginR); gdlGetDesiredAxisMargin(e, "Y", yMarginB, yMarginT); gdlGetDesiredAxisMargin(e, "Z", zMarginF, zMarginB); // handle Log options passing via Keywords // note: undocumented keywords [xyz]type still exist and // have priority on [xyz]log ! static int xTypeIx = e->KeywordIx( "XTYPE" ); static int yTypeIx = e->KeywordIx( "YTYPE" ); static int xLogIx = e->KeywordIx( "XLOG" ); static int yLogIx = e->KeywordIx( "YLOG" ); static int zLogIx = e->KeywordIx( "ZLOG" ); static int xTickunitsIx = e->KeywordIx( "XTICKUNITS" ); static int yTickunitsIx = e->KeywordIx( "YTICKUNITS" ); if ( e->KeywordPresent( xTypeIx ) ) xLog = e->KeywordSet( xTypeIx ); else xLog = e->KeywordSet( xLogIx ); if ( e->KeywordPresent( yTypeIx ) ) yLog = e->KeywordSet( yTypeIx ); else yLog = e->KeywordSet( yLogIx ); if ( xLog && e->KeywordSet( xTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); xLog = FALSE; } if ( yLog && e->KeywordSet( yTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); yLog = FALSE; } if (xLog || yLog) isLog=true; else isLog=false; // ztype does not exist in IDL zLog=e->KeywordSet ( zLogIx ); if ( ( xStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "X", xStart, xEnd, xLog ); } if ( ( yStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "Y", yStart, yEnd, yLog ); } static int MIN_VALUE=e->KeywordIx("MIN_VALUE"); static int MAX_VALUE=e->KeywordIx("MAX_VALUE"); bool hasMinVal=e->KeywordPresent(MIN_VALUE); bool hasMaxVal=e->KeywordPresent(MAX_VALUE); DDouble minVal=datamin; DDouble maxVal=datamax; e->AssureDoubleScalarKWIfPresent ( MIN_VALUE, minVal ); e->AssureDoubleScalarKWIfPresent ( MAX_VALUE, maxVal ); // then only apply expansion of axes: if ( ( zStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "Z", zStart, zEnd, zLog ); } //OVERPLOT: get stored range values instead to use them! static int overplotKW=e->KeywordIx ( "OVERPLOT" ); overplot=e->KeywordSet(overplotKW); make2dBox=(!overplot&&!doT3d); make3dBox=(!overplot&& doT3d); //projection: would work only with 2D X and Y. bool mapSet=false; #ifdef USE_LIBPROJ4 static LPTYPE idata; static XYTYPE odata; get_mapset ( mapSet ); mapSet = mapSet && overplot; if ( mapSet ) { ref=map_init ( ); if ( ref==NULL ) e->Throw ( "Projection initialization failed." ); } #endif if (overplot) //retrieve information in case they are not in the command line ans apply // some computation (alas)! { gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); gdlGetAxisType("Z", zLog); GetCurrentUserLimits(actStream, xStart, xEnd, yStart, yEnd); gdlGetCurrentAxisRange("Z", zStart, zEnd); //we should memorize the number of levels! if (!doT3d) { restorelayout=true; actStream->OnePageSaveLayout(); // we'll give back actual plplot's setup at end DDouble *sx, *sy; GetSFromPlotStructs( &sx, &sy ); DFloat *wx, *wy; GetWFromPlotStructs( &wx, &wy ); DDouble pxStart, pxEnd, pyStart, pyEnd; DataCoordLimits( sx, sy, wx, wy, &pxStart, &pxEnd, &pyStart, &pyEnd, true ); actStream->vpor( wx[0], wx[1], wy[0], wy[1] ); actStream->wind( pxStart, pxEnd, pyStart, pyEnd ); } } static DDouble x0,y0,xs,ys; //conversion to normalized coords x0=(xLog)?-log10(xStart):-xStart; y0=(yLog)?-log10(yStart):-yStart; xs=(xLog)?(log10(xEnd)-log10(xStart)):xEnd-xStart;xs=1.0/xs; ys=(yLog)?(log10(yEnd)-log10(yStart)):yEnd-yStart;ys=1.0/ys; if (!setZrange) { zStart=max(minVal,zStart); zEnd=min(zEnd,maxVal); } if(!overplot) { // background BEFORE next plot since it is the only place plplot may redraw the background... gdlSetGraphicsBackgroundColorFromKw ( e, actStream ); //BACKGROUND gdlNextPlotHandlingNoEraseOption(e, actStream); //NOERASE } if(make2dBox) { //start a plot // viewport and world coordinates // set the PLOT charsize before computing box, see plot command. gdlSetPlotCharsize(e, actStream); if ( gdlSetViewPortAndWorldCoordinates(e, actStream, xLog, yLog, xMarginL, xMarginR, yMarginB, yMarginT, xStart, xEnd, yStart, yEnd, iso)==FALSE ) return; //no good: should catch an exception to get out of this mess. } if (doT3d) { plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw("Illegal 3D transformation. (FIXME)"); } Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0=x0; Data3d.y0=y0; Data3d.xs=xs; Data3d.ys=ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } //necessary even if overplot // set the PLOT charsize before computing box, see plot command. gdlSetPlotCharsize(e, actStream); if (gdlSet3DViewPortAndWorldCoordinates(e, actStream, plplot3d, xLog, yLog, xStart, xEnd, yStart, yEnd, zStart, zEnd, zLog) == FALSE) return; //start 3D->2D coordinate conversions in plplot actStream->stransform(gdl3dTo2dTransformContour, &Data3d); } if ( xLog && xStart<=0.0 ) Warning ( "CONTOUR: Infinite x plot range." ); if ( yLog && yStart<=0.0 ) Warning ( "CONTOUR: Infinite y plot range." ); if ( zLog && zStart<=0.0 ) Warning ( "CONTOUR: Infinite z plot range." ); // labeling // initiated by /FOLLOW. // C_ANNOTATION=vector of strings: strings replace the default numerical values. Implies FOLLOW. Impossible with PLPLOT! // C_CHARSIZE. IDL doc false: c_charsize independent from /CHARSIZE. Charsize should be 3/4 size of AXIS LABELS, // but in fact c_charsize is independent from all [XYZ]charsize setups. Implies FOLLOW. // C_CHARTHICK Implies FOLLOW. // C_COLORS=vector, (eventually converted to integer), give color index. repated if less than contours. // C_LABELS=vector of 0 and 1 (float, double, int) . Implies FOLLOW. // C_LINESTYLE =vector of linestyles. Defaults to !P.LINESTYLE // C_ORIENTATION = vector of angles of lines to FILL (needs FILL KW) . // C_SPACING= vector of spacing in CENTIMETRES of lines to FILL (needs FILL KW) . // if C_SPACING and C_ORIENTATION absent, FILL will do a solid fill . // C_THICK=vector of thickness. repated if less than contours. defaults to !P.THICK or THICK static int FOLLOW=e->KeywordIx("FOLLOW"); static int C_CHARSIZE=e->KeywordIx("C_CHARSIZE"); static int C_CHARTHICK=e->KeywordIx("C_CHARTHICK"); static int C_LABELS=e->KeywordIx ( "C_LABELS" ); bool dolabels=false; static int FILL=e->KeywordIx("FILL"); static int C_SPACING=e->KeywordIx ( "C_SPACING" ); bool dospacing=false; static int C_ORIENTATION=e->KeywordIx ( "C_ORIENTATION" ); bool doori=false; bool label=( e->KeywordSet ( FOLLOW ) || e->KeywordSet ( C_CHARSIZE ) || e->KeywordSet( C_CHARTHICK ) || e->KeywordSet( C_LABELS ) ); bool fill=( e->KeywordSet(FILL) || e->KeywordSet (C_SPACING) || e->KeywordSet (C_ORIENTATION) ); if (fill) label=false; //mutually exclusive if (recordPath) {fill=true;} // managing the levels list OR the nlevels value // LEVELS=vector_of_values_in_increasing_order // NLEVELS=[1..60] PLINT nlevel; PLFLT *clevel; ArrayGuard clevel_guard; static int levelsix=e->KeywordIx ( "LEVELS" ); BaseGDL* b_levels=e->GetKW ( levelsix ); if ( b_levels!=NULL ) { DDoubleGDL* d_levels=e->GetKWAs( levelsix ); nlevel=d_levels-> N_Elements ( ); clevel=( PLFLT * ) &( *d_levels )[0]; // are the levels ordered ? for ( SizeT i=1; iThrow ( "Contour levels must be in increasing order." ); } } else { PLFLT zintv; DDouble mapmax,mapmin; mapmax=(zLog)?log10(zEnd):zEnd; mapmin=(zLog)?log10(zStart):zStart; // first, compute autolevel interval... zintv=AutoTick ( mapmax-mapmin); //zintv never null. static int NLEVELS=e->KeywordIx("NLEVELS"); if ( e->KeywordSet ( NLEVELS ) ) { DLong l_nlevel=nlevel; // GCC 3.4.4 needs that e->AssureLongScalarKWIfPresent ( NLEVELS, l_nlevel ); nlevel=l_nlevel; if ( nlevel<0) nlevel=2; //as IDL if (nlevel==0) nlevel=3; //idem } else { nlevel=(PLINT) floor ( ( mapmax-mapmin )/zintv ); if ( nlevel<=0 ) nodata=true; //yes, happens if image has constant value... } //levels values tries to be as rounded as possible aka IDL. //trick to round DDouble cmax,cmin; cmax=ceil(mapmax/zintv)*zintv; cmin=floor(mapmin/zintv)*zintv; zintv=(cmax-cmin)/(nlevel+1); if (!setZrange) { //update CRANGE if it was rounded above. zStart=cmin; zEnd=cmax; } if (fill) { nlevel=nlevel+1; } clevel=new PLFLT[nlevel]; clevel_guard.Reset ( clevel ); //IDL does this: if (zLog) for( SizeT i=1; i<=nlevel; i++) clevel[i-1] = pow(10.0,(zintv * i + cmin)); else for( SizeT i=1; i<=nlevel; i++) clevel[i-1] = zintv * i + cmin; } // set label params always since they are not forgotten by plplot.'label' tells if they should be used. // IDL default: 3/4 of the axis charsize (CHARSIZE keyword or !P.CHARSIZE) // PlPlot default: .3 // should be: DFloat label_size=.75*actStream->charScale(); however IDL doc false (?). DFloat label_size=0.9; //IDL behaviour, IDL doc is false, label of contours is not 3/4 of !P.CHARSIZE or CHARSIZE if ( e->KeywordSet ( C_CHARSIZE ) ) e->AssureFloatScalarKWIfPresent ( C_CHARSIZE, label_size ); // set up after: actStream->setcontlabelparam ( LABELOFFSET, (PLFLT) label_size, LABELSPACING, (label)?1:0 ); DFloat label_thick=1; if ( e->KeywordSet ( C_CHARTHICK ) ) e->AssureFloatScalarKWIfPresent ( C_CHARTHICK, label_thick ); actStream->setcontlabelformat (4, 3 ); // PLOT ONLY IF NODATA=0 if (!nodata) { //use of intermediate map for correct handling of blanking values and nans. We take advantage of the fact that //this program makes either filled regions with plshades() [but plshades hates Nans!] or contours with plcont, //which needs Nans to avoid blanked regions. The idea is to mark unwanted regions with Nans for plcont, and //with a blanking value (minmin) for plshade. Eventually one could use a zdefined() function testing on top of it. PLFLT ** map; if (irregular) { //x-y ranges: DDouble xmin,xmax,ymin,ymax; long xsize,ysize; actStream->GetGeometry(xsize,ysize); GetMinMaxVal ( xValTemp, &xmin, &xmax ); GetMinMaxVal ( yValTemp, &ymin, &ymax ); // find a good compromise for default size of gridded map... ixEl=max(51.0,2*sqrt((double)xEl)+1); //preferably odd iyEl=max(51.0,2*sqrt((double)yEl)+1); ixEl=ixElAlloc2dGrid( &map, ixEl, iyEl); PLFLT data=0; actStream->griddata(&(*xValTemp)[0],&(*yValTemp)[0],&(*zVal)[0],xEl, &(*xVal)[0],ixEl,&(*yVal)[0],iyEl,map,GRID_DTLI,data); for ( SizeT i=0, k=0; i maxVal) v=(fill)?maxmax:d_nan; map[i][j] = v; } } xEl=ixEl; yEl=iyEl; }else{ actStream->Alloc2dGrid( &map, xEl, yEl); for ( SizeT i=0, k=0; i maxVal) v=(fill)?minmin:d_nan; map[i][j] = v; } } } // provision for 2 types of grids. PLcGrid cgrid1; // X and Y independent deformation PLFLT* xg1; PLFLT* yg1; PLcGrid2 cgrid2; // Dependent X Y (e.g., rotation) bool tidyGrid1WorldData=false; bool tidyGrid2WorldData=false; bool oneDim=true; // the Grids: // 1 DIM X & Y if ( xVal->Rank ( )==1&&yVal->Rank ( )==1 && !mapSet) //mapSet: must create a 2d grid { oneDim=true; xg1 = new PLFLT[xEl]; yg1 = new PLFLT[yEl]; cgrid1.xg = xg1; cgrid1.yg = yg1; cgrid1.nx = xEl; cgrid1.ny = yEl; for ( SizeT i=0; i0?log10(cgrid1.xg[i]):1E-12; // #define EXTENDED_DEFAULT_LOGRANGE 12 if (yLog) for ( SizeT i=0; i0?log10(cgrid1.yg[i]):1E-12; tidyGrid1WorldData=true; } else //if ( xVal->Rank ( )==2&&yVal->Rank ( )==2 ) { oneDim=false; actStream->Alloc2dGrid ( &cgrid2.xg, xEl, yEl ); actStream->Alloc2dGrid ( &cgrid2.yg, xEl, yEl ); tidyGrid2WorldData=true; cgrid2.nx=xEl; cgrid2.ny=yEl; //create 2D grid for ( SizeT i=0; i0)?log10(cgrid2.xg[i][j]):1E-12; } if (yLog) for ( SizeT i=0; i0)?log10(cgrid2.yg[i][j]):1E-12; } } //Colors. DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset static int c_colorsIx=e->KeywordIx ( "C_COLORS" ); bool docolors=false; // Get decomposed value for colors DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); if ( e->GetKW ( c_colorsIx )!=NULL ) { colors=e->GetKWAs( c_colorsIx ); docolors=true; } else { // Get COLOR from PLOT system variable colors=new DLongGDL( 1, BaseGDL::NOZERO ); colors_guard.Init ( colors ); // delete upon exit colors=static_cast(pStruct->GetTag(pStruct->Desc()->TagIndex("COLOR"), 0)); docolors=false; } //treat decomposed problem here (simpler: colors for table 0 will already be truncated to 0xFF) if (!decomposed) for ( SizeT i=0; iN_Elements(); ++i ){(*colors)[i]&=0xFF;} static int c_linestyleIx=e->KeywordIx ( "C_LINESTYLE" ); bool dostyle=false; static int c_thickIx=e->KeywordIx ( "C_THICK" ); bool dothick=false; if ( e->GetKW ( c_thickIx )!=NULL ) { thick=e->GetKWAs( c_thickIx ); dothick=true; } else { // Get THICK from PLOT system variable thick=new DFloatGDL( 1, BaseGDL::NOZERO ); thick_guard.Init ( thick ); // delete upon exit DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset thick=static_cast(pStruct->GetTag(pStruct->Desc()->TagIndex("THICK"), 0)); dothick=false; } if ( e->GetKW ( C_LABELS )!=NULL ) { labels=e->GetKWAs( C_LABELS ); dolabels=true; } else //every other level { labels=new DLongGDL ( dimension (nlevel), BaseGDL::ZERO ); labels_guard.Init( labels); for ( SizeT i=0; iGetKW ( c_linestyleIx )!=NULL ) { style=e->GetKWAs( c_linestyleIx ); dostyle=true; } if ( e->GetKW ( C_ORIENTATION )!=NULL ) { orientation=e->GetKWAs( C_ORIENTATION ); doori=true; } else { orientation=new DFloatGDL ( dimension (1), BaseGDL::ZERO ); orientation_guard.Init( orientation); (*orientation)[0]=0; } if ( e->GetKW ( C_SPACING )!=NULL ) { spacing=e->GetKWAs( C_SPACING ); dospacing=true; } else { spacing=new DFloatGDL ( dimension (1), BaseGDL::ZERO ); spacing_guard.Init(spacing); (*spacing)[0]=0.25; } bool hachures=(dospacing || doori); // Important: make all clipping computations BEFORE setting graphic properties (color, size) static int CLIP=e->KeywordIx("CLIP"); static int NOCLIP=e->KeywordIx("NOCLIP"); bool doClip=(e->KeywordSet(CLIP) && !(e->KeywordSet(NOCLIP))); bool stopClip=false; if ( doClip ) if ( startClipping(e, actStream)==true ) stopClip=true; //provides some defaults: if (!docolors) gdlSetGraphicsForegroundColorFromKw ( e, actStream ); if (!dothick) gdlSetPenThickness(e, actStream); gdlSetPlotCharsize(e, actStream); actStream->psty(0); //solid fill by default! PLFLT colorindex; PLFLT value; //used for all filled contours: they use colortable 1; value is between 0 and 1. if (docolors) actStream->SetColorMap1Table(nlevel, colors , decomposed ); //load colormap1 with given colors (decomposed or not)) else actStream->SetColorMap1DefaultColors(nlevel, decomposed); if (fill) { if (hachures) { PLINT ori; PLINT spa; actStream->psty(1); // C_ORIENTATION = vector of angles of lines to FILL (needs FILL KW) . // C_SPACING= vector of spacing in CENTIMETRES of lines to FILL (needs FILL KW) . // if C_SPACING and C_ORIENTATION absent, FILL will do a solid fill . for ( SizeT i=0; istransform(gdl3dTo2dTransformContour, &Data3d); } ori=floor(10.0*(*orientation)[i%orientation->N_Elements()]); spa=floor(10000*(*spacing)[i%spacing->N_Elements()]); actStream->pat(1,&ori,&spa); value=static_cast(i)/nlevel; if (dothick) actStream->Thick(( *thick )[i%thick->N_Elements()]); if (dostyle) gdlLineStyle(actStream, ( *style )[i%style->N_Elements ( )]); //not working; plplot bug see https://sourceforge.net/p/plplot/bugs/111 actStream->shade( map, xEl, yEl, isLog?doIt:NULL, xStart, xEnd, yStart, yEnd, clevel[i], clevel[i+1], 1, value, static_cast(( *thick )[i%thick->N_Elements()]), 0,0,0,0, //NOTE TO DISCOURAGE CORRECTIONS: if trick with plcallback does not work, it is because Cmake did not set correctly //the PLPLOT_HAS_PLCALLBACK ifdef, not beacuse the following code is wrong. (PLCALLBACK::fill), (oneDim), (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); } actStream->psty(0); // if (docolors) gdlSetGraphicsForegroundColorFromKw( e, actStream ); // if (dothick) gdlSetPenThickness(e, actStream); // if (dostyle) gdlLineStyle(actStream, 0); } //end FILL with equispaced lines else if (doT3d & !hasZvalue) { //contours will be filled with solid color and displaced in Z according to their value for ( SizeT i=0; istransform(gdl3dTo2dTransformContour, &Data3d); value=static_cast(i)/nlevel; actStream->shade( map, xEl, yEl, isLog?doIt:NULL, xStart, xEnd, yStart, yEnd, clevel[i], maxmax, 1,value, 0,0,0,0,0, PLCALLBACK::fill, (oneDim), //Onedim is accelerator since rectangles are kept rectangles see plplot doc (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); } } else { //every other case of fill // note that plshades is not protected against 1 level (color formula is // "shade_color = color_min + i / (PLFLT) ( nlevel - 2 ) * color_range;" // meaning that nlevel=xx must be xx>=2 for plshades to work!) if (nlevel>2 && !(docolors)) { //acceleration with shades when no c_colors are given. use continuous table1, decomposed or not. //acceleration is most sensible when a (x,y) transform (rotate, stretch) is in place since plplot does not recompute the map. actStream->shades( map, xEl, yEl, isLog?doIt:NULL, xStart, xEnd, yStart, yEnd, clevel, nlevel, 1, 0, 0, PLCALLBACK::fill, (oneDim), (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); } else { //fill with colors defined with c_colors or n<=2 if(nlevel > 1) for ( SizeT i=0; i(i)/nlevel; actStream->shade( map, xEl, yEl, isLog?doIt:NULL, xStart, xEnd, yStart, yEnd, clevel[i], maxmax, 1,value, 0,0,0,0,0, PLCALLBACK::fill, (oneDim), //Onedim is accelerator since rectangles are kept rectangles see plplot doc (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); } else printf(" Problem, sorry! plplot doesn't like to FILL with a single level!"); } } } else { //no fill = contours . use normal pen procedures. if (!docolors) gdlSetGraphicsForegroundColorFromKw ( e, actStream ); DFloat referencePenThickness; if (!dothick) {gdlSetPenThickness(e, actStream); referencePenThickness = gdlGetPenThickness(e, actStream);} gdlSetPlotCharsize(e, actStream); for ( SizeT i=0; istransform(gdl3dTo2dTransformContour, &Data3d); } if (docolors) actStream->Color ( ( *colors )[i%colors->N_Elements ( )], decomposed); if (dothick) { actStream->Thick (( *thick )[i%thick->N_Elements ( )]); referencePenThickness = ( *thick )[i%thick->N_Elements ( )]; } if (dostyle) gdlLineStyle(actStream, ( *style )[i%style->N_Elements ( )]); if (doT3d) { //no label in T3D , bug in plplot... actStream->setcontlabelparam ( LABELOFFSET, (PLFLT) label_size, LABELSPACING, 0 ); actStream->cont ( map, xEl, yEl, 1, xEl, 1, yEl, &( clevel[i] ), 1, (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); } else { if (dolabels && iN_Elements()) { if ( label_thick < referencePenThickness ) { //one pass with (current) thick without labels, over with (smaller) label+contour. //else (lables thicker than contours) impossible with plplot... actStream->setcontlabelparam ( LABELOFFSET, (PLFLT) label_size, LABELSPACING, 0 ); actStream->cont ( map, xEl, yEl, 1, xEl, 1, yEl, &( clevel[i] ), 1, (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); //thick contours, no label actStream->Thick(label_thick); } actStream->setcontlabelparam ( LABELOFFSET, (PLFLT) label_size, LABELSPACING*sqrt(label_size),(PLINT)(*labels)[i] ); actStream->cont ( map, xEl, yEl, 1, xEl, 1, yEl, &( clevel[i] ), 1, (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); if (!dothick) gdlSetPenThickness(e, actStream); } else { actStream->cont ( map, xEl, yEl, 1, xEl, 1, yEl, &( clevel[i] ), 1, (oneDim)?(PLCALLBACK::tr1):(PLCALLBACK::tr2), (oneDim)?(void *)&cgrid1:(void *)&cgrid2); } } } // if (docolors) gdlSetGraphicsForegroundColorFromKw ( e, actStream ); // if (dothick) gdlSetPenThickness(e, actStream); // if (dostyle) gdlLineStyle(actStream, 0); } if (tidyGrid2WorldData) { actStream->Free2dGrid ( cgrid2.xg, xEl, yEl ); actStream->Free2dGrid ( cgrid2.yg, xEl, yEl ); } if (tidyGrid1WorldData) { delete[] xg1; delete[] yg1; } if (stopClip) stopClipping(actStream); actStream->Free2dGrid(map, xEl, yEl); } //finished? Store Zrange and Loginess unless we are overplot: if ( make2dBox || make3dBox ) { gdlStoreAxisCRANGE("Z", zStart, zEnd, zLog); gdlStoreAxisType("Z",zLog); } if (doT3d) { actStream->stransform(NULL,NULL); //remove transform BEFORE writing axes, ticks.. } //Draw axes after the data because /fill could potentially overlap the axes. //... if keyword "OVERPLOT" is not set if ( make2dBox ) //onlyplace where tick etc is relevant! { gdlSetGraphicsForegroundColorFromKw ( e, actStream ); //COLOR gdlBox(e, actStream, xStart, xEnd, yStart, yEnd, xLog, yLog); } if(make3dBox) { //overplot box DDouble t3xStart, t3xEnd, t3yStart, t3yEnd, t3zStart, t3zEnd; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY t3xStart=(xLog)?log10(xStart):xStart, t3xEnd=(xLog)?log10(xEnd):xEnd, t3yStart=(yLog)?log10(yStart):yStart, t3yEnd=(yLog)?log10(yEnd):yEnd, t3zStart=0; t3zEnd=1.0; actStream->w3d(scale, scale, scale*(1.0 - zValue), t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "X", xStart, xEnd, xLog); gdlAxis3(e, actStream, "Y", yStart, yEnd, yLog); break; case XY: // X->Y Y->X plane XY t3yStart=(xLog)?log10(xStart):xStart, t3yEnd=(xLog)?log10(xEnd):xEnd, t3xStart=(yLog)?log10(yStart):yStart, t3xEnd=(yLog)?log10(yEnd):yEnd, t3zStart=0; t3zEnd=1.0; actStream->w3d(scale, scale, scale*(1.0 - zValue), t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Y", xStart, xEnd, xLog); gdlAxis3(e, actStream, "X", yStart, yEnd, yLog); break; case XZ: // Y->Y X->Z plane YZ t3zStart=(xLog)?log10(xStart):xStart, t3zEnd=(xLog)?log10(xEnd):xEnd, t3yStart=(yLog)?log10(yStart):yStart, t3yEnd=(yLog)?log10(yEnd):yEnd, t3xStart=0; t3xEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Z", xStart, xEnd, xLog, 0); gdlAxis3(e, actStream, "Y", yStart, yEnd, yLog); break; case YZ: // X->X Y->Z plane XZ t3xStart=(xLog)?log10(xStart):xStart, t3xEnd=(xLog)?log10(xEnd):xEnd, t3zStart=(yLog)?log10(yStart):yStart, t3zEnd=(yLog)?log10(yEnd):yEnd, t3yStart=0; t3yEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "X", xStart, xEnd, xLog); gdlAxis3(e, actStream, "Z", yStart, yEnd, yLog,1); break; case XZXY: //X->Y Y->Z plane YZ t3yStart=(xLog)?log10(xStart):xStart, t3yEnd=(xLog)?log10(xEnd):xEnd, t3zStart=(yLog)?log10(yStart):yStart, t3zEnd=(yLog)?log10(yEnd):yEnd, t3xStart=0; t3xEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Y", xStart, xEnd, xLog); gdlAxis3(e, actStream, "Z", yStart, yEnd, yLog); break; case XZYZ: //X->Z Y->X plane XZ t3zStart=(xLog)?log10(xStart):xStart, t3zEnd=(xLog)?log10(xEnd):xEnd, t3xStart=(yLog)?log10(yStart):yStart, t3xEnd=(yLog)?log10(yEnd):yEnd, t3yStart=0; t3yEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Z", xStart, xEnd, xLog,1); gdlAxis3(e, actStream, "X", yStart, yEnd, yLog); break; } // title and sub title gdlWriteTitleAndSubtitle(e, actStream); } } private: void call_plplot (EnvT* e, GDLGStream* actStream) { } private: virtual void post_call (EnvT*, GDLGStream* actStream) { if (restorelayout) actStream->RestoreLayout(); actStream->lsty(1);//reset linestyle actStream->sizeChar(1.0); } }; // contour_call class void contour (EnvT* e) { contour_call contour; contour.call ( e, 1 ); } } // namespace #undef PLCALLBACK gdl-0.9.9/src/plotting_convert_coord.cpp000066400000000000000000001114531340051421000203530ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #define TONORMCOORDX( in, out, log) out = (log) ? sx[0] + sx[1] * log10(in) : sx[0] + sx[1] * in; #define TODATACOORDX( in, out, log) out = (log) ? pow(10.0, (in -sx[0])/sx[1]) : (in -sx[0])/sx[1]; #define TONORMCOORDY( in, out, log) out = (log) ? sy[0] + sy[1] * log10(in) : sy[0] + sy[1] * in; #define TODATACOORDY( in, out, log) out = (log) ? pow(10.0, (in -sy[0])/sy[1]) : (in -sy[0])/sy[1]; #define TONORMCOORDZ( in, out, log, doT3d) out = (doT3d)? (log) ? sz[0] + sz[1] * log10(in) : sz[0] + sz[1] * in : (log) ? log10(in) : in; #define TODATACOORDZ( in, out, log, doT3d) out = (doT3d)? (log) ? pow(10.0, (in -sz[0])/sz[1]) : (in -sz[0])/sz[1] : (log) ? pow(10.0,in) : in; namespace lib { using namespace std; static DDouble cubeCorners[32]= { 0,1,0,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1 }; DDoubleGDL* convert_coord_double(EnvT* e, DDoubleGDL* xVal, DDoubleGDL* yVal, DDoubleGDL* zVal) { typedef enum { DATA=0, NORMAL, DEVICE } COORDSYS; COORDSYS icoordinateSystem=DATA, ocoordinateSystem=DATA ; //check presence of DATA,DEVICE and NORMAL options static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); static int TO_DATAIx=e->KeywordIx("TO_DATA"); static int TO_DEVICEIx=e->KeywordIx("TO_DEVICE"); static int TO_NORMALIx=e->KeywordIx("TO_NORMAL"); if ( e->KeywordSet(DATAIx) ) icoordinateSystem=DATA; if ( e->KeywordSet(DEVICEIx) ) icoordinateSystem=DEVICE; if ( e->KeywordSet(NORMALIx) ) icoordinateSystem=NORMAL; if ( e->KeywordSet(TO_DATAIx) ) ocoordinateSystem=DATA; if ( e->KeywordSet(TO_DEVICEIx) ) ocoordinateSystem=DEVICE; if ( e->KeywordSet(TO_NORMALIx) ) ocoordinateSystem=NORMAL; static int t3dIx = e->KeywordIx( "T3D"); bool doT3d=(e->KeywordSet(t3dIx) || T3Denabled()); DLong dims[2] = {3, 0}; DDoubleGDL* res; SizeT nrows; nrows = xVal->Dim(0); dims[1] = nrows; dimension dim((DLong *) dims, 2); res = new DDoubleGDL(dim, BaseGDL::NOZERO); //eliminate simplest case here: if (ocoordinateSystem==icoordinateSystem) { #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for for (OMPInt i = 0; i < nrows; ++i) { (*res)[i * 3 + 0] = (*xVal)[i]; (*res)[i * 3 + 1] = (*yVal)[i]; (*res)[i * 3 + 2] = (*zVal)[i]; } } return res; } DDouble *sx, *sy, *sz; GetSFromPlotStructs(&sx, &sy, &sz); bool xLog, yLog, zLog; gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); gdlGetAxisType("Z", zLog); int xSize, ySize; //give default values DStructGDL* dStruct = SysVar::D(); unsigned xsizeTag = dStruct->Desc()->TagIndex( "X_SIZE"); unsigned ysizeTag = dStruct->Desc()->TagIndex( "Y_SIZE"); xSize = (*static_cast( dStruct->GetTag( xsizeTag, 0)))[0]; ySize = (*static_cast( dStruct->GetTag( ysizeTag, 0)))[0]; // Use Size in lieu of VSize GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); DLong wIx = actDevice->ActWin(); if( wIx != -1) bool success = actDevice->WSize(wIx, &xSize, &ySize); //on failure, sizes are ot changed by WSize. //projection? bool mapSet=false; #ifdef USE_LIBPROJ4 static LPTYPE idata; static XYTYPE odata; get_mapset ( mapSet ); if ( mapSet ) { ref=map_init (); if ( ref==NULL ) e->Throw ( "Projection initialization failed." ); } #endif //convert input (we can overwrite X Y and Z) to normalized switch(icoordinateSystem) { case DATA: // to u,v #ifdef USE_LIBPROJ4 if ( mapSet ) { #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for private(idata,odata) for (SizeT i = 0; i < nrows; i++) { idata.u = (*xVal)[i] * DEG_TO_RAD; idata.v = (*yVal)[i] * DEG_TO_RAD; odata = PJ_FWD(idata, ref); (*xVal)[i] = odata.u; (*yVal)[i] = odata.v; } } } #endif // to norm: #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for for (OMPInt i = 0; i < nrows; ++i) { TONORMCOORDX((*xVal)[i], (*xVal)[i], xLog); TONORMCOORDY((*yVal)[i], (*yVal)[i], yLog); TONORMCOORDZ((*zVal)[i], (*zVal)[i], zLog, doT3d); } } break; case DEVICE: #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for for (OMPInt i = 0; i < nrows; ++i) { (*xVal)[i] /= xSize; (*yVal)[i] /= ySize; // (zSize is 1) } } default: break; } //convert to output from normalized switch(ocoordinateSystem) { case DATA: // from norm: #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for for (OMPInt i = 0; i < nrows; ++i) { TODATACOORDX((*xVal)[i], (*xVal)[i], xLog); TODATACOORDY((*yVal)[i], (*yVal)[i], yLog); TODATACOORDZ((*zVal)[i], (*zVal)[i], zLog, doT3d); } } // from u,v #ifdef USE_LIBPROJ4 if ( mapSet ) { #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for private(idata,odata) for (SizeT i = 0; i < nrows; i++) { odata.u = (*xVal)[i]; odata.v = (*yVal)[i]; idata = PJ_INV(odata, ref); (*xVal)[i] = idata.u * RAD_TO_DEG; (*yVal)[i] = idata.v * RAD_TO_DEG; } } } #endif break; case DEVICE: #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for for (OMPInt i = 0; i < nrows; ++i) { (*xVal)[i] *= xSize; (*yVal)[i] *= ySize; //(zSize is 1) } } default: break; } #pragma omp parallel if (nrows >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nrows)) { #pragma omp for for (OMPInt i = 0; i < nrows; ++i) { (*res)[i * 3 + 0] = (*xVal)[i]; (*res)[i * 3 + 1] = (*yVal)[i]; (*res)[i * 3 + 2] = (*zVal)[i]; } } return res; } BaseGDL* convert_coord( EnvT* e) { DDoubleGDL* xVal, *yVal, *zVal; Guard xval_guard, yval_guard, zval_guard; SizeT xEl, yEl, zEl, minEl, xDim, yDim, zDim; //behaviour: 1 argument: needs to be [2,*] or [3,*] else 2 args: X,vector, Y vector 1 (z=vector zero). else 3 args, 3 vectors. //in case of vectors, note usual behaviour: //minimum set of dimensions of arrays. singletons expanded to dimension, //T3D static int t3dIx = e->KeywordIx( "T3D"); bool doT3d=(e->KeywordSet(t3dIx) || T3Denabled()); DDoubleGDL *xValou; DDoubleGDL *yValou; Guard xvalou_guard, yvalou_guard; SizeT nParam=e->NParam(); if( nParam < 1) e->Throw( "Incorrect number of arguments."); BaseGDL* p0; BaseGDL* p1; BaseGDL* p2; DType type=GDL_FLOAT; static int doubleIx = e->KeywordIx( "DOUBLE"); if (e->KeywordSet(doubleIx)) type=GDL_DOUBLE; p0 = e->GetParDefined( 0); if (p0->Type() == GDL_DOUBLE) type=GDL_DOUBLE; if( e->NParam() == 1) { if (p0->Dim(0) == 0) e->Throw( "Expression must be an array in this context: "+e->GetParString(0)); if (p0->Dim(0) != 2 && p0->Dim(0) != 3) e->Throw( "When only 1 param, dims must be (2,n) or (3,n)"); //with n=0 also!!! SizeT dim0=p0->Dim(0); minEl=p0->Dim(1); if (minEl==0) minEl=1; // aka in convert_coord([44,22])-->n_dim=1,dim=2 xVal=new DDoubleGDL(dimension(minEl), BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit DDoubleGDL* tmpVal=e->GetParAs< DDoubleGDL>(0); for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpVal)[i*dim0+0]; yVal=new DDoubleGDL(dimension(minEl), BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpVal)[i*dim0+1]; zVal=new DDoubleGDL(dimension(minEl), BaseGDL::ZERO); zval_guard.Reset(zVal); // delete upon exit if (dim0==3) for (SizeT i=0; i< minEl ; ++i) (*zVal)[i]=(*tmpVal)[i*dim0+2]; } if (nParam >= 2) { p1 = e->GetParDefined( 1); if (p1->Type() == GDL_DOUBLE) type=GDL_DOUBLE; xVal=e->GetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); xDim=xVal->Dim(0); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); yDim=yVal->Dim(0); //minEl: minEl=-1; minEl=(minEl>xEl&&xDim)?xEl:minEl; minEl=(minEl>yEl&&yDim)?yEl:minEl; if (minEl==-1){ minEl=1; } else { minEl=(minEl>xEl&&xDim)?xEl:minEl; minEl=(minEl>yEl&&yDim)?yEl:minEl; } DDoubleGDL* tmpxVal=e->GetParAs< DDoubleGDL>(0); xVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit if (xDim) for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[i]; else for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[0]; DDoubleGDL* tmpyVal=e->GetParAs< DDoubleGDL>(1); yVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit if (yDim) for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[i]; else for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[0]; zVal=new DDoubleGDL(minEl, BaseGDL::ZERO); zval_guard.Reset(zVal); // delete upon exit } if (nParam == 3) { p2 = e->GetParDefined( 2); if (p2->Type() == GDL_DOUBLE) type=GDL_DOUBLE; xVal=e->GetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); xDim=xVal->Dim(0); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); yDim=yVal->Dim(0); zVal=e->GetParAs(2); zEl=zVal->N_Elements(); zDim=zVal->Dim(0); //minEl: minEl=-1; minEl=(minEl>xEl&&xDim)?xEl:minEl; minEl=(minEl>yEl&&yDim)?yEl:minEl; minEl=(minEl>zEl&&zDim)?zEl:minEl; if (minEl==-1){ minEl=1; } else { minEl=(minEl>xEl&&xDim)?xEl:minEl; minEl=(minEl>yEl&&yDim)?yEl:minEl; minEl=(minEl>zEl&&zDim)?zEl:minEl; } DDoubleGDL* tmpxVal=e->GetParAs< DDoubleGDL>(0); xVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit if (xDim) for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[i]; else for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[0]; DDoubleGDL* tmpyVal=e->GetParAs< DDoubleGDL>(1); yVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit if (yDim) for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[i]; else for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[0]; DDoubleGDL* tmpzVal=e->GetParAs< DDoubleGDL>(2); zVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); zval_guard.Reset(zVal); // delete upon exit if (zDim) for (SizeT i=0; i< minEl ; ++i) (*zVal)[i]=(*tmpzVal)[i]; else for (SizeT i=0; i< minEl ; ++i) (*zVal)[i]=(*tmpzVal)[0]; } if ( doT3d ) //convert X,Y,Z in X',Y' as per T3D perspective. { DDoubleGDL* t3dMatrix; Guard t3dMatrix_guard; t3dMatrix=gdlGetT3DMatrix(); //the original one t3dMatrix_guard.Reset(t3dMatrix); DDouble *sx, *sy, *sz; GetSFromPlotStructs(&sx, &sy, &sz); xValou=new DDoubleGDL(dimension(minEl)); yValou=new DDoubleGDL(dimension(minEl)); Guard xval_guard, yval_guard; xval_guard.reset(xValou); yval_guard.reset(yValou); gdlProject3dCoordinatesIn2d(t3dMatrix, xVal, sx, yVal, sy, zVal, sz, xValou, yValou); xVal=xValou; yVal=yValou; } DDoubleGDL* res=convert_coord_double( e, xVal, yVal, zVal); if (type == GDL_DOUBLE) { return res; } //else return something... DFloatGDL* res1 = static_cast(res->Convert2(GDL_FLOAT, BaseGDL::COPY)); delete res; return res1; } //THE FOLLOWING ARE POSSIBLY THE WORST WAY TO DO THE JOB. At least they are to be used *only* //for [4,4] generalized 3D matrices void SelfTranspose3d(DDoubleGDL* me) { //crude quick hack to have the same behaviour as the other functions. SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim1,dim0),BaseGDL::NOZERO)); for (int j=0; j < dim0; ++j) for (int i=0; i < dim1; ++i)(*mat)[i*dim1+j]=(*me)[j*dim0 + i]; memcpy(me->DataAddr(),mat->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(mat); } void SelfReset3d(DDoubleGDL* me) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* Identity=(new DDoubleGDL(dimension(dim0,dim1))); for(SizeT i=0; iDataAddr(),Identity->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(Identity); } DDoubleGDL* Translate3d(DDoubleGDL* me, DDouble* trans) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); Guard mat_guard; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim0,dim1))); mat_guard.Reset(mat); SelfReset3d(mat); //identity Matrix for(SizeT i=0; i<3; ++i) {(*mat)[3*dim1+i]=trans[i];} return mat->MatrixOp(me,false,false); } void SelfTranslate3d(DDoubleGDL* me, DDouble* trans) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim0,dim1))); SelfReset3d(mat); //identity Matrix for(SizeT i=0; i<3; ++i) {(*mat)[3*dim1+i]=trans[i];} DDoubleGDL* intermediary=mat->MatrixOp(me,false,false); memcpy(me->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); GDLDelete(mat); } DDoubleGDL* Scale3d(DDoubleGDL* me, DDouble *scale) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); Guard mat_guard; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim0,dim1))); mat_guard.Reset(mat); SelfReset3d(mat); //identity Matrix for(SizeT i=0; i<3; ++i) {(*mat)[i*dim1+i]=scale[i];} return mat->MatrixOp(me,false,false); } void SelfScale3d(DDoubleGDL* me, DDouble *scale) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim0,dim1))); SelfReset3d(mat); //identity Matrix for(SizeT i=0; i<3; ++i) {(*mat)[i*dim1+i]=scale[i];} DDoubleGDL* intermediary=mat->MatrixOp(me,false,false); memcpy(me->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); GDLDelete(mat); } #define DPI (double)(4*atan(1.0)) #define DEGTORAD (DPI/180.0) #define RADTODEG (180.0/DPI) void SelfRotate3d(DDoubleGDL* me, DDouble *rot) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=(new DDoubleGDL(dimension(4,4))); SelfReset3d(mat); DDoubleGDL* maty=(new DDoubleGDL(dimension(4,4))); SelfReset3d(maty); DDoubleGDL* matz=(new DDoubleGDL(dimension(4,4))); SelfReset3d(matz); SizeT ncols=4; double c,s; for(SizeT j=0; j<3; ++j) { c=cos(rot[j]*DEGTORAD); s=sin(rot[j]*DEGTORAD); switch(j) { case 0: { (*mat)[1 * ncols + 1] = c; (*mat)[1 * ncols + 2] = s; (*mat)[2 * ncols + 1] = -s; (*mat)[2 * ncols + 2] = c; break; } case 1: { (*maty)[0 * ncols + 0] = c; (*maty)[0 * ncols + 2] = -s; (*maty)[2 * ncols + 0] = s; (*maty)[2 * ncols + 2] = c; DDoubleGDL* intermediary=maty->MatrixOp(mat,false,false); memcpy(mat->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); break; } case 2: { (*matz)[0 * ncols + 0] = c; (*matz)[0 * ncols + 1] = s; (*matz)[1 * ncols + 0] = -s; (*matz)[1 * ncols + 1] = c; DDoubleGDL* intermediary=matz->MatrixOp(mat,false,false); memcpy(mat->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); } } } DDoubleGDL* intermediary=mat->MatrixOp(me,false,false); memcpy(me->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); GDLDelete(matz); GDLDelete(maty); GDLDelete(mat); } void SelfPerspective3d(DDoubleGDL* me, DDouble zdist) { if (!isfinite(zdist)) return; //Nan if (zdist==0.0) return; SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim0,dim1))); SelfReset3d(mat); //identity Matrix (*mat)[2*dim1+3]=-1.0/zdist; DDoubleGDL* intermediary=mat->MatrixOp(me,false,false); memcpy(me->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); GDLDelete(mat); } void SelfOblique3d(DDoubleGDL* me, DDouble dist, DDouble angle) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=(new DDoubleGDL(dimension(dim0,dim1))); SelfReset3d(mat); //identity Matrix (*mat)[2*dim1+2]=0.0; (*mat)[2*dim1+0]=dist*cos(angle*DEGTORAD); (*mat)[2*dim1+1]=dist*sin(angle*DEGTORAD); DDoubleGDL* intermediary=mat->MatrixOp(me,false,false); memcpy(me->DataAddr(),intermediary->DataAddr(),dim0*dim1*sizeof(double)); GDLDelete(intermediary); GDLDelete(mat); } void SelfExch3d(DDoubleGDL* me, DLong code) { SizeT dim0=me->Dim(0); SizeT dim1=me->Dim(1); if (dim0 !=4 && dim1 !=4) return; DDoubleGDL* mat=me->Dup(); switch(code) { case 1: //exchange 0 and 1 for(SizeT i=0; icode[0]]=(x+ptr->x0)*ptr->xs; (*xyzw)[ptr->code[1]]=(y+ptr->y0)*ptr->ys;; (*xyzw)[ptr->code[2]]=ptr->zValue; DDoubleGDL* trans=xyzw->MatrixOp(ptr->Matrix,false,true); *xt=(*trans)[0]; *yt=(*trans)[1]; GDLDelete(trans); GDLDelete(xyzw); } //Special for Contour (not special for the moment in fact): void gdl3dTo2dTransformContour(PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data) { struct GDL_3DTRANSFORMDATA *ptr = (GDL_3DTRANSFORMDATA* )data; DDoubleGDL* xyzw=new DDoubleGDL(dimension(4)); (*xyzw)[3]=1.0; (*xyzw)[ptr->code[0]]=(x+ptr->x0)*ptr->xs; (*xyzw)[ptr->code[1]]=(y+ptr->y0)*ptr->ys;; (*xyzw)[ptr->code[2]]=ptr->zValue; DDoubleGDL* trans=xyzw->MatrixOp(ptr->Matrix,false,true); *xt=(*trans)[0]; *yt=(*trans)[1]; GDLDelete(trans); GDLDelete(xyzw); } //retrieve !P.T, DDoubleGDL* gdlGetT3DMatrix() { DDoubleGDL* t3dMatrix=(new DDoubleGDL(dimension(4,4),BaseGDL::NOZERO)); DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset static unsigned tTag=pStruct->Desc()->TagIndex("T"); for (int i=0; iN_Elements(); ++i )(*t3dMatrix)[i]=(*static_cast(pStruct->GetTag(tTag, 0)))[i]; SelfTranspose3d(t3dMatrix); return t3dMatrix; } // retrieve !P.T, (or use passed matrix) // scale to current X.S Y.S and Z.S, returns a matrix that can be applied directly to // XYZ data to get projected X' Y' *normalized* coordinates values DDoubleGDL* gdlGetScaledNormalizedT3DMatrix(DDoubleGDL* passedMatrix) { DDoubleGDL* t3dMatrix; if (passedMatrix==NULL) t3dMatrix=gdlGetT3DMatrix(); else t3dMatrix=passedMatrix; DDouble *sx, *sy, *sz; GetSFromPlotStructs(&sx, &sy, &sz); DDoubleGDL* toScaled=(new DDoubleGDL(dimension(4,4),BaseGDL::NOZERO)); SelfReset3d(toScaled); DDouble depla[3]={sx[0],sy[0],sz[0]}; DDouble scale[3]={sx[1],sy[1],sz[1]}; SelfScale3d(toScaled, scale); //pay attention to order for matrices! SelfTranslate3d(toScaled,depla); DDoubleGDL* returnMatrix=t3dMatrix->MatrixOp(toScaled,false,false); GDLDelete(toScaled); if (passedMatrix==NULL) GDLDelete(t3dMatrix); return returnMatrix; } void gdlNormed3dToWorld3d(DDoubleGDL *xValin, DDoubleGDL *yValin, DDoubleGDL* zValin, DDoubleGDL *xValou, DDoubleGDL *yValou, DDoubleGDL* zValou) { DDouble *sx, *sy, *sz; GetSFromPlotStructs(&sx, &sy, &sz); DDoubleGDL* toWorld=(new DDoubleGDL(dimension(4,4),BaseGDL::NOZERO)); SelfReset3d(toWorld); DDouble depla[3]={-sx[0],-sy[0],-sz[0]}; DDouble scale[3]={1/sx[1],1/sy[1],1/sz[1]}; SelfTranslate3d(toWorld,depla); //pay attention to order for matrices! SelfScale3d(toWorld, scale); //populate a 4D matrix with reduced coordinates through sx,sy,sz: SizeT nEl=xValin->N_Elements(); DDoubleGDL* xyzw=new DDoubleGDL(dimension(nEl,4)); memcpy(&((*xyzw)[0]),xValin->DataAddr(),nEl*sizeof(double)); memcpy(&((*xyzw)[nEl]),yValin->DataAddr(),nEl*sizeof(double)); if (zValin != NULL) memcpy(&((*xyzw)[2*nEl]),zValin->DataAddr(),nEl*sizeof(double)); else for (int index=0; index< nEl; ++index){ (*xyzw)[2*nEl+index]=1.0;} for (int index=0; index< nEl; ++index){ (*xyzw)[3*nEl+index]=1.0;} DDoubleGDL* trans=xyzw->MatrixOp(toWorld,false,true); memcpy(xValou->DataAddr(), trans->DataAddr(),nEl*sizeof(double)); memcpy(yValou->DataAddr(), &(*trans)[nEl],nEl*sizeof(double)); if (zValou != NULL) memcpy(zValou->DataAddr(), &(*trans)[2*nEl],nEl*sizeof(double)); GDLDelete(trans); GDLDelete(xyzw); GDLDelete(toWorld); } void gdl3dto2dProjectDDouble(DDoubleGDL* t3dMatrix, DDoubleGDL *xVal, DDoubleGDL *yVal, DDoubleGDL* zVal, DDoubleGDL *xValou, DDoubleGDL *yValou, int* code) { DDoubleGDL *decodedAxis[3]={xVal,yVal,zVal}; int *localCode=code; if (localCode == NULL) localCode=code012; //populate a 4D matrix with reduced coordinates through sx,sy,sz: SizeT nEl=xVal->N_Elements(); DDoubleGDL* xyzw=new DDoubleGDL(dimension(nEl,4)); memcpy(&((*xyzw)[0]),decodedAxis[localCode[0]]->DataAddr(),nEl*sizeof(double)); memcpy(&((*xyzw)[nEl]),decodedAxis[localCode[1]]->DataAddr(),nEl*sizeof(double)); memcpy(&((*xyzw)[2*nEl]),decodedAxis[localCode[2]]->DataAddr(),nEl*sizeof(double)); for (int index=0; index< nEl; ++index){ (*xyzw)[3*nEl+index]=1.0;} DDoubleGDL* trans=xyzw->MatrixOp(t3dMatrix,false,true); memcpy(xValou->DataAddr(), trans->DataAddr(),nEl*sizeof(double)); memcpy(yValou->DataAddr(), &(*trans)[nEl],nEl*sizeof(double)); GDLDelete(trans); GDLDelete(xyzw); } void gdlProject3dCoordinatesIn2d(DDoubleGDL* Matrix, DDoubleGDL *xVal, DDouble* sx, DDoubleGDL *yVal, DDouble *sy, DDoubleGDL* zVal, DDouble *sz , DDoubleGDL *xValou, DDoubleGDL *yValou) { DDoubleGDL* toScaled=(new DDoubleGDL(dimension(4,4),BaseGDL::NOZERO)); SelfReset3d(toScaled); DDouble depla[3]={sx[0],sy[0],sz[0]}; DDouble scale[3]={sx[1],sy[1],sz[1]}; SelfScale3d(toScaled, scale); SelfTranslate3d(toScaled,depla); //populate a 4D matrix with reduced coordinates through sx,sy,sz: SizeT nEl=xVal->N_Elements(); DDoubleGDL* xyzw=new DDoubleGDL(dimension(nEl,4)); memcpy(&((*xyzw)[0]),xVal->DataAddr(),nEl*sizeof(double)); memcpy(&((*xyzw)[nEl]),yVal->DataAddr(),nEl*sizeof(double)); memcpy(&((*xyzw)[2*nEl]),zVal->DataAddr(),nEl*sizeof(double)); for (int index=0; index< nEl; ++index){ (*xyzw)[3*nEl+index]=1.0;} DDoubleGDL* temp=Matrix->MatrixOp(toScaled,false,false); DDoubleGDL* trans=xyzw->MatrixOp(temp,false,true); memcpy(xValou->DataAddr(), trans->DataAddr(),nEl*sizeof(double)); memcpy(yValou->DataAddr(), &(*trans)[nEl],nEl*sizeof(double)); GDLDelete(trans); GDLDelete(xyzw); GDLDelete(temp); } bool isMatrixRotation(DDoubleGDL* Matrix,DDouble &rx, DDouble &ry, DDouble &rz, DDouble &scale) { DDoubleGDL* t3dMatrix=Matrix->Dup(); // !P.T=rt#cs#9r#Ry#Rx(#Rz?)#tr !Ry contains az! // r9#sc#tr# rt#cs#9r#Ry#Rx(#Rz?)#tr #rt = r9#sc#tr#!P.T#rt = Ry#Rx(#Rz?) // // a= r9#sc#tr#!P.T#rt //construct derotator of Matrix=!P.T . We can find sc if not stretch. //substract translation rt static DDouble rt[3]={-0.5, -0.5, -0.5}; SelfTranslate3d(t3dMatrix,rt); //!P.T#rt //on the other end compute the good invert translation-rotation t3dMatrix DDoubleGDL* test=(new DDoubleGDL(dimension(4,4))); SelfReset3d(test); static DDouble r9[3]={90.0, 0.0, 0.0}; SelfRotate3d(test,r9); static DDouble tr[3]={0.5, 0.5, 0.5}; SelfTranslate3d(test,tr); // product of the two should be a pure scaled rotx,roty(rotz)(scale) matrix, hence: DDoubleGDL* xz=(t3dMatrix->MatrixOp(test,false,false)); rx=atan2((*xz)[1*4+2],(*xz)[1*4+1])*RADTODEG; ry=atan2((*xz)[2*4+0],sqrt(pow((*xz)[2*4+1],2.0)+pow((*xz)[2*4+2],2.0)))*RADTODEG; rz=atan2((*xz)[1*4+0],(*xz)[0*4+0])*RADTODEG; //test by rotation inverse static DDouble Rot[3]; memset(Rot,'\0',3*sizeof(DDouble)); Rot[2]=-rz; SelfRotate3d(xz,Rot); //#zR memset(Rot,'\0',3*sizeof(DDouble)); Rot[0]=-rx; SelfRotate3d(xz,Rot); //#xR memset(Rot,'\0',3*sizeof(DDouble)); Rot[1]=-ry; SelfRotate3d(xz,Rot); //#yR scale=(*xz)[0]; DDouble sum=(*xz)[0]+(*xz)[5]+(*xz)[10]; sum/=scale; //sum of scaled Rotation matrix diagonal if (abs(sum-3.0)<1E-4) return true; else return false; } DDoubleGDL* gdlConvertT3DMatrixToPlplotRotationMatrix( DDouble zValue, DDouble &az, DDouble &alt, DDouble &ay, DDouble &scale, ORIENTATION3D &code) { //returns NULL if error! DDoubleGDL* t3dMatrix=(new DDoubleGDL(dimension(4,4))); //retrieve !P.T and find az, alt, inversions, and (possibly) scale and roty DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset static unsigned tTag=pStruct->Desc()->TagIndex("T"); for (int i=0; iN_Elements(); ++i )(*t3dMatrix)[i]=(*static_cast(pStruct->GetTag(tTag, 0)))[i]; SelfTranspose3d(t3dMatrix); //check repeatedly rotations & translations if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) { code=NORMAL3D; goto done; // 0 } SelfExch3d(t3dMatrix,01); //XY, 1 if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) { code=XY; goto done; } SelfExch3d(t3dMatrix,01); //-XY SelfExch3d(t3dMatrix,02); //+XZ 2 if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) { code=XZ; goto done; } SelfExch3d(t3dMatrix,02); //-XZ SelfExch3d(t3dMatrix,12); //+YZ 3 if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) { code=YZ; goto done; } SelfExch3d(t3dMatrix,12); //-YZ SelfExch3d(t3dMatrix,01); //XY first SelfExch3d(t3dMatrix,02); //+XZ 5 if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) { code=XZXY; goto done; } SelfExch3d(t3dMatrix,02); //-XZ SelfExch3d(t3dMatrix,12); //+YZ 4 if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) { code=XZYZ; goto done; } SelfExch3d(t3dMatrix,12); //-YZ SelfExch3d(t3dMatrix,01); //-XY //redundant // SelfExch3d(t3dMatrix,12); // YZ first // // SelfExch3d(t3dMatrix,01); //XY 5 // if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) // { // code=YZXY; goto done; // } // SelfExch3d(t3dMatrix,01); //-XY // SelfExch3d(t3dMatrix,02); //+XZ 4 // if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) // { // code=YZXZ; goto done; // } // SelfExch3d(t3dMatrix,02); //-XZ // SelfExch3d(t3dMatrix,12); //-YZ // // SelfExch3d(t3dMatrix,02); // XZ first // // SelfExch3d(t3dMatrix,01); //XY 4 // if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) // { // code=XZXY; goto done; // } // SelfExch3d(t3dMatrix,01); //-XY // SelfExch3d(t3dMatrix,12); //+YZ 4 // if (isMatrixRotation(t3dMatrix,alt,az,ay,scale)) // { // code=XZYZ; goto done; // } return (DDoubleGDL*)(NULL); //ERROR! done: if (alt > 90.0 || alt <-1.E-3) return (DDoubleGDL*)(NULL); if (alt<0.0) alt=0.0; //prevents plplot complain for epsilon not being strictly positive. //recompute transformation matrix with plplot conventions: DDoubleGDL* plplot3d=gdlComputePlplotRotationMatrix(az, alt, zValue, scale); return plplot3d; } void scale3_pro(EnvT* e) { static unsigned tTag=SysVar::P()->Desc()->TagIndex("T"); const double invsqrt3=1.0/sqrt(3.0); //AX DDouble ax=30.0; static int AX=e->KeywordIx("AX"); e->AssureDoubleScalarKWIfPresent(AX, ax); //AZ DDouble az=30.0; static int AZ=e->KeywordIx("AZ"); e->AssureDoubleScalarKWIfPresent(AZ, az); DDoubleGDL* mat=(new DDoubleGDL(dimension(4,4),BaseGDL::NOZERO)); SelfReset3d(mat); static DDouble mytrans[3]={-0.5, -0.5, -0.5}; SelfTranslate3d(mat,mytrans); static DDouble myscale[3]={invsqrt3, invsqrt3, invsqrt3}; SelfScale3d(mat,myscale); DDouble rot1[3]={-90.0, az, 0.0}; DDouble rot2[3]={ax, 0.0, 0.0}; SelfRotate3d(mat,rot1); SelfRotate3d(mat,rot2); static DDouble mytrans2[3]={0.5, 0.5, 0.5}; SelfTranslate3d(mat,mytrans2); SelfTranspose3d(mat); for (int i=0; iN_Elements(); ++i )(*static_cast(SysVar::P()->GetTag(tTag, 0)))[i]=(*mat)[i]; DDouble size; //XRANGE static int xrangeIx = e->KeywordIx( "XRANGE"); DDoubleGDL* xrange = e->IfDefGetKWAs( xrangeIx); if (xrange != NULL){ if (xrange->N_Elements()<2) e->Throw("XRANGE needs at least a 2-elements vector"); static unsigned sTag=SysVar::X()->Desc()->TagIndex("S"); size=((*xrange)[1]-(*xrange)[0]); (*static_cast(SysVar::X()->GetTag(sTag, 0)))[0]=-(*xrange)[0]/size; (*static_cast(SysVar::X()->GetTag(sTag, 0)))[1]=1.0/size; } //YRANGE static int yrangeIx = e->KeywordIx( "YRANGE"); DDoubleGDL* yrange = e->IfDefGetKWAs( yrangeIx); if (yrange != NULL){ if (yrange->N_Elements()<2) e->Throw("YRANGE needs at least a 2-elements vector"); static unsigned sTag=SysVar::Y()->Desc()->TagIndex("S"); size=((*yrange)[1]-(*yrange)[0]); (*static_cast(SysVar::Y()->GetTag(sTag, 0)))[0]=-(*yrange)[0]/size; (*static_cast(SysVar::Y()->GetTag(sTag, 0)))[1]=1.0/size; } //ZRANGE static int zrangeIx = e->KeywordIx( "ZRANGE"); DDoubleGDL* zrange = e->IfDefGetKWAs( zrangeIx); if (zrange != NULL){ if (zrange->N_Elements()<2) e->Throw("ZRANGE needs at least a 2-elements vector"); static unsigned sTag=SysVar::Z()->Desc()->TagIndex("S"); size=((*zrange)[1]-(*zrange)[0]); (*static_cast(SysVar::Z()->GetTag(sTag, 0)))[0]=-(*zrange)[0]/size; (*static_cast(SysVar::Z()->GetTag(sTag, 0)))[1]=1.0/size; } } void t3d_pro( EnvT* e) { static unsigned tTag=SysVar::P()->Desc()->TagIndex("T"); DDoubleGDL *mat=NULL; DDoubleGDL *matin=NULL; // MATRIX keyword (read, write) static int matrixIx=e->KeywordIx("MATRIX"); bool externalarray=e->KeywordPresent(matrixIx); static int resetIx = e->KeywordIx( "RESET"); bool reset=e->KeywordSet(resetIx); if (e->NParam() > 1) { e->Throw("Accepts only one (optional) 4x4 array"); } else if (e->NParam() == 1 && !reset) { matin=e->GetParAs< DDoubleGDL > (0); if (matin->Rank() != 2) e->Throw(e->GetParString(0)+"must be a 2d array."); if (matin->Dim(0) != 4 || matin->Dim(1) != 4) e->Throw(e->GetParString(0)+"must be a [4,4] array."); mat=matin->Dup(); } else { mat=(new DDoubleGDL(dimension(4,4))); for (int i=0; iN_Elements(); ++i )(*mat)[i]=(*static_cast(SysVar::P()->GetTag(tTag, 0)))[i]; } SelfTranspose3d(mat); //for c matrix handling if (reset) SelfReset3d(mat); //TRANSLATE static int translateIx = e->KeywordIx( "TRANSLATE"); DDoubleGDL* translate = e->IfDefGetKWAs( translateIx); if (translate != NULL) { if (translate->N_Elements() != 3) e->Throw("TRANSLATE parameter must be a [3] array."); SelfTranslate3d(mat, (DDouble*)translate->DataAddr()); } //SCALE static int scaleIx = e->KeywordIx( "SCALE"); DDoubleGDL* scale = e->IfDefGetKWAs( scaleIx); if (scale != NULL) { if (scale->N_Elements() != 3) e->Throw("SCALE parameter must be a [3] array."); SelfScale3d(mat, (DDouble*)scale->DataAddr()); } //ROTATE static int rotateIx = e->KeywordIx( "ROTATE"); DDoubleGDL* rotate = e->IfDefGetKWAs( rotateIx); if (rotate != NULL) { if (rotate->N_Elements() != 3) e->Throw("ROTATE parameter must be a [3] array."); SelfRotate3d(mat, (DDouble*)rotate->DataAddr()); } //PERSPECTIVE static int perspIx = e->KeywordIx("PERSPECTIVE"); BaseGDL* perspective=e->GetKW(perspIx); if (perspective != NULL) { DDoubleGDL* persp= static_cast(perspective->Convert2( GDL_DOUBLE, BaseGDL::COPY)); SelfPerspective3d(mat, (*persp)[0]); } //OBLIQUE static int obliqueIx = e->KeywordIx( "OBLIQUE"); DDoubleGDL* oblique = e->IfDefGetKWAs( obliqueIx); if (oblique != NULL) { if (oblique->N_Elements() != 2) e->Throw("OBLIQUE parameter must be a [2] array."); SelfOblique3d(mat, (*oblique)[0],(*oblique)[1]); } DLong code; //XYEXCH static int exchxyIx = e->KeywordIx( "XYEXCH"); bool exchxy=e->KeywordSet(exchxyIx); if (exchxy) code=01; //XZEXCH static int exchxzIx = e->KeywordIx( "XZEXCH"); bool exchxz=e->KeywordSet(exchxzIx); if (exchxz) code=02; //YYEXCH static int exchyzIx = e->KeywordIx( "YZEXCH"); bool exchyz=e->KeywordSet(exchyzIx); if (exchyz) code=12; if (exchxy||exchxz||exchyz) SelfExch3d(mat, code ); SelfTranspose3d(mat); //prior to give back. if ( externalarray ) { e->SetKW(matrixIx, mat); } else { for (int i=0; iN_Elements(); ++i )(*static_cast(SysVar::P()->GetTag(tTag, 0)))[i]=(*mat)[i]; GDLDelete(mat); } } } // namespace gdl-0.9.9/src/plotting_cursor.cpp000066400000000000000000000204461340051421000170230ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib{ using namespace std; void empty(EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); if (actDevice->Name() == "X") { GDLGStream *actStream = actDevice->GetStream(false);//this command SHOULD NOT open a window if none opened. if (actStream != NULL) actStream->Flush(); } } void tvcrs( EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); if (actDevice == NULL) e->Throw("No device available"); GDLGStream *actStream = actDevice->GetStream(); if (actStream == NULL) e->Throw("Unable to create window."); if (!actStream->HasCrossHair()) { e->Throw("Routine is not defined for current graphics device."); } SizeT nParam = e->NParam(1); if (nParam < 2 ) { e->Throw("TVCRS with 1 argument not implemented (fixme)"); } DDoubleGDL *x,*y; x = e->GetParAs< DDoubleGDL > (0); y = e->GetParAs< DDoubleGDL > (1); PLINT plplot_level; actStream->glevel(plplot_level); // when level < 2, we have to read if ![x|y].crange exist // if not, we have to build a [0,1]/[0,1] window if (plplot_level < 2) { actStream->NextPlot(); actStream->vpor(0, 1, 0, 1); actStream->wind(0, 1, 0, 1); } PLFLT ix,iy; static int DATA = e->KeywordIx("DATA"); static int NORMAL = e->KeywordIx("NORMAL"); static int DEVICE = e->KeywordIx("DEVICE"); if (e->KeywordSet(DATA)) // /DATA { DDouble tempx,tempy; tempx=(*x)[0]; tempy=(*y)[0]; bool mapSet = false; get_mapset(mapSet); if (mapSet) { #ifdef USE_LIBPROJ4 if (ref == NULL) e->Throw("Projection initialization failed."); LPTYPE idataN; idataN.u = tempx* DEG_TO_RAD; idataN.v = tempy* DEG_TO_RAD; XYTYPE odata = PJ_FWD(idataN, ref); // norm to world invalid since projection. use !x.s and !y.s directly DDouble *sx, *sy; GetSFromPlotStructs( &sx, &sy ); tempx= sx[0] +odata.u * sx[1]; tempy= sy[0] +odata.v * sy[1]; //normed values actStream->NormedDeviceToDevice(tempx,tempy,ix,iy); DLong iix=ix; DLong iiy=iy; actStream->WarpPointer(iix,iiy); actStream->Flush(); actStream->UnsetFocus(); return; #endif } bool xLog, yLog; gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); if(xLog) tempx=pow(10,tempx); if(yLog) tempy=pow(10,tempy); actStream->WorldToDevice(tempx,tempy,ix,iy); } else if (e->KeywordSet(NORMAL)) { actStream->NormedDeviceToDevice((*x)[0],(*y)[0],ix,iy); } else // (e->KeywordSet(DEVICE)) { ix=(*x)[0]; iy=(*y)[0]; } DLong iix=ix; DLong iiy=iy; actStream->WarpPointer(iix,iiy); actStream->Flush(); actStream->UnsetFocus(); } // get cursor from plPlot AC February 2008 // fully compatible with IDL using our own cursor routines GD Jan 2013 void cursor(EnvT* e){ enum CursorOpt { NOWAIT=0, WAIT, //1 CHANGE, //2 DOWN, //3 UP //4 }; GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); if (actDevice == NULL) e->Throw("No device available"); GDLGStream *actStream = actDevice->GetStream(); if (actStream == NULL) e->Throw("Unable to create window."); if (!actStream->HasCrossHair()) { e->Throw("Routine is not defined for current graphics device."); } SizeT nParam = e->NParam(1); if (nParam < 2 || nParam > 3) { e->Throw("Incorrect number of arguments."); } e->AssureGlobalPar(0); e->AssureGlobalPar(1); static PLGraphicsIn gin; PLINT plplot_level; actStream->glevel(plplot_level); // when level < 2, we have to read if ![x|y].crange exist // if not, we have to build a [0,1]/[0,1] window if (plplot_level < 2) { actStream->NextPlot(); actStream->vpor(0, 1, 0, 1); actStream->wind(0, 1, 0, 1); } // mimic idl logic: DLong wait = WAIT; if (nParam == 3) { e->AssureLongScalarPar(2, wait); } static int NOWAITIx = e->KeywordIx("NOWAIT"); static int CHANGEIx = e->KeywordIx("CHANGE"); static int WAITIx = e->KeywordIx("WAIT"); static int DOWNIx = e->KeywordIx("DOWN"); static int UPIx = e->KeywordIx("UP"); static int DEVICEIx = e->KeywordIx("DEVICE"); static int NORMALIx = e->KeywordIx("NORMAL"); if (e->KeywordSet(NOWAITIx)) wait=NOWAIT; if (e->KeywordSet(CHANGEIx)) wait=CHANGE; if (e->KeywordSet(WAITIx)) wait=WAIT; if (e->KeywordSet(DOWNIx)) wait=DOWN; if (e->KeywordSet(UPIx)) wait=UP; if(actStream->GetGin(&gin, wait)==false) return; // outside window report -1 -1 at least for DEVICE values if (gin.pX < 0 || gin.pX > actStream->xPageSize() || gin.pY < 0 || gin.pY > actStream->yPageSize()) { gin.pX = -1; gin.pY = -1; } if (e->KeywordSet(DEVICEIx)) { DLongGDL* xLong; DLongGDL* yLong; xLong = new DLongGDL(gin.pX); yLong = new DLongGDL(gin.pY); e->SetPar(0, xLong); e->SetPar(1, yLong); } else { DDoubleGDL* x; DDoubleGDL* y; if (e->KeywordSet(NORMALIx)) { x = new DDoubleGDL(gin.dX); y = new DDoubleGDL(gin.dY); } else { // default (/data) DDouble tempx,tempy; #ifdef USE_LIBPROJ4 bool mapSet = false; get_mapset(mapSet); if (!mapSet) { #endif actStream->NormToWorld((DDouble)gin.dX, (DDouble)gin.dY, tempx, tempy); #ifdef USE_LIBPROJ4 } else { ref = map_init(); if (ref == NULL) e->Throw("Projection initialization failed."); XYTYPE idata, idataN; idataN.u = gin.dX; idataN.v = gin.dY; DDouble *sx, *sy; // norm to world invalid since projection. use !x.s and !y.s directly // was: actStream->NormToWorld(idataN.u, idataN.v, idata.u, idata.v); GetSFromPlotStructs( &sx, &sy ); idata.u = (idataN.u - sx[0])/sx[1]; idata.v = (idataN.v - sy[0])/sy[1]; LPTYPE odata = PJ_INV(idata, ref); tempx = odata.u * RAD_TO_DEG; tempy = odata.v * RAD_TO_DEG; } #endif bool xLog, yLog; gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); if(xLog) tempx=pow(10,tempx); if(yLog) tempy=pow(10,tempy); x = new DDoubleGDL(tempx); y = new DDoubleGDL(tempy); } e->SetPar(0, x); e->SetPar(1, y); } // we update the !Mouse structure (4 fields, only 3 managed up to now) // found on the web: //"Information about which mouse button has been used (if) any is stored in the !err variable. A value of 1 corresponds to the left, 2 to middle and 4 to the right button." //!err is obsolete but still working: DStructGDL* Struct = SysVar::Mouse(); if (Struct != NULL) { static unsigned xMouseTag = Struct->Desc()->TagIndex("X"); (*static_cast(Struct->GetTag(xMouseTag)))[0] = gin.pX; static unsigned yMouseTag = Struct->Desc()->TagIndex("Y"); (*static_cast(Struct->GetTag(yMouseTag)))[0] = gin.pY; static unsigned ButtonMouseTag = Struct->Desc()->TagIndex("BUTTON"); if (gin.button == 5) gin.button = 16; // today we have 5 buttons mouses! if (gin.button == 4) gin.button = 8; // but we keep the previous logic: if (gin.button == 3) gin.button = 4; // in powers of 2 (0,1,2,4..) (*static_cast(Struct->GetTag(ButtonMouseTag)))[0] = gin.button; } DVar *err=FindInVarList(sysVarList, "ERR"); (static_cast(err->Data()))[0]= gin.button; } } // namespace gdl-0.9.9/src/plotting_device.cpp000066400000000000000000000436151340051421000167500ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #include // GSL_CONST_MKSA_INCH namespace lib { using namespace std; void device( EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); //GET functions are examined BEFORE setting functions. // GET_DECOMPOSED ? { static int get_decomposedIx = e->KeywordIx( "GET_DECOMPOSED" ); if ( e->KeywordPresent( get_decomposedIx ) ) { DLong value = actDevice->GetDecomposed( ); if ( value == -1 ) e->Throw( "Keyword GET_DECOMPOSED not allowed for call to: DEVICE" ); else e->SetKW( get_decomposedIx, new DLongGDL( value ) ); } } //The font-related commands will not really work in graphic widgets unitil the plplot-related part is taken into account (PLESC font). //But all the elements are there. //SET_FONT? //must be before GET_FONTNAME if in same commandline. { static int set_fontIx = e->KeywordIx( "SET_FONT" ); if ( e->KeywordPresent( set_fontIx ) ) { DStringGDL* pattern = e->GetKWAs( set_fontIx); if (!actDevice->SetFont((*pattern)[0])) e->Throw( "Keyword SET_FONT not allowed for call to: DEVICE" ) ; } } //GET_FONTNAMES? { static int get_fontnamesIx = e->KeywordIx( "GET_FONTNAMES" ); if ( e->KeywordPresent( get_fontnamesIx ) ) { BaseGDL* value = actDevice->GetFontnames( ); if ( value != NULL ) e->SetKW( get_fontnamesIx, value->Dup() ); //Throw error elsewhere. } } //GET_FONTNUM? { static int get_fontnumIx = e->KeywordIx( "GET_FONTNUM" ); if ( e->KeywordPresent( get_fontnumIx ) ) { DLong value = actDevice->GetFontnum( ); if ( value >= 0 ) e->SetKW( get_fontnumIx, new DLongGDL( value) ); //Throw error elsewhere. } } //GET_CURRENT_FONT? { static int get_current_fontIx = e->KeywordIx( "GET_CURRENT_FONT" ); if ( e->KeywordPresent( get_current_fontIx ) ) { DString value = actDevice->GetCurrentFont( ); //should NOT open graphic window e->SetKW( get_current_fontIx, new DStringGDL( value) ); } } //GET_FONTNUM? //TODO // GET_GRAPHICS_FUNCTION { static int get_graphics_FunctionIx = e->KeywordIx( "GET_GRAPHICS_FUNCTION"); if( e->KeywordPresent( get_graphics_FunctionIx)) { DLong value = actDevice->GetGraphicsFunction(); //OPENS A WINDOW IF NONE EXIST if(value == -1) e->Throw( "Keyword GET_GRAPHICS_FUNCTION not allowed for call to: DEVICE"); else e->SetKW( get_graphics_FunctionIx, new DLongGDL( value)); } } // GET_PAGE_SIZE ? { static int get_page_sizeIx = e->KeywordIx("GET_PAGE_SIZE"); if( e->KeywordPresent( get_page_sizeIx)) { DIntGDL* value = actDevice->GetPageSize(); if (value == NULL) e->Throw( "Keyword GET_PAGE_SIZE not allowed for call to: DEVICE"); else e->SetKW( get_page_sizeIx, value ); } } // GET_PIXEL_DEPTH ? { static int get_pixel_depthIx = e->KeywordIx( "GET_PIXEL_DEPTH"); if( e->KeywordPresent( get_pixel_depthIx)) { DLong value = actDevice->GetPixelDepth(); if(value == -1) e->Throw( "Keyword GET_PIXEL_DEPTH not allowed for call to: DEVICE"); else e->SetKW( get_pixel_depthIx, new DLongGDL( value )); } } // GET_SCREEN_SIZE { static int get_screen_sizeIx = e->KeywordIx("GET_SCREEN_SIZE"); if( e->KeywordPresent( get_screen_sizeIx)) { DLongGDL* fvalue=actDevice->GetScreenSize(); if (fvalue == NULL) e->Throw( "Keyword GET_SCREEN_SIZE not allowed for call to: DEVICE"); else { (*fvalue)[0]=floor((*fvalue)[0]); (*fvalue)[1]=floor((*fvalue)[1]); e->SetKW( get_screen_sizeIx, fvalue); } } } // GET_VISUAL_DEPTH ? { static int get_visual_depthIx = e->KeywordIx( "GET_VISUAL_DEPTH"); if( e->KeywordPresent( get_visual_depthIx)) { DLong value = actDevice->GetVisualDepth(); if(value == -1) e->Throw( "Keyword GET_VISUAL_DEPTH not allowed for call to: DEVICE"); else e->SetKW( get_visual_depthIx, new DLongGDL( value)); } } // GET_VISUAL_NAME ? { static int get_visual_nameIx = e->KeywordIx( "GET_VISUAL_NAME"); if( e->KeywordPresent( get_visual_nameIx)) { DString value = actDevice->GetVisualName(); if(value == "") e->Throw( "Keyword GET_VISUAL_NAME not allowed for call to: DEVICE"); else e->SetKW( get_visual_nameIx, new DStringGDL( value)); } } // GET_WINDOW_POSITION ? { static int get_window_positionIx = e->KeywordIx("GET_WINDOW_POSITION"); if( e->KeywordPresent( get_window_positionIx)) { DIntGDL* value = actDevice->GetWindowPosition(); //OPENS A WINDOW IF NONE EXISTS if (value == NULL) e->Throw( "Keyword GET_WINDOW_POSITION not allowed for call to: DEVICE"); else e->SetKW( get_window_positionIx, value); } } // GET_WRITE_MASK ? { static int get_write_maskIx = e->KeywordIx( "GET_WRITE_MASK"); if( e->KeywordPresent( get_write_maskIx)) { DLong value = actDevice->GetWriteMask(); if(value == -1) e->Throw( "Keyword GET_WRITE_MASK not allowed for call to: DEVICE"); else e->SetKW( get_write_maskIx, new DLongGDL( value)); } } // WINDOW_STATE ? { static int window_stateIx = e->KeywordIx( "WINDOW_STATE"); if( e->KeywordPresent( window_stateIx)) { DByteGDL* value = actDevice->WindowState(); if(value == NULL) e->Throw( "Keyword WINDOW_STATE not allowed for call to: DEVICE"); else e->SetKW( window_stateIx, value); } } // CLOSE_FILE {{{ { static int closeFileIx = e->KeywordIx( "CLOSE_FILE"); if( e->KeywordSet( closeFileIx)) { bool success = actDevice->CloseFile(); if( !success) e->Throw( "Current device does not support keyword CLOSE_FILE."); } } // Z_BUFFERING { static int z_bufferingIx = e->KeywordIx( "Z_BUFFERING"); BaseGDL* z_buffering = e->GetKW( z_bufferingIx); if( z_buffering != NULL) { bool success = actDevice->ZBuffering( e->KeywordSet( z_bufferingIx)); if( !success) e->Throw( "Current device does not support keyword Z_BUFFERING."); } } // SET_RESOLUTION { static int set_resolutionIx = e->KeywordIx( "SET_RESOLUTION"); BaseGDL* set_resolution = e->GetKW( set_resolutionIx); if( set_resolution != NULL) { DLongGDL* resolution = e->GetKWAs( set_resolutionIx); if( resolution->N_Elements() != 2) e->Throw( "Keyword array parameter SET_RESOLUTION must have 2 elements."); DLong x = (*resolution)[0]; DLong y = (*resolution)[1]; if( x<0 || y<0) e->Throw( "Value of Resolution is out of allowed range."); bool success = actDevice->SetResolution( x, y); if( !success) e->Throw( "Current device does not support keyword SET_RESOLUTION."); } } // SET_CHARACTER_SIZE { static int set_character_sizeIx = e->KeywordIx( "SET_CHARACTER_SIZE"); BaseGDL* set_character_size = e->GetKW( set_character_sizeIx); if( set_character_size != NULL) { DLongGDL* character_size = e->GetKWAs( set_character_sizeIx); if( character_size->N_Elements() != 2) e->Throw( "Keyword array parameter SET_CHARACTER_SIZE must have 2 elements."); DLong x = (*character_size)[0]; DLong y = (*character_size)[1]; if( x<0 || y<0) e->Throw( "Value of Character Size is out of allowed range."); bool success = actDevice->SetCharacterSize( x, y); if( !success) e->Throw( "Current device does not support keyword SET_CHARACTER_SIZE."); } } // DECOMPOSED { static int decomposedIx = e->KeywordIx( "DECOMPOSED"); BaseGDL* decomposed = e->GetKW( decomposedIx); if( decomposed != NULL) { bool success = actDevice->Decomposed( e->KeywordSet( decomposedIx)); if( !success) e->Throw( "Current device does not support keyword DECOMPOSED."); } } // SET_GRAPHICS_FUNCTION { static int set_graphicsFunctionIx = e->KeywordIx( "SET_GRAPHICS_FUNCTION"); BaseGDL* set_gfunction = e->GetKW( set_graphicsFunctionIx); if( set_gfunction != NULL) { DLongGDL* gfunction = e->GetKWAs( set_graphicsFunctionIx); bool success = actDevice->SetGraphicsFunction((*gfunction)[0]); if( !success) e->Throw( "Current device does not support keyword SET_GRAPHICS_FUNCTION."); } } // CURSOR_STANDARD { static int cursorStandardIx = e->KeywordIx( "CURSOR_STANDARD"); BaseGDL* res = e->GetKW( cursorStandardIx); if( res != NULL) { DLongGDL* val = e->GetKWAs( cursorStandardIx); bool success = actDevice->CursorStandard((*val)[0]); if( !success) e->Throw( "Current device does not support keyword CURSOR_STANDARD."); } } // RETAIN { static int valIx = e->KeywordIx( "RETAIN"); BaseGDL* res = e->GetKW( valIx); if( res != NULL) { DLongGDL* val = e->GetKWAs( valIx); bool success = actDevice->SetBackingStore((*val)[0]); if( !success) e->Throw( "Current device does not support keyword RETAIN."); } } // CURSOR_CROSSHAIR { static int valIx = e->KeywordIx( "CURSOR_CROSSHAIR"); BaseGDL* res = e->GetKW( valIx); if( res != NULL) { bool success = actDevice->CursorCrosshair(); if( !success) e->Throw( "Current device does not support keyword CURSOR_CROSSHAIR."); } } // CURSOR_ORIGINAL (WARNING: SAME CODE AS CURSOR_CROSSHAIR!) { static int valIx = e->KeywordIx( "CURSOR_ORIGINAL"); BaseGDL* res = e->GetKW( valIx); if( res != NULL) { bool success = actDevice->CursorCrosshair(); if( !success) e->Throw( "Current device does not support keyword CURSOR_ORIGINAL."); } } // FILENAME { static int fileNameIx = e->KeywordIx( "FILENAME"); BaseGDL* fileName = e->GetKW( fileNameIx); if( fileName != NULL) { DString fName; e->AssureStringScalarKW( fileNameIx, fName); if( fName == "") e->Throw( "Null filename not allowed."); WordExp(fName); bool success = actDevice->SetFileName( fName); if( !success) e->Throw( "Current device does not support keyword FILENAME."); } } // LANDSCAPE and PORTRAIT need to be executed before XSIZE, YSIZE, XOFFSET and YOFFSET! { static int portraitIx = e->KeywordIx( "PORTRAIT"); static int landscapeIx = e->KeywordIx( "LANDSCAPE"); //IDL consider the value of the first typed of the two options, if both are present. //I dunoo how to do that with GDL parsing. if (e->KeywordSet(portraitIx) && e->KeywordSet(landscapeIx)) Warning("Warning: both PORTRAIT and LANDSCAPE specified!"); // LANDSCAPE { BaseGDL* landscapeKW=e->GetKW(landscapeIx); if (landscapeKW != NULL) { DLong isLandscape; e->AssureLongScalarKW( landscapeIx, isLandscape); if (isLandscape == 0) { bool success = actDevice->SetPortrait(); if (!success) e->Throw("Current device does not support keyword LANDSCAPE"); } else { bool success = actDevice->SetLandscape(); if (!success) e->Throw("Current device does not support keyword LANDSCAPE"); } } } // PORTRAIT { BaseGDL* portraitKW=e->GetKW(portraitIx); if (portraitKW != NULL) { DLong isPortrait; e->AssureLongScalarKW( portraitIx, isPortrait); if (isPortrait == 0) { bool success = actDevice->SetLandscape(); if (!success) e->Throw("Current device does not support keyword PORTRAIT"); } else { bool success = actDevice->SetPortrait(); if (!success) e->Throw("Current device does not support keyword PORTRAIT"); } } } } { static int inchesIx = e->KeywordIx( "INCHES"); // XOFFSET { static int xOffsetIx = e->KeywordIx( "XOFFSET"); BaseGDL* xOffsetKW = e->GetKW( xOffsetIx); if( xOffsetKW != NULL) { DFloat xOffsetValue; e->AssureFloatScalarKW( xOffsetIx, xOffsetValue); bool success = actDevice->SetXOffset( xOffsetValue * (e->KeywordSet(inchesIx) ? 100. * GSL_CONST_MKSA_INCH : 1.) ); if( !success) e->Throw( "Current device does not support keyword XOFFSET."); } } // YOFFSET { static int yOffsetIx = e->KeywordIx( "YOFFSET"); BaseGDL* yOffsetKW = e->GetKW( yOffsetIx); if( yOffsetKW != NULL) { DFloat yOffsetValue; e->AssureFloatScalarKW( yOffsetIx, yOffsetValue); bool success = actDevice->SetYOffset( yOffsetValue * (e->KeywordSet(inchesIx) ? 100. * GSL_CONST_MKSA_INCH : 1.) ); if( !success) e->Throw( "Current device does not support keyword YOFFSET."); } } // XSIZE { static int xSizeIx = e->KeywordIx( "XSIZE"); BaseGDL* xSizeKW = e->GetKW( xSizeIx); if( xSizeKW != NULL) { DFloat xSizeValue; e->AssureFloatScalarKW( xSizeIx, xSizeValue); bool success = actDevice->SetXPageSize( xSizeValue * (e->KeywordSet(inchesIx) ? 100. * GSL_CONST_MKSA_INCH : 1.) ); if( !success) e->Throw( "Current device does not support keyword XSIZE."); } } // YSIZE { static int ySizeIx = e->KeywordIx( "YSIZE"); BaseGDL* ySizeKW = e->GetKW( ySizeIx); if( ySizeKW != NULL) { DFloat ySizeValue; e->AssureFloatScalarKW( ySizeIx, ySizeValue); bool success = actDevice->SetYPageSize( ySizeValue * (e->KeywordSet(inchesIx) ? 100. * GSL_CONST_MKSA_INCH : 1.) ); if( !success) e->Throw( "Current device does not support keyword YSIZE."); } } } // SCALE_FACTOR { static int scaleIx = e->KeywordIx( "SCALE_FACTOR"); BaseGDL* scaleKW = e->GetKW( scaleIx); if( scaleKW != NULL) { DFloat scaleValue; e->AssureFloatScalarKW( scaleIx, scaleValue); bool success = actDevice->SetScale( scaleValue); if( !success) e->Throw( "Current device does not support keyword SCALE."); } } // COLOR { // TODO: turn off with COLOR=0? static int colorIx = e->KeywordIx( "COLOR"); BaseGDL* colorKW = e->GetKW( colorIx); if( colorKW != NULL) { DLong colorValue; e->AssureLongScalarKW( colorIx, colorValue); bool success = actDevice->SetColor(colorValue); if( !success) e->Throw( "Current device does not support keyword COLOR."); } } // ENCAPSULATED { static int encapsulatedIx = e->KeywordIx( "ENCAPSULATED"); BaseGDL* encapsulatedKW = e->GetKW( encapsulatedIx); if( encapsulatedKW != NULL) { bool success; if ((*e->GetKWAs(encapsulatedIx))[0] == 0) success = actDevice->SetEncapsulated(false); else success = actDevice->SetEncapsulated(true); if (!success) e->Throw( "Current device does not support keyword ENCAPSULATED."); } } //BITS_PER_PIXEL { static int bppIx = e->KeywordIx( "BITS_PER_PIXEL"); BaseGDL* bppKW = e->GetKW( bppIx); if( bppKW != NULL) { bool success; success = actDevice->SetBPP((*e->GetKWAs(bppIx))[0]); if (!success) e->Throw( "Current device does not support keyword BITS_PER_PIXEL."); } } // COPY { static int copyIx = e->KeywordIx("COPY"); if( e->KeywordPresent( copyIx)) { DLongGDL* parameters=e->GetKWAs(copyIx); if (parameters->N_Elements() > 7 || parameters->N_Elements() < 6) e->Throw("Keyword array parameter COPY must have from 6 to 7 elements."); // WRONG!! device number may also be a gui number in some cases... HAVING TWO X11-like GRAPHIC DEVICES IS NOT GOOD AT ALL! FIXME! if (parameters->N_Elements() == 7) { if (!actDevice->WState((*parameters)[6])) e->Throw("Window number "+i2s((*parameters)[6])+" out of range or no more windows or known bug with widgets"); } bool doesTheCopy=actDevice->CopyRegion(parameters); if (!doesTheCopy) e->Throw( "Keyword COPY not allowed for call to: DEVICE"); } } // SET_PIXEL_DEPTH ? { static int set_pixel_depthIx = e->KeywordIx( "SET_PIXEL_DEPTH"); if( e->KeywordPresent( set_pixel_depthIx)) { BaseGDL* depthKW = e->GetKW(set_pixel_depthIx); if( depthKW != NULL) { bool success = actDevice->SetPixelDepth((*e->GetKWAs(set_pixel_depthIx))[0]); if(!success) e->Throw( "Keyword SET_PIXEL_DEPTH not allowed for call to: DEVICE"); } } } } } // namespace gdl-0.9.9/src/plotting_erase.cpp000066400000000000000000000064171340051421000166070ustar00rootroot00000000000000/*************************************************************************** plotting_erase.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; class erase_call : public plotting_routine_call { private: bool handle_args(EnvT* e) // {{{ { if (nParam() > 1) e->Throw( "Incorrect number of arguments."); return false; } // }}} void old_body( EnvT* e, GDLGStream* actStream) // {{{ { } // }}} private: void call_plplot(EnvT* e, GDLGStream* actStream) // {{{ { DLong chan = 0; static int chanIx = e->KeywordIx( "CHANNEL" ); if ( e->KeywordPresent( chanIx ) ) { e->AssureLongScalarKWIfPresent( chanIx, chan ); if ( (chan > 3) || (chan < 0) ) e->Throw( "Value of Channel is out of allowed range." ); } else { //get !P.CHANNEL value DStructGDL* pStruct = SysVar::P( ); //MUST NOT BE STATIC, due to .reset chan = (*static_cast (pStruct->GetTag( pStruct->Desc( )->TagIndex( "CHANNEL" ), 0 )))[0]; } DStructGDL* dStruct = SysVar::D( ); //MUST NOT BE STATIC, due to .reset DLong MaxColorIdx; MaxColorIdx = (*static_cast (dStruct->GetTag( dStruct->Desc( )->TagIndex( "N_COLORS" ), 0 )))[0]; DLong bColor = -1; static int bColorIx = e->KeywordIx( "COLOR" ); if ( nParam( ) == 0 ) { if ( e->KeywordPresent( bColorIx ) ) { e->AssureLongScalarKWIfPresent( bColorIx, bColor ); } else // we have to read back !p.background value { DStructGDL* pStruct = SysVar::P( ); //MUST NOT BE STATIC, due to .reset bColor = (*static_cast (pStruct->GetTag( pStruct->Desc( )->TagIndex( "BACKGROUND" ), 0 )))[0]; } } else { e->AssureLongScalarPar( 0, bColor ); } if ( bColor > MaxColorIdx ) bColor = MaxColorIdx; if ( bColor < 0 ) bColor = 0; DLong decomposed = GraphicsDevice::GetDevice( )->GetDecomposed( ); actStream->Background( bColor, decomposed ); if ( chan > 0 ) actStream->Clear( chan - 1 ); else actStream->Clear( ); } private: virtual void post_call(EnvT*, GDLGStream*) // {{{ { } // }}} }; void erase(EnvT* e) { erase_call erase; erase.call(e, 0); } } // namespace gdl-0.9.9/src/plotting_image.cpp000066400000000000000000000331411340051421000165640ustar00rootroot00000000000000/*************************************************************************** plotting_image.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #include "math_utl.hpp" namespace lib { using namespace std; class tv_image_call : public plotting_routine_call { private: BaseGDL* image; DLong trueColor; DByteGDL* byteImage; Guard byteImageGuard; DLong imageWidth, imageHeight; DLong xSize, ySize; DLong botLeftPixelX, botLeftPixelY; DLong channel; SizeT rank; bool handle_args(EnvT* e) { trueColor = 0; static int TRUEIx=e->KeywordIx("TRUE"); static int ORDERIx=e->KeywordIx("ORDER"); static int CHANNELIx=e->KeywordIx("CHANNEL"); image = e->GetParDefined(0); rank = image->Rank(); e->AssureLongScalarKWIfPresent(TRUEIx, trueColor); if (rank < 1 || rank > 3) e->Throw("Image array must have rank 1, 2 or 3"); if (rank <= 2 && trueColor != 0) e->Throw("Array must have 3 dimensions: " + e->GetParString(0)); if (trueColor < 0 || trueColor > 3) e->Throw("Value of TRUE keyword is out of allowed range."); // to be changed if (trueColor == 1 && xwd->depth < 24) e->Throw("Device depth must be 24 or greater for trueColor color display"); DLong orderVal = SysVar::TV_ORDER(); e->AssureLongScalarKWIfPresent(ORDERIx, orderVal); channel = 0; if (e->NParam(0) == 4) e->AssureLongScalarPar(3, channel); e->AssureLongScalarKWIfPresent(CHANNELIx, channel); if (channel < 0 || channel > 3) e->Throw("Value of Channel is out of allowed range."); if (rank == 1) { byteImage = static_cast (image->Convert2(GDL_BYTE, BaseGDL::COPY)); byteImageGuard.Init(byteImage); if (orderVal != 0) { byteImage->Reverse(0); } imageWidth = byteImage->Dim(0); imageHeight = 1; } else if (rank == 2) { byteImage = static_cast (image->Convert2(GDL_BYTE, BaseGDL::COPY)); byteImageGuard.Init(byteImage); if (orderVal != 0) { byteImage->Reverse(1); } imageWidth = byteImage->Dim(0); imageHeight = byteImage->Dim(1); } else if (rank == 3) { if (trueColor == 1) { byteImage = static_cast (image->Convert2(GDL_BYTE, BaseGDL::COPY)); byteImageGuard.Init(byteImage); if (byteImage->Dim(0) < 3) e->Throw("Array Dim(0)) + "," + i2s(byteImage->Dim(1)) + "," + i2s(byteImage->Dim(2)) + "]> does not have enough elements."); if (orderVal != 0) { byteImage->Reverse(2); } imageWidth = byteImage->Dim(1); imageHeight = byteImage->Dim(2); } if (trueColor == 2) { byteImage = static_cast (image->Convert2(GDL_BYTE, BaseGDL::COPY)); byteImageGuard.Init(byteImage); if (byteImage->Dim(1) < 3) e->Throw("Array Dim(0)) + "," + i2s(byteImage->Dim(1)) + "," + i2s(byteImage->Dim(2)) + "]> does not have enough elements."); if (orderVal != 0) { byteImage->Reverse(2); } imageWidth = byteImage->Dim(0); imageHeight = byteImage->Dim(2); } if (trueColor == 3) { byteImage = static_cast (image->Convert2(GDL_BYTE, BaseGDL::COPY)); byteImageGuard.Init(byteImage); if (byteImage->Dim(2) < 3) e->Throw("Array Dim(0)) + "," + i2s(byteImage->Dim(1)) + "," + i2s(byteImage->Dim(2)) + "]> does not have enough elements."); if (orderVal != 0) { byteImage->Reverse(1); } imageWidth = byteImage->Dim(0); imageHeight = byteImage->Dim(1); } if (trueColor == 0) { // here we have a rank =3 which is indeed a disguised rank 2 if (image->Dim(0) == 1) { imageWidth = image->Dim(1); imageHeight = image->Dim(2); } else if (image->Dim(1) == 1) { imageWidth = image->Dim(0); imageHeight = image->Dim(2); } else if (image->Dim(2) == 1) { imageWidth = image->Dim(0); imageHeight = image->Dim(1); } else { //passed a tricolor image whithout saying it! imageWidth = image->Dim(0); imageHeight = image->Dim(1); if (imageWidth == 3 ) {imageWidth=1;} else { if (imageHeight == 3 ) imageHeight = 1;} //rather horrible patch } byteImage = static_cast (image->Convert2(GDL_BYTE, BaseGDL::COPY)); byteImageGuard.Init(byteImage); SizeT newdims[2]; newdims[0] = imageWidth; newdims[1] = imageHeight; dimension dim(newdims, 2); (static_cast(byteImage))->SetDim(dim); rank=2; if (orderVal != 0) { byteImage->Reverse(1); } } } return false; } private: void old_body(EnvT* e, GDLGStream * actStream) { enum { DATA = 0, NORMAL, DEVICE, NONE } coordinateSystem = NONE; static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); static int INCHES=e->KeywordIx("INCHES"); static int XSIZE=e->KeywordIx("XSIZE"); static int YSIZE=e->KeywordIx("YSIZE"); static int CENTIMETERS=e->KeywordIx("CENTIMETERS"); //check presence of DATA,DEVICE and NORMAL options if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; bool mapSet = false; #ifdef USE_LIBPROJ4 // Map Stuff (xtype = 3) get_mapset(mapSet); if (mapSet) { ref = map_init(); if (ref == NULL) { e->Throw("Projection initialization failed."); } } #endif SizeT nParam = e->NParam(1); DLong xPageSize = actStream->xPageSize(); DLong yPageSize = actStream->yPageSize(); DLong positionOnPage = 0; botLeftPixelX = 0; botLeftPixelY = 0; //DEVICE HAS FIXED PIXELS? bool fixedPixelSize = (((*static_cast (SysVar::D()->GetTag(SysVar::D()->Desc()->TagIndex("FLAGS"), 0)))[0] & 1) == 0); //image size. In DEV, CM or INCHES PLFLT devx, devy, x ,y; devx = 0; devy = 0; bool xSizeGiven, ySizeGiven; double aspect=static_cast(imageWidth)/static_cast(imageHeight); xSizeGiven=e->KeywordPresent(XSIZE); if (xSizeGiven) e->AssureDoubleScalarKWIfPresent(XSIZE, devx); ySizeGiven=e->KeywordPresent(YSIZE); if (ySizeGiven) e->AssureDoubleScalarKWIfPresent(YSIZE, devy); //interpret size: if (xSizeGiven || ySizeGiven) { PLFLT x1,y1, x2 ,y2; if (coordinateSystem == DATA) { actStream->world2device(0, 0, x1,y1); actStream->world2device(devx, devy, x2,y2); devx=x2-x1; devy=y2-y1; } else if (coordinateSystem == NORMAL) { actStream->NormedDeviceToDevice(0, 0, x1,y1); actStream->NormedDeviceToDevice(devx, devy, x2,y2); devx=(x2-x1); devy=(y2-y1); } else if (coordinateSystem == DEVICE) { } else { if (e->KeywordSet(INCHES)) { devx *= (10 * 2.54); devy *= (10 * 2.54); actStream->mm2device(devx, devy, x,y); devx=x; devy=y; } else if (e->KeywordSet(CENTIMETERS)) { devx *= (10.); devy *= (10.); actStream->mm2device(devx, devy, x,y); devx=x; devy=y; } } if (xSizeGiven && !ySizeGiven) {devy=devx/aspect; ySizeGiven=true;} if (!xSizeGiven && ySizeGiven) {devx=devy*aspect; xSizeGiven=true;} } else { double pageaspect=xPageSize/yPageSize; if (aspect>pageaspect){ devx=xPageSize*0.9; //10% margin devy=devx/aspect; } else { devy=yPageSize*0.9; //10% margin devx=devy*aspect; } } if (nParam == 2) { int nPerPageX, nPerPageY, ix, iy; e->AssureLongScalarPar(1, positionOnPage); if (!fixedPixelSize && !(xSizeGiven && ySizeGiven)) e->Throw("XSIZE and/or YSIZE needed for proper positioning."); nPerPageX = xPageSize / imageWidth; nPerPageY = yPageSize / imageHeight; // AC 2011/11/06, bug 3433502 if (nPerPageX > 0) { ix = positionOnPage % nPerPageX; } else {nPerPageX = 1; ix = 0;} if (nPerPageY > 0) { iy = (positionOnPage / nPerPageX) % nPerPageY; } else {nPerPageY=1; iy = 0;} botLeftPixelX = imageWidth*ix; botLeftPixelY = yPageSize - imageHeight * (iy + 1); } else if (nParam >= 3) { PLFLT xLLf, yLLf; e->AssureDoubleScalarPar(1, xLLf); //may be DATA or NORM or DEVICE. DEV,NORM and DATA preferred on INCH and CENTIM. INCH and CM imply DEVICE e->AssureDoubleScalarPar(2, yLLf); //idem //convert to device Pixel: if (coordinateSystem == DATA) { // actStream->WorldToDevice(xLLf, yLLf, x,y); actStream->world2device(xLLf, yLLf, x,y); botLeftPixelX=x; botLeftPixelY=y; } else if (coordinateSystem == NORMAL) { actStream->NormedDeviceToDevice(xLLf, yLLf, x,y); botLeftPixelX=x; botLeftPixelY=y; } else if (coordinateSystem == DEVICE) { botLeftPixelX = xLLf; botLeftPixelY = yLLf; } else { if (e->KeywordSet(INCHES)) { xLLf *= (10 * 2.54); yLLf *= (10 * 2.54); actStream->mm2device(xLLf, yLLf, x,y); botLeftPixelX=x; botLeftPixelY=y; } else if (e->KeywordSet(CENTIMETERS)) { xLLf *= (10.); yLLf *= (10.); actStream->mm2device(xLLf, yLLf, x,y); botLeftPixelX=x; botLeftPixelY=y; } else { botLeftPixelX = xLLf; botLeftPixelY = yLLf; } } } xSize = devx; ySize = devy; int debug=0; if (debug == 1) { std::cout << "==================== " << std::endl; std::cout << "trueColor " << trueColor < chan_guard; // actStream->flush(); if (channel == 0) { if (!actStream->PaintImage(&(*byteImage)[0], imageWidth, imageHeight, devicebox, trueColor, channel)) e->Throw("device does not support Paint"); } else if (rank == 3) { // Rank == 3 w/channel SizeT dims[2]; dims[0] = imageWidth; dims[1] = imageHeight; dimension dim(dims, 2); DByteGDL* byteImage_chan = new DByteGDL(dim, BaseGDL::ZERO); for (SizeT i = (channel - 1); i < byteImage->N_Elements(); i += 3) { (*byteImage_chan)[i / 3] = (*byteImage)[i]; } // Send just single channel if (!actStream->PaintImage(&(*byteImage_chan)[0], imageWidth, imageHeight, devicebox, trueColor, channel)) e->Throw("device does not support Paint"); chan_guard.Init(byteImage_chan); // delete upon exit } else if (rank == 2) { // Rank = 2 w/channel if (!actStream->PaintImage(&(*byteImage)[0], imageWidth, imageHeight, devicebox, trueColor, channel)) e->Throw("device does not support Paint"); } } private: void post_call(EnvT*, GDLGStream * actStream) // {{{ { // if (doT3d) { // plplot3d_guard.Reset(plplot3d); // actStream->stransform(NULL, NULL); // } } }; void tv_image(EnvT* e) { tv_image_call tv_image; tv_image.call(e, 1); } } // namespace gdl-0.9.9/src/plotting_map_proj.cpp000066400000000000000000000722721340051421000173210ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; static bool isRot; static bool noInv; static DDouble sRot,cRot; BaseGDL* map_proj_forward_fun( EnvT* e ) { #ifdef USE_LIBPROJ4 BaseGDL* p0; BaseGDL* p1; DDoubleGDL *lon; DDoubleGDL *lat; Guard lonGuard, latGuard; DLongGDL* gons=NULL; DLongGDL* lines=NULL; DLongGDL* connectivity=NULL; DDoubleGDL *res=NULL; SizeT nEl; SizeT nParam = e->NParam( ); if ( nParam < 1 || nParam > 2 ) e->Throw( "Incorrect number of arguments." ); //RADIANS static int radianIx = e->KeywordIx( "RADIANS" ); bool radians = e->KeywordSet( radianIx ); // Get MATRIX bool externalMap; DStructGDL* map = GetMapAsMapStructureKeyword(e, externalMap); ref = map_init( map ); if ( ref == NULL ) { e->Throw( "Projection initialization failed." ); } // keywords "POLYGONS", "POLYLINES" and "FILL" static int gonsIx = e->KeywordIx( "POLYGONS" ); bool doGons = e->KeywordPresent( gonsIx ); static int linesIx = e->KeywordIx( "POLYLINES" ); bool doLines = e->KeywordPresent( linesIx ); static int fillIx = e->KeywordIx( "FILL" ); bool doFill = e->KeywordSet( fillIx ); //keyword CONNECTIVITY static int connIx = e->KeywordIx( "CONNECTIVITY" ); bool doConn = e->KeywordPresent( connIx ); if ( doConn ) connectivity=e->GetKWAs(connIx); //with connectivity, polygons or polylines, and 1 argument, dimension MUST be [2,*] bool fussy=(doConn || doGons || doLines); //Get arguments if ( nParam == 1 ) { //lat is not present... p0 = e->GetParDefined( 0 ); DDoubleGDL* ll = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY )); if (fussy) { if (p0->Rank() != 2) e->Throw( "(X,Y) array must be (2,N)."); if (p0->Dim(0) != 2) e->Throw( "(X,Y) array must be (2,N)."); } nEl = p0->N_Elements( ) / 2; //as simple as that lon = new DDoubleGDL( dimension( nEl ), BaseGDL::NOZERO ); lonGuard.Reset( lon ); lat = new DDoubleGDL( dimension( nEl ), BaseGDL::NOZERO ); latGuard.Reset( lat ); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for ( OMPInt i = 0; i < nEl; ++i ) { (*lon)[i] = (*ll)[2 * i] * ((radians) ? 1.0 : DEG_TO_RAD); (*lat)[i] = (*ll)[2 * i + 1] * ((radians) ? 1.0 : DEG_TO_RAD); } } } else { //nParam==2 p0 = e->GetParDefined( 0 ); nEl = p0->N_Elements( ); p1 = e->GetParDefined( 1 ); if ( p1->N_Elements( ) != nEl ) e->Throw( "X & Y arrays must have same number of points." ); //allocate arrays DDoubleGDL *tmplon = static_cast (p0->Convert2( GDL_DOUBLE, BaseGDL::COPY )); DDoubleGDL *tmplat = static_cast (p1->Convert2( GDL_DOUBLE, BaseGDL::COPY )); lon = new DDoubleGDL( dimension( nEl ), BaseGDL::NOZERO ); lonGuard.Reset( lon ); lat = new DDoubleGDL( dimension( nEl ), BaseGDL::NOZERO ); latGuard.Reset( lat ); #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for for ( OMPInt i = 0; i < nEl; ++i ) { (*lon)[i] = (*tmplon)[i] * ((radians)? 1: DEG_TO_RAD); (*lat)[i] = (*tmplat)[i] * ((radians)? 1: DEG_TO_RAD); } } } if ( doGons || doLines ) { res=gdlProjForward(ref, map, lon,lat, connectivity, doConn, gons, doGons, lines, doLines, doFill); if ( doGons ) e->SetKW( gonsIx, gons ); else e->SetKW( linesIx, lines ); } else { //do it oursef LPTYPE idata; XYTYPE odata; DLong dims[2]; dims[0] = 2; dims[1] = nEl; dimension dim( dims, 2 ); res = new DDoubleGDL( dim, BaseGDL::NOZERO ); #ifdef PROJ_IS_THREADSAFE #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for #endif for ( OMPInt i = 0; i < nEl; ++i ) { idata.u = (*lon)[i]; idata.v = (*lat)[i]; odata = PJ_FWD( idata, ref ); (*res)[2 * i] = odata.u; (*res)[2 * i + 1] = odata.v; } } #ifdef PROJ_IS_THREADSAFE } #endif return res; #else e->Throw( "GDL was compiled without support for map projections" ); return NULL; #endif } BaseGDL* map_proj_inverse_fun(EnvT* e) { #ifdef USE_LIBPROJ4 // xy -> lonlat SizeT nParam = e->NParam(); if (nParam < 1 || nParam > 2) e->Throw("Incorrect number of arguments."); static int radianIx = e->KeywordIx("RADIANS"); bool radians=e->KeywordSet(radianIx); // Get MATRIX bool externalMap; DStructGDL* map = GetMapAsMapStructureKeyword(e, externalMap); ref = map_init( map ); if ( ref == NULL ) { e->Throw( "Projection initialization failed." ); } //protect against projections that have no inverse in proj.4 (and inverse in libproj) (silly, is'nt it?) (I guess I'll copy all //this code one day and make our own certified version! if (noInv ) e->Throw("The proj4 library version you use unfortunately defines no inverse for this projection!"); XYTYPE idata; LPTYPE odata; BaseGDL* p0; BaseGDL* p1; DDoubleGDL* x; DDoubleGDL* y; DDoubleGDL* xy; DDoubleGDL* res; DLong dims[2]; if (nParam == 1) { p0 = e->GetParDefined(0); DDoubleGDL* xy = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); dims[0] = 2; if (p0->Rank() == 2) { //[2,dim1]->N_elements=2*Dim1 dims[1] = p0->Dim(1); dimension dim((DLong *) dims, 2); res = new DDoubleGDL(dim, BaseGDL::NOZERO); } else { //[dim0] or [n,dim1,...] -> 2*N_elements idem! dims[1] = p0->N_Elements() / 2; dimension dim((DLong *) dims, 2); res = new DDoubleGDL(dim, BaseGDL::NOZERO); } SizeT nEl = p0->N_Elements() / 2; #ifdef PROJ_IS_THREADSAFE #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for #endif for (OMPInt i = 0; i < nEl; ++i) { idata.u = (*xy)[2 * i]; idata.v = (*xy)[2 * i + 1]; odata = PJ_INV(idata, ref); (*res)[2 * i] = odata.u * ((radians)?1.0:RAD_TO_DEG); (*res)[2 * i + 1] = odata.v * ((radians)?1.0:RAD_TO_DEG); } #ifdef PROJ_IS_THREADSAFE } #endif return res; } else if (nParam == 2) { p0 = e->GetParDefined(0); SizeT nEl = p0->N_Elements(); p1 = e->GetParDefined(1); if (p1->N_Elements() != nEl) e->Throw("X & Y arrays must have same number of points."); DDoubleGDL* x = static_cast (p0->Convert2(GDL_DOUBLE, BaseGDL::COPY)); DDoubleGDL* y = static_cast (p1->Convert2(GDL_DOUBLE, BaseGDL::COPY)); dims[0] = 2; dims[1] = nEl; dimension dim((DLong *) dims, 2); res = new DDoubleGDL(dim, BaseGDL::NOZERO); #ifdef PROJ_IS_THREADSAFE #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl)) { #pragma omp for #endif for (OMPInt i = 0; i < nEl; ++i) { idata.u = (*x)[i]; idata.v = (*y)[i]; odata = PJ_INV(idata, ref); (*res)[2 * i] = odata.u * ((radians)?1.0:RAD_TO_DEG); (*res)[2 * i + 1] = odata.v * ((radians)?1.0:RAD_TO_DEG); } #ifdef PROJ_IS_THREADSAFE } #endif return res; } e->Throw("More than 2 parameters not handled."); //impossible to reach! return NULL; #else e->Throw("GDL was compiled without support for map projections"); return NULL; #endif } #ifdef USE_LIBPROJ4 PROJTYPE map_init(DStructGDL * map) { //enum all the projections enum { Invalid = 0, Stereographic, Orthographic, LambertConic, LambertAzimuthal, Gnomonic, AzimuthalEquidistant, Satellite, Cylindrical, Mercator, Mollweide, Sinusoidal, Aitoff, HammerAitoff, AlbersEqualAreaConic, TransverseMercator, MillerCylindrical, Robinson, LambertEllipsoidConic, GoodesHomolosine, Geographic, GCTP_UTM, GCTP_StatePlane, GCTP_AlbersEqualArea, GCTP_LambertConformalConic, GCTP_Mercator, GCTP_PolarStereographic, GCTP_Polyconic, GCTP_EquidistantConic, GCTP_TransverseMercator, GCTP_Stereographic, GCTP_LambertAzimutha, GCTP_Azimuthal, GCTP_Gnomonic, GCTP_Orthographic, GCTP_NearSidePerspective, GCTP_Sinusoidal, GCTP_Equirectangular, GCTP_MillerCylindrical, GCTP_VanderGrinten, GCTP_HotineObliqueMercator, GCTP_Robinson, GCTP_SpaceObliqueMercator, GCTP_AlaskaConformal, GCTP_InterruptedGoode, GCTP_Mollweide, GCTP_InterruptedMollweide, GCTP_Hammer, GCTP_WagnerIV, GCTP_WagnerVII, GCTP_OblatedEqualArea, GCTP_IntegerizedSinusoidal, GCTP_CylindricalEqualArea } Projection = Stereographic; enum { //see projElement below NONE = 0, SPHE, CLON, CLAT, SPR1, SPR2, HGHT, TILT, CAZM, SMAJ, SMIN, SFAC, ZONE, FE, FN, SLAT, SPAR, LON1, LON2, AZML, SATN, PATH, SHPM, SHPN, GSSM } projElementIndex; int isAngle[]={-100,0,1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0 }; string projElement[] = { //same order that projElementIndex, please! "Null", " +R=", " +lon_0=", " +lat_0=", " +lat_1=", " +lat_2=", " +h=", " +tilt=", " +alpha=", " +a=", " +b=", " +k0=", " +zone=", " +x_0=", " +y_0=", " +lat_ts=", " +lat_0=", " +lon_1=", " +lon_2=", " +lonc=", " +lsat=", " +path=", " +m=", " +n=", " +n=4 +m="}; string obliqueProjElement[] = { //same order that projElementIndex, please! "Null", " +R=", " +o_lon_p=", " +o_lat_p=", " +lat_1=", " +lat_2=", " +h=", " +tilt=", " +alpha=", " +a=", " +b=", " +k0=", " +zone=", " +x_0=", " +y_0=", " +lat_ts=", " +lat_0=", " +lon_1=", " +lon_2=", " +lonc=", " +lsat=", " +path=", " +m=", " +n=", " +n=4 +m="}; typedef struct { int projindex; int projnum; int projtype; string projname; string proj4name; int numopts; int theCode[16]; int theVarCode[16]; } projCoding; static projCoding projectionOptions[]={ // index, proj. Number as in doc, Name, Proj.4 litle name, number of projElements to read, // Values as index in projElements (options for proj.4), idem for variant. {0 , 0 ,0,"Invalid Projection", "none", 0 , {0},{0}}, {1 , 1 ,0,"Stereographic" , "stere" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {2 , 2 ,0,"Orthographic" , "ortho" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {3 , 3 ,1,"LambertConic" , "lcc" , 6 , {SPHE , 0 , SPR1 , SPR2 , CLON , CLAT , 0},{0}} , {4 , 4 ,0,"LambertAzimuthal" , "laea" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {5 , 5 ,0,"Gnomonic" , "gnom" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {6 , 6 ,0,"AzimuthalEquidistant" , "aeqd" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {7 , 7 ,0,"Satellite" , "tpers" , 6 , {SPHE , 0 , HGHT , TILT , CLON , CLAT , 0},{0}} , {8 , 8 ,2,"Cylindrical" , "eqc" , 6 , {SPHE , 0 , 0 , CAZM , CLON , CLAT , 0},{0}} , {9 , 9 ,2,"Mercator" , "merc" , 6 , {SPHE , 0 , 0 , CAZM , CLON , CLAT , 0},{0}} , {10 , 10 ,4,"Mollweide" , "moll" , 6 , {SPHE , 0 , 0 , CAZM , CLON , CLAT , 0},{0}} , {11 , 11 ,4,"Sinusoidal" , "sinu" , 6 , {SPHE , 0 , 0 , CAZM , CLON , CLAT , 0},{0}} , {12 , 12 ,3,"Aitoff" , "aitoff" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {13 , 13 ,3,"HammerAitoff" , "hammer" , 6 , {SPHE , 0 , 0 , 0 , CLON , CLAT , 0},{0}} , {14 , 14 ,1,"AlbersEqualAreaConic" , "aea" , 6 , {SPHE , 0 , SPR1 , SPR2 , CLON , CLAT , 0},{0}} , {15 , 15 ,2,"TransverseMercator" , "tmerc" , 6 , {SMAJ , SMIN , SFAC , 0 , CLON , CLAT , 0},{0}} , {16 , 16 ,2,"MillerCylindrical" , "mill" , 6 , {SPHE , 0 , 0 , CAZM , CLON , CLAT , 0},{0}} , {17 , 17 ,4,"Robinson" , "robin" , 6 , {SPHE , 0 , 0 , CAZM , CLON , CLAT , 0},{0}} , {18 , 18 ,1,"LambertEllipsoidConic" , "lcc" , 6 , {SMAJ , SMIN , SPR1 , SPR2 , CLON , CLAT , 0},{0}} , {19 , 19 ,4,"GoodesHomolosine" , #ifdef USE_LIBPROJ4_NEW "igh" , #else "goode" , #endif 5 , {SPHE , 0 , 0 , 0 , CLON , 0 , 0},{0}} , {20 , 100 ,5,"Geographic" , "lonlat" , 0 , {SMAJ , SMIN , 0 , 0 , 0 , 0 , 0 , 0},{0}} , {21 , 101 ,5,"GCTP_UTM" , "utm" , 3 , {CLON , CLAT , ZONE , 0 , 0 , 0 , 0 , 0},{0}} , //may use "+south" {22 , 102 ,2,"GCTP_StatePlane" , "utm" , 3 , {SMAJ , SMIN , ZONE , 0 , 0 , 0 , 0 , 0},{0}} , //may use "+south" {23 , 103 ,1,"GCTP_AlbersEqualArea" , "aea" , 8 , {SMAJ , SMIN , SPR1 , SPR2 , CLON , CLAT , FE , FN},{0}} , {24 , 104 ,1,"GCTP_LambertConformalConic" , "lcc" , 8 , {SMAJ , SMIN , SPR1 , SPR2 , CLON , CLAT , FE , FN},{0}} , {25 , 105 ,2,"GCTP_Mercator" , "merc" , 8 , {SMAJ , SMIN , 0 , 0 , CLON , SLAT , FE , FN},{0}} , {26 , 106 ,0,"GCTP_PolarStereographic" , "ups" , 9 , {SMAJ , SMIN , 0 , 0 , CLON , SLAT , FE , FN , CLAT},{0}} , //may use "+south" {27 , 107 ,1,"GCTP_Polyconic" , "poly" , 8 , {SMAJ , SMIN , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {28 , 108 ,1,"GCTP_EquidistantConic" , "eqdc" , 8 , {SMAJ , SMIN , SPAR , 0 , CLON , CLAT , FE , FN , 0}, {SMAJ , SMIN , SPR1 , SPR2 , CLON , CLAT , FE , FN , 0}} , {29 , 109 ,2,"GCTP_TransverseMercator" , "tmerc" , 8 , {SMAJ , SMIN , SFAC , 0 , CLON , CLAT , FE , FN},{0}} , {30 , 110 ,0,"GCTP_Stereographic" , "stere" , 8 , {SPHE , 0 , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {31 , 111 ,0,"GCTP_LambertAzimutha" , "laea" , 8 , {SMAJ , SMIN , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {32 , 112 ,0,"GCTP_Azimuthal" , "aeqd" , 8 , {SPHE , 0 , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {33 , 113 ,0,"GCTP_Gnomonic" , "gnom" , 8 , {SPHE , 0 , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {34 , 114 ,0,"GCTP_Orthographic" , "ortho" , 8 , {SPHE , 0 , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {35 , 115 ,0,"GCTP_NearSidePerspective" , "nsper" , 8 , {SPHE , 0 , HGHT , 0 , CLON , CLAT , FE , FN},{0}} , {36 , 116 ,4,"GCTP_Sinusoidal" , "sinu" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {37 , 117 ,2,"GCTP_Equirectangular" , "eqc" , 8 , {SPHE , 0 , 0 , 0 , CLON , SLAT , FE , FN},{0}} , {38 , 118 ,2,"GCTP_MillerCylindrical" , "mill" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {39 , 119 ,3,"GCTP_VanderGrinten" , "vandg" , 8 , {SPHE , 0 , 0 , 0 , CLON , CLAT , FE , FN},{0}} , {40 , 120 ,2,"GCTP_HotineObliqueMercator" , "omerc" , 12 , {SMAJ , SMIN , SFAC , 0 , 0 , CLAT , FE , FN , LON1 , SPR1 , LON2 , SPR2 , 0},{SMAJ , SMIN , SFAC , CAZM , AZML , CLAT , FE , FN , 0 , 0 , 0 , 0 , 0}} , {41 , 121 ,4,"GCTP_Robinson" , "robin" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {42 , 122 ,2,"GCTP_SpaceObliqueMercator" , "lsat" , 12 , {SMAJ , SMIN , 0 , 0 , 0 , 0 , FE , FN , 0 , 0 , 0 , 0 , 0},{SMAJ , SMIN , SATN , PATH , 0 , 0 , FE , FN , 0 , 0 , 0 , 0 , 0}} , {43 , 123 ,0,"GCTP_AlaskaConformal" , "alsk" , 8 , {SMAJ , SMIN , 0 , 0 , 0 , 0 , FE , FN},{0}} , {44 , 124 ,4,"GCTP_InterruptedGoode" , "igh" , 8 , {SPHE , 0 , 0 , 0 , 0 , 0 , 0 , 0},{0}} , {45 , 125 ,4,"GCTP_Mollweide" , "moll" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {46 , 126 ,4,"GCTP_InterruptedMollweide" , "moll" , 8 , {SPHE , 0 , 0 , 0 , 0 , 0 , 0 , 0},{0}} , {47 , 127 ,4,"GCTP_Hammer" , "hammer" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {48 , 128 ,4,"GCTP_WagnerIV" , "wag4" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {49 , 129 ,3,"GCTP_WagnerVII" , "wag7" , 8 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN},{0}} , {50 , 130 ,3,"GCTP_OblatedEqualArea" , "oea" , 9 , {SPHE , 0 , SHPM , SHPN , CLON , CLAT , FE , FN , 0},{0}} , {51 , 131 ,9,"GCTP_IntegerizedSinusoidal" , "yet_unknown" , 11 , {SPHE , 0 , 0 , 0 , CLON , 0 , FE , FN , GSSM , 0 , 0},{0}} , {52 , 132 ,2,"GCTP_CylindricalEqualArea" , "cea" , 8 , {SMAJ , SMIN , SPAR , 0 , CLON , 0 , FE , FN},{0}} }; bool variant=false; unsigned projectionTag = map->Desc()->TagIndex("PROJECTION"); unsigned p0lonTag = map->Desc()->TagIndex("P0LON"); unsigned p0latTag = map->Desc()->TagIndex("P0LAT"); unsigned aTag = map->Desc()->TagIndex("A"); unsigned e2Tag = map->Desc()->TagIndex("E2"); unsigned pTag = map->Desc()->TagIndex("P"); unsigned rTag = map->Desc()->TagIndex("ROTATION"); unsigned simpleTag = map->Desc()->TagIndex("SIMPLE"); unsigned projNameTag = map->Desc()->TagIndex("UP_NAME"); DDouble map_rot = (*static_cast (map->GetTag(rTag, 0)))[0]; DLong map_projection = (*static_cast (map->GetTag(projectionTag, 0)))[0]; DDouble map_p0lon = (*static_cast (map->GetTag(p0lonTag, 0)))[0]; DDouble map_p0lat = (*static_cast (map->GetTag(p0latTag, 0)))[0]; DDouble map_a = (*static_cast (map->GetTag(aTag, 0)))[0]; DDouble map_e2 = (*static_cast (map->GetTag(e2Tag, 0)))[0]; DDoubleGDL* map_p = (static_cast (map->GetTag(pTag, 0))); DDouble map_lat1 = (*static_cast (map->GetTag(pTag, 0)))[3]; DDouble map_lat2 = (*static_cast (map->GetTag(pTag, 0)))[4]; DString projName = (*static_cast (map->GetTag(projNameTag, 0)))[0]; static char *parms[32];//parameters for LIBPROj.4, old style DLong nparms = 0; //GCTP support if (map_projection == 20) { map_projection = (*static_cast (map->GetTag(simpleTag, 0)))[0] + GoodesHomolosine + 1; if ((*static_cast (map->GetTag(pTag, 0)))[projectionOptions[map_projection].numopts] == 1) variant=true; //seen tag B variant } if (map_projection <1) return NULL; //protect against projections that have no inverse in proj.4 (and inverse in libproj) (silly, is'nt it?) (I guess I'll copy all //this code one day and make our own certified version! noInv=FALSE; if (map_projection == 12 || map_projection == 13 || map_projection == 47 || map_projection == 49) { noInv=TRUE; } char proj[64]; char p0lon[64]; char p0lat[64]; char a[64]; char e2[64]; char lat_1[64]; char lat_2[64]; char lat_ts[64]; char opt[64]; char h[64]; char tilt[64]; char azi[64]; // Oblique projection parameters char ob_proj[64]; char ob_lon[64]; char ob_lat[64]; DDouble proj_p0lon = 0.0; //Default DDouble proj_p0lat = 90.0; //Default static DLong last_proj = 0; static DDouble last_p0lon = -9999; static DDouble last_p0lat = -9999; static DDouble last_a = -9999; static DDouble last_e2 = -9999; static DDouble last_lat1 = -9999; static DDouble last_lat2 = -9999; static DDouble last_rot = -9999; static DDoubleGDL* last_p = new DDoubleGDL(16, BaseGDL::INDGEN); static DString last_projName = "..................."; bool trans = false; bool redo = (map_projection != last_proj || map_p0lon != last_p0lon || map_p0lat != last_p0lat || map_a != last_a || map_e2 != last_e2 || map_lat1 != last_lat1 || map_lat2 != last_lat2 || map_rot != last_rot || projName != last_projName ); for (SizeT i = 0; i < 16; ++i) if ((*static_cast (last_p))[i] != (*static_cast (map_p))[i]) redo = true; if (redo) { // fprintf(stderr, "new projection number %d\n", map_projection); //save values here, we may change them later for local convenience last_proj = map_projection; last_p0lon = map_p0lon; last_p0lat = map_p0lat; last_a = map_a; last_e2 = map_e2; last_lat1 = map_lat1; last_lat2 = map_lat2; last_rot = map_rot; last_projName = projName; for (SizeT i = 0; i < 16; ++i) (*static_cast (last_p))[i] = (*static_cast (map_p))[i]; if (map_rot != 0.0) { isRot = true; sRot=sin(map_rot*DEG_TO_RAD); cRot=cos(map_rot*DEG_TO_RAD); } else isRot=false; //Trick for using ALL the libproj.4 projections. if (map_projection == 999) { //our special code #ifdef USE_LIBPROJ4_NEW prev_ref = pj_init_plus(projName.c_str()); if (!prev_ref) {Warning("LIBPROJ.4 returned error message: "); Warning(pj_strerrno(pj_errno));} #else prev_ref = proj_initstr((char*)projName.c_str()); if (!prev_ref) {Warning("LIBPROJ.4 returned error message: "); Warning(proj_strerrno(proj_errno));} #endif return prev_ref; } if ( projectionOptions[map_projection].projtype > 1 && abs(map_p0lat)>1 ) trans=true; DDouble val; //GCTP Projections only: std::string projCommand; projCommand+=(trans?"+proj=ob_tran +o_proj=":" +proj=")+projectionOptions[map_projection].proj4name; for (int i=0; i (map_p))[i]; if (isAngle[projectionOptions[map_projection].theVarCode[i]] == 1) val *= ((map_projection > GoodesHomolosine)?1.0E-6:RAD_TO_DEG); projCommand+=trans?obliqueProjElement[projectionOptions[map_projection].theVarCode[i]]:projElement[projectionOptions[map_projection].theVarCode[i]]; projCommand+=i2s(val); } } else { if (projectionOptions[map_projection].theCode[i] != 0) { val=(*static_cast (map_p))[i]; if ( ( (map_projection==GCTP_UTM || map_projection==GCTP_StatePlane) && i==2) || (map_projection==GCTP_PolarStereographic && i==8) ) { if (val < 0) { //negative Zone is South! val *= -1.0; projCommand+=" +south"; } } if (isAngle[projectionOptions[map_projection].theCode[i]] == 1) val *= ((map_projection > GoodesHomolosine)?1.0E-6:RAD_TO_DEG); projCommand+=trans?obliqueProjElement[projectionOptions[map_projection].theCode[i]]:projElement[projectionOptions[map_projection].theCode[i]]; projCommand+=i2s(val); } } } if (map_projection > GoodesHomolosine) { //use projComand automatically defined above // cout< 89.999 ) map_p0lat = 89.999; //take some precautions as PROJ.4 is not proetected!!! if ( map_p0lat < -89.999 ) map_p0lat = -89.999; sprintf(ob_lon, "o_lon_p=%lf", proj_p0lon); proj_p0lat = 90.0 - map_p0lat; //ADD CENTRAL_AZIMUTH!! map_p0lat = 0.0; sprintf(ob_lat, "o_lat_p=%lf", proj_p0lat); } sprintf(p0lon, "lon_0=%lf", map_p0lon); sprintf(p0lat, "lat_0=%lf", map_p0lat); // if (map_e2 == 0.0) { // sprintf(a, "R=%lf", map_a); // } else { sprintf(a, "a=%lf", map_a); sprintf(e2, "es=%lf", map_e2); // } parms[nparms++] = &a[0]; if (map_e2 != 0.0) parms[nparms++] = &e2[0]; if (trans && map_projection != Satellite && map_projection != GCTP_WagnerVII //no invert in old and new libproj4. #ifdef USE_LIBPROJ4_NEW && map_projection != Mercator //crashes with map_grid!!! && map_projection != TransverseMercator //idem!! && map_projection != Orthographic //idem!! && map_projection != Aitoff //idem!! #endif ) { strcpy(ob_proj, "proj=ob_tran"); parms[nparms++] = &ob_proj[0]; sprintf(proj, "o_proj=%s", projectionOptions[map_projection].proj4name.c_str()); parms[nparms++] = &proj[0]; parms[nparms++] = &ob_lon[0]; parms[nparms++] = &ob_lat[0]; parms[nparms++] = &p0lon[0]; parms[nparms++] = &p0lat[0]; } else { sprintf(proj, "proj=%s", projectionOptions[map_projection].proj4name.c_str()); parms[nparms++] = &proj[0]; parms[nparms++] = &p0lon[0]; parms[nparms++] = &p0lat[0]; } switch (map_projection) { case Mercator: sprintf(lat_ts,"lat_ts=%lf",map_lat1 * RAD_TO_DEG); parms[nparms++] = &lat_ts[0]; break; case LambertConic: case AlbersEqualAreaConic: case LambertEllipsoidConic: if (map_lat2 == 0.0) { sprintf(lat_1, "lat_0=%lf", map_lat1 * RAD_TO_DEG); parms[nparms++] = &lat_1[0]; } else { sprintf(lat_1, "lat_1=%lf", map_lat1 * RAD_TO_DEG); sprintf(lat_2, "lat_2=%lf", map_lat2 * RAD_TO_DEG); parms[nparms++] = &lat_1[0]; parms[nparms++] = &lat_2[0]; } break; case Satellite: //Satellite looks wrong ??? check sprintf(h, "h=%lf", ((*static_cast (map_p))[0])); parms[nparms++] = &h[0]; sprintf(tilt, "tilt=%lf", RAD_TO_DEG * atan2((*static_cast (map_p))[2], (*static_cast (map_p))[3])); parms[nparms++] = &tilt[0]; // sprintf(azi, "azi=%lf", map_rot); // parms[nparms++] = &azi[0]; break; } // // fprintf(stderr, "nparms=%d:", nparms); // for (SizeT i = 0; i < nparms; ++i) fprintf(stderr, "+%s ", parms[i]); // fprintf(stderr, "\n"); #ifdef USE_LIBPROJ4_NEW prev_ref = PJ_INIT(nparms, parms); if (!prev_ref) {Warning("LIBPROJ.4 returned error message: "); Warning(pj_strerrno(pj_errno));} #else prev_ref = PJ_INIT(nparms, parms); if (!prev_ref) {Warning("LIBPROJ.4 returned error message: "); Warning(proj_strerrno(proj_errno));} #endif } return prev_ref; } #ifdef USE_LIBPROJ4_NEW PROJDATA protect_proj_fwd( PROJDATA idata, PROJTYPE proj ) { XYTYPE odata; DDouble u,v; if ( isfinite( (idata.u)*(idata.v) ) ) { odata = LIB_PJ_FWD( idata, proj ); if (isfinite(odata.u) && odata.u != HUGE_VAL){ if(isRot) { u=odata.u; v=odata.v; odata.u=u*cRot+v*sRot; odata.v=-u*sRot+v*cRot; } return odata; } } return badProj; } PROJDATA protect_proj_inv( PROJDATA idata, PROJTYPE proj ) { if (noInv ) return badProj ; // throw GDLException("The proj4 library version you use unfortunately defines no inverse for this projection!"); LPTYPE odata; DDouble u,v; if ( isfinite( (idata.u)*(idata.v) ) ) { odata = LIB_PJ_INV( idata, proj ); if (isfinite(odata.u) && odata.u != HUGE_VAL) { if(isRot) { u=odata.u; v=odata.v; odata.u=u*cRot-v*sRot; odata.v=u*sRot+v*cRot; } return odata; } } return badProj; } #else PROJDATA protect_proj_fwd (PROJDATA idata, PROJTYPE proj){ XYTYPE odata; DDouble u,v; if ( isfinite( (idata.u)*(idata.v) ) ) { odata = LIB_PJ_FWD( idata, proj ); if (isfinite(odata.u) && odata.u != HUGE_VAL){ if(isRot) { u=odata.u; v=odata.v; odata.u=u*cRot+v*sRot; odata.v=-u*sRot+v*cRot; } return odata; } } return badProj; } PROJDATA protect_proj_inv (PROJDATA idata, PROJTYPE proj){ if (noInv ) return badProj ; XYTYPE odata; DDouble u,v; if ( isfinite( (idata.u)*(idata.v) ) ) { odata = LIB_PJ_INV( idata, proj ); if (isfinite(odata.u) && odata.u != HUGE_VAL) { if(isRot) { u=odata.u; v=odata.v; odata.u=u*cRot-v*sRot; odata.v=u*sRot+v*cRot; } return odata; } } return badProj; } #endif //dummy functions for compatibility support of GCTP projections. Should define map_pipeline values. void map_proj_gctp_forinit(EnvT* e) { }; void map_proj_gctp_revinit(EnvT* e) { }; #endif } // namespace gdl-0.9.9/src/plotting_misc.cpp000066400000000000000000000207411340051421000164370ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; void set_plot(EnvT* e) // modifies !D system variable { SizeT nParam=e->NParam(); if ( nParam<1 ) e->Throw("Incorrect number of arguments."); DString device; e->AssureScalarPar(0, device); // this is the device name device=StrUpCase(device); bool success=GraphicsDevice::SetDevice(device); if ( !success ) { GraphicsDevice::ListDevice(); #ifndef _MSC_VER if (device=="X") { cout << "This system seems to be a X11 capable one where GDL was compiled without X11 lib." << endl; } #endif e->Throw("Device not supported/unknown: "+device); } DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset unsigned colorTag=pStruct->Desc()->TagIndex("COLOR"); unsigned bckTag=pStruct->Desc()->TagIndex("BACKGROUND"); if ( device=="PS" ||device=="SVG" ) { (*static_cast(pStruct->GetTag(colorTag, 0)))[0]=0; (*static_cast(pStruct->GetTag(bckTag, 0)))[0]=255; } else if ( device=="X" || device=="MAC" || device=="WIN") { (*static_cast(pStruct->GetTag(colorTag, 0)))[0]=16777215; (*static_cast(pStruct->GetTag(bckTag, 0)))[0]=0; } else { (*static_cast(pStruct->GetTag(colorTag, 0)))[0]=255; (*static_cast(pStruct->GetTag(bckTag, 0)))[0]=0; } } void tvlct( EnvT* e ) { int nParam = e->NParam( 1 ); //, "TVLCT"); static int getKW = e->KeywordIx( "GET" ); bool get = e->KeywordSet( getKW ); static int hlsKW = e->KeywordIx( "HLS" ); bool hls = e->KeywordSet( hlsKW ); static int hsvKW = e->KeywordIx( "HSV" ); bool hsv = e->KeywordSet( hsvKW ); DLong start = 0; GDLCT* actCT = GraphicsDevice::GetCT( ); if ( nParam <= 2 ) // TVLCT,I[,Start] { if ( nParam == 2 ) e->AssureLongScalarPar( 1, start ); if ( start < 0 ) start = 0; if ( get ) // always RGB { BaseGDL*& p0 = e->GetParGlobal( 0 ); SizeT nCol = ctSize - start; DByteGDL* rgb = new DByteGDL( dimension( nCol, 3 ), BaseGDL::NOZERO ); for ( SizeT i = start, ii = 0; i < ctSize; ++i, ++ii ) actCT->Get( i, (*rgb)[ ii], (*rgb)[ ii + nCol], (*rgb)[ ii + 2 * nCol] ); GDLDelete( p0 ); p0 = rgb; } else { if ( hls || hsv ) { DFloatGDL* rgb = e->GetParAs< DFloatGDL>(0); if ( rgb->Dim( 1 ) != 3 ) e->Throw( "Array must have dimensions of (1, 3): " + e->GetParString( 0 ) ); SizeT nCol = rgb->Dim( 0 ); SizeT setCol = nCol + start; if ( setCol > ctSize ) setCol = ctSize; if ( hls ) for ( SizeT i = start, ii = 0; i < setCol; ++i, ++ii ) actCT->SetHLS( i, (*rgb)[ ii], (*rgb)[ ii + nCol], (*rgb)[ ii + 2 * nCol] ); else for ( SizeT i = start, ii = 0; i < setCol; ++i, ++ii ) actCT->SetHSV( i, (*rgb)[ ii], (*rgb)[ ii + nCol], (*rgb)[ ii + 2 * nCol] ); } else { DByteGDL* rgb = e->GetParAs< DByteGDL>(0); if ( rgb->Dim( 1 ) != 3 ) e->Throw( "Array must have dimensions of (1, 3): " + e->GetParString( 0 ) ); SizeT nCol = rgb->Dim( 0 ); SizeT setCol = nCol + start; if ( setCol > ctSize ) setCol = ctSize; for ( SizeT i = start, ii = 0; i < setCol; ++i, ++ii ) actCT->Set( i, (*rgb)[ ii], (*rgb)[ ii + nCol], (*rgb)[ ii + 2 * nCol] ); } } } else // TVLCT,I1,I2,I3[,Start] { if ( nParam == 4 ) e->AssureLongScalarPar( 3, start ); if ( start < 0 ) start = 0; if ( get ) // always RGB { BaseGDL*& p0 = e->GetParGlobal( 0 ); BaseGDL*& p1 = e->GetParGlobal( 1 ); BaseGDL*& p2 = e->GetParGlobal( 2 ); SizeT nCol = ctSize - start; DByteGDL* r = new DByteGDL( dimension( nCol ), BaseGDL::NOZERO ); DByteGDL* g = new DByteGDL( dimension( nCol ), BaseGDL::NOZERO ); DByteGDL* b = new DByteGDL( dimension( nCol ), BaseGDL::NOZERO ); for ( SizeT i = start, ii = 0; i < ctSize; ++i, ++ii ) actCT->Get( i, (*r)[ ii], (*g)[ ii], (*b)[ ii] ); GDLDelete( p0 ); p0 = r; GDLDelete( p1 ); p1 = g; GDLDelete( p2 ); p2 = b; } else { if ( hls || hsv ) { DFloatGDL* r = e->GetParAs< DFloatGDL>(0); DFloatGDL* g = e->GetParAs< DFloatGDL>(1); DFloatGDL* b = e->GetParAs< DFloatGDL>(2); SizeT rCol = r->N_Elements( ); SizeT gCol = g->N_Elements( ); SizeT bCol = b->N_Elements( ); SizeT nCol = rCol; if ( gCol < nCol ) nCol = gCol; if ( bCol < nCol ) nCol = bCol; SizeT setCol = nCol + start; if ( setCol > ctSize ) setCol = ctSize; if ( hls ) for ( SizeT i = start, ii = 0; i < setCol; ++i, ++ii ) actCT->SetHLS( i, (*r)[ ii], (*g)[ ii], (*b)[ ii] ); else for ( SizeT i = start, ii = 0; i < setCol; ++i, ++ii ) actCT->SetHSV( i, (*r)[ ii], (*g)[ ii], (*b)[ ii] ); } else { DByteGDL* r = e->GetParAs< DByteGDL>(0); DByteGDL* g = e->GetParAs< DByteGDL>(1); DByteGDL* b = e->GetParAs< DByteGDL>(2); SizeT rCol = r->N_Elements( ); SizeT gCol = g->N_Elements( ); SizeT bCol = b->N_Elements( ); SizeT nCol = rCol; if ( gCol < nCol ) nCol = gCol; if ( bCol < nCol ) nCol = bCol; SizeT setCol = nCol + start; if ( setCol > ctSize ) setCol = ctSize; for ( SizeT i = start, ii = 0; i < setCol; ++i, ++ii ) actCT->Set( i, (*r)[ ii], (*g)[ ii], (*b)[ ii] ); } } } // AC, 07/02/2012, please report any unexpected side effect (see test_tvlct.pro) if ( !get ) { PLINT red[ctSize], green[ctSize], blue[ctSize]; actCT->Get( red, green, blue ); GraphicsDevice* actDevice = GraphicsDevice::GetDevice( ); int nbActiveStreams = actDevice->MaxWin( ); //new colormap must be given to *all* streams. for ( int i = 0; i < nbActiveStreams; ++i ) { GDLGStream* actStream = actDevice->GetStreamAt( i ); if ( actStream != NULL ) actStream->SetColorMap0( red, green, blue, ctSize ); } } } BaseGDL* get_screen_size( EnvT* e) { //GD: DO NOT NEVER EVER TOUCH THIS WITHOUT TRIPLE THINKING. //ANY CHANGE MUST BE IN GetScreenSize() and GetScreenResolution() for a DERIVED CLASS. SizeT nParam=e->NParam(); SizeT authorized_nb_params=1; if ( nParam > authorized_nb_params) e->Throw( "Incorrect number of arguments."); char *TheDisplay=NULL; #ifdef HAVE_X if ( nParam == 1) { DString GivenDisplay; e->AssureStringScalarPar(0, GivenDisplay); TheDisplay = new char [GivenDisplay.size()+1]; strcpy (TheDisplay, GivenDisplay.c_str()); } static int displayNameIx = e->KeywordIx( "DISPLAY_NAME"); if ( e->KeywordPresent( displayNameIx)) { DString GivenDisplay; e->AssureStringScalarKWIfPresent( displayNameIx, GivenDisplay);; TheDisplay = new char [GivenDisplay.size()+1]; strcpy (TheDisplay, GivenDisplay.c_str()); } #endif GraphicsDevice* currentDevice=GraphicsDevice::GetDevice(); static int resolutionIx = e->KeywordIx( "RESOLUTION"); if( e->KeywordPresent( resolutionIx)) { e->SetKW(0, currentDevice->GetScreenResolution(TheDisplay)); } return currentDevice->GetScreenSize(TheDisplay); } } // namespace gdl-0.9.9/src/plotting_oplot.cpp000066400000000000000000000241011340051421000166330ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #ifdef _MSC_VER #define isnan _isnan #endif namespace lib { using namespace std; // using std::isinf; #ifndef _MSC_VER using std::isnan; #endif class oplot_call : public plotting_routine_call { DDoubleGDL *yVal, *xVal, *xTemp, *yTemp; SizeT xEl, yEl, zEl; DDouble minVal, maxVal, xStart, xEnd, yStart, yEnd, zValue; bool doMinMax; bool xLog, yLog, wasBadxLog, wasBadyLog; Guard xval_guard, yval_guard, xtemp_guard; DLong iso; bool doT3d; private: bool handle_args(EnvT* e) { //T3D? static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //note: Z (VALUE) will be used uniquely if Z is not effectively defined. static int zvIx = e->KeywordIx( "ZVALUE"); zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); zValue=min(zValue,0.999999); //to avoid problems with plplot zValue=max(zValue,0.0); // system variable !P.NSUM first DLong nsum=(*static_cast(SysVar::P()-> GetTag(SysVar::P()->Desc()->TagIndex("NSUM"), 0)))[0]; static int NSUMIx = e->KeywordIx( "NSUM"); e->AssureLongScalarKWIfPresent( NSUMIx, nsum); static int polarIx = e->KeywordIx( "POLAR"); bool polar = (e->KeywordSet(polarIx)); // DDoubleGDL *yValBis, *xValBis; // Guard xvalBis_guard, yvalBis_guard; //test and transform eventually if POLAR and/or NSUM! if( nParam() == 1) { yTemp = e->GetParAs< DDoubleGDL>( 0); if (yTemp->Rank() == 0) e->Throw("Expression must be an array in this context: "+e->GetParString(0)); yEl=yTemp->N_Elements(); xEl=yEl; xTemp = new DDoubleGDL( dimension( xEl), BaseGDL::INDGEN); xtemp_guard.Reset( xTemp); // delete upon exit } else { xTemp = e->GetParAs< DDoubleGDL>( 0); if (xTemp->Rank() == 0) e->Throw("Expression must be an array in this context: "+e->GetParString(0)); xEl=xTemp->N_Elements(); yTemp = e->GetParAs< DDoubleGDL>( 1); if (yTemp->Rank() == 0) e->Throw("Expression must be an array in this context: "+e->GetParString(1)); yEl=yTemp->N_Elements(); //silently drop unmatched values if (yEl != xEl) { SizeT size; size = min(xEl, yEl); xEl = size; yEl = size; } } //check nsum validity nsum=max(1,nsum); nsum=min(nsum,(DLong)xEl); if (nsum == 1) { if (polar) { xVal = new DDoubleGDL(dimension(xEl), BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit yVal = new DDoubleGDL(dimension(yEl), BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for (int i = 0; i < xEl; i++) (*xVal)[i] = (*xTemp)[i] * cos((*yTemp)[i]); for (int i = 0; i < yEl; i++) (*yVal)[i] = (*xTemp)[i] * sin((*yTemp)[i]); } else { //careful about previously set autopointers! if (nParam() == 1) xval_guard.Init( xtemp_guard.release()); xVal = xTemp; yVal = yTemp; } } else { int i, j, k; DLong size = (DLong)xEl / nsum; xVal = new DDoubleGDL(size, BaseGDL::ZERO); //SHOULD BE ZERO, IS NOT! xval_guard.Reset(xVal); // delete upon exit yVal = new DDoubleGDL(size, BaseGDL::ZERO); //IDEM yval_guard.Reset(yVal); // delete upon exit for (i = 0, k = 0; i < size; i++) { (*xVal)[i] = 0.0; (*yVal)[i] = 0.0; for (j = 0; j < nsum; j++, k++) { (*xVal)[i] += (*xTemp)[k]; (*yVal)[i] += (*yTemp)[k]; } } for (i = 0; i < size; i++) (*xVal)[i] /= nsum; for (i = 0; i < size; i++) (*yVal)[i] /= nsum; if (polar) { DDouble x, y; for (i = 0; i < size; i++) { x = (*xVal)[i] * cos((*yVal)[i]); y = (*xVal)[i] * sin((*yVal)[i]); (*xVal)[i] = x; (*yVal)[i] = y; } } } return false; } private: void old_body( EnvT* e, GDLGStream* actStream) { DLong psym; DDouble minVal, maxVal; bool doMinMax; bool xLog; bool yLog; gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); GetCurrentUserLimits(actStream, xStart, xEnd, yStart, yEnd); //now we can setup minVal and maxVal to defaults: Start-End and overload if KW present minVal = yStart; //to give a reasonable value... maxVal = yEnd; //idem doMinMax = false; //although we will not use it... static int MIN_VALUEIx = e->KeywordIx("MIN_VALUE"); static int MAX_VALUEIx = e->KeywordIx("MAX_VALUE"); if( e->KeywordSet(MIN_VALUEIx) || e->KeywordSet(MAX_VALUEIx)) doMinMax = true; //...unless explicitely required e->AssureDoubleScalarKWIfPresent( MIN_VALUEIx, minVal); e->AssureDoubleScalarKWIfPresent( MAX_VALUEIx, maxVal); // int noclipvalue=0; // static int NOCLIPIx = e->KeywordIx("NOCLIP"); // e->AssureLongScalarKWIfPresent( NOCLIPIx, noclipvalue); // // Clipping is enabled by default for OPLOT. // // make all clipping computations BEFORE setting graphic properties (color, size) // bool doClip=(e->KeywordSet(CLIPIx)||!(noclipvalue==0)); bool stopClip=false; // if ( doClip ) if ( startClipping(e, actStream)==true ) stopClip=true; // start drawing. Graphic Keywords accepted:CLIP(YES), COLOR(YES), LINESTYLE(YES), NOCLIP(YES), // PSYM(YES), SYMSIZE(YES), T3D(YES), ZVALUE(YES) gdlSetGraphicsForegroundColorFromKw(e, actStream); // it is important to fix symsize before changing vpor or win gdlGetPsym(e, psym); gdlSetPenThickness(e, actStream); gdlSetSymsize(e, actStream); gdlSetLineStyle(e, actStream); actStream->setSymbolSizeConversionFactors(); bool mapSet=false; #ifdef USE_LIBPROJ4 get_mapset(mapSet); if ( mapSet ) { ref=map_init(); if ( ref==NULL ) { e->Throw("Projection initialization failed."); } DDouble *sx, *sy; GetSFromPlotStructs( &sx, &sy ); DFloat *wx, *wy; GetWFromPlotStructs( &wx, &wy ); DDouble pxStart, pxEnd, pyStart, pyEnd; DataCoordLimits( sx, sy, wx, wy, &pxStart, &pxEnd, &pyStart, &pyEnd, true ); // actStream->OnePageSaveLayout(); // one page actStream->vpor( wx[0], wx[1], wy[0], wy[1] ); actStream->wind( pxStart, pxEnd, pyStart, pyEnd ); } #endif if ( doT3d ) //convert X,Y,Z in X',Y' as per T3D perspective. { DDoubleGDL* plplot3d; DDouble az, alt, ay, scale; ORIENTATION3D axisExchangeCode; plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw("Illegal 3D transformation. (FIXME)"); } static DDouble x0,y0,xs,ys; //conversion to normalized coords x0=(xLog)?-log10(xStart):-xStart; y0=(yLog)?-log10(yStart):-yStart; xs=(xLog)?(log10(xEnd)-log10(xStart)):xEnd-xStart;xs=1.0/xs; ys=(yLog)?(log10(yEnd)-log10(yStart)):yEnd-yStart;ys=1.0/ys; Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0=x0; Data3d.y0=y0; Data3d.xs=xs; Data3d.ys=ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } actStream->stransform(gdl3dTo2dTransform, &Data3d); } #ifdef USE_LIBPROJ4 if ( mapSet && psym < 1) { GDLgrProjectedPolygonPlot(actStream, ref, NULL, xVal, yVal, false, false, NULL); psym=-psym; if (psym > 0) draw_polyline(actStream, xVal, yVal, minVal, maxVal, doMinMax, xLog, yLog, psym); } else draw_polyline(actStream, xVal, yVal, minVal, maxVal, doMinMax, xLog, yLog, psym); #else draw_polyline(actStream, xVal, yVal, minVal, maxVal, doMinMax, xLog, yLog, psym); #endif if (stopClip) stopClipping(actStream); } private: void call_plplot(EnvT* e, GDLGStream* actStream) { } private: void post_call(EnvT* e, GDLGStream* actStream) { if (doT3d) actStream->stransform(NULL,NULL); // actStream->RestoreLayout(); actStream->lsty(1);//reset linestyle actStream->sizeChar(1.0); } }; // oplot_call class void oplot(EnvT* e) { oplot_call oplot; oplot.call(e, 1); } } // namespace gdl-0.9.9/src/plotting_plot.cpp000066400000000000000000000476121340051421000164700ustar00rootroot00000000000000/*************************************************************************** plotting_plot.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #ifdef _MSC_VER #define isnan _isnan #endif namespace lib { using namespace std; // using std::isinf; #ifndef _MSC_VER using std::isnan; #endif class plot_call : public plotting_routine_call { DDoubleGDL *yVal, *xVal, *xTemp, *yTemp; SizeT xEl, yEl, zEl; DDouble minVal, maxVal, xStart, xEnd, yStart, yEnd, zValue; bool doMinMax; bool xLog, yLog, wasBadxLog, wasBadyLog; Guard xval_guard, yval_guard, xtemp_guard; DLong iso; bool doT3d; DFloat UsymConvX, UsymConvY; int calendar_codex; int calendar_codey; private: bool handle_args(EnvT* e) { //T3D ? static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //note: Z (VALUE) will be used uniquely if Z is not effectively defined. static int zvIx = e->KeywordIx( "ZVALUE"); zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); zValue=min(zValue,0.999999); //to avoid problems with plplot zValue=max(zValue,0.0); // system variable !P.NSUM first DLong nsum=(*static_cast(SysVar::P()-> GetTag(SysVar::P()->Desc()->TagIndex("NSUM"), 0)))[0]; static int NSUMIx = e->KeywordIx( "NSUM"); e->AssureLongScalarKWIfPresent( NSUMIx, nsum); static int polarIx = e->KeywordIx( "POLAR"); bool polar = (e->KeywordSet(polarIx)); DDoubleGDL *yValBis, *xValBis; Guard xvalBis_guard, yvalBis_guard; //test and transform eventually if POLAR and/or NSUM! if (nParam() == 1) { yTemp = e->GetParAs< DDoubleGDL > (0); if (yTemp->Rank() == 0) e->Throw("Expression must be an array in this context: " + e->GetParString(0)); yEl=yTemp->N_Elements(); xEl=yEl; xTemp = new DDoubleGDL(dimension(xEl), BaseGDL::INDGEN); xtemp_guard.Reset(xTemp); // delete upon exit } else { xTemp = e->GetParAs< DDoubleGDL > (0); if (xTemp->Rank() == 0) e->Throw("Expression must be an array in this context: " + e->GetParString(0)); xEl=xTemp->N_Elements(); yTemp = e->GetParAs< DDoubleGDL > (1); if (yTemp->Rank() == 0) e->Throw("Expression must be an array in this context: " + e->GetParString(1)); yEl=yTemp->N_Elements(); //silently drop unmatched values if (yEl!= xEl) { SizeT size; size = min(xEl, yEl); xEl = size; yEl = size; } } //check nsum validity nsum = max(1, nsum); nsum = min(nsum, (DLong)xEl); if (nsum == 1) { if (polar) { xVal = new DDoubleGDL(dimension(xEl), BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit yVal = new DDoubleGDL(dimension(yEl), BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for (int i = 0; i < xEl; i++) (*xVal)[i] = (*xTemp)[i] * cos((*yTemp)[i]); for (int i = 0; i < yEl; i++) (*yVal)[i] = (*xTemp)[i] * sin((*yTemp)[i]); } else { //careful about previously set autopointers! if (nParam() == 1) xval_guard.Init( xtemp_guard.release()); xVal = xTemp; yVal = yTemp; } } else { int i, j, k; DLong size = (DLong)xEl / nsum; xVal = new DDoubleGDL(size, BaseGDL::ZERO); //SHOULD BE ZERO, IS NOT! xval_guard.Reset(xVal); // delete upon exit yVal = new DDoubleGDL(size, BaseGDL::ZERO); //IDEM yval_guard.Reset(yVal); // delete upon exit for (i = 0, k = 0; i < size; i++) { (*xVal)[i] = 0.0; (*yVal)[i] = 0.0; for (j = 0; j < nsum; j++, k++) { (*xVal)[i] += (*xTemp)[k]; (*yVal)[i] += (*yTemp)[k]; } } for (i = 0; i < size; i++) (*xVal)[i] /= nsum; for (i = 0; i < size; i++) (*yVal)[i] /= nsum; if (polar) { DDouble x, y; for (i = 0; i < size; i++) { x = (*xVal)[i] * cos((*yVal)[i]); y = (*xVal)[i] * sin((*yVal)[i]); (*xVal)[i] = x; (*yVal)[i] = y; } } } xLog=FALSE; yLog=FALSE; // handle Log options passing via Functions names PLOT_IO/OO/OI // the behavior can be superseed by [xy]log or [xy]type string ProName = e->GetProName( ); if ( ProName != "PLOT" ) { if ( ProName == "PLOT_IO" ) yLog = TRUE; if ( ProName == "PLOT_OI" ) xLog = TRUE; if ( ProName == "PLOT_OO" ) { xLog = TRUE; yLog = TRUE; } } // handle Log options passing via Keywords // note: undocumented keywords [xyz]type still exist and // have priority on [xyz]log ! static int xLogIx = e->KeywordIx( "XLOG" ); static int yLogIx = e->KeywordIx( "YLOG" ); if (e->KeywordPresent(xLogIx)) xLog = e->KeywordSet(xLogIx); if (e->KeywordPresent(yLogIx)) yLog = e->KeywordSet(yLogIx); // note: undocumented keywords [xyz]type still exist and // have priority on [xyz]log ! In fact, it is the modulo (1, 3, 5 ... --> /log) static int xTypeIx = e->KeywordIx( "XTYPE" ); static int yTypeIx = e->KeywordIx( "YTYPE" ); static int xType, yType; if (e->KeywordPresent(xTypeIx)) { e->AssureLongScalarKWIfPresent(xTypeIx, xType); if ((xType % 2) == 1) xLog= TRUE; else xLog= FALSE; } if (e->KeywordPresent(yTypeIx)) { e->AssureLongScalarKWIfPresent( yTypeIx, yType); if ((yType % 2) == 1) yLog= TRUE; else yLog= FALSE; } // cout << xType<< " " <KeywordIx( "XTICKUNITS" ); static int yTickunitsIx = e->KeywordIx( "YTICKUNITS" ); calendar_codex = gdlGetCalendarCode(e,"X"); calendar_codey = gdlGetCalendarCode(e,"Y"); if ( e->KeywordSet( xTickunitsIx ) && xLog) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); xLog = FALSE; } if ( e->KeywordSet( yTickunitsIx ) && yLog) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); yLog = FALSE; } // cout << xLog << " " << yLog << endl; // compute adequate values for log scale, warn adequately... wasBadxLog = FALSE; wasBadyLog = FALSE; if (xLog) { DLong minEl, maxEl; xVal->MinMax(&minEl, &maxEl, NULL, NULL, true,0,xEl); //restrict minmax to xEl fist elements!!!! if ((*xVal)[minEl] <= 0.0) wasBadxLog = TRUE; xValBis = new DDoubleGDL(dimension(xEl), BaseGDL::NOZERO); xvalBis_guard.Reset(xValBis); // delete upon exit for (int i = 0; i < xEl; i++) (*xValBis)[i] = log10((*xVal)[i]); } else xValBis = xVal; if (yLog) { DLong minEl, maxEl; yVal->MinMax(&minEl, &maxEl, NULL, NULL, true,0,yEl); if ((*yVal)[minEl] <= 0.0) wasBadyLog = TRUE; yValBis = new DDoubleGDL(dimension(yEl), BaseGDL::NOZERO); yvalBis_guard.Reset(yValBis); // delete upon exit for (int i = 0; i < yEl; i++) (*yValBis)[i] = log10((*yVal)[i]); } else yValBis = yVal; #define UNDEF_RANGE_VALUE 1E-12 { DLong minEl, maxEl; xValBis->MinMax(&minEl, &maxEl, NULL, NULL, true, 0, xEl); //restrict minmax to xEl fist elements!!!! xStart = (*xVal)[minEl]; xEnd = (*xVal)[maxEl]; if (isnan(xStart)) xStart = UNDEF_RANGE_VALUE; if (isnan(xEnd)) xEnd = 1.0; if (xStart==xEnd) xStart=xEnd-UNDEF_RANGE_VALUE; yValBis->MinMax(&minEl, &maxEl, NULL, NULL, true, 0, yEl); yStart = (*yVal)[minEl]; yEnd = (*yVal)[maxEl]; if (isnan(yStart)) yStart = UNDEF_RANGE_VALUE; if (isnan(yEnd)) yEnd = 1.0; if (yStart==yEnd) yStart=yEnd-UNDEF_RANGE_VALUE; } //MIN_VALUE and MAX_VALUE overwrite yStart/yEnd eventually (note: the points will not be "seen" at all in plots) minVal = yStart; //to give a reasonable value... maxVal = yEnd; //idem doMinMax = false; //although we will not use it... static int MIN_VALUEIx = e->KeywordIx("MIN_VALUE"); static int MAX_VALUEIx = e->KeywordIx("MAX_VALUE"); if( e->KeywordSet(MIN_VALUEIx) || e->KeywordSet(MAX_VALUEIx)) doMinMax = true; //...unless explicitely required e->AssureDoubleScalarKWIfPresent( MIN_VALUEIx, minVal); e->AssureDoubleScalarKWIfPresent( MAX_VALUEIx, maxVal); yStart=gdlPlot_Max(yStart,minVal); yEnd=gdlPlot_Min(yEnd,maxVal); if (yEnd <= yStart) yEnd=yStart+1; //XRANGE and YRANGE overrides all that, but Start/End should be recomputed accordingly DDouble xAxisStart, xAxisEnd, yAxisStart, yAxisEnd; bool setx=gdlGetDesiredAxisRange(e, "X", xAxisStart, xAxisEnd); bool sety=gdlGetDesiredAxisRange(e, "Y", yAxisStart, yAxisEnd); if(setx && sety) { xStart=xAxisStart; xEnd=xAxisEnd; yStart=yAxisStart; yEnd=yAxisEnd; } else if (sety) { yStart=yAxisStart; yEnd=yAxisEnd; } else if (setx) { xStart=xAxisStart; xEnd=xAxisEnd; //must compute min-max for other axis! { gdlDoRangeExtrema(xVal,yVal,yStart,yEnd,xStart,xEnd,doMinMax,minVal,maxVal); } } //handle Nozero option after all that! (gdlAxisNoZero test if /ynozero option is valid (ex: no YRANGE) if(!gdlYaxisNoZero(e) && yStart >0 && !yLog ) yStart=0.0; #undef UNDEF_RANGE_VALUE //ISOTROPIC iso=0; static int ISOTROPICIx = e->KeywordIx("ISOTROPIC"); e->AssureLongScalarKWIfPresent( ISOTROPICIx, iso); return false; } private: void old_body( EnvT* e, GDLGStream* actStream) { // background BEFORE next plot since it is the only place plplot may redraw the background... gdlSetGraphicsBackgroundColorFromKw(e, actStream); //start a plot gdlNextPlotHandlingNoEraseOption(e, actStream); //NOERASE // [XY]STYLE DLong xStyle=0, yStyle=0; gdlGetDesiredAxisStyle(e, "X", xStyle); gdlGetDesiredAxisStyle(e, "Y", yStyle); //xStyle and yStyle apply on range values if ((xStyle & 1) != 1) { PLFLT intv = gdlAdjustAxisRange(e, "X", xStart, xEnd, xLog, calendar_codex); } if ((yStyle & 1) != 1) { PLFLT intv = gdlAdjustAxisRange(e, "Y", yStart, yEnd, yLog, calendar_codey); } // MARGIN DFloat xMarginL, xMarginR, yMarginB, yMarginT; gdlGetDesiredAxisMargin(e, "X", xMarginL, xMarginR); gdlGetDesiredAxisMargin(e, "Y", yMarginB, yMarginT); // viewport and world coordinates // set the PLOT charsize before setting viewport (margin depend on charsize) gdlSetPlotCharsize(e, actStream); if (doT3d) { static DDouble x0,y0,xs,ys; //conversion to normalized coords x0=(xLog)?-log10(xStart):-xStart; y0=(yLog)?-log10(yStart):-yStart; xs=(xLog)?(log10(xEnd)-log10(xStart)):xEnd-xStart;xs=1.0/xs; ys=(yLog)?(log10(yEnd)-log10(yStart)):yEnd-yStart;ys=1.0/ys; DDoubleGDL* plplot3d; DDouble az, alt, ay, scale; ORIENTATION3D axisExchangeCode; plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw("Illegal 3D transformation. (FIXME)"); } if (gdlSet3DViewPortAndWorldCoordinates(e, actStream, plplot3d, xLog, yLog, xStart, xEnd, yStart, yEnd) == FALSE) return; gdlSetGraphicsForegroundColorFromKw(e, actStream); DDouble t3xStart, t3xEnd, t3yStart, t3yEnd, t3zStart, t3zEnd; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY t3xStart=(xLog)?log10(xStart):xStart, t3xEnd=(xLog)?log10(xEnd):xEnd, t3yStart=(yLog)?log10(yStart):yStart, t3yEnd=(yLog)?log10(yEnd):yEnd, t3zStart=0; t3zEnd=1.0; actStream->w3d(scale, scale, scale*(1.0 - zValue), t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "X", xStart, xEnd, xLog); gdlAxis3(e, actStream, "Y", yStart, yEnd, yLog); break; case XY: // X->Y Y->X plane XY t3yStart=(xLog)?log10(xStart):xStart, t3yEnd=(xLog)?log10(xEnd):xEnd, t3xStart=(yLog)?log10(yStart):yStart, t3xEnd=(yLog)?log10(yEnd):yEnd, t3zStart=0; t3zEnd=1.0; actStream->w3d(scale, scale, scale*(1.0 - zValue), t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Y", xStart, xEnd, xLog); gdlAxis3(e, actStream, "X", yStart, yEnd, yLog); break; case XZ: // Y->Y X->Z plane YZ t3zStart=(xLog)?log10(xStart):xStart, t3zEnd=(xLog)?log10(xEnd):xEnd, t3yStart=(yLog)?log10(yStart):yStart, t3yEnd=(yLog)?log10(yEnd):yEnd, t3xStart=0; t3xEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Z", xStart, xEnd, xLog,0); gdlAxis3(e, actStream, "Y", yStart, yEnd, yLog); break; case YZ: // X->X Y->Z plane XZ t3xStart=(xLog)?log10(xStart):xStart, t3xEnd=(xLog)?log10(xEnd):xEnd, t3zStart=(yLog)?log10(yStart):yStart, t3zEnd=(yLog)?log10(yEnd):yEnd, t3yStart=0; t3yEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "X", xStart, xEnd, xLog); gdlAxis3(e, actStream, "Z", yStart, yEnd, yLog,1); break; case XZXY: //X->Y Y->Z plane YZ t3yStart=(xLog)?log10(xStart):xStart, t3yEnd=(xLog)?log10(xEnd):xEnd, t3zStart=(yLog)?log10(yStart):yStart, t3zEnd=(yLog)?log10(yEnd):yEnd, t3xStart=0; t3xEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Y", xStart, xEnd, xLog); gdlAxis3(e, actStream, "Z", yStart, yEnd, yLog); break; case XZYZ: //X->Z Y->X plane XZ t3zStart=(xLog)?log10(xStart):xStart, t3zEnd=(xLog)?log10(xEnd):xEnd, t3xStart=(yLog)?log10(yStart):yStart, t3xEnd=(yLog)?log10(yEnd):yEnd, t3yStart=0; t3yEnd=1.0; actStream->w3d(scale, scale, scale, t3xStart,t3xEnd,t3yStart,t3yEnd,t3zStart,t3zEnd, alt, az); gdlAxis3(e, actStream, "Z", xStart, xEnd, xLog,1); gdlAxis3(e, actStream, "X", yStart, yEnd, yLog); break; } //finish box: since there is no option in plplot for upper box 3d axes, do it ourselve: Data3d.zValue = 0; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0=x0; Data3d.y0=y0; Data3d.xs=xs; Data3d.ys=ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; actStream->stransform(gdl3dTo2dTransform, &Data3d); actStream->join(t3xStart,t3yEnd,t3xEnd,t3yEnd); actStream->join(t3xEnd,t3yStart,t3xEnd,t3yEnd); break; case XY: // X->Y Y->X plane XY Data3d.code = code012; actStream->stransform(gdl3dTo2dTransform, &Data3d); actStream->join(t3yStart,t3xEnd,t3yEnd,t3xEnd); actStream->join(t3yEnd,t3xStart,t3yEnd,t3xEnd); break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; actStream->stransform(gdl3dTo2dTransform, &Data3d); actStream->join(t3zStart,t3yStart,t3zEnd,t3yStart); actStream->join(t3zEnd,t3yStart,t3zEnd,t3yEnd); default: break; // case YZ: // X->X Y->Z plane XZ // cerr<<"yz"<stransform(gdl3dTo2dTransform, &Data3d); // break; // case XZXY: //X->Y Y->Z plane YZ // cerr<<"xzxy"<stransform(gdl3dTo2dTransform, &Data3d); // break; // case XZYZ: //X->Z Y->X plane XZ // cerr<<"xzyz"<stransform(gdl3dTo2dTransform, &Data3d); // break; } //data: will plot using coordinates transform. //TODO: unless PSYM=0 (optimize) Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0=x0; Data3d.y0=y0; Data3d.xs=xs; Data3d.ys=ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } actStream->stransform(gdl3dTo2dTransform, &Data3d); // title and sub title gdlWriteTitleAndSubtitle(e, actStream); } else { //fix viewport and coordinates for non-3D box. this permits to have correct UsymConv values. // it is important to fix simsize before! gdlSetSymsize(e, actStream); if (gdlSetViewPortAndWorldCoordinates(e, actStream, xLog, yLog, xMarginL, xMarginR, yMarginB, yMarginT, xStart, xEnd, yStart, yEnd, iso)==FALSE) return; //no good: should catch an exception to get out of this mess. actStream->setSymbolSizeConversionFactors(); //current pen color... gdlSetGraphicsForegroundColorFromKw(e, actStream); gdlBox(e, actStream, xStart, xEnd, yStart, yEnd, xLog, yLog); } } private: void call_plplot(EnvT* e, GDLGStream* actStream) { DLong psym; // plot the data static int nodataIx = e->KeywordIx( "NODATA"); if ( !e->KeywordSet(nodataIx) ) { bool stopClip=false; if ( startClipping(e, actStream, false)==TRUE ) stopClip=true; // here graphic properties gdlSetPenThickness(e, actStream); gdlSetLineStyle(e, actStream); gdlGetPsym(e, psym); //PSYM draw_polyline(actStream, xVal, yVal, minVal, maxVal, doMinMax, xLog, yLog, psym); if (stopClip) stopClipping(actStream); } } private: void post_call(EnvT* e, GDLGStream* actStream) { // gdlBox(e, actStream, xStart, xEnd, yStart, yEnd, xLog, yLog); if (doT3d) actStream->stransform(NULL,NULL); actStream->lsty(1);//reset linestyle actStream->sizeChar(1.0); } }; void plot(EnvT* e) { plot_call plot; plot.call(e, 1); } void plot_io(EnvT* e) {plot(e);} void plot_oo(EnvT* e) {plot(e);} void plot_oi(EnvT* e) {plot(e);} } // namespace gdl-0.9.9/src/plotting_plots.cpp000066400000000000000000000402251340051421000166440ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; class plots_call: public plotting_routine_call { DDoubleGDL *xVal, *yVal, *zVal; Guard xval_guard, yval_guard, zval_guard; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd; DLong psym; bool xLog, yLog, zLog; SizeT xEl, yEl, zEl; bool append; bool doClip; bool restorelayout; bool doT3d, real3d; DDouble zValue; DDoubleGDL* plplot3d; Guard plplot3d_guard; DLongGDL *color; bool mapSet; ORIENTATION3D axisExchangeCode; DDouble az, alt, ay, scale; enum { DATA=0, NORMAL, DEVICE } coordinateSystem; private: bool handle_args(EnvT* e) { gdlGetPsym(e, psym); //PSYM if (psym==10) e->Throw("PSYM (plotting symbol) out of range"); //not allowed for PLOTS! real3d=false; //T3D static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx) || T3Denabled()); //note: Z (VALUE) will be used uniquely if Z is not effectively defined. // Then Z is useful only if (doT3d). static int zvIx = e->KeywordIx( "Z"); zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); static int continueIx = e->KeywordIx( "CONTINUE"); append=e->KeywordSet(continueIx); if ( nParam()==1 ) { BaseGDL* p0; p0=e->GetParDefined(0); SizeT dim0=p0->Dim(0); if ( dim0<2 || dim0>3 ) e->Throw("When only 1 param, dims must be (2,n) or (3,n)"); DDoubleGDL *val=e->GetParAs< DDoubleGDL>(0); xEl=p0->N_Elements()/dim0; xVal=new DDoubleGDL(dimension(xEl), BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit yEl=p0->N_Elements()/dim0; yVal=new DDoubleGDL(dimension(yEl), BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for ( SizeT i=0; iN_Elements()/dim0; zVal=new DDoubleGDL(dimension(zEl), BaseGDL::NOZERO); zval_guard.Reset(zVal); // delete upon exit if (dim0==3) for ( SizeT i=0; iGetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); SizeT maxEl; maxEl=(xEl>yEl)?xEl:yEl; if (maxEl > 1) { //there is at least one non-single SizeT minEl; minEl=(xVal->Dim(0)==0)?maxEl:((xElDim(0)==0)?minEl:((yElDim(0)==0) { DDoubleGDL* tmpxVal=e->GetParAs< DDoubleGDL>(0); xVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); xEl=minEl; xval_guard.Reset(xVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[0]; } if (yVal->Dim(0)==0) { DDoubleGDL* tmpyVal=e->GetParAs< DDoubleGDL>(1); yVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); yEl=minEl; yval_guard.Reset(yVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[0]; } } //z will be set at Zero unless Z=value is given zEl=xEl; zVal=new DDoubleGDL(dimension(zEl)); zval_guard.Reset(zVal); // delete upon exit for (SizeT i=0; i< zEl ; ++i) (*zVal)[i]=zValue; } else if ( nParam()==3 ) { if (doT3d) real3d=true; zVal=e->GetParAs< DDoubleGDL>(2); zEl=zVal->N_Elements(); xVal=e->GetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); //Z has no effect if T3D is not active, either through the T3D kw or through the !P.T3D sysvar. SizeT maxEl; maxEl=(xEl>yEl)?xEl:yEl; maxEl=(maxEl>zEl)?maxEl:zEl; if (maxEl > 1) { //there is at least one non-single SizeT minEl; minEl=(xVal->Dim(0)==0)?maxEl:((xElDim(0)==0)?minEl:((yElDim(0)==0)?minEl:((zElDim(0)==0) { DDoubleGDL* tmpxVal=e->GetParAs< DDoubleGDL>(0); xVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); xEl=minEl; xval_guard.Reset(xVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[0]; } if (yVal->Dim(0)==0) { DDoubleGDL* tmpyVal=e->GetParAs< DDoubleGDL>(1); yVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); yEl=minEl; yval_guard.Reset(yVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[0]; } if (zVal->Dim(0)==0) { DDoubleGDL* tmpzVal=e->GetParAs< DDoubleGDL>(2); zVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); zEl=minEl; zval_guard.Reset(zVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*zVal)[i]=(*tmpzVal)[0]; } } } if ( doT3d && !real3d) { //test to avois passing a non-rotation matrix to plplots's stransform. plplot limitation-> FIXME! plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw("Illegal 3D transformation. (FIXME)"); } else GDLDelete(plplot3d); } return false; } void old_body(EnvT* e, GDLGStream* actStream) { //check presence of DATA,DEVICE and NORMAL options static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); coordinateSystem = DATA; //check presence of DATA,DEVICE and NORMAL options if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; //T3D incompatible with DEVICE option. if (coordinateSystem == DEVICE) doT3d =false; // get_axis_type gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); gdlGetAxisType("Z", zLog); //get DATA limits (not necessary CRANGE, see AXIS / SAVE behaviour!) GetCurrentUserLimits(actStream, xStart, xEnd, yStart, yEnd); // get !Z.CRANGE gdlGetCurrentAxisRange("Z", zStart, zEnd); if (zStart != 0.0 && zStart == zEnd) { Message("PLOTS: !Z.CRANGE ERROR, setting to [0,1]"); zStart = 0; zEnd = 1; } // it is important to fix symsize before changing vpor or win gdlSetSymsize(e, actStream); //SYMSIZE int noclipvalue=1; static int NOCLIPIx = e->KeywordIx("NOCLIP"); e->AssureLongScalarKWIfPresent( NOCLIPIx, noclipvalue); doClip=(noclipvalue==0); //PLOTS by default does not clip, even if clip is defined by CLIP= restorelayout=true; mapSet=false; #ifdef USE_LIBPROJ4 get_mapset(mapSet); mapSet=(mapSet && coordinateSystem==DATA); if ( mapSet ) { ref=map_init(); if ( ref==NULL ) { e->Throw("Projection initialization failed."); } restorelayout=true; } #endif if ( doT3d && !real3d) { doClip=false; //impossible to clip in 3d using plplot. we should do it ourselves. restorelayout=false; if ( coordinateSystem==NORMAL ){ xLog=false; yLog=false;} } else { if (restorelayout) actStream->OnePageSaveLayout(); // one page actStream->vpor(0, 1, 0, 1); //ALL PAGE if ( coordinateSystem==DEVICE ) { actStream->wind(0.0, actStream->xPageSize(), 0.0, actStream->yPageSize()); xLog=false; yLog=false; } else if ( coordinateSystem==NORMAL ) { actStream->wind(0, 1, 0, 1); xLog=false; yLog=false; } else //with PLOTS, we can plot *outside* the box(e)s in DATA coordinates. { setPlplotScale(actStream); } } actStream->setSymbolSizeConversionFactors(); } private: void call_plplot(EnvT* e, GDLGStream* actStream) { // start drawing. Graphic Keywords accepted: CLIP(YES), COLOR(OK), DATA(YES), DEVICE(YES), //LINESTYLE(OK), NOCLIP(YES), NORMAL(YES), PSYM(OK), SYMSIZE(OK), T3D(NO), THICK(OK), Z(NO) static int colorIx=e->KeywordIx ( "COLOR" ); bool doColor=false; if ( e->GetKW ( colorIx )!=NULL ) { color=e->GetKWAs( colorIx ); doColor=true; } if ( doT3d && !real3d) { //if X,Y and Z are passed, we will use !P.T and not our plplot "interpretation" of !P.T //if the x and y scaling is OK, using !P.T directly permits to use other projections //than those used implicitly by plplot. See @showhaus example for *DL // case where we project 2D data on 3D: use plplot-like matrix. static DDouble x0,y0,xs,ys; //conversion to normalized coords if (coordinateSystem==NORMAL) { //TODO: THIS IS NOT CORRECT. The conversion is limited to the world box, not the 3d-projected normalized coordinates. x0=0;y0=0;xs=1.0;ys=1.0; } else { x0=(xLog)?-log10(xStart):-xStart; y0=(yLog)?-log10(yStart):-yStart; xs=(xLog)?(log10(xEnd)-log10(xStart)):xEnd-xStart;xs=1.0/xs; ys=(yLog)?(log10(yEnd)-log10(yStart)):yEnd-yStart;ys=1.0/ys; } // here zvalue here is zcoord on Z axis, to be scaled between 0 and 1 for compatibility with call of gdlConvertT3DMatrixToPlplotRotationMatrix() zValue /= (zEnd - zStart); plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix(zValue, az, alt, ay, scale, axisExchangeCode); Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0 = x0; Data3d.y0 = y0; Data3d.xs = xs; Data3d.ys = ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } actStream->stransform(gdl3dTo2dTransform, &Data3d); } // make all clipping computations BEFORE setting graphic properties (color, size) bool stopClip=false; if ( doClip ) if ( startClipping(e, actStream, true)==true ) stopClip=true; //will use pClip if needed //properties if (!doColor || color->N_Elements() == 1){ //if no KW or only 1 color, no need to complicate things //at draw_polyline level! gdlSetGraphicsForegroundColorFromKw(e, actStream); //COLOR doColor=false; } gdlSetLineStyle(e, actStream); //LINESTYLE gdlSetPenThickness(e, actStream); //THICK if (real3d) { //try first if the matrix is a plplot-compatible one plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) //use the original !P.T matrix (better than nothing) { Warning("Using Illegal 3D transformation, continuing. (FIXME)"); plplot3d=gdlGetT3DMatrix(); //the original one plplot3d_guard.Reset(plplot3d); Data3d.code = code012; } else { switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } } DDoubleGDL *xValou=new DDoubleGDL(dimension(xEl)); DDoubleGDL *yValou=new DDoubleGDL(dimension(yEl)); Guard xval_guard, yval_guard; xval_guard.reset(xValou); yval_guard.reset(yValou); //rescale to normalized box before conversions --- works for both matrices. // gdl3dto2dProjectDDouble(gdlGetScaledNormalizedT3DMatrix(plplot3d),xVal,yVal,zVal,xValou,yValou,Data3d.code); gdl3dto2dProjectDDouble(plplot3d,xVal,yVal,zVal,xValou,yValou,Data3d.code); ///TODO: Get proper USerSymSize in 3D. #ifdef USE_LIBPROJ4 if ( mapSet && psym < 1) { GDLgrProjectedPolygonPlot(actStream, ref, NULL, xValou, yValou, false, false, NULL); psym=-psym; if (psym > 0) draw_polyline(actStream, xValou, yValou, 0.0, 0.0, false, xLog, yLog, psym, mapSet, append, doColor?color:NULL); } else draw_polyline(actStream, xValou, yValou, 0.0, 0.0, false, xLog, yLog, psym, mapSet, append, doColor?color:NULL); } else { if ( mapSet && psym < 1) { GDLgrProjectedPolygonPlot(actStream, ref, NULL, xVal, yVal, false, false, NULL); //connect lines correctly psym=-psym; if (psym > 0) draw_polyline(actStream, xVal, yVal, 0.0, 0.0, false, xLog, yLog, psym, mapSet, append, doColor?color:NULL); } else draw_polyline(actStream, xVal, yVal, 0.0, 0.0, false, xLog, yLog, psym, mapSet, append, doColor?color:NULL); } #else draw_polyline(actStream, xValou, yValou, 0.0, 0.0, false, xLog, yLog, psym, false, append, doColor?color:NULL); } else draw_polyline(actStream, xVal, yVal, 0.0, 0.0, false, xLog, yLog, psym, false, append, doColor?color:NULL); #endif if (stopClip) stopClipping(actStream); } private: virtual void post_call(EnvT*, GDLGStream* actStream) { if (doT3d && !real3d) { plplot3d_guard.Reset(plplot3d); actStream->stransform(NULL,NULL); } if (restorelayout) actStream->RestoreLayout(); actStream->lsty(1); } }; void plots(EnvT* e) { plots_call plots; plots.call(e, 1); } } // namespace gdl-0.9.9/src/plotting_polyfill.cpp000066400000000000000000000344371340051421000173450ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; class polyfill_call: public plotting_routine_call { DDoubleGDL *xVal, *yVal, *zVal; Guard xval_guard, yval_guard, zval_guard; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd; bool xLog, yLog, zLog; SizeT xEl, yEl, zEl; bool doClip; bool restorelayout; bool doT3d, real3d; DDouble zValue; DDoubleGDL* plplot3d; Guard plplot3d_guard; DLongGDL *color; bool mapSet; ORIENTATION3D axisExchangeCode; DDouble az, alt, ay, scale; enum { DATA=0, NORMAL, DEVICE } coordinateSystem; private: bool handle_args(EnvT* e) { real3d=false; //T3D static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //note: Z (VALUE) will be used uniquely if Z is not effectively defined. // Then Z is useful only if (doT3d). static int zvIx = e->KeywordIx( "Z"); zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); if ( nParam()==1 ) { BaseGDL* p0; p0=e->GetParDefined(0); SizeT dim0=p0->Dim(0); if ( dim0<2 || dim0>3 ) e->Throw("When only 1 param, dims must be (2,n) or (3,n)"); if (p0->Dim(1) < 3 ) e->Throw("Not enough valid and unique points specified."); DDoubleGDL *val=e->GetParAs< DDoubleGDL>(0); xEl=p0->N_Elements()/dim0; xVal=new DDoubleGDL(dimension(xEl), BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit yEl=p0->N_Elements()/dim0; yVal=new DDoubleGDL(dimension(yEl), BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for ( SizeT i=0; iN_Elements()/dim0; zVal=new DDoubleGDL(dimension(zEl), BaseGDL::NOZERO); zval_guard.Reset(zVal); // delete upon exit if (dim0==3) for ( SizeT i=0; iGetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); if ( xEl < 3 || yEl < 3 ) e->Throw("Not enough valid and unique points specified."); //silently drop unmatched values if ( yEl!=xEl ) { SizeT size; size=min(xEl, yEl); xEl=size; yEl=size; } //z will be set at Zero unless Z=value is given zEl=xEl; zVal=new DDoubleGDL(dimension(zEl)); zval_guard.Reset(zVal); // delete upon exit for (SizeT i=0; i< zEl ; ++i) (*zVal)[i]=zValue; } else if ( nParam()==3 ) { if (doT3d) real3d=true; zVal=e->GetParAs< DDoubleGDL>(2); zEl=zVal->N_Elements(); xVal=e->GetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); //Z has no effect if T3D is not active, either through the T3D kw or through the !P.T3D sysvar. if (doT3d) { if ( xEl < 3 || yEl < 3 || zEl < 3) e->Throw("Not enough valid and unique points specified."); } else { if ( xEl < 3 || yEl < 3 ) e->Throw("Not enough valid and unique points specified."); //z will be set at Zero unless Z=value is given zEl=xEl; zVal=new DDoubleGDL(dimension(zEl)); zval_guard.Reset(zVal); // delete upon exit for (SizeT i=0; i< zEl ; ++i) (*zVal)[i]=zValue; } if ( !(xEl==yEl&&yEl==zEl) ) { SizeT size; size=min(xEl, yEl); size=min(size, zEl); xEl=size; yEl=size; zEl=size; } } if ( doT3d && !real3d) { //test to throw before plot values changes plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw("Illegal 3D transformation. (FIXME)"); } } return false; } void old_body(EnvT* e, GDLGStream* actStream) { //check presence of DATA,DEVICE and NORMAL options static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); coordinateSystem = DATA; //check presence of DATA,DEVICE and NORMAL options if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; //T3D incompatible with DEVICE option. if (coordinateSystem == DEVICE) doT3d =false; // get_axis_type gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); gdlGetAxisType("Z", zLog); //get DATA limits (not necessary CRANGE, see AXIS / SAVE behaviour!) GetCurrentUserLimits(actStream, xStart, xEnd, yStart, yEnd); // get !Z.CRANGE gdlGetCurrentAxisRange("Z", zStart, zEnd); if (zStart != 0.0 && zStart == zEnd) { Message("PLOTS: !Z.CRANGE ERROR, setting to [0,1]"); zStart = 0; zEnd = 1; } int noclipvalue=1; static int NOCLIPIx = e->KeywordIx("NOCLIP"); e->AssureLongScalarKWIfPresent( NOCLIPIx, noclipvalue); doClip=(noclipvalue==0); //POLYFILL by default does not clip, even if clip is defined by CLIP= or !P.CLIP, and CONTRARY TO THE DOCUMENTATION!!!! restorelayout=true; mapSet=false; #ifdef USE_LIBPROJ4 get_mapset(mapSet); mapSet=(mapSet && coordinateSystem==DATA); if ( mapSet ) { ref=map_init(); if ( ref==NULL ) { e->Throw("Projection initialization failed."); } restorelayout=true; } #endif if ( doT3d && !real3d) { doClip=false; //impossible to clip in 3d using plplot. we should do it ourselves. restorelayout=false; if ( coordinateSystem==NORMAL ){ xLog=false; yLog=false;} } else { if (restorelayout) actStream->OnePageSaveLayout(); // one page actStream->vpor(0, 1, 0, 1); //ALL PAGE if ( coordinateSystem==DEVICE ) { actStream->wind(0.0, actStream->xPageSize(), 0.0, actStream->yPageSize()); xLog=false; yLog=false; } else if ( coordinateSystem==NORMAL ) { actStream->wind(0, 1, 0, 1); xLog=false; yLog=false; } else //with POLYFILL, we can plot *outside* the box(e)s in DATA coordinates. { setPlplotScale(actStream); } } } private: void call_plplot(EnvT* e, GDLGStream* actStream) { static int colorIx=e->KeywordIx ( "COLOR" ); bool doColor=false; if ( e->GetKW ( colorIx )!=NULL ) { color=e->GetKWAs( colorIx ); doColor=true; } if ( doT3d && !real3d) { //if X,Y and Z are passed, we will use !P.T and not our plplot "interpretation" of !P.T //if the x and y scaling is OK, using !P.T directly permits to use other projections //than those used implicitly by plplot. See @showhaus example for *DL // case where we project 2D data on 3D: use plplot-like matrix. static DDouble x0,y0,xs,ys; //conversion to normalized coords if (coordinateSystem==NORMAL) { //TODO: THIS IS NOT CORRECT. The conversion is limited to the world box, not the 3d-projected normalized coordinates. x0=0;y0=0;xs=1.0;ys=1.0; } else { x0=(xLog)?-log10(xStart):-xStart; y0=(yLog)?-log10(yStart):-yStart; xs=(xLog)?(log10(xEnd)-log10(xStart)):xEnd-xStart;xs=1.0/xs; ys=(yLog)?(log10(yEnd)-log10(yStart)):yEnd-yStart;ys=1.0/ys; } // here zvalue here is zcoord on Z axis, to be scaled between 0 and 1 for compatibility with call of gdlConvertT3DMatrixToPlplotRotationMatrix() zValue /= (zEnd - zStart); plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix(zValue, az, alt, ay, scale, axisExchangeCode); Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0 = x0; Data3d.y0 = y0; Data3d.xs = xs; Data3d.ys = ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } actStream->stransform(gdl3dTo2dTransform, &Data3d); } // make all clipping computations BEFORE setting graphic properties (color, size) bool stopClip=false; if ( doClip ) if ( startClipping(e, actStream, true)==true ) stopClip=true; //will use pClip if needed // LINE_FILL, SPACING, LINESTYLE, ORIENTATION, THICK old code: should be put in line with CONTOUR code (FIXME) static int line_fillIx=e->KeywordIx("LINE_FILL"); if ( e->KeywordSet(line_fillIx) ) { PLINT ori=0, spa=1500; static int orientationIx=e->KeywordIx("ORIENTATION"); if ( e->KeywordSet(orientationIx) ) ori=PLINT(1e1*(*e->GetKWAs(orientationIx))[0]); static int spacingIx=e->KeywordIx("SPACING"); if ( e->KeywordSet(spacingIx) ) spa=PLINT(1e4*(*e->GetKWAs(spacingIx))[0]); gdlSetPenThickness(e, actStream); gdlSetLineStyle(e, actStream); actStream->psty(8); actStream->pat(1, &ori, &spa); } else { actStream->psty(0); } gdlSetLineStyle(e, actStream); //LINESTYLE gdlSetPenThickness(e, actStream); //THICK gdlSetGraphicsForegroundColorFromKw(e, actStream); //COLOR if (real3d) { //try first if the matrix is a plplot-compatible one plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) //use the original !P.T matrix (better than nothing) { Warning("Using Illegal 3D transformation, continuing. (FIXME)"); plplot3d=gdlGetT3DMatrix(); //the original one plplot3d_guard.Reset(plplot3d); Data3d.code = code012; } else { switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } } DDoubleGDL *xValou=new DDoubleGDL(dimension(xEl)); DDoubleGDL *yValou=new DDoubleGDL(dimension(yEl)); Guard xval_guard, yval_guard; xval_guard.reset(xValou); yval_guard.reset(yValou); //rescale to normalized box before conversions --- works for both matrices. gdl3dto2dProjectDDouble(gdlGetScaledNormalizedT3DMatrix(plplot3d),xVal,yVal,zVal,xValou,yValou,Data3d.code); ///TODO: Get proper USerSymSize in 3D. #ifdef USE_LIBPROJ4 if (mapSet) GDLgrProjectedPolygonPlot(actStream, ref, NULL, xVal, yVal, false, true, NULL); else actStream->fill(xEl, static_cast(&(*xValou)[0]), static_cast(&(*yValou)[0])); } else { if (mapSet) GDLgrProjectedPolygonPlot(actStream, ref, NULL, xVal, yVal, false, true, NULL); else actStream->fill(xEl, static_cast(&(*xVal)[0]), static_cast(&(*yVal)[0])); } #else actStream->fill(xEl, static_cast(&(*xValou)[0]), static_cast(&(*yValou)[0])); } else { actStream->fill(xEl, static_cast(&(*xVal)[0]), static_cast(&(*yVal)[0])); } #endif if (stopClip) stopClipping(actStream); } private: virtual void post_call(EnvT*, GDLGStream *actStream) { if (doT3d && !real3d) { plplot3d_guard.Reset(plplot3d); actStream->stransform(NULL,NULL); } if (restorelayout) actStream->RestoreLayout(); actStream->lsty(1); //reset linestyle actStream->psty(0); //reset fill } }; void polyfill(EnvT* e) { polyfill_call polyfill; polyfill.call(e, 1); } } // namespace gdl-0.9.9/src/plotting_shade_surf.cpp000066400000000000000000000406341340051421000176320ustar00rootroot00000000000000/*************************************************************************** plotting_shade_surf.cpp - GDL routines for plotting ------------------- begin : May 07 2013 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; // shared parameter static PLFLT lightSourcePos[3]={1.0,1.0,0.0}; class shade_surf_call: public plotting_routine_call { DDoubleGDL *zVal, *yVal, *xVal; Guard xval_guard, yval_guard, zval_guard, p0_guard; SizeT xEl, yEl, zEl; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd, datamax, datamin; bool nodata; bool setZrange; bool xLog; bool yLog; bool zLog; ORIENTATION3D axisExchangeCode; DLongGDL *shades; Guard shades_guard; bool doShade; private: bool handle_args (EnvT* e) { // in all cases, we have to exit here if ( nParam()==2 || nParam()>3 ) { e->Throw ( "Incorrect number of arguments." ); } // handle Log options passing via Keywords // note: undocumented keywords [xyz]type still exist and // have priority on [xyz]log ! static int xTypeIx = e->KeywordIx( "XTYPE" ); static int yTypeIx = e->KeywordIx( "YTYPE" ); static int zTypeIx = e->KeywordIx( "ZTYPE" ); static int xLogIx = e->KeywordIx( "XLOG" ); static int yLogIx = e->KeywordIx( "YLOG" ); static int zLogIx = e->KeywordIx( "ZLOG" ); static int xTickunitsIx = e->KeywordIx( "XTICKUNITS" ); static int yTickunitsIx = e->KeywordIx( "YTICKUNITS" ); static int zTickunitsIx = e->KeywordIx( "ZTICKUNITS" ); if ( e->KeywordPresent( xTypeIx ) ) xLog = e->KeywordSet( xTypeIx ); else xLog = e->KeywordSet( xLogIx ); if ( e->KeywordPresent( yTypeIx ) ) yLog = e->KeywordSet( yTypeIx ); else yLog = e->KeywordSet( yLogIx ); if ( e->KeywordPresent( zTypeIx ) ) zLog = e->KeywordSet( zTypeIx ); else zLog = e->KeywordSet( zLogIx ); if ( xLog && e->KeywordSet( xTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); xLog = FALSE; } if ( yLog && e->KeywordSet( yTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); yLog = FALSE; } if ( zLog && e->KeywordSet( zTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); zLog = FALSE; } if ( nParam ( ) > 0 ) { // By testing here using EquivalentRank() we avoid computing zval if there was a problem. // AC 2018/04/24 // a sub-array like: a=RANDOMU(seed, 3,4,5) & (this procedure name), a[1,*,*] // should be OK ... if ( (e->GetNumericArrayParDefined ( 0 ))->EquivalentRank ( )!=2 ) e->Throw ( "Array must have 2 dimensions: "+e->GetParString ( 0 ) ); } if ( nParam ( )==1 ) { BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init ( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xEl=zVal->Dim ( 1 ); yEl=zVal->Dim ( 0 ); xVal=new DDoubleGDL ( dimension ( xEl ), BaseGDL::INDGEN ); xval_guard.Init ( xVal ); // delete upon exit if (xLog) xVal->Inc(); yVal=new DDoubleGDL ( dimension ( yEl ), BaseGDL::INDGEN ); yval_guard.Init ( yVal ); // delete upon exit if (yLog) yVal->Inc(); } else { BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init ( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xVal=e->GetParAs< DDoubleGDL>( 1 ); yVal=e->GetParAs< DDoubleGDL>( 2 ); if ( xVal->Rank ( )>2 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( yVal->Rank ( )>2 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( xVal->Rank ( )==0 || yVal->Rank ( )==0 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( xVal->Rank ( )==1 ) { xEl=xVal->Dim ( 0 ); if ( xEl!=zVal->Dim ( 1 ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( yVal->Rank ( )==1 ) { yEl=yVal->Dim ( 0 ); if ( yEl!=zVal->Dim ( 0 ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( xVal->Rank ( )==2 ) { xEl=xVal->Dim ( 0 ); if ( ( xVal->Dim ( 0 )!=zVal->Dim ( 1 ) )&&( xVal->Dim ( 1 )!=zVal->Dim ( 0 ) ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( yVal->Rank ( )==2 ) { yEl=yVal->Dim ( 1 ); if ( ( yVal->Dim ( 0 )!=zVal->Dim ( 1 ) )&&( yVal->Dim ( 1 )!=zVal->Dim ( 0 ) ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } } GetMinMaxVal ( xVal, &xStart, &xEnd ); GetMinMaxVal ( yVal, &yStart, &yEnd ); //XRANGE and YRANGE overrides all that, but Start/End should be recomputed accordingly DDouble xAxisStart, xAxisEnd, yAxisStart, yAxisEnd; bool setx=gdlGetDesiredAxisRange(e, "X", xAxisStart, xAxisEnd); bool sety=gdlGetDesiredAxisRange(e, "Y", yAxisStart, yAxisEnd); if (setx) { xStart=xAxisStart; xEnd=xAxisEnd; } if (sety) { yStart=yAxisStart; yEnd=yAxisEnd; } // z range datamax=0.0; datamin=0.0; GetMinMaxVal ( zVal, &datamin, &datamax ); zStart=datamin; zEnd=datamax; setZrange = gdlGetDesiredAxisRange(e, "Z", zStart, zEnd); //SHADES: Doing the job will be for nothing since plplot does not give the functionality. static int shadesIx=e->KeywordIx ( "SHADES" ); doShade=false; if ( e->GetKW ( shadesIx )!=NULL ) { shades=e->GetKWAs( shadesIx ); doShade=true; } else { // Get COLOR from PLOT system variable DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset shades=new DLongGDL( 1, BaseGDL::NOZERO ); shades_guard.Init ( shades ); // delete upon exit shades=static_cast(pStruct->GetTag(pStruct->Desc()->TagIndex("COLOR"), 0)); doShade=false; } if (doShade) Warning ( "SHADE_SURF: SHADES array ignored, shading with current color table." ); return false; } private: void old_body (EnvT* e, GDLGStream* actStream) // {{{ { //T3D static int t3dIx = e->KeywordIx( "T3D"); bool doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //ZVALUE static int zvIx = e->KeywordIx( "ZVALUE"); DDouble zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); zValue=min(zValue,0.999999); //to avoid problems with plplot //SAVE static int savet3dIx = e->KeywordIx( "SAVE"); bool saveT3d=e->KeywordSet(savet3dIx); //NODATA static int nodataIx = e->KeywordIx( "NODATA"); nodata=e->KeywordSet(nodataIx); // [XYZ]STYLE DLong xStyle=0, yStyle=0, zStyle=0; ; gdlGetDesiredAxisStyle(e, "X", xStyle); gdlGetDesiredAxisStyle(e, "Y", yStyle); gdlGetDesiredAxisStyle(e, "Z", zStyle); //check here since after AutoIntvAC values will be good but arrays passed //to plplot will be bad... if ( xLog && xStart<=0.0 ) { Warning ( "SHADE_SURF: Infinite x plot range." ); nodata=true; } if ( yLog && yStart<=0.0 ) { Warning ( "SHADE_SURF: Infinite y plot range." ); nodata=true; } if ( zLog && zStart<=0.0 ) Warning ( "SHADE_SURF: Infinite z plot range." ); if ( ( xStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "X", xStart, xEnd, xLog ); } if ( ( yStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "Y", yStart, yEnd, yLog ); } static int MIN_VALUEIx = e->KeywordIx( "MIN_VALUE"); static int MAX_VALUEIx = e->KeywordIx( "MAX_VALUE"); bool hasMinVal=e->KeywordPresent(MIN_VALUEIx); bool hasMaxVal=e->KeywordPresent(MAX_VALUEIx); DDouble minVal=datamin; DDouble maxVal=datamax; e->AssureDoubleScalarKWIfPresent ( MIN_VALUEIx, minVal ); e->AssureDoubleScalarKWIfPresent ( MAX_VALUEIx, maxVal ); if (!setZrange) { zStart=max(minVal,zStart); zEnd=min(zEnd,maxVal); } // then only apply expansion of axes: if ( ( zStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange ( e, "Z", zStart, zEnd, zLog ); } // background BEFORE next plot since it is the only place plplot may redraw the background... gdlSetGraphicsBackgroundColorFromKw ( e, actStream ); //BACKGROUND gdlNextPlotHandlingNoEraseOption(e, actStream); //NOERASE // set the PLOT charsize before computing box, see plot command. gdlSetPlotCharsize(e, actStream); // Deal with T3D options -- either present and we have to deduce az and alt contained in it, // or absent and we have to compute !P.T from az and alt. PLFLT alt=30.0; PLFLT az=30.0; //set az and ax (alt) DFloat alt_change=alt; static int AXIx=e->KeywordIx("AX"); e->AssureFloatScalarKWIfPresent(AXIx, alt_change); alt=alt_change; alt=fmod(alt,360.0); //restrict between 0 and 90 for plplot! if (alt > 90.0 || alt < 0.0) { e->Throw ( "SHADE_SURF: AX restricted to [0-90] range by plplot (fix plplot!)" ); } DFloat az_change=az; static int AZIx=e->KeywordIx("AZ"); e->AssureFloatScalarKWIfPresent(AZIx, az_change); az=az_change; //now we are in plplot different kind of 3d DDoubleGDL* plplot3d; DDouble ay, scale; //not useful at this time if (doT3d) //convert to this world... { plplot3d=gdlConvertT3DMatrixToPlplotRotationMatrix(zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw ( "SHADE_SURF: Illegal 3D transformation." ); } } else //make the transformation ourselves { scale=1/sqrt(3.0); //Compute transformation matrix with plplot conventions: plplot3d=gdlComputePlplotRotationMatrix( az, alt, zValue,scale); // save !P.T if asked to... if (saveT3d) //will use ax and az values... { DDoubleGDL* t3dMatrix=plplot3d->Dup(); SelfTranspose3d(t3dMatrix); DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset static unsigned tTag=pStruct->Desc()->TagIndex("T"); for (int i=0; iN_Elements(); ++i )(*static_cast(pStruct->GetTag(tTag, 0)))[i]=(*t3dMatrix)[i]; GDLDelete(t3dMatrix); } } if ( gdlSet3DViewPortAndWorldCoordinates(e, actStream, plplot3d, xLog, yLog, xStart, xEnd, yStart, yEnd, zStart, zEnd, zLog)==FALSE ) return; if (xLog) xStart=log10(xStart); if (yLog) yStart=log10(yStart); if (zLog) zStart=log10(zStart); if (xLog) xEnd=log10(xEnd); if (yLog) yEnd=log10(yEnd); if (zLog) zEnd=log10(zEnd); actStream->w3d(scale,scale,scale*(1.0-zValue), xStart, xEnd, yStart, yEnd, zStart, zEnd, alt, az); //Draw 3d mesh before axes // PLOT ONLY IF NODATA=0 if (!nodata) { //use of intermediate map for correct handling of blanking values and nans. PLFLT ** map; actStream->Alloc2dGrid( &map, xEl, yEl); for ( SizeT i=0, k=0; i mav) v=mav; } else { if ( !isfinite(v) ) v=minVal; if ( hasMinVal && v < minVal) v=minVal; if ( hasMaxVal && v > maxVal) v=maxVal; } map[i][j] = v; } } // 1 types of grid only: 1D X and Y. PLcGrid cgrid1; // X and Y independent deformation PLFLT* xg1; PLFLT* yg1; xg1 = new PLFLT[xEl]; yg1 = new PLFLT[yEl]; cgrid1.xg = xg1; cgrid1.yg = yg1; cgrid1.nx = xEl; cgrid1.ny = yEl; for ( SizeT i=0; i0?log10(cgrid1.xg[i]):1E-12; // #define EXTENDED_DEFAULT_LOGRANGE 12 if (yLog) for ( SizeT i=0; i0?log10(cgrid1.yg[i]):1E-12; // Important: make all clipping computations BEFORE setting graphic properties (color, size) static int NOCLIPIx = e->KeywordIx("NOCLIP"); static int CLIPIx = e->KeywordIx("CLIP"); bool doClip=(e->KeywordSet(CLIPIx)||e->KeywordSet(NOCLIPIx)); bool stopClip=false; if ( doClip ) if ( startClipping(e, actStream)==false ) stopClip=true; gdlSetGraphicsForegroundColorFromKw ( e, actStream ); //mesh option PLINT meshOpt; meshOpt=(doShade)?MAG_COLOR:0; static int SKIRTIx = e->KeywordIx("SKIRT"); if (e->KeywordSet ( SKIRTIx )) meshOpt+=DRAW_SIDES; // Get decomposed value for shades DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); if (doShade) actStream->SetColorMap1DefaultColors(256, decomposed ); else actStream->SetColorMap1Ramp(decomposed, 0.5); //position of light Source. Plplot does not use only the direction of the beam but the position of the illuminating //source. And its illumination looks strange. We try to make the ill. source a bit far in the good direction. PLFLT sun[3]; sun[0]=xStart+(xEnd-xStart)*(0.5+lightSourcePos[0]); sun[1]=yStart+(yEnd-yStart)*(0.5+lightSourcePos[1]); sun[2]=zStart+(zEnd-zStart)*((1.0-zValue)+lightSourcePos[2]); actStream->lightsource(sun[0],sun[1],sun[2]); actStream->surf3d(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt,NULL,0); if (stopClip) stopClipping(actStream); //Clean alllocated data struct delete[] xg1; delete[] yg1; actStream->Free2dGrid(map, xEl, yEl); } //Draw axes with normal color! gdlSetGraphicsForegroundColorFromKw ( e, actStream ); //COLOR gdlBox3(e, actStream, xStart, xEnd, yStart, yEnd, zStart, zEnd, xLog, yLog, zLog, true); } private: void call_plplot (EnvT* e, GDLGStream* actStream) { } private: virtual void post_call (EnvT*, GDLGStream* actStream) { actStream->lsty(1);//reset linestyle actStream->sizeChar(1.0); } }; // SHADE_SURF_call class void shade_surf(EnvT* e) { shade_surf_call shade_surf; shade_surf.call(e, 1); } void set_shading(EnvT* e) { DDoubleGDL *light; static int lightIx=e->KeywordIx ( "LIGHT" ); if ( e->GetKW ( lightIx )!=NULL ) { light=e->GetKWAs( lightIx ); if (light->N_Elements()>3) e->Throw("Keyword array parameter LIGHT must have from 1 to 3 elements."); for (SizeT i=0; i< light->N_Elements(); ++i) lightSourcePos[i]=(*light)[i]; } } } // namespace gdl-0.9.9/src/plotting_surface.cpp000066400000000000000000000417061340051421000171400ustar00rootroot00000000000000/*************************************************************************** plotting_surface.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { //XRANGE etc behaviour not as IDL (in some ways, better!) //TBD: LEGO using namespace std; class surface_call: public plotting_routine_call { DDoubleGDL *zVal, *yVal, *xVal; Guard xval_guard, yval_guard, zval_guard, p0_guard; SizeT xEl, yEl, zEl; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd, datamax, datamin; bool nodata; bool setZrange; bool xLog; bool yLog; bool zLog; ORIENTATION3D axisExchangeCode; private: bool handle_args (EnvT* e) { // in all cases, we have to exit here if ( nParam()==2 || nParam()>3 ) { e->Throw ( "Incorrect number of arguments." ); } // handle Log options passing via Keywords // note: undocumented keywords [xyz]type still exist and // have priority on [xyz]log ! static int xTypeIx = e->KeywordIx( "XTYPE" ); static int yTypeIx = e->KeywordIx( "YTYPE" ); static int zTypeIx = e->KeywordIx( "ZTYPE" ); static int xLogIx = e->KeywordIx( "XLOG" ); static int yLogIx = e->KeywordIx( "YLOG" ); static int zLogIx = e->KeywordIx( "ZLOG" ); static int xTickunitsIx = e->KeywordIx( "XTICKUNITS" ); static int yTickunitsIx = e->KeywordIx( "YTICKUNITS" ); static int zTickunitsIx = e->KeywordIx( "ZTICKUNITS" ); if ( e->KeywordPresent( xTypeIx ) ) xLog = e->KeywordSet( xTypeIx ); else xLog = e->KeywordSet( xLogIx ); if ( e->KeywordPresent( yTypeIx ) ) yLog = e->KeywordSet( yTypeIx ); else yLog = e->KeywordSet( yLogIx ); if ( e->KeywordPresent( zTypeIx ) ) zLog = e->KeywordSet( zTypeIx ); else zLog = e->KeywordSet( zLogIx ); if ( xLog && e->KeywordSet( xTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); xLog = FALSE; } if ( yLog && e->KeywordSet( yTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); yLog = FALSE; } if ( zLog && e->KeywordSet( zTickunitsIx ) ) { Message( "PLOT: LOG setting ignored for Date/Time TICKUNITS." ); zLog = FALSE; } if ( nParam ( ) > 0 ) { // By testing here using EquivalentRank() we avoid computing zval if there was a problem. // AC 2018/04/24 // a sub-array like: a=RANDOMU(seed, 3,4,5) & (this procedure name), a[1,*,*] // should be OK ... if ( (e->GetNumericArrayParDefined ( 0 ))->EquivalentRank ( )!=2 ) e->Throw ( "Array must have 2 dimensions: "+e->GetParString ( 0 ) ); } if ( nParam ( )==1 ) { BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init ( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xEl=zVal->Dim ( 1 ); yEl=zVal->Dim ( 0 ); xVal=new DDoubleGDL ( dimension ( xEl ), BaseGDL::INDGEN ); xval_guard.Init ( xVal ); // delete upon exit if (xLog) xVal->Inc(); yVal=new DDoubleGDL ( dimension ( yEl ), BaseGDL::INDGEN ); yval_guard.Init ( yVal ); // delete upon exit if (yLog) yVal->Inc(); } else { BaseGDL* p0=e->GetNumericArrayParDefined ( 0 )->Transpose ( NULL ); p0_guard.Init ( p0 ); // delete upon exit zVal=static_cast( p0->Convert2 ( GDL_DOUBLE, BaseGDL::COPY ) ); zval_guard.Init ( zVal ); // delete upon exit xVal=e->GetParAs< DDoubleGDL>( 1 ); yVal=e->GetParAs< DDoubleGDL>( 2 ); if ( xVal->Rank ( )>2 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( yVal->Rank ( )>2 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( xVal->Rank ( )==0 || yVal->Rank ( )==0 ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); if ( xVal->Rank ( )==1 ) { xEl=xVal->Dim ( 0 ); if ( xEl!=zVal->Dim ( 1 ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( yVal->Rank ( )==1 ) { yEl=yVal->Dim ( 0 ); if ( yEl!=zVal->Dim ( 0 ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( xVal->Rank ( )==2 ) { xEl=xVal->Dim ( 0 ); if ( ( xVal->Dim ( 0 )!=zVal->Dim ( 1 ) )&&( xVal->Dim ( 1 )!=zVal->Dim ( 0 ) ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } if ( yVal->Rank ( )==2 ) { yEl=yVal->Dim ( 1 ); if ( ( yVal->Dim ( 0 )!=zVal->Dim ( 1 ) )&&( yVal->Dim ( 1 )!=zVal->Dim ( 0 ) ) ) e->Throw ( "X, Y, or Z array dimensions are incompatible." ); } } GetMinMaxVal ( xVal, &xStart, &xEnd ); GetMinMaxVal ( yVal, &yStart, &yEnd ); //XRANGE and YRANGE overrides all that, but Start/End should be recomputed accordingly DDouble xAxisStart, xAxisEnd, yAxisStart, yAxisEnd; bool setx=gdlGetDesiredAxisRange(e, "X", xAxisStart, xAxisEnd); bool sety=gdlGetDesiredAxisRange(e, "Y", yAxisStart, yAxisEnd); if (setx) { xStart=xAxisStart; xEnd=xAxisEnd; } if (sety) { yStart=yAxisStart; yEnd=yAxisEnd; } // z range datamax=0.0; datamin=0.0; GetMinMaxVal ( zVal, &datamin, &datamax ); zStart=datamin; zEnd=datamax; setZrange = gdlGetDesiredAxisRange(e, "Z", zStart, zEnd); return false; } private: void old_body (EnvT* e, GDLGStream* actStream) // {{{ { //T3D static int t3dIx = e->KeywordIx( "T3D"); bool doT3d=(e->KeywordSet(t3dIx)|| T3Denabled()); //ZVALUE static int zvIx = e->KeywordIx( "ZVALUE"); DDouble zValue=0.0; e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); zValue=min(zValue,0.999999); //to avoid problems with plplot //SAVE static int savet3dIx = e->KeywordIx( "SAVE"); bool saveT3d=e->KeywordSet(savet3dIx); //NODATA static int nodataIx = e->KeywordIx( "NODATA"); nodata=e->KeywordSet(nodataIx); //SHADES static int shadesIx = e->KeywordIx( "SHADES"); BaseGDL* shadevalues=e->GetKW ( shadesIx ); bool doShade=(shadevalues != NULL); //... But 3d mesh will be colorized anyway! if (doShade) Warning ( "SURFACE: Using Fixed (Z linear) Shade Values Only (FIXME)." ); // [XYZ]STYLE DLong xStyle=0, yStyle=0, zStyle=0; ; gdlGetDesiredAxisStyle(e, "X", xStyle); gdlGetDesiredAxisStyle(e, "Y", yStyle); gdlGetDesiredAxisStyle(e, "Z", zStyle); //check here since after AutoIntvAC values will be good but arrays passed //to plplot will be bad... if ( xLog && xStart<=0.0 ) { Warning ( "SURFACE: Infinite x plot range." ); nodata=true; } if ( yLog && yStart<=0.0 ) { Warning ( "SURFACE: Infinite y plot range." ); nodata=true; } if ( zLog && zStart<=0.0 ) Warning ( "SURFACE: Infinite z plot range." ); if ( ( xStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e,"X", xStart, xEnd, xLog ); } if ( ( yStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "Y", yStart, yEnd, yLog ); } static int MIN_VALUEIx = e->KeywordIx( "MIN_VALUE"); static int MAX_VALUEIx = e->KeywordIx( "MAX_VALUE"); bool hasMinVal=e->KeywordPresent(MIN_VALUEIx); bool hasMaxVal=e->KeywordPresent(MAX_VALUEIx); DDouble minVal=datamin; DDouble maxVal=datamax; e->AssureDoubleScalarKWIfPresent ( MIN_VALUEIx, minVal ); e->AssureDoubleScalarKWIfPresent ( MAX_VALUEIx, maxVal ); if (!setZrange) { zStart=max(minVal,zStart); zEnd=min(zEnd,maxVal); } // then only apply expansion of axes: if ( ( zStyle&1 )!=1 ) { PLFLT intv=gdlAdjustAxisRange (e, "Z", zStart, zEnd, zLog ); } // background BEFORE next plot since it is the only place plplot may redraw the background... gdlSetGraphicsBackgroundColorFromKw ( e, actStream ); //BACKGROUND gdlNextPlotHandlingNoEraseOption(e, actStream); //NOERASE // set the PLOT charsize before computing box, see plot command. gdlSetPlotCharsize(e, actStream); // Deal with T3D options -- either present and we have to deduce az and alt contained in it, // or absent and we have to compute !P.T from az and alt. PLFLT alt=30.0; PLFLT az=30.0; //set az and ax (alt) DFloat alt_change=alt; static int AXIx=e->KeywordIx("AX"); e->AssureFloatScalarKWIfPresent(AXIx, alt_change); alt=alt_change; alt=fmod(alt,360.0); //restrict between 0 and 90 for plplot! if (alt > 90.0 || alt < 0.0) { e->Throw ( "SURFACE: AX restricted to [0-90] range by plplot (fix plplot!)" ); } DFloat az_change=az; static int AZIx=e->KeywordIx("AZ"); e->AssureFloatScalarKWIfPresent(AZIx, az_change); az=az_change; //now we are in plplot different kind of 3d DDoubleGDL* plplot3d; DDouble ay, scale; //not useful at this time if (doT3d) //convert to this world... { plplot3d=gdlConvertT3DMatrixToPlplotRotationMatrix(zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw ( "SURFACE: Illegal 3D transformation." ); } } else //make the transformation ourselves { scale=1/sqrt(3.0); //Compute transformation matrix with plplot conventions: plplot3d=gdlComputePlplotRotationMatrix( az, alt, zValue,scale); // save !P.T if asked to... if (saveT3d) //will use ax and az values... { DDoubleGDL* t3dMatrix=plplot3d->Dup(); SelfTranspose3d(t3dMatrix); DStructGDL* pStruct=SysVar::P(); //MUST NOT BE STATIC, due to .reset static unsigned tTag=pStruct->Desc()->TagIndex("T"); for (int i=0; iN_Elements(); ++i )(*static_cast(pStruct->GetTag(tTag, 0)))[i]=(*t3dMatrix)[i]; GDLDelete(t3dMatrix); } } if ( gdlSet3DViewPortAndWorldCoordinates(e, actStream, plplot3d, xLog, yLog, xStart, xEnd, yStart, yEnd, zStart, zEnd, zLog)==FALSE ) return; if (xLog) xStart=log10(xStart); if (yLog) yStart=log10(yStart); if (zLog) zStart=log10(zStart); if (xLog) xEnd=log10(xEnd); if (yLog) yEnd=log10(yEnd); if (zLog) zEnd=log10(zEnd); actStream->w3d(scale,scale,scale*(1.0-zValue), xStart, xEnd, yStart, yEnd, zStart, zEnd, alt, az); static int UPPER_ONLYIx = e->KeywordIx( "UPPER_ONLY"); static int LOWER_ONLYIx = e->KeywordIx( "LOWER_ONLY"); bool up=e->KeywordSet ( UPPER_ONLYIx ); bool low=e->KeywordSet ( LOWER_ONLYIx ); if (up && low) nodata=true; //IDL behaviour DLong bottomColorIndex=-1; static int BOTTOMIx = e->KeywordIx( "BOTTOM"); e->AssureLongScalarKWIfPresent(BOTTOMIx, bottomColorIndex); //Draw 3d mesh before axes // PLOT ONLY IF NODATA=0 if (!nodata) { //use of intermediate map for correct handling of blanking values and nans. PLFLT ** map; actStream->Alloc2dGrid( &map, xEl, yEl); for ( SizeT i=0, k=0; i mav) v=mav; } else { if ( !isfinite(v) ) v=minVal; if ( hasMinVal && v < minVal) v=minVal; if ( hasMaxVal && v > maxVal) v=maxVal; } map[i][j] = v; } } // 1 types of grid only: 1D X and Y. PLcGrid cgrid1; // X and Y independent deformation PLFLT* xg1; PLFLT* yg1; xg1 = new PLFLT[xEl]; yg1 = new PLFLT[yEl]; cgrid1.xg = xg1; cgrid1.yg = yg1; cgrid1.nx = xEl; cgrid1.ny = yEl; for ( SizeT i=0; i0?log10(cgrid1.xg[i]):1E-12; // #define EXTENDED_DEFAULT_LOGRANGE 12 if (yLog) for ( SizeT i=0; i0?log10(cgrid1.yg[i]):1E-12; // Important: make all clipping computations BEFORE setting graphic properties (color, size) static int NOCLIPIx = e->KeywordIx("NOCLIP"); static int CLIPIx = e->KeywordIx("CLIP"); bool doClip=(e->KeywordSet(CLIPIx)||e->KeywordSet(NOCLIPIx)); bool stopClip=false; if ( doClip ) if ( startClipping(e, actStream)==true ) stopClip=true; gdlSetGraphicsForegroundColorFromKw ( e, actStream ); //mesh option PLINT meshOpt; meshOpt=DRAW_LINEXY; static int HORIZONTALIx = e->KeywordIx("HORIZONTAL"); if (e->KeywordSet ( HORIZONTALIx )) meshOpt=DRAW_LINEX; static int SKIRTIx = e->KeywordIx("SKIRT"); if (e->KeywordSet ( SKIRTIx )) meshOpt+=DRAW_SIDES; //mesh plots both sides, so use it when UPPER_ONLY is not set. //if UPPER_ONLY is set, use plot3d/plot3dc //if LOWER_ONLY is set, use mesh/meshc and remove by plot3d! //in not up not low: mesh since mesh plots both sides if (up) { if (doShade) actStream->plot3dc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt+MAG_COLOR,NULL,0); else actStream->plot3dc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt,NULL,0); } else //mesh (both sides) but contains 'low' (remove top) and/or bottom { if (bottomColorIndex!=-1) { gdlSetGraphicsForegroundColorFromKw ( e, actStream, "BOTTOM" ); actStream->meshc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt,NULL,0); gdlSetGraphicsForegroundColorFromKw ( e, actStream ); if (!low) //redraw top with top color { if (doShade) actStream->plot3dc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt+MAG_COLOR,NULL,0); else actStream->plot3dc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt,NULL,0); } } else { if (doShade) actStream->meshc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt+MAG_COLOR,NULL,0); else actStream->meshc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt,NULL,0); } //redraw upper part with background color to remove it... Not 100% satisfying though. if (low) { if (e->KeywordSet ( SKIRTIx )) meshOpt-=DRAW_SIDES; gdlSetGraphicsPenColorToBackground(actStream); actStream->plot3dc(xg1,yg1,map,cgrid1.nx,cgrid1.ny,meshOpt,NULL,0); gdlSetGraphicsForegroundColorFromKw ( e, actStream ); } } if (stopClip) stopClipping(actStream); //Clean allocated data struct delete[] xg1; delete[] yg1; actStream->Free2dGrid(map, xEl, yEl); } //Draw axes with normal color! gdlSetGraphicsForegroundColorFromKw ( e, actStream ); //COLOR gdlBox3(e, actStream, xStart, xEnd, yStart, yEnd, zStart, zEnd, xLog, yLog, zLog, true); } private: void call_plplot (EnvT* e, GDLGStream* actStream) { } private: virtual void post_call (EnvT*, GDLGStream* actStream) { actStream->lsty(1);//reset linestyle actStream->sizeChar(1.0); } }; // surface_call class void surface(EnvT* e) { surface_call surface; surface.call(e, 1); } } // namespace gdl-0.9.9/src/plotting_windows.cpp000066400000000000000000000156361340051421000172050ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" namespace lib { using namespace std; void window( EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); int maxWin = actDevice->MaxWin(); if( maxWin == 0) e->Throw( "Routine is not defined for current graphics device."); SizeT nParam=e->NParam(); DLong wIx = 0; static int FREEIx = e->KeywordIx("FREE"); static int TITLEIx = e->KeywordIx("TITLE"); static int XPOSIx = e->KeywordIx("XPOS"); static int YPOSIx = e->KeywordIx("YPOS"); static int XSIZEIx = e->KeywordIx("XSIZE"); static int YSIZEIx = e->KeywordIx("YSIZE"); static int RETAINIx = e->KeywordIx("RETAIN"); static int PIXMAPIx = e->KeywordIx("PIXMAP"); if( e->KeywordSet(FREEIx)) { wIx = actDevice->WAddFree(); if( wIx == -1) e->Throw( "No more window handles left."); } else { if( nParam == 1) { e->AssureLongScalarPar( 0, wIx); if( wIx < 0 || wIx >= actDevice->MaxNonFreeWin()) //to comply with IDL e->Throw( "Window number "+i2s(wIx)+ " out of range or no more windows."); } } DString title; if( e->KeywordPresent(TITLEIx)) { e->AssureStringScalarKWIfPresent( TITLEIx, title); } else { title = "GDL "+i2s( wIx); } DLong xPos=-1, yPos=-1; //NOTE: xPos=-1 and yPos=-1 are when XPOS and YPOS options were not used! e->AssureLongScalarKWIfPresent( XPOSIx, xPos); e->AssureLongScalarKWIfPresent( YPOSIx, yPos); DLong xSize, ySize; actDevice->DefaultXYSize(&xSize, &ySize); e->AssureLongScalarKWIfPresent( XSIZEIx, xSize); e->AssureLongScalarKWIfPresent( YSIZEIx, ySize); int debug=0; if (debug) { cout << "input values :"<< endl; cout << "xPos/yPos :"<< xPos << " " << yPos << endl; cout << "xSize/ySize :"<< xSize << " " << ySize << endl; } if (xSize < 0) xSize=10000; if (ySize < 0) ySize=10000; //NOTE: xPos=-1 and yPos=-1 are when XPOS and YPOS options were not used! // AC 2014/02/26: this seems to be not need as long as xSize/ySize > 0 // which is done above // if( xSize <= 0 || ySize <= 0 || xPos < -1 || yPos < -1) // e->Throw( "Unable to create window " // "(BadValue (integer parameter out of range for operation))."); DLong retainType = 0; if( e->KeywordPresent( RETAINIx)) { e->AssureLongScalarKWIfPresent( RETAINIx, retainType); } bool success = actDevice->SetBackingStore(retainType); bool hide=e->KeywordSet( PIXMAPIx); success = actDevice->WOpen( wIx, title, xSize, ySize, xPos, yPos, hide); if( !success) e->Throw( "Unable to create window."); if ( e->KeywordSet( PIXMAPIx)) { success = actDevice->Hide(); } else success = actDevice->UnsetFocus(); actDevice->GetStream()->DefaultBackground(); actDevice->GetStream()->Clear(); } void wset(EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); int maxWin = actDevice->MaxWin(); if (maxWin == 0) e->Throw("Routine is not defined for current graphics device."); SizeT nParam = e->NParam(); DLong wIx = 0; if (nParam != 0) { e->AssureLongScalarPar(0, wIx); } //special case for "WSET,-1" if (wIx == -1) { wIx = actDevice->GetNonManagedWidgetActWin(); if (wIx == -1) {//set !D.WINDOW to -1: no windows available, only *managed* widgets are eventually present. actDevice->SetActWin(wIx); //this simply sets !D.WINDOW to -1. return; } } if (wIx == 0) { if (actDevice->ActWin() == -1) { DLong xSize, ySize; actDevice->DefaultXYSize(&xSize, &ySize); bool success = actDevice->WOpen(0, "GDL 0", xSize, ySize, -1, -1, false); if (!success) e->Throw("Unable to create window."); // success = actDevice->UnsetFocus(); // following a deviceXXX->WOpen //FIXME: ADD support for RETAIN (BackingSTORE)) actDevice->GetStream()->DefaultBackground(); actDevice->GetStream()->Clear(); return; } } bool success = actDevice->WSet(wIx); if (!success) e->Throw("Window is closed and unavailable."); } void wshow( EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); int maxWin = actDevice->MaxWin(); if( maxWin == 0) e->Throw( "Routine is not defined for current graphics device."); SizeT nParam=e->NParam(); DLong wIx = 0; if (nParam != 0) e->AssureLongScalarPar( 0, wIx); else wIx = actDevice->ActWin(); // note by AC on 2012-Aug-16 // On the system I tested (Ubuntu 10.4), I was not able to have // the expected SHOW behavior, with IDL 7.0 and GDL :( // Help/suggestions welcome // works for me (GD) on mandriva 2010.2 bool show = true; if (nParam == 2) { DIntGDL *showval = e->GetParAs(1); show = (*showval)[0] != 0; } int iconic = -1; //signals absent parameter static int ICONICIx = e->KeywordIx("ICONIC"); if( e->KeywordPresent(ICONICIx)) iconic=e->KeywordSet(ICONICIx); if (!actDevice->WShow( wIx, show, iconic)) e->Throw( "Window number "+i2s(wIx)+" out of range or no more windows."); } void wdelete( EnvT* e) { GraphicsDevice* actDevice = GraphicsDevice::GetDevice(); int maxWin = actDevice->MaxWin(); if( maxWin == 0) e->Throw( "Routine is not defined for current graphics device."); SizeT nParam=e->NParam(); if( nParam == 0) { DLong wIx = actDevice->ActWin(); bool success = actDevice->WDelete( wIx); if( !success) e->Throw( "Window number "+i2s(wIx)+ " invalid or no more windows."); return; } for( SizeT i=0; iAssureLongScalarPar( i, wIx); bool success = actDevice->WDelete( wIx); if( !success) e->Throw( "Window number "+i2s(wIx)+ " invalid or no more windows."); } } } // namespace gdl-0.9.9/src/plotting_xyouts.cpp000066400000000000000000000407101340051421000170550ustar00rootroot00000000000000/*************************************************************************** plotting.cpp - GDL routines for plotting ------------------- begin : July 22 2002 copyright : (C) 2002-2011 by Marc Schellens et al. email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "plotting.hpp" #define DPI (double)(4*atan(1.0)) #define DEGTORAD DPI/180.0 namespace lib { using namespace std; static DDouble lastTextPosX=0.0; static DDouble lastTextPosY=0.0; class xyouts_call: public plotting_routine_call { PLFLT currentBoxXmin, currentBoxXmax, currentBoxYmin, currentBoxYmax, currentBoxZmin, currentBoxZmax; PLFLT vpXmin, vpXmax, vpYmin, vpYmax; DDoubleGDL *xVal, *yVal, *zVal; Guard xval_guard, yval_guard, zval_guard; DDouble xStart, xEnd, yStart, yEnd, zStart, zEnd; DStringGDL* strVal; SizeT xEl, yEl, zEl, strEl; SizeT minEl; bool xLog, yLog, zLog; bool restorelayout; bool doClip, restoreClipBox; PLFLT savebox[4]; bool kwWidth; PLFLT width; DLongGDL *color; DFloatGDL *spacing,*orientation,*charthick,*alignement,*size; Guard alignement_guard, orientation_guard,size_guard; bool doT3d; DDoubleGDL* plplot3d; Guard plplot3d_guard; bool singleArg; DDouble zValue; ORIENTATION3D axisExchangeCode; DDouble az, alt, ay, scale; enum { DATA=0, NORMAL, DEVICE } coordinateSystem; private: bool handle_args(EnvT* e) { //T3D static int t3dIx = e->KeywordIx( "T3D"); doT3d=(e->KeywordSet(t3dIx) || T3Denabled()); //note: Z (VALUE) will be used uniquely if Z is not effectively defined. // Then Z is useful only if (doT3d). static int zvIx = e->KeywordIx( "Z"); zValue=0.0; if (doT3d) e->AssureDoubleScalarKWIfPresent ( zvIx, zValue ); singleArg=false; if ( nParam()==1 ) { singleArg=true; //string only... xVal=new DDoubleGDL(1, BaseGDL::ZERO); xval_guard.Reset(xVal); // delete upon exit yVal=new DDoubleGDL(1, BaseGDL::ZERO); yval_guard.Reset(yVal); // delete upon exit xEl=yEl=xVal->N_Elements(); strVal=e->GetParAs(0); strEl=strVal->N_Elements(); zVal=new DDoubleGDL(1); zval_guard.Reset(zVal); // delete upon exit (*zVal)[0]=zValue; minEl=strEl; //in this case only } else if ( nParam()==3 ) { xVal=e->GetParAs< DDoubleGDL>(0); xEl=xVal->N_Elements(); yVal=e->GetParAs< DDoubleGDL>(1); yEl=yVal->N_Elements(); strVal=e->GetParAs(2); strEl=strVal->N_Elements(); //behaviour: if x or y are not an array, they are repeated to match minEl //if x or y have less elements than s, minEl is max(x,y) else minEl is size(s) //z will be set at Zero unless Z=value is given if ( (xVal->Dim(0)==0) && (yVal->Dim(0)==0) ) { minEl=strEl; DDoubleGDL* tmpxVal=e->GetParAs< DDoubleGDL>(0); xVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); //should remove previous xVal if allocated -- fixme. xval_guard.Reset(xVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[0]; DDoubleGDL* tmpyVal=e->GetParAs< DDoubleGDL>(1); yVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); //idem and below yval_guard.Reset(yVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[0]; } else if (xVal->Dim(0)==0) { minEl=(yElGetParAs< DDoubleGDL>(0); xVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); xval_guard.Reset(xVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*xVal)[i]=(*tmpxVal)[0]; } else if (yVal->Dim(0)==0) { minEl=(xElGetParAs< DDoubleGDL>(1); yVal=new DDoubleGDL(minEl, BaseGDL::NOZERO); yval_guard.Reset(yVal); // delete upon exit for (SizeT i=0; i< minEl ; ++i) (*yVal)[i]=(*tmpyVal)[0]; } else { minEl=(xElThrow("Not enough parameters. Either 1 parameter or 3 " "parameters valid."); } if ( doT3d ) { //test to avois passing a non-rotation matrix to plplots's stransform. plplot limitation-> FIXME! plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix( zValue, az, alt, ay, scale, axisExchangeCode); if (plplot3d == NULL) { e->Throw("Illegal 3D transformation. (FIXME)"); } else GDLDelete(plplot3d); } return true; } private: void getTextPos(GDLGStream *a, DDouble &wx, DDouble &wy) { a->DeviceToWorld(lastTextPosX, lastTextPosY, wx, wy); if (GDL_DEBUG_PLSTREAM) fprintf(stderr,"getTextPos: Got norm: %lf %lf giving %lf %lf world\n", lastTextPosX, lastTextPosY, wx, wy); } void old_body(EnvT* e, GDLGStream* actStream) { // WIDTH keyword (read, write) static int widthIx=e->KeywordIx("WIDTH"); kwWidth=e->KeywordPresent(widthIx); width=0.; //check presence of DATA,DEVICE and NORMAL options static int DATAIx=e->KeywordIx("DATA"); static int DEVICEIx=e->KeywordIx("DEVICE"); static int NORMALIx=e->KeywordIx("NORMAL"); coordinateSystem = DATA; //check presence of DATA,DEVICE and NORMAL options if (e->KeywordSet(DATAIx)) coordinateSystem = DATA; if (e->KeywordSet(DEVICEIx)) coordinateSystem = DEVICE; if (e->KeywordSet(NORMALIx)) coordinateSystem = NORMAL; //T3D incompatible with DEVICE option. if (coordinateSystem == DEVICE) doT3d =false; // get_axis_type gdlGetAxisType("X", xLog); gdlGetAxisType("Y", yLog); gdlGetAxisType("Z", zLog); //get DATA limits (not necessary CRANGE, see AXIS / SAVE behaviour!) GetCurrentUserLimits(actStream, xStart, xEnd, yStart, yEnd); // get !Z.CRANGE gdlGetCurrentAxisRange("Z", zStart, zEnd); if (zStart != 0.0 && zStart == zEnd) { Message("PLOTS: !Z.CRANGE ERROR, setting to [0,1]"); zStart = 0; zEnd = 1; } int noclipvalue=1; static int NOCLIPIx = e->KeywordIx("NOCLIP"); e->AssureLongScalarKWIfPresent( NOCLIPIx, noclipvalue); doClip=(noclipvalue==0); //XYOUTS by default does not clip, even if clip is defined by CLIP= or !P.CLIP, and CONTRARY TO THE DOCUMENTATION!!!! restorelayout=true; bool mapSet=false; #ifdef USE_LIBPROJ4 get_mapset(mapSet); mapSet=(mapSet && coordinateSystem==DATA); if ( mapSet ) { ref=map_init(); if ( ref==NULL ) { e->Throw("Projection initialization failed."); } restorelayout=true; } #endif if ( doT3d ) { doClip=false; //impossible to clip in 3d using plplot. we should do it ourselves. restorelayout=false; } else { if (restorelayout) actStream->OnePageSaveLayout(); // one page actStream->vpor(0, 1, 0, 1); //ALL PAGE if ( coordinateSystem==DEVICE ) { actStream->wind(0.0, actStream->xPageSize(), 0.0, actStream->yPageSize()); xLog=false; yLog=false; } else if ( coordinateSystem==NORMAL ) { actStream->wind(0, 1, 0, 1); xLog=false; yLog=false; } else //with XYOUTS, we can plot *outside* the box(e)s in DATA coordinates. { setPlplotScale(actStream); } } PLFLT x,y,aspectw,aspectd; aspectw=actStream->boxAspectWorld(); aspectd=actStream->boxAspectDevice(); static int colorIx=e->KeywordIx ( "COLOR" ); bool docolor=false; static int charthickIx=e->KeywordIx ( "CHARTHICK" ); bool docharthick=false; static int charsizeIx=e->KeywordIx ( "CHARSIZE" ); bool docharsize=false; if ( e->GetKW ( colorIx )!=NULL ) { color=e->GetKWAs( colorIx ); docolor=true; } if ( e->GetKW ( charthickIx )!=NULL ) { charthick=e->GetKWAs( charthickIx ); docharthick=true; } if ( e->GetKW ( charsizeIx )!=NULL ) { size=e->GetKWAs( charsizeIx ); docharsize=true; } else //for security in future conditional evaluation... { size=new DFloatGDL ( dimension (1), BaseGDL::ZERO ); size_guard.Init ( size); (*size)[0]=1.0; } static int orientationIx=e->KeywordIx ( "ORIENTATION" ); if ( e->GetKW ( orientationIx )!=NULL ) { orientation=e->GetKWAs( orientationIx ); } else { orientation=new DFloatGDL ( dimension (1), BaseGDL::ZERO ); orientation_guard.Init ( orientation); (*orientation)[0]=0; } static int alignIx=e->KeywordIx ( "ALIGNMENT" ); if ( e->GetKW ( alignIx )!=NULL ) { alignement=e->GetKWAs( alignIx ); } else { alignement=new DFloatGDL ( dimension (1), BaseGDL::ZERO ); alignement_guard.Init (alignement); (*alignement)[0]=0; } // make all clipping computations BEFORE setting graphic properties (color, size) bool stopClip=false; if ( doClip ) if ( startClipping(e, actStream, true)==true ) stopClip=true; // *** start drawing by defalut values gdlSetGraphicsForegroundColorFromKw(e, actStream); if (!docharthick) gdlSetPlotCharthick(e, actStream); if (!docharsize) gdlSetPlotCharsize(e, actStream, true); //accept SIZE kw! if (doT3d) { //set up plplot 3D transform // case where we project 2D data on 3D: use plplot-like matrix. static DDouble x0,y0,xs,ys; //conversion to normalized coords if (coordinateSystem==NORMAL) {; x0=0;y0=0;xs=1.0;ys=1.0; } else { x0=(xLog)?-log10(xStart):-xStart; y0=(yLog)?-log10(yStart):-yStart; xs=(xLog)?(log10(xEnd)-log10(xStart)):xEnd-xStart;xs=1.0/xs; ys=(yLog)?(log10(yEnd)-log10(yStart)):yEnd-yStart;ys=1.0/ys; } DDouble az, alt, ay, scale; // here zvalue here is zcoord on Z axis, to be scaled between 0 and 1 for compatibility with call of gdlConvertT3DMatrixToPlplotRotationMatrix() zValue /= (zEnd - zStart); plplot3d = gdlConvertT3DMatrixToPlplotRotationMatrix(zValue, az, alt, ay, scale, axisExchangeCode); //if matrix was not checked to be ok at start, we could authorize a non_rotation matrix, but would have to avoid using stransform. Data3d.zValue = zValue; Data3d.Matrix = plplot3d; //try to change for !P.T in future? Data3d.x0 = x0; Data3d.y0 = y0; Data3d.xs = xs; Data3d.ys = ys; switch (axisExchangeCode) { case NORMAL3D: //X->X Y->Y plane XY Data3d.code = code012; break; case XY: // X->Y Y->X plane XY Data3d.code = code102; break; case XZ: // Y->Y X->Z plane YZ Data3d.code = code210; break; case YZ: // X->X Y->Z plane XZ Data3d.code = code021; break; case XZXY: //X->Y Y->Z plane YZ Data3d.code = code120; break; case XZYZ: //X->Z Y->X plane XZ Data3d.code = code201; break; } actStream->stransform(gdl3dTo2dTransform, &Data3d); } // Get decomposed value for colors DLong decomposed=GraphicsDevice::GetDevice()->GetDecomposed(); DDouble *sx, *sy, *sz; GetSFromPlotStructs(&sx, &sy, &sz); for ( SizeT i=0; i((*xVal)[i%xVal->N_Elements ( )]); //insure even 1 parameter, string array y=static_cast((*yVal)[i%xVal->N_Elements ( )]); #ifdef USE_LIBPROJ4 if ( mapSet ) { LPTYPE idata; XYTYPE odata; idata.u=x * DEG_TO_RAD; idata.v=y * DEG_TO_RAD; odata=PJ_FWD(idata, ref); x=odata.u; y=odata.v; } #endif if ( coordinateSystem==DATA ) { //in case 3d matrix, the matrix transform above is in log, so coordinates must be in log. if( xLog ) x=log10(x); if( yLog ) y=log10(y); } if ( !isfinite(x)|| !isfinite(y) ) continue; //no plot if ( docharsize && ( *size )[i%size->N_Elements ( )] < 0) continue; //no plot either //plot! if (docharsize) actStream->sizeChar(( *size )[i%size->N_Elements ( )]); if (docolor) actStream->Color ( ( *color )[i%color->N_Elements ( )], decomposed); if (docharthick) actStream->Thick(( *charthick )[i%charthick->N_Elements()]); //orientation word is not orientation page depending on axes increment direction [0..1] vs. [1..0] PLFLT oriD=(( *orientation )[i%orientation->N_Elements ( )]); //ori DEVICE PLFLT oriW=oriD; //ori WORLD oriD *= DEGTORAD; if (sx[1]<0) oriW=180.0-oriW; if (sy[1]<0) oriW*=-1; oriW *= DEGTORAD; PLFLT cosOriD=cos(oriD); PLFLT sinOriD=sin(oriD); PLFLT cosOriW=cos(oriW); PLFLT sinOriW=sin(oriW); PLFLT align=( *alignement )[i%alignement->N_Elements ( )]; align=max(align,0.0); align=min(align,1.0); PLFLT dispx,dispy, chsize, dx, dy; // displacement due to offset (reference in IDL is baseline, // in plplot it's the half-height) is best computed in device coords chsize=actStream->dCharHeight()*0.5; actStream->WorldToDevice(x, y, dx, dy); actStream->DeviceToWorld(dx-chsize*sinOriD,dy+chsize*cosOriD,dispx,dispy); string out=(*strVal)[i%strVal->N_Elements ( )]; double returnedStringCharLength; actStream->ptex(dispx, dispy, cosOriW, sinOriW*aspectw/aspectd, align, out.c_str(), &returnedStringCharLength); if (singleArg || (i==minEl-1 ) ) //then x and y are not given and whatever the number of strings, are retrieved // from lastTextPos. We must thus remember lastTextPos. { //we want normed size: width=returnedStringCharLength*actStream->nCharLength(); //save position - compute must be in DEVICE coords, or in normed*aspect! actStream->WorldToNormedDevice(x, y, dx, dy); //normed actStream->NormedDeviceToWorld(dx+(1.0-align)*width*cosOriD,dy+(1.0-align)*width*sinOriD/aspectd,dispx,dispy); actStream->WorldToDevice(dispx, dispy, lastTextPosX, lastTextPosY); } } if (stopClip) stopClipping(actStream); if ( kwWidth ) { // width is in "normalized coordinates" e->SetKW(widthIx, new DFloatGDL(width)); } } private: void call_plplot(EnvT* e, GDLGStream* actStream) // {{{ { } private: virtual void post_call(EnvT* e, GDLGStream* actStream) // {{{ { if (doT3d) { plplot3d_guard.Reset(plplot3d); actStream->stransform(NULL,NULL); } if (restorelayout) actStream->RestoreLayout(); actStream->sizeChar(1.0); } }; void xyouts(EnvT* e) { xyouts_call xyouts; xyouts.call(e, 1); } } // namespace gdl-0.9.9/src/plplot_wxwidgets.h000066400000000000000000000471661340051421000166620ustar00rootroot00000000000000// $Id: plplot_wxwidgets.h,v 1.1 2014-09-21 15:15:08 pjb7687 Exp $ // // Copyright (C) 2008 Werner Smekal // // This file is part of PLplot. // // PLplot is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published // by the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PLplot 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 Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with PLplot; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef __WXWIDGETS_H__ #define __WXWIDGETS_H__ // some special wxWidgets headers #include // freetype headers and macros #ifdef PL_HAVE_FREETYPE #include "plfreetype.h" #endif #ifndef max_number_of_grey_levels_used_in_text_smoothing #define max_number_of_grey_levels_used_in_text_smoothing 64 #endif #define NDEV 100 // Max number of output device types in menu //-------------------------------------------------------------------------- // Physical dimension constants used by the driver // Virtual coordinate scaling parameter, used to do calculations at // higher resolution. Chosen so that maximum plP_setphy coordinate // is 32000 which is close to but still less than the maximum possible // which is 32767. // // The trick here is to do everything in device coordinates on the driver // side, but report/receive everything in virtual coordinates to/from the // PLplot core. // #define VSCALE ( 40. ) // pixels per inch #define DEVICE_PIXELS_PER_IN ( 80. ) #define VIRTUAL_PIXELS_PER_IN ( DEVICE_PIXELS_PER_IN * VSCALE ) // mm per inch #define MM_PER_IN ( 25.4 ) // pixels per mm #define DEVICE_PIXELS_PER_MM ( DEVICE_PIXELS_PER_IN / MM_PER_IN ) #define VIRTUAL_PIXELS_PER_MM ( VIRTUAL_PIXELS_PER_IN / MM_PER_IN ) // Default dimensions of the canvas (in inches) #define CANVAS_WIDTH ( 10.0 ) #define CANVAS_HEIGHT ( 7.5 ) // size of plot in pixels on screen if not given #define PLOT_WIDTH ( 800 ) #define PLOT_HEIGHT ( 600 ) // These need to be distinguished since the handling is slightly different. #define LOCATE_INVOKED_VIA_API 1 #define LOCATE_INVOKED_VIA_DRIVER 2 // Available backends #define wxBACKEND_DC 0 #define wxBACKEND_AGG 1 #define wxBACKEND_GC 2 class wxPLplotFrame; // base device class class wxPLDevBase { public: // methods wxPLDevBase( int bcknd ); virtual ~wxPLDevBase( void ); // virtual functions which need to implemented virtual void DrawLine( short x1a, short y1a, short x2a, short y2a ) = 0; virtual void DrawPolyline( short *xa, short *ya, PLINT npts ) = 0; virtual void ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1 = -1, PLINT y1 = -1, PLINT x2 = -1, PLINT y2 = -1 ) = 0; virtual void FillPolygon( PLStream *pls ) = 0; virtual void BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH ) = 0; void AddtoClipRegion( int x1, int y1, int x2, int y2 ); virtual void CreateCanvas() = 0; virtual void SetWidth( PLStream *pls ) = 0; virtual void SetColor0( PLStream *pls ) = 0; virtual void SetColor1( PLStream *pls ) = 0; virtual void SetExternalBuffer( void* buffer ) = 0; #ifdef PL_HAVE_FREETYPE virtual void PutPixel( short x, short y, PLINT color ) = 0; virtual void PutPixel( short x, short y ) = 0; virtual PLINT GetPixel( short x, short y ) = 0; #endif // PL_HAVE_FREETYPE virtual void ProcessString( PLStream* pls, EscText* args ) = 0; virtual void PSDrawText( PLUNICODE* ucs4, int ucs4Len, bool drawText ); virtual void PSDrawTextToDC( char* utf8_string, bool drawText ) = 0; virtual void PSSetFont( PLUNICODE fci ) = 0; public: // variables const int backend; bool ready; bool ownGUI; bool showGUI; bool waiting; bool resizing; bool exit; int comcount; wxPLplotFrame* m_frame; PLINT xpos; PLINT ypos; PLINT width; PLINT height; PLINT bm_width; PLINT bm_height; PLINT xmin; PLINT xmax; PLINT ymin; PLINT ymax; PLFLT scalex; PLFLT scaley; bool plstate_width; // Flags indicating change of state before bool plstate_color0; // device is fully initialized bool plstate_color1; // taken from gcw driver PLGraphicsIn gin; // Graphics input structure int locate_mode; // Set while in locate mode bool draw_xhair; // Set during xhair draws // clipping region int clipminx, clipmaxx; int clipminy, clipmaxy; bool newclipregion; // variables for antializing int freetype; int smooth_text; const char ** devDesc; // Descriptive names for file-oriented devices. Malloc'ed. const char ** devName; // Keyword names of file-oriented devices. Malloc'ed. int ndev; wxBitmapType bitmapType; // font variables static const int max_string_length = 500; wxFont * m_font; bool underlined; double fontSize; double fontScale; wxCoord textWidth, textHeight, textDescent, textLeading; PLUNICODE fci; //the distance between the superscript top and subscript base from the baseline wxCoord superscriptHeight, subscriptDepth; double lineSpacing; double yOffset; PLINT posX, posY; PLFLT rotation, cos_rot, sin_rot; PLFLT shear, cos_shear, sin_shear; PLFLT stride; }; class wxPLDevDC : public wxPLDevBase { public: // methods wxPLDevDC( void ); ~wxPLDevDC( void ); void DrawLine( short x1a, short y1a, short x2a, short y2a ); void DrawPolyline( short *xa, short *ya, PLINT npts ); void ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1 = -1, PLINT y1 = -1, PLINT x2 = -1, PLINT y2 = -1 ); void FillPolygon( PLStream *pls ); void BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH ); void CreateCanvas(); void SetWidth( PLStream *pls ); void SetColor0( PLStream *pls ); void SetColor1( PLStream *pls ); void SetExternalBuffer( void* buffer ); #ifdef PL_HAVE_FREETYPE void PutPixel( short x, short y, PLINT color ); void PutPixel( short x, short y ); PLINT GetPixel( short x, short y ); #endif // PL_HAVE_FREETYPE void ProcessString( PLStream* pls, EscText* args ); void PSDrawTextToDC( char* utf8_string, bool drawText ); void PSSetFont( PLUNICODE fci ); private: // variables wxBitmap* m_bitmap; wxDC * m_dc; }; #ifdef HAVE_AGG // antigrain headers #include "agg2/agg_basics.h" #include "agg2/agg_rendering_buffer.h" #include "agg2/agg_rasterizer_scanline_aa.h" #include "agg2/agg_scanline_u.h" #include "agg2/agg_scanline_bin.h" #include "agg2/agg_conv_stroke.h" #include "agg2/agg_pixfmt_rgb.h" #include "agg2/agg_renderer_base.h" #include "agg2/agg_renderer_scanline.h" #include "agg2/agg_renderer_primitives.h" #include "agg2/agg_path_storage.h" #include "agg2/agg_conv_curve.h" #include "agg2/agg_conv_contour.h" #include "agg2/agg_font_freetype.h" class wxPLDevAGG : public wxPLDevBase { // type definitions and enums typedef agg::pixfmt_rgb24 pixFormat; typedef agg::renderer_base rendererBase; typedef agg::renderer_scanline_aa_solid rendererSolid; typedef agg::font_engine_freetype_int32 fontEngineType; typedef agg::font_cache_manager fontManagerType; typedef agg::font_cache_manager::gray8_adaptor_type fontRasterizer; typedef agg::font_cache_manager::gray8_scanline_type fontScanline; typedef agg::conv_curve convCurve; typedef agg::conv_stroke convStroke; typedef agg::conv_transform pathTransform; typedef agg::conv_transform strokeTransform; enum drawPathFlag { Fill, Stroke, FillAndStroke }; public: // methods wxPLDevAGG( void ); ~wxPLDevAGG( void ); void DrawLine( short x1a, short y1a, short x2a, short y2a ); void DrawPolyline( short *xa, short *ya, PLINT npts ); void ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1 = -1, PLINT y1 = -1, PLINT x2 = -1, PLINT y2 = -1 ); void FillPolygon( PLStream *pls ); void BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH ); void CreateCanvas(); void SetWidth( PLStream *pls ); void SetColor0( PLStream *pls ); void SetColor1( PLStream *pls ); void SetExternalBuffer( void* buffer ); #ifdef PL_HAVE_FREETYPE void PutPixel( short x, short y, PLINT color ); void PutPixel( short x, short y ); PLINT GetPixel( short x, short y ); #endif // PL_HAVE_FREETYPE void ProcessString( PLStream* pls, EscText* args ); void PSDrawTextToDC( char* utf8_string, bool drawText ); void PSSetFont( PLUNICODE fci ); void drawPath( drawPathFlag flag ); void AGGAddtoClipRegion( short x1, short y1, short x2, short y2 ); private: // variables wxDC * mDC; wxImage * mBuffer; agg::rendering_buffer mRenderingBuffer; fontEngineType mFontEngine; fontManagerType mFontManager; agg::conv_curve mCurves; agg::conv_contour > mContour; pixFormat mPixFormat; rendererBase mRendererBase; rendererSolid mRendererSolid; agg::scanline_u8 mScanLine; agg::rasterizer_scanline_aa<> mRasterizer; agg::path_storage mPath; agg::trans_affine mTransform; convCurve mConvCurve; convStroke mConvStroke; pathTransform mPathTransform; strokeTransform mStrokeTransform; double mStrokeWidth; wxUint8 mStrokeOpacity; unsigned char mColorRedStroke; unsigned char mColorGreenStroke; unsigned char mColorBlueStroke; unsigned char mColorRedFill; unsigned char mColorGreenFill; unsigned char mColorBlueFill; double textWidth, textHeight; wxString fontdir; }; #endif #if wxUSE_GRAPHICS_CONTEXT #include class wxPLDevGC : public wxPLDevBase { public: // methods wxPLDevGC( void ); ~wxPLDevGC( void ); void DrawLine( short x1a, short y1a, short x2a, short y2a ); void DrawPolyline( short *xa, short *ya, PLINT npts ); void ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1 = -1, PLINT y1 = -1, PLINT x2 = -1, PLINT y2 = -1 ); void FillPolygon( PLStream *pls ); void BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH ); void CreateCanvas(); void SetWidth( PLStream *pls ); void SetColor0( PLStream *pls ); void SetColor1( PLStream *pls ); void SetExternalBuffer( void* buffer ); #ifdef PL_HAVE_FREETYPE void PutPixel( short x, short y, PLINT color ); void PutPixel( short x, short y ); PLINT GetPixel( short x, short y ); #endif // PL_HAVE_FREETYPE void ProcessString( PLStream* pls, EscText* args ); void PSDrawTextToDC( char* utf8_string, bool drawText ); void PSSetFont( PLUNICODE fci ); private: // variables wxBitmap * m_bitmap; wxDC * m_dc; wxGraphicsContext* m_context; // text colors unsigned char textRed, textGreen, textBlue; unsigned char mStrokeOpacity; unsigned char mColorRedStroke; unsigned char mColorGreenStroke; unsigned char mColorBlueStroke; unsigned char mColorRedFill; unsigned char mColorGreenFill; unsigned char mColorBlueFill; }; #endif struct dev_entry { wxString dev_name; wxString dev_menu_short; wxString dev_menu_long; wxString dev_file_app; bool pixelDevice; }; // after how many commands the window should be refreshed #define MAX_COMCOUNT 10000 // wxwidgets application definition (if needed) WX_DEFINE_ARRAY( wxPLplotFrame *, wxArrayOfwxPLplotFrame ); class wxPLplotApp : public wxApp { public: virtual bool OnInit(); // virtual int OnExit(); void SetExitFlag( bool flag = true ) { exit = flag; }; bool GetExitFlag( void ) { return exit; }; void SetAdvanceFlag( bool flag = true ) { advance = flag; }; bool GetAdvanceFlag( void ) { return advance; }; void SetRefreshFlag( bool flag = true ); void AddFrame( wxPLplotFrame* frame ) { FrameArray.Add( frame ); }; void RemoveFrame( wxPLplotFrame* frame ) { FrameArray.Remove( frame ); }; size_t FrameCount( void ) { return FrameArray.GetCount(); } void OnIdle( wxIdleEvent& event ); private: bool exit; bool advance; wxArrayOfwxPLplotFrame FrameArray; DECLARE_EVENT_TABLE() }; // definition of the actual window/frame shown class wxPLplotWindow : public wxWindow { public: wxPLplotWindow( wxWindow* parent, PLStream *pls ); void SetRefreshFlag( bool flag = true ) { refresh = flag; }; bool GetRefreshFlag( void ) { return refresh; }; void SetOrientation( int rot ); private: void OnPaint( wxPaintEvent& event ); void OnChar( wxKeyEvent& event ); void OnIdle( wxIdleEvent& event ); void OnErase( wxEraseEvent & WXUNUSED( event ) ); void OnSize( wxSizeEvent & WXUNUSED( event ) ); void OnMaximize( wxMaximizeEvent & WXUNUSED( event ) ); void OnMouse( wxMouseEvent& event ); void Locate( void ); void DrawCrosshair(); PLStream * m_pls; wxPLDevBase* m_dev; // windows needs to know this structure bool refresh; bool xhair_drawn; int mouse_x, mouse_y, old_mouse_x, old_mouse_y; DECLARE_EVENT_TABLE() }; // declaration of the actual window/frame shown class wxPLplotFrame : public wxFrame { public: wxPLplotFrame( const wxString& title, PLStream* pls ); void OnMenu( wxCommandEvent& event ); void OnClose( wxCloseEvent& event ); bool SavePlot( const char* filename, const char* devname, int width, int height ); void SetRefreshFlag( bool flag = true ) { m_window->SetRefreshFlag( flag ); }; bool GetRefreshFlag( void ) { return m_window->GetRefreshFlag(); }; private: wxPanel * m_panel; wxPLplotWindow* m_window; wxPLDevBase * m_dev; // frame needs to know this structure DECLARE_EVENT_TABLE() }; // menu ids enum { wxPL_Save = 10000, wxPL_Next = 10100, wxPL_Locate, wxPL_Orientation_0, wxPL_Orientation_90, wxPL_Orientation_180, wxPL_Orientation_270 }; // Pixel size dialog class wxGetSizeDialog : public wxDialog { public: // constructors and destructors wxGetSizeDialog( wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE, int width = 800, int height = 600 ); int getWidth() { return spinControlWidth->GetValue(); } int getHeight() { return spinControlHeight->GetValue(); } private: wxSpinCtrl* spinControlWidth; wxSpinCtrl* spinControlHeight; private: DECLARE_EVENT_TABLE() }; // Use this macro if you want to define your own main() or WinMain() function // and call wxEntry() from there. #define IMPLEMENT_PLAPP_NO_MAIN( appname ) \ wxAppConsole * wxPLCreateApp() \ { \ wxAppConsole::CheckBuildOptions( WX_BUILD_OPTIONS_SIGNATURE, \ "your program" ); \ return new appname; \ } \ wxAppInitializer \ wxAppInitializer( (wxAppInitializerFunction) ( wxApp::GetInitializerFunction() == NULL ? wxPLCreateApp : wxApp::GetInitializerFunction() ) ); \ DECLARE_PLAPP( appname ) \ appname & wxPLGetApp() { return *wx_static_cast( appname *, wxApp::GetInstance() ); } #define DECLARE_PLAPP( appname ) extern appname &wxPLGetApp(); // workaround against warnings for unused variables static inline void Use( void * ) { } #define WX_SUPPRESS_UNUSED_WARN( x ) Use( &x ) //-------------------------------------------------------------------------- // Declarations for the device. //-------------------------------------------------------------------------- void plD_init_wxwidgets( PLStream * ); void plD_init_wxpng( PLStream * ); void plD_line_wxwidgets( PLStream *, short, short, short, short ); void plD_polyline_wxwidgets( PLStream *, short *, short *, PLINT ); void plD_eop_wxwidgets( PLStream * ); void plD_bop_wxwidgets( PLStream * ); void plD_tidy_wxwidgets( PLStream * ); void plD_state_wxwidgets( PLStream *, PLINT ); void plD_esc_wxwidgets( PLStream *, PLINT, void * ); void wx_set_dc( PLStream* pls, wxDC* dc ); void wx_set_buffer( PLStream* pls, wxImage* buffer ); void wx_set_size( PLStream* pls, int width, int height ); int plD_errorexithandler_wxwidgets( char *errormessage ); void plD_erroraborthandler_wxwidgets( char *errormessage ); //-------------------------------------------------------------------------- // Debug functions //-------------------------------------------------------------------------- // define if you want debug output // #define _DEBUG // // #define _DEBUG_VERBOSE // void Log_Verbose( const char *fmt, ... ); void Log_Debug( const char *fmt, ... ); //-------------------------------------------------------------------------- // Font style and weight lookup tables //-------------------------------------------------------------------------- const wxFontFamily fontFamilyLookup[5] = { wxFONTFAMILY_SWISS, // sans-serif wxFONTFAMILY_ROMAN, // serif wxFONTFAMILY_TELETYPE, // monospace wxFONTFAMILY_SCRIPT, // script wxFONTFAMILY_SWISS // symbol }; const int fontStyleLookup[3] = { wxFONTFLAG_DEFAULT, // upright wxFONTFLAG_ITALIC, // italic wxFONTFLAG_SLANT // oblique }; const int fontWeightLookup[2] = { wxFONTFLAG_DEFAULT, // medium wxFONTFLAG_BOLD // bold }; #endif // __WXWIDGETS_H__ gdl-0.9.9/src/print.cpp000066400000000000000000000172421340051421000147220ustar00rootroot00000000000000/*************************************************************************** print.cpp - GDL PRINT(F) functions ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include #include "datatypes.hpp" #include "envt.hpp" #include "getfmtast.hpp" #include "basic_pro.hpp" #include "objects.hpp" #include "FMTOut.hpp" #include "terminfo.hpp" #include "gdljournal.hpp" #include "dinterpreter.hpp" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0x2000 #endif namespace lib { using namespace std; void print_vmsCompat( EnvT* e, int* parOffset) { // SA: handling special VMS-compatibility syntax, e.g.: print, '$(F)', 100 // (if FORMAT not defined, more than 2 params, first param is scalar string // and begins with "$(" then first param minus "$" is treated as FORMAT) if (e->GetKW(0) == NULL && e->NParam() > 1 + *parOffset) { BaseGDL* par = e->GetParDefined(*parOffset); if (par->Type() == GDL_STRING && par->Scalar() && (*static_cast(par))[0].compare(0,2,"$(") == 0) { e->SetKeyword("FORMAT", new DStringGDL((*static_cast(par))[0].c_str()+1)); (*parOffset)++; } } } void printf( EnvT* e) { SizeT nParam=e->NParam(); if( nParam < 1) e->Throw( "Incorrect number of arguments."); DLong lun; e->AssureLongScalarPar( 0, lun); ostream* os; ostringstream oss; bool stdLun = check_lun( e, lun); SizeT width; int sockNum = -1; if( stdLun) { if( lun == 0) e->Throw( "Cannot write to stdin. Unit: "+i2s( lun)); os = (lun == -1)? &cout : &cerr; width = TermWidth(); } else { if( fileUnits[ lun-1].F77()) e->Throw( "Formatted IO not allowed with F77_UNFORMATTED " "files. Unit: "+i2s( lun)); if( fileUnits[ lun-1].Xdr() != NULL) e->Throw( "Formatted IO not allowed with XDR " "files. Unit: "+i2s( lun)); sockNum = fileUnits[ lun-1].SockNum(); if (sockNum == -1) { if( fileUnits[ lun-1].Compress()) os = &fileUnits[ lun-1].OgzStream(); else os = &fileUnits[ lun-1].OStream(); } else os = &oss; width = fileUnits[ lun-1].Width(); } int parOffset = 1; print_vmsCompat(e, &parOffset); print_os( os, e, parOffset, width); // Socket send if (sockNum != -1) { int status = send(sockNum, oss.rdbuf()->str().c_str(), oss.rdbuf()->str().size(), MSG_NOSIGNAL); if (status != oss.rdbuf()->str().size()) e->Throw( "SEND error Unit: "+i2s( lun)+":"+oss.rdbuf()->str()); } if( stdLun) { GDLInterpreter* ip = e->Interpreter(); write_journal( ip->GetClearActualLine()); write_journal_comment( e, parOffset, width); } } void print( EnvT* e) { SizeT width = TermWidth(); int parOffset = 0; print_vmsCompat(e, &parOffset); print_os( &cout, e, parOffset, width); GDLInterpreter* ip = e->Interpreter(); write_journal( ip->GetClearActualLine()); write_journal_comment( e, parOffset, width); } void print_os( ostream* os, EnvT* e, int parOffset, SizeT width) { // FORMAT keyword if( e->GetKW( 0) != NULL) { DString fmtString; e->AssureScalarKW( 0, fmtString); if( fmtString != "") { try { RefFMTNode fmtAST = GetFMTAST( fmtString); #ifdef GDL_DEBUG antlr::print_tree pt; cout << "Format parser output:" << endl; pt.pr_tree(static_cast(fmtAST)); cout << "Format Parser end." << endl; #endif // formatted output ignores WIDTH FMTOut Formatter( fmtAST, os, e, parOffset); return; } catch( antlr::ANTLRException& ex) { //Authorize the format to be "new" C format. Should better be handled in the parser, FIXME! try { DString fmtSTring2="(%\""+fmtString+"\")"; RefFMTNode fmtAST = GetFMTAST( fmtSTring2); FMTOut Formatter( fmtAST, os, e, parOffset); return; } catch ( antlr::ANTLRException& ex) { e->Throw( ex.getMessage()); } } } } //else // default-format output. can be implied print (to be written: FIXME) { int nParam = e->NParam(); if( nParam == parOffset) { (*os) << endl; return; } BaseGDL* par; bool lastParScalar = false; BaseGDL* parOffsetPar = e->GetPar( parOffset); bool anyArrayBefore = false; if( parOffsetPar != NULL) anyArrayBefore = parOffsetPar->Rank() > 0; SizeT actPos = 0; for( SizeT i=parOffset; i parOffset) lastParScalar = /*par->Type() == GDL_STRING &&*/ par->Scalar(); par=e->GetPar( i); if( par == NULL) // allowed here: NullGDL::GetSingleInstance()) e->Throw("Variable is undefined: "+e->GetParString( i)); if (lastParScalar && anyArrayBefore && par->Rank() != 0) (*os) << endl; // e.g. print,[1],1,[1] anyArrayBefore |= par->Rank() != 0; par->ToStream( *os, width, &actPos); // debug // (*os) << flush; } bool singleNullChar = (par->Type() == GDL_STRING && !lastParScalar && (nParam-parOffset)>1 && (*static_cast(par))[0] == ""); // } if( (par->Dim().Rank() == 0 && !singleNullChar) || par->Type() == GDL_STRUCT) { (*os) << endl; } } } // SA: we're better than IDL! - we accept more than 20 parameters ;) void pm(EnvT* e) { int nParam = e->NParam(); if (nParam == 0) return; // GDL magick (based on the Python interface code) static int printIx = LibProIx("PRINT"); EnvT* env = new EnvT(NULL, libProList[printIx]); Guard env_guard(env); BaseGDL* par; env->SetNextPar(&par); // printing first the title if TITLE keyword present static int titleIx = e->KeywordIx("TITLE"); if (e->GetKW(titleIx) != NULL) { par = e->GetKW(titleIx); static_cast(env->GetPro())->Pro()( env); } // passing on the FORMAT keyword static int formatIx = e->KeywordIx("FORMAT"); if (e->GetKW(formatIx) != NULL) { if (e->GetKW(formatIx)->Rank() != 0) e->Throw("FORMAT keyword must be a scalar"); env->SetKeyword("FORMAT", &e->GetKW(formatIx)); } // // is it needed here? MS: not anymore :-) // StackSizeGuard guard( GDLInterpreter::CallStack()); // GDLInterpreter::CallStack().push_back(env); // looping over the parameters for (SizeT i = 0; i < nParam; ++i) { if (e->GetParDefined(i)->N_Elements() <= 1) { par = e->GetParDefined(i); static_cast(env->GetPro())->Pro()(static_cast(env)); } else { if (e->GetParDefined(i)->Type() == GDL_STRUCT) e->Throw("Transposing arrays of structures is undefined"); par = e->GetParDefined(i)->Transpose(NULL); static_cast(env->GetPro())->Pro()(static_cast(env)); delete par; } } } } // namespace gdl-0.9.9/src/print_tree.cpp000066400000000000000000000101141340051421000157300ustar00rootroot00000000000000/*************************************************************************** print_tree.cpp - description Print an ANTLR abstract syntax tree in operator prefix form. Used for debugging only. Modified from antlr package ------------------- begin : ? copyright : Software rights: http://www.antlr.org/license.html email : ? ***************************************************************************/ #include "includefirst.hpp" #include #include #include "print_tree.hpp" #include "dnode.hpp" namespace antlr { /* * pr_name * Print the character string associated with an ANTLR tree node. */ void print_tree::pr_name( RefAST node ) { std::string str; RefDNode dNode = static_cast( node); // str = dNode->getText(); str = std::string("[") + i2s(dNode->getType()) + ":" + i2s(dNode->CData()) + "]" + node->getText(); // printf("%s ", str.c_str()); printf("%s(%d) ", str.c_str(), dNode->getLine()); } // pr_name void print_tree::pr_name( ProgNodeP node ) { std::string str; str = node->getText(); printf("%s(%d) ", str.c_str(), node->getLine()); } // pr_name /* * pr_indent * Print indentation for a node. */ void print_tree::pr_indent() { const SizeT BUFSIZE = 80; char buf[ BUFSIZE+1 ]; unsigned i; for (i = 0; i < indent_level && i < BUFSIZE; i++) { buf[i] = ' '; } buf[i] = '\0'; printf("%s", buf ); } // pr_indent void print_tree::pr_open_angle() { if ( indent_level ) printf("\n"); pr_indent(); printf("<"); indent_level += INDENT; } // pr_open_angle /* * pr_close_angle * Print the ">" bracket to show the close of a tree production. */ void print_tree::pr_close_angle(bool first) { assert( indent_level > 0 ); indent_level -= INDENT; if (!first) { printf("\n"); pr_indent(); } printf(">"); } // pr_close_angle /* * pr_leaves * Print the leaves of an AST node */ void print_tree::pr_leaves( RefAST top ) { RefAST t; for( t = ( (top && is_nonleaf(top)) ? top->getFirstChild() : (RefAST)NULL ); t; t = t->getNextSibling() ) { if (is_nonleaf( t )) pr_top( t ); else pr_name( t ); } } // pr_leaves void print_tree::pr_leaves( ProgNodeP top ) { ProgNodeP t; for( t = ( (top && is_nonleaf(top)) ? top->getFirstChild() : NULL ); t; t = t->getNextSibling() ) { if (is_nonleaf( t )) pr_top( t ); else pr_name( t ); if( t->getNextSibling() != NULL && t->KeepRight()) { printf("^"); break; } } } // pr_leaves /* * pr_top * Recursively print a tree (or a sub-tree) from the top down. */ void print_tree::pr_top( RefAST top ) { RefAST t; bool first = true; pr_open_angle(); pr_name( top ); if (is_nonleaf( top )) { for( t = ( (top && is_nonleaf(top)) ? top->getFirstChild() : (RefAST)NULL ); t; t = t->getNextSibling() ) { if (is_nonleaf( t )) first = false; } pr_leaves( top ); } pr_close_angle( first ); } // pr_top void print_tree::pr_top( ProgNodeP top ) { ProgNodeP t; bool first = true; pr_open_angle(); pr_name( top ); if (is_nonleaf( top )) { for( t = ( (top && is_nonleaf(top)) ? top->getFirstChild() : NULL ); t; t = t->getNextSibling() ) { if (is_nonleaf( t )) first = false; if( t->getNextSibling() != NULL && t->KeepRight()) { printf("^"); break; } } pr_leaves( top ); } pr_close_angle( first ); } // pr_top /* * pr_tree * Main entry point for tree print. */ void print_tree::pr_tree( RefAST top ) { RefAST t; for (t = top; t != NULL; t = t->getNextSibling()) { indent_level = 0; pr_top( t ); printf("\n"); } } // pr_tree void print_tree::pr_tree( ProgNodeP top ) { ProgNodeP t; for (t = top; t != NULL; t = t->getNextSibling()) { indent_level = 0; pr_top( t ); printf("\n"); if( t->getNextSibling() != NULL && t->KeepRight()) { printf("^"); break; } } } // pr_tree } // namespace gdl-0.9.9/src/print_tree.hpp000066400000000000000000000025131340051421000157410ustar00rootroot00000000000000/*************************************************************************** print_tree.hpp Print an ANTLR abstract syntax tree in operator prefix form. Used for debugging only. ------------------- begin : ? copyright : ? (modified from ANTLR package) email : ? ***************************************************************************/ #ifndef _PRINT_TREE_HPP_ #define _PRINT_TREE_HPP_ #include "typedefs.hpp" #include "prognode.hpp" #include #include namespace antlr { class print_tree { private: typedef enum { INDENT = 2 } bogus; unsigned long indent_level; private: void pr_name( RefAST node ); void pr_name( ProgNodeP node ); void pr_indent(); void pr_top( RefAST top ); void pr_top( ProgNodeP top ); void pr_open_angle(); void pr_close_angle(bool first); void pr_leaves( RefAST top ); void pr_leaves( ProgNodeP top ); bool is_nonleaf( RefAST node ) { bool rslt = (node->getFirstChild() != NULL); return rslt; } bool is_nonleaf( ProgNodeP node ) { bool rslt = (node->getFirstChild() != NULL); return rslt; } public: void pr_tree( const RefAST top ); void pr_tree( const ProgNodeP top ); }; // print_tree } // namespace #endif gdl-0.9.9/src/pro/000077500000000000000000000000001340051421000136545ustar00rootroot00000000000000gdl-0.9.9/src/pro/appleman.pro000066400000000000000000000044171340051421000162010ustar00rootroot00000000000000pro AppleMan,xRange,yRange,RESULT=res,XSIZE=xS,YSIZE=yS,$ NoDisplay=NoDisplay, test=test, help=help on_error, 2 ;+ ; ; NAME: appleman ; ; PURPOSE: Generate a GDL window showing the mandelbrot set. ; ; CATEGORY: Demo ; ; CALLING SEQUENCE: appleman,[xRange,yRange,RESULT=result] ; ; KEYWORD PARAMETERS: ; RESULT : the resulting byte array for further porcessing ; ; COMMON BLOCKS: ; ; SIDE EFFECTS: ; ; RESTRICTIONS: ; ; PROCEDURE: convergence or divergence of modulus of complex number ; after a given number of iterations ; ; EXAMPLE: ; ; MODIFICATION HISTORY: ; Written by: Marc Schellens 2004-12-01 ; 2011-12-29: Alain : few extra keywords ; ;- ; LICENCE: ; Copyright (C) 2004, 2011 ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- ;device,PSEUDO_COLOR=8,DECOMPOSED=0 if KEYWORD_SET(help) then begin print, 'pro AppleMan, xRange, yRange, RESULT=res, $' print, ' NoDisplay=NoDisplay, test=test, help=help' return endif ; if N_ELEMENTS(xRange) eq 0 then xRange = [ -1.0, 2.3] if N_ELEMENTS(yRange) eq 0 then yRange = [ -1.3, 1.3] ; iter = 255 if ~keyword_set(xS) then xS = 640 if ~keyword_set(yS) then yS = 512 xD = float(xRange[1]-xRange[0]) yD = float(yRange[1]-yRange[0]) xStep = xD / xS yStep = yD / yS ; xStartVec = LINDGEN( xS) * xStep + xRange[0] yStartVec = LINDGEN( yS) * yStep + yRange[0] constArr = COMPLEX(REBIN(xStartVec, xS, yS),$ REBIN(TRANSPOSE(yStartVec), xS, yS)) valArr = COMPLEXARR( xS, yS) res = INTARR( xS, yS) oriIndex = LINDGEN( LONG(xS) * yS) for i = 0, iter-1 do begin ;; valArr = valArr^2 - constArr ;; whereIn = WHERE((ABS(valArr) LE 4.0d), COMPLEMENT=whereOut) ;; if whereIn[0] eq -1 then break ;; valArr = valArr[ whereIn] constArr = constArr[ whereIn] ;; if whereOut[0] ne -1 then begin res[ oriIndex[ whereOut]] = i+1 oriIndex = oriIndex[ whereIn] endif endfor if ~arg_present(res) || ~KEYWORD_SET(NoDisplay) then begin loadct,15 tv,res endif if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/array_indices.pro000066400000000000000000000046321340051421000172170ustar00rootroot00000000000000;$Id: array_indices.pro,v 1.4 2015-12-02 20:46:44 gilles-duvert Exp $ function Array_Indices,a,ix,dimensions=dimensions on_error, 2 ;+ ; ; ; ; NAME: ; ARRAY_INDICES ; ; PURPOSE: ; translates a one-dimensional index (like given by where() function) ; into a multidimensional one (i.e. the array indices according to ; the multidimensional array) ; ; PARAMETERS: ; a the array ; ix the onedimensional index (or array of indices) ; ; CATEGORY: ; ; ; CALLING SEQUENCE: ; result = array_index(a,i) ; ; ; ; ; KEYWORD PARAMETERS: ; dimensions: with this keyword the array "a" is a vector giving the ; dimensions. Use this keyword if you don't want to spoil the ; memory to generate a sample array "a" with the output dimensions. ; ; ; OUTPUTS: ; ; ; ; ; OPTIONAL OUTPUTS: ; ; ; ; COMMON BLOCKS: ; ; ; SIDE EFFECTS: ; ; ; RESTRICTIONS: ; ; ; PROCEDURE: ; ; ; EXAMPLE: ; GDL> a=intarr(23,24,27,33) ; GDL> a[13,19,2,11]=1 ; GDL> ix=where(a) ; GDL> print,l_getdim(a,ix) ; 13 19 2 11 ; ; ; ; MODIFICATION HISTORY: ; Written by: Marc Schellens, 02-12-2004 ; introduces dimensions keyword by Reto Stockli (2015/11/29) ; ; ;- ; LICENCE: ; Copyright (C) 2004-2015, ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- ;; check number of parameters if n_params() ne 2 then begin message,'Wrong number of parameters.' endif ;; check index type ty = size( ix, /TYPE) if ty ge 6 and ty le 11 then begin message,'Index must be of integer type.' endif ;; get index range maxIx = max( ix, MIN=minIx) ;; check if the array "a" provides the dimensions ;; and evaluate dimensions if (keyword_set(dimensions)) then begin ntot = product(a,/integer) dim = a ndim = n_elements(a) endif else begin ntot = n_elements(a) dim = size(a,/dimensions) ndim = n_elements(dim) endelse if minIx lt 0 or maxIx ge ntot then begin message,'Index out of range.' endif r=lonarr( ndim>1,n_elements(ix)) ;; index 1 r[0,*]=ix mod dim[0] ;; index 2..n-1 sum=1L for i=1,ndim-2 do begin sum=sum*dim[i-1] r[i,*]=(ix / sum) mod dim[i] endfor ;; index n if ndim ge 2 then begin i=ndim-1 sum=sum*dim[i-1] r[i,*]=ix / sum endif return,r end gdl-0.9.9/src/pro/bilinear.pro000066400000000000000000000031551340051421000161670ustar00rootroot00000000000000; part of GNU Data Language - GDL ;------------------------------------------------------------- ;+ ; NAME: ; BILINEAR ; PURPOSE: ; Bilinearly regrid a 2D array on a set of x,y coordinates ; CATEGORY: ; Array Manipulation. ; CALLING SEQUENCE: ; z2 = bilinear(z,x,y,missing=missing) ; INPUTS: ; Z = input 2-d array. in ; X, Y : X and Y index positions where Z2 is to be estimated ; from Z ; missing: value for points falling outside the z boundaries ; KEYWORD PARAMETERS: ; none ; OUTPUTS: ; z2 = resulting array. out ; ; PROCEDURE: ; Uses INTERPOLATE /GRID ; ; MODIFICATION HISTORY: ; Written by: 2011-12-17 G. Duvert (Initial import) ; ;- ; LICENCE: ; Copyright (C) 2011 ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; function BILINEAR, z, x, y, missing=missing ; ON_ERROR, 2 ;Return to caller if error ; if (N_PARAMS() ne 3) then MESSAGE, 'Incorrect number of arguments.' ; dimx=SIZE(x,/n_dimensions) dimy=SIZE(y,/n_dimensions) ; if ((dimx gt 2) || (dimy gt 2)) then MESSAGE, 'X and Y must be 1D or 2D, max.' if ( dimx ne dimy ) then MESSAGE, 'X and Y must be of same dimension(s).' ; if ((dimx eq 1) && (dimy eq 1)) then begin return, INTERPOLATE(z, x, y, /GRID, missing=missing) endif else begin return, INTERPOLATE(z, x, y, missing=missing) endelse ; end gdl-0.9.9/src/pro/calendar.pro000066400000000000000000000034701340051421000161530ustar00rootroot00000000000000; by Sylwester Arabas ; depends on the UNIX 'cal' utility ; pro CALENDAR, p1, p2, test=test ; ON_ERROR, 2 ; ;; sanity checks msg = ' must not be undefined, zero-valued nor multi-element value' msg_y = 'valid year range is 1 ... 9999' msg_m = 'valid month range is 1 ... 12' m_range = [1,12] y_range = [1,9999] if N_PARAMS() eq 1 then begin p1=FLOOR(p1) if ~KEYWORD_SET(p1) || N_ELEMENTS(p1) ne 1 then $ MESSAGE, 'first argument' + msg if p1 lt y_range[0] || p1 gt y_range[1] then MESSAGE, msg_y endif if N_PARAMS() eq 2 then begin p2=FLOOR(p2) if ~KEYWORD_SET(p2) || N_ELEMENTS(p2) ne 1 then $ MESSAGE, 'second argument' + msg if p1 lt m_range[0] || p1 gt m_range[1] then MESSAGE, msg_m if p2 lt y_range[0] || p2 gt y_range[1] then MESSAGE, msg_y endif ;; acquireing the calendar from cal cmd = 'LC_ALL=C cal' chrsz = 3 if N_PARAMS() eq 1 then begin cmd += ' ' + STRING(p1) chrsz = 1 endif else if N_PARAMS() eq 2 then begin cmd += ' ' + STRING(p1) + ' ' + STRING(p2) endif spawn, cmd, text, exit_status=status, err if status ne 0 then MESSAGE, 'failed to execute cal' ; ;; finding the length of the longest line maxlen = 0. for line = 0, N_ELEMENTS(text) - 1 do $ maxlen = max([maxlen, STRLEN(text[line])]) ;; setting up the plot space x_rng = [-0.05,1.05] * maxlen y_rng = [1,-.1] * N_ELEMENTS(text) PLOT, [0], [0], xrange=x_rng, yrange=y_rng, /nodata, $ xmargin=[1,1], ymargin=[1,1], xstyle=5, ystyle=5 ;; drawing a frame PLOTS, $ [x_rng[0], x_rng[0], x_rng[1], x_rng[1], x_rng[0]], $ [y_rng[0], y_rng[1], y_rng[1], y_rng[0], y_rng[0]] ;; plotting the output from cal for line = 0, N_ELEMENTS(text) - 1 do $ for char = 0, STRLEN(text[line]) do $ XYOUTS, char, line, STRMID(text[line], char, 1), chars=chrsz ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/checks000077500000000000000000000011251340051421000150410ustar00rootroot00000000000000#!/bin/bash # SA: checking if every .pro file is listed in the Makefile.am test \ "`fgrep '.pro' Makefile.am | tr '\\\\' ' ' | tr "\n" ' ' | tr -s ' '`" \ = \ " `LC_COLLATE=C ls *.pro | tr "\n" ' ' | tr -s ' '`" && exit echo "--------------------------------------------------------------" echo "REASON: list of .pro files vs. entries in src/pro/Makefile.am:" LC_COLLATE=C ls -1 *.pro \ | awk '{ print " " $0 " \\" }' \ | diff /dev/stdin Makefile.am \ | fgrep .pro | tr '<' '-' | tr '\\' ' ' | tr -s ' ' echo "--------------------------------------------------------------" exit 1 gdl-0.9.9/src/pro/chisqr_cvf.pro000066400000000000000000000064351340051421000165350ustar00rootroot00000000000000;+ ; NAME: CHISQR_CVF ; ; PURPOSE: ; ; For the chi squared distribution, find the parameter x that gives ; you a probability P(X > x) = prob, where 'prob' is specified in ; the call to Chisqr_cvf. When you call this program, you also need ; to specify the number of degrees of freedom of the chi squared ; distribution, 'n_dof'. ; ; Use that for the chi squared distribution, CDF(a,b) = IGAMMA(b/2,a/2). ; ; INPUT: ; prob : probability that you want to calculate for the chi squared ; distribution. Floating point or double precision number, no defaults. ; ; n_dof : the number of degrees of freedom. Integer, no defaults. ; ; OUTPUT: ; CHISQR_CVF returns the value of 'x' for which P(X > x) = prob, ; where 'prob' is specified when calling the function. ; ; ; LICENCE: MIT License ; ; Copyright (c) 2017 Dominic H.F.M. Schnitzeler ; ; 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. ; ; MODIFICATION HISTORY: ; 31-Oct-2017 : adding keywords Help & test, formatting ; function CHISQR_CVF, prob, n_dof, test=test, help=help ; if KEYWORD_SET(help) then begin print, 'function CHISQR_CVF, prob, n_dof, test=test, help=help' return, -1 endif ;print, 'gdl' ; if ((prob LT 0.) or (prob GT 1.)) then begin MESSAGE, 'Chisqr_cvf_ds: the specified probability must lie between 0. and 1.' endif x_min= 0d ; starting point x_max= 10d ; guess ;; ;; Increase x_max if required: while (Igamma(n_dof/2d , x_max/2d) LT (1.-prob)) do x_max*=2 ;; ;; At this point, you can assume that the correct value for x lies ;; between x_min and x_max. Now use bisection to 'home in' on the ;; correct value for x. eps = 1d-10 ; precision with which you want to approximate prob x_new = (x_min+x_max)/2d val = Igamma(n_dof/2d , x_new/2d) ; while ABS(val - (1-prob)) gt eps do begin if (val LT (1-prob)) then x_min=x_new else x_max=x_new x_new = (x_min+x_max)/2d val = Igamma(n_dof/2d , x_new/2d) endwhile ;; ;; Ensure that a floating point number is written out if the input ;; for 'prob' is a floating point number. ;; If 'prob' is double precision, then the output is automatically ;; double precision. ;; if SIZE(prob,/type) eq 4 then x_new=FLOAT(x_new) ;; if KEYWORD_SET(test) then STOP ;; return, x_new ;; END gdl-0.9.9/src/pro/congrid.pro000066400000000000000000000123051340051421000160240ustar00rootroot00000000000000; part of GNU Data Language - GDL ;------------------------------------------------------------- ;+ ; NAME: ; CONGRID ; PURPOSE: ; Shrink or expands an array (any dimensions) to any size, ; however only the first 3 dims (max) will be resized. ; CATEGORY: ; Array Manipulation. ; CALLING SEQUENCE: ; t2 = CONGRID(t,mx[,my[,mZ]]) ; INPUTS: ; t = input array. in ; mx, my, mz = new (output) array size. in ; t2 = resulting array. out ; KEYWORD PARAMETERS: ; /INTERPOLATE means do bilinear interpolation. Kept for ; compatibility but unused: interpolation IS linear. ; CUBIC=cubic: use a cubic interpolation. Currently limited by ; the availability of cubic interpolation in GDL's INTERPOLATE. ; /CENTER means assume pixels centered. This means ; the pixel at (0,[0,[0]]) is clipped to 1/4 size. ; Default is that pixel start (not center) is at index.' ; MISSING=missing gives a value for undefined pixels. ; /MINUS_ONE: option will be ignored. MISSING can be used instead. ; /HELP gives this help.' ; ; NOTE: ; CONGRID performs a resampling. Does not conserve Fluxes. ; OUTPUTS: ; t2 = resulting array. out ; ; MODIFICATION HISTORY: ; Written by: 2011-12-17 G. Duvert (Initial import) ; ;- ; LICENCE: ; Copyright (C) 2011 ; 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 2 of the License, or ; (at your option) any later version. ; ;- function CONGRID, t, mx, my, mz, $ CENTER=center, $ INTERP=interp, $ CUBIC = cubic, $ MINUS_ONE=minus_one, $ MISSING=missing, $ HELP=help, test=test npar=N_PARAMS() if (npar lt 2) or (npar gt 4) or KEYWORD_SET(help) then begin print,' Shrink or expands an array (any dimensions) to any size,' print,' however only the first 3 dims (max) will be resized.' print,' CALLING SEQUENCE:' print,' t2 = congrid2(t,mx[,my][,mz])' print,' t = input array. in' print,' mx, my, mz = new (output) array size. in' print,' t2 = resulting array. out' print,' Keywords:' print,' /INTERPOLATE means do bilinear interpolation. Kept for' print,' compatibility but unused: interpolation IS linear.' print,' /CENTER means assume pixels centered. This means' print,' the pixel at (0,[0,[0]]) is clipped to 1/4 size.' print,' Default is that pixel start (not center) is at index.' print,' CUBIC=cubic: use a cubic interpolation.' print,' MISSING=missing gives a value for undefined pixels.' print,' /MINUS_ONE: option will be ignored. MISSING can be used instead.' print, ' /HELP gives this help.' print,' NOTE: CONGRID performs a resampling. Does not conserve Fluxes.' return,'' endif ; ON_ERROR, 2 ;Return to caller if error ; ndim = SIZE(t, /N_DIMENSIONS) dims = SIZE(t, /DIMENSIONS) ; if(ndim EQ 0) then MESSAGE, 'Array must have 1, 2, or 3 dimensions.' if(ndim gt 3) then $ MESSAGE, 'Warning, array dimensions >3, using non-standard CONGRID extension.', /informational ; cflag = KEYWORD_SET(center) ; 0=start, 1=center. minone = KEYWORD_SET(minus_one) nnbor = ~KEYWORD_SET(interp) ; nearest neighbor is default for 1 and 2 dim ; ; if (npar gt ndim+1) then message, 'Too many output dimensions.' ; nopt=0 IF (N_ELEMENTS(mx) NE 0) THEN BEGIN fx= (minone gt 0)? float(dims[0]-1)/(mx-1) : float(dims[0])/mx x = (cflag gt 0) ?fx*(FINDGEN(mx)+0.5)-0.5 : fx*FINDGEN(mx) nopt=1 ENDIF ; ; if 2 dim my MUST be present! IF (N_ELEMENTS(my) EQ 0 && ndim ge 2) THEN MESSAGE, '2nd dimension not specified.' IF (N_ELEMENTS(my) NE 0 && ndim ge 2) THEN BEGIN fy= (minone gt 0)? float(dims[1]-1)/(my-1) : float(dims[1])/my y = (cflag gt 0) ?fy*(FINDGEN(my)+0.5)-0.5 : fy*FINDGEN(my) nopt=2 ENDIF ; ; if 3 dim mz MUST be present! IF (N_ELEMENTS(mz) EQ 0 && ndim ge 3) THEN MESSAGE, '3rd dimension not specified.' IF (N_ELEMENTS(mz) NE 0 && ndim ge 3) THEN BEGIN fz= (minone gt 0) ? float(dims[2]-1)/(mz-1) : float(dims[2])/mz z = (cflag gt 0) ? fz*(FINDGEN(mz)+0.5)-0.5 : fz*FINDGEN(mz) nopt=3 ENDIF ; IF (nopt lt ndim) THEN BEGIN ;; create a transposition vector p=SHIFT(INDGEN(ndim),-nopt) temp=TRANSPOSE(t,p) CASE nopt OF 3: temp2 = INTERPOLATE(temp,x,y,z,/grid,cubic=cubic,missing=missing) 2: temp2 = INTERPOLATE(temp,x,y,/grid,nearest_neighbour=nnbor,cubic=cubic,missing=missing) 1: temp2 = INTERPOLATE(temp,x,/grid,nearest_neighbour=nnbor,cubic=cubic,missing=missing) ENDCASE p=SHIFT(INDGEN(ndim),nopt) t2=TRANSPOSE(temp2,p) ENDIF ELSE BEGIN CASE nopt OF 3: t2 = INTERPOLATE(t,x,y,z,/grid,cubic=cubic,missing=missing) 2: t2 = INTERPOLATE(t,x,y,/grid,nearest_neighbour=nnbor,cubic=cubic,missing=missing) 1: t2 = INTERPOLATE(t,x,/grid,nearest_neighbour=nnbor,cubic=cubic,missing=missing) ENDCASE ENDELSE ; if KEYWORD_SET(test) then STOP ; return,t2 ; end gdl-0.9.9/src/pro/correlate.pro000066400000000000000000000046261340051421000163660ustar00rootroot00000000000000; by Sylwester Arabas ; part of GNU Data Language - GDL ; ; Revised by AC, 21-Nov-2016 (case N_PARAMS() == 1 and /cov) ; https://sourceforge.net/p/gnudatalanguage/bugs/714/ ; from example in Coyote Web Site ; http://www.idlcoyote.com/code_tips/pca.html ; ; Note by AC: this code is clearly not finished ... ; Complex cannot be used as input ; function CORRELATE, x, y, covariance=covariance, double=double ; ON_ERROR, 2 ; if N_PARAMS() eq 2 then begin ;; if ISA(x,/complex) OR ISA(y,/complex) then begin MESSAGE, /continue, 'Complex type for input not ready, please contribute.' endif ;; l = N_ELEMENTS(x) < N_ELEMENTS(y) ;; mx = MEAN(x[0:l-1], double=double) my = MEAN(y[0:l-1], double=double) cov = TOTAL((x - mx) * (y - my)) / (l - 1.) ;; if KEYWORD_SET(covariance) then return, cov ;; sx = SQRT(TOTAL((x[0:l-1] - mx)^2, double=double) / (l - 1.)) sy = SQRT(TOTAL((y[0:l-1] - my)^2, double=double) / (l - 1.)) return, cov / sx / sy ;; endif else if N_PARAMS() eq 1 then begin ;; if ISA(x,/complex) OR ISA(y,/complex) then begin MESSAGE, /continue, 'Complex type for input not ready, please contribute.' endif ;; if (SIZE(x))[0] ne 2 then MESSAGE, 'Expecting two-dimensional array' ;; dbl = KEYWORD_SET(double) || SIZE(x, /type) eq 5 nx = (SIZE(x))[1] cov = dbl ? dblarr(nx, nx, /nozero) : fltarr(nx, nx, /nozero) ;; ;; one option would be to call CORRELATE a couple of time... ;; but the code below should be faster ;;for i = 0, nx - 1 do for j = 0, nx - 1 do $ ;; cov[i, j] = CORRELATE(x[i, *], x[j, *], double=double, covariance=covariance) ;; tmp = dbl ? dblarr(nx, /nozero) : fltarr(nx, /nozero) ;; ;; AC : obsolete form ;; for i = 0, nx - 1 do tmp[i] = mean(x[i, *], double=double) dims = SIZE(x, /DIMENSIONS) tmp = TOTAL(x, 2)/dims[1] ;; for i = 0, nx - 1 do begin for j = 0, nx - 1 do begin cov[i, j] = total((x[i, *] - tmp[i]) * (x[j, *] - tmp[j])) endfor endfor ;; if KEYWORD_SET(covariance) then return, cov / (dims[1]-1) ;; for i = 0, nx - 1 do tmp[i, *] = SQRT(TOTAL((x[i, *] - tmp[i])^2, double=double) / (nx - 1.)) for i = 0, nx - 1 do begin cov[i, *] /= tmp[i] cov[*, i] /= tmp[i] endfor return, cov endif ; MESSAGE, 'Incorrect number of arguments.' ; end gdl-0.9.9/src/pro/cw_bgroup_donotuseyet.pro000066400000000000000000000156611340051421000210400ustar00rootroot00000000000000; part of GNU Data Language - GDL ;------------------------------------------------------------- ;+ ; NAME: ; CW_BGROUP ; PURPOSE: ; Create a compound checkbox, radiobox or regular button group ; ; CATEGORY: ; GUI widgets ; ; CALLING SEQUENCE: ; widgetID = CW_BGROUP(ParentID, ButtonNames, $ ; BUTTON_UVALUE=button_uvalue, COLUMN=column, EVENT_FUNCT=event_funct,$ ; EXCLUSIVE=exclusive,NONEXCLUSIVE=nonexclusive,SPACE=space,$ ; XPAD=xpad, YPAD=ypad, FONT=font, FRAME=frame, IDS=ids,$ ; LABEL_LEFT=label_left, LABEL_TOP=label_top, MAP=map, NO_RELEASE=no_release,$ ; RETURN_ID=return_id, RETURN_INDEX=return_index, RETURN_NAME=return_name,$ ; ROW=row, SCROLL=scroll, SET_VALUE=sel_value, TAB_MODE=tab_mode,$ ; X_SCROLL_SIZE=x_scroll_size, Y_SCROLL_SIZE=y_scroll_size,$ ; SET_VALUE=set_value, UNAME=uname, UVALUE=uvalue, XOFFSET=xoffset,$ ; XSIZE=xsize, YOFFSET=yoffset, YSIZE=ysize) ; ; INPUTS: ; ; KEYWORD PARAMETERS: ; ; OUTPUTS: ; widgetID = widget ID of compound widget ; ; MODIFICATION HISTORY: ; written 2013-10-29 by Marc Schellens (Initial import) ; ;- ; LICENCE: ; Copyright (C) 2013 ; 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 2 of the License, or ; (at your option) any later version. ; ; function CW_BGROUP_EVENT,ev widget_control,ev.handler,GET_UVALUE=state1 if size(state1,/TYPE) ne 8 then begin ;; no STRUCT? ;; if no struct, uvalue is the UVALUE holder's ID widget_control,state1,GET_UVALUE=state endif else begin state = state1 endelse widget_control,ev.id,GET_UVALUE=index if ev.select ne 0 then begin state.lastButton = index endif if state.exclusiveMode eq 0 then begin endif if state.exclusiveMode eq 1 then begin endif if state.exclusiveMode eq 2 then begin state.buttonState[index] = ev.select endif widget_control,ev.handler,SET_UVALUE=state if state.noRelease ne 0 and ev.select eq 0 then return,0 retEv = { ID:state.topBaseID, $ TOP:ev.top,$ HANDLER:0L,$ SELECT:ev.select, $ VALUE:state.rArray[index] } return,retEv end function CW_BGROUP_GETV,id bbase = widget_info(id,/CHILD) widget_control,bbase,GET_UVALUE=state if state.exclusiveMode eq 0 then begin message,"CW_BGROUP: Unable to get plain button group value." endif if state.exclusiveMode eq 1 then begin return,state.rArray[state.lastButton] endif return,state.buttonState end pro CW_BGROUP_SETV,id,value bbase = widget_info(id,/CHILD) widget_control,bbase,GET_UVALUE=state if state.exclusiveMode eq 0 then begin message,"CW_BGROUP: Unable to set plain button group value." return endif if state.exclusiveMode eq 1 then begin state.lastButton = value widget_control,state.buttonID[value],SET_BUTTON=1 widget_control,bbase,SET_UVALUE=state return endif for b=0,N_ELEMENTS(value)-1 do begin state.buttonState[b] = value[b] widget_control,state.buttonID[b],SET_BUTTON=value[b] endfor widget_control,bbase,SET_UVALUE=state end function CW_BGROUP,parentID, buttonNames, $ BUTTON_UVALUE=button_uvalue, COLUMN=column, EVENT_FUNCT=event_funct,$ EXCLUSIVE=exclusive,NONEXCLUSIVE=nonexclusive,SPACE=space,$ XPAD=xpad, YPAD=ypad, FONT=font, FRAME=frame, IDS=ids,$ LABEL_LEFT=label_left, LABEL_TOP=label_top, MAP=map, NO_RELEASE=no_release,$ RETURN_ID=return_id, RETURN_INDEX=return_index, RETURN_NAME=return_name,$ ROW=row, SCROLL=scroll, SET_VALUE=set_value, TAB_MODE=tab_mode,$ X_SCROLL_SIZE=x_scroll_size, Y_SCROLL_SIZE=y_scroll_size,$ UNAME=uname, UVALUE=uvalue, XOFFSET=xoffset,$ XSIZE=xsize, YOFFSET=yoffset, YSIZE=ysize nButtons = N_ELEMENTS(buttonNames) if nButtons eq 0 then begin MESSAGE,"CW_BGROUP: 2nd parameter (button names) not valid." return,0 endif if N_ELEMENTS( button_uvalue) gt 0 then begin if N_ELEMENTS( button_uvalue) ne nButtons then begin MESSAGE,"CW_BGROUP: BUTTON_UVALUE mut contain one element for each button." return,0 endif endif exclusiveMode = 0 if keyword_set(exclusive) then begin if keyword_set(nonexclusive) then begin MESSAGE,"CW_BGROUP: Conficting keywords: [NON]EXCLUSIVE." return,0 endif exclusiveMode = 1 endif if keyword_set(nonexclusive) then begin exclusiveMode = 2 endif widgetID = widget_base(parentID,/COL,MAP=map,UNAME=uname,UVALUE=uvalue,$ FUNC_GET_VALUE='CW_BGROUP_GETV', PRO_SET_VALUE='CW_BGROUP_SETV', $ EVENT_FUNC=event_funct,$ XSIZE=xsize,YSIZE=ysize) uValueHolder = 0 if N_ELEMENTS(label_top) ne 0 then begin label = widget_label( widgetID, VALUE=label_top) uValueHolder = label endif if uValueHolder eq 0 then begin baseID = widget_base(widgetID,EXCLUSIVE=exclusive,NONEXCLUSIVE=nonexclusive,$ COLUMN=column,ROW=row, EVENT_FUNC="CW_BGROUP_EVENT") uValueHolder = baseID endif else begin baseID = widget_base(widgetID,EXCLUSIVE=exclusive,NONEXCLUSIVE=nonexclusive,$ COLUMN=column,ROW=row, EVENT_FUNC="CW_BGROUP_EVENT",UVALUE=label) endelse ids = lonarr(nButtons) ;; if N_ELEMENTS( button_uvalue) gt 0 then begin for b=0,nButtons-1 do begin ids[b]=widget_button(baseID,VALUE=buttonNames[b],UVALUE=b) endfor ;; endif else begin ;; for b=0,nButtons-1 do begin ;; ids[b]=widget_button(baseID,VALUE=buttonNames[b]) ;; endfor ;; endelse rMode = -1 if N_ELEMENTS( button_uvalue) gt 0 then begin rMode = 1 ; button_uvalue (overrides) rArray = button_uvalue ; help,1,rArray endif else begin if keyword_set( return_name) then begin rMode = 3 rArray = buttonNames ; help,3,rArray endif else if keyword_set( return_id) then begin rMode = 4 rArray = ids ; help,4,rArray endif else begin ;; default -> return index rMode = 2 rArray = lindgen( nButtons) ; help,2,rArray endelse endelse internalUValue = {rArray:rArray,$ exclusiveMode: exclusiveMode,$ buttonID: ids,$ buttonState: intarr(nButtons),$ lastButton: 0,$ noRelease: keyword_set(no_release),$ buttonBase: baseID,$ topBaseID: widgetID } widget_control,uValueHolder,SET_UVALUE=internalUValue if N_ELEMENTS(set_value) ne 0 then CW_BGROUP_SETV, widgetID, set_value return,widgetID end gdl-0.9.9/src/pro/define_msgblk.pro000066400000000000000000000003021340051421000171620ustar00rootroot00000000000000pro define_msgblk, blockname, errornames, errorformats,ignore_duplicate = ignore_duplicate, prefix = prefix print,"define_msgblk not active, this functionality is not preset in GDL, FIXME!" end gdl-0.9.9/src/pro/define_msgblk_from_file.pro000066400000000000000000000003351340051421000212120ustar00rootroot00000000000000pro define_msgblk_from_file, filename, block = block , verbose=verbose, ignore_duplicate = ignore_duplicate, prefix = prefix print,"define_msgblk_from_file not active, this functionality is not preset in GDL, FIXME!" end gdl-0.9.9/src/pro/delvar.pro000066400000000000000000000030131340051421000156500ustar00rootroot00000000000000;+ ; NAME: ; DELVAR ; PURPOSE: ; As IDL's DELVAR internal function (GDL:FIXME!), using ; code taken from 'delvarx.pro' under BSD license, all rights reserved. ; CALLING SEQUENCE: ; DELVAR, vra1, var2 .... var48 ; ; INPUTS: ; p0, p1... p48 - variables to delete ; ; RESTRICTIONS: ; Can't use recursively due to EXECUTE function ; ; METHOD: ; Uses EXECUTE and TEMPORARY function (old version of delvarx) ; new version of delvarx using ptr_new(/no_copy) does not work ; with GDL ; ; REVISION HISTORY: ; Copied from the Solar library, written by slf, 25-Feb-1993 ; Added to Astronomy Library, September 1995 ; Converted to IDL V5.0 W. Landsman September 1997 ; Modified, 26-Mar-2003, Zarro (EER/GSFC) 26-Mar-2003 ; - added FREE_MEM to free pointer/objects ; Modified, 26-Jul-2013 as 'delvar' for GDL, with 48 ; parameters,by G. Duvert ;- PRO delvar, p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28,p29,p30,p31,p32,p33,p34,p35,p36,p37,p38,p39,p40,p41,p42,p43,p44,p45,p46,p47 ; 48 is enough? FOR i = 0, N_PARAMS()-1 DO BEGIN ; for each parameter param = STRCOMPRESS("p" + STRING(i),/remove) ; only delete if defined on input (avoids error message) exestat = execute("defined=n_elements(" + param + ")" ) IF defined GT 0 THEN BEGIN exestat = execute("heap_free," + param) exestat = execute(param + "=0") exestat = execute("dvar=temporary(" + param + ")" ) ENDIF ENDFOR RETURN END gdl-0.9.9/src/pro/deriv.pro000066400000000000000000000200641340051421000155110ustar00rootroot00000000000000;+ ; NAME: DERIV ; ; PURPOSE: ; This function performs a numerical differentiation ; using a 3 points interpolation in Lagrangian way. ; The advantage of this procedure is we don't have to know the ; analytical equation of the "tabulated" data. ; Lagrangian interpolation means we "fit" the data with a polynomial ; which cross the data at collocation points. The fact we assume we ; have a polynomial give an explicit formula for the derivative. ; ; When only Y (data) are provided, a constant step of 1 is assumed ; between x-positions. Except at the edges, the formula is very simple. ; ; When X (positions) and Y (data) are provided, a more complex computation ; is donne. ; ; See below (in Section PROCEDURE) where you can found the formulae ; ; CATEGORY: Numerical analysis. ; ; CALLING SEQUENCE: ; result = DERIV, [x], y, [help=help], [test=test], [check=check] ; ; -- result = DERIV(data) (also : d=DERIV(Y)) ; -- result = DERIV(positions, data) (also : d=DERIV(X,Y)) ; ; INPUTS: ; -- When only one array (X) is provided, X contains the data to ; be differentiated () ; -- When two arrays are provided ; X is the array containing the positions of data (colocations) ; Y is the array containing the data ; ; OPTIONAL INPUTS: none ; ; KEYWORD PARAMETERS: ; -- no_check : since we do extra checks, do not do them ! ; (DESACTIVATED ! but we keep it for compatility issue) ; -- check : you can ask for extra tests on input ; ; -- Help : give a very simple summary of procedure then exit ; -- Test : will stop just before the return statement ; (useful for internal checking/debugging) ; ; OUTPUTS: Return the numerical derivative (Lagrangian formalism) ; Please note that the output type will be Float OR Double ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: none ; ; RESTRICTIONS: - We do check if the length of the 2 arrays (if 2) ; are the same (as in IDL) ; - We can check if the x(n+1)-x(n) is <> 0. (not ; done in IDL) ; - We can check if the X array is well sorted (not ; done in IDL) ; - We can check if Delta_x is constant or not (not ; done in IDL) ; - Neither IDL version or GDL version manage NaN values ; ; COMPATIBILITY: ; - this function is NOT FULLY compatible with the IDL one. ; NEVERTHELESS, it should give the same output with the same "normal" input(s). ; We DO have ADD some checks (zero steps, size of Y array, sorting, ; shortcut for constant step) which were missing in initial procedure. ; This will give clear warning when a problem is encountered. ; ; WARNING: ; - NaN values are maybe not fully managed now ; ; PROCEDURE: ; - in the IDL version, it is written that the procedure is described ; in Hildebrand, Introduction to Numerical Analysis, Mc Graw Hill, ; 1956, p. 82 (see IMCCE library, Bat A, Floor 2, Paris ; Observatory). But in that book, only the simple formulae for ; constant steps are explicitaly written. Nothing else in Chapter 3. ; ; - for the case with constant step, the procedure is obvious, ; except at the edges. We do use the formulae given in Hildebrand (p82) ; - when the X step is variable, a more complex computation is ; mandatory. We use the formulae written here: ; http://sonia_madani.club.fr/Cloaque/Arithmurgistan/Derivation/lagrange.html ; ; EXAMPLE: see also the accompagning program TEST_DERIV ; d=DERIV(REPLICATE(1.,nbp)) ; d=DERIV(x_pos, y_data) ; ; TESTABILITY: the best way is to try on a pure slope ! ; ; MODIFICATION HISTORY: ; - 17/03/2006 created by Alain Coulais (ARSC) ; - 09/10/2012 default is to be as tolerant as possible (/check if needed) ! ; ;- ; LICENCE: ; Copyright (C) 2006, 2012 Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ; ;- function DERIV, x, y, help=help, test=test, no_check=no_check, check=check ; ON_ERROR, 2 ; ; When GDL behavior of {MESSAGE, .skip, .Continue} will be similar to ; IDL, the following flag can be switch to 1 ! ; flag_message=1 name_proc='% DERIV: ' ; if ((N_PARAMS() EQ 0) OR (N_PARAMS() GT 2)) then begin if (flag_message EQ 1) then begin MESSAGE, 'Incorrect number of arguments' endif else begin print, '% DERIV: Incorrect number of arguments' help=1 endelse endif ; if KEYWORD_SET(help) then begin print, 'function DERIV, [x,] y, $' print, ' [help=help, test=test, no_check=no_check, check=check]' return, -1 endif ; nbp_x=N_ELEMENTS(x) if (nbp_x LT 3) then begin txt='Data must have at least 3 points !' if (flag_message EQ 1) then MESSAGE, txt else print, name_proc+txt return, -1 endif ; if (SIZE(x,/type) EQ 7) then begin txt='No STRING vector allowed !' if (flag_message EQ 1) then MESSAGE, txt else print, name_proc+txt return, -1 endif ; ; We check whether X and Y arrays have same size ! if (N_PARAMS() EQ 2) then begin nbp_y=N_ELEMENTS(y) if (nbp_x NE nbp_y) then begin txt='X and Y vectors must have same size !' if (flag_message EQ 1) then MESSAGE, txt else print, name_proc+txt return, -1 endif if (SIZE(y,/type) EQ 7) then begin txt='No STRING vector allowed !' if (flag_message EQ 1) then MESSAGE, txt else print, name_proc+txt return, -1 endif endif ; ; First case : we only have Data, no Position. ; That means that the data are equally spaced. ; We use the 3 formulae given by Hildebrand ; if (N_PARAMS() EQ 1) then begin ;; derivee=SHIFT(x,-1)-SHIFT(x,1) ;; ;; Specific computation for the 2 Edges ;; (if needed, the type conversion (Int/Long --> Float) will be ;; done here automatically) ;; derivee[0]=-3.0*x[0]+4.0*x[1]-x[2] derivee[nbp_x-1]=3.0*x[nbp_x-1]-4.0*x[nbp_x-2]+x[nbp_x-3] ;; derivee=derivee/2. endif ; ; Second case : we have Positions (X) and Data (Y) ; We use the formulae expressed on Web Site ; if (N_PARAMS() EQ 2) then begin if KEYWORD_SET(check) then begin ;; some checks : sorting, no-nul steps, no-constant steps, ... ;; dx=x-SHIFT(x,1) dx=dx[1:*] dx_min=MIN(dx) dx_max=MAX(dx) ;; ;; X locations must be sorted (by increasing order) ;; if (dx_min LT 0.0) then begin txt='X colocations MUST be sorted !' if (flag_message EQ 1) then MESSAGE, txt else print, name_proc+txt return, -1 endif ;; ;; X locations must be strictly different (to avoid zero division) ;; if (dx_min EQ 0.0) then begin txt='At least 2 X colocations are EQUAL !' if (flag_message EQ 1) then MESSAGE, txt else print, name_proc+txt return, -1 endif ;; ;; When All steps are equal, we can used "FAST" way ... ;; if (dx_min EQ dx_max) then begin if KEYWORD_SET(verbose) then print, name_proc+'Found constant STEP ... Algorithm changed' derivee=DERIV(y)/dx_min if KEYWORD_SET(test) then STOP return, derivee endif ;; after here, X are well conditionned ! ;; x0 < x1 < x2 endif ;; ;; 3 useful expressions ;; x0_x1=SHIFT(x,1)-x x1_x2=x-SHIFT(x,-1) x0_x2=SHIFT(x,1)-SHIFT(x,-1) ;; derivee=SHIFT(y,1)*x1_x2/(x0_x1*x0_x2) derivee=derivee+y*(1./x1_x2-1./x0_x1) derivee=derivee-SHIFT(y,-1)*x0_x1/(x0_x2*x1_x2) ;; ;; The 2 Edges (see matrix formulae on Web Page) ;; derivee[0]=y[0]*(1./x0_x1[1]+1./x0_x2[1]) derivee[0]=derivee[0]-y[1]*x0_x2[1]/(x0_x1[1]*x1_x2[1]) derivee[0]=derivee[0]+y[2]*x0_x1[1]/(x0_x2[1]*x1_x2[1]) ;; ;; useful index nm3=nbp_x-3 nm2=nbp_x-2 nm1=nbp_x-1 ;; derivee[nm1]=-y[nm3]*x1_x2[nm2]/(x0_x1[nm2]*x0_x2[nm2]) derivee[nm1]=derivee[nm1]+y[nm2]*x0_x2[nm2]/(x0_x1[nm2]*x1_x2[nm2]) derivee[nm1]=derivee[nm1]-y[nm1]*(1./x0_x2[nm2]+1./x1_x2[nm2]) endif ; if KEYWORD_SET(test) then STOP ; return, derivee ; end gdl-0.9.9/src/pro/diag_matrix.pro000066400000000000000000000110161340051421000166650ustar00rootroot00000000000000;+ ; ; please report problems / examples / extensions ; ; NAME: DIAG_MATRIX ; ; PURPOSE: 1/ returning the diagonal of the input matrix ; 2/ generating a square matrix with a given diagonal. ; ; CATEGORY: Matrix utilities ; ; CALLING SEQUENCE: ; - case 1: my_diagonal=DIAG_MATRIX(matrix) ; - case 2: matrix=DIAG_MATRIX(a_diag_vector, an_offset) ; ; INPUTS: ; - case 1: a matrix (square or not) ; - case 2: a vector (might be a singleton) ; ; OPTIONAL INPUTS: ; - case 1: none ; - case 2: an offset ; ; KEYWORD PARAMETERS: ; ; OUTPUTS: ; - case 1: a vector, the diagonal ; - case 2: a square matrix ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: none ; ; RESTRICTIONS: none known ! ; ; PROCEDURE: straightforward ; ; EXAMPLE: ; ; - case 1: print, DIAG_MATRIX(DIST(10)) ; ; - case 2: ; ** generating a NxN rotation matrix: ; matrix=DIAG_MATRIX(REPLICATE(1.,nbp-1),1) ; matrix[0,nbp-1]=1. ; ** generating a IDENTITY matrix (equal to: identity=IDENTITY(nbp) ; identity=DIAG_MATRIX(REPLICATE(1.,nbp)) ; ; MODIFICATION HISTORY: ; ; * 23-JAN-2012: initial version by Alain C. ; ; * 11-APR-2013: - in fact, when creating the output matrix, ; we have to derive the type from the input diagonal ! ; - more documentation ; ;- ; LICENCE: Copyright (C) 2012, 2013, Alain Coulais, under GNU GPL v2 or later ; ; 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 2 of the License, or ; (at your option) any later version. ;- ; function DIAG_MATRIX, input, position, $ debug=debug, help=help, test=test ; if N_PARAMS() EQ 0 then MESSAGE, 'Incorrect number of arguments.' ; if KEYWORD_SET(help) then begin print, 'function DIAG_MATRIX, input, position, $' print, ' debug=debug, help=help, test=test' return, -1 endif ; if SIZE(input,/n_dim) GT 2 then begin MESSAGE, 'Only 1 or 2 dimensions allowed '+input endif ; ; case 1, first usage: returning the diagonal ; if (SIZE(input,/n_dim) EQ 2) then begin if N_PARAMS() EQ 1 then position=0 info_size=SIZE(input,/dim) x=info_size[0] y=info_size[1] ;; diag=INDGEN(MIN([x,y])) ;; if (position EQ 0) then begin xx=diag yy=diag endif ;; txt='% Specified offset to array is out of range: ' ;; if (position GT 0) then begin if (position GE x) then begin MESSAGE, txt+STRING(position)+' versus: '+STRING(x) endif xx=diag+position xx=xx[WHERE(xx LT x)] yy=diag[0:N_ELEMENTS(xx)-1] endif if (position LT 0) then begin if (ABS(position) GE y) then begin MESSAGE, txt+STRING(position)+' versus: '+STRING(y) endif yy=diag+ABS(position) yy=yy[WHERE(yy LT y)] xx=diag[0:N_ELEMENTS(yy)-1] endif resu=REFORM(input[xx,yy]) if KEYWORD_SET(debug) then begin print, '-----------------------' print, 'x :', x, ', y :', y, ', Position indice: ', position print, 'input matrix :' print, input print, 'position XX :', xx print, 'position YY :', yy print, 'extracted vector :', resu endif endif ; ; case 2: second usage: generating a square matrix populated ; by "diagonals" passed by argument, with a given "offset". ; if (SIZE(input,/n_dim) LE 1) then begin ;; determining the size of the output matrix if N_PARAMS() EQ 1 then position=0 nbp=N_ELEMENTS(input)+ABS(position) ;; creating wthe output matrix with adequate type type=SIZE(input,/type) resu=MAKE_ARRAY(nbp,nbp, type=type) ;; diag=INDGEN(nbp) if (position EQ 0) then begin resu[diag,diag]=input xx=diag yy=diag endif if (position GT 0) then begin xx=diag+position xx=xx[WHERE(xx LT nbp)] yy=diag[0:N_ELEMENTS(xx)-1] resu[xx,yy]=input endif if (position LT 0) then begin yy=diag+ABS(position) yy=yy[WHERE(yy LT nbp)] xx=diag[0:N_ELEMENTS(yy)-1] resu[xx,yy]=input endif if KEYWORD_SET(debug) then begin print, '-----------------------' print, 'Position indice: ', position print, 'input vector :', input print, 'position XX :', xx print, 'position YY :', yy print, 'computed matrix :' print, resu endif endif ; if KEYWORD_SET(test) then STOP ; return, resu ; end gdl-0.9.9/src/pro/dialog_message.pro000066400000000000000000000304611340051421000173450ustar00rootroot00000000000000;+ ; NAME: DIALOG_MESSAGE ; ; PURPOSE: ; ; This function try to reproduce the IDL's DIALOG_MESSAGE behavior ; using "zenity" or "wxwidgets" ; ; zenity, under GNU GPL, is available on most Linux distributions and ; and also on OSX (tested) and MSwin (not tested ?). It is better to ; have zenity version >= 2.23.1. ; ; wxwidgets version >= 2.8 ; ; CATEGORY: ; ; CALLING SEQUENCE: ; ; resu_list=DIALOG_MESSAGE( Message_Text [, TITLE=string] ; [, /ERROR | , /INFORMATION | , /QUESTION] <<-- the main options ; [, /CANCEL] [, /CENTER] [, /DEFAULT_CANCEL | , /DEFAULT_NO] ; [,DIALOG_PARENT=widget_id] [, DISPLAY_NAME=string] [, RESOURCE_NAME=string]) ; ; INPUTS: ; Message_Text: A scalar string or string array that contains the text of ; the message to be displayed. If this argument is set to an array of strings, ; each array element is displayed as a separate line of text. ; ; OPTIONAL INPUTS: none ; ; KEYWORD PARAMETERS: ; CANCEL: Set this keyword to add a "Cancel" button to the dialog. ; CENTER: Set this keyword to center the dialog on the screen. ; DEFAULT_CANCEL: Set this keyword to make the "Cancel" button the default ; selection for the dialog. The default selection is the button that is selected ; when the user presses the default keystroke (usually Space or Return depending ; on the platform). Setting DEFAULT_CANCEL implies that the CANCEL keyword is also ; set. ; DEFAULT_NO: Set this keyword to make the "No" button the default selection ; for "Question" dialogs. Normally, the default is "Yes". ; DIALOG_PARENT: Set this keyword to the widget ID of a widget over which ; the message dialog should be positioned. When displayed, the DIALOG_MESSAGE dialog ; will be positioned over the specified widget. Dialogs are often related to a ; non-dialog widget tree. The ID of the widget in that tree to which the dialog is most ; closely related should be specified. ; DISPLAY_NAME: Set this keyword equal to a string indicating the name of the ; X Windows display on which the dialog is to appear. This keyword is ignored if the ; DIALOG_PARENT keyword is specified. This keyword is also ignored on Microsoft Windows ; platforms. ; ERROR: Set this keyword to create an "Error" dialog. The default dialog type ; is "Warning". ; INFORMATION: Set this keyword to create an "Information" dialog. The default ; dialog type is "Warning". ; QUESTION: Set this keyword to create a "Question" dialog. The default dialog ; type is "Warning". ; RESOURCE_NAME: A string containing an X Window System resource name to be applied ; to the dialog. See RESOURCE_NAME for a complete discussion of this keyword. ; TITLE: Set this keyword to a scalar string that contains the text of a title to ; be displayed in the dialog frame. If this keyword is not specified, the dialog has the ; dialog type as its title as shown in the table under DIALOG_MESSAGE. ; ; NON IDL KEYWORDS ; ; ZENITY_NAME: Set this keyword to a scalar string used to overwrite Zenity ; executable name. ; ZENITY_PATH: If set, Zenith will be searched in this path. If it doesn't ; exist, then it will be searched in common unix paths. This can also be done ; by exporting the shell variable $ZENITY_PATH. ; HELP: Display a help message and return ; DEBUG: Display bebug messages ; VERBOSE: Switch on verbose mode ; ; OUTPUTS: ; ; OPTIONAL OUTPUTS: ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: ; - due to Zenity's capacities, the function ingnores ; the keyword parameters: DEFAULT_CANCEL, DEFAULT_NO, ; DIALOG_PARENT, CENTER ; ; RESTRICTIONS: ; - need Zenity v2.23.1 or higher to use filters ; (--ok-label=TEXTE and --cancel-label=TEXTE ) ; - interface is not exactly the same ... ; ; PROCEDURE: straithforward ; ; EXAMPLE: resu_list=DIALOG_MESSAGE('hola') ; resu_list=DIALOG_MESSAGE('would you like to continue ?', /question) ; ; TESTABILITY: please test using interactive TEST_DIALOG_MESSAGE in testsuite/ ; and add new test cases in this file ; ; MODIFICATION HISTORY: ; ; 23-Feb-2011: Implemented by Pedro Corona from DIALOG_PICKFILE written by Maxime Lenoir. ; 2-Mar-2011: Alain Coulais: Included the capability of manage more than one line of text ; older zenity Version management (no custom filters before v2.23.1) ; 15-Nov-2012: AC: complete revision, some codes exported into common ZENITY_CHECK() ; for better maintainability, better stick to orignal, ; using --list when need (old Zenity or/and /cancel) ; 05-Apr-2015: JP: Code for Windows platform is added. ;- ; ; This function try to reproduce the IDL's DIALOG_MESSAGE behavior using "zenity". ; ; zenity, under GNU GPL, is available in package on most Linux ; distributions (available and tested on CentOS 5.4, Mandriva 2010 and Ubuntu 9.04) ; Also on OSX: http://www.macports.org/ports.php?by=name&substr=zenity ; ; Since the implementation use Zenity as dialog messenger, ; some functionalities are different from the original one ; but this function works well for general purpose. ; ; Make sure that you have Zenity in your PATH ; You need to have Zenity v2.23.1 or higher to use filters and /Cancel renaming. ; ; Note: this code was tested, in conjonction with TEST_DIALOG_MESSAGE ; with Zenity 2.16, 2.24 and 2.30. Please report output of ; "zenity --version" and error code from TEST_DIALOG_MESSAGE if problem. ; ;- ; LICENCE: ; Copyright (C) 2011, Pedro Corona and Maxime Lenoir (main author), ; 2012 Alain Coulais. 2015 JPark. ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; function DIALOG_MESSAGE_ZENITY, Message_Text, TITLE=title, CANCEL=cancel, $ ERROR=error, INFORMATION=information, QUESTION=question, $ DEFAULT_CANCEL=defaul_cancel, DEFAULT_NO=default_no, $ CENTER=center, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, RESOURCE_NAME=resource_name, $ HELP=help, test=test, debug=debug, $ ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path on_error, 2 ; if (N_params() NE 1) then MESSAGE, 'Incorrect number of arguments.' ; zenity=ZENITY_CHECK( zenity_name=zenity_name, zenity_path=zenity_path, $ zenity_version=zenity_version, $ help=help, test=test, debug=debug, verbose=verbose) ; ; improbing more than one text line zenity_message_text=Message_Text[0] for i=1, N_ELEMENTS(Message_Text)-1 do zenity_message_text+='\n'+Message_Text[i] ; cmd=zenity+' --text="'+zenity_message_text+'" ' ; ; Set the X Window display if KEYWORD_SET(display_name) then cmd+='--display="'+STRING(display_name)+'" ' if KEYWORD_SET(resource_name) then cmd+='--name="'+STRING(resource_name)+'" ' ; ; TITLE or INFORMATIONAL or ERROR ; default title (if nothing provided, is "Warning") title='' if KEYWORD_SET(error) then title='Error' if KEYWORD_SET(question) then title='Question' if KEYWORD_SET(error) AND KEYWORD_SET(question) then title='Information' if KEYWORD_SET(information) then title='Information' if KEYWORD_SET(title) then title=STRING(title[0]) if STRLEN(title) GT 0 then cmd+='--title="'+title+'" ' ; ;temporal string to store the kind of zenity in. ;default option INFORMATION ;kindof='--info' ; ERROR ;if KEYWORD_SET(error) then kindof='--warning' ; QUESTION ;if KEYWORD_SET(question) && ~KEYWORD_SET(information) && ~KEYWORD_SET(error) then begin ; even with new zenity, we cannot have directly 3 buttons ... ; if KEYWORD_SET(question) then begin if KEYWORD_SET(cancel) then begin kindof='--list --column="selection" "Yes" "Cancel" "No"' endif else begin if (zenity_version GE 22301) then begin kindof='--question --cancel-label="No" --ok-label="Yes"' endif else begin ;; old zenity: names of buttons cannot be changed ... kindof='--question' endelse endelse endif else begin if KEYWORD_SET(cancel) then begin if (zenity_version GE 22301) then begin kindof='--question --cancel-label="Cancel" --ok-label="Yes"' endif else begin kindof='--list --column="selection" "Cancel" "OK"' endelse endif else begin kindof='--error' endelse endelse ; if KEYWORD_SET(debug) then begin print, 'commande :', cmd print, 'option :', kindof endif ; cmd+=kindof ; ; effective call to external Zenity SPAWN, cmd, result, error, exit_status=exit_status ; if KEYWORD_SET(debug) then begin print, 'Zenity result : ', result print, 'Zenity error : ', error print, 'Zenity exit status : ', exit_status endif ; reponse='Failed' if ~KEYWORD_SET(question) AND ~KEYWORD_SET(cancel) then reponse='OK' if ~KEYWORD_SET(question) AND KEYWORD_SET(cancel) then begin if (zenity_version GE 22301) then begin if (exit_status eq 0) then reponse='OK' else reponse='Cancel' endif else begin ;; because we needed to use the "--list" reponse=result endelse endif ; if KEYWORD_SET(question) then begin if ~KEYWORD_SET(cancel) then begin if (exit_status eq 0) then reponse='Yes' else reponse='No' endif else begin ;; this is directly the result from Zenity ! (result is is {Yes|Cancel|No}) reponse=result endelse endif ; ; due to strange logic maybe unexpected case remaining ? if reponse EQ 'Failed' then begin MESSAGE,/continue, 'You triggered an unexpected case' MESSAGE,/continue, 'Please report the case (bug) to GDL team on sf.net !' endif ; if KEYWORD_SET(test) then STOP ; return, reponse ; end ; ; ------------------------------------------------------------ ; function DIALOG_MESSAGE, Message_Text, TITLE=title, CANCEL=cancel, $ ERROR=error, INFORMATION=information, QUESTION=question, $ DEFAULT_CANCEL=defaul_cancel, DEFAULT_NO=default_no, $ CENTER=center, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, RESOURCE_NAME=resource_name, $ HELP=help, test=test, debug=debug, $ ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path, $ FORCE_ZENITY=force_zenity on_error, 2 ; if KEYWORD_SET(help) then begin print, 'function DIALOG_MESSAGE, Message_Text, TITLE=title, CANCEL=cancel, $' print, ' ERROR=error, INFORMATION=information, QUESTION=question, $' print, ' DEFAULT_CANCEL=defaul_cancel, DEFAULT_NO=default_no, $' print, ' CENTER=center, DIALOG_PARENT=dialog_parent, $' print, ' DISPLAY_NAME=display_name, RESOURCE_NAME=resource_name, $' print, ' HELP=help, test=test, debug=debug, $' print, ' ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path, FORCE_ZENITY=force_zenity' return, -1 endif ; if (N_params() NE 1) then MESSAGE, 'Incorrect number of arguments.' ; wxwidget_available = (!version.OS eq 'Windows') ? 0 : WXWIDGETS_EXISTS() ; if (wxwidget_available) and not(KEYWORD_SET(FORCE_ZENITY)) then begin return, DIALOG_MESSAGE_WXWIDGETS(Message_Text, TITLE=title, CANCEL=cancel, $ ERROR=error, INFORMATION=information, QUESTION=question, $ DEFAULT_CANCEL=defaul_cancel, DEFAULT_NO=default_no, $ CENTER=center, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, RESOURCE_NAME=resource_name) endif else if (!version.OS eq 'Windows') then begin print,Message_text endif else begin return, DIALOG_MESSAGE_ZENITY(Message_Text, TITLE=title, CANCEL=cancel, $ ERROR=error, INFORMATION=information, QUESTION=question, $ DEFAULT_CANCEL=defaul_cancel, DEFAULT_NO=default_no, $ CENTER=center, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, RESOURCE_NAME=resource_name, $ HELP=help, test=test, debug=debug, $ ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path) endelse ; end ; gdl-0.9.9/src/pro/dialog_pickfile.pro000066400000000000000000000431411340051421000175060ustar00rootroot00000000000000;+ ; NAME: DIALOG_PICKFILE ; ; PURPOSE: ; ; This function try to reproduce the IDL's DIALOG_PICKFILE ; behavior using "zenity" or "wxwidgets". ; ; zenity, under GNU GPL, is available on most Linux distributions ; and also on OSX (tested) It is better to ; have zenity version >= 2.23.1 for smarter capabilities. ; ; CATEGORY: ; ; CALLING SEQUENCE: resu_list=DIALOG_PICKFILE() ; ; INPUTS: none ; ; OPTIONAL INPUTS: none ; ; KEYWORD PARAMETERS: ; DEFAULT_EXTENSION: Set this keyword to a scalar string ; representing the default extension to be appended onto the returned file name ; or names. If the returned file name already has an extension, ; then the value set for this keyword is not appended. The string value set ; for this keyword should not include a period (.). ; DIALOG_PARENT: This keywork isn't supported. ; DIRECTORY: Set this keyword to display only the existing ; directories in the directory specified by the PATH keyword. If a path is not ; specified, setting this keyword shows directories in the current directory. ; The Browse for Folder dialog is opened to the directory specified by the path ; definition. Individual files are displayed but can't be selected. ; The return value contains the path of the directory selected, or ; directory created and selected by the user. ; DISPLAY_NAME: X display ; FILE: Set this keyword to a scalar string that contains the name ; of the initial file selection. This keyword is useful for specifying a default ; filename. ; FILTER: Set this keyword to a string value or an array of strings ; specifying the file types to be displayed in the file list. This keyword is ; used to reduce the number of files displayed in the file list. The user can ; modify the filter unless the FIX_FILTER keyword is set. If the value contains ; a vector of strings, multiple filters are used to filter the files. ; The filter *.* is automatically added to any filter you specify. ; Needs Zenity >= 2.23.1 ; FIX_FILTER: This keyword isn't supported ; GET_PATH: Set this keyword to a named variable in which the path of ; the selection is returned. ; GROUP: Ths keyword isn't supported ; MULTIPLE_FILES: Set this keyword to allow for multiple file selection ; in the file-selection dialog. When you set this keyword, the user can select ; multiple files using the platform-specific selection method. The currently ; selected files appear in the selection text field of the dialog. ; With this keyword set, DIALOG_PICKFILE can return a string array that contains ; the full path name of the selected file or files. ; MUST_EXIST: Set this keyword to allow only files that already exist ; to be returned ; OVERWRITE_PROMPT: If this keyword is set along with the WRITE keyword ; and the user selects a file that already exists, then a dialog will be displayed ; asking if the user wants to replace the existing file or not. ; For multiple selections, the user is prompted separately for each file. ; If the user selects "No" the file won't be returned; if the user selects "Yes" ; then the selection is allowed. This keyword has no effect unless the WRITE ; keyword is also set. ; PATH: Set this keyword to a string that contains the initial path from ; which to select files. Relative paths are appended to current working directory. ; If this keyword is not set, current working directory is used. ; READ: Set this keyword to make the title of the dialog ; "Please Select a File|Directory for Reading". ; RESOURCE_NAME: X name ; TITLE: Set this keyword to a scalar string to be used for the dialog title. ; If it is not specified, the default title is "Please Select a File|Directory". ; WRITE: Set this keyword to make the title of the dialog "Please Select a ; File|Directory for Writing". This keyword must be set to allow OVERWRITE_PROMPT. ; ; NON IDL KEYWORDS ; ; ZENITY_NAME: Set this keyword to a scalar string used to overwrite Zenity ; executable name. ; ZENITY_PATH: If set, Zenity will be searched in this path. If it doesn't ; exist, then it will be searched in common unix paths. This can also be done ; by exporting the shell variable $ZENITY_PATH. ; HELP: Display a help message and return ; DEBUG: Display bebug messages ; VERBOSE: Switch on verbose mode ; ; ; OUTPUTS: ; ; OPTIONAL OUTPUTS: ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: ; ; RESTRICTIONS: ; * Zenity version: ; - need Zenity v2.23.1 or higher to use filters. ; - interface is not exactly the same depending Zenity ; versions ... ; * wxWidgets version: ; - need wx 2.8 or higher ; ; PROCEDURE: straithforward ; ; EXAMPLE: files=DIALOG_PICKFILE(FILTER=['*.c','*.cpp'],/MULTIPLE_FILES) ; ; MODIFICATION HISTORY: ; ; Idea by Alain Coulais on June 2010, implementation by Maxime Lenoir ; (first public version 16 June 2010). ; ; 06-JUN-2011: - dates in ESO FITS files are using ":" as a separator, ; in conflict with Zenity internal separator. Adding ; a new parameter (ZENITY_SEP) and move to "|" as ; default. ; - if keyword DEBUG set to a number > 1 then the zenity command ; is printed, if > 2 then we exit ; ; 14-NOV-2012: - large part of code, common with DIALOG_MESSAGE, ; related to Zenity, moved into ZENITY_CHECK() ; ; 14-May-2013: - correcting "bug" 3612324: must start in current directory when ; no path given. This problem appears due to change in ; Zenity in Gnome3 (e.g. : http://www.kirsle.net/blog/kirsle/zenity-and-gnome-3) ; ; 03-Apr-2015: - JP: Code for Windows platform is added. ; ;- ; ; This function try to reproduce the IDL's DIALOG_PICKFILE behavior using "zenity". ; ; zenity, under GNU GPL, is available in package on most Linux ; distributions (available and tested on CentOS 5.4, Mandriva 2010 and Ubuntu 9.04) ; Also on OSX: http://www.macports.org/ports.php?by=name&substr=zenity ; ; Since the implementation use Zenity as File Selector, ; some functionalities are different from the original one ; but this function works well for general purpose. ; ; Make sure that you have Zenity in your PATH ; You need to have Zenity v2.23.1 or higher to use filters. ; ; If you try to get existing files w/ /WRITE and /OVERWRITE_PROMPT, ; you'll be prompted when the main dialog get closed. ; Each cancelation leads to the removal of the associated file ; from the returned file list. ; ; Default extension also applies to selected files ; (and not only to file names typed into the dialog) ; ;- ; LICENCE: ; Copyright (C) 2010, Maxime Lenoir (main author) and Alain Coulais (idea, contact) ; ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; ; function DIALOG_PICKFILE_ZENITY, DEFAULT_EXTENSION=default_extension, $ DIRECTORY=directory, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, FILE=file, FILTER=filter, $ FIX_FILTER=fix_filter, GET_PATH=get_path, GROUP=group, $ MULTIPLE_FILES=multiple_files, MUST_EXIST=must_exist, $ OVERWRITE_PROMPT=overwrite_prompt, PATH=path, $ READ=read, WRITE=write, RESOURCE_NAME=resource_name, $ TITLE=title, $ ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path, $ ZENITY_SEP=ZENITY_SEP, $ HELP=help, test=test, debug=debug, verbose=verbose ; ; ; zenity=ZENITY_CHECK( zenity_name=zenity_name, zenity_path=zenity_path, $ zenity_version=zenity_version, $ help=help, test=test, debug=debug, verbose=verbose) ; if (!zenity.version LT 0) then begin return, '' endif ; ; Check default_extension if KEYWORD_SET(default_extension) then default_extension=STRING(default_extension[0]) ; ; Zenity file selection mode cmd=zenity+' --file-selection ' get_path='' ; ; Only display directories if KEYWORD_SET(directory) then begin cmd+='--directory ' type='Directory' endif else type='File' ; Dialog_parent can't be used w/ Zenity ; Set the X Window display if KEYWORD_SET(display_name) then cmd+='--display="'+STRING(display_name)+'" ' if KEYWORD_SET(resource_name) then cmd+='--name="'+STRING(resource_name)+'" ' ; Set the initial file selection. Since zenity can't distinguish initial path from initial selected file, ; we have to concatenate path and file ; if path is set and exist, initial path = path ; if path and file are set, then initial = path/file if exists, path otherwise (or current working directory if invalid path) ; if file is set, initial = file ; Zenity can't initialy select a non-exising file/directory ; ; in gnome3, by default, Zenity (eg: 3.4.0 in Ubuntu 12.04) ; uses value storing in ~/.recently-used ; for the path. We must set it up now :( ; (no side effects found up to now with older versions of Zenity) ; start='' if KEYWORD_SET(path) then begin path=STRING(path[0]) start+=path+path_sep() endif else begin CD, current=current path=current start+=current+path_sep() end ; if KEYWORD_SET(file) then file=STRING(file[0]) ; if start ne '' then begin if KEYWORD_SET(file) && FILE_TEST(start+file) then begin cmd+='--filename="'+start+file+'" ' endif else begin if FILE_TEST(start) then cmd+='--filename="'+start+'" ' endelse endif ; ; Set the filters (Zenity version >= 2.23.1) ; if KEYWORD_SET(filter) then begin if (zenity_version lt 22301) then begin MESSAGE, 'Zenity version need to be >= 2.23.1 to support filters', /cont endif else begin ;; Check if zenity ver < 2.23.1 if SIZE(filter, /dimensions) eq 0 then filter=[filter] ; Filter is as scalar STRING filters='' fsize=SIZE(filter, /n_elements) if fsize gt 0 then begin ;; Transform filter in Zenity(GTK) syntax for i=0, fsize-1 do filter[i]=STRJOIN(STRSPLIT(STRING(filter[i]), ';', /extract), ' ') if fsize gt 1 then begin ; concatenate all filters for i=0, fsize-2 do begin filters+=STRING(filter[i])+' ' endfor filters+=STRING(filter[fsize-1]) cmd+='--file-filter="'+filters+'" ' ; Add gobal filter endif for i=0, fsize-1 do cmd+='--file-filter="'+filter[i]+'" ' ; Add individual filters cmd+='--file-filter="*.*" ' ; Add no-filter endif endelse endif ; Can't perform fix_filter w/ Zenity ; Group (Dialog_parent) can't be used w/ Zenity ; Set multiple files option ; if N_ELEMENTS(zenity_sep) EQ 0 then zenity_sep='|' ; if KEYWORD_SET(multiple_files) then begin if KEYWORD_SET(directory) then begin MESSAGE, 'Selecting multiple directories is not supported.',/cont endif else begin cmd+='--multiple --separator="'+zenity_sep+'" ' endelse endif ; ; Must exist can't be used w/ Zenity, but if the selected file ; doesn't exist, it won't be returned (see below) ; ; Read KW if KEYWORD_SET(read) && ~KEYWORD_SET(title) && ~KEYWORD_SET(write) then begin cmd+='--title="Please Select a '+type+' for Reading" ' endif ; ; Resource_name can't be used w/ Zenity ; ; Write KW if KEYWORD_SET(write) && ~KEYWORD_SET(title) && ~KEYWORD_SET(read) then begin readtitle='"Please Select a '+type+' for Writing" ' cmd+='--title='+readtitle endif ; R/W KW if KEYWORD_SET(read) && KEYWORD_SET(write) && ~KEYWORD_SET(title) then begin readtitle='"Please Select a '+type+' for Reading for Writing" ' cmd+='--title='+readtitle endif ; Set window title if KEYWORD_SET(title) then begin title=STRING(title[0]) cmd+='--title="'+title+'" ' endif else begin if ~KEYWORD_SET(read) && ~KEYWORD_SET(write) then begin cmd+='--title="Please Select a '+type+'" ' endif endelse ; if KEYWORD_SET(debug) then begin if debug GT 1 then MESSAGE,/continue, "Zenity command: "+cmd if debug GT 2 then return, '' endif ; ; Call Zenity SPAWN, cmd, result, exit_status=ex if (ex ne 0) then return, '' ; ; Zenity is known to return string arrays if result is gt than some ; length ... (1024 on CentOS 5.5 x86_64) merge in one string result=STRJOIN(TEMPORARY(result)) ; results=STRSPLIT(result, zenity_sep, /extract) rsize=SIZE(results, /n_elements) if (rsize eq 0) then return, '' ; Set the path ; If directory, get_path = the directory ; else get_path = result's directory if KEYWORD_SET(directory) then begin get_path=results[0]+PATH_SEP() endif else begin get_path=FILE_DIRNAME(results[0])+PATH_SEP() endelse ; Must exist filter if KEYWORD_SET(must_exist) then begin ix=WHERE(FILE_TEST(results), c) if c eq 0 then return, '' ; No file exist results=results[ix] rsize=SIZE(results, /n_elements) if rsize eq 0 then return, '' endif ; Overwrite prompt if KEYWORD_SET(overwrite_prompt) && KEYWORD_SET(write) then begin ;; Zenity can't be in save and multiselection mode at the same time ;; That's why save mode is disable and overwrite prompt is done when Zenity returns MESSAGE, 'For each cancelation, associated file will be deleted from the file list at return', /cont over=BYTARR(rsize) for i=0, rsize-1 do begin ; for each selected files if FILE_TEST(results[i]) then begin ; check if it already exists SPAWN, zenity+' --question --title='+readtitle+'--text="'+results[i]+' already exists.\nDo you want to replace it ?"', exit_status=ex over[i]=~ex ; As Zenity can't pop-up question dialog, if user don't want to overwrite the file, just pop it from the list endif endfor ix=WHERE(over, c) ; indexes of files which must be deleted if c eq 0 then return, '' ; if every files have to be deleted, return results=results[ix] ; Delete file that shouldn't be overwritten rsize=SIZE(results, /n_elements) if rsize eq 0 then return, '' endif ; default extension (simple behaviour, unlike IDL [no filter taken into account]) if KEYWORD_SET(default_extension) then begin w=WHERE(STRPOS(FILE_BASENAME(results),'.') eq -1) if w ne [-1] then results[w]+='.'+default_extension endif ; if KEYWORD_SET(debug) OR KEYWORD_SET(debug) then STOP ; return, results ; end ; ; -------------------------------------------------------------- ; function DIALOG_PICKFILE, DEFAULT_EXTENSION=default_extension, $ DIRECTORY=directory, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, FILE=file, FILTER=filter, $ FIX_FILTER=fix_filter, GET_PATH=get_path, GROUP=group, $ MULTIPLE_FILES=multiple_files, MUST_EXIST=must_exist, $ OVERWRITE_PROMPT=overwrite_prompt, PATH=path, $ READ=read, WRITE=write, RESOURCE_NAME=resource_name, $ TITLE=title, $ ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path, $ ZENITY_SEP=ZENITY_SEP, FORCE_ZENITY=force_zenity, $ HELP=help, test=test, debug=debug, verbose=verbose ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'function DIALOG_PICKFILE, DEFAULT_EXTENSION=default_extension, $' print, ' DIRECTORY=directory, DIALOG_PARENT=dialog_parent, $' print, ' DISPLAY_NAME=display_name, FILE=file, FILTER=filter, $' print, ' FIX_FILTER=fix_filter, GET_PATH=get_path, GROUP=group, $' print, ' MULTIPLE_FILES=multiple_files, MUST_EXIST=must_exist, $' print, ' OVERWRITE_PROMPT=overwrite_prompt, PATH=path, ' print, ' READ=read, WRITE=write, RESOURCE_NAME=resource_name, $' print, ' TITLE=title, ' print, ' ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path, $' print, ' ZENITY_SEP=ZENITY_SEP, FORCE_ZENITY=force_zenity, $' print, ' HELP=help, test=test, debug=debug, verbose=verbose' return, '' endif ; wxwidget_available = WXWIDGETS_EXISTS() ; if (wxwidget_available) and not(KEYWORD_SET(FORCE_ZENITY)) then begin return, DIALOG_PICKFILE_WXWIDGETS(DEFAULT_EXTENSION=default_extension, $ DIRECTORY=directory, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, FILE=file, FILTER=filter, $ FIX_FILTER=fix_filter, GET_PATH=get_path, GROUP=group, $ MULTIPLE_FILES=multiple_files, MUST_EXIST=must_exist, $ OVERWRITE_PROMPT=overwrite_prompt, PATH=path, $ READ=read, WRITE=write, RESOURCE_NAME=resource_name, $ TITLE=title) endif else begin return, DIALOG_PICKFILE_ZENITY(DEFAULT_EXTENSION=default_extension, $ DIRECTORY=directory, DIALOG_PARENT=dialog_parent, $ DISPLAY_NAME=display_name, FILE=file, FILTER=filter, $ FIX_FILTER=fix_filter, GET_PATH=get_path, GROUP=group, $ MULTIPLE_FILES=multiple_files, MUST_EXIST=must_exist, $ OVERWRITE_PROMPT=overwrite_prompt, PATH=path, $ READ=read, WRITE=write, RESOURCE_NAME=resource_name, $ TITLE=title, $ ZENITY_NAME=zenity_name, ZENITY_PATH=zenity_path, $ ZENITY_SEP=ZENITY_SEP, $ HELP=help, test=test, debug=debug, verbose=verbose) endelse ; end gdl-0.9.9/src/pro/dicom/000077500000000000000000000000001340051421000147475ustar00rootroot00000000000000gdl-0.9.9/src/pro/dicom/gdlffdicom__assoc__define.pro000066400000000000000000001013361340051421000225730ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ;+ ;

Definition of each DICOM tag in the buffer

;@private ;- pro GDLffDICOMTag__define, struct struct = {GDLffDICOMTag, $ group_number: 0u, $ element_number: 0u, $ index:0l,$ vr:'', $ len:0l, $ description: '', $ commit: 0b, $ value: ptr_new()} end ;+ ;

Definition of each DICOM Dictionary entry

;@private ;- pro GDLffDICOMDictionary__define, struct, INIT=init struct = replicate({GDLffDICOMDictionary, $ group_number: 0u, $ element_number: 0u,$ vr: '', $ vm: '', $ name: '', $ version: ''},2085) if (keyword_set(init)) then begin ; The Dictionary procedure is generated code from dicom.dic in the GPL ; release of DCMTK by OFFIS software gdlffdicom__dictionary, struct endif end ;+ ;

Open a DICOM file and parse DICOM tags

;@param filename {in}{required}{type=String} Open and parse this filename ;@keyword auto_syntax {in}{optional} Automatically determine the ;transfer syntax (recommended) ;@keyword raise {in}{optional} Raise an exception in the calling ;program if an error occurs (useful for debugging) ;@keyword index_tags {in}{optional} Index group and element numbers ;(necessary for accessing DICOM tags by group and element number) ;@keyword index_sequences {in}{optional} Index sequence information ;(necessary for accessing DICOM tags in nested sequences) ;@keyword implicit_vr {in}{optional} Parse using the Implicit VR transfer syntax ;@keyword explicit_vr {in}{optional} Parse using the Explicit VR transfer syntax ;@keyword big_endian {in}{optional} Parse as a Big Endian file ;@keyword little_endian {in}{optional} Parse as a Little Endian file ;@keyword limit {in}{optional}{type=long} Only parse a limited number of bytes ;@keyword meta_only {in}{optional} Only parse the meta header ;@keyword access_time {out}{optional} The number of seconds taken to open and ;parse the file. ;@keyword no_catch {private} Do not catch any exceptions ;@returns 1 if file was opened and parsed, 0 if there was an error ;- function GDLffDICOM__assoc::Open, filename, IMPLICIT_VR=implicit_vr, EXPLICIT_VR=explicit_vr, ACCESS_TIME=access_time, BIG_ENDIAN=big_endian, LITTLE_ENDIAN=little_endian, $ LIMIT=limit, INDEX_TAGS=index_tags, META_ONLY=meta_only, AUTO_SYNTAX=auto_syntax, NO_CATCH=no_catch, RAISE=raise, INDEX_SEQUENCES=index_sequences, READ_ONLY=read_only ; Check keywords if (keyword_set(auto_syntax) and keyword_set(meta_only)) then message, LEVEL=-1, "Auto syntax and meta only are mutually exclusive keywords." if (~ keyword_set(auto_syntax)) then begin if (~keyword_set(little_endian) and ~keyword_set(big_endian)) then auto_syntax = 1b ; message, LEVEL=-1, "Neither big nor little endian is set" if (~keyword_set(implicit_vr) and ~keyword_set(explicit_vr)) then auto_syntax = 1b ; message, LEVEL=-1, "Neither explicit of implicit VR is set" endif if (keyword_set(little_endian) and keyword_set(big_endian)) then message, LEVEL=-1, "Cannot set both big and little endian" if (keyword_set(big_endian) and keyword_set(implicit_vr)) then message, LEVEL=-1, "Implicit big endian is not a vlaid transfer syntax" if (self.lun ne 0) then message, LEVEL=-1, "Cannot open another file while one is already open. Try GDLffDICOM__assoc::close" if (~ keyword_set(no_catch)) then begin CATCH, Error_status IF Error_status NE 0 then begin ; Close the file and generate an error message Error_message = !ERR_STRING CATCH,/CANCEL self -> close if (keyword_set(raise)) then begin on_error, 2 Message, Error_message, LEVEL=-1 ; Generate message to caller endif else return, 0b endif endif if (arg_present(access_time) or (n_elements(access_time) gt 0)) then start_time = systime(1) if (keyword_set(auto_syntax)) then begin index_tags = 1 ; Just open the meta header of the file at little endian if (self -> open(filename, /IMPLICIT_VR, /LITTLE_ENDIAN, /META_ONLY, INDEX_TAGS=index_tags, /NO_CATCH, /READ_ONLY)) then begin ; Read the tansfer syntax tag if (self -> readelement('0002'x,'0010'x, TransferSyntaxUID, VR='UI')) then begin TransferSyntaxUID = (strtrim(gdlffdicom_trim(strjoin(TransferSyntaxUID,'')),2)) case (TransferSyntaxUID) of '1.2.840.10008.1.2.2': begin little_endian=0 implicit_vr=0 end '1.2.840.10008.1.2.1': begin little_endian=1 implicit_vr=0 end '1.2.840.10008.1.2': begin little_endian=1 implicit_vr=1 end else: message, "Transfer syntax unknown '" + TransferSyntaxUID + "' for file " + filename endcase big_endian = ~ little_endian explicit_vr = ~ implicit_vr endif else message, "Transfer Syntax UID not found" endif self -> close endif if(keyword_set(explicit_vr)) then self.explicit_vr = 1b if(keyword_set(implicit_vr)) then self.explicit_vr = 0b self.index_tags = keyword_set(index_tags) self.index_sequences = keyword_set(index_sequences) if (keyword_set(big_endian)) then self.big_endian = 1b if (keyword_set(little_endian)) then self.big_endian = 0b self.read_only = keyword_set(read_only) if (self.read_only) then begin if (self.big_endian) then $ openr, lun, filename, /get_lun, /swap_if_little_endian $ ; This is a big endian file else $ openr, lun, filename, /get_lun, /swap_if_big_endian ; This is a little endian file endif else begin if (self.big_endian) then $ openu, lun, filename, /get_lun, /swap_if_little_endian $ ; This is a big endian file else $ openu, lun, filename, /get_lun, /swap_if_big_endian ; This is a little endian file endelse self.lun = lun ; The standard DICOM header is 132 bytes offset = 128l point_lun, self.lun, offset chars = ' ' readu, self.lun, chars if (chars ne 'DICM') then message, "Not a valid DICOM file " + filename offset = offset + 4l inside_metadata = 1b index = 0l bufgrow = 1024l bufsize = bufgrow (*self.offsets) = lonarr(bufgrow) (*self.lens) = lonarr(bufgrow) (*self.vrs) = strarr(bufgrow) if (self.index_tags) then begin (*self.group_numbers) = uintarr(bufgrow) (*self.element_numbers) = uintarr(bufgrow) endif if (self.index_sequences) then begin (*self.parent_sequences) = lonarr(bufgrow) (*self.item_numbers) = lonarr(bufgrow) (*self.parent_items) = lonarr(bufgrow) current_sequence = replicate(-1l,20) current_item = replicate(-1l,20) current_item_number = replicate(-1l,20) current_nesting = 0l stop_offset = replicate('FFFFFFFF'x,20) endif stat = fstat(lun) if (n_elements(limit) eq 0) then limit = stat.size while (offset + 4l lt limit) do begin is_delimiter = 0b if (inside_metadata or self.index_tags) then begin point_lun, self.lun, offset tag = uintarr(2) readu, self.lun, tag is_delimiter = (tag[0] eq 'FFFE'x) and ((tag[1] eq 'E000'x) or (tag[1] eq 'E00D'x) or (tag[1] eq 'E0DD'x)) if (inside_metadata) then begin ; metadata is always little endian ; a big endian file will need to be swapped again if (self.big_endian) then $ swap_endian_inplace, tag ; No more 0002 group tags indicates the end of the meta-data set if (tag[0] ne '0002'x) then begin inside_metadata = 0b if (self.big_endian) then $ swap_endian_inplace, tag if (keyword_set(meta_only)) then begin self.size = index if (arg_present(access_time) or (n_elements(access_time) gt 0)) then access_time = systime(1) - start_time return, 1b endif endif endif endif if (~is_delimiter and (self.explicit_vr or inside_metadata)) then begin offset = offset + 4l point_lun, self.lun, offset vr = ' ' readu, self.lun, vr vr_inds = where(vr eq ['OB', 'OW', 'OF', 'SQ', 'UT', 'UN'],vr_count) if (vr_count gt 0) then begin offset = offset + 4l point_lun, self.lun, offset len = 0ul readu, self.lun, len offset = offset + 4l endif else begin offset = offset + 2l point_lun, self.lun, offset len = 0u readu, self.lun, len offset = offset + 2l endelse endif else begin vr = '' dict_inds = where((self.dictionary.group_number eq tag[0]) and (self.dictionary.element_number eq tag[1]),dict_count) if (dict_count gt 0) then vr = self.dictionary[dict_inds[0]].vr offset = offset + 4l point_lun, self.lun, offset len = 0l readu, self.lun, len offset = offset + 4l endelse if (inside_metadata) then begin ; metadata is always little endian ; a big endian file will need to be swapped again if (self.big_endian) then $ swap_endian_inplace, len endif (*self.offsets)[index] = offset (*self.lens)[index] = len (*self.vrs)[index] = vr if (self.index_tags) then begin (*self.group_numbers)[index] = tag[0] (*self.element_numbers)[index] = tag[1] endif if (self.index_sequences) then begin (*self.parent_sequences)[index] = current_sequence[current_nesting] if (is_delimiter and (tag[1] eq 'E000'x)) then begin len = 0l current_item_number[current_nesting] = current_item_number[current_nesting] + 1l (*self.item_numbers)[index] = current_item_number[current_nesting] current_item[current_nesting] = index if ((*self.parent_sequences)[index] ge 0) then $ (*self.parent_items)[index] = (*self.parent_items)[(*self.parent_sequences)[index]] endif else begin (*self.parent_items)[index] = current_item[current_nesting] (*self.item_numbers)[index] = current_item_number[current_nesting] if (vr eq 'SQ') then begin current_nesting = current_nesting + 1 if (current_nesting ge 20) then message, "No more than 20 sequences can be nested" current_sequence[current_nesting] = index current_item_number[current_nesting] = 0l if (len ne 'FFFFFFFF'x) then stop_offset[current_nesting] = offset + len $ else stop_offset[current_nesting] = 'FFFFFFFF'x len = 0l endif if (is_delimiter and (tag[1] eq 'E0DD'x) and (stop_offset[current_nesting] eq 'FFFFFFFF'x)) then $ stop_offset[current_nesting] = offset + len endelse while ((current_nesting gt 0) and (stop_offset[current_nesting] ne 'FFFFFFFF'x) and $ (stop_offset[current_nesting] le offset + len)) do begin current_nesting = current_nesting -1 endwhile endif if (len ne 'FFFFFFFF'x) then offset = offset + len index = index + 1 if (index ge bufsize) then begin (*self.offsets) = [(*self.offsets),lonarr(bufgrow)] (*self.lens) = [(*self.lens),lonarr(bufgrow)] (*self.vrs) = [(*self.vrs),strarr(bufgrow)] if (self.index_tags) then begin (*self.group_numbers) = [(*self.group_numbers),bytarr(bufgrow)] (*self.element_numbers) = [(*self.element_numbers),bytarr(bufgrow)] endif if (self.index_sequences) then begin (*self.parent_sequences) = [(*self.parent_sequences),lonarr(bufgrow)] (*self.parent_items) = [(*self.parent_items),lonarr(bufgrow)] (*self.item_numbers) = [(*self.item_numbers),lonarr(bufgrow)] endif bufsize = bufsize + bufgrow endif endwhile self.size = index if (arg_present(access_time) or (n_elements(access_time) gt 0)) then access_time = systime(1) - start_time return, 1b end ;+ ;

Dump all parsed information to the console

;- pro GDLffDICOM__assoc::Dump, LUN=lun for index=0l,self.size-1l do begin ; Need to make it look like DumpElements str = string(index, (*self.offsets)[index], (*self.lens)[index], FORMAT="(I5,I10,I10)") if (self.index_tags) then $ str = str + string((*self.group_numbers)[index], (*self.element_numbers)[index],FORMAT="(' [',Z04,',',Z04,'] ')") if (self.explicit_vr) then $ str = str + ' ' + (*self.vrs)[index] if (self.index_sequences) then $ str = str + string((*self.parent_sequences)[index],(*self.parent_items)[index], FORMAT="(I10,I10)") if (n_elements(lun) gt 0) then printf, lun, str $ else print, str endfor end ;+ ;

Find a DICOM tag by group and element numbers

;@param group_number {in}{type=int}{required} An UINT specifying the group number of the ;tag ;@param element_number {in}{type=int}{required} An UINT specifying the element number of the ;tag ;@keyword count {out}{type=lonarr}{optional} The number of matching DICOM ;tags. ;@returns The indicies of the matching dicom tags in the file. ;- function GDLffDICOM__assoc::findtaginds, group_number, element_number, COUNT=count group_inds = where(group_number eq *self.group_numbers,count) if (count gt 0) then begin element_inds = where(element_number eq (*self.element_numbers)[group_inds],count) if (count gt 0) then return, group_inds[element_inds] endif count = 0l return, [-1l] end ;+ ;

Read a DICOM tag which has the given group and element number. The ;VR must be specified for an implicit VR file.

;@param group_number {in}{type=int}{optional} An UINT specifying the group number of the ;tag ;@param element_number {in}{type=int}{optional} An UINT specifying the element number of the ;tag ;@keyword vr {in}{optional} Read field using this VR. This must be ;specified for an implicit VR file. ;@param value_out {out}{required} The value read from the DICOM file ;@keyword offset {out}{optional} The byte offset where the value was ;found ;@keyword index {in}{optional} Read the element given at this position ;rather than searching for the group, element pair ;@returns 1 if the element was read. 0 if it wasn't found ;- function GDLffDICOM__assoc::readelement, group_number, element_number, value_out, OFFSET=offset, INDEX=index, VR=vr, SKIP_UNSUPPORTED=skip_unsupported if ((n_elements(index) eq 0)) then begin inds = self -> findtaginds(group_number, element_number,COUNT=count) if ((count gt 0)) then index = inds[0] endif if (n_elements(index) gt 0) then begin offset = (*self.offsets)[index] point_lun, self.lun, offset len = (*self.lens)[index] if (len eq 0) then return, 0b vr = (*self.vrs)[index] if (n_elements(vr) gt 0) then begin value_out = self -> generatevalue(vr, len,SKIP_UNSUPPORTED=skip_unsupported) readu, self.lun, value_out return, 1b endif else begin if (~keyword_set(skip_unsupported)) then $ message, "VR keyword must be specified for implicit files" return, 0b endelse endif return, 0b end ;+ ;

Generate an IDL variable for the given VR and byte length

;@private ;@param vr {required}{in} The Value Representation for the variable ;@param len {required}{in} The length of the value ;@returns The IDL variable ;- function GDLffDICOM__assoc::generatevalue, vr, len, SKIP_UNSUPPORTED=skip_unsupported vrs = ['AE','AS','AT','CS','DA','DL','DS','DT','FL','FD','IS','LO','LT','OB','OF','OW','PN','SH','SL','SQ','SS','ST','TM','UI','UL','UN','US','UT','xs'] types = [7 ,7 ,13 ,7 ,7 ,0 ,7 ,7 ,4 ,5 ,7 ,7 , 7 ,1 ,5 ,2 ,7 ,7 ,3 ,0 ,2 ,7 ,7 ,7 ,13 ,1 ,12 ,7, 12] ; xs could be SS or US depending on context vr_inds = where(vrs eq vr,count) if (count gt 0) then begin type = types[vr_inds[0]] case (type) of 1: return, bytarr(len) 2: return, intarr(len/2l) 3: return, lonarr(len/4l) 4: return, fltarr(len/2l) 5: return, dblarr(len/4l) 7: return, strjoin(replicate(' ', len),'') 12: return, uintarr(len/2l) 13: return, ulonarr(len/4l) else: message, "Unsupported VR type " + vr endcase endif else begin if (~keyword_set(skip_unsupported)) then message, 'Unsupported VR ' + vr return, 0b endelse end function GDLffDICOM__assoc::NewSOPInstanceUID, group_number, element_number if (n_elements(group_number) eq 0) then group_number = '0008'x if (n_elements(element_number) eq 0) then element_number = '0018'x return, self -> NewUID(group_number, element_number) end ;+ ;

Generate and write a new SOP Instance UID. This generates a UID ;such that it doesn't change the length of the file.

;@returns The SOP Instance UID String or an empty string if no UID ;could be generated. ;- function GDLffDICOM__assoc::NewUID, group_number, element_number if (n_elements(time_multiplier) eq 0) then time_multiplier = 1l $ else time_multiplier = time_multiplier+1l if (self -> readelement(group_number,element_number, SOPInstanceUID, OFFSET=offset, VR='UI')) then begin SOPInstanceUID = strtrim(SOPInstanceUID) ; Remove trailing blanks only SOPInstanceUID = GDLffDICOM__assoc_GenerateUID(strlen(SOPInstanceUID),/EMPTY_ON_ERROR,ERROR=error) if ((SOPInstanceUID ne '')) then begin point_lun, self.lun, offset if (~ self.read_only) then $ writeu, self.lun, SOPInstanceUID $ else return, '' endif else errm = dialog_message(["GDLffDICOM Error: Cannot set UID of " + (fstat(self.lun)).name,error]) return, SOPInstanceUID endif return, '' end ;+ ;

Write a new SOP Instance UID. This generates a UID ;must be the same length such that it doesn't change the length of the file.

;- function GDLffDICOM__assoc::WriteElement, group_number, element_number, newValue, VR=vr if (self -> readelement(group_number,element_number, value, OFFSET=offset, VR=vr)) then begin value = strtrim(value) ; Remove trailing blanks only if (strlen(value) ne strlen(newValue)) then return, 0b if ((value ne '')) then begin point_lun, self.lun, offset if (~ self.read_only) then $ writeu, self.lun, newValue $ else return, 0b endif else errm = dialog_message(["GDLffDICOM Error: Cannot set value of " + (fstat(self.lun)).name,error]) return, 1b endif return, 0b end ;+ ;

Write a new SOP Instance UID. This generates a UID ;must be the same length such that it doesn't change the length of the file.

;- function GDLffDICOM__assoc::WriteUID, group_number, element_number, NewInstanceUID if (self -> readelement(group_number,element_number, SOPInstanceUID, OFFSET=offset, VR='UI')) then begin SOPInstanceUID = strtrim(SOPInstanceUID) ; Remove trailing blanks only if (strlen(SOPInstanceUID) ne strlen(NewInstanceUID)) then return, 0b if ((NewInstanceUID ne '')) then begin point_lun, self.lun, offset if (~ self.read_only) then $ writeu, self.lun, NewInstanceUID endif else errm = dialog_message(["GDLffDICOM Error: Cannot set UID of " + (fstat(self.lun)).name,error]) return, 1b endif return, 0b end ;+ ;

Associate the contents of the pixeldata tag in the DICOM file with ; an image. This will automatically determine the location of the ; pixeldata tag and its dimensions.

; @keyword count {out}{optional} The number of images contained in the associated variable ; @keyword index {in}{optional} The index of the pixeldata tag ; @keyword image {in}{optional} Associate using the dimensions of this ; value ; @keyword true {out}{optional} If greater than 1 use this value as an argument for ; rendering the image using tv ;@keyword access_time {out}{optional} The number of seconds taken to ;assocate the value. ;@keyword raise {in}{optional} Raise an exception in the calling ;program if an error occurs (useful for debugging) ;@keyword no_catch {private} Do not catch any exceptions ;@returns The associated variable ;- function GDLffDICOM__assoc::assoc, INDEX=index, IMAGE=value, COUNT=count, ACCESS_TIME=access_time, $ NO_CATCH=no_catch, RAISE=raise, TRUE=true, OFFSET=offset if (~ keyword_set(no_catch)) then begin CATCH, Error_status IF Error_status NE 0 then begin Error_message = !ERR_STRING CATCH,/CANCEL if (keyword_set(raise)) then begin on_error, 2 Message, Error_message, LEVEL=-1 ; Generate message to caller endif else begin count = 0 return, [0] endelse endif endif if (arg_present(access_time) or (n_elements(access_time) gt 0)) then start_time = systime(1) ; Useful DICOM elements ;(0028,0010) US 2, 1 Rows ;(0028,0011) US 2, 1 Columns ;(0028,0100) US 2, 1 BitsAllocated ;(0028,0101) US 2, 1 BitsStored ;(0028,0102) US 2, 1 HighBit ;(0028,0103) US 2, 1 PixelRepresentation true = 0b if (n_elements(index) eq 0) then begin inds = self -> findtaginds('7fe0'x,'0010'x,COUNT=count) if (count gt 0) then index = inds[0] else message, "No pixeldata tag found" endif if (n_elements(value) eq 0) then begin if (self -> readelement('0028'x,'0002'x,samples,VR='US') and $ self -> readelement('0028'x,'0010'x,rows,VR='US') and $ self -> readelement('0028'x,'0011'x,columns,VR='US') and $ self -> readelement('0028'x,'0100'x,bitsallocated,VR='US') and $ self -> readelement('0028'x,'0101'x,bitsstored,VR='US') and $ self -> readelement('0028'x,'0103'x,pixelrepresentation,VR='US')) then begin ; if (bitsallocated ne bitsstored) then message, "Only understands same number of stored and allocated bits" + string(bitsallocated,bitsstored) case (bitsallocated) of 8: begin if (pixelrepresentation eq 1u) then message, "Bytes cannot be signed" if (samples gt 1u) then begin if (~ self -> readelement('0028'x,'0006'x,planar,VR='US')) then planar = 0u if (planar) then begin value = bytarr(columns,rows,samples) if (samples eq 3u) then true = 3b endif else begin value = bytarr(samples,columns,rows) if (samples eq 3u) then true = 1b endelse endif else $ value = bytarr(columns,rows) end 16: begin if (pixelrepresentation eq 1u) then value = intarr(columns,rows) $ else value = uintarr(columns,rows) end else: message, "Unknown image depth" endcase endif else message, "Image dimensions not found" endif s = size(value) case (s[s[0l]+1l]) of 1: nbytes = s[s[0l]+2l] ; byte 2: nbytes = s[s[0l]+2l]*2l ; integer 3: nbytes = s[s[0l]+2l]*4l ; long 4: nbytes = s[s[0l]+2l]*2l ; float 5: nbytes = s[s[0l]+2l]*4l ; double 12: nbytes = s[s[0l]+2l]*2l ; unsigned integer 13: nbytes = s[s[0l]+2l]*4l ; unsigned long 14: nbytes = s[s[0l]+2l]*8l ; 64-bit int 15: nbytes = s[s[0l]+2l]*8l ; 64-bit uint else: message, "Unsupported type" endcase if ((index ge 0) and (index lt self.size)) then begin count = long((*self.lens)[index] / nbytes) if (count * nbytes ne (*self.lens)[index]) then $ message, "The size of the value doesn't wholly fit inside the dicom field. " + string( nbytes, (*self.lens)[index], FORMAT="('value[',I0,'], dicom[',I0,']')") if (arg_present(access_time) or (n_elements(access_time) gt 0)) then access_time = systime(1) - start_time offset = (*self.offsets)[index] return, assoc(self.lun, value, offset) endif else count = 0 end ;+ ;

Write a new DICOM file tag by tag. The output file will ; contain values specified in the argument, otherwise the values are ; copied from the existing file. The argument should be a ; struct array containing the following fields

;
    ;
  • group_number (UINT) ;
  • element_number (UINT) ;
  • index (LONG) ;
  • vr (STRING) ;
  • len (LONG) ;
  • value (PTR) ;
; @param values {in}{optional} A struct array with new values to write ;- pro GDLffDICOM__assoc::write, filename, values if ((fstat(self.lun)).name eq filename) then message, "Cannot commit to a file from which we are reading" if (self.big_endian) then $ openw, write_lun, filename, /get_lun, /swap_if_little_endian $ ; This is a big endian file else $ openw, write_lun, filename, /get_lun, /swap_if_big_endian ; This is a little endian file writeu, write_lun, bytarr(128) writeu, write_lun, 'DICM' inside_metadata = 1b is_delimiter = 0b adj_lens = (*self.lens) ; Adjust sequence lengths to handle modified elements for i=0,n_elements(values)-1l do begin index = values[i].index ;help, values[i], /structure, adj_lens, index, adj_lens[index], values[i].len ;print, adj_lens[index] ne values[i].len if (adj_lens[index] ne values[i].len) then begin diff = values[i].len - adj_lens[index] ; help, diff if (self.index_sequences) then begin parent_index = (*self.parent_sequences)[index] parent_item = (*self.parent_items)[index] while (parent_index ge 0) do begin if (adj_lens[parent_index] ne ulong('FFFFFFFF'x)) then $ adj_lens[parent_index] = adj_lens[parent_index] + diff if (parent_item ge 0) then begin if (adj_lens[parent_item] ne ulong('FFFFFFFF'x)) then $ adj_lens[parent_item] = adj_lens[parent_item] + diff endif parent_index = (*self.parent_sequences)[parent_index] endwhile endif endif endfor ; Write file tag by tag for index=0l,self.size-1l do begin if (n_elements(values) gt 0) then $ v_inds = where(index eq values.index,v_count) $ else v_count = 0 if (v_count gt 0) then begin i = v_inds[0] tag = uint([values[i].group_number,values[i].element_number]) len = values[i].len vr = values[i].vr endif else begin tag = uint([(*self.group_numbers)[index],(*self.element_numbers)[index]]) len = adj_lens[index] vr = (*self.vrs)[index] endelse ;inds = where((*self.parent_items) eq index,count) ;if (count gt 0) then begin ; total_len = ulong(total(adj_lens[inds])) ; if (total_len ne len) then print, "Length mismatch ", len, total_len,count ; ;else print, "Length match ", total_len, len ;endif is_delimiter = (tag[0] eq 'FFFE'x) and ((tag[1] eq 'E000'x) or (tag[1] eq 'E00D'x) or (tag[1] eq 'E0DD'x)) if (~self.explicit_vr and inside_metadata) then begin case (tag[1]) of '0000'x: vr = 'UL' '0001'x: vr = 'OB' '0002'x: vr = 'UI' '0003'x: vr = 'UI' '0010'x: vr = 'UI' '0012'x: vr = 'UI' '0013'x: vr = 'SH' '0016'x: vr = 'AE' '0100'x: vr = 'UI' '0102'x: vr = 'OB' else: vr = 'UN' endcase endif if (inside_metadata) then begin ; metadata is always little endian ; a big endian file will need to be swapped again ; No more 0002 group tags indicates the end of the meta-data set if (tag[0] ne '0002'x) then $ inside_metadata = 0b endif if (inside_metadata) then begin if (self.big_endian) then $ swap_endian_inplace, tag endif writeu, write_lun, tag[0:1] if (~is_delimiter and (self.explicit_vr or inside_metadata)) then begin writeu, write_lun, strmid(vr,0,2) vr_inds = where(vr eq ['OB', 'OW', 'OF', 'SQ', 'UT', 'UN'],vr_count) if (vr_count gt 0) then begin writeu, write_lun, uint('0000'x) len = ulong(len) endif else begin len = uint(len) endelse endif else begin len = ulong(len) endelse write_len = len[0] if (inside_metadata) then begin ; metadata is always little endian ; a big endian file will need to be swapped again if (self.big_endian) then $ swap_endian_inplace, write_len endif ;if (write_len eq ulong('FFFFFFFF'x)) then print, "undefined length" $ ;else begin ;endelse writeu, write_lun, write_len if ((vr ne 'SQ') and ~is_delimiter and self.index_sequences) then begin if (v_count gt 0) then begin writeu, write_lun, *values[i].value endif else begin offset = (*self.offsets)[index] if (long64(offset) + len le (fstat(self.lun)).size) then begin point_lun, self.lun, offset gdlffdicom_copy_lun, self.lun, write_lun, len endif else begin print, "Warning, truncating bytes" point_lun, self.lun, offset gdlffdicom_copy_lun, self.lun, write_lun, (fstat(self.lun)).size - offset endelse endelse endif endfor free_lun, write_lun end ;+ ;

Close the file and free the lun

;- pro GDLffDICOM__assoc::close if (self.lun gt 0) then begin free_lun, self.lun self.lun = 0 endif self.size = 0l end ;+ ;

Cleanup pointers

;- pro GDLffDICOM__assoc::cleanup if (self.lun gt 0) then free_lun, self.lun ptr_free, self.lens ptr_free, self.offsets ptr_free, self.vrs ptr_free, self.group_numbers ptr_free, self.element_numbers ptr_free, self.parent_sequences ptr_free, self.parent_items ptr_free, self.item_numbers end ;+ ;

Initialise the object

;- function GDLffDICOM__assoc::init GDLffDICOMDictionary__define, dictionary, /INIT self.dictionary = dictionary self.lens = ptr_new(/ALLOCATE_HEAP) self.offsets = ptr_new(/ALLOCATE_HEAP) self.vrs = ptr_new(/ALLOCATE_HEAP) self.group_numbers = ptr_new(/ALLOCATE_HEAP) self.element_numbers = ptr_new(/ALLOCATE_HEAP) self.parent_sequences = ptr_new(/ALLOCATE_HEAP) self.parent_items = ptr_new(/ALLOCATE_HEAP) self.item_numbers = ptr_new(/ALLOCATE_HEAP) return, 1 end ;+ ;

The DICOM update object

;

This object allows you to parse a DICOM file and associate the ;pixel data with an IDL variable. This means that you can make changes ;to the data in a DICOM file easily and efficently without touching ;any other parts of the file. It is recommended that you use ; dcmodify from the DICOM toolkit (www.dcmtk.org) to change any ; non-pixel DICOM tags. A wrapper class for dcmtk is provided in this release. ;

;- pro GDLffDICOM__assoc__define, struct GDLffDICOMDictionary__define, struct struct = {GDLffDICOM__assoc, $ dictionary: struct, $ lun: 0l, $ lens: ptr_new(), $ offsets: ptr_new(), $ vrs: ptr_new(), $ group_numbers: ptr_new(), $ element_numbers: ptr_new(), $ parent_sequences: ptr_new(), $ parent_items: ptr_new(), $ item_numbers: ptr_new(), $ index_sequences: 0B, $ size: 0l, $ index_tags: 0B, $ explicit_vr: 0B, $ big_endian: 0B, $ read_only: 0b $ } end gdl-0.9.9/src/pro/dicom/gdlffdicom__assoc__test.pro000077500000000000000000000175471340051421000223350ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ; The test data for this routine can be obtained from ; http://www.creatis.insa-lyon.fr/~jpr/PUBLIC/gdcm/gdcmData.tar.gz pro gdlffdicom__assoc__test0 files = file_search('*dcm',COUNT=nfiles) nprocessed = 0 nidlffdicom = 0 du = obj_new('gdlffdicom__assoc') for i=0l,nfiles-1l do begin if (du -> open( files[i], ACCESS_TIME=at)) then begin print, "Open " + files[i] + " access time", at images = du -> assoc(COUNT=count, ACCESS_TIME=at, TRUE=true) print, "Associate Acess time", at if (count gt 0) then begin nprocessed = nprocessed + 1 window, nprocessed if (true) then begin for j=0l,count-1l do tv, images[j], TRUE=true endif else begin for j=0l,count-1l do tvscl, images[j], j mod 4 endelse endif else print, "Could not read " + files[i] result = du -> NewSOPInstanceUID() print, result du -> close ; Warning - Causes segmentation fault for some invalid files endif endfor obj_destroy, du print, "Number of files successfully processed by gdlffdicom__assoc: ", nprocessed, ". Total number of files ", nfiles, FORMAT="(A,I0,A,I0)" print, "Number of files successfully opened by IDLffDICOM: ", nidlffdicom, ". Total number of files ", nfiles, FORMAT="(A,I0,A,I0)" end pro gdlffdicom__assoc__test1 files = file_search('*dcm',COUNT=nfiles) for i=0l,nfiles-1l do begin du = obj_new('gdlffdicom__assoc') print, "Opening " + files[i] if (du -> open( files[i],ACCESS_TIME=at,/INDEX_SEQUENCES)) then begin du -> dump du -> close endif endfor obj_destroy, du end pro gdlffdicom__assoc__test2 file = 'GE_LOGIQBook-8-RGB-HugePreview.dcm' du = obj_new('gdlffdicom__assoc') if (du -> open( file,ACCESS_TIME=at,/INDEX_SEQUENCES, /INDEX_TAGS, /NO_CATCH)) then begin print, "Open " + file + " access time", at du -> dump du -> close endif obj_destroy, du end pro gdlffdicom__assoc__test3 file = 'PHILIPS_Intera-16-MONO2-Uncompress.dcm' ; The files swithes endian mid-sequence du = obj_new('gdlffdicom__assoc') if (du -> open( file,ACCESS_TIME=at, /INDEX_TAGS, /NO_CATCH)) then begin ;/INDEX_SEQUENCES, /INDEX_TAGS, /NO_CATCH)) then begin print, "Open " + file + " access time", at ;du -> dump du -> close endif obj_destroy, du end pro gdlffdicom__assoc__test4 file = 'GE_LOGIQBook-8-RGB-HugePreview.dcm' du = obj_new('gdlffdicom__assoc') if (du -> open( file,ACCESS_TIME=at,/INDEX_SEQUENCES, /INDEX_TAGS, /NO_CATCH)) then begin print, "Open " + file + " access time", at ;help, du du -> write, file + '_copy' du -> close endif obj_destroy, du end pro gdlffdicom__assoc__test5 files = file_search('*dcm',COUNT=nfiles) du = obj_new('gdlffdicom__assoc') for i=0l,nfiles-1l do begin print, "Opening " + files[i] if (du -> open( files[i],ACCESS_TIME=at,/INDEX_SEQUENCES)) then begin du -> write, files[i] + '_copy' du -> close spawn, strjoin(['diff',files[i], files[i] + '_copy'],' '), EXIT_STATUS=exit_status if (exit_status NE 0) then print, "Could not write to file " + files[i] endif endfor obj_destroy, du ;help, /heap end pro gdlffdicom__assoc__test, inds, ALL=all if (keyword_set(all)) then inds = indgen(5) for i=0,n_elements(inds)-1 do begin call_procedure, STRING('gdlffdicom__assoc__test',inds[i],FORMAT="(A,I0)") endfor end pro GDLffDICOM__assoc_GenerateUID_test1 for i=124,31,-1 do begin uid = GDLffDICOM__assoc_GenerateUID(i) print, uid if (strlen(uid) ne i) then message endfor for i=31,124 do begin uid = GDLffDICOM__assoc_GenerateUID(i) print, uid if (strlen(uid) ne i) then message endfor for i=124,31,-1 do begin uid = GDLffDICOM__assoc_GenerateUID(i) print, uid if (strlen(uid) ne i) then message endfor end pro GDLffDICOM__assoc_GenerateUID_test2 s = 31 ni = 10000l ; 0000l nj = 1l uids = strarr(ni) for j=0l,nj-1 do begin for i=0l,ni-1 do uids[i] = GDLffDICOM__assoc_GenerateUID(s) inds = sort(uids) if (n_elements(uniq(uids[inds],inds)) ne ni) then begin print, uids[inds] message, 'UIDs not unique' endif endfor end pro GDLffDICOM__assoc_GenerateUID_test3 s = 64 ni = 100000l nj = 1l uids = strarr(ni) for j=0l,nj-1 do begin for i=0l,ni-1 do uids[i] = GDLffDICOM__assoc_GenerateUID(s) inds = sort(uids) if (n_elements(uniq(uids[inds],inds)) ne ni) then message endfor end pro GDLffDICOM__assoc_test6 file = '\\a3printer2\farmyard\wmidl\nmtkdualrenal0\test\2008.0.14125138.dcm' du = obj_new('gdlffdicom__assoc') if (du -> open( file,ACCESS_TIME=at,/INDEX_SEQUENCES, /INDEX_TAGS, /NO_CATCH)) then begin print, "Open " + file + " access time", at du -> dump du -> close endif obj_destroy, du end pro GDLffDICOM__assoc_test7 file = 'E:\public\esoft\gastric_emptying\2006.0.5699771.dcm' du = obj_new('gdlffdicom__assoc') if (du -> open( file,ACCESS_TIME=at,/INDEX_SEQUENCES, /INDEX_TAGS, /NO_CATCH)) then begin print, "Open " + file + " access time", at du -> dump du -> close endif obj_destroy, du end pro GDLffDICOM__assoc_test8 file = 'E:\public\esoft\gastric_emptying\2006.0.5699771.dcm' du = obj_new('gdlffdicom') if (du -> read( file,ACCESS_TIME=at,/INDEX_SEQUENCES, /INDEX_TAGS, /NO_CATCH)) then begin print, "Open " + file + " access time", at du -> dumpElements du -> close endif obj_destroy, du end pro gdlffdicom__assoc__test_spec, spec files = file_search(spec,COUNT=nfiles) nprocessed = 0 nidlffdicom = 0 du = obj_new('gdlffdicom__assoc') for i=0l,nfiles-1l do begin if (du -> open( files[i], ACCESS_TIME=at)) then begin print, "Open " + files[i] + " access time", at images = du -> assoc(COUNT=count, ACCESS_TIME=at, TRUE=true) print, "Associate Acess time", at if (count gt 0) then begin nprocessed = nprocessed + 1 window, nprocessed if (true) then begin for j=0l,count-1l do tv, images[j], TRUE=true endif else begin for j=0l,count-1l do tvscl, images[j], j mod 4 endelse endif else print, "Could not read " + files[i] result = du -> NewSOPInstanceUID() print, result du -> close ; Warning - Causes segmentation fault for some invalid files endif endfor obj_destroy, du print, "Number of files successfully processed by gdlffdicom__assoc: ", nprocessed, ". Total number of files ", nfiles, FORMAT="(A,I0,A,I0)" print, "Number of files successfully opened by IDLffDICOM: ", nidlffdicom, ". Total number of files ", nfiles, FORMAT="(A,I0,A,I0)" end gdl-0.9.9/src/pro/dicom/gdlffdicom__assoc_generateuid.pro000077500000000000000000000053601340051421000235010ustar00rootroot00000000000000 function GDLffDICOM__assoc_GenerateUID, length, EMPTY_ON_ERROR=eoe, ERROR=error common GDLffDICOM__assoc, instance_id, last_time, root, seed root = '1.2.826.4567.' nr = strlen(root) nl = 18ul nt = 10ul ni = 4ul ns = nl + nt + ni if (n_elements(length) gt 0) then begin if (length - nr gt 99) then begin error = "Cannot generate a UID that long ("+string(length,FORMAT="(I0)")+"), maximum length is " + string(nr+99,FORMAT="(I0)") if (keyword_set(eoe)) then return, '' $ else message, error endif if (length - nr lt 6) then begin error = "Cannot generate a UID that short ("+string(length,FORMAT="(I0)")+"), minimum length is " + string(nr+6,FORMAT="(I0)") if (keyword_set(eoe)) then return, '' $ else message, error endif ratio = float(length - nr)/ns nl = ceil(nl*ratio) nt = ceil(nt*ratio) ni= ceil(ni*ratio) endif nts = string(nt,FORMAT="(I0)") nis = string(ni,FORMAT="(I0)") byte = 0b lmhostid = '' result = lmgr(LMHOSTID=lmhostid_hex) nlh = ceil(2.0*nl/3.0) for i=strlen(lmhostid_hex)-nlh,strlen(lmhostid_hex)-2,2 do begin reads, strmid(lmhostid_hex,i,2),byte, FORMAT="(Z2)" lmhostid = lmhostid + string(byte,FORMAT="(I3.3)") endfor lmhostid = strmid(lmhostid,0,nl) current_time = ulong(systime(1)) if (n_elements(instance_id) eq 0) then begin instance_id = ulong(randomu(seed)*10l^(nis-1)) ; Start somewhere in the first tenth of the instances endif if (n_elements(last_time) eq 0) then last_time = 0l ;print, current_time eq last_time, instance_id, ni if ((instance_id gt 10ul^ni) and (current_time eq last_time)) then begin ; This whole waiting business is going ; to ensure that the programmer/tester ; increased the length of the field ; before there is any possibility of ; non-unique IDs message, "GDLffDICOM needs to wait 2 seconds to generate a UID. Please try setting the length of the UID field to larger.",/CONTINUE wait, 2 instance_id = ulong(randomu(seed)*10ul^(nis-1)) ; Start somewhere in the first tenth of the instances current_time = current_time + 1 endif time = string(current_time mod 10ul^nt,FORMAT="(I"+nts+"."+nts+")") ;instance_id = instance_id mod 10ul^ni ;help, instance_id instance = string(instance_id mod 10ul^ni,FORMAT="(I"+nis+"."+nis+")") ;print, instance, nis, instance_id instance_id = instance_id + 1 uid = root + lmhostid + time + instance offset = strlen(uid) - length if (offset gt 0) then lmhostid = strmid(lmhostid,offset,nl-offset) uid = root + lmhostid + time + instance last_time = current_time return, uid end gdl-0.9.9/src/pro/dicom/gdlffdicom__define.pro000066400000000000000000000475371340051421000212600ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ;+ ;

Convert a GDLffDICOM References into GDLffDICOM__assoc indexes

;@private ;- function GDLffDICOM::Indexes, references if (self.size lt self.ntags) then begin inds = where(references gt self.size,count) if (count gt 0) then references[inds] = self.pixel_index endif return, references end ;+ ;

Find the indexes of DICOM tags which match the ith Dictionary entry

;@private ;@param inds {in}{required} A subset of indexes to search ;@param find_inds {out}{required} The indicies to the indexes which ;match ;@param i {in}{required} The dictionary entry to search ;- pro GDLffDICOM::FindDefinedElement, inds, find_inds, i group_inds = where((self.dictionary[i]).group_number eq (*self.group_numbers)[inds],group_count) if (group_count gt 0) then begin element_inds = where((self.dictionary[i]).element_number eq (*self.element_numbers)[inds[group_inds]],element_count) if (element_count gt 0) then begin if (n_elements(find_inds) gt 0) then $ find_inds = [find_inds,group_inds[element_inds]] $ else $ find_inds = [group_inds[element_inds]] endif endif end ;+ ;

Find the Dictionary entries for and matching DICOM tags

;@private ;- function GDLffDICOM::GetDictionary, group_number, element_number, REFERENCE=references if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif if (references[0] eq -1) then return, [-1] dictionaries = replicate({GDLffDICOMDictionary},n_elements(references)) for i=0l,n_elements(references)-1l do begin group_number = (*self.group_numbers)[self -> indexes(references[i])] element_number = (*self.element_numbers)[self -> indexes(references[i])] group_inds = where(self.dictionary.group_number eq group_number,group_count) if (group_count gt 0) then begin element_inds = where((self.dictionary.element_number)[group_inds] eq element_number,element_count) if (element_count gt 0) then begin dictionaries[i] = (self.dictionary)[group_inds[element_inds[0]]] endif endif endfor return, dictionaries end ;+ ;

Open the file for updating and initialise dicom tag buffer

;@private ;- function GDLffDICOM::Open2, filename, _REF_EXTRA=ex self -> reset result = self -> GDLffDICOM__assoc::Open(filename,_EXTRA=ex, /INDEX_SEQUENCES, /INDEX_TAGS) if (self.size gt 0) then begin *self.pixel_assoc = self -> assoc(INDEX=index, COUNT=count) if (count gt 0) then begin self.pixel_index = index self.frame_count = count self.ntags = self.size + count -1l endif else self.ntags = self.size (*self.dicom_tags) = replicate({GDLffDICOMTag},self.ntags) endif ; Set up the extra pixel indicies here return, result end ;+ ;

Destroy the object

;- pro GDLffDICOM::Cleanup if (n_elements(*self.dicom_tags) gt 0) then $ for i=0l,self.ntags-1l do ptr_free, (*self.dicom_tags)[i].value ptr_free, self.dicom_tags ptr_free, self.pixel_assoc self -> GDLffDICOM__assoc::Cleanup end ;+ ;

Dump a description of all elements

;- pro GDLffDICOM::DumpElements, filename fmt = "(I4,' : (',Z04,',',Z04,') : ',A2,' : ',A,' : ',I0,' : ',A)" if (n_elements(filename) gt 0) then openw, lun, filename, /GET_LUN values = self -> getValue(/NO_COPY) for i=0l,self.ntags-1l do begin dicom_tag = (*self.dicom_tags)[i] if ((ptr_valid(dicom_tag.value) && (n_elements(*dicom_tag.value) gt 0))) then value = *dicom_tag.value $ else value = "" case (size(value,/type)) of else: begin if (n_elements(value) gt 12) then $ value = strjoin(strtrim((string(value[0:11])),2),' ') + ' ...' $ else $ value = strjoin(strtrim((string(value)),2),' ') end endcase if (n_elements(lun) gt 0) then begin printf, lun, i, dicom_tag.group_number, dicom_tag.element_number, $ dicom_tag.vr, dicom_tag.description, dicom_tag.len, value, $ FORMAT=fmt endif else begin print, i, dicom_tag.group_number, dicom_tag.element_number, $ dicom_tag.vr, dicom_tag.description, dicom_tag.len, value, $ FORMAT=fmt endelse endfor if (n_elements(lun) gt 0) then free_lun, lun end ;+ ;

Get references to all child elements of this reference.

;- function GDLffDICOM::GetChildren, reference if (self.index_sequences and (n_elements(reference) gt 0)) then begin references = where((*self.parent_sequences) eq self -> indexes(reference[0]),count) if (count gt 0) then return, references $ else return, -1 endif else $ return, -1 end ;+ ;

Return an array of string descriptions, as defined in the DICOM ;dictionary of DCMTK by OFFIS software

;- function GDLffDICOM::GetDescription, group_number, element_number, REFERENCE=references dictionaries = self -> GetDictionary(group_number, element_number, REFERENCE=references) if (size(dictionaries,/type) eq 8) then return, [dictionaries.name] return, [-1] end ;+ ;

Return an array of DICOM element numbers

;- function GDLffDICOM::GetElement, group_number, element_number, REFERENCE=references if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif else references = [references] if (references[0] eq -1) then return, [-1] return, long((*self.element_numbers)[self -> indexes(references)]) end ;+ ;

Return an array of DICOM group numbers

;- function GDLffDICOM::GetGroup, group_number, element_number, REFERENCE=references if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif else references = [references] if (references[0] eq -1) then return, [-1] return, long((*self.group_numbers)[self -> indexes(references)]) end ;+ ;

Return an array of the length of elements in bytes

;- function GDLffDICOM::GetLength, group_number, element_number, REFERENCE=references if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif else references = [references] if (references[0] eq -1) then return, [-1] return, (*self.lens)[self -> indexes(references)] end ;+ ;

Get references to all parent element of this reference.

;- function GDLffDICOM::GetParent, references if (self.index_sequences) then $ return, [(*self.parent_sequences)[self -> indexes(references)]] $ else $ return, [-1] end ;+ ;

Return the preamble of the DICOM file

;- function GDLffDICOM::GetPreamble preamble = bytarr(128) if (self.lun gt 0) then begin point_lun, self.lun, 0 readu, self.lun, preamble return, preamble endif end ;+ ;

Return an array of references which match the arguments

;- function GDLffDICOM::GetReference, group_number, element_number, DESCRIPTION=description, VR=vr inds = indgen(self.ntags) if (n_elements(group_number) gt 0) then begin group_inds = where(group_number eq (*self.group_numbers)[inds],group_count) if (group_count gt 0) then inds = inds[group_inds] else return, -1 endif if (n_elements(element_number) gt 0) then begin element_inds = where(element_number eq (*self.element_numbers)[inds],element_count) if (element_count gt 0) then inds = inds[element_inds] else return, -1 endif if ((n_elements(description) gt 0)) then begin for i=0,n_elements(self.dictionary)-1l do begin if (strpos(strlowcase((self.dictionary[i]).name),strlowcase(description)) ge 0) then begin self -> FindDefinedElement, inds, desc_inds, i endif endfor if (n_elements(desc_inds) gt 0) then inds = inds[desc_inds] else return, -1 endif if ((n_elements(vr) gt 0)) then begin ; if (self.explicit_vr) then begin vr_inds = where(vr eq (*self.vrs)[inds],vr_count) if (vr_count gt 0) then inds = inds[vr_inds] else return, -1 ; endif else begin ; dict_inds = where((self.dictionary.vr) eq vr,dict_count) ; for j=0l,n_elements(dict_inds)-1l do $ ; self -> FindDefinedElement, inds, vr_inds, dict_inds[j] ; if (n_elements(vr_inds) gt 0) then inds = inds[vr_inds] else return, -1 ; endelse endif pixel_inds = where(inds eq self.pixel_index, pixel_count) if ((pixel_count gt 0) and (self.ntags gt self.size)) then begin inds = [inds,self.size+indgen(self.ntags-self.size)] endif return, inds end ;+ ;

Return an array of pointers to DICOM tag values

;@keyword pixeldata Use this keyword to return all the pixeldat tags ;- function GDLffDICOM::GetValue, group_number, element_number, REFERENCE=references, NO_COPY=no_copy if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif else references = [references] if (references[0] eq -1) then return, [-1] ;help, references dictionaries = self -> GetDictionary(REFERENCE=references) ;help, references, *self.dicom_tags if (self.explicit_vr) then vrs = (*self.vrs)[references] $ else vrs = dictionaries.vr for i=0,n_elements(references)-1l do begin if (~ptr_valid((*self.dicom_tags)[references[i]].value)) then begin (*self.dicom_tags)[references[i]].description = dictionaries[i].name (*self.dicom_tags)[references[i]].vr = vrs[i] (*self.dicom_tags)[references[i]].group_number = (*self.group_numbers)[references[i]] (*self.dicom_tags)[references[i]].element_number = (*self.element_numbers)[references[i]] (*self.dicom_tags)[references[i]].index = references[i] (*self.dicom_tags)[references[i]].commit = 0b if ((references[i] eq self.pixel_index)) then begin ; and (self.ntags gt self.size) (*self.dicom_tags)[references[i]].len = (*self.lens)[references[i]]/self.frame_count (*self.dicom_tags)[references[i]].value = ptr_new((*self.pixel_assoc)[0]) for j=self.size,self.ntags-1l do begin (*self.dicom_tags)[j] = (*self.dicom_tags)[references[i]] (*self.dicom_tags)[j].value = ptr_new((*self.pixel_assoc)[j-self.size+1l]) endfor endif else begin inds = where(vrs[i] eq ['','SQ','DL'],unsupported_count) if (unsupported_count eq 0) then begin if (self -> readelement(group_number, element_number, value_out, OFFSET=offset, INDEX=references[i], VR=vrs[i], /SKIP_UNSUPPORTED)) then begin (*self.dicom_tags)[references[i]].len = (*self.lens)[references[i]] (*self.dicom_tags)[references[i]].value = ptr_new(value_out) endif else begin (*self.dicom_tags)[references[i]].len = 0 (*self.dicom_tags)[references[i]].value = ptr_new(/ALLOCATE_HEAP) endelse endif else begin (*self.dicom_tags)[references[i]].len = (*self.lens)[references[i]] (*self.dicom_tags)[references[i]].value = ptr_new(/ALLOCATE_HEAP) endelse endelse endif ; help, (*self.dicom_tags)[references[i]].value ; help, *(*self.dicom_tags)[references[i]].value endfor if (keyword_set(no_copy)) then begin return, [((*self.dicom_tags)[references]).value] endif else begin ptrcopy = ptrarr(n_elements(references),/allocate_heap) for i=0l,n_elements(references)-1l do begin ptr = ((*self.dicom_tags)[references[i]]).value if (n_elements(*ptr) gt 0) then *ptrcopy[i] = *ptr endfor return, ptrcopy endelse end ;+ ;

Return an array of the VR or DICOM tags

;- function GDLffDICOM::GetVR, group_number, element_number, REFERENCE=references if (self.explicit_vr) then begin if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif else references = [references] if (references[0] eq -1) then return, [-1] return, (*self.vrs)[self -> indexes(references)] endif else begin dictionaries = self -> GetDictionary(group_number, element_number,REFERENCE=references) if (size(dictionaries,/type) eq 8) then return, (dictionaries.vr) return, [-1] endelse end ;+ ;

Initialise the object

;- function GDLffDICOM::Init, filename, VERBOSE=verbose if (~ self -> GDLffDICOM__assoc::Init()) then return, 0 self.dicom_tags = ptr_new(/ALLOCATE_HEAP) self.pixel_assoc = ptr_new(/ALLOCATE_HEAP) if (n_elements(filename)) then return, self -> Read(filename) return, 1 end ;+ ;

Open a file for reading and writing

;- function GDLffDICOM::Read, filename, ENDIAN=endian, _REF_EXTRA=ex if (n_elements(endian) gt 0) then begin case (endian) of 1: return, self -> Open2(filename, /IMPLICIT_VR, /LITTLE_ENDIAN, _EXTRA=ex) 2: return, self -> Open2(filename, /EXPLICIT_VR, /LITTLE_ENDIAN, _EXTRA=ex) 3: return, self -> Open2(filename, /IMPLICIT_VR, /BIG_ENDIAN, _EXTRA=ex) 4: return, self -> Open2(filename, /EXPLICIT_VR, /BIG_ENDIAN, _EXTRA=ex) endcase endif else return, self -> Open2(filename, _EXTRA=ex) end ;+ ;

Close the file and reset all buffers

;- pro GDLffDICOM::Reset if (n_elements(*self.dicom_tags) gt 0) then $ for i=0l,self.ntags-1l do ptr_free, (*self.dicom_tags)[i].value self -> close end ;+ ;

Get the byte offset of DICOM tags in the file

;- function GDLffDICOM::GetOffset, group_number, element_number, REFERENCE=references if (n_elements(references) eq 0) then begin references = self -> GetReference(group_number, element_number) endif else references = [references] if (references[0] eq -1) then return, [-1] return, (*self.offsets)[self -> indexes(references)] end ;+ ;

Set the value the first matching DICOM element if it exists, but do not write it until the commit ;method is called

;@returns The reference for the element written ;- function GDLffDICOM::SetElement, group_number, element_number, value, REFERENCE=reference if (n_elements(value) eq 0) then message, "Setting element to a null value is not supported" if (n_elements(reference) eq 1) then begin self -> SetValue, reference, value return, reference endif else begin references = self -> GetReference(group_number, element_number) if (references[0] gt 0) then $ self -> SetValue, references[0], value return, references[0] endelse end ;+ ;

Copy a values of a group from the specified dicom object into this ;object. The tag must exist in this object for it to be copied. ; All elements in the group are copied unless a list of element ;numbers is explicitly provided. ;

;- pro GDLffDICOM::CopyGroup, dicom_obj, group_number, element_numbers if (n_elements(element_numbers) gt 0) then begin src_references = lonarr(n_elements(element_numbers)) dst_references = lonarr(n_elements(element_numbers)) for i=0l,n_elements(element_numbers)-1l do begin src_references[i] = (dicom_obj -> GetReference(group_number, element_numbers[i]))[0] dst_references[i] = (self -> GetReference(group_number, element_numbers[i]))[0] endfor endif else begin dst_references = self -> GetReference(group_number) element_numbers = self -> GetElement(REFERENCE=dst_references) src_references = lonarr(n_elements(element_numbers)) for i=0l,n_elements(element_numbers)-1l do begin src_references[i] = (dicom_obj -> GetReference(group_number, element_numbers[i]))[0] endfor endelse for i=0l,n_elements(dst_references)-1l do begin ; print, "Copying element ", src_references[i], " to ", dst_references[i] if ((dst_references[i] ge 0) and (src_references[i] ge 0)) then begin ptr = (dicom_obj -> GetValue(REFERENCE=src_references[i]))[0] if (n_elements(*ptr) gt 0) then self -> SetValue, dst_references[i], ptr,/USE_PTR endif endfor end ;+ ;

Set the value of a DICOM tag, but do not write it until the commit ;method is called

;- pro GDLffDICOM::SetValue, reference, value, USE_PTR=use_ptr if (n_elements(reference) ne 1) then message, "Must specify one and only one reference" if ((reference gt 0) and (reference lt self.size) and (reference ne self.pixel_index)) then begin if (~ptr_valid((*self.dicom_tags)[reference].value)) then (*self.dicom_tags)[reference].value = ptr_new(/ALLOCATE_HEAP) vr = (self -> GetVR(REFERENCE=reference))[0] group_number = (self -> GetGroup(REFERENCE=reference))[0] element_number = (self -> GetElement(REFERENCE=reference))[0] vrs = ['AE','AS','AT','CS','DA','DL','DS','DT','FL','FD','IS','LO','LT','OB','OF','OW','PN','SH','SL','SQ','SS','ST','TM','UI','UL','UN','US','UT'] types = [7 ,7 ,13 ,7 ,7 ,0 ,7 ,7 ,4 ,5 ,7 ,7 , 7 ,1 ,5 ,2 ,7 ,7 ,3 ,0 ,2 ,7 ,7 ,7 ,13 ,1 ,12 ,7] vr_inds = where(vrs eq vr,count) if (count gt 0) then begin type = types[vr_inds[0]] ; Temporarily dereference the pointer without copying the data if (keyword_set(use_ptr)) then vvalue = temporary(*value) $ else vvalue = temporary(value) if (type ne size(vvalue,/type)) then message, "IDL type does not match VR" case (type) of 1: len = n_elements(vvalue) 2: len = n_elements(vvalue) * 2l 3: len = n_elements(vvalue) * 4l 4: len = n_elements(vvalue) * 2l 5: len = n_elements(vvalue) * 4l 7: begin len = strlen(vvalue) if (len mod 2 eq 1) then begin vvalue = vvalue + ' ' len = len + 1l endif end 12: len = n_elements(vvalue) * 2l 13: len = n_elements(vvalue) * 4l else: message, "Unsupported VR type" endcase if (keyword_set(use_ptr)) then *value = temporary(vvalue) $ else value = temporary(vvalue) endif else message, 'Unsupported VR' (*self.dicom_tags)[reference].group_number = group_number (*self.dicom_tags)[reference].element_number = element_number (*self.dicom_tags)[reference].vr = vr (*self.dicom_tags)[reference].len = len if (keyword_set(use_ptr)) then (*self.dicom_tags)[reference].value = value $ else *(*self.dicom_tags)[reference].value = value (*self.dicom_tags)[reference].commit = 1b (*self.dicom_tags)[reference].index = reference endif else message, 'Cannot set value' end ;+ ;

Write all DICOM tags to a new file

;- function GDLffDICOM::Commit, filename inds = where(((*self.dicom_tags)[0:self.size-1l]).commit,count) if (count gt 0) then values = (*self.dicom_tags)[inds] self -> write, filename, values return, 1 end ;+ ;

A DICOM reader and writer

;- pro GDLffDICOM__define, struct struct = {GDLffDICOM, inherits GDLffDICOM__assoc, $ dicom_tags: ptr_new(), $ pixel_index: 0l, $ pixel_assoc: ptr_new(), $ frame_count: 0l, $ ntags: 0l $ } end gdl-0.9.9/src/pro/dicom/gdlffdicom__dictionary.pro000066400000000000000000014132371340051421000221660ustar00rootroot00000000000000pro gdlffdicom__dictionary, struct struct[0].group_number='0000'x & struct[0].element_number='0000'x & struct[0].vr='UL' & struct[0].vm='1' & struct[0].version='dicom98' & struct[0].name='CommandGroupLength' struct[1].group_number='0000'x & struct[1].element_number='0002'x & struct[1].vr='UI' & struct[1].vm='1' & struct[1].version='dicom98' & struct[1].name='AffectedSOPClassUID' struct[2].group_number='0000'x & struct[2].element_number='0003'x & struct[2].vr='UI' & struct[2].vm='1' & struct[2].version='dicom98' & struct[2].name='RequestedSOPClassUID' struct[3].group_number='0000'x & struct[3].element_number='0100'x & struct[3].vr='US' & struct[3].vm='1' & struct[3].version='dicom98' & struct[3].name='CommandField' struct[4].group_number='0000'x & struct[4].element_number='0110'x & struct[4].vr='US' & struct[4].vm='1' & struct[4].version='dicom98' & struct[4].name='MessageID' struct[5].group_number='0000'x & struct[5].element_number='0120'x & struct[5].vr='US' & struct[5].vm='1' & struct[5].version='dicom98' & struct[5].name='MessageIDBeingRespondedTo' struct[6].group_number='0000'x & struct[6].element_number='0600'x & struct[6].vr='AE' & struct[6].vm='1' & struct[6].version='dicom98' & struct[6].name='MoveDestination' struct[7].group_number='0000'x & struct[7].element_number='0700'x & struct[7].vr='US' & struct[7].vm='1' & struct[7].version='dicom98' & struct[7].name='Priority' struct[8].group_number='0000'x & struct[8].element_number='0800'x & struct[8].vr='US' & struct[8].vm='1' & struct[8].version='dicom98' & struct[8].name='DataSetType' struct[9].group_number='0000'x & struct[9].element_number='0900'x & struct[9].vr='US' & struct[9].vm='1' & struct[9].version='dicom98' & struct[9].name='Status' struct[10].group_number='0000'x & struct[10].element_number='0901'x & struct[10].vr='AT' & struct[10].vm='1-n' & struct[10].version='dicom98' & struct[10].name='OffendingElement' struct[11].group_number='0000'x & struct[11].element_number='0902'x & struct[11].vr='LO' & struct[11].vm='1' & struct[11].version='dicom98' & struct[11].name='ErrorComment' struct[12].group_number='0000'x & struct[12].element_number='0903'x & struct[12].vr='US' & struct[12].vm='1' & struct[12].version='dicom98' & struct[12].name='ErrorID' struct[13].group_number='0000'x & struct[13].element_number='1000'x & struct[13].vr='UI' & struct[13].vm='1' & struct[13].version='dicom98' & struct[13].name='AffectedSOPInstanceUID' struct[14].group_number='0000'x & struct[14].element_number='1001'x & struct[14].vr='UI' & struct[14].vm='1' & struct[14].version='dicom98' & struct[14].name='RequestedSOPInstanceUID' struct[15].group_number='0000'x & struct[15].element_number='1002'x & struct[15].vr='US' & struct[15].vm='1' & struct[15].version='dicom98' & struct[15].name='EventTypeID' struct[16].group_number='0000'x & struct[16].element_number='1005'x & struct[16].vr='AT' & struct[16].vm='1-n' & struct[16].version='dicom98' & struct[16].name='AttributeIdentifierList' struct[17].group_number='0000'x & struct[17].element_number='1008'x & struct[17].vr='US' & struct[17].vm='1' & struct[17].version='dicom98' & struct[17].name='ActionTypeID' struct[18].group_number='0000'x & struct[18].element_number='1020'x & struct[18].vr='US' & struct[18].vm='1' & struct[18].version='dicom98' & struct[18].name='NumberOfRemainingSuboperations' struct[19].group_number='0000'x & struct[19].element_number='1021'x & struct[19].vr='US' & struct[19].vm='1' & struct[19].version='dicom98' & struct[19].name='NumberOfCompletedSuboperations' struct[20].group_number='0000'x & struct[20].element_number='1022'x & struct[20].vr='US' & struct[20].vm='1' & struct[20].version='dicom98' & struct[20].name='NumberOfFailedSuboperations' struct[21].group_number='0000'x & struct[21].element_number='1023'x & struct[21].vr='US' & struct[21].vm='1' & struct[21].version='dicom98' & struct[21].name='NumberOfWarningSuboperations' struct[22].group_number='0000'x & struct[22].element_number='1030'x & struct[22].vr='AE' & struct[22].vm='1' & struct[22].version='dicom98' & struct[22].name='MoveOriginatorApplicationEntityTitle' struct[23].group_number='0000'x & struct[23].element_number='1031'x & struct[23].vr='US' & struct[23].vm='1' & struct[23].version='dicom98' & struct[23].name='MoveOriginatorMessageID' struct[24].group_number='0002'x & struct[24].element_number='0000'x & struct[24].vr='UL' & struct[24].vm='1' & struct[24].version='dicom98' & struct[24].name='MetaElementGroupLength' struct[25].group_number='0002'x & struct[25].element_number='0001'x & struct[25].vr='OB' & struct[25].vm='1' & struct[25].version='dicom98' & struct[25].name='FileMetaInformationVersion' struct[26].group_number='0002'x & struct[26].element_number='0002'x & struct[26].vr='UI' & struct[26].vm='1' & struct[26].version='dicom98' & struct[26].name='MediaStorageSOPClassUID' struct[27].group_number='0002'x & struct[27].element_number='0003'x & struct[27].vr='UI' & struct[27].vm='1' & struct[27].version='dicom98' & struct[27].name='MediaStorageSOPInstanceUID' struct[28].group_number='0002'x & struct[28].element_number='0010'x & struct[28].vr='UI' & struct[28].vm='1' & struct[28].version='dicom98' & struct[28].name='TransferSyntaxUID' struct[29].group_number='0002'x & struct[29].element_number='0012'x & struct[29].vr='UI' & struct[29].vm='1' & struct[29].version='dicom98' & struct[29].name='ImplementationClassUID' struct[30].group_number='0002'x & struct[30].element_number='0013'x & struct[30].vr='SH' & struct[30].vm='1' & struct[30].version='dicom98' & struct[30].name='ImplementationVersionName' struct[31].group_number='0002'x & struct[31].element_number='0016'x & struct[31].vr='AE' & struct[31].vm='1' & struct[31].version='dicom98' & struct[31].name='SourceApplicationEntityTitle' struct[32].group_number='0002'x & struct[32].element_number='0100'x & struct[32].vr='UI' & struct[32].vm='1' & struct[32].version='dicom98' & struct[32].name='PrivateInformationCreatorUID' struct[33].group_number='0002'x & struct[33].element_number='0102'x & struct[33].vr='OB' & struct[33].vm='1' & struct[33].version='dicom98' & struct[33].name='PrivateInformation' struct[34].group_number='0004'x & struct[34].element_number='0000'x & struct[34].vr='UL' & struct[34].vm='1' & struct[34].version='dicom98' & struct[34].name='FileSetGroupLength' struct[35].group_number='0004'x & struct[35].element_number='1130'x & struct[35].vr='CS' & struct[35].vm='1' & struct[35].version='dicom98' & struct[35].name='FileSetID' struct[36].group_number='0004'x & struct[36].element_number='1141'x & struct[36].vr='CS' & struct[36].vm='1-8' & struct[36].version='dicom98' & struct[36].name='FileSetDescriptorFileID' struct[37].group_number='0004'x & struct[37].element_number='1142'x & struct[37].vr='CS' & struct[37].vm='1' & struct[37].version='dicom98' & struct[37].name='SpecificCharacterSetOfFileSetDescriptorFile' struct[38].group_number='0004'x & struct[38].element_number='1200'x & struct[38].vr='up' & struct[38].vm='1' & struct[38].version='dicom98' & struct[38].name='OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity' struct[39].group_number='0004'x & struct[39].element_number='1202'x & struct[39].vr='up' & struct[39].vm='1' & struct[39].version='dicom98' & struct[39].name='OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity' struct[40].group_number='0004'x & struct[40].element_number='1212'x & struct[40].vr='US' & struct[40].vm='1' & struct[40].version='dicom98' & struct[40].name='FileSetConsistencyFlag' struct[41].group_number='0004'x & struct[41].element_number='1220'x & struct[41].vr='SQ' & struct[41].vm='1' & struct[41].version='dicom98' & struct[41].name='DirectoryRecordSequence' struct[42].group_number='0004'x & struct[42].element_number='1400'x & struct[42].vr='up' & struct[42].vm='1' & struct[42].version='dicom98' & struct[42].name='OffsetOfTheNextDirectoryRecord' struct[43].group_number='0004'x & struct[43].element_number='1410'x & struct[43].vr='US' & struct[43].vm='1' & struct[43].version='dicom98' & struct[43].name='RecordInUseFlag' struct[44].group_number='0004'x & struct[44].element_number='1420'x & struct[44].vr='up' & struct[44].vm='1' & struct[44].version='dicom98' & struct[44].name='OffsetOfReferencedLowerLevelDirectoryEntity' struct[45].group_number='0004'x & struct[45].element_number='1430'x & struct[45].vr='CS' & struct[45].vm='1' & struct[45].version='dicom98' & struct[45].name='DirectoryRecordType' struct[46].group_number='0004'x & struct[46].element_number='1432'x & struct[46].vr='UI' & struct[46].vm='1' & struct[46].version='dicom98' & struct[46].name='PrivateRecordUID' struct[47].group_number='0004'x & struct[47].element_number='1500'x & struct[47].vr='CS' & struct[47].vm='1-8' & struct[47].version='dicom98' & struct[47].name='ReferencedFileID' struct[48].group_number='0004'x & struct[48].element_number='1504'x & struct[48].vr='up' & struct[48].vm='1' & struct[48].version='dicom98' & struct[48].name='MRDRDirectoryRecordOffset' struct[49].group_number='0004'x & struct[49].element_number='1510'x & struct[49].vr='UI' & struct[49].vm='1' & struct[49].version='dicom98' & struct[49].name='ReferencedSOPClassUIDInFile' struct[50].group_number='0004'x & struct[50].element_number='1511'x & struct[50].vr='UI' & struct[50].vm='1' & struct[50].version='dicom98' & struct[50].name='ReferencedSOPInstanceUIDInFile' struct[51].group_number='0004'x & struct[51].element_number='1512'x & struct[51].vr='UI' & struct[51].vm='1' & struct[51].version='dicom98' & struct[51].name='ReferencedTransferSyntaxUIDInFile' struct[52].group_number='0004'x & struct[52].element_number='1600'x & struct[52].vr='UL' & struct[52].vm='1' & struct[52].version='dicom98' & struct[52].name='NumberOfReferences' struct[53].group_number='0008'x & struct[53].element_number='0000'x & struct[53].vr='UL' & struct[53].vm='1' & struct[53].version='dicom98' & struct[53].name='IdentifyingGroupLength' struct[55].group_number='0008'x & struct[55].element_number='0005'x & struct[55].vr='CS' & struct[55].vm='1-n' & struct[55].version='dicom98' & struct[55].name='SpecificCharacterSet' struct[56].group_number='0008'x & struct[56].element_number='0008'x & struct[56].vr='CS' & struct[56].vm='1-n' & struct[56].version='dicom98' & struct[56].name='ImageType' struct[57].group_number='0008'x & struct[57].element_number='0012'x & struct[57].vr='DA' & struct[57].vm='1' & struct[57].version='dicom98' & struct[57].name='InstanceCreationDate' struct[58].group_number='0008'x & struct[58].element_number='0013'x & struct[58].vr='TM' & struct[58].vm='1' & struct[58].version='dicom98' & struct[58].name='InstanceCreationTime' struct[59].group_number='0008'x & struct[59].element_number='0014'x & struct[59].vr='UI' & struct[59].vm='1' & struct[59].version='dicom98' & struct[59].name='InstanceCreatorUID' struct[60].group_number='0008'x & struct[60].element_number='0016'x & struct[60].vr='UI' & struct[60].vm='1' & struct[60].version='dicom98' & struct[60].name='SOPClassUID' struct[61].group_number='0008'x & struct[61].element_number='0018'x & struct[61].vr='UI' & struct[61].vm='1' & struct[61].version='dicom98' & struct[61].name='SOPInstanceUID' struct[62].group_number='0008'x & struct[62].element_number='0020'x & struct[62].vr='DA' & struct[62].vm='1' & struct[62].version='dicom98' & struct[62].name='StudyDate' struct[63].group_number='0008'x & struct[63].element_number='0021'x & struct[63].vr='DA' & struct[63].vm='1' & struct[63].version='dicom98' & struct[63].name='SeriesDate' struct[64].group_number='0008'x & struct[64].element_number='0022'x & struct[64].vr='DA' & struct[64].vm='1' & struct[64].version='dicom98' & struct[64].name='AcquisitionDate' struct[66].group_number='0008'x & struct[66].element_number='0023'x & struct[66].vr='DA' & struct[66].vm='1' & struct[66].version='dicom2000' & struct[66].name='ContentDate' struct[67].group_number='0008'x & struct[67].element_number='0024'x & struct[67].vr='DA' & struct[67].vm='1' & struct[67].version='dicom98' & struct[67].name='OverlayDate' struct[68].group_number='0008'x & struct[68].element_number='0025'x & struct[68].vr='DA' & struct[68].vm='1' & struct[68].version='dicom98' & struct[68].name='CurveDate' struct[69].group_number='0008'x & struct[69].element_number='002A'x & struct[69].vr='DT' & struct[69].vm='1' & struct[69].version='dicom2000' & struct[69].name='AcquisitionDatetime' struct[70].group_number='0008'x & struct[70].element_number='0030'x & struct[70].vr='TM' & struct[70].vm='1' & struct[70].version='dicom98' & struct[70].name='StudyTime' struct[71].group_number='0008'x & struct[71].element_number='0031'x & struct[71].vr='TM' & struct[71].vm='1' & struct[71].version='dicom98' & struct[71].name='SeriesTime' struct[72].group_number='0008'x & struct[72].element_number='0032'x & struct[72].vr='TM' & struct[72].vm='1' & struct[72].version='dicom98' & struct[72].name='AcquisitionTime' struct[74].group_number='0008'x & struct[74].element_number='0033'x & struct[74].vr='TM' & struct[74].vm='1' & struct[74].version='dicom2000' & struct[74].name='ContentTime' struct[75].group_number='0008'x & struct[75].element_number='0034'x & struct[75].vr='TM' & struct[75].vm='1' & struct[75].version='dicom98' & struct[75].name='OverlayTime' struct[76].group_number='0008'x & struct[76].element_number='0035'x & struct[76].vr='TM' & struct[76].vm='1' & struct[76].version='dicom98' & struct[76].name='CurveTime' struct[77].group_number='0008'x & struct[77].element_number='0050'x & struct[77].vr='SH' & struct[77].vm='1' & struct[77].version='dicom98' & struct[77].name='AccessionNumber' struct[78].group_number='0008'x & struct[78].element_number='0052'x & struct[78].vr='CS' & struct[78].vm='1' & struct[78].version='dicom98' & struct[78].name='QueryRetrieveLevel' struct[79].group_number='0008'x & struct[79].element_number='0054'x & struct[79].vr='AE' & struct[79].vm='1-n' & struct[79].version='dicom98' & struct[79].name='RetrieveAETitle' struct[80].group_number='0008'x & struct[80].element_number='0056'x & struct[80].vr='CS' & struct[80].vm='1' & struct[80].version='dicom2000' & struct[80].name='InstanceAvailability' struct[81].group_number='0008'x & struct[81].element_number='0058'x & struct[81].vr='UI' & struct[81].vm='1-n' & struct[81].version='dicom98' & struct[81].name='FailedSOPInstanceUIDList' struct[82].group_number='0008'x & struct[82].element_number='0060'x & struct[82].vr='CS' & struct[82].vm='1' & struct[82].version='dicom98' & struct[82].name='Modality' struct[83].group_number='0008'x & struct[83].element_number='0061'x & struct[83].vr='CS' & struct[83].vm='1-n' & struct[83].version='dicom98' & struct[83].name='ModalitiesInStudy' struct[84].group_number='0008'x & struct[84].element_number='0064'x & struct[84].vr='CS' & struct[84].vm='1' & struct[84].version='dicom98' & struct[84].name='ConversionType' struct[85].group_number='0008'x & struct[85].element_number='0068'x & struct[85].vr='CS' & struct[85].vm='1' & struct[85].version='dicom99' & struct[85].name='PresentationIntentType' struct[86].group_number='0008'x & struct[86].element_number='0070'x & struct[86].vr='LO' & struct[86].vm='1' & struct[86].version='dicom98' & struct[86].name='Manufacturer' struct[87].group_number='0008'x & struct[87].element_number='0080'x & struct[87].vr='LO' & struct[87].vm='1' & struct[87].version='dicom98' & struct[87].name='InstitutionName' struct[88].group_number='0008'x & struct[88].element_number='0081'x & struct[88].vr='ST' & struct[88].vm='1' & struct[88].version='dicom98' & struct[88].name='InstitutionAddress' struct[89].group_number='0008'x & struct[89].element_number='0082'x & struct[89].vr='SQ' & struct[89].vm='1' & struct[89].version='dicom98' & struct[89].name='InstitutionCodeSequence' struct[90].group_number='0008'x & struct[90].element_number='0090'x & struct[90].vr='PN' & struct[90].vm='1' & struct[90].version='dicom98' & struct[90].name='ReferringPhysiciansName' struct[91].group_number='0008'x & struct[91].element_number='0092'x & struct[91].vr='ST' & struct[91].vm='1' & struct[91].version='dicom98' & struct[91].name='ReferringPhysiciansAddress' struct[92].group_number='0008'x & struct[92].element_number='0094'x & struct[92].vr='SH' & struct[92].vm='1-n' & struct[92].version='dicom98' & struct[92].name='ReferringPhysiciansTelephoneNumbers' struct[93].group_number='0008'x & struct[93].element_number='0096'x & struct[93].vr='SQ' & struct[93].vm='1' & struct[93].version='dicom2003' & struct[93].name='ReferringPhysicianIdentificationSequence' struct[94].group_number='0008'x & struct[94].element_number='0100'x & struct[94].vr='SH' & struct[94].vm='1' & struct[94].version='dicom98' & struct[94].name='CodeValue' struct[95].group_number='0008'x & struct[95].element_number='0102'x & struct[95].vr='SH' & struct[95].vm='1' & struct[95].version='dicom98' & struct[95].name='CodingSchemeDesignator' struct[96].group_number='0008'x & struct[96].element_number='0103'x & struct[96].vr='SH' & struct[96].vm='1' & struct[96].version='dicom99' & struct[96].name='CodingSchemeVersion' struct[97].group_number='0008'x & struct[97].element_number='0104'x & struct[97].vr='LO' & struct[97].vm='1' & struct[97].version='dicom98' & struct[97].name='CodeMeaning' struct[98].group_number='0008'x & struct[98].element_number='0105'x & struct[98].vr='CS' & struct[98].vm='1' & struct[98].version='dicom99' & struct[98].name='MappingResource' struct[99].group_number='0008'x & struct[99].element_number='0106'x & struct[99].vr='DT' & struct[99].vm='1' & struct[99].version='dicom99' & struct[99].name='ContextGroupVersion' struct[100].group_number='0008'x & struct[100].element_number='0107'x & struct[100].vr='DT' & struct[100].vm='1' & struct[100].version='dicom99' & struct[100].name='ContextGroupLocalVersion' struct[101].group_number='0008'x & struct[101].element_number='010B'x & struct[101].vr='CS' & struct[101].vm='1' & struct[101].version='dicom99' & struct[101].name='CodeSetExtensionFlag' struct[103].group_number='0008'x & struct[103].element_number='010C'x & struct[103].vr='UI' & struct[103].vm='1' & struct[103].version='dicom99' & struct[103].name='CodingSchemeUID' struct[104].group_number='0008'x & struct[104].element_number='010D'x & struct[104].vr='UI' & struct[104].vm='1' & struct[104].version='dicom99' & struct[104].name='CodeSetExtensionCreatorUID' struct[105].group_number='0008'x & struct[105].element_number='010F'x & struct[105].vr='CS' & struct[105].vm='1' & struct[105].version='dicom99' & struct[105].name='ContextIdentifier' struct[106].group_number='0008'x & struct[106].element_number='0110'x & struct[106].vr='SQ' & struct[106].vm='1' & struct[106].version='dicom2003' & struct[106].name='CodingSchemeIdentificationSequence' struct[107].group_number='0008'x & struct[107].element_number='0112'x & struct[107].vr='LO' & struct[107].vm='1' & struct[107].version='dicom2003' & struct[107].name='CodingSchemeRegistry' struct[108].group_number='0008'x & struct[108].element_number='0114'x & struct[108].vr='ST' & struct[108].vm='1' & struct[108].version='dicom2003' & struct[108].name='CodingSchemeExternalID' struct[109].group_number='0008'x & struct[109].element_number='0115'x & struct[109].vr='ST' & struct[109].vm='1' & struct[109].version='dicom2003' & struct[109].name='CodingSchemeName' struct[110].group_number='0008'x & struct[110].element_number='0116'x & struct[110].vr='ST' & struct[110].vm='1' & struct[110].version='dicom2003' & struct[110].name='ResponsibleOrganization' struct[111].group_number='0008'x & struct[111].element_number='0201'x & struct[111].vr='SH' & struct[111].vm='1' & struct[111].version='dicom2000' & struct[111].name='TimezoneOffsetFromUTC' struct[112].group_number='0008'x & struct[112].element_number='1010'x & struct[112].vr='SH' & struct[112].vm='1' & struct[112].version='dicom98' & struct[112].name='StationName' struct[113].group_number='0008'x & struct[113].element_number='1030'x & struct[113].vr='LO' & struct[113].vm='1' & struct[113].version='dicom98' & struct[113].name='StudyDescription' struct[114].group_number='0008'x & struct[114].element_number='1032'x & struct[114].vr='SQ' & struct[114].vm='1' & struct[114].version='dicom98' & struct[114].name='ProcedureCodeSequence' struct[115].group_number='0008'x & struct[115].element_number='103E'x & struct[115].vr='LO' & struct[115].vm='1' & struct[115].version='dicom98' & struct[115].name='SeriesDescription' struct[116].group_number='0008'x & struct[116].element_number='1040'x & struct[116].vr='LO' & struct[116].vm='1' & struct[116].version='dicom98' & struct[116].name='InstitutionalDepartmentName' struct[117].group_number='0008'x & struct[117].element_number='1048'x & struct[117].vr='PN' & struct[117].vm='1-n' & struct[117].version='dicom98' & struct[117].name='PhysiciansOfRecord' struct[118].group_number='0008'x & struct[118].element_number='1049'x & struct[118].vr='SQ' & struct[118].vm='1' & struct[118].version='dicom2003' & struct[118].name='PhysiciansOfRecordIdentificationSequence' struct[119].group_number='0008'x & struct[119].element_number='1050'x & struct[119].vr='PN' & struct[119].vm='1-n' & struct[119].version='dicom98' & struct[119].name='PerformingPhysiciansName' struct[120].group_number='0008'x & struct[120].element_number='1052'x & struct[120].vr='SQ' & struct[120].vm='1' & struct[120].version='dicom2003' & struct[120].name='PerformingPhysicianIdentificationSequence' struct[121].group_number='0008'x & struct[121].element_number='1060'x & struct[121].vr='PN' & struct[121].vm='1-n' & struct[121].version='dicom98' & struct[121].name='NameOfPhysiciansReadingStudy' struct[122].group_number='0008'x & struct[122].element_number='1062'x & struct[122].vr='SQ' & struct[122].vm='1' & struct[122].version='dicom2003' & struct[122].name='PhysiciansReadingStudyIdentificationSequence' struct[123].group_number='0008'x & struct[123].element_number='1070'x & struct[123].vr='PN' & struct[123].vm='1-n' & struct[123].version='dicom98' & struct[123].name='OperatorsName' struct[124].group_number='0008'x & struct[124].element_number='1072'x & struct[124].vr='SQ' & struct[124].vm='1' & struct[124].version='dicom2003' & struct[124].name='OperatorIdentificationSequence' struct[125].group_number='0008'x & struct[125].element_number='1080'x & struct[125].vr='LO' & struct[125].vm='1-n' & struct[125].version='dicom98' & struct[125].name='AdmittingDiagnosesDescription' struct[126].group_number='0008'x & struct[126].element_number='1084'x & struct[126].vr='SQ' & struct[126].vm='1' & struct[126].version='dicom2001' & struct[126].name='AdmittingDiagnosesCodeSequence' struct[127].group_number='0008'x & struct[127].element_number='1090'x & struct[127].vr='LO' & struct[127].vm='1' & struct[127].version='dicom98' & struct[127].name='ManufacturersModelName' struct[128].group_number='0008'x & struct[128].element_number='1100'x & struct[128].vr='SQ' & struct[128].vm='1' & struct[128].version='dicom98' & struct[128].name='ReferencedResultsSequence' struct[129].group_number='0008'x & struct[129].element_number='1110'x & struct[129].vr='SQ' & struct[129].vm='1' & struct[129].version='dicom98' & struct[129].name='ReferencedStudySequence' struct[130].group_number='0008'x & struct[130].element_number='1111'x & struct[130].vr='SQ' & struct[130].vm='1' & struct[130].version='dicom2003' & struct[130].name='ReferencedPerformedProcedureStepSequence' struct[131].group_number='0008'x & struct[131].element_number='1115'x & struct[131].vr='SQ' & struct[131].vm='1' & struct[131].version='dicom98' & struct[131].name='ReferencedSeriesSequence' struct[132].group_number='0008'x & struct[132].element_number='1120'x & struct[132].vr='SQ' & struct[132].vm='1' & struct[132].version='dicom98' & struct[132].name='ReferencedPatientSequence' struct[133].group_number='0008'x & struct[133].element_number='1125'x & struct[133].vr='SQ' & struct[133].vm='1' & struct[133].version='dicom98' & struct[133].name='ReferencedVisitSequence' struct[134].group_number='0008'x & struct[134].element_number='1130'x & struct[134].vr='SQ' & struct[134].vm='1' & struct[134].version='dicom98' & struct[134].name='ReferencedOverlaySequence' struct[135].group_number='0008'x & struct[135].element_number='113A'x & struct[135].vr='SQ' & struct[135].vm='1' & struct[135].version='dicom2001' & struct[135].name='ReferencedWaveformSequence' struct[136].group_number='0008'x & struct[136].element_number='1140'x & struct[136].vr='SQ' & struct[136].vm='1' & struct[136].version='dicom98' & struct[136].name='ReferencedImageSequence' struct[137].group_number='0008'x & struct[137].element_number='1145'x & struct[137].vr='SQ' & struct[137].vm='1' & struct[137].version='dicom98' & struct[137].name='ReferencedCurveSequence' struct[138].group_number='0008'x & struct[138].element_number='114A'x & struct[138].vr='SQ' & struct[138].vm='1' & struct[138].version='dicom2001' & struct[138].name='ReferencedInstanceSequence' struct[139].group_number='0008'x & struct[139].element_number='1150'x & struct[139].vr='UI' & struct[139].vm='1' & struct[139].version='dicom98' & struct[139].name='ReferencedSOPClassUID' struct[140].group_number='0008'x & struct[140].element_number='1155'x & struct[140].vr='UI' & struct[140].vm='1' & struct[140].version='dicom98' & struct[140].name='ReferencedSOPInstanceUID' struct[141].group_number='0008'x & struct[141].element_number='115A'x & struct[141].vr='UI' & struct[141].vm='1-n' & struct[141].version='dicom99' & struct[141].name='SOPClassesSupported' struct[143].group_number='0008'x & struct[143].element_number='1160'x & struct[143].vr='IS' & struct[143].vm='1-n' & struct[143].version='dicom2000' & struct[143].name='ReferencedFrameNumber' struct[144].group_number='0008'x & struct[144].element_number='1195'x & struct[144].vr='UI' & struct[144].vm='1' & struct[144].version='dicom98' & struct[144].name='TransactionUID' struct[145].group_number='0008'x & struct[145].element_number='1197'x & struct[145].vr='US' & struct[145].vm='1' & struct[145].version='dicom98' & struct[145].name='FailureReason' struct[146].group_number='0008'x & struct[146].element_number='1198'x & struct[146].vr='SQ' & struct[146].vm='1' & struct[146].version='dicom98' & struct[146].name='FailedSOPSequence' struct[147].group_number='0008'x & struct[147].element_number='1199'x & struct[147].vr='SQ' & struct[147].vm='1' & struct[147].version='dicom98' & struct[147].name='ReferencedSOPSequence' struct[148].group_number='0008'x & struct[148].element_number='2111'x & struct[148].vr='ST' & struct[148].vm='1' & struct[148].version='dicom98' & struct[148].name='DerivationDescription' struct[149].group_number='0008'x & struct[149].element_number='2112'x & struct[149].vr='SQ' & struct[149].vm='1' & struct[149].version='dicom98' & struct[149].name='SourceImageSequence' struct[150].group_number='0008'x & struct[150].element_number='2120'x & struct[150].vr='SH' & struct[150].vm='1' & struct[150].version='dicom98' & struct[150].name='StageName' struct[151].group_number='0008'x & struct[151].element_number='2122'x & struct[151].vr='IS' & struct[151].vm='1' & struct[151].version='dicom98' & struct[151].name='StageNumber' struct[152].group_number='0008'x & struct[152].element_number='2124'x & struct[152].vr='IS' & struct[152].vm='1' & struct[152].version='dicom98' & struct[152].name='NumberOfStages' struct[153].group_number='0008'x & struct[153].element_number='2127'x & struct[153].vr='SH' & struct[153].vm='1' & struct[153].version='dicom2001' & struct[153].name='ViewName' struct[154].group_number='0008'x & struct[154].element_number='2128'x & struct[154].vr='IS' & struct[154].vm='1' & struct[154].version='dicom98' & struct[154].name='ViewNumber' struct[155].group_number='0008'x & struct[155].element_number='2129'x & struct[155].vr='IS' & struct[155].vm='1' & struct[155].version='dicom98' & struct[155].name='NumberOfEventTimers' struct[156].group_number='0008'x & struct[156].element_number='212A'x & struct[156].vr='IS' & struct[156].vm='1' & struct[156].version='dicom98' & struct[156].name='NumberOfViewsInStage' struct[157].group_number='0008'x & struct[157].element_number='2130'x & struct[157].vr='DS' & struct[157].vm='1-n' & struct[157].version='dicom98' & struct[157].name='EventElapsedTimes' struct[158].group_number='0008'x & struct[158].element_number='2132'x & struct[158].vr='LO' & struct[158].vm='1-n' & struct[158].version='dicom98' & struct[158].name='EventTimerNames' struct[159].group_number='0008'x & struct[159].element_number='2142'x & struct[159].vr='IS' & struct[159].vm='1' & struct[159].version='dicom98' & struct[159].name='StartTrim' struct[160].group_number='0008'x & struct[160].element_number='2143'x & struct[160].vr='IS' & struct[160].vm='1' & struct[160].version='dicom98' & struct[160].name='StopTrim' struct[161].group_number='0008'x & struct[161].element_number='2144'x & struct[161].vr='IS' & struct[161].vm='1' & struct[161].version='dicom98' & struct[161].name='RecommendedDisplayFrameRate' struct[162].group_number='0008'x & struct[162].element_number='2218'x & struct[162].vr='SQ' & struct[162].vm='1' & struct[162].version='dicom98' & struct[162].name='AnatomicRegionSequence' struct[163].group_number='0008'x & struct[163].element_number='2220'x & struct[163].vr='SQ' & struct[163].vm='1' & struct[163].version='dicom98' & struct[163].name='AnatomicRegionModifierSequence' struct[164].group_number='0008'x & struct[164].element_number='2228'x & struct[164].vr='SQ' & struct[164].vm='1' & struct[164].version='dicom98' & struct[164].name='PrimaryAnatomicStructureSequence' struct[165].group_number='0008'x & struct[165].element_number='2229'x & struct[165].vr='SQ' & struct[165].vm='1' & struct[165].version='dicom98' & struct[165].name='AnatomicStructureSpaceOrRegionSequence' struct[166].group_number='0008'x & struct[166].element_number='2230'x & struct[166].vr='SQ' & struct[166].vm='1' & struct[166].version='dicom98' & struct[166].name='PrimaryAnatomicStructureModifierSequence' struct[167].group_number='0008'x & struct[167].element_number='2240'x & struct[167].vr='SQ' & struct[167].vm='1' & struct[167].version='dicom98' & struct[167].name='TransducerPositionSequence' struct[168].group_number='0008'x & struct[168].element_number='2242'x & struct[168].vr='SQ' & struct[168].vm='1' & struct[168].version='dicom98' & struct[168].name='TransducerPositionModifierSequence' struct[169].group_number='0008'x & struct[169].element_number='2244'x & struct[169].vr='SQ' & struct[169].vm='1' & struct[169].version='dicom98' & struct[169].name='TransducerOrientationSequence' struct[170].group_number='0008'x & struct[170].element_number='2246'x & struct[170].vr='SQ' & struct[170].vm='1' & struct[170].version='dicom98' & struct[170].name='TransducerOrientationModifierSequence' struct[171].group_number='0008'x & struct[171].element_number='9007'x & struct[171].vr='CS' & struct[171].vm='4' & struct[171].version='dicom2003' & struct[171].name='FrameType' struct[172].group_number='0008'x & struct[172].element_number='9092'x & struct[172].vr='SQ' & struct[172].vm='1' & struct[172].version='dicom2003' & struct[172].name='ReferencedImageEvidenceSequence' struct[173].group_number='0008'x & struct[173].element_number='9121'x & struct[173].vr='SQ' & struct[173].vm='1' & struct[173].version='dicom2003' & struct[173].name='ReferencedRawDataSequence' struct[174].group_number='0008'x & struct[174].element_number='9123'x & struct[174].vr='UI' & struct[174].vm='1' & struct[174].version='dicom2003' & struct[174].name='CreatorVersionUID' struct[175].group_number='0008'x & struct[175].element_number='9124'x & struct[175].vr='SQ' & struct[175].vm='1' & struct[175].version='dicom2003' & struct[175].name='DerivationImageSequence' struct[176].group_number='0008'x & struct[176].element_number='9154'x & struct[176].vr='SQ' & struct[176].vm='1' & struct[176].version='dicom2003' & struct[176].name='SourceImageEvidenceSequence' struct[177].group_number='0008'x & struct[177].element_number='9205'x & struct[177].vr='CS' & struct[177].vm='1' & struct[177].version='dicom2003' & struct[177].name='PixelPresentation' struct[178].group_number='0008'x & struct[178].element_number='9206'x & struct[178].vr='CS' & struct[178].vm='1' & struct[178].version='dicom2003' & struct[178].name='VolumetricProperties' struct[179].group_number='0008'x & struct[179].element_number='9207'x & struct[179].vr='CS' & struct[179].vm='1' & struct[179].version='dicom2003' & struct[179].name='VolumeBasedCalculationTechnique' struct[180].group_number='0008'x & struct[180].element_number='9208'x & struct[180].vr='CS' & struct[180].vm='1' & struct[180].version='dicom2003' & struct[180].name='ComplexImageComponent' struct[181].group_number='0008'x & struct[181].element_number='9209'x & struct[181].vr='CS' & struct[181].vm='1' & struct[181].version='dicom2003' & struct[181].name='AcquisitionContrast' struct[182].group_number='0008'x & struct[182].element_number='9215'x & struct[182].vr='SQ' & struct[182].vm='1' & struct[182].version='dicom2003' & struct[182].name='DerivationCodeSequence' struct[183].group_number='0008'x & struct[183].element_number='9237'x & struct[183].vr='SQ' & struct[183].vm='1' & struct[183].version='dicom2003' & struct[183].name='ReferencedGrayscalePresentationStateSequence' struct[184].group_number='0010'x & struct[184].element_number='0000'x & struct[184].vr='UL' & struct[184].vm='1' & struct[184].version='dicom98' & struct[184].name='PatientGroupLength' struct[185].group_number='0010'x & struct[185].element_number='0010'x & struct[185].vr='PN' & struct[185].vm='1' & struct[185].version='dicom98' & struct[185].name='PatientsName' struct[186].group_number='0010'x & struct[186].element_number='0020'x & struct[186].vr='LO' & struct[186].vm='1' & struct[186].version='dicom98' & struct[186].name='PatientID' struct[187].group_number='0010'x & struct[187].element_number='0021'x & struct[187].vr='LO' & struct[187].vm='1' & struct[187].version='dicom98' & struct[187].name='IssuerOfPatientID' struct[188].group_number='0010'x & struct[188].element_number='0030'x & struct[188].vr='DA' & struct[188].vm='1' & struct[188].version='dicom98' & struct[188].name='PatientsBirthDate' struct[189].group_number='0010'x & struct[189].element_number='0032'x & struct[189].vr='TM' & struct[189].vm='1' & struct[189].version='dicom98' & struct[189].name='PatientsBirthTime' struct[190].group_number='0010'x & struct[190].element_number='0040'x & struct[190].vr='CS' & struct[190].vm='1' & struct[190].version='dicom98' & struct[190].name='PatientsSex' struct[191].group_number='0010'x & struct[191].element_number='0050'x & struct[191].vr='SQ' & struct[191].vm='1' & struct[191].version='dicom98' & struct[191].name='PatientsInsurancePlanCodeSequence' struct[192].group_number='0010'x & struct[192].element_number='0101'x & struct[192].vr='SQ' & struct[192].vm='1' & struct[192].version='dicom2001' & struct[192].name='PatientsPrimaryLanguageCodeSequence' struct[193].group_number='0010'x & struct[193].element_number='0102'x & struct[193].vr='SQ' & struct[193].vm='1' & struct[193].version='dicom2001' & struct[193].name='PatientsPrimaryLanguageCodeModifierSequence' struct[194].group_number='0010'x & struct[194].element_number='1000'x & struct[194].vr='LO' & struct[194].vm='1-n' & struct[194].version='dicom98' & struct[194].name='OtherPatientIDs' struct[195].group_number='0010'x & struct[195].element_number='1001'x & struct[195].vr='PN' & struct[195].vm='1-n' & struct[195].version='dicom98' & struct[195].name='OtherPatientNames' struct[196].group_number='0010'x & struct[196].element_number='1005'x & struct[196].vr='PN' & struct[196].vm='1' & struct[196].version='dicom98' & struct[196].name='PatientsBirthName' struct[197].group_number='0010'x & struct[197].element_number='1010'x & struct[197].vr='AS' & struct[197].vm='1' & struct[197].version='dicom98' & struct[197].name='PatientsAge' struct[198].group_number='0010'x & struct[198].element_number='1020'x & struct[198].vr='DS' & struct[198].vm='1' & struct[198].version='dicom98' & struct[198].name='PatientsSize' struct[199].group_number='0010'x & struct[199].element_number='1030'x & struct[199].vr='DS' & struct[199].vm='1' & struct[199].version='dicom98' & struct[199].name='PatientsWeight' struct[200].group_number='0010'x & struct[200].element_number='1040'x & struct[200].vr='LO' & struct[200].vm='1' & struct[200].version='dicom98' & struct[200].name='PatientsAddress' struct[201].group_number='0010'x & struct[201].element_number='1060'x & struct[201].vr='PN' & struct[201].vm='1' & struct[201].version='dicom98' & struct[201].name='PatientsMothersBirthName' struct[202].group_number='0010'x & struct[202].element_number='1080'x & struct[202].vr='LO' & struct[202].vm='1' & struct[202].version='dicom98' & struct[202].name='MilitaryRank' struct[203].group_number='0010'x & struct[203].element_number='1081'x & struct[203].vr='LO' & struct[203].vm='1' & struct[203].version='dicom98' & struct[203].name='BranchOfService' struct[204].group_number='0010'x & struct[204].element_number='1090'x & struct[204].vr='LO' & struct[204].vm='1' & struct[204].version='dicom98' & struct[204].name='MedicalRecordLocator' struct[205].group_number='0010'x & struct[205].element_number='2000'x & struct[205].vr='LO' & struct[205].vm='1-n' & struct[205].version='dicom98' & struct[205].name='MedicalAlerts' struct[206].group_number='0010'x & struct[206].element_number='2110'x & struct[206].vr='LO' & struct[206].vm='1-n' & struct[206].version='dicom98' & struct[206].name='ContrastAllergies' struct[207].group_number='0010'x & struct[207].element_number='2150'x & struct[207].vr='LO' & struct[207].vm='1' & struct[207].version='dicom98' & struct[207].name='CountryOfResidence' struct[208].group_number='0010'x & struct[208].element_number='2152'x & struct[208].vr='LO' & struct[208].vm='1' & struct[208].version='dicom98' & struct[208].name='RegionOfResidence' struct[209].group_number='0010'x & struct[209].element_number='2154'x & struct[209].vr='SH' & struct[209].vm='1-n' & struct[209].version='dicom98' & struct[209].name='PatientsTelephoneNumbers' struct[210].group_number='0010'x & struct[210].element_number='2160'x & struct[210].vr='SH' & struct[210].vm='1' & struct[210].version='dicom98' & struct[210].name='EthnicGroup' struct[211].group_number='0010'x & struct[211].element_number='2180'x & struct[211].vr='SH' & struct[211].vm='1' & struct[211].version='dicom98' & struct[211].name='Occupation' struct[212].group_number='0010'x & struct[212].element_number='21A0'x & struct[212].vr='CS' & struct[212].vm='1' & struct[212].version='dicom98' & struct[212].name='SmokingStatus' struct[213].group_number='0010'x & struct[213].element_number='21B0'x & struct[213].vr='LT' & struct[213].vm='1' & struct[213].version='dicom98' & struct[213].name='AdditionalPatientHistory' struct[214].group_number='0010'x & struct[214].element_number='21C0'x & struct[214].vr='US' & struct[214].vm='1' & struct[214].version='dicom98' & struct[214].name='PregnancyStatus' struct[215].group_number='0010'x & struct[215].element_number='21D0'x & struct[215].vr='DA' & struct[215].vm='1' & struct[215].version='dicom98' & struct[215].name='LastMenstrualDate' struct[216].group_number='0010'x & struct[216].element_number='21F0'x & struct[216].vr='LO' & struct[216].vm='1' & struct[216].version='dicom98' & struct[216].name='PatientsReligiousPreference' struct[217].group_number='0010'x & struct[217].element_number='4000'x & struct[217].vr='LT' & struct[217].vm='1' & struct[217].version='dicom98' & struct[217].name='PatientComments' struct[218].group_number='0012'x & struct[218].element_number='0010'x & struct[218].vr='LO' & struct[218].vm='1' & struct[218].version='dicom2003' & struct[218].name='ClinicalTrialSponsorName' struct[219].group_number='0012'x & struct[219].element_number='0020'x & struct[219].vr='LO' & struct[219].vm='1' & struct[219].version='dicom2003' & struct[219].name='ClinicalTrialProtocolID' struct[220].group_number='0012'x & struct[220].element_number='0021'x & struct[220].vr='LO' & struct[220].vm='1' & struct[220].version='dicom2003' & struct[220].name='ClinicalTrialProtocolName' struct[221].group_number='0012'x & struct[221].element_number='0030'x & struct[221].vr='LO' & struct[221].vm='1' & struct[221].version='dicom2003' & struct[221].name='ClinicalTrialSiteID' struct[222].group_number='0012'x & struct[222].element_number='0031'x & struct[222].vr='LO' & struct[222].vm='1' & struct[222].version='dicom2003' & struct[222].name='ClinicalTrialSiteName' struct[223].group_number='0012'x & struct[223].element_number='0040'x & struct[223].vr='LO' & struct[223].vm='1' & struct[223].version='dicom2003' & struct[223].name='ClinicalTrialSubjectID' struct[224].group_number='0012'x & struct[224].element_number='0042'x & struct[224].vr='LO' & struct[224].vm='1' & struct[224].version='dicom2003' & struct[224].name='ClinicalTrialSubjectReadingID' struct[225].group_number='0012'x & struct[225].element_number='0050'x & struct[225].vr='LO' & struct[225].vm='1' & struct[225].version='dicom2003' & struct[225].name='ClinicalTrialTimePointID' struct[226].group_number='0012'x & struct[226].element_number='0051'x & struct[226].vr='ST' & struct[226].vm='1' & struct[226].version='dicom2003' & struct[226].name='ClinicalTrialTimePointDescription' struct[227].group_number='0012'x & struct[227].element_number='0060'x & struct[227].vr='LO' & struct[227].vm='1' & struct[227].version='dicom2003' & struct[227].name='ClinicalTrialCoordinatingCenterName' struct[228].group_number='0018'x & struct[228].element_number='0000'x & struct[228].vr='UL' & struct[228].vm='1' & struct[228].version='dicom98' & struct[228].name='AcquisitionGroupLength' struct[229].group_number='0018'x & struct[229].element_number='0010'x & struct[229].vr='LO' & struct[229].vm='1' & struct[229].version='dicom98' & struct[229].name='ContrastBolusAgent' struct[230].group_number='0018'x & struct[230].element_number='0012'x & struct[230].vr='SQ' & struct[230].vm='1' & struct[230].version='dicom98' & struct[230].name='ContrastBolusAgentSequence' struct[231].group_number='0018'x & struct[231].element_number='0014'x & struct[231].vr='SQ' & struct[231].vm='1' & struct[231].version='dicom98' & struct[231].name='ContrastBolusAdministrationRouteSequence' struct[232].group_number='0018'x & struct[232].element_number='0015'x & struct[232].vr='CS' & struct[232].vm='1' & struct[232].version='dicom98' & struct[232].name='BodyPartExamined' struct[233].group_number='0018'x & struct[233].element_number='0020'x & struct[233].vr='CS' & struct[233].vm='1-n' & struct[233].version='dicom98' & struct[233].name='ScanningSequence' struct[234].group_number='0018'x & struct[234].element_number='0021'x & struct[234].vr='CS' & struct[234].vm='1-n' & struct[234].version='dicom98' & struct[234].name='SequenceVariant' struct[235].group_number='0018'x & struct[235].element_number='0022'x & struct[235].vr='CS' & struct[235].vm='1-n' & struct[235].version='dicom98' & struct[235].name='ScanOptions' struct[236].group_number='0018'x & struct[236].element_number='0023'x & struct[236].vr='CS' & struct[236].vm='1' & struct[236].version='dicom98' & struct[236].name='MRAcquisitionType' struct[237].group_number='0018'x & struct[237].element_number='0024'x & struct[237].vr='SH' & struct[237].vm='1' & struct[237].version='dicom98' & struct[237].name='SequenceName' struct[238].group_number='0018'x & struct[238].element_number='0025'x & struct[238].vr='CS' & struct[238].vm='1' & struct[238].version='dicom98' & struct[238].name='AngioFlag' struct[239].group_number='0018'x & struct[239].element_number='0026'x & struct[239].vr='SQ' & struct[239].vm='1' & struct[239].version='dicom98' & struct[239].name='InterventionDrugInformationSequence' struct[240].group_number='0018'x & struct[240].element_number='0027'x & struct[240].vr='TM' & struct[240].vm='1' & struct[240].version='dicom98' & struct[240].name='InterventionDrugStopTime' struct[241].group_number='0018'x & struct[241].element_number='0028'x & struct[241].vr='DS' & struct[241].vm='1' & struct[241].version='dicom98' & struct[241].name='InterventionDrugDose' struct[242].group_number='0018'x & struct[242].element_number='0029'x & struct[242].vr='SQ' & struct[242].vm='1' & struct[242].version='dicom98' & struct[242].name='InterventionDrugCodeSequence' struct[243].group_number='0018'x & struct[243].element_number='002A'x & struct[243].vr='SQ' & struct[243].vm='1' & struct[243].version='dicom98' & struct[243].name='AdditionalDrugSequence' struct[245].group_number='0018'x & struct[245].element_number='0031'x & struct[245].vr='LO' & struct[245].vm='1' & struct[245].version='dicom98' & struct[245].name='Radiopharmaceutical' struct[246].group_number='0018'x & struct[246].element_number='0034'x & struct[246].vr='LO' & struct[246].vm='1' & struct[246].version='dicom98' & struct[246].name='InterventionDrugName' struct[247].group_number='0018'x & struct[247].element_number='0035'x & struct[247].vr='TM' & struct[247].vm='1' & struct[247].version='dicom98' & struct[247].name='InterventionDrugStartTime' struct[248].group_number='0018'x & struct[248].element_number='0036'x & struct[248].vr='SQ' & struct[248].vm='1' & struct[248].version='dicom98' & struct[248].name='InterventionalTherapySequence' struct[249].group_number='0018'x & struct[249].element_number='0037'x & struct[249].vr='CS' & struct[249].vm='1' & struct[249].version='dicom98' & struct[249].name='RETIRED_TherapyType' struct[250].group_number='0018'x & struct[250].element_number='0038'x & struct[250].vr='CS' & struct[250].vm='1' & struct[250].version='dicom98' & struct[250].name='InterventionalStatus' struct[251].group_number='0018'x & struct[251].element_number='0039'x & struct[251].vr='CS' & struct[251].vm='1' & struct[251].version='dicom98' & struct[251].name='TherapyDescription' struct[252].group_number='0018'x & struct[252].element_number='0040'x & struct[252].vr='IS' & struct[252].vm='1' & struct[252].version='dicom98' & struct[252].name='CineRate' struct[253].group_number='0018'x & struct[253].element_number='0050'x & struct[253].vr='DS' & struct[253].vm='1' & struct[253].version='dicom98' & struct[253].name='SliceThickness' struct[254].group_number='0018'x & struct[254].element_number='0060'x & struct[254].vr='DS' & struct[254].vm='1' & struct[254].version='dicom98' & struct[254].name='KVP' struct[255].group_number='0018'x & struct[255].element_number='0070'x & struct[255].vr='IS' & struct[255].vm='1' & struct[255].version='dicom98' & struct[255].name='CountsAccumulated' struct[256].group_number='0018'x & struct[256].element_number='0071'x & struct[256].vr='CS' & struct[256].vm='1' & struct[256].version='dicom98' & struct[256].name='AcquisitionTerminationCondition' struct[257].group_number='0018'x & struct[257].element_number='0072'x & struct[257].vr='DS' & struct[257].vm='1' & struct[257].version='dicom98' & struct[257].name='EffectiveDuration' struct[258].group_number='0018'x & struct[258].element_number='0073'x & struct[258].vr='CS' & struct[258].vm='1' & struct[258].version='dicom98' & struct[258].name='AcquisitionStartCondition' struct[259].group_number='0018'x & struct[259].element_number='0074'x & struct[259].vr='IS' & struct[259].vm='1' & struct[259].version='dicom98' & struct[259].name='AcquisitionStartConditionData' struct[260].group_number='0018'x & struct[260].element_number='0075'x & struct[260].vr='IS' & struct[260].vm='1' & struct[260].version='dicom98' & struct[260].name='AcquisitionTerminationConditionData' struct[261].group_number='0018'x & struct[261].element_number='0080'x & struct[261].vr='DS' & struct[261].vm='1' & struct[261].version='dicom98' & struct[261].name='RepetitionTime' struct[262].group_number='0018'x & struct[262].element_number='0081'x & struct[262].vr='DS' & struct[262].vm='1' & struct[262].version='dicom98' & struct[262].name='EchoTime' struct[263].group_number='0018'x & struct[263].element_number='0082'x & struct[263].vr='DS' & struct[263].vm='1' & struct[263].version='dicom98' & struct[263].name='InversionTime' struct[264].group_number='0018'x & struct[264].element_number='0083'x & struct[264].vr='DS' & struct[264].vm='1' & struct[264].version='dicom98' & struct[264].name='NumberOfAverages' struct[265].group_number='0018'x & struct[265].element_number='0084'x & struct[265].vr='DS' & struct[265].vm='1' & struct[265].version='dicom98' & struct[265].name='ImagingFrequency' struct[266].group_number='0018'x & struct[266].element_number='0085'x & struct[266].vr='SH' & struct[266].vm='1' & struct[266].version='dicom98' & struct[266].name='ImagedNucleus' struct[267].group_number='0018'x & struct[267].element_number='0086'x & struct[267].vr='IS' & struct[267].vm='1-n' & struct[267].version='dicom98' & struct[267].name='EchoNumbers' struct[268].group_number='0018'x & struct[268].element_number='0087'x & struct[268].vr='DS' & struct[268].vm='1' & struct[268].version='dicom98' & struct[268].name='MagneticFieldStrength' struct[269].group_number='0018'x & struct[269].element_number='0088'x & struct[269].vr='DS' & struct[269].vm='1' & struct[269].version='dicom98' & struct[269].name='SpacingBetweenSlices' struct[270].group_number='0018'x & struct[270].element_number='0089'x & struct[270].vr='IS' & struct[270].vm='1' & struct[270].version='dicom98' & struct[270].name='NumberOfPhaseEncodingSteps' struct[271].group_number='0018'x & struct[271].element_number='0090'x & struct[271].vr='DS' & struct[271].vm='1' & struct[271].version='dicom98' & struct[271].name='DataCollectionDiameter' struct[272].group_number='0018'x & struct[272].element_number='0091'x & struct[272].vr='IS' & struct[272].vm='1' & struct[272].version='dicom98' & struct[272].name='EchoTrainLength' struct[273].group_number='0018'x & struct[273].element_number='0093'x & struct[273].vr='DS' & struct[273].vm='1' & struct[273].version='dicom98' & struct[273].name='PercentSampling' struct[274].group_number='0018'x & struct[274].element_number='0094'x & struct[274].vr='DS' & struct[274].vm='1' & struct[274].version='dicom98' & struct[274].name='PercentPhaseFieldOfView' struct[275].group_number='0018'x & struct[275].element_number='0095'x & struct[275].vr='DS' & struct[275].vm='1' & struct[275].version='dicom98' & struct[275].name='PixelBandwidth' struct[276].group_number='0018'x & struct[276].element_number='1000'x & struct[276].vr='LO' & struct[276].vm='1' & struct[276].version='dicom98' & struct[276].name='DeviceSerialNumber' struct[277].group_number='0018'x & struct[277].element_number='1004'x & struct[277].vr='LO' & struct[277].vm='1' & struct[277].version='dicom98' & struct[277].name='PlateID' struct[278].group_number='0018'x & struct[278].element_number='1010'x & struct[278].vr='LO' & struct[278].vm='1' & struct[278].version='dicom98' & struct[278].name='SecondaryCaptureDeviceID' struct[279].group_number='0018'x & struct[279].element_number='1011'x & struct[279].vr='LO' & struct[279].vm='1' & struct[279].version='dicom98' & struct[279].name='HardcopyCreationDeviceID' struct[280].group_number='0018'x & struct[280].element_number='1012'x & struct[280].vr='DA' & struct[280].vm='1' & struct[280].version='dicom98' & struct[280].name='DateOfSecondaryCapture' struct[281].group_number='0018'x & struct[281].element_number='1014'x & struct[281].vr='TM' & struct[281].vm='1' & struct[281].version='dicom98' & struct[281].name='TimeOfSecondaryCapture' struct[282].group_number='0018'x & struct[282].element_number='1016'x & struct[282].vr='LO' & struct[282].vm='1' & struct[282].version='dicom98' & struct[282].name='SecondaryCaptureDeviceManufacturer' struct[283].group_number='0018'x & struct[283].element_number='1017'x & struct[283].vr='LO' & struct[283].vm='1' & struct[283].version='dicom98' & struct[283].name='HardcopyDeviceManufacturer' struct[284].group_number='0018'x & struct[284].element_number='1018'x & struct[284].vr='LO' & struct[284].vm='1' & struct[284].version='dicom98' & struct[284].name='SecondaryCaptureDeviceManufacturersModelName' struct[285].group_number='0018'x & struct[285].element_number='1019'x & struct[285].vr='LO' & struct[285].vm='1-n' & struct[285].version='dicom98' & struct[285].name='SecondaryCaptureDeviceSoftwareVersions' struct[286].group_number='0018'x & struct[286].element_number='101A'x & struct[286].vr='LO' & struct[286].vm='1-n' & struct[286].version='dicom98' & struct[286].name='HardcopyDeviceSoftwareVersion' struct[287].group_number='0018'x & struct[287].element_number='101B'x & struct[287].vr='LO' & struct[287].vm='1' & struct[287].version='dicom98' & struct[287].name='HardcopyDeviceManufacturersModelName' struct[288].group_number='0018'x & struct[288].element_number='1020'x & struct[288].vr='LO' & struct[288].vm='1-n' & struct[288].version='dicom98' & struct[288].name='SoftwareVersions' struct[289].group_number='0018'x & struct[289].element_number='1022'x & struct[289].vr='SH' & struct[289].vm='1' & struct[289].version='dicom98' & struct[289].name='VideoImageFormatAcquired' struct[290].group_number='0018'x & struct[290].element_number='1023'x & struct[290].vr='LO' & struct[290].vm='1' & struct[290].version='dicom98' & struct[290].name='DigitalImageFormatAcquired' struct[291].group_number='0018'x & struct[291].element_number='1030'x & struct[291].vr='LO' & struct[291].vm='1' & struct[291].version='dicom98' & struct[291].name='ProtocolName' struct[292].group_number='0018'x & struct[292].element_number='1040'x & struct[292].vr='LO' & struct[292].vm='1' & struct[292].version='dicom98' & struct[292].name='ContrastBolusRoute' struct[293].group_number='0018'x & struct[293].element_number='1041'x & struct[293].vr='DS' & struct[293].vm='1' & struct[293].version='dicom98' & struct[293].name='ContrastBolusVolume' struct[294].group_number='0018'x & struct[294].element_number='1042'x & struct[294].vr='TM' & struct[294].vm='1' & struct[294].version='dicom98' & struct[294].name='ContrastBolusStartTime' struct[295].group_number='0018'x & struct[295].element_number='1043'x & struct[295].vr='TM' & struct[295].vm='1' & struct[295].version='dicom98' & struct[295].name='ContrastBolusStopTime' struct[296].group_number='0018'x & struct[296].element_number='1044'x & struct[296].vr='DS' & struct[296].vm='1' & struct[296].version='dicom98' & struct[296].name='ContrastBolusTotalDose' struct[298].group_number='0018'x & struct[298].element_number='1045'x & struct[298].vr='IS' & struct[298].vm='1' & struct[298].version='dicom98' & struct[298].name='SyringeCounts' struct[299].group_number='0018'x & struct[299].element_number='1046'x & struct[299].vr='DS' & struct[299].vm='1-n' & struct[299].version='dicom98' & struct[299].name='ContrastFlowRates' struct[300].group_number='0018'x & struct[300].element_number='1047'x & struct[300].vr='DS' & struct[300].vm='1-n' & struct[300].version='dicom98' & struct[300].name='ContrastFlowDurations' struct[301].group_number='0018'x & struct[301].element_number='1048'x & struct[301].vr='CS' & struct[301].vm='1' & struct[301].version='dicom98' & struct[301].name='ContrastBolusIngredient' struct[302].group_number='0018'x & struct[302].element_number='1049'x & struct[302].vr='DS' & struct[302].vm='1' & struct[302].version='dicom98' & struct[302].name='ContrastBolusIngredientConcentration' struct[303].group_number='0018'x & struct[303].element_number='1050'x & struct[303].vr='DS' & struct[303].vm='1' & struct[303].version='dicom98' & struct[303].name='SpatialResolution' struct[304].group_number='0018'x & struct[304].element_number='1060'x & struct[304].vr='DS' & struct[304].vm='1' & struct[304].version='dicom98' & struct[304].name='TriggerTime' struct[305].group_number='0018'x & struct[305].element_number='1061'x & struct[305].vr='LO' & struct[305].vm='1' & struct[305].version='dicom98' & struct[305].name='TriggerSourceOrType' struct[306].group_number='0018'x & struct[306].element_number='1062'x & struct[306].vr='IS' & struct[306].vm='1' & struct[306].version='dicom98' & struct[306].name='NominalInterval' struct[307].group_number='0018'x & struct[307].element_number='1063'x & struct[307].vr='DS' & struct[307].vm='1' & struct[307].version='dicom98' & struct[307].name='FrameTime' struct[308].group_number='0018'x & struct[308].element_number='1064'x & struct[308].vr='LO' & struct[308].vm='1' & struct[308].version='dicom98' & struct[308].name='FramingType' struct[309].group_number='0018'x & struct[309].element_number='1065'x & struct[309].vr='DS' & struct[309].vm='1-n' & struct[309].version='dicom98' & struct[309].name='FrameTimeVector' struct[310].group_number='0018'x & struct[310].element_number='1066'x & struct[310].vr='DS' & struct[310].vm='1' & struct[310].version='dicom98' & struct[310].name='FrameDelay' struct[311].group_number='0018'x & struct[311].element_number='1067'x & struct[311].vr='DS' & struct[311].vm='1' & struct[311].version='dicom2000' & struct[311].name='ImageTriggerDelay' struct[312].group_number='0018'x & struct[312].element_number='1068'x & struct[312].vr='DS' & struct[312].vm='1' & struct[312].version='dicom2000' & struct[312].name='MultiplexGroupTimeOffset' struct[313].group_number='0018'x & struct[313].element_number='1069'x & struct[313].vr='DS' & struct[313].vm='1' & struct[313].version='dicom2000' & struct[313].name='TriggerTimeOffset' struct[314].group_number='0018'x & struct[314].element_number='106A'x & struct[314].vr='CS' & struct[314].vm='1' & struct[314].version='dicom2000' & struct[314].name='SynchronizationTrigger' struct[315].group_number='0018'x & struct[315].element_number='106C'x & struct[315].vr='US' & struct[315].vm='2' & struct[315].version='dicom2000' & struct[315].name='SynchronizationChannel' struct[316].group_number='0018'x & struct[316].element_number='106E'x & struct[316].vr='UL' & struct[316].vm='1' & struct[316].version='dicom2000' & struct[316].name='TriggerSamplePosition' struct[318].group_number='0018'x & struct[318].element_number='1070'x & struct[318].vr='LO' & struct[318].vm='1' & struct[318].version='dicom98' & struct[318].name='RadiopharmaceuticalRoute' struct[320].group_number='0018'x & struct[320].element_number='1071'x & struct[320].vr='DS' & struct[320].vm='1' & struct[320].version='dicom98' & struct[320].name='RadiopharmaceuticalVolume' struct[322].group_number='0018'x & struct[322].element_number='1072'x & struct[322].vr='TM' & struct[322].vm='1' & struct[322].version='dicom98' & struct[322].name='RadiopharmaceuticalStartTime' struct[324].group_number='0018'x & struct[324].element_number='1073'x & struct[324].vr='TM' & struct[324].vm='1' & struct[324].version='dicom98' & struct[324].name='RadiopharmaceuticalStopTime' struct[325].group_number='0018'x & struct[325].element_number='1074'x & struct[325].vr='DS' & struct[325].vm='1' & struct[325].version='dicom98' & struct[325].name='RadionuclideTotalDose' struct[326].group_number='0018'x & struct[326].element_number='1075'x & struct[326].vr='DS' & struct[326].vm='1' & struct[326].version='dicom98' & struct[326].name='RadionuclideHalfLife' struct[327].group_number='0018'x & struct[327].element_number='1076'x & struct[327].vr='DS' & struct[327].vm='1' & struct[327].version='dicom98' & struct[327].name='RadionuclidePositronFraction' struct[328].group_number='0018'x & struct[328].element_number='1077'x & struct[328].vr='DS' & struct[328].vm='1' & struct[328].version='dicom98' & struct[328].name='RadiopharmaceuticalSpecificActivity' struct[329].group_number='0018'x & struct[329].element_number='1080'x & struct[329].vr='CS' & struct[329].vm='1' & struct[329].version='dicom98' & struct[329].name='BeatRejectionFlag' struct[330].group_number='0018'x & struct[330].element_number='1081'x & struct[330].vr='IS' & struct[330].vm='1' & struct[330].version='dicom98' & struct[330].name='LowRRValue' struct[331].group_number='0018'x & struct[331].element_number='1082'x & struct[331].vr='IS' & struct[331].vm='1' & struct[331].version='dicom98' & struct[331].name='HighRRValue' struct[332].group_number='0018'x & struct[332].element_number='1083'x & struct[332].vr='IS' & struct[332].vm='1' & struct[332].version='dicom98' & struct[332].name='IntervalsAcquired' struct[333].group_number='0018'x & struct[333].element_number='1084'x & struct[333].vr='IS' & struct[333].vm='1' & struct[333].version='dicom98' & struct[333].name='IntervalsRejected' struct[334].group_number='0018'x & struct[334].element_number='1085'x & struct[334].vr='LO' & struct[334].vm='1' & struct[334].version='dicom98' & struct[334].name='PVCRejection' struct[335].group_number='0018'x & struct[335].element_number='1086'x & struct[335].vr='IS' & struct[335].vm='1' & struct[335].version='dicom98' & struct[335].name='SkipBeats' struct[336].group_number='0018'x & struct[336].element_number='1088'x & struct[336].vr='IS' & struct[336].vm='1' & struct[336].version='dicom98' & struct[336].name='HeartRate' struct[337].group_number='0018'x & struct[337].element_number='1090'x & struct[337].vr='IS' & struct[337].vm='1' & struct[337].version='dicom98' & struct[337].name='CardiacNumberOfImages' struct[338].group_number='0018'x & struct[338].element_number='1094'x & struct[338].vr='IS' & struct[338].vm='1' & struct[338].version='dicom98' & struct[338].name='TriggerWindow' struct[339].group_number='0018'x & struct[339].element_number='1100'x & struct[339].vr='DS' & struct[339].vm='1' & struct[339].version='dicom98' & struct[339].name='ReconstructionDiameter' struct[340].group_number='0018'x & struct[340].element_number='1110'x & struct[340].vr='DS' & struct[340].vm='1' & struct[340].version='dicom98' & struct[340].name='DistanceSourceToDetector' struct[341].group_number='0018'x & struct[341].element_number='1111'x & struct[341].vr='DS' & struct[341].vm='1' & struct[341].version='dicom98' & struct[341].name='DistanceSourceToPatient' struct[342].group_number='0018'x & struct[342].element_number='1114'x & struct[342].vr='DS' & struct[342].vm='1' & struct[342].version='dicom98' & struct[342].name='EstimatedRadiographicMagnificationFactor' struct[343].group_number='0018'x & struct[343].element_number='1120'x & struct[343].vr='DS' & struct[343].vm='1' & struct[343].version='dicom98' & struct[343].name='GantryDetectorTilt' struct[344].group_number='0018'x & struct[344].element_number='1121'x & struct[344].vr='DS' & struct[344].vm='1' & struct[344].version='dicom98' & struct[344].name='GantryDetectorSlew' struct[345].group_number='0018'x & struct[345].element_number='1130'x & struct[345].vr='DS' & struct[345].vm='1' & struct[345].version='dicom98' & struct[345].name='TableHeight' struct[346].group_number='0018'x & struct[346].element_number='1131'x & struct[346].vr='DS' & struct[346].vm='1' & struct[346].version='dicom98' & struct[346].name='TableTraverse' struct[347].group_number='0018'x & struct[347].element_number='1134'x & struct[347].vr='CS' & struct[347].vm='1' & struct[347].version='dicom98' & struct[347].name='TableMotion' struct[348].group_number='0018'x & struct[348].element_number='1135'x & struct[348].vr='DS' & struct[348].vm='1-n' & struct[348].version='dicom98' & struct[348].name='TableVerticalIncrement' struct[349].group_number='0018'x & struct[349].element_number='1136'x & struct[349].vr='DS' & struct[349].vm='1-n' & struct[349].version='dicom98' & struct[349].name='TableLateralIncrement' struct[350].group_number='0018'x & struct[350].element_number='1137'x & struct[350].vr='DS' & struct[350].vm='1-n' & struct[350].version='dicom98' & struct[350].name='TableLongitudinalIncrement' struct[351].group_number='0018'x & struct[351].element_number='1138'x & struct[351].vr='DS' & struct[351].vm='1' & struct[351].version='dicom98' & struct[351].name='TableAngle' struct[352].group_number='0018'x & struct[352].element_number='113A'x & struct[352].vr='CS' & struct[352].vm='1' & struct[352].version='dicom99' & struct[352].name='TableType' struct[353].group_number='0018'x & struct[353].element_number='1140'x & struct[353].vr='CS' & struct[353].vm='1' & struct[353].version='dicom98' & struct[353].name='RotationDirection' struct[354].group_number='0018'x & struct[354].element_number='1141'x & struct[354].vr='DS' & struct[354].vm='1' & struct[354].version='dicom98' & struct[354].name='AngularPosition' struct[355].group_number='0018'x & struct[355].element_number='1142'x & struct[355].vr='DS' & struct[355].vm='1-n' & struct[355].version='dicom98' & struct[355].name='RadialPosition' struct[356].group_number='0018'x & struct[356].element_number='1143'x & struct[356].vr='DS' & struct[356].vm='1' & struct[356].version='dicom98' & struct[356].name='ScanArc' struct[357].group_number='0018'x & struct[357].element_number='1144'x & struct[357].vr='DS' & struct[357].vm='1' & struct[357].version='dicom98' & struct[357].name='AngularStep' struct[358].group_number='0018'x & struct[358].element_number='1145'x & struct[358].vr='DS' & struct[358].vm='1' & struct[358].version='dicom98' & struct[358].name='CenterOfRotationOffset' struct[359].group_number='0018'x & struct[359].element_number='1147'x & struct[359].vr='CS' & struct[359].vm='1' & struct[359].version='dicom98' & struct[359].name='FieldOfViewShape' struct[360].group_number='0018'x & struct[360].element_number='1149'x & struct[360].vr='IS' & struct[360].vm='1-2' & struct[360].version='dicom98' & struct[360].name='FieldOfViewDimensions' struct[361].group_number='0018'x & struct[361].element_number='1150'x & struct[361].vr='IS' & struct[361].vm='1' & struct[361].version='dicom98' & struct[361].name='ExposureTime' struct[362].group_number='0018'x & struct[362].element_number='1151'x & struct[362].vr='IS' & struct[362].vm='1' & struct[362].version='dicom98' & struct[362].name='XRayTubeCurrent' struct[363].group_number='0018'x & struct[363].element_number='1152'x & struct[363].vr='IS' & struct[363].vm='1' & struct[363].version='dicom98' & struct[363].name='Exposure' struct[364].group_number='0018'x & struct[364].element_number='1153'x & struct[364].vr='IS' & struct[364].vm='1' & struct[364].version='dicom98' & struct[364].name='ExposureInMicroAs' struct[365].group_number='0018'x & struct[365].element_number='1154'x & struct[365].vr='DS' & struct[365].vm='1' & struct[365].version='dicom98' & struct[365].name='AveragePulseWidth' struct[366].group_number='0018'x & struct[366].element_number='1155'x & struct[366].vr='CS' & struct[366].vm='1' & struct[366].version='dicom98' & struct[366].name='RadiationSetting' struct[367].group_number='0018'x & struct[367].element_number='1156'x & struct[367].vr='CS' & struct[367].vm='1' & struct[367].version='dicom99' & struct[367].name='RectificationType' struct[368].group_number='0018'x & struct[368].element_number='115A'x & struct[368].vr='CS' & struct[368].vm='1' & struct[368].version='dicom98' & struct[368].name='RadiationMode' struct[369].group_number='0018'x & struct[369].element_number='115E'x & struct[369].vr='DS' & struct[369].vm='1' & struct[369].version='dicom98' & struct[369].name='ImageAreaDoseProduct' struct[370].group_number='0018'x & struct[370].element_number='1160'x & struct[370].vr='SH' & struct[370].vm='1' & struct[370].version='dicom98' & struct[370].name='FilterType' struct[371].group_number='0018'x & struct[371].element_number='1161'x & struct[371].vr='LO' & struct[371].vm='1-n' & struct[371].version='dicom98' & struct[371].name='TypeOfFilters' struct[372].group_number='0018'x & struct[372].element_number='1162'x & struct[372].vr='DS' & struct[372].vm='1' & struct[372].version='dicom98' & struct[372].name='IntensifierSize' struct[373].group_number='0018'x & struct[373].element_number='1164'x & struct[373].vr='DS' & struct[373].vm='2' & struct[373].version='dicom98' & struct[373].name='ImagerPixelSpacing' struct[374].group_number='0018'x & struct[374].element_number='1166'x & struct[374].vr='CS' & struct[374].vm='1-n' & struct[374].version='dicom2001' & struct[374].name='Grid' struct[375].group_number='0018'x & struct[375].element_number='1170'x & struct[375].vr='IS' & struct[375].vm='1' & struct[375].version='dicom98' & struct[375].name='GeneratorPower' struct[376].group_number='0018'x & struct[376].element_number='1180'x & struct[376].vr='SH' & struct[376].vm='1' & struct[376].version='dicom98' & struct[376].name='CollimatorGridName' struct[377].group_number='0018'x & struct[377].element_number='1181'x & struct[377].vr='CS' & struct[377].vm='1' & struct[377].version='dicom98' & struct[377].name='CollimatorType' struct[379].group_number='0018'x & struct[379].element_number='1182'x & struct[379].vr='IS' & struct[379].vm='1-2' & struct[379].version='dicom98' & struct[379].name='FocalDistance' struct[381].group_number='0018'x & struct[381].element_number='1183'x & struct[381].vr='DS' & struct[381].vm='1-2' & struct[381].version='dicom98' & struct[381].name='XFocusCenter' struct[383].group_number='0018'x & struct[383].element_number='1184'x & struct[383].vr='DS' & struct[383].vm='1-2' & struct[383].version='dicom98' & struct[383].name='YFocusCenter' struct[384].group_number='0018'x & struct[384].element_number='1190'x & struct[384].vr='DS' & struct[384].vm='1-n' & struct[384].version='dicom98' & struct[384].name='FocalSpots' struct[385].group_number='0018'x & struct[385].element_number='1191'x & struct[385].vr='CS' & struct[385].vm='1' & struct[385].version='dicom99' & struct[385].name='AnodeTargetMaterial' struct[386].group_number='0018'x & struct[386].element_number='11A0'x & struct[386].vr='DS' & struct[386].vm='1' & struct[386].version='dicom99' & struct[386].name='BodyPartThickness' struct[387].group_number='0018'x & struct[387].element_number='11A2'x & struct[387].vr='DS' & struct[387].vm='1' & struct[387].version='dicom99' & struct[387].name='CompressionForce' struct[388].group_number='0018'x & struct[388].element_number='1200'x & struct[388].vr='DA' & struct[388].vm='1-n' & struct[388].version='dicom98' & struct[388].name='DateOfLastCalibration' struct[389].group_number='0018'x & struct[389].element_number='1201'x & struct[389].vr='TM' & struct[389].vm='1-n' & struct[389].version='dicom98' & struct[389].name='TimeOfLastCalibration' struct[390].group_number='0018'x & struct[390].element_number='1210'x & struct[390].vr='SH' & struct[390].vm='1-n' & struct[390].version='dicom98' & struct[390].name='ConvolutionKernel' struct[391].group_number='0018'x & struct[391].element_number='1242'x & struct[391].vr='IS' & struct[391].vm='1' & struct[391].version='dicom98' & struct[391].name='ActualFrameDuration' struct[392].group_number='0018'x & struct[392].element_number='1243'x & struct[392].vr='IS' & struct[392].vm='1' & struct[392].version='dicom98' & struct[392].name='CountRate' struct[393].group_number='0018'x & struct[393].element_number='1244'x & struct[393].vr='US' & struct[393].vm='1' & struct[393].version='dicom98' & struct[393].name='PreferredPlaybackSequencing' struct[394].group_number='0018'x & struct[394].element_number='1250'x & struct[394].vr='SH' & struct[394].vm='1' & struct[394].version='dicom2003' & struct[394].name='ReceiveCoilName' struct[395].group_number='0018'x & struct[395].element_number='1251'x & struct[395].vr='SH' & struct[395].vm='1' & struct[395].version='dicom2003' & struct[395].name='TransmitCoilName' struct[396].group_number='0018'x & struct[396].element_number='1260'x & struct[396].vr='SH' & struct[396].vm='1' & struct[396].version='dicom98' & struct[396].name='PlateType' struct[397].group_number='0018'x & struct[397].element_number='1261'x & struct[397].vr='LO' & struct[397].vm='1' & struct[397].version='dicom98' & struct[397].name='PhosphorType' struct[399].group_number='0018'x & struct[399].element_number='1300'x & struct[399].vr='DS' & struct[399].vm='1' & struct[399].version='dicom98' & struct[399].name='ScanVelocity' struct[400].group_number='0018'x & struct[400].element_number='1301'x & struct[400].vr='CS' & struct[400].vm='1-n' & struct[400].version='dicom98' & struct[400].name='WholeBodyTechnique' struct[401].group_number='0018'x & struct[401].element_number='1302'x & struct[401].vr='IS' & struct[401].vm='1' & struct[401].version='dicom98' & struct[401].name='ScanLength' struct[402].group_number='0018'x & struct[402].element_number='1310'x & struct[402].vr='US' & struct[402].vm='4' & struct[402].version='dicom98' & struct[402].name='AcquisitionMatrix' struct[403].group_number='0018'x & struct[403].element_number='1312'x & struct[403].vr='CS' & struct[403].vm='1' & struct[403].version='dicom98' & struct[403].name='InPlanePhaseEncodingDirection' struct[404].group_number='0018'x & struct[404].element_number='1314'x & struct[404].vr='DS' & struct[404].vm='1' & struct[404].version='dicom98' & struct[404].name='FlipAngle' struct[405].group_number='0018'x & struct[405].element_number='1315'x & struct[405].vr='CS' & struct[405].vm='1' & struct[405].version='dicom98' & struct[405].name='VariableFlipAngleFlag' struct[406].group_number='0018'x & struct[406].element_number='1316'x & struct[406].vr='DS' & struct[406].vm='1' & struct[406].version='dicom98' & struct[406].name='SAR' struct[407].group_number='0018'x & struct[407].element_number='1318'x & struct[407].vr='DS' & struct[407].vm='1' & struct[407].version='dicom98' & struct[407].name='dBdt' struct[408].group_number='0018'x & struct[408].element_number='1400'x & struct[408].vr='LO' & struct[408].vm='1' & struct[408].version='dicom98' & struct[408].name='AcquisitionDeviceProcessingDescription' struct[409].group_number='0018'x & struct[409].element_number='1401'x & struct[409].vr='LO' & struct[409].vm='1' & struct[409].version='dicom98' & struct[409].name='AcquisitionDeviceProcessingCode' struct[410].group_number='0018'x & struct[410].element_number='1402'x & struct[410].vr='CS' & struct[410].vm='1' & struct[410].version='dicom98' & struct[410].name='CassetteOrientation' struct[411].group_number='0018'x & struct[411].element_number='1403'x & struct[411].vr='CS' & struct[411].vm='1' & struct[411].version='dicom98' & struct[411].name='CassetteSize' struct[412].group_number='0018'x & struct[412].element_number='1404'x & struct[412].vr='US' & struct[412].vm='1' & struct[412].version='dicom98' & struct[412].name='ExposuresOnPlate' struct[413].group_number='0018'x & struct[413].element_number='1405'x & struct[413].vr='IS' & struct[413].vm='1' & struct[413].version='dicom98' & struct[413].name='RelativeXRayExposure' struct[414].group_number='0018'x & struct[414].element_number='1450'x & struct[414].vr='DS' & struct[414].vm='1' & struct[414].version='dicom2003' & struct[414].name='ColumnAngulation' struct[415].group_number='0018'x & struct[415].element_number='1460'x & struct[415].vr='DS' & struct[415].vm='1' & struct[415].version='dicom98' & struct[415].name='TomoLayerHeight' struct[416].group_number='0018'x & struct[416].element_number='1470'x & struct[416].vr='DS' & struct[416].vm='1' & struct[416].version='dicom98' & struct[416].name='TomoAngle' struct[417].group_number='0018'x & struct[417].element_number='1480'x & struct[417].vr='DS' & struct[417].vm='1' & struct[417].version='dicom98' & struct[417].name='TomoTime' struct[418].group_number='0018'x & struct[418].element_number='1490'x & struct[418].vr='CS' & struct[418].vm='1' & struct[418].version='dicom99' & struct[418].name='TomoType' struct[419].group_number='0018'x & struct[419].element_number='1491'x & struct[419].vr='CS' & struct[419].vm='1' & struct[419].version='dicom99' & struct[419].name='TomoClass' struct[420].group_number='0018'x & struct[420].element_number='1495'x & struct[420].vr='IS' & struct[420].vm='1' & struct[420].version='dicom99' & struct[420].name='NumberOfTomosynthesisSourceImages' struct[421].group_number='0018'x & struct[421].element_number='1500'x & struct[421].vr='CS' & struct[421].vm='1' & struct[421].version='dicom98' & struct[421].name='PositionerMotion' struct[422].group_number='0018'x & struct[422].element_number='1508'x & struct[422].vr='CS' & struct[422].vm='1' & struct[422].version='dicom99' & struct[422].name='PositionerType' struct[423].group_number='0018'x & struct[423].element_number='1510'x & struct[423].vr='DS' & struct[423].vm='1' & struct[423].version='dicom98' & struct[423].name='PositionerPrimaryAngle' struct[424].group_number='0018'x & struct[424].element_number='1511'x & struct[424].vr='DS' & struct[424].vm='1' & struct[424].version='dicom98' & struct[424].name='PositionerSecondaryAngle' struct[425].group_number='0018'x & struct[425].element_number='1520'x & struct[425].vr='DS' & struct[425].vm='1-n' & struct[425].version='dicom98' & struct[425].name='PositionerPrimaryAngleIncrement' struct[426].group_number='0018'x & struct[426].element_number='1521'x & struct[426].vr='DS' & struct[426].vm='1-n' & struct[426].version='dicom98' & struct[426].name='PositionerSecondaryAngleIncrement' struct[427].group_number='0018'x & struct[427].element_number='1530'x & struct[427].vr='DS' & struct[427].vm='1' & struct[427].version='dicom98' & struct[427].name='DetectorPrimaryAngle' struct[428].group_number='0018'x & struct[428].element_number='1531'x & struct[428].vr='DS' & struct[428].vm='1' & struct[428].version='dicom98' & struct[428].name='DetectorSecondaryAngle' struct[430].group_number='0018'x & struct[430].element_number='1600'x & struct[430].vr='CS' & struct[430].vm='1-3' & struct[430].version='dicom98' & struct[430].name='ShutterShape' struct[431].group_number='0018'x & struct[431].element_number='1602'x & struct[431].vr='IS' & struct[431].vm='1' & struct[431].version='dicom98' & struct[431].name='ShutterLeftVerticalEdge' struct[432].group_number='0018'x & struct[432].element_number='1604'x & struct[432].vr='IS' & struct[432].vm='1' & struct[432].version='dicom98' & struct[432].name='ShutterRightVerticalEdge' struct[433].group_number='0018'x & struct[433].element_number='1606'x & struct[433].vr='IS' & struct[433].vm='1' & struct[433].version='dicom98' & struct[433].name='ShutterUpperHorizontalEdge' struct[434].group_number='0018'x & struct[434].element_number='1608'x & struct[434].vr='IS' & struct[434].vm='1' & struct[434].version='dicom98' & struct[434].name='ShutterLowerHorizontalEdge' struct[435].group_number='0018'x & struct[435].element_number='1610'x & struct[435].vr='IS' & struct[435].vm='2' & struct[435].version='dicom98' & struct[435].name='CenterOfCircularShutter' struct[436].group_number='0018'x & struct[436].element_number='1612'x & struct[436].vr='IS' & struct[436].vm='1' & struct[436].version='dicom98' & struct[436].name='RadiusOfCircularShutter' struct[437].group_number='0018'x & struct[437].element_number='1620'x & struct[437].vr='IS' & struct[437].vm='2-2n' & struct[437].version='dicom98' & struct[437].name='VerticesOfThePolygonalShutter' struct[438].group_number='0018'x & struct[438].element_number='1622'x & struct[438].vr='US' & struct[438].vm='1' & struct[438].version='dicom2000' & struct[438].name='ShutterPresentationValue' struct[439].group_number='0018'x & struct[439].element_number='1623'x & struct[439].vr='US' & struct[439].vm='1' & struct[439].version='dicom2000' & struct[439].name='ShutterOverlayGroup' struct[440].group_number='0018'x & struct[440].element_number='1700'x & struct[440].vr='CS' & struct[440].vm='1-3' & struct[440].version='dicom98' & struct[440].name='CollimatorShape' struct[441].group_number='0018'x & struct[441].element_number='1702'x & struct[441].vr='IS' & struct[441].vm='1' & struct[441].version='dicom98' & struct[441].name='CollimatorLeftVerticalEdge' struct[442].group_number='0018'x & struct[442].element_number='1704'x & struct[442].vr='IS' & struct[442].vm='1' & struct[442].version='dicom98' & struct[442].name='CollimatorRightVerticalEdge' struct[443].group_number='0018'x & struct[443].element_number='1706'x & struct[443].vr='IS' & struct[443].vm='1' & struct[443].version='dicom98' & struct[443].name='CollimatorUpperHorizontalEdge' struct[444].group_number='0018'x & struct[444].element_number='1708'x & struct[444].vr='IS' & struct[444].vm='1' & struct[444].version='dicom98' & struct[444].name='CollimatorLowerHorizontalEdge' struct[445].group_number='0018'x & struct[445].element_number='1710'x & struct[445].vr='IS' & struct[445].vm='2' & struct[445].version='dicom98' & struct[445].name='CenterOfCircularCollimator' struct[446].group_number='0018'x & struct[446].element_number='1712'x & struct[446].vr='IS' & struct[446].vm='1' & struct[446].version='dicom98' & struct[446].name='RadiusOfCircularCollimator' struct[447].group_number='0018'x & struct[447].element_number='1720'x & struct[447].vr='IS' & struct[447].vm='2-2n' & struct[447].version='dicom98' & struct[447].name='VerticesOfThePolygonalCollimator' struct[448].group_number='0018'x & struct[448].element_number='1800'x & struct[448].vr='CS' & struct[448].vm='1' & struct[448].version='dicom2000' & struct[448].name='AcquisitionTimeSynchronized' struct[449].group_number='0018'x & struct[449].element_number='1801'x & struct[449].vr='SH' & struct[449].vm='1' & struct[449].version='dicom2000' & struct[449].name='TimeSource' struct[450].group_number='0018'x & struct[450].element_number='1802'x & struct[450].vr='CS' & struct[450].vm='1' & struct[450].version='dicom2000' & struct[450].name='TimeDistributionProtocol' struct[451].group_number='0018'x & struct[451].element_number='2001'x & struct[451].vr='IS' & struct[451].vm='1-n' & struct[451].version='dicom2001' & struct[451].name='PageNumberVector' struct[452].group_number='0018'x & struct[452].element_number='2002'x & struct[452].vr='SH' & struct[452].vm='1-n' & struct[452].version='dicom2001' & struct[452].name='FrameLabelVector' struct[453].group_number='0018'x & struct[453].element_number='2003'x & struct[453].vr='DS' & struct[453].vm='1-n' & struct[453].version='dicom2001' & struct[453].name='FramePrimaryAngleVector' struct[454].group_number='0018'x & struct[454].element_number='2004'x & struct[454].vr='DS' & struct[454].vm='1-n' & struct[454].version='dicom2001' & struct[454].name='FrameSecondaryAngleVector' struct[455].group_number='0018'x & struct[455].element_number='2005'x & struct[455].vr='DS' & struct[455].vm='1-n' & struct[455].version='dicom2001' & struct[455].name='SliceLocationVector' struct[456].group_number='0018'x & struct[456].element_number='2006'x & struct[456].vr='SH' & struct[456].vm='1-n' & struct[456].version='dicom2001' & struct[456].name='DisplayWindowLabelVector' struct[457].group_number='0018'x & struct[457].element_number='2010'x & struct[457].vr='DS' & struct[457].vm='2' & struct[457].version='dicom2001' & struct[457].name='NominalScannedPixelSpacing' struct[458].group_number='0018'x & struct[458].element_number='2020'x & struct[458].vr='CS' & struct[458].vm='1' & struct[458].version='dicom2001' & struct[458].name='DigitizingDeviceTransportDirection' struct[459].group_number='0018'x & struct[459].element_number='2030'x & struct[459].vr='DS' & struct[459].vm='1' & struct[459].version='dicom2001' & struct[459].name='RotationOfScannedFilm' struct[460].group_number='0018'x & struct[460].element_number='3100'x & struct[460].vr='CS' & struct[460].vm='1' & struct[460].version='dicom2001' & struct[460].name='IVUSAcquisition' struct[461].group_number='0018'x & struct[461].element_number='3101'x & struct[461].vr='DS' & struct[461].vm='1' & struct[461].version='dicom2001' & struct[461].name='IVUSPullbackRate' struct[462].group_number='0018'x & struct[462].element_number='3102'x & struct[462].vr='DS' & struct[462].vm='1' & struct[462].version='dicom2001' & struct[462].name='IVUSGatedRate' struct[463].group_number='0018'x & struct[463].element_number='3103'x & struct[463].vr='IS' & struct[463].vm='1' & struct[463].version='dicom2001' & struct[463].name='IVUSPullbackStartFrameNumber' struct[464].group_number='0018'x & struct[464].element_number='3104'x & struct[464].vr='IS' & struct[464].vm='1' & struct[464].version='dicom2001' & struct[464].name='IVUSPullbackStopFrameNumber' struct[465].group_number='0018'x & struct[465].element_number='3105'x & struct[465].vr='IS' & struct[465].vm='1-n' & struct[465].version='dicom2001' & struct[465].name='LesionNumber' struct[466].group_number='0018'x & struct[466].element_number='5000'x & struct[466].vr='SH' & struct[466].vm='1-n' & struct[466].version='dicom98' & struct[466].name='OutputPower' struct[467].group_number='0018'x & struct[467].element_number='5010'x & struct[467].vr='LO' & struct[467].vm='3' & struct[467].version='dicom98' & struct[467].name='TransducerData' struct[468].group_number='0018'x & struct[468].element_number='5012'x & struct[468].vr='DS' & struct[468].vm='1' & struct[468].version='dicom98' & struct[468].name='FocusDepth' struct[469].group_number='0018'x & struct[469].element_number='5020'x & struct[469].vr='LO' & struct[469].vm='1' & struct[469].version='dicom98' & struct[469].name='ProcessingFunction' struct[470].group_number='0018'x & struct[470].element_number='5021'x & struct[470].vr='LO' & struct[470].vm='1' & struct[470].version='dicom98' & struct[470].name='PostprocessingFunction' struct[471].group_number='0018'x & struct[471].element_number='5022'x & struct[471].vr='DS' & struct[471].vm='1' & struct[471].version='dicom98' & struct[471].name='MechanicalIndex' struct[472].group_number='0018'x & struct[472].element_number='5024'x & struct[472].vr='DS' & struct[472].vm='1' & struct[472].version='dicom98' & struct[472].name='BoneThermalIndex' struct[473].group_number='0018'x & struct[473].element_number='5026'x & struct[473].vr='DS' & struct[473].vm='1' & struct[473].version='dicom98' & struct[473].name='CranialThermalIndex' struct[474].group_number='0018'x & struct[474].element_number='5027'x & struct[474].vr='DS' & struct[474].vm='1' & struct[474].version='dicom98' & struct[474].name='SoftTissueThermalIndex' struct[475].group_number='0018'x & struct[475].element_number='5028'x & struct[475].vr='DS' & struct[475].vm='1' & struct[475].version='dicom98' & struct[475].name='SoftTissueFocusThermalIndex' struct[476].group_number='0018'x & struct[476].element_number='5029'x & struct[476].vr='DS' & struct[476].vm='1' & struct[476].version='dicom98' & struct[476].name='SoftTissueSurfaceThermalIndex' struct[477].group_number='0018'x & struct[477].element_number='5050'x & struct[477].vr='IS' & struct[477].vm='1' & struct[477].version='dicom98' & struct[477].name='DepthOfScanField' struct[478].group_number='0018'x & struct[478].element_number='5100'x & struct[478].vr='CS' & struct[478].vm='1' & struct[478].version='dicom98' & struct[478].name='PatientPosition' struct[479].group_number='0018'x & struct[479].element_number='5101'x & struct[479].vr='CS' & struct[479].vm='1' & struct[479].version='dicom98' & struct[479].name='ViewPosition' struct[480].group_number='0018'x & struct[480].element_number='5104'x & struct[480].vr='SQ' & struct[480].vm='1' & struct[480].version='dicom99' & struct[480].name='ProjectionEponymousNameCodeSequence' struct[481].group_number='0018'x & struct[481].element_number='5210'x & struct[481].vr='DS' & struct[481].vm='6' & struct[481].version='dicom98' & struct[481].name='ImageTransformationMatrix' struct[482].group_number='0018'x & struct[482].element_number='5212'x & struct[482].vr='DS' & struct[482].vm='3' & struct[482].version='dicom98' & struct[482].name='ImageTranslationVector' struct[483].group_number='0018'x & struct[483].element_number='6000'x & struct[483].vr='DS' & struct[483].vm='1' & struct[483].version='dicom98' & struct[483].name='Sensitivity' struct[484].group_number='0018'x & struct[484].element_number='6011'x & struct[484].vr='SQ' & struct[484].vm='1' & struct[484].version='dicom98' & struct[484].name='SequenceOfUltrasoundRegions' struct[485].group_number='0018'x & struct[485].element_number='6012'x & struct[485].vr='US' & struct[485].vm='1' & struct[485].version='dicom98' & struct[485].name='RegionSpatialFormat' struct[486].group_number='0018'x & struct[486].element_number='6014'x & struct[486].vr='US' & struct[486].vm='1' & struct[486].version='dicom98' & struct[486].name='RegionDataType' struct[487].group_number='0018'x & struct[487].element_number='6016'x & struct[487].vr='UL' & struct[487].vm='1' & struct[487].version='dicom98' & struct[487].name='RegionFlags' struct[488].group_number='0018'x & struct[488].element_number='6018'x & struct[488].vr='UL' & struct[488].vm='1' & struct[488].version='dicom98' & struct[488].name='RegionLocationMinX0' struct[489].group_number='0018'x & struct[489].element_number='601A'x & struct[489].vr='UL' & struct[489].vm='1' & struct[489].version='dicom98' & struct[489].name='RegionLocationMinY0' struct[490].group_number='0018'x & struct[490].element_number='601C'x & struct[490].vr='UL' & struct[490].vm='1' & struct[490].version='dicom98' & struct[490].name='RegionLocationMaxX1' struct[491].group_number='0018'x & struct[491].element_number='601E'x & struct[491].vr='UL' & struct[491].vm='1' & struct[491].version='dicom98' & struct[491].name='RegionLocationMaxY1' struct[492].group_number='0018'x & struct[492].element_number='6020'x & struct[492].vr='SL' & struct[492].vm='1' & struct[492].version='dicom98' & struct[492].name='ReferencePixelX0' struct[493].group_number='0018'x & struct[493].element_number='6022'x & struct[493].vr='SL' & struct[493].vm='1' & struct[493].version='dicom98' & struct[493].name='ReferencePixelY0' struct[494].group_number='0018'x & struct[494].element_number='6024'x & struct[494].vr='US' & struct[494].vm='1' & struct[494].version='dicom98' & struct[494].name='PhysicalUnitsXDirection' struct[495].group_number='0018'x & struct[495].element_number='6026'x & struct[495].vr='US' & struct[495].vm='1' & struct[495].version='dicom98' & struct[495].name='PhysicalUnitsYDirection' struct[496].group_number='0018'x & struct[496].element_number='6028'x & struct[496].vr='FD' & struct[496].vm='1' & struct[496].version='dicom98' & struct[496].name='ReferencePixelPhysicalValueX' struct[497].group_number='0018'x & struct[497].element_number='602A'x & struct[497].vr='FD' & struct[497].vm='1' & struct[497].version='dicom98' & struct[497].name='ReferencePixelPhysicalValueY' struct[498].group_number='0018'x & struct[498].element_number='602C'x & struct[498].vr='FD' & struct[498].vm='1' & struct[498].version='dicom98' & struct[498].name='PhysicalDeltaX' struct[499].group_number='0018'x & struct[499].element_number='602E'x & struct[499].vr='FD' & struct[499].vm='1' & struct[499].version='dicom98' & struct[499].name='PhysicalDeltaY' struct[500].group_number='0018'x & struct[500].element_number='6030'x & struct[500].vr='UL' & struct[500].vm='1' & struct[500].version='dicom98' & struct[500].name='TransducerFrequency' struct[501].group_number='0018'x & struct[501].element_number='6031'x & struct[501].vr='CS' & struct[501].vm='1' & struct[501].version='dicom98' & struct[501].name='TransducerType' struct[502].group_number='0018'x & struct[502].element_number='6032'x & struct[502].vr='UL' & struct[502].vm='1' & struct[502].version='dicom98' & struct[502].name='PulseRepetitionFrequency' struct[503].group_number='0018'x & struct[503].element_number='6034'x & struct[503].vr='FD' & struct[503].vm='1' & struct[503].version='dicom98' & struct[503].name='DopplerCorrectionAngle' struct[504].group_number='0018'x & struct[504].element_number='6036'x & struct[504].vr='FD' & struct[504].vm='1' & struct[504].version='dicom98' & struct[504].name='SteeringAngle' struct[505].group_number='0018'x & struct[505].element_number='6038'x & struct[505].vr='UL' & struct[505].vm='1' & struct[505].version='dicom2003' & struct[505].name='RETIRED_DopplerSampleVolumeXPosition' struct[506].group_number='0018'x & struct[506].element_number='6039'x & struct[506].vr='SL' & struct[506].vm='1' & struct[506].version='dicom2003' & struct[506].name='DopplerSampleVolumeXPosition' struct[507].group_number='0018'x & struct[507].element_number='603A'x & struct[507].vr='UL' & struct[507].vm='1' & struct[507].version='dicom2003' & struct[507].name='RETIRED_DopplerSampleVolumeYPosition' struct[508].group_number='0018'x & struct[508].element_number='603B'x & struct[508].vr='SL' & struct[508].vm='1' & struct[508].version='dicom2003' & struct[508].name='DopplerSampleVolumeYPosition' struct[509].group_number='0018'x & struct[509].element_number='603C'x & struct[509].vr='UL' & struct[509].vm='1' & struct[509].version='dicom2003' & struct[509].name='RETIRED_TMLinePositionX0' struct[510].group_number='0018'x & struct[510].element_number='603D'x & struct[510].vr='SL' & struct[510].vm='1' & struct[510].version='dicom2003' & struct[510].name='TMLinePositionX0' struct[511].group_number='0018'x & struct[511].element_number='603E'x & struct[511].vr='UL' & struct[511].vm='1' & struct[511].version='dicom2003' & struct[511].name='RETIRED_TMLinePositionY0' struct[512].group_number='0018'x & struct[512].element_number='603F'x & struct[512].vr='SL' & struct[512].vm='1' & struct[512].version='dicom2003' & struct[512].name='TMLinePositionY0' struct[513].group_number='0018'x & struct[513].element_number='6040'x & struct[513].vr='UL' & struct[513].vm='1' & struct[513].version='dicom2003' & struct[513].name='RETIRED_TMLinePositionX1' struct[514].group_number='0018'x & struct[514].element_number='6041'x & struct[514].vr='SL' & struct[514].vm='1' & struct[514].version='dicom2003' & struct[514].name='TMLinePositionX1' struct[515].group_number='0018'x & struct[515].element_number='6042'x & struct[515].vr='UL' & struct[515].vm='1' & struct[515].version='dicom2003' & struct[515].name='RETIRED_TMLinePositionY1' struct[516].group_number='0018'x & struct[516].element_number='6043'x & struct[516].vr='SL' & struct[516].vm='1' & struct[516].version='dicom2003' & struct[516].name='TMLinePositionY1' struct[517].group_number='0018'x & struct[517].element_number='6044'x & struct[517].vr='US' & struct[517].vm='1' & struct[517].version='dicom98' & struct[517].name='PixelComponentOrganization' struct[518].group_number='0018'x & struct[518].element_number='6046'x & struct[518].vr='UL' & struct[518].vm='1' & struct[518].version='dicom98' & struct[518].name='PixelComponentMask' struct[519].group_number='0018'x & struct[519].element_number='6048'x & struct[519].vr='UL' & struct[519].vm='1' & struct[519].version='dicom98' & struct[519].name='PixelComponentRangeStart' struct[520].group_number='0018'x & struct[520].element_number='604A'x & struct[520].vr='UL' & struct[520].vm='1' & struct[520].version='dicom98' & struct[520].name='PixelComponentRangeStop' struct[521].group_number='0018'x & struct[521].element_number='604C'x & struct[521].vr='US' & struct[521].vm='1' & struct[521].version='dicom98' & struct[521].name='PixelComponentPhysicalUnits' struct[522].group_number='0018'x & struct[522].element_number='604E'x & struct[522].vr='US' & struct[522].vm='1' & struct[522].version='dicom98' & struct[522].name='PixelComponentDataType' struct[523].group_number='0018'x & struct[523].element_number='6050'x & struct[523].vr='UL' & struct[523].vm='1' & struct[523].version='dicom98' & struct[523].name='NumberOfTableBreakPoints' struct[524].group_number='0018'x & struct[524].element_number='6052'x & struct[524].vr='UL' & struct[524].vm='1-n' & struct[524].version='dicom98' & struct[524].name='TableOfXBreakPoints' struct[525].group_number='0018'x & struct[525].element_number='6054'x & struct[525].vr='FD' & struct[525].vm='1-n' & struct[525].version='dicom98' & struct[525].name='TableOfYBreakPoints' struct[526].group_number='0018'x & struct[526].element_number='6056'x & struct[526].vr='UL' & struct[526].vm='1' & struct[526].version='dicom98' & struct[526].name='NumberOfTableEntries' struct[527].group_number='0018'x & struct[527].element_number='6058'x & struct[527].vr='UL' & struct[527].vm='1-n' & struct[527].version='dicom98' & struct[527].name='TableOfPixelValues' struct[528].group_number='0018'x & struct[528].element_number='605A'x & struct[528].vr='FL' & struct[528].vm='1-n' & struct[528].version='dicom98' & struct[528].name='TableOfParameterValues' struct[529].group_number='0018'x & struct[529].element_number='7000'x & struct[529].vr='CS' & struct[529].vm='1' & struct[529].version='dicom99' & struct[529].name='DetectorConditionsNominalFlag' struct[530].group_number='0018'x & struct[530].element_number='7001'x & struct[530].vr='DS' & struct[530].vm='1' & struct[530].version='dicom99' & struct[530].name='DetectorTemperature' struct[531].group_number='0018'x & struct[531].element_number='7004'x & struct[531].vr='CS' & struct[531].vm='1' & struct[531].version='dicom99' & struct[531].name='DetectorType' struct[532].group_number='0018'x & struct[532].element_number='7005'x & struct[532].vr='CS' & struct[532].vm='1' & struct[532].version='dicom99' & struct[532].name='DetectorConfiguration' struct[533].group_number='0018'x & struct[533].element_number='7006'x & struct[533].vr='LT' & struct[533].vm='1' & struct[533].version='dicom99' & struct[533].name='DetectorDescription' struct[534].group_number='0018'x & struct[534].element_number='7008'x & struct[534].vr='LT' & struct[534].vm='1' & struct[534].version='dicom99' & struct[534].name='DetectorMode' struct[535].group_number='0018'x & struct[535].element_number='700A'x & struct[535].vr='SH' & struct[535].vm='1' & struct[535].version='dicom99' & struct[535].name='DetectorID' struct[536].group_number='0018'x & struct[536].element_number='700C'x & struct[536].vr='DA' & struct[536].vm='1' & struct[536].version='dicom99' & struct[536].name='DateOfLastDetectorCalibration' struct[537].group_number='0018'x & struct[537].element_number='700E'x & struct[537].vr='TM' & struct[537].vm='1' & struct[537].version='dicom99' & struct[537].name='TimeOfLastDetectorCalibration' struct[538].group_number='0018'x & struct[538].element_number='7010'x & struct[538].vr='IS' & struct[538].vm='1' & struct[538].version='dicom99' & struct[538].name='ExposuresOnDetectorSinceLastCalibration' struct[539].group_number='0018'x & struct[539].element_number='7011'x & struct[539].vr='IS' & struct[539].vm='1' & struct[539].version='dicom99' & struct[539].name='ExposuresOnDetectorSinceManufactured' struct[540].group_number='0018'x & struct[540].element_number='7012'x & struct[540].vr='DS' & struct[540].vm='1' & struct[540].version='dicom99' & struct[540].name='DetectorTimeSinceLastExposure' struct[541].group_number='0018'x & struct[541].element_number='7014'x & struct[541].vr='DS' & struct[541].vm='1' & struct[541].version='dicom99' & struct[541].name='DetectorActiveTime' struct[542].group_number='0018'x & struct[542].element_number='7016'x & struct[542].vr='DS' & struct[542].vm='1' & struct[542].version='dicom99' & struct[542].name='DetectorActivationOffsetFromExposure' struct[543].group_number='0018'x & struct[543].element_number='701A'x & struct[543].vr='DS' & struct[543].vm='2' & struct[543].version='dicom99' & struct[543].name='DetectorBinning' struct[544].group_number='0018'x & struct[544].element_number='7020'x & struct[544].vr='DS' & struct[544].vm='2' & struct[544].version='dicom99' & struct[544].name='DetectorElementPhysicalSize' struct[545].group_number='0018'x & struct[545].element_number='7022'x & struct[545].vr='DS' & struct[545].vm='2' & struct[545].version='dicom99' & struct[545].name='DetectorElementSpacing' struct[546].group_number='0018'x & struct[546].element_number='7024'x & struct[546].vr='CS' & struct[546].vm='1' & struct[546].version='dicom99' & struct[546].name='DetectorActiveShape' struct[547].group_number='0018'x & struct[547].element_number='7026'x & struct[547].vr='DS' & struct[547].vm='1-2' & struct[547].version='dicom99' & struct[547].name='DetectorActiveDimensions' struct[548].group_number='0018'x & struct[548].element_number='7028'x & struct[548].vr='DS' & struct[548].vm='2' & struct[548].version='dicom99' & struct[548].name='DetectorActiveOrigin' struct[549].group_number='0018'x & struct[549].element_number='7030'x & struct[549].vr='DS' & struct[549].vm='2' & struct[549].version='dicom99' & struct[549].name='FieldOfViewOrigin' struct[550].group_number='0018'x & struct[550].element_number='7032'x & struct[550].vr='DS' & struct[550].vm='1' & struct[550].version='dicom99' & struct[550].name='FieldOfViewRotation' struct[551].group_number='0018'x & struct[551].element_number='7034'x & struct[551].vr='CS' & struct[551].vm='1' & struct[551].version='dicom99' & struct[551].name='FieldOfViewHorizontalFlip' struct[552].group_number='0018'x & struct[552].element_number='7040'x & struct[552].vr='LT' & struct[552].vm='1' & struct[552].version='dicom99' & struct[552].name='GridAbsorbingMaterial' struct[553].group_number='0018'x & struct[553].element_number='7041'x & struct[553].vr='LT' & struct[553].vm='1' & struct[553].version='dicom99' & struct[553].name='GridSpacingMaterial' struct[554].group_number='0018'x & struct[554].element_number='7042'x & struct[554].vr='DS' & struct[554].vm='1' & struct[554].version='dicom99' & struct[554].name='GridThickness' struct[555].group_number='0018'x & struct[555].element_number='7044'x & struct[555].vr='DS' & struct[555].vm='1' & struct[555].version='dicom99' & struct[555].name='GridPitch' struct[556].group_number='0018'x & struct[556].element_number='7046'x & struct[556].vr='IS' & struct[556].vm='2' & struct[556].version='dicom99' & struct[556].name='GridAspectRatio' struct[557].group_number='0018'x & struct[557].element_number='7048'x & struct[557].vr='DS' & struct[557].vm='1' & struct[557].version='dicom99' & struct[557].name='GridPeriod' struct[558].group_number='0018'x & struct[558].element_number='704C'x & struct[558].vr='DS' & struct[558].vm='1' & struct[558].version='dicom99' & struct[558].name='GridFocalDistance' struct[560].group_number='0018'x & struct[560].element_number='7050'x & struct[560].vr='CS' & struct[560].vm='1-n' & struct[560].version='dicom2000' & struct[560].name='FilterMaterial' struct[561].group_number='0018'x & struct[561].element_number='7052'x & struct[561].vr='DS' & struct[561].vm='1-n' & struct[561].version='dicom99' & struct[561].name='FilterThicknessMinimum' struct[562].group_number='0018'x & struct[562].element_number='7054'x & struct[562].vr='DS' & struct[562].vm='1-n' & struct[562].version='dicom99' & struct[562].name='FilterThicknessMaximum' struct[563].group_number='0018'x & struct[563].element_number='7060'x & struct[563].vr='CS' & struct[563].vm='1' & struct[563].version='dicom99' & struct[563].name='ExposureControlMode' struct[564].group_number='0018'x & struct[564].element_number='7062'x & struct[564].vr='LT' & struct[564].vm='1' & struct[564].version='dicom99' & struct[564].name='ExposureControlModeDescription' struct[565].group_number='0018'x & struct[565].element_number='7064'x & struct[565].vr='CS' & struct[565].vm='1' & struct[565].version='dicom99' & struct[565].name='ExposureStatus' struct[566].group_number='0018'x & struct[566].element_number='7065'x & struct[566].vr='DS' & struct[566].vm='1' & struct[566].version='dicom99' & struct[566].name='PhototimerSetting' struct[567].group_number='0018'x & struct[567].element_number='8150'x & struct[567].vr='DS' & struct[567].vm='1' & struct[567].version='dicom2000' & struct[567].name='ExposureTimeInMicroS' struct[568].group_number='0018'x & struct[568].element_number='8151'x & struct[568].vr='DS' & struct[568].vm='1' & struct[568].version='dicom2000' & struct[568].name='XRayTubeCurrentInMicroA' struct[569].group_number='0018'x & struct[569].element_number='9004'x & struct[569].vr='CS' & struct[569].vm='1' & struct[569].version='dicom2003' & struct[569].name='ContentQualification' struct[570].group_number='0018'x & struct[570].element_number='9005'x & struct[570].vr='SH' & struct[570].vm='1' & struct[570].version='dicom2003' & struct[570].name='PulseSequenceName' struct[571].group_number='0018'x & struct[571].element_number='9006'x & struct[571].vr='SQ' & struct[571].vm='1' & struct[571].version='dicom2003' & struct[571].name='MRImagingModifierSequence' struct[572].group_number='0018'x & struct[572].element_number='9008'x & struct[572].vr='CS' & struct[572].vm='1' & struct[572].version='dicom2003' & struct[572].name='EchoPulseSequence' struct[573].group_number='0018'x & struct[573].element_number='9009'x & struct[573].vr='CS' & struct[573].vm='1' & struct[573].version='dicom2003' & struct[573].name='InversionRecovery' struct[574].group_number='0018'x & struct[574].element_number='9010'x & struct[574].vr='CS' & struct[574].vm='1' & struct[574].version='dicom2003' & struct[574].name='FlowCompensation' struct[575].group_number='0018'x & struct[575].element_number='9011'x & struct[575].vr='CS' & struct[575].vm='1' & struct[575].version='dicom2003' & struct[575].name='MultipleSpinEcho' struct[576].group_number='0018'x & struct[576].element_number='9012'x & struct[576].vr='CS' & struct[576].vm='1' & struct[576].version='dicom2003' & struct[576].name='MultiPlanarExcitation' struct[577].group_number='0018'x & struct[577].element_number='9014'x & struct[577].vr='CS' & struct[577].vm='1' & struct[577].version='dicom2003' & struct[577].name='PhaseContrast' struct[578].group_number='0018'x & struct[578].element_number='9015'x & struct[578].vr='CS' & struct[578].vm='1' & struct[578].version='dicom2003' & struct[578].name='TimeOfFlightContrast' struct[579].group_number='0018'x & struct[579].element_number='9016'x & struct[579].vr='CS' & struct[579].vm='1' & struct[579].version='dicom2003' & struct[579].name='Spoiling' struct[580].group_number='0018'x & struct[580].element_number='9017'x & struct[580].vr='CS' & struct[580].vm='1' & struct[580].version='dicom2003' & struct[580].name='SteadyStatePulseSequence' struct[581].group_number='0018'x & struct[581].element_number='9018'x & struct[581].vr='CS' & struct[581].vm='1' & struct[581].version='dicom2003' & struct[581].name='EchoPlanarPulseSequence' struct[582].group_number='0018'x & struct[582].element_number='9019'x & struct[582].vr='FD' & struct[582].vm='1' & struct[582].version='dicom2003' & struct[582].name='TagAngleFirstAxis' struct[583].group_number='0018'x & struct[583].element_number='9020'x & struct[583].vr='CS' & struct[583].vm='1' & struct[583].version='dicom2003' & struct[583].name='MagnetizationTransfer' struct[584].group_number='0018'x & struct[584].element_number='9021'x & struct[584].vr='CS' & struct[584].vm='1' & struct[584].version='dicom2003' & struct[584].name='T2Preparation' struct[585].group_number='0018'x & struct[585].element_number='9022'x & struct[585].vr='CS' & struct[585].vm='1' & struct[585].version='dicom2003' & struct[585].name='BloodSignalNulling' struct[586].group_number='0018'x & struct[586].element_number='9024'x & struct[586].vr='CS' & struct[586].vm='1' & struct[586].version='dicom2003' & struct[586].name='SaturationRecovery' struct[587].group_number='0018'x & struct[587].element_number='9025'x & struct[587].vr='CS' & struct[587].vm='1' & struct[587].version='dicom2003' & struct[587].name='SpectrallySelectedSuppression' struct[588].group_number='0018'x & struct[588].element_number='9026'x & struct[588].vr='CS' & struct[588].vm='1' & struct[588].version='dicom2003' & struct[588].name='SpectrallySelectedExcitation' struct[589].group_number='0018'x & struct[589].element_number='9027'x & struct[589].vr='CS' & struct[589].vm='1' & struct[589].version='dicom2003' & struct[589].name='SpatialPreSaturation' struct[590].group_number='0018'x & struct[590].element_number='9028'x & struct[590].vr='CS' & struct[590].vm='1' & struct[590].version='dicom2003' & struct[590].name='Tagging' struct[591].group_number='0018'x & struct[591].element_number='9029'x & struct[591].vr='CS' & struct[591].vm='1' & struct[591].version='dicom2003' & struct[591].name='OversamplingPhase' struct[592].group_number='0018'x & struct[592].element_number='9030'x & struct[592].vr='FD' & struct[592].vm='1' & struct[592].version='dicom2003' & struct[592].name='TagSpacingFirstDimension' struct[593].group_number='0018'x & struct[593].element_number='9032'x & struct[593].vr='CS' & struct[593].vm='1' & struct[593].version='dicom2003' & struct[593].name='GeometryOfKSpaceTraversal' struct[594].group_number='0018'x & struct[594].element_number='9033'x & struct[594].vr='CS' & struct[594].vm='1' & struct[594].version='dicom2003' & struct[594].name='SegmentedKSpaceTraversal' struct[595].group_number='0018'x & struct[595].element_number='9034'x & struct[595].vr='CS' & struct[595].vm='1' & struct[595].version='dicom2003' & struct[595].name='RectilinearPhaseEncodeReordering' struct[596].group_number='0018'x & struct[596].element_number='9035'x & struct[596].vr='FD' & struct[596].vm='1' & struct[596].version='dicom2003' & struct[596].name='TagThickness' struct[597].group_number='0018'x & struct[597].element_number='9036'x & struct[597].vr='CS' & struct[597].vm='1' & struct[597].version='dicom2003' & struct[597].name='PartialFourierDirection' struct[598].group_number='0018'x & struct[598].element_number='9037'x & struct[598].vr='CS' & struct[598].vm='1' & struct[598].version='dicom2003' & struct[598].name='CardiacSynchronizationTechnique' struct[599].group_number='0018'x & struct[599].element_number='9041'x & struct[599].vr='LO' & struct[599].vm='1' & struct[599].version='dicom2003' & struct[599].name='ReceiveCoilManufacturerName' struct[600].group_number='0018'x & struct[600].element_number='9042'x & struct[600].vr='SQ' & struct[600].vm='1' & struct[600].version='dicom2003' & struct[600].name='MRReceiveCoilSequence' struct[601].group_number='0018'x & struct[601].element_number='9043'x & struct[601].vr='CS' & struct[601].vm='1' & struct[601].version='dicom2003' & struct[601].name='ReceiveCoilType' struct[602].group_number='0018'x & struct[602].element_number='9044'x & struct[602].vr='CS' & struct[602].vm='1' & struct[602].version='dicom2003' & struct[602].name='QuadratureReceiveCoil' struct[603].group_number='0018'x & struct[603].element_number='9045'x & struct[603].vr='SQ' & struct[603].vm='1' & struct[603].version='dicom2003' & struct[603].name='MultiCoilDefinitionSequence' struct[604].group_number='0018'x & struct[604].element_number='9046'x & struct[604].vr='LO' & struct[604].vm='1' & struct[604].version='dicom2003' & struct[604].name='MultiCoilConfiguration' struct[605].group_number='0018'x & struct[605].element_number='9047'x & struct[605].vr='SH' & struct[605].vm='1' & struct[605].version='dicom2003' & struct[605].name='MultiCoilElementName' struct[606].group_number='0018'x & struct[606].element_number='9048'x & struct[606].vr='CS' & struct[606].vm='1' & struct[606].version='dicom2003' & struct[606].name='MultiCoilElementUsed' struct[607].group_number='0018'x & struct[607].element_number='9049'x & struct[607].vr='SQ' & struct[607].vm='1' & struct[607].version='dicom2003' & struct[607].name='MRTransmitCoilSequence' struct[608].group_number='0018'x & struct[608].element_number='9050'x & struct[608].vr='LO' & struct[608].vm='1' & struct[608].version='dicom2003' & struct[608].name='TransmitCoilManufacturerName' struct[609].group_number='0018'x & struct[609].element_number='9051'x & struct[609].vr='CS' & struct[609].vm='1' & struct[609].version='dicom2003' & struct[609].name='TransmitCoilType' struct[610].group_number='0018'x & struct[610].element_number='9052'x & struct[610].vr='FD' & struct[610].vm='1-2' & struct[610].version='dicom2003' & struct[610].name='SpectralWidth' struct[611].group_number='0018'x & struct[611].element_number='9053'x & struct[611].vr='FD' & struct[611].vm='1-2' & struct[611].version='dicom2003' & struct[611].name='ChemicalShiftReference' struct[612].group_number='0018'x & struct[612].element_number='9054'x & struct[612].vr='CS' & struct[612].vm='1' & struct[612].version='dicom2003' & struct[612].name='VolumeLocalizationTechnique' struct[613].group_number='0018'x & struct[613].element_number='9058'x & struct[613].vr='US' & struct[613].vm='1' & struct[613].version='dicom2003' & struct[613].name='MRAcquisitionFrequencyEncodingSteps' struct[614].group_number='0018'x & struct[614].element_number='9059'x & struct[614].vr='CS' & struct[614].vm='1' & struct[614].version='dicom2003' & struct[614].name='Decoupling' struct[615].group_number='0018'x & struct[615].element_number='9060'x & struct[615].vr='CS' & struct[615].vm='1-2' & struct[615].version='dicom2003' & struct[615].name='DecoupledNucleus' struct[616].group_number='0018'x & struct[616].element_number='9061'x & struct[616].vr='FD' & struct[616].vm='1-2' & struct[616].version='dicom2003' & struct[616].name='DecouplingFrequency' struct[617].group_number='0018'x & struct[617].element_number='9062'x & struct[617].vr='CS' & struct[617].vm='1' & struct[617].version='dicom2003' & struct[617].name='DecouplingMethod' struct[618].group_number='0018'x & struct[618].element_number='9063'x & struct[618].vr='FD' & struct[618].vm='1-2' & struct[618].version='dicom2003' & struct[618].name='DecouplingChemicalShiftReference' struct[619].group_number='0018'x & struct[619].element_number='9064'x & struct[619].vr='CS' & struct[619].vm='1' & struct[619].version='dicom2003' & struct[619].name='KSpaceFiltering' struct[620].group_number='0018'x & struct[620].element_number='9065'x & struct[620].vr='CS' & struct[620].vm='1-2' & struct[620].version='dicom2003' & struct[620].name='TimeDomainFiltering' struct[621].group_number='0018'x & struct[621].element_number='9066'x & struct[621].vr='US' & struct[621].vm='1-2' & struct[621].version='dicom2003' & struct[621].name='NumberOfZeroFills' struct[622].group_number='0018'x & struct[622].element_number='9067'x & struct[622].vr='CS' & struct[622].vm='1' & struct[622].version='dicom2003' & struct[622].name='BaselineCorrection' struct[623].group_number='0018'x & struct[623].element_number='9069'x & struct[623].vr='FD' & struct[623].vm='1' & struct[623].version='dicom2003' & struct[623].name='ParallelReductionFactorInPlane' struct[624].group_number='0018'x & struct[624].element_number='9070'x & struct[624].vr='FD' & struct[624].vm='1' & struct[624].version='dicom2003' & struct[624].name='CardiacRRIntervalSpecified' struct[625].group_number='0018'x & struct[625].element_number='9073'x & struct[625].vr='FD' & struct[625].vm='1' & struct[625].version='dicom2003' & struct[625].name='AcquisitionDuration' struct[626].group_number='0018'x & struct[626].element_number='9074'x & struct[626].vr='DT' & struct[626].vm='1' & struct[626].version='dicom2003' & struct[626].name='FrameAcquisitionDatetime' struct[627].group_number='0018'x & struct[627].element_number='9075'x & struct[627].vr='CS' & struct[627].vm='1' & struct[627].version='dicom2003' & struct[627].name='DiffusionDirectionality' struct[628].group_number='0018'x & struct[628].element_number='9076'x & struct[628].vr='SQ' & struct[628].vm='1' & struct[628].version='dicom2003' & struct[628].name='DiffusionGradientDirectionSequence' struct[629].group_number='0018'x & struct[629].element_number='9077'x & struct[629].vr='CS' & struct[629].vm='1' & struct[629].version='dicom2003' & struct[629].name='ParallelAcquisition' struct[630].group_number='0018'x & struct[630].element_number='9078'x & struct[630].vr='CS' & struct[630].vm='1' & struct[630].version='dicom2003' & struct[630].name='ParallelAcquisitionTechnique' struct[631].group_number='0018'x & struct[631].element_number='9079'x & struct[631].vr='FD' & struct[631].vm='1-n' & struct[631].version='dicom2003' & struct[631].name='InversionTimes' struct[632].group_number='0018'x & struct[632].element_number='9080'x & struct[632].vr='ST' & struct[632].vm='1' & struct[632].version='dicom2003' & struct[632].name='MetaboliteMapDescription' struct[633].group_number='0018'x & struct[633].element_number='9081'x & struct[633].vr='CS' & struct[633].vm='1' & struct[633].version='dicom2003' & struct[633].name='PartialFourier' struct[634].group_number='0018'x & struct[634].element_number='9082'x & struct[634].vr='FD' & struct[634].vm='1' & struct[634].version='dicom2003' & struct[634].name='EffectiveEchoTime' struct[635].group_number='0018'x & struct[635].element_number='9084'x & struct[635].vr='SQ' & struct[635].vm='1' & struct[635].version='dicom2003' & struct[635].name='ChemicalShiftSequence' struct[636].group_number='0018'x & struct[636].element_number='9085'x & struct[636].vr='CS' & struct[636].vm='1' & struct[636].version='dicom2003' & struct[636].name='CardiacSignalSource' struct[637].group_number='0018'x & struct[637].element_number='9087'x & struct[637].vr='FD' & struct[637].vm='1' & struct[637].version='dicom2003' & struct[637].name='DiffusionBValue' struct[638].group_number='0018'x & struct[638].element_number='9089'x & struct[638].vr='FD' & struct[638].vm='3' & struct[638].version='dicom2003' & struct[638].name='DiffusionGradientOrientation' struct[639].group_number='0018'x & struct[639].element_number='9090'x & struct[639].vr='FD' & struct[639].vm='3' & struct[639].version='dicom2003' & struct[639].name='VelocityEncodingDirection' struct[640].group_number='0018'x & struct[640].element_number='9091'x & struct[640].vr='FD' & struct[640].vm='1' & struct[640].version='dicom2003' & struct[640].name='VelocityEncodingMinimumValue' struct[641].group_number='0018'x & struct[641].element_number='9093'x & struct[641].vr='US' & struct[641].vm='1' & struct[641].version='dicom2003' & struct[641].name='NumberOfKSpaceTrajectories' struct[642].group_number='0018'x & struct[642].element_number='9094'x & struct[642].vr='CS' & struct[642].vm='1' & struct[642].version='dicom2003' & struct[642].name='CoverageOfKSpace' struct[643].group_number='0018'x & struct[643].element_number='9095'x & struct[643].vr='UL' & struct[643].vm='1' & struct[643].version='dicom2003' & struct[643].name='SpectroscopyAcquisitionPhaseRows' struct[644].group_number='0018'x & struct[644].element_number='9096'x & struct[644].vr='FD' & struct[644].vm='1' & struct[644].version='dicom2003' & struct[644].name='RETIRED_ParallelReductionFactorInPlane' struct[645].group_number='0018'x & struct[645].element_number='9098'x & struct[645].vr='FD' & struct[645].vm='1-2' & struct[645].version='dicom2003' & struct[645].name='TransmitterFrequency' struct[646].group_number='0018'x & struct[646].element_number='9100'x & struct[646].vr='CS' & struct[646].vm='1-2' & struct[646].version='dicom2003' & struct[646].name='ResonantNucleus' struct[647].group_number='0018'x & struct[647].element_number='9101'x & struct[647].vr='CS' & struct[647].vm='1' & struct[647].version='dicom2003' & struct[647].name='FrequencyCorrection' struct[648].group_number='0018'x & struct[648].element_number='9103'x & struct[648].vr='SQ' & struct[648].vm='1' & struct[648].version='dicom2003' & struct[648].name='MRSpectroscopyFOVGeometrySequence' struct[649].group_number='0018'x & struct[649].element_number='9104'x & struct[649].vr='FD' & struct[649].vm='1' & struct[649].version='dicom2003' & struct[649].name='SlabThickness' struct[650].group_number='0018'x & struct[650].element_number='9105'x & struct[650].vr='FD' & struct[650].vm='3' & struct[650].version='dicom2003' & struct[650].name='SlabOrientation' struct[651].group_number='0018'x & struct[651].element_number='9106'x & struct[651].vr='FD' & struct[651].vm='3' & struct[651].version='dicom2003' & struct[651].name='MidSlabPosition' struct[652].group_number='0018'x & struct[652].element_number='9107'x & struct[652].vr='SQ' & struct[652].vm='1' & struct[652].version='dicom2003' & struct[652].name='MRSpatialSaturationSequence' struct[653].group_number='0018'x & struct[653].element_number='9112'x & struct[653].vr='SQ' & struct[653].vm='1' & struct[653].version='dicom2003' & struct[653].name='MRTimingAndRelatedParametersSequence' struct[654].group_number='0018'x & struct[654].element_number='9114'x & struct[654].vr='SQ' & struct[654].vm='1' & struct[654].version='dicom2003' & struct[654].name='MREchoSequence' struct[655].group_number='0018'x & struct[655].element_number='9115'x & struct[655].vr='SQ' & struct[655].vm='1' & struct[655].version='dicom2003' & struct[655].name='MRModifierSequence' struct[656].group_number='0018'x & struct[656].element_number='9117'x & struct[656].vr='SQ' & struct[656].vm='1' & struct[656].version='dicom2003' & struct[656].name='MRDiffusionSequence' struct[657].group_number='0018'x & struct[657].element_number='9118'x & struct[657].vr='SQ' & struct[657].vm='1' & struct[657].version='dicom2003' & struct[657].name='CardiacTriggerSequence' struct[658].group_number='0018'x & struct[658].element_number='9119'x & struct[658].vr='SQ' & struct[658].vm='1' & struct[658].version='dicom2003' & struct[658].name='MRAveragesSequence' struct[659].group_number='0018'x & struct[659].element_number='9125'x & struct[659].vr='SQ' & struct[659].vm='1' & struct[659].version='dicom2003' & struct[659].name='MRFOVGeometrySequence' struct[660].group_number='0018'x & struct[660].element_number='9126'x & struct[660].vr='SQ' & struct[660].vm='1' & struct[660].version='dicom2003' & struct[660].name='VolumeLocalizationSequence' struct[661].group_number='0018'x & struct[661].element_number='9127'x & struct[661].vr='UL' & struct[661].vm='1' & struct[661].version='dicom2003' & struct[661].name='SpectroscopyAcquisitionDataColumns' struct[662].group_number='0018'x & struct[662].element_number='9147'x & struct[662].vr='CS' & struct[662].vm='1' & struct[662].version='dicom2003' & struct[662].name='DiffusionAnisotropyType' struct[663].group_number='0018'x & struct[663].element_number='9151'x & struct[663].vr='DT' & struct[663].vm='1' & struct[663].version='dicom2003' & struct[663].name='FrameReferenceDatetime' struct[664].group_number='0018'x & struct[664].element_number='9152'x & struct[664].vr='SQ' & struct[664].vm='1' & struct[664].version='dicom2003' & struct[664].name='MRMetaboliteMapSequence' struct[665].group_number='0018'x & struct[665].element_number='9155'x & struct[665].vr='FD' & struct[665].vm='1' & struct[665].version='dicom2003' & struct[665].name='ParallelReductionFactorOutOfPlane' struct[666].group_number='0018'x & struct[666].element_number='9159'x & struct[666].vr='UL' & struct[666].vm='1' & struct[666].version='dicom2003' & struct[666].name='SpectroscopyAcquisitionOutOfPlanePhaseSteps' struct[667].group_number='0018'x & struct[667].element_number='9166'x & struct[667].vr='CS' & struct[667].vm='1' & struct[667].version='dicom2003' & struct[667].name='BulkMotionStatus' struct[668].group_number='0018'x & struct[668].element_number='9168'x & struct[668].vr='FD' & struct[668].vm='1' & struct[668].version='dicom2003' & struct[668].name='ParallelReductionFactorSecondInPlane' struct[669].group_number='0018'x & struct[669].element_number='9169'x & struct[669].vr='CS' & struct[669].vm='1' & struct[669].version='dicom2003' & struct[669].name='CardiacBeatRejectionTechnique' struct[670].group_number='0018'x & struct[670].element_number='9170'x & struct[670].vr='CS' & struct[670].vm='1' & struct[670].version='dicom2003' & struct[670].name='RespiratoryMotionCompensationTechnique' struct[671].group_number='0018'x & struct[671].element_number='9171'x & struct[671].vr='CS' & struct[671].vm='1' & struct[671].version='dicom2003' & struct[671].name='RespiratorySignalSource' struct[672].group_number='0018'x & struct[672].element_number='9172'x & struct[672].vr='CS' & struct[672].vm='1' & struct[672].version='dicom2003' & struct[672].name='BulkMotionCompensationTechnique' struct[673].group_number='0018'x & struct[673].element_number='9173'x & struct[673].vr='CS' & struct[673].vm='1' & struct[673].version='dicom2003' & struct[673].name='BulkMotionSignalSource' struct[674].group_number='0018'x & struct[674].element_number='9174'x & struct[674].vr='CS' & struct[674].vm='1' & struct[674].version='dicom2003' & struct[674].name='ApplicableSafetyStandardAgency' struct[675].group_number='0018'x & struct[675].element_number='9175'x & struct[675].vr='LO' & struct[675].vm='1' & struct[675].version='dicom2003' & struct[675].name='ApplicableSafetyStandardDescription' struct[676].group_number='0018'x & struct[676].element_number='9176'x & struct[676].vr='SQ' & struct[676].vm='1' & struct[676].version='dicom2003' & struct[676].name='OperatingModeSequence' struct[677].group_number='0018'x & struct[677].element_number='9177'x & struct[677].vr='CS' & struct[677].vm='1' & struct[677].version='dicom2003' & struct[677].name='OperatingModeType' struct[678].group_number='0018'x & struct[678].element_number='9178'x & struct[678].vr='CS' & struct[678].vm='1' & struct[678].version='dicom2003' & struct[678].name='OperationMode' struct[679].group_number='0018'x & struct[679].element_number='9179'x & struct[679].vr='CS' & struct[679].vm='1' & struct[679].version='dicom2003' & struct[679].name='SpecificAbsorptionRateDefinition' struct[680].group_number='0018'x & struct[680].element_number='9180'x & struct[680].vr='CS' & struct[680].vm='1' & struct[680].version='dicom2003' & struct[680].name='GradientOutputType' struct[681].group_number='0018'x & struct[681].element_number='9181'x & struct[681].vr='FD' & struct[681].vm='1' & struct[681].version='dicom2003' & struct[681].name='SpecificAbsorptionRateValue' struct[682].group_number='0018'x & struct[682].element_number='9182'x & struct[682].vr='FD' & struct[682].vm='1' & struct[682].version='dicom2003' & struct[682].name='GradientOutput' struct[683].group_number='0018'x & struct[683].element_number='9183'x & struct[683].vr='CS' & struct[683].vm='1' & struct[683].version='dicom2003' & struct[683].name='FlowCompensationDirection' struct[684].group_number='0018'x & struct[684].element_number='9184'x & struct[684].vr='FD' & struct[684].vm='1' & struct[684].version='dicom2003' & struct[684].name='TaggingDelay' struct[686].group_number='0018'x & struct[686].element_number='9195'x & struct[686].vr='FD' & struct[686].vm='1' & struct[686].version='dicom2003' & struct[686].name='RETIRED_ChemicalShiftsMinimumIntegrationLimitInHz' struct[688].group_number='0018'x & struct[688].element_number='9196'x & struct[688].vr='FD' & struct[688].vm='1' & struct[688].version='dicom2003' & struct[688].name='RETIRED_ChemicalShiftsMaximumIntegrationLimitInHz' struct[689].group_number='0018'x & struct[689].element_number='9197'x & struct[689].vr='SQ' & struct[689].vm='1' & struct[689].version='dicom2003' & struct[689].name='MRVelocityEncodingSequence' struct[690].group_number='0018'x & struct[690].element_number='9198'x & struct[690].vr='CS' & struct[690].vm='1' & struct[690].version='dicom2003' & struct[690].name='FirstOrderPhaseCorrection' struct[691].group_number='0018'x & struct[691].element_number='9199'x & struct[691].vr='CS' & struct[691].vm='1' & struct[691].version='dicom2003' & struct[691].name='WaterReferencedPhaseCorrection' struct[692].group_number='0018'x & struct[692].element_number='9200'x & struct[692].vr='CS' & struct[692].vm='1' & struct[692].version='dicom2003' & struct[692].name='MRSpectroscopyAcquisitionType' struct[693].group_number='0018'x & struct[693].element_number='9214'x & struct[693].vr='CS' & struct[693].vm='1' & struct[693].version='dicom2003' & struct[693].name='RespiratoryCyclePosition' struct[694].group_number='0018'x & struct[694].element_number='9217'x & struct[694].vr='FD' & struct[694].vm='1' & struct[694].version='dicom2003' & struct[694].name='VelocityEncodingMaximumValue' struct[695].group_number='0018'x & struct[695].element_number='9218'x & struct[695].vr='SS' & struct[695].vm='1' & struct[695].version='dicom2003' & struct[695].name='TagSpacingSecondDimension' struct[696].group_number='0018'x & struct[696].element_number='9219'x & struct[696].vr='SS' & struct[696].vm='1' & struct[696].version='dicom2003' & struct[696].name='TagAngleSecondAxis' struct[697].group_number='0018'x & struct[697].element_number='9220'x & struct[697].vr='FD' & struct[697].vm='1' & struct[697].version='dicom2003' & struct[697].name='FrameAcquisitionDuration' struct[698].group_number='0018'x & struct[698].element_number='9226'x & struct[698].vr='SQ' & struct[698].vm='1' & struct[698].version='dicom2003' & struct[698].name='MRImageFrameTypeSequence' struct[699].group_number='0018'x & struct[699].element_number='9227'x & struct[699].vr='SQ' & struct[699].vm='1' & struct[699].version='dicom2003' & struct[699].name='MRSpectroscopyFrameTypeSequence' struct[700].group_number='0018'x & struct[700].element_number='9231'x & struct[700].vr='US' & struct[700].vm='1' & struct[700].version='dicom2003' & struct[700].name='MRAcquisitionPhaseEncodingStepsInPlane' struct[701].group_number='0018'x & struct[701].element_number='9232'x & struct[701].vr='US' & struct[701].vm='1' & struct[701].version='dicom2003' & struct[701].name='MRAcquisitionPhaseEncodingStepsOutOfPlane' struct[702].group_number='0018'x & struct[702].element_number='9234'x & struct[702].vr='UL' & struct[702].vm='1' & struct[702].version='dicom2003' & struct[702].name='SpectroscopyAcquisitionPhaseColumns' struct[703].group_number='0018'x & struct[703].element_number='9236'x & struct[703].vr='CS' & struct[703].vm='1' & struct[703].version='dicom2003' & struct[703].name='CardiacCyclePosition' struct[704].group_number='0018'x & struct[704].element_number='9239'x & struct[704].vr='SQ' & struct[704].vm='1' & struct[704].version='dicom2003' & struct[704].name='SpecificAbsorptionRateSequence' struct[705].group_number='0018'x & struct[705].element_number='A001'x & struct[705].vr='SQ' & struct[705].vm='1' & struct[705].version='dicom2003' & struct[705].name='ContributingEquipmentSequence' struct[706].group_number='0018'x & struct[706].element_number='A002'x & struct[706].vr='DT' & struct[706].vm='1' & struct[706].version='dicom2003' & struct[706].name='ContributionDateTime' struct[707].group_number='0018'x & struct[707].element_number='A003'x & struct[707].vr='ST' & struct[707].vm='1' & struct[707].version='dicom2003' & struct[707].name='ContributionDescription' struct[708].group_number='0020'x & struct[708].element_number='0000'x & struct[708].vr='UL' & struct[708].vm='1' & struct[708].version='dicom98' & struct[708].name='ImageGroupLength' struct[709].group_number='0020'x & struct[709].element_number='000D'x & struct[709].vr='UI' & struct[709].vm='1' & struct[709].version='dicom98' & struct[709].name='StudyInstanceUID' struct[710].group_number='0020'x & struct[710].element_number='000E'x & struct[710].vr='UI' & struct[710].vm='1' & struct[710].version='dicom98' & struct[710].name='SeriesInstanceUID' struct[711].group_number='0020'x & struct[711].element_number='0010'x & struct[711].vr='SH' & struct[711].vm='1' & struct[711].version='dicom98' & struct[711].name='StudyID' struct[712].group_number='0020'x & struct[712].element_number='0011'x & struct[712].vr='IS' & struct[712].vm='1' & struct[712].version='dicom98' & struct[712].name='SeriesNumber' struct[713].group_number='0020'x & struct[713].element_number='0012'x & struct[713].vr='IS' & struct[713].vm='1' & struct[713].version='dicom98' & struct[713].name='AcquisitionNumber' struct[714].group_number='0020'x & struct[714].element_number='0013'x & struct[714].vr='IS' & struct[714].vm='1' & struct[714].version='dicom98' & struct[714].name='InstanceNumber' struct[715].group_number='0020'x & struct[715].element_number='0019'x & struct[715].vr='IS' & struct[715].vm='1' & struct[715].version='dicom99' & struct[715].name='ItemNumber' struct[716].group_number='0020'x & struct[716].element_number='0020'x & struct[716].vr='CS' & struct[716].vm='2' & struct[716].version='dicom98' & struct[716].name='PatientOrientation' struct[717].group_number='0020'x & struct[717].element_number='0022'x & struct[717].vr='IS' & struct[717].vm='1' & struct[717].version='dicom98' & struct[717].name='OverlayNumber' struct[718].group_number='0020'x & struct[718].element_number='0024'x & struct[718].vr='IS' & struct[718].vm='1' & struct[718].version='dicom98' & struct[718].name='CurveNumber' struct[719].group_number='0020'x & struct[719].element_number='0026'x & struct[719].vr='IS' & struct[719].vm='1' & struct[719].version='dicom98' & struct[719].name='LookupTableNumber' struct[720].group_number='0020'x & struct[720].element_number='0032'x & struct[720].vr='DS' & struct[720].vm='3' & struct[720].version='dicom98' & struct[720].name='ImagePositionPatient' struct[721].group_number='0020'x & struct[721].element_number='0037'x & struct[721].vr='DS' & struct[721].vm='6' & struct[721].version='dicom98' & struct[721].name='ImageOrientationPatient' struct[722].group_number='0020'x & struct[722].element_number='0052'x & struct[722].vr='UI' & struct[722].vm='1' & struct[722].version='dicom98' & struct[722].name='FrameOfReferenceUID' struct[723].group_number='0020'x & struct[723].element_number='0060'x & struct[723].vr='CS' & struct[723].vm='1' & struct[723].version='dicom98' & struct[723].name='Laterality' struct[724].group_number='0020'x & struct[724].element_number='0062'x & struct[724].vr='CS' & struct[724].vm='1' & struct[724].version='dicom99' & struct[724].name='ImageLaterality' struct[725].group_number='0020'x & struct[725].element_number='0100'x & struct[725].vr='IS' & struct[725].vm='1' & struct[725].version='dicom98' & struct[725].name='TemporalPositionIdentifier' struct[726].group_number='0020'x & struct[726].element_number='0105'x & struct[726].vr='IS' & struct[726].vm='1' & struct[726].version='dicom98' & struct[726].name='NumberOfTemporalPositions' struct[727].group_number='0020'x & struct[727].element_number='0110'x & struct[727].vr='DS' & struct[727].vm='1' & struct[727].version='dicom98' & struct[727].name='TemporalResolution' struct[728].group_number='0020'x & struct[728].element_number='0200'x & struct[728].vr='UI' & struct[728].vm='1' & struct[728].version='dicom2000' & struct[728].name='SynchronizationFrameOfReferenceUID' struct[729].group_number='0020'x & struct[729].element_number='1000'x & struct[729].vr='IS' & struct[729].vm='1' & struct[729].version='dicom98' & struct[729].name='SeriesInStudy' struct[730].group_number='0020'x & struct[730].element_number='1002'x & struct[730].vr='IS' & struct[730].vm='1' & struct[730].version='dicom98' & struct[730].name='ImagesInAcquisition' struct[731].group_number='0020'x & struct[731].element_number='1004'x & struct[731].vr='IS' & struct[731].vm='1' & struct[731].version='dicom98' & struct[731].name='AcquisitionsInStudy' struct[732].group_number='0020'x & struct[732].element_number='1040'x & struct[732].vr='LO' & struct[732].vm='1' & struct[732].version='dicom98' & struct[732].name='PositionReferenceIndicator' struct[733].group_number='0020'x & struct[733].element_number='1041'x & struct[733].vr='DS' & struct[733].vm='1' & struct[733].version='dicom98' & struct[733].name='SliceLocation' struct[734].group_number='0020'x & struct[734].element_number='1070'x & struct[734].vr='IS' & struct[734].vm='1-n' & struct[734].version='dicom98' & struct[734].name='OtherStudyNumbers' struct[735].group_number='0020'x & struct[735].element_number='1200'x & struct[735].vr='IS' & struct[735].vm='1' & struct[735].version='dicom98' & struct[735].name='NumberOfPatientRelatedStudies' struct[736].group_number='0020'x & struct[736].element_number='1202'x & struct[736].vr='IS' & struct[736].vm='1' & struct[736].version='dicom98' & struct[736].name='NumberOfPatientRelatedSeries' struct[737].group_number='0020'x & struct[737].element_number='1204'x & struct[737].vr='IS' & struct[737].vm='1' & struct[737].version='dicom98' & struct[737].name='NumberOfPatientRelatedInstances' struct[738].group_number='0020'x & struct[738].element_number='1206'x & struct[738].vr='IS' & struct[738].vm='1' & struct[738].version='dicom98' & struct[738].name='NumberOfStudyRelatedSeries' struct[739].group_number='0020'x & struct[739].element_number='1208'x & struct[739].vr='IS' & struct[739].vm='1' & struct[739].version='dicom98' & struct[739].name='NumberOfStudyRelatedInstances' struct[740].group_number='0020'x & struct[740].element_number='1209'x & struct[740].vr='IS' & struct[740].vm='1' & struct[740].version='dicom98' & struct[740].name='NumberOfSeriesRelatedInstances' struct[741].group_number='0020'x & struct[741].element_number='4000'x & struct[741].vr='LT' & struct[741].vm='1' & struct[741].version='dicom98' & struct[741].name='ImageComments' struct[742].group_number='0020'x & struct[742].element_number='9056'x & struct[742].vr='SH' & struct[742].vm='1' & struct[742].version='dicom2003' & struct[742].name='StackID' struct[743].group_number='0020'x & struct[743].element_number='9057'x & struct[743].vr='UL' & struct[743].vm='1' & struct[743].version='dicom2003' & struct[743].name='InStackPositionNumber' struct[744].group_number='0020'x & struct[744].element_number='9071'x & struct[744].vr='SQ' & struct[744].vm='1' & struct[744].version='dicom2003' & struct[744].name='FrameAnatomySequence' struct[745].group_number='0020'x & struct[745].element_number='9072'x & struct[745].vr='CS' & struct[745].vm='1' & struct[745].version='dicom2003' & struct[745].name='FrameLaterality' struct[746].group_number='0020'x & struct[746].element_number='9111'x & struct[746].vr='SQ' & struct[746].vm='1' & struct[746].version='dicom2003' & struct[746].name='FrameContentSequence' struct[747].group_number='0020'x & struct[747].element_number='9113'x & struct[747].vr='SQ' & struct[747].vm='1' & struct[747].version='dicom2003' & struct[747].name='PlanePositionSequence' struct[748].group_number='0020'x & struct[748].element_number='9116'x & struct[748].vr='SQ' & struct[748].vm='1' & struct[748].version='dicom2003' & struct[748].name='PlaneOrientationSequence' struct[749].group_number='0020'x & struct[749].element_number='9128'x & struct[749].vr='UL' & struct[749].vm='1' & struct[749].version='dicom2003' & struct[749].name='TemporalPositionIndex' struct[750].group_number='0020'x & struct[750].element_number='9153'x & struct[750].vr='FD' & struct[750].vm='1' & struct[750].version='dicom2003' & struct[750].name='TriggerDelayTime' struct[751].group_number='0020'x & struct[751].element_number='9156'x & struct[751].vr='US' & struct[751].vm='1' & struct[751].version='dicom2003' & struct[751].name='FrameAcquisitionNumber' struct[752].group_number='0020'x & struct[752].element_number='9157'x & struct[752].vr='UL' & struct[752].vm='1-n' & struct[752].version='dicom2003' & struct[752].name='DimensionIndexValues' struct[753].group_number='0020'x & struct[753].element_number='9158'x & struct[753].vr='LT' & struct[753].vm='1' & struct[753].version='dicom2003' & struct[753].name='FrameComments' struct[754].group_number='0020'x & struct[754].element_number='9161'x & struct[754].vr='UI' & struct[754].vm='1' & struct[754].version='dicom2003' & struct[754].name='ConcatenationUID' struct[755].group_number='0020'x & struct[755].element_number='9162'x & struct[755].vr='US' & struct[755].vm='1' & struct[755].version='dicom2003' & struct[755].name='InConcatenationNumber' struct[756].group_number='0020'x & struct[756].element_number='9163'x & struct[756].vr='US' & struct[756].vm='1' & struct[756].version='dicom2003' & struct[756].name='InConcatenationTotalNumber' struct[757].group_number='0020'x & struct[757].element_number='9164'x & struct[757].vr='UI' & struct[757].vm='1' & struct[757].version='dicom2003' & struct[757].name='DimensionOrganizationUID' struct[758].group_number='0020'x & struct[758].element_number='9165'x & struct[758].vr='AT' & struct[758].vm='1' & struct[758].version='dicom2003' & struct[758].name='DimensionIndexPointer' struct[759].group_number='0020'x & struct[759].element_number='9167'x & struct[759].vr='AT' & struct[759].vm='1' & struct[759].version='dicom2003' & struct[759].name='FunctionalGroupPointer' struct[760].group_number='0020'x & struct[760].element_number='9213'x & struct[760].vr='LO' & struct[760].vm='1' & struct[760].version='dicom2003' & struct[760].name='DimensionIndexPrivateCreator' struct[761].group_number='0020'x & struct[761].element_number='9221'x & struct[761].vr='SQ' & struct[761].vm='1' & struct[761].version='dicom2003' & struct[761].name='DimensionOrganizationSequence' struct[762].group_number='0020'x & struct[762].element_number='9222'x & struct[762].vr='SQ' & struct[762].vm='1' & struct[762].version='dicom2003' & struct[762].name='DimensionIndexSequence' struct[763].group_number='0020'x & struct[763].element_number='9228'x & struct[763].vr='UL' & struct[763].vm='1' & struct[763].version='dicom2003' & struct[763].name='ConcatenationFrameOffsetNumber' struct[764].group_number='0020'x & struct[764].element_number='9238'x & struct[764].vr='LO' & struct[764].vm='1' & struct[764].version='dicom2003' & struct[764].name='FunctionalGroupPrivateCreator' struct[765].group_number='0028'x & struct[765].element_number='0000'x & struct[765].vr='UL' & struct[765].vm='1' & struct[765].version='dicom98' & struct[765].name='ImagePresentationGroupLength' struct[766].group_number='0028'x & struct[766].element_number='0002'x & struct[766].vr='US' & struct[766].vm='1' & struct[766].version='dicom98' & struct[766].name='SamplesPerPixel' struct[767].group_number='0028'x & struct[767].element_number='0004'x & struct[767].vr='CS' & struct[767].vm='1' & struct[767].version='dicom98' & struct[767].name='PhotometricInterpretation' struct[768].group_number='0028'x & struct[768].element_number='0006'x & struct[768].vr='US' & struct[768].vm='1' & struct[768].version='dicom98' & struct[768].name='PlanarConfiguration' struct[769].group_number='0028'x & struct[769].element_number='0008'x & struct[769].vr='IS' & struct[769].vm='1' & struct[769].version='dicom98' & struct[769].name='NumberOfFrames' struct[771].group_number='0028'x & struct[771].element_number='0009'x & struct[771].vr='AT' & struct[771].vm='1-n' & struct[771].version='dicom98' & struct[771].name='FrameIncrementPointer' struct[772].group_number='0028'x & struct[772].element_number='0010'x & struct[772].vr='US' & struct[772].vm='1' & struct[772].version='dicom98' & struct[772].name='Rows' struct[773].group_number='0028'x & struct[773].element_number='0011'x & struct[773].vr='US' & struct[773].vm='1' & struct[773].version='dicom98' & struct[773].name='Columns' struct[774].group_number='0028'x & struct[774].element_number='0012'x & struct[774].vr='US' & struct[774].vm='1' & struct[774].version='dicom98' & struct[774].name='Planes' struct[775].group_number='0028'x & struct[775].element_number='0014'x & struct[775].vr='US' & struct[775].vm='1' & struct[775].version='dicom98' & struct[775].name='UltrasoundColorDataPresent' struct[776].group_number='0028'x & struct[776].element_number='0030'x & struct[776].vr='DS' & struct[776].vm='2' & struct[776].version='dicom98' & struct[776].name='PixelSpacing' struct[777].group_number='0028'x & struct[777].element_number='0031'x & struct[777].vr='DS' & struct[777].vm='2' & struct[777].version='dicom98' & struct[777].name='ZoomFactor' struct[778].group_number='0028'x & struct[778].element_number='0032'x & struct[778].vr='DS' & struct[778].vm='2' & struct[778].version='dicom98' & struct[778].name='ZoomCenter' struct[779].group_number='0028'x & struct[779].element_number='0034'x & struct[779].vr='IS' & struct[779].vm='2' & struct[779].version='dicom98' & struct[779].name='PixelAspectRatio' struct[781].group_number='0028'x & struct[781].element_number='0051'x & struct[781].vr='CS' & struct[781].vm='1-n' & struct[781].version='dicom98' & struct[781].name='CorrectedImage' struct[782].group_number='0028'x & struct[782].element_number='0100'x & struct[782].vr='US' & struct[782].vm='1' & struct[782].version='dicom98' & struct[782].name='BitsAllocated' struct[783].group_number='0028'x & struct[783].element_number='0101'x & struct[783].vr='US' & struct[783].vm='1' & struct[783].version='dicom98' & struct[783].name='BitsStored' struct[784].group_number='0028'x & struct[784].element_number='0102'x & struct[784].vr='US' & struct[784].vm='1' & struct[784].version='dicom98' & struct[784].name='HighBit' struct[785].group_number='0028'x & struct[785].element_number='0103'x & struct[785].vr='US' & struct[785].vm='1' & struct[785].version='dicom98' & struct[785].name='PixelRepresentation' struct[786].group_number='0028'x & struct[786].element_number='0106'x & struct[786].vr='xs' & struct[786].vm='1' & struct[786].version='dicom98' & struct[786].name='SmallestImagePixelValue' struct[787].group_number='0028'x & struct[787].element_number='0107'x & struct[787].vr='xs' & struct[787].vm='1' & struct[787].version='dicom98' & struct[787].name='LargestImagePixelValue' struct[788].group_number='0028'x & struct[788].element_number='0108'x & struct[788].vr='xs' & struct[788].vm='1' & struct[788].version='dicom98' & struct[788].name='SmallestPixelValueInSeries' struct[789].group_number='0028'x & struct[789].element_number='0109'x & struct[789].vr='xs' & struct[789].vm='1' & struct[789].version='dicom98' & struct[789].name='LargestPixelValueInSeries' struct[790].group_number='0028'x & struct[790].element_number='0110'x & struct[790].vr='xs' & struct[790].vm='1' & struct[790].version='dicom98' & struct[790].name='SmallestImagePixelValueInPlane' struct[791].group_number='0028'x & struct[791].element_number='0111'x & struct[791].vr='xs' & struct[791].vm='1' & struct[791].version='dicom98' & struct[791].name='LargestImagePixelValueInPlane' struct[792].group_number='0028'x & struct[792].element_number='0120'x & struct[792].vr='xs' & struct[792].vm='1' & struct[792].version='dicom98' & struct[792].name='PixelPaddingValue' struct[793].group_number='0028'x & struct[793].element_number='0300'x & struct[793].vr='CS' & struct[793].vm='1' & struct[793].version='dicom99' & struct[793].name='QualityControlImage' struct[794].group_number='0028'x & struct[794].element_number='0301'x & struct[794].vr='CS' & struct[794].vm='1' & struct[794].version='dicom99' & struct[794].name='BurnedInAnnotation' struct[795].group_number='0028'x & struct[795].element_number='1040'x & struct[795].vr='CS' & struct[795].vm='1' & struct[795].version='dicom98' & struct[795].name='PixelIntensityRelationship' struct[796].group_number='0028'x & struct[796].element_number='1041'x & struct[796].vr='SS' & struct[796].vm='1' & struct[796].version='dicom99' & struct[796].name='PixelIntensityRelationshipSign' struct[797].group_number='0028'x & struct[797].element_number='1050'x & struct[797].vr='DS' & struct[797].vm='1-n' & struct[797].version='dicom98' & struct[797].name='WindowCenter' struct[798].group_number='0028'x & struct[798].element_number='1051'x & struct[798].vr='DS' & struct[798].vm='1-n' & struct[798].version='dicom98' & struct[798].name='WindowWidth' struct[799].group_number='0028'x & struct[799].element_number='1052'x & struct[799].vr='DS' & struct[799].vm='1' & struct[799].version='dicom98' & struct[799].name='RescaleIntercept' struct[800].group_number='0028'x & struct[800].element_number='1053'x & struct[800].vr='DS' & struct[800].vm='1' & struct[800].version='dicom98' & struct[800].name='RescaleSlope' struct[801].group_number='0028'x & struct[801].element_number='1054'x & struct[801].vr='LO' & struct[801].vm='1' & struct[801].version='dicom98' & struct[801].name='RescaleType' struct[802].group_number='0028'x & struct[802].element_number='1055'x & struct[802].vr='LO' & struct[802].vm='1-n' & struct[802].version='dicom98' & struct[802].name='WindowCenterWidthExplanation' struct[803].group_number='0028'x & struct[803].element_number='1090'x & struct[803].vr='CS' & struct[803].vm='1' & struct[803].version='dicom98' & struct[803].name='RecommendedViewingMode' struct[804].group_number='0028'x & struct[804].element_number='1101'x & struct[804].vr='xs' & struct[804].vm='3' & struct[804].version='dicom98' & struct[804].name='RedPaletteColorLookupTableDescriptor' struct[805].group_number='0028'x & struct[805].element_number='1102'x & struct[805].vr='xs' & struct[805].vm='3' & struct[805].version='dicom98' & struct[805].name='GreenPaletteColorLookupTableDescriptor' struct[806].group_number='0028'x & struct[806].element_number='1103'x & struct[806].vr='xs' & struct[806].vm='3' & struct[806].version='dicom98' & struct[806].name='BluePaletteColorLookupTableDescriptor' struct[807].group_number='0028'x & struct[807].element_number='1199'x & struct[807].vr='UI' & struct[807].vm='1' & struct[807].version='dicom98' & struct[807].name='PaletteColorLookupTableUID' struct[808].group_number='0028'x & struct[808].element_number='1201'x & struct[808].vr='OW' & struct[808].vm='1' & struct[808].version='dicom98' & struct[808].name='RedPaletteColorLookupTableData' struct[809].group_number='0028'x & struct[809].element_number='1202'x & struct[809].vr='OW' & struct[809].vm='1' & struct[809].version='dicom98' & struct[809].name='GreenPaletteColorLookupTableData' struct[810].group_number='0028'x & struct[810].element_number='1203'x & struct[810].vr='OW' & struct[810].vm='1' & struct[810].version='dicom98' & struct[810].name='BluePaletteColorLookupTableData' struct[811].group_number='0028'x & struct[811].element_number='1221'x & struct[811].vr='OW' & struct[811].vm='1' & struct[811].version='dicom98' & struct[811].name='SegmentedRedPaletteColorLookupTableData' struct[812].group_number='0028'x & struct[812].element_number='1222'x & struct[812].vr='OW' & struct[812].vm='1' & struct[812].version='dicom98' & struct[812].name='SegmentedGreenPaletteColorLookupTableData' struct[813].group_number='0028'x & struct[813].element_number='1223'x & struct[813].vr='OW' & struct[813].vm='1' & struct[813].version='dicom98' & struct[813].name='SegmentedBluePaletteColorLookupTableData' struct[814].group_number='0028'x & struct[814].element_number='1300'x & struct[814].vr='CS' & struct[814].vm='1' & struct[814].version='dicom99' & struct[814].name='ImplantPresent' struct[815].group_number='0028'x & struct[815].element_number='1350'x & struct[815].vr='CS' & struct[815].vm='1' & struct[815].version='dicom2000' & struct[815].name='PartialView' struct[816].group_number='0028'x & struct[816].element_number='1351'x & struct[816].vr='ST' & struct[816].vm='1' & struct[816].version='dicom2000' & struct[816].name='PartialViewDescription' struct[817].group_number='0028'x & struct[817].element_number='2110'x & struct[817].vr='CS' & struct[817].vm='1' & struct[817].version='dicom98' & struct[817].name='LossyImageCompression' struct[818].group_number='0028'x & struct[818].element_number='2112'x & struct[818].vr='DS' & struct[818].vm='1-n' & struct[818].version='dicom99' & struct[818].name='LossyImageCompressionRatio' struct[819].group_number='0028'x & struct[819].element_number='3000'x & struct[819].vr='SQ' & struct[819].vm='1' & struct[819].version='dicom98' & struct[819].name='ModalityLUTSequence' struct[820].group_number='0028'x & struct[820].element_number='3002'x & struct[820].vr='xs' & struct[820].vm='3' & struct[820].version='dicom98' & struct[820].name='LUTDescriptor' struct[821].group_number='0028'x & struct[821].element_number='3003'x & struct[821].vr='LO' & struct[821].vm='1' & struct[821].version='dicom98' & struct[821].name='LUTExplanation' struct[822].group_number='0028'x & struct[822].element_number='3004'x & struct[822].vr='LO' & struct[822].vm='1' & struct[822].version='dicom98' & struct[822].name='ModalityLUTType' struct[823].group_number='0028'x & struct[823].element_number='3006'x & struct[823].vr='OW' & struct[823].vm='1-n' & struct[823].version='dicom2000' & struct[823].name='LUTData' struct[824].group_number='0028'x & struct[824].element_number='3010'x & struct[824].vr='SQ' & struct[824].vm='1' & struct[824].version='dicom98' & struct[824].name='VOILUTSequence' struct[825].group_number='0028'x & struct[825].element_number='3110'x & struct[825].vr='SQ' & struct[825].vm='1' & struct[825].version='dicom2000' & struct[825].name='SoftcopyVOILUTSequence' struct[826].group_number='0028'x & struct[826].element_number='5000'x & struct[826].vr='SQ' & struct[826].vm='1' & struct[826].version='dicom98' & struct[826].name='BiPlaneAcquisitionSequence' struct[827].group_number='0028'x & struct[827].element_number='6010'x & struct[827].vr='US' & struct[827].vm='1' & struct[827].version='dicom98' & struct[827].name='RepresentativeFrameNumber' struct[828].group_number='0028'x & struct[828].element_number='6020'x & struct[828].vr='US' & struct[828].vm='1-n' & struct[828].version='dicom98' & struct[828].name='FrameNumbersOfInterestFOI' struct[829].group_number='0028'x & struct[829].element_number='6022'x & struct[829].vr='LO' & struct[829].vm='1-n' & struct[829].version='dicom98' & struct[829].name='FramesOfInterestDescription' struct[830].group_number='0028'x & struct[830].element_number='6030'x & struct[830].vr='US' & struct[830].vm='1-n' & struct[830].version='dicom98' & struct[830].name='RETIRED_MaskPointers' struct[831].group_number='0028'x & struct[831].element_number='6040'x & struct[831].vr='US' & struct[831].vm='1-n' & struct[831].version='dicom98' & struct[831].name='RWavePointer' struct[832].group_number='0028'x & struct[832].element_number='6100'x & struct[832].vr='SQ' & struct[832].vm='1' & struct[832].version='dicom98' & struct[832].name='MaskSubtractionSequence' struct[833].group_number='0028'x & struct[833].element_number='6101'x & struct[833].vr='CS' & struct[833].vm='1' & struct[833].version='dicom98' & struct[833].name='MaskOperation' struct[834].group_number='0028'x & struct[834].element_number='6102'x & struct[834].vr='US' & struct[834].vm='2-2n' & struct[834].version='dicom98' & struct[834].name='ApplicableFrameRange' struct[835].group_number='0028'x & struct[835].element_number='6110'x & struct[835].vr='US' & struct[835].vm='1-n' & struct[835].version='dicom98' & struct[835].name='MaskFrameNumbers' struct[836].group_number='0028'x & struct[836].element_number='6112'x & struct[836].vr='US' & struct[836].vm='1' & struct[836].version='dicom98' & struct[836].name='ContrastFrameAveraging' struct[837].group_number='0028'x & struct[837].element_number='6114'x & struct[837].vr='FL' & struct[837].vm='2' & struct[837].version='dicom98' & struct[837].name='MaskSubPixelShift' struct[838].group_number='0028'x & struct[838].element_number='6120'x & struct[838].vr='SS' & struct[838].vm='1' & struct[838].version='dicom98' & struct[838].name='TIDOffset' struct[839].group_number='0028'x & struct[839].element_number='6190'x & struct[839].vr='ST' & struct[839].vm='1' & struct[839].version='dicom98' & struct[839].name='MaskOperationExplanation' struct[840].group_number='0028'x & struct[840].element_number='9001'x & struct[840].vr='UL' & struct[840].vm='1' & struct[840].version='dicom2003' & struct[840].name='DataPointRows' struct[841].group_number='0028'x & struct[841].element_number='9002'x & struct[841].vr='UL' & struct[841].vm='1' & struct[841].version='dicom2003' & struct[841].name='DataPointColumns' struct[842].group_number='0028'x & struct[842].element_number='9003'x & struct[842].vr='CS' & struct[842].vm='1-2' & struct[842].version='dicom2003' & struct[842].name='SignalDomainColumns' struct[843].group_number='0028'x & struct[843].element_number='9099'x & struct[843].vr='US' & struct[843].vm='1' & struct[843].version='dicom2003' & struct[843].name='LargestMonochromePixelValue' struct[844].group_number='0028'x & struct[844].element_number='9108'x & struct[844].vr='CS' & struct[844].vm='1' & struct[844].version='dicom2003' & struct[844].name='DataRepresentation' struct[845].group_number='0028'x & struct[845].element_number='9110'x & struct[845].vr='SQ' & struct[845].vm='1' & struct[845].version='dicom2003' & struct[845].name='PixelMeasuresSequence' struct[846].group_number='0028'x & struct[846].element_number='9132'x & struct[846].vr='SQ' & struct[846].vm='1' & struct[846].version='dicom2003' & struct[846].name='FrameVOILUTSequence' struct[847].group_number='0028'x & struct[847].element_number='9145'x & struct[847].vr='SQ' & struct[847].vm='1' & struct[847].version='dicom2003' & struct[847].name='PixelValueTransformationSequence' struct[848].group_number='0028'x & struct[848].element_number='9235'x & struct[848].vr='CS' & struct[848].vm='1' & struct[848].version='dicom2003' & struct[848].name='SignalDomainRows' struct[849].group_number='0032'x & struct[849].element_number='0000'x & struct[849].vr='UL' & struct[849].vm='1' & struct[849].version='dicom98' & struct[849].name='StudyGroupLength' struct[850].group_number='0032'x & struct[850].element_number='000A'x & struct[850].vr='CS' & struct[850].vm='1' & struct[850].version='dicom98' & struct[850].name='StudyStatusID' struct[851].group_number='0032'x & struct[851].element_number='000C'x & struct[851].vr='CS' & struct[851].vm='1' & struct[851].version='dicom98' & struct[851].name='StudyPriorityID' struct[852].group_number='0032'x & struct[852].element_number='0012'x & struct[852].vr='LO' & struct[852].vm='1' & struct[852].version='dicom98' & struct[852].name='StudyIDIssuer' struct[853].group_number='0032'x & struct[853].element_number='0032'x & struct[853].vr='DA' & struct[853].vm='1' & struct[853].version='dicom98' & struct[853].name='StudyVerifiedDate' struct[854].group_number='0032'x & struct[854].element_number='0033'x & struct[854].vr='TM' & struct[854].vm='1' & struct[854].version='dicom98' & struct[854].name='StudyVerifiedTime' struct[855].group_number='0032'x & struct[855].element_number='0034'x & struct[855].vr='DA' & struct[855].vm='1' & struct[855].version='dicom98' & struct[855].name='StudyReadDate' struct[856].group_number='0032'x & struct[856].element_number='0035'x & struct[856].vr='TM' & struct[856].vm='1' & struct[856].version='dicom98' & struct[856].name='StudyReadTime' struct[857].group_number='0032'x & struct[857].element_number='1000'x & struct[857].vr='DA' & struct[857].vm='1' & struct[857].version='dicom98' & struct[857].name='ScheduledStudyStartDate' struct[858].group_number='0032'x & struct[858].element_number='1001'x & struct[858].vr='TM' & struct[858].vm='1' & struct[858].version='dicom98' & struct[858].name='ScheduledStudyStartTime' struct[859].group_number='0032'x & struct[859].element_number='1010'x & struct[859].vr='DA' & struct[859].vm='1' & struct[859].version='dicom98' & struct[859].name='ScheduledStudyStopDate' struct[860].group_number='0032'x & struct[860].element_number='1011'x & struct[860].vr='TM' & struct[860].vm='1' & struct[860].version='dicom98' & struct[860].name='ScheduledStudyStopTime' struct[861].group_number='0032'x & struct[861].element_number='1020'x & struct[861].vr='LO' & struct[861].vm='1' & struct[861].version='dicom98' & struct[861].name='ScheduledStudyLocation' struct[862].group_number='0032'x & struct[862].element_number='1021'x & struct[862].vr='AE' & struct[862].vm='1-n' & struct[862].version='dicom98' & struct[862].name='ScheduledStudyLocationAETitles' struct[863].group_number='0032'x & struct[863].element_number='1030'x & struct[863].vr='LO' & struct[863].vm='1' & struct[863].version='dicom98' & struct[863].name='ReasonForStudy' struct[864].group_number='0032'x & struct[864].element_number='1031'x & struct[864].vr='SQ' & struct[864].vm='1' & struct[864].version='dicom2003' & struct[864].name='RequestingPhysicianIdentificationSequence' struct[865].group_number='0032'x & struct[865].element_number='1032'x & struct[865].vr='PN' & struct[865].vm='1' & struct[865].version='dicom98' & struct[865].name='RequestingPhysician' struct[866].group_number='0032'x & struct[866].element_number='1033'x & struct[866].vr='LO' & struct[866].vm='1' & struct[866].version='dicom98' & struct[866].name='RequestingService' struct[867].group_number='0032'x & struct[867].element_number='1040'x & struct[867].vr='DA' & struct[867].vm='1' & struct[867].version='dicom98' & struct[867].name='StudyArrivalDate' struct[868].group_number='0032'x & struct[868].element_number='1041'x & struct[868].vr='TM' & struct[868].vm='1' & struct[868].version='dicom98' & struct[868].name='StudyArrivalTime' struct[869].group_number='0032'x & struct[869].element_number='1050'x & struct[869].vr='DA' & struct[869].vm='1' & struct[869].version='dicom98' & struct[869].name='StudyCompletionDate' struct[870].group_number='0032'x & struct[870].element_number='1051'x & struct[870].vr='TM' & struct[870].vm='1' & struct[870].version='dicom98' & struct[870].name='StudyCompletionTime' struct[871].group_number='0032'x & struct[871].element_number='1055'x & struct[871].vr='CS' & struct[871].vm='1' & struct[871].version='dicom98' & struct[871].name='StudyComponentStatusID' struct[872].group_number='0032'x & struct[872].element_number='1060'x & struct[872].vr='LO' & struct[872].vm='1' & struct[872].version='dicom98' & struct[872].name='RequestedProcedureDescription' struct[873].group_number='0032'x & struct[873].element_number='1064'x & struct[873].vr='SQ' & struct[873].vm='1' & struct[873].version='dicom98' & struct[873].name='RequestedProcedureCodeSequence' struct[874].group_number='0032'x & struct[874].element_number='1070'x & struct[874].vr='LO' & struct[874].vm='1' & struct[874].version='dicom98' & struct[874].name='RequestedContrastAgent' struct[875].group_number='0032'x & struct[875].element_number='4000'x & struct[875].vr='LT' & struct[875].vm='1' & struct[875].version='dicom98' & struct[875].name='StudyComments' struct[876].group_number='0038'x & struct[876].element_number='0000'x & struct[876].vr='UL' & struct[876].vm='1' & struct[876].version='dicom98' & struct[876].name='VisitGroupLength' struct[877].group_number='0038'x & struct[877].element_number='0004'x & struct[877].vr='SQ' & struct[877].vm='1' & struct[877].version='dicom98' & struct[877].name='ReferencedPatientAliasSequence' struct[878].group_number='0038'x & struct[878].element_number='0008'x & struct[878].vr='CS' & struct[878].vm='1' & struct[878].version='dicom98' & struct[878].name='VisitStatusID' struct[879].group_number='0038'x & struct[879].element_number='0010'x & struct[879].vr='LO' & struct[879].vm='1' & struct[879].version='dicom98' & struct[879].name='AdmissionID' struct[880].group_number='0038'x & struct[880].element_number='0011'x & struct[880].vr='LO' & struct[880].vm='1' & struct[880].version='dicom98' & struct[880].name='IssuerOfAdmissionID' struct[881].group_number='0038'x & struct[881].element_number='0016'x & struct[881].vr='LO' & struct[881].vm='1' & struct[881].version='dicom98' & struct[881].name='RouteOfAdmissions' struct[882].group_number='0038'x & struct[882].element_number='001A'x & struct[882].vr='DA' & struct[882].vm='1' & struct[882].version='dicom98' & struct[882].name='ScheduledAdmissionDate' struct[883].group_number='0038'x & struct[883].element_number='001B'x & struct[883].vr='TM' & struct[883].vm='1' & struct[883].version='dicom98' & struct[883].name='ScheduledAdmissionTime' struct[884].group_number='0038'x & struct[884].element_number='001C'x & struct[884].vr='DA' & struct[884].vm='1' & struct[884].version='dicom98' & struct[884].name='ScheduledDischargeDate' struct[885].group_number='0038'x & struct[885].element_number='001D'x & struct[885].vr='TM' & struct[885].vm='1' & struct[885].version='dicom98' & struct[885].name='ScheduledDischargeTime' struct[886].group_number='0038'x & struct[886].element_number='001E'x & struct[886].vr='LO' & struct[886].vm='1' & struct[886].version='dicom98' & struct[886].name='ScheduledPatientInstitutionResidence' struct[887].group_number='0038'x & struct[887].element_number='0020'x & struct[887].vr='DA' & struct[887].vm='1' & struct[887].version='dicom98' & struct[887].name='AdmittingDate' struct[888].group_number='0038'x & struct[888].element_number='0021'x & struct[888].vr='TM' & struct[888].vm='1' & struct[888].version='dicom98' & struct[888].name='AdmittingTime' struct[889].group_number='0038'x & struct[889].element_number='0030'x & struct[889].vr='DA' & struct[889].vm='1' & struct[889].version='dicom98' & struct[889].name='DischargeDate' struct[890].group_number='0038'x & struct[890].element_number='0032'x & struct[890].vr='TM' & struct[890].vm='1' & struct[890].version='dicom98' & struct[890].name='DischargeTime' struct[891].group_number='0038'x & struct[891].element_number='0040'x & struct[891].vr='LO' & struct[891].vm='1' & struct[891].version='dicom98' & struct[891].name='DischargeDiagnosisDescription' struct[892].group_number='0038'x & struct[892].element_number='0044'x & struct[892].vr='SQ' & struct[892].vm='1' & struct[892].version='dicom98' & struct[892].name='DischargeDiagnosisCodeSequence' struct[893].group_number='0038'x & struct[893].element_number='0050'x & struct[893].vr='LO' & struct[893].vm='1' & struct[893].version='dicom98' & struct[893].name='SpecialNeeds' struct[894].group_number='0038'x & struct[894].element_number='0300'x & struct[894].vr='LO' & struct[894].vm='1' & struct[894].version='dicom98' & struct[894].name='CurrentPatientLocation' struct[895].group_number='0038'x & struct[895].element_number='0400'x & struct[895].vr='LO' & struct[895].vm='1' & struct[895].version='dicom98' & struct[895].name='PatientsInstitutionResidence' struct[896].group_number='0038'x & struct[896].element_number='0500'x & struct[896].vr='LO' & struct[896].vm='1' & struct[896].version='dicom98' & struct[896].name='PatientState' struct[897].group_number='0038'x & struct[897].element_number='4000'x & struct[897].vr='LT' & struct[897].vm='1' & struct[897].version='dicom98' & struct[897].name='VisitComments' struct[898].group_number='003A'x & struct[898].element_number='0004'x & struct[898].vr='CS' & struct[898].vm='1' & struct[898].version='dicom2000' & struct[898].name='WaveformOriginality' struct[899].group_number='003A'x & struct[899].element_number='0005'x & struct[899].vr='US' & struct[899].vm='1' & struct[899].version='dicom2000' & struct[899].name='NumberOfWaveformChannels' struct[900].group_number='003A'x & struct[900].element_number='0010'x & struct[900].vr='UL' & struct[900].vm='1' & struct[900].version='dicom2000' & struct[900].name='NumberOfWaveformSamples' struct[901].group_number='003A'x & struct[901].element_number='001A'x & struct[901].vr='DS' & struct[901].vm='1' & struct[901].version='dicom2000' & struct[901].name='SamplingFrequency' struct[902].group_number='003A'x & struct[902].element_number='0020'x & struct[902].vr='SH' & struct[902].vm='1' & struct[902].version='dicom2000' & struct[902].name='MultiplexGroupLabel' struct[903].group_number='003A'x & struct[903].element_number='0200'x & struct[903].vr='SQ' & struct[903].vm='1' & struct[903].version='dicom2000' & struct[903].name='ChannelDefinitionSequence' struct[904].group_number='003A'x & struct[904].element_number='0202'x & struct[904].vr='IS' & struct[904].vm='1' & struct[904].version='dicom2000' & struct[904].name='WaveformChannelNumber' struct[905].group_number='003A'x & struct[905].element_number='0203'x & struct[905].vr='SH' & struct[905].vm='1' & struct[905].version='dicom2000' & struct[905].name='ChannelLabel' struct[906].group_number='003A'x & struct[906].element_number='0205'x & struct[906].vr='CS' & struct[906].vm='1-n' & struct[906].version='dicom2000' & struct[906].name='ChannelStatus' struct[907].group_number='003A'x & struct[907].element_number='0208'x & struct[907].vr='SQ' & struct[907].vm='1' & struct[907].version='dicom2000' & struct[907].name='ChannelSourceSequence' struct[908].group_number='003A'x & struct[908].element_number='0209'x & struct[908].vr='SQ' & struct[908].vm='1' & struct[908].version='dicom2000' & struct[908].name='ChannelSourceModifiersSequence' struct[909].group_number='003A'x & struct[909].element_number='020A'x & struct[909].vr='SQ' & struct[909].vm='1' & struct[909].version='dicom2000' & struct[909].name='SourceWaveformSequence' struct[910].group_number='003A'x & struct[910].element_number='020C'x & struct[910].vr='LO' & struct[910].vm='1' & struct[910].version='dicom2000' & struct[910].name='ChannelDerivationDescription' struct[911].group_number='003A'x & struct[911].element_number='0210'x & struct[911].vr='DS' & struct[911].vm='1' & struct[911].version='dicom2000' & struct[911].name='ChannelSensitivity' struct[912].group_number='003A'x & struct[912].element_number='0211'x & struct[912].vr='SQ' & struct[912].vm='1' & struct[912].version='dicom2000' & struct[912].name='ChannelSensitivityUnitsSequence' struct[913].group_number='003A'x & struct[913].element_number='0212'x & struct[913].vr='DS' & struct[913].vm='1' & struct[913].version='dicom2000' & struct[913].name='ChannelSensitivityCorrectionFactor' struct[914].group_number='003A'x & struct[914].element_number='0213'x & struct[914].vr='DS' & struct[914].vm='1' & struct[914].version='dicom2000' & struct[914].name='ChannelBaseline' struct[915].group_number='003A'x & struct[915].element_number='0214'x & struct[915].vr='DS' & struct[915].vm='1' & struct[915].version='dicom2000' & struct[915].name='ChannelTimeSkew' struct[916].group_number='003A'x & struct[916].element_number='0215'x & struct[916].vr='DS' & struct[916].vm='1' & struct[916].version='dicom2000' & struct[916].name='ChannelSampleSkew' struct[917].group_number='003A'x & struct[917].element_number='0218'x & struct[917].vr='DS' & struct[917].vm='1' & struct[917].version='dicom2000' & struct[917].name='ChannelOffset' struct[918].group_number='003A'x & struct[918].element_number='021A'x & struct[918].vr='US' & struct[918].vm='1' & struct[918].version='dicom2000' & struct[918].name='WaveformBitsStored' struct[919].group_number='003A'x & struct[919].element_number='0220'x & struct[919].vr='DS' & struct[919].vm='1' & struct[919].version='dicom2000' & struct[919].name='FilterLowFrequency' struct[920].group_number='003A'x & struct[920].element_number='0221'x & struct[920].vr='DS' & struct[920].vm='1' & struct[920].version='dicom2000' & struct[920].name='FilterHighFrequency' struct[921].group_number='003A'x & struct[921].element_number='0222'x & struct[921].vr='DS' & struct[921].vm='1' & struct[921].version='dicom2000' & struct[921].name='NotchFilterFrequency' struct[922].group_number='003A'x & struct[922].element_number='0223'x & struct[922].vr='DS' & struct[922].vm='1' & struct[922].version='dicom2000' & struct[922].name='NotchFilterBandwidth' struct[923].group_number='0040'x & struct[923].element_number='0000'x & struct[923].vr='UL' & struct[923].vm='1' & struct[923].version='dicom98' & struct[923].name='ModalityWorklistGroupLength' struct[924].group_number='0040'x & struct[924].element_number='0001'x & struct[924].vr='AE' & struct[924].vm='1-n' & struct[924].version='dicom98' & struct[924].name='ScheduledStationAETitle' struct[925].group_number='0040'x & struct[925].element_number='0002'x & struct[925].vr='DA' & struct[925].vm='1' & struct[925].version='dicom98' & struct[925].name='ScheduledProcedureStepStartDate' struct[926].group_number='0040'x & struct[926].element_number='0003'x & struct[926].vr='TM' & struct[926].vm='1' & struct[926].version='dicom98' & struct[926].name='ScheduledProcedureStepStartTime' struct[927].group_number='0040'x & struct[927].element_number='0004'x & struct[927].vr='DA' & struct[927].vm='1' & struct[927].version='dicom98' & struct[927].name='ScheduledProcedureStepEndDate' struct[928].group_number='0040'x & struct[928].element_number='0005'x & struct[928].vr='TM' & struct[928].vm='1' & struct[928].version='dicom98' & struct[928].name='ScheduledProcedureStepEndTime' struct[929].group_number='0040'x & struct[929].element_number='0006'x & struct[929].vr='PN' & struct[929].vm='1' & struct[929].version='dicom98' & struct[929].name='ScheduledPerformingPhysiciansName' struct[930].group_number='0040'x & struct[930].element_number='0007'x & struct[930].vr='LO' & struct[930].vm='1' & struct[930].version='dicom98' & struct[930].name='ScheduledProcedureStepDescription' struct[931].group_number='0040'x & struct[931].element_number='0008'x & struct[931].vr='SQ' & struct[931].vm='1' & struct[931].version='dicom2001' & struct[931].name='ScheduledProtocolCodeSequence' struct[932].group_number='0040'x & struct[932].element_number='0009'x & struct[932].vr='SH' & struct[932].vm='1' & struct[932].version='dicom98' & struct[932].name='ScheduledProcedureStepID' struct[933].group_number='0040'x & struct[933].element_number='000A'x & struct[933].vr='SQ' & struct[933].vm='1' & struct[933].version='dicom2001' & struct[933].name='StageCodeSequence' struct[934].group_number='0040'x & struct[934].element_number='000B'x & struct[934].vr='SQ' & struct[934].vm='1' & struct[934].version='dicom2003' & struct[934].name='ScheduledPerformingPhysicianIdentificationSequence' struct[935].group_number='0040'x & struct[935].element_number='0010'x & struct[935].vr='SH' & struct[935].vm='1-n' & struct[935].version='dicom98' & struct[935].name='ScheduledStationName' struct[936].group_number='0040'x & struct[936].element_number='0011'x & struct[936].vr='SH' & struct[936].vm='1' & struct[936].version='dicom98' & struct[936].name='ScheduledProcedureStepLocation' struct[937].group_number='0040'x & struct[937].element_number='0012'x & struct[937].vr='LO' & struct[937].vm='1' & struct[937].version='dicom98' & struct[937].name='PreMedication' struct[938].group_number='0040'x & struct[938].element_number='0020'x & struct[938].vr='CS' & struct[938].vm='1' & struct[938].version='dicom98' & struct[938].name='ScheduledProcedureStepStatus' struct[939].group_number='0040'x & struct[939].element_number='0100'x & struct[939].vr='SQ' & struct[939].vm='1' & struct[939].version='dicom98' & struct[939].name='ScheduledProcedureStepSequence' struct[940].group_number='0040'x & struct[940].element_number='0220'x & struct[940].vr='SQ' & struct[940].vm='1' & struct[940].version='dicom2001' & struct[940].name='ReferencedNonImageCompositeSOPInstanceSequence' struct[941].group_number='0040'x & struct[941].element_number='0241'x & struct[941].vr='AE' & struct[941].vm='1' & struct[941].version='dicom98' & struct[941].name='PerformedStationAETitle' struct[942].group_number='0040'x & struct[942].element_number='0242'x & struct[942].vr='SH' & struct[942].vm='1' & struct[942].version='dicom98' & struct[942].name='PerformedStationName' struct[943].group_number='0040'x & struct[943].element_number='0243'x & struct[943].vr='SH' & struct[943].vm='1' & struct[943].version='dicom98' & struct[943].name='PerformedLocation' struct[944].group_number='0040'x & struct[944].element_number='0244'x & struct[944].vr='DA' & struct[944].vm='1' & struct[944].version='dicom98' & struct[944].name='PerformedProcedureStepStartDate' struct[945].group_number='0040'x & struct[945].element_number='0245'x & struct[945].vr='TM' & struct[945].vm='1' & struct[945].version='dicom98' & struct[945].name='PerformedProcedureStepStartTime' struct[946].group_number='0040'x & struct[946].element_number='0250'x & struct[946].vr='DA' & struct[946].vm='1' & struct[946].version='dicom98' & struct[946].name='PerformedProcedureStepEndDate' struct[947].group_number='0040'x & struct[947].element_number='0251'x & struct[947].vr='TM' & struct[947].vm='1' & struct[947].version='dicom98' & struct[947].name='PerformedProcedureStepEndTime' struct[948].group_number='0040'x & struct[948].element_number='0252'x & struct[948].vr='CS' & struct[948].vm='1' & struct[948].version='dicom98' & struct[948].name='PerformedProcedureStepStatus' struct[950].group_number='0040'x & struct[950].element_number='0253'x & struct[950].vr='SH' & struct[950].vm='1' & struct[950].version='dicom99' & struct[950].name='PerformedProcedureStepID' struct[951].group_number='0040'x & struct[951].element_number='0254'x & struct[951].vr='LO' & struct[951].vm='1' & struct[951].version='dicom98' & struct[951].name='PerformedProcedureStepDescription' struct[952].group_number='0040'x & struct[952].element_number='0255'x & struct[952].vr='LO' & struct[952].vm='1' & struct[952].version='dicom98' & struct[952].name='PerformedProcedureTypeDescription' struct[953].group_number='0040'x & struct[953].element_number='0260'x & struct[953].vr='SQ' & struct[953].vm='1' & struct[953].version='dicom2001' & struct[953].name='PerformedProtocolCodeSequence' struct[954].group_number='0040'x & struct[954].element_number='0270'x & struct[954].vr='SQ' & struct[954].vm='1' & struct[954].version='dicom98' & struct[954].name='ScheduledStepAttributesSequence' struct[955].group_number='0040'x & struct[955].element_number='0275'x & struct[955].vr='SQ' & struct[955].vm='1' & struct[955].version='dicom98' & struct[955].name='RequestAttributesSequence' struct[956].group_number='0040'x & struct[956].element_number='0280'x & struct[956].vr='ST' & struct[956].vm='1' & struct[956].version='dicom98' & struct[956].name='CommentsOnThePerformedProcedureStep' struct[957].group_number='0040'x & struct[957].element_number='0281'x & struct[957].vr='SQ' & struct[957].vm='1' & struct[957].version='dicom2003' & struct[957].name='PerformedProcedureStepDiscontinuationReasonCodeSequence' struct[958].group_number='0040'x & struct[958].element_number='0293'x & struct[958].vr='SQ' & struct[958].vm='1' & struct[958].version='dicom98' & struct[958].name='QuantitySequence' struct[959].group_number='0040'x & struct[959].element_number='0294'x & struct[959].vr='DS' & struct[959].vm='1' & struct[959].version='dicom98' & struct[959].name='Quantity' struct[960].group_number='0040'x & struct[960].element_number='0295'x & struct[960].vr='SQ' & struct[960].vm='1' & struct[960].version='dicom98' & struct[960].name='MeasuringUnitsSequence' struct[961].group_number='0040'x & struct[961].element_number='0296'x & struct[961].vr='SQ' & struct[961].vm='1' & struct[961].version='dicom98' & struct[961].name='BillingItemSequence' struct[962].group_number='0040'x & struct[962].element_number='0300'x & struct[962].vr='US' & struct[962].vm='1' & struct[962].version='dicom98' & struct[962].name='TotalTimeOfFluoroscopy' struct[963].group_number='0040'x & struct[963].element_number='0301'x & struct[963].vr='US' & struct[963].vm='1' & struct[963].version='dicom98' & struct[963].name='TotalNumberOfExposures' struct[964].group_number='0040'x & struct[964].element_number='0302'x & struct[964].vr='US' & struct[964].vm='1' & struct[964].version='dicom98' & struct[964].name='EntranceDose' struct[965].group_number='0040'x & struct[965].element_number='0303'x & struct[965].vr='US' & struct[965].vm='1-2' & struct[965].version='dicom98' & struct[965].name='ExposedArea' struct[966].group_number='0040'x & struct[966].element_number='0306'x & struct[966].vr='DS' & struct[966].vm='1' & struct[966].version='dicom98' & struct[966].name='DistanceSourceToEntrance' struct[967].group_number='0040'x & struct[967].element_number='0307'x & struct[967].vr='DS' & struct[967].vm='1' & struct[967].version='dicom99' & struct[967].name='RETIRED_DistanceSourceToSupport' struct[968].group_number='0040'x & struct[968].element_number='030E'x & struct[968].vr='SQ' & struct[968].vm='1' & struct[968].version='dicom2001' & struct[968].name='ExposureDoseSequence' struct[969].group_number='0040'x & struct[969].element_number='0310'x & struct[969].vr='ST' & struct[969].vm='1' & struct[969].version='dicom98' & struct[969].name='CommentsOnRadiationDose' struct[970].group_number='0040'x & struct[970].element_number='0312'x & struct[970].vr='DS' & struct[970].vm='1' & struct[970].version='dicom99' & struct[970].name='XRayOutput' struct[971].group_number='0040'x & struct[971].element_number='0314'x & struct[971].vr='DS' & struct[971].vm='1' & struct[971].version='dicom99' & struct[971].name='HalfValueLayer' struct[972].group_number='0040'x & struct[972].element_number='0316'x & struct[972].vr='DS' & struct[972].vm='1' & struct[972].version='dicom99' & struct[972].name='OrganDose' struct[973].group_number='0040'x & struct[973].element_number='0318'x & struct[973].vr='CS' & struct[973].vm='1' & struct[973].version='dicom99' & struct[973].name='OrganExposed' struct[974].group_number='0040'x & struct[974].element_number='0320'x & struct[974].vr='SQ' & struct[974].vm='1' & struct[974].version='dicom98' & struct[974].name='BillingProcedureStepSequence' struct[975].group_number='0040'x & struct[975].element_number='0321'x & struct[975].vr='SQ' & struct[975].vm='1' & struct[975].version='dicom98' & struct[975].name='FilmConsumptionSequence' struct[976].group_number='0040'x & struct[976].element_number='0324'x & struct[976].vr='SQ' & struct[976].vm='1' & struct[976].version='dicom98' & struct[976].name='BillingSuppliesAndDevicesSequence' struct[977].group_number='0040'x & struct[977].element_number='0330'x & struct[977].vr='SQ' & struct[977].vm='1' & struct[977].version='dicom98' & struct[977].name='RETIRED_ReferencedProcedureStepSequence' struct[978].group_number='0040'x & struct[978].element_number='0340'x & struct[978].vr='SQ' & struct[978].vm='1' & struct[978].version='dicom98' & struct[978].name='PerformedSeriesSequence' struct[979].group_number='0040'x & struct[979].element_number='0400'x & struct[979].vr='LT' & struct[979].vm='1' & struct[979].version='dicom98' & struct[979].name='CommentsOnTheScheduledProcedureStep' struct[980].group_number='0040'x & struct[980].element_number='050A'x & struct[980].vr='LO' & struct[980].vm='1' & struct[980].version='dicom2000' & struct[980].name='SpecimenAccessionNumber' struct[981].group_number='0040'x & struct[981].element_number='0550'x & struct[981].vr='SQ' & struct[981].vm='1' & struct[981].version='dicom2000' & struct[981].name='SpecimenSequence' struct[982].group_number='0040'x & struct[982].element_number='0551'x & struct[982].vr='LO' & struct[982].vm='1' & struct[982].version='dicom2000' & struct[982].name='SpecimenIdentifier' struct[983].group_number='0040'x & struct[983].element_number='0555'x & struct[983].vr='SQ' & struct[983].vm='1' & struct[983].version='dicom99' & struct[983].name='AcquisitionContextSequence' struct[984].group_number='0040'x & struct[984].element_number='0556'x & struct[984].vr='ST' & struct[984].vm='1' & struct[984].version='dicom99' & struct[984].name='AcquisitionContextDescription' struct[985].group_number='0040'x & struct[985].element_number='059A'x & struct[985].vr='SQ' & struct[985].vm='1' & struct[985].version='dicom2000' & struct[985].name='SpecimenTypeCodeSequence' struct[986].group_number='0040'x & struct[986].element_number='06FA'x & struct[986].vr='LO' & struct[986].vm='1' & struct[986].version='dicom99' & struct[986].name='SlideIdentifier' struct[987].group_number='0040'x & struct[987].element_number='071A'x & struct[987].vr='SQ' & struct[987].vm='1' & struct[987].version='dicom99' & struct[987].name='ImageCenterPointCoordinatesSequence' struct[988].group_number='0040'x & struct[988].element_number='072A'x & struct[988].vr='DS' & struct[988].vm='1' & struct[988].version='dicom99' & struct[988].name='XOffsetInSlideCoordinateSystem' struct[989].group_number='0040'x & struct[989].element_number='073A'x & struct[989].vr='DS' & struct[989].vm='1' & struct[989].version='dicom99' & struct[989].name='YOffsetInSlideCoordinateSystem' struct[990].group_number='0040'x & struct[990].element_number='074A'x & struct[990].vr='DS' & struct[990].vm='1' & struct[990].version='dicom99' & struct[990].name='ZOffsetInSlideCoordinateSystem' struct[991].group_number='0040'x & struct[991].element_number='08D8'x & struct[991].vr='SQ' & struct[991].vm='1' & struct[991].version='dicom99' & struct[991].name='PixelSpacingSequence' struct[992].group_number='0040'x & struct[992].element_number='08DA'x & struct[992].vr='SQ' & struct[992].vm='1' & struct[992].version='dicom99' & struct[992].name='CoordinateSystemAxisCodeSequence' struct[993].group_number='0040'x & struct[993].element_number='08EA'x & struct[993].vr='SQ' & struct[993].vm='1' & struct[993].version='dicom99' & struct[993].name='MeasurementUnitsCodeSequence' struct[994].group_number='0040'x & struct[994].element_number='1001'x & struct[994].vr='SH' & struct[994].vm='1' & struct[994].version='dicom98' & struct[994].name='RequestedProcedureID' struct[995].group_number='0040'x & struct[995].element_number='1002'x & struct[995].vr='LO' & struct[995].vm='1' & struct[995].version='dicom98' & struct[995].name='ReasonForTheRequestedProcedure' struct[996].group_number='0040'x & struct[996].element_number='1003'x & struct[996].vr='SH' & struct[996].vm='1' & struct[996].version='dicom98' & struct[996].name='RequestedProcedurePriority' struct[997].group_number='0040'x & struct[997].element_number='1004'x & struct[997].vr='LO' & struct[997].vm='1' & struct[997].version='dicom98' & struct[997].name='PatientTransportArrangements' struct[998].group_number='0040'x & struct[998].element_number='1005'x & struct[998].vr='LO' & struct[998].vm='1' & struct[998].version='dicom98' & struct[998].name='RequestedProcedureLocation' struct[999].group_number='0040'x & struct[999].element_number='1006'x & struct[999].vr='SH' & struct[999].vm='1' & struct[999].version='dicom98' & struct[999].name='PlacerOrderNumberProcedure' struct[1000].group_number='0040'x & struct[1000].element_number='1007'x & struct[1000].vr='SH' & struct[1000].vm='1' & struct[1000].version='dicom98' & struct[1000].name='FillerOrderNumberProcedure' struct[1001].group_number='0040'x & struct[1001].element_number='1008'x & struct[1001].vr='LO' & struct[1001].vm='1' & struct[1001].version='dicom98' & struct[1001].name='ConfidentialityCode' struct[1002].group_number='0040'x & struct[1002].element_number='1009'x & struct[1002].vr='SH' & struct[1002].vm='1' & struct[1002].version='dicom98' & struct[1002].name='ReportingPriority' struct[1003].group_number='0040'x & struct[1003].element_number='1010'x & struct[1003].vr='PN' & struct[1003].vm='1-n' & struct[1003].version='dicom98' & struct[1003].name='NamesOfIntendedRecipientsOfResults' struct[1004].group_number='0040'x & struct[1004].element_number='1011'x & struct[1004].vr='SQ' & struct[1004].vm='1' & struct[1004].version='dicom2003' & struct[1004].name='IntendedRecipientsOfResultsIdentificationSequence' struct[1005].group_number='0040'x & struct[1005].element_number='1101'x & struct[1005].vr='SQ' & struct[1005].vm='1' & struct[1005].version='dicom2003' & struct[1005].name='PersonIdentificationCodeSequence' struct[1006].group_number='0040'x & struct[1006].element_number='1102'x & struct[1006].vr='ST' & struct[1006].vm='1' & struct[1006].version='dicom2003' & struct[1006].name='PersonsAddress' struct[1007].group_number='0040'x & struct[1007].element_number='1103'x & struct[1007].vr='LO' & struct[1007].vm='1-n' & struct[1007].version='dicom2003' & struct[1007].name='PersonsTelephoneNumbers' struct[1008].group_number='0040'x & struct[1008].element_number='1400'x & struct[1008].vr='LT' & struct[1008].vm='1' & struct[1008].version='dicom98' & struct[1008].name='RequestedProcedureComments' struct[1009].group_number='0040'x & struct[1009].element_number='2001'x & struct[1009].vr='retired' & struct[1009].vm='CP' & struct[1009].version='409' & struct[1009].name='in' struct[1010].group_number='0040'x & struct[1010].element_number='2001'x & struct[1010].vr='LO' & struct[1010].vm='1' & struct[1010].version='dicom98' & struct[1010].name='RETIRED_ReasonForTheImagingServiceRequest' struct[1011].group_number='0040'x & struct[1011].element_number='2004'x & struct[1011].vr='DA' & struct[1011].vm='1' & struct[1011].version='dicom2001' & struct[1011].name='IssueDateOfImagingServiceRequest' struct[1012].group_number='0040'x & struct[1012].element_number='2005'x & struct[1012].vr='TM' & struct[1012].vm='1' & struct[1012].version='dicom2001' & struct[1012].name='IssueTimeOfImagingServiceRequest' struct[1013].group_number='0040'x & struct[1013].element_number='2006'x & struct[1013].vr='SH' & struct[1013].vm='1' & struct[1013].version='dicom98' & struct[1013].name='RETIRED_PlacerOrderNumberImagingServiceRequest' struct[1014].group_number='0040'x & struct[1014].element_number='2007'x & struct[1014].vr='SH' & struct[1014].vm='1' & struct[1014].version='dicom98' & struct[1014].name='RETIRED_FillerOrderNumberImagingServiceRequest' struct[1015].group_number='0040'x & struct[1015].element_number='2008'x & struct[1015].vr='PN' & struct[1015].vm='1' & struct[1015].version='dicom98' & struct[1015].name='OrderEnteredBy' struct[1016].group_number='0040'x & struct[1016].element_number='2009'x & struct[1016].vr='SH' & struct[1016].vm='1' & struct[1016].version='dicom98' & struct[1016].name='OrderEnterersLocation' struct[1017].group_number='0040'x & struct[1017].element_number='2010'x & struct[1017].vr='SH' & struct[1017].vm='1' & struct[1017].version='dicom98' & struct[1017].name='OrderCallbackPhoneNumber' struct[1018].group_number='0040'x & struct[1018].element_number='2016'x & struct[1018].vr='LO' & struct[1018].vm='1' & struct[1018].version='dicom99' & struct[1018].name='PlacerOrderNumberImagingServiceRequest' struct[1019].group_number='0040'x & struct[1019].element_number='2017'x & struct[1019].vr='LO' & struct[1019].vm='1' & struct[1019].version='dicom99' & struct[1019].name='FillerOrderNumberImagingServiceRequest' struct[1020].group_number='0040'x & struct[1020].element_number='2400'x & struct[1020].vr='LT' & struct[1020].vm='1' & struct[1020].version='dicom98' & struct[1020].name='ImagingServiceRequestComments' struct[1021].group_number='0040'x & struct[1021].element_number='3001'x & struct[1021].vr='LO' & struct[1021].vm='1' & struct[1021].version='dicom98' & struct[1021].name='ConfidentialityConstraintOnPatientDataDescription' struct[1022].group_number='0040'x & struct[1022].element_number='4001'x & struct[1022].vr='CS' & struct[1022].vm='1' & struct[1022].version='dicom2001' & struct[1022].name='GeneralPurposeScheduledProcedureStepStatus' struct[1023].group_number='0040'x & struct[1023].element_number='4002'x & struct[1023].vr='CS' & struct[1023].vm='1' & struct[1023].version='dicom2001' & struct[1023].name='GeneralPurposePerformedProcedureStepStatus' struct[1024].group_number='0040'x & struct[1024].element_number='4003'x & struct[1024].vr='CS' & struct[1024].vm='1' & struct[1024].version='dicom2001' & struct[1024].name='GeneralPurposeScheduledProcedureStepPriority' struct[1025].group_number='0040'x & struct[1025].element_number='4004'x & struct[1025].vr='SQ' & struct[1025].vm='1' & struct[1025].version='dicom2001' & struct[1025].name='ScheduledProcessingApplicationsCodeSequence' struct[1026].group_number='0040'x & struct[1026].element_number='4005'x & struct[1026].vr='DT' & struct[1026].vm='1' & struct[1026].version='dicom2001' & struct[1026].name='ScheduledProcedureStepStartDateAndTime' struct[1027].group_number='0040'x & struct[1027].element_number='4006'x & struct[1027].vr='CS' & struct[1027].vm='1' & struct[1027].version='dicom2001' & struct[1027].name='MultipleCopiesFlag' struct[1028].group_number='0040'x & struct[1028].element_number='4007'x & struct[1028].vr='SQ' & struct[1028].vm='1' & struct[1028].version='dicom2001' & struct[1028].name='PerformedProcessingApplicationsCodeSequence' struct[1029].group_number='0040'x & struct[1029].element_number='4009'x & struct[1029].vr='SQ' & struct[1029].vm='1' & struct[1029].version='dicom2001' & struct[1029].name='HumanPerformerCodeSequence' struct[1030].group_number='0040'x & struct[1030].element_number='4011'x & struct[1030].vr='DT' & struct[1030].vm='1' & struct[1030].version='dicom2001' & struct[1030].name='ExpectedCompletionDateAndTime' struct[1031].group_number='0040'x & struct[1031].element_number='4015'x & struct[1031].vr='SQ' & struct[1031].vm='1' & struct[1031].version='dicom2001' & struct[1031].name='ResultingGeneralPurposePerformedProcedureStepsSequence' struct[1032].group_number='0040'x & struct[1032].element_number='4016'x & struct[1032].vr='SQ' & struct[1032].vm='1' & struct[1032].version='dicom2001' & struct[1032].name='ReferencedGeneralPurposeScheduledProcedureStepSequence' struct[1033].group_number='0040'x & struct[1033].element_number='4018'x & struct[1033].vr='SQ' & struct[1033].vm='1' & struct[1033].version='dicom2001' & struct[1033].name='ScheduledWorkitemCodeSequence' struct[1034].group_number='0040'x & struct[1034].element_number='4019'x & struct[1034].vr='SQ' & struct[1034].vm='1' & struct[1034].version='dicom2001' & struct[1034].name='PerformedWorkitemCodeSequence' struct[1035].group_number='0040'x & struct[1035].element_number='4020'x & struct[1035].vr='CS' & struct[1035].vm='1' & struct[1035].version='dicom2001' & struct[1035].name='InputAvailabilityFlag' struct[1036].group_number='0040'x & struct[1036].element_number='4021'x & struct[1036].vr='SQ' & struct[1036].vm='1' & struct[1036].version='dicom2001' & struct[1036].name='InputInformationSequence' struct[1037].group_number='0040'x & struct[1037].element_number='4022'x & struct[1037].vr='SQ' & struct[1037].vm='1' & struct[1037].version='dicom2001' & struct[1037].name='RelevantInformationSequence' struct[1038].group_number='0040'x & struct[1038].element_number='4023'x & struct[1038].vr='UI' & struct[1038].vm='1' & struct[1038].version='dicom2001' & struct[1038].name='ReferencedGeneralPurposeScheduledProcedureStepTransactionUID' struct[1039].group_number='0040'x & struct[1039].element_number='4025'x & struct[1039].vr='SQ' & struct[1039].vm='1' & struct[1039].version='dicom2001' & struct[1039].name='ScheduledStationNameCodeSequence' struct[1040].group_number='0040'x & struct[1040].element_number='4026'x & struct[1040].vr='SQ' & struct[1040].vm='1' & struct[1040].version='dicom2001' & struct[1040].name='ScheduledStationClassCodeSequence' struct[1041].group_number='0040'x & struct[1041].element_number='4027'x & struct[1041].vr='SQ' & struct[1041].vm='1' & struct[1041].version='dicom2001' & struct[1041].name='ScheduledStationGeographicLocationCodeSequence' struct[1042].group_number='0040'x & struct[1042].element_number='4028'x & struct[1042].vr='SQ' & struct[1042].vm='1' & struct[1042].version='dicom2001' & struct[1042].name='PerformedStationNameCodeSequence' struct[1043].group_number='0040'x & struct[1043].element_number='4029'x & struct[1043].vr='SQ' & struct[1043].vm='1' & struct[1043].version='dicom2001' & struct[1043].name='PerformedStationClassCodeSequence' struct[1044].group_number='0040'x & struct[1044].element_number='4030'x & struct[1044].vr='SQ' & struct[1044].vm='1' & struct[1044].version='dicom2001' & struct[1044].name='PerformedStationGeographicLocationCodeSequence' struct[1045].group_number='0040'x & struct[1045].element_number='4031'x & struct[1045].vr='SQ' & struct[1045].vm='1' & struct[1045].version='dicom2001' & struct[1045].name='RequestedSubsequentWorkitemCodeSequence' struct[1046].group_number='0040'x & struct[1046].element_number='4032'x & struct[1046].vr='SQ' & struct[1046].vm='1' & struct[1046].version='dicom2001' & struct[1046].name='NonDICOMOutputCodeSequence' struct[1047].group_number='0040'x & struct[1047].element_number='4033'x & struct[1047].vr='SQ' & struct[1047].vm='1' & struct[1047].version='dicom2001' & struct[1047].name='OutputInformationSequence' struct[1048].group_number='0040'x & struct[1048].element_number='4034'x & struct[1048].vr='SQ' & struct[1048].vm='1' & struct[1048].version='dicom2001' & struct[1048].name='ScheduledHumanPerformersSequence' struct[1049].group_number='0040'x & struct[1049].element_number='4035'x & struct[1049].vr='SQ' & struct[1049].vm='1' & struct[1049].version='dicom2001' & struct[1049].name='ActualHumanPerformersSequence' struct[1050].group_number='0040'x & struct[1050].element_number='4036'x & struct[1050].vr='LO' & struct[1050].vm='1' & struct[1050].version='dicom2001' & struct[1050].name='HumanPerformersOrganization' struct[1051].group_number='0040'x & struct[1051].element_number='4037'x & struct[1051].vr='PN' & struct[1051].vm='1' & struct[1051].version='dicom2001' & struct[1051].name='HumanPerformersName' struct[1052].group_number='0040'x & struct[1052].element_number='8302'x & struct[1052].vr='DS' & struct[1052].vm='1' & struct[1052].version='dicom2000' & struct[1052].name='EntranceDoseInmGy' struct[1053].group_number='0040'x & struct[1053].element_number='9096'x & struct[1053].vr='SQ' & struct[1053].vm='1' & struct[1053].version='dicom2003' & struct[1053].name='RealWorldValueMappingSequence' struct[1054].group_number='0040'x & struct[1054].element_number='9210'x & struct[1054].vr='SS' & struct[1054].vm='1' & struct[1054].version='dicom2003' & struct[1054].name='LUTLabel' struct[1055].group_number='0040'x & struct[1055].element_number='9211'x & struct[1055].vr='xs' & struct[1055].vm='1' & struct[1055].version='dicom2003' & struct[1055].name='RealWorldValueLastValueMapped' struct[1056].group_number='0040'x & struct[1056].element_number='9212'x & struct[1056].vr='FD' & struct[1056].vm='1-n' & struct[1056].version='dicom2003' & struct[1056].name='RealWorldValueLUTData' struct[1057].group_number='0040'x & struct[1057].element_number='9216'x & struct[1057].vr='xs' & struct[1057].vm='1' & struct[1057].version='dicom2003' & struct[1057].name='RealWorldValueFirstValueMapped' struct[1058].group_number='0040'x & struct[1058].element_number='9224'x & struct[1058].vr='FD' & struct[1058].vm='1' & struct[1058].version='dicom2003' & struct[1058].name='RealWorldValueIntercept' struct[1059].group_number='0040'x & struct[1059].element_number='9225'x & struct[1059].vr='FD' & struct[1059].vm='1' & struct[1059].version='dicom2003' & struct[1059].name='RealWorldValueSlope' struct[1060].group_number='0040'x & struct[1060].element_number='A010'x & struct[1060].vr='CS' & struct[1060].vm='1' & struct[1060].version='dicom2000' & struct[1060].name='RelationshipType' struct[1061].group_number='0040'x & struct[1061].element_number='A027'x & struct[1061].vr='LO' & struct[1061].vm='1' & struct[1061].version='dicom2000' & struct[1061].name='VerifyingOrganization' struct[1062].group_number='0040'x & struct[1062].element_number='A030'x & struct[1062].vr='DT' & struct[1062].vm='1' & struct[1062].version='dicom2000' & struct[1062].name='VerificationDateTime' struct[1063].group_number='0040'x & struct[1063].element_number='A032'x & struct[1063].vr='DT' & struct[1063].vm='1' & struct[1063].version='dicom2000' & struct[1063].name='ObservationDateTime' struct[1064].group_number='0040'x & struct[1064].element_number='A040'x & struct[1064].vr='CS' & struct[1064].vm='1' & struct[1064].version='dicom2000' & struct[1064].name='ValueType' struct[1065].group_number='0040'x & struct[1065].element_number='A043'x & struct[1065].vr='SQ' & struct[1065].vm='1' & struct[1065].version='dicom99' & struct[1065].name='ConceptNameCodeSequence' struct[1066].group_number='0040'x & struct[1066].element_number='A050'x & struct[1066].vr='CS' & struct[1066].vm='1' & struct[1066].version='dicom2000' & struct[1066].name='ContinuityOfContent' struct[1067].group_number='0040'x & struct[1067].element_number='A073'x & struct[1067].vr='SQ' & struct[1067].vm='1' & struct[1067].version='dicom2000' & struct[1067].name='VerifyingObserverSequence' struct[1068].group_number='0040'x & struct[1068].element_number='A075'x & struct[1068].vr='PN' & struct[1068].vm='1' & struct[1068].version='dicom2000' & struct[1068].name='VerifyingObserverName' struct[1069].group_number='0040'x & struct[1069].element_number='A088'x & struct[1069].vr='SQ' & struct[1069].vm='1' & struct[1069].version='dicom2000' & struct[1069].name='VerifyingObserverIdentificationCodeSequence' struct[1070].group_number='0040'x & struct[1070].element_number='A0B0'x & struct[1070].vr='US' & struct[1070].vm='2-2n' & struct[1070].version='dicom2000' & struct[1070].name='ReferencedWaveformChannels' struct[1071].group_number='0040'x & struct[1071].element_number='A120'x & struct[1071].vr='DT' & struct[1071].vm='1' & struct[1071].version='dicom2000' & struct[1071].name='DateTime' struct[1072].group_number='0040'x & struct[1072].element_number='A121'x & struct[1072].vr='DA' & struct[1072].vm='1' & struct[1072].version='dicom99' & struct[1072].name='Date' struct[1073].group_number='0040'x & struct[1073].element_number='A122'x & struct[1073].vr='TM' & struct[1073].vm='1' & struct[1073].version='dicom99' & struct[1073].name='Time' struct[1074].group_number='0040'x & struct[1074].element_number='A123'x & struct[1074].vr='PN' & struct[1074].vm='1' & struct[1074].version='dicom99' & struct[1074].name='PersonName' struct[1075].group_number='0040'x & struct[1075].element_number='A124'x & struct[1075].vr='UI' & struct[1075].vm='1' & struct[1075].version='dicom2000' & struct[1075].name='UID' struct[1076].group_number='0040'x & struct[1076].element_number='A130'x & struct[1076].vr='CS' & struct[1076].vm='1' & struct[1076].version='dicom2000' & struct[1076].name='TemporalRangeType' struct[1077].group_number='0040'x & struct[1077].element_number='A132'x & struct[1077].vr='UL' & struct[1077].vm='1-n' & struct[1077].version='dicom2000' & struct[1077].name='ReferencedSamplePositions' struct[1078].group_number='0040'x & struct[1078].element_number='A136'x & struct[1078].vr='US' & struct[1078].vm='1-n' & struct[1078].version='dicom99' & struct[1078].name='ReferencedFrameNumbers' struct[1079].group_number='0040'x & struct[1079].element_number='A138'x & struct[1079].vr='DS' & struct[1079].vm='1-n' & struct[1079].version='dicom2000' & struct[1079].name='ReferencedTimeOffsets' struct[1080].group_number='0040'x & struct[1080].element_number='A13A'x & struct[1080].vr='DT' & struct[1080].vm='1-n' & struct[1080].version='dicom2000' & struct[1080].name='ReferencedDatetime' struct[1081].group_number='0040'x & struct[1081].element_number='A160'x & struct[1081].vr='UT' & struct[1081].vm='1' & struct[1081].version='dicom99' & struct[1081].name='TextValue' struct[1082].group_number='0040'x & struct[1082].element_number='A168'x & struct[1082].vr='SQ' & struct[1082].vm='1' & struct[1082].version='dicom99' & struct[1082].name='ConceptCodeSequence' struct[1083].group_number='0040'x & struct[1083].element_number='A170'x & struct[1083].vr='SQ' & struct[1083].vm='1' & struct[1083].version='dicom2001' & struct[1083].name='PurposeOfReferenceCodeSequence' struct[1084].group_number='0040'x & struct[1084].element_number='A180'x & struct[1084].vr='US' & struct[1084].vm='1' & struct[1084].version='dicom2000' & struct[1084].name='AnnotationGroupNumber' struct[1085].group_number='0040'x & struct[1085].element_number='A195'x & struct[1085].vr='SQ' & struct[1085].vm='1' & struct[1085].version='dicom2000' & struct[1085].name='ModifierCodeSequence' struct[1086].group_number='0040'x & struct[1086].element_number='A300'x & struct[1086].vr='SQ' & struct[1086].vm='1' & struct[1086].version='dicom2000' & struct[1086].name='MeasuredValueSequence' struct[1087].group_number='0040'x & struct[1087].element_number='A301'x & struct[1087].vr='SQ' & struct[1087].vm='1' & struct[1087].version='dicom2003' & struct[1087].name='NumericValueQualifierCodeSequence' struct[1088].group_number='0040'x & struct[1088].element_number='A30A'x & struct[1088].vr='DS' & struct[1088].vm='1-n' & struct[1088].version='dicom99' & struct[1088].name='NumericValue' struct[1089].group_number='0040'x & struct[1089].element_number='A360'x & struct[1089].vr='SQ' & struct[1089].vm='1' & struct[1089].version='dicom2000' & struct[1089].name='PredecessorDocumentsSequence' struct[1090].group_number='0040'x & struct[1090].element_number='A370'x & struct[1090].vr='SQ' & struct[1090].vm='1' & struct[1090].version='dicom2000' & struct[1090].name='ReferencedRequestSequence' struct[1091].group_number='0040'x & struct[1091].element_number='A372'x & struct[1091].vr='SQ' & struct[1091].vm='1' & struct[1091].version='dicom2000' & struct[1091].name='PerformedProcedureCodeSequence' struct[1092].group_number='0040'x & struct[1092].element_number='A375'x & struct[1092].vr='SQ' & struct[1092].vm='1' & struct[1092].version='dicom2000' & struct[1092].name='CurrentRequestedProcedureEvidenceSequence' struct[1093].group_number='0040'x & struct[1093].element_number='A385'x & struct[1093].vr='SQ' & struct[1093].vm='1' & struct[1093].version='dicom2000' & struct[1093].name='PertinentOtherEvidenceSequence' struct[1094].group_number='0040'x & struct[1094].element_number='A491'x & struct[1094].vr='CS' & struct[1094].vm='1' & struct[1094].version='dicom2000' & struct[1094].name='CompletionFlag' struct[1095].group_number='0040'x & struct[1095].element_number='A492'x & struct[1095].vr='LO' & struct[1095].vm='1' & struct[1095].version='dicom2000' & struct[1095].name='CompletionFlagDescription' struct[1096].group_number='0040'x & struct[1096].element_number='A493'x & struct[1096].vr='CS' & struct[1096].vm='1' & struct[1096].version='dicom2000' & struct[1096].name='VerificationFlag' struct[1097].group_number='0040'x & struct[1097].element_number='A504'x & struct[1097].vr='SQ' & struct[1097].vm='1' & struct[1097].version='dicom2000' & struct[1097].name='ContentTemplateSequence' struct[1098].group_number='0040'x & struct[1098].element_number='A525'x & struct[1098].vr='SQ' & struct[1098].vm='1' & struct[1098].version='dicom2000' & struct[1098].name='IdenticalDocumentsSequence' struct[1099].group_number='0040'x & struct[1099].element_number='A730'x & struct[1099].vr='SQ' & struct[1099].vm='1' & struct[1099].version='dicom2000' & struct[1099].name='ContentSequence' struct[1100].group_number='0040'x & struct[1100].element_number='B020'x & struct[1100].vr='SQ' & struct[1100].vm='1' & struct[1100].version='dicom2000' & struct[1100].name='AnnotationSequence' struct[1101].group_number='0040'x & struct[1101].element_number='DB00'x & struct[1101].vr='CS' & struct[1101].vm='1' & struct[1101].version='dicom2000' & struct[1101].name='TemplateIdentifier' struct[1102].group_number='0040'x & struct[1102].element_number='DB06'x & struct[1102].vr='DT' & struct[1102].vm='1' & struct[1102].version='dicom2003' & struct[1102].name='RETIRED_TemplateVersion' struct[1103].group_number='0040'x & struct[1103].element_number='DB07'x & struct[1103].vr='DT' & struct[1103].vm='1' & struct[1103].version='dicom2003' & struct[1103].name='RETIRED_TemplateLocalVersion' struct[1104].group_number='0040'x & struct[1104].element_number='DB0B'x & struct[1104].vr='CS' & struct[1104].vm='1' & struct[1104].version='dicom2003' & struct[1104].name='RETIRED_TemplateExtensionFlag' struct[1105].group_number='0040'x & struct[1105].element_number='DB0C'x & struct[1105].vr='UI' & struct[1105].vm='1' & struct[1105].version='dicom2003' & struct[1105].name='RETIRED_TemplateExtensionOrganizationUID' struct[1106].group_number='0040'x & struct[1106].element_number='DB0D'x & struct[1106].vr='UI' & struct[1106].vm='1' & struct[1106].version='dicom2003' & struct[1106].name='RETIRED_TemplateExtensionCreatorUID' struct[1107].group_number='0040'x & struct[1107].element_number='DB73'x & struct[1107].vr='UL' & struct[1107].vm='1-n' & struct[1107].version='dicom2000' & struct[1107].name='ReferencedContentItemIdentifier' struct[1108].group_number='0050'x & struct[1108].element_number='0000'x & struct[1108].vr='UL' & struct[1108].vm='1' & struct[1108].version='dicom98' & struct[1108].name='XRayAngioDeviceGroupLength' struct[1109].group_number='0050'x & struct[1109].element_number='0004'x & struct[1109].vr='was' & struct[1109].vm='in' & struct[1109].version='DICOM96' & struct[1109].name='CalibrationObject' struct[1110].group_number='0050'x & struct[1110].element_number='0004'x & struct[1110].vr='CS' & struct[1110].vm='1' & struct[1110].version='dicom98' & struct[1110].name='CalibrationImage' struct[1111].group_number='0050'x & struct[1111].element_number='0010'x & struct[1111].vr='SQ' & struct[1111].vm='1' & struct[1111].version='dicom98' & struct[1111].name='DeviceSequence' struct[1112].group_number='0050'x & struct[1112].element_number='0014'x & struct[1112].vr='DS' & struct[1112].vm='1' & struct[1112].version='dicom98' & struct[1112].name='DeviceLength' struct[1113].group_number='0050'x & struct[1113].element_number='0016'x & struct[1113].vr='DS' & struct[1113].vm='1' & struct[1113].version='dicom98' & struct[1113].name='DeviceDiameter' struct[1114].group_number='0050'x & struct[1114].element_number='0017'x & struct[1114].vr='CS' & struct[1114].vm='1' & struct[1114].version='dicom98' & struct[1114].name='DeviceDiameterUnits' struct[1115].group_number='0050'x & struct[1115].element_number='0018'x & struct[1115].vr='DS' & struct[1115].vm='1' & struct[1115].version='dicom98' & struct[1115].name='DeviceVolume' struct[1116].group_number='0050'x & struct[1116].element_number='0019'x & struct[1116].vr='DS' & struct[1116].vm='1' & struct[1116].version='dicom98' & struct[1116].name='InterMarkerDistance' struct[1117].group_number='0050'x & struct[1117].element_number='0020'x & struct[1117].vr='LO' & struct[1117].vm='1' & struct[1117].version='dicom98' & struct[1117].name='DeviceDescription' struct[1118].group_number='0054'x & struct[1118].element_number='0000'x & struct[1118].vr='UL' & struct[1118].vm='1' & struct[1118].version='dicom98' & struct[1118].name='NuclearMedicineGroupLength' struct[1119].group_number='0054'x & struct[1119].element_number='0010'x & struct[1119].vr='US' & struct[1119].vm='1-n' & struct[1119].version='dicom98' & struct[1119].name='EnergyWindowVector' struct[1120].group_number='0054'x & struct[1120].element_number='0011'x & struct[1120].vr='US' & struct[1120].vm='1' & struct[1120].version='dicom98' & struct[1120].name='NumberOfEnergyWindows' struct[1121].group_number='0054'x & struct[1121].element_number='0012'x & struct[1121].vr='SQ' & struct[1121].vm='1' & struct[1121].version='dicom98' & struct[1121].name='EnergyWindowInformationSequence' struct[1122].group_number='0054'x & struct[1122].element_number='0013'x & struct[1122].vr='SQ' & struct[1122].vm='1' & struct[1122].version='dicom98' & struct[1122].name='EnergyWindowRangeSequence' struct[1123].group_number='0054'x & struct[1123].element_number='0014'x & struct[1123].vr='DS' & struct[1123].vm='1' & struct[1123].version='dicom98' & struct[1123].name='EnergyWindowLowerLimit' struct[1124].group_number='0054'x & struct[1124].element_number='0015'x & struct[1124].vr='DS' & struct[1124].vm='1' & struct[1124].version='dicom98' & struct[1124].name='EnergyWindowUpperLimit' struct[1125].group_number='0054'x & struct[1125].element_number='0016'x & struct[1125].vr='SQ' & struct[1125].vm='1' & struct[1125].version='dicom98' & struct[1125].name='RadiopharmaceuticalInformationSequence' struct[1126].group_number='0054'x & struct[1126].element_number='0017'x & struct[1126].vr='IS' & struct[1126].vm='1' & struct[1126].version='dicom98' & struct[1126].name='ResidualSyringeCounts' struct[1127].group_number='0054'x & struct[1127].element_number='0018'x & struct[1127].vr='SH' & struct[1127].vm='1' & struct[1127].version='dicom98' & struct[1127].name='EnergyWindowName' struct[1128].group_number='0054'x & struct[1128].element_number='0020'x & struct[1128].vr='US' & struct[1128].vm='1-n' & struct[1128].version='dicom98' & struct[1128].name='DetectorVector' struct[1129].group_number='0054'x & struct[1129].element_number='0021'x & struct[1129].vr='US' & struct[1129].vm='1' & struct[1129].version='dicom98' & struct[1129].name='NumberOfDetectors' struct[1130].group_number='0054'x & struct[1130].element_number='0022'x & struct[1130].vr='SQ' & struct[1130].vm='1' & struct[1130].version='dicom98' & struct[1130].name='DetectorInformationSequence' struct[1131].group_number='0054'x & struct[1131].element_number='0030'x & struct[1131].vr='US' & struct[1131].vm='1-n' & struct[1131].version='dicom98' & struct[1131].name='PhaseVector' struct[1132].group_number='0054'x & struct[1132].element_number='0031'x & struct[1132].vr='US' & struct[1132].vm='1' & struct[1132].version='dicom98' & struct[1132].name='NumberOfPhases' struct[1133].group_number='0054'x & struct[1133].element_number='0032'x & struct[1133].vr='SQ' & struct[1133].vm='1' & struct[1133].version='dicom98' & struct[1133].name='PhaseInformationSequence' struct[1134].group_number='0054'x & struct[1134].element_number='0033'x & struct[1134].vr='US' & struct[1134].vm='1' & struct[1134].version='dicom98' & struct[1134].name='NumberOfFramesInPhase' struct[1135].group_number='0054'x & struct[1135].element_number='0036'x & struct[1135].vr='IS' & struct[1135].vm='1' & struct[1135].version='dicom98' & struct[1135].name='PhaseDelay' struct[1136].group_number='0054'x & struct[1136].element_number='0038'x & struct[1136].vr='IS' & struct[1136].vm='1' & struct[1136].version='dicom98' & struct[1136].name='PauseBetweenFrames' struct[1137].group_number='0054'x & struct[1137].element_number='0050'x & struct[1137].vr='US' & struct[1137].vm='1-n' & struct[1137].version='dicom98' & struct[1137].name='RotationVector' struct[1138].group_number='0054'x & struct[1138].element_number='0051'x & struct[1138].vr='US' & struct[1138].vm='1' & struct[1138].version='dicom98' & struct[1138].name='NumberOfRotations' struct[1139].group_number='0054'x & struct[1139].element_number='0052'x & struct[1139].vr='SQ' & struct[1139].vm='1' & struct[1139].version='dicom98' & struct[1139].name='RotationInformationSequence' struct[1140].group_number='0054'x & struct[1140].element_number='0053'x & struct[1140].vr='US' & struct[1140].vm='1' & struct[1140].version='dicom98' & struct[1140].name='NumberOfFramesInRotation' struct[1141].group_number='0054'x & struct[1141].element_number='0060'x & struct[1141].vr='US' & struct[1141].vm='1-n' & struct[1141].version='dicom98' & struct[1141].name='RRIntervalVector' struct[1142].group_number='0054'x & struct[1142].element_number='0061'x & struct[1142].vr='US' & struct[1142].vm='1' & struct[1142].version='dicom98' & struct[1142].name='NumberOfRRIntervals' struct[1143].group_number='0054'x & struct[1143].element_number='0062'x & struct[1143].vr='SQ' & struct[1143].vm='1' & struct[1143].version='dicom98' & struct[1143].name='GatedInformationSequence' struct[1144].group_number='0054'x & struct[1144].element_number='0063'x & struct[1144].vr='SQ' & struct[1144].vm='1' & struct[1144].version='dicom98' & struct[1144].name='DataInformationSequence' struct[1145].group_number='0054'x & struct[1145].element_number='0070'x & struct[1145].vr='US' & struct[1145].vm='1-n' & struct[1145].version='dicom98' & struct[1145].name='TimeSlotVector' struct[1146].group_number='0054'x & struct[1146].element_number='0071'x & struct[1146].vr='US' & struct[1146].vm='1' & struct[1146].version='dicom98' & struct[1146].name='NumberOfTimeSlots' struct[1147].group_number='0054'x & struct[1147].element_number='0072'x & struct[1147].vr='SQ' & struct[1147].vm='1' & struct[1147].version='dicom98' & struct[1147].name='TimeSlotInformationSequence' struct[1148].group_number='0054'x & struct[1148].element_number='0073'x & struct[1148].vr='DS' & struct[1148].vm='1' & struct[1148].version='dicom98' & struct[1148].name='TimeSlotTime' struct[1149].group_number='0054'x & struct[1149].element_number='0080'x & struct[1149].vr='US' & struct[1149].vm='1-n' & struct[1149].version='dicom98' & struct[1149].name='SliceVector' struct[1150].group_number='0054'x & struct[1150].element_number='0081'x & struct[1150].vr='US' & struct[1150].vm='1' & struct[1150].version='dicom98' & struct[1150].name='NumberOfSlices' struct[1151].group_number='0054'x & struct[1151].element_number='0090'x & struct[1151].vr='US' & struct[1151].vm='1-n' & struct[1151].version='dicom98' & struct[1151].name='AngularViewVector' struct[1152].group_number='0054'x & struct[1152].element_number='0100'x & struct[1152].vr='US' & struct[1152].vm='1-n' & struct[1152].version='dicom98' & struct[1152].name='TimeSliceVector' struct[1153].group_number='0054'x & struct[1153].element_number='0101'x & struct[1153].vr='US' & struct[1153].vm='1' & struct[1153].version='dicom98' & struct[1153].name='NumberOfTimeSlices' struct[1154].group_number='0054'x & struct[1154].element_number='0200'x & struct[1154].vr='DS' & struct[1154].vm='1' & struct[1154].version='dicom98' & struct[1154].name='StartAngle' struct[1155].group_number='0054'x & struct[1155].element_number='0202'x & struct[1155].vr='CS' & struct[1155].vm='1' & struct[1155].version='dicom98' & struct[1155].name='TypeOfDetectorMotion' struct[1156].group_number='0054'x & struct[1156].element_number='0210'x & struct[1156].vr='IS' & struct[1156].vm='1-n' & struct[1156].version='dicom98' & struct[1156].name='TriggerVector' struct[1157].group_number='0054'x & struct[1157].element_number='0211'x & struct[1157].vr='US' & struct[1157].vm='1' & struct[1157].version='dicom98' & struct[1157].name='NumberOfTriggersInPhase' struct[1158].group_number='0054'x & struct[1158].element_number='0220'x & struct[1158].vr='SQ' & struct[1158].vm='1' & struct[1158].version='dicom98' & struct[1158].name='ViewCodeSequence' struct[1160].group_number='0054'x & struct[1160].element_number='0222'x & struct[1160].vr='SQ' & struct[1160].vm='1' & struct[1160].version='dicom98' & struct[1160].name='ViewModifierCodeSequence' struct[1161].group_number='0054'x & struct[1161].element_number='0300'x & struct[1161].vr='SQ' & struct[1161].vm='1' & struct[1161].version='dicom98' & struct[1161].name='RadionuclideCodeSequence' struct[1162].group_number='0054'x & struct[1162].element_number='0302'x & struct[1162].vr='was' & struct[1162].vm='in' & struct[1162].version='DICOM96' & struct[1162].name='RadiopharmaceuticalRouteCodeSequence' struct[1163].group_number='0054'x & struct[1163].element_number='0302'x & struct[1163].vr='SQ' & struct[1163].vm='1' & struct[1163].version='dicom98' & struct[1163].name='AdministrationRouteCodeSequence' struct[1164].group_number='0054'x & struct[1164].element_number='0304'x & struct[1164].vr='SQ' & struct[1164].vm='1' & struct[1164].version='dicom98' & struct[1164].name='RadiopharmaceuticalCodeSequence' struct[1165].group_number='0054'x & struct[1165].element_number='0306'x & struct[1165].vr='SQ' & struct[1165].vm='1' & struct[1165].version='dicom98' & struct[1165].name='CalibrationDataSequence' struct[1166].group_number='0054'x & struct[1166].element_number='0308'x & struct[1166].vr='US' & struct[1166].vm='1' & struct[1166].version='dicom98' & struct[1166].name='EnergyWindowNumber' struct[1167].group_number='0054'x & struct[1167].element_number='0400'x & struct[1167].vr='SH' & struct[1167].vm='1' & struct[1167].version='dicom98' & struct[1167].name='ImageID' struct[1168].group_number='0054'x & struct[1168].element_number='0410'x & struct[1168].vr='SQ' & struct[1168].vm='1' & struct[1168].version='dicom98' & struct[1168].name='PatientOrientationCodeSequence' struct[1169].group_number='0054'x & struct[1169].element_number='0412'x & struct[1169].vr='SQ' & struct[1169].vm='1' & struct[1169].version='dicom98' & struct[1169].name='PatientOrientationModifierCodeSequence' struct[1170].group_number='0054'x & struct[1170].element_number='0414'x & struct[1170].vr='SQ' & struct[1170].vm='1' & struct[1170].version='dicom98' & struct[1170].name='PatientGantryRelationshipCodeSequence' struct[1171].group_number='0054'x & struct[1171].element_number='1000'x & struct[1171].vr='CS' & struct[1171].vm='2' & struct[1171].version='dicom98' & struct[1171].name='SeriesType' struct[1172].group_number='0054'x & struct[1172].element_number='1001'x & struct[1172].vr='CS' & struct[1172].vm='1' & struct[1172].version='dicom98' & struct[1172].name='Units' struct[1173].group_number='0054'x & struct[1173].element_number='1002'x & struct[1173].vr='CS' & struct[1173].vm='1' & struct[1173].version='dicom98' & struct[1173].name='CountsSource' struct[1174].group_number='0054'x & struct[1174].element_number='1004'x & struct[1174].vr='CS' & struct[1174].vm='1' & struct[1174].version='dicom98' & struct[1174].name='ReprojectionMethod' struct[1175].group_number='0054'x & struct[1175].element_number='1100'x & struct[1175].vr='CS' & struct[1175].vm='1' & struct[1175].version='dicom98' & struct[1175].name='RandomsCorrectionMethod' struct[1176].group_number='0054'x & struct[1176].element_number='1101'x & struct[1176].vr='LO' & struct[1176].vm='1' & struct[1176].version='dicom98' & struct[1176].name='AttenuationCorrectionMethod' struct[1177].group_number='0054'x & struct[1177].element_number='1102'x & struct[1177].vr='CS' & struct[1177].vm='1' & struct[1177].version='dicom98' & struct[1177].name='DecayCorrection' struct[1178].group_number='0054'x & struct[1178].element_number='1103'x & struct[1178].vr='LO' & struct[1178].vm='1' & struct[1178].version='dicom98' & struct[1178].name='ReconstructionMethod' struct[1179].group_number='0054'x & struct[1179].element_number='1104'x & struct[1179].vr='LO' & struct[1179].vm='1' & struct[1179].version='dicom98' & struct[1179].name='DetectorLinesOfResponseUsed' struct[1180].group_number='0054'x & struct[1180].element_number='1105'x & struct[1180].vr='LO' & struct[1180].vm='1' & struct[1180].version='dicom98' & struct[1180].name='ScatterCorrectionMethod' struct[1181].group_number='0054'x & struct[1181].element_number='1200'x & struct[1181].vr='DS' & struct[1181].vm='1' & struct[1181].version='dicom98' & struct[1181].name='AxialAcceptance' struct[1182].group_number='0054'x & struct[1182].element_number='1201'x & struct[1182].vr='IS' & struct[1182].vm='2' & struct[1182].version='dicom98' & struct[1182].name='AxialMash' struct[1183].group_number='0054'x & struct[1183].element_number='1202'x & struct[1183].vr='IS' & struct[1183].vm='1' & struct[1183].version='dicom98' & struct[1183].name='TransverseMash' struct[1184].group_number='0054'x & struct[1184].element_number='1203'x & struct[1184].vr='DS' & struct[1184].vm='2' & struct[1184].version='dicom98' & struct[1184].name='DetectorElementSize' struct[1185].group_number='0054'x & struct[1185].element_number='1210'x & struct[1185].vr='DS' & struct[1185].vm='1' & struct[1185].version='dicom98' & struct[1185].name='CoincidenceWindowWidth' struct[1186].group_number='0054'x & struct[1186].element_number='1220'x & struct[1186].vr='CS' & struct[1186].vm='1-n' & struct[1186].version='dicom98' & struct[1186].name='SecondaryCountsType' struct[1187].group_number='0054'x & struct[1187].element_number='1300'x & struct[1187].vr='DS' & struct[1187].vm='1' & struct[1187].version='dicom98' & struct[1187].name='FrameReferenceTime' struct[1188].group_number='0054'x & struct[1188].element_number='1310'x & struct[1188].vr='IS' & struct[1188].vm='1' & struct[1188].version='dicom98' & struct[1188].name='PrimaryPromptsCountsAccumulated' struct[1189].group_number='0054'x & struct[1189].element_number='1311'x & struct[1189].vr='IS' & struct[1189].vm='1-n' & struct[1189].version='dicom98' & struct[1189].name='SecondaryCountsAccumulated' struct[1190].group_number='0054'x & struct[1190].element_number='1320'x & struct[1190].vr='DS' & struct[1190].vm='1' & struct[1190].version='dicom98' & struct[1190].name='SliceSensitivityFactor' struct[1191].group_number='0054'x & struct[1191].element_number='1321'x & struct[1191].vr='DS' & struct[1191].vm='1' & struct[1191].version='dicom98' & struct[1191].name='DecayFactor' struct[1192].group_number='0054'x & struct[1192].element_number='1322'x & struct[1192].vr='DS' & struct[1192].vm='1' & struct[1192].version='dicom98' & struct[1192].name='DoseCalibrationFactor' struct[1193].group_number='0054'x & struct[1193].element_number='1323'x & struct[1193].vr='DS' & struct[1193].vm='1' & struct[1193].version='dicom98' & struct[1193].name='ScatterFractionFactor' struct[1194].group_number='0054'x & struct[1194].element_number='1324'x & struct[1194].vr='DS' & struct[1194].vm='1' & struct[1194].version='dicom98' & struct[1194].name='DeadTimeFactor' struct[1195].group_number='0054'x & struct[1195].element_number='1330'x & struct[1195].vr='US' & struct[1195].vm='1' & struct[1195].version='dicom98' & struct[1195].name='ImageIndex' struct[1196].group_number='0054'x & struct[1196].element_number='1400'x & struct[1196].vr='CS' & struct[1196].vm='1-n' & struct[1196].version='dicom98' & struct[1196].name='CountsIncluded' struct[1197].group_number='0054'x & struct[1197].element_number='1401'x & struct[1197].vr='CS' & struct[1197].vm='1' & struct[1197].version='dicom98' & struct[1197].name='DeadTimeCorrectionFlag' struct[1198].group_number='0060'x & struct[1198].element_number='0000'x & struct[1198].vr='UL' & struct[1198].vm='1' & struct[1198].version='dicom99' & struct[1198].name='HistogramGroupLength' struct[1199].group_number='0060'x & struct[1199].element_number='3000'x & struct[1199].vr='SQ' & struct[1199].vm='1' & struct[1199].version='dicom99' & struct[1199].name='HistogramSequence' struct[1200].group_number='0060'x & struct[1200].element_number='3002'x & struct[1200].vr='US' & struct[1200].vm='1' & struct[1200].version='dicom99' & struct[1200].name='HistogramNumberOfBins' struct[1201].group_number='0060'x & struct[1201].element_number='3004'x & struct[1201].vr='xs' & struct[1201].vm='1' & struct[1201].version='dicom99' & struct[1201].name='HistogramFirstBinValue' struct[1202].group_number='0060'x & struct[1202].element_number='3006'x & struct[1202].vr='xs' & struct[1202].vm='1' & struct[1202].version='dicom99' & struct[1202].name='HistogramLastBinValue' struct[1203].group_number='0060'x & struct[1203].element_number='3008'x & struct[1203].vr='US' & struct[1203].vm='1' & struct[1203].version='dicom99' & struct[1203].name='HistogramBinWidth' struct[1204].group_number='0060'x & struct[1204].element_number='3010'x & struct[1204].vr='LO' & struct[1204].vm='1' & struct[1204].version='dicom99' & struct[1204].name='HistogramExplanation' struct[1205].group_number='0060'x & struct[1205].element_number='3020'x & struct[1205].vr='UL' & struct[1205].vm='1-n' & struct[1205].version='dicom99' & struct[1205].name='HistogramData' struct[1206].group_number='0070'x & struct[1206].element_number='0000'x & struct[1206].vr='UL' & struct[1206].vm='1' & struct[1206].version='dicom2000' & struct[1206].name='PresentationStateGroupLength' struct[1207].group_number='0070'x & struct[1207].element_number='0001'x & struct[1207].vr='SQ' & struct[1207].vm='1' & struct[1207].version='dicom2000' & struct[1207].name='GraphicAnnotationSequence' struct[1208].group_number='0070'x & struct[1208].element_number='0002'x & struct[1208].vr='CS' & struct[1208].vm='1' & struct[1208].version='dicom2000' & struct[1208].name='GraphicLayer' struct[1209].group_number='0070'x & struct[1209].element_number='0003'x & struct[1209].vr='CS' & struct[1209].vm='1' & struct[1209].version='dicom2000' & struct[1209].name='BoundingBoxAnnotationUnits' struct[1210].group_number='0070'x & struct[1210].element_number='0004'x & struct[1210].vr='CS' & struct[1210].vm='1' & struct[1210].version='dicom2000' & struct[1210].name='AnchorPointAnnotationUnits' struct[1211].group_number='0070'x & struct[1211].element_number='0005'x & struct[1211].vr='CS' & struct[1211].vm='1' & struct[1211].version='dicom2000' & struct[1211].name='GraphicAnnotationUnits' struct[1212].group_number='0070'x & struct[1212].element_number='0006'x & struct[1212].vr='ST' & struct[1212].vm='1' & struct[1212].version='dicom2000' & struct[1212].name='UnformattedTextValue' struct[1213].group_number='0070'x & struct[1213].element_number='0008'x & struct[1213].vr='SQ' & struct[1213].vm='1' & struct[1213].version='dicom2000' & struct[1213].name='TextObjectSequence' struct[1214].group_number='0070'x & struct[1214].element_number='0009'x & struct[1214].vr='SQ' & struct[1214].vm='1' & struct[1214].version='dicom2000' & struct[1214].name='GraphicObjectSequence' struct[1215].group_number='0070'x & struct[1215].element_number='0010'x & struct[1215].vr='FL' & struct[1215].vm='2' & struct[1215].version='dicom2000' & struct[1215].name='BoundingBoxTopLeftHandCorner' struct[1216].group_number='0070'x & struct[1216].element_number='0011'x & struct[1216].vr='FL' & struct[1216].vm='2' & struct[1216].version='dicom2000' & struct[1216].name='BoundingBoxBottomRightHandCorner' struct[1217].group_number='0070'x & struct[1217].element_number='0012'x & struct[1217].vr='CS' & struct[1217].vm='1' & struct[1217].version='dicom2000' & struct[1217].name='BoundingBoxTextHorizontalJustification' struct[1218].group_number='0070'x & struct[1218].element_number='0014'x & struct[1218].vr='FL' & struct[1218].vm='2' & struct[1218].version='dicom2000' & struct[1218].name='AnchorPoint' struct[1219].group_number='0070'x & struct[1219].element_number='0015'x & struct[1219].vr='CS' & struct[1219].vm='1' & struct[1219].version='dicom2000' & struct[1219].name='AnchorPointVisibility' struct[1220].group_number='0070'x & struct[1220].element_number='0020'x & struct[1220].vr='US' & struct[1220].vm='1' & struct[1220].version='dicom2000' & struct[1220].name='GraphicDimensions' struct[1221].group_number='0070'x & struct[1221].element_number='0021'x & struct[1221].vr='US' & struct[1221].vm='1' & struct[1221].version='dicom2000' & struct[1221].name='NumberOfGraphicPoints' struct[1222].group_number='0070'x & struct[1222].element_number='0022'x & struct[1222].vr='FL' & struct[1222].vm='2-n' & struct[1222].version='dicom2000' & struct[1222].name='GraphicData' struct[1223].group_number='0070'x & struct[1223].element_number='0023'x & struct[1223].vr='CS' & struct[1223].vm='1' & struct[1223].version='dicom2000' & struct[1223].name='GraphicType' struct[1224].group_number='0070'x & struct[1224].element_number='0024'x & struct[1224].vr='CS' & struct[1224].vm='1' & struct[1224].version='dicom2000' & struct[1224].name='GraphicFilled' struct[1225].group_number='0070'x & struct[1225].element_number='0041'x & struct[1225].vr='CS' & struct[1225].vm='1' & struct[1225].version='dicom2000' & struct[1225].name='ImageHorizontalFlip' struct[1226].group_number='0070'x & struct[1226].element_number='0042'x & struct[1226].vr='US' & struct[1226].vm='1' & struct[1226].version='dicom2000' & struct[1226].name='ImageRotation' struct[1227].group_number='0070'x & struct[1227].element_number='0052'x & struct[1227].vr='SL' & struct[1227].vm='2' & struct[1227].version='dicom2000' & struct[1227].name='DisplayedAreaTopLeftHandCorner' struct[1228].group_number='0070'x & struct[1228].element_number='0053'x & struct[1228].vr='SL' & struct[1228].vm='2' & struct[1228].version='dicom2000' & struct[1228].name='DisplayedAreaBottomRightHandCorner' struct[1229].group_number='0070'x & struct[1229].element_number='005A'x & struct[1229].vr='SQ' & struct[1229].vm='1' & struct[1229].version='dicom2000' & struct[1229].name='DisplayedAreaSelectionSequence' struct[1230].group_number='0070'x & struct[1230].element_number='0060'x & struct[1230].vr='SQ' & struct[1230].vm='1' & struct[1230].version='dicom2000' & struct[1230].name='GraphicLayerSequence' struct[1231].group_number='0070'x & struct[1231].element_number='0062'x & struct[1231].vr='IS' & struct[1231].vm='1' & struct[1231].version='dicom2000' & struct[1231].name='GraphicLayerOrder' struct[1232].group_number='0070'x & struct[1232].element_number='0066'x & struct[1232].vr='US' & struct[1232].vm='1' & struct[1232].version='dicom2000' & struct[1232].name='GraphicLayerRecommendedDisplayGrayscaleValue' struct[1233].group_number='0070'x & struct[1233].element_number='0067'x & struct[1233].vr='US' & struct[1233].vm='3' & struct[1233].version='dicom2000' & struct[1233].name='GraphicLayerRecommendedDisplayRGBValue' struct[1234].group_number='0070'x & struct[1234].element_number='0068'x & struct[1234].vr='LO' & struct[1234].vm='1' & struct[1234].version='dicom2000' & struct[1234].name='GraphicLayerDescription' struct[1235].group_number='0070'x & struct[1235].element_number='0080'x & struct[1235].vr='CS' & struct[1235].vm='1' & struct[1235].version='dicom2000' & struct[1235].name='PresentationLabel' struct[1236].group_number='0070'x & struct[1236].element_number='0081'x & struct[1236].vr='LO' & struct[1236].vm='1' & struct[1236].version='dicom2000' & struct[1236].name='PresentationDescription' struct[1237].group_number='0070'x & struct[1237].element_number='0082'x & struct[1237].vr='DA' & struct[1237].vm='1' & struct[1237].version='dicom2000' & struct[1237].name='PresentationCreationDate' struct[1238].group_number='0070'x & struct[1238].element_number='0083'x & struct[1238].vr='TM' & struct[1238].vm='1' & struct[1238].version='dicom2000' & struct[1238].name='PresentationCreationTime' struct[1239].group_number='0070'x & struct[1239].element_number='0084'x & struct[1239].vr='PN' & struct[1239].vm='1' & struct[1239].version='dicom2000' & struct[1239].name='PresentationCreatorsName' struct[1240].group_number='0070'x & struct[1240].element_number='0100'x & struct[1240].vr='CS' & struct[1240].vm='1' & struct[1240].version='dicom2000' & struct[1240].name='PresentationSizeMode' struct[1241].group_number='0070'x & struct[1241].element_number='0101'x & struct[1241].vr='DS' & struct[1241].vm='2' & struct[1241].version='dicom2000' & struct[1241].name='PresentationPixelSpacing' struct[1242].group_number='0070'x & struct[1242].element_number='0102'x & struct[1242].vr='IS' & struct[1242].vm='2' & struct[1242].version='dicom2000' & struct[1242].name='PresentationPixelAspectRatio' struct[1243].group_number='0070'x & struct[1243].element_number='0103'x & struct[1243].vr='FL' & struct[1243].vm='1' & struct[1243].version='dicom2000' & struct[1243].name='PresentationPixelMagnificationRatio' struct[1244].group_number='0088'x & struct[1244].element_number='0000'x & struct[1244].vr='UL' & struct[1244].vm='1' & struct[1244].version='dicom98' & struct[1244].name='StorageGroupLength' struct[1245].group_number='0088'x & struct[1245].element_number='0130'x & struct[1245].vr='SH' & struct[1245].vm='1' & struct[1245].version='dicom98' & struct[1245].name='StorageMediaFileSetID' struct[1246].group_number='0088'x & struct[1246].element_number='0140'x & struct[1246].vr='UI' & struct[1246].vm='1' & struct[1246].version='dicom98' & struct[1246].name='StorageMediaFileSetUID' struct[1247].group_number='0088'x & struct[1247].element_number='0200'x & struct[1247].vr='SQ' & struct[1247].vm='1' & struct[1247].version='dicom98' & struct[1247].name='IconImageSequence' struct[1248].group_number='0088'x & struct[1248].element_number='0904'x & struct[1248].vr='LO' & struct[1248].vm='1' & struct[1248].version='dicom98' & struct[1248].name='TopicTitle' struct[1249].group_number='0088'x & struct[1249].element_number='0906'x & struct[1249].vr='ST' & struct[1249].vm='1' & struct[1249].version='dicom98' & struct[1249].name='TopicSubject' struct[1250].group_number='0088'x & struct[1250].element_number='0910'x & struct[1250].vr='LO' & struct[1250].vm='1' & struct[1250].version='dicom98' & struct[1250].name='TopicAuthor' struct[1251].group_number='0088'x & struct[1251].element_number='0912'x & struct[1251].vr='LO' & struct[1251].vm='1-32' & struct[1251].version='dicom98' & struct[1251].name='TopicKeyWords' struct[1252].group_number='0100'x & struct[1252].element_number='0410'x & struct[1252].vr='CS' & struct[1252].vm='1' & struct[1252].version='dicom2000' & struct[1252].name='SOPInstanceStatus' struct[1253].group_number='0100'x & struct[1253].element_number='0420'x & struct[1253].vr='DT' & struct[1253].vm='1' & struct[1253].version='dicom2000' & struct[1253].name='SOPAuthorizationDateAndTime' struct[1254].group_number='0100'x & struct[1254].element_number='0424'x & struct[1254].vr='LT' & struct[1254].vm='1' & struct[1254].version='dicom2000' & struct[1254].name='SOPAuthorizationComment' struct[1255].group_number='0100'x & struct[1255].element_number='0426'x & struct[1255].vr='LO' & struct[1255].vm='1' & struct[1255].version='dicom2000' & struct[1255].name='AuthorizationEquipmentCertificationNumber' struct[1256].group_number='0400'x & struct[1256].element_number='0005'x & struct[1256].vr='US' & struct[1256].vm='1' & struct[1256].version='dicom2001' & struct[1256].name='MACIDNumber' struct[1257].group_number='0400'x & struct[1257].element_number='0010'x & struct[1257].vr='UI' & struct[1257].vm='1' & struct[1257].version='dicom2001' & struct[1257].name='MACCalculationTransferSyntaxUID' struct[1258].group_number='0400'x & struct[1258].element_number='0015'x & struct[1258].vr='CS' & struct[1258].vm='1' & struct[1258].version='dicom2001' & struct[1258].name='MACAlgorithm' struct[1259].group_number='0400'x & struct[1259].element_number='0020'x & struct[1259].vr='AT' & struct[1259].vm='1-n' & struct[1259].version='dicom2001' & struct[1259].name='DataElementsSigned' struct[1260].group_number='0400'x & struct[1260].element_number='0100'x & struct[1260].vr='UI' & struct[1260].vm='1' & struct[1260].version='dicom2001' & struct[1260].name='DigitalSignatureUID' struct[1261].group_number='0400'x & struct[1261].element_number='0105'x & struct[1261].vr='DT' & struct[1261].vm='1' & struct[1261].version='dicom2001' & struct[1261].name='DigitalSignatureDateTime' struct[1262].group_number='0400'x & struct[1262].element_number='0110'x & struct[1262].vr='CS' & struct[1262].vm='1' & struct[1262].version='dicom2001' & struct[1262].name='CertificateType' struct[1263].group_number='0400'x & struct[1263].element_number='0115'x & struct[1263].vr='OB' & struct[1263].vm='1' & struct[1263].version='dicom2001' & struct[1263].name='CertificateOfSigner' struct[1264].group_number='0400'x & struct[1264].element_number='0120'x & struct[1264].vr='OB' & struct[1264].vm='1' & struct[1264].version='dicom2001' & struct[1264].name='Signature' struct[1265].group_number='0400'x & struct[1265].element_number='0305'x & struct[1265].vr='CS' & struct[1265].vm='1' & struct[1265].version='dicom2001' & struct[1265].name='CertifiedTimestampType' struct[1266].group_number='0400'x & struct[1266].element_number='0310'x & struct[1266].vr='OB' & struct[1266].vm='1' & struct[1266].version='dicom2001' & struct[1266].name='CertifiedTimestamp' struct[1267].group_number='0400'x & struct[1267].element_number='0500'x & struct[1267].vr='SQ' & struct[1267].vm='1' & struct[1267].version='dicom2003' & struct[1267].name='EncryptedAttributesSequence' struct[1268].group_number='0400'x & struct[1268].element_number='0510'x & struct[1268].vr='UI' & struct[1268].vm='1' & struct[1268].version='dicom2003' & struct[1268].name='EncryptedContentTransferSyntaxUID' struct[1269].group_number='0400'x & struct[1269].element_number='0520'x & struct[1269].vr='OB' & struct[1269].vm='1' & struct[1269].version='dicom2003' & struct[1269].name='EncryptedContent' struct[1270].group_number='0400'x & struct[1270].element_number='0550'x & struct[1270].vr='SQ' & struct[1270].vm='1' & struct[1270].version='dicom2003' & struct[1270].name='ModifiedAttributesSequence' struct[1271].group_number='2000'x & struct[1271].element_number='0000'x & struct[1271].vr='UL' & struct[1271].vm='1' & struct[1271].version='dicom98' & struct[1271].name='FilmSessionGroupLength' struct[1272].group_number='2000'x & struct[1272].element_number='0010'x & struct[1272].vr='IS' & struct[1272].vm='1' & struct[1272].version='dicom98' & struct[1272].name='NumberOfCopies' struct[1273].group_number='2000'x & struct[1273].element_number='001E'x & struct[1273].vr='SQ' & struct[1273].vm='1' & struct[1273].version='dicom99' & struct[1273].name='PrinterConfigurationSequence' struct[1274].group_number='2000'x & struct[1274].element_number='0020'x & struct[1274].vr='CS' & struct[1274].vm='1' & struct[1274].version='dicom98' & struct[1274].name='PrintPriority' struct[1275].group_number='2000'x & struct[1275].element_number='0030'x & struct[1275].vr='CS' & struct[1275].vm='1' & struct[1275].version='dicom98' & struct[1275].name='MediumType' struct[1276].group_number='2000'x & struct[1276].element_number='0040'x & struct[1276].vr='CS' & struct[1276].vm='1' & struct[1276].version='dicom98' & struct[1276].name='FilmDestination' struct[1277].group_number='2000'x & struct[1277].element_number='0050'x & struct[1277].vr='LO' & struct[1277].vm='1' & struct[1277].version='dicom98' & struct[1277].name='FilmSessionLabel' struct[1278].group_number='2000'x & struct[1278].element_number='0060'x & struct[1278].vr='IS' & struct[1278].vm='1' & struct[1278].version='dicom98' & struct[1278].name='MemoryAllocation' struct[1279].group_number='2000'x & struct[1279].element_number='0062'x & struct[1279].vr='in' & struct[1279].vm='which' & struct[1279].version='is' & struct[1279].name='Supp37' struct[1280].group_number='2000'x & struct[1280].element_number='0061'x & struct[1280].vr='IS' & struct[1280].vm='1' & struct[1280].version='dicom99' & struct[1280].name='MaximumMemoryAllocation' struct[1281].group_number='2000'x & struct[1281].element_number='0062'x & struct[1281].vr='CS' & struct[1281].vm='1' & struct[1281].version='dicom98' & struct[1281].name='ColorImagePrintingFlag' struct[1282].group_number='2000'x & struct[1282].element_number='0063'x & struct[1282].vr='CS' & struct[1282].vm='1' & struct[1282].version='dicom98' & struct[1282].name='CollationFlag' struct[1283].group_number='2000'x & struct[1283].element_number='0065'x & struct[1283].vr='CS' & struct[1283].vm='1' & struct[1283].version='dicom98' & struct[1283].name='AnnotationFlag' struct[1284].group_number='2000'x & struct[1284].element_number='0067'x & struct[1284].vr='CS' & struct[1284].vm='1' & struct[1284].version='dicom98' & struct[1284].name='ImageOverlayFlag' struct[1285].group_number='2000'x & struct[1285].element_number='0069'x & struct[1285].vr='CS' & struct[1285].vm='1' & struct[1285].version='dicom98' & struct[1285].name='PresentationLUTFlag' struct[1286].group_number='2000'x & struct[1286].element_number='006A'x & struct[1286].vr='CS' & struct[1286].vm='1' & struct[1286].version='dicom98' & struct[1286].name='ImageBoxPresentationLUTFlag' struct[1287].group_number='2000'x & struct[1287].element_number='00A0'x & struct[1287].vr='US' & struct[1287].vm='1' & struct[1287].version='dicom99' & struct[1287].name='MemoryBitDepth' struct[1288].group_number='2000'x & struct[1288].element_number='00A1'x & struct[1288].vr='US' & struct[1288].vm='1' & struct[1288].version='dicom99' & struct[1288].name='PrintingBitDepth' struct[1289].group_number='2000'x & struct[1289].element_number='00A2'x & struct[1289].vr='SQ' & struct[1289].vm='1' & struct[1289].version='dicom99' & struct[1289].name='MediaInstalledSequence' struct[1290].group_number='2000'x & struct[1290].element_number='00A4'x & struct[1290].vr='SQ' & struct[1290].vm='1' & struct[1290].version='dicom99' & struct[1290].name='OtherMediaAvailableSequence' struct[1291].group_number='2000'x & struct[1291].element_number='00A8'x & struct[1291].vr='SQ' & struct[1291].vm='1' & struct[1291].version='dicom99' & struct[1291].name='SupportedImageDisplayFormatsSequence' struct[1292].group_number='2000'x & struct[1292].element_number='0500'x & struct[1292].vr='SQ' & struct[1292].vm='1' & struct[1292].version='dicom98' & struct[1292].name='ReferencedFilmBoxSequence' struct[1293].group_number='2000'x & struct[1293].element_number='0510'x & struct[1293].vr='SQ' & struct[1293].vm='1' & struct[1293].version='dicom98' & struct[1293].name='ReferencedStoredPrintSequence' struct[1294].group_number='2010'x & struct[1294].element_number='0000'x & struct[1294].vr='UL' & struct[1294].vm='1' & struct[1294].version='dicom98' & struct[1294].name='FilmBoxGroupLength' struct[1295].group_number='2010'x & struct[1295].element_number='0010'x & struct[1295].vr='ST' & struct[1295].vm='1' & struct[1295].version='dicom98' & struct[1295].name='ImageDisplayFormat' struct[1296].group_number='2010'x & struct[1296].element_number='0030'x & struct[1296].vr='CS' & struct[1296].vm='1' & struct[1296].version='dicom98' & struct[1296].name='AnnotationDisplayFormatID' struct[1297].group_number='2010'x & struct[1297].element_number='0040'x & struct[1297].vr='CS' & struct[1297].vm='1' & struct[1297].version='dicom98' & struct[1297].name='FilmOrientation' struct[1298].group_number='2010'x & struct[1298].element_number='0050'x & struct[1298].vr='CS' & struct[1298].vm='1' & struct[1298].version='dicom98' & struct[1298].name='FilmSizeID' struct[1299].group_number='2010'x & struct[1299].element_number='0052'x & struct[1299].vr='CS' & struct[1299].vm='1' & struct[1299].version='dicom99' & struct[1299].name='PrinterResolutionID' struct[1300].group_number='2010'x & struct[1300].element_number='0054'x & struct[1300].vr='CS' & struct[1300].vm='1' & struct[1300].version='dicom99' & struct[1300].name='DefaultPrinterResolutionID' struct[1301].group_number='2010'x & struct[1301].element_number='0060'x & struct[1301].vr='CS' & struct[1301].vm='1' & struct[1301].version='dicom98' & struct[1301].name='MagnificationType' struct[1302].group_number='2010'x & struct[1302].element_number='0080'x & struct[1302].vr='CS' & struct[1302].vm='1' & struct[1302].version='dicom98' & struct[1302].name='SmoothingType' struct[1303].group_number='2010'x & struct[1303].element_number='00A6'x & struct[1303].vr='CS' & struct[1303].vm='1' & struct[1303].version='dicom99' & struct[1303].name='DefaultMagnificationType' struct[1304].group_number='2010'x & struct[1304].element_number='00A7'x & struct[1304].vr='CS' & struct[1304].vm='1-n' & struct[1304].version='dicom99' & struct[1304].name='OtherMagnificationTypesAvailable' struct[1305].group_number='2010'x & struct[1305].element_number='00A8'x & struct[1305].vr='CS' & struct[1305].vm='1' & struct[1305].version='dicom99' & struct[1305].name='DefaultSmoothingType' struct[1306].group_number='2010'x & struct[1306].element_number='00A9'x & struct[1306].vr='CS' & struct[1306].vm='1-n' & struct[1306].version='dicom99' & struct[1306].name='OtherSmoothingTypesAvailable' struct[1307].group_number='2010'x & struct[1307].element_number='0100'x & struct[1307].vr='CS' & struct[1307].vm='1' & struct[1307].version='dicom98' & struct[1307].name='BorderDensity' struct[1308].group_number='2010'x & struct[1308].element_number='0110'x & struct[1308].vr='CS' & struct[1308].vm='1' & struct[1308].version='dicom98' & struct[1308].name='EmptyImageDensity' struct[1309].group_number='2010'x & struct[1309].element_number='0120'x & struct[1309].vr='US' & struct[1309].vm='1' & struct[1309].version='dicom98' & struct[1309].name='MinDensity' struct[1310].group_number='2010'x & struct[1310].element_number='0130'x & struct[1310].vr='US' & struct[1310].vm='1' & struct[1310].version='dicom98' & struct[1310].name='MaxDensity' struct[1311].group_number='2010'x & struct[1311].element_number='0140'x & struct[1311].vr='CS' & struct[1311].vm='1' & struct[1311].version='dicom98' & struct[1311].name='Trim' struct[1312].group_number='2010'x & struct[1312].element_number='0150'x & struct[1312].vr='ST' & struct[1312].vm='1' & struct[1312].version='dicom98' & struct[1312].name='ConfigurationInformation' struct[1313].group_number='2010'x & struct[1313].element_number='0152'x & struct[1313].vr='LT' & struct[1313].vm='1' & struct[1313].version='dicom99' & struct[1313].name='ConfigurationInformationDescription' struct[1314].group_number='2010'x & struct[1314].element_number='0154'x & struct[1314].vr='IS' & struct[1314].vm='1' & struct[1314].version='dicom99' & struct[1314].name='MaximumCollatedFilms' struct[1315].group_number='2010'x & struct[1315].element_number='015E'x & struct[1315].vr='US' & struct[1315].vm='1' & struct[1315].version='dicom98' & struct[1315].name='Illumination' struct[1316].group_number='2010'x & struct[1316].element_number='0160'x & struct[1316].vr='US' & struct[1316].vm='1' & struct[1316].version='dicom98' & struct[1316].name='ReflectedAmbientLight' struct[1317].group_number='2010'x & struct[1317].element_number='0376'x & struct[1317].vr='DS' & struct[1317].vm='2' & struct[1317].version='dicom99' & struct[1317].name='PrinterPixelSpacing' struct[1318].group_number='2010'x & struct[1318].element_number='0500'x & struct[1318].vr='SQ' & struct[1318].vm='1' & struct[1318].version='dicom98' & struct[1318].name='ReferencedFilmSessionSequence' struct[1319].group_number='2010'x & struct[1319].element_number='0510'x & struct[1319].vr='SQ' & struct[1319].vm='1' & struct[1319].version='dicom98' & struct[1319].name='ReferencedImageBoxSequence' struct[1320].group_number='2010'x & struct[1320].element_number='0520'x & struct[1320].vr='SQ' & struct[1320].vm='1' & struct[1320].version='dicom98' & struct[1320].name='ReferencedBasicAnnotationBoxSequence' struct[1321].group_number='2020'x & struct[1321].element_number='0000'x & struct[1321].vr='UL' & struct[1321].vm='1' & struct[1321].version='dicom98' & struct[1321].name='ImageBoxGroupLength' struct[1322].group_number='2020'x & struct[1322].element_number='0010'x & struct[1322].vr='US' & struct[1322].vm='1' & struct[1322].version='dicom98' & struct[1322].name='ImagePosition' struct[1323].group_number='2020'x & struct[1323].element_number='0020'x & struct[1323].vr='CS' & struct[1323].vm='1' & struct[1323].version='dicom98' & struct[1323].name='Polarity' struct[1324].group_number='2020'x & struct[1324].element_number='0030'x & struct[1324].vr='DS' & struct[1324].vm='1' & struct[1324].version='dicom98' & struct[1324].name='RequestedImageSize' struct[1325].group_number='2020'x & struct[1325].element_number='0040'x & struct[1325].vr='CS' & struct[1325].vm='1' & struct[1325].version='dicom99' & struct[1325].name='RequestedDecimateCropBehavior' struct[1326].group_number='2020'x & struct[1326].element_number='0050'x & struct[1326].vr='CS' & struct[1326].vm='1' & struct[1326].version='dicom99' & struct[1326].name='RequestedResolutionID' struct[1327].group_number='2020'x & struct[1327].element_number='00A0'x & struct[1327].vr='CS' & struct[1327].vm='1' & struct[1327].version='dicom99' & struct[1327].name='RequestedImageSizeFlag' struct[1328].group_number='2020'x & struct[1328].element_number='00A2'x & struct[1328].vr='CS' & struct[1328].vm='1' & struct[1328].version='dicom99' & struct[1328].name='DecimateCropResult' struct[1330].group_number='2020'x & struct[1330].element_number='0110'x & struct[1330].vr='SQ' & struct[1330].vm='1' & struct[1330].version='dicom98' & struct[1330].name='BasicGrayscaleImageSequence' struct[1332].group_number='2020'x & struct[1332].element_number='0111'x & struct[1332].vr='SQ' & struct[1332].vm='1' & struct[1332].version='dicom98' & struct[1332].name='BasicColorImageSequence' struct[1334].group_number='2020'x & struct[1334].element_number='0130'x & struct[1334].vr='SQ' & struct[1334].vm='1' & struct[1334].version='dicom98' & struct[1334].name='RETIRED_ReferencedImageOverlayBoxSequence' struct[1336].group_number='2020'x & struct[1336].element_number='0140'x & struct[1336].vr='SQ' & struct[1336].vm='1' & struct[1336].version='dicom98' & struct[1336].name='RETIRED_ReferencedVOILUTBoxSequence' struct[1337].group_number='2030'x & struct[1337].element_number='0000'x & struct[1337].vr='UL' & struct[1337].vm='1' & struct[1337].version='dicom98' & struct[1337].name='AnnotationGroupLength' struct[1338].group_number='2030'x & struct[1338].element_number='0010'x & struct[1338].vr='US' & struct[1338].vm='1' & struct[1338].version='dicom98' & struct[1338].name='AnnotationPosition' struct[1339].group_number='2030'x & struct[1339].element_number='0020'x & struct[1339].vr='LO' & struct[1339].vm='1' & struct[1339].version='dicom98' & struct[1339].name='TextString' struct[1340].group_number='2040'x & struct[1340].element_number='0000'x & struct[1340].vr='UL' & struct[1340].vm='1' & struct[1340].version='dicom98' & struct[1340].name='OverlayBoxGroupLength' struct[1341].group_number='2040'x & struct[1341].element_number='0010'x & struct[1341].vr='SQ' & struct[1341].vm='1' & struct[1341].version='dicom98' & struct[1341].name='ReferencedOverlayPlaneSequence' struct[1342].group_number='2040'x & struct[1342].element_number='0011'x & struct[1342].vr='US' & struct[1342].vm='1-99' & struct[1342].version='dicom98' & struct[1342].name='ReferencedOverlayPlaneGroups' struct[1343].group_number='2040'x & struct[1343].element_number='0020'x & struct[1343].vr='SQ' & struct[1343].vm='1' & struct[1343].version='dicom99' & struct[1343].name='OverlayPixelDataSequence' struct[1344].group_number='2040'x & struct[1344].element_number='0060'x & struct[1344].vr='CS' & struct[1344].vm='1' & struct[1344].version='dicom98' & struct[1344].name='OverlayMagnificationType' struct[1345].group_number='2040'x & struct[1345].element_number='0070'x & struct[1345].vr='CS' & struct[1345].vm='1' & struct[1345].version='dicom98' & struct[1345].name='OverlaySmoothingType' struct[1346].group_number='2040'x & struct[1346].element_number='0072'x & struct[1346].vr='CS' & struct[1346].vm='1' & struct[1346].version='dicom99' & struct[1346].name='OverlayOrImageMagnification' struct[1347].group_number='2040'x & struct[1347].element_number='0074'x & struct[1347].vr='US' & struct[1347].vm='1' & struct[1347].version='dicom99' & struct[1347].name='MagnifyToNumberOfColumns' struct[1348].group_number='2040'x & struct[1348].element_number='0080'x & struct[1348].vr='CS' & struct[1348].vm='1' & struct[1348].version='dicom98' & struct[1348].name='OverlayForegroundDensity' struct[1349].group_number='2040'x & struct[1349].element_number='0082'x & struct[1349].vr='CS' & struct[1349].vm='1' & struct[1349].version='dicom99' & struct[1349].name='OverlayBackgroundDensity' struct[1350].group_number='2040'x & struct[1350].element_number='0090'x & struct[1350].vr='CS' & struct[1350].vm='1' & struct[1350].version='dicom98' & struct[1350].name='OverlayMode' struct[1351].group_number='2040'x & struct[1351].element_number='0100'x & struct[1351].vr='CS' & struct[1351].vm='1' & struct[1351].version='dicom98' & struct[1351].name='ThresholdDensity' struct[1352].group_number='2050'x & struct[1352].element_number='0000'x & struct[1352].vr='UL' & struct[1352].vm='1' & struct[1352].version='dicom98' & struct[1352].name='PresentationLUTGroupLength' struct[1353].group_number='2050'x & struct[1353].element_number='0010'x & struct[1353].vr='SQ' & struct[1353].vm='1' & struct[1353].version='dicom98' & struct[1353].name='PresentationLUTSequence' struct[1354].group_number='2050'x & struct[1354].element_number='0020'x & struct[1354].vr='CS' & struct[1354].vm='1' & struct[1354].version='dicom98' & struct[1354].name='PresentationLUTShape' struct[1355].group_number='2050'x & struct[1355].element_number='0500'x & struct[1355].vr='SQ' & struct[1355].vm='1' & struct[1355].version='dicom98' & struct[1355].name='ReferencedPresentationLUTSequence' struct[1356].group_number='2100'x & struct[1356].element_number='0000'x & struct[1356].vr='UL' & struct[1356].vm='1' & struct[1356].version='dicom98' & struct[1356].name='PrintJobGroupLength' struct[1357].group_number='2100'x & struct[1357].element_number='0010'x & struct[1357].vr='SH' & struct[1357].vm='1' & struct[1357].version='dicom98' & struct[1357].name='PrintJobID' struct[1358].group_number='2100'x & struct[1358].element_number='0020'x & struct[1358].vr='CS' & struct[1358].vm='1' & struct[1358].version='dicom98' & struct[1358].name='ExecutionStatus' struct[1359].group_number='2100'x & struct[1359].element_number='0030'x & struct[1359].vr='CS' & struct[1359].vm='1' & struct[1359].version='dicom98' & struct[1359].name='ExecutionStatusInfo' struct[1360].group_number='2100'x & struct[1360].element_number='0040'x & struct[1360].vr='DA' & struct[1360].vm='1' & struct[1360].version='dicom98' & struct[1360].name='CreationDate' struct[1361].group_number='2100'x & struct[1361].element_number='0050'x & struct[1361].vr='TM' & struct[1361].vm='1' & struct[1361].version='dicom98' & struct[1361].name='CreationTime' struct[1362].group_number='2100'x & struct[1362].element_number='0070'x & struct[1362].vr='AE' & struct[1362].vm='1' & struct[1362].version='dicom98' & struct[1362].name='Originator' struct[1363].group_number='2100'x & struct[1363].element_number='0140'x & struct[1363].vr='AE' & struct[1363].vm='1' & struct[1363].version='dicom98' & struct[1363].name='DestinationAE' struct[1364].group_number='2100'x & struct[1364].element_number='0160'x & struct[1364].vr='SH' & struct[1364].vm='1' & struct[1364].version='dicom98' & struct[1364].name='OwnerID' struct[1365].group_number='2100'x & struct[1365].element_number='0170'x & struct[1365].vr='IS' & struct[1365].vm='1' & struct[1365].version='dicom98' & struct[1365].name='NumberOfFilms' struct[1366].group_number='2100'x & struct[1366].element_number='0500'x & struct[1366].vr='SQ' & struct[1366].vm='1' & struct[1366].version='dicom98' & struct[1366].name='ReferencedPrintJobSequence' struct[1367].group_number='2110'x & struct[1367].element_number='0000'x & struct[1367].vr='UL' & struct[1367].vm='1' & struct[1367].version='dicom98' & struct[1367].name='PrinterGroupLength' struct[1368].group_number='2110'x & struct[1368].element_number='0010'x & struct[1368].vr='CS' & struct[1368].vm='1' & struct[1368].version='dicom98' & struct[1368].name='PrinterStatus' struct[1369].group_number='2110'x & struct[1369].element_number='0020'x & struct[1369].vr='CS' & struct[1369].vm='1' & struct[1369].version='dicom98' & struct[1369].name='PrinterStatusInfo' struct[1370].group_number='2110'x & struct[1370].element_number='0030'x & struct[1370].vr='LO' & struct[1370].vm='1' & struct[1370].version='dicom98' & struct[1370].name='PrinterName' struct[1371].group_number='2110'x & struct[1371].element_number='0099'x & struct[1371].vr='SH' & struct[1371].vm='1' & struct[1371].version='dicom98' & struct[1371].name='PrintQueueID' struct[1372].group_number='2120'x & struct[1372].element_number='0000'x & struct[1372].vr='UL' & struct[1372].vm='1' & struct[1372].version='dicom98' & struct[1372].name='QueueGroupLength' struct[1373].group_number='2120'x & struct[1373].element_number='0010'x & struct[1373].vr='CS' & struct[1373].vm='1' & struct[1373].version='dicom98' & struct[1373].name='QueueStatus' struct[1374].group_number='2120'x & struct[1374].element_number='0050'x & struct[1374].vr='SQ' & struct[1374].vm='1' & struct[1374].version='dicom98' & struct[1374].name='PrintJobDescriptionSequence' struct[1376].group_number='2120'x & struct[1376].element_number='0070'x & struct[1376].vr='SQ' & struct[1376].vm='1' & struct[1376].version='dicom98' & struct[1376].name='QueueReferencedPrintJobSequence' struct[1377].group_number='2130'x & struct[1377].element_number='0000'x & struct[1377].vr='UL' & struct[1377].vm='1' & struct[1377].version='dicom98' & struct[1377].name='PrintContentGroupLength' struct[1378].group_number='2130'x & struct[1378].element_number='0010'x & struct[1378].vr='SQ' & struct[1378].vm='1' & struct[1378].version='dicom98' & struct[1378].name='PrintManagementCapabilitiesSequence' struct[1379].group_number='2130'x & struct[1379].element_number='0015'x & struct[1379].vr='SQ' & struct[1379].vm='1' & struct[1379].version='dicom98' & struct[1379].name='PrinterCharacteristicsSequence' struct[1380].group_number='2130'x & struct[1380].element_number='0030'x & struct[1380].vr='SQ' & struct[1380].vm='1' & struct[1380].version='dicom98' & struct[1380].name='FilmBoxContentSequence' struct[1381].group_number='2130'x & struct[1381].element_number='0040'x & struct[1381].vr='SQ' & struct[1381].vm='1' & struct[1381].version='dicom98' & struct[1381].name='ImageBoxContentSequence' struct[1382].group_number='2130'x & struct[1382].element_number='0050'x & struct[1382].vr='SQ' & struct[1382].vm='1' & struct[1382].version='dicom98' & struct[1382].name='AnnotationContentSequence' struct[1383].group_number='2130'x & struct[1383].element_number='0060'x & struct[1383].vr='SQ' & struct[1383].vm='1' & struct[1383].version='dicom98' & struct[1383].name='ImageOverlayBoxContentSequence' struct[1384].group_number='2130'x & struct[1384].element_number='0080'x & struct[1384].vr='SQ' & struct[1384].vm='1' & struct[1384].version='dicom98' & struct[1384].name='PresentationLUTContentSequence' struct[1385].group_number='2130'x & struct[1385].element_number='00A0'x & struct[1385].vr='SQ' & struct[1385].vm='1' & struct[1385].version='dicom98' & struct[1385].name='ProposedStudySequence' struct[1386].group_number='2130'x & struct[1386].element_number='00C0'x & struct[1386].vr='SQ' & struct[1386].vm='1' & struct[1386].version='dicom98' & struct[1386].name='OriginalImageSequence' struct[1387].group_number='3002'x & struct[1387].element_number='0000'x & struct[1387].vr='UL' & struct[1387].vm='1' & struct[1387].version='dicom98' & struct[1387].name='RTImageGroupLength' struct[1388].group_number='3002'x & struct[1388].element_number='0002'x & struct[1388].vr='SH' & struct[1388].vm='1' & struct[1388].version='dicom98' & struct[1388].name='RTImageLabel' struct[1389].group_number='3002'x & struct[1389].element_number='0003'x & struct[1389].vr='LO' & struct[1389].vm='1' & struct[1389].version='dicom98' & struct[1389].name='RTImageName' struct[1390].group_number='3002'x & struct[1390].element_number='0004'x & struct[1390].vr='ST' & struct[1390].vm='1' & struct[1390].version='dicom98' & struct[1390].name='RTImageDescription' struct[1391].group_number='3002'x & struct[1391].element_number='000A'x & struct[1391].vr='CS' & struct[1391].vm='1' & struct[1391].version='dicom98' & struct[1391].name='ReportedValuesOrigin' struct[1392].group_number='3002'x & struct[1392].element_number='000C'x & struct[1392].vr='CS' & struct[1392].vm='1' & struct[1392].version='dicom98' & struct[1392].name='RTImagePlane' struct[1393].group_number='3002'x & struct[1393].element_number='000D'x & struct[1393].vr='DS' & struct[1393].vm='3' & struct[1393].version='dicom2000' & struct[1393].name='XRayImageReceptorTranslation' struct[1394].group_number='3002'x & struct[1394].element_number='000E'x & struct[1394].vr='DS' & struct[1394].vm='1' & struct[1394].version='dicom98' & struct[1394].name='XRayImageReceptorAngle' struct[1395].group_number='3002'x & struct[1395].element_number='0010'x & struct[1395].vr='DS' & struct[1395].vm='6' & struct[1395].version='dicom98' & struct[1395].name='RTImageOrientation' struct[1396].group_number='3002'x & struct[1396].element_number='0011'x & struct[1396].vr='DS' & struct[1396].vm='2' & struct[1396].version='dicom98' & struct[1396].name='ImagePlanePixelSpacing' struct[1397].group_number='3002'x & struct[1397].element_number='0012'x & struct[1397].vr='DS' & struct[1397].vm='2' & struct[1397].version='dicom98' & struct[1397].name='RTImagePosition' struct[1398].group_number='3002'x & struct[1398].element_number='0020'x & struct[1398].vr='SH' & struct[1398].vm='1' & struct[1398].version='dicom98' & struct[1398].name='RadiationMachineName' struct[1399].group_number='3002'x & struct[1399].element_number='0022'x & struct[1399].vr='DS' & struct[1399].vm='1' & struct[1399].version='dicom98' & struct[1399].name='RadiationMachineSAD' struct[1400].group_number='3002'x & struct[1400].element_number='0024'x & struct[1400].vr='DS' & struct[1400].vm='1' & struct[1400].version='dicom98' & struct[1400].name='RadiationMachineSSD' struct[1401].group_number='3002'x & struct[1401].element_number='0026'x & struct[1401].vr='DS' & struct[1401].vm='1' & struct[1401].version='dicom98' & struct[1401].name='RTImageSID' struct[1402].group_number='3002'x & struct[1402].element_number='0028'x & struct[1402].vr='DS' & struct[1402].vm='1' & struct[1402].version='dicom98' & struct[1402].name='SourceToReferenceObjectDistance' struct[1403].group_number='3002'x & struct[1403].element_number='0029'x & struct[1403].vr='IS' & struct[1403].vm='1' & struct[1403].version='dicom98' & struct[1403].name='FractionNumber' struct[1404].group_number='3002'x & struct[1404].element_number='0030'x & struct[1404].vr='SQ' & struct[1404].vm='1' & struct[1404].version='dicom98' & struct[1404].name='ExposureSequence' struct[1405].group_number='3002'x & struct[1405].element_number='0032'x & struct[1405].vr='DS' & struct[1405].vm='1' & struct[1405].version='dicom98' & struct[1405].name='MetersetExposure' struct[1406].group_number='3002'x & struct[1406].element_number='0034'x & struct[1406].vr='DS' & struct[1406].vm='4' & struct[1406].version='dicom2001' & struct[1406].name='DiaphragmPosition' struct[1407].group_number='3004'x & struct[1407].element_number='0000'x & struct[1407].vr='UL' & struct[1407].vm='1' & struct[1407].version='dicom98' & struct[1407].name='RTDoseGroupLength' struct[1408].group_number='3004'x & struct[1408].element_number='0001'x & struct[1408].vr='CS' & struct[1408].vm='1' & struct[1408].version='dicom98' & struct[1408].name='DVHType' struct[1409].group_number='3004'x & struct[1409].element_number='0002'x & struct[1409].vr='CS' & struct[1409].vm='1' & struct[1409].version='dicom98' & struct[1409].name='DoseUnits' struct[1410].group_number='3004'x & struct[1410].element_number='0004'x & struct[1410].vr='CS' & struct[1410].vm='1' & struct[1410].version='dicom98' & struct[1410].name='DoseType' struct[1411].group_number='3004'x & struct[1411].element_number='0006'x & struct[1411].vr='LO' & struct[1411].vm='1' & struct[1411].version='dicom98' & struct[1411].name='DoseComment' struct[1412].group_number='3004'x & struct[1412].element_number='0008'x & struct[1412].vr='DS' & struct[1412].vm='3' & struct[1412].version='dicom98' & struct[1412].name='NormalizationPoint' struct[1413].group_number='3004'x & struct[1413].element_number='000A'x & struct[1413].vr='CS' & struct[1413].vm='1' & struct[1413].version='dicom98' & struct[1413].name='DoseSummationType' struct[1414].group_number='3004'x & struct[1414].element_number='000C'x & struct[1414].vr='DS' & struct[1414].vm='2-n' & struct[1414].version='dicom98' & struct[1414].name='GridFrameOffsetVector' struct[1415].group_number='3004'x & struct[1415].element_number='000E'x & struct[1415].vr='DS' & struct[1415].vm='1' & struct[1415].version='dicom98' & struct[1415].name='DoseGridScaling' struct[1416].group_number='3004'x & struct[1416].element_number='0010'x & struct[1416].vr='SQ' & struct[1416].vm='1' & struct[1416].version='dicom98' & struct[1416].name='RTDoseROISequence' struct[1417].group_number='3004'x & struct[1417].element_number='0012'x & struct[1417].vr='DS' & struct[1417].vm='1' & struct[1417].version='dicom98' & struct[1417].name='DoseValue' struct[1418].group_number='3004'x & struct[1418].element_number='0040'x & struct[1418].vr='DS' & struct[1418].vm='3' & struct[1418].version='dicom98' & struct[1418].name='DVHNormalizationPoint' struct[1419].group_number='3004'x & struct[1419].element_number='0042'x & struct[1419].vr='DS' & struct[1419].vm='1' & struct[1419].version='dicom98' & struct[1419].name='DVHNormalizationDoseValue' struct[1420].group_number='3004'x & struct[1420].element_number='0050'x & struct[1420].vr='SQ' & struct[1420].vm='1' & struct[1420].version='dicom98' & struct[1420].name='DVHSequence' struct[1421].group_number='3004'x & struct[1421].element_number='0052'x & struct[1421].vr='DS' & struct[1421].vm='1' & struct[1421].version='dicom98' & struct[1421].name='DVHDoseScaling' struct[1422].group_number='3004'x & struct[1422].element_number='0054'x & struct[1422].vr='CS' & struct[1422].vm='1' & struct[1422].version='dicom98' & struct[1422].name='DVHVolumeUnits' struct[1423].group_number='3004'x & struct[1423].element_number='0056'x & struct[1423].vr='IS' & struct[1423].vm='1' & struct[1423].version='dicom98' & struct[1423].name='DVHNumberOfBins' struct[1424].group_number='3004'x & struct[1424].element_number='0058'x & struct[1424].vr='DS' & struct[1424].vm='2-2n' & struct[1424].version='dicom98' & struct[1424].name='DVHData' struct[1425].group_number='3004'x & struct[1425].element_number='0060'x & struct[1425].vr='SQ' & struct[1425].vm='1' & struct[1425].version='dicom98' & struct[1425].name='DVHReferencedROISequence' struct[1426].group_number='3004'x & struct[1426].element_number='0062'x & struct[1426].vr='CS' & struct[1426].vm='1' & struct[1426].version='dicom98' & struct[1426].name='DVHROIContributionType' struct[1427].group_number='3004'x & struct[1427].element_number='0070'x & struct[1427].vr='DS' & struct[1427].vm='1' & struct[1427].version='dicom98' & struct[1427].name='DVHMinimumDose' struct[1428].group_number='3004'x & struct[1428].element_number='0072'x & struct[1428].vr='DS' & struct[1428].vm='1' & struct[1428].version='dicom98' & struct[1428].name='DVHMaximumDose' struct[1429].group_number='3004'x & struct[1429].element_number='0074'x & struct[1429].vr='DS' & struct[1429].vm='1' & struct[1429].version='dicom98' & struct[1429].name='DVHMeanDose' struct[1430].group_number='3006'x & struct[1430].element_number='0000'x & struct[1430].vr='UL' & struct[1430].vm='1' & struct[1430].version='dicom98' & struct[1430].name='RTStructureSetGroupLength' struct[1431].group_number='3006'x & struct[1431].element_number='0002'x & struct[1431].vr='SH' & struct[1431].vm='1' & struct[1431].version='dicom98' & struct[1431].name='StructureSetLabel' struct[1432].group_number='3006'x & struct[1432].element_number='0004'x & struct[1432].vr='LO' & struct[1432].vm='1' & struct[1432].version='dicom98' & struct[1432].name='StructureSetName' struct[1433].group_number='3006'x & struct[1433].element_number='0006'x & struct[1433].vr='ST' & struct[1433].vm='1' & struct[1433].version='dicom98' & struct[1433].name='StructureSetDescription' struct[1434].group_number='3006'x & struct[1434].element_number='0008'x & struct[1434].vr='DA' & struct[1434].vm='1' & struct[1434].version='dicom98' & struct[1434].name='StructureSetDate' struct[1435].group_number='3006'x & struct[1435].element_number='0009'x & struct[1435].vr='TM' & struct[1435].vm='1' & struct[1435].version='dicom98' & struct[1435].name='StructureSetTime' struct[1436].group_number='3006'x & struct[1436].element_number='0010'x & struct[1436].vr='SQ' & struct[1436].vm='1' & struct[1436].version='dicom98' & struct[1436].name='ReferencedFrameOfReferenceSequence' struct[1437].group_number='3006'x & struct[1437].element_number='0012'x & struct[1437].vr='SQ' & struct[1437].vm='1' & struct[1437].version='dicom98' & struct[1437].name='RTReferencedStudySequence' struct[1438].group_number='3006'x & struct[1438].element_number='0014'x & struct[1438].vr='SQ' & struct[1438].vm='1' & struct[1438].version='dicom98' & struct[1438].name='RTReferencedSeriesSequence' struct[1439].group_number='3006'x & struct[1439].element_number='0016'x & struct[1439].vr='SQ' & struct[1439].vm='1' & struct[1439].version='dicom98' & struct[1439].name='ContourImageSequence' struct[1440].group_number='3006'x & struct[1440].element_number='0020'x & struct[1440].vr='SQ' & struct[1440].vm='1' & struct[1440].version='dicom98' & struct[1440].name='StructureSetROISequence' struct[1441].group_number='3006'x & struct[1441].element_number='0022'x & struct[1441].vr='IS' & struct[1441].vm='1' & struct[1441].version='dicom98' & struct[1441].name='ROINumber' struct[1442].group_number='3006'x & struct[1442].element_number='0024'x & struct[1442].vr='UI' & struct[1442].vm='1' & struct[1442].version='dicom98' & struct[1442].name='ReferencedFrameOfReferenceUID' struct[1443].group_number='3006'x & struct[1443].element_number='0026'x & struct[1443].vr='LO' & struct[1443].vm='1' & struct[1443].version='dicom98' & struct[1443].name='ROIName' struct[1444].group_number='3006'x & struct[1444].element_number='0028'x & struct[1444].vr='ST' & struct[1444].vm='1' & struct[1444].version='dicom98' & struct[1444].name='ROIDescription' struct[1445].group_number='3006'x & struct[1445].element_number='002A'x & struct[1445].vr='IS' & struct[1445].vm='3' & struct[1445].version='dicom98' & struct[1445].name='ROIDisplayColor' struct[1446].group_number='3006'x & struct[1446].element_number='002C'x & struct[1446].vr='DS' & struct[1446].vm='1' & struct[1446].version='dicom98' & struct[1446].name='ROIVolume' struct[1447].group_number='3006'x & struct[1447].element_number='0030'x & struct[1447].vr='SQ' & struct[1447].vm='1' & struct[1447].version='dicom98' & struct[1447].name='RTRelatedROISequence' struct[1448].group_number='3006'x & struct[1448].element_number='0033'x & struct[1448].vr='CS' & struct[1448].vm='1' & struct[1448].version='dicom98' & struct[1448].name='RTROIRelationship' struct[1449].group_number='3006'x & struct[1449].element_number='0036'x & struct[1449].vr='CS' & struct[1449].vm='1' & struct[1449].version='dicom98' & struct[1449].name='ROIGenerationAlgorithm' struct[1450].group_number='3006'x & struct[1450].element_number='0038'x & struct[1450].vr='LO' & struct[1450].vm='1' & struct[1450].version='dicom98' & struct[1450].name='ROIGenerationDescription' struct[1451].group_number='3006'x & struct[1451].element_number='0039'x & struct[1451].vr='SQ' & struct[1451].vm='1' & struct[1451].version='dicom98' & struct[1451].name='ROIContourSequence' struct[1452].group_number='3006'x & struct[1452].element_number='0040'x & struct[1452].vr='SQ' & struct[1452].vm='1' & struct[1452].version='dicom98' & struct[1452].name='ContourSequence' struct[1453].group_number='3006'x & struct[1453].element_number='0042'x & struct[1453].vr='CS' & struct[1453].vm='1' & struct[1453].version='dicom98' & struct[1453].name='ContourGeometricType' struct[1454].group_number='3006'x & struct[1454].element_number='0044'x & struct[1454].vr='DS' & struct[1454].vm='1' & struct[1454].version='dicom98' & struct[1454].name='ContourSlabThickness' struct[1455].group_number='3006'x & struct[1455].element_number='0045'x & struct[1455].vr='DS' & struct[1455].vm='3' & struct[1455].version='dicom98' & struct[1455].name='ContourOffsetVector' struct[1456].group_number='3006'x & struct[1456].element_number='0046'x & struct[1456].vr='IS' & struct[1456].vm='1' & struct[1456].version='dicom98' & struct[1456].name='NumberOfContourPoints' struct[1457].group_number='3006'x & struct[1457].element_number='0048'x & struct[1457].vr='IS' & struct[1457].vm='1' & struct[1457].version='dicom2000' & struct[1457].name='ContourNumber' struct[1458].group_number='3006'x & struct[1458].element_number='0049'x & struct[1458].vr='IS' & struct[1458].vm='1-n' & struct[1458].version='dicom2000' & struct[1458].name='AttachedContours' struct[1459].group_number='3006'x & struct[1459].element_number='0050'x & struct[1459].vr='DS' & struct[1459].vm='3-3n' & struct[1459].version='dicom98' & struct[1459].name='ContourData' struct[1460].group_number='3006'x & struct[1460].element_number='0080'x & struct[1460].vr='SQ' & struct[1460].vm='1' & struct[1460].version='dicom98' & struct[1460].name='RTROIObservationsSequence' struct[1461].group_number='3006'x & struct[1461].element_number='0082'x & struct[1461].vr='IS' & struct[1461].vm='1' & struct[1461].version='dicom98' & struct[1461].name='ObservationNumber' struct[1462].group_number='3006'x & struct[1462].element_number='0084'x & struct[1462].vr='IS' & struct[1462].vm='1' & struct[1462].version='dicom98' & struct[1462].name='ReferencedROINumber' struct[1463].group_number='3006'x & struct[1463].element_number='0085'x & struct[1463].vr='SH' & struct[1463].vm='1' & struct[1463].version='dicom98' & struct[1463].name='ROIObservationLabel' struct[1464].group_number='3006'x & struct[1464].element_number='0086'x & struct[1464].vr='SQ' & struct[1464].vm='1' & struct[1464].version='dicom98' & struct[1464].name='RTROIIdentificationCodeSequence' struct[1465].group_number='3006'x & struct[1465].element_number='0088'x & struct[1465].vr='ST' & struct[1465].vm='1' & struct[1465].version='dicom98' & struct[1465].name='ROIObservationDescription' struct[1466].group_number='3006'x & struct[1466].element_number='00A0'x & struct[1466].vr='SQ' & struct[1466].vm='1' & struct[1466].version='dicom98' & struct[1466].name='RelatedRTROIObservationsSequence' struct[1467].group_number='3006'x & struct[1467].element_number='00A4'x & struct[1467].vr='CS' & struct[1467].vm='1' & struct[1467].version='dicom98' & struct[1467].name='RTROIInterpretedType' struct[1468].group_number='3006'x & struct[1468].element_number='00A6'x & struct[1468].vr='PN' & struct[1468].vm='1' & struct[1468].version='dicom98' & struct[1468].name='ROIInterpreter' struct[1469].group_number='3006'x & struct[1469].element_number='00B0'x & struct[1469].vr='SQ' & struct[1469].vm='1' & struct[1469].version='dicom98' & struct[1469].name='ROIPhysicalPropertiesSequence' struct[1470].group_number='3006'x & struct[1470].element_number='00B2'x & struct[1470].vr='CS' & struct[1470].vm='1' & struct[1470].version='dicom98' & struct[1470].name='ROIPhysicalProperty' struct[1471].group_number='3006'x & struct[1471].element_number='00B4'x & struct[1471].vr='DS' & struct[1471].vm='1' & struct[1471].version='dicom98' & struct[1471].name='ROIPhysicalPropertyValue' struct[1472].group_number='3006'x & struct[1472].element_number='00C0'x & struct[1472].vr='SQ' & struct[1472].vm='1' & struct[1472].version='dicom98' & struct[1472].name='FrameOfReferenceRelationshipSequence' struct[1473].group_number='3006'x & struct[1473].element_number='00C2'x & struct[1473].vr='UI' & struct[1473].vm='1' & struct[1473].version='dicom98' & struct[1473].name='RelatedFrameOfReferenceUID' struct[1474].group_number='3006'x & struct[1474].element_number='00C4'x & struct[1474].vr='CS' & struct[1474].vm='1' & struct[1474].version='dicom98' & struct[1474].name='FrameOfReferenceTransformationType' struct[1475].group_number='3006'x & struct[1475].element_number='00C6'x & struct[1475].vr='DS' & struct[1475].vm='16' & struct[1475].version='dicom98' & struct[1475].name='FrameOfReferenceTransformationMatrix' struct[1476].group_number='3006'x & struct[1476].element_number='00C8'x & struct[1476].vr='LO' & struct[1476].vm='1' & struct[1476].version='dicom98' & struct[1476].name='FrameOfReferenceTransformationComment' struct[1477].group_number='3008'x & struct[1477].element_number='0010'x & struct[1477].vr='SQ' & struct[1477].vm='1' & struct[1477].version='dicom99' & struct[1477].name='MeasuredDoseReferenceSequence' struct[1478].group_number='3008'x & struct[1478].element_number='0012'x & struct[1478].vr='ST' & struct[1478].vm='1' & struct[1478].version='dicom99' & struct[1478].name='MeasuredDoseDescription' struct[1479].group_number='3008'x & struct[1479].element_number='0014'x & struct[1479].vr='CS' & struct[1479].vm='1' & struct[1479].version='dicom99' & struct[1479].name='MeasuredDoseType' struct[1480].group_number='3008'x & struct[1480].element_number='0016'x & struct[1480].vr='DS' & struct[1480].vm='1' & struct[1480].version='dicom99' & struct[1480].name='MeasuredDoseValue' struct[1481].group_number='3008'x & struct[1481].element_number='0020'x & struct[1481].vr='SQ' & struct[1481].vm='1' & struct[1481].version='dicom99' & struct[1481].name='TreatmentSessionBeamSequence' struct[1482].group_number='3008'x & struct[1482].element_number='0022'x & struct[1482].vr='IS' & struct[1482].vm='1' & struct[1482].version='dicom99' & struct[1482].name='CurrentFractionNumber' struct[1483].group_number='3008'x & struct[1483].element_number='0024'x & struct[1483].vr='DA' & struct[1483].vm='1' & struct[1483].version='dicom99' & struct[1483].name='TreatmentControlPointDate' struct[1484].group_number='3008'x & struct[1484].element_number='0025'x & struct[1484].vr='TM' & struct[1484].vm='1' & struct[1484].version='dicom99' & struct[1484].name='TreatmentControlPointTime' struct[1485].group_number='3008'x & struct[1485].element_number='002A'x & struct[1485].vr='CS' & struct[1485].vm='1' & struct[1485].version='dicom99' & struct[1485].name='TreatmentTerminationStatus' struct[1486].group_number='3008'x & struct[1486].element_number='002B'x & struct[1486].vr='SH' & struct[1486].vm='1' & struct[1486].version='dicom99' & struct[1486].name='TreatmentTerminationCode' struct[1487].group_number='3008'x & struct[1487].element_number='002C'x & struct[1487].vr='CS' & struct[1487].vm='1' & struct[1487].version='dicom99' & struct[1487].name='TreatmentVerificationStatus' struct[1488].group_number='3008'x & struct[1488].element_number='0030'x & struct[1488].vr='SQ' & struct[1488].vm='1' & struct[1488].version='dicom99' & struct[1488].name='ReferencedTreatmentRecordSequence' struct[1489].group_number='3008'x & struct[1489].element_number='0032'x & struct[1489].vr='DS' & struct[1489].vm='1' & struct[1489].version='dicom99' & struct[1489].name='SpecifiedPrimaryMeterset' struct[1490].group_number='3008'x & struct[1490].element_number='0033'x & struct[1490].vr='DS' & struct[1490].vm='1' & struct[1490].version='dicom99' & struct[1490].name='SpecifiedSecondaryMeterset' struct[1491].group_number='3008'x & struct[1491].element_number='0036'x & struct[1491].vr='DS' & struct[1491].vm='1' & struct[1491].version='dicom99' & struct[1491].name='DeliveredPrimaryMeterset' struct[1492].group_number='3008'x & struct[1492].element_number='0037'x & struct[1492].vr='DS' & struct[1492].vm='1' & struct[1492].version='dicom99' & struct[1492].name='DeliveredSecondaryMeterset' struct[1493].group_number='3008'x & struct[1493].element_number='003A'x & struct[1493].vr='DS' & struct[1493].vm='1' & struct[1493].version='dicom99' & struct[1493].name='SpecifiedTreatmentTime' struct[1494].group_number='3008'x & struct[1494].element_number='003B'x & struct[1494].vr='DS' & struct[1494].vm='1' & struct[1494].version='dicom99' & struct[1494].name='DeliveredTreatmentTime' struct[1495].group_number='3008'x & struct[1495].element_number='0040'x & struct[1495].vr='SQ' & struct[1495].vm='1' & struct[1495].version='dicom99' & struct[1495].name='ControlPointDeliverySequence' struct[1496].group_number='3008'x & struct[1496].element_number='0042'x & struct[1496].vr='DS' & struct[1496].vm='1' & struct[1496].version='dicom99' & struct[1496].name='SpecifiedMeterset' struct[1497].group_number='3008'x & struct[1497].element_number='0044'x & struct[1497].vr='DS' & struct[1497].vm='1' & struct[1497].version='dicom99' & struct[1497].name='DeliveredMeterset' struct[1498].group_number='3008'x & struct[1498].element_number='0048'x & struct[1498].vr='DS' & struct[1498].vm='1' & struct[1498].version='dicom99' & struct[1498].name='DoseRateDelivered' struct[1499].group_number='3008'x & struct[1499].element_number='0050'x & struct[1499].vr='SQ' & struct[1499].vm='1' & struct[1499].version='dicom99' & struct[1499].name='TreatmentSummaryCalculatedDoseReferenceSequence' struct[1500].group_number='3008'x & struct[1500].element_number='0052'x & struct[1500].vr='DS' & struct[1500].vm='1' & struct[1500].version='dicom99' & struct[1500].name='CumulativeDoseToDoseReference' struct[1501].group_number='3008'x & struct[1501].element_number='0054'x & struct[1501].vr='DA' & struct[1501].vm='1' & struct[1501].version='dicom99' & struct[1501].name='FirstTreatmentDate' struct[1502].group_number='3008'x & struct[1502].element_number='0056'x & struct[1502].vr='DA' & struct[1502].vm='1' & struct[1502].version='dicom99' & struct[1502].name='MostRecentTreatmentDate' struct[1503].group_number='3008'x & struct[1503].element_number='005A'x & struct[1503].vr='IS' & struct[1503].vm='1' & struct[1503].version='dicom99' & struct[1503].name='NumberOfFractionsDelivered' struct[1504].group_number='3008'x & struct[1504].element_number='0060'x & struct[1504].vr='SQ' & struct[1504].vm='1' & struct[1504].version='dicom99' & struct[1504].name='OverrideSequence' struct[1505].group_number='3008'x & struct[1505].element_number='0062'x & struct[1505].vr='AT' & struct[1505].vm='1' & struct[1505].version='dicom99' & struct[1505].name='OverrideParameterPointer' struct[1506].group_number='3008'x & struct[1506].element_number='0064'x & struct[1506].vr='IS' & struct[1506].vm='1' & struct[1506].version='dicom99' & struct[1506].name='MeasuredDoseReferenceNumber' struct[1507].group_number='3008'x & struct[1507].element_number='0066'x & struct[1507].vr='ST' & struct[1507].vm='1' & struct[1507].version='dicom99' & struct[1507].name='OverrideReason' struct[1508].group_number='3008'x & struct[1508].element_number='0070'x & struct[1508].vr='SQ' & struct[1508].vm='1' & struct[1508].version='dicom99' & struct[1508].name='CalculatedDoseReferenceSequence' struct[1509].group_number='3008'x & struct[1509].element_number='0072'x & struct[1509].vr='IS' & struct[1509].vm='1' & struct[1509].version='dicom99' & struct[1509].name='CalculatedDoseReferenceNumber' struct[1510].group_number='3008'x & struct[1510].element_number='0074'x & struct[1510].vr='ST' & struct[1510].vm='1' & struct[1510].version='dicom99' & struct[1510].name='CalculatedDoseReferenceDescription' struct[1511].group_number='3008'x & struct[1511].element_number='0076'x & struct[1511].vr='DS' & struct[1511].vm='1' & struct[1511].version='dicom99' & struct[1511].name='CalculatedDoseReferenceDoseValue' struct[1512].group_number='3008'x & struct[1512].element_number='0078'x & struct[1512].vr='DS' & struct[1512].vm='1' & struct[1512].version='dicom99' & struct[1512].name='StartMeterset' struct[1513].group_number='3008'x & struct[1513].element_number='007A'x & struct[1513].vr='DS' & struct[1513].vm='1' & struct[1513].version='dicom99' & struct[1513].name='EndMeterset' struct[1514].group_number='3008'x & struct[1514].element_number='0080'x & struct[1514].vr='SQ' & struct[1514].vm='1' & struct[1514].version='dicom99' & struct[1514].name='ReferencedMeasuredDoseReferenceSequence' struct[1515].group_number='3008'x & struct[1515].element_number='0082'x & struct[1515].vr='IS' & struct[1515].vm='1' & struct[1515].version='dicom99' & struct[1515].name='ReferencedMeasuredDoseReferenceNumber' struct[1516].group_number='3008'x & struct[1516].element_number='0090'x & struct[1516].vr='SQ' & struct[1516].vm='1' & struct[1516].version='dicom99' & struct[1516].name='ReferencedCalculatedDoseReferenceSequence' struct[1517].group_number='3008'x & struct[1517].element_number='0092'x & struct[1517].vr='IS' & struct[1517].vm='1' & struct[1517].version='dicom99' & struct[1517].name='ReferencedCalculatedDoseReferenceNumber' struct[1518].group_number='3008'x & struct[1518].element_number='00A0'x & struct[1518].vr='SQ' & struct[1518].vm='1' & struct[1518].version='dicom99' & struct[1518].name='BeamLimitingDeviceLeafPairsSequence' struct[1519].group_number='3008'x & struct[1519].element_number='00B0'x & struct[1519].vr='SQ' & struct[1519].vm='1' & struct[1519].version='dicom99' & struct[1519].name='RecordedWedgeSequence' struct[1520].group_number='3008'x & struct[1520].element_number='00C0'x & struct[1520].vr='SQ' & struct[1520].vm='1' & struct[1520].version='dicom99' & struct[1520].name='RecordedCompensatorSequence' struct[1521].group_number='3008'x & struct[1521].element_number='00D0'x & struct[1521].vr='SQ' & struct[1521].vm='1' & struct[1521].version='dicom99' & struct[1521].name='RecordedBlockSequence' struct[1522].group_number='3008'x & struct[1522].element_number='00E0'x & struct[1522].vr='SQ' & struct[1522].vm='1' & struct[1522].version='dicom99' & struct[1522].name='TreatmentSummaryMeasuredDoseReferenceSequence' struct[1523].group_number='3008'x & struct[1523].element_number='0100'x & struct[1523].vr='SQ' & struct[1523].vm='1' & struct[1523].version='dicom99' & struct[1523].name='RecordedSourceSequence' struct[1524].group_number='3008'x & struct[1524].element_number='0105'x & struct[1524].vr='LO' & struct[1524].vm='1' & struct[1524].version='dicom99' & struct[1524].name='SourceSerialNumber' struct[1525].group_number='3008'x & struct[1525].element_number='0110'x & struct[1525].vr='SQ' & struct[1525].vm='1' & struct[1525].version='dicom99' & struct[1525].name='TreatmentSessionApplicationSetupSequence' struct[1526].group_number='3008'x & struct[1526].element_number='0116'x & struct[1526].vr='CS' & struct[1526].vm='1' & struct[1526].version='dicom99' & struct[1526].name='ApplicationSetupCheck' struct[1527].group_number='3008'x & struct[1527].element_number='0120'x & struct[1527].vr='SQ' & struct[1527].vm='1' & struct[1527].version='dicom99' & struct[1527].name='RecordedBrachyAccessoryDeviceSequence' struct[1528].group_number='3008'x & struct[1528].element_number='0122'x & struct[1528].vr='IS' & struct[1528].vm='1' & struct[1528].version='dicom99' & struct[1528].name='ReferencedBrachyAccessoryDeviceNumber' struct[1529].group_number='3008'x & struct[1529].element_number='0130'x & struct[1529].vr='SQ' & struct[1529].vm='1' & struct[1529].version='dicom99' & struct[1529].name='RecordedChannelSequence' struct[1530].group_number='3008'x & struct[1530].element_number='0132'x & struct[1530].vr='DS' & struct[1530].vm='1' & struct[1530].version='dicom99' & struct[1530].name='SpecifiedChannelTotalTime' struct[1531].group_number='3008'x & struct[1531].element_number='0134'x & struct[1531].vr='DS' & struct[1531].vm='1' & struct[1531].version='dicom99' & struct[1531].name='DeliveredChannelTotalTime' struct[1532].group_number='3008'x & struct[1532].element_number='0136'x & struct[1532].vr='IS' & struct[1532].vm='1' & struct[1532].version='dicom99' & struct[1532].name='SpecifiedNumberOfPulses' struct[1533].group_number='3008'x & struct[1533].element_number='0138'x & struct[1533].vr='IS' & struct[1533].vm='1' & struct[1533].version='dicom99' & struct[1533].name='DeliveredNumberOfPulses' struct[1534].group_number='3008'x & struct[1534].element_number='013A'x & struct[1534].vr='DS' & struct[1534].vm='1' & struct[1534].version='dicom99' & struct[1534].name='SpecifiedPulseRepetitionInterval' struct[1535].group_number='3008'x & struct[1535].element_number='013C'x & struct[1535].vr='DS' & struct[1535].vm='1' & struct[1535].version='dicom99' & struct[1535].name='DeliveredPulseRepetitionInterval' struct[1536].group_number='3008'x & struct[1536].element_number='0140'x & struct[1536].vr='SQ' & struct[1536].vm='1' & struct[1536].version='dicom99' & struct[1536].name='RecordedSourceApplicatorSequence' struct[1537].group_number='3008'x & struct[1537].element_number='0142'x & struct[1537].vr='IS' & struct[1537].vm='1' & struct[1537].version='dicom99' & struct[1537].name='ReferencedSourceApplicatorNumber' struct[1538].group_number='3008'x & struct[1538].element_number='0150'x & struct[1538].vr='SQ' & struct[1538].vm='1' & struct[1538].version='dicom99' & struct[1538].name='RecordedChannelShieldSequence' struct[1539].group_number='3008'x & struct[1539].element_number='0152'x & struct[1539].vr='IS' & struct[1539].vm='1' & struct[1539].version='dicom99' & struct[1539].name='ReferencedChannelShieldNumber' struct[1540].group_number='3008'x & struct[1540].element_number='0160'x & struct[1540].vr='SQ' & struct[1540].vm='1' & struct[1540].version='dicom99' & struct[1540].name='BrachyControlPointDeliveredSequence' struct[1541].group_number='3008'x & struct[1541].element_number='0162'x & struct[1541].vr='DA' & struct[1541].vm='1' & struct[1541].version='dicom99' & struct[1541].name='SafePositionExitDate' struct[1542].group_number='3008'x & struct[1542].element_number='0164'x & struct[1542].vr='TM' & struct[1542].vm='1' & struct[1542].version='dicom99' & struct[1542].name='SafePositionExitTime' struct[1543].group_number='3008'x & struct[1543].element_number='0166'x & struct[1543].vr='DA' & struct[1543].vm='1' & struct[1543].version='dicom99' & struct[1543].name='SafePositionReturnDate' struct[1544].group_number='3008'x & struct[1544].element_number='0168'x & struct[1544].vr='TM' & struct[1544].vm='1' & struct[1544].version='dicom99' & struct[1544].name='SafePositionReturnTime' struct[1545].group_number='3008'x & struct[1545].element_number='0200'x & struct[1545].vr='CS' & struct[1545].vm='1' & struct[1545].version='dicom99' & struct[1545].name='CurrentTreatmentStatus' struct[1546].group_number='3008'x & struct[1546].element_number='0202'x & struct[1546].vr='ST' & struct[1546].vm='1' & struct[1546].version='dicom99' & struct[1546].name='TreatmentStatusComment' struct[1547].group_number='3008'x & struct[1547].element_number='0220'x & struct[1547].vr='SQ' & struct[1547].vm='1' & struct[1547].version='dicom99' & struct[1547].name='FractionGroupSummarySequence' struct[1548].group_number='3008'x & struct[1548].element_number='0223'x & struct[1548].vr='IS' & struct[1548].vm='1' & struct[1548].version='dicom99' & struct[1548].name='ReferencedFractionNumber' struct[1549].group_number='3008'x & struct[1549].element_number='0224'x & struct[1549].vr='CS' & struct[1549].vm='1' & struct[1549].version='dicom99' & struct[1549].name='FractionGroupType' struct[1550].group_number='3008'x & struct[1550].element_number='0230'x & struct[1550].vr='CS' & struct[1550].vm='1' & struct[1550].version='dicom99' & struct[1550].name='BeamStopperPosition' struct[1551].group_number='3008'x & struct[1551].element_number='0240'x & struct[1551].vr='SQ' & struct[1551].vm='1' & struct[1551].version='dicom99' & struct[1551].name='FractionStatusSummarySequence' struct[1552].group_number='3008'x & struct[1552].element_number='0250'x & struct[1552].vr='DA' & struct[1552].vm='1' & struct[1552].version='dicom99' & struct[1552].name='TreatmentDate' struct[1553].group_number='3008'x & struct[1553].element_number='0251'x & struct[1553].vr='TM' & struct[1553].vm='1' & struct[1553].version='dicom99' & struct[1553].name='TreatmentTime' struct[1554].group_number='300A'x & struct[1554].element_number='0000'x & struct[1554].vr='UL' & struct[1554].vm='1' & struct[1554].version='dicom98' & struct[1554].name='RTPlanGroupLength' struct[1555].group_number='300A'x & struct[1555].element_number='0002'x & struct[1555].vr='SH' & struct[1555].vm='1' & struct[1555].version='dicom98' & struct[1555].name='RTPlanLabel' struct[1556].group_number='300A'x & struct[1556].element_number='0003'x & struct[1556].vr='LO' & struct[1556].vm='1' & struct[1556].version='dicom98' & struct[1556].name='RTPlanName' struct[1557].group_number='300A'x & struct[1557].element_number='0004'x & struct[1557].vr='ST' & struct[1557].vm='1' & struct[1557].version='dicom98' & struct[1557].name='RTPlanDescription' struct[1558].group_number='300A'x & struct[1558].element_number='0006'x & struct[1558].vr='DA' & struct[1558].vm='1' & struct[1558].version='dicom98' & struct[1558].name='RTPlanDate' struct[1559].group_number='300A'x & struct[1559].element_number='0007'x & struct[1559].vr='TM' & struct[1559].vm='1' & struct[1559].version='dicom98' & struct[1559].name='RTPlanTime' struct[1560].group_number='300A'x & struct[1560].element_number='0009'x & struct[1560].vr='LO' & struct[1560].vm='1-n' & struct[1560].version='dicom98' & struct[1560].name='TreatmentProtocols' struct[1561].group_number='300A'x & struct[1561].element_number='000A'x & struct[1561].vr='CS' & struct[1561].vm='1' & struct[1561].version='dicom98' & struct[1561].name='TreatmentIntent' struct[1562].group_number='300A'x & struct[1562].element_number='000B'x & struct[1562].vr='LO' & struct[1562].vm='1-n' & struct[1562].version='dicom98' & struct[1562].name='TreatmentSites' struct[1563].group_number='300A'x & struct[1563].element_number='000C'x & struct[1563].vr='CS' & struct[1563].vm='1' & struct[1563].version='dicom98' & struct[1563].name='RTPlanGeometry' struct[1564].group_number='300A'x & struct[1564].element_number='000E'x & struct[1564].vr='ST' & struct[1564].vm='1' & struct[1564].version='dicom98' & struct[1564].name='PrescriptionDescription' struct[1565].group_number='300A'x & struct[1565].element_number='0010'x & struct[1565].vr='SQ' & struct[1565].vm='1' & struct[1565].version='dicom98' & struct[1565].name='DoseReferenceSequence' struct[1566].group_number='300A'x & struct[1566].element_number='0012'x & struct[1566].vr='IS' & struct[1566].vm='1' & struct[1566].version='dicom98' & struct[1566].name='DoseReferenceNumber' struct[1567].group_number='300A'x & struct[1567].element_number='0014'x & struct[1567].vr='CS' & struct[1567].vm='1' & struct[1567].version='dicom98' & struct[1567].name='DoseReferenceStructureType' struct[1568].group_number='300A'x & struct[1568].element_number='0015'x & struct[1568].vr='CS' & struct[1568].vm='1' & struct[1568].version='dicom99' & struct[1568].name='NominalBeamEnergyUnit' struct[1569].group_number='300A'x & struct[1569].element_number='0016'x & struct[1569].vr='LO' & struct[1569].vm='1' & struct[1569].version='dicom98' & struct[1569].name='DoseReferenceDescription' struct[1570].group_number='300A'x & struct[1570].element_number='0018'x & struct[1570].vr='DS' & struct[1570].vm='3' & struct[1570].version='dicom98' & struct[1570].name='DoseReferencePointCoordinates' struct[1571].group_number='300A'x & struct[1571].element_number='001A'x & struct[1571].vr='DS' & struct[1571].vm='1' & struct[1571].version='dicom98' & struct[1571].name='NominalPriorDose' struct[1572].group_number='300A'x & struct[1572].element_number='0020'x & struct[1572].vr='CS' & struct[1572].vm='1' & struct[1572].version='dicom98' & struct[1572].name='DoseReferenceType' struct[1573].group_number='300A'x & struct[1573].element_number='0021'x & struct[1573].vr='DS' & struct[1573].vm='1' & struct[1573].version='dicom98' & struct[1573].name='ConstraintWeight' struct[1574].group_number='300A'x & struct[1574].element_number='0022'x & struct[1574].vr='DS' & struct[1574].vm='1' & struct[1574].version='dicom98' & struct[1574].name='DeliveryWarningDose' struct[1575].group_number='300A'x & struct[1575].element_number='0023'x & struct[1575].vr='DS' & struct[1575].vm='1' & struct[1575].version='dicom98' & struct[1575].name='DeliveryMaximumDose' struct[1576].group_number='300A'x & struct[1576].element_number='0025'x & struct[1576].vr='DS' & struct[1576].vm='1' & struct[1576].version='dicom98' & struct[1576].name='TargetMinimumDose' struct[1577].group_number='300A'x & struct[1577].element_number='0026'x & struct[1577].vr='DS' & struct[1577].vm='1' & struct[1577].version='dicom98' & struct[1577].name='TargetPrescriptionDose' struct[1578].group_number='300A'x & struct[1578].element_number='0027'x & struct[1578].vr='DS' & struct[1578].vm='1' & struct[1578].version='dicom98' & struct[1578].name='TargetMaximumDose' struct[1579].group_number='300A'x & struct[1579].element_number='0028'x & struct[1579].vr='DS' & struct[1579].vm='1' & struct[1579].version='dicom98' & struct[1579].name='TargetUnderdoseVolumeFraction' struct[1580].group_number='300A'x & struct[1580].element_number='002A'x & struct[1580].vr='DS' & struct[1580].vm='1' & struct[1580].version='dicom98' & struct[1580].name='OrganAtRiskFullVolumeDose' struct[1581].group_number='300A'x & struct[1581].element_number='002B'x & struct[1581].vr='DS' & struct[1581].vm='1' & struct[1581].version='dicom98' & struct[1581].name='OrganAtRiskLimitDose' struct[1582].group_number='300A'x & struct[1582].element_number='002C'x & struct[1582].vr='DS' & struct[1582].vm='1' & struct[1582].version='dicom98' & struct[1582].name='OrganAtRiskMaximumDose' struct[1583].group_number='300A'x & struct[1583].element_number='002D'x & struct[1583].vr='DS' & struct[1583].vm='1' & struct[1583].version='dicom98' & struct[1583].name='OrganAtRiskOverdoseVolumeFraction' struct[1584].group_number='300A'x & struct[1584].element_number='0040'x & struct[1584].vr='SQ' & struct[1584].vm='1' & struct[1584].version='dicom98' & struct[1584].name='ToleranceTableSequence' struct[1585].group_number='300A'x & struct[1585].element_number='0042'x & struct[1585].vr='IS' & struct[1585].vm='1' & struct[1585].version='dicom98' & struct[1585].name='ToleranceTableNumber' struct[1586].group_number='300A'x & struct[1586].element_number='0043'x & struct[1586].vr='SH' & struct[1586].vm='1' & struct[1586].version='dicom98' & struct[1586].name='ToleranceTableLabel' struct[1587].group_number='300A'x & struct[1587].element_number='0044'x & struct[1587].vr='DS' & struct[1587].vm='1' & struct[1587].version='dicom98' & struct[1587].name='GantryAngleTolerance' struct[1588].group_number='300A'x & struct[1588].element_number='0046'x & struct[1588].vr='DS' & struct[1588].vm='1' & struct[1588].version='dicom98' & struct[1588].name='BeamLimitingDeviceAngleTolerance' struct[1589].group_number='300A'x & struct[1589].element_number='0048'x & struct[1589].vr='SQ' & struct[1589].vm='1' & struct[1589].version='dicom98' & struct[1589].name='BeamLimitingDeviceToleranceSequence' struct[1590].group_number='300A'x & struct[1590].element_number='004A'x & struct[1590].vr='DS' & struct[1590].vm='1' & struct[1590].version='dicom98' & struct[1590].name='BeamLimitingDevicePositionTolerance' struct[1591].group_number='300A'x & struct[1591].element_number='004C'x & struct[1591].vr='DS' & struct[1591].vm='1' & struct[1591].version='dicom98' & struct[1591].name='PatientSupportAngleTolerance' struct[1592].group_number='300A'x & struct[1592].element_number='004E'x & struct[1592].vr='DS' & struct[1592].vm='1' & struct[1592].version='dicom98' & struct[1592].name='TableTopEccentricAngleTolerance' struct[1593].group_number='300A'x & struct[1593].element_number='0051'x & struct[1593].vr='DS' & struct[1593].vm='1' & struct[1593].version='dicom98' & struct[1593].name='TableTopVerticalPositionTolerance' struct[1594].group_number='300A'x & struct[1594].element_number='0052'x & struct[1594].vr='DS' & struct[1594].vm='1' & struct[1594].version='dicom98' & struct[1594].name='TableTopLongitudinalPositionTolerance' struct[1595].group_number='300A'x & struct[1595].element_number='0053'x & struct[1595].vr='DS' & struct[1595].vm='1' & struct[1595].version='dicom98' & struct[1595].name='TableTopLateralPositionTolerance' struct[1596].group_number='300A'x & struct[1596].element_number='0055'x & struct[1596].vr='CS' & struct[1596].vm='1' & struct[1596].version='dicom98' & struct[1596].name='RTPlanRelationship' struct[1597].group_number='300A'x & struct[1597].element_number='0070'x & struct[1597].vr='SQ' & struct[1597].vm='1' & struct[1597].version='dicom98' & struct[1597].name='FractionGroupSequence' struct[1598].group_number='300A'x & struct[1598].element_number='0071'x & struct[1598].vr='IS' & struct[1598].vm='1' & struct[1598].version='dicom98' & struct[1598].name='FractionGroupNumber' struct[1599].group_number='300A'x & struct[1599].element_number='0078'x & struct[1599].vr='IS' & struct[1599].vm='1' & struct[1599].version='dicom98' & struct[1599].name='NumberOfFractionsPlanned' struct[1600].group_number='300A'x & struct[1600].element_number='0079'x & struct[1600].vr='IS' & struct[1600].vm='1' & struct[1600].version='dicom2001' & struct[1600].name='NumberOfFractionPatternDigitsPerDay' struct[1601].group_number='300A'x & struct[1601].element_number='007A'x & struct[1601].vr='IS' & struct[1601].vm='1' & struct[1601].version='dicom98' & struct[1601].name='RepeatFractionCycleLength' struct[1602].group_number='300A'x & struct[1602].element_number='007B'x & struct[1602].vr='LT' & struct[1602].vm='1' & struct[1602].version='dicom98' & struct[1602].name='FractionPattern' struct[1603].group_number='300A'x & struct[1603].element_number='0080'x & struct[1603].vr='IS' & struct[1603].vm='1' & struct[1603].version='dicom98' & struct[1603].name='NumberOfBeams' struct[1604].group_number='300A'x & struct[1604].element_number='0082'x & struct[1604].vr='DS' & struct[1604].vm='3' & struct[1604].version='dicom98' & struct[1604].name='BeamDoseSpecificationPoint' struct[1605].group_number='300A'x & struct[1605].element_number='0084'x & struct[1605].vr='DS' & struct[1605].vm='1' & struct[1605].version='dicom98' & struct[1605].name='BeamDose' struct[1606].group_number='300A'x & struct[1606].element_number='0086'x & struct[1606].vr='DS' & struct[1606].vm='1' & struct[1606].version='dicom98' & struct[1606].name='BeamMeterset' struct[1607].group_number='300A'x & struct[1607].element_number='00A0'x & struct[1607].vr='IS' & struct[1607].vm='1' & struct[1607].version='dicom98' & struct[1607].name='NumberOfBrachyApplicationSetups' struct[1608].group_number='300A'x & struct[1608].element_number='00A2'x & struct[1608].vr='DS' & struct[1608].vm='3' & struct[1608].version='dicom98' & struct[1608].name='BrachyApplicationSetupDoseSpecificationPoint' struct[1609].group_number='300A'x & struct[1609].element_number='00A4'x & struct[1609].vr='DS' & struct[1609].vm='1' & struct[1609].version='dicom98' & struct[1609].name='BrachyApplicationSetupDose' struct[1610].group_number='300A'x & struct[1610].element_number='00B0'x & struct[1610].vr='SQ' & struct[1610].vm='1' & struct[1610].version='dicom98' & struct[1610].name='BeamSequence' struct[1611].group_number='300A'x & struct[1611].element_number='00B2'x & struct[1611].vr='SH' & struct[1611].vm='1' & struct[1611].version='dicom98' & struct[1611].name='TreatmentMachineName' struct[1612].group_number='300A'x & struct[1612].element_number='00B3'x & struct[1612].vr='CS' & struct[1612].vm='1' & struct[1612].version='dicom98' & struct[1612].name='PrimaryDosimeterUnit' struct[1613].group_number='300A'x & struct[1613].element_number='00B4'x & struct[1613].vr='DS' & struct[1613].vm='1' & struct[1613].version='dicom98' & struct[1613].name='SourceAxisDistance' struct[1614].group_number='300A'x & struct[1614].element_number='00B6'x & struct[1614].vr='SQ' & struct[1614].vm='1' & struct[1614].version='dicom98' & struct[1614].name='BeamLimitingDeviceSequence' struct[1615].group_number='300A'x & struct[1615].element_number='00B8'x & struct[1615].vr='CS' & struct[1615].vm='1' & struct[1615].version='dicom98' & struct[1615].name='RTBeamLimitingDeviceType' struct[1616].group_number='300A'x & struct[1616].element_number='00BA'x & struct[1616].vr='DS' & struct[1616].vm='1' & struct[1616].version='dicom98' & struct[1616].name='SourceToBeamLimitingDeviceDistance' struct[1617].group_number='300A'x & struct[1617].element_number='00BC'x & struct[1617].vr='IS' & struct[1617].vm='1' & struct[1617].version='dicom98' & struct[1617].name='NumberOfLeafJawPairs' struct[1618].group_number='300A'x & struct[1618].element_number='00BE'x & struct[1618].vr='DS' & struct[1618].vm='3-n' & struct[1618].version='dicom98' & struct[1618].name='LeafPositionBoundaries' struct[1619].group_number='300A'x & struct[1619].element_number='00C0'x & struct[1619].vr='IS' & struct[1619].vm='1' & struct[1619].version='dicom98' & struct[1619].name='BeamNumber' struct[1620].group_number='300A'x & struct[1620].element_number='00C2'x & struct[1620].vr='LO' & struct[1620].vm='1' & struct[1620].version='dicom98' & struct[1620].name='BeamName' struct[1621].group_number='300A'x & struct[1621].element_number='00C3'x & struct[1621].vr='ST' & struct[1621].vm='1' & struct[1621].version='dicom98' & struct[1621].name='BeamDescription' struct[1622].group_number='300A'x & struct[1622].element_number='00C4'x & struct[1622].vr='CS' & struct[1622].vm='1' & struct[1622].version='dicom98' & struct[1622].name='BeamType' struct[1623].group_number='300A'x & struct[1623].element_number='00C6'x & struct[1623].vr='CS' & struct[1623].vm='1' & struct[1623].version='dicom98' & struct[1623].name='RadiationType' struct[1624].group_number='300A'x & struct[1624].element_number='00C7'x & struct[1624].vr='CS' & struct[1624].vm='1' & struct[1624].version='dicom2001' & struct[1624].name='HighDoseTechniqueType' struct[1625].group_number='300A'x & struct[1625].element_number='00C8'x & struct[1625].vr='IS' & struct[1625].vm='1' & struct[1625].version='dicom98' & struct[1625].name='ReferenceImageNumber' struct[1626].group_number='300A'x & struct[1626].element_number='00CA'x & struct[1626].vr='SQ' & struct[1626].vm='1' & struct[1626].version='dicom98' & struct[1626].name='PlannedVerificationImageSequence' struct[1627].group_number='300A'x & struct[1627].element_number='00CC'x & struct[1627].vr='LO' & struct[1627].vm='1-n' & struct[1627].version='dicom98' & struct[1627].name='ImagingDeviceSpecificAcquisitionParameters' struct[1628].group_number='300A'x & struct[1628].element_number='00CE'x & struct[1628].vr='CS' & struct[1628].vm='1' & struct[1628].version='dicom98' & struct[1628].name='TreatmentDeliveryType' struct[1629].group_number='300A'x & struct[1629].element_number='00D0'x & struct[1629].vr='IS' & struct[1629].vm='1' & struct[1629].version='dicom98' & struct[1629].name='NumberOfWedges' struct[1630].group_number='300A'x & struct[1630].element_number='00D1'x & struct[1630].vr='SQ' & struct[1630].vm='1' & struct[1630].version='dicom98' & struct[1630].name='WedgeSequence' struct[1631].group_number='300A'x & struct[1631].element_number='00D2'x & struct[1631].vr='IS' & struct[1631].vm='1' & struct[1631].version='dicom98' & struct[1631].name='WedgeNumber' struct[1632].group_number='300A'x & struct[1632].element_number='00D3'x & struct[1632].vr='CS' & struct[1632].vm='1' & struct[1632].version='dicom98' & struct[1632].name='WedgeType' struct[1633].group_number='300A'x & struct[1633].element_number='00D4'x & struct[1633].vr='SH' & struct[1633].vm='1' & struct[1633].version='dicom98' & struct[1633].name='WedgeID' struct[1634].group_number='300A'x & struct[1634].element_number='00D5'x & struct[1634].vr='IS' & struct[1634].vm='1' & struct[1634].version='dicom98' & struct[1634].name='WedgeAngle' struct[1635].group_number='300A'x & struct[1635].element_number='00D6'x & struct[1635].vr='DS' & struct[1635].vm='1' & struct[1635].version='dicom98' & struct[1635].name='WedgeFactor' struct[1636].group_number='300A'x & struct[1636].element_number='00D8'x & struct[1636].vr='DS' & struct[1636].vm='1' & struct[1636].version='dicom98' & struct[1636].name='WedgeOrientation' struct[1637].group_number='300A'x & struct[1637].element_number='00DA'x & struct[1637].vr='DS' & struct[1637].vm='1' & struct[1637].version='dicom98' & struct[1637].name='SourceToWedgeTrayDistance' struct[1638].group_number='300A'x & struct[1638].element_number='00E0'x & struct[1638].vr='IS' & struct[1638].vm='1' & struct[1638].version='dicom98' & struct[1638].name='NumberOfCompensators' struct[1639].group_number='300A'x & struct[1639].element_number='00E1'x & struct[1639].vr='SH' & struct[1639].vm='1' & struct[1639].version='dicom98' & struct[1639].name='MaterialID' struct[1640].group_number='300A'x & struct[1640].element_number='00E2'x & struct[1640].vr='DS' & struct[1640].vm='1' & struct[1640].version='dicom98' & struct[1640].name='TotalCompensatorTrayFactor' struct[1641].group_number='300A'x & struct[1641].element_number='00E3'x & struct[1641].vr='SQ' & struct[1641].vm='1' & struct[1641].version='dicom98' & struct[1641].name='CompensatorSequence' struct[1642].group_number='300A'x & struct[1642].element_number='00E4'x & struct[1642].vr='IS' & struct[1642].vm='1' & struct[1642].version='dicom98' & struct[1642].name='CompensatorNumber' struct[1643].group_number='300A'x & struct[1643].element_number='00E5'x & struct[1643].vr='SH' & struct[1643].vm='1' & struct[1643].version='dicom98' & struct[1643].name='CompensatorID' struct[1644].group_number='300A'x & struct[1644].element_number='00E6'x & struct[1644].vr='DS' & struct[1644].vm='1' & struct[1644].version='dicom98' & struct[1644].name='SourceToCompensatorTrayDistance' struct[1645].group_number='300A'x & struct[1645].element_number='00E7'x & struct[1645].vr='IS' & struct[1645].vm='1' & struct[1645].version='dicom98' & struct[1645].name='CompensatorRows' struct[1646].group_number='300A'x & struct[1646].element_number='00E8'x & struct[1646].vr='IS' & struct[1646].vm='1' & struct[1646].version='dicom98' & struct[1646].name='CompensatorColumns' struct[1647].group_number='300A'x & struct[1647].element_number='00E9'x & struct[1647].vr='DS' & struct[1647].vm='2' & struct[1647].version='dicom98' & struct[1647].name='CompensatorPixelSpacing' struct[1648].group_number='300A'x & struct[1648].element_number='00EA'x & struct[1648].vr='DS' & struct[1648].vm='2' & struct[1648].version='dicom98' & struct[1648].name='CompensatorPosition' struct[1649].group_number='300A'x & struct[1649].element_number='00EB'x & struct[1649].vr='DS' & struct[1649].vm='1-n' & struct[1649].version='dicom98' & struct[1649].name='CompensatorTransmissionData' struct[1650].group_number='300A'x & struct[1650].element_number='00EC'x & struct[1650].vr='DS' & struct[1650].vm='1-n' & struct[1650].version='dicom98' & struct[1650].name='CompensatorThicknessData' struct[1651].group_number='300A'x & struct[1651].element_number='00ED'x & struct[1651].vr='IS' & struct[1651].vm='1' & struct[1651].version='dicom98' & struct[1651].name='NumberOfBoli' struct[1652].group_number='300A'x & struct[1652].element_number='00EE'x & struct[1652].vr='CS' & struct[1652].vm='1' & struct[1652].version='dicom99' & struct[1652].name='CompensatorType' struct[1653].group_number='300A'x & struct[1653].element_number='00F0'x & struct[1653].vr='IS' & struct[1653].vm='1' & struct[1653].version='dicom98' & struct[1653].name='NumberOfBlocks' struct[1654].group_number='300A'x & struct[1654].element_number='00F2'x & struct[1654].vr='DS' & struct[1654].vm='1' & struct[1654].version='dicom98' & struct[1654].name='TotalBlockTrayFactor' struct[1655].group_number='300A'x & struct[1655].element_number='00F4'x & struct[1655].vr='SQ' & struct[1655].vm='1' & struct[1655].version='dicom98' & struct[1655].name='BlockSequence' struct[1656].group_number='300A'x & struct[1656].element_number='00F5'x & struct[1656].vr='SH' & struct[1656].vm='1' & struct[1656].version='dicom98' & struct[1656].name='BlockTrayID' struct[1657].group_number='300A'x & struct[1657].element_number='00F6'x & struct[1657].vr='DS' & struct[1657].vm='1' & struct[1657].version='dicom98' & struct[1657].name='SourceToBlockTrayDistance' struct[1658].group_number='300A'x & struct[1658].element_number='00F8'x & struct[1658].vr='CS' & struct[1658].vm='1' & struct[1658].version='dicom98' & struct[1658].name='BlockType' struct[1659].group_number='300A'x & struct[1659].element_number='00FA'x & struct[1659].vr='CS' & struct[1659].vm='1' & struct[1659].version='dicom98' & struct[1659].name='BlockDivergence' struct[1660].group_number='300A'x & struct[1660].element_number='00FB'x & struct[1660].vr='CS' & struct[1660].vm='1' & struct[1660].version='dicom2003' & struct[1660].name='BlockMountingPosition' struct[1661].group_number='300A'x & struct[1661].element_number='00FC'x & struct[1661].vr='IS' & struct[1661].vm='1' & struct[1661].version='dicom98' & struct[1661].name='BlockNumber' struct[1662].group_number='300A'x & struct[1662].element_number='00FE'x & struct[1662].vr='LO' & struct[1662].vm='1' & struct[1662].version='dicom98' & struct[1662].name='BlockName' struct[1663].group_number='300A'x & struct[1663].element_number='0100'x & struct[1663].vr='DS' & struct[1663].vm='1' & struct[1663].version='dicom98' & struct[1663].name='BlockThickness' struct[1664].group_number='300A'x & struct[1664].element_number='0102'x & struct[1664].vr='DS' & struct[1664].vm='1' & struct[1664].version='dicom98' & struct[1664].name='BlockTransmission' struct[1665].group_number='300A'x & struct[1665].element_number='0104'x & struct[1665].vr='IS' & struct[1665].vm='1' & struct[1665].version='dicom98' & struct[1665].name='BlockNumberOfPoints' struct[1666].group_number='300A'x & struct[1666].element_number='0106'x & struct[1666].vr='DS' & struct[1666].vm='2-2n' & struct[1666].version='dicom98' & struct[1666].name='BlockData' struct[1667].group_number='300A'x & struct[1667].element_number='0107'x & struct[1667].vr='SQ' & struct[1667].vm='1' & struct[1667].version='dicom98' & struct[1667].name='ApplicatorSequence' struct[1668].group_number='300A'x & struct[1668].element_number='0108'x & struct[1668].vr='SH' & struct[1668].vm='1' & struct[1668].version='dicom98' & struct[1668].name='ApplicatorID' struct[1669].group_number='300A'x & struct[1669].element_number='0109'x & struct[1669].vr='CS' & struct[1669].vm='1' & struct[1669].version='dicom98' & struct[1669].name='ApplicatorType' struct[1670].group_number='300A'x & struct[1670].element_number='010A'x & struct[1670].vr='LO' & struct[1670].vm='1' & struct[1670].version='dicom98' & struct[1670].name='ApplicatorDescription' struct[1671].group_number='300A'x & struct[1671].element_number='010C'x & struct[1671].vr='DS' & struct[1671].vm='1' & struct[1671].version='dicom98' & struct[1671].name='CumulativeDoseReferenceCoefficient' struct[1672].group_number='300A'x & struct[1672].element_number='010E'x & struct[1672].vr='DS' & struct[1672].vm='1' & struct[1672].version='dicom98' & struct[1672].name='FinalCumulativeMetersetWeight' struct[1673].group_number='300A'x & struct[1673].element_number='0110'x & struct[1673].vr='IS' & struct[1673].vm='1' & struct[1673].version='dicom98' & struct[1673].name='NumberOfControlPoints' struct[1674].group_number='300A'x & struct[1674].element_number='0111'x & struct[1674].vr='SQ' & struct[1674].vm='1' & struct[1674].version='dicom98' & struct[1674].name='ControlPointSequence' struct[1675].group_number='300A'x & struct[1675].element_number='0112'x & struct[1675].vr='IS' & struct[1675].vm='1' & struct[1675].version='dicom98' & struct[1675].name='ControlPointIndex' struct[1676].group_number='300A'x & struct[1676].element_number='0114'x & struct[1676].vr='DS' & struct[1676].vm='1' & struct[1676].version='dicom98' & struct[1676].name='NominalBeamEnergy' struct[1677].group_number='300A'x & struct[1677].element_number='0115'x & struct[1677].vr='DS' & struct[1677].vm='1' & struct[1677].version='dicom98' & struct[1677].name='DoseRateSet' struct[1678].group_number='300A'x & struct[1678].element_number='0116'x & struct[1678].vr='SQ' & struct[1678].vm='1' & struct[1678].version='dicom98' & struct[1678].name='WedgePositionSequence' struct[1679].group_number='300A'x & struct[1679].element_number='0118'x & struct[1679].vr='CS' & struct[1679].vm='1' & struct[1679].version='dicom98' & struct[1679].name='WedgePosition' struct[1680].group_number='300A'x & struct[1680].element_number='011A'x & struct[1680].vr='SQ' & struct[1680].vm='1' & struct[1680].version='dicom98' & struct[1680].name='BeamLimitingDevicePositionSequence' struct[1681].group_number='300A'x & struct[1681].element_number='011C'x & struct[1681].vr='DS' & struct[1681].vm='2-2n' & struct[1681].version='dicom98' & struct[1681].name='LeafJawPositions' struct[1682].group_number='300A'x & struct[1682].element_number='011E'x & struct[1682].vr='DS' & struct[1682].vm='1' & struct[1682].version='dicom98' & struct[1682].name='GantryAngle' struct[1683].group_number='300A'x & struct[1683].element_number='011F'x & struct[1683].vr='CS' & struct[1683].vm='1' & struct[1683].version='dicom98' & struct[1683].name='GantryRotationDirection' struct[1684].group_number='300A'x & struct[1684].element_number='0120'x & struct[1684].vr='DS' & struct[1684].vm='1' & struct[1684].version='dicom98' & struct[1684].name='BeamLimitingDeviceAngle' struct[1685].group_number='300A'x & struct[1685].element_number='0121'x & struct[1685].vr='CS' & struct[1685].vm='1' & struct[1685].version='dicom98' & struct[1685].name='BeamLimitingDeviceRotationDirection' struct[1686].group_number='300A'x & struct[1686].element_number='0122'x & struct[1686].vr='DS' & struct[1686].vm='1' & struct[1686].version='dicom98' & struct[1686].name='PatientSupportAngle' struct[1687].group_number='300A'x & struct[1687].element_number='0123'x & struct[1687].vr='CS' & struct[1687].vm='1' & struct[1687].version='dicom98' & struct[1687].name='PatientSupportRotationDirection' struct[1688].group_number='300A'x & struct[1688].element_number='0124'x & struct[1688].vr='DS' & struct[1688].vm='1' & struct[1688].version='dicom98' & struct[1688].name='TableTopEccentricAxisDistance' struct[1689].group_number='300A'x & struct[1689].element_number='0125'x & struct[1689].vr='DS' & struct[1689].vm='1' & struct[1689].version='dicom98' & struct[1689].name='TableTopEccentricAngle' struct[1690].group_number='300A'x & struct[1690].element_number='0126'x & struct[1690].vr='CS' & struct[1690].vm='1' & struct[1690].version='dicom98' & struct[1690].name='TableTopEccentricRotationDirection' struct[1691].group_number='300A'x & struct[1691].element_number='0128'x & struct[1691].vr='DS' & struct[1691].vm='1' & struct[1691].version='dicom98' & struct[1691].name='TableTopVerticalPosition' struct[1692].group_number='300A'x & struct[1692].element_number='0129'x & struct[1692].vr='DS' & struct[1692].vm='1' & struct[1692].version='dicom98' & struct[1692].name='TableTopLongitudinalPosition' struct[1693].group_number='300A'x & struct[1693].element_number='012A'x & struct[1693].vr='DS' & struct[1693].vm='1' & struct[1693].version='dicom98' & struct[1693].name='TableTopLateralPosition' struct[1694].group_number='300A'x & struct[1694].element_number='012C'x & struct[1694].vr='DS' & struct[1694].vm='3' & struct[1694].version='dicom98' & struct[1694].name='IsocenterPosition' struct[1695].group_number='300A'x & struct[1695].element_number='012E'x & struct[1695].vr='DS' & struct[1695].vm='3' & struct[1695].version='dicom98' & struct[1695].name='SurfaceEntryPoint' struct[1696].group_number='300A'x & struct[1696].element_number='0130'x & struct[1696].vr='DS' & struct[1696].vm='1' & struct[1696].version='dicom98' & struct[1696].name='SourceToSurfaceDistance' struct[1697].group_number='300A'x & struct[1697].element_number='0134'x & struct[1697].vr='DS' & struct[1697].vm='1' & struct[1697].version='dicom98' & struct[1697].name='CumulativeMetersetWeight' struct[1698].group_number='300A'x & struct[1698].element_number='0180'x & struct[1698].vr='SQ' & struct[1698].vm='1' & struct[1698].version='dicom98' & struct[1698].name='PatientSetupSequence' struct[1699].group_number='300A'x & struct[1699].element_number='0182'x & struct[1699].vr='IS' & struct[1699].vm='1' & struct[1699].version='dicom98' & struct[1699].name='PatientSetupNumber' struct[1700].group_number='300A'x & struct[1700].element_number='0184'x & struct[1700].vr='LO' & struct[1700].vm='1' & struct[1700].version='dicom98' & struct[1700].name='PatientAdditionalPosition' struct[1701].group_number='300A'x & struct[1701].element_number='0190'x & struct[1701].vr='SQ' & struct[1701].vm='1' & struct[1701].version='dicom98' & struct[1701].name='FixationDeviceSequence' struct[1702].group_number='300A'x & struct[1702].element_number='0192'x & struct[1702].vr='CS' & struct[1702].vm='1' & struct[1702].version='dicom98' & struct[1702].name='FixationDeviceType' struct[1703].group_number='300A'x & struct[1703].element_number='0194'x & struct[1703].vr='SH' & struct[1703].vm='1' & struct[1703].version='dicom98' & struct[1703].name='FixationDeviceLabel' struct[1704].group_number='300A'x & struct[1704].element_number='0196'x & struct[1704].vr='ST' & struct[1704].vm='1' & struct[1704].version='dicom98' & struct[1704].name='FixationDeviceDescription' struct[1705].group_number='300A'x & struct[1705].element_number='0198'x & struct[1705].vr='SH' & struct[1705].vm='1' & struct[1705].version='dicom98' & struct[1705].name='FixationDevicePosition' struct[1706].group_number='300A'x & struct[1706].element_number='01A0'x & struct[1706].vr='SQ' & struct[1706].vm='1' & struct[1706].version='dicom98' & struct[1706].name='ShieldingDeviceSequence' struct[1707].group_number='300A'x & struct[1707].element_number='01A2'x & struct[1707].vr='CS' & struct[1707].vm='1' & struct[1707].version='dicom98' & struct[1707].name='ShieldingDeviceType' struct[1708].group_number='300A'x & struct[1708].element_number='01A4'x & struct[1708].vr='SH' & struct[1708].vm='1' & struct[1708].version='dicom98' & struct[1708].name='ShieldingDeviceLabel' struct[1709].group_number='300A'x & struct[1709].element_number='01A6'x & struct[1709].vr='ST' & struct[1709].vm='1' & struct[1709].version='dicom98' & struct[1709].name='ShieldingDeviceDescription' struct[1710].group_number='300A'x & struct[1710].element_number='01A8'x & struct[1710].vr='SH' & struct[1710].vm='1' & struct[1710].version='dicom98' & struct[1710].name='ShieldingDevicePosition' struct[1711].group_number='300A'x & struct[1711].element_number='01B0'x & struct[1711].vr='CS' & struct[1711].vm='1' & struct[1711].version='dicom98' & struct[1711].name='SetupTechnique' struct[1712].group_number='300A'x & struct[1712].element_number='01B2'x & struct[1712].vr='ST' & struct[1712].vm='1' & struct[1712].version='dicom98' & struct[1712].name='SetupTechniqueDescription' struct[1713].group_number='300A'x & struct[1713].element_number='01B4'x & struct[1713].vr='SQ' & struct[1713].vm='1' & struct[1713].version='dicom98' & struct[1713].name='SetupDeviceSequence' struct[1714].group_number='300A'x & struct[1714].element_number='01B6'x & struct[1714].vr='CS' & struct[1714].vm='1' & struct[1714].version='dicom98' & struct[1714].name='SetupDeviceType' struct[1715].group_number='300A'x & struct[1715].element_number='01B8'x & struct[1715].vr='SH' & struct[1715].vm='1' & struct[1715].version='dicom98' & struct[1715].name='SetupDeviceLabel' struct[1716].group_number='300A'x & struct[1716].element_number='01BA'x & struct[1716].vr='ST' & struct[1716].vm='1' & struct[1716].version='dicom98' & struct[1716].name='SetupDeviceDescription' struct[1717].group_number='300A'x & struct[1717].element_number='01BC'x & struct[1717].vr='DS' & struct[1717].vm='1' & struct[1717].version='dicom98' & struct[1717].name='SetupDeviceParameter' struct[1718].group_number='300A'x & struct[1718].element_number='01D0'x & struct[1718].vr='ST' & struct[1718].vm='1' & struct[1718].version='dicom98' & struct[1718].name='SetupReferenceDescription' struct[1719].group_number='300A'x & struct[1719].element_number='01D2'x & struct[1719].vr='DS' & struct[1719].vm='1' & struct[1719].version='dicom98' & struct[1719].name='TableTopVerticalSetupDisplacement' struct[1720].group_number='300A'x & struct[1720].element_number='01D4'x & struct[1720].vr='DS' & struct[1720].vm='1' & struct[1720].version='dicom98' & struct[1720].name='TableTopLongitudinalSetupDisplacement' struct[1721].group_number='300A'x & struct[1721].element_number='01D6'x & struct[1721].vr='DS' & struct[1721].vm='1' & struct[1721].version='dicom98' & struct[1721].name='TableTopLateralSetupDisplacement' struct[1722].group_number='300A'x & struct[1722].element_number='0200'x & struct[1722].vr='CS' & struct[1722].vm='1' & struct[1722].version='dicom98' & struct[1722].name='BrachyTreatmentTechnique' struct[1723].group_number='300A'x & struct[1723].element_number='0202'x & struct[1723].vr='CS' & struct[1723].vm='1' & struct[1723].version='dicom98' & struct[1723].name='BrachyTreatmentType' struct[1724].group_number='300A'x & struct[1724].element_number='0206'x & struct[1724].vr='SQ' & struct[1724].vm='1' & struct[1724].version='dicom98' & struct[1724].name='TreatmentMachineSequence' struct[1725].group_number='300A'x & struct[1725].element_number='0210'x & struct[1725].vr='SQ' & struct[1725].vm='1' & struct[1725].version='dicom98' & struct[1725].name='SourceSequence' struct[1726].group_number='300A'x & struct[1726].element_number='0212'x & struct[1726].vr='IS' & struct[1726].vm='1' & struct[1726].version='dicom98' & struct[1726].name='SourceNumber' struct[1727].group_number='300A'x & struct[1727].element_number='0214'x & struct[1727].vr='CS' & struct[1727].vm='1' & struct[1727].version='dicom98' & struct[1727].name='SourceType' struct[1728].group_number='300A'x & struct[1728].element_number='0216'x & struct[1728].vr='LO' & struct[1728].vm='1' & struct[1728].version='dicom98' & struct[1728].name='SourceManufacturer' struct[1729].group_number='300A'x & struct[1729].element_number='0218'x & struct[1729].vr='DS' & struct[1729].vm='1' & struct[1729].version='dicom98' & struct[1729].name='ActiveSourceDiameter' struct[1730].group_number='300A'x & struct[1730].element_number='021A'x & struct[1730].vr='DS' & struct[1730].vm='1' & struct[1730].version='dicom98' & struct[1730].name='ActiveSourceLength' struct[1731].group_number='300A'x & struct[1731].element_number='0222'x & struct[1731].vr='DS' & struct[1731].vm='1' & struct[1731].version='dicom98' & struct[1731].name='SourceEncapsulationNominalThickness' struct[1732].group_number='300A'x & struct[1732].element_number='0224'x & struct[1732].vr='DS' & struct[1732].vm='1' & struct[1732].version='dicom98' & struct[1732].name='SourceEncapsulationNominalTransmission' struct[1733].group_number='300A'x & struct[1733].element_number='0226'x & struct[1733].vr='LO' & struct[1733].vm='1' & struct[1733].version='dicom98' & struct[1733].name='SourceIsotopeName' struct[1734].group_number='300A'x & struct[1734].element_number='0228'x & struct[1734].vr='DS' & struct[1734].vm='1' & struct[1734].version='dicom98' & struct[1734].name='SourceIsotopeHalfLife' struct[1735].group_number='300A'x & struct[1735].element_number='022A'x & struct[1735].vr='DS' & struct[1735].vm='1' & struct[1735].version='dicom98' & struct[1735].name='ReferenceAirKermaRate' struct[1736].group_number='300A'x & struct[1736].element_number='022C'x & struct[1736].vr='DA' & struct[1736].vm='1' & struct[1736].version='dicom98' & struct[1736].name='AirKermaRateReferenceDate' struct[1737].group_number='300A'x & struct[1737].element_number='022E'x & struct[1737].vr='TM' & struct[1737].vm='1' & struct[1737].version='dicom98' & struct[1737].name='AirKermaRateReferenceTime' struct[1738].group_number='300A'x & struct[1738].element_number='0230'x & struct[1738].vr='SQ' & struct[1738].vm='1' & struct[1738].version='dicom98' & struct[1738].name='ApplicationSetupSequence' struct[1739].group_number='300A'x & struct[1739].element_number='0232'x & struct[1739].vr='CS' & struct[1739].vm='1' & struct[1739].version='dicom98' & struct[1739].name='ApplicationSetupType' struct[1740].group_number='300A'x & struct[1740].element_number='0234'x & struct[1740].vr='IS' & struct[1740].vm='1' & struct[1740].version='dicom98' & struct[1740].name='ApplicationSetupNumber' struct[1741].group_number='300A'x & struct[1741].element_number='0236'x & struct[1741].vr='LO' & struct[1741].vm='1' & struct[1741].version='dicom98' & struct[1741].name='ApplicationSetupName' struct[1742].group_number='300A'x & struct[1742].element_number='0238'x & struct[1742].vr='LO' & struct[1742].vm='1' & struct[1742].version='dicom98' & struct[1742].name='ApplicationSetupManufacturer' struct[1743].group_number='300A'x & struct[1743].element_number='0240'x & struct[1743].vr='IS' & struct[1743].vm='1' & struct[1743].version='dicom98' & struct[1743].name='TemplateNumber' struct[1744].group_number='300A'x & struct[1744].element_number='0242'x & struct[1744].vr='SH' & struct[1744].vm='1' & struct[1744].version='dicom98' & struct[1744].name='TemplateType' struct[1745].group_number='300A'x & struct[1745].element_number='0244'x & struct[1745].vr='LO' & struct[1745].vm='1' & struct[1745].version='dicom98' & struct[1745].name='TemplateName' struct[1746].group_number='300A'x & struct[1746].element_number='0250'x & struct[1746].vr='DS' & struct[1746].vm='1' & struct[1746].version='dicom98' & struct[1746].name='TotalReferenceAirKerma' struct[1747].group_number='300A'x & struct[1747].element_number='0260'x & struct[1747].vr='SQ' & struct[1747].vm='1' & struct[1747].version='dicom98' & struct[1747].name='BrachyAccessoryDeviceSequence' struct[1748].group_number='300A'x & struct[1748].element_number='0262'x & struct[1748].vr='IS' & struct[1748].vm='1' & struct[1748].version='dicom98' & struct[1748].name='BrachyAccessoryDeviceNumber' struct[1749].group_number='300A'x & struct[1749].element_number='0263'x & struct[1749].vr='SH' & struct[1749].vm='1' & struct[1749].version='dicom98' & struct[1749].name='BrachyAccessoryDeviceID' struct[1750].group_number='300A'x & struct[1750].element_number='0264'x & struct[1750].vr='CS' & struct[1750].vm='1' & struct[1750].version='dicom98' & struct[1750].name='BrachyAccessoryDeviceType' struct[1751].group_number='300A'x & struct[1751].element_number='0266'x & struct[1751].vr='LO' & struct[1751].vm='1' & struct[1751].version='dicom98' & struct[1751].name='BrachyAccessoryDeviceName' struct[1752].group_number='300A'x & struct[1752].element_number='026A'x & struct[1752].vr='DS' & struct[1752].vm='1' & struct[1752].version='dicom98' & struct[1752].name='BrachyAccessoryDeviceNominalThickness' struct[1753].group_number='300A'x & struct[1753].element_number='026C'x & struct[1753].vr='DS' & struct[1753].vm='1' & struct[1753].version='dicom98' & struct[1753].name='BrachyAccessoryDeviceNominalTransmission' struct[1754].group_number='300A'x & struct[1754].element_number='0280'x & struct[1754].vr='SQ' & struct[1754].vm='1' & struct[1754].version='dicom98' & struct[1754].name='ChannelSequence' struct[1755].group_number='300A'x & struct[1755].element_number='0282'x & struct[1755].vr='IS' & struct[1755].vm='1' & struct[1755].version='dicom98' & struct[1755].name='ChannelNumber' struct[1756].group_number='300A'x & struct[1756].element_number='0284'x & struct[1756].vr='DS' & struct[1756].vm='1' & struct[1756].version='dicom98' & struct[1756].name='ChannelLength' struct[1757].group_number='300A'x & struct[1757].element_number='0286'x & struct[1757].vr='DS' & struct[1757].vm='1' & struct[1757].version='dicom98' & struct[1757].name='ChannelTotalTime' struct[1758].group_number='300A'x & struct[1758].element_number='0288'x & struct[1758].vr='CS' & struct[1758].vm='1' & struct[1758].version='dicom98' & struct[1758].name='SourceMovementType' struct[1759].group_number='300A'x & struct[1759].element_number='028A'x & struct[1759].vr='IS' & struct[1759].vm='1' & struct[1759].version='dicom98' & struct[1759].name='NumberOfPulses' struct[1760].group_number='300A'x & struct[1760].element_number='028C'x & struct[1760].vr='DS' & struct[1760].vm='1' & struct[1760].version='dicom98' & struct[1760].name='PulseRepetitionInterval' struct[1761].group_number='300A'x & struct[1761].element_number='0290'x & struct[1761].vr='IS' & struct[1761].vm='1' & struct[1761].version='dicom98' & struct[1761].name='SourceApplicatorNumber' struct[1762].group_number='300A'x & struct[1762].element_number='0291'x & struct[1762].vr='SH' & struct[1762].vm='1' & struct[1762].version='dicom98' & struct[1762].name='SourceApplicatorID' struct[1763].group_number='300A'x & struct[1763].element_number='0292'x & struct[1763].vr='CS' & struct[1763].vm='1' & struct[1763].version='dicom98' & struct[1763].name='SourceApplicatorType' struct[1764].group_number='300A'x & struct[1764].element_number='0294'x & struct[1764].vr='LO' & struct[1764].vm='1' & struct[1764].version='dicom98' & struct[1764].name='SourceApplicatorName' struct[1765].group_number='300A'x & struct[1765].element_number='0296'x & struct[1765].vr='DS' & struct[1765].vm='1' & struct[1765].version='dicom98' & struct[1765].name='SourceApplicatorLength' struct[1766].group_number='300A'x & struct[1766].element_number='0298'x & struct[1766].vr='LO' & struct[1766].vm='1' & struct[1766].version='dicom98' & struct[1766].name='SourceApplicatorManufacturer' struct[1767].group_number='300A'x & struct[1767].element_number='029C'x & struct[1767].vr='DS' & struct[1767].vm='1' & struct[1767].version='dicom98' & struct[1767].name='SourceApplicatorWallNominalThickness' struct[1768].group_number='300A'x & struct[1768].element_number='029E'x & struct[1768].vr='DS' & struct[1768].vm='1' & struct[1768].version='dicom98' & struct[1768].name='SourceApplicatorWallNominalTransmission' struct[1769].group_number='300A'x & struct[1769].element_number='02A0'x & struct[1769].vr='DS' & struct[1769].vm='1' & struct[1769].version='dicom98' & struct[1769].name='SourceApplicatorStepSize' struct[1770].group_number='300A'x & struct[1770].element_number='02A2'x & struct[1770].vr='IS' & struct[1770].vm='1' & struct[1770].version='dicom98' & struct[1770].name='TransferTubeNumber' struct[1771].group_number='300A'x & struct[1771].element_number='02A4'x & struct[1771].vr='DS' & struct[1771].vm='1' & struct[1771].version='dicom98' & struct[1771].name='TransferTubeLength' struct[1772].group_number='300A'x & struct[1772].element_number='02B0'x & struct[1772].vr='SQ' & struct[1772].vm='1' & struct[1772].version='dicom98' & struct[1772].name='ChannelShieldSequence' struct[1773].group_number='300A'x & struct[1773].element_number='02B2'x & struct[1773].vr='IS' & struct[1773].vm='1' & struct[1773].version='dicom98' & struct[1773].name='ChannelShieldNumber' struct[1774].group_number='300A'x & struct[1774].element_number='02B3'x & struct[1774].vr='SH' & struct[1774].vm='1' & struct[1774].version='dicom98' & struct[1774].name='ChannelShieldID' struct[1775].group_number='300A'x & struct[1775].element_number='02B4'x & struct[1775].vr='LO' & struct[1775].vm='1' & struct[1775].version='dicom98' & struct[1775].name='ChannelShieldName' struct[1776].group_number='300A'x & struct[1776].element_number='02B8'x & struct[1776].vr='DS' & struct[1776].vm='1' & struct[1776].version='dicom98' & struct[1776].name='ChannelShieldNominalThickness' struct[1777].group_number='300A'x & struct[1777].element_number='02BA'x & struct[1777].vr='DS' & struct[1777].vm='1' & struct[1777].version='dicom98' & struct[1777].name='ChannelShieldNominalTransmission' struct[1778].group_number='300A'x & struct[1778].element_number='02C8'x & struct[1778].vr='DS' & struct[1778].vm='1' & struct[1778].version='dicom98' & struct[1778].name='FinalCumulativeTimeWeight' struct[1779].group_number='300A'x & struct[1779].element_number='02D0'x & struct[1779].vr='SQ' & struct[1779].vm='1' & struct[1779].version='dicom98' & struct[1779].name='BrachyControlPointSequence' struct[1780].group_number='300A'x & struct[1780].element_number='02D2'x & struct[1780].vr='DS' & struct[1780].vm='1' & struct[1780].version='dicom98' & struct[1780].name='ControlPointRelativePosition' struct[1781].group_number='300A'x & struct[1781].element_number='02D4'x & struct[1781].vr='DS' & struct[1781].vm='3' & struct[1781].version='dicom98' & struct[1781].name='ControlPoint3DPosition' struct[1782].group_number='300A'x & struct[1782].element_number='02D6'x & struct[1782].vr='DS' & struct[1782].vm='1' & struct[1782].version='dicom98' & struct[1782].name='CumulativeTimeWeight' struct[1783].group_number='300A'x & struct[1783].element_number='02E0'x & struct[1783].vr='CS' & struct[1783].vm='1' & struct[1783].version='dicom2003' & struct[1783].name='CompensatorDivergence' struct[1784].group_number='300A'x & struct[1784].element_number='02E1'x & struct[1784].vr='CS' & struct[1784].vm='1' & struct[1784].version='dicom2003' & struct[1784].name='CompensatorMountingPosition' struct[1785].group_number='300A'x & struct[1785].element_number='02E2'x & struct[1785].vr='DS' & struct[1785].vm='1-n' & struct[1785].version='dicom2003' & struct[1785].name='SourceToCompensatorDistance' struct[1786].group_number='300C'x & struct[1786].element_number='0000'x & struct[1786].vr='UL' & struct[1786].vm='1' & struct[1786].version='dicom98' & struct[1786].name='RTRelationshipGroupLength' struct[1787].group_number='300C'x & struct[1787].element_number='0002'x & struct[1787].vr='SQ' & struct[1787].vm='1' & struct[1787].version='dicom98' & struct[1787].name='ReferencedRTPlanSequence' struct[1788].group_number='300C'x & struct[1788].element_number='0004'x & struct[1788].vr='SQ' & struct[1788].vm='1' & struct[1788].version='dicom98' & struct[1788].name='ReferencedBeamSequence' struct[1789].group_number='300C'x & struct[1789].element_number='0006'x & struct[1789].vr='IS' & struct[1789].vm='1' & struct[1789].version='dicom98' & struct[1789].name='ReferencedBeamNumber' struct[1790].group_number='300C'x & struct[1790].element_number='0007'x & struct[1790].vr='IS' & struct[1790].vm='1' & struct[1790].version='dicom98' & struct[1790].name='ReferencedReferenceImageNumber' struct[1791].group_number='300C'x & struct[1791].element_number='0008'x & struct[1791].vr='DS' & struct[1791].vm='1' & struct[1791].version='dicom98' & struct[1791].name='StartCumulativeMetersetWeight' struct[1792].group_number='300C'x & struct[1792].element_number='0009'x & struct[1792].vr='DS' & struct[1792].vm='1' & struct[1792].version='dicom98' & struct[1792].name='EndCumulativeMetersetWeight' struct[1793].group_number='300C'x & struct[1793].element_number='000A'x & struct[1793].vr='SQ' & struct[1793].vm='1' & struct[1793].version='dicom98' & struct[1793].name='ReferencedBrachyApplicationSetupSequence' struct[1794].group_number='300C'x & struct[1794].element_number='000C'x & struct[1794].vr='IS' & struct[1794].vm='1' & struct[1794].version='dicom98' & struct[1794].name='ReferencedBrachyApplicationSetupNumber' struct[1795].group_number='300C'x & struct[1795].element_number='000E'x & struct[1795].vr='IS' & struct[1795].vm='1' & struct[1795].version='dicom98' & struct[1795].name='ReferencedSourceNumber' struct[1796].group_number='300C'x & struct[1796].element_number='0020'x & struct[1796].vr='SQ' & struct[1796].vm='1' & struct[1796].version='dicom98' & struct[1796].name='ReferencedFractionGroupSequence' struct[1797].group_number='300C'x & struct[1797].element_number='0022'x & struct[1797].vr='IS' & struct[1797].vm='1' & struct[1797].version='dicom98' & struct[1797].name='ReferencedFractionGroupNumber' struct[1798].group_number='300C'x & struct[1798].element_number='0040'x & struct[1798].vr='SQ' & struct[1798].vm='1' & struct[1798].version='dicom98' & struct[1798].name='ReferencedVerificationImageSequence' struct[1799].group_number='300C'x & struct[1799].element_number='0042'x & struct[1799].vr='SQ' & struct[1799].vm='1' & struct[1799].version='dicom98' & struct[1799].name='ReferencedReferenceImageSequence' struct[1800].group_number='300C'x & struct[1800].element_number='0050'x & struct[1800].vr='SQ' & struct[1800].vm='1' & struct[1800].version='dicom98' & struct[1800].name='ReferencedDoseReferenceSequence' struct[1801].group_number='300C'x & struct[1801].element_number='0051'x & struct[1801].vr='IS' & struct[1801].vm='1' & struct[1801].version='dicom98' & struct[1801].name='ReferencedDoseReferenceNumber' struct[1802].group_number='300C'x & struct[1802].element_number='0055'x & struct[1802].vr='SQ' & struct[1802].vm='1' & struct[1802].version='dicom98' & struct[1802].name='BrachyReferencedDoseReferenceSequence' struct[1803].group_number='300C'x & struct[1803].element_number='0060'x & struct[1803].vr='SQ' & struct[1803].vm='1' & struct[1803].version='dicom98' & struct[1803].name='ReferencedStructureSetSequence' struct[1804].group_number='300C'x & struct[1804].element_number='006A'x & struct[1804].vr='IS' & struct[1804].vm='1' & struct[1804].version='dicom98' & struct[1804].name='ReferencedPatientSetupNumber' struct[1805].group_number='300C'x & struct[1805].element_number='0080'x & struct[1805].vr='SQ' & struct[1805].vm='1' & struct[1805].version='dicom98' & struct[1805].name='ReferencedDoseSequence' struct[1806].group_number='300C'x & struct[1806].element_number='00A0'x & struct[1806].vr='IS' & struct[1806].vm='1' & struct[1806].version='dicom98' & struct[1806].name='ReferencedToleranceTableNumber' struct[1807].group_number='300C'x & struct[1807].element_number='00B0'x & struct[1807].vr='SQ' & struct[1807].vm='1' & struct[1807].version='dicom98' & struct[1807].name='ReferencedBolusSequence' struct[1808].group_number='300C'x & struct[1808].element_number='00C0'x & struct[1808].vr='IS' & struct[1808].vm='1' & struct[1808].version='dicom98' & struct[1808].name='ReferencedWedgeNumber' struct[1809].group_number='300C'x & struct[1809].element_number='00D0'x & struct[1809].vr='IS' & struct[1809].vm='1' & struct[1809].version='dicom98' & struct[1809].name='ReferencedCompensatorNumber' struct[1810].group_number='300C'x & struct[1810].element_number='00E0'x & struct[1810].vr='IS' & struct[1810].vm='1' & struct[1810].version='dicom98' & struct[1810].name='ReferencedBlockNumber' struct[1811].group_number='300C'x & struct[1811].element_number='00F0'x & struct[1811].vr='IS' & struct[1811].vm='1' & struct[1811].version='dicom98' & struct[1811].name='ReferencedControlPointIndex' struct[1812].group_number='300E'x & struct[1812].element_number='0000'x & struct[1812].vr='UL' & struct[1812].vm='1' & struct[1812].version='dicom98' & struct[1812].name='RTApprovalGroupLength' struct[1813].group_number='300E'x & struct[1813].element_number='0002'x & struct[1813].vr='CS' & struct[1813].vm='1' & struct[1813].version='dicom98' & struct[1813].name='ApprovalStatus' struct[1814].group_number='300E'x & struct[1814].element_number='0004'x & struct[1814].vr='DA' & struct[1814].vm='1' & struct[1814].version='dicom98' & struct[1814].name='ReviewDate' struct[1815].group_number='300E'x & struct[1815].element_number='0005'x & struct[1815].vr='TM' & struct[1815].vm='1' & struct[1815].version='dicom98' & struct[1815].name='ReviewTime' struct[1816].group_number='300E'x & struct[1816].element_number='0008'x & struct[1816].vr='PN' & struct[1816].vm='1' & struct[1816].version='dicom98' & struct[1816].name='ReviewerName' struct[1817].group_number='4008'x & struct[1817].element_number='0000'x & struct[1817].vr='UL' & struct[1817].vm='1' & struct[1817].version='dicom98' & struct[1817].name='ResultsGroupLength' struct[1818].group_number='4008'x & struct[1818].element_number='0040'x & struct[1818].vr='SH' & struct[1818].vm='1' & struct[1818].version='dicom98' & struct[1818].name='ResultsID' struct[1819].group_number='4008'x & struct[1819].element_number='0042'x & struct[1819].vr='LO' & struct[1819].vm='1' & struct[1819].version='dicom98' & struct[1819].name='ResultsIDIssuer' struct[1820].group_number='4008'x & struct[1820].element_number='0050'x & struct[1820].vr='SQ' & struct[1820].vm='1' & struct[1820].version='dicom98' & struct[1820].name='ReferencedInterpretationSequence' struct[1821].group_number='4008'x & struct[1821].element_number='0100'x & struct[1821].vr='DA' & struct[1821].vm='1' & struct[1821].version='dicom98' & struct[1821].name='InterpretationRecordedDate' struct[1822].group_number='4008'x & struct[1822].element_number='0101'x & struct[1822].vr='TM' & struct[1822].vm='1' & struct[1822].version='dicom98' & struct[1822].name='InterpretationRecordedTime' struct[1823].group_number='4008'x & struct[1823].element_number='0102'x & struct[1823].vr='PN' & struct[1823].vm='1' & struct[1823].version='dicom98' & struct[1823].name='InterpretationRecorder' struct[1824].group_number='4008'x & struct[1824].element_number='0103'x & struct[1824].vr='LO' & struct[1824].vm='1' & struct[1824].version='dicom98' & struct[1824].name='ReferenceToRecordedSound' struct[1825].group_number='4008'x & struct[1825].element_number='0108'x & struct[1825].vr='DA' & struct[1825].vm='1' & struct[1825].version='dicom98' & struct[1825].name='InterpretationTranscriptionDate' struct[1826].group_number='4008'x & struct[1826].element_number='0109'x & struct[1826].vr='TM' & struct[1826].vm='1' & struct[1826].version='dicom98' & struct[1826].name='InterpretationTranscriptionTime' struct[1827].group_number='4008'x & struct[1827].element_number='010A'x & struct[1827].vr='PN' & struct[1827].vm='1' & struct[1827].version='dicom98' & struct[1827].name='InterpretationTranscriber' struct[1828].group_number='4008'x & struct[1828].element_number='010B'x & struct[1828].vr='ST' & struct[1828].vm='1' & struct[1828].version='dicom98' & struct[1828].name='InterpretationText' struct[1829].group_number='4008'x & struct[1829].element_number='010C'x & struct[1829].vr='PN' & struct[1829].vm='1' & struct[1829].version='dicom98' & struct[1829].name='InterpretationAuthor' struct[1830].group_number='4008'x & struct[1830].element_number='0111'x & struct[1830].vr='SQ' & struct[1830].vm='1' & struct[1830].version='dicom98' & struct[1830].name='InterpretationApproverSequence' struct[1831].group_number='4008'x & struct[1831].element_number='0112'x & struct[1831].vr='DA' & struct[1831].vm='1' & struct[1831].version='dicom98' & struct[1831].name='InterpretationApprovalDate' struct[1832].group_number='4008'x & struct[1832].element_number='0113'x & struct[1832].vr='TM' & struct[1832].vm='1' & struct[1832].version='dicom98' & struct[1832].name='InterpretationApprovalTime' struct[1833].group_number='4008'x & struct[1833].element_number='0114'x & struct[1833].vr='PN' & struct[1833].vm='1' & struct[1833].version='dicom98' & struct[1833].name='PhysicianApprovingInterpretation' struct[1834].group_number='4008'x & struct[1834].element_number='0115'x & struct[1834].vr='LT' & struct[1834].vm='1' & struct[1834].version='dicom98' & struct[1834].name='InterpretationDiagnosisDescription' struct[1835].group_number='4008'x & struct[1835].element_number='0117'x & struct[1835].vr='SQ' & struct[1835].vm='1' & struct[1835].version='dicom98' & struct[1835].name='InterpretationDiagnosisCodeSequence' struct[1836].group_number='4008'x & struct[1836].element_number='0118'x & struct[1836].vr='SQ' & struct[1836].vm='1' & struct[1836].version='dicom98' & struct[1836].name='ResultsDistributionListSequence' struct[1837].group_number='4008'x & struct[1837].element_number='0119'x & struct[1837].vr='PN' & struct[1837].vm='1' & struct[1837].version='dicom98' & struct[1837].name='DistributionName' struct[1838].group_number='4008'x & struct[1838].element_number='011A'x & struct[1838].vr='LO' & struct[1838].vm='1' & struct[1838].version='dicom98' & struct[1838].name='DistributionAddress' struct[1839].group_number='4008'x & struct[1839].element_number='0200'x & struct[1839].vr='SH' & struct[1839].vm='1' & struct[1839].version='dicom98' & struct[1839].name='InterpretationID' struct[1840].group_number='4008'x & struct[1840].element_number='0202'x & struct[1840].vr='LO' & struct[1840].vm='1' & struct[1840].version='dicom98' & struct[1840].name='InterpretationIDIssuer' struct[1841].group_number='4008'x & struct[1841].element_number='0210'x & struct[1841].vr='CS' & struct[1841].vm='1' & struct[1841].version='dicom98' & struct[1841].name='InterpretationTypeID' struct[1842].group_number='4008'x & struct[1842].element_number='0212'x & struct[1842].vr='CS' & struct[1842].vm='1' & struct[1842].version='dicom98' & struct[1842].name='InterpretationStatusID' struct[1843].group_number='4008'x & struct[1843].element_number='0300'x & struct[1843].vr='ST' & struct[1843].vm='1' & struct[1843].version='dicom98' & struct[1843].name='Impressions' struct[1844].group_number='4008'x & struct[1844].element_number='4000'x & struct[1844].vr='ST' & struct[1844].vm='1' & struct[1844].version='dicom98' & struct[1844].name='ResultsComments' struct[1845].group_number='4FFE'x & struct[1845].element_number='0001'x & struct[1845].vr='SQ' & struct[1845].vm='1' & struct[1845].version='dicom2001' & struct[1845].name='MACParametersSequence' struct[1846].group_number='5200'x & struct[1846].element_number='9229'x & struct[1846].vr='SQ' & struct[1846].vm='1' & struct[1846].version='dicom2003' & struct[1846].name='SharedFunctionalGroupsSequence' struct[1847].group_number='5200'x & struct[1847].element_number='9230'x & struct[1847].vr='SQ' & struct[1847].vm='1' & struct[1847].version='dicom2003' & struct[1847].name='PerFrameFunctionalGroupsSequence' struct[1848].group_number='5400'x & struct[1848].element_number='0000'x & struct[1848].vr='UL' & struct[1848].vm='1' & struct[1848].version='dicom2000' & struct[1848].name='WaveformGroupLength' struct[1849].group_number='5400'x & struct[1849].element_number='0100'x & struct[1849].vr='SQ' & struct[1849].vm='1' & struct[1849].version='dicom2000' & struct[1849].name='WaveformSequence' struct[1850].group_number='5400'x & struct[1850].element_number='0110'x & struct[1850].vr='ox' & struct[1850].vm='1' & struct[1850].version='dicom2000' & struct[1850].name='ChannelMinimumValue' struct[1851].group_number='5400'x & struct[1851].element_number='0112'x & struct[1851].vr='ox' & struct[1851].vm='1' & struct[1851].version='dicom2000' & struct[1851].name='ChannelMaximumValue' struct[1852].group_number='5400'x & struct[1852].element_number='1004'x & struct[1852].vr='US' & struct[1852].vm='1' & struct[1852].version='dicom2000' & struct[1852].name='WaveformBitsAllocated' struct[1853].group_number='5400'x & struct[1853].element_number='1006'x & struct[1853].vr='CS' & struct[1853].vm='1' & struct[1853].version='dicom2000' & struct[1853].name='WaveformSampleInterpretation' struct[1854].group_number='5400'x & struct[1854].element_number='100A'x & struct[1854].vr='ox' & struct[1854].vm='1' & struct[1854].version='dicom2000' & struct[1854].name='WaveformPaddingValue' struct[1855].group_number='5400'x & struct[1855].element_number='1010'x & struct[1855].vr='ox' & struct[1855].vm='1' & struct[1855].version='dicom2000' & struct[1855].name='WaveformData' struct[1856].group_number='5600'x & struct[1856].element_number='0010'x & struct[1856].vr='OF' & struct[1856].vm='1' & struct[1856].version='dicom2003' & struct[1856].name='FirstOrderPhaseCorrectionAngle' struct[1857].group_number='5600'x & struct[1857].element_number='0020'x & struct[1857].vr='OF' & struct[1857].vm='1' & struct[1857].version='dicom2003' & struct[1857].name='SpectroscopyData' struct[1858].group_number='7FE0'x & struct[1858].element_number='0000'x & struct[1858].vr='UL' & struct[1858].vm='1' & struct[1858].version='dicom98' & struct[1858].name='PixelDataGroupLength' struct[1859].group_number='7FE0'x & struct[1859].element_number='0010'x & struct[1859].vr='ox' & struct[1859].vm='1' & struct[1859].version='dicom98' & struct[1859].name='PixelData' struct[1860].group_number='FFFA'x & struct[1860].element_number='FFFA'x & struct[1860].vr='SQ' & struct[1860].vm='1' & struct[1860].version='dicom2001' & struct[1860].name='DigitalSignaturesSequence' struct[1861].group_number='FFFC'x & struct[1861].element_number='FFFC'x & struct[1861].vr='OB' & struct[1861].vm='1' & struct[1861].version='dicom98' & struct[1861].name='DataSetTrailingPadding' struct[1862].group_number='FFFE'x & struct[1862].element_number='E000'x & struct[1862].vr='na' & struct[1862].vm='1' & struct[1862].version='dicom98' & struct[1862].name='Item' struct[1863].group_number='FFFE'x & struct[1863].element_number='E00D'x & struct[1863].vr='na' & struct[1863].vm='1' & struct[1863].version='dicom98' & struct[1863].name='ItemDelimitationItem' struct[1864].group_number='FFFE'x & struct[1864].element_number='E0DD'x & struct[1864].vr='na' & struct[1864].vm='1' & struct[1864].version='dicom98' & struct[1864].name='SequenceDelimitationItem' struct[1865].group_number='0000'x & struct[1865].element_number='1007'x & struct[1865].vr='AT' & struct[1865].vm='1-n' & struct[1865].version='DICOM93' & struct[1865].name='ModificationList' struct[1866].group_number='0008'x & struct[1866].element_number='0042'x & struct[1866].vr='CS' & struct[1866].vm='1' & struct[1866].version='DICOM93' & struct[1866].name='NuclearMedicineSeriesType' struct[1867].group_number='0008'x & struct[1867].element_number='2110'x & struct[1867].vr='CS' & struct[1867].vm='1' & struct[1867].version='DICOM93' & struct[1867].name='RETIRED_LossyImageCompression' struct[1868].group_number='0008'x & struct[1868].element_number='2200'x & struct[1868].vr='CS' & struct[1868].vm='1' & struct[1868].version='DICOM93' & struct[1868].name='TransducerPosition' struct[1869].group_number='0008'x & struct[1869].element_number='2204'x & struct[1869].vr='CS' & struct[1869].vm='1' & struct[1869].version='DICOM93' & struct[1869].name='TransducerOrientation' struct[1870].group_number='0008'x & struct[1870].element_number='2208'x & struct[1870].vr='CS' & struct[1870].vm='1' & struct[1870].version='DICOM93' & struct[1870].name='AnatomicStructure' struct[1871].group_number='0018'x & struct[1871].element_number='0030'x & struct[1871].vr='LO' & struct[1871].vm='1-n' & struct[1871].version='DICOM93' & struct[1871].name='Radionuclide' struct[1872].group_number='0018'x & struct[1872].element_number='0032'x & struct[1872].vr='DS' & struct[1872].vm='1' & struct[1872].version='DICOM93' & struct[1872].name='EnergyWindowCenterline' struct[1873].group_number='0018'x & struct[1873].element_number='0033'x & struct[1873].vr='DS' & struct[1873].vm='1-n' & struct[1873].version='DICOM93' & struct[1873].name='EnergyWindowTotalWidth' struct[1874].group_number='0018'x & struct[1874].element_number='1146'x & struct[1874].vr='DS' & struct[1874].vm='1-n' & struct[1874].version='DICOM93' & struct[1874].name='RotationOffset' struct[1875].group_number='0020'x & struct[1875].element_number='0014'x & struct[1875].vr='IS' & struct[1875].vm='1' & struct[1875].version='DICOM93' & struct[1875].name='IsotopeNumber' struct[1876].group_number='0020'x & struct[1876].element_number='0015'x & struct[1876].vr='IS' & struct[1876].vm='1' & struct[1876].version='DICOM93' & struct[1876].name='PhaseNumber' struct[1877].group_number='0020'x & struct[1877].element_number='0016'x & struct[1877].vr='IS' & struct[1877].vm='1' & struct[1877].version='DICOM93' & struct[1877].name='IntervalNumber' struct[1878].group_number='0020'x & struct[1878].element_number='0017'x & struct[1878].vr='IS' & struct[1878].vm='1' & struct[1878].version='DICOM93' & struct[1878].name='TimeSlotNumber' struct[1879].group_number='0020'x & struct[1879].element_number='0018'x & struct[1879].vr='IS' & struct[1879].vm='1' & struct[1879].version='DICOM93' & struct[1879].name='AngleNumber' struct[1880].group_number='2040'x & struct[1880].element_number='0500'x & struct[1880].vr='is' & struct[1880].vm='by' & struct[1880].version='Correction' & struct[1880].name='retired' struct[1881].group_number='2040'x & struct[1881].element_number='0500'x & struct[1881].vr='SQ' & struct[1881].vm='1' & struct[1881].version='DICOM93' & struct[1881].name='RETIRED_ReferencedImageBoxSequence' struct[1882].group_number='0000'x & struct[1882].element_number='0001'x & struct[1882].vr='UL' & struct[1882].vm='1' & struct[1882].version='ACR' & struct[1882].name='ACR_NEMA_CommandGroupLengthToEnd' struct[1883].group_number='0000'x & struct[1883].element_number='0010'x & struct[1883].vr='CS' & struct[1883].vm='1' & struct[1883].version='ACR' & struct[1883].name='ACR_NEMA_CommandRecognitionCode' struct[1884].group_number='0000'x & struct[1884].element_number='0200'x & struct[1884].vr='AE' & struct[1884].vm='1' & struct[1884].version='ACR' & struct[1884].name='ACR_NEMA_Initiator' struct[1885].group_number='0000'x & struct[1885].element_number='0300'x & struct[1885].vr='AE' & struct[1885].vm='1' & struct[1885].version='ACR' & struct[1885].name='ACR_NEMA_Receiver' struct[1886].group_number='0000'x & struct[1886].element_number='0400'x & struct[1886].vr='AE' & struct[1886].vm='1' & struct[1886].version='ACR' & struct[1886].name='ACR_NEMA_FindLocation' struct[1887].group_number='0000'x & struct[1887].element_number='0850'x & struct[1887].vr='US' & struct[1887].vm='1' & struct[1887].version='ACR' & struct[1887].name='ACR_NEMA_NumberOfMatches' struct[1888].group_number='0000'x & struct[1888].element_number='0860'x & struct[1888].vr='US' & struct[1888].vm='1' & struct[1888].version='ACR' & struct[1888].name='ACR_NEMA_ResponseSequenceNumber' struct[1889].group_number='0000'x & struct[1889].element_number='4000'x & struct[1889].vr='AT' & struct[1889].vm='1' & struct[1889].version='ACR' & struct[1889].name='ACR_NEMA_DialogReceiver' struct[1890].group_number='0000'x & struct[1890].element_number='4010'x & struct[1890].vr='AT' & struct[1890].vm='1' & struct[1890].version='ACR' & struct[1890].name='ACR_NEMA_TerminalType' struct[1891].group_number='0000'x & struct[1891].element_number='5010'x & struct[1891].vr='SH' & struct[1891].vm='1' & struct[1891].version='ACR' & struct[1891].name='ACR_NEMA_MessageSetID' struct[1892].group_number='0000'x & struct[1892].element_number='5020'x & struct[1892].vr='SH' & struct[1892].vm='1' & struct[1892].version='ACR' & struct[1892].name='ACR_NEMA_EndMessageSet' struct[1893].group_number='0000'x & struct[1893].element_number='5110'x & struct[1893].vr='AT' & struct[1893].vm='1' & struct[1893].version='ACR' & struct[1893].name='ACR_NEMA_DisplayFormat' struct[1894].group_number='0000'x & struct[1894].element_number='5120'x & struct[1894].vr='AT' & struct[1894].vm='1' & struct[1894].version='ACR' & struct[1894].name='ACR_NEMA_PagePositionID' struct[1895].group_number='0000'x & struct[1895].element_number='5130'x & struct[1895].vr='CS' & struct[1895].vm='1' & struct[1895].version='ACR' & struct[1895].name='ACR_NEMA_TextFormatID' struct[1896].group_number='0000'x & struct[1896].element_number='5140'x & struct[1896].vr='CS' & struct[1896].vm='1' & struct[1896].version='ACR' & struct[1896].name='ACR_NEMA_NormalReverse' struct[1897].group_number='0000'x & struct[1897].element_number='5150'x & struct[1897].vr='CS' & struct[1897].vm='1' & struct[1897].version='ACR' & struct[1897].name='ACR_NEMA_AddGrayScale' struct[1898].group_number='0000'x & struct[1898].element_number='5160'x & struct[1898].vr='CS' & struct[1898].vm='1' & struct[1898].version='ACR' & struct[1898].name='ACR_NEMA_Borders' struct[1899].group_number='0000'x & struct[1899].element_number='5170'x & struct[1899].vr='IS' & struct[1899].vm='1' & struct[1899].version='ACR' & struct[1899].name='ACR_NEMA_Copies' struct[1900].group_number='0000'x & struct[1900].element_number='5180'x & struct[1900].vr='CS' & struct[1900].vm='1' & struct[1900].version='ACR' & struct[1900].name='ACR_NEMA_OldMagnificationType' struct[1901].group_number='0000'x & struct[1901].element_number='5190'x & struct[1901].vr='CS' & struct[1901].vm='1' & struct[1901].version='ACR' & struct[1901].name='ACR_NEMA_Erase' struct[1902].group_number='0000'x & struct[1902].element_number='51A0'x & struct[1902].vr='CS' & struct[1902].vm='1' & struct[1902].version='ACR' & struct[1902].name='ACR_NEMA_Print' struct[1903].group_number='0000'x & struct[1903].element_number='51B0'x & struct[1903].vr='US' & struct[1903].vm='1-n' & struct[1903].version='ACR' & struct[1903].name='ACR_NEMA_Overlays' struct[1904].group_number='0008'x & struct[1904].element_number='0001'x & struct[1904].vr='UL' & struct[1904].vm='1' & struct[1904].version='ACR' & struct[1904].name='ACR_NEMA_IdentifyingGroupLengthToEnd' struct[1905].group_number='0008'x & struct[1905].element_number='0010'x & struct[1905].vr='CS' & struct[1905].vm='1' & struct[1905].version='ACR' & struct[1905].name='ACR_NEMA_RecognitionCode' struct[1906].group_number='0008'x & struct[1906].element_number='0040'x & struct[1906].vr='US' & struct[1906].vm='1' & struct[1906].version='ACR' & struct[1906].name='ACR_NEMA_OldDataSetType' struct[1907].group_number='0008'x & struct[1907].element_number='0041'x & struct[1907].vr='LT' & struct[1907].vm='1' & struct[1907].version='ACR' & struct[1907].name='ACR_NEMA_DataSetSubtype' struct[1908].group_number='0008'x & struct[1908].element_number='1000'x & struct[1908].vr='AE' & struct[1908].vm='1' & struct[1908].version='ACR' & struct[1908].name='ACR_NEMA_NetworkID' struct[1909].group_number='0008'x & struct[1909].element_number='4000'x & struct[1909].vr='LT' & struct[1909].vm='1-n' & struct[1909].version='ACR' & struct[1909].name='ACR_NEMA_IdentifyingComments' struct[1910].group_number='0010'x & struct[1910].element_number='1050'x & struct[1910].vr='LT' & struct[1910].vm='1-n' & struct[1910].version='ACR' & struct[1910].name='ACR_NEMA_InsurancePlanIdentification' struct[1911].group_number='0018'x & struct[1911].element_number='1240'x & struct[1911].vr='IS' & struct[1911].vm='1-n' & struct[1911].version='ACR' & struct[1911].name='ACR_NEMA_UpperLowerPixelValues' struct[1912].group_number='0018'x & struct[1912].element_number='4000'x & struct[1912].vr='LT' & struct[1912].vm='1-n' & struct[1912].version='ACR' & struct[1912].name='ACR_NEMA_AcquisitionComments' struct[1913].group_number='0018'x & struct[1913].element_number='5030'x & struct[1913].vr='DS' & struct[1913].vm='1' & struct[1913].version='ACR' & struct[1913].name='ACR_NEMA_DynamicRange' struct[1914].group_number='0018'x & struct[1914].element_number='5040'x & struct[1914].vr='DS' & struct[1914].vm='1' & struct[1914].version='ACR' & struct[1914].name='ACR_NEMA_TotalGain' struct[1915].group_number='0020'x & struct[1915].element_number='0030'x & struct[1915].vr='DS' & struct[1915].vm='3' & struct[1915].version='ACR' & struct[1915].name='ACR_NEMA_ImagePosition' struct[1916].group_number='0020'x & struct[1916].element_number='0035'x & struct[1916].vr='DS' & struct[1916].vm='6' & struct[1916].version='ACR' & struct[1916].name='ACR_NEMA_ImageOrientation' struct[1917].group_number='0020'x & struct[1917].element_number='0050'x & struct[1917].vr='DS' & struct[1917].vm='1' & struct[1917].version='ACR' & struct[1917].name='ACR_NEMA_Location' struct[1918].group_number='0020'x & struct[1918].element_number='0070'x & struct[1918].vr='LT' & struct[1918].vm='1' & struct[1918].version='ACR' & struct[1918].name='ACR_NEMA_ImageGeometryType' struct[1919].group_number='0020'x & struct[1919].element_number='0080'x & struct[1919].vr='CS' & struct[1919].vm='1-n' & struct[1919].version='ACR' & struct[1919].name='ACR_NEMA_MaskingImage' struct[1920].group_number='0020'x & struct[1920].element_number='1001'x & struct[1920].vr='IS' & struct[1920].vm='1' & struct[1920].version='ACR' & struct[1920].name='ACR_NEMA_AcquisitionsInSeries' struct[1921].group_number='0020'x & struct[1921].element_number='1003'x & struct[1921].vr='IS' & struct[1921].vm='1' & struct[1921].version='ACR' & struct[1921].name='ACR_NEMA_ImagesInSeries' struct[1922].group_number='0020'x & struct[1922].element_number='1005'x & struct[1922].vr='IS' & struct[1922].vm='1' & struct[1922].version='ACR' & struct[1922].name='ACR_NEMA_ImagesInStudy' struct[1923].group_number='0020'x & struct[1923].element_number='1020'x & struct[1923].vr='CS' & struct[1923].vm='1-n' & struct[1923].version='ACR' & struct[1923].name='ACR_NEMA_Reference' struct[1924].group_number='0020'x & struct[1924].element_number='3401'x & struct[1924].vr='CS' & struct[1924].vm='1' & struct[1924].version='ACR' & struct[1924].name='ACR_NEMA_ModifyingDeviceID' struct[1925].group_number='0020'x & struct[1925].element_number='3402'x & struct[1925].vr='CS' & struct[1925].vm='1' & struct[1925].version='ACR' & struct[1925].name='ACR_NEMA_ModifiedImageID' struct[1926].group_number='0020'x & struct[1926].element_number='3403'x & struct[1926].vr='DA' & struct[1926].vm='1' & struct[1926].version='ACR' & struct[1926].name='ACR_NEMA_ModifiedImageDate' struct[1927].group_number='0020'x & struct[1927].element_number='3404'x & struct[1927].vr='LO' & struct[1927].vm='1' & struct[1927].version='ACR' & struct[1927].name='ACR_NEMA_ModifyingDeviceManufacturer' struct[1928].group_number='0020'x & struct[1928].element_number='3405'x & struct[1928].vr='TM' & struct[1928].vm='1' & struct[1928].version='ACR' & struct[1928].name='ACR_NEMA_ModifiedImageTime' struct[1929].group_number='0020'x & struct[1929].element_number='3406'x & struct[1929].vr='LT' & struct[1929].vm='1' & struct[1929].version='ACR' & struct[1929].name='ACR_NEMA_ModifiedImageDescription' struct[1930].group_number='0020'x & struct[1930].element_number='5000'x & struct[1930].vr='AT' & struct[1930].vm='1-n' & struct[1930].version='ACR' & struct[1930].name='ACR_NEMA_OriginalImageIdentification' struct[1931].group_number='0020'x & struct[1931].element_number='5002'x & struct[1931].vr='CS' & struct[1931].vm='1-n' & struct[1931].version='ACR' & struct[1931].name='ACR_NEMA_OriginalImageIdentificationNomenclature' struct[1932].group_number='0028'x & struct[1932].element_number='0005'x & struct[1932].vr='US' & struct[1932].vm='1' & struct[1932].version='ACR' & struct[1932].name='ACR_NEMA_ImageDimensions' struct[1933].group_number='0028'x & struct[1933].element_number='0040'x & struct[1933].vr='CS' & struct[1933].vm='1' & struct[1933].version='ACR' & struct[1933].name='ACR_NEMA_ImageFormat' struct[1934].group_number='0028'x & struct[1934].element_number='0050'x & struct[1934].vr='LT' & struct[1934].vm='1-n' & struct[1934].version='ACR' & struct[1934].name='ACR_NEMA_ManipulatedImage' struct[1935].group_number='0028'x & struct[1935].element_number='0060'x & struct[1935].vr='CS' & struct[1935].vm='1' & struct[1935].version='ACR' & struct[1935].name='ACR_NEMA_CompressionCode' struct[1936].group_number='0028'x & struct[1936].element_number='0104'x & struct[1936].vr='xs' & struct[1936].vm='1' & struct[1936].version='ACR' & struct[1936].name='ACR_NEMA_SmallestValidPixelValue' struct[1937].group_number='0028'x & struct[1937].element_number='0105'x & struct[1937].vr='xs' & struct[1937].vm='1' & struct[1937].version='ACR' & struct[1937].name='ACR_NEMA_LargestValidPixelValue' struct[1938].group_number='0028'x & struct[1938].element_number='0200'x & struct[1938].vr='US' & struct[1938].vm='1' & struct[1938].version='ACR' & struct[1938].name='ACR_NEMA_ImageLocation' struct[1939].group_number='0028'x & struct[1939].element_number='1080'x & struct[1939].vr='CS' & struct[1939].vm='1' & struct[1939].version='ACR' & struct[1939].name='ACR_NEMA_GrayScale' struct[1940].group_number='0028'x & struct[1940].element_number='1100'x & struct[1940].vr='xs' & struct[1940].vm='3' & struct[1940].version='ACR' & struct[1940].name='ACR_NEMA_GrayLookupTableDescriptor' struct[1941].group_number='0028'x & struct[1941].element_number='1200'x & struct[1941].vr='xs' & struct[1941].vm='1-n' & struct[1941].version='ACR' & struct[1941].name='ACR_NEMA_GrayLookupTableData' struct[1942].group_number='0028'x & struct[1942].element_number='4000'x & struct[1942].vr='LT' & struct[1942].vm='1-n' & struct[1942].version='ACR' & struct[1942].name='ACR_NEMA_ImagePresentationComments' struct[1943].group_number='4000'x & struct[1943].element_number='0000'x & struct[1943].vr='UL' & struct[1943].vm='1' & struct[1943].version='ACR' & struct[1943].name='ACR_NEMA_TextGroupLength' struct[1944].group_number='4000'x & struct[1944].element_number='0010'x & struct[1944].vr='LT' & struct[1944].vm='1-n' & struct[1944].version='ACR' & struct[1944].name='ACR_NEMA_TextArbitrary' struct[1945].group_number='4000'x & struct[1945].element_number='4000'x & struct[1945].vr='LT' & struct[1945].vm='1-n' & struct[1945].version='ACR' & struct[1945].name='ACR_NEMA_TextComments' struct[1946].group_number='0028'x & struct[1946].element_number='005F'x & struct[1946].vr='CS' & struct[1946].vm='1' & struct[1946].version='ACR' & struct[1946].name='ACR_NEMA_2C_CompressionRecognitionCode' struct[1947].group_number='0028'x & struct[1947].element_number='0061'x & struct[1947].vr='SH' & struct[1947].vm='1' & struct[1947].version='ACR' & struct[1947].name='ACR_NEMA_2C_CompressionOriginator' struct[1948].group_number='0028'x & struct[1948].element_number='0062'x & struct[1948].vr='SH' & struct[1948].vm='1' & struct[1948].version='ACR' & struct[1948].name='ACR_NEMA_2C_CompressionLabel' struct[1949].group_number='0028'x & struct[1949].element_number='0063'x & struct[1949].vr='SH' & struct[1949].vm='1' & struct[1949].version='ACR' & struct[1949].name='ACR_NEMA_2C_CompressionDescription' struct[1950].group_number='0028'x & struct[1950].element_number='0065'x & struct[1950].vr='CS' & struct[1950].vm='1-n' & struct[1950].version='ACR' & struct[1950].name='ACR_NEMA_2C_CompressionSequence' struct[1951].group_number='0028'x & struct[1951].element_number='0066'x & struct[1951].vr='AT' & struct[1951].vm='1-n' & struct[1951].version='ACR' & struct[1951].name='ACR_NEMA_2C_CompressionStepPointers' struct[1952].group_number='0028'x & struct[1952].element_number='0068'x & struct[1952].vr='US' & struct[1952].vm='1' & struct[1952].version='ACR' & struct[1952].name='ACR_NEMA_2C_RepeatInterval' struct[1953].group_number='0028'x & struct[1953].element_number='0069'x & struct[1953].vr='US' & struct[1953].vm='1' & struct[1953].version='ACR' & struct[1953].name='ACR_NEMA_2C_BitsGrouped' struct[1954].group_number='0028'x & struct[1954].element_number='0070'x & struct[1954].vr='US' & struct[1954].vm='1-n' & struct[1954].version='ACR' & struct[1954].name='ACR_NEMA_2C_PerimeterTable' struct[1955].group_number='0028'x & struct[1955].element_number='0071'x & struct[1955].vr='xs' & struct[1955].vm='1' & struct[1955].version='ACR' & struct[1955].name='ACR_NEMA_2C_PerimeterValue' struct[1956].group_number='0028'x & struct[1956].element_number='0080'x & struct[1956].vr='US' & struct[1956].vm='1' & struct[1956].version='ACR' & struct[1956].name='ACR_NEMA_2C_PredictorRows' struct[1957].group_number='0028'x & struct[1957].element_number='0081'x & struct[1957].vr='US' & struct[1957].vm='1' & struct[1957].version='ACR' & struct[1957].name='ACR_NEMA_2C_PredictorColumns' struct[1958].group_number='0028'x & struct[1958].element_number='0082'x & struct[1958].vr='US' & struct[1958].vm='1-n' & struct[1958].version='ACR' & struct[1958].name='ACR_NEMA_2C_PredictorConstants' struct[1959].group_number='0028'x & struct[1959].element_number='0090'x & struct[1959].vr='CS' & struct[1959].vm='1' & struct[1959].version='ACR' & struct[1959].name='ACR_NEMA_2C_BlockedPixels' struct[1960].group_number='0028'x & struct[1960].element_number='0091'x & struct[1960].vr='US' & struct[1960].vm='1' & struct[1960].version='ACR' & struct[1960].name='ACR_NEMA_2C_BlockRows' struct[1961].group_number='0028'x & struct[1961].element_number='0092'x & struct[1961].vr='US' & struct[1961].vm='1' & struct[1961].version='ACR' & struct[1961].name='ACR_NEMA_2C_BlockColumns' struct[1962].group_number='0028'x & struct[1962].element_number='0093'x & struct[1962].vr='US' & struct[1962].vm='1' & struct[1962].version='ACR' & struct[1962].name='ACR_NEMA_2C_RowOverlap' struct[1963].group_number='0028'x & struct[1963].element_number='0094'x & struct[1963].vr='US' & struct[1963].vm='1' & struct[1963].version='ACR' & struct[1963].name='ACR_NEMA_2C_ColumnOverlap' struct[1964].group_number='0028'x & struct[1964].element_number='0400'x & struct[1964].vr='CS' & struct[1964].vm='1' & struct[1964].version='ACR' & struct[1964].name='ACR_NEMA_2C_TransformLabel' struct[1965].group_number='0028'x & struct[1965].element_number='0401'x & struct[1965].vr='CS' & struct[1965].vm='1' & struct[1965].version='ACR' & struct[1965].name='ACR_NEMA_2C_TransformVersionNumber' struct[1966].group_number='0028'x & struct[1966].element_number='0402'x & struct[1966].vr='US' & struct[1966].vm='1' & struct[1966].version='ACR' & struct[1966].name='ACR_NEMA_2C_NumberOfTransformSteps' struct[1967].group_number='0028'x & struct[1967].element_number='0403'x & struct[1967].vr='CS' & struct[1967].vm='1-n' & struct[1967].version='ACR' & struct[1967].name='ACR_NEMA_2C_SequenceOfCompressedData' struct[1968].group_number='0028'x & struct[1968].element_number='0404'x & struct[1968].vr='AT' & struct[1968].vm='1-n' & struct[1968].version='ACR' & struct[1968].name='ACR_NEMA_2C_DetailsOfCoefficients' struct[1969].group_number='0028'x & struct[1969].element_number='0410'x & struct[1969].vr='US' & struct[1969].vm='1' & struct[1969].version='ACR' & struct[1969].name='ACR_NEMA_2C_RowsForNthOrderCoefficients' struct[1970].group_number='0028'x & struct[1970].element_number='0411'x & struct[1970].vr='US' & struct[1970].vm='1' & struct[1970].version='ACR' & struct[1970].name='ACR_NEMA_2C_ColumnsForNthOrderCoefficients' struct[1971].group_number='0028'x & struct[1971].element_number='0412'x & struct[1971].vr='CS' & struct[1971].vm='1-n' & struct[1971].version='ACR' & struct[1971].name='ACR_NEMA_2C_CoefficientCoding' struct[1972].group_number='0028'x & struct[1972].element_number='0413'x & struct[1972].vr='AT' & struct[1972].vm='1-n' & struct[1972].version='ACR' & struct[1972].name='ACR_NEMA_2C_CoefficientCodingPointers' struct[1973].group_number='0028'x & struct[1973].element_number='0700'x & struct[1973].vr='CS' & struct[1973].vm='1' & struct[1973].version='ACR' & struct[1973].name='ACR_NEMA_2C_DCTLabel' struct[1974].group_number='0028'x & struct[1974].element_number='0701'x & struct[1974].vr='CS' & struct[1974].vm='1-n' & struct[1974].version='ACR' & struct[1974].name='ACR_NEMA_2C_DataBlockDescription' struct[1975].group_number='0028'x & struct[1975].element_number='0702'x & struct[1975].vr='AT' & struct[1975].vm='1-n' & struct[1975].version='ACR' & struct[1975].name='ACR_NEMA_2C_DataBlock' struct[1976].group_number='0028'x & struct[1976].element_number='0710'x & struct[1976].vr='US' & struct[1976].vm='1' & struct[1976].version='ACR' & struct[1976].name='ACR_NEMA_2C_NormalizationFactorFormat' struct[1977].group_number='0028'x & struct[1977].element_number='0720'x & struct[1977].vr='US' & struct[1977].vm='1' & struct[1977].version='ACR' & struct[1977].name='ACR_NEMA_2C_ZonalMapNumberFormat' struct[1978].group_number='0028'x & struct[1978].element_number='0721'x & struct[1978].vr='AT' & struct[1978].vm='1-n' & struct[1978].version='ACR' & struct[1978].name='ACR_NEMA_2C_ZonalMapLocation' struct[1979].group_number='0028'x & struct[1979].element_number='0722'x & struct[1979].vr='US' & struct[1979].vm='1' & struct[1979].version='ACR' & struct[1979].name='ACR_NEMA_2C_ZonalMapFormat' struct[1980].group_number='0028'x & struct[1980].element_number='0730'x & struct[1980].vr='US' & struct[1980].vm='1' & struct[1980].version='ACR' & struct[1980].name='ACR_NEMA_2C_AdaptiveMapFormat' struct[1981].group_number='0028'x & struct[1981].element_number='0740'x & struct[1981].vr='US' & struct[1981].vm='1' & struct[1981].version='ACR' & struct[1981].name='ACR_NEMA_2C_CodeNumberFormat' struct[1982].group_number='0028'x & struct[1982].element_number='0800'x & struct[1982].vr='CS' & struct[1982].vm='1-n' & struct[1982].version='ACR' & struct[1982].name='ACR_NEMA_2C_CodeLabel' struct[1983].group_number='0028'x & struct[1983].element_number='0802'x & struct[1983].vr='US' & struct[1983].vm='1' & struct[1983].version='ACR' & struct[1983].name='ACR_NEMA_2C_NumberOfTables' struct[1984].group_number='0028'x & struct[1984].element_number='0803'x & struct[1984].vr='AT' & struct[1984].vm='1-n' & struct[1984].version='ACR' & struct[1984].name='ACR_NEMA_2C_CodeTableLocation' struct[1985].group_number='0028'x & struct[1985].element_number='0804'x & struct[1985].vr='US' & struct[1985].vm='1' & struct[1985].version='ACR' & struct[1985].name='ACR_NEMA_2C_BitsForCodeWord' struct[1986].group_number='0028'x & struct[1986].element_number='0808'x & struct[1986].vr='AT' & struct[1986].vm='1-n' & struct[1986].version='ACR' & struct[1986].name='ACR_NEMA_2C_ImageDataLocation' struct[1987].group_number='1000'x & struct[1987].element_number='0000'x & struct[1987].vr='UL' & struct[1987].vm='1' & struct[1987].version='ACR' & struct[1987].name='ACR_NEMA_2C_CodeTableGroupLength' struct[1988].group_number='1000'x & struct[1988].element_number='0010'x & struct[1988].vr='US' & struct[1988].vm='3' & struct[1988].version='ACR' & struct[1988].name='ACR_NEMA_2C_EscapeTriplet' struct[1989].group_number='1000'x & struct[1989].element_number='0011'x & struct[1989].vr='US' & struct[1989].vm='3' & struct[1989].version='ACR' & struct[1989].name='ACR_NEMA_2C_RunLengthTriplet' struct[1990].group_number='1000'x & struct[1990].element_number='0012'x & struct[1990].vr='US' & struct[1990].vm='1' & struct[1990].version='ACR' & struct[1990].name='ACR_NEMA_2C_HuffmanTableSize' struct[1991].group_number='1000'x & struct[1991].element_number='0013'x & struct[1991].vr='US' & struct[1991].vm='3' & struct[1991].version='ACR' & struct[1991].name='ACR_NEMA_2C_HuffmanTableTriplet' struct[1992].group_number='1000'x & struct[1992].element_number='0014'x & struct[1992].vr='US' & struct[1992].vm='1' & struct[1992].version='ACR' & struct[1992].name='ACR_NEMA_2C_ShiftTableSize' struct[1993].group_number='1000'x & struct[1993].element_number='0015'x & struct[1993].vr='US' & struct[1993].vm='3' & struct[1993].version='ACR' & struct[1993].name='ACR_NEMA_2C_ShiftTableTriplet' struct[1994].group_number='1010'x & struct[1994].element_number='0000'x & struct[1994].vr='UL' & struct[1994].vm='1' & struct[1994].version='ACR' & struct[1994].name='ACR_NEMA_2C_ZonalMapGroupLength' struct[1995].group_number='1010'x & struct[1995].element_number='0004'x & struct[1995].vr='US' & struct[1995].vm='1-n' & struct[1995].version='ACR' & struct[1995].name='ACR_NEMA_2C_ZonalMap' struct[1996].group_number='7FE0'x & struct[1996].element_number='0020'x & struct[1996].vr='OW' & struct[1996].vm='1-n' & struct[1996].version='ACR' & struct[1996].name='ACR_NEMA_2C_CoefficientsSDVN' struct[1997].group_number='7FE0'x & struct[1997].element_number='0030'x & struct[1997].vr='OW' & struct[1997].vm='1-n' & struct[1997].version='ACR' & struct[1997].name='ACR_NEMA_2C_CoefficientsSDHN' struct[1998].group_number='7FE0'x & struct[1998].element_number='0040'x & struct[1998].vr='OW' & struct[1998].vm='1-n' & struct[1998].version='ACR' & struct[1998].name='ACR_NEMA_2C_CoefficientsSDDN' struct[1999].group_number='0018'x & struct[1999].element_number='0036'x & struct[1999].vr='SQ' & struct[1999].vm='1' & struct[1999].version='CP20' & struct[1999].name='InterventionSequence' struct[2000].group_number='0018'x & struct[2000].element_number='0039'x & struct[2000].vr='CS' & struct[2000].vm='1' & struct[2000].version='CP20' & struct[2000].name='RETIRED_TherapyDescription' struct[2001].group_number='0018'x & struct[2001].element_number='003A'x & struct[2001].vr='ST' & struct[2001].vm='1' & struct[2001].version='CP20' & struct[2001].name='InterventionDescription' struct[2002].group_number='0008'x & struct[2002].element_number='3001'x & struct[2002].vr='SQ' & struct[2002].vm='1' & struct[2002].version='CP25' & struct[2002].name='AlternateRepresentationSequence' struct[2003].group_number='0040'x & struct[2003].element_number='0440'x & struct[2003].vr='SQ' & struct[2003].vm='1' & struct[2003].version='CP20' & struct[2003].name='ProtocolContextSequence' struct[2004].group_number='0040'x & struct[2004].element_number='0441'x & struct[2004].vr='SQ' & struct[2004].vm='1' & struct[2004].version='CP20' & struct[2004].name='ContentItemModifierSequence' struct[2005].group_number='0008'x & struct[2005].element_number='1250'x & struct[2005].vr='SQ' & struct[2005].vm='1' & struct[2005].version='CP21' & struct[2005].name='RelatedSeriesSequence' struct[2006].group_number='0054'x & struct[2006].element_number='0500'x & struct[2006].vr='CS' & struct[2006].vm='1' & struct[2006].version='CP20' & struct[2006].name='SliceProgressionDirection' struct[2007].group_number='0028'x & struct[2007].element_number='000A'x & struct[2007].vr='AT' & struct[2007].vm='1-n' & struct[2007].version='CP21' & struct[2007].name='FrameDimensionPointer' struct[2008].group_number='0040'x & struct[2008].element_number='4010'x & struct[2008].vr='DT' & struct[2008].vm='1' & struct[2008].version='CP21' & struct[2008].name='ScheduledProcedureStepModificationDateAndTime' struct[2009].group_number='0054'x & struct[2009].element_number='0039'x & struct[2009].vr='CS' & struct[2009].vm='1' & struct[2009].version='CP22' & struct[2009].name='PhaseDescription' struct[2010].group_number='0018'x & struct[2010].element_number='9240'x & struct[2010].vr='US' & struct[2010].vm='1' & struct[2010].version='CP22' & struct[2010].name='RFEchoTrainLength' struct[2011].group_number='0018'x & struct[2011].element_number='9241'x & struct[2011].vr='US' & struct[2011].vm='1' & struct[2011].version='CP22' & struct[2011].name='GradientEchoTrainLength' struct[2012].group_number='0040'x & struct[2012].element_number='9210'x & struct[2012].vr='SH' & struct[2012].vm='1' & struct[2012].version='CP24' & struct[2012].name='LUTLabel' struct[2013].group_number='0018'x & struct[2013].element_number='9218'x & struct[2013].vr='FD' & struct[2013].vm='1' & struct[2013].version='CP24' & struct[2013].name='TagSpacingSecondDimension' struct[2014].group_number='0018'x & struct[2014].element_number='9083'x & struct[2014].vr='SQ' & struct[2014].vm='1' & struct[2014].version='CP25' & struct[2014].name='MetaboliteMapCodeSequence' struct[2015].group_number='0018'x & struct[2015].element_number='9295'x & struct[2015].vr='FD' & struct[2015].vm='1' & struct[2015].version='CP25' & struct[2015].name='ChemicalShiftsMinimumIntegrationLimitInPpm' struct[2016].group_number='0018'x & struct[2016].element_number='9296'x & struct[2016].vr='FD' & struct[2016].vm='1' & struct[2016].version='CP25' & struct[2016].name='ChemicalShiftsMaximumIntegrationLimitInPpm' struct[2017].group_number='0028'x & struct[2017].element_number='6023'x & struct[2017].vr='CS' & struct[2017].vm='1-n' & struct[2017].version='CP25' & struct[2017].name='FrameOfInterestType' struct[2018].group_number='0040'x & struct[2018].element_number='100A'x & struct[2018].vr='SQ' & struct[2018].vm='1' & struct[2018].version='CP25' & struct[2018].name='ReasonForRequestedProcedureCodeSequence' struct[2019].group_number='003A'x & struct[2019].element_number='0300'x & struct[2019].vr='SQ' & struct[2019].vm='1' & struct[2019].version='supp42' & struct[2019].name='MultiplexedAudioChannelsDescriptionCodeSequence' struct[2020].group_number='003A'x & struct[2020].element_number='0301'x & struct[2020].vr='IS' & struct[2020].vm='1' & struct[2020].version='supp42' & struct[2020].name='ChannelIdentificationCode' struct[2021].group_number='003A'x & struct[2021].element_number='0302'x & struct[2021].vr='CS' & struct[2021].vm='1' & struct[2021].version='supp42' & struct[2021].name='ChannelMode' struct[2022].group_number='0018'x & struct[2022].element_number='1046'x & struct[2022].vr='DS' & struct[2022].vm='1-n' & struct[2022].version='supp58' & struct[2022].name='ContrastFlowRate' struct[2023].group_number='0018'x & struct[2023].element_number='1047'x & struct[2023].vr='DS' & struct[2023].vm='1-n' & struct[2023].version='supp58' & struct[2023].name='ContrastFlowDuration' struct[2024].group_number='0018'x & struct[2024].element_number='9301'x & struct[2024].vr='SQ' & struct[2024].vm='1' & struct[2024].version='supp58' & struct[2024].name='CTAcquisitionTypeSequence' struct[2025].group_number='0018'x & struct[2025].element_number='9302'x & struct[2025].vr='CS' & struct[2025].vm='1' & struct[2025].version='supp58' & struct[2025].name='AcquisitionType' struct[2026].group_number='0018'x & struct[2026].element_number='9303'x & struct[2026].vr='FD' & struct[2026].vm='1' & struct[2026].version='supp58' & struct[2026].name='TubeAngle' struct[2027].group_number='0018'x & struct[2027].element_number='9304'x & struct[2027].vr='SQ' & struct[2027].vm='1' & struct[2027].version='supp58' & struct[2027].name='CTAcquisitionDetailsSequence' struct[2028].group_number='0018'x & struct[2028].element_number='9305'x & struct[2028].vr='FD' & struct[2028].vm='1' & struct[2028].version='supp58' & struct[2028].name='RevolutionTime' struct[2029].group_number='0018'x & struct[2029].element_number='9306'x & struct[2029].vr='FD' & struct[2029].vm='1' & struct[2029].version='supp58' & struct[2029].name='SingleCollimationWidth' struct[2030].group_number='0018'x & struct[2030].element_number='9307'x & struct[2030].vr='FD' & struct[2030].vm='1' & struct[2030].version='supp58' & struct[2030].name='TotalCollimationWidth' struct[2031].group_number='0018'x & struct[2031].element_number='9308'x & struct[2031].vr='SQ' & struct[2031].vm='1' & struct[2031].version='supp58' & struct[2031].name='CTTableDynamicsSequence' struct[2032].group_number='0018'x & struct[2032].element_number='9309'x & struct[2032].vr='FD' & struct[2032].vm='1' & struct[2032].version='supp58' & struct[2032].name='TableSpeed' struct[2033].group_number='0018'x & struct[2033].element_number='9310'x & struct[2033].vr='FD' & struct[2033].vm='1' & struct[2033].version='supp58' & struct[2033].name='TableFeedPerRotation' struct[2034].group_number='0018'x & struct[2034].element_number='9311'x & struct[2034].vr='FD' & struct[2034].vm='1' & struct[2034].version='supp58' & struct[2034].name='SpiralPitchFactor' struct[2035].group_number='0018'x & struct[2035].element_number='9312'x & struct[2035].vr='SQ' & struct[2035].vm='1' & struct[2035].version='supp58' & struct[2035].name='CTGeometrySequence' struct[2036].group_number='0018'x & struct[2036].element_number='9313'x & struct[2036].vr='FD' & struct[2036].vm='3' & struct[2036].version='supp58' & struct[2036].name='DataCollectionCenterPatient' struct[2037].group_number='0018'x & struct[2037].element_number='9314'x & struct[2037].vr='SQ' & struct[2037].vm='1' & struct[2037].version='supp58' & struct[2037].name='CTReconstructionSequence' struct[2038].group_number='0018'x & struct[2038].element_number='9315'x & struct[2038].vr='CS' & struct[2038].vm='1' & struct[2038].version='supp58' & struct[2038].name='ReconstructionAlgorithm' struct[2039].group_number='0018'x & struct[2039].element_number='9316'x & struct[2039].vr='CS' & struct[2039].vm='1' & struct[2039].version='supp58' & struct[2039].name='ConvolutionKernelGroup' struct[2040].group_number='0018'x & struct[2040].element_number='9317'x & struct[2040].vr='FD' & struct[2040].vm='2' & struct[2040].version='supp58' & struct[2040].name='ReconstructionFieldOfView' struct[2041].group_number='0018'x & struct[2041].element_number='9318'x & struct[2041].vr='FD' & struct[2041].vm='3' & struct[2041].version='supp58' & struct[2041].name='ReconstructionTargetCenterPatient' struct[2042].group_number='0018'x & struct[2042].element_number='9319'x & struct[2042].vr='FD' & struct[2042].vm='1' & struct[2042].version='supp58' & struct[2042].name='ReconstructionAngle' struct[2043].group_number='0018'x & struct[2043].element_number='9320'x & struct[2043].vr='SH' & struct[2043].vm='1' & struct[2043].version='supp58' & struct[2043].name='ImageFilter' struct[2044].group_number='0018'x & struct[2044].element_number='9321'x & struct[2044].vr='SQ' & struct[2044].vm='1' & struct[2044].version='supp58' & struct[2044].name='CTExposureSequence' struct[2045].group_number='0018'x & struct[2045].element_number='9322'x & struct[2045].vr='FD' & struct[2045].vm='2' & struct[2045].version='supp58' & struct[2045].name='ReconstructionPixelSpacing' struct[2046].group_number='0018'x & struct[2046].element_number='9323'x & struct[2046].vr='CS' & struct[2046].vm='1' & struct[2046].version='supp58' & struct[2046].name='ExposureModulationType' struct[2047].group_number='0018'x & struct[2047].element_number='9324'x & struct[2047].vr='FD' & struct[2047].vm='1' & struct[2047].version='supp58' & struct[2047].name='EstimatedDoseSaving' struct[2048].group_number='0018'x & struct[2048].element_number='9325'x & struct[2048].vr='SQ' & struct[2048].vm='1' & struct[2048].version='supp58' & struct[2048].name='CTXRayDetailsSequence' struct[2049].group_number='0018'x & struct[2049].element_number='9326'x & struct[2049].vr='SQ' & struct[2049].vm='1' & struct[2049].version='supp58' & struct[2049].name='CTPositionSequence' struct[2050].group_number='0018'x & struct[2050].element_number='9327'x & struct[2050].vr='FD' & struct[2050].vm='1' & struct[2050].version='supp58' & struct[2050].name='TablePosition' struct[2051].group_number='0018'x & struct[2051].element_number='9328'x & struct[2051].vr='FD' & struct[2051].vm='1' & struct[2051].version='supp58' & struct[2051].name='ExposureTimeInms' struct[2052].group_number='0018'x & struct[2052].element_number='9329'x & struct[2052].vr='SQ' & struct[2052].vm='1' & struct[2052].version='supp58' & struct[2052].name='CTImageFrameTypeSequence' struct[2053].group_number='0018'x & struct[2053].element_number='9330'x & struct[2053].vr='FD' & struct[2053].vm='1' & struct[2053].version='supp58' & struct[2053].name='XRayTubeCurrentInmA' struct[2054].group_number='0018'x & struct[2054].element_number='9332'x & struct[2054].vr='FD' & struct[2054].vm='1' & struct[2054].version='supp58' & struct[2054].name='ExposureInmAs' struct[2055].group_number='0018'x & struct[2055].element_number='9333'x & struct[2055].vr='CS' & struct[2055].vm='1' & struct[2055].version='supp58' & struct[2055].name='ConstantVolumeFlag' struct[2056].group_number='0018'x & struct[2056].element_number='9334'x & struct[2056].vr='CS' & struct[2056].vm='1' & struct[2056].version='supp58' & struct[2056].name='FluoroscopyFlag' struct[2057].group_number='0018'x & struct[2057].element_number='9335'x & struct[2057].vr='FD' & struct[2057].vm='1' & struct[2057].version='supp58' & struct[2057].name='DistanceSourceToDataCollectionCenter' struct[2058].group_number='0018'x & struct[2058].element_number='9337'x & struct[2058].vr='US' & struct[2058].vm='1' & struct[2058].version='supp58' & struct[2058].name='ContrastBolusAgentNumber' struct[2059].group_number='0018'x & struct[2059].element_number='9338'x & struct[2059].vr='SQ' & struct[2059].vm='1' & struct[2059].version='supp58' & struct[2059].name='ContrastBolusIngredientCodeSequence' struct[2060].group_number='0018'x & struct[2060].element_number='9340'x & struct[2060].vr='SQ' & struct[2060].vm='1' & struct[2060].version='supp58' & struct[2060].name='ContrastAdministrationProfileSequence' struct[2061].group_number='0018'x & struct[2061].element_number='9341'x & struct[2061].vr='SQ' & struct[2061].vm='1' & struct[2061].version='supp58' & struct[2061].name='ContrastBolusUsageSequence' struct[2062].group_number='0018'x & struct[2062].element_number='9342'x & struct[2062].vr='CS' & struct[2062].vm='1' & struct[2062].version='supp58' & struct[2062].name='ContrastBolusAgentAdministered' struct[2063].group_number='0018'x & struct[2063].element_number='9343'x & struct[2063].vr='CS' & struct[2063].vm='1' & struct[2063].version='supp58' & struct[2063].name='ContrastBolusAgentDetected' struct[2064].group_number='0018'x & struct[2064].element_number='9344'x & struct[2064].vr='CS' & struct[2064].vm='1' & struct[2064].version='supp58' & struct[2064].name='ContrastBolusAgentPhase' struct[2065].group_number='0018'x & struct[2065].element_number='9345'x & struct[2065].vr='FD' & struct[2065].vm='1' & struct[2065].version='supp58' & struct[2065].name='CTDIvol' struct[2066].group_number='0070'x & struct[2066].element_number='0080'x & struct[2066].vr='CS' & struct[2066].vm='1' & struct[2066].version='supp73' & struct[2066].name='ContentLabel' struct[2067].group_number='0070'x & struct[2067].element_number='0081'x & struct[2067].vr='LO' & struct[2067].vm='1' & struct[2067].version='supp73' & struct[2067].name='ContentDescription' struct[2068].group_number='0070'x & struct[2068].element_number='0084'x & struct[2068].vr='PN' & struct[2068].vm='1' & struct[2068].version='supp73' & struct[2068].name='ContentCreatorsName' struct[2069].group_number='0008'x & struct[2069].element_number='1200'x & struct[2069].vr='SQ' & struct[2069].vm='1' & struct[2069].version='supp73' & struct[2069].name='StudiesContainingOtherReferencedInstancesSequence' struct[2070].group_number='0070'x & struct[2070].element_number='0306'x & struct[2070].vr='CS' & struct[2070].vm='1' & struct[2070].version='supp73' & struct[2070].name='ShapeType' struct[2071].group_number='0070'x & struct[2071].element_number='0308'x & struct[2071].vr='SQ' & struct[2071].vm='1' & struct[2071].version='supp73' & struct[2071].name='RegistrationSequence' struct[2072].group_number='0070'x & struct[2072].element_number='0309'x & struct[2072].vr='SQ' & struct[2072].vm='1' & struct[2072].version='supp73' & struct[2072].name='MatrixRegistrationSequence' struct[2073].group_number='0070'x & struct[2073].element_number='030A'x & struct[2073].vr='SQ' & struct[2073].vm='1' & struct[2073].version='supp73' & struct[2073].name='MatrixSequence' struct[2074].group_number='0070'x & struct[2074].element_number='030C'x & struct[2074].vr='CS' & struct[2074].vm='1' & struct[2074].version='supp73' & struct[2074].name='FrameOfReferenceTransformationMatrixType' struct[2075].group_number='0070'x & struct[2075].element_number='030D'x & struct[2075].vr='SQ' & struct[2075].vm='1' & struct[2075].version='supp73' & struct[2075].name='RegistrationTypeCodeSequence' struct[2076].group_number='0070'x & struct[2076].element_number='030F'x & struct[2076].vr='ST' & struct[2076].vm='1' & struct[2076].version='supp73' & struct[2076].name='FiducialDescription' struct[2077].group_number='0070'x & struct[2077].element_number='0310'x & struct[2077].vr='SH' & struct[2077].vm='1' & struct[2077].version='supp73' & struct[2077].name='FiducialIdentifier' struct[2078].group_number='0070'x & struct[2078].element_number='0311'x & struct[2078].vr='SQ' & struct[2078].vm='1' & struct[2078].version='supp73' & struct[2078].name='FiducialIdentifierCodeSequence' struct[2079].group_number='0070'x & struct[2079].element_number='0312'x & struct[2079].vr='FD' & struct[2079].vm='1' & struct[2079].version='supp73' & struct[2079].name='ContourUncertaintyRadius' struct[2080].group_number='0070'x & struct[2080].element_number='0314'x & struct[2080].vr='SQ' & struct[2080].vm='1' & struct[2080].version='supp73' & struct[2080].name='UsedFiducialsSequence' struct[2081].group_number='0070'x & struct[2081].element_number='0318'x & struct[2081].vr='SQ' & struct[2081].vm='1' & struct[2081].version='supp73' & struct[2081].name='GraphicCoordinatesDataSequence' struct[2082].group_number='0070'x & struct[2082].element_number='031A'x & struct[2082].vr='UI' & struct[2082].vm='1' & struct[2082].version='supp73' & struct[2082].name='FiducialUID' struct[2083].group_number='0070'x & struct[2083].element_number='031C'x & struct[2083].vr='SQ' & struct[2083].vm='1' & struct[2083].version='supp73' & struct[2083].name='FiducialSetSequence' struct[2084].group_number='0070'x & struct[2084].element_number='031E'x & struct[2084].vr='SQ' & struct[2084].vm='1' & struct[2084].version='supp73' & struct[2084].name='FiducialSequence' endgdl-0.9.9/src/pro/dicom/gdlffdicom__test.pro000077500000000000000000000134121340051421000207710ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ; The test data for this routine can be obtained from ; http://www.creatis.insa-lyon.fr/~jpr/PUBLIC/gdcm/gdcmData.tar.gz pro GDLffDICOM__test0 dicom_obj = obj_new('GDLffDICOM') starttime =systime(1) result = dicom_obj -> Read('NM-MONO2-16-13x-heart.dcm') if (result) then begin description = dicom_obj -> GetDescription(REFERENCE=42) element = dicom_obj -> GetElement(REFERENCE=42) group = dicom_obj -> GetGroup(REFERENCE=42) vr = dicom_obj -> GetVR(REFERENCE=42) len = dicom_obj -> GetLength(REFERENCE=42) parent = dicom_obj -> GetParent(42) value = dicom_obj -> GetValue(REFERENCE=42,/no_copy) preamble = dicom_obj -> GetPreamble() print, "Time", systime(1)-starttime ; help, description[0], element[0], group[0], vr[0], len[0], parent[0], (*value[0])[0], preamble print, "Description", dicom_obj -> GetReference(DESCRIPTION='BitsAllocated') print, "VR", dicom_obj -> GetReference(VR='US') print, "Tag", dicom_obj -> GetReference('0028'x,'0100'x) print, "ALL", dicom_obj -> GetReference('0028'x,'0100'x,DESCRIPTION='BitsAllocated',VR='US') endif obj_destroy, dicom_obj ; help, /heap end pro GDLffDICOM__test1 dicom_obj = obj_new('GDLffDICOM') result = dicom_obj -> Read('NM-MONO2-16-13x-heart.dcm',/no_catch) if (result) then begin reference = dicom_obj -> GetReference('0028'x,'0100'x) value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) ; help, (*(value[0])) result = dicom_obj -> Commit('NM-MONO2-16-13x-heart.dcm_copy') endif obj_destroy, dicom_obj ;help, /heap end pro GDLffDICOM__test2 dicom_obj = obj_new('GDLffDICOM') result = dicom_obj -> Read('NM-MONO2-16-13x-heart.dcm') if (result) then begin ; help, result reference = dicom_obj -> GetReference('0010'x,'0010'x) value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) ; help, (*(value[0])) dicom_obj -> SetValue, reference, 'Robert Barnett' value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) ; help, (*(value[0])) result = dicom_obj -> Commit('NM-MONO2-16-13x-heart.dcm_copy') endif obj_destroy, dicom_obj ;help, /heap end pro GDLffDICOM__test3 dicom_obj = obj_new('GDLffDICOM') result = dicom_obj -> Read('NM-MONO2-16-13x-heart.dcm') if (result) then begin ;help, result reference = dicom_obj -> GetReference('0010'x,'0010'x) dicom_obj -> SetValue, reference, 'Robert Barnett' value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) ;help, (*(value[0])) reference = dicom_obj -> GetReference('0018'x,'0015'x) dicom_obj -> SetValue, reference, 'Chicken' value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) ;help, (*(value[0])) result = dicom_obj -> Commit('NM-MONO2-16-13x-heart.dcm_copy') endif obj_destroy, dicom_obj ;help, /heap end pro GDLffDICOM__test4 dicom_obj = obj_new('GDLffDICOM') result = dicom_obj -> Read('GE_LOGIQBook-8-RGB-HugePreview.dcm',/NO_CATCH) if (result) then begin ;help, result ; reference = dicom_obj -> GetReference('0008'x,'2111'x) ; dicom_obj -> SetValue, reference[0], 'Robert Barnett' ; value = dicom_obj -> GetValue(REFERENCE=reference[0],/no_copy) ; help, (*(value[0])) ; reference = dicom_obj -> GetReference('7fe1'x,'0010'x) ; y = 0 ; dicom_obj -> SetValue, reference[y], 'Chicken' ; value = dicom_obj -> GetValue(REFERENCE=reference[y],/no_copy) ; help, (*(value[0])) result = dicom_obj -> Commit('GE_LOGIQBook-8-RGB-HugePreview.dcm_copy') ;dicom_obj -> dump endif obj_destroy, dicom_obj ;help, result ;help, /heap end pro GDLffDICOM__test, inds, ALL=all ;/farmyard/robert/download/gdcmdata if (keyword_set(all)) then inds = indgen(5) for i=0,n_elements(inds)-1 do begin call_procedure, STRING('GDLffDICOM__test',inds[i],FORMAT="(A,I0)") endfor end pro GDLffDICOM__test5 file = '\\a3printer2\farmyard\wmidl\nmtkdualrenal0\test\2008.0.14125138.dcm' dicom_obj = obj_new('GDLffDICOM') result = dicom_obj -> Read(file);,/NO_CATCH) if (result) then begin dicom_obj -> dumpElements endif obj_destroy, dicom_obj end pro GDLffDICOM__test6 cd, '~/Public/IDL/nmaprototype' ;cd, 'E:\public\IDL\nmaprototype' dicom_obj = obj_new('GDLffDICOM') result = dicom_obj -> Read('snapshot_template.dcm') if (result) then begin sop_uid = GDLffDICOM__assoc_GenerateUID(40) help, sop_uid reference = dicom_obj -> GetReference('0008'x,'0018'x) value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) help, (*(value[0])) dicom_obj -> SetValue, reference, sop_uid value = dicom_obj -> GetValue(REFERENCE=reference,/no_copy) help, (*(value[0])) result = dicom_obj -> Commit('output0.dcm') endif obj_destroy, dicom_obj ;help, /heap end gdl-0.9.9/src/pro/dicom/gdlffdicom_copy_lun.pro000066400000000000000000000023421340051421000215000ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ; Introduced for compatibility with IDL pro gdlffdicom_copy_lun, fromUnit, toUnit, Num if (num gt 0) then begin buffer = bytarr(Num) readu, fromUnit, buffer writeu, toUnit, temporary(buffer) endif end gdl-0.9.9/src/pro/dicom/gdlffdicom_date.pro000066400000000000000000000035641340051421000205740ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ;+ ; Return a DICOM formatted date string ; @field elsapsed_seconds ;- function gdlffdicom_date, elapsed_seconds, UTC=utc if (n_elements(elapsed_seconds)) then begin if (size(elapsed_seconds,/type) eq 7) then date_str = elapsed_seconds $ else date_str = systime(0,double(elapsed_seconds), UTC=utc) endif else $ date_str = systime(UTC=utc) dow = '' mon = '' day = 0l hour = 0l minute = 0l second = 0l year = 0l s1 = ':' s2 = ':' READS, date_str, dow, mon, day, hour, s1, minute, s2, second, year, FORMAT="(A3,A4,I3,I3,A1,I02,A1,I02,I5)" imon = where(mon eq ['',' Jan',' Feb',' Mar',' Apr',' May',' Jun',' Jul',' Aug',' Sep',' Oct',' Nov',' Dec'],count) if (count gt 0) then return, string(year,imon[0],day,FORMAT="(I04,I02,I02)") $ else message, 'No such month' ; for i=0l,10000 do help, gdlffdicom_date(systime(1)+randomu(seed)*100000000.) end gdl-0.9.9/src/pro/dicom/gdlffdicom_time.pro000066400000000000000000000046311340051421000206110ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ; function gdlffdicom_seconds, date_str, time_str ; READS, date_str, year, imon, day, FORMAT="(I04,I02,I02)" ; READS, time_str, hour,minute,second,FORMAT="(I02,I02,I02)" ; dow = 'Mon' ; s1 = ':' ; s2 = ':' ; mon = (['',' Jan',' Feb',' Mar',' Apr',' May',' Jun',' Jul',' Aug',' Sep',' Oct',' Nov',' Dec'])[imon] ; str = string(dow, mon, day, hour, s1, minute, s2, second, year, FORMAT="(A3,A4,I3,I3,A1,I02,A1,I02,I5)") ; help, str, year, imon, day, hour, minute, second ; return, systime(0,str) ; ; help, gdlffdicom_seconds(gdlffdicom_date(),gdlffdicom_time()) ; end function gdlffdicom_time, elapsed_seconds, UTC=utc if (n_elements(elapsed_seconds)) then begin if (size(elapsed_seconds,/type) eq 7) then date_str = elapsed_seconds $ else date_str = systime(0,double(elapsed_seconds), UTC=utc) endif else $ date_str = systime(UTC=utc) dow = '' mon = '' day = 0l hour = 0l minute = 0l second = 0l year = 0l s1 = ':' s2 = ':' READS, date_str, dow, mon, day, hour, s1, minute, s2, second, year, FORMAT="(A3,A4,I3,I3,A1,I02,A1,I02,I5)" ;imon = where(mon eq ['',' Jan',' Feb',' Mar',' Apr',' May',' Jun',' Jul',' Aug',' Sep',' Oct',' Nov',' Dec'],count) ;help, mon return, string(hour,minute,second,FORMAT="(I02,I02,I02,'.000000')") ;print, dow, mon, day, hour, s1, minute, s2, second, year, FORMAT="(A3,A4,I3,I3,A1,I02,A1,I02,I5)" ;help, dow, mon, day, hour, minute, second, year end gdl-0.9.9/src/pro/dicom/gdlffdicom_trim.pro000066400000000000000000000023551340051421000206270ustar00rootroot00000000000000;L+ ; LICENSE: ; ; IDL user contributed source code ; Copyright (C) 2006 Robbie Barnett ; ; This library 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 2.1 of the License, ; or (at your option) any later version. ; ; This library 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 Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public License ; along with this library; if not, write to the ; Free Software Foundation, Inc. ; 51 Franklin Street, Suite 500 ; Boston, MA 02110-1335, USA ; ; Please send queries to: ; Robbie Barnett ; Nuclear Medicine and Ultrasound ; Westmead Hospital ; +61 2 9845 7223 ;L- ; Trim off a trailing null character function gdlffdicom_trim, value len = strlen(value) if ((len gt 0) && (byte(strmid(value,0,1,/REVERSE_OFFSET)) eq 0)) then $ return, strmid(value,0,len-1) $ else $ return, value end gdl-0.9.9/src/pro/dilate.pro000066400000000000000000000457551340051421000156600ustar00rootroot00000000000000; ; GDL replacement to DILATE in IDL ; Bin Wu ; Aug. 2018 ; ; Arguments (from IDL): Image Structure X0 Y0 Z0 ; Keywords (from IDL): ; BACKGROUND ; Set this keyword to the pixel value that is to be considered the background when ; dilation is being performed in constrained mode. The default value is 0. ; CONSTRAINED (a boolean keyword) ; If this keyword is set and grayscale dilation has been selected, the dilation ; algorithm will operate in constrained mode. In this mode, a pixel is set to the ; value determined by normal grayscale dilation rules in the output image only if ; the current value destination pixel value matches the BACKGROUND pixel value. Once ; a pixel in the output image has been set to a value other than the BACKGROUND ; value, it cannot change. ; GRAY (a boolean keyword) ; Set this keyword to perform grayscale, rather than binary, dilation. The nonzero ; elements of the Structure parameter determine the shape of the structuring element ; (neighborhood). If VALUES is not present, all elements of the structuring element ; are 0, yielding the neighborhood maximum operator. ; PRESERVE_TYPE (a boolean keyword) ; Set this keyword to return the same type as the input array. This keyword only ; applies if the GRAY keyword is set. ; UINT (a boolean keyword) ; Set this keyword to return an unsigned integer array. This keyword only applies if ; the GRAY keyword is set. ; ULONG (a boolean keyword) ; Set this keyword to return an unsigned longword integer array. This keyword only ; applies if the GRAY keyword is set. ; VALUES ; An array with the same dimensions as Structure providing the values of the ; structuring element. The presence of this parameter implies grayscale dilation. ; Each pixel of the result is the maximum of the sum of the corresponding elements ; of VALUE and the Image pixel value. If the resulting sum is greater than 255, the ; return value is 255. ; Return (from IDL): the dilation of image ; Syntax (from IDL): ; Result = DILATE( Image, Structure [, X0 [, Y0 [, Z0]]] [, /CONSTRAINED [, ; BACKGROUND=value]] [, /GRAY [, /PRESERVE_TYPE | , /UINT | , /ULONG]] [, ; VALUES=array] ) ; Ref: http://www.harrisgeospatial.com/docs/DILATE.html ; FUNCTION DILATE, Image, Structure, X0, Y0, Z0, $ CONSTRAINED=CONSTRAINED, BACKGROUND=BACKGROUND, $ GRAY=GRAY, PRESERVE_TYPE=PRESERVE_TYPE, $ UINT=UINT, ULONG=ULONG, VALUES=VALUES ; Return the caller of a procedure in the event of an error. ON_ERROR, 2 ; At least Image and Structure are needed. IF (N_PARAMS() LE 1) THEN BEGIN MESSAGE, 'Incorrect number of arguments.' ENDIF ; Get the Structure size. dimStt = SIZE(Structure) ; Get the image size. dims = SIZE(Image) ; Make sure Structure has the same dimension as Image. IF (dims[0] NE dimStt[0]) THEN BEGIN CASE dimStt[0] OF 1: BEGIN CASE dims[0] OF 2: Structure = [[Structure],[REPLICATE(0,dimStt[1],1)]] 3: Structure = [[[Structure],[REPLICATE(0,dimStt[1],1)]],[[REPLICATE(0,dimStt[1],2)]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 2: BEGIN CASE dims[0] OF 1: Structure = Structure[*,0] 3: Structure = [[[Structure]],[[REPLICATE(0,dimStt[1],dimStt[2])]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 3: BEGIN CASE dims[0] OF 1: Structure = Structure[*,0,0] 2: Structure = Structure[*,*,0] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE dimStt=SIZE(Structure) ENDIF ; Get the coordinate of the origin of Structure. CASE dimStt[0] OF 1: IF (N_ELEMENTS(X0) EQ 0) THEN X0 = dimStt[1]/2 2: BEGIN IF (N_ELEMENTS(X0) EQ 0) THEN X0 = dimStt[1]/2 IF (N_ELEMENTS(Y0) EQ 0) THEN Y0 = dimStt[2]/2 END 3: BEGIN IF (N_ELEMENTS(X0) EQ 0) THEN X0 = dimStt[1]/2 IF (N_ELEMENTS(Y0) EQ 0) THEN Y0 = dimStt[2]/2 IF (N_ELEMENTS(Z0) EQ 0) THEN Z0 = dimStt[3]/2 END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE ; Set default value to BACKGROUND. IF (KEYWORD_SET(BACKGROUND) EQ 0) THEN BACKGROUND = 0 ; Gray: a boolean keyword. IF (KEYWORD_SET(GRAY) OR KEYWORD_SET(VALUES)) THEN BEGIN ; Gray image; ; ; Make sure VALUES has the same dimension as Image. IF KEYWORD_SET(VALUES) THEN BEGIN dimVal = SIZE(VALUES) IF (dims[0] NE dimVal[0]) THEN BEGIN CASE dimVal[0] OF 1: BEGIN CASE dims[0] OF 2: VALUES = [[VALUES],[REPLICATE(0,dimVal[1],1)]] 3: VALUES = [[[VALUES],[REPLICATE(0,dimVal[1],1)]],[[REPLICATE(0,dimVal[1],2)]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 2: BEGIN CASE dims[0] OF 1: VALUES = VALUES[*,0] 3: VALUES = [[[VALUES]],[[REPLICATE(0,dimVal[1],dimVal[2])]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 3: BEGIN CASE dims[0] OF 1: VALUES = VALUES[*,0,0] 2: VALUES = VALUES[*,*,0] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE dimVal=SIZE(VALUES) ENDIF CASE dimVal[0] OF 1: BEGIN IF dimVal[1] LT dimStt[1] THEN VALUES = [VALUES,REPLICATE(0,dimStt[1] - dimVal[1],1)] IF dimVal[1] GT dimStt[1] THEN VALUES = VALUES[0:dimStt[1]-1,*] END 2: BEGIN IF dimVal[1] LT dimStt[1] THEN VALUES = [VALUES,REPLICATE(0,dimStt[1] - dimVal[1],dimVal[2])] IF dimVal[1] GT dimStt[1] THEN VALUES = VALUES[0:dimStt[1]-1,*] dimVal = SIZE(VALUES) IF dimVal[2] LT dimStt[2] THEN VALUES = [[VALUES],[REPLICATE(0,dimVal[1],dimStt[2] - dimVal[2])]] IF dimVal[2] GT dimStt[2] THEN VALUES = VALUES[*,0:dimStt[2]-1] END 3: BEGIN IF dimVal[1] LT dimStt[1] THEN VALUES = [VALUES,REPLICATE(0,dimStt[1] - dimVal[1],dimVal[2],dimVal[3])] IF dimVal[1] GT dimStt[1] THEN VALUES = VALUES[0:dimStt[1]-1,*] dimVal = SIZE(VALUES) IF dimVal[2] LT dimStt[2] THEN VALUES = [[VALUES],[REPLICATE(0,dimVal[1],dimStt[2] - dimVal[2],dimVal[3])]] IF dimVal[2] GT dimStt[2] THEN VALUES = VALUES[*,0:dimStt[2]-1,*] dimVal = SIZE(VALUES) IF dimVal[3] LT dimStt[3] THEN VALUES = [[[VALUES]],[[REPLICATE(0,dimVal[1],dimVal[2],dimStt[3] - dimVal[3])]]] IF dimVal[3] GT dimStt[3] THEN VALUES = VALUES[*,*,0:dimStt[3]-1] END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE ENDIF ; ; In case VALUES are not given, as the image is Gray, ; set VALUES to be of the same size as Structure ; with all the elements to be 0. IF (KEYWORD_SET(VALUES) EQ 0) THEN BEGIN CASE dimStt[0] OF 1: VALUES = REPLICATE(0, dimStt[1]) 2: VALUES = REPLICATE(0, dimStt[1], dimStt[2]) 3: VALUES = REPLICATE(0, dimStt[1], dimStt[2], dimStt[3]) ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE ENDIF ; dilateImg = Image ; ; Two situations: CONSTRAINED and UNCONSTRAINED IF KEYWORD_SET(CONSTRAINED) THEN BEGIN ; An auxiliary variable. tmpImg = dilateImg ; ; CONSTRAINED situation. ; 1D-3D. CASE dimStt[0] OF 1: BEGIN tmpS = REVERSE(Structure) tmpV = REVERSE(VALUES) tmpValue = INTARR(dims[1]) tmpValue[X0] = $ dilateImg[X0:dims[1]-dimStt[1]+X0] FOR I = 0, dims[1]-1 DO BEGIN IF dilateImg[I] EQ BACKGROUND THEN BEGIN tmpM1 = (I-dimStt[1]+1+X0 LT 0) ? 0:I-dimStt[1]+1+X0 tmpM2 = (I+X0 GT dims[1]-1) ? dims[1]-1:I+X0 tmpSM1 = (I-dimStt[1]+1+X0 LT 0) ? -I+dimStt[1]-1-X0:0 tmpSM2 = (I+X0 GT dims[1]-1) ? dimStt[1]-1-I-X0+dims[1]-1:dimStt[1]-1 tmpImg[I] = MIN([255,MAX($ (tmpValue[tmpM1:tmpM2] + $ tmpV[tmpSM1:tmpSM2]) * $ tmpS[tmpSM1:tmpSM2])]) ENDIF ENDFOR END 2: BEGIN tmpS = REVERSE(REVERSE(Structure),2) tmpV = REVERSE(REVERSE(VALUES),2) tmpValue = INTARR(dims[1],dims[2]) tmpValue[X0,Y0] = $ adilateImg[X0:dims[1]-dimStt[1]+X0,Y0:dims[2]-dimStt[2]+Y0] FOR I = 0, dims[1]-1 DO BEGIN FOR J = 0, dims[2]-1 DO BEGIN IF dilateImg[I,J] EQ BACKGROUND THEN BEGIN tmpM1 = (I-dimStt[1]+1+X0 LT 0) ? 0:I-dimStt[1]+1+X0 tmpN1 = (J-dimStt[2]+1+Y0 LT 0) ? 0:J-dimStt[2]+1+Y0 tmpM2 = (I+X0 GT dims[1]-1) ? dims[1]-1:I+X0 tmpN2 = (J+Y0 GT dims[2]-1) ? dims[2]-1:J+Y0 tmpSM1 = (I-dimStt[1]+1+X0 LT 0) ? -I+dimStt[1]-1-X0:0 tmpSN1 = (J-dimStt[2]+1+Y0 LT 0) ? -J+dimStt[2]-1-Y0:0 tmpSM2 = (I+X0 GT dims[1]-1) ? dimStt[1]-1-I-X0+dims[1]-1:dimStt[1]-1 tmpSN2 = (J+Y0 GT dims[2]-1) ? dimStt[2]-1-J-Y0+dims[2]-1:dimStt[2]-1 tmpImg[I,J] = MIN([255,MAX($ (tmpValue[tmpM1:tmpM2,tmpN1:tmpN2] + $ tmpV[tmpSM1:tmpSM2,tmpSN1:tmpSN2]) * $ tmpS[tmpSM1:tmpSM2,tmpSN1:tmpSN2])]) ENDIF ENDFOR ENDFOR END 3: BEGIN tmpS = REVERSE(REVERSE(REVERSE(Structure),2),3) tmpV = REVERSE(REVERSE(REVERSE(VALUES),2),3) tmpValue = INTARR(dims[1],dims[2],dims[3]) tmpValue[X0,Y0,Z0] = $ dilateImg[X0:dims[1]-dimStt[1]+X0,Y0:dims[2]-dimStt[2]+Y0,Z0:dims[3]-dimStt[3]+Z0] FOR I = 0, dims[1]-1 DO BEGIN FOR J = 0, dims[2]-1 DO BEGIN FOR K = 0, dims[3]-1 DO BEGIN IF dilateImg[I,J,K] EQ BACKGROUND THEN BEGIN tmpM1 = (I-dimStt[1]+1+X0 LT 0) ? 0:I-dimStt[1]+1+X0 tmpN1 = (J-dimStt[2]+1+Y0 LT 0) ? 0:J-dimStt[2]+1+Y0 tmpL1 = (K-dimStt[3]+1+Z0 LT 0) ? 0:K-dimStt[3]+1+Z0 tmpM2 = (I+X0 GT dims[1]-1) ? dims[1]-1:I+X0 tmpN2 = (J+Y0 GT dims[2]-1) ? dims[2]-1:J+Y0 tmpL2 = (K+Z0 GT dims[3]-1) ? dims[3]-1:K+Z0 tmpSM1 = (I-dimStt[1]+1+X0 LT 0) ? -I+dimStt[1]-1-X0:0 tmpSN1 = (J-dimStt[2]+1+Y0 LT 0) ? -J+dimStt[2]-1-Y0:0 tmpSL1 = (K-dimStt[3]+1+Z0 LT 0) ? -K+dimStt[3]-1-Z0:0 tmpSM2 = (I+X0 GT dims[1]-1) ? dimStt[1]-1-I-X0+dims[1]-1:dimStt[1]-1 tmpSN2 = (J+Y0 GT dims[2]-1) ? dimStt[2]-1-J-Y0+dims[2]-1:dimStt[2]-1 tmpSL2 = (K+Z0 GT dims[3]-1) ? dimStt[3]-1-K-Z0+dims[3]-1:dimStt[3]-1 tmpImg[I,J,K] = MIN([255,MAX($ (tmpValue[tmpM1:tmpM2,tmpN1:tmpN2,tmpL1:tmpL2] + $ tmpV[tmpSM1:tmpSM2,tmpSN1:tmpSN2,tmpSL1:tmpSL2]) * $ tmpS[tmpSM1:tmpSM2,tmpSN1:tmpSN2,tmpSL1:tmpSL2])]) ENDIF ENDFOR ENDFOR ENDFOR END ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE dilateImg = tmpImg ; ENDIF ELSE BEGIN ; An auxiliary variable. tmpImg = dilateImg ; ; UNCONSTRAINED situation. ; 1D-3D. CASE dimStt[0] OF 1: BEGIN tmpS = REVERSE(Structure) tmpV = REVERSE(VALUES) tmpValue = INTARR(dims[1]) tmpValue[X0] = $ dilateImg[X0:dims[1]-dimStt[1]+X0] FOR I = 0, dims[1]-1 DO BEGIN tmpM1 = (I-dimStt[1]+1+X0 LT 0) ? 0:I-dimStt[1]+1+X0 tmpM2 = (I+X0 GT dims[1]-1) ? dims[1]-1:I+X0 tmpSM1 = (I-dimStt[1]+1+X0 LT 0) ? -I+dimStt[1]-1-X0:0 tmpSM2 = (I+X0 GT dims[1]-1) ? dimStt[1]-1-I-X0+dims[1]-1:dimStt[1]-1 tmpImg[I] = MIN([255,MAX($ (tmpValue[tmpM1:tmpM2] + $ tmpV[tmpSM1:tmpSM2]) * $ tmpS[tmpSM1:tmpSM2])]) ENDFOR END 2: BEGIN tmpS = REVERSE(REVERSE(Structure),2) tmpV = REVERSE(REVERSE(VALUES),2) tmpValue = INTARR(dims[1],dims[2]) tmpValue[X0,Y0] = $ dilateImg[X0:dims[1]-dimStt[1]+X0,Y0:dims[2]-dimStt[2]+Y0] FOR I = 0, dims[1]-1 DO BEGIN FOR J = 0, dims[2]-1 DO BEGIN tmpM1 = (I-dimStt[1]+1+X0 LT 0) ? 0:I-dimStt[1]+1+X0 tmpN1 = (J-dimStt[2]+1+Y0 LT 0) ? 0:J-dimStt[2]+1+Y0 tmpM2 = (I+X0 GT dims[1]-1) ? dims[1]-1:I+X0 tmpN2 = (J+Y0 GT dims[2]-1) ? dims[2]-1:J+Y0 tmpSM1 = (I-dimStt[1]+1+X0 LT 0) ? -I+dimStt[1]-1-X0:0 tmpSN1 = (J-dimStt[2]+1+Y0 LT 0) ? -J+dimStt[2]-1-Y0:0 tmpSM2 = (I+X0 GT dims[1]-1) ? dimStt[1]-1-I-X0+dims[1]-1:dimStt[1]-1 tmpSN2 = (J+Y0 GT dims[2]-1) ? dimStt[2]-1-J-Y0+dims[2]-1:dimStt[2]-1 tmpImg[I,J] = MIN([255,MAX($ (tmpValue[tmpM1:tmpM2,tmpN1:tmpN2] + $ tmpV[tmpSM1:tmpSM2,tmpSN1:tmpSN2]) * $ tmpS[tmpSM1:tmpSM2,tmpSN1:tmpSN2])]) ENDFOR ENDFOR END 3: BEGIN tmpS = REVERSE(REVERSE(REVERSE(Structure),2),3) tmpV = REVERSE(REVERSE(REVERSE(VALUES),2),3) tmpValue = INTARR(dims[1],dims[2],dims[3]) tmpValue[X0,Y0,Z0] = $ dilateImg[X0:dims[1]-dimStt[1]+X0,Y0:dims[2]-dimStt[2]+Y0,Z0:dims[3]-dimStt[3]+Z0] FOR I = 0, dims[1]-1 DO BEGIN FOR J = 0, dims[2]-1 DO BEGIN FOR K = 0, dims[3]-1 DO BEGIN tmpM1 = (I-dimStt[1]+1+X0 LT 0) ? 0:I-dimStt[1]+1+X0 tmpN1 = (J-dimStt[2]+1+Y0 LT 0) ? 0:J-dimStt[2]+1+Y0 tmpL1 = (K-dimStt[3]+1+Z0 LT 0) ? 0:K-dimStt[3]+1+Z0 tmpM2 = (I+X0 GT dims[1]-1) ? dims[1]-1:I+X0 tmpN2 = (J+Y0 GT dims[2]-1) ? dims[2]-1:J+Y0 tmpL2 = (K+Z0 GT dims[3]-1) ? dims[3]-1:K+Z0 tmpSM1 = (I-dimStt[1]+1+X0 LT 0) ? -I+dimStt[1]-1-X0:0 tmpSN1 = (J-dimStt[2]+1+Y0 LT 0) ? -J+dimStt[2]-1-Y0:0 tmpSL1 = (K-dimStt[3]+1+Z0 LT 0) ? -K+dimStt[3]-1-Z0:0 tmpSM2 = (I+X0 GT dims[1]-1) ? dimStt[1]-1-I-X0+dims[1]-1:dimStt[1]-1 tmpSN2 = (J+Y0 GT dims[2]-1) ? dimStt[2]-1-J-Y0+dims[2]-1:dimStt[2]-1 tmpSL2 = (K+Z0 GT dims[3]-1) ? dimStt[3]-1-K-Z0+dims[3]-1:dimStt[3]-1 tmpImg[I,J,K] = MIN([255,MAX($ (tmpValue[tmpM1:tmpM2,tmpN1:tmpN2,tmpL1:tmpL2] + $ tmpV[tmpSM1:tmpSM2,tmpSN1:tmpSN2,tmpSL1:tmpSL2]) * $ tmpS[tmpSM1:tmpSM2,tmpSN1:tmpSN2,tmpSL1:tmpSL2])]) ENDFOR ENDFOR ENDFOR END ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE dilateImg = tmpImg ENDELSE ; ENDIF ELSE BEGIN ; Binary image otherwise. dilateImg = Image GT 0 ; ; An auxiliary variable. tmpImg = dilateImg - dilateImg ; ; 1D-3D. CASE dimStt[0] OF 1: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN IF dilateImg[I] EQ 1 THEN BEGIN tmpImg[I-X0:I+dimStt[1]-1-X0] = $ tmpImg[I-X0:I+dimStt[1]-1-X0] OR $ Structure ENDIF ENDFOR END 2: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN FOR J = Y0, dims[2]-dimStt[2]+Y0 DO BEGIN IF dilateImg[I,J] EQ 1 THEN BEGIN tmpImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0] = $ tmpImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0] OR $ Structure ENDIF ENDFOR ENDFOR END 3: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN FOR J = Y0, dims[2]-dimStt[2]+Y0 DO BEGIN FOR K = Z0, dims[3]-dimStt[3]+Z0 DO BEGIN IF dilateImg[I,J] EQ 1 THEN BEGIN tmpImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0,K-Z0:K+dimStt[3]-1-Z0] = $ tmpImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0,K-Z0:K+dimStt[3]-1-Z0] OR $ Structure ENDIF ENDFOR ENDFOR ENDFOR END ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE ; dilateImg = tmpImg ENDELSE ; Gray: a boolean keyword. IF KEYWORD_SET(GRAY) THEN BEGIN ; Gray image; ; ; Give the type of the returned array. IF KEYWORD_SET(PRESERVE_TYPE) THEN BEGIN tp = TYPENAME(Image) dilateImg = CALL_FUNCTION(tp,dilateImg) ENDIF IF KEYWORD_SET(UINT) THEN dilateImg = UINT(dilateImg) IF KEYWORD_SET(ULONG) THEN dilateImg = ULONG(dilateImg) ENDIF RETURN, dilateImg END gdl-0.9.9/src/pro/dist.pro000066400000000000000000000027771340051421000153560ustar00rootroot00000000000000;+ ; NAME: ; DIST ; ; ; PURPOSE: ; Return an array with its values equal to the distance from the ; origin. ; ; ; CATEGORY: ; General utilities ; ; ; CALLING SEQUENCE: ; array = dist(m[,n]) ; ; ; INPUTS: ; m,n The dimensions of the array. ; ; ; OUTPUTS: ; array float The resultant array. ; ; ; MODIFICATION HISTORY: ; 14-Mar-2005 : written by SJT ; 21-Jul-2005 : PC faster algorithm ; 06-Oct-2009 : AC ; -- managing DIST([12,24]) and DIST([12,24],13) ; -- managing 0 or Neg Values ; ; LICENCE: ; Copyright (C) 2005, SJT, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- function DIST, m, n on_error, 2 ; ; When "m" or "n" contain more than one element, ; only the first one is used ! ; if (N_ELEMENTS(m) GT 1) then m=m[0] if (N_ELEMENTS(n) GT 1) then n=n[0] ; ; if only "m" is provided if (N_ELEMENTS(n) EQ 0) then n = m ; if ((m LE 0) OR (n LE 0)) then begin MESSAGE, "Array dimensions must be greater than 0." endif ; x = FINDGEN(m) x = (x < (m-x))^2 result = FLTARR(m, n, /nozero) result[*,0] = SQRT(x) for i = 1l, n/2 do begin dist = SQRT(x + i^2.) ; i^2. is slightly faster than float(i)^2 result[0,i ] = dist ; [0,i] is way faster than [*,i] result[0,n-i] = dist endfor return, result end gdl-0.9.9/src/pro/doc_library.pro000066400000000000000000000053711340051421000166750ustar00rootroot00000000000000;+ ; NAME: ; DOC_LIBRARY ; ; PURPOSE: ; Extract and display documentation headers from a program or routine. ; ; CATEGORY: ; Documentation ; ; CALLING SEQUENCE: ; DOC_LIBRARY, procedure ; ; INPUTS: ; procedure STRING The procedure to document. ; ; KEYWORD PARAMETERS: ; /print Set to print the output to the default printer. ; /nowait read documentation in another window while GDL session goes on. ; SIDE EFFECTS: ; A file is created in /tmp and deleted after use (unless /nowait is successful). ; ; RESTRICTIONS: ; Only one documentation block per file is handled. ; ; EXAMPLE: ; DOC_LIBRARY, 'doc_library' ; ; MODIFICATION HISTORY: ; Original: 2013-March-28; SJT (see Feature Requests 3606434) ; Mods for win32 2015-May-18 G. Jung ; /NOWAIT keyword for win32 (Windows) and 'X' (unix) ; LICENCE: ; This code in under GNU GPL v2 or later ; pro DOC_LIBRARY, proc, print = print, test=test, nowait=nowait ;- if ~KEYWORD_SET(test) then ON_ERROR, 2 ; addexe="" tempprefix="/tmp/" ; if (!version.os_family eq 'Windows') then begin addexe=".EXE" tempprefix=getenv("TEMP")+"\" endif ; if KEYWORD_SET(print) then begin less = FILE_WHICH(getenv('PATH'), 'lp') if (less eq '') then less = FILE_WHICH(GETENV('PATH'), 'lpr') if (less eq '') then begin print, "Neither lp nor lpr was found" return endif endif else begin less = FILE_WHICH(GETENV('PATH'), 'less'+addexe) if (less eq '') then less = FILE_WHICH(GETENV('PATH'), 'more'+addexe) if (less eq '') then begin if (!version.os_family eq 'Windows') then less='more' $ else begin print, "Neither more nor less was found" return endelse endif endelse ; proc_path = FILE_WHICH(proc+'.pro', /include_current) if (proc_path eq '') then begin print, proc, ' not found' return endif out_name = tempprefix+proc+'.txt' OPENR, ipu, proc_path, /get dflag = 0b inln = '' OPENW, isu, out_name, /get dflag=0 while (~EOF(ipu)) do begin READF, ipu, inln inln = STRTRIM(inln, 2) if (STRPOS(inln, ';') eq 0) then begin if (STRPOS(inln, ';+') eq 0) then dflag = 1b if (STRPOS(inln, ';-') eq 0) then break inln = strmid(inln,1) endif else if dflag then inln='@>'+inln ;; if dflag then printf, isu, inln endwhile ; FREE_LUN, isu, ipu ; if KEYWORD_SET(nowait) then begin if (!version.os_family eq 'unix') then begin if (!D.name eq 'X') then $ SPAWN, 'xterm -e '+less+' '+out_name+' &' $ else begin print," You need !D.name='X' to do that /nowait" SPAWN, less+' '+out_name FILE_DELETE, out_name endelse endif else SPAWN, /nowait, less+' '+out_name endif ; if ~KEYWORD_SET(nowait) then begin SPAWN, less+' '+out_name FILE_DELETE, out_name endif ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/envi/000077500000000000000000000000001340051421000146155ustar00rootroot00000000000000gdl-0.9.9/src/pro/envi/read_envi_file.pro000066400000000000000000000465301340051421000203020ustar00rootroot00000000000000;+ ; ; NAME: ; READ_ENVI_FILE ; PURPOSE: ; Reads an ENVI style formatted image file (both compressed and ; uncompressed). ; ; CATEGORY: ; File I/O ; ; CALLING SEQUENCE: ; READ_ENVI_FILE, filename, image=image, info=image_info ; ; KEYWORD PARAMETERS: ; FILENAME: A string containing the full filepath name of the image. ; IMAGE: Variable name to contain the image/array ; INFO: Variable name to contain the image information as a structure ; HELP: showing how to use and exit ; ; OUTPUTS: ; image: An array containing the image ; image_info: A structure containing information about the image ; eg. number of samples, number of lines, number of bands, ; data type, interleave, file description, band names. ; ; MODIFICATION HISTORY: ; 02-Jul-2012: Written by Josh Sixsmith ; 16-Feb-2014: Better managment of input filenames ; ; LICENCE: ; Copyright (C) 2012, Josh Sixsmith ; 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 of the License, or ; (at your option) any later version. ; ;- ; function NUM_SAMPLES, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fnsw = WHERE(STRPOS(header, "samples") NE -1, count) IF (count NE 0) THEN BEGIN fns = STRTRIM(header[fnsw], 2) fns1 = STRPOS(fns, '=') ns = STRMID(fns, fns1 + 2) ;; RETURN, (LONG(ns))[0] ENDIF ELSE BEGIN MESSAGE, 'Number of Samples Not Found.' ENDELSE ; END ; ;----------------------------------------------------------------------- ; function NUM_LINES, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fnlw = WHERE(STRPOS(header, "lines") NE -1, count) IF (count NE 0) THEN BEGIN fnl = STRTRIM(header[fnlw], 2) fnl1 = STRPOS(fnl, '=') nl = STRMID(fnl, fnl1 + 2) ;; RETURN, (LONG(nl))[0] ENDIF ELSE BEGIN MESSAGE, 'Number of Lines Not Found.' ENDELSE ; END ; ;----------------------------------------------------------------------- ; function NUM_BANDS, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fnbw = WHERE(STRPOS(header, "bands") NE -1, count) IF (count NE 0) THEN BEGIN fnb = STRTRIM(header[fnbw], 2) fnb1 = STRPOS(fnb, '=') nb = STRMID(fnb, fnb1 + 2) ;; RETURN, (LONG(nb))[0] ENDIF ELSE BEGIN MESSAGE, 'Number of Bands Not Found.' ENDELSE ; END ; ;----------------------------------------------------------------------- ; function MAP_INFO, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fmiw = WHERE(STRPOS(header, "map") NE -1, count) IF (count NE 0) THEN BEGIN fmi = STRTRIM(header[fmiw], 2) b1 = STRPOS(fmi, '{') b2 = STRPOS(fmi, '}', /reverse_search) b2b = STRSPLIT(STRMID(fmi, b1+1, b2-b1-1), ',', /extract) mi = {MapInfo, $ ProjectionName : b2b[0], $ ULRefX : b2b[1], $ ULRefY : b2b[2],$ ULXCoord : b2b[3],$ ULYCoord : b2b[4], $ XS : b2b[5], $ YS : b2b[6], $ Zone : b2b[7], $ Units : b2b[8]} ENDIF ELSE BEGIN mi = {map_info, empty:''} ENDELSE ; RETURN, mi ; END ; ;----------------------------------------------------------------------- ; FUNCTION DATATYPE, header ; COMPILE_OPT hidden ON_ERROR, 2 ; ;; Maybe need a check for correct data type, using filesize and array ;; dimensions before trying to read the data. ; fdtw = WHERE(STRPOS(header, "data type") NE -1, count) IF (count NE 0) THEN BEGIN fdt = STRTRIM(header[fdtw], 2) fdt1 = STRPOS(fdt, '=') dtype = STRMID(fdt, fdt1 + 2) ;; RETURN, (FIX(dtype))[0] ENDIF ELSE BEGIN MESSAGE, 'No Data Type Found.' ENDELSE ; END ; ;----------------------------------------------------------------------- ; FUNCTION interleave, header ; COMPILE_OPT hidden ON_ERROR, 2 ; filw = WHERE(STRPOS(header, "interleave") NE -1, count) IF (count NE 0) THEN BEGIN fil = STRTRIM(header[filw], 2) fil1 = STRPOS(fil, '=') ileave = STRMID(fil, fil1 + 2) ;; IF (STRCMP(ileave, 'BSQ', /fold_case)) EQ 1 THEN BEGIN intleave = 0 ENDIF ELSE BEGIN IF (strcmp(ileave, 'BIL', /fold_case)) EQ 1 THEN BEGIN intleave = 1 ENDIF ELSE BEGIN IF (STRCMP(ileave, 'BIP', /fold_case)) EQ 1 THEN BEGIN intleave = 2 ENDIF ELSE BEGIN MESSAGE, 'Unknown Interleaving; Need either BSQ/BIL/BIP.' ENDELSE ENDELSE ENDELSE ;; ENDIF ELSE BEGIN MESSAGE, 'No Interleave Found, Assuming BSQ.', /continue intleave = 0 ENDELSE ; RETURN, intleave ; END ; ;----------------------------------------------------------------------- ; function READ_HEADER, filename ; COMPILE_OPT hidden ON_ERROR, 2 ; OPENR, lun, filename, /get_lun array = '' line = '' ; WHILE NOT EOF(lun) DO BEGIN READF, lun, line array = [array, line] ENDWHILE ; FREE_LUN, lun RETURN, array[1:*] ; END ; ;----------------------------------------------------------------------- ; function SENSOR_TYPE, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fstw = WHERE(STRPOS(header, "sensor type") NE -1, count) IF (count NE 0) THEN BEGIN fst = STRTRIM(header[fstw], 2) fst1 = STRPOS(fst, '=') stype = (STRMID(fst, fst1 + 2))[0] ;; ENDIF ELSE BEGIN stype = "Unknown" ENDELSE ; RETURN, stype END ; ;----------------------------------------------------------------------- ; function WAVELENGTH_UNITS, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fwuw = WHERE(STRPOS(header, "wavelength units") NE -1, count) IF (count NE 0) THEN BEGIN fwu = STRTRIM(header[fwuw], 2) fwu1 = STRPOS(fwu, '=') wvunits = (STRMID(fwu, fwu1 + 2))[0] ;; ENDIF ELSE BEGIN wvunits = "Unknown" ENDELSE ; RETURN, wvunits END ; ;----------------------------------------------------------------------- ; function BAND_NAMES, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fbnw = WHERE(STRPOS(header, "band names") NE -1, count) IF (count NE 0) THEN BEGIN fbn = STRTRIM(header[fbnw], 2) fbn1 = STRPOS(fbn, '{') ;; eb_array = STRPOS(header[fbnw+1:*], '}') names = '' FOR i = 1, N_ELEMENTS(eb_array) DO BEGIN names = names + header[fbnw+i] ENDFOR eb = STRPOS(names, '}') names = STRTRIM(STRMID(names, 0, eb), 2) b_names = STRSPLIT(names, ',', /extract) ;; ENDIF ELSE BEGIN nb = num_bands(header) band = STRING(LONARR(nb)) number=STRING(LONARR(nb)) b_names=STRING(LONARR(nb)) ;; ;;create the array with value 'Band' placed in each element FOR i=0L, nb[0]-1 DO BEGIN band[i]= 'Band ' ENDFOR ;; ;;create the array with values of 1 to the total number of files FOR i=0L, nb[0]-1 DO BEGIN number[i]= STRTRIM(i+1,1) ENDFOR ;; ;;concatenate (join) the band and number arrays into one singular array FOR i=0L, nb[0]-1 DO BEGIN b_names[i]= band[i] + number[i] ENDFOR ENDELSE ; RETURN, b_names END ; ;----------------------------------------------------------------------- ; function BYTE_ORDER, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fbow = WHERE(STRPOS(header, "byte order") NE -1, count) IF (count NE 0) THEN BEGIN fbo = STRTRIM(header[fbow], 2) fbo1 = STRPOS(fbo, '=') byt_order = (FIX(STRMID(fbo, fbo1 + 2)))[0] ENDIF ELSE BEGIN MESSAGE, 'Byte order not found, assuming byte order of current machine.', /continue byt_order = (BYTE(1,0,1))[0] ? 0 : 1 ENDELSE ; RETURN, byt_order ; END ; ;----------------------------------------------------------------------- ; function HEADER_OFFSET, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fhow = WHERE(STRPOS(header, "header offset") NE -1, count) IF (count NE 0) THEN BEGIN fho = STRTRIM(header[fhow], 2) fho1 = STRPOS(fho, '=') offset = (LONG(STRMID(fho, fho1 + 2)))[0] ENDIF ELSE BEGIN MESSAGE, 'No offset found, assuming zero.', /continue offset = 0L ENDELSE ; RETURN, offset ; END ; ;----------------------------------------------------------------------- ; function DESCRIPTION, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fdsw = WHERE(STRPOS(header, "description") NE -1, count) IF (count NE 0) THEN BEGIN fds = STRTRIM(header[fdsw], 2) fds1 = STRPOS(fds, '{') ;; ;; Using the same method as for band names. It seems to work fine. eb_array = STRPOS(header[fdsw+1:*], '}') desc = '' FOR i = 1, N_ELEMENTS(eb_array) DO BEGIN desc = desc + header[fdsw+i] ENDFOR eb = STRPOS(desc, '}') descrip = (STRTRIM(STRMID(desc, 0, eb), 2))[0] ;; ENDIF ELSE BEGIN descrip = 'None' ENDELSE ; RETURN, descrip ; END ; ;----------------------------------------------------------------------- ; FUNCTION FILETYPE, header ; COMPILE_OPT hidden ON_ERROR, 2 ; fftw = WHERE(STRPOS(header, "file type") NE -1, count) IF (count NE 0) THEN BEGIN ff_t = STRTRIM(header[fftw], 2) fft1 = STRPOS(ff_t, '=') ftype = (STRMID(ff_t, fft1 + 2))[0] ENDIF ELSE BEGIN MESSAGE, 'File type not found, assumed ENVI Standard.', /continue ftype = 'ENVI Standard' ENDELSE ; RETURN, ftype ; END ; ;----------------------------------------------------------------------- ; function F_COMPRESSION, header ; COMPILE_OPT hidden ON_ERROR, 2 ; ffcw = WHERE(STRPOS(header, "file compression") NE -1, count) IF (count NE 0) THEN BEGIN ffc = STRTRIM(header[ffcw], 2) ffc1 = STRPOS(ffc, '=') fc = STRMID(ffc, ffc1 + 2) rfc = FIX(fc[0]) ENDIF ELSE BEGIN rfc = 0 ENDELSE ; RETURN, rfc ; END ; ; ----------------------------------------------------- ; better managing finding the files (.IMG + .HDR or .IMG.HDR + .IMG) ; function ENVI_SELECT_FILENAME, filename, hname, fname, test=test, debug=debug ; suffixe=STRMID(filename, 3, /reverse_offset) files_found=0 ; ; testing first case: HDR file as input. ; IF (STRCMP(suffixe, '.hdr', /fold_case)) EQ 1 THEN BEGIN ;; path path=FILE_DIRNAME(filename, /mark_directory) if path EQ './' then path='' ;; bodyname=FILE_BASENAME(filename, '.hdr') fname=FILE_SEARCH(path+bodyname+'.img',/fold) if (STRLEN(fname) EQ 0) then begin mess='No IMG data file found corresponding to HDR header file : ' MESSAGE, mess+filename endif if (N_ELEMENTS(fname) GT 1) then begin MESSAGE,/continue, 'More than one IMG data file found, first used !' fname=fname[0] endif hname=filename files_found=1 endif ; ; testing first case: IMG file as input. ; IF (STRCMP(suffixe, '.img', /fold_case)) EQ 1 THEN BEGIN ;; path path=FILE_DIRNAME(filename, /mark_directory) if path EQ './' then path='' ;; bodyname=FILE_BASENAME(filename, '.img') ;; we use '*.hdr' because we may have '.img.hdr' or '.hdr' hname=FILE_SEARCH(path+bodyname+'*.hdr',/fold) if (STRLEN(hname) EQ 0) then begin mess='No HDR header file found corresponding to IMG data file : ' MESSAGE, mess+filename endif if (N_ELEMENTS(hname) GT 1) then begin MESSAGE,/continue, 'More than one HDR header file found, first used !' hname=hname[0] endif fname=filename files_found=1 endif ; ; if just the "file_basename" is provide, do we have the files ? ; if (files_found EQ 0) then begin ;; path path=FILE_DIRNAME(filename, /mark_directory) if path EQ './' then path='' ;; hname=FILE_SEARCH(filename+'*.hdr',/fold) fname=FILE_SEARCH(filename+'*.img',/fold) ; if (N_ELEMENTS(hname) EQ 0) then $ MESSAGE, /cont, 'no HDR header file found with given basename pattern' ;; if (N_ELEMENTS(fname) EQ 0) then $ MESSAGE, /cont, 'no IMG data file found with given basename pattern' ;; if ((N_ELEMENTS(hname) EQ 1) AND (N_ELEMENTS(fname) EQ 1)) then begin b1=FILE_BASENAME(hname,'.hdr',/fold) b1bis=FILE_BASENAME(hname,'.img.hdr',/fold) b2=FILE_BASENAME(fname,'.img',/fold) if STRCMP(b1,b2,/fold_case) EQ 1 then files_found=1 if STRCMP(b1bis,b2,/fold_case) EQ 1 then files_found=1 if files_found EQ 0 then begin MESSAGE, /cont, 'bad files names, please check the input filter' endif endif ;; txt='found, please check input filename' if (N_ELEMENTS(hname) GT 1) then begin MESSAGE, /cont, 'More than one HDR header file '+txt endif if (N_ELEMENTS(fname) GT 1) then begin MESSAGE, /cont, 'More than one IMG data file '+txt endif endif ; ; Are really the files around ? Are the files void ? ; if (files_found EQ 1) then begin count=0 if ~FILE_TEST(fname) then begin count++ MESSAGE, /continue, 'IMG data file not found (no file/bad name ?)' endif else begin if FILE_TEST(fname,/zero_length) then begin count++ MESSAGE, /continue, 'IMG data file does not contain data !' endif endelse if ~FILE_TEST(hname) then begin count++ MESSAGE, /continue, 'HDR header file not found (no file/bad name ?)' endif else begin if FILE_TEST(hname,/zero_length) then begin count++ MESSAGE, /continue, 'HDR header file does not contain data !' endif endelse if (count NE 0) then files_found=0 endif ; if (files_found GT 0) then begin PRINT, 'IMG data filename = ', fname PRINT, 'HDR header filename = ', hname PRINT, 'Directory name = ', FILE_DIRNAME(hname, /mark_directory) endif ; if KEYWORD_SET(test) then STOP ; return, files_found ; end ; ;----------------------------------------------------------------------- ; pro READ_ENVI_FILE, filename, image=image, info=info, $ help=help, test=test, debug=debug ; if ~KEYWORD_SET(debug) then ON_ERROR, 2 ; if KEYWORD_SET(help) THEN BEGIN PRINT, 'pro TEST_READ_ENVI, filename, image=image, info=info, $' PRINT, ' help=help, test=test, debug=debug' PRINT, '' PRINT, 'Reads an ENVI style image format. Set info to a variable' PRINT, 'that will contain a structure containing the image' PRINT, 'information such as samples, lines, bands, data type etc.' PRINT, '' PRINT, 'Warning : currently, suffixes can be only .IMG for data files and' PRINT, '(.IMG.HRD or .HDR) for Header files [with any Up/Low case combi]' return ENDIF ; txt='FILENAME (.HDR, .IMG or basename)' ; if N_PARAMS() EQ 0 then filename=DIALOG_PICKFILE(filter='*.hdr') if N_ELEMENTS(filename) GT 1 then $ MESSAGE, 'You can provide only one '+txt+' at once' ; ; from a given file name (w/o extension .hrd/.img + w/o path) ; returning ONE and only one pair of Hname+Fname ; files_found=ENVI_SELECT_FILENAME(filename, hname, fname, test=test) if ~files_found then MESSAGE, 'Please check carrefully the input '+txt ; ; after this point, we have one IMG file and one HDR file ; (existances checked) ; if KEYWORD_SET(debug) then STOP ; hdr = READ_HEADER(hname) ; ;; Get the description info descript = DESCRIPTION(hdr) ; ;; Get samples, lines, bands, datatype, interleave ns = NUM_SAMPLES(hdr) nl = NUM_LINES(hdr) nb = NUM_BANDS(hdr) ; dtype = DATATYPE(hdr) intleave = INTERLEAVE(hdr) ; CASE intleave OF ;; BSQ Interleaving 0: BEGIN CASE dtype OF 0: MESSAGE, 'Undefined Data Type.' 1: image = BYTARR(ns, nl, nb, /nozero) 2: image = INTARR(ns, nl, nb, /nozero) 3: image = LONARR(ns, nl, nb, /nozero) 4: image = FLTARR(ns, nl, nb, /nozero) 5: image = DBLARR(ns, nl, nb, /nozero) 6: image = COMPLEXARR(ns, nl, nb, /nozero) 7: image = STRARR(ns, nl, nb) 8: MESSAGE, 'Structured Arrays Not Supported.' 9: image = DCOMPLEXARR(ns, nl, nb, /nozero) 10: image = PTRARR(ns, nl, nb, /nozero) 11: image = OBJARR(ns, nl, nb, /nozero) 12: image = UINTARR(ns, nl, nb, /nozero) 13: image = ULONARR(ns, nl, nb, /nozero) 14: image = LON64ARR(ns, nl, nb, /nozero) 15: image = ULON64ARR(ns, nl, nb, /nozero) ELSE: MESSAGE, 'Unknown Data Type.' ENDCASE BREAK END ; BIL Interleaving 1: BEGIN CASE dtype OF 0: MESSAGE, 'Undefined Data Type.' 1: image = BYTARR(ns, nb, nl, /nozero) 2: image = INTARR(ns, nb, nl, /nozero) 3: image = LONARR(ns, nb, nl, /nozero) 4: image = FLTARR(ns, nb, nl, /nozero) 5: image = DBLARR(ns, nb, nl, /nozero) 6: image = COMPLEXARR(ns, nb, nl, /nozero) 7: image = STRARR(ns, nb, nl) 8: MESSAGE, 'Structured Arrays Not Supported.' 9: image = DCOMPLEXARR(ns, nb, nl, /nozero) 10: image = PTRARR(ns, nb, nl, /nozero) 11: image = OBJARR(ns, nb, nl, /nozero) 12: image = UINTARR(ns, nb, nl, /nozero) 13: image = ULONARR(ns, nb, nl, /nozero) 14: image = LON64ARR(ns, nb, nl, /nozero) 15: image = ULON64ARR(ns, nb, nl, /nozero) ELSE: MESSAGE, 'Unknown Data Type.' ENDCASE BREAK END ; BIP Interleaving 2: BEGIN CASE dtype OF 0: MESSAGE, 'Undefined Data Type.' 1: image = BYTARR(nb, ns, nl, /nozero) 2: image = INTARR(nb, ns, nl, /nozero) 3: image = LONARR(nb, ns, nl, /nozero) 4: image = FLTARR(nb, ns, nl, /nozero) 5: image = DBLARR(nb, ns, nl, /nozero) 6: image = COMPLEXARR(nb, ns, nl, /nozero) 7: image = STRARR(nb, ns, nl) 8: MESSAGE, 'Structured Arrays Not Supported.' 9: image = DCOMPLEXARR(nb, ns, nl, /nozero) 10: image = PTRARR(nb, ns, nl, /nozero) 11: image = OBJARR(nb, ns, nl, /nozero) 12: image = UINTARR(nb, ns, nl, /nozero) 13: image = ULONARR(nb, ns, nl, /nozero) 14: image = LON64ARR(nb, ns, nl, /nozero) 15: image = ULON64ARR(nb, ns, nl, /nozero) ELSE: MESSAGE, 'Unknown Data Type.' ENDCASE BREAK END ELSE: MESSAGE, 'Unknown Interleave.' ENDCASE ; ;; byte order of file f_byte_order = BYTE_ORDER(hdr) ; ;; file type ftype = FILETYPE(hdr) ; ;; byte order of current machine m_byte_order = (BYTE(1,0,1))[0] ? 0 : 1 ; ;; header offset h_offset = HEADER_OFFSET(hdr) ; ;; file compression compressed = F_COMPRESSION(hdr) ; IF (f_byte_order NE m_byte_order) THEN BEGIN IF compressed NE 0 THEN BEGIN OPENR, lun, fname, /get_lun, /swap_endian, /compress ENDIF ELSE BEGIN OPENR, lun, fname, /get_lun, /swap_endian ENDELSE POINT_LUN, lun, h_offset READU, lun, image FREE_LUN, lun ENDIF ELSE BEGIN ;; Open and read the image file IF compressed NE 0 THEN BEGIN OPENR, lun, fname, /get_lun, /compress ENDIF ELSE BEGIN OPENR, lun, fname, /get_lun ENDELSE POINT_LUN, lun, h_offset READU, lun, image FREE_LUN, lun ENDELSE ; stype = SENSOR_TYPE(hdr) wl_units = WAVELENGTH_UNITS(hdr) bnames = BAND_NAMES(hdr) info = {Samples:ns, Lines:nl, Bands:nb, Data_Type:dtype,$ Interleave:intleave, Filename:fname, Sensor_Type:stype, $ Wavelength_Units:wl_units, Band_Names:bnames, $ Byte_Order:f_byte_order, Header_offset:h_offset, $ Description:descript, File_Type:ftype} ; if KEYWORD_SET(test) then STOP ; END gdl-0.9.9/src/pro/envi/test_write_read_envi.pro000066400000000000000000000026341340051421000215510ustar00rootroot00000000000000; ; Josh Sixsmith 5 Jul 2012, under GNU GPL v3 or later ; ; A simple test that checks the dimensions of the read and written image ; pro TEST_WRITE_READ_ENVI, columns=columns, rows=rows, bands=bands, $ out_name=out_name, help=help, test=test ; if KEYWORD_SET(help) then begin print, 'pro TEST_WRITE_READ_ENVI, columns=columns, rows=rows, $' print, ' bands=bands, out_name=out_name, $' print, ' help=help, test=test' return endif ; ; create a dummy image if N_ELEMENTS(columns) eq 0 then columns = 400 if N_ELEMENTS(rows) eq 0 then rows = 400 if N_ELEMENTS(bands) eq 0 then begin img = RANDOMN(sd, columns, rows) nb = 1 ns = columns nl = rows endif else begin img = RANDOMN(sd, columns, rows, bands) nb = bands ns = columns nl = rows endelse ; if (N_ELEMENTS(out_name) eq 0) then out_name='envi_test_img' ; ; begin by writing the image ; WRITE_ENVI_FILE, img, out_name=out_name, ns=ns, nl=nl, nb=nb ; ; now to read in the image ; READ_ENVI_FILE, out_name, image=r_img, info=img_info ; ; testing by checking the equivalency of the read image with the ; written image ; check = SIZE(img, /dimensions) eq SIZE(r_img, /dimensions) wh = WHERE(check eq 0, count) if (count eq 0) then begin MESSAGE, 'Test Passed', /continue endif else begin MESSAGE, 'Test Failed', /continue endelse ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/envi/write_envi_file.pro000066400000000000000000000117761340051421000205250ustar00rootroot00000000000000;+ ; ; NAME: ; WRITE_ENVI_FILE ; PURPOSE: ; Writes an ENVI style formatted image file (both compressed and ; uncompressed). ; ; CATEGORY: ; File I/O ; ; CALLING SEQUENCE: ; WRITE_ENVI_FILE, data, out_name=outname, ns=ns, nl=nl, nb=nb, ; interleave=interleave, bnames=bnames, data_type=dtype, ; byte_order=byte_order, descrip=descrip, ; compress=compress, help=help, test=test ; ; KEYWORD PARAMETERS: ; data: The variable containing the image data ; out_name: A string detailing the name of the file to be written ; ns: The number of samples in the array ; nl: The number of lines in the array ; nb: The number of bands in the array ; interleave: Optional; specify the interleave (0:BSQ, 1:BIL, 2:BIP) ; bnames: Optional; specify the band names to be output ; data_type: Optional; Specify the data type of the array (Check IDL/GDL ; data types for relevant codes) ; byte_order: Optional; Specify the byte ordering of the machine ; descrip: Optional; Specify a description of the data ; Compress: If set will compress the file. ; HELP: Showing how to use and exit ; ; OUTPUTS: ; Writes an ENVI style formatted image file. ; ; MODIFICATION HISTORY: ; 02-Jul-2012: Written by Josh Sixsmith ; ; LICENCE: ; Copyright (C) 2012, Josh Sixsmith ; 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 of the License, or ; (at your option) any later version. ; ;- pro WRITE_ENVI_FILE, data, out_name=outname, ns=ns, nl=nl, nb=nb, $ interleave=interleave, bnames=bnames, data_type=dtype, $ byte_order=byte_order, descrip=descrip, $ compress=compress, help=help, test=test IF KEYWORD_SET(help) THEN BEGIN PRINT, 'pro WRITE_ENVI_FILE, data, out_name=outname, ns=ns, $' PRINT, ' nl=nl, nb=nb, interleave=interleave, $' PRINT, ' bnames=bnames, data_type=dtype, $' PRINT, ' byte_order=byte_order, descrip=descrip, $' PRINT, ' compress=compress, help=help, test=test' return ENDIF ;; IF N_ELEMENTS(outname) EQ 0 THEN MESSAGE, 'Output filename not specified.' IF N_ELEMENTS(ns) EQ 0 THEN MESSAGE, 'Number of samples not specified.' IF N_ELEMENTS(nl) EQ 0 THEN MESSAGE, 'Number of lines not specified.' IF N_ELEMENTS(nb) EQ 0 THEN MESSAGE, 'Number of bands not specified.' ;; IF N_ELEMENTS(interleave) EQ 0 THEN interleave=0 IF N_ELEMENTS(offset) EQ 0 THEN offset=0 IF N_ELEMENTS(byte_order) EQ 0 THEN byte_order = (BYTE(1,0,1))[0] ? 0 : 1 IF N_ELEMENTS(dtype) EQ 0 THEN dtype = SIZE(data, /type) ;; ;; Write the header file hname = outname + '.hdr' OPENW, lun, hname, /get_lun ;; IF N_ELEMENTS(descrip) EQ 0 THEN BEGIN PRINTF, lun, format = '(%"ENVI \ndescription= {\n Create New File Result [%s]}")', SYSTIME() ENDIF ELSE BEGIN PRINTF, lun, format = '(%"ENVI \ndescription= {\n %s [%s]}")', descrip, SYSTIME() ENDELSE ;; PRINTF, lun, format = '(%"samples = %i")', ns PRINTF, lun, format = '(%"lines = %i")', nl PRINTF, lun, format = '(%"bands = %i")', nb PRINTF, lun, format = '(%"data type = %i")', dtype ;; IF KEYWORD_SET(compress) THEN BEGIN cmpr = 1 PRINTF, lun, format = '(%"file compression = %i")', cmpr ENDIF ;; CASE interleave OF 0: intleave = 'bsq' 1: intleave = 'bil' 2: intleave = 'bip' ENDCASE ;; PRINTF, lun, format='(%"interleave = %s")', intleave PRINTF, lun, format='(%"byte order = %i")', byte_order ;; IF N_ELEMENTS(bnames) EQ 0 THEN BEGIN ;; band=STRING(LONARR(nb)) number=STRING(LONARR(nb)) bnames=STRING(LONARR(nb)) ;; ;;create the array with value 'Band' placed in each element FOR i=0L, nb-1 DO BEGIN band[i]= 'Band ' ENDFOR ;; ;; create the array with values of 1 to the total number of files FOR i=0L, nb-1 DO BEGIN number[i]= STRTRIM(i+1,1) ENDFOR ;; ;; concatenate (join) the band and number arrays into one singular array FOR i=0L, nb-1 DO BEGIN bnames[i]= band[i] + number[i] ENDFOR ;; ENDIF ; PRINTF, lun, "band names = {" ; IF nb LE 2 THEN BEGIN IF nb EQ 1 THEN BEGIN PRINTF, lun, format='(%"%s}")', bnames ENDIF ELSE BEGIN PRINTF, lun, format='(%"%s,")', bnames[0] PRINTF, lun, format='(%"%s}")', bnames[1] ENDELSE ENDIF ELSE BEGIN FOR i=0, nb-2 DO BEGIN PRINTF, lun, format='(%"%s,")', bnames[i] ENDFOR PRINTF, lun, format='(%"%s}")', bnames[i] ENDELSE ; FREE_LUN, lun ; ; Write the image file ; IF KEYWORD_SET(compress) then begin OPENW, lun, outname, /get_lun, /compress ENDIF ELSE BEGIN OPENW, lun, outname, /get_lun ENDELSE WRITEU, lun, data FREE_LUN, lun ; if KEYWORD_SET(test) then STOP ; END gdl-0.9.9/src/pro/erode.pro000066400000000000000000000250021340051421000154730ustar00rootroot00000000000000; ; GDL replacement to ERODE in IDL ; Bin Wu ; Aug. 2018 ; ; Arguments (from IDL): Image Structure X0 Y0 Z0 ; Keywords (from IDL): ; GRAY (a boolean keyword) ; Set this keyword to perform grayscale, rather than binary, erosion. Nonzero ; elements of the Structure parameter determine the shape of the structuring element ; (neighborhood). If VALUES is not present, all elements of the structuring element ; are 0, yielding the neighborhood minimum operator. ; PRESERVE_TYPE (a boolean keyword) ; Set this keyword to return the same type as the input array. This keyword only ; applies if the GRAY keyword is set. ; UINT (a boolean keyword) ; Set this keyword to return an unsigned integer array. This keyword only applies if ; the GRAY keyword is set. ; ULONG (a boolean keyword) ; Set this keyword to return an unsigned longword integer array. This keyword only ; applies if the GRAY keyword is set. ; VALUES ; An array of the same dimensions as Structure providing the values of the ; structuring element. The presence of this keyword implies grayscale erosion. Each ; pixel of the result is the minimum of Image less the corresponding elements of ; VALUE. If the resulting difference is less than zero, the return value will be ; zero. ; Return (from IDL): the erosion of image ; Syntax (from IDL): ; Result = ERODE( Image, Structure [, X0 [, Y0 [, Z0]]] [, /GRAY [, /PRESERVE_TYPE | , /UINT ; | , /ULONG]] [, VALUES=array] ) ; Ref: http://www.harrisgeospatial.com/docs/ERODE.html ; FUNCTION ERODE, Image, Structure, X0, Y0, Z0, $ GRAY=GRAY, PRESERVE_TYPE=PRESERVE_TYPE, $ UINT=UINT, ULONG=ULONG, VALUES=VALUES ; Return the caller of a procedure in the event of an error. ON_ERROR, 2 ; At least Image and Structure are needed. IF (N_PARAMS() LE 1) THEN BEGIN MESSAGE, 'Incorrect number of arguments.' ENDIF ; Get the Structure size. dimStt = SIZE(Structure) ; Get the image size. dims = SIZE(Image) ; Make sure Structure has the same dimension as Image. IF (dims[0] NE dimStt[0]) THEN BEGIN CASE dimStt[0] OF 1: BEGIN CASE dims[0] OF 2: Structure = [[Structure],[REPLICATE(0,dimStt[1],1)]] 3: Structure = [[[Structure],[REPLICATE(0,dimStt[1],1)]],[[REPLICATE(0,dimStt[1],2)]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 2: BEGIN CASE dims[0] OF 1: Structure = Structure[*,0] 3: Structure = [[[Structure]],[[REPLICATE(0,dimStt[1],dimStt[2])]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 3: BEGIN CASE dims[0] OF 1: Structure = Structure[*,0,0] 2: Structure = Structure[*,*,0] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE dimStt=SIZE(Structure) ENDIF ; Get the coordinate of the origin of Structure. CASE dimStt[0] OF 1: IF (N_ELEMENTS(X0) EQ 0) THEN X0 = dimStt[1]/2 2: BEGIN IF (N_ELEMENTS(X0) EQ 0) THEN X0 = dimStt[1]/2 IF (N_ELEMENTS(Y0) EQ 0) THEN Y0 = dimStt[2]/2 END 3: BEGIN IF (N_ELEMENTS(X0) EQ 0) THEN X0 = dimStt[1]/2 IF (N_ELEMENTS(Y0) EQ 0) THEN Y0 = dimStt[2]/2 IF (N_ELEMENTS(Z0) EQ 0) THEN Z0 = dimStt[3]/2 END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE ; Gray: a boolean keyword. IF (KEYWORD_SET(GRAY) OR KEYWORD_SET(VALUES)) THEN BEGIN ; Gray image; ; ; Make sure VALUES has the same dimension as Image. IF KEYWORD_SET(VALUES) THEN BEGIN dimVal = SIZE(VALUES) IF (dims[0] NE dimVal[0]) THEN BEGIN CASE dimVal[0] OF 1: BEGIN CASE dims[0] OF 2: VALUES = [[VALUES],[REPLICATE(0,dimVal[1],1)]] 3: VALUES = [[[VALUES],[REPLICATE(0,dimVal[1],1)]],[[REPLICATE(0,dimVal[1],2)]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 2: BEGIN CASE dims[0] OF 1: VALUES = VALUES[*,0] 3: VALUES = [[[VALUES]],[[REPLICATE(0,dimVal[1],dimVal[2])]]] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END 3: BEGIN CASE dims[0] OF 1: VALUES = VALUES[*,0,0] 2: VALUES = VALUES[*,*,0] ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE dimVal=SIZE(VALUES) ENDIF CASE dimVal[0] OF 1: BEGIN IF dimVal[1] LT dimStt[1] THEN VALUES = [VALUES,REPLICATE(0,dimStt[1] - dimVal[1],1)] IF dimVal[1] GT dimStt[1] THEN VALUES = VALUES[0:dimStt[1]-1,*] END 2: BEGIN IF dimVal[1] LT dimStt[1] THEN VALUES = [VALUES,REPLICATE(0,dimStt[1] - dimVal[1],dimVal[2])] IF dimVal[1] GT dimStt[1] THEN VALUES = VALUES[0:dimStt[1]-1,*] dimVal = SIZE(VALUES) IF dimVal[2] LT dimStt[2] THEN VALUES = [[VALUES],[REPLICATE(0,dimVal[1],dimStt[2] - dimVal[2])]] IF dimVal[2] GT dimStt[2] THEN VALUES = VALUES[*,0:dimStt[2]-1] END 3: BEGIN IF dimVal[1] LT dimStt[1] THEN VALUES = [VALUES,REPLICATE(0,dimStt[1] - dimVal[1],dimVal[2],dimVal[3])] IF dimVal[1] GT dimStt[1] THEN VALUES = VALUES[0:dimStt[1]-1,*] dimVal = SIZE(VALUES) IF dimVal[2] LT dimStt[2] THEN VALUES = [[VALUES],[REPLICATE(0,dimVal[1],dimStt[2] - dimVal[2],dimVal[3])]] IF dimVal[2] GT dimStt[2] THEN VALUES = VALUES[*,0:dimStt[2]-1,*] dimVal = SIZE(VALUES) IF dimVal[3] LT dimStt[3] THEN VALUES = [[[VALUES]],[[REPLICATE(0,dimVal[1],dimVal[2],dimStt[3] - dimVal[3])]]] IF dimVal[3] GT dimStt[3] THEN VALUES = VALUES[*,*,0:dimStt[3]-1] END ELSE: PRINT, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' ENDCASE ENDIF ; ; In case VALUES are not given, as the image is Gray, ; set VALUES to be of the same size as Structure ; with all the elements to be 0. IF (KEYWORD_SET(VALUES) EQ 0) THEN BEGIN CASE dimStt[0] OF 1: VALUES = REPLICATE(0, dimStt[1]) 2: VALUES = REPLICATE(0, dimStt[1], dimStt[2]) 3: VALUES = REPLICATE(0, dimStt[1], dimStt[2], dimStt[3]) ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE ENDIF ; erodeImg = Image ; ; An auxiliary variable. tmpImg = erodeImg - erodeImg ; 1D-3D. CASE dimStt[0] OF 1: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN tmpImg[I] = MAX([0,MIN((erodeImg[I-X0:I+dimStt[1]-1-X0] - VALUES) * Structure)]) ENDFOR END 2: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN FOR J = Y0, dims[2]-dimStt[2]+Y0 DO BEGIN tmpImg[I,J] = MAX([0,MIN((erodeImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0] - VALUES) * Structure)]) ENDFOR ENDFOR END 3: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN FOR J = Y0, dims[2]-dimStt[2]+Y0 DO BEGIN FOR K = Z0, dims[3]-dimStt[3]+Z0 DO BEGIN tmpImg[I,J,K] = MAX([0,MIN((erodeImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0,K-Z0:K+dimStt[3]-1-Z0] - VALUES) * Structure)]) ENDFOR ENDFOR ENDFOR END ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE erodeImg = tmpImg ENDIF ELSE BEGIN ; Binary image otherwise. erodeImg = Image GT 0 ; ; An auxiliary variable. tmpImg = erodeImg - erodeImg tmpS = TOTAL(Structure) ; ; 1D-3D. CASE dimStt[0] OF 1: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN IF erodeImg[I] EQ 1 THEN BEGIN tmpImg[I] = $ TOTAL(erodeImg[I-X0:I+dimStt[1]-1-X0] * $ Structure) EQ tmpS ENDIF ENDFOR END 2: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN FOR J = Y0, dims[2]-dimStt[2]+Y0 DO BEGIN IF erodeImg[I,J] EQ 1 THEN BEGIN tmpImg[I,J] = $ TOTAL(erodeImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0] * $ Structure) EQ tmpS ENDIF ENDFOR ENDFOR END 3: BEGIN FOR I = X0, dims[1]-dimStt[1]+X0 DO BEGIN FOR J = Y0, dims[2]-dimStt[2]+Y0 DO BEGIN FOR K = Z0, dims[3]-dimStt[3]+Z0 DO BEGIN IF erodeImg[I,J,K] EQ 1 THEN BEGIN tmpImg[I,J,K] = $ TOTAL(erodeImg[I-X0:I+dimStt[1]-1-X0,J-Y0:J+dimStt[2]-1-Y0,K-Z0:K+dimStt[3]-1-Z0] * $ Structure) EQ tmpS ENDIF ENDFOR ENDFOR ENDFOR END ELSE: BEGIN MESSAGE, 'The input is an invalid image, considering only 1D, 2D, and 3D at the moment.' END ENDCASE ; erodeImg = tmpImg ENDELSE ; Gray: a boolean keyword. IF KEYWORD_SET(GRAY) THEN BEGIN ; Gray image; ; ; Give the type of the returned array. IF KEYWORD_SET(PRESERVE_TYPE) THEN BEGIN tp = TYPENAME(Image) erodeImg = CALL_FUNCTION(tp,erodeImg) ENDIF IF KEYWORD_SET(UINT) THEN erodeImg = UINT(erodeImg) IF KEYWORD_SET(ULONG) THEN erodeImg = ULONG(erodeImg) ENDIF RETURN, erodeImg END gdl-0.9.9/src/pro/errplot.pro000066400000000000000000000027741340051421000160770ustar00rootroot00000000000000;+ ; NAME: ; ERRPLOT ; ; PURPOSE: ; Plot error bars over a previously drawn plot. ; ; CALLING SEQUENCE: ; ERRPLOT, [X], Low, High, WIDTH=value ; ; INPUTS: ; X : vector of X (abcissa) values of Y ( the data) (optional). ; Low : vector of Y-error_min ; High: vector of Y+error_max ; ; KEYWORD Parameters: ; WIDTH: Error bar width. ; is in units of the width of the plot. (default: 1%) ; ; EXAMPLES: ; Symmetrical error bars of value err ; PLOT, Y ; ERRPLOT, Y-ERR, Y+ERR ; ;- PRO ERRPLOT, XVAL, LOW, HIGH, WIDTH = WIDTH, COLOR=COLOR, _EXTRA=_EXTRA compile_opt hidden,idl2 IF N_PARAMS() EQ 0 then message,"Variable is undefined: X." npar = N_Params() if npar eq 1 then message, 'Variable is undefined: LOW' IF (npar EQ 2) THEN BEGIN HIGH = LOW LOW = XVAL xval = findgen(n_elements(low)) ENDIF npts = N_Elements(HIGH) < N_Elements(LOW) < N_Elements(XVAL) ; compute width winsize=(!X.WINDOW[1] - !X.WINDOW[0]) * !D.X_SIZE / 2 IF N_Elements(width) EQ 0 THEN width = 1E-2*winsize ELSE width*=winsize/100. ;clip issue: normally errobars are clipped noclip = (n_elements(noclip) gt 0) ? noclip : !P.NOCLIP FOR i=0,npts-1 DO BEGIN xy0 = convert_coord(xval[i], low[i], /DATA, /TO_DEVICE) xy1 = convert_coord(xval[i], high[i], /DATA, /TO_DEVICE) plots, [xy0[0] + [-width, width,0], xy1[0] + [0, -width, width]], [replicate(xy0[1],3), replicate(xy1[1],3)], /DEVICE, NOCLIP=noclip, COLOR=COLOR, _extra=extra ENDFOR END gdl-0.9.9/src/pro/escape_special_char.pro000066400000000000000000000073451340051421000203440ustar00rootroot00000000000000;+ ; NAME: ESCAPE_SPECIAL_CHAR ; ; important Nota Bene : AC 2018 : it would be great to be able to *remove* this ; code in the future ... All "file_*" functions should be able to ; manage by them-selves the special chars. ; ; ESCAPE_SPECIAL_CHAR function escape special characteres present ; in input string argument and returns the result. ; Special characteres can be given by Keyword : list_of_special_char ; or default list is used. ; ; LICENCE: ; Copyright (C) 2010, Lea Noreskal and Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ; ; AC 2018 : we do removed "." in the list ; but not sure if "?" or "*" should be in the list ... ; ; ------------------------ ; ; Modifications history : ; - June 2010: created by Lea Noreskal ; - 28 June 2010: modified by Alain Coulais (N_PARAMS(), /help) ; ; - 2018-04-10 : AC ; *0* input string should be a singleton ! ; *1* manage repetition of same char (" " --> "\ \ ") ; *2* remove of "." in the list ... ; *3* adding the space " " in the list (and remove bad ; STRJOIN(STRSPLIT(str_out, /EXTRACT), '\ ') ) ; ;- ------------------------ ; function ESCAPE_SPECIAL_CHAR, str_in, show_list=show_list, $ list_of_special_char=list_of_special_char, $ test=test, help=help, debug=debug, verbose=verbose ; if N_PARAMS() NE 1 then begin MESSAGE, /continue, 'You must provide a input string !' help=1 endif if KEYWORD_SET(help) then begin print, 'function ESCAPE_SPECIAL_CHAR, str_in, show_list=show_list, $' print, ' list_of_special_char=list_of_special_char, $' print, ' test=test, help=help, debug=debug, verbose=verbose' return, -1 endif ; if N_ELEMENTS(str_in) GT 1 then MESSAGE, 'input string should not be an array' ; if KEYWORD_SET(verbose) then begin MESSAGE, /continue, '/verbose keyword not available, please contribute' endif ; ; list of special characteres can be modified if it is not complete ;if( not KEYWORD_SET(list_of_special_char)) then list_of_special_char ='[*^$,&\]' ;tab=STRSPLIT(str_in, list_of_special_char, /REGEX, /preserve) ;print, tab if ~KEYWORD_SET(list_of_special_char) then list_of_special_char =' ^$,&\' ; if KEYWORD_SET(show_list) then begin print, 'List of Special Chars which will be escaped :' print, list_of_special_char endif ; tab=STRSPLIT(str_in, list_of_special_char, /preserve_null) ; str_out='' ; ; for ii=0,N_ELEMENTS(tab)-1 do begin if (ii+1 LT N_ELEMENTS(tab)) then begin ;;print,ii, ' : ', tab[ii] ,' > ', STRMID(str_in,tab[ii],tab[ii+1]-tab[ii]-1) if (tab[ii] GT 0) then begin ;;escape special char str_out=str_out+'\'+STRMID(str_in,tab[ii]-1,1)+STRMID(str_in,tab[ii],tab[ii+1]-tab[ii]-1) endif else begin ;;beginning of the world str_out=str_out+STRMID(str_in,tab[ii],tab[ii+1]-tab[ii]-1) endelse endif else begin ;;print, ii, ' : ', tab[ii] ,' > ', STRMID(str_in,tab[ii]) if(tab[ii] GT 0) then begin ;;escape special char str_out=str_out+'\'+STRMID(str_in,tab[ii]-1,1)+STRMID(str_in,tab[ii]) endif else begin ;;end of the word str_out=str_out+STRMID(str_in,tab[ii]) endelse endelse endfor ; ;merger of each part and escape spaces ;str_out=STRJOIN(STRSPLIT(str_out, /EXTRACT), '\ ') ; if KEYWORD_SET(debug) then begin for ii=0, N_ELEMENTS(str_in) do begin print, 'Before : ', str_in[ii] print, 'After : ', str_out[ii] endfor endif ; if KEYWORD_SET(test) then STOP ; return, str_out ; end gdl-0.9.9/src/pro/factorial.pro000066400000000000000000000050711340051421000163450ustar00rootroot00000000000000function FACTORIAL, input, stirling=stirling, ul64=ul64 ;+ ; ; NAME: Factorial ; ; PURPOSE: Calculates N! ; ; CATEGORY: Mathematics ; ; CALLING SEQUENCE: result=factorial(n) ; ; KEYWORD PARAMETERS: ; /stirling : Use the Stirling approximation ; /ul64 : Use unsigned long 64 bit, ignored if stirling is set ; ; INPUTS: "input": can be a singleton or an array ... ; ; OUTPUTS: The factorial of the "input" ; - output types are: ; -- UL64 if /ul64 set AND /Stirling not set ; -- DOUBLE in all other cases ; ; EXAMPLES: ; res=FACTORIAL(20) --> Double ; res=FACTORIAL(20,/ul64) --> ul64 ; res=FACTORIAL(20.) --> Double ; res=FACTORIAL(20, /striling) --> Double ; res_vec=FACTORIAL([20,21,22]) --> Double Array ; res_vec=FACTORIAL([20,21,22],/ul64) --> Ulong64 Array ; ; RESTRICTIONS: ; IEEE floating point maximum number if 120! ; ; MODIFICATION HISTORY: ; Written by: Christopher Lee 2004-12-10 ; Corrections by : Alain Coulais 2008-04-17 ; -- see testsuite/test_factorial.pro ; -- bad computation for INTEGER and /UL64 !! ;- ; LICENCE: ; Copyright (C) 2004, ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- ; ON_ERROR, 2 ; if (MIN(input) LT 0) then begin MESSAGE, 'Values in input array must be non-negative.' endif ; t=SIZE(input,/type) ; integer = (t eq 2) or (t eq 3) or $ (t eq 12) or (t eq 13) or $ (t eq 14) or (t eq 15) ; if KEYWORD_SET(stirling) then begin dbl_in=input+0.0D result=SQRT(2.0D*!dpi*dbl_in)*(dbl_in/EXP(1.0D))^dbl_in endif else begin if (integer) then begin if (N_ELEMENTS(input) EQ 1) then begin result=1.0D for i=2, input[0] do result=result*i endif else begin dims=SIZE(input,/dim) result=DBLARR(dims,/nozero) for jj=0, N_ELEMENTS(input)-1 do begin current=input[jj] tmp=1.0D for i=2, current do tmp=tmp*i result[jj]=tmp endfor endelse endif else begin result=GAMMA(input+1.0D) endelse if KEYWORD_SET(ul64) then begin if (MAX(input) GT 20) then begin txt='% Program caused arithmetic error: Floating illegal operand' MESSAGE, txt, /continue endif result=ULONG64(result) endif endelse ; return, result ; end gdl-0.9.9/src/pro/file_copy.pro000066400000000000000000000121521340051421000163500ustar00rootroot00000000000000;+ ; NAME: FILE_COPY ; ; RESTRICTIONS: only for Unix (Unix, Linux and Mac OS X) systems ; ;- ; LICENCE: ; Copyright (C) 2010, Lea Noreskal; contact: Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; --------------------------------- ; pro FILE_COPY, source, dest, require_directory=require_directory, $ allow_same=allow_same, noexpand_path=noexpand_path, recursive=recursive, $ overwrite=overwrite, quiet=quiet, verbose=verbose, help=help, test=test ;, $ ;not ready : force=force, copy_named_pipe=copy_named_pipe, copy_symlink=copy_symlink ; if (N_PARAMS() LT 2) then BEGIN print, '% FILE_COPY: Incorrect number of arguments.' return endif ; if (Not KEYWORD_SET(noexpand_path)) then begin flist='' for ii=0,N_ELEMENTS(source)-1 do begin dir=FILE_SEARCH(FILE_DIRNAME(source[ii]),/fully) res=FILE_SEARCH(dir, FILE_BASENAME(source[ii]), /fully) for jj=0,N_ELEMENTS(res)-1 do begin if(FILE_DIRNAME(res[jj], /MARK_DIRECTORY) eq dir) then flist=[flist, res[jj]] ; ;print, 'dir ', dir, ' res ', FILE_DIRNAME(res[jj]) endfor endfor if(N_ELEMENTS(flist) gt 1) then source=flist[1:*]; print, flist ;; ; ... for ii=0,N_ELEMENTS(dest)-1 do begin struct=FILE_INFO(dest[ii]) if(struct.exists) then dest[ii]=escape_special_char(struct.name) endfor ;... endif ; either dest has the same size as source or it is a directory destIsDir=0 ; 0 if dest is an array, 1 if it is a directory if ( N_ELEMENTS(source) ne N_ELEMENTS(dest)) then begin if( (N_ELEMENTS(dest) gt 1) $ or (FILE_TEST(dest[0], /directory) eq 0) ) then begin print, '% FILE_COPY: Arrays source and dest must have same size, or dest must be a directory' return endif ; N_elements(dest) = 1 and dest is a directory destIsDir=1 endif ; ; if KEYWORD_SET(help) then begin print, 'FUNCTION FILE_DELETE, source, dest,' print, ' allow_same=allow_same, noexpand_path=noexpand_path, recursive=recursive, $' print, ' overwrite=overwrite, require_directory=require directory, quiet=quiet, verbose=verbose, help=help, test=test' ;print, ' UNIX-Only Keywords: [/COPY_NAMED_PIPE] [, /COPY_SYMLINK] [, /FORCE] ' return endif ; command='\cp ' option='-' ;if KEYWORD_SET(allow_same) then begin ; print, 'Sorry, Keyword allow_same is not available now.' ; return ;endif ; if KEYWORD_SET(require_directory) then begin ; verify if dest contains only directories for ii=0, N_ELEMENTS(dest)-1 do begin if ( FILE_TEST(dest[ii], /directory) eq 0 ) then begin print, '% FILE_COPY: require_directory, ', dest[ii], ' is not a valid directory ' return endif endfor endif ; if KEYWORD_SET(recursive) then begin option=option+'r' endif ; ;if KEYWORD_SET(noexpand_path) then begin ; print, 'Sorry, Keyword NOEXPAND_PATH is not available now.' ; return ;endif ; ;cp=0; ;if KEYWORD_SET(overwrite) then begin ;endif ; if KEYWORD_SET(copy_named_pipe) then begin print, 'Sorry, Keyword copy_named_pipe is not available now.' return endif ; if KEYWORD_SET(copy_symlink) then begin option=option+'d' endif ; if KEYWORD_SET(force) then begin option=option+'f' endif ; ;if KEYWORD_SET(quiet) then begin ; print, 'Sorry, Keyword quiet is not available now.' ; return ;endif ; if KEYWORD_SET(verbose) then begin option=option+'v' endif ; ; if (STRLEN(option) GT 1 ) then begin command=command+option ;print, 'opt >', option, ' Comm : ', command endif ; for ii=0, N_ELEMENTS(source)-1 do begin if not KEYWORD_SET(recursive) then begin if (FILE_TEST(source[ii], /directory) eq 1 ) then begin if (KEYWORD_SET(verbose) or not KEYWORD_SET(quiet)) then print, '% FILE_COPY: ', source[ii], ' is a directory, use option /recursive' return endif endif ; escape special characters snameesc=escape_special_char(source[ii]) destname=dest[0] ; dest is a directory ; if(destIsDir eq 0) then destname=dest[ii] ; dest is an array with several destination ; dnameesc=escape_special_char(destname) ;if(KEYWORD_SET(allow_same) and (snameesc eq dnameesc)) > ne rien faire ;verify if it is possible to copy, without keyword overwrite cp=1; if ((Not KEYWORD_SET(overwrite)) and FILE_TEST(destname,/directory)) then begin ;sname=get_filename(source[ii]) ; sname=FILE_BASENAME(source[ii]) res = FILE_SEARCH(destname, sname, COUNT=nb) ;print ,'RES : ' , res, ' sname : ', sname if (nb ne 0) then cp=0 ; there is not same files in directory endif ;copy if((cp eq 1) and (not KEYWORD_SET(allow_same) or (snameesc ne dnameesc))) then SPAWN, command+' '+snameesc+' '+dnameesc if(cp eq 0 and (KEYWORD_SET(verbose) or not KEYWORD_SET(quiet))) then print, '% FILE_COPY: ', source[ii] ,' overwrite not allowed ' endfor ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/file_expand_path.pro000066400000000000000000000006731340051421000176760ustar00rootroot00000000000000;+ ; NAME: FILE_EXPAND_PATH ; ;- ; LICENCE: ; Copyright (C) 2010, Lea Noreskal, contact Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; function FILE_EXPAND_PATH , path return , FILE_SEARCH(path, /FULLY_QUALIFY_PATH) end ; gdl-0.9.9/src/pro/file_lines.pro000066400000000000000000000100351340051421000165060ustar00rootroot00000000000000;+ ; NAME: FILE_LINES ; ; PURPOSE: return the number of lines in an ASCII file ; ; CATEGORY: ; ; CALLING SEQUENCE: nb_lines=FILE_LINES(filename) ; ; INPUTS: -- the file name, can be prefixed by the path ; ; OPTIONAL INPUTS: none ; ; KEYWORD PARAMETERS: /compress is not available now ; /noexpand_path is not available now ; ; OUTPUTS: -- the line number, in Long64 type ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: as is on July 2012, we still have problems related to ; WordExp() in "str.cpp", when a file is prefixed or ; suffixed by white space, FILE_TEST() returns "1" wrongly. ; ; RESTRICTIONS: only for Unix (Unix, Linux and Mac OS X) systems ; ; PROCEDURE: ; ; EXAMPLE: print, FILE_LINES("/etc/passwd") ; ; MODIFICATION HISTORY: ; - 26/07/2006: created by Alain Coulais (ARSC) ; - 30/05/2008: Michael Mueller (U of Arizona) fixed inconsistent ; handling of files that don't end in newline ; - 14/01/2010: Lucio Baggio (LATMOS/CNRS) avoided shell interaction ; - 04/07/2012: Alain ; * Correcting bug 3189065 : better message when no-existing file ! ; * Correcting bug 3175753 : bad value when filename begin with number ; * managing input files list ; - 25/03/2014: Alain ; * pb when "~" in filename ; - 11/05/2015: Alain : better managment of Directories ! ; - 26/03/2018: must be Long64 ! ; ;- ; LICENCE: ; Copyright (C) 2006--2014 Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; function FILE_LINES, filenames, compress=compress, noexpand_path=noexpand_path, $ verbose=verbose, test=test ; ON_ERROR, 2 ;Return to caller ; if KEYWORD_SET(compress) then begin ;; we consider 2 solutions : zgrep and zcat zcommand=[''] SPAWN, 'zgrep --help', res, error, exit_status=status if (status EQ 0) then begin zcommand=['zgrep -Ec "$" '] endif else begin SPAWN, 'zcat --help', res, error, exit_status=status if (status EQ 0) then zcommand=['zcat ','| wc -l'] endelse if (STRLEN(zcommand[0]) EQ 0) then begin print, 'Sorry, no solution found for Keyword COMPRESS (please help !)' return, -1 endif endif ; if KEYWORD_SET(noexpand_path) then begin print, 'Sorry, Keyword NOEXPAND_PATH is not available now.' return, -1 endif ; nbp=LON64ARR(N_ELEMENTS(filenames)) ; for ii=0, N_ELEMENTS(filenames)-1 do begin ;; filename=filenames[ii] if (FILE_TEST(filename) EQ 0) then begin MESSAGE, 'Error opening file. File: '+filename endif if (FILE_TEST(filename,/directory) EQ 1) then begin MESSAGE, 'Unable to open directory. File: '+filename endif ;; ;; subsituting "~" when at first place ;; (seems to be no sense to be in another place) ;; if STRPOS(filename,'~') EQ 0 then begin filename=GETENV('HOME')+STRMID(filename,1) endif ;; if KEYWORD_SET(compress) then begin ;; we consider 2 solutions : zgrep and zcat if N_ELEMENTS(zcommand) EQ 1 then begin commande=zcommand[0]+filename endif else begin commande=zcommand[0]+filename+zcommand[1] endelse SPAWN, commande, resultat nbp[ii]=(LONG64((STRSPLIT(resultat,' ',/extract))[0])) endif else begin commande=["wc", "-l",filename] SPAWN, commande, resultat, /NOSHELL nbp[ii]=(LONG64((STRSPLIT(resultat,' ',/extract))[0])) ;;nbp[ii]=(LONG(STRCOMPRESS(resultat,/remove_all)))(0) ;; ;; checking remaining missing bad endline commande=["tail","-c 1",filename] SPAWN, commande, resultat, /NOSHELL nbp[ii] += resultat NE '' endelse if KEYWORD_SET(verbose) then print, filename, ' : ', nbp[ii] endfor ; if KEYWORD_SET(test) then STOP ; if N_ELEMENTS(filenames) EQ 1 then return, nbp[0] else return, nbp ; end gdl-0.9.9/src/pro/file_link.pro000066400000000000000000000022721340051421000163350ustar00rootroot00000000000000;+ ; NAME: FILE_LINK ; ; PURPOSE: dummy routine to inform user ; The built-in file_lnk would return, " FILE_LINK is not featured for windows systems" ; But different methods of creating file_links may be used in a windows' system. ; So the C++ file_link is removed and this is placed in src/pro: ; ; CATEGORY: placeholder ; ; CALLING SEQUENCE: FILE_LINK,SourcePath, DestPath [, /ALLOW_SAME] [, /HARDLINK] [, /NOEXPAND_PATH] [, /VERBOSE] ; ; One way I know how to do this: SPAWN,"ln -s target link " ; If you run from an MSYS shell, and export MSYS=winsymlinks:nativestrict ;- ; pro FILE_LINK, SourcePath, DestPath, verbose=verbose, test=test ; if ~(!version.os_family eq 'Windows') then $ message,/continu,' file_link.pro is a dummy (placeholder) routine' $ else $ message,/continu," FILE_LINK is not featured for MS-windows systems" ; if (!version.os_family eq 'Windows') then $ if (getenv('MSYS') eq 'winsymlinks:nativestrict') then symlink = 'MSYS' else $ symlink = 'NO' if keyword_set(verbose) and (symlink eq 'MSYS') then $ message,/continue,' in MSYS2, Running as administrator, can make a link by SPAWN,"ln -s target link " '' ; if KEYWORD_SET(test) then STOP return ; end gdl-0.9.9/src/pro/file_move.pro000066400000000000000000000111531340051421000163440ustar00rootroot00000000000000;+ ; NAME: FILE_MOVE ; ; RESTRICTIONS: only for Unix (Unix, Linux and Mac OS X) systems ; ;- ; LICENCE: ; Copyright (C) 2015, NATCHKEBIA Ilia; contact: Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; ------------------------ ; ; Modifications history : ; ; - 2018-04-10 : AC ; * remove of no-more-need of ESCAPE_SPECIAL_CHAR() ; * few cleaning ... ; ; ------------------------ ; pro FILE_MOVE, source, dest, require_directory=require_directory, $ allow_same=allow_same, noexpand_path=noexpand_path, $ overwrite=overwrite, verbose=verbose, help=help, test=test ; if KEYWORD_SET(help) then begin print, 'pro FILE_MOVE, source, dest, $' print, ' allow_same=allow_same, noexpand_path=noexpand_path, recursive=recursive, $' print, ' overwrite=overwrite, require_directory=require directory, $' print, ' verbose=verbose, help=help, test=test' return endif ; if (N_PARAMS() LT 2) then BEGIN MESSAGE, 'Incorrect number of arguments.' endif ; if ~KEYWORD_SET(noexpand_path) then begin ;; flist='' for ii=0, N_ELEMENTS(source)-1 do begin ;; dir=FILE_SEARCH(FILE_DIRNAME(source[ii]),/fully) res=FILE_SEARCH(dir, FILE_BASENAME(source[ii]), /fully) ;; for jj=0,N_ELEMENTS(res)-1 do begin if (FILE_DIRNAME(res[jj]) eq dir) then flist=[flist, res[jj]] ; ;; print, 'dir ', dir, ' res ', FILE_DIRNAME(res[jj]) endfor endfor ;; if (N_ELEMENTS(flist) gt 1) then source=flist[1:*] ; print, flist ;; ;; ... for ii=0,N_ELEMENTS(dest)-1 do begin struct=FILE_INFO(dest[ii]) if (struct.exists) then dest[ii]=ESCAPE_SPECIAL_CHAR(struct.name) endfor ;; endif ; either dest has the same size as source or it is a directory destIsDir=0 ; 0 if dest is an array, 1 if it is a directory if ( N_ELEMENTS(source) ne N_ELEMENTS(dest)) then begin if( (N_ELEMENTS(dest) gt 1) or (FILE_TEST(dest[0], /directory) eq 0) ) then begin MESSAGE, 'Arrays source and dest must have same size, or dest must be a directory!' endif ;; N_elements(dest) = 1 and dest is a directory destIsDir=1 endif ; if KEYWORD_SET(require_directory) then begin ;; verify if dest contains only directories for ii=0, N_ELEMENTS(dest)-1 do begin if (FILE_TEST(dest[ii], /directory) eq 0 ) then begin MESSAGE, 'require_directory, ', dest[ii], ' is not a valid directory ' endif endfor endif ; if KEYWORD_SET(verbose) then begin option=option+'v' endif ; ; command='\cp ' option='-rf' ; if (STRLEN(option) GT 1 ) then begin command=command+option ;;print, 'opt >', option, ' Comm : ', command endif ; for ii=0, N_ELEMENTS(source)-1 do begin ;; ;;test if file exists if (FILE_TEST(source[ii]) eq 0) then begin MESSAGE, 'file >>'+source[ii]+'<< does not exist! ' endif ;; escape special characters snameesc=ESCAPE_SPECIAL_CHAR(source[ii]) ;; ;; dest is a directory destname=dest[0] ;; ;; dest is an array with several destinatioN if(destIsDir eq 0) then destname=dest[ii] ;; ;;escape space characters dnameesc=ESCAPE_SPECIAL_CHAR(destname) ;; if (KEYWORD_SET(allow_same) and (snameesc eq dnameesc)) then return ;; ;;verify if it is possible to copy, without keyword overwrite cp=1 if ~KEYWORD_SET(overwrite) then begin nb=FILE_TEST(destname) if (nb eq 0) then cp=0 ; there is not same files in directory endif ;copy if((cp eq 0) or KEYWORD_SET(overwrite) and destIsDir eq 0) then begin SPAWN, command+' '+snameesc+' '+dnameesc SPAWN, 'rm '+option+' '+snameesc endif else begin if (destIsDir eq 1) then begin SPAWN, command+' '+snameesc+' '+dnameesc+'/' SPAWN, 'rm '+option+' '+snameesc ;NEEDS TO IMPLEMENT!!!! ;If DestPath specifies an existing directory and SourcePath also names a directory, FILE_MOVE checks for the existence of a subdirectory of DestPath with the same name as the source directory. If this subdirectory does not exist, the source directory is moved to the specified location. If the subdirectory does exist, an error is issued, and the rename operation is not carried out. endif else begin if(not KEYWORD_SET(quiet)) then print, '% FILE_MOVE: ', 'Destination file already exists. File: ', dest[ii] endelse endelse endfor ; ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/file_which.pro000066400000000000000000000064341340051421000165060ustar00rootroot00000000000000;+ ; NAME: FILE_WHICH ; ; PURPOSE: ; ; This function searches for a specific file in several specific directories. ; ; SYNTAX: ; ; result = FILE_WHICH( [path, ] file [, /INCLUDE_CURRENT_DIR] ) ; ; RETURN VALUE: ; ; If any file is found, returns the full path of the first found file; if no ; file is found, returns a NULL STRING. ; ; ARGUMENTS: ; ; - path: A search path to be searched. If this argument is not given, the value of ; !path will be used. ; - file: The file which is going to be searched for. ; ; KEYWORDS: ; ; - INCLUDE_CURRENT_DIR: If set, FILE_WHICH function will search current directory for the file before ; searching the directories in the "path" argument. If not set, current ; directory will not be searched. ; ; EXAMPLES: ; ; To search for the file "file_which.pro": ; ; file_which_path = FILE_WHICH( 'file_which.pro' ) ; ; MODIFICATION HISTORY: ; 30-Mar-2011 : written by H. Xu (xuhdev), initial import by Sylwester ; 19-Aug-2010 : Alain Coulais : small bug (double last "/") ; ; LICENCE: ; Copyright (C) 2011, H. Xu ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; function FILE_WHICH, path, file, include_current_dir=include_current_dir, $ help=help, test=test, debug=debug ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'function FILE_WHICH, path, file, include_current_dir=include_current_dir, $' print, ' help=help, test=test, debug=debug' return, -1 endif ; if KEYWORD_SET(test) then begin MESSAGE, /continue, "no actif keyword /TEST due to multiple return" endif ; if (N_PARAMS() EQ 0) then begin MESSAGE, /continue, "No file/path provided !" return, '' end ; if (N_PARAMS() EQ 2 ) then begin the_path = path the_file = file endif else begin the_path = !PATH the_file = path endelse ; if KEYWORD_SET(debug) then STOP ; ; if the file is empty, then we don't need to search for it if (the_file eq '') then begin return, '' endif ; ; split the_path into a list paths = STRSPLIT(the_path, PATH_SEP(/SEARCH_PATH), /EXTRACT ) ; ; if keyword INCLUDE_CURRENT_DIR is set, then add current path in front of the paths if (KEYWORD_SET(include_current_dir)) then begin CD, CURRENT = cur_path paths = [cur_path, paths] endif ; path_seper = PATH_SEP() ; path seperator for current platform n_paths = N_ELEMENTS(paths) ; path count ; for i = 0, n_paths - 1 do begin ;; apath = paths[i] ; ith path len_apath = STRLEN( apath ) apath_last_char = STRMID(apath, len_apath-1) ; the last character ;; ;; if apath doesn't end with a path seperator, then append one onto it if ((apath_last_char EQ path_seper ) OR $ ( !version.os_family EQ 'Windows' AND apath_last_char EQ '/' ) )$ then begin apath = STRMID( apath, 0, len_apath - 1 ) endif ;; ;; now apath should be the full path of the file which is to be checked apath = apath + path_seper + the_file ;; ; apath exists means it's what we want if (FILE_TEST(apath)) then begin return, apath endif endfor ; ; return an empty STRING if we didn't find the file ; return, '' ; end gdl-0.9.9/src/pro/filepath.pro000066400000000000000000000047121340051421000161760ustar00rootroot00000000000000;+ ; NAME: FILEPATH ; ; PURPOSE: ; 1) If /tmp keyword is set, returns a default directory for temporary ; files ; 2) If /terminal keyword is set, returns the user's terminal filename ; 3) Otherwise, concatenate the specified filename with the directory ; given by the root_dir keyword (or the GDL install directory if the ; root_dir keyword is not specified) ; ; ; CATEGORY: ; File Manipulation ; ; ; CALLING SEQUENCE: ; result=filepath(filename,root_dir=,subdirectory=,/tmp,/terminal) ; ; ; INPUTS: ; filename Scalar string of the filename ; root_dir Scalar string of the directory ; subdirectory Scalar or Array of subdirectories which will be ; concatenated to root_dir ; ; KEYWORDS: ; tmp If set, returns a directory for temporary files ; terminal If set, returns the filename of the user's terminal ; ; ; MODIFICATION HISTORY: ; 12-Jan-2006 : written by Pierre Chanial ; ; LICENCE: ; Copyright (C) 2006, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- function filepath_concat, dir1_, dir2_ compile_opt hidden on_error, 2 ; prevents inputs from being modified dir1 = dir1_ dir2 = dir2_ sep = path_sep() if strmid(dir1, 0, /reverse_offset) eq sep then begin dir1 = strmid(dir1, 0, strlen(dir1)-1) endif if strmid(dir2, 0, 1) eq sep then begin dir2 = strmid(dir2, 1) endif return, dir1+sep+dir2 end function filepath, filename, root_dir=root_dir, subdirectory=subdirectory, terminal=terminal, tmp=tmp on_error, 2 if keyword_set(terminal) then begin return, '/dev/tty' endif if keyword_set(tmp) then begin ; IDL uses IDL_TMPDIR but in GDL, IDL_TMPDIR is an alias for GDL_TMPDIR root_dir = getenv('GDL_TMPDIR') ;XXXpch well atm, GDL_TMPDIR and IDL_TMPDIR are not yet aliases. ;next line should be removed when getenv will correctly handle GDL_TMPDIR root_dir = '/tmp/' path = root_dir endif else begin if n_elements(root_dir) eq 0 then root_dir = !dir path = root_dir for i=0, n_elements(subdirectory)-1 do begin path = filepath_concat(path, subdirectory[i]) endfor endelse return, filepath_concat(path, filename) end gdl-0.9.9/src/pro/findex.pro000066400000000000000000000061231340051421000156550ustar00rootroot00000000000000;+ ; ROUTINE: findex ; ; PURPOSE: Compute "floating point index" into a table using binary ; search. The resulting output may be used with INTERPOLATE. ; ; USAGE: result = findex(u,v) ; ; INPUT: ; u a monotonically increasing or decreasing 1-D grid ; v a scalar, or array of values ; ; OUTPUT: ; result Floating point index. Integer part of RESULT(i) gives ; the index into to U such that V(i) is between ; U(RESULT(i)) and U(RESULT(i)+1). The fractional part ; is the weighting factor ; ; V(i)-U(RESULT(i)) ; --------------------- ; U(RESULT(i)+1)-U(RESULT(i)) ; ; ; DISCUSSION: ; This routine is used to expedite one dimensional ; interpolation on irregular 1-d grids. Using this routine ; with INTERPOLATE is much faster then IDL's INTERPOL ; procedure because it uses a binary instead of linear ; search algorithm. The speedup is even more dramatic when ; the same independent variable (V) and grid (U) are used ; for several dependent variable interpolations. ; ; ; EXAMPLE: ; ;; In this example I found the FINDEX + INTERPOLATE combination ;; to be about 60 times faster then INTERPOL. ; ; u=randomu(iseed,200000) & u=u(SORT(u)) ; v=randomu(iseed,10) & v=v(SORT(v)) ; y=randomu(iseed,200000) & y=y(SORT(y)) ; ; t=systime(1) & y1=interpolate(y,findex(u,v)) & print,systime(1)-t ; t=systime(1) & y2=interpol(y,u,v) & print,systime(1)-t ; print,f='(3(a,10f7.4/))','findex: ',y1,'interpol: ',y2,'diff: ',y1-y2 ; ; AUTHOR: Paul Ricchiazzi 21 Feb 97 ; Institute for Computational Earth System Science ; University of California, Santa Barbara ; paul@icess.ucsb.edu ; ; REVISIONS: ; ; LICENCE: (note added by Sylwester Arabas) ; This code was posted by Paul Ricchiazzi at the comp.land.idl-pvwave ; newsgroup on Feb 21 1997. The post mentions 'donating this procedure ; to the IDL community' - it is thus regarded as 'public domain' licence ; compatible with GNU GPL. ; ;- ; function FINDEX, u, v, test=test ; nu=N_ELEMENTS(u) nv=N_ELEMENTS(v) ; if nu eq 2 then return,(v-u[0])/(u[1]-u[0]) ; us=u-SHIFT(u,+1) us=us[1:*] umx=max(us,min=umn) if umx gt 0 and umn lt 0 then MESSAGE,'u must be monotonic' if umx gt 0 then inc=1 else inc=0 ; maxcomp=FIX(ALOG(FLOAT(nu))/ALOG(2.)+.5) ; ; maxcomp = maximum number of binary search iteratios ; jlim=LONARR(2,nv) jlim[0,*]=0 ; array of lower limits jlim[1,*]=nu-1 ; array of upper limits ; iter=0 repeat begin jj=(jlim[0,*]+jlim[1,*])/2 ii=WHERE(v ge u[jj],n) & if n gt 0 then jlim[1-inc,ii]=jj[ii] ii=WHERE(v lt u[jj],n) & if n gt 0 then jlim[inc,ii]=jj[ii] jdif=max(jlim[1,*]-jlim[0,*]) if iter gt maxcomp then begin print, maxcomp, iter, jdif MESSAGE, 'binary search failed' endif iter=iter+1 endrep until jdif eq 1 ; w=v-v w[*]=(v-u[jlim[0,*]])/(u[jlim[0,*]+1]-u[jlim[0,*]])+jlim[0,*] ; if KEYWORD_SET(test) then STOP ; return, w ; end gdl-0.9.9/src/pro/findfile.pro000066400000000000000000000155161340051421000161660ustar00rootroot00000000000000;+ ; NAME: FINDFILE ; ; This functionality is obsolete. It should not be used in new GDL ; code. You are adviced to use FILE_SEARCH() instead, which is ; intresic in GDL. ; ; PURPOSE: return a string array containing the list of files ; ; CATEGORY: File Manipulation ; ; CALLING SEQUENCE: list=FINDFILE([filter], [count=count]) ; where filter can be like '*.txt' ; ; INPUTS: nothing ; OR a string filter, which may be void ('') ; or containing some wildcards ('?' and '*') ; ; KEYWORD PARAMETERS: ; count= the number of files matching the filter ; ; Extended KEYWORD: ; sh_location= a string in order to quickly substitute the default ; "sh location" (/bin/sh) to another one ; spawn_options= a 3 element string array in order to quickly ; substitute the default use of SPAWN call ; ; OUTPUTS: a string array if at least one file matches the filter ; OR a void string if nothing found ; ; OPTIONAL OUTPUTS: count= the number of founded elements ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: Since using SPAWN, intrinsically dangerous, ; see Restrictions below ; ; RESTRICTIONS: ; ; 0/ This functionality is obsolete. Only provideto avoid ; desapointing for old users of IDL moving to GDL with old codes. ; ; I/ Dependence to OS: This function is dependant of the location of "sh" ; shell. It has been verified that the current version is working on ; some Linux and a Mac OS X systems. ; ; II/ Intrinsic danger of Shell calling: Since we allow to substitute ; the Unix command which may called throw SPAWN, we have to say that ; miss-use of this function is possible [this problem was mentioned ; in news:comp.lang.idl-pvwave] ; ; III/ We use a trick "post_ls=' 2> /dev/null'" in order to avoid ; a message coming from "ls". I don't know the behavior on other OS ; If needed (to be check on other systems), a possible Keyword ; "dev_null" is ready for future uses. ; ; EXAMPLE: ; print, FINDFILE('*.pro') ; print, FINDFILE('*.pro', spawn_options=['/bin/bash','-c','ls']) ; ; MODIFICATION HISTORY: ; - 21/03/2006 written by Alain Coulais (ARSC) ; ;- ; LICENCE: ; Copyright (C) 2006, Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; function FINDFILE, filtre_, count=count, $ sh_location=sh_location, spawn_options=spawn_options, $ verbose=verbose, quiet=quiet, test=test, help=help ; ON_ERROR, 2 ; ; if not(KEYWORD_SET(quiet)) then begin print, 'This functionality is obsolete.' print, 'You are adviced to use FILE_SEARCH() instead.' endif ; ; When nothing is found ... ; void_answer='' void_count=0 ; name_of_proc='FINDFILE' mess={fatal: 'Fatal in "'+name_of_proc+'" : ', $ info: 'Info in "'+name_of_proc+'" : ', $ warning: 'Warning in "'+name_of_proc+'" : '} ; if KEYWORD_SET(help) then begin print, 'function FINDFILE, filtre, count=count, $' print, ' sh_location=sh_location, spawn_options=spawn_options, $' print, ' verbose=verbose, test=test, help=help' count=void_count return, void_answer endif ; ; ---- now we manage the "input filtre" : we have 3 cases: 0, 1, >1 ; fields in "filter" ; if (N_PARAMS() EQ 0) then filtre=void_answer if (N_ELEMENTS(filtre_) EQ 1) then filtre=filtre_ if (N_ELEMENTS(filtre_) GT 1) then begin ;; unfortunatelly, the behavior of ON_ERROR/Message do not fit ;; exactly the IDL one then I use /continue mess_txt='Expression must be a scalar or 1 element array in this context:' MESSAGE, mess_txt ;; return, void_answer ;; WARNING--> I expected to write only ;; MESSAGE, mess_txt endif ; ; From here, "filtre" is known ; We have to check whether "filtre" is String type or not ; if (SIZE(filtre,/type) NE 7) then begin MESSAGE, 'String expression required in this context' ;; return, void_answer ;; WARNING--> I expected to write only ;; MESSAGE, 'String expression required in this context' endif ; ; ------------------------ Spawn Managment ----------------- ; ; basic case is to use "ls -d ; ; We assume the SHELL "sh" is in PATH : /bin ; This is OK on some Linux and Mac OS X ; if (N_ELEMENTS(spawn_options) EQ 3) then begin ;; is it a String Array ? if (SIZE(spawn_options,/TYPE) EQ 7) then begin if KEYWORD_SET(verbose) then begin print, mess.info+' [spawn_options=] was used' endif endif else begin if KEYWORD_SET(verbose) then begin print, mess.warning+' [spawn_options=] was not a STRING array (3 elements)' endif endelse endif else begin spawn_options=['/bin/sh', '-c', 'ls'] if KEYWORD_SET(verbose) then begin print, mess.info+' DEFAULT [spawn_options=] used' print, TRANSPOSE(spawn_options) endif endelse ; ; do we have a new way to call "sh" ? ; Not very useful because of [spawn_options=] solution ; if (N_ELEMENTS(sh_location) EQ 1) then begin ;; is it a String ? if (SIZE(sh_location,/TYPE) EQ 7) then begin if KEYWORD_SET(verbose) then begin print, mess.info+' [sh_location=] was used' endif spawn_options[0]=sh_location endif else begin if KEYWORD_SET(verbose) then begin print, mess.warning+' [sh_location=] was not a STRING' endif endelse endif ; ; Warning : in order to output nothing when nothing is found ; we have to add a subtile redicection ; to avoid message: <> ; Since we don't now how it may work on other systems, ; we do not manage it fully .... ; dev_null=1 if KEYWORD_SET(dev_null) then begin post_ls=' 2> /dev/null' endif else begin post_ls='' endelse ; ; NOW, we add the filter to the "ls" command ; (the "extra" space ' ' is a simple way to avoid usual error !) ; spawn_options[2]=spawn_options[2]+' '+filtre+post_ls ; ; ------------------------------------------------ ; NOW, all is ready, we SPAWN the command ; SPAWN, spawn_options, resultat, /noshell ; ; ------------------------------------------------ ; We have to process the COUNT keyword parameter ; info_resultat=SIZE(resultat) if (info_resultat[0] EQ 0) then begin count=0 endif else begin count=N_ELEMENTS(resultat) endelse ; ; ------------------------------------------------ ; If Verbosity is requested ... ; if KEYWORD_SET(verbose) then begin print, mess.info+'Filter was: ... <<',filtre,'>>' if (count GT 0) then begin print, mess.info+'Number of founded elements:', count print, mess.info+'Values are:', resultat endif else begin print, mess.warning+'Nothing founded !' endelse endif ; if KEYWORD_SET(test) then STOP ; return, resultat ; end ; gdl-0.9.9/src/pro/gdl_multimin_fdf.pro000066400000000000000000000021371340051421000177040ustar00rootroot00000000000000;+ ; NAME: ; GDL_MULTIMIN_FDF ; PURPOSE: ; Helper for internal function DFPMIN ; DFPMIN needs 2 functions, f and df (derivatives of f) ; whereas GSL's minimizer used in our version of DFPMIN uses a 3rd ; function, fdf, that returns both f and df at the same time (clever). ; this function calls appropriately f, df and 'f and df' and solves ; the problem of adapting GSL to DFPMIN. ; MODIFICATION HISTORY: ; Written by: Gilles Duvert ; 10 Jul 2017: first version ;- ; LICENCE: ; Copyright (C) 2017 ; 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 2 of the License, or ; (at your option) any later version. ;- function gdl_multimin_fdf,x,f,df,code ; called from gdl itself. ; if code=0, return result of 'f' at x ; if code=1, return result of 'df' at x ; if code=2, return both results as [] case code of 0: return,call_function(f,x) 1: return, call_function(df,x) 2: return, [call_function(f,x),call_function(df,x)] endcase end gdl-0.9.9/src/pro/get_login_info.pro000066400000000000000000000007651340051421000173700ustar00rootroot00000000000000; ; Under GNU GPL v2 or later ; Alain C., 24-Jan-2012 ; ; tested on various Linux and OSX ... ; function GET_LOGIN_INFO ; machine_name='Unknow' user_name='Unknow' ; ; it seems that it is better to use 'hostname' insteed 'hostname -s' ; SPAWN, 'hostname', resu, exit_status=exit_status if (exit_status EQ 0) then machine_name=resu ; SPAWN, 'whoami', resu, exit_status=exit_status if (exit_status EQ 0) then user_name=resu ; return, {MACHINE_NAME: machine_name, $ USER_NAME: user_name} ; end ; gdl-0.9.9/src/pro/handle_create.pro000066400000000000000000000011641340051421000171560ustar00rootroot00000000000000; support for obsolete pro/func. function handle_create,id,first_child=first_child,no_copy=no_copy,sibling=sibling,value=value ; note:first_child & sibling are ignored. common gdlhandles,ids,ptrs,parentid if n_elements(ids) eq 0 then begin ids=[1] last=1 if n_elements(value) eq 0 then ptrs=[ptr_new()] else ptrs=[ptr_new(value)] if (n_params() eq 0) then parentid=[0] else parentid=[id] endif else begin last=ids[-1]+1 ids=[ids,last] if n_elements(value) eq 0 then ptrs=[ptrs,ptr_new()] else ptrs=[ptrs,ptr_new(value)] if (n_params() eq 0) then parentid=[parentid,0] else parentid=[parentid,id] end return,last end gdl-0.9.9/src/pro/handle_free.pro000066400000000000000000000003411340051421000166300ustar00rootroot00000000000000; support for obsolete pro/func. pro handle_free,id common gdlhandles if n_elements(ids) eq 0 then return w=where(ids eq id, count) if count eq 1 then begin ptr_free,ptrs[w] ids[w]=-1 ; sufficient but bad practice end end gdl-0.9.9/src/pro/handle_info.pro000066400000000000000000000013761340051421000166530ustar00rootroot00000000000000; GD, May 2015 ; support for obsolete pro/func. ; function HANDLE_INFO, id, parent=parent, first_child=first_child, $ num_children=num_children, sibling=sibling, $ valid_id=valid_id ; common gdlhandles ; res=REPLICATE(0,n_elements(id)) null=res parid=res if (N_PARAMS() ne 1) then return,res ; for i=0L, N_ELEMENTS(id)-1 do begin w=WHERE(ids eq id[i], count) if count eq 1 then res[i]=1 if count eq 1 then parid[i]=parentid[w] endfor ; if KEYWORD_SET(valid_id) then return,res if TOTAL(res) eq 0 then return,res if KEYWORD_SET(parent) then return, parid if KEYWORD_SET(sibling) then return, null if KEYWORD_SET(first_child) then return, null if KEYWORD_SET(num_children) then return, null ; return, res ; end gdl-0.9.9/src/pro/handle_value.pro000066400000000000000000000004741340051421000170320ustar00rootroot00000000000000; support for obsolete pro/func. pro handle_value,id,value,no_copy=no_copy,set=set common gdlhandles if n_params() ne 2 then return w=where(ids eq id, count) if count ne 1 then return if keyword_set(set) then begin ptr_free,ptrs[w] ptrs[w]=ptr_new(value) endif else begin value=*(ptrs[w[0]]) endelse end gdl-0.9.9/src/pro/helpform.pro000066400000000000000000000212571340051421000162210ustar00rootroot00000000000000;+ ; NAME: ; HELPFORM ; ; AUTHOR: ; Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770 ; craigm@lheamail.gsfc.nasa.gov ; ; PURPOSE: ; Generate a descriptive string in IDL HELP format ; ; CALLING SEQUENCE: ; STRINGS = HELPFORM(NAME, VALUE, [/SHORTFORM,] [/SINGLE,] [WIDTH=width]) ; ; DESCRIPTION: ; ; The HELPFORM function converts an IDL data value into a ; representation very similar to the format produced by the built-in ; command HELP. Programmers can thus present data types and values ; to users in a format they are familiar with. ; ; For example, if the variable A is defined in the following manner, ; and HELP is called, then the following transcript will result: ; ; IDL> a = [1,2] ; IDL> help, a ; A INT = Array[2] ; ; The same result can be achieved with the HELPFORM function: ; ; IDL> print, helpform('A', a) ; A INT = Array[2] ; ; The benefit is that the output of HELPFORM is a string that can be ; outputted or reformatted. This capability is not available in all ; versions of IDL. ; ; HELPFORM actually produces *two* forms of output. The above ; output is considered the "long" form, as it appears in the IDL ; HELP command, and is the default. A "short" form can also be ; produced, and is very similar to the information that appears in ; certain terse IDL error messages. It is activated by setting the ; SHORTFORM keyword. ; ; If the variable name is too long, the HELPFORM may be forced to be ; two lines long to have consistent formatting. In that case a ; two-element string is returned. If a single line is desired, use ; the SINGLE keyword, but this comes at the expense of consistent ; output formatting. ; ; INPUTS: ; ; NAME - A scalar string containing the name of the IDL variable. ; An empty string is permitted. The name is ignored if the ; SHORTFORM keyword is set. ; ; VALUE - Any IDL value to be examined. VALUE is optional if the ; SIZE keyword is passed and uniquely describes the data. ; VALUE should be passed for scalars and structures, since ; the help form for these values requires additional ; information beyond the SIZE. ; ; KEYWORDS: ; ; SIZE - the IDL SIZE descriptor for the value to be printed. ; Default: information is taken from VALUE. ; ; SINGLE - if set, then output which would normally ; appear on two lines for consistent formatting, appears on ; one single line instead. ; ; FULL_STRUCT - if set, then a detailed output is printed for ; structures, similar to HELP, VALUE, /STRUCTURE. ; ; SHORTFORM - set this keyword for a shorter output format that can ; be used in error messages. ; ; WIDTH - the width of the terminal in characters (used for ; formatting). ; Default: 80 ; ; RETURNS: ; ; An array of strings containing the HELPFORM output, which may have ; more than one element depending on the length of NAME, SHORTFORM ; and SINGLE. The helpforms of pointer- and object-typed values ; does not include the sequence number, but are otherwise correct. ; ; EXAMPLE: ; ; IDL> print, helpform('A', size=[1,2,1,2]) ; A BYTE = Array[2] ; ;; Do not pass VALUE and instead use SIZE to specify the type ; ; IDL> print, helpform('A', size=[1,2,1,2], /shortform) ; BYTE (Array[2]) ; ;; Compare to the short form, which is meant to be placed in ; ;; error messages ; ; IDL> print, helpform('fjsldkfjsldfkjslkdfjslkdfjslkdfjsldkfjk',a) ; fjsldkfjsldfkjslkdfjslkdfjslkdfjsldkfjk ; INT = Array[2] ; IDL> print, helpform('fjsldkfjsldfkjslkdfjslkdfjslkdfjsldkfjk',a,/single) ; fjsldkfjsldfkjslkdfjslkdfjslkdfjsldkfjk INT = Array[2] ; ;; Compare the long and short forms ; ; ; SEE ALSO: ; ; INPUTFORM, HELP ; ; MODIFICATION HISTORY: ; Written, CM, 13 May 2000 ; Documented, 04 Jul 2000 ; Improved output for objects, CM, 11 Jan 2001 ; Added support for full structure output, CM 08 Feb 2001 ; Added forward_function declaration for safety, CM 08 Apr 2001 ; Print more info about POINTER type, CM 08 Apr 2001 ; ; $Id: helpform.pro,v 1.2 2016-09-19 21:29:57 gilles-duvert Exp $ ; ;- ; Copyright (C) 2000-2001, Craig Markwardt ; This software is provided as is without any warranty whatsoever. ; Permission to use, copy, modify, and distribute modified or ; unmodified copies is granted, provided this copyright and disclaimer ; are included unchanged. ;- forward_function helpform function helpform, name0, value, size=sz, single=single, shortform=short, $ width=width0, structure_name=stname, tagform=tagform, $ full_struct=struct ;; Names of all the known IDL types, as of IDL 5.2 typenames = ['UNDEFINED', 'BYTE', 'INT', 'LONG', 'FLOAT', 'DOUBLE', $ 'COMPLEX', 'STRING', 'STRUCT', 'DCOMPLEX', 'POINTER', $ 'OBJREF', 'UINT', 'ULONG', $ 'LONG64', 'ULONG64', 'UNKNOWN'] blanks = string(replicate(32b,80)) if n_elements(sz) LT 3 then sz = size(value) tp = sz[sz[0]+1] < 16 if n_elements(name0) EQ 0 then name0 = '' name = strtrim(name0[0],2) nlen = 15 ;; Length of name tlen = 9 ;; Length of type name if n_elements(width0) EQ 0 then width0 = 80 width = floor(width0[0]) if tp EQ 8 AND keyword_set(struct) then begin sz1 = size(value) if sz1[sz1[0]+1] NE 8 then goto, NOT_STRUCT nt = n_tags(value) len = n_tags(value, /length) tn = tag_names(value) sn = tag_names(value, /structure_name) if sn EQ '' then sn = '' a = string(sn, nt, len, $ format='("** Structure ",A0,", ",I0," tags, length=",I0,":")') for i = 0, nt-1 do begin a = [a, ' '+helpform(tn[i], value[0].(i), /tagform)] endfor return, a endif NOT_STRUCT: if NOT keyword_set(short) then begin ;; Pad the name out, or else put the name on a line by itself if strlen(name) GT nlen then begin if keyword_set(single) then begin a1 = name+' ' endif else begin a0 = name a1 = strmid(blanks,0,nlen)+' ' endelse endif else begin a1 = strmid(name+blanks,0,nlen)+' ' endelse a1 = a1 + strmid(typenames[tp]+blanks,0,tlen) if NOT keyword_set(tagform) then $ a1 = a1 +' = ' endif else begin a1 = strmid(typenames[tp]+blanks,0,tlen) endelse ndims = sz[0] if ndims GT 0 then begin ;; It is an array, compose the dimensions dims = sz[1:ndims] v = 'Array[' for i = 0L, ndims-1 do begin v = v + strtrim(dims[i],2) if i LT ndims-1 then v = v + ', ' endfor v = v + ']' ;; If it is a structure, add the structure name (structures are ;; never scalars) if NOT keyword_set(short) AND tp EQ 8 then begin ;; Protect against empty value if n_elements(stname) EQ 0 then begin if n_elements(value) GT 0 then v0 = value[0] else v0 = {dummy:0} sn = tag_names(v0, /structure_name) sn = sn[0] endif else begin sn = strtrim(stname[0],2) endelse if sn EQ '' then sn = '' v = '-> '+sn+' ' + v endif endif else begin ;; It is a scalar ;; Protect against empty or vector value if n_elements(value) GT 0 then begin v0 = value[0] endif else begin if tp NE 10 AND tp NE 11 then tp = 0 endelse case tp < 16 of 0: v = '' 1: v = string(v0, format='(I4)') 7: begin w = (width - 35) > 5 if strlen(v0) GT w then $ v = "'"+strmid(v0,0,w)+"'..." $ else $ v = "'"+v0+"'" end 10: begin sz = size(v0) if sz[sz[0]+1] EQ 10 then v = string(v0[0], /print) $ else v = '' end 11: begin if n_elements(stname) EQ 0 then begin forward_function obj_class sz = size(v0) if sz[sz[0]+1] EQ 11 then sn = '('+obj_class(v0)+')' $ else sn = '' endif else begin sn = '('+strupcase(strtrim(stname[0],2))+')' endelse v = '' end 16: v = '' else: v = string(v0) endcase endelse if keyword_set(short) then return, a1 + '('+v+')' a1 = a1 + v if n_elements(a0) GT 0 then return, [a0, a1] else return, a1 end gdl-0.9.9/src/pro/hist_2d.pro000066400000000000000000000043211340051421000157320ustar00rootroot00000000000000; by Sylwester Arabas ; uses hist_nd() released under GPL by J.D. Smith ; function HIST_2D, v1, v2, bin1=bin1, bin2=bin2, max1=max1, max2=max2, min1=min1, min2=min2, $ test=test, help=help ; ON_ERROR, 2 ; if N_PARAMS() LT 2 then begin MESSAGE, 'Incorrect number of arguments.' endif if (SIZE(v1,/n_dim) EQ 0) AND (SIZE(v2,/n_dim) EQ 0) then begin MESSAGE, 'one of the 2 Expressions must be an array in this context' endif ; if KEYWORD_SET(help) then begin print, 'function HIST_2D, v1, v2, $' print, ' bin1=bin1, bin2=bin2, max1=max1, max2=max2, min1=min1, min2=min2, $' print, ' test=test, help=help' return, -1 endif ; ;; bin-widths default to 1 if N_ELEMENTS(bin1) eq 0 then bin1 = 1 if N_ELEMENTS(bin2) eq 0 then bin2 = 1 ;; min and max default to minimum and maximum values ... with some exceptions if N_ELEMENTS(min1) eq 0 then begin if N_ELEMENTS(max1) ne 0 then min1 = 0 < min(v1, /nan) else min1 = 0 < min(v1, max=max1, /nan) endif else if N_ELEMENTS(max1) eq 0 then max1 = max(v1, /nan) if N_ELEMENTS(min2) eq 0 then begin if N_ELEMENTS(max2) ne 0 then min2 = 0 < min(v2, /nan) else min2 = 0 < min(v2, max=max2, /nan) endif else if N_ELEMENTS(max2) eq 0 then max2 = max(v2, /nan) ;; sanity checks for some undefined-behaviour conditions if bin1 le 0 then MESSAGE, "bin1 must be > 0" if bin2 le 0 then MESSAGE, "bin2 must be > 0" if ~FINITE(min1) || ~FINITE(min2) || ~FINITE(max1) || ~FINITE(max2) then $ MESSAGE, "min1, min2, max1 and max2 must all be finite" if min1 eq max1 then MESSAGE, "min1 must not be equal to max1" if min2 eq max2 then MESSAGE, "min2 must not be equal to max2" ;; the shorter array determines how many elements are taken into account n = N_ELEMENTS(v1) < N_ELEMENTS(v2) if n eq 1 then begin ;; emulating IDL behaviour with 1-element arrays and scalars data = TRANSPOSE([[v1[0], max1 + 1], [v2[0], max2 + 1]]) endif else begin data = TRANSPOSE([[v1[0 : n - 1]], [v2[0 : n - 1]]]) endelse ; ret = HIST_ND(TEMPORARY(data), [bin1, bin2], min=[min1, min2], max=[max1, max2]) ; if SIZE(ret,/n_dimensions) eq 1 then ret=REFORM(ret, N_ELEMENTS(ret), 1) ; if KEYWORD_SET(test) then STOP ; return, ret ; end gdl-0.9.9/src/pro/hist_equal.pro000066400000000000000000000150221340051421000165340ustar00rootroot00000000000000;+ ; ; NAME: ; HIST_EQUAL ; ; PURPOSE: ; Scales an input image by equalising its histogram. By setting ; a percent it can an also scale an image via a linear contrast. ; ; CATEGORY: Image processing. ; ; CALLING SEQUENCE: ; Result = HIST_EQUAL(image, BinSIZE=value, ; Fcn=column_vector, Histogram_Only=value, Maxv=value, ; Minv=value, Omax=variable, Omin=variable, Percent=value, ; Top=value) ; ; KEYWORD PARAMETERS: ; ; BINSIZE: The SIZE of the bin in which to construct the ; histogram. Defaulted to 1 for an image of type BYTE. The ; default for other data types is (maxv-minv)/5000double. ; ; FCN: The cumulative probability distribution function. (Not ; currently implemented). ; ; HISTOGRAM_ONLY: Returns the cumulative histogram of type Long. ; ; MAXV: The maximum value of the original image to ; consider. Defaulted to 255 if image is of type BYTE, ; otherwise the image is searched for the maximum value. ; ; MINV: The minimum value of the original image to ; consider. Default is 0 if image is of type BYTE, otherwise ; the image is searched for the minimum value. ; ; PERCENT: If set to a value between 0 and 100, the histogram of ; the image will be linearly stretched between the upper and ; lower values found by the specified percent of the cumulative ; histogram. ; ; TOP: The maximum value of the scaled result. Defaulted to 255. ; ; OUTPUTS: An image that is has been modified by its histogram. If the ; Histogram_Only keyword has been set, then the cumulative ; histogram (of type Long) will be output. ; ; ; OPTIONAL OUTPUTS: ; ; OMAX: Will contain the maximum value used for constructing the histogram. ; OMIN: Will contain the minimum value used for constructing the histogram. ; ; COMMON BLOCKS: ; ; SIDE EFFECTS: ; ; RESTRICTIONS: ; ; The FCN keyword is currently not implemented. ; ; PROCEDURE: ; Sources: ; http://www.cacs.louisiana.edu/~cice/cacs508/fa11/lecture%2005%200908.pdf ; http://www.cis.rit.edu/class/simg782/lectures/lecture_05/lec782_05_05.pdf ; ; EXAMPLE: ; http://idlastro.gsfc.nasa.gov/idl_html_help/HIST_EQUAL.html ; image = dist(100) ; tv, image ; scl_img = hist_equal(image, minv=10, maxv=200, top=220) ; tv, scl_img ; ; window, 1, xSIZE=900, ySIZE=550 ; !p.multi=[0,2,1] ; plot, histogram(image), title='Histogram' ; oplot, histogram(scl_img), color=255 ; plot, total(histogram(image), /cumulative), title='Cumulative Histogram' ; oplot, total(histogram(scl_img), /cumulative), color=255 ; xyouts, 0.2324805, 0.0200364, 'White = Original', /normal, charSIZE=2 ; xyouts, 0.5795328, 0.0200364, 'Red = Equalised', /normal, charSIZE=2 ; ; MODIFICATION HISTORY: ; 2012-May-01 Written by: Josh Sixsmith ; 2012-May-07 Fixed percent keyword argument ; 2012-May-22 Alain Coulais: Details (/help,/test), initial import in GDL ; 2012-May-25 Alain: typo in LINEAR_PERCENT :( , formatting ; 218-Sept-27 Alain: better message when max==min ! ; ;- ; LICENCE: ; Copyright (C) 2010, Josh Sixsmith ; 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 of the License, or ; (at your option) any later version. ; ;- ; pro LINEAR_PERCENT, cumuhist, percent, min, binSIZE, maxDN, minDN ; n = cumuhist[N_ELEMENTS(cumuhist)-1] low = (percent/100.) high = (1 - (percent/100.)) ; x1 = VALUE_LOCATE(cumuhist, n * low) if x1 eq -1 then x1 = 0 while cumuhist[x1] eq cumuhist[x1 + 1] do begin x1 = x1 + 1 endwhile ; close1 = ABS(low - cumuhist[x1]/n) close2 = ABS(low - cumuhist[x1 + 1]/n) x1 = (close1 le close2) ? x1 : x1 + 1 minDN = x1 * binSIZE + min ; x2 = VALUE_LOCATE(cumuhist, n * high) while cumuhist[x2] eq cumuhist[x2 - 1] do begin x2 = x2 - 1 endwhile ; close1 = ABS(high - cumuhist[x2]/n) close2 = ABS(high - cumuhist[x2 + 1]/n) x2 = (close1 le close2) ? x2 : x2 + 1 maxDN = x2 * binSIZE + min ; end ; ; ------------------------------------ ; function HIST_EQUAL, img, binSIZE=bs, fcn=fcn, Histogram_Only=ho, $ maxv=maxv, minv=minv, omax=omax_, omin=omin_, $ percent=percent, Top=top_, $ help=help, test=test ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'function HIST_EQUAL, img, binSIZE=bs, fcn=fcn, Histogram_Only=ho, $' print, ' maxv=maxv, minv=minv, omax=omax_, omin=omin_, $' print, ' percent=percent, Top=top_, $' print, ' help=help, test=test' return, -1 endif ; txt='Cumulative Probability Distribution Function not currently supported' if KEYWORD_SET(fcn) then MESSAGE, txt ; ; if (percent le 0) or (percent ge 100) then MESSAGE, 'Percent must be between 0 and 100' ; if N_ELEMENTS(maxv) eq 0 then maxv = MAX(img, min=min_) if N_ELEMENTS(minv) eq 0 then minv = min_ ; if minv GE maxv then MESSAGE, 'MINV must be less than MAXV.' ; if N_ELEMENTS(top_) eq 1 then top = top_[0] else top = 255 ; type = SIZE(img, /type) ; if N_ELEMENTS(bs) eq 0 then begin if type eq 1 then begin bs = 1 endif else begin ;; Calculate as double. Precision needed for very small values. bs = (maxv - minv)/5000d endelse endif ; hist = HISTOGRAM(img, binSIZE=bs, omax=omax_, omin=omin_, max=maxv, min=minv) ;; Zeroing the first element of the histogram hist[0] = 0 ; cumu = TOTAL(hist, /cumulative, /double) if KEYWORD_SET(ho) then return, long(cumu) ; if N_ELEMENTS(percent) gt 0 then begin if (percent le 0) or (percent ge 100) then MESSAGE, 'Percent must be between 0 and 100' LINEAR_PERCENT, cumu, percent, minv, bs, maxDN, minDN scl = BYTSCL(img, max=maxDN, min=minDN, top=top) ;; if KEYWORD_SET(test) then STOP return, scl endif ; bytsc = BYTSCL(cumu, top=top) ; if SIZE(img, /type) eq 1 then begin ;; Check for minv. Clip to zero if non zero scl = (minv eq 0) ? bytsc[img] : bytsc[(img > minv) - minv] endif else begin ;; Scale by the binSIZE to in order to get the bin position ;; Check for minv. Clip to zero if non zero scl = (minv eq 0) ? bytsc[img/bs] : bytsc[((img > minv) - minv)/bs] endelse ; if KEYWORD_SET(test) then STOP ; return, scl ; end gdl-0.9.9/src/pro/hist_nd.pro000066400000000000000000000144331340051421000160330ustar00rootroot00000000000000;+ ; NAME: ; HIST_ND ; ; PURPOSE: ; ; Perform an N-dimensional histogram, also known as the joint ; density function of N variables, ala HIST_2D. ; ; CALLING SEQUENCE: ; hist=HIST_ND(V,[BINSIZE,MIN=,MAX=,NBINS=,REVERSE_INDICES=]) ; ; INPUTS: ; ; V: A NxP array representing P data points in N dimensions. ; ; BINSIZE: The size of the bin to use. Either an N point vector ; specifying a separate size for each dimension, or a scalar, ; which will be used for all dimensions. If BINSIZE is not ; passed, NBINS must be. ; ; OPTIONAL INPUTS: ; ; MIN: The minimum value for the histogram. Either a P point ; vector specifying a separate minimum for each dimension, or ; a scalar, which will be used for all dimensions. If ; omitted, the natural minimum within the dataset will be ; used. ; ; MAX: The maximum value for the histogram. Either a P point ; vector specifying a separate maximmum for each dimension, or ; a scalar, which will be used for all dimensions. If omitted, ; the natural maximum within the dataset will be used. ; ; NBINS: Rather than specifying the binsize, you can pass NBINS, ; the number of bins in each dimension, which can be a P point ; vector, or a scalar. If BINSIZE it also passed, NBINS will ; be ignored, otherwise BINSIZE will then be calculated as ; binsize=(max-min)/nbins. Note that *unlike* RSI's version ; of histogram as of IDL 5.4, this keyword actually works as ; advertised, giving you NBINS bins over the range min to max. ; ; KEYWORD PARAMETERS: ; ; MIN,MAX,NBINS: See above ; ; REVERSE_INDICES: Set to a named variable to receive the ; reverse indices, for mapping which points occurred in a ; given bin. Note that this is a 1-dimensional reverse index ; vector (see HISTOGRAM). E.g., to find the indices of points ; which fell in a histogram bin [i,j,k], look up: ; ; ind=[i+nx*(j+ny*k)] ; ri[ri[ind]:ri[ind+1]-1] ; ; See also ARRAY_INDICES for converting in the other ; direction. ; ; OUTPUTS: ; ; hist: The N-Dimensional histogram, an array of size ; N1xN2xN3x...xND where the Ni's are the number of bins ; implied by the data, and/or the optional inputs min, max and ; binsize. ; ; OPTIONAL OUTPUTS: ; ; The reverse indices. ; ; EXAMPLE: ; ; v=randomu(sd,3,100) ; h=hist_nd(v,.25,MIN=0,MAX=1,REVERSE_INDICES=ri) ; ; SEE ALSO: ; ; HISTOGRAM, HIST_2D ; ; MODIFICATION HISTORY: ; ; Mon Mar 5 09:45:53 2007, J.D. Smith ; ; Correctly trim out of range elements from the ; histogram, when MIN/MAX are specified. Requires IDL ; v6.1 or later. ; ; Tue Aug 19 09:13:43 2003, J.D. Smith ; ; Slight update to BINSIZE logic to provide consistency ; with HIST_2D. ; ; Fri Oct 11 10:10:01 2002, J.D. Smith ; ; Updated to use new DIMENSION keyword to MAX/MIN. ; ; Fri Apr 20 12:57:34 2001, JD Smith ; ; Slight update to NBINS logic. More aggressive keyword ; checking. ; ; Wed Mar 28 19:41:10 2001, JD Smith ; ; Written, based on HIST_2D, and suggestions of CM. ; ;- ;############################################################################## ; ; LICENSE ; ; Copyright (C) 2001-2003, 2004, 2007 J.D. Smith ; ; This file 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 2, or (at your ; option) any later version. ; ; This file 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 file; see the file COPYING. If not, write to the ; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ; Boston, MA 02110-1301, USA. ; ;############################################################################## function hist_nd,V,bs,MIN=mn,MAX=mx,NBINS=nbins,REVERSE_INDICES=ri s=size(V,/DIMENSIONS) if n_elements(s) ne 2 then message,'Input must be N (dimensions) x P (points)' if s[0] gt 8 then message, 'Only up to 8 dimensions allowed' imx=max(V,DIMENSION=2,MIN=imn) if n_elements(mx) eq 0 then mx=imx if n_elements(mn) eq 0 then mn=imn if s[0] gt 1 then begin if n_elements(mn) eq 1 then mn=replicate(mn,s[0]) if n_elements(mx) eq 1 then mx=replicate(mx,s[0]) if n_elements(bs) eq 1 then bs=replicate(bs,s[0]) if n_elements(nbins) eq 1 then nbins=replicate(nbins,s[0]) endif if ~array_equal(mn le mx,1b) then $ message,'Min must be less than or equal to max.' if n_elements(bs) eq 0 then begin if n_elements(nbins) ne 0 then begin nbins=long(nbins) ;No fractional bins, please bs=float(mx-mn)/nbins ;a correct formulation endif else message,'Must pass either binsize or NBINS' endif else nbins=long((mx-mn)/bs+1) total_bins=product(nbins,/PRESERVE_TYPE) ;Total number of bins h=long((V[s[0]-1,*]-mn[s[0]-1])/bs[s[0]-1]) ;; The scaled indices, s[n]+N[n-1]*(s[n-1]+N[n-2]*(s[n-2]+... for i=s[0]-2,0,-1 do h=nbins[i]*temporary(h) + long((V[i,*]-mn[i])/bs[i]) out_of_range=[~array_equal(mn le imn,1b),~array_equal(mx ge imx,1b)] if ~array_equal(out_of_range,0b) then begin in_range=1 if out_of_range[0] then $ ;out of range low in_range=total(V ge rebin(mn,s,/SAMP),1,/PRESERVE_TYPE) eq s[0] if out_of_range[1] then $ ;out of range high in_range AND= total(V le rebin(mx,s,/SAMP),1,/PRESERVE_TYPE) eq s[0] h=(temporary(h) + 1L)*temporary(in_range) - 1L endif ret=make_array(TYPE=3,DIMENSION=nbins,/NOZERO) if arg_present(ri) then $ ret[0]=histogram(h,MIN=0L,MAX=total_bins-1L,REVERSE_INDICES=ri) $ else $ ret[0]=histogram(h,MIN=0L,MAX=total_bins-1L) return,ret end gdl-0.9.9/src/pro/identity.pro000066400000000000000000000027331340051421000162340ustar00rootroot00000000000000;$Id: identity.pro,v 1.4 2016-09-19 21:29:57 gilles-duvert Exp $ function IDENTITY, n, double=double_keyword, help=help ;+ ; ; NAME: ; identity ; ; PURPOSE: ; returns an n x n identity matrix ; ; CATEGORY: ; Mathematics: Matrices ; ; CALLING SEQUENCE: ; i=IDENTITY(4) ; ; KEYWORD PARAMETERS: ; DOUBLE_KEYWORD : Keyword for double precision calculation ; ; OUTPUTS: ; The identity matrix ; ; PROCEDURE: ; Creates an n x n matrix, fills the diagonal elements with the ; value 1.0 ; ; EXAMPLE: ; i = IDENTITY(4) ; print, i ; 1.00000 0.00000 0.0000 0.00000 ; 0.00000 1.00000 0.0000 0.00000 ; 0.00000 0.00000 1.0000 0.00000 ; 0.00000 0.00000 0.0000 1.00000 ; ; MODIFICATION HISTORY: ; Written by: 2004-03-20 Christopher Lee. ; 2011-12-17 G. Duvert (if n==1 !) ; ;- ; LICENCE: ; Copyright (C) 2004, 2011 ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, "function IDENTITY, n, double=double_keyword, help=help" return, -1 endif ; diag=INDGEN(n) ; if (KEYWORD_SET(double_keyword)) then begin id=DBLARR(n,n) endif else begin id=FLTARR(n,n) endelse ; id[diag,diag]=1 ; return, id ; end gdl-0.9.9/src/pro/idl_container.pro000066400000000000000000000010121340051421000172020ustar00rootroot00000000000000;+ ; ; NAME: ; IDL_CONTAINER ; ; PURPOSE: ; create an IDL container ; ; :Categories: ; Object Programming, Graphics ; ; this provides the procedure interface to creating an IDL_container. ; ; idl_container__define.pro will further defines this to be fully inherited from ; GDL_CONTAINER, which is a built-in object of GDL. ; ;--------------------------------------------------------------------------- Function IDL_CONTAINER Compile_Opt hidden return, obj_new('idl_container') END gdl-0.9.9/src/pro/idl_container__define.pro000066400000000000000000000007251340051421000206650ustar00rootroot00000000000000;+ ; ; NAME: ; IDL_CONTAINER__Define ; ; PURPOSE: ; define a compatible idl_container by inheriting from the GDL_CONTAINER ; :Categories: ; Object Programming, Graphics ; ; ; This is the class definition module. ; ;--------------------------------------------------------------------------- PRO IDL_CONTAINER__Define, class Compile_Opt hidden class = { IDL_CONTAINER, $ INHERITS GDL_CONTAINER $ } END gdl-0.9.9/src/pro/idl_object.pro000066400000000000000000000006601340051421000164760ustar00rootroot00000000000000;+ ; ; NAME: ; IDL_OBJECT ; ; PURPOSE: ; create an 'IDL_OBJECT' object ; ; :Categories: ; Object Programming, Graphics ; ; this provides the procedure interface to creating an IDL_OBJECT. ; ; IDL_OBJECT is a built-in reference to GDL_OBJECT ; ;--------------------------------------------------------------------------- Function IDL_OBJECT Compile_Opt hidden return, obj_new('idl_object') END gdl-0.9.9/src/pro/idl_validname.pro000066400000000000000000000102171340051421000171670ustar00rootroot00000000000000;+ ; ; NAME: IDL_VALIDNAME ; ; PURPOSE: ; replacement for IDL_VALIDNAME ; ; MODIFICATION HISTORY: ; - 2010-Oct. : creation by Rene Preusker ; - 2011-Aug-18: modification by Alain Coulais : ; adding FAKE keywords /CONVERT_ALL, ; /CONVERT_SPACES for test with HealPix lib. ; - 2011-Aug-20: Alain: implement draft of CONVERT_SPACES ; - 2011-Aug: Hong Xu : implement "reserved words" ; - 2013-July: Tim : better managment of "\" and "$" (patch 66) ; Alain : "!" at first place only OK; multi inputs loop ; ; LICENCE: ; Copyright (C) 2010, R. Preusker ; Copyright (C) 2011, Alain Coulais, Hong Xu ; Copyright (C) 2013, Tim, Alain Coulais ; ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; function IDL_VALIDNAME, in_list, $ convert_spaces=convert_spaces, $ convert_all=convert_all, $ help=help, test=test ; if KEYWORD_SET(help) then begin print, 'function IDL_VALIDNAME, in_list, $' print, ' convert_spaces=convert_spaces, $' print, ' convert_all=convert_all, $' print, ' help=help, test=test' return, -1 endif ; reserved_words=['AND', $ 'BEGIN', $ 'BREAK', $ 'CASE', $ 'COMMON', $ 'COMPILE_OPT', $ 'CONTINUE', $ 'DO', $ 'ELSE', $ 'END', $ 'ENDCASE', $ 'ENDELSE', $ 'ENDFOR', $ 'ENDIF', $ 'ENDREP', $ 'ENDSWITCH', $ 'ENDWHILE', $ 'EQ', $ 'FOR', $ 'FORWARD_FUNCTION', $ 'FUNCTION', $ 'GE', $ 'GOTO', $ 'GT', $ 'IF', $ 'INHERITS', $ 'LE', $ 'LT', $ 'MOD', $ 'NE', $ 'NOT', $ 'OF', $ 'ON_IOERROR', $ 'OR', $ 'PRO', $ 'REPEAT', $ 'SWITCH', $ 'THEN', $ 'UNTIL', $ 'WHILE', $ 'XOR'] ; ;; AC 03/11/2011 ;; we need a working STREGEX to be able to run IDL_VALIDNAME ;; (please don't remove this test: if STREGEX is wrong, infinite loop below) ; if KEYWORD_SET(convert_all) then begin if (STREGEX('1abc','[^0-9a-z]') NE -1) then begin MESSAGE, 'No working STREGEX, we cannot do this test.' endif endif ; out_list=in_list ; for iii=0, n_elements(out_list)-1 do begin ;; out=out_list[iii] ;; if (out EQ '') then begin if KEYWORD_SET(convert_all) then out='_' out_list[iii]=out break endif ;; if KEYWORD_SET(convert_spaces) or KEYWORD_SET(convert_all) then begin while 1 do begin res = STRPOS(out, ' ') if (res EQ -1) then break STRPUT, out, '_', res endwhile endif ;; if KEYWORD_SET(convert_all) then begin ;; first_char = STRMID(out, 0, 1) ;; _ = WHERE(reserved_words EQ STRUPCASE(out), n) if (n gt 0) then out = '_' + out while 1 do begin res = STREGEX(out, '[^0-9A-Za-z_$]') if res EQ -1 then break STRPUT, out, '_', res endwhile ;; numbers and $ are not allowed as first char ;; if STREGEX(first_char, '^[0-9$]') EQ 0 then out = "_" + out ;; one exception: if first char is "!", is is OK if (first_char EQ '!') then out='!'+STRMID(out,1) endif else begin _ = WHERE(reserved_words EQ STRUPCASE(out), n) if (STREGEX(out, '^[0-9$]') EQ 0) or $ STREGEX(out, '[^0-9A-Za-z_$]') ne -1 or $ n gt 0 then out='' endelse out_list[iii]=out endfor ; if KEYWORD_SET(test) then STOP ; return, out_list ; end gdl-0.9.9/src/pro/image_statistics.pro000066400000000000000000000112101340051421000177250ustar00rootroot00000000000000;+ ; NAME: IMAGE_STATISTICS ; ; PURPOSE: ; ; CATEGORY: ; ; ; ; CALLING SEQUENCE: ; ; ; ; INPUTS: ; ; ; ; OPTIONAL INPUTS: ; ; ; ; KEYWORD PARAMETERS: ; ; ; ; OUTPUTS: ; ; ; ; OPTIONAL OUTPUTS: ; ; ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: ; ; ; ; RESTRICTIONS: ; ; ; ; PROCEDURE: ; ; ; ; EXAMPLE: ; ; ; LICENCE: this code is under GNU GPL v2 or later. (C) 2011 ; ; MODIFICATION HISTORY: ; -- first draft created by Alain Coulais, 10-Nov-2011 ; -- 15-Nov-2011 : AC : better managmenet of output types ; -- 02-Jul-2012 : Josh Sixsmith : Added the labeled keyword ;- ; pro ImSt_MESS, keyword_name MESSAGE, /continue, 'This keyword '+STRUPCASE(keyword_name)+' is not available' MESSAGE, /continue, 'Please consider to contribute (by submitting Patches on SF.net)' end ; pro IMAGE_STATISTICS, input_data, mask=mask, count=count, $ data_sum=data_sum, maximum=maximum, $ mean=mean_, minimum=minimum, $ stddev=stddev_, sum_of_squares=sum_of_squares, $ variance=variance_, $ lut=lut, vector=vector, $ weight_sum=weight_sum, weighted=weighted, $ labeled=labeled, $ help=help, test=test, verbose=verbose ; if N_PARAMS() NE 1 then MESSAGE, 'Incorrect number of arguments.' ; if ((SIZE(input_data))[0] LT 1) then MESSAGE, 'Expression must be an array in this context' ; if KEYWORD_SET(help) then begin print, 'pro IMAGE_STATISTICS, data, mask=mask, count=count, $' print, ' data_sum=data_sum, maximum=maximum, $' print, ' mean=mean_, minimum=minimum, $' print, ' stddev=stddev_, sum_of_squares=sum_of_squares, $' print, ' variance=variance_, $' print, ' lut=lut, vector=vector, $' print, ' weight_sum=weight_sum, weighted=weighted, $' print, ' labeled=labeled, $' print, ' help=help, test=test, verbose=verbose' return endif ; if KEYWORD_SET(lut) then ImSt_MESS, 'lut' if KEYWORD_SET(vector) then ImSt_MESS, 'vector' if KEYWORD_SET(weight_sum) then ImSt_MESS, 'weight_sum' if KEYWORD_SET(weighted) then ImSt_MESS, 'weighted' ; image=input_data if KEYWORD_SET(mask) then begin if KEYWORD_SET(labeled) then begin hist=HISTOGRAM(mask, reverse_indices=ri) n=N_ELEMENTS(hist) mean_=FLTARR(n, /nozero) maximum=FLTARR(n, /nozero) minimum=FLTARR(n, /nozero) count=ULONARR(n, /nozero) data_sum=FLTARR(n, /nozero) sum_of_squares=FLTARR(n, /nozero) for i=0L, n-1 do begin if ri[i] NE ri[i+1] then begin data=image[ri[ri[i]:ri[i+1]-1]] mean_[i] = MEAN(data,/double) maximum[i] = MAX(data, min=min_i) minimum[i] = min_i count[i] = N_ELEMENTS(data) data_sum[i] = TOTAL(data, /double) sum_of_squares[i] = FLOAT(TOTAL(data^2D, /double)) endif endfor endif else begin OK=WHERE(mask NE 0, nbp_ok) if (nbp_ok GT 0) then image=input_data[OK] endelse endif ; if KEYWORD_SET(labeled) then begin ; basically do nothing, just allows us to create a block for the non-labeled ; calculations endif else begin count=ULONG(N_ELEMENTS(image)) data_sum=FLOAT(TOTAL(image,/double)) mean_=FLOAT(MEAN(image,/double)) maximum=MAX(image, min=minimum) maximum=FLOAT(maximum) minimum=FLOAT(minimum) sum_of_squares=FLOAT(TOTAL(image^2.D,/double)) endelse ; if N_ELEMENTS(image) GT 1 then begin if KEYWORD_SET(labeled) then begin stddev_=FLTARR(n, /nozero) variance_=FLTARR(n, /nozero) for i=0L, n-1 do begin if ri[i] NE ri[i+1] then begin data=image[ri[ri[i]:ri[i+1]-1]] stddev_[i] = STDDEV(data, /double) variance_[i] = VARIANCE(data, /double) endif endfor endif else begin stddev_=FLOAT(STDDEV(image,/double)) variance_=FLOAT(VARIANCE(image,/double)) endelse endif else begin stddev_=0.0 variance_=0.0 endelse ; if KEYWORD_SET(verbose) then begin if KEYWORD_SET(mask) then begin print, 'Statistics on MASKED Image:' endif else begin print, 'Statistics on Image:' endelse print, 'Total Number of Pixels = ', count print, 'Total of Pixel Values = ', data_sum print, 'Maximum Pixel Value = ', maximum print, 'Mean of Pixel Values = ', mean_ print, 'Minimum Pixel Value = ', minimum print, 'Standard Deviation of Pixel Values = ', stddev_ print, 'Total of Squared Pixel Values = ', sum_of_squares print, 'Variance of Pixel Values = ', variance_ endif ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/imsl_erf.pro000066400000000000000000000005001340051421000161710ustar00rootroot00000000000000; by Sylwester Arabas function imsl_erf, x, double=dbl, inverse=inv on_error, 2 if ~keyword_set(inv) then return, erf(x, double=dbl) if total([x] ge 1 or [x] le -1) gt 0 then $ message, 'The inverse error function is defined only for -1 < x < 1' return, gdl_erfinv(x, double=dbl) end gdl-0.9.9/src/pro/imsl_zerosys.pro000066400000000000000000000021711340051421000171410ustar00rootroot00000000000000; by Sylwester Arabas function imsl_zerosys, f, n, double=double, err_rel=err_rel, $ fnorm=fnorm, jacobian=jacobian, itmax=itmax, xguess=xguess on_error, 2 ; informing about not supported keywords fmt = '(%"Warning: Keyword parameter %s not supported in call to: IMSL_ZEROSYS. Ignored.")' if keyword_set(err_rel) then message, string('ERR_REL', format=fmt), /continue if keyword_set(fnorm) then message, string('FNORM', format=fmt), /continue if keyword_set(jacobian) then message, string('JACOBIAN', format=fmt), /continue ; sanity checks if n_params() eq 0 then message, $ 'please supply a name of a function defining the system as the first parameter' if n_params() eq 1 && ~keyword_set(xguess) then message, $ 'please supply the size of the system as the second parameter' ; calling NEWTON with the magick /HYBRID keyword for switching to the modified ; Powell hydrid algorithm (FIXME: error messages prefixed by NEWTON) if ~keyword_set(xguess) then xguess = keyword_set(double) ? dblarr(n) : fltarr(n) return, newton(xguess, f, double=double, itmax=itmax, /hybrid) end gdl-0.9.9/src/pro/interpol.pro000066400000000000000000000137371340051421000162450ustar00rootroot00000000000000; ; under GNU GPL v2 or later ; ; by Sylwester Arabas ; relies on findex.pro by Paul Ricchiazzi ; ; revised 27-Feb-2012 by Alain C. after bug report 3495104 ; We have to manage also points in "p2" outside "p1" range ... ; (new cases not include in testsuite/test_interpol.pro) ; ; revised 18-Feb-2013 by Alain C. after bug report 3602770 ; We have to manage NaN and Infinity ... ; ; resived 29-Oct-2013 by Alain C. thanks to Gael mixing ; of Double/Long64 types in HFI Planck Monte Carlo pipeline. ; function INTERPOL, p0, p1, p2, lsquadratic=lsquadratic, $ quadratic=quadratic, spline=spline, $ test=test, help=help, debug=debug ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'function INTERPOL, p0, p1, p2, lsquadratic=lsquadratic, $' print, ' quadratic=quadratic, spline=spline, $' print, ' test=test, help=help, debug=debug' print, '/lsquadratic and /quadratic not available, help welcome !' return, -1 endif ; ; input type sanity checks ; ; type of return output comes from "p0" type ; p0_type=SIZE(p0, /type) if ((p0_type EQ 7) OR (p0_type EQ 8) OR (p0_type EQ 10)) then $ MESSAGE, 'expression TYPE not allowed in this context: p0' ; p1_type=SIZE(p1, /type) if ((p1_type EQ 7) OR (p1_type EQ 8) OR (p1_type EQ 10)) then $ MESSAGE, 'expression TYPE not allowed in this context: p1' ; ;; sanity checks ; if N_PARAMS() eq 1 then $ MESSAGE, 'Two or three parameters required' if KEYWORD_SET(lsquadratic) then $ MESSAGE, 'LSQUADRATIC keyword not supported yet (FIXME!)' if KEYWORD_SET(quadratic) then $ MESSAGE, 'QUADRATIC keyword not supported yet (FIXME!)' ; ; if N_PARAMS() eq 3 and N_ELEMENTS(p0) ne N_ELEMENTS(p1) then $ ; MESSAGE, 'In the three-parameter case the first and second argument must be of equal length' ; ; if N_PARAMS() eq 3 then begin if N_ELEMENTS(p0) ne N_ELEMENTS(p1) then $ MESSAGE, 'In the three-parameter case the first and second argument must be of equal length' ;; ;; note by AC, 27-02-2012: is it really true ?? all_equal_test=ABS((p1 - SHIFT(p1,+1))[1:*]) if MIN(TEMPORARY(all_equal_test)) eq 0 then begin MESSAGE, /cont, $ ; usually only triggered for integer arrays 'In the three-parameter case, the second argument must be strictly increasing or strictly decreasing.' endif endif ; ; isint = SIZE(p0, /type) lt 4 || SIZE(p0, /type) gt 11 ; ; AC, 29-oct-2013, other "bad" types exited before ; Float is "4", Dbl is 5, Cplx 6, DCplx 9 (TBC) ; if ((p0_type LT 4) OR (p0_type GT 11)) then p0_type=4 ; ; AC 2012/03/05: useful values ... may be updated later nbp_inside=N_ELEMENTS(p0) nbp_outside=0 ; ExistNotFinite=0 ; if N_PARAMS() eq 2 then begin ;; regular grid case if SIZE(p1, /dimensions) eq 0 then begin ind = FINDGEN(p1) / (p1 - (p1 eq 1 ? 0 : 1)) * (N_ELEMENTS(p0) - 1) endif else begin MESSAGE, 'In the two-parameter case the second parameter must be a scalar' ;; TODO: IDL does something else here... endelse endif else if ~KEYWORD_SET(spline) then begin ;; first, we exclude the NaN and Infinity values ... ;; if fact, we copy in another array the not finite values ... p2_info=SIZE(p2,/dim) index_p2_finite=WHERE(FINITE(p2) EQ 1, nbp_ok) if (nbp_ok GT 0) then begin if (N_ELEMENTS(p2) GT nbp_ok) then begin ExistNotFinite=1 index_p2_not_finite=WHERE(FINITE(p2) EQ 0) p2_not_finite=p2[index_p2_not_finite] p2=p2[index_p2_finite] endif else begin ;; all data are finite ... we don't need to recopy ExistNotFinite=0 endelse endif else begin ;; all input data are not finite ... if KEYWORD_SET(test) then STOP return, p2 endelse ;; irregular grid case ;; we need to manage points outside p1 range p1_min=MIN(p1, max=p1_max) outside_OK=WHERE((p2 LT p1_min) OR (p2 GT p1_max), nbp_outside) if (nbp_outside GT 0) then begin outside=p2[outside_OK] inside_OK=WHERE((p2 GE p1_min) AND (p2 LE p1_max), nbp_inside) if (nbp_inside GT 0) then begin p2_inside=p2[inside_OK] ind = FINDEX(p1, p2_inside) endif endif else begin ;; if we are here, all the points in "p2" are inside "p1" range ind=FINDEX(p1,p2) endelse endif ; if KEYWORD_SET(spline) then begin if (N_ELEMENTS(p0) LT 4) then MESSAGE, 'as least 4 input points need !' ;; spline case if N_PARAMS() eq 2 then begin x = FINDGEN(N_ELEMENTS(p0)) y = SPL_INTERP(x, p0, SPL_INIT(x, p0), ind) endif else begin if (N_ELEMENTS(p1) LT 4) then MESSAGE, 'as least 4 input points need !' y = SPL_INTERP(p1, p0, SPL_INIT(p1, p0), p2) endelse result=FIX(TEMPORARY(y), type=SIZE(p0, /type)) endif else begin ;; linear interpolation case if (nbp_inside GT 0) then result=INTERPOLATE(isint ? FLOAT(p0) : p0, ind) if (nbp_outside GT 0) then begin if p2_info eq 0 then begin tmp=MAKE_ARRAY(1, type=p0_type) endif else begin tmp=MAKE_ARRAY(p2_info, type=p0_type) endelse if (nbp_inside GT 0) then tmp[inside_OK]=result last=N_ELEMENTS(p0)-1 slope_begin=(1.*p0[1]-p0[0])/(p1[1]-p1[0]) slope_end =(1.*p0[last-1]-p0[last])/(p1[last-1]-p1[last]) for ii=0, nbp_outside-1 do begin if outside[ii] LT p1_min then begin tmp[outside_OK[ii]]=slope_begin*(outside[ii]-p1[0])+p0[0] endif else begin tmp[outside_OK[ii]]=slope_end*(outside[ii]-p1[last-1])+p0[last-1] endelse endfor if p2_info eq 0 then tmp=tmp[0] result=tmp endif endelse ; if ExistNotFinite then begin resres=MAKE_ARRAY(p2_info, type=p0_type) resres[index_p2_not_finite]=p2_not_finite resres[index_p2_finite]=result result=resres endif ; if KEYWORD_SET(test) or KEYWORD_SET(debug) then STOP ; return, result ; end gdl-0.9.9/src/pro/json_serialize.pro000066400000000000000000000126121340051421000174200ustar00rootroot00000000000000;+ ; NAME: JSON_SERIALIZE ; ; PURPOSE: ; ; This function returns the JSON description of a LIST, HASH or STRUCTURE (or arrays thereof). ; JSON is a light exchange format for data, easy to read by humand and computers alike. ; ; SYNTAX: ; ; string = JSON_SERIALIZE(something, /LOWERCASE) ; ; RETURN VALUE: ; ; a string ; ; ARGUMENTS: ; ; something: A valid STRUCUTRE, HASH or LIST, or array of them ; ; KEYWORDS: ; ; - LOWERCASE : currently unsupported. ; ; EXAMPLES: ; ; GDL> struct={ Planet: "Saturn", image: "testsuite:Saturn.jpg", weight:95.159 , units:"Earth Mass" } ; GDL> print, json_serialize(struct) ; {"PLANET":"Saturn","IMAGE":"testsuite:Saturn.jpg","WEIGHT": 95.1590,"UNITS":"Earth Mass"} ; ; MODIFICATION HISTORY: ; 03-May-2017 : written by G. Duvert ; ; LICENCE: ; Copyright (C) 2017, G. Duvert ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; function json_serialize,value,tagname=tagname,lowercase=lowercase COMPILE_OPT idl2, HIDDEN ON_ERROR, 2 ret=size(value) ndim=ret[0] type=ret[ndim+1] if( n_elements(tagname) gt 0) then tmpstr='"'+tagname+'":' else tmpstr='' n=n_elements(value) ; unfortunately lists etc are seen as arrays by 'size', so: mytype=typename(value) if (mytype eq 'LIST' or mytype eq 'HASH' or mytype eq 'ORDEREDHASH' or mytype eq 'DICTIONARY') then n=1 ; else 'OBJREF' if (n eq 1 ) then begin case type of 8: begin tagn=tag_names(value) tmpstr+='{' for j=0,n_tags(value)-1 do begin tmpstr+=json_serialize(tagname=tagn[j],value.(j)) if (j lt n_tags(value)-1 ) then tmpstr+="," end tmpstr+='}' end 11: begin ; more tricky depending on single value of array mytype=typename(value) if (mytype eq 'LIST') then begin tmpstr+='[' nn=value.Count() for j=0,nn-1 do begin tmpstr+=json_serialize(value[j]) if (j lt nn-1) then tmpstr+="," endfor tmpstr+=']' endif else begin tmpstr+='{' nn=value.Count() keys=value.Keys() for j=0,nn-1 do begin tmpstr+=json_serialize(tagname=keys[j],value[j]) if (j lt nn-1) then tmpstr+="," endfor tmpstr+='}' endelse end 7: tmpstr+='"'+value+'"' 10: message,"Type POINTER not allowed with JSON." 0: message,"Type UNDEFINED not allowed with JSON." 6: message,"Type COMPLEX not allowed with JSON." 9: message,"Type DCOMPLEX not allowed with JSON." ELSE: tmpstr+=string(value) endcase endif else begin tmpstr+="[" for i=0,n-1 do begin case type of 8: begin tagn=tag_names((value[i])) tmpstr+='{' for j=0,n_tags((value[i]))-1 do begin tmpstr+=json_serialize(tagname=tagn[j],(value[i]).(j)) if (j lt n_tags((value[i]))-1 ) then tmpstr+="," end tmpstr+='}' end 11: begin ; more tricky depending on single value of array mytype=typename((value[i])) if (mytype eq 'LIST') then begin tmpstr+='[' nn=(value[i]).Count() for j=0,nn-1 do begin tmpstr+=json_serialize((value[i])[j]) if (j lt nn-1) then tmpstr+="," endfor tmpstr+=']' endif else begin tmpstr+='{' nn=(value[i]).Count() keys=(value[i]).Keys() for j=0,nn-1 do begin tmpstr+=json_serialize(tagname=keys[j],(value[i])[j]) if (j lt nn-1) then tmpstr+="," endfor tmpstr+='}' endelse end 7: tmpstr+='"'+(value[i])+'"' 10: message,"Type POINTER not allowed with JSON." 0: message,"Type UNDEFINED not allowed with JSON." 6: message,"Type COMPLEX not allowed with JSON." 9: message,"Type DCOMPLEX not allowed with JSON." ELSE: tmpstr+=string((value[i])[i]) endcase if (i lt n-1) then tmpstr+="," endfor tmpstr+="]" endelse return,tmpstr end ;function json_serialize_sub_list,value ; print,"LIST" ; return,'!' ;end ; ; ;function json_serialize,value,lowercase=lowercase ; ; ret=size(value) ; ndim=ret[0] ; if (ndim gt 1) then message,'aaaaaaaaa pas booooooonn' ; type=ret[ndim+1] ; mytype=typename(value) ; if (type ne 11 and type ne 8) then message,'aaaaaaaaa pas booooooonn' ; if (type eq 11 and (mytype ne 'LIST' and mytype ne 'HASH' and mytype NE 'ORDEREDHASH' and mytype ne 'DICTIONARY')) then message,'aaaaaaaaa pas booooooonn' ; if type eq 8 then begin ; tagn=tag_names(value) ; tmpstr="{" ; for i=0,n_tags(value)-1 do begin ; tmpstr+=json_serialize_sub_struct_or_hash(tagn[i],value.(i)) ; if (i lt n_tags(value)-1) then tmpstr+="," ; end ; tmpstr+="}" ; return, tmpstr ; endif ;; if mytype eq ;; if mytype eq LIST then begin ;; endif else if mytype eq then begin ; return, 0 ;end gdl-0.9.9/src/pro/kurtosis.pro000066400000000000000000000032601340051421000162620ustar00rootroot00000000000000;$Id: kurtosis.pro,v 1.3 2012-07-13 22:28:02 alaingdl Exp $ ; function KURTOSIS, x, double=double, NaN=NaN, dimension=dimension ; ;+ ; ; NAME: KURTOSIS ; ; PURPOSE: ; Calculates the kurtosis of the input data ; ; CATEGORY: ; Mathematics: Statistics ; ; CALLING SEQUENCE: ; Result=kurtosis(x) ; ; KEYWORD PARAMETERS: ; DOUBLE : Keyword for double precision calculation ; NAN : Flag to treat IEEE Special Floating-Point values as missing data ; DIMENSION : if absent or equal to zero, compute the variance over the ; whole data. otherwise, compute along the related dimension. ; ; OUTPUTS: ; Result is the mean of input data ; ; ; RESTRICTIONS: ; The input x needs to be an array of numbers (i.e not strings, ; struct, ptr, object) ; ; PROCEDURE: ; kurtosis = 1/N sum((x-MEAN(x))^4/SQRT(VARIANCE(x))) - 3, ; Uses the MOMENT function ; ; EXAMPLE: ; a=FINDGEN(100) ; result=KURTOSIS(a) ; print, result ; -1.23606 ; ; MODIFICATION HISTORY: ; 20-Mar-2004 : Written by Christopher Lee ; 18-Jul-2005 : PC, moment.pro update ; 13-Jul-2012 : Alain Coulais : adding DIMENSION keyword, using MOMENT() ; ; LICENCE: ; Copyright (C) 2004, Christopher Lee, 2005 P. Chanial, 2012 Alain Coulais ; ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; ON_ERROR, 2 ; tmp=MOMENT(x, kurtosis=kurtosis, double=double, NaN=NaN, $ dimension=dimension, maxmoment=4) ; return, kurtosis ; end gdl-0.9.9/src/pro/la_invert.pro000066400000000000000000000003431340051421000163610ustar00rootroot00000000000000; ; A trivial wrap around for LA_INVERT, ; for compatibility because it is used by iCosmo; ; Alain C., 23-JAN-2012 ; function LA_INVERT, input, status=status, double=double ; return, INVERT(input, status, double=double) ; end gdl-0.9.9/src/pro/last_item.pro000066400000000000000000000023451340051421000163630ustar00rootroot00000000000000;+ ; Project : SOHO - CDS ; ; Name : LAST_ITEM ; ; Purpose : Returns the last element of the input variable. ; ; Explanation : Returns the last element of whatever the input variable is. ; ; Use : IDL> print,last_item(indgen(10)) ; ---> 9 ; ; Find the latest archive telemetry file: ; IDL> print,last_item(findfile(concat_dir('$CDS_TM_DATA','tm*'))) ; ; Inputs : item - variable/array/structure to extract from ; ; Opt. Inputs : None ; ; Outputs : Function returns last value. ; ; Opt. Outputs: None ; ; Keywords : None ; ; Calls : None ; ; Common : None ; ; Restrictions: None ; ; Side effects: None ; ; Category : Util, numerical ; ; Prev. Hist. : None ; ; Written : C D Pike, RAL, 9-Dec-94 ; ; Modified : ; ; Version : Version 1, 9-Dec-94 ;- function last_item, item on_error, 2 ; check input if n_params() lt 1 then begin message, 'Use: xlast = last_item(x)' endif return,item[n_elements(item)-1] end gdl-0.9.9/src/pro/linfit.pro000066400000000000000000000040241340051421000156630ustar00rootroot00000000000000; ; GDL replacement to LINFIT in IDL ; Bin Wu ; Sep. 2018 ; ; Ref: http://www.harrisgeospatial.com/docs/LINFIT.html ; FUNCTION LINFIT,X,Y,$ CHISQR=CHISQR,COVAR=COVAR,DOUBLE=DOUBLE,$ MEASURE_ERRORS=MEASURE_ERRORS,PROB=PROB,SIGMA=SIGMA,YFIT=YFIT ; Return the caller of a procedure in the event of an error. ON_ERROR, 2 ; To ensure X and Y are both vectors with the same size. dimsX = SIZE(X) dimsY = SIZE(Y) IF (dimsX[0] NE 1) OR (dimsY[0] NE 1) OR (dimsX[1] NE dimsY[1]) THEN MESSAGE, 'X and Y must be vectors of the same size' ; To force the computation to be done in double-precision arithmetic. IF KEYWORD_SET(DOUBLE) THEN BEGIN X = DOUBLE(X) Y = DOUBLE(Y) ENDIF ; To give a vector containing standard measurement errors for each point Y[i]. IF KEYWORD_SET(MEASURE_ERRORS) THEN BEGIN dimsE = SIZE(MEASURE_ERRORS) IF (dimsE[0] NE 1) OR (dimsE[1] NE dimsY[1]) THEN MESSAGE, 'MEASURE_ERRORS must be of the same size as Y' ENDIF ELSE BEGIN MEASURE_ERRORS = Y - Y + 1 ENDELSE ; Coefficients calculation. S = TOTAL(1/(MEASURE_ERRORS^2)) Sx = TOTAL(X/(MEASURE_ERRORS^2)) Sy = TOTAL(Y/(MEASURE_ERRORS^2)) Ti = (X-Sx/S)/MEASURE_ERRORS Stt = TOTAL(Ti^2) ; Solve 2x2 linear equations by CRAMER's rule B = TOTAL(Ti*Y/MEASURE_ERRORS)/Stt A = (Sy - Sx*B)/S ; Variance estimation. Va = (1+Sx^2/S/Stt)/S Vb = 1/Stt CVab = -Sx/S/Stt COVAR = [[Va, CVab],[CVab,Vb]] ; Approximated Y. YFIT = A + B*X ; Calculate the unreduced chi-square goodness-of-fit statistic. CHISQR = TOTAL(((Y-YFIT)/MEASURE_ERRORS)^2) ; The 1-sigma uncertainty estimates for the returned parameters and the probability that the computed fit. SIGMA = [SQRT(Va),SQRT(Vb)] IF KEYWORD_SET(MEASURE_ERRORS) THEN PROB = 1 - IGAMMA((dimsY[1]-2)/2.0,CHISQR/2) ELSE BEGIN PROB = Y-Y+1 fct = SQRT(CHISQR/(dimsY[1]-2)) SIGMA = SIGMA*fct ENDELSE AB = [A,B] RETURN, AB END gdl-0.9.9/src/pro/lmgr.pro000066400000000000000000000043421340051421000153420ustar00rootroot00000000000000;$Id: lmgr.pro,v 1.3 2016-06-05 14:18:41 gilles-duvert Exp $ ;+ ; ; ; ; NAME: ; LMGR ; ; ; PURPOSE: ; return license information ; emulates an IDL desktop license ; As GDL does not need license management this routine is ; for IDL compatibility only ; ; ; CATEGORY: ; compatibility ; ; ; CALLING SEQUENCE: ; res = LMGR(/CLIENTSERVER,/DEMO,/EMBEDDED, ; /RUNTIME,/STUDENT,/TRIAL,/VM, ; [EXPIRE_DATE=variable],/FORCE_DEMO, ; [INSTALL_NUM=variable],[LMHOSTID=variable], ; [SITE_NOTICE=variable] ; ; ; OUTPUTS: 1 if no keyword is set ; 0 otherwise ; ; ; ; COMMON BLOCKS: ; none ; ; SIDE EFFECTS: ; none ; ; ; MODIFICATION HISTORY: ; Written by: Marc Schellens ; Special undocumented features for testing presence of additional licensed programs added by G. Duvert ; ; ;- ; LICENCE: ; Copyright (C) 2005, ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- function LMGR,some_additional_licensed_program,$ CLIENTSERVER=cs,DEMO=demo,EMBEDDED=eb,$ RUNTIME=rt,STUDENT=student,TRIAL=trial,VM=vm,$ EXPIRE_DATE=expire,FORCE_DEMO=force,$ INSTALL_NUM=install_num,LMHOSTID=hostid,$ SITE_NOTICE=site_notice, VERSION=version on_error, 2 hostid = '000000000001' install_num = '00001' site_notice= 'GNU' ; undocumeted feature: tests for other programs & licences, with their VERSION: ; probably necessary to answer "no" and return a warning if (n_params() gt 0) then begin message,/informational,'Procedure is testing presence of an external program: "'+some_additional_licensed_program+'", absent from GDL' return, 0 endif ; if keyword_set( cs) then return,0 if keyword_set( demo) then return,0 if keyword_set( eb) then return,0 if keyword_set( rt) then return,0 if keyword_set( student) then return,0 if keyword_set( trial) then return,0 if keyword_set( vm) then return,0 return,1 end gdl-0.9.9/src/pro/loadct.pro000066400000000000000000000063761340051421000156600ustar00rootroot00000000000000;+ ; ; NAME: ; LOADCT ; ; PURPOSE: ; Load a predefined color table ; ; CATEGORY: ; graphics ; ; CALLING SEQUENCE: ; LOADCT,[table_number], GET_NAMES=names, FILE=file,$ ; NCOLORS=mynColors, BOTTOM=mybottom, $ ; SILENT=silent, RGB_TABLE=rgb_table ; ; KEYWORD PARAMETERS: ; SILENT if set lading colortable message is suppressed ; GET_NAMES set to a named variable in which all the colortable ; names are returned ; FILE=file IDL compatibility only, no effect ; NCOLORS number of colors to use. the smaller of ; !D.table_size-1 and NCOLORS is used ; BOTTOM first color index to use ; RGB_TABLE=mytable return table colors in mytable, do not load ; colortable. ; ; OUTPUTS: ; none ; ; OPTIONAL OUTPUTS: ; keyword outputs, if any ; ; COMMON BLOCKS: ; COLORS GDL colors common block ; ; SIDE EFFECTS: ; color tables of current graphic device are changed ; ; PROCEDURE: ; uses the internal library procedure LOADCT_INTERNALGDL ; ; MODIFICATION HISTORY: ; -- Written by Marc Schellens in 2005 ; ; -- AC, 2014-Aug-10: now we get back RGB_TABLE ! ; ;- ; LICENCE: ; Copyright (C) 2005, 2014 ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- ; pro LOADCT, table, GET_NAMES=names, FILE=file,$ NCOLORS=mynColors, BOTTOM=mybottom, $ SILENT=silent, RGB_TABLE=rgb_table ON_ERROR, 2 ; common colors, r_orig, g_orig, b_orig, r_curr, g_curr, b_curr ; if KEYWORD_SET(file) then $ MESSAGE, 'FILE keyword not implemented yet, ignored. (FIXME)', /continue ; if (N_ELEMENTS(table) eq 0) and ARG_PRESENT(names) then begin LOADCT_INTERNALGDL, GET_NAMES=names return endif ; if (N_ELEMENTS(table) eq 0) or not KEYWORD_SET(silent) then begin LOADCT_INTERNALGDL, GET_NAMES=names if N_ELEMENTS(table) eq 0 then begin for n=0,N_ELEMENTS(names)-1 do begin print, FORMAT="(I2,2X,A)",n,names[n] endfor READ, table, PROMPT='Enter table number: ' endif endif ; if ARG_PRESENT(RGB_TABLE) then begin LOADCT_INTERNALGDL, table, RGB_TABLE=rgb_table return endif ; LOADCT_INTERNALGDL, table ; if not KEYWORD_SET( silent) then begin MESSAGE,'Loading table ' + names[table],/INFO endif ; if N_ELEMENTS(mybottom) eq 0 then bottom=0 else begin bottom=mybottom bottom >= 0 & bottom <= !D.table_size-1 end ; if N_ELEMENTS(mynColors) eq 0 then begin nColors=!D.table_size endif else begin nColors=mynColors nColors >= 1 & nColors <=!D.table_size end ; if (bottom+nColors GE !D.table_size) then nColors=!D.table_size-bottom ; TVLCT,r,g,b,/GET ; if N_ELEMENTS( r_orig) eq 0 then begin r_orig = BYTARR(!D.table_size) g_orig = BYTARR(!D.table_size) b_orig = BYTARR(!D.table_size) endif ; idx=LINDGEN(nColors)*(!D.table_size-1)/(nColors-1) ; r=r[idx] g=g[idx] b=b[idx] ; r_orig[bottom] = r g_orig[bottom] = g b_orig[bottom] = b ; r_curr = r_orig g_curr = g_orig b_curr = b_orig ; ; note that loading colors is very slow on X11 with plplot. TVLCT, r_curr, g_curr, b_curr ; end gdl-0.9.9/src/pro/make_dll.pro000066400000000000000000000141311340051421000161460ustar00rootroot00000000000000; ; Alain C. + Ilia N., 8 July 2015, back from the Nika2 pipeline meeting ; Quick and dirty to provide useful tool. ; (large experience of *.so files compiled by hand or via IDL working ; in GDL (e.g. PIOlib, Nika, ...)) ; ; The trouble is to have a "idl_export.h" around ; ; under GNU GPL V2 or later ; ; --------------------------------------- ; Modifications history : ; ; - 2018-JAN-25 : completely rewritten by Gilles Duvert, using most of ; the parameters. Tested on Nika pipeline. ; ; - 2018-JAN-26 : AC : trying to improve & simplify the default ; interface. ; ; - 2018-SEP-18 : AC : Change a test for OSX ; ; --------------------------------------- ; ; Do we have access to a "idl_export.h" file ? It is mandatory ! ; the logic ? 1: local, 2: in an 'include/', 3: anywhere ; function LOOKFOR_IDL_EXPORT, test=test, verbose=verbose ; ON_ERROR, 2 ; ; do we have the file in the current directory ?! ; ok=FILE_TEST('idl_export.h') if KEYWORD_SET(verbose) then print, 'result of step 1 : ', ok if ok then result='idl_export.h' ; if ~ok then begin ;; ;; file "idl_export.h" usualy under sub-dir include/ ;; locate="locate 'include/idl_export.h'" SPAWN, locate, result, exit=exit_status, count=count ;; if (exit_status GT 1) then begin MESSAGE, 'Sorry, GDL procedure "make_dll.pro" is not working on this computer.' endif if ~((exit_status EQ 1) or (count EQ 0) ) then ok=1 if KEYWORD_SET(verbose) then print, 'result of step 2 : ', ok endif if ~ok then begin ;; ;; let try again on less conventional place locate="locate 'idl_export.h'" SPAWN, locate, result, exit=exit_status, count=count if (exit_status GT 1) then begin MESSAGE, 'Sorry, GDL procedure "make_dll.pro" is not working on this computer.' endif if ~((exit_status EQ 1) or (count EQ 0) ) then ok=1 if KEYWORD_SET(verbose) then print, 'result of step 3 : ', ok endif if ~ok then begin txt='header file "idl_export.h" is mandatory! "idl_export.h" ' txt=txt+'is part of IDL and not included in this distribution.' MESSAGE, txt+' It can be found on the web.' endif ; ; We just need the path to this header file ; idlInclude=result[0] ; if KEYWORD_SET(verbose) then print, 'header located here : ', idlInclude ; if KEYWORD_SET(test) then stop ; return, idlInclude ; end ; ; --------------------------------------- ; pro MAKE_DLL, input_files, output_file, Exported_Routine_Names, $ CC=CC, LD=LD, COMPILE_DIRECTORY=COMPILE_DIRECTORY, $ DLL_PATH=DLL_PATH, EXPORTED_DATA=EXPORTED_DATA, $ EXTRA_CFLAGS=EXTRA_CFLAGS, EXTRA_LFLAGS=EXTRA_LFLAGS, $ INPUT_DIRECTORY=INPUT_DIRECTORY, $ NOCLEANUP=NOCLEANUP, OUTPUT_DIRECTORY=OUTPUT_DIRECTORY, $ REUSE_EXISTING=REUSE_EXISTING, SHOW_ALL_OUTPUT=SHOW_ALL_OUTPUT, $ verbose=verbose, test=test, help=help, debug=debug ; if KEYWORD_SET(help) then begin print, 'pro MAKE_DLL, input_files, output_file, Exported_Routine_Names, $' print, ' CC=CC, LD=LD, COMPILE_DIRECTORY=COMPILE_DIRECTORY, $' print, ' DLL_PATH=DLL_PATH, EXPORTED_DATA=EXPORTED_DATA, $' print, ' EXTRA_CFLAGS=EXTRA_CFLAGS, EXTRA_LFLAGS=EXTRA_LFLAGS, $' print, ' INPUT_DIRECTORY=INPUT_DIRECTORY, $' print, ' NOCLEANUP=NOCLEANUP, OUTPUT_DIRECTORY=OUTPUT_DIRECTORY, $' print, ' REUSE_EXISTING=REUSE_EXISTING, SHOW_ALL_OUTPUT=SHOW_ALL_OUTPUT, $' print, ' verbose=verbose, test=test, help=help, debug=debug' return endif ; objext='.o' cext='.c' libext='.so' ; ; AC 2018-01-29 : to be generalized ; see also "mg_idl_export.h" for OSX ; do_include=0 if do_include then begin idlInclude=LOOKFOR_IDL_EXPORT(verbose=verbose, test=test) idlInclude=STRSPLIT(idlInclude, 'idl_export.h', /extract, /regex) idlInclude=idlInclude[0] endif else begin idlInclude='' endelse ; if ~KEYWORD_SET(cc) then ref_cc=!make_dll.cc if ~KEYWORD_SET(LD) then ref_ld=!make_dll.ld if ~KEYWORD_SET(EXTRA_CFLAGS) then EXTRA_CFLAGS=' ' if ~KEYWORD_SET(EXTRA_LFLAGS) then EXTRA_LFLAGS=' ' if ~KEYWORD_SET(COMPILE_DIRECTORY) then COMPILE_DIRECTORY=!make_dll.COMPILE_DIRECTORY if ~KEYWORD_SET(INPUT_DIRECTORY) then INPUT_DIRECTORY=COMPILE_DIRECTORY if ~KEYWORD_SET(OUTPUT_DIRECTORY) then OUTPUT_DIRECTORY= COMPILE_DIRECTORY ; if (N_PARAMS() EQ 2) then begin Exported_Routine_Names=output_file output_file=input_files[0] endif ; ; real files ; source=PATH_SEP_ADD(input_directory)+input_files+cext obj=PATH_SEP_ADD(compile_directory)+input_files+objext lib=PATH_SEP_ADD(output_directory)+output_file+libext ; print, source print, obj print, lib ; ;stop ; dll_path is used also to test if exist. givedll=ARG_PRESENT(DLL_PATH) ; if KEYWORD_SET(REUSE_EXISTING) then begin if (FILE_TEST(lib)) then begin if (givedll) then DLL_PATH=lib return end end ; ; insert location of "idl_export.h" ; cc=ref_cc if STRLEN(idlInclude) GT 0 then begin step1=STRSPLIT(cc, '%Z', /extract, /regex) cc=step1[0]+' '+idlInclude+' '+step1[1] endif else begin step1=STRSPLIT(cc, '-I%Z', /extract, /regex) cc=step1[0]+' '+step1[1] endelse ;stop ; ; ; CFLAGS parameter step1=STRSPLIT(cc, '%X', /extract, /regex) cc=step1[0]+' '+extra_cflags+' '+step1[1] ; ref_cc=cc for i=0, N_ELEMENTS(source)-1 do begin cc=ref_cc ;; inserting the C-filename step1=STRSPLIT(cc, '%C', /extract, /regex) cc=step1[0]+' '+source[i]+' '+step1[1] ;;insert the obj %O step1=STRSPLIT(cc, '%O', /extract, /regex) cc=step1[0]+' '+obj[i] if KEYWORD_set(debug) then print, cc ;; spawn spawn, cc endfor ; if KEYWORD_set(debug) then STOP ;link ld=ref_ld ; if (!version.os EQ 'darwin') then begin step1=STRSPLIT(ld, '-shared ', /extract, /regex) ld=step1[0]+' -dylib '+step1[1] endif ; ;%L : library name. step1=STRSPLIT(ld, '%L', /extract, /regex) ld=step1[0]+lib+step1[1] ;%X by EXTRA_LFLAGS step1=STRSPLIT(ld, '%X', /extract, /regex) ld=step1[0]+EXTRA_LFLAGS ;%O by all the .o: step1=STRSPLIT(ld, '%O', /extract, /regex) ld=step1[0]+strjoin(obj,' ')+step1[1] ; if KEYWORD_set(debug) then print, ld ; spawn spawn, ld if (givedll) then DLL_PATH=lib ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/map_clip_set.pro000066400000000000000000000100611340051421000170330ustar00rootroot00000000000000;+ ; NAME: ; MAP_CLIP_SET ; ; ; PURPOSE: ; Sets up the clipping/splitting pipeline for the projection ; ; ; CATEGORY: ; Map utilities ; ; ; CALLING SEQUENCE: ; ; ; INPUTS: ; ; ; OUTPUTS: ; ; ; MODIFICATION HISTORY: ; 25-Jul-2006 : written by JMG ; 2014: modified by GD ; ; LICENCE: ; Copyright (C) 2006, Joel M. Gales ; 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 2 of the License, or ; (at your option) any later version. ; ;- pro map_clip_set,map_structure=map_structure,$ reset=reset,split=split,clip_plane=clip_plane,$ transform=transform,clip_uv=clip_uv, show=show on_error, 2 giveback=0 if (n_elements(map_structure) eq 0) then begin map_structure=!map giveback=1 endif if (keyword_set(reset)) then begin map_structure.pipeline=0.0 endif if (keyword_set(transform)) then begin i = 0 while (map_structure.pipeline[0,i] ne 0 and map_structure.pipeline[0,i] ne 3) do i = i + 1 if (i eq 11) then begin message, 'Too many pipeline stages..' endif else begin map_structure.pipeline[0,i] = 3 endelse endif if (n_elements(split) ne 0) then begin i = 0 while (map_structure.pipeline[0,i] ne 0 and map_structure.pipeline[0,i] ne 3) do i = i + 1 if (i eq 11) then begin message, 'Too many pipeline stages..' endif else begin ; print,"split=",split map_structure.pipeline[0,i+1] = 3 map_structure.pipeline[0,i] = 1 map_structure.pipeline[1,i] = -1*split[2] map_structure.pipeline[2,i] = -1*split[3] map_structure.pipeline[3,i] = -1*split[4] map_structure.pipeline[4,i] = -1*split[5] lon=split[0]*!DTOR & lat=split[1]*!DTOR x = cos(lon) * cos(lat) & y = sin(lon) * cos(lat) &z = sin(lat) map_structure.pipeline[5,i] = x map_structure.pipeline[6,i] = y map_structure.pipeline[7,i] = z endelse endif if (n_elements(clip_plane) ne 0) then begin i = 0 while (map_structure.pipeline[0,i] ne 0 and map_structure.pipeline[0,i] ne 3) do i = i + 1 if (i eq 11) then begin message, 'Too many pipeline stages..' endif else begin ; print,"clip_plane=",clip_plane map_structure.pipeline[0,i+1] = 3 map_structure.pipeline[0,i] = 2 f = sqrt(clip_plane[0]^2 + clip_plane[1]^2 + clip_plane[2]^2) if (f eq 0) then f = 1 map_structure.pipeline[1,i] = clip_plane[0] / f map_structure.pipeline[2,i] = clip_plane[1] / f map_structure.pipeline[3,i] = clip_plane[2] / f map_structure.pipeline[4,i] = clip_plane[3] / f endelse endif if (n_elements(clip_uv) ne 0) then begin i = 0 while (map_structure.pipeline[0,i] ne 3 and i lt 11) do i = i + 1 if (i eq 11) then begin map_structure.pipeline[0,0] = 3 map_structure.pipeline[0,1] = 4 map_structure.pipeline[1,1] = clip_uv[0] map_structure.pipeline[2,1] = clip_uv[1] map_structure.pipeline[3,1] = clip_uv[2] map_structure.pipeline[4,1] = clip_uv[3] endif else begin map_structure.pipeline[0,i+1] = 4 map_structure.pipeline[1,i+1] = clip_uv[0] map_structure.pipeline[2,i+1] = clip_uv[1] map_structure.pipeline[3,i+1] = clip_uv[2] map_structure.pipeline[4,i+1] = clip_uv[3] endelse endif if (keyword_set(show)) then begin i=0 while(map_structure.pipeline[0,i] ne 0) do begin a=float(map_structure.pipeline[1,i]) b=float(map_structure.pipeline[2,i]) c=float(map_structure.pipeline[3,i]) d=float(map_structure.pipeline[4,i]) case fix(map_structure.pipeline[0,i]) of 1: print,"PIPELINE_SPLIT",a,b,c,d 2: print,"PIPELINE_PLANE",a,b,c,d 3: print,"PIPELINE_TRANS",a,b,c,d 4: print,"PIPELINE_UVBOX",a,b,c,d endcase i++ endwhile endif if (giveback eq 1) then !map=map_structure return end gdl-0.9.9/src/pro/matrix_multiply.pro000066400000000000000000000041111340051421000176360ustar00rootroot00000000000000;+ ; NAME: MATRIX_MULTIPLY ; ; PURPOSE: GDL substitute to the IDL intrinsic function ; ; AUTHOR: Philippe Prugniel 2008/02/29 ; ; Modifications: ; 05-Feb-2013: when GDL is compiled with Eigen Lib., we use internal ; fast MATMUL function. It is not ready for Complex/DoubleComplex ; 01-Mar-2013: with Eigen Lib, matmul function is OK with complex values, removed ; some code ; 28-Mar-2013: MATMUL removed, direct interface to Eigen3, all types ; should be OK ; ; Copyright (C) 2008, 2013. ; 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 2 of the License, or ; (at your option) any later version. ; ;----------------------------------------------------------------------------- ; function MATRIX_MULTIPLY, a, b, ATRANSPOSE=atr, BTRANSPOSE=btr, help=help Message,"Unconsitent GDL Install: Matrix_multpily is now and INTERNAL function, please report" ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'function MATRIX_MULTIPLY, a, b, ATRANSPOSE=atr, BTRANSPOSE=btr, help=help' return, -1 endif ; IF (N_PARAMS() NE 2) THEN BEGIN MESSAGE, 'Incorrect number of arguments.' ENDIF ; ; note by AC, 28 MArch 2013: we don't removed that if we need ; to go back to basic tests related to Eigen3 ... ; ; "type" will be 1 if GDL compiled with Eigen, 0 ; !matmul_quiet to avoid repeating internal message if no Eigen around ... ; ;DEFSYSV, "!matmul_quiet", exist=quiet ;if ~quiet then begin ; type=MATMUL(/available, quiet=quiet) ; DEFSYSV, "!matmul_quiet", 1, 1 ;endif else begin ; type=MATMUL(/available,/quiet) ;endelse ; ;if (type EQ 0) then begin case (1) of KEYWORD_SET(atr) and not KEYWORD_SET(btr): return, TRANSPOSE(a) # b KEYWORD_SET(btr) and not KEYWORD_SET(atr): return, a # TRANSPOSE(b) KEYWORD_SET(atr) and KEYWORD_SET(btr): return, TRANSPOSE(a) # TRANSPOSE(b) else : return, a # b endcase ;endif else begin ; return, MATMUL(a, b, ATRANSPOSE=atr, BTRANSPOSE=btr, debug=debug) ;endelse ; end gdl-0.9.9/src/pro/meanabsdev.pro000066400000000000000000000025661340051421000165140ustar00rootroot00000000000000;$Id: meanabsdev.pro,v 1.3 2017-06-14 16:09:04 gilles-duvert Exp $ function meanabsdev, x, double=double, NaN=NaN ;+ ; ; ; ; NAME: ; meanabsdev ; ; PURPOSE: ; Calculates the mean absolute deviation of the input data ; ; ; CATEGORY: ; Mathematics: Statistics ; ; CALLING SEQUENCE: ; Result=meanabsdev(x) ; ; ; KEYWORD PARAMETERS: ; DOUBLE : Keyword for double precision calculation ; NAN : Flag to ignore IEEE Floating point NaN ; ; OUTPUTS: ; Result is the mean absolute deviation of input data ; ; ; RESTRICTIONS: ; The input x needs to be an array of numbers (i.e not strings, ; struct, ptr, object) ; ; PROCEDURE: ; mean absolute deviation = (1/N) sum(abs(x-mean(x))), ; Uses the MOMENT function ; ; EXAMPLE: ; a=findgen(100) ; result=meanabsdev(a) ; print, result ; 25.0000 ; ; MODIFICATION HISTORY: ; 20-Mar-2004 : Written by Christopher Lee ; 18-Jul-2005 : PC, moment.pro update ; ; LICENCE: ; Copyright (C) 2004, ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- on_error, 2 junk = moment(x, maxmoment=2, mdev=mdev, double=double, NaN=NaN) return, mdev end gdl-0.9.9/src/pro/norm.pro000066400000000000000000000074001340051421000153520ustar00rootroot00000000000000;+ ; NAME: NORM ; ; PURPOSE: ; For vectors, returns a norm ; For matrix, returns the L0, L1 or L2 norm (only) ; ; CATEGORY: ; Algebra ; ; CALLING SEQUENCE: ; result=norm(a [, /double] [, /lnorm] ) ; ; INPUTS: ; a Vector or Matrix (can be complex) ; ; OUTPUTS: ; result Norm (see Purpose) ; ; IDL DIFFERENCES: ; scalars are treated as vectors ; double=0 does not convert the result to float (like total) ; ; MODIFICATION HISTORY: ; 12-Jan-2006 : written by Pierre Chanial ; 12-Jul-2017 : AlainC., except the case (Lnorm=2 & matrix & Complex ; input), try to be complete. ; ; LICENCE: ; Copyright (C) 2006, P. Chanial, 2017, A. Coulais ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; function NORM, array, double=double, lnorm=lnormOut, test=test, help=help ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, "function NORM, array, double=double, lnorm=lnormOut, $" print, " test=test, help=help" return, -1 endif ; type=SIZE(array, /type) ndim=SIZE(array, /n_dimensions) ; if ((ndim LT 1) OR (ndim GT 2)) then begin MESSAGE, 'Input must be an N-element vector or an M by N array.' endif ; ; "lnorm" value must be carefuly processed ... ; single element of numerical type but not complex ; if (N_ELEMENTS(lnormOut) GT 0) then begin if (N_ELEMENTS(lnormOut) GT 1) then $ MESSAGE, 'LNORM must be a scalar or a 1-element array.' lnorm=lnormOut[0] endif else begin if (ndim EQ 1) then lnorm=2 if (ndim EQ 2) then lnorm=0 endelse ; "lnorm" must be numeric : integer or float but no complex if ~(ISA(lnorm,/integer) OR ISA(lnorm,/float)) then $ MESSAGE,/continue, 'bad type for LNORM, converted into Double' ; ; "lnorm" must be a double lnorm=DOUBLE(lnorm) ; if KEYWORD_SET(test) then $ print, "input norm value, used norm value : ", lnormout, lnorm ; ; Do we have NaN in input array ?? O if no NaN, 1 otherwise nan=1-ARRAY_EQUAL(FINITE(array), 1) ; ; First we process the Vector case (ndim == 1), ; no peculiar problem :) ; if (ndim EQ 1) then begin case lnorm of ;; infinity norm 0: result=MAX(ABS(array), NAN=nan) ;; L(1) norm 1: result=TOTAL(ABS(array), /DOUBLE, NAN=nan) ;; L(2) norm (Euclidean) 2: result=SQRT(TOTAL(ABS(array)^2d, /DOUBLE, NAN=nan)) ;; General L(n) norm (tested with negatives values) ;; print, norm(findgen(10)+1, lnorm=-10,/doubl) ;; 0.99990060 else: result=(TOTAL(ABS(array)^lnorm, /DOUBLE, NAN=nan))^(1/lnorm) endcase endif ; if (ndim EQ 2) then begin case lnorm of ;; infinity norm (maximum absolute *row* sum norm) 0: result=MAX(TOTAL(ABS(array), 1, /DOUBLE, NAN=nan)) ;; L(1) norm (maximum absolute *column* sum norm) 1: result=MAX(TOTAL(ABS(array), 2, /DOUBLE, NAN=nan)) ;; L(2) norm (spectral norm) 2: begin ;; we are not ready for Complex inputs in GDL if ISA(array, /complex) then begin MESSAGE, /continue, 'Complex Input not ready in GDL !' MESSAGE, 'please contribute : LA_SVD missing :(' endif else begin SVDC, array, W, U, V, /DOUBLE result = MAX(W) endelse end ;; no other case for Matrix else: MESSAGE, 'For MATRIX input, LNORM must be equal to 0, 1, or 2' endcase endif ; ; Which type for the result ? Float or Double ! ; Default is "float" result_type=4 if KEYWORD_SET(double) then result_type=5 if (type EQ 5) OR (type EQ 9) then result_type=5 ; if KEYWORD_SET(test) then STOP ; return, FIX(result, TYPE=result_type) ; end gdl-0.9.9/src/pro/obsolete/000077500000000000000000000000001340051421000154705ustar00rootroot00000000000000gdl-0.9.9/src/pro/obsolete/file_basename_old.pro000066400000000000000000000072341340051421000216300ustar00rootroot00000000000000; ; Since First July 2013, because a C++ internal version is available ; this file is OBSOLETING, will be removed in the future !! ; ; ;+ ; NAME: FILE_BASENAME ; ; PURPOSE: The FILE_BASENAME function returns the basename of a file ; path. A file path is a string containing one or more segments ; consisting of names separated by directory delimiter characters ; (slash (/) under UNIX, or backslash (\) under Microsoft ; Windows). The basename is the final rightmost segment of the file ; path; it is usually a file, but can also be a directory name. ; ; FILE_BASENAME is based on the standard UNIX basename(1) utility. ; CATEGORY: UNIX utility. ; ; CALLING SEQUENCE: Result = FILE_BASENAME(Path [, RemoveSuffix] [, /FOLD_CASE]) ; ; INPUTS: Path: A scalar string or string array containing paths for ; which the basename is desired. ; ; OPTIONAL INPUTS: RemoveSuffix: An optional scalar string or ; 1-element string array specifying a filename suffix to be removed ; from the end of the basename, if present. ; ; KEYWORD PARAMETERS: /FOLD_CASE is not available now (and useless ; for Unix). return -1 if activated ; ; OUTPUTS: A scalar string or string array containing the basename for ; each element of the Path argument. ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: none ; ; RESTRICTIONS: only for Unix (Unix, Linux and Mac OS X) systems ; ; Rules used by FILE_BASENAME ; FILE_BASENAME makes a copy of the input file path string, then ; modifies the copy according to the following rules: ; - If Path is a NULL string, then FILE_BASENAME returns a NULL ; string. ; - If Path consists entirely of directory delimiter characters, the ; result of FILE_BASENAME is a single directory delimiter character. ; - If there are any trailing directory delimiter characters, they ; are removed. ; - If any directory delimiter characters remain, all characters up ; to and including the last directory delimiter are removed. ; - If the RemoveSuffix argument is present, is not identical to the ; characters remaining, and matches the suffix of the characters ; remaining, the suffix is removed. Otherwise, the Result is not ; modified by this step. ; ; PROCEDURE: ; ; EXAMPLE: ; ; print, file_basename('/usr/local/rsi/idl/lib/dist.pro', '.pro') ; GDL prints: ; dist ; ; MODIFICATION HISTORY: ; - Sept 2007: created by Sebastien Masson ; - Sept 2007: managing insufficient numbers of parameters, /help ; - June 2010: escape special characters by Lea Noreskal ; ;- ; LICENCE: ; Copyright (C) 2007, Sebastien Masson ; 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 2 of the License, or ; (at your option) any later version. ;- ; FUNCTION FILE_BASENAME_OLD, Path, RemoveSuffix, $ FOLD_CASE = fold_case, help=help ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'FUNCTION FILE_BASENAME, Path, [RemoveSuffix], [/FOLD_CASE], [/help]' return, -1 endif ; if ((N_PARAMS() LT 1) OR (N_PARAMS() GT 2)) then begin MESSAGE, 'Incorrect number of arguments.' endif ; IF KEYWORD_SET(fold_case) then begin MESSAGE, 'Sorry, Keyword FOLD_CASE is not available now.' endif ; sfx = N_ELEMENTS(RemoveSuffix) NE 0 ? RemoveSuffix : '' result = STRARR(N_ELEMENTS(Path)) ; for i = 0, N_ELEMENTS(path) - 1 do begin if STRTRIM(path[i], 2) ne '' then begin SPAWN, '\basename ' + ESCAPE_SPECIAL_CHAR(path[i]) + ' ' + ESCAPE_SPECIAL_CHAR(sfx), res result[i] = TEMPORARY(res) endif else result[i] = path[i] endfor ; return, SIZE(path, /n_dim) eq 0 ? result[0] : result ; end gdl-0.9.9/src/pro/obsolete/file_delete_old.pro000066400000000000000000000110371340051421000213130ustar00rootroot00000000000000;+ ; NAME: FILE_DELETE ; ; ----------------------------------------------------------- ; AC 2018-Sept-18 ; OBSOLETE ! Since GDL 0.9.8, an internal c++ version now exists. ; ----------------------------------------------------------- ; ; RESTRICTIONS: only for Unix (Unix, Linux and Mac OS X) systems ; ; MODIFICATION HISTORY: ; - April 2009: created by Alain Coulais, request by Igor C. ; - June 2010: modified by Lea Noreskal ; ;- ; LICENCE: ; Copyright (C) 2009, Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; --------------------------------- ; pro FILE_DELETE_ONE, list_of_files, allow_nonexistent=allow_nonexistent, $ quiet=quiet, verbose=verbose , recursive=recursive, $ noexpand_path=noexpand_path command='\rm ' option='' if KEYWORD_SET(allow_nonexistent) then begin option=option+'f' endif if KEYWORD_SET(recursive) then begin option=option+'r' endif if KEYWORD_SET(verbose) then begin option=option+'v' endif if (STRLEN(option) GT 0) then begin option='-'+option endif for ii=0,N_ELEMENTS(list_of_files)-1 do begin ;; escape special char nameescp=ESCAPE_SPECIAL_CHAR(list_of_files[ii]) ;; if ~KEYWORD_SET(noexpand_path) then begin struct=FILE_INFO(list_of_files[ii]) if (struct.exists) then nameescp=escape_special_char(struct.name) endif ;; ;; empty directory emptdir='' if (FILE_TEST(nameescp , /directory) and ~KEYWORD_SET(recursive)) then begin res = FILE_SEARCH(list_of_files[ii] , '*' , COUNT=nb) if ((nb eq 0) and ~KEYWORD_SET(recursive)) then emptdir=' -r' endif ;; res = FILE_INFO(nameescp) if ((res.EXISTS eq 1) and (res.WRITE ne 0)) then begin SPAWN, command+option+emptdir+' '+nameescp, result, result_error ;; ;; /QUIET is used to suppress error message when an error happens. ;;It does not affect the logging of the action which is controlled by /VERBOSE. if KEYWORD_SET(verbose) then print,'% FILE_DELETE: Removed file: ', nameescp ;; endif else if ~KEYWORD_SET(quiet) then begin ; No error message when /QUIET if ( res.EXISTS ne 1 ) then $ if ~KEYWORD_SET(allow_nonexistent) then print, '% FILE_DELETE: No such file: ', list_of_files[ii] if (res.EXISTS eq 1 and res.WRITE eq 0) then print, '% FILE_DELETE: No right to delete: ', nameescp endif endfor end ; ; ----------------------------------------------------------- ; pro FILE_DELETE_OLD, files0, files1, files2, files3, files4, files5, files6, files7, files8, files9, $ files10, files11, files12, files13, files14, files15, files16, files17, files18, files19, $ files20, files21, files22, files23, files24, files25, files26, files27, files28, files29, $ allow_nonexistent=allow_nonexistent, noexpand_path=noexpand_path, recursive=recursive, $ quiet=quiet, verbose=verbose, test=test, help=help ; ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'pro FILE_DELETE, files0, files1, files2, files3, files4, files5, files6, files7, files8, files9, $' print, ' files10, files11, files12, files13, files14, files15, files16, files17, files18, files19, $' print, ' files20, files21, files22, files23, files24, files25, files26, files27, files28, files29, $' print, ' allow_nonexistent=allow_nonexistent, noexpand_path=noexpand_path, recursive=recursive, $' print, ' quiet=quiet, verbose=verbose, test=test, help=help' return endif ; if (STRUPCASE(!version.os_family) eq 'WINDOWS') then $ MESSAGE, "Sorry, FILE_DELETE is not available on Windows (FixMe!)" if (N_PARAMS() LT 1) then begin print, '% FILE_DELETE: Incorrect number of arguments.' return endif ; list=LIST(files0, files1, files2, files3, files4, files5, files6, files7, files8, files9, $ files10, files11, files12, files13, files14, files15, files16, files17, files18, files19, $ files20, files21, files22, files23, files24, files25, files26, files27, files28, files29) ; for __i__=0, N_PARAMS()-1 do begin CALL_PROCEDURE, 'FILE_DELETE_ONE', list[__i__], allow_nonexistent=allow_nonexistent, $ quiet=quiet, verbose=verbose, recursive=recursive, noexpand_path=noexpand_path endfor ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/obsolete/file_dirname_old.pro000066400000000000000000000067731340051421000215030ustar00rootroot00000000000000; ; Since First July 2013, because a C++ internal version is available ; this file is OBSOLETING, will be removed in the future !! ; ;+ ; NAME: FILE_DIRNAME ; ; PURPOSE: The FILE_DIRNAME function returns the dirname of a file ; path. A file path is a string containing one or more segments ; consisting of names separated by directory delimiter characters ; (slash (/) under UNIX, or backslash (\) under Microsoft ; Windows). The dirname is the final rightmost segment of the file ; path; it is usually a file, but can also be a directory name. ; ; FILE_DIRNAME is based on the standard Unix dirname(1) utility. ; ; CATEGORY: UNIX utility. ; ; CALLING SEQUENCE: Result = FILE_DIRNAME(Path [, /MARK_DIRECTORY]) ; ; INPUTS: Path: A scalar string or string array containing the dirname ; for each element of the Path argument. ; ; OPTIONAL INPUTS: none ; ; KEYWORD PARAMETERS: /MARK_DIRECTORY: Set this keyword to include a ; directory separator character at the end of the returned directory ; name string. Including the directory character allows you to ; concatenate a file name to the end of the directory name string ; without having to supply the separator character manually. This is ; convenient for cross platform programming, as the separator ; characters differ between operating systems. ; ; OUTPUTS: Result: A scalar string or string array containing the ; dirname for each element of the Path argument. ; Note: By default, the dirname does not include a final directory ; separator character; this behavior can be changed using the ; MARK_DIRECTORY keyword. ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: none ; ; RESTRICTIONS: only for Unix (Unix, Linux and Mac OS X) systems ; ; Rules used by FILE_DIRNAME ; FILE_DIRNAME makes a copy of the input path string, and then ; modifies the copy according to the following rules: ; - If Path is a NULL string, then FILE_DIRNAME returns a single ; dot (.) character, representing the current working directory of ; the IDL process. ; - If Path consists entirely of directory delimiter characters, ; the result of FILE_DIRNAME is a single directory delimiter ; character. ; - All characters to the right of the rightmost directory ; delimiter character are removed. ; - All trailing directory delimiter characters are removed. ; - If the MARK_DIRECTORY keyword is set, a single directory ; delimiter character is appended to the end. ; ; PROCEDURE: ; ; EXAMPLE: ; ; print, file_dirname('/usr/local/rsi/idl/lib/dist.pro') ; IDL prints: ; /usr/local/rsi/idl/lib ; ; MODIFICATION HISTORY: ; - Sept 2007: created by Sebastien Masson ; - Setp 2007: mananing wrong numbers of parameters, /help ; - June 2010: escape special characters by Lea Noreskal ; ;- ; LICENCE: ; Copyright (C) 2007, Sebastien Masson ; 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 2 of the License, or ; (at your option) any later version. ;- ; FUNCTION FILE_DIRNAME_OLD, Path, MARK_DIRECTORY = mark_directory, help=help on_error, 2 ; if KEYWORD_SET(help) then begin PRINT, 'FUNCTION FILE_DIRNAME, Path [, /mark_directory] [, /help]' return, -1 endif ; IF (N_PARAMS() NE 1) THEN BEGIN MESSAGE, 'Incorrect number of arguments.' ENDIF ; command = '\dirname ' + ESCAPE_SPECIAL_CHAR(Path) SPAWN, command, result ; IF KEYWORD_SET(mark_directory) THEN result = result + PATH_SEP() ; return, result ; END gdl-0.9.9/src/pro/obsolete/restore_old.pro000066400000000000000000000102101340051421000205250ustar00rootroot00000000000000;+ ; NAME: RESTORE ; ; ----------------------------------------------------------------------------- ; AC 2018-Sept-15 ; OBSOLETE ! Since GDL 0.9.8, SAVE & RESTORE are internaly managed ; Neverteless these codes can be use to test the CMSV lib. ; ----------------------------------------------------------------------------- ; ; PURPOSE: ; Serves as a wrapper around CMSAVE from Craig B. Markwardt CMVSLIB ; library. You must download and install yourself this CMVSLIB library ; then add it PATH in your GDL_PATH. This library can be found here: ; http://cow.physics.wisc.edu/~craigm/idl/cmsave.html ; ; MODIFICATION HISTORY: ; 01-Sep-2006 : written by Joel Gales ; 15-dec-2006 : by Alain Coulais (AC) ; 1/ explicite HTTP link in header to external CMVSLIB library ; 2/ test via EXECUTE() in pro to warn new users for missing ; external CMVSLIB library ; 12-feb-2007: modifications by AC: ; 1a/ managing filename. ; 1b/ default filename if no filename provided (see CMSAVE) ; 2/ add keyword /verbose ... (but bug in CMRESTORE (2 time print !)) ; 3/ warning for 3 keywords not managed yet ; 13-Nov-2012: modifications by AC: ; 1/ feature request 3581835 ; 2/ proper STRING conversion of input file name ; 3/ extra keywords /help and /test ; ; LICENCE: ; Copyright (C) 2006-2012, J. Gales and A. Coulais ; 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 2 of the License, or ; (at your option) any later version. ; ;- pro RESTORE_OLD, filename0, filename=filename1, $ RELAXED_STRUCTURE_ASSIGNMENT=RELAXED_STRUCTURE_ASSIGNMENT, $ DESCRIPTION=DESCRIPTION, RESTORED_OBJECTS=RESTORED_OBJECTS, $ help=help, verbose=verbose, test=test ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'pro RESTORE, filename0, filename=filename1' print, ' RELAXED_STRUCTURE_ASSIGNMENT=RELAXED_STRUCTURE_ASSIGNMENT, $' print, ' DESCRIPTION=DESCRIPTION, RESTORED_OBJECTS=RESTORED_OBJECTS, $' print, ' help=help, verbose=verbose, test=test' return end ; if (EXECUTE('res=CMSVLIB(/QUERY)') EQ 0) then begin MESSAGE, /CONTINUE, "Missing CMSVlib in your GDL_PATH or IDL_PATH" MESSAGE, /CONTINUE, "please read RESTORE header for help." return endif ; ; not available KEYWORDs (compatibility reasons) ; if (N_ELEMENTS(RELAXED_STRUCTURE_ASSIGNMENT) GT 0) then begin print, "% RESTORE: keyword RELAXED_STRUCTURE_ASSIGNMENT not managed" endif ; if (N_ELEMENTS(DESCRIPTION) GT 0) then begin print, "% RESTORE: keyword DESCRIPTION not managed" endif ; if (N_ELEMENTS(RESTORED_OBJECTS) GT 0) then begin print, "% RESTORE: keyword RESTORED_OBJECTS not managed" endif ; ; what is the effective filename ? ; if (N_ELEMENTS(filename0) EQ 0) AND (N_ELEMENTS(filename1) EQ 0) then begin ;; filename set by default filename = 'cmsave.sav' print, "% RESTORE: default FILENAME is used : ", filename endif else begin ;; when f0 and f1 are both provided, param f0 is used ... if (N_ELEMENTS(filename1) GT 0) then filename=filename1 if (N_ELEMENTS(filename0) GT 0) then filename=filename0 ;; ;; one and only one file at a time if (N_ELEMENTS(filename) GT 1) then begin txt = "Expression must be a scalar or 1 element array in this context: " HELP, filename, out=out mess='<'+STRTRIM(STRMID(out, STRLEN('filename')),2)+'>' MESSAGE, txt + mess endif ;; ;; Can we convert the "filename" into a true string ... res=EXECUTE('tmp_name=STRING(filename)') if (res EQ 0) then begin return endif else begin filename=tmp_name endelse ;; endelse ; ; we check whether the file is here or not ... ; if (FILE_TEST(filename) NE 1) then begin MESSAGE, "FILE not found : "+filename endif ; CMRESTORE, filename, verbose=verbose, names=_nme_, $ data=data, pass_method='struct' ; for i = 0, N_ELEMENTS(_nme_) - 1 do begin dummy = ROUTINE_NAMES(_nme_[i], data.(i), store=-1) endfor ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/src/pro/obsolete/save_old.pro000066400000000000000000000174721340051421000200210ustar00rootroot00000000000000;+ ; NAME: SAVE ; ; ----------------------------------------------------------- ; AC 2018-Sept-15 ; OBSOLETE ! Since GDL 0.9.8, SAVE & RESTORE are internaly managed ; Neverteless these codes can be use to test the CMSV lib. ; ----------------------------------------------------------- ; ; PURPOSE: ; Serves as a wrapper around CMSAVE from Craig B. Markwardt CMSVLIB ; library. You must download and install yourself this CMSVLIB library ; then add it PATH in your GDL_PATH. This library can be found here: ; http://cow.physics.wisc.edu/~craigm/idl/cmsave.html ; ; Nota Bene : CMSAVE in CMSV lib. is limited to 30 parameters (without ; using /append). We use /append to have 100 working parameters ; ; MODIFICATION HISTORY: ; 01-Sep-2006 : written by Joel Gales ; 15-dec-2006 : modifications by Alain Coulais (AC) ; 1/ explicite HTTP link in header to external CMSVLIB library ; 2/ test via EXECUTE() in pro to warn new users for missing ; external CMSVLIB library ; 3/ final test if we need to do or not since CMSAVE crash if nothing to do ; 13-feb-2007 : modifications by AC ; 1/ better management of void call to CMSAVE (case wich give a crash) ; 2/ explicit test and message if unamed variables ; 3/ explicit warning if /all keyword (not managed by CMSAVE) ; 4/ if no filename, indicate the name of the default filename ; 25-Nov-2012 : extension from "only" 30 parameters to 100 ; (this is requested by code Scanamorphos) ; ; LICENCE: ; Copyright (C) 2006, J. Gales; 2012, A. Coulais ; 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 2 of the License, or ; (at your option) any later version. ; ;- ; pro SAVE_APPEND, file=filename_def, $ p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, $ p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, $ p20, p21, p22, p23, p24, p25, p26, p27, p28, p29 ; nb_params=N_PARAMS() cmsv_max_params=30 max_params=cmsv_max_params if (nb_params LT cmsv_max_params) then max_params=nb_params ; parm = 'cmsave,' for __i__=0, max_params-1 do begin p = STRCOMPRESS('p' + STRING(__i__), /remove_all) stat = EXECUTE('arg=ROUTINE_NAMES(' + p +',arg_name=-2)') ;; we manage "arg" to reject "unmaned" variables if (STRLEN(arg) LT 1) then begin txt_mess="Expression must be named variable in this context: <" txt_mess=txt_mess+STRCOMPRESS(HELPFORM('', p,/short)+">.") ;; AC 27/02/2007: will be better to not do a /continue ;; but currently hard to escape from the ON_ERROR, 2 in GDL MESSAGE, txt_mess, /continue return endif cmd = arg + '=TEMPORARY(' + p + ')' cmd = arg + '=' + p stat = EXECUTE(cmd[0]) parm = parm + arg + ',' endfor ; parm = STRMID(parm, 0, STRLEN(parm)-1) parm = parm + ",/APPEND, filename='"+filename_def+"'" ; ; real call to the CMSAVE routine ; stat=EXECUTE(parm[0]) ; end ; ; ----------------------------------------------------------- ; pro SAVE_OLD, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, $ p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, $ p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, $ p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, $ p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, $ p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, $ p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, $ p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, $ p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, $ p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, $ filename=filename0, verbose=verbose, xdr=xdr, $ compatible=compat0, append=append, all=all, $ status=status, varstatus=colstatus, mtimes=mtimes, $ names=names, data=data, pass_method=method, $ errmsg=errmsg, quiet=quiet, nocatch=nocatch, useunit=useunit, $ test=test ; ON_ERROR, 2 ; ; is the external CMSVlib present ? if (EXECUTE('res=CMSVLIB(/QUERY)') EQ 0) then begin MESSAGE, /CONTINUE, "Missing CMSVlib in your GDL_PATH or IDL_PATH" MESSAGE, /CONTINUE, "please read SAVE header for help." return endif ; ; 2012-Nov-25: CMSAVE in CMSV lib. is limited to 30 parameters ; nb_params=N_PARAMS() cmsv_max_params=30 max_params=cmsv_max_params if (nb_params LT cmsv_max_params) then max_params=nb_params ; ; Positional Parameters parm = 'cmsave,' for __i__=0, max_params-1 do begin p = STRCOMPRESS('p' + STRING(__i__), /remove_all) stat = EXECUTE('arg=ROUTINE_NAMES(' + p +',arg_name=-1)') ;; we manage "arg" to reject "unmaned" variables if (STRLEN(arg) LT 1) then begin txt_mess="Expression must be named variable in this context: <" txt_mess=txt_mess+STRCOMPRESS(HELPFORM('', p,/short)+">.") ;; AC 27/02/2007: will be better to not do a /continue ;; but currently hard to escape from the ON_ERROR, 2 in GDL MESSAGE, txt_mess, /continue return endif cmd = arg + '=TEMPORARY(' + p + ')' cmd = arg + '=' + p stat = EXECUTE(cmd[0]) parm = parm + arg + ',' endfor ; parm = STRMID(parm, 0, STRLEN(parm)-1) ; ;AC 15/12/06: when calling without argument, CMSAVE gives a ;segmentation fault --> better way to stop ; if (STRCOMPRESS(STRUPCASE(parm),/remove_all) EQ 'CMSAVE') then begin MESSAGE, "no VAR. provided, nothing to do", /continue return endif ; ; Keywords ; ; special case for beginners: what is the default name of the filename ?! ; if (N_ELEMENTS(filename0) NE 0) then begin parm = parm + ',filename=filename0' filename_def=filename0[0] endif else begin filename_def = 'cmsave.sav' ; if future change, see inside CMSAVE print, "% SAVE: default FILENAME is used : ", filename_def endelse ; if (N_ELEMENTS(verbose) ne 0) then parm = parm + ',verbose=verbose' if (N_ELEMENTS(xdr) ne 0) then parm = parm + ',xdr=xdr' if (N_ELEMENTS(compat0) ne 0) then parm = parm + ',compatible=compat0' if (N_ELEMENTS(append) ne 0) then parm = parm + ',append=append' if (N_ELEMENTS(status) ne 0) then parm = parm + ',status=status' if (N_ELEMENTS(colstatus) ne 0) then parm = parm + ',varstatus=colstatus' if (N_ELEMENTS(mtimes) ne 0) then parm = parm + ',mtimes=mtimes' if (N_ELEMENTS(names) ne 0) then parm = parm + ',names=names' if (N_ELEMENTS(data) ne 0) then parm = parm + ',data=data' if (N_ELEMENTS(method) ne 0) then parm = parm + ',pass_method=method' if (N_ELEMENTS(errmsg) ne 0) then parm = parm + ',errmsg=errmsg' if (N_ELEMENTS(quiet) ne 0) then parm = parm + ',quiet=quiet' if (N_ELEMENTS(nocatch) ne 0) then parm = parm + ',nocatch=nocatch' if (N_ELEMENTS(useunit) ne 0) then parm = parm + ',useunit=useunit' ; ; special case: This important keyword is not working now. ; if (N_ELEMENTS(all) ne 0) then begin parm = parm + ',all=all' MESSAGE, " warning : keyword /ALL not working now", /continue endif ; ; help for debugging ... ; if KEYWORD_SET(test) then begin print, parm STOP endif ; ; real call to the CMSAVE routine ; stat=EXECUTE(parm[0]) ; ; when more than 30 parameters, we use /append ; if (nb_params GT cmsv_max_params) then begin SAVE_APPEND, file=filename_def, $ p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, $ p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, $ p50, p51, p52, p53, p54, p55, p56, p57, p58, p59 endif if (nb_params GT 2*cmsv_max_params) then begin SAVE_APPEND, file=filename_def, $ p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, $ p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, $ p80, p81, p82, p83, p84, p85, p86, p87, p88, p89 endif if (nb_params GT 3*cmsv_max_params) then begin SAVE_APPEND, file=filename_def, $ p90, p91, p92, p93, p94, p95, p96, p97, p98, p99 endif ; return end gdl-0.9.9/src/pro/obsolete/spl_init_old.pro000066400000000000000000000104311340051421000206700ustar00rootroot00000000000000;+ ; NAME: ; SPL_INIT ; ; DESCRIPTION: ; Given arrays X and Y of length N containing a tabulated function, i.e. ; Yi = f(Xi), with X1 > X2 > ... > Xn, and given values YP1 and YPN for the ; first derivative of the interpolating function at points 1 and N, ; respectively, this routine returns and array Y2 of length N which contains ; the second derivatives of the interpolating function at the tabulated ; points Xi. If YP1 and/or YPN are equal to 1.E30 or larger, the routine ; is signalled to set the corresponding boundary condition for a natural ; spline, with zero second derivative on that boundary. ; ; This routine is a replacement for the IDL intrinsic function ; to be used with GDL while this latter does not have it as an ; intrinsic. ; ; Note that the keyword DOUBLE of the IDL intrinsic function is ignored. ; Tests in single precision have shown that the routine is exactly ; similar to the IDL function. ; SPL_INTERP is also recoded similarly. ; ; SOURCE: ; Numerical Recipes, 1986. (page 88) ; ; CALLING SEQUENCE: ; y2 = SPL_INIT( x, y, YP0=yp1, YPN_1=ypn) ; ; INPUTS: ; x - independent variable vector ; y - dependent variable vector ; yp1 - first derivative at x(0) ; ypn - first derivative at x(n-1) ; ; OUTPUTS: ; y2 - second derivatives at all x, of length n ; ; HISTORY: ; -- converted to IDL, D. Neill, October, 1991 ; -- arranged as a substitution for SPL_INIT (for use in GDL) ; Ph. Prugniel, 2008/02/29 ; -- correction a bug for SIG by AC on 2009/08/27 ; -- renamed a SPL_INIT_OLD since a C++ version implemented in ; GDL, A. Coulais, 2009/08/27 ; ; ----------------------------------------------------------------------------- ; NOTE: ; Name this function: spl_init to use it as a replacement of the IDL intrinsic ; when using GDL ; But, to make a comparison of numerical results with the IDL intrinsic ; function, as it is made in the attached program: test_splf, change its ; name in "psplinf", so that IDL can execute either its intrinsic or ; the substitute. ; Anyway, this comparison has been made with success and if you just ; want to use this function in GDL ... ignore this remark ; ----------------------------------------------------------------------------- ;function PSPLINF, x, y, YP0=yp1, YPN_1=ypn, DOUBLE=double function SPL_INIT_OLD, x, y, YP0=yp1, YPN_1=ypn, DOUBLE=double, debug=debug print, 'GDL syntax, a C++ version is now available' n = N_ELEMENTS(x) ; we should use the same type as for the input y ! y2 = DBLARR(n) u = DBLARR(n) ; ; The lower boundary condition is set either to be "natural" ; if (N_ELEMENTS(yp1) EQ 0) then begin y2[0] = 0. u[0] = 0. ;; ;; or else to have a specified first derivative ;; endif else begin y2[0] = -0.5 u[0] = ( 3. / ( x[1]-x[0] ) ) * ( ( y[1]-y[0] ) / ( x[1]-x[0] ) - yp1 ) endelse ; I suppose we can also take advantage here of the TRISOL function ; from IDL... we can remove the for loops ; ; This is the decomposition loop of the tridiagonal algorithm. Y2 and ; U are used for temporary storage of the decomposed factors. ; ; AC 09/08/25 : bug which may appear with unsorted X data ... psig_old = DOUBLE((x - SHIFT(x, -1))) / (SHIFT(x, +1) - SHIFT(x, -1)) psig=psig_old for ii=1, n-2 do psig[ii]=(x[ii]-x[ii-1])/((x[ii+1]-x[ii-1])) if KEYWORD_SET(debug) then begin print, psig_old print, psig endif pu = (DOUBLE(SHIFT(y,-1) - y) / (SHIFT(x,-1) - x) - $ (y - SHIFT(y,1)) / (x - SHIFT(x,1))) / (SHIFT(x,-1)- SHIFT(x,1)) for i=1,n-2 do begin p = psig[i] * y2[i-1] + 2.0D y2[i] = ( psig[i]-1.0D ) / p u[i]=( 6.0D * pu[i] - psig[i]*u[i-1] ) / p ;;if KEYWORD_SET(debug) then print, i, psig[i], pu[i], p endfor ; ; The upper boundary condition is set either to be "natural" ; if n_elements(ypn) eq 0 then begin qn=0. un=0. ; ; or else to have a specified first deriviative ; endif else begin qn=0.5 dx=x[n-1]-x[n-2] un=(3./dx)*(ypn-(y[n-1]-y[n-2])/dx) endelse ; y2[n-1] = ( un - qn * u[n-2] ) / ( qn * y2[n-2] + 1. ) ; ; This is the backsubstitution loop of the tridiagonal algorithm ; if KEYWORD_SET(debug) then begin print, "psig:",psig print, "pu:",pu for ii=0, n-1 do print, ii, y2[ii] , u[ii] endif for k=n-2,0,-1 do begin y2[k] = y2[k] * y2[k+1] + u[k] endfor ; return, y2 end ; spl_init.pro gdl-0.9.9/src/pro/obsolete/spl_interp_old.pro000066400000000000000000000046131340051421000212330ustar00rootroot00000000000000;+ ; NAME: ; SPL_INTERP ; ; DESCRIPTION: ; Given arrays XA and YA of length N, which tabulate a function (with the ; XA's in order), and given the array Y2A, which is the output from ; SPLINE.PRO, this routine returns the cubic-spline interpolated values ; at the locations of the array X. ; ; Note that the keyword DOUBLE of the IDL intrinsic function is ignored. ; Tests in single precision have shown that the routine is exactly ; similar to the IDL function. ; SPL_INIT is also recoded similarly. ; ; SOURCE: ; Numerical Recipes, 1986. (page 89) ; ; CALLING SEQUENCE: ; y = spl_interp(xa,ya,y2a,x) ; ; INPUTS: ; xa - independent variable vector ; ya - dependent variable vector ; y2a- second derivative vector from SPLINF.PRO ; x - x value of interest ; ; OUTPUTS: ; y - cubic-spline interpolated value at x ; ; HISTORY: ; -- converted to IDL, D. Neill, October, 1991 ; -- arranged as a substitution for SPL_INTERP (for use in GDL) ; Ph. Prugniel, 2008/02/29 ; -- renamed as SPL_INTERP_OLD since a C++ version implemented in ; GDL, A. Coulais, 2009/08/27 ;- ; ----------------------------------------------------------------------------- ; NOTE: ; Name this function: spl_init to use it as a replacement of the IDL intrinsic ; when using GDL ; But, to make a comparison of numerical results with the IDL intrinsic ; function, as it is made in the attached program: test_splt, change its ; name in: ; function psplint,xa,ya,y2a,x ; name used to make comparison test with IDL ; so that IDL can execute either its intrinsic or the substitute. ; Anyway, this comparison has been made with success and if you just ; want to use this function in GDL ... ignore this remark ; ----------------------------------------------------------------------------- ;function PSPLINT, xa, ya, y2a, x, DOUBLE=double function SPL_INTERP_OLD, xa, ya, y2a, x, DOUBLE=double print, 'GDL syntax, a C++ version is now available' n = N_ELEMENTS(xa) klo = VALUE_LOCATE(xa, x) > 0L < (n-2) khi = klo + 1 ; ; KLO and KHI now bracket the input value of X ; if MIN(xa[khi]-xa[klo]) eq 0 then $ message, 'SPLINT - XA inputs must be distinct' ; ; Cubic spline polynomial is now evaluated ; h = xa[khi] - xa[klo] a = ( xa[khi] - x ) / h b = ( x - xa[klo] ) / h return, a * ya[klo] + b * ya[khi] + $ ( ( a^3 - a ) * y2a[klo] + ( b^3 - b ) * y2a[khi] ) * ( h^2 ) / 6.D end ; spl_interp.pro gdl-0.9.9/src/pro/online_help.pro000066400000000000000000000206061340051421000166760ustar00rootroot00000000000000;+ ; ; NAME: ONLINE_HELP ; ; PURPOSE: accessing the documentation, the general one or for a given ; procedure of function (intrinsic or not) ; ; CATEGORY: documentation ; ; CALLING SEQUENCE: ( ? or ONLINE_HELP ) or ( ?fft or ONLINE_HELP, 'fft') ; ; INPUTS: no mandatory ones ; ; OPTIONAL INPUTS: name of a procedure, function or code ; ; KEYWORD PARAMETERS: ; original ones: book=, context=, full_path=, title= ; extensions : nopdf=nopdf, nohtml=nohtml, nokey=nokey, browser=browser, $ ; path2pdf=path2pdf, path2key=path2key, link2html=link2htlm, $ ; test=test, debug=debug, help=help, verbose=verbose ; ; OUTPUTS: none ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: may or not succeed to start a WEB browser. ; ; RESTRICTIONS: ; ; 1/ except if a copy of the "GDL.pdf" is locally available ; and in the !path, an internet connection is mandatory ... ; ; 2/ the result is very sensitive to the version of the WEB browser ; and which plugings (and pluging versions) are available. ; ; PROCEDURE: straitforward ; ; EXAMPLE: ONLINE_HELP, 'fft', browser='midori' ; ; MODIFICATION HISTORY: ; -- 01-March-2013: creation by Alain Coulais, ; -- 18-April-2013: managing the book= keyword, with/out /full_path ; ; LICENCE: This code is under GNU GPL v2 or later. ; ; ; Very preliminary concept. the goal is to link to internal pages of ; the PDF file "gdl.pdf" (eventually downloaded if not found) ; (currently at: http://gnudatalanguage.sourceforge.net/gdl.pdf) ; and also starting online HTML doc. ; ; The PDF file is currently at: http://gnudatalanguage.sourceforge.net/gdl.pdf ; Following Adobe Documention, direct links to page, chapter shall be possible ; http://partners.adobe.com/public/developer/en/acrobat/PDFOpenParameters.pdf ; We use now only the search option ralated to Acroread viewer. ; Up to now, no equivalent functions inside alternative PDF ; readers (evince, xpdf) but is is supposed to be OK with "pdf.js" ; pluging in Firefox https://github.com/mozilla/pdf.js/issues/1875 ; ; We have to consider to have local HTML version of the documentation. ; ; It seems that recent Firefox browsers can be call passing --new-tab ; / --new-win ; ;- pro ONLINE_HELP, name, book=book, context=context, full_path=full_path, title=title, $ nopdf=nopdf, nohtml=nohtml, nokey=nokey, browser=browser, $ path2pdf=path2pdf, path2key=path2key, link2html=link2htlm, $ test=test, debug=debug, help=help, verbose=verbose ; ON_ERROR, 2 ; if ~KEYWORD_SET(test) then ON_ERROR, 2 ; if KEYWORD_SET(help) then begin print, 'pro ONLINE_HELP, name, book=book, context=context, full_path=full_path, title=title, $' print, ' nopdf=nopdf, nohtml=nohtml, nokey=nokey, browser=browser, $' print, ' path2pdf=path2pdf, path2key=path2key, link2html=link2htlm, $' print, ' test=test, debug=debug, help=help, verbose=verbose' print, '' return endif ; if N_PARAMS() EQ 0 then name='' ; if N_PARAMS() EQ 1 then name=STRCOMPRESS(name,/remove_all) ; ; do we have access to X11 ?? ; (we may consider using Lynx (tested succesfully) but is it really ; useful ?) ; status=EXECUTE('xy=GET_SCREEN_SIZE()') if (status EQ 0) then begin MESSAGE, 'Since we are unable to connect to X Windows display, no ONLINE HELP' endif ; if KEYWORD_SET(context) then begin MESSAGE, /continue, 'This option (only MSwin) is not available' endif ; ; setting a default browser if not provided ; this code was tested with konqueror, midori and firefox ; if ~KEYWORD_SET(browser) then begin ;; classical default ! browser='firefox' ;; ;; on some GNU/Linux systems, a BROWSER is defined ... default_browser=GETENV('BROWSER') if (STRLEN(default_browser) GT 0) then browser=default_browser ;; ;; on OSX, it seems to be better to use "open" but this is not ;; working over ssh -X connection ... (suggestion welcome !) ;; if (!version.os EQ 'darwin') then browser='open' endif ; ; we check if the default or selected brower is in the path ; SPAWN, 'which '+browser, ok, error ; if (STRLEN(ok) EQ 0) then begin MESSAGE, /continue, 'WEB Browser not found : '+browser MESSAGE, 'Please provide the name (+path) to the browser you want to use' endif ; space=' ' background=' &' ; if KEYWORD_SET(book) then begin ;; ;; when the document is a PDF file, we try to use a PDF viewer ;; idx_suffixe=STRPOS(book, '.', /reverse_search) ;; when the suffixe is not found we need "browser" if (idx_suffixe GE 0) then begin suffixe=STRMID(book, idx_suffixe+1) if STRLOWCASE(suffixe) EQ 'pdf' then begin ;; don't hesitate to complete this list list_of_pdf_viewers=['xpdf','evince','atril','acroread'] ;; if we don't locate a PDF viewer, we will use the default (web) Brower for ii=0, N_ELEMENTS(list_of_pdf_viewers)-1 do begin SPAWN, 'which '+list_of_pdf_viewers[ii], ok, error if (STRLEN(ok) NE 0) then begin browser=list_of_pdf_viewers[ii] break endif endfor endif endif if ~KEYWORD_SET(full_path) then begin ;;message, /continue, 'ToDo : managing !HELP_PATH' DEFSYSV, '!HELP_PATH', exist=exist if exist then begin book=FILE_WHICH(!HELP_PATH,book) if (STRLEN(book) EQ 0) then MESSAGE, 'no file found, please check !HELP_PATH and book name' endif else begin ;; falling back to standard multi-tab help MESSAGE, /continue, '!HELP_PATH not set !' endelse endif ;; we have to check whether the file exist or not !! if FILE_TEST(book) then begin command=browser+space+book+background goto, execute_command endif endif ; ; link to IDL exelis in-line documentation ; link1='' if ~KEYWORD_SET(nohtml) then begin if ~KEYWORD_SET(link2html) then link2html='http://www.exelisvis.com/docs/' suffixe='.html' ;; if STRLEN(name) GT 0 then begin link1=space+link2html+STRUPCASE(name)+suffixe endif else begin link1=space+link2html endelse endif ; ; link to PDF ; if not found in the !PATH, this file is downloaded the first time ; link2='' if ~KEYWORD_SET(nopdf) then begin path2pdf='http://gnudatalanguage.sourceforge.net/' local_pdf=FILE_WHICH(!path, 'gdl.pdf',/include_current_dir) ;; ;; if no "gdl.pdf" in the !Path, trying to download it if STRLEN(local_pdf) EQ 0 then begin script='' SPAWN, 'which wget', res if STRLEN(res) GT 0 then begin script='wget ' endif else begin SPAWN, 'which curl', res if STRLEN(res) GT 0 then script='curl -O ' endelse if (STRLEN(script) GT 0) then begin SPAWN, script+path2pdf+'gdl.pdf', ok, pb endif local_pdf=FILE_WHICH(!path, 'gdl.pdf',/include_current_dir) endif ;; if (STRLEN(local_pdf) GT 0) then begin if STRLEN(name) GT 0 then begin ;; activating the search capability inside PDF, ;; worked on Acroread pluging ;; should worked withing link2='file://'+FILE_EXPAND_PATH(local_pdf)+'#search="'+name+'"' endif else begin link2='file://'+FILE_EXPAND_PATH(local_pdf) endelse endif else begin MESSAGE, /continue, 'GDL pdf documentaion not found :(' endelse endif ; link3='' if ~KEYWORD_SET(nokey) then begin path2key='http://aramis.obspm.fr/~coulais/IDL_et_GDL/' ;; if (STRLEN(name) GT 0) then begin ;; is it a .PRO file ?? pro_file=FILE_WHICH(name+'.pro') if STRLEN(pro_file) GT 0 then begin link3='file://'+pro_file+space link3=link3+path2key+'Matrice_IDLvsGDL.html#'+STRUPCASE(STRMID(name,0,1)) endif else begin link3=path2key+'known_keywords.html#GDL_'+STRUPCASE(name) endelse endif else begin link3=path2key+'Matrice_IDLvsGDL.html' endelse endif ; ; line by line the command used by browser ; if keyword_set(verbose) then begin MESSAGE, /continue, 'link2html= : '+link2html MESSAGE, /continue, 'path2pdf = : '+path2pdf MESSAGE, /continue, 'path2key = : '+path2key endif ; command=browser+space+link1+space+link2+space+link3+background ; execute_command: ; if KEYWORD_SET(debug) then begin print, command STOP endif SPAWN, command ; if KEYWORD_SET(test) then stop ; end gdl-0.9.9/src/pro/oploterr.pro000066400000000000000000000071311340051421000162460ustar00rootroot00000000000000;+ ; NAME: oploterr ; ; PURPOSE: oplot points with (symetrical) error bars ; ; CATEGORY: plotting ; ; CALLING SEQUENCE: oploterr [,x], y, y_error,[psym] ; ; INPUTS: Y (mandatory) ; y_error (mandatory) ; ; OPTIONAL INPUTS: x (optional) ; psym (optional, default : 7) ; ; for the procedure : ; help <-- return list of keywords ; ; OUTPUTS: none ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: none ? ; ; RESTRICTIONS: - if sizes are differents, smaller size is used ; - if not enough points, no plot ; - arrays cannot be of type string ; - we convert the rrors to ABS(error) ; - take care that: ; -- if 2 vectors (in this order): Y, Yerrors ; -- if 3 vectors (in this order): X, Y, Yerrors ; ; PROCEDURE: - checks the number of input vectors ; - oplot the errors ; ; EXAMPLE: see test_oploterr.pro ; ; nbp=10 & y=REPLICATE(1.,nbp) & yerr=RANDOMN(seed,10) & x=10+findgen(10)*2. ; ; plot, y, yerr ; oploterr, y, yerr ; plot, x, y ; oploterr, x, y, yerr ; ; MODIFICATION HISTORY: ; - 24/07/2013 created by GD as an edited version of PLOTERR by AC ; ;- ; LICENCE: ; Copyright (C) 2013, Alain Coulais, Gilles Duvert ; 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 2 of the License, or ; (at your option) any later version. ;- ; pro OPLOTERR, x, y, y_error, psym, help=help ; ON_ERROR,2 ; if KEYWORD_SET(help) then begin print, 'pro OPLOTERR, [x,] y, y_error, [psym]' return endif ; ; ; only "y" and "err" are mandatory ; nb_inputs=N_PARAMS(0) ; if (nb_inputs LT 2 or nb_inputs GT 4) then begin mess='Must be called with 2-4 parameters: ' mess=mess+'[X,] Y, Y_ERR [,PSYM] ...' message, mess return endif ; ; Here, we have ONLY Y and Y_error ; if (nb_inputs EQ 2) then begin y_new=x y_err=y nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) ;; the 2 missing fields nbp_x=MIN([nbp_y, nbp_ey]) ;; we have to generate a X vector x_new=DINDGEN(nbp_x) endif ; ; We have X, Y and Y_error or Y,Yerror and psym... ; if (nb_inputs EQ 3) then begin if (n_elements(y_error) lt 2) then begin ; Y,Yerror and psym y_new=x x_new=dindgen(N_ELEMENTS(y_new)) y_err=ABS(y) nbp_x=N_ELEMENTS(x_new) nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) mypsym=y_error ; psym endif else begin x_new=x y_new=y y_err=ABS(y_error) nbp_x=N_ELEMENTS(x_new) nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) mypsym=7 endelse endif if (nb_inputs EQ 4) then begin x_new=x y_new=y y_err=ABS(y_error) nbp_x=N_ELEMENTS(x_new) nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) mypsym=psym endif ; nbp_min=MIN([nbp_x,nbp_y,nbp_ey]) if (nbp_min LT 2) then message, 'Not enough points to plot.' ; ; we limit the range for all array up to "nbp_min" ; if (nbp_x GT nbp_min) then x_new=x_new[0:nbp_min-1] if (nbp_y GT nbp_min) then y_new=y_new[0:nbp_min-1] if (nbp_ey GT nbp_min) then y_err=y_err[0:nbp_min-1] ; ; oplot the values with psym oplot,x_new,y_new,psym=mypsym ; we need 2 arrays for the top and the bottom of Errors ; y_low=y_new-y_err y_hig=y_new+y_err ; use NaN with PLOTS to go fast! null=replicate(!values.d_nan,nbp_min) x_new=reform(transpose([[x_new],[x_new],[null]]),3*nbp_min) y_new=reform(transpose([[y_low],[y_hig],[null]]),3*nbp_min) ; overplot the error bars ; plots,x_new,y_new,noclip=0 ; end ; gdl-0.9.9/src/pro/path_sep.pro000066400000000000000000000036541340051421000162110ustar00rootroot00000000000000;+ ; NAME: PATH_SEP ; ; PURPOSE: 1) Returns the character used by the OS to separate directories ; and filenames. ; 2) if keyword SEARCH_PATH is set, returns the character used by the ; OS to separate libraries, like for instance in !PATH ; 3) if keyword PARENT_DIRECTORY is set, returns the string used ; by the OS to refer to the parent directory ; ; ; CATEGORY: ; File Manipulation ; ; ; CALLING SEQUENCE: ; result=path_set([/SEARCH_PATH | /PARENT_DIRECTORY]) ; ; ; KEYWORDS: ; search_path If set, returns the library separator ; parent_directory If set, returns the parent directory ; ; ; MODIFICATION HISTORY: ; 19-Jan-2006 : written by Pierre Chanial ; 26-Jun-2009 : Alain Coulais: ; * better hierarchy in cascading if/then/else ; * correction of bug : returning pure String, not array ; (before: STRING = Array[1]; now STRING = '/') ; ; LICENCE: ; Copyright (C) 2006, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- function PATH_SEP, parent_directory=parent_directory, $ search_path=search_path, test=test ON_ERROR, 2 if KEYWORD_SET(search_path) then begin if KEYWORD_SET(parent_directory) then begin MESSAGE, /info, 'Conflicting keywords specified. Returning SEARCH_PATH.' endif array = [':', ';'] endif else begin if KEYWORD_SET(parent_directory) then begin return, '..' endif else begin array = ['/', '\'] endelse endelse OS = ['unix', 'Windows'] iOS = WHERE(OS eq !version.os_family) if iOS LT 0 then MESSAGE, 'bad detection of OS_Family' if KEYWORD_SET(test) then STOP return, (array[iOS])[0] ; force conversion end gdl-0.9.9/src/pro/ploterr.pro000066400000000000000000000227551340051421000161000ustar00rootroot00000000000000;+ ; NAME: ploterr ; ; PURPOSE: plot points with (symetrical) error bars ; ; This is a fully compatible procedure to the original one provide by ; IDL. This version contains several useful extensions (/hat, ; x_errors, _extra ...) ; ; CATEGORY: plotting ; ; CALLING SEQUENCE: ploterr [,x], y, y_error [,x_error][,psym=psym][,type=type] ; ; INPUTS: Y (mandatory) ; y_error (mandatory) ; ; OPTIONAL INPUTS: x (optional) ; x_error (optional) ; ; Inititals KEYWORD PARAMETERS (compatibles with the IDL version of PLOTERR) ; psym (default : 7) ; type (0 lin/lin, 1 log/lin, 2 lin/log 3 log/log) ; ; Extended KEYWORD PARAMETERS (specific to this version) ; for the errors bars : ; hat <-- /hat adds a small line at error bar ends ; length_of_hat <-- 1 or 2 positives values ; bar_color <-- we can plot the bars with a different color ; for the plot : ; xrange <-- explicit use of !X.range ; yrange <-- explicit use of !X.range ; xlog <-- alternative to Type Key ; ylog <-- alternative to Type Key ; _extra <-- allow to provide paramters to PLOT ; for the procedure : ; help <-- return list of keywords ; test <-- for debugging purpose ; ; OUTPUTS: none ; ; OPTIONAL OUTPUTS: none ; ; COMMON BLOCKS: none ; ; SIDE EFFECTS: none (but some PLOT variables may changed) ; ; RESTRICTIONS: - if sizes are differents, smaller size is used ; - if not enough points, no plot ; - arrays cannot be of type string ; - we convert the rrors to ABS(error) ; - take care that: ; -- if 2 vectors (in this order): Y, Yerrors ; -- if 3 vectors (in this order): X, Y, Yerrors ; -- if 4 vectors (in this order): X, Y, Yerrors, Xerrors ; ; PROCEDURE: - checks the number of input vectors ; - plot the data ; - oplot the errors ; ; EXAMPLE: see test_ploterr.pro ; ; nbp=10 & y=REPLICATE(1.,nbp) & yerr=RANDOMN(seed,10) & x=10+findgen(10)*2. ; ; ploterr, y, yerr ; ploterr, y, yerr, /hat ; ploterr, x, y, yerr ; ploterr, x, y, yerr, yerr/3., /hat ; ; MODIFICATION HISTORY: ; - 26/02/2006 : created by Alain Coulais (ARSC) ; - 10/10/2007 : REFORM() needed :( ; ;- ; LICENCE: ; Copyright (C) 2006, Alain Coulais ; 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 2 of the License, or ; (at your option) any later version. ;- ; pro PLOTERR, x, y, y_error, x_error, psym=psym, type=type, $ xrange=xrange, yrange=yrange, xlog=xlog, ylog=ylog, $ hat=hat, length_of_hat=length_of_hat, bar_color=bar_color, $ _extra=_extra, help=help, test=test ; ON_ERROR,2 ; if KEYWORD_SET(help) then begin print, 'pro PLOTERR, x, y, y_error, x_error, psym=psym, type=type, $' print, ' xrange=xrange, yrange=yrange, xlog=xlog, ylog=ylog, $' print, ' hat=hat, length_of_hat=length_of_hat, bar_color=bar_color, $' print, ' _extra=_extra, help=help, test=test' return endif ; ; we have some prefered default ; if (N_ELEMENTS(type) EQ 0) then type = 0 if (N_ELEMENTS(psym) eq 0) then psym = 7 ; ; only "y" and "err" are mandatory ; nb_inputs=N_PARAMS(0) ; if (nb_inputs LT 2) then begin mess='Must be called with 2-5 parameters: ' mess=mess+'[X,] Y, Y_ERR [,X_ERR] [,PSYM [,TYPE]] ...' message, mess return endif ; ; Here, we have ONLY Y and Y_error ; if (nb_inputs EQ 2) then begin y_new=REFORM(x) y_err=REFORM(y) nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) ;; the 2 missing fields nbp_x=MIN([nbp_y, nbp_ey]) nbp_ex=nbp_ey ;; we have to generate a X vector x_new=FINDGEN(nbp_x) endif ; ; We have X, Y and Y_error ; if (nb_inputs EQ 3) then begin x_new=REFORM(x) y_new=REFORM(y) y_err=ABS(REFORM(y_error)) nbp_x=N_ELEMENTS(x_new) nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) ;; only one missing field nbp_ex=nbp_ey endif ; ; a priori without X_error flag_x=0 ; We have the 4 info: X, Y, Y_error and X_error ; if (nb_inputs EQ 4) then begin ;; if we have X_error, we switch on the flag flag_x=1 x_new=REFORM(x) y_new=REFORM(y) y_err=ABS(REFORM(y_error)) x_err=ABS(REFORM(x_error)) nbp_x=N_ELEMENTS(x_new) nbp_y=N_ELEMENTS(y_new) nbp_ey=N_ELEMENTS(y_err) nbp_ex=N_ELEMENTS(x_err) endif ; ; If we may would like to check pre-processing ... ; if KEYWORD_SET(test) then STOP ; nbp_min=MIN([nbp_x,nbp_y,nbp_ey,nbp_ex]) if (nbp_min LT 2) then message, 'Not enough points to plot.' ; ; we limit the range for all array up to "nbp_min" ; if (nbp_x GT nbp_min) then x_new=x_new[0:nbp_min-1] if (nbp_y GT nbp_min) then y_new=y_new[0:nbp_min-1] if (nbp_ey GT nbp_min) then y_err=y_err[0:nbp_min-1] ; ; we need 2 arrays for the top and the bottom of Errors ; y_low=y_new-y_err y_hig=y_new+y_err ; use NaN with PLOTS to go fast! null=replicate(!values.d_nan,nbp_min) ; ; Eventually, we have also 2 arrays for X-errors if (flag_x EQ 1) then begin if (nbp_ex GT nbp_min) then x_err=x_err[0:nbp_min-1] x_low=x_new-x_err x_hig=x_new+x_err endif ; ; --------------------- ; managment of plot type ; if !{x|y}.type EQ 0 --> Lin ; if !{x|y}.type EQ 1 --> Log ; ; since GDL does not have the "xtype" and "ytype" keywords for PLOT ; As it was for GDL 0.8.11, we use instead xlog and ylog ! ; if (N_ELEMENTS(type) EQ 1) then begin if (type GT 0) then begin xlog = type/2 ylog = type and 1 endif endif ; ; Do we have a pre-set !y.range ? ; if (N_ELEMENTS(yrange) NE 2) then begin if (!y.range[0] EQ !y.range[1]) then begin yrange=[MIN(y_low), MAX(y_hig)] endif else begin yrange=!y.range endelse endif ; ; Do we have a pre-set !y.range ? ; if (N_ELEMENTS(xrange) NE 2) then begin if (!x.range[0] EQ !x.range[1]) then begin if (flag_x EQ 1) then begin xrange=[MIN(x_low), MAX(x_hig)] endif else begin xrange=[MIN(x_new),MAX(x_new)] endelse endif else begin xrange=!x.range endelse endif ; ; we now do the plot of the data themselves ! ; PLOT, x_new, y_new, xlog=xlog, ylog=ylog, $ xrange=xrange, yrange=yrange, psym=psym, _extra=_extra ; ; shall we switch to another color ? ; if (N_ELEMENTS(bar_color) EQ 1) then begin ref_color=!p.color !p.color=bar_color endif ; ; we overplot the error bars ; ; begin of basic PLOTERR feature (only on Y axis ...) ; speedup trick by GD - to be tested - x_new2=reform(transpose([[x_new],[x_new],[null]]),3*nbp_min) y_new2=reform(transpose([[y_low],[y_hig],[null]]),3*nbp_min) plots,x_new2,y_new2 ;for i=0,(nbp_min-1) do PLOTS,[x_new[i], x_new[i]], [y_low[i], y_hig[i]] ; ; end of basic PLOTERR feature ; begin of extra PLOTERR features ! ; if (flag_x EQ 1) then begin x_new3=reform(transpose([[x_low],[x_hig],[null]]),3*nbp_min) y_new3=reform(transpose([[y_new],[y_new],[null]]),3*nbp_min) plots,x_new3,y_new3 ; for i=0,(nbp_min-1) do PLOTS,[x_low[i], x_hig[i]], [y_new[i], y_new[i]] endif ; if KEYWORD_SET(hat) then begin ;; ;; we have to manage the length of the hat (Keyword length_of_hat) ;; we compute first a default and switch off a flag ;; x_half_def=(!X.crange[1]-!X.crange[0])/100. y_half_def=(!Y.crange[1]-!Y.crange[0])/100. ;; useful only if x_err ... flag_length_hat=0 ;; ;; the "length_of_hat" is the FULL length --> /2. ;; if (N_ELEMENTS(length_of_hat) EQ 1) then begin if (length_of_hat GT 0.) then begin flag_length_hat=1 x_half=length_of_hat/2. y_half=x_half ;; useful only if x_err ... endif endif if (N_ELEMENTS(length_of_hat) EQ 2) then begin if ((length_of_hat[0] GT 0.) AND (length_of_hat[1] GT 0.)) then begin flag_length_hat=1 x_half=length_of_hat[0]/2. y_half=length_of_hat[1]/2. ;; useful only if x_err ... endif endif ;; ;; what is the state of the flag ? ;; if (flag_length_hat EQ 0) then begin x_half=x_half_def y_half=y_half_def endif ;; ;; Now, since the length of the hat is known, we plot ;; ;; first we plot the Horizontal hats of the Vertical bars ;; x_hatlow=x_new-x_half x_hathig=x_new+x_half x_new4=reform(transpose([[x_hatlow],[x_hathig],[null],[x_hatlow],[x_hathig],[null]]),6*nbp_min) y_new4=reform(transpose([[y_low],[y_low],[null],[y_hig],[y_hig],[null]]),6*nbp_min) plots,x_new4,y_new4 ; for i=0,(nbp_min-1) do begin ; PLOTS,[x_hatlow[i], x_hathig[i]], [y_low[i], y_low[i]] ; PLOTS,[x_hatlow[i], x_hathig[i]], [y_hig[i], y_hig[i]] ; endfor ;; ;; second we plot the Vertical hats of the Horizontal bars ;; if (flag_x EQ 1) then begin y_hatlow=y_new-y_half y_hathig=y_new+y_half y_new5=reform(transpose([[y_hatlow],[y_hathig],[null],[y_hatlow],[y_hathig],[null]]),6*nbp_min) x_new5=reform(transpose([[x_low],[x_low],[null],[x_hig],[x_hig],[null]]),6*nbp_min) plots,x_new5,y_new5 ; for i=0,(nbp_min-1) do begin ; PLOTS,[x_low[i], x_low[i]], [y_hatlow[i], y_hathig[i]] ; PLOTS,[x_hig[i], x_hig[i]], [y_hatlow[i], y_hathig[i]] ; endfor endif endif ; if (N_ELEMENTS(bar_color) EQ 1) then !p.color=ref_color ; if KEYWORD_SET(test) then STOP ; end ; gdl-0.9.9/src/pro/poly.pro000066400000000000000000000022701340051421000153620ustar00rootroot00000000000000;$Id: poly.pro,v 1.2 2010-01-20 11:41:59 slayoo Exp $ ;+ ; ; ; ; NAME: POLY ; ; ; PURPOSE: Calculates the polynomial of X where with coefficients C ; and order n_elements(c)-1 ; ; ; ; CATEGORY: Algebra/ mathematics ; ; ; CALLING SEQUENCE: result= POLY(x,c) ; ; ; OUTPUTS: result : c[0] + c[1]*x + c[2]*x^2 + .... ; ; RESTRICTIONS: X and C should be numbers ; ; PROCEDURE: Starting from the highest order (N=n_max) exponent loop ; to the lowest (N=1) adding x[N] and multipying by c[N] ; ; ; EXAMPLE: x=[1,2,3] ; c=[1,1,2] ; print, poly(x,c) ; 4 11 22 ; ; ; MODIFICATION HISTORY: ; Written by: Christopher Lee 2005-07-08 ; ; ; ;- ; LICENCE: ; Copyright (C) 2004, ; 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 2 of the License, or ; (at your option) any later version. ; ; ;- function poly, x,c on_error, 2 IF (N_PARAMS() NE 2) THEN BEGIN message, 'Incorrect number of arguments.' ENDIF nc=n_elements(c) p=x*0. for i=nc-1,1L,-1 do p=(p+c[i])*x p=p+c[0] return, p end gdl-0.9.9/src/pro/poly_area.pro000066400000000000000000000023021340051421000163460ustar00rootroot00000000000000; NAME: POLY_AREA ; ; ; PURPOSE: Calculates the area of the polygon defined by the ; vectors x and y ; ; ; CATEGORY: Algebra/ mathematics ; ; ; CALLING SEQUENCE: result = POLY_AREA(X, Y[, /DOUBLE] [, /SIGNED]) ; ; ; OUTPUTS: result : area of polygon defined by X and Y ; ; PROCEDURE: ; ; EXAMPLE: x = [1, 0, -1, 0] ; y = [0, 1, 0, -1] ; print, poly_area(x, y) ; 2.00000 ; ; MODIFICATION HISTORY: ; Written by: John Serafin 2009-12-21 ; ;- ; LICENCE: ; Copyright (C) 2009, ; 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 2 of the License, or ; (at your option) any later version. ; ; function poly_area, x, y, double=double, signed=signed on_error, 2 IF (N_PARAMS() NE 2) THEN BEGIN message, 'Incorrect number of arguments.' ENDIF if keyword_set(double) then begin xs = double(shift(x, -1)) ys = double(shift(y, -1)) endif else begin xs = shift(x, -1) ys = shift(y, -1) endelse area = total(x*ys - xs*y)/2 if not keyword_set(signed) then area = abs(area) return, area end gdl-0.9.9/src/pro/polyfillv.pro000066400000000000000000000053351340051421000164240ustar00rootroot00000000000000FUNCTION polyfillv,x,y,sx,sy,runlength=run_length ;+ ; ; NAME: polyfillv ; ; MODIFICATION HISTORY: ; Written by: Reto Stockli ; ;- ; LICENCE: ; Copyright (C) 2004, 2011 ; 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 2 of the License, or ; (at your option) any later version. ; ;- ;; reprogrammed after ;; http://alienryderflex.com/polygon_fill/ ;; public-domain code by Darel Rex Finley, 2007 ;; by ;; the implementation differs slightly from the IDL one ;; determine size of polygon polycorners = n_elements(x) ;; check arguments IF polycorners LT 3 THEN BEGIN print,"POLYFILLV: Not enough valid and unique points specified." stop ENDIF IF polycorners NE n_elements(y) THEN BEGIN print,"POLYFILLV: X and Y vectors not same size" stop ENDIF IF (sx LE 0L) OR (sy LE 0L) THEN BEGIN print,"POLYFILLV: Array dimensions must be greater than 0." stop ENDIF IF keyword_set(run_length) THEN BEGIN print,"The Keyword Run_Length is not yet implemented." stop ENDIF ;; initialize output array idx = -1L fx = float(x) fy = float(y) ;; Loop through the rows of the image. FOR py=0L,sy-1L DO BEGIN fpy = float(py) n = 0L first = 1B nodex = 0.0 j = polycorners-1L FOR i=0L,polycorners-1L DO BEGIN IF ((fy[i] LE fpy) AND (fy[j] GT fpy)) OR $ ((fy[j] LE fpy) AND (fy[i] GT fpy)) THEN BEGIN fpx = fx[i] + (fpy-fy[i])/(fy[j]-fy[i])*(fx[j]-fx[i]) px = fix(fpx) ;; print,i,px,py,x[i],y[i],x[j],y[j],fpx IF first THEN BEGIN nodex = px first = 0B ENDIF ELSE BEGIN nodex = [nodex,px] ENDELSE n += 1L ENDIF j=i ENDFOR ;; print,"Line: ",py," Nodes: ",n nodes = n_elements(nodex) IF nodes GE 2L THEN BEGIN ;; Sort the nodes nodex = nodex[sort(nodex)] ;; Fill the pixels between node pairs. FOR i=0L,nodes-1L,2 DO BEGIN IF (nodex[i+1] GE 0) THEN BEGIN IF (nodex[i] LT 0) THEN nodex[i] = 0 ;; reset to left edge of raster IF (nodex[i+1] GT sx) THEN nodex[i+1] = sx ;; reset to right edge of raster numx=nodex[i+1] - nodex[i] IF numx GT 0L THEN BEGIN valx=(lindgen(numx) + nodex[i]) + py * sx IF idx[0] EQ -1L THEN idx = valx ELSE idx = [idx,valx] ENDIF ENDIF ENDFOR ENDIF ENDFOR RETURN,idx END gdl-0.9.9/src/pro/polywarp.pro000066400000000000000000000055261340051421000162630ustar00rootroot00000000000000; ; ; ; NAME: POLYWARP ; ; ; PURPOSE: Performs polynomial spatial warping with given points. ; ; ; CATEGORY: Image Processing/ mathematics ; ; ; CALLING SEQUENCE: polywarp, Xi, Yi, Xo, Yo, Degree, Kx, Ky [, /DOUBLE] [, STATUS=variable] ; ; ; OUTPUTS: Estimated coefficients Kx[i,j] and Ky[i,j] of the polynomial functions ; Xi = Sum[i,j](Kx[i,j] * Xo^j * Yo^i) ; Yi = Sum[i,j](Ky[i,j] * Xo^j * Yo^i) ; ; ; RESTRICTIONS: Xi, Yi, Xo, and Yo should be number array with the same lengths. ; The number of Xi and Yi should be greater or equal than (degree+1)^2. ; ; ; PROCEDURE: Estimates Kx[i,j] and Ky[i,j] using least eqares estimation. ; ; ; EXAMPLE: Xi = [33, 53, 53, 56] ; Yi = [34, 12, 123, 125] ; Xo = [75, 21, 82, 67] ; Yo = [89, 37, 89, 17] ; POLYWARP, Xi, Yi, Xo, Yo, 1, Kx, Ky ; print, Kx ; 227.312 -4.59099 ; -2.39530 0.0590162 ; print, Ky ; 628.383 -17.3927 ; -6.83405 0.219644 ; ; ; MODIFICATION HISTORY: ; Written by: Jeongbin Park, 2015-Apr-05 ; ; ;- ; LICENCE: ; Copyright (C) 2015, Jeongbin Park ; 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 2 of the License, or ; (at your option) any later version. ; ;- pro polywarp, Xi, Yi, Xo, Yo, Degree, Kx, Ky, DOUBLE=isdouble, STATUS=status on_error, 2 IF (N_PARAMS() LT 5) THEN BEGIN message, 'Incorrect number of arguments.' ENDIF n = n_elements(Xi) IF ((n NE n_elements(Yi)) OR (n NE n_elements(Xo)) OR (n NE n_elements(Yo))) THEN BEGIN message, 'Inconsistent number of elements.' ENDIF k = (Degree+1)^2 IF (n LT k) THEN BEGIN message, '# of points must be ge (degree+1)^2.' ENDIF _X = DBLARR(n, k, /NOZERO) _Xi = DOUBLE(Xi) _Yi = DOUBLE(Yi) _Xo = DOUBLE(Xo) _Yo = DOUBLE(Yo) FOR i = 0, n-1 do begin FOR jj = 0, Degree do begin FOR ii = 0, Degree do begin _X[i, jj*(Degree+1)+ii] = _Xo[i]^jj*_Yo[i]^ii ENDFOR ENDFOR ENDFOR _trX = TRANSPOSE(_X) _Sol = INVERT(_trX#_X, STATUS, /DOUBLE)#_trX CASE STATUS OF 1: MESSAGE, "Singular matrix detected.", /INFORMATIONAL 2: MESSAGE, "Warning: Invert detected a small pivot element.", /INFORMATIONAL ELSE: ENDCASE IF (keyword_set(DOUBLE) OR (SIZE(Xi, /TN) EQ "DOUBLE") OR (SIZE(Yi, /TN) EQ "DOUBLE") OR $ (SIZE(Xo, /TN) EQ "DOUBLE") OR (SIZE(Yo, /TN) EQ "DOUBLE")) THEN BEGIN kX = DOUBLE(_Sol#_Xi) kY = DOUBLE(_Sol#_Yi) ENDIF ELSE BEGIN kX = FLOAT(_Sol#_Xi) kY = FLOAT(_Sol#_Yi) ENDELSE kX = REFORM(kX, Degree+1, Degree+1, /OVERWRITE) kY = REFORM(kY, Degree+1, Degree+1, /OVERWRITE) end gdl-0.9.9/src/pro/popd.pro000066400000000000000000000017221340051421000153420ustar00rootroot00000000000000;+ ; NAME: POPD ; ; PURPOSE: ; Change the current working directory to the top entry of the ; directory stack handled by PUSHD and POPD and remove it from the stack. ; ; ; CATEGORY: ; Directory management ; ; ; CALLING SEQUENCE: ; popd ; ; ; MODIFICATION HISTORY: ; 12-Jan-2006 : written by Pierre Chanial ; ; LICENCE: ; Copyright (C) 2006, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- pro popd common dir_stack, nstack, stack on_error, 2 if n_elements(nstack) eq 0 then nstack = (stack = 0) if nstack eq 0 then begin message, 'Directory stack is empty.' endif cd, stack[0] if --nstack eq 0 then begin stack = 0 endif else begin stack = stack[1:*] endelse end gdl-0.9.9/src/pro/primes.pro000066400000000000000000000026071340051421000157020ustar00rootroot00000000000000;+ ; NAME: PRIMES ; ; PURPOSE: ; Returns an array with the requested number of prime numbers starting ; from 2. ; ; ; CATEGORY: ; arithmetic ; ; ; CALLING SEQUENCE: ; p = primes(n) ; ; ; INPUTS: ; n Number of requested prime numbers ; ; OUTPUTS: ; p Array of the n first prime numbers starting from 2 ; ; ; MODIFICATION HISTORY: ; 12-Jan-2006 : written by Pierre Chanial ; ; LICENCE: ; Copyright (C) 2006, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- function primes, n on_error, 2 if n eq 1 then return, [2l] primes = lonarr(n) primes[0] = [2, 3] candidate = 5l ; number of prime numbers already calculated nprimes = 2l while nprimes lt n do begin for iprimes=1l, nprimes do begin ; upper limit is never reached prime = primes[iprimes] if candidate mod prime eq 0 then break ; it is not a prime number if prime*prime gt candidate then begin ; it is a prime number primes[nprimes++] = candidate break endif endfor candidate += 2l ; get next candidate endwhile return, primes end gdl-0.9.9/src/pro/printd.pro000066400000000000000000000017031340051421000156770ustar00rootroot00000000000000;+ ; NAME: PRINTD ; ; PURPOSE: ; Print the content of the directory stack handled by PUSHD and POPD. ; ; ; CATEGORY: ; Directory management ; ; ; CALLING SEQUENCE: ; printd ; ; ; MODIFICATION HISTORY: ; 12-Jan-2006 : written by Pierre Chanial ; ; LICENCE: ; Copyright (C) 2006, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- pro printd common dir_stack, nstack, stack on_error, 2 if n_elements(nstack) eq 0 then nstack = (stack = 0) if nstack eq 0 then message, 'Directory stack is empty.' cd, curr=curr print, 'Current Directory: ', curr print, 'Directory Stack Contents:' for i=0l, nstack-1 do begin print, format=('(i3,") ",a)'), i, stack[i] endfor end gdl-0.9.9/src/pro/pushd.pro000066400000000000000000000021071340051421000155210ustar00rootroot00000000000000;+ ; NAME: PUSHD ; ; PURPOSE: ; Store the current working directory on top of the directory stack ; handled by PUSHD and POPD and change the current working directory to ; a user supplied directory. ; ; ; CATEGORY: ; Directory management ; ; ; CALLING SEQUENCE: ; pushd, directory ; ; ; INPUTS: ; directory Scalar string of the requested working directory ; ; ; MODIFICATION HISTORY: ; 12-Jan-2006 : written by Pierre Chanial ; ; LICENCE: ; Copyright (C) 2006, P. Chanial ; 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 2 of the License, or ; (at your option) any later version. ; ;- pro pushd, directory common dir_stack, nstack, stack on_error, 2 if n_elements(nstack) eq 0 then nstack = (stack = 0) cd, directory, current=current if not keyword_set(nstack++) then begin stack = [current] endif else begin stack = [current, stack] endelse end gdl-0.9.9/src/pro/py_plot.pro000066400000000000000000000010741340051421000160660ustar00rootroot00000000000000;; simple example file for using python's matplotlib package from GDL pro PY_PLOT,x,y,XLABEL=xlabel,YLABEL=ylabel,TITLE=title,GRID=grid on_error, 2 if N_ELEMENTS( xlabel) eq 1 then begin PYTHON,"matplotlib.matlab","xlabel",STRING(xlabel) endif if N_ELEMENTS( ylabel) eq 1 then begin PYTHON,"matplotlib.matlab","ylabel",STRING(ylabel) endif if N_ELEMENTS( title) eq 1 then begin PYTHON,"matplotlib.matlab","title",STRING(title) endif if KEYWORD_SET( grid) then begin PYTHON,"matplotlib.matlab","grid",1 endif PYTHON,"python_plot","py_plot",x,y end gdl-0.9.9/src/pro/py_print.pro000066400000000000000000000001101340051421000162320ustar00rootroot00000000000000pro py_print,a on_error, 2 PYTHON,"python_print","py_print",a end gdl-0.9.9/src/pro/query_bmp.pro000066400000000000000000000006301340051421000164000ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_BMP, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, 'BMP', info=info) ; end gdl-0.9.9/src/pro/query_dicom.pro000066400000000000000000000006321340051421000167170ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_DICOM, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, 'DCM', info=info) ; end gdl-0.9.9/src/pro/query_gif.pro000066400000000000000000000006301340051421000163670ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_GIF, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, 'GIF', info=info) ; end gdl-0.9.9/src/pro/query_image.pro000066400000000000000000000006641340051421000167130ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_IMAGE, filename, info, _ref_extra=ex ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, info=info, _strict_extra=ex) ; end gdl-0.9.9/src/pro/query_jpeg.pro000066400000000000000000000006341340051421000165530ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_JPEG, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, 'JPEG', info=info) ; end gdl-0.9.9/src/pro/query_pict.pro000066400000000000000000000006331340051421000165640ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_PICT, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, 'PICT', info=info) ; end gdl-0.9.9/src/pro/query_png.pro000066400000000000000000000006301340051421000164060ustar00rootroot00000000000000; ; by Sylwester Arabas ; function QUERY_PNG, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; return, MAGICK_PING(filename, 'PNG', info=info) ; end gdl-0.9.9/src/pro/query_ppm.pro000066400000000000000000000006571340051421000164270ustar00rootroot00000000000000; ; by Sylwester Arabas function QUERY_PPM, filename, info ; ON_ERROR, 2 ; ; Do we have access to ImageMagick functionnalities ?? ; if (MAGICK_EXISTS() EQ 0) then begin MESSAGE, /continue, "GDL was compiled without ImageMagick support." MESSAGE, "You must have ImageMagick support to use this functionaly." endif ; ; TODO: MAXVAL keyword ; return, MAGICK_PING(filename, 'PNM', info=info) ; end gdl-0.9.9/src/pro/query_tiff.pro000066400000000000000000000014001340051421000165460ustar00rootroot00000000000000; ; by Sylwester Arabas ; libtiff version by Remi A. Solås ; function QUERY_TIFF, filename, info, geotiff=geotiff, image_index=image_index ON_ERROR, 2 if TIFF_EXISTS() eq 0 then begin MESSAGE, /informational, "GDL was compiled without libtiff." if MAGICK_EXISTS() eq 0 then begin MESSAGE, /continue, "GDL was compiled without ImageMagick." MESSAGE, "Either libtiff or ImageMagick is required to use QUERY_TIFF." endif MESSAGE, /informational, "ImageMagick enabled as fallback with limited TIFF support." return, MAGICK_PING(filename, 'TIFF', info=info, image_index=image_index) endif return, TIFF_QUERY(filename, info=info, geotiff=geotiff, image_index=image_index) end gdl-0.9.9/src/pro/read_ascii.pro000066400000000000000000000340231340051421000164630ustar00rootroot00000000000000;+ ; NAME: READ_ASCII ; ; ; PURPOSE: Reads an ASCII file. The output is a structure whose tags contains ; columns (1D array) from the file. Its use is flexible: the user can ; specify the types, and tag names of the fields and he/she also can ; group columns into a single tag (2D array). ; ; ; CATEGORY: IO ; ; ; CALLING SEQUENCE: ; structure=read_ascii(filename, count=, data_start=, delimiter=, ; missing_value=, comment_symbol=, record_start= ; num_records=, template=, header=, verbose=) ; ; ; INPUT: ; filename Name of the ASCII file to be read ; ; ; KEYED INPUTS: ; data_start Specify the number of lines that constitute the header ; These lines will be discarded as records, but are available ; with the header keyword ; ; delimiter If set (or non equal to ''), the records will be split ; according to the supplied delimiter locations and the length ; of the fields is not necessarily the same for all records. ; Otherwise, template.fieldlocations will be used to identify ; the fields (columns). If the template is not provided, the ; delimiter default is ' ' ; ; missing_value Specify the value that will be used for missing or ; non-numeric values ; ; comment_symbol Comment symbol. The part of the line that begins with ; the comment symbol and ends to the end of line is discarded ; Default is ';' ; ; record_start Record number of the first record to be read (starts from 0) ; ; num_record Number of records to be read ; ; template structure that defines how the file will be processed ; the tags datastart, delimiter, missingvalue and commentsymbol ; can be overridden by the keywords data_start, delimiter, ; missing_value and comment_symbol. ; ; template.VERSION template version number (not used) ; template.FIELDCOUNT=n number of fields ; template.FIELDNAMES[n] field names ; template.FIELDTYPES[n] field integer types ; template.FIELDGROUPS[n] group ID. fields can be grouped into a single tag ; template.FIELDLOCATIONS[n] start positions of the fields ; template.DATASTART see data_start keyed input ; template.DELIMITER see delimiter keyed input ; template.MISSINGVALUE see missing_value keyed input ; template.COMMENTSYMBOL see comment_symbol keyed input ; ; if field of different types are grouped together, the following priority ; if assumed to determine the tag type: ; BYTE
>', /continue nb_pbs=nb_pbs+1 endif if ARRAY_EQUAL(pos,[2,12]) eq 0 then begin if KEYWORD_SET(verbose) then MESSAGE, 'error str7 pos <>', /continue nb_pbs=nb_pbs+1 endif ; pos=STRSPLIT(str7,'a',length=length,/preserve) exp_pos=LONG([INDGEN(3), INDGEN(9)+4,INDGEN(10)+14]) exp_len=LONARR(STRLEN(str7)-1) exp_len[2]=1 exp_len[2+9]=1 ; if ARRAY_EQUAL(pos,exp_pos) eq 0 then begin if KEYWORD_SET(verbose) then MESSAGE, 'error str7 pos <> /preserve', /continue nb_pbs=nb_pbs+1 endif if ARRAY_EQUAL(length,exp_len) eq 0 then begin if KEYWORD_SET(verbose) then MESSAGE, 'error str7 length <> /preserve', /continue nb_pbs=nb_pbs+1 endif ; ; tests on str5 ; tab=STRSPLIT(str5,/preserve) res=LONG([0,1,3,5,7,9]) if (ARRAY_EQUAL(tab,res, /NO_TYPECONV) eq 0) then begin if KEYWORD_SET(verbose) then MESSAGE, 'error str5 preserve_null', /continue nb_pbs=nb_pbs+1 endif ext=STRSPLIT(str5,/preserve,/extract) if((N_ELEMENTS(ext) ne 6)) then begin if KEYWORD_SET(verbose) then MESSAGE, 'error str5 extract , preserve', /continue nb_pbs=nb_pbs+1 endif ; ; bug found via STR_SEP 3286746 in the Patch section ; tab=STR_SEP('ahasadfasdf','dfa') res=['ahasa','sdf'] if (ARRAY_EQUAL(tab,res, /NO_TYPECONV) eq 0) then begin if KEYWORD_SET(verbose) then MESSAGE, 'error STR_SEP 3286746', /continue nb_pbs=nb_pbs+1 endif tab=STR_SEP('ahasadfasdfa','dfa') res=['ahasa','s',''] if (ARRAY_EQUAL(tab,res, /NO_TYPECONV) eq 0) then begin if KEYWORD_SET(verbose) then MESSAGE, 'error STR_SEP 3286746, /preserve_null', /continue nb_pbs=nb_pbs+1 endif ; ; we must return a STRARR except for '' ; tab=STRSPLIT('eeee','e',/extract) if (SIZE(tab, /n_dim) NE 0) then begin if KEYWORD_SET(verbose) then MESSAGE, 'bad size for void string', /continue nb_pbs=nb_pbs+1 endif tab=STRSPLIT('eeABCee','e',/extract) if (SIZE(tab, /n_dim) NE 1) then begin if KEYWORD_SET(verbose) then MESSAGE, 'bad size for 1D STRARR', /continue nb_pbs=nb_pbs+1 endif if (tab NE 'ABC') then begin if KEYWORD_SET(verbose) then MESSAGE, 'bad value in STRARR', /continue nb_pbs=nb_pbs+1 endif tab=STRSPLIT('eeABCeeABCee','e',/extract) if (SIZE(tab, /n_dim) NE 1) then begin if KEYWORD_SET(verbose) then MESSAGE, 'bad size for 2 elements STRARR', /continue nb_pbs=nb_pbs+1 endif ;textoidl uses strstrans which uses strsplit vide='' if (EXECUTE('res=TEXTOIDL(vide)') EQ 0) then begin MESSAGE, /CONTINUE, "Missing TexToIDL in your GDL_PATH or IDL_PATH" endif else begin res='!7l!X!U2!N' tab=TEXTOIDL('\mu^2') if (res NE tab) then begin if KEYWORD_SET(verbose) then MESSAGE, 'error when using TexToIDL', /continue nb_pbs=nb_pbs+1 endif endelse ;new version: supports arrays: res=strsplit(strarray,COUNT=c, LENGTH=l) ; line="=======================================" MESSAGE, /Continue, line MESSAGE, /Continue, " " mess=' errors encoutered during STRSPLIT tests' if (nb_pbs GT 0) then mess=STRING(nb_pbs)+mess else mess='NO'+mess MESSAGE, /Continue, mess MESSAGE, /Continue, " " MESSAGE, /Continue, line ; ; if /debug OR /test nodes, we don't want to exit if (nb_pbs GT 0) then begin if ~(KEYWORD_SET(debug) or KEYWORD_SET(test) or KEYWORD_SET(no_exit)) then EXIT, status=1 endif ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_structures.pro000066400000000000000000000052461340051421000203310ustar00rootroot00000000000000; ; AC 28/01/2013: I found no equivalent tests in the testsuite ! ; ; bug reported by Gilles on Jan. 23, 2013 ; http://sourceforge.net/tracker/?func=detail&aid=3601949&group_id=97659&atid=618683 ; ; Modifications history : ; - 2017-12-14 : AC. updating final message, ; creating a related test for SIZE (test_size.pro) ; - 2018-01-31 : AC. change of test 0a ; pro TEST_STRUCTURES, no_exit=no_exit, verbose=verbose, $ help=help, test=test, debug=debug ; if KEYWORD_SET(help) then begin print, 'pro TEST_STRUCTURES, no_exit=no_exit, verbose=verbose, $' print, ' help=help, test=test, debug=debug, $' return endif ; nb_errors=0 ; ; the structure we create has a name: "TEST" ; structarray=REPLICATE({test, value:0.0},10) ;populate values: structarray.value=FINDGEN(10) ; HELP, structarray.value ; ; basic tests using SIZE() & co. ; ; this test was change by Alain C., 2018-01-31 because ; different result than in IDL 8.2 & 8.4. ; C code of "typename" also changed if (TYPENAME(structarray) NE "STRUCT") then begin message,/continue, '(0a) unexpected results in TYPENAME() !' nb_errors=nb_errors+1 endif ; if (SIZE(structarray,/sname) NE "TEST") then begin message,/continue, '(0b) unexpected results in SIZE(... ,/sname) !' nb_errors=nb_errors+1 endif if (SIZE(structarray,/tname) NE "STRUCT") then begin message,/continue, '(0c) unexpected results in SIZE(... ,/tname) !' nb_errors=nb_errors+1 endif if (SIZE(structarray,/type) NE 8) then begin message,/continue, '(0d) unexpected results in SIZE(... ,/type) !' nb_errors=nb_errors+1 endif if ~ARRAY_EQUAL(SIZE(structarray), [1L,10,8,10]) then begin message,/continue, '(0e) unexpected results in SIZE() !' nb_errors=nb_errors+1 endif ; ;get subset: www=WHERE(structarray.value gt 6) HELP, www ; if (ARRAY_EQUAL(www, [7,8,9]) NE 1) then begin message,/continue, '(1) unexpected results in <> values !' nb_errors=nb_errors+1 endif ; res1=EXECUTE('HELP, structarray[www].value') if (res1 NE 1) then begin message,/continue, ' unexpected badly interpreted Struct indexing ! (case 1)' nb_errors=nb_errors+1 endif ; tab=0. res2=EXECUTE('tab=structarray[www].value') if (res2 NE 1) then begin message,/continue, ' unexpected badly interpreted Struct indexing ! (case 2)' nb_errors=nb_errors+1 endif ; if (ARRAY_EQUAL(tab, 1.*[7,8,9]) NE 1) then begin message,/continue, '(2) unexpected results in extracted values !' nb_errors=nb_errors+1 endif ; ; ----------------- final message ---------- ; BANNER_FOR_TESTSUITE, 'TEST_STRUCTURES', nb_errors ; if (nb_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_suite.pro000066400000000000000000000630131340051421000172330ustar00rootroot00000000000000;; test some language elements of GDL pro if_test if 1 then $ if 0 then begin & end $ else if 1 then $ if 0 then begin & end $ else a=1e if a ne 1e then begin message, '***IF: ERROR', /conti exit, status=1 endif print, 'IF: OK' end pro switch_test a='abc' ;; empty switch a of 1: complex(1): begin & end 'def': 'abc': 1.0: begin & end else: endswitch switch a of 1: begin message, '***SWITCH: ERROR', /conti exit, status=1 end complex(1): begin message, '***SWITCH: ERROR', /conti exit, status=1 end 'def': begin message, '***SWITCH: ERROR', /conti exit, status=1 end 'abc': begin abc = 1 end 1.0: fall = abc+1 else: e=1 endswitch if abc ne 1 then begin message, '***SWITCH: ERROR', /conti exit, status=1 endif if fall ne abc+1 then begin message, '***SWITCH: ERROR', /conti exit, status=1 endif if e ne 1 then begin message, '***SWITCH: ERROR', /conti exit, status=1 endif switch 1 of 0: begin message, "***SWITCH: ERROR", /conti exit, status=1 end 0: begin message, "***SWITCH: ERROR", /conti exit, status=1 end 1: endswitch print,'SWITCH: OK' end pro case_test a='abc' case a of 1: begin message, '***CASE: ERROR', /conti exit, status=1 end complex(1): begin message, '***CASE: ERROR', /conti exit, status=1 end 'def': begin message, '***CASE: ERROR', /conti exit, status=1 end 'abc': begin c=1 end 1.0: begin message, '***CASE: ERROR', /conti exit, status=1 end else: begin message, '***CASE: ERROR', /conti exit, status=1 end endcase if c ne 1 then begin message, '***CASE: ERROR', /conti exit, status=1 endif case a of 1: begin message, '***CASE: ERROR', /conti exit, status=1 end complex(1): begin message, '***CASE: ERROR', /conti exit, status=1 end 'def': begin message, '***CASE: ERROR', /conti exit, status=1 end 'a': begin message, '***CASE: ERROR', /conti exit, status=1 end 1.0d: begin message, '***CASE: ERROR', /conti exit, status=1 end else: e=1 end if e ne 1 then begin message, '***CASE: ERROR', /conti exit, status=1 endif case 1 of 0: begin message, "***CASE: ERROR", /conti exit, status=1 end 0: begin message, "***CASE: ERROR", /conti exit, status=1 end 1: endcase print, 'CASE: OK' end pro while_test i=0 while i lt 100 do begin i=i+1 endwhile if i eq 100 then print,'WHILE: OK' else begin message, '***WHILE: ERROR', /conti exit, status=1 endelse end pro for_test c=0 for i=0,99 do c=c+1 if c ne 100 then begin message, '***FOR: ERROR', /conti exit, status=1 endif c=0 for i=0,990,10 do c=c+1 if c ne 100 then begin message, '***FOR: Step: ERROR', /conti exit, status=1 endif a=0 for i=0, 0 do begin for j=0, 1 do begin if i eq 0 then continue endfor a = 1 endfor if a eq 0 then begin message, '***FOR: CONTINUE: ERROR', /conti exit, status=1 endif print, 'FOR: OK' end pro repeat_test i=0 repeat begin i=i+1 endrep until (i eq 100) repeat begin endrep until (i eq 100) repeat begin endrep until 1 if i eq 100 then print,'REPEAT: OK' else begin message, '***REPEAT: ERROR', /conti exit, status=1 endelse end pro goto_test ;; simple goto,jump11 message, '***GOTO: Error', /conti exit, status=1 jump21: goto,jump31 message, '***GOTO: Error', /conti exit, status=1 jump11: goto,jump21 message, '***GOTO: Error', /conti exit, status=1 jump31: count=0 ;; within loop for i=0,10 do begin goto,jump1 message, '***GOTO: Error1', /conti exit, status=1 jump2: goto,jump3 message, '***GOTO: Error2', /conti exit, status=1 jump1: goto,jump2 message, '***GOTO: Error3', /conti exit, status=1 jump3: goto,jump4 ; even to jump out of the block and in again is ok jump5: if 0 then goto,jump5 else goto,jump7 message, '***GOTO: Error4', /conti exit, status=1 jump7: if 1 then begin goto,jump8 message, '***GOTO: Error5', /conti exit, status=1 jump8: endif else begin message, '***GOTO: Error6', /conti exit, status=1 endelse count=count+1 endfor goto,jump6 jump4: goto,jump5 jump6: if count ne 11 then begin message, '***GOTO: ERROR7', /conti exit, status=1 endif IF (1)then begin IF (1)then begin ;print,"Going to Label1" goto, Label1 end else begin message, '***GOTO: ERROR8', /conti exit, status=1 end Label1: end print,'GOTO: OK' end function REF_PAR_RET,x return,(1?x:1) end pro ref_par_called,x,y,target if x ne target or y ne target then print,"REF_PAR: error 4" x=537 y=537 end pro REF_PAR_TEST p = ptr_new(10) a = 10 ref_par_called,(REF_PAR_RET(a)),(REF_PAR_RET(*p)),10 if a NE 537 OR *p NE 537 then print,"REF_PAR: error 1" p = ptr_new(10) a = 10 ref_par_called,++(REF_PAR_RET(a)),++(REF_PAR_RET(*p)),11 if a NE 537 OR *p NE 537 then print,"REF_PAR: error 2" p = ptr_new(10) a = 10 ref_par_called,(REF_PAR_RET(a))++,(REF_PAR_RET(*p))++,10 if a NE 11 OR *p NE 11 then print,"REF_PAR: error 3" end function ret99 return,99b end function ret,a return,a end function retEq,a return,(a=3) end function retTag,a return,(a.t=3) end function ret2,b return,ret(b) end function ret3,b return,ret2(b) end function retOverwriteLocal a=[['m','a'],['r','c']] return,reform(a,4,/OVERWRITE) end function retOverwriteGlobal,a return,reform(a,4,/OVERWRITE) end function retOverwriteExpression a=[['m','a'],['r','c']] return,reform(a[*],4,/OVERWRITE) end pro ret_test ref_par_test if ret99() ne 99.0 then begin message, '***RET: ERROR1', /conti exit, status=1 endif if retEq(u) ne 3 then begin message, '***RET: ERROR2', /conti exit, status=1 endif (retEq(u2)) = 4 if u2 ne 4 then begin message, '***RET: ERROR4', /conti exit, status=1 endif (ret3(u3))=7 if u3 ne 7 then begin message, '***RET: ERROR5', /conti exit, status=1 endif s={t:0} if retTag(s) ne 3 then begin message, '***RET: ERROR6', /conti exit, status=1 endif ;(ret(s))=2 n = retOverwriteLocal() if n[2] ne "r" then begin message, '***RET: ERROR7', /conti exit, status=1 endif a=[[1,2],[3,4]] (retOverwriteGlobal(a))-- if a[1] ne 1 then begin message, '***RET: ERROR8', /conti exit, status=1 endif n = retOverwriteExpression() if n[2] ne "r" then begin message, '***RET: ERROR9', /conti exit, status=1 endif a=1 c=ret(4*(3+reform(a,1,/OVERWRITE)+1)*2) if a ne 1 then begin message, '***RET: ERROR10', /conti exit, status=1 endif if c ne 40 then begin message, '***RET: ERROR11', /conti exit, status=1 endif common ret_common,aa aa=1 c=ret(4*(3+reform(aa,1,/OVERWRITE)+1)*2) if aa ne 1 then begin message, '***RET: ERROR12', /conti exit, status=1 endif if c ne 40 then begin message, '***RET: ERROR13', /conti exit, status=1 endif print,'RET: OK'; end pro struct_test s={s:"a string",tag: indgen(5),c:complex(1,2)} if s.tag[ 3] ne 3 then begin message, '***STRUCT: ERROR1', /conti exit, status=1 endif s={s1,tag: indgen(5),s:s} if s.tag[ 3] ne 3 then begin message, '***STRUCT: ERROR1b', /conti exit, status=1 endif s.tag++ if s.tag[ 3] ne 4 then begin message, '***STRUCT: ERROR2', /conti exit, status=1 endif s.tag = 9 if s.tag[ 3] ne 9 then begin message, '***STRUCT: ERROR3', /conti exit, status=1 endif s.tag = [10,11,12] if s.tag[ 2] ne 12 then begin message, '***STRUCT: ERROR4', /conti exit, status=1 endif ss=[s,s] ss[*].tag=indgen(5,2) if ss[1].tag[2] ne 7 then begin message, '***STRUCT: ERROR5', /conti exit, status=1 endif s={s:indgen(5),$ t:"string",$ u:complexarr(3,5),$ v:dcomplexarr(99,2),$ x:sindgen(100)$ } ss={ss:s,s2:s} sss={sss:ss,ss:[s,s]} sa = s for i=0,2 do begin sa={s1:sa,s2:[sa,sa]} endfor sa = {named,t:s} for i=0,3 do begin sa={s1:sa,s2:[sa,sa]} endfor sa=0 ;p=ptr_new( sss) ;((*p).sss.ss)[2] = 5 ;print,((*p).ss)[2] sss.sss.ss.s[2] = 10 if sss.sss.ss.s[2] ne 10 then begin message, '***STRUCT: ERROR6', /conti exit, status=1 endif (ret(sss)).sss.ss.s[1] = 11 if sss.sss.ss.s[1] ne 11 then begin message, '***STRUCT: ERROR7', /conti exit, status=1 endif if (ret(sss)).sss.ss.s[3] ne 3 then begin message, '***STRUCT: ERROR8', /conti exit, status=1 endif (ret(sss)).sss.(0).s[1] = 11 if sss.(0).ss.s[1] ne 11 then begin message, '***STRUCT: ERROR9', /conti exit, status=1 endif if ({a:3}).a ne 3 then begin print, '***STRUCT: ERROR10', /conti exit, status=1 endif ;; array and struct s4=[sss,sss] s5=[[s4],[s4]] if s5[1,1].sss.ss.s[3] ne 3 then begin print, '***STRUCT: ERROR11', /conti exit, status=1 endif a = {a0, var1: 0, var2: 0.0d0} b = {a0, '0L', ' 1.0'} ; bug tracker ID: 3612104 a=ptrarr(1) a(0)=ptr_new('a') s={a:a} ss={sst:s} if *s.a(0) ne 'a' then begin message, '***STRUCT: ERROR12', /conti exit, status=1 endif if *ss.sst.a(0) ne 'a' then begin message, '***STRUCT: ERROR13', /conti exit, status=1 endif print,'STRUCT: OK' end pro multi,a,b,c b=9 if a ne 9 then begin message, '***MULTI: ERROR1', /conti exit, status=1 endif if c ne 9 then begin message, '***MULTI: ERROR2', /conti exit, status=1 endif end pro multi_test multi,a,a,a if a ne 9 then begin message, '***MULTI: ERROR3', /conti exit, status=1 endif print,'MULTI: OK' end function o::init self.a=9 return,1 end function o::get return,self.a end pro o::test self.a=1 if self.a ne 1 then begin message, '***OBJECT: ERROR1', /conti exit, status=1 endif self[0].a=2 if self[0].a ne 2 then begin message, '***OBJECT: ERROR2', /conti exit, status=1 endif (self).a[0]=3 if (self[0]).a[[-2]] ne 3 then begin message, '***OBJECT: ERROR3', /conti exit, status=1 endif if self[[0]].a ne 3 then begin message, '***OBJECT: ERROR4', /conti exit, status=1 endif ;; would be legal in GDL (but IDL complains) ;if (self[[0]]).a ne 3 then begin ; message, '***OBJECT: ERROR5', /conti ; exit, status=1 ;endif end pro o::cleanup common object_test,o_cleanup o_cleanup=-1 end pro object_test common object_test ;; object s={o,a:0} obj=obj_new('o') if obj->get() ne 9 then begin message, '***OBJECT: ERROR6', /conti exit, status=1 endif obj->test (obj)->test obj[0]->test (obj[0])->test if not obj_valid( obj) then begin message, '***OBJECT: ERROR7', /conti exit, status=1 endif obj_destroy,obj if obj_valid( obj) then begin message, '***OBJECT: ERROR8', /conti exit, status=1 endif if o_cleanup ne -1 then begin message, '***OBJECT: ERROR9', /conti exit, status=1 endif print,'OBJECT: OK' end pro ct1 common tc,x,y,z if x ne 3 then begin message, '***COMMON: ERROR1', /conti exit, status=1 endif y=7 end pro ct2 common tc if x ne 3 then begin message, '***COMMON: ERROR2', /conti exit, status=1 endif if y ne 7 then begin message, '***COMMON: ERROR3', /conti exit, status=1 endif z=9 end function ct3 common tc3,a return,a end pro common_test common tc,a,b,c common tc,d,e,f common tc a=3 ct1 ct2 if a ne 3 then begin message, '***COMMON: ERROR4', /conti exit, status=1 endif if b ne 7 then begin message, '***COMMON: ERROR5', /conti exit, status=1 endif if c ne 9 then begin message, '***COMMON: ERROR6', /conti exit, status=1 endif if d ne 3 then begin message, '***COMMON: ERROR7', /conti exit, status=1 endif if e ne 7 then begin message, '***COMMON: ERROR8', /conti exit, status=1 endif if f ne 9 then begin message, '***COMMON: ERROR9', /conti exit, status=1 endif if x ne 3 then begin message, '***COMMON: ERROR10', /conti exit, status=1 endif if y ne 7 then begin message, '***COMMON: ERROR11', /conti exit, status=1 endif if z ne 9 then begin message, '***COMMON: ERROR12', /conti exit, status=1 endif (ct3()) = 2 if ct3() ne 2 then begin message, '***COMMON: ERROR13', /conti exit, status=1 endif print,'COMMON: OK' end pro set22,a,X=x a=2 x=2 end pro ref_test,MEMCHECK=mCheck set22,b if b ne 2 then begin message, "***REF: ERROR1", /conti exit, status=1 endif if not keyword_set( mCheck) then begin p=ptr_new(/alloc) set22,*p if *p ne 2 then begin message, "***REF: ERROR2", /conti exit, status=1 endif ptr_free,p p=ptr_new(/alloc) pp=ptr_new(p) set22,**pp if **pp ne 2 then begin message, "***REF: ERROR3", /conti exit, status=1 endif ptr_free,p,pp endif a=indgen(3) set22,reform(a,1,3,/OVERWRITE) if a ne 2 then begin message, "***REF: ERROR4", /conti exit, statis=1 endif a=4 & x=4 set22,a++,X=x++ if a ne 5 or x ne 5 then begin message, "***REF: ERROR5", /conti exit, status=1 endif a=1 & x=1 set22,++a,X=++x if a ne 2 or x ne 2 then begin message, "***REF: ERROR6", /conti exit, status=1 endif a=1 & x=1 set22,(a=4),X=(x=4) if a ne 2 or x ne 2 then begin message, "***REF: ERROR7", /conti exit, status=1 endif a=4 & x=4 set22,++(a=1),X=++(x=1) if a ne 2 or x ne 2 then begin message, "***REF: ERROR8", /conti exit, status=1 endif set22,++(a[0]=4),X=++(x[0]=4) if a ne 5 or x ne 5 then begin message, "***REF: ERROR9", /conti exit, status=1 endif print,'REF: OK' end function base::init common inheritance,baseInit,baseCleanup,derivInit,derivCleanup baseInit=1 return,1 end pro base::cleanup common inheritance,baseInit,baseCleanup,derivInit,derivCleanup baseCleanup=1 end pro base::set self.b='base' end pro base::setbase self.b='base' end function base::get return,self.b end function deriv::init common inheritance,baseInit,baseCleanup,derivInit,derivCleanup r=self->base::init() derivInit=1 return,1 end pro deriv::cleanup common inheritance,baseInit,baseCleanup,derivInit,derivCleanup self->base::cleanup derivCleanup=1 end pro deriv::set self.b='deriv' end pro inheritance_test base={ base, b: ''} deriv={ deriv, INHERITS base, d: ''} common inheritance o=obj_new( 'deriv') if baseInit ne 1 then begin message, '***INHERITANCE: ERROR1', /conti exit, status=1 endif if derivInit ne 1 then begin message, '***INHERITANCE: ERROR2', /conti exit, status=1 endif o->setbase if o->get() ne 'base' then begin message, '***INHERITANCE: ERROR3', /conti exit, status=1 endif o->set if o->get() ne 'deriv' then begin message, '***INHERITANCE: ERROR4', /conti exit, status=1 endif o->base::set if o->get() ne 'base' then begin message, '***INHERITANCE: ERROR5', /conti exit, status=1 endif obj_destroy, o if baseInit ne 1 then begin message, '***INHERITANCE: ERROR6', /conti exit, status=1 endif if derivInit ne 1 then begin message, '***INHERITANCE: ERROR7', /conti exit, status=1 endif print,'INHERITANCE: OK' end function syntax_test,a,b,c return,byte(a,b,c) end pro syntax_test s={a:0} t=s[0].a t=s[[0]].a t=(s[0]).a t=(s[[0]]).a b=(a=2) if b ne 2 then begin message, '***SYNTAX_TEST: ERROR1', /conti exit, status=1 endif a=(byte(1,0,1))[0] a=(syntax_test(1,0,1))[0] ;((a=4)) syntax error ;(a=2)=3 forbidden in GDL (as it hardly makes sense) end pro inc_test a=1 (ret(a))++ ++(ret(a)) if a ne 3 then begin message, "***INC: ERROR1", /conti exit, status=1 endif b = intarr(3) b[1]++ ++b[1] (b[1])++ ++(b[1]) if b[1] ne 4 then begin message, "***INC: ERROR2", /conti exit, status=1 endif b[[1,2]]+=1 if b[1] ne 5 then begin message, "***INC: ERROR3", /conti exit, status=1 endif (a=2)++ if a ne 3 then begin message, '***INC_TEST: ERROR4', /conti exit, status=1 endif ((a=2))++ if a ne 3 then begin message, '***INC_TEST: ERROR5', /conti exit, status=1 endif ++(a=2) if a ne 3 then begin message, '***INC_TEST: ERROR6', /conti exit, status=1 endif ++((a=2)) if a ne 3 then begin message, '***INC_TEST: ERROR7', /conti exit, status=1 endif print,'INC: OK' end pro continuebreak_test repeat begin goto,start message, '***CONTINUE/BREAK: ERROR2', /conti exit, status=1 start: for i=0,40,2 do begin if i lt 6 then continue if i lt 6 then begin message, '***CONTINUE/BREAK: ERROR1', /conti exit, status=1 endif if i gt 10 then break if i gt 10 then begin message, '***CONTINUE/BREAK: ERROR2', /conti exit, status=1 endif goto,in1 message, '***CONTINUE/BREAK: ERROR2', /conti exit, status=1 goto,out1 in1: endfor goto,out2 out1: out2: endrep until 1 print,'CONTINUE/BREAK: OK' end pro e2,A=a,B=b if a ne 'a' then begin message, 'EXTRA: ERROR1', /conti exit, status=1 endif if b ne 'b' then begin message, 'EXTRA: ERROR2', /conti exit, status=1 endif end pro eref,_REF_EXTRA=ex e2,_EXTRA=ex end pro eval,_EXTRA=ex e2,_EXTRA=ex end pro e1,R2=a,R1=b a=1 b=2 end pro eret,_REF_EXTRA=ex e1,_EXTRA=ex end pro extra_test,_REF_EXTRA=ex eval,b='b',a='a',c=u ;; eref,b='b',a='a',c=u eret,r1=r1,r2=r2 if r1 ne 2 then begin message, '***EXTRA: ERROR3', /conti exit, status=1 endif if r2 ne 1 then begin message, '***EXTRA: ERROR4', /conti exit, status=1 endif print,'EXTRA: OK' end pro expr_test ; BUG tracker ID: 3579499 str_template={value:1.0} str_array=replicate(str_template,10) str={data:str_array} tmp=cos(str_template.value) tmp=cos(str_array(0).value) tmp=cos(str.data(0).value) a=0 a++ a *= 2 a ^= 2 b = a+2*3-(9*2)+9 if b ne 1 then begin message, '***EXPR: ERROR1', /conti exit, status=1 endif a=indgen(6,6,6) a[3,3,3]=-1 if a[3,3,3] ne -1 then begin message, '***EXPR: ERROR2', /conti exit, status=1 endif a=a+100 if a[3,3,3] ne 99 then begin message, '***EXPR: ERROR2a', /conti exit, status=1 endif a[*]=a[*]-100 if a[3,3,3] ne -1 then begin message, '***EXPR: ERROR2b', /conti exit, status=1 endif sdef={s,a:intarr(3),s:strarr(3)} s1={s,indgen(3),s:sindgen(3)} if s1.a[1] ne 1 then begin message, '***EXPR: ERROR3', /conti exit, status=1 endif s2={s} sArr=[s2,s2] sArr[1].s[1]='test' if sArr[1].s[1] ne 'test' then begin message, '***EXPR: ERROR4', /conti exit, status=1 endif a=1 c=4*(3+reform(a,1,/OVERWRITE)+1)*2 if c ne 40 then begin message, '***EXPR: ERROR5', /conti exit, status=1 endif if a ne 1 then begin message, '***EXPR: ERROR6', /conti exit, status=1 endif if ~1 and ~2 && ~3 and 4 || ~ 5 ne 0 then begin message, '***EXPR: ERROR7', /conti exit, status=1 endif print,'EXPR: OK' end function fac,n if n le 1 then return,1 return,fac(n-1)*n end pro recursion_test if fac( 5) ne 120 then begin message, "***RECURSION: ERROR", /conti exit, status=1 endif print,'RECURSION: OK' end pro index_test x=[1,2,3] l=3 y=x[0:l-1] if y[2] ne 3 then begin message, "***INDEX: ERROR0", /conti exit, status=1 endif b=byte( "abcdefg") d=bytarr(20) d[10]=b if string( d[10:16]) ne "abcdefg" then begin message, "***INDEX: ERROR1", /conti exit, status=1 endif i=indgen(3,3) s=[[-1],[-2]] i[1,1]=s if i[1,2] ne -2 then begin message, "***INDEX: ERROR2", /conti exit, status=1 endif c=intarr(3) (((c[1])))=1 if c[1] ne 1 then begin message, '***INDEX: ERROR3', /conti exit, status=1 endif print,'ARRAY INDEXING: OK' end pro operator_test a=indgen(4) b=indgen(4) c=a#b if c[2,3] ne 6 then begin message, "***OPERATOR: ERROR1", /conti exit, status=1 endif b=indgen(4,2) c=a#b if c[0,1] ne 38 then begin message, "***OPERATOR: ERROR2", /conti exit, status=1 endif a=indgen(2,4) b=indgen(4) c=a#b if c[1] ne 34 then begin message, "***OPERATOR: ERROR3", /conti exit, status=1 endif b=indgen(4,2) c=a#b if c[0,1] ne 76 then begin message, "***OPERATOR: ERROR4", /conti exit, status=1 endif x=indgen(10) # transpose(intarr(10)+1) if x[9,9] ne 9 then begin message, "***OPERATOR: ERROR5", /conti exit, status=1 endif ;; with scalar r= 4 # indgen(1,4) if r[0,2] ne 8 then begin message, "***OPERATOR: ERROR6", /conti exit, status=1 endif r= indgen(4) # 4 if r[1] ne 4 then begin message, "***OPERATOR: ERROR7", /conti exit, status=1 endif if ~(!NULL eq !NULL) then begin message, "***OPERATOR: ERROR8", /conti exit, status=1 endif if ~(un_def eq !NULL) then begin message, "***OPERATOR: ERROR9", /conti exit, status=1 endif if ~(!NULL eq un_def) then begin message, "***OPERATOR: ERROR10", /conti exit, status=1 endif if !NULL ne !NULL then begin message, "***OPERATOR: ERROR8", /conti exit, status=1 endif if un_def ne !NULL then begin message, "***OPERATOR: ERROR9", /conti exit, status=1 endif if !NULL ne un_def then begin message, "***OPERATOR: ERROR10", /conti exit, status=1 endif print,'OPERATORS: OK' end pro assignment_test c = indgen( 4, 4) t = intarr( 5, 5) t[0,0] = c if t[3,3] ne 15 then begin message, "***ASSIGNMENT: ERROR1", /conti exit, status=1 endif t = intarr( 5, 5) t[0,1] = c if t[3,3] ne 11 then begin message, "***ASSIGNMENT: ERROR2", /conti exit, status=1 endif t = intarr( 5, 5) t[1,0] = c if t[3,3] ne 14 then begin message, "***ASSIGNMENT: ERROR3", /conti exit, status=1 endif t = intarr( 5, 5) t[1,1] = c if t[3,3] ne 10 then begin message, "***ASSIGNMENT: ERROR4", /conti exit, status=1 endif t = intarr( 5, 5) a=indgen(3,3) t[1,1]=a if t[2,2] ne 4 then begin message, "***ASSIGNMENT: ERROR5", /conti exit, status=1 endif t = intarr( 5, 5) a=indgen(3,3) t[1]=a if t[3,0] ne 2 then begin message, "***ASSIGNMENT: ERROR6", /conti exit, status=1 endif a=(1?0:9) b=0 (1?a:b) = 2 if a ne 2 then begin message, "***ASSIGNMENT: ERROR7", /conti exit, status=1 endif ((a=3))=2 if a ne 2 then begin message, "***ASSIGNMENT: ERROR8", /conti exit, status=1 endif A=create_struct("boo",dblarr(10),"foo",dblarr(10)) B=replicate(A,30) data=findgen(30) B[0:29].boo[3] = data[0:29] if B[29].boo[3] ne 29.0 then begin message, "***ASSIGNMENT: ERROR9", /conti exit, status=1 endif print,"ASSIGNMENT: OK" end pro left_libfunction_test u=indgen(4) (reform(u,4,/OVERWRITE))++ if u[2] ne 3 then begin message, "***LEFT_LIBFUNCTION: ERROR1", /conti exit, status=1 endif print,"LEFT_LIBFUNCTION: OK" end pro stride_index_test a=lindgen( 11, 20, 31) ;print,total( a[1:*:3]) if total( a[1:10:4, 2:16:2, 5:29:5]) ne 408480. then begin message, "***STRIDE_INDEX: ERROR 1", /conti exit, status=1 endif if total( a[*, 2:14:2, 20:29:5]) ne 776622. then begin message, "***STRIDE_INDEX: ERROR 2", /conti exit, status=1 endif if total( a[1:6:2, *, 17:29:5]) ne 890550. then begin message, "***STRIDE_INDEX: ERROR 3", /conti exit, status=1 endif if total( a[[7,1], 2:16:2, 5:29:5]) ne 272240. then begin message, "***STRIDE_INDEX: ERROR 4", /conti exit, status=1 endif if total( a[3:9:2, [7,1], 2:*:4]) ne 228480. then begin message, "***STRIDE_INDEX: ERROR ", /conti exit, status=1 endif if total( a[*, 5:*:5, [7,1]]) ne 65670. then begin message, "***STRIDE_INDEX: ERROR 5", /conti exit, status=1 endif if total( a[5:7, 2:16:2, 5:29:5]) ne 408600. then begin message, "***STRIDE_INDEX: ERROR 6", /conti exit, status=1 endif if total( a[3:9:2, 5:7, 2:*:4]) ne 344832. then begin message, "***STRIDE_INDEX: ERROR 7", /conti exit, status=1 endif if total( a[*, 5:*:5, 5:7]) ne 142065. then begin message, "***STRIDE_INDEX: ERROR 8", /conti exit, status=1 endif b=lindgen(50) if total( b[1:32:7]) ne 75. then begin message, "***STRIDE_INDEX: ERROR 9", /conti exit, status=1 endif if total( b[1:*:3]) ne 425. then begin message, "***STRIDE_INDEX: ERROR 10", /conti exit, status=1 endif print,"STRIDE_INDEX: OK" end ; 'TEST_SUITE main program called.' ; ;; set MEMCHECK to perform a memory leak check ;; as the heap (number of allocated cells) always grows so does ;; the memory consumption ;; with MEMCHECK set, no ptr and object allocations are made pro TEST_SUITE, MEMCHECK=mCheck s=systime(1) if_test switch_test case_test while_test for_test repeat_test goto_test ret_test struct_test multi_test if not keyword_set( mCheck) then object_test common_test ref_test,MEMCHECK=mCheck syntax_test inc_test if not keyword_set( mCheck) then inheritance_test continuebreak_test extra_test expr_test recursion_test index_test operator_test assignment_test left_libfunction_test stride_index_test print,"TEST_SUITE finished. Time: ",systime(1)-s end gdl-0.9.9/testsuite/test_surface_basic.pro000066400000000000000000000104621340051421000206730ustar00rootroot00000000000000; ; AC, le 19/03/2008 derivated from TEST_CONTOUR_BASIC ; AC, le 20/03/2008 non square case ! more useful ! ; ; several tests around SURFACE procedure ; ; We can jump to level 1 or level 2 tests ; ; I defined 3 levels: ; -level 0- basic (only Z) ; -level 1- intermediate (Z, and (X,Y) 1D) ; -level 2- high (z, x, Y are both 2D with same size) ; ; GDL 0.9 All tests OK ; pro TEST_SURFACE_BASIC, xnbp=xnbp, ynbp=ynbp, $ level=level, test=test, help=help ; if KEYWORD_SET(help) then begin PRINT, 'pro TEST_SURFACE_BASIC, xnbp=xnbp, ynbp=ynbp, $' PRINT, ' level=level, test=test, help=help' return endif ; old_version=0 ; mess='' ; if (N_ELEMENTS(level) EQ 0) then level=0 ; ; we generate data, and X, Y ; if (N_ELEMENTS(xnbp) NE 1) then xnbp=128 if (N_ELEMENTS(ynbp) NE 1) then ynbp=2*xnbp ; data=DIST(xnbp, ynbp) x=FINDGEN(xnbp) y=FINDGEN(ynbp) ; pos_info=[0.2,0.2,0.8,0.8] ; ; we jump if we check only from specific level (0,1,2) ; if (level EQ 1) then goto, level1 if (level EQ 2) then goto, level2 ; ; ----- basic tests --------- level0: PRINT, 'Start of basic test (SURFACE, z)' ; SURFACE, data READ, 'press enter to continue: ', mess ; SURFACE, data, /xstyle, title='/Xstyle enforced' READ, 'press enter to continue: ', mess ; SURFACE, data, /ystyle, title='/Ystyle enforced' READ, 'press enter to continue: ', mess ; SURFACE, data, /xstyle, /ystyle, title='/Xstyle and /Ystyle enforced' READ, 'press enter to continue: ', mess ; SURFACE, data, pos=pos_info, title='pos= used (no X or Y style ...)' READ, 'press enter to continue: ', mess ; SURFACE, data, pos=pos_info, /xstyle, /ystyle, title='pos= used, /Xstyle and /Ysstyle also' READ, 'press enter to continue: ', mess ; ; ----- intermediate tests --------- level1: PRINT, 'Start of tests with intermediate difficulties (SURFACE, z, x, y, with x and y 1D)' ; SURFACE, data, x, y READ, 'press enter to continue: ', mess ; SURFACE, data, x, y, /xstyle, title='X style enforced' READ, 'press enter to continue: ', mess ; SURFACE, data, x, y, /xstyle, /ystyle, title='X and Y style enforced' READ, 'press enter to continue: ', mess ; SURFACE, data, x, y, pos=pos_info, title='pos= used' READ, 'press enter to continue: ', mess ; SURFACE, data, x*2, y, title='X range expanded (*2)' READ, 'press enter to continue: ', mess ; SURFACE, data, x-xnbp, y, title='X range shifted (shifted to neg.)' READ, 'press enter to continue: ', mess ; SURFACE, data, x-xnbp/2, y, title='X range shifted (center on 0.)' READ, 'press enter to continue: ', mess ; SURFACE, data, x, y*2, title='Y range expanded (*2)' READ, 'press enter to continue: ', mess ; if (old_version EQ 1) then PRINT, 'Warning: this should be wrong' SURFACE, data, x, y-ynbp, title='Y range shifted (shifted to neg.)' READ, 'press enter to continue: ', mess ; if (old_version EQ 1) then PRINT, 'Warning: this should be wrong' SURFACE, data, x, y-ynbp/2, title='Y range shifted (center on 0.)' READ, 'press enter to continue: ', mess ; if (old_version EQ 1) then PRINT, 'Warning: this should be wrong' SURFACE, data, x, y-ynbp/2, pos=pos_info, title='Y range shifted (center on 0.) with pos=' READ, 'press enter to continue: ', mess ; if (old_version EQ 1) then PRINT, 'Warning: this should be wrong' SURFACE, data, x, y-ynbp/2, yrange=[-ynbp, ynbp], title='Y range shifted (center on 0.) with yrange' READ, 'press enter to continue: ', mess ; if KEYWORD_SET(test) then STOP ; ; ----- high tests --------- level2: PRINT, 'Start of tests with high difficulties (working since GDL 0.9)' PRINT, 'X, Y and Z and all 2D arrays with same size' ; ; we compute the locations on the grid (i.e. one (x,y) for each z) x=x#REPLICATE(1.,ynbp) y=REPLICATE(1.,xnbp)#y ; if (old_version EQ 1) then PRINT, 'Warning: this should be not working ...' SURFACE, data, x, y READ, 'press enter to continue: ', mess ; ; the same but we add a noise on X positions ; if (old_version EQ 1) then PRINT, 'Warning: this should be not working ...' SURFACE, data, x+RANDOMN(seed, xnbp, ynbp), y, /xstyle, /ystyle READ, 'press enter to continue: ', mess ; ; the same but we add a noise on Y positions ; if (old_version EQ 1) then PRINT, 'Warning: this should be not working ...' SURFACE, data, x, y+RANDOMN(seed, xnbp, ynbp), /xstyle, /ystyle READ, 'press enter to continue: ', mess ; PRINT, 'test suite for CONTOUR is now finished' ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_systime.pro000066400000000000000000000152721340051421000176030ustar00rootroot00000000000000; ; Alain Coulais and Sylwester Arabas, during the GHM 2011 in Paris. ; Copyright 2011. This code is under GNU GPL v2 or any later. ; ; * TEST_SYSTIME_LOCALE ; ; In some cases, when external libraries are compiled with ; non "C" locales, this can affect internal procedures in GDL ... ; One case was SYSTIME(), broken by external Image Magick with "bad" locale ; ; This test must be call before any use of LOCALE_GET(). ; This test is not perfect because internal locale in GDL are changed ; by a call to LOCALE_GET(). ; ; * TEST_SYSTIME_ZERO ; ; In fact the input in range inside ]-1,1[ is used as 0 ... ; ; ----------------------------------------------- ; pro TEST_SYSTIME_LOCALE, cumul_errors, help=help, test=test, verbose=verbose ; if KEYWORD_SET(help) then begin print, 'pro TEST_SYSTIME_LOCALE, nb_pbs_locale, help=help, test=test, verbose=verbose' print, '' print, 'we test whether we use C locale, as internaly needed in GDL' return endif ; nb_pbs_locale=0 ; ; same formating in Unix/Linux/OSX "date" ; than IDL/GDL internal SYSTIME ; command='date +"%a %b %d %T %Y"' command_C='LC_ALL=C '+command ; ; We cannot make a direct test because we are not sure ; to be in the same sec., then min. then hour. ! ; But the true test is on Month ! ; resu_GDL=SYSTIME() SPAWN, command_C, resu_LC_ALL SPAWN, command, resu ; debut_GDL=STRMID(resu_GDL,0,7) debut_C=STRMID(resu_LC_ALL,0,7) debut_brut=STRMID(resu,0,7) ; if (debut_GDL NE debut_C) then begin MESSAGE, /continue, 'Problem with LOCALE in GDL' nb_pbs_locale=1 ;;if ~KEYWORD_SET(no_exit) then EXIT, status=1 endif ; ; this test is not pertinent for GDL, ; it is only to inform that you may have problems ; due to your LOCALE ; ;if (debut_brut NE debut_C) then begin ; MESSAGE, /continue, 'Warning: for your LOCALE outside GDL' ; MESSAGE, /continue, 'Warning: it is expected C locale for good compilation' ;endif ; if KEYWORD_SET(verbose) then begin print, 'first two Lines should be equal, except may be in the "second" value !' print, 'resu_GDL : ', resu_GDL print, 'resu_LC_ALL : ', resu_LC_ALL print, 'resu (no LC) : ', resu endif ; BANNER_FOR_TESTSUITE, "TEST_SYSTIME_LOCALE", nb_pbs_locale, /short, verb=verbose ; ERRORS_CUMUL, cumul_errors, nb_pbs_locale ; if KEYWORD_SET(test) then STOP ; end ; ; ----------------------------------------------- ; pro TEST_SYSTIME_ZERO, cumul_errors, verbose=verbose, test=test, help=help ; if KEYWORD_SET(help) then begin print, 'pro TEST_SYSTIME_LOCALE, nb_pbs_locale, help=help, test=test, verbose=verbose' print, '' print, 'we test whether we use C locale, as internaly needed in GDL' return endif ; ; should return something like : Wed May 13 16:19:34 2015 ; nb_pbs_zero=0 ; resu_vide=SYSTIME() ; ; let's say all we be done in less than 5 sec. ... ; do we need a delay ? while (STRMID(resu_vide,17,2) GT 58) do begin wait, 1 resu_vide=SYSTIME() endwhile ; prefix=STRMID(resu_vide,0,16) ; ; various inputs need to be tested ... ; resu_zero=SYSTIME(0) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1 i' resu_zero=SYSTIME(0.0) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1 f' resu_zero=SYSTIME(0.0d) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1 d' resu_zero=SYSTIME([0]) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1 i a' resu_zero=SYSTIME([0.0]) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1 f a' resu_zero=SYSTIME(0.9) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1+ f' resu_zero=SYSTIME(-0.9) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1- f' resu_zero=SYSTIME([0.9]) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1+ a' resu_zero=SYSTIME([-0.9]) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 1- a' ; ; testing string conversion ; resu_zero=SYSTIME('0.0') if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 2' resu_zero=SYSTIME('0.9') if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 2+' resu_zero=SYSTIME('-0.9') if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 2-' resu_zero=SYSTIME(['0.0']) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 2 a' resu_zero=SYSTIME(['0.9']) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 2+ a' resu_zero=SYSTIME(['-0.9']) if (prefix NE STRMID(resu_zero,0,16)) then ERRORS_ADD, nb_pbs_zero, 'case 2- a' ; BANNER_FOR_TESTSUITE, "TEST_SYSTIME_ZERO", nb_pbs_zero, /short, verb=verbose ; ERRORS_CUMUL, cumul_errors, nb_pbs_zero ; if KEYWORD_SET(test) then STOP ; end ; ; ---------------------------------------------------- ; pro TEST_SYSTIME_EPOCH, cumul_errors, verbose=verbose, test=test, help=help ; nb_pbs_epoch=0 ; ; Unix billennium expected='Sun Sep 09 01:46:40 2001' value=SYSTIME(0,1000000000,/utc) if (expected NE value) then ERRORS_ADD, nb_pbs_epoch, 'Unix billennium conversion failed !' ; ; we do have a Float/Double diff here: ; SYSTIME(0,1234567891,/utc) == SYSTIME(0,1234567891.0d,/utc) != SYSTIME(0,1234567891.0,/utc) ; expected='Fri Feb 13 23:31:30 2009' value=SYSTIME(0,1234567890,/utc) if (expected NE value) then ERRORS_ADD, nb_pbs_epoch, 'Decimal Row Keyboard conversion failed !' ; BANNER_FOR_TESTSUITE, "TEST_SYSTIME_EPOCH", nb_pbs_epoch, /short, verb=verbose ; ERRORS_CUMUL, cumul_errors, nb_pbs_epoch ; if KEYWORD_SET(test) then STOP ; end ; ---------------------------------------------------- ; pro TEST_SYSTIME_JULIAN, cumul_errors, verbose=verbose, test=test, help=help ; ; not ready now, other pbs found ... MESSAGE,/continue, 'Not finished' MESSAGE,/continue, 'Not finished, please contributed !' MESSAGE,/continue, 'Not finished' ; nb_pbs_julian=0 ; BANNER_FOR_TESTSUITE, "TEST_SYSTIME_JULIAN", nb_pbs_julian, /short, verb=verbose ; ERRORS_CUMUL, cumul_errors, nb_pbs_julian ; if KEYWORD_SET(test) then STOP ; end ; ; ---------------------------------------------------- ; pro TEST_SYSTIME, help=help, test=test, no_exit=no_exit, verbose=verbose ; if KEYWORD_SET(help) then begin print, 'pro TEST_SYSTIME, help=help, test=test, no_exit=no_exit, verbose=verbose' print, '' print, 'few tests related to SYSTIME : locale, values ...' return endif ; cumul_errors=0 ; TEST_SYSTIME_LOCALE, cumul_errors, verbose=verbose, test=test ; TEST_SYSTIME_ZERO, cumul_errors, verbose=verbose, test=test ; TEST_SYSTIME_EPOCH, cumul_errors, verbose=verbose, test=test ; TEST_SYSTIME_JULIAN, cumul_errors, verbose=verbose, test=test ; ; ---- Final message ---- ; BANNER_FOR_TESTSUITE, "TEST_SYSTIME", cumul_errors ; if (cumul_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_tic_toc.pro000066400000000000000000000031301340051421000175200ustar00rootroot00000000000000; ; AC, 2016-03-03 ; ; basic test to check whether TIC and TOC are working ... ; testing "label" and sum ... ; pro TEST_TIC_TOC, nb_times=nb_times, no_exit=no_exit, $ help=help, test=test, verbose=verbose ; if KEYWORD_SET(help) then begin print, 'pro TEST_TIC_TOC, nb_times=nb_times, no_exit=no_exit, $' print, ' help=help, test=test, verbose=verbose' return endif ; fft_dim=1729 ; cumul=TIC('cumul') ; ; how many time we compute ... if ~KEYWORD_SET(nb_times) then nb_times=4 val_times=DBLARR(nb_times) ; for i=0, nb_times-1 do begin ;; Start another clock named FFT ;; combined with the iteration number clock = TIC('FFT' + STRTRIM(i, 2)) r = FFT(RANDOMU(seed, fft_dim, fft_dim)) ;; For each iteration grab the end system time, ;; then calculate and and print out the elapsed time val_times[i]=TOC(clock) print, 'Time elapsed in loop '+STRING(i,'(i2)')+' : ', $ val_times[i], ' seconds.' endfor ; ; Grab the final system for the entire loop ; and calculate and print the total elapsed time ; val_cumul=TOC(cumul) val_cumul=val_cumul[0] ; print, 'Cumulative Time elapsed : ', TOTAL(val_times), ' seconds.' print, 'Total Time elapsed : ', val_cumul, ' seconds.' ; errors=0 ; ; We accepte a tolerance of 1 % (ok on various Linux, might be wrong ; on OSX [cf "test_wait"]) tolerance=0.01 if (ABS((TOTAL(val_times)-val_cumul)/val_cumul) GT tolerance) then errors=1 ; BANNER_FOR_TESTSUITE, 'TEST_TIC_TOC', errors, short=short ; if (errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_tiff.pro000066400000000000000000000137711340051421000170400ustar00rootroot00000000000000; ; Testing TIFF support: QUERY_TIFF ; TODO: READ_TIFF and WRITE_TIFF (when implemented using libtiff/libgeotiff) ; ; Licensed under GNU GPL version 3 or later ; ; ------------------------------------------ ; Modification history: ; ; 2018-06-20 : Remi A. Solås ; - Updated sample image names ; - Added basic READ_TIFF tests for 8-bit grayscale images ; ; 2018-06-19 : Remi A. Solås ; - Initial version ; - Basic QUERY_TIFF tests for both tiff and geotiff ; ; 2018-09-19 : AC : ; - Allowing running it on IDL ... ; - Maj for most Pro/Funct ; - This code is not working with FL Fawlty Language 0.79.43.1 ; ; ------------------------------------------ ; function INTERNAL_GDL_TIFF FORWARD_FUNCTION TIFF_EXISTS return, TIFF_EXISTS() end ; function INTERNAL_GDL_GEOTIFF FORWARD_FUNCTION GEOTIFF_EXISTS return, GEOTIFF_EXISTS() end ; ; ------------------------------------------ ; pro TEST_QUERY_TIFF, ntoterr, test=test, verbose=verbose ; nerr=0 ;; Regular TIFF, tiled file=FILE_SEARCH_for_testsuite('tiff/8bit_gray_tiled.tif') ; if QUERY_TIFF(file, info) eq 1 then begin if info.channels ne 1 then $ ERRORS_ADD, nerr, 'Unexpected number of CHANNELS in ' + file if ~ARRAY_EQUAL(info.dimensions, [1024, 1024]) then $ ERRORS_ADD, nerr, 'Unexpected value of DIMENSIONS in ' + file if info.has_palette ne 0 then $ ERRORS_ADD, nerr, 'Unexpected value of HAS_PALETTE in ' + file if info.num_images ne 1 then $ ERRORS_ADD, nerr, 'Unexpected value of NUM_IMAGES in ' + file if info.image_index ne 0 then $ ERRORS_ADD, nerr, 'Unexpected value of IMAGE_INDEX in ' + file if info.pixel_type ne 1 then $ ERRORS_ADD, nerr, 'Unexpected value of PIXEL_TYPE in ' + file if info.type ne 'TIFF' then $ ERRORS_ADD, nerr, 'Unexpected value of TYPE in ' + file if info.bits_per_sample ne 8 then $ ERRORS_ADD, nerr, 'Unexpected value of BITS_PER_SAMPLE in ' + file if info.orientation ne 1 then $ ERRORS_ADD, nerr, 'Unexpected value of ORIENTATION in ' + file if info.planar_config ne 1 then $ ERRORS_ADD, nerr, 'Unexpected value of PLANAR_CONFIG in ' + file if ~ARRAY_EQUAL(info.resolution, [1, 1]) then $ ERRORS_ADD, nerr, 'Unexpected value of RESOLUTION in ' + file if info.units ne 2 then $ ERRORS_ADD, nerr, 'Unexpected value of UNITS in ' + file if ~ARRAY_EQUAL(info.tile_SIZE, [256, 112]) then $ ERRORS_ADD, nerr, 'Unexpected value of TILE_SIZE in ' + file endif else ERRORS_ADD, nerr, 'QUERY_TIFF failed to query ' + file ; ; ------ ; BANNER_FOR_TESTSUITE, 'TEST_QUERY_GEOTIFF', nerr, /status ERRORS_CUMUL, ntoterr, nerr if KEYWORD_SET(test) then STOP ; end ; ; ------------------------------------------ ; pro TEST_QUERY_GEOTIFF, ntoterr, test=test, verbose=verbose ; nerr=0 ;; GeoTIFF, untiled file=FILE_SEARCH_for_testsuite('tiff/8bit_gray_geo.tif') if QUERY_TIFF(file, info, geotiff=geo) eq 1 then begin if ~ARRAY_EQUAL(info.tile_SIZE, [info.dimensions[0], 1]) then $ ERRORS_ADD, nerr, 'Unexpected value of TILE_SIZE in ' + file if ~ARRAY_EQUAL(geo.modelPixelScaleTag, [60, 60, 0]) then $ ERRORS_ADD, nerr, 'Unexpected value of MODELPIXELSCALETAG in ' + file if ~ARRAY_EQUAL(geo.modelTiePointTag, [0, 0, 0, 440720, 100000, 0]) then $ ERRORS_ADD, nerr, 'Unexpected value of MODELTIEPOINTTAG in ' + file if geo.gtModelTypeGeoKey ne 1 then $ ERRORS_ADD, nerr, 'Unexpected value of GTMODELTYPEGEOKEY in ' + file if geo.gtRasterTypeGeoKey ne 1 then $ ERRORS_ADD, nerr, 'Unexpected value of GTRASTERTYPEGEOKEY in ' + file if geo.projectedCsTypeGeoKey ne 21892 then $ ERRORS_ADD, nerr, 'Unexpected value of PROJECTEDCRTYPEGEOKEY in ' + file endif else ERRORS_ADD, nerr, 'QUERY_TIFF failed to query ' + file ; ; ------ ; BANNER_FOR_TESTSUITE, 'TEST_QUERY_GEOTIFF', nerr, /status ERRORS_CUMUL, ntoterr, nerr if KEYWORD_SET(test) then STOP ; end ; ------------------------------------------ pro TEST_READ_TIFF, ntoterr, test=test, verbose=verbose ; nerr=0 ; ;; 8-bit grayscale with SUB_RECT file=FILE_SEARCH_FOR_TESTSUITE('tiff/8bit_gray_geo.tif') ; AC 2018-sep-19 : not very happy ! ; ;image=TIFF_READ(file, sub_rect=[5, 15, 30, 90]) image=READ_TIFF(file, sub_rect=[5, 15, 30, 90]) if ~ARRAY_EQUAL(SIZE(image, /dimensions), [30, 90]) then $ ERRORS_ADD, nerr, 'Unexpected return value of SUB_RECT of ' + file if ~ARRAY_EQUAL(image[0:5], [107, 107, 115, 140, 99, 115]) then $ ERRORS_ADD, nerr, 'Unexpected pixel values in tested range of ' + file if ((image[0, 0] ne 107) || (image[0, 89] ne 0) || $ (image[29, 0] ne 107) || (image[29, 89] ne 41)) then $ ERRORS_ADD, nerr, 'Unexpected pixel values in corners of ' + file ; ; ------ ; BANNER_FOR_TESTSUITE, 'TEST_READ_TIFF', nerr, /status ERRORS_CUMUL, ntoterr, nerr if KEYWORD_SET(test) then STOP ; end ; ; ------------------------------------------ ; pro TEST_TIFF, help=help, test=test, no_exit=no_exit, verbose=verbose if KEYWORD_SET(help) then begin print, 'pro TEST_TIFF, help=help, test=test, no_exit=no_exit, verbose=verbose' return endif ; if (GDL_IDL_FL() EQ 'FL') then MESSAGE, /continue, 'This code don''t work on FL now' ; DEFSYSV, '!gdl', exists=is_it_gdl ; if (is_it_gdl) then begin status_tiff=INTERNAL_GDL_TIFF() if ~status_tiff then begin MESSAGE, /continue, 'GDL was compiled without TIFF support' EXIT, status=77 endif status_geotiff=INTERNAL_GDL_GEOTIFF() if ~status_geotiff then MESSAGE, /continue, 'GDL was compiled without GEO TIFF support' endif else begin status_tiff=1 status_geotiff=1 endelse ; if status_tiff then begin TEST_QUERY_TIFF, ntoterr, test=test, verbose=verbose TEST_READ_TIFF, ntoterr, test=test, verbose=verbose endif if status_geotiff then TEST_QUERY_GEOTIFF, ntoterr, test=test, verbose=verbose ; ; ----------------- final MESSAGE ---------- ; BANNER_FOR_TESTSUITE, 'TEST_TIFF', ntoterr ; if ntoterr gt 0 && ~KEYWORD_SET(no_exit) then EXIT, status=1 if KEYWORD_SET(test) then stop ; end gdl-0.9.9/testsuite/test_titles.pro000066400000000000000000000124741340051421000174130ustar00rootroot00000000000000; Work under GNU GPL ; ; Alain Coulais ; Distributed version 2008/02/07 ; Initial version in June 2007 ; ; Purpose: test suite for TITLE, SUBTITLE, XTITLE and YTITLE keywords ; in PLOT and CONTOUR, showing positioning, math and greek options ; ; Demo for Embedded Formatting Commands ; http://idlastro.gsfc.nasa.gov/idl_html_help/Embedded_Formatting_Commands.html ; http://idlastro.gsfc.nasa.gov/idl_html_help/Formatting_Command_Examples.html ;---------------------------------------------------------------------- ; This function create a STRING containing "number" time the "character" ; function AC_STRV, character, number ; vector=character for ii=1, number-1 do vector=vector+character return, vector end pro title_scale, _extra=_extra tt=AC_STRV('f', 40) plot, findgen(10), titl=tt, xtit=tt, ytit=tt, subti=tt, _extra=_extra end ; ; complex title with greek and math... ; pro titre1, full=full, ymargin=ymargin, charsize=charsize t1='!6F(s) = (2!4p)!e-1/2!n !mi!s!a!e!m' + STRING(36b) t1=t1+'!r!b!i-!m' + STRING(36b) + '!nF(x)e!e-i2!4p!3xs!ndx' if KEYWORD_SET(full) then t1b=t1 else t1b='' if N_ELEMENTS(ymargin) EQ 0 then ymargin=[3,5] if N_ELEMENTS(charsize) EQ 0 then charsize=2. plot, findgen(10), charsize=charsize, /nodata, ymargin=ymargin, $ title=t1, xtitle=t1b, ytitle=t1b, subtitle=t1b xyouts, 0.2, 0.5, charsize=3, t1,/normal xyouts, 1, 2, charsize=2.2, t1,/data end pro titre2 t2='!MI!S!A!E!8x!R!B!Ip!N !7q!Ii!N!8U!S!E2!R!Ii!Ndx' if KEYWORD_SET(full) then t2b=t2 else t2b='' plot, findgen(10),/nodata, ymargin=[3,5], charsize=2, title=t2, $ xtitle=t2b, ytitle=t2b, subtitle=t2b XYOUTS, 0.5, .5, t2, $ charSIZE = 8, /NORMAL end ; ; exemple basic de superposition ; pro titre3 t3='!S!3dessous!rDESSUS n!Son!rOUI' plot, findgen(10), charsize=3, ymargin=[5,8], title=t3 end ; ; les differents indices ... ; pro titre4 t4='!3!n niveauref!LlL!n!DdD!n!IiI!n!AaA!n!BbB!n!EeE!n!UuU!UuU' plot, findgen(10), charsize=3, ymargin=[5,8], title=t4 t4b='!3!n!scou!r!uca !n!scou!r!Lca' plot, findgen(10), charsize=3, ymargin=[5,8], title=t4b end ; ; testing and adjusting aligment ; pro TITRE5, charsize=charsize ; if N_ELEMENTS(charsize) NE 1 then charsize=2 ; title='aAa!iaiA!uaUA!n!iaA!nDD!dadDA!nttt!lalLA!naa' plot, ymargin=[3,6], findgen(10), title=title, charsize=charsize rep='' read, 'suite (rc)', rep ; ; testing the "sub" index capabilities ; title='aAa!iaiA!uaUA!n!iaA!nDD!dadDA!nttt!lalLA!naa' title=title+'!eaa!ubb!ecc!n!daa!euu' plot, ymargin=[3,6], findgen(10), title=title, charsize=charsize rep='' read, 'suite (rc)', rep title='aAa!iaiA!uaUA!n!iaA!nDD!dadDA!nttt!lalLA!naa' plot, ymargin=[3,6], findgen(10), title=title, charsize=charsize end ; ; ---------------------------------------- ; showing the effects of positioning commands (!U, !L, !M ...) ; pro TITLE_FORMATING_EXAMPLE, postscript=postscript, title=title ; if KEYWORD_SET(postscript) then begin set_plot, 'ps' device, filename='title_example.ps' endif ; PcharRef=!p.charsize if (!p.charsize LT 1e-6) then begin !p.charsize=2 print, 'You can play with !p.charsize to test other Char Sizes ...' endif ; if (N_ELEMENTS(title) EQ 0) then begin title='!3RefLevel' title=title+'!LLower!S!EExponent!R!IIndex!N Normal' title=title+'!S!EExp!R!IInd!N!S!U Up!R!D Down!N!S!A Above!R!B Below' endif ; plot, findgen(10), title=title, $ xtitle=title, ytitle=title, subtitle=title ; ; remember size= does not exist in GDL ; XYOUTS, 1, 5, title ; if KEYWORD_SET(postscript) then begin device,/close print, 'PostScript File "title_example.ps" generated' set_plot, 'x' endif ; !p.charsize=PcharRef ; end ; ; ----------------------------------------------- ; AC le 20/01/2008 ; we alway have to check the effect with !p.multi ... ; pro TEST_TITLES_PMULTI, all_titles=all_titles, title=title, help=help ; if KEYWORD_SET(help) then begin print, 'pro TEST_TITLES_PMULTI, all_titles=all_titles, $' print, ' title=title, help=help' print, '' print, 'Advices: we can used external parameters (!p.charsize ...)' print, 'to play with other options' return endif ; device,/decomposed ; if (N_ELEMENTS(title) EQ 0) then title='gaspQWERTYassdsfgagfafd' ; xtitle='' ytitle='' subtitle='' if KEYWORD_SET(all_titles) then begin xtitle=title ytitle=title subtitle=title endif ; window, 0 !p.multi=0 plot, findgen(10), title=title, subtitle=subtitle, xtitle=xtitle, ytitle=ytitle oplot, 10-findgen(10), color='ff'x ; window, 1 !p.multi=[0,2,2] plot, findgen(10), title=title, subtitle=subtitle, xtitle=xtitle, ytitle=ytitle oplot, 10-findgen(10), color='ff'x plot, findgen(10), title=title, subtitle=subtitle, xtitle=xtitle, ytitle=ytitle oplot, 10-findgen(10), color='ff00'x !p.multi=0 end ; ; --------------------------------- ; calling hub ; pro TEST_TITLES, all=all ; s='' TITLE_FORMATING_EXAMPLE READ, 'Please type any key to continue', s ; TEST_TITLES_PMULTI, /all READ, 'Please type any key to continue', s ; TITRE1 READ, 'Please type any key to continue', s ; if NOT(keyword_set(all)) then begin print, 'To go further, you have to run individually the examples' print, 'or to call them via /all keyword' return endif ; TITRE2 READ, 'Please type any key to continue', s ; TITRE3 READ, 'Please type any key to continue', s ; TITRE4 READ, 'Please type any key to continue', s ; TITRE5 READ, 'Please type any key to continue', s ; end gdl-0.9.9/testsuite/test_total.pro000066400000000000000000000253351340051421000172320ustar00rootroot00000000000000; ; Initial author : P. Chanial 2006.01.17 ; Code under GNU GPL V2 or later ; ; NOTA BENE : AC, 9 Feb. 2018 : unfinished modifs and extensions ; Some changes need in source code (basic_fun.cpp) ; ; --------------------------------------- ; Modifications history : ; ; - 2018-FEB-04 : AC. Corrected "bug" when cumulating large number ; of byte ... large rewriting, trying to automatic ; and to have numerical cases at the limits ... ; ; --------------------------------------- ; Script : regression-total pro regression, a ; ; AC 2018 March : this part of the test should be recycle ... TODO !!! ; print, 'Testing '+size(a, /tname)+':' ; help, total(a), total(a, /NaN), total(a, /cumul), total(a, /cumul, /NaN), output = output ; print, output ; help, total(a, /double), total(a, /NaN, /double), total(a, /cumul, /double), total(a, /cumul, /NaN, /double), output=output ; print, output ; help, total(a, 1), total(a, 1, /NaN), total(a, 1, /cumul), total(a, 1, /cumul, /NaN), output=output ; print, output ; help, total(a, 1, /double), total(a, 1, /NaN, /double), total(a, 1, /cumul, /double), total(a, 1, /cumul, /NaN, /double), output=output ; print, output ; help, total(a, 2), total(a, 2, /NaN), total(a, 2, /cumul), total(a, 2, /cumul, /NaN), output=output ; print, output ; help, total(a, 2, /double), total(a, 2, /NaN, /double), total(a, 2, /cumul, /double), total(a, 2, /cumul, /NaN, /double), output=output ; print, output ; help, total(a, 3), total(a, 3, /NaN), total(a, 3, /cumul), total(a, 3, /cumul, /NaN), output=output ; print, output ; help, total(a, 3, /double), total(a, 3, /NaN, /double), total(a, 3, /cumul, /double), total(a, 3, /cumul, /NaN, /double), output=output ; print, output print, '-- 1' & print, total(a) print, '-- 2' & print, total(a, /NaN) print, '-- 3' & print, total(a, /cumul) print, '-- 4' & print, total(a, /cumul, /NaN) print, '-- 5' & print, total(a, /double) print, '-- 6' & print, total(a, /NaN, /double) print, '-- 7' & print, total(a, /cumul, /double) print, '-- 8' & print, total(a, /cumul, /NaN, /double) print, '===========================================' print, '-- 9' & print, total(a, 1) print, '-- 10' & print, total(a, 1, /NaN) print, '-- 11' & print, total(a, 1, /cumul) print, '-- 12' & print, total(a, 1, /cumul, /NaN) print, '-- 13' & print, total(a, 1, /double) print, '-- 14' & print, total(a, 1, /NaN, /double) print, '-- 15' & print, total(a, 1, /cumul, /double) print, '-- 16' & print, total(a, 1, /cumul, /NaN, /double) print, '===========================================' print, '-- 17' & print, total(a, 2) print, '-- 18' & print, total(a, 2, /NaN) print, '-- 19' & print, total(a, 2, /cumul) print, '-- 20' & print, total(a, 2, /cumul, /NaN) print, '-- 21' & print, total(a, 2, /double) print, '-- 22' & print, total(a, 2, /NaN, /double) print, '-- 23' & print, total(a, 2, /cumul, /double) print, '-- 24' & print, total(a, 2, /cumul, /NaN, /double) print, '===========================================' print, '-- 25' & print, total(a, 3) print, '-- 26' & print, total(a, 3, /NaN) print, '-- 27' & print, total(a, 3, /cumul) print, '-- 28' & print, total(a, 3, /cumul, /NaN) print, '-- 29' & print, total(a, 3, /double) print, '-- 30' & print, total(a, 3, /NaN, /double) print, '-- 31' & print, total(a, 3, /cumul, /double) print, '-- 32' & print, total(a, 3, /cumul, /NaN, /double) end pro TEST_TOTAL_NAN_INF, cumul_errors, test=test, verbose=verbose ; print, 'AC 2018 March : this part of the test should be recycle ... TODO !!!' ;BANNER_FOR_TESTSUITE, pref='TEST_TOTAL_NAN_INF', 'unfinished !', 1000 ; unfinished ! return ;; we need a way to know whether IDL or GDL is running... DEFSYSV, '!gdl', exists=isGDL ;filename = (isGDL?'gdl':'idl'+strtrim(!version.release,1))+$ ; '-test-total.txt' ;journal, filename a = bytarr(3, 3, 3)+1b regression, a a = findgen(3, 3, 3) a[0,0,0] = !values.f_nan a[1,1,0] = !values.f_infinity a[2,1,0] = -!values.f_infinity a[0,2,1] = !values.f_nan a[2,0,2] = !values.f_nan regression, a a = dindgen(3, 3, 3) a[0,0,0] = !values.d_nan a[0,1,1] = !values.d_infinity a[2,0,1] = -!values.d_infinity a[0,2,1] = !values.d_nan a[2,2,2] = !values.d_nan regression, a a = complexarr(3, 3, 3)+1 a[0,0,0] = complex(3, !values.f_nan) a[1,1,0] = complex(!values.f_nan, !values.f_infinity) a[2,1,0] = complex(0, -!values.f_infinity) a[0,2,1] = complex(78, !values.f_nan) a[2,0,2] = complex(!values.f_infinity, 40) regression, a a = dcomplexarr(3, 3, 3)+1 a[0,0,0] = complex(3, !values.d_nan) a[1,1,0] = complex(!values.d_nan, !values.d_infinity) a[2,1,0] = complex(0, -!values.d_infinity) a[0,2,1] = complex(78, !values.d_nan) a[2,0,2] = complex(!values.d_infinity, 40) regression, a ; journal end ; ; ----------------------------------------------------------------- ; pro TEST_TOTAL_LARGE, cumul_errors, test=test, verbose=verbose ; ;BANNER_FOR_TESTSUITE, pref='TEST_TOTAL_LARGE', 'unfinished !', 1000 ;return ; errors=0 kk=1 for ii=0, 7 do begin ;; internal=0 ;; kk=10L*kk a=LINDGEN(kk) res1=TOTAL([a,-a],/int) res2=TOTAL([a,-a]) tmp=TOTAL([a,-a],/int,/cumul) res3=tmp[-1] ; last value tmp=TOTAL([a,-a],/cumul);,/dou) res4=tmp[-1] ; last value ;; if ~ARRAY_EQUAL(0ll, res1, /no_type) then $ ERRORS_ADD, internal, 'res 1, kk='+string(kk) if ~ARRAY_EQUAL(0ll, res3, /no_type) then $ ERRORS_ADD, internal, 'res 3, kk='+string(kk) if ~ARRAY_EQUAL(0., res2, /no_type) then $ ERRORS_ADD, internal, 'res 2, kk='+string(kk) ;; we cannot test on "res4", just to show the problem if KEYWORD_SET(verbose) then print, kk, res1, res2, res3, res4 ;; ERRORS_CUMUL, errors, internal ;; endfor ; ; https://sourceforge.net/p/gnudatalanguage/bugs/593/ ; showing Float conversion tricks ... ; (computations are OK, print seems to be not OK if bad format) ; res_f=17865335. res_d=17865335d res_l=17865335l res_l64=17865335ll ; a=[8926507,8938828,0] if ~ARRAY_EQUAL(TOTAL(a), res_f, /no_type) then $ ERRORS_ADD, errors, 'case 3 Long to Float' if ~ARRAY_EQUAL(TOTAL(a,/double), res_d, /no_type) then $ ERRORS_ADD, errors, 'case 3 Long to Double' if ~ARRAY_EQUAL(TOTAL(a,/int), res_l64, /no_type) then $ ERRORS_ADD, errors, 'case 3 Long to /int Long64' if ~ARRAY_EQUAL(TOTAL(a,/preserve), res_l, /no_type) then $ ERRORS_ADD, errors, 'case 3 Long to /pre Long' ; ; playing with big values in "special" type ; grand=80000000ll ; ; res=grand*(grand-1)/2 ; res_f=3199999960000000. res_d=3199999960000000.d res_l64=3199999960000000 res_ul=216376832ul if ~ARRAY_EQUAL(TOTAL(ULINDGEN(grand)), res_f, /no_type) then $ ERRORS_ADD, errors, 'case default in ULong' if ~ARRAY_EQUAL(TOTAL(ULINDGEN(grand), /double), res_d, /no_type) then $ ERRORS_ADD, errors, 'case ULong Double' if ~ARRAY_EQUAL(TOTAL(ULINDGEN(grand),/pres), res_ul, /no_type) then $ ERRORS_ADD, errors, 'case ULong ULong' if ~ARRAY_EQUAL(TOTAL(ULINDGEN(grand),/int), res_l64, /no_type) then $ ERRORS_ADD, errors, 'case ULong Long64' ; ; cf mail @ Gilles ; ; -------------- ; BANNER_FOR_TESTSUITE, "TEST_TOTAL_LARGE", errors, /short, verb=verbose ERRORS_CUMUL, cumul_errors, errors if KEYWORD_SET(test) then STOP ; end ; pro TEST_TOTAL_INT, cumul_errors, test=test, verbose=verbose, debug=debug ; offset=201b nbps=0 ; dims=[3,4,5] muldims=PRODUCT(dims, /integer) in=BYTARR(dims) in=in+offset ; GIVE_LIST_NUMERIC, list_num_types, list_num_names, /integer ; exp1f_ref=FLOAT(muldims)*FLOAT(offset) exp1int_ref=muldims*LONG64(offset) ; exp1intc = [$ [ [201.,402.,603.], [804.,1005.,1206.], [1407.,1608.,1809.], [2010.,2211.,2412.] ], $ [ [2613.,2814.,3015.], [3216.,3417.,3618.], [3819.,4020.,4221.], [4422.,4623.,4824.] ], $ [ [5025.,5226.,5427.], [5628.,5829.,6030.], [6231.,6432.,6633.], [6834.,7035.,7236.] ], $ [ [7437.,7638.,7839.], [8040.,8241.,8442.], [8643.,8844.,9045.], [9246.,9447.,9648.] ], $ [ [9849.,10050.,10251.], [10452.,10653.,10854.], [11055,11256,11457.], [11658.,11859.,12060.] ]$ ] ;exp1intc = LON64ARR(dims) exp1fc = FIX(exp1intc, type=FLOAT) exp1intc = FIX(exp1intc, type=LONG64) for ii=0, N_ELEMENTS(list_num_types)-1 do begin ;; internal=nbps ;; type=list_num_types[ii] name=list_num_names[ii] input=FIX(in, type=type) exp1pres=FIX(exp1int_ref, type=type) exp1presc=FIX(exp1intc, type=type) res1f=TOTAL(input) res1int=TOTAL(input,/int) res1pres=TOTAL(input,/preserve) res1fc=TOTAL(input,/cumulative) res1intc=TOTAL(input,/int,/cumulative) res1presc=TOTAL(input,/preserve,/cumulative) exp1fc = FLOAT(exp1intc) exp1intc = LONG64(exp1intc) ;; ;; few special cases exp1f=exp1f_ref exp1int=exp1int_ref if type GE 14 then exp1f=DOUBLE(exp1f_ref) if type EQ 15 then exp1int=ULONG64(exp1int_ref) if type GE 14 then exp1fc=DOUBLE(exp1fc) if type EQ 15 then exp1intc=ULONG64(exp1intc) ;; if KEYWORD_SET(verbose) then begin print, 'Exp: ', name, exp1f, exp1int, exp1pres print, 'Res: ', name, res1f, res1int, res1pres endif if ~ARRAY_EQUAL(res1f, exp1f, /no_type) then $ ERRORS_ADD, nbps, 'res 1 F Type='+name if ~ARRAY_EQUAL(res1int, exp1int, /no_type) then $ ERRORS_ADD, nbps, 'res 1 /Int Type='+name if ~ARRAY_EQUAL(res1pres, exp1pres, /no_type) then $ ERRORS_ADD, nbps, 'res 1 /Pres Type='+name if ~ARRAY_EQUAL(res1fc, exp1fc, /no_type) then $ ERRORS_ADD, nbps, 'res 1 /cumulative Type='+name if ~ARRAY_EQUAL(res1intc, exp1intc, /no_type) then $ ERRORS_ADD, nbps, 'res 1 /int /cumulative Type='+name if ~ARRAY_EQUAL(res1presc, exp1presc, /no_type) then $ ERRORS_ADD, nbps, 'res 1 /preserve /cumulative Type='+name ;; if KEYWORD_SET(debug) then if nbps GT internal then stop endfor ; ; ----- final ---- ; BANNER_FOR_TESTSUITE, 'TEST_TOTAL_INT', nbps, /short ERRORS_CUMUL, cumul_errors, nbps if KEYWORD_set(test) then STOP ; end ; pro TEST_TOTAL_COMPLEX, cumul_errors, test=test, verbose=verbose nbps=0 r = [1,2,3] i = [4,5,6] c = COMPLEX(r, i) tot = total(c, /cumulative) BANNER_FOR_TESTSUITE, 'TEST_TOTAL_COMPLEX', nbps, /short ERRORS_CUMUL, cumul_errors, nbps if KEYWORD_set(test) then STOP ; end ; ----------------------------------------------------------------- ; pro TEST_TOTAL, help=help, test=test, verbose=verbose, no_exit=no_exit ; if KEYWORD_SET(test) then begin print, 'pro TEST_TOTAL, help=help, test=test, verbose=verbose, no_exit=no_exit' return endif ; cumul_errors=0 ; TEST_TOTAL_NAN_INF, cumul_errors, test=test, verbose=verbose ; TEST_TOTAL_LARGE, cumul_errors, test=test, verbose=verbose ; TEST_TOTAL_INT, cumul_errors, test=test, verbose=verbose ; ; ----------------- final message ---------- ; BANNER_FOR_TESTSUITE, 'TEST_TOTAL', cumul_errors, short=short ; if (cumul_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_triangulate.pro000066400000000000000000000042311340051421000204160ustar00rootroot00000000000000; ; AC 11/11/2016 ; Very preliminary tests on TRIANGULATE, TRIGRID, ... ; ; ---------------------- ; ; Regridding a Gaussian computed on a Spiral ... ; pro TEST_GAUSS2D_ON_SPIRAL, nbp, no_display=no_display, no_fit=no_fit, $ help=help, verbose=verbose, test=test, $ no_wait=no_wait, benchmark=benchmark ; if KEYWORD_SET(benchmark) then TIC ; if N_PARAMS() LT 1 then nbp=1000 if nbp LT 10 then nbp=1000 ; ; waiting time if ~KEYWORD_SET(no_wait) then wait=1. else wait=no_wait ; t=100.*FINDGEN(nbp)/nbp x=t*COS(t) y=t*SIN(t) z=EXP(-(x^2+y^2)/1000) ; TRIANGULATE, x, y, tr ; if KEYWORD_SET(benchmark) then begin TOC & print, 'After TRIANGULATE and before TRIGRID' & TIC endif ; trigrid_gauss2d=TRIGRID(x, y, z, tr) ; if KEYWORD_SET(benchmark) then begin TOC & print, 'After TRIGRID and before Gauss 2D FIT (if)' & TIC endif ; WINDOW, xsize=1000, ysize=500 !p.multi=[0,2,0] ; PLOT, x, y, psym=-1, symsize=0.3, /iso, title=STRING(nbp)+ ' npbs in Spiral' SURFACE, trigrid_gauss2d ; if ~KEYWORD_SET(no_fit) then begin ;; is_code_around=EXECUTE("a=GAUSS2DFIT(RANDOMU(seed, 12,12))") if is_code_around then begin g=GAUSS2DFIT(trigrid_gauss2d, g_params) print, g_params endif if KEYWORD_SET(benchmark) then begin TOC & print, 'After Gauss 2D FIT (if)' & TIC endif endif ; if ~KEYWORD_SET(no_wait) then wait=1. else wait=no_wait if (wait GT 0) then WAIT, wait ; if KEYWORD_SET(test) then STOP ; end ; pro TEST_TRIANGULATE, help=help, test=test, verbose=verbose, benchmark=benchmark, $ no_exit=no_exit, no_display=no_display ; if KEYWORD_SET(help) then begin print, 'pro TEST_TRIANGULATE, help=help, test=test, verbose=verbose, benchmark=benchmark, $' print, ' no_exit=no_exit, no_display=no_display' return endif ; TEST_GAUSS2D_ON_SPIRAL, 100, no_display=no_display, $ benchmark=benchmark, no_fit=no_fit ; TEST_GAUSS2D_ON_SPIRAL, 1000, no_display=no_display, $ benchmark=benchmark, no_fit=no_fit ; TEST_GAUSS2D_ON_SPIRAL, 10000, no_display=no_display, $ benchmark=benchmark, no_fit=no_fit ; end gdl-0.9.9/testsuite/test_trisol.pro000066400000000000000000000031731340051421000174170ustar00rootroot00000000000000; ; Alain Coulais, 03 Fevrier 2012, ; under GNU GPL v2 or later ; ; basic tests for TRISOL ; pro TEST_TRISOL, double=double, verbose=verbose, $ help=help, test=test, debug=debug ; if KEYWORD_SET(help) then begin print, 'pro TEST_TRISOL, double=double, verbose=verbose, $' print, ' help=help, test=test, debug=debug' return endif ; ; Define Sub Diag Vect. containing the sub-diagonal elements ; with a strarting 0.0 element: subdiag=REPLICATE(1.0,4)*2. subdiag[0]=0.0 ; ; Define "diag" containing the main diagonal elements: diag=REPLICATE(-4.0,4) ; ; Define Sup Diag Vect. containing the super-diagonal elements ; with a trailing 0.0 element: supdiag=REPLICATE(1.0,4) supdiag[-1]=0.0 ; ; Define the right-hand side vector: RHSvect = [6.0, -8.0, -5.0, 8.0] ; ; Compute the solution and print: result = TRISOL(subdiag*1D, diag*1D, supdiag*1D, RHSvect*1D, double=double) ;result = TRISOL(subdiag, diag, supdiag, RHSvect, double=double) PRINT, result ; TheMatrix=DIAG_MATRIX(diag) TheMatrix=TheMatrix+DIAG_MATRIX(subdiag[1:*],-1) TheMatrix=TheMatrix+DIAG_MATRIX(supdiag[0:-1-1],1) if KEYWORD_SET(debug) then begin print, TheMatrix endif ; LHSvect=TheMatrix##result error=TOTAL((LHSvect-RHSvect)^2) ; if (error GT 1e-10) then begin if KEYWORD_SET(test) then STOP ;; please notice the error may also come from other parts of codes ;; (e.g. bug in DIAG_MATRIX) MESSAGE, /continue, 'Numerical error founded.' EXIT, status=1 endif else begin if ~KEYWORD_SET(verbose) then begin MESSAGE, /continue, 'TRISOL succesfully tested' endif endelse ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_tv.pro000066400000000000000000000153701340051421000165360ustar00rootroot00000000000000; ; Alain C. 24/Feb/2009 ; fast way to check whether TV works in all cases of permutation in [1,N,M] ; ; Modifications history : ; ; * AC 2016-03-03 : merging TEST_TV_DAMIER and TEST_TV_DAMIER_COLOR, ; adding tic/toc to check X11 bottleneck(s) on network (remote TV/plot ; are too slow) ; * AC 2017-08-17 : details when files missing, errors count, banner ... ; * AC 2018-01-09 : clarifying details, should extendable easily for bench ; * AC 2018-10-24 : should work now with X11, Win & Mac ... ; function TITLE4TEST_TV, data, debug=debug ; if KEYWORD_SET(debug) then print, 'Size: ', SIZE(data) ; sep=',' if ((SIZE(data))(0) EQ 2) then begin x=(SIZE(data))(1) y=(SIZE(data))(2) return, STRCOMPRESS('['+STRING(x)+sep+STRING(y)+']') endif if ((SIZE(data))(0) EQ 3) then begin x=(SIZE(data))(1) y=(SIZE(data))(2) z=(SIZE(data))(3) sep=',' return, STRCOMPRESS('['+STRING(x)+sep+STRING(y)+sep+STRING(z)+']') endif print, 'Fatal: we should never be here !' STOP end ; ------------------------------------- ; pro MY_WINDOW, indice, data ; tmp_data=REFORM(data) xdim=(SIZE(tmp_data))(1) ydim=(SIZE(tmp_data))(2) ; ;print, xdim, ydim yoffset=50+indice*(ydim+20) xoffset=10 ; WINDOW, indice, title=STRING(indice)+' '+TITLE4TEST_TV(data), $ xpos=xoffset, ypos=yoffset, xsize=xdim, ysize=ydim TVSCL, data ; end ; ; ------------------------------------- ; We need to test that when changing the color table, ; this table will be propagated in other windows ; when they will be active via WSET ; pro TEST_TV_WSET, cumul_errors, test=test ; ; Read "Saturn.jpg" and return content in "image" status=GET_IMAGE_FOR_TESTSUITE(image) if (status eq 0) then begin ERRORS_CUMUL, cumul_errors, 0 return endif ; xdim=(SIZE(image))(2) ydim=(SIZE(image))(3) ; this test, as it is now, is wrong when the screen is too small (use ; Xvfb :1 -screen 0 1024x768x24 & for example) ; I return if window sizes are too big DEVICE, get_screen_size=scrsize scrsizex=scrsize[0] scrsizey=scrsize[1] if (2*xdim ge scrsizex or 3*ydim ge scrsizey) then begin print,"test TEST_TV_WSET not executed, screen size to small (FIXME)" return end ; image=TOTAL(image,1) ; DEVICE, decomposed=0 ; LOADCT, 13 ; WINDOW, 0, xsize=xdim, ysize=3*ydim WINDOW, 2, xsize=xdim, ysize=3*ydim ; WSET, 0 ; TV, image, 0 LOADCT, 20 TV, image, 1 LOADCT, 30 TV, image, 2 ; ; switching to window 2 WSET, 2 TV, image, 2 LOADCT, 20 TV, image, 1 LOADCT, 13 TV, image, 0 ; ; reading contents of the 2 windows : should have the same ; content_win2=TVRD() ; WSET, 0 content_win0=TVRD() ; local_error=0 if ~ARRAY_EQUAL(content_win0,content_win2) then local_error++ ; ERRORS_CUMUL, cumul_errors, local_error ; BANNER_FOR_TESTSUITE, "TEST_TV_WSET", local_error, /SHORT ; if KEYWORD_SET(test) then STOP ; end ; ; ------------------------------------- ; pro TEST_TV_DAMIER, numwin, color=color, benchmark=benchmark, $ nb_cells_max=nb_cells_max, silent=silent, $ test=test, debug=debug, help=help ; if KEYWORD_SET(help) then begin print, 'pro TEST_TV_DAMIER, numwin, color=color, benchmark=benchmark, $' print, ' nb_cells_max=nb_cells_max, silent=silent, $' print, ' test=test, debug=debug, help=help' print, '' print, 'Three levels of time benchmarking : 0 no, =1 global, =2 detail' return end ; if ~ISA(silent) then silent=1 ; ; AC 2016-04-14 : seems not to be useful ; AC 2017-01-11 : useful now ! better support of DEVICE, decomposed=0|1 if KEYWORD_SET(color) then DEVICE, decomposed=0 ; ; Three levels of time benchmarking : 0 non, 1 global, 2 detail ; if KEYWORD_SET(benchmark) then begin t_glob=TIC('global') endif else begin benchmark=0 endelse ; if N_PARAMS() EQ 0 then numwin=0 ; units=64 nbx=10 nby=8 WINDOW, numwin, xsi=units*nbx, ysi=units*nby ; ; AC 2016-04-14 useful to have W&B reproducible ! LOADCT, 0 ; vignette=DIST(units) ; offset_line=0 nb_cells=nbx*nby if KEYWORD_SET(nb_cells_max) then begin if (nb_cells_max GT 0) AND (nb_cells_max LT nb_cells/2) then begin nb_cells=nb_cells_max*2 endif endif ; for ii=0, (nb_cells/2-1) do begin offset_line=(ii / (nbx/2)) mod 2 if KEYWORD_SET(debug) then print, ii, offset_line, 2*ii+offset_line ;; ;; loading here color table if needed if KEYWORD_SET(color) then begin if (benchmark GT 1) then begin print, 'Before loading Color Table ' TIC endif LOADCT, ii, silent=silent if (benchmark GT 1) then TOC endif ;; if (benchmark GT 1) then begin print, 'Before TVSCL' TIC endif TVSCL, vignette, 2*ii+offset_line if (benchmark GT 1) then TOC endfor ; if KEYWORD_SET(benchmark) then TOC, t_glob ; BANNER_FOR_TESTSUITE, "TEST_TV_DAMIER", 0, /SHORT ; if KEYWORD_SET(test) then STOP ;; end ; ; ------------------------------------- ; pro TEST_TV_OVER_BOX ; ; Read "Saturn.jpg" and return content in "image" status=GET_IMAGE_FOR_TESTSUITE(image) if (status eq 0) then return ; redChannel = REFORM(image[0, *, *]) greenChannel = REFORM(image[1, *, *]) blueChannel = REFORM(image[2, *, *]) ; aa=FINDGEN(32) WINDOW,11 LOADCT,13 ; plot,aa,back=88 tv, redChannel,0,CHAN=1 tv, redChannel,0,0,/DATA,CHAN=1 tv, greenChannel,0,CHAN=2 tv, greenChannel,10,10,/DATA,CHAN=2 tv, blueChannel,0,CHAN=3 tv, blueChannel,20,20,/DATA,CHAN=3 WINDOW,12 !P.MULTI=[0,3,2] for i=0,5 do begin plot,aa TV, image, 10,10,/DATA,/true,xsize=50 end !P.MULTI=0 ; BANNER_FOR_TESTSUITE, "TEST_TV_OVER_BOX", 0, /SHORT ; end ; ; ------------------------------------- ; should display (from bottom on the left) 6 small windows in grey ; pro TEST_TV_REFORM ; DEVICE, /decomposed ; xdim=350 ydim=100 ; yoffset=FINDGEN(7)*ydim xoffset=REPLICATE(0,7) ; a=DIST(xdim, ydim) b1=REFORM(a,1, xdim, ydim) b2=REFORM(a,xdim, 1, ydim) b3=REFORM(a,xdim, ydim, 1) ; MY_WINDOW, 0, a MY_WINDOW, 1, b1 MY_WINDOW, 2, REFORM(b1) MY_WINDOW, 3, b2 MY_WINDOW, 4, REFORM(b2) MY_WINDOW, 5, b3 MY_WINDOW, 6, REFORM(b3) ; BANNER_FOR_TESTSUITE, "TEST_TV_REFORM", 0, /SHORT ; end ; ; ------------------------------------- ; pro TEST_TV, help=help, test=test, no_exit=no_exit ; if KEYWORD_SET(help) then begin print, 'pro TEST_TV, help=help, test=test, no_exit=no_exit' return endif ; rname=ROUTINE_NAME() ; if ~CHECK_IF_DEVICE_IS_OK(rname, /force) then begin if ~KEYWORD_SET(no_exit) then EXIT, status=77 else STOP endif ; TEST_TV_REFORM ; TEST_TV_DAMIER, 8 TEST_TV_DAMIER, 9, /COLOR ; TEST_TV_OVER_BOX ; ; only this test gives a feedback now TEST_TV_WSET, errors ; ;stop if ~KEYWORD_SET(no_exit) then while !d.window GE 0 do WDELETE print, 'You can use keyword /No_Exit to de-activate auto closing' ; ; ----------------- final message ---------- ; BANNER_FOR_TESTSUITE, 'TEST_TV', errors ; if (errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_tvlct.pro000066400000000000000000000016461340051421000172420ustar00rootroot00000000000000; ; AC, 05-Feb-2012 ; ; Testing if TVLCT is working ... ; pro GENERATE_COLORS, nbp, r, g, b ; r=BYTSCL(SIN(FINDGEN(nbp)*!pi/nbp*10)) g=BYTSCL(SIN(FINDGEN(nbp)*!pi/nbp*30)) b=BINDGEN(nbp) ; end ; pro TEST_TVLCT ; ; direct switch into True Color mode DEVICE, decomposed=0 ; nbp=256 x_pos=10 y_pos=500 offset=nbp ; GENERATE_COLORS, nbp, r, g, b ; WINDOW, 0, title='TVLCT, R,G,B', $ xpos=x_pos, ypos=y_pos, xsize=nbp, ysize=nbp TVLCT, r, g, b TV, DIST(nbp) ; ; permutation WINDOW, 1, title='TVLCT, B,R,G', $ xpos=x_pos+offset, ypos=y_pos, xsize=nbp, ysize=nbp TVLCT, b, r, g TV, DIST(nbp) ; ; vectors ; ; reset to basic RGB WINDOW, 2, title='TVLCT, [R, G, B]', $ xpos=x_pos, ypos=y_pos-offset, xsize=nbp, ysize=nbp TVLCT, [[r],[g],[b]] TV, DIST(nbp) ; ; permutation WINDOW, 3, title='TVLCT, [B, G, R]', $ xpos=x_pos+offset, ypos=y_pos-offset, xsize=nbp, ysize=nbp TVLCT, [[b],[r],[g]] TV, DIST(nbp) ; end gdl-0.9.9/testsuite/test_typename.pro000066400000000000000000000062771340051421000177350ustar00rootroot00000000000000; ; Alain C., 2014/03/27 ; ; very basic tests for TYPENAME() function ; 3 types (Obj, Struct, Pointer) are not ready at all) ; ; --------------------------------- ; Modifications history : ; ; 2018-Feb-02: AC. tests should now cover the 4 cases for Structures ; ; --------------------------------- ; pro TEST_TYPENAME, help=help, test=test, verbose=verbose, no_exit=no_exit ; if KEYWORD_SET(help) then begin print, 'pro TEST_TYPENAME, help=help, test=test, verbose=verbose, no_exit=no_exit' return endif ; nb_errors=0 ; if (TYPENAME(a_undef) NE "UNDEFINED") then ERRORS_ADD, nb_errors, 'bad type with UNDEFINED' ; a=!null if (TYPENAME(a) NE "UNDEFINED") then ERRORS_ADD, nb_errors, 'bad type with !NULL' ; if (TYPENAME(1b) NE "BYTE") then ERRORS_ADD, nb_errors, 'bad type with BYTE' if (TYPENAME(1) NE "INT") then ERRORS_ADD, nb_errors, 'bad type with INT' if (TYPENAME(LONG(1)) NE "LONG") then ERRORS_ADD, nb_errors, 'bad type with LONG' if (TYPENAME(1.) NE "FLOAT") then ERRORS_ADD, nb_errors, 'bad type with FLOAT' if (TYPENAME(1.D) NE "DOUBLE") then ERRORS_ADD, nb_errors, 'bad type with DOUBLE' if (TYPENAME(complex(1.,0)) NE "COMPLEX") then ERRORS_ADD, nb_errors, 'bad type with COMPLEX' if (TYPENAME(dcomplex(1.,0)) NE "DCOMPLEX") then ERRORS_ADD, nb_errors, 'bad type with DCOMPLEX' if (TYPENAME(1l) NE "LONG") then ERRORS_ADD, nb_errors, 'bad type with LONG' if (TYPENAME(1ll) NE "LONG64") then ERRORS_ADD, nb_errors, 'bad type with LONG64' if (TYPENAME(1ul) NE "ULONG") then ERRORS_ADD, nb_errors, 'bad type with ULONG' if (TYPENAME(1ull) NE "ULONG64") then ERRORS_ADD, nb_errors, 'bad type with ULONG64' ; if (TYPENAME(HASH([1,2,3])) NE "HASH") then ERRORS_ADD, nb_errors, 'bad type with HASH' if (TYPENAME(LIST(1,2,3)) NE "LIST") then ERRORS_ADD, nb_errors, 'bad type with LIST' ; ; this class should be in the GDL_PATH, or in src/pro/dicom ; res=EXECUTE("tmp=OBJ_NEW('gdlffdicom')") if res EQ 0 then begin MESSAGE, /continue, 'skipping test on OBJ_NEW' MESSAGE, /continue, 'please check whether "gdlffdicom" class is in the path ...' endif else begin if (TYPENAME(tmp) NE "GDLFFDICOM") then ERRORS_ADD, nb_errors, 'bad type with Dicom Obj' endelse ; ; structures : 4 cases to be tested : array or not, ANONYMOUS or NAMED ; txt='bad type with Structure : ' struct_anon={aa:1} if (TYPENAME(struct_anon) NE "ANONYMOUS") then ERRORS_ADD, nb_errors, txt+'ANONYMOUS' struct_name={gdltest,aaa:1} if (TYPENAME(struct_name) NE "GDLTEST") then ERRORS_ADD, nb_errors, txt+'NAME' ; struct_anon_arr=REPLICATE({zz1:1},10) if (TYPENAME(struct_anon_arr) NE "STRUCT") then ERRORS_ADD, nb_errors, txt+'ANONYMOUS (array)' struct_name_arr=REPLICATE({gdl_arr,zz2:2},10) if (TYPENAME(struct_name_arr) NE "STRUCT") then ERRORS_ADD, nb_errors, txt+'NAME (array)' if (TYPENAME(struct_name_arr[*]) NE "STRUCT") then ERRORS_ADD, nb_errors, txt+'NAME (array[*])' ; expect='GDL_ARR' ; name of the fiels in the array struct. for ii=0, n_elements(STRUCT_NAME_ARR)-1 do $ if (TYPENAME(struct_name_arr[ii]) NE expect) then ERRORS_ADD, nb_errors, txt+'sub NAME at '+string(ii) ; ; ---- Final message ---- ; BANNER_FOR_TESTSUITE, 'TEST_TYPENAME', nb_errors ; if (nb_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_uf77.pro000066400000000000000000000024351340051421000166730ustar00rootroot00000000000000; ; AC, le 21/02/2006, MaJ le 10/10/2006 ; ; write a 2D array mixing Int and Float ; then read back the array ; Can be used to check if f77u is OK between differents computers ; pro TEST_UF77, nbp=nbp, test=test, help=help, $ reread=reread, filename=filename ; if KEYWORD_SET(help) then begin print, 'pro TEST_UF77, nbp=nbp, test=test, help=help, $' print, ' reread=reread, filename=filename' print, '' print, '/reread --> only read back the binary file' print, 'filename= --> change filename' print, 'nbp= --> chnage array size' return endif ; if (N_ELEMENTS(nbp) NE 1) then nbp=128 ; if (N_ELEMENTS(filename) NE 1) then begin filename='test_u77.bindata' print, 'Default file name is : ', filename endif ; ; de temps en temps, up, un petit Goto ! ; if KEYWORD_SET(reread) then goto, label_reread ; ; ecriture du fichier ; get_lun, nblun openw, nblun, filename writeu, nblun, nbp writeu, nblun, dist(nbp) close, nblun free_lun, nblun ; print, 'Writing is done, file name is :', filename ; label_reread: ; ; relecture du ficheir ; get_lun, nblun openr, nblun, filename readu, nblun, nbp data=fltarr(nbp, nbp) readu, nblun, data close, nblun free_lun, nblun ; print, 'Reading is done' ; TVSCL, data ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_valgrind.pro000066400000000000000000000032121340051421000177030ustar00rootroot00000000000000; ; AC at LAX, 29/09/2009 ; ; How to have systematic tests with valgring ? ; ; pro VALGRIND_INIT_ARRAYS, nbp=nbp, x, y, x_v, y_v, data ; if N_ELEMENTS(nbp) EQ 0 then nbp=100 ; xnbp=nbp ynbp=xnbp ; data=DIST(xnbp, ynbp) x=FINDGEN(xnbp) y=FINDGEN(ynbp) ; x_v=x#REPLICATE(1.,ynbp) y_v=REPLICATE(1.,xnbp)#y ; end ; pro VALGRIND_CONTOUR, nbp=nbp, level=level, test=test, quiet=quiet ; if N_ELEMENTS(level) EQ 0 then return if (level LE 0) OR (level GT 3) then return ; VALGRIND_INIT_ARRAYS, nbp=nbp, x, y, x_v, y_v, data ; if NOT(KEYWORD_SET(quiet)) then print, 'Begin of VALGRIND_CONTOUR with level=', level ; if (level EQ 1) then CONTOUR, data if (level EQ 2) then CONTOUR, data, x, y if (level EQ 3) then CONTOUR, data, x_v, y_v ; if KEYWORD_SET(test) then STOP ; if NOT(KEYWORD_SET(quiet)) then print, 'End of VALGRIND_CONTOUR' ; end ; pro VALGRIND_SURFACE, nbp=nbp, level=level, test=test, quiet=quiet ; if N_ELEMENTS(level) EQ 0 then return if (level LE 0) OR (level GT 3) then return ; VALGRIND_INIT_ARRAYS, nbp=nbp, x, y, x_v, y_v, data ; if NOT(KEYWORD_SET(quiet)) then print, 'Begin of VALGRIND_SURFACE with level=', level ; if (level EQ 1) then SURFACE, data if (level EQ 2) then SURFACE, data, x, y if (level EQ 3) then SURFACE, data, x_v, y_v ; if KEYWORD_SET(test) then STOP ; if NOT(KEYWORD_SET(quiet)) then print, 'End of VALGRIND_SURFACE' ; end ; pro TEST_VALGRIND, nbp=nbp, quiet=quiet print, 'Some tests for Valgrind (usage: valgrind path/to/gdl)' print, 'don''t forgot that when a flag is set, problem is not more displayed' ; for ii=1,3 do VALGRIND_SURFACE, nbp=nbp, quiet=quiet, level=ii for ii=1,3 do VALGRIND_CONTOUR, nbp=nbp, quiet=quiet, level=ii end gdl-0.9.9/testsuite/test_voigt.pro000066400000000000000000000174731340051421000172430ustar00rootroot00000000000000; NG 27/05/2008 ; test procedures for Intrinsic GDL voigt function ; If you find bugs, limitations, other interresting cases, ; please report them to Alain Coulais : alaingdl@users.sourceforge.net ;-------------------------------------------------------------------- ; ; I-Compatibility with IDL syntax ; II-Plot of voigt function ; III-Comparison with Armstrong et al. VOIGT values ; IV-Test with negative numbers ; V-Test with not a number and infinite values ; ;----------------------------------------------------------------------- ; I-Compatibility with IDL syntax ;----------------------------------------------------------------------- pro test_voigt_behaviour ; ;1. "arguments are both scalars" (take a look at III-Comparison with Armstrong) ; print,'------------------------------------------------------------' print,'If both arguments are scalars, the function returns a scalar' print,'------------------------------------------------------------' print,'A = 1.705 et U = 0.04' A=1.705 U=0.04 r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r ;2. "arguments are both arrays" print,'-----------------------------------------------------------------------------' print,'If both arguments are arrays returns array with the smallest array dimensions' print,'-----------------------------------------------------------------------------' ; 2-1."With same dimensions" print,'----- Same dimensions -----' print,'A=[ 5 , 4 , 3.22 , 1.0005 ] et U=[ 1.002 , 2.003 , 5.106 , 9.0025 ]' A=[ 5 , 4 , 3.22 , 1.0005 ] U=[ 1.002 , 2.003 , 5.106 , 9.0025 ] r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r print,'' ;use for better display ; 2-2."With different dimensions" print,'----- Different dimensions -----' print,'A=[ 5 , 3.22 , 1.0005 ] et U=[ 1.002 , 2.003 , 5.106 , 9.0025 ]' A=[ 5 , 3.22 , 1.0005 ] U=[ 1.002 , 2.003 , 5.106 , 9.0025 ] r=voigt(A,U) print ,'voigt(A,U)=',voigt(A,U) help,r print,'' ;use for better display print,'A=[5 , 3.22 , 1.0005 ] et U=[ 1.002 , 2.003 ]' A=[ 5, 3.22 , 1.0005 ] U=[1.002, 2.003] r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r print,'' ;use for better display ;3. "One argument is a scalar and the other is an array print,'-----------------------------------------------------------------------------------' print,'If arguments are one array and scalar and returns array with the smallest array dim' print,'-----------------------------------------------------------------------------------' print,'A=[ 5 , 3.22 , 1.0005 ] et U=5.00' A=[5 , 3.22 , 1.0005 ] U=5.00 r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r print,'' ;use for better display print,'A=4.002 et U=[ 5.00 , 2.003 , 4 , 6 ]' U=[ 5.00 , 2.003 , 4 , 6 ] A=4.002 r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r print,'' ;use for better display ;4. "Argument A is a double" print,'--------------------------------------------------------------------------------' print,'If argument A is a double returns double' print,'--------------------------------------------------------------------------------' print,'A=4.00000d et U=[ 5.00 , 2.003 , 4 , 6 ]' A=4.00000d U= [ 5.00 , 2.003 , 4 , 6 ] r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r print,'' ;use for better display print,'A=[ 1.4002 , 7.000900d , 4.000 ] et U=[ 5.00 , 2.003 , 4 , 6 ]' A=[1.4002 , 7.000900d , 4.000 ] U=[ 5.00 , 2.003 , 4 , 6 ] r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r print,'' print,'A=[ 1.4002 , 7.000900 , 4.000 ] et U=[ 5.00d , 2.003d , 4 , 6 ]' A=[1.4002 , 7.000900 , 4.000 ] U=[ 5.00d , 2.003d , 4 , 6 ] r=voigt(A,U) print ,'r=voigt(A,U)=',voigt(A,U) help,r end ;----------------------------------------------------------------------- ; II-Plot of voigt function ;----------------------------------------------------------------------- pro test_voigt_plot x=findgen(2000)/10-100 a=[0.01, 0.1, 0.25, .5, 1., 2., 4., 8., 16., 32., 64., 128.] nb_a=N_ELEMENTS(a) window, 0, xsize=800, ysize=600 !p.multi=[0,3,4] for ii=0, nb_a-1 do begin plot, x, VOIGT(a[ii],x), title = 'VOIGT function with damper = '+ STRING( a[ii]) end !p.multi=0 end ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; III-Comparison with Armstrong et al. VOIGT values ;----------------------------------------------------------------------- pro test_voigt_ArmstrongValues ; DEFSYSV, '!gdl', exists=is_it_gdl if (is_it_gdl EQ 1) then soft='GDL' else soft='IDL' ; print,'-------------------------------------------------' ;use for better display print,'Comparison between Armstrong and '+soft+' VOIGT values' print,'-------------------------------------------------' print,'. For x=5.4 et y=e-10 Armstrong => voigt = 2.260842e-12' print,'. For x=5.4 et y=e-10 Humlicek CPF12 1979 => voigt = 2.260845e-12' print,'. For x=5.4 et y=e-10 Humlicek W4 1982 => voigt = 2.260842e-12' print,'. For x=5.4 et y=e-10 Hui => voigt = 2.667847e-8' print,'. For x=5.4 et y=e-10 Lether and Wenston => voigt = 2.260845e-12' print,' Computed by '+soft+' value of voigt = ',voigt(1e-10,5.4) print,'' print,'. For x=5.5 et y=e-14 Armstrong => voigt = 7.307387e-14' print,'. For x=5.5 et y=e-14 Humlicek CPF12 1979 => voigt = 7.307387e-14' print,'. For x=5.5 et y=e-14 W4 1982 => voigt = 1.966215e-16' print,'. For x=5.5 et y=e-14 Hui => voigt = 9.238980e-9' print,'. For x=5.5 et y=e-14 Lether and Wenston => voigt = 7.307386e-14' print,' Computed by '+soft+' value of voigt = ',voigt(1e-14,5.5) print,'' end ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; IV-Test with negative numbers ;----------------------------------------------------------------------- pro test_voigt_negative print,'-------------------------------------------------' ;use for better display print, 'Show behaviour with negativ number' print,'-------------------------------------------------' print,'' print,'A=[ -5 , 4 , 3.22 , -1.0005 ] et U=[ -1.002 , 2.003 ]' A=[-5,4,3.22,-1.0005] B=[-1.002,2.003] print , voigt(A,B) print,'' print,'A= -1 et U= 1' A=-1 B=1 print , voigt(A,B) end ;----------------------------------------------------------------------- ; V-Test with not a number and infinite values ;----------------------------------------------------------------------- pro test_voigt_NaN print,'' print,'----------there is no negative NaN in gdl-----------------' A = [1.0005,8.33,4222d,!VALUES.D_NAN,-!VALUES.F_INFINITY ] print ,'A = [1.0005,8.33,4222d,!VALUES.D_NAN,-!VALUES.F_INFINITY ]' print ,'U =2.00' U=2.00 print ,'voigt(A,U) = ',voigt(A,U) print,'' print,'"limit value when u= (+-)!VALUES.F_INFINITY =0.000000"' print,' voigt (2.000,!VALUES.F_INFINITY)= ' print,voigt (2.000,!VALUES.F_INFINITY) end ;----------------------------------------------------------------------- ; VI-Test use to see if there is no memory leak ;----------------------------------------------------------------------- pro test_voigt_time, nb_loops=nb_loops ; if (N_ELEMENTS(nb_loops) EQ 0) then nb_loops=12 ; ;x=findgen(2000)/10-100 a=[0.01, 0.1, 0.25, .5, 1., 2., 4., 8., 16., 32., 64., 128.] nb_a=N_ELEMENTS(a) ; t0=SYSTIME(1) for jj=0, nb_loops-1 do begin for ii=0, nb_a-1 do begin y1=VOIGT(a[ii],dist(512)) endfor endfor print, 'VOIGT: ', SYSTIME(1)-t0 ; end ; ; showing IDL/GDL differences in behavoir ; pro TEST_VOIGT_SINGLETON, test=test ; a=1 u=[1,2,3,-10.] ; res1=VOIGT(a,u) res2=VOIGT([a],u) res3=VOIGT(REPLICATE(a,N_ELEMENTS(u)),u) ; if KEYWORD_SET(test) then STOP ; end ; pro TEST_VOIGT ; print, 'AC 2014-04-29: not finished ...' TEST_VOIGT_SINGLETON ; end gdl-0.9.9/testsuite/test_wait.pro000066400000000000000000000032121340051421000170410ustar00rootroot00000000000000; ; AC 12 Mars 2008 ; ; Because I saw WAIT is not very accurate ! ; ; You can check whether the CPU is loaded or not ; (e.g. "GDL > WAIT, 60" should not overloaded a CPU). ; At the beggining we used a inadequate primitive ; which overloaded a CPU just by waiting. ; pro TEST_WAIT, delay=delay, inner_loop=inner_loop, tol_error=tol_error, $ help=help, test=test, no_exit=no_exit ; if KEYWORD_SET(help) then begin print, 'pro TEST_WAIT, delay=delay, inner_loop=inner_loop, tol_error=tol_error, $' print, ' help=help, test=test, no_exit=no_exit' print, '' print, 'Delay can be an array.' return endif ; ; on CentOS, tol_error below 1.2e-3 is not OK ; on Suse, tol_error below 5e-3 is not OK ; on OSX 10 & 11, tol_error below 5e-3 is not OK ; if ~KEYWORD_SET(tol_error) then tol_error=5e-3 ; if STRLOWCASE(!version.os) EQ 'darwin' then tol_error=1.5e-2 ; nb_errors=0 ; if ~KEYWORD_SET(delay) then delay=[0.1, 0.25, 0.5, 1.0] if ~KEYWORD_SET(inner_loop) then inner_loop=3 ; for ii=0, N_ELEMENTS(delay)-1 do begin cur_delay=delay[ii] print, 'Currently tested DELAY : ', cur_delay for jj=0, inner_loop-1 do begin t0=SYSTIME(1) WAIT, cur_delay diff=SYSTIME(1)-t0 if (ABS(diff-cur_delay) GT tol_error) then nb_errors=nb_errors+1 print, diff endfor endfor ; if (nb_errors GT 0) then begin MESSAGE,/continue, 'Tolerance Time error was exceed '+ $ STRCOMPRESS(STRING(nb_errors))+' times.' if ~KEYWORD_SET(no_exit) then EXIT, status=1 endif else begin MESSAGE,/continue, 'Success: Tolerance Time Error was never exceed by WAIT' endelse ; if KEYWORD_SET(test) then STOP ; end ; gdl-0.9.9/testsuite/test_wavelet.pro000066400000000000000000000041251340051421000175500ustar00rootroot00000000000000; by Sylwester Arabas pro test_wavelet, plot=plot p = keyword_set(plot) n = 16 ; signal length / number of wavelets (1D case) nn = 8 ; dimension length (2D case) eps = 1e-6 ; a small number maxc = 20 ; GSL max: 20 for kw_column = 0, 1 do for kw_double = 0, 1 do for kw_over = 0, 1 do $ for dim = 1, 2 do begin if p then begin if dim eq 1 then !P.MULTI = [0, 4, n / 4] $ else !P.MULTI = [0, nn, nn] endif for c = 4, maxc, 2 do begin for i = 0, (dim eq 1 ? n : nn * nn) - 1 do begin ; inverse-transforming a unit vector x1 = dim eq 1 ? fltarr(n) : fltarr(nn, nn) & x1[i] = 1 v1 = x1 v1 = wtn(v1, c, /inverse, double=kw_double, column=kw_column, over=kw_over) ; plotting if desired if p then begin if dim eq 1 then plot, v1 else surface, v1 endif ; testing if the transform of the inverse transform equals the unit vector wh = where(abs(x1 - wtn(v1, c, double=kw_double, column=kw_column)) gt eps, cnt) if cnt gt 0 then begin message, 'wtn(wtn(a, /inv)) != a', /conti exit, status=1 endif ; testing if every wavelet (not the mother) has a zero mean if i gt 0 and abs(mean(v1)) gt eps then begin message, 'abs(mean(v1)) > eps', /conti exit, status=1 endif ; testing if every other member of the basis is orthogonal to this one for j = 0, (dim eq 1 ? n : nn * nn) - 1 do begin x2 = dim eq 1 ? fltarr(n) : fltarr(nn, nn) & x2[j] = 1 v2 = x2 v2 = wtn(v2, c, /inverse, double=kw_double, column=kw_column, over=kw_over) v1v2 = total(v1 * v2) if i eq j and v1v2 lt 1 - eps then begin message, 'i eq j and v1v2 < 1 - eps !!!', /conti exit, status=1 endif if i ne j and v1v2 gt 0 + eps then begin message, 'i ne j and v1v2 > 0 + eps !!!', /conti exit, status=1 endif endfor ; j endfor ; i endfor ; c endfor ; dim end ; pro gdl-0.9.9/testsuite/test_where.pro000066400000000000000000000144071340051421000172170ustar00rootroot00000000000000; ; AC, 18 March 2014 ; ; We found by chance a bug in WHERE related to OpenMP. ; Any idea to extend test here are very welcome. ; ; ; ------------------------ ; pro TEST_WHERE_NULL, cumul_errors, verbose=verbose, test=test ; nb_errors=0 ; a=REPLICATE(1,10) ; null1=WHERE(a GT 1,complement=c1,/null) if ~ISA(null1,/null) then ERRORS_ADD, nb_errors, 'bad value for : null1' if ISA(c1,/null) then ERRORS_ADD, nb_errors, 'bad value for : c1' ; ok=WHERE(a EQ 1,complement=null2,/null) if ISA(ok,/null) then ERRORS_ADD, nb_errors, 'bad value for : ok' if ~ISA(null2,/null) then ERRORS_ADD, nb_errors, 'bad value for : null2' ; BANNER_FOR_TESTSUITE, 'TEST_WHERE_NULL', nb_errors, /status ERRORS_CUMUL, cumul_errors, nb_errors ; if KEYWORD_SET(test) then STOP ; end ; ; ------------------------ ; ; statistical approach : the initial way to find it ! ; pro TEST_WHERE_WITH_RANDOM, nbp_in, cumul_errors, verbose=verbose, test=test ; nb_errors=0 ; nbp_in should normally been of small size as we are just interested in threaded vs. unthreaded behaviour. ; for very large nbp_in Total() may be a problem. input=RANDOMU(seed, nbp_in) ; ; we force threads by using a small value for CPU,TPOOL_MIN_ELTS SAVECPU=!CPU CPU,TPOOL_MIN_ELTS=nbp_in/10 CPU,TPOOL_NTHREADS=!CPU.HW_NCPU ; ; what where() sees is an array, mostly of zeros and ones. But any array can be passed to where(). logical_value=input GE 0.5 ; this will be our template ; ;loop on types that are accepted by WHERE. the total of 'ok' location should be count, the total of 'nok' location must be zero. ; special care for complex values is needed. ; strings cannot be tested this way because of TOTAL() function itype=[1,2,3,4,5,12,13,14,15,6,9] stype=['Byte','Integer','Longword integer','Floating point','Double-precision floating','Unsigned Integer','Unsigned Longword Integer',$ '64-bit Integer','Unsigned 64-bit Integer','Complex floating','Double-precision complex'] if KEYWORD_SET(verbose) then print,'First pass, threaded, n_threads=',!CPU.TPOOL_NTHREADS for i=0,n_elements(itype)-1 do begin type=itype[i] typename=stype[i] case type of 6: begin & x=fix(logical_value,type=4) & y=x & val=complex(x,y) & end 9: begin & x=fix(logical_value,type=9) & y=x & val=dcomplex(x,y) & end else: val=fix(logical_value,type=type) endcase ok=WHERE(val, nbp_ok) ; test ok is... ok if nbp_ok gt 0 then begin if total(val[ok],/integer) ne nbp_ok then begin nb_errors++ if KEYWORD_SET(verbose) then print,'where() wrong for type '+typename endif endif else begin nb_errors++ ; as most probably there should be some values gt 0.5! print,"unexpected error occured, please investigate." ; as this gonna be worrying endelse ; ok=WHERE(val, nbp_ok, comp=nok, ncomp=nbp_nok) ; test ok is...(same as before, but remember: we DO NOT pass in the same lines of code as before!) if nbp_ok gt 0 then begin if total(val[ok],/integer) ne nbp_ok then begin nb_errors++ if KEYWORD_SET(verbose) then print,'where() wrong for type '+typename endif endif else begin nb_errors++ ; as most probably there should be some values gt 0.5! print,'unexpected error occured for where(), type '+typename+', please investigate.' ; as this gonna be worrying endelse if nbp_nok gt 0 then begin if total(val[nok],/integer) ne 0 then begin nb_errors++ if KEYWORD_SET(verbose) then print,'where(comp=xxx) wrong for type '+typename endif endif else begin nb_errors++ ; as most probably there should be some values gt 0.5! print,'unexpected error occured for where(comp=xxx), type '+typename+', please investigate.' ; as this gonna be worrying endelse endfor if KEYWORD_SET(verbose) then print,'Second pass, unthreaded (one thread)' CPU,TPOOL_NTHREADS=1 for i=0,n_elements(itype)-1 do begin type=itype[i] typename=stype[i] case type of 6: begin & x=fix(logical_value,type=4) & y=x & val=complex(x,y) & end 9: begin & x=fix(logical_value,type=9) & y=x & val=dcomplex(x,y) & end else: val=fix(logical_value,type=type) endcase ok=WHERE(val, nbp_ok) ; test ok is... ok if nbp_ok gt 0 then begin if total(val[ok],/integer) ne nbp_ok then begin nb_errors++ if KEYWORD_SET(verbose) then print,'where() wrong for type '+typename endif endif else begin nb_errors++ ; as most probably there should be some values gt 0.5! print,"unexpected error occured, please investigate." ; as this gonna be worrying endelse ; ok=WHERE(val, nbp_ok, comp=nok, ncomp=nbp_nok) ; test ok is...(same as before, but remember: we DO NOT pass in the same lines of code as before!) if nbp_ok gt 0 then begin if total(val[ok],/integer) ne nbp_ok then begin nb_errors++ if KEYWORD_SET(verbose) then print,'where() wrong for type '+typename endif endif else begin nb_errors++ ; as most probably there should be some values gt 0.5! print,'unexpected error occured for where(), type '+typename+', please investigate.' ; as this gonna be worrying endelse if nbp_nok gt 0 then begin if total(val[nok],/integer) ne 0 then begin nb_errors++ if KEYWORD_SET(verbose) then print,'where(comp=xxx) wrong for type '+typename endif endif else begin nb_errors++ ; as most probably there should be some values gt 0.5! print,'unexpected error occured for where(comp=xxx), type '+typename+', please investigate.' ; as this gonna be worrying endelse endfor CPU,RESTORE=SAVECPU ; BANNER_FOR_TESTSUITE, 'TEST_WHERE_WITH_RANDOM', nb_errors, /status ERRORS_CUMUL, cumul_errors, nb_errors ; if KEYWORD_SET(test) then STOP ; end ; ; ------------------------ ; pro TEST_WHERE, size, help=help, verbose=verbose, no_exit=no_exit, test=test ; if KEYWORD_SET(help) then begin print, 'pro TEST_WHERE, [size_of_test,] $' print, ' help=help, verbose=verbose, $' print, ' no_exit=no_exit, test=test' print, '...default size is 1000000 normally sufficient' return endif ; if (n_elements(size) le 0) then size=1E6 nb_errors=0 ; TEST_WHERE_NULL, nb_errors, verbose=verbose ; TEST_WHERE_WITH_RANDOM, size, nb_errors, verbose=verbose ; ; ----------------- final message ---------- ; BANNER_FOR_TESTSUITE, 'TEST_WHERE', nb_errors ; if (nb_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_widgets.pro000066400000000000000000000332461340051421000175550ustar00rootroot00000000000000; this file is part of GDL ; using the widgets prints the generated events ; 30. Oct 2013 Marc Schellens ; expanded by GD. Thanks to MIDI's GuiSelect procedure for ideas. ; pro exit_gui,ev widget_control,ev.top,/DESTROY end pro cleanup_xmanager, id print,"Cleaning up called by xmanager..." widget_control,id,/DESTROY end pro cleanup, id print,"Cleaning up called by base widget..." widget_control,id,/DESTROY end pro cleanup_control, id print,"Cleaning up called by widget_control..." widget_control,id,/DESTROY end pro i_am_realized, id print,"Widget "+string(id)+" is realized now." end pro event_in_base, id print,"event in base" help,id print,"event in "+string(id.id) end pro slider_killed,id print,"slider "+string(id)+" was killed" end pro button_killed,id ; print,"button "+string(id)+" was killed" end pro handle_Event,ev common mycount,count help,ev,/str widget_control,ev.id,get_uvalue=uv widget_control,ev.top,get_uvalue=topuv if n_elements(uv) gt 0 then begin if (strlen(tag_names(ev,/structure_name)) le 1) then begin print,"unhandled compound widget event" return end ; print,"uvalue.type=",uv.type case uv.type of 'file': begin widget_control,ev.id,get_value=value ;& print,value case value of "Y": widget_control,ev.id,set_value="N" "N": widget_control,ev.id,set_value="Y" else: return endcase end 'data': begin widget_control,ev.id,get_value=value widget_control,topuv[0],set_value=value widget_control,topuv[1],set_value=value end 'quit': widget_control,ev.top,/DESTROY else: return endcase endif end pro test_widgets, table, nocanvas=nocanvas, notree=notree, $ block=block,fontname=fontname, help=help common mycount, count count=0 if ~keyword_set(fontname) then fontname="Fixed 32" if ~keyword_set(block) then block=0 if keyword_set(help) then begin print,"useage: test_widgets[,table][,/help][,/nocanvas][,/notree]" print,"Will display some examples of currently available widgets" print,"if table is passed as argument and is a structure, tab 3 will show the" print,"elements of the structure as buttons in a scrolled panel" print,"options: /nocanvas removes the widget_draw" print," /notree remove the tree widget" print," fontname=""Helvetica Narrow 32"" to change a test text font." return endif ; ev = {vEv,type:'',pos:[0,0]} ;Create a base widget. base = WIDGET_BASE(MBAR=mbar,title="gdl widget examples", $ event_pro='event_in_base',kill_notify='cleanup') ; menu = WIDGET_BUTTON(mbar,VALUE="Menu") ex = WIDGET_BUTTON(menu,VALUE="Exit",EVENT_PRO="exit_gui") siz= WIDGET_BUTTON(menu,VALUE="Resize (error)",EVENT_PRO="resize_gui") ;buttons as menu buttons fileID = Widget_Button(mbar, Value='Complicated Menu') saveID = Widget_Button(fileID, Value='submenu 1', /MENU) button = Widget_Button(saveID, Value='entry 1', UNAME='POSTSCRIPT') button = Widget_Button(saveID, Value='entry 2', UNAME='PDF') raster = Widget_Button(saveID, Value='submenu 2', /MENU) button = Widget_Button(raster, Value='BMP', UNAME='RASTER_BMP') button = Widget_Button(raster, Value='GIF', UNAME='RASTER_GIF') button = Widget_Button(raster, Value='JPEG', UNAME='RASTER_JPEG') button = Widget_Button(raster, Value='PNG', UNAME='RASTER_PNG') button = Widget_Button(raster, Value='TIFF', UNAME='RASTER_TIFF') imraster = Widget_Button(saveID, Value='submenu 3', /MENU) button = Widget_Button(imraster, Value='BMP', UNAME='IMAGEMAGICK_BMP') button = Widget_Button(imraster, Value='GIF', UNAME='IMAGEMAGICK_GIF') button = Widget_Button(imraster, Value='JPEG', UNAME='IMAGEMAGICK_JPEG') button = Widget_Button(imraster, Value='PNG', UNAME='IMAGEMAGICK_PNG') button = Widget_Button(imraster, Value='TIFF', UNAME='IMAGEMAGICK_TIFF') button = Widget_Button(fileID, Value='entry 3', /Separator, UNAME='SAVECOMMANDS') button = Widget_Button(fileID, Value='entry 4', UNAME='RESTORECOMMANDS') button = Widget_Button(fileID, Value='entry 5', /Separator, UNAME='QUIT') tab = widget_tab( base) ; note inversion tab5<->tab5 tab1 = widget_base( tab, TITLE="GDL",/COL) tab2 = widget_base( tab, TITLE="is",/COL) tab3 = widget_base( tab, TITLE="with",/COL) tab4 = widget_base( tab, TITLE="lots",/COL) tab5 = widget_base( tab, TITLE="of",/COL) tab6 = widget_base( tab, TITLE="widgets",/COL) tab7 = widget_base( tab, TITLE="now!",/COL) ;TAB1: Attach 256 x 256 draw widgets. if ~keyword_set(nocanvas) then begin draw = WIDGET_DRAW(tab1, XSIZE = 1800, YSIZE = 600,x_scroll_size=256,y_scroll_size=256,frame=20) draw2 = WIDGET_DRAW(tab1, xoff=100, yoff=100, xsize=256,ysize=256,/button_events,keyboard_events=1,/motion_events) end else begin dummy=widget_label(tab1, value="WIDGET_DRAW not shown, (/NOCANVAS option)", font=fontname) end ; TAB2: radio=widget_base(tab2,/EXCLUSIVE,COL=1) rb1=widget_button(radio,VALUE="button in EXCLUSIVE base 1",uvalue={vEv,'rb1',[8,0]}) rb2=widget_button(radio,VALUE="button in EXCLUSIVE base 2",uvalue={vEv,'rb2',[9,0]}) check=widget_base(tab2,/NONEXCLUSIVE,COL=1) cb1=widget_button(check,VALUE="button in NONEXCLUSIVE base 1",uvalue={vEv,'cb1',[81,0]}) cb2=widget_button(check,VALUE="button in NONEXCLUSIVE base 2",uvalue={vEv,'cb2',[12,0]}) sl1=widget_slider(tab2,MIN=0,MAX=100,TITLE="WIDGET_SLIDER-DRAG+FRAME",kill_notify='slider_killed',/DRAG,FRAME=3) sl=widget_slider(tab2,MIN=0,MAX=100,TITLE="WIDGET_SLIDER-NORMAL-NOVAL",kill_notify='slider_killed',/SUPPRESS); ;tab3 charpix = 8.5 butSize = 7*charpix actionBase=widget_base(tab3,/ROW) quitButton = widget_button(actionBase,value='WILL QUIT',uvalue={vEv,'quit',[5,0]}) downButton = widget_button(actionBase,value='A 300 px Button..', /dynamic_resize) selectBase=widget_base(tab3,/ROW) ;a label that can be updated by pushing buttons labeltoupdate = widget_label(selectBase, value='Label xsize=100(pixels),ysize=30(pixels)',$ xsize=100,ysize=30,/align_left) ;show last button clicked value statusLabel = widget_text(selectBase,value='text, xsize=32(characters),ysize=10(chars)', $ xsize=32,ysize=10) ;pass label to top (avoid using a common) widget_control,base,set_uvalue=[statusLabel,labeltoupdate] ;base for listing contents of tables and to show selected files nrows=n_elements(table) ; passed table if ( n_elements(table) eq 0 or size(table,/type) ne 8 ) then begin tbltemplate={table2,string:'a very very very long string ',real:33.33,double:8.0080808D,another:'another',yanother:'very long string'} ; make a long table of nrows nrows=50 table=replicate(tbltemplate,nrows) endif ;names of columns tags = tag_names(table) ; nb of colums=nb tags ncols=n_tags(table) ;set max size (chars) of displayed button/label for each column maxSize = intarr(nCols) for icol = 0, nCols-1 do maxSize[icol] = 1 + MAX(strlen(strtrim(table.(icol),2))) nrows=n_elements(table); check... ;buttons containing header keyword values buttons = lonarr(nCols,nRows) ;buttons containing column labels tagButtons=lonarr(nCols) fileButtons = lonarr(nRows) fileNumbers = lonarr(nRows) ;base for listing contents of tables and to show selected files fileBase=widget_base(tab3,/scroll,/frame,/row) ;base to contain column labels and cells with table values and selected files listentries=widget_base(filebase,row=nRows+1) ;create column labels dummy = widget_label(listentries,value=' ', xsize=30) dummy1 = widget_label(listentries,value=' ',xsize=30) for icol =0, nCols-1 do tagButtons(icol)=widget_label(listentries,value=tags(icol), xsize=charpix*maxSize[icol],/align_left) for iRow=0,nRows-1 do begin fileNumbers(iRow)=widget_label(listentries, value=string(iRow), xsize=30, ysize=25) fileButtons(iRow)=widget_button(listentries, value="*", uvalue={vEv,'file',[iRow,-1]}, xsize=30, ysize=25) for icol=0,nCols-1 do buttons(icol, iRow) = widget_button(listentries, value=strtrim((table[iRow].(icol)),2), uvalue={vEv,'data',[icol,iRow]}, ysize=25, xsize=charpix*maxSize[iCol],/align_left,kill_notify='button_killed') endfor ;;overwrite label: ;print,"label to update id="+string(labeltoupdate) widget_control, labeltoupdate, set_value="Text2 has been replaced with widget_control" ; tab4 bg=widget_base(tab4,/ROW) values = ['One', 'Two', 'Three', 'Four', 'Five','Six'] CATCH,cw_bgroup_error if cw_bgroup_error eq 0 then bgroup1 = CW_BGROUP(bg, values, /COLUMN, /EXCLUSIVE, $ LABEL_TOP='Exclusive', /FRAME, SET_VALUE=3) else $ message,/contin," can't make a CW_Bgroup widget" CATCH,/CANCEL ;bgroup1 = CW_BGROUP(bg, values, /COLUMN, /EXCLUSIVE, $ ; LABEL_TOP='Exclusive', /FRAME, SET_VALUE=3) ;bgroup2 = CW_BGROUP(bg, values, /COLUMN, /NONEXCLUSIVE, $ ; LABEL_TOP='Nonexclusive', /FRAME, SET_VALUE=[1,0,1,0,1]) CATCH,cw_bgroup_error if cw_bgroup_error eq 0 then bgroup2 = CW_BGROUP(bg, values, /COLUMN, /NONEXCLUSIVE, $ LABEL_TOP='Nonexclusive', /FRAME, SET_VALUE=[1,0,1,0,1]) else $ message,/contin," can't make a CW_Bgroup widget" CATCH,/CANCEL ; tab5 label1=widget_label(tab5,VALUE="Text on the left (/align_left)",/align_left,uvalue={vEv,'lll',[1,-1]},/sunken_frame) label2=widget_label(tab5,VALUE="FONT: "+fontname,/align_left,uvalue={vEv,'lll',[1,-1]},font=fontname) label3=widget_label(tab5,VALUE="...and on the right (/align_right)",/align_right,uvalue={vEv,'lll',[1,-1]}) text1=widget_text(tab5,VALUE=["This is a loooooooooooooooooooooong editable text widget",$ "created with","WIDGET_TEXT","without YSIZE keyword"],$ /EDITABLE,/ALL_EVENTS) text2=widget_text(tab5,VALUE=["Not editable text",$ "created with","WIDGET_TEXT","with YSIZE=10"],$ EDITABLE=0,/ALL_EVENTS,XSIZE=32,YSIZE=10) text3=widget_text(tab5,VALUE=["right align text"],/EDIT,/align_right); list=widget_list(tab5,value=["A","list","created","with","WIDGET_LIST","(no YSIZE)"]) list=widget_list(tab5,value=["An aligned","list","created","with","WIDGET_LIST","(no YSIZE)"],/align_right) droplist=widget_droplist(tab5,VALUE=["A","droplist","created","with","WIDGET_DROPLIST","(no YSIZE)"],title="A droplist") droplist=widget_droplist(tab5,VALUE=["ib","pt"],title="A droplist") droplist=widget_droplist(tab5,VALUE=["An aligned","droplist","created","with","WIDGET_DROPLIST","(no YSIZE)"],/align_right) combo=widget_combobox(tab5,VALUE=["A not-aligned","not editable","combobox","created","with","WIDGET_COMBOBOX","(no YSIZE)"]) combo=widget_combobox(tab5,VALUE=["A right-aligned","combobox","created","with","WIDGET_COMBOBOX","(no YSIZE)"],/editable,/align_right) ; tab6: a widget_table mytable1=widget_table(tab6,value=dist(7),xsize=5,ysize=5,/editable,/all_events) ;to be implemented! ;widget_control,mytable1,/editable,use_table_sel=[1,1,4,4] widget_control,mytable1,edit_cell=[0,0] widget_control,mytable1,background_color=[255,255,0],use_table_sel=[1,1,4,4] ntable = min([5,nrows-1]) mytable2=widget_table(tab6,value=table[0:ntable],$ /row_major,row_labels='',column_labels=tags,column_width=50,/resizeable_columns,y_scroll_size=40,/disjoint,/all_events) ; ;tab7: a tree table if ~keyword_set(notree) then begin racine = widget_tree(tab7) wtRoot = widget_tree(racine, VALUE='GDL', /folder, /draggable, /drop_events) feuille_11 = WIDGET_TREE(wtRoot, VALUE='is', $ UVALUE={vEv,'LEAF',[0,0]}) branche_12 = WIDGET_TREE(wtRoot, VALUE='...', $ /FOLDER, /EXPANDED) feuille_121 = WIDGET_TREE(branche_12, VALUE='with', $ UVALUE={vEv,'LEAF',[0,0]}) feuille_122 = WIDGET_TREE(branche_12, VALUE='a lot of', $ UVALUE={vEv,'LEAF',[0,0]}) feuille_13 = WIDGET_TREE(wtRoot, VALUE='widgets', $ UVALUE={vEv,'LEAF',[0,0]}) feuille_14 = WIDGET_TREE(wtRoot, VALUE='now', $ UVALUE={vEv,'LEAF',[0,0]}) end ; overwrite buttons; for iRow=0,nRows-1 do widget_control,fileButtons(iRow) , set_value="Y" ;; ;tests for /notify_realize and /kill_notify ; widget_control,base,notify_realize='i_am_realized' ;Realize the widgets. WIDGET_CONTROL, /REALIZE, base if ~keyword_set(nocanvas) then begin ;Obtain the window index. index =0 & index2 = 1 print,"Draw widgets:",draw,draw2 WIDGET_CONTROL, draw, GET_VALUE = index WIDGET_CONTROL, draw2, GET_VALUE = index2 ; ; Accomodate the "NO_WIDGET_DRAW" crowd: ; ; 0 <= index,index2 < 32 if (!d.name eq "WIN") or (!d.name eq "X") $ and (index lt 32) and (index2 lt 32) then begin device,window_state=wcheck if wcheck[index] eq 0 then window,index if wcheck[index2] eq 0 then window,index2 endif ;; ;; Set the new widget to be the current graphics window print,"window indexes",index,index2 ; for window index 32 or greater we cannot call WINDOW to create but ; it may be "closed and unavailable" when WX is not the plot device. CATCH,wset_error if wset_error eq 0 then WSET,index else $ message,/contin," can't plot to, or image on, the draw widget" CATCH,/CANCEL PLOT, FINDGEN(100) ;; we try to TV an image, skipped if not found ... ;; Read "Saturn.jpg" and return content in "image" status=GET_IMAGE_FOR_TESTSUITE(image) if status EQ 0 then begin print, 'Test Image not found, skipped ...' endif else begin TV, image,10,10, /data, /true endelse ;; if wset_error ne 0 then wait,2 CATCH,wset_error if wset_error eq 0 then WSET,index2 else $ message,/contin," can't plot to, or image on, the draw widget" CATCH,/CANCEL f=FINDGEN(1000)/100. CONTOUR, COS(DIST(100,100)/10.) end ; xmanager,"handle",base,cleanup="cleanup_xmanager",no_block=~block ; end gdl-0.9.9/testsuite/test_window_background.pro000066400000000000000000000136201340051421000216070ustar00rootroot00000000000000; ; AC, 17 Aout 2015, Shizuoka ; ; In fact, this code is testing background value in WINDOW via TVRD ; and ERASE. ; Then, it may be broken if WINDOW, ERASE or TVRD became broken !! ; ; Note: the tests clearly show problems for old GDL on ; DEVICE, /decomposed, but no warning for DEVICE, decomposed=0 ; ; ----------------------------------------------- ; function MINIMAXI, array, channel, verbose=verbose, test=test ; if (n_params() EQ 1) then res=[MIN(array),MAX(array)] if (n_params() EQ 2) then res=[MIN(array[channel,*,*]),MAX(array[channel,*,*])] ; if KEYWORD_SET(verbose) then $ print, 'Min in Array : ', res[0], ', Max in Array : ', res[1] ; if KEYWORD_SET(test) then STOP ; return, res end ; ; ----------------------------------------------- ; pro TEST_WIN_BACK_DECOMPOSED, cumul_errors, test=test, verbose=verbose ; errors=0 ; DEVICE, /decomposed ; !P.background='ff'x back_ref=!P.background back_ref_mod=back_ref ; WINDOW, 0, xsize=100, ysize=100 ; resu=TVRD(/true) mm=MINIMAXI(resu,0) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(1) more than one value in plane RED !' if mm[0] NE back_ref then ERRORS_ADD, errors, '(1) read value not EQ to back' mm=MINIMAXI(resu,1) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(1) more than one value in plane GREEN !' mm=MINIMAXI(resu,2) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(1) more than one value in plane BLUE !' ; ; Since Background color not change, ; result should be the same after an ERASE !! ; erase resu=TVRD(/true) mm=MINIMAXI(resu,0) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(2) more than one value !' if mm[0] NE back_ref then ERRORS_ADD, errors, '(2) read value not EQ to back' ; ; changing the back via ERASE ; back_new='ee00'x back_new_mod=back_new/256 erase, color=back_new resu=TVRD(/true) mm=MINIMAXI(resu, 1) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(3) more than one value !' if mm[0] NE back_new_mod then ERRORS_ADD, errors, '(3) read value not EQ to back' ; ; change the back via !p.back ; !P.background=back_new WINDOW, xsize=100, ysize=100 resu=TVRD(/true) mm=MINIMAXI(resu,1) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(4) more than one value !' if mm[0] NE back_new_mod then ERRORS_ADD, errors, '(4) read value not EQ to back' ; ; one more window ; !P.background=back_new WINDOW, /free, xsize=100, ysize=100 resu=TVRD(/true) mm=MINIMAXI(resu,1) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(5) more than one value !' if mm[0] NE back_new_mod then ERRORS_ADD, errors, '(5) read value not EQ to back' ; ; one more window ; !P.background=back_ref WINDOW, /free, xsize=100, ysize=100 resu=TVRD(/true) mm=MINIMAXI(resu,0) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(6) more than one value !' if mm[0] NE back_ref_mod then ERRORS_ADD, errors, '(6) read value not EQ to back' ; ; back to first window ; !P.background=back_ref WSET, 0 ERASE ;WINDOW, /free, xsize=100, ysize=100 RESU=TVRD(/true) mm=MINIMAXI(resu,0) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(7) more than one value !' if mm[0] NE back_ref_mod then ERRORS_ADD, errors, '(7) read value not EQ to back' ; ; final message ; ;if ~KEYWORD_SET(verbose) then short=1 else short=0 BANNER_FOR_TESTSUITE, 'TEST_WIN_BACK_DECOMPOSED', errors, short=short, /status ERRORS_CUMUL, cumul_errors, errors if KEYWORD_set(test) then STOP ; end ; ; ----------------------------------------------- ; ; This example was provided by Eric Hivon, HEAPix ; (see mails 2015/08/12) ; the color map is changed to setup RED for color "0", ; background is white. ; pro TEST_RED_WHITE_NO_DECOMPOSED, cumul_errors, test=test, verbose=verbose ; errors=0 ; DEVICE, decomposed=0 LOADCT,0 TVLCT, /get, rgb back=255B rgb[0,*] = [back,0,0] rgb[1,*] = [0,0,back] TVLCT, rgb ; WINDOW, /free, xsize=250, ysize=200 PLOT, FINDGEN(10), back=255, col=0, title='RED on WHITE' ; ; some "no trivial" tests can be made ! ; resu=TVRD() mm=MINIMAXI(resu) if mm[0] NE mm[1] then ERRORS_ADD, errors, '(RW) more than one value for plane 0 !' if mm[0] NE back then ERRORS_ADD, errors, '(RW) wrong value for Back !' ; resu=TVRD(/true) ; max_diff=MAX(ABS(resu(1,*,*)-resu(2,*,*))) if (max_diff GT 0) then ERRORS_ADD, errors, 'something''s wrong in planes 1-2' ; ; final message ; ;if ~KEYWORD_SET(verbose) then short=1 else short=0 BANNER_FOR_TESTSUITE, 'TEST_RED_WHITE_NO_DECOMPOSED', errors, short=short, /status ERRORS_CUMUL, cumul_errors, errors if KEYWORD_set(test) then STOP ; end ; ; ---------------------------------------------------------------------- ; pro TEST_WIN_BACK_NO_DECOMPOSED, cumul_errors, test=test, verbose=verbose ; print, 'this case is not finished' BANNER_FOR_TESTSUITE, 'TEST_WIN_BACK_NO_DECOMPOSED', 'this case is not finished' ; errors=0 ; DEVICE, decomposed=0 LOADCT,0 back=255B !p.background=back ; plot, findgen(10) ; ; final message ; ;if ~KEYWORD_SET(verbose) then short=1 else short=0 BANNER_FOR_TESTSUITE, 'TEST_WIN_BACK_NO_DECOMPOSED', errors, short=short, /status ERRORS_CUMUL, cumul_errors, errors if KEYWORD_set(test) then STOP ; end ; ; ----------------------------------------------- ; pro TEST_WINDOW_BACKGROUND, help=help, verbose=verbose, debug=debug, $ test=test, no_exit=no_exit ; if KEYWORD_SET(help) then begin print, 'pro TEST_WINDOW_BACKGROUND, verbose=verbose, debug=debug, $' print, ' test=test, no_exit=no_exit' return endif ; rname=ROUTINE_NAME() ; if ~CHECK_IF_DEVICE_IS_OK(rname, /force) then begin if ~KEYWORD_SET(no_exit) then EXIT, status=77 else STOP endif ; init_device_mode=!d.name DEVICE, get_dec=init_get_dec ; cumul_errors=0 ; TEST_WIN_BACK_DECOMPOSED, cumul_errors, test=test, verbose=verbose TEST_WIN_BACK_NO_DECOMPOSED, cumul_errors, test=test, verbose=verbose TEST_RED_WHITE_NO_DECOMPOSED, cumul_errors, test=test, verbose=verbose ; BANNER_FOR_TESTSUITE, 'TEST_WINDOW_BACKGROUND', cumul_errors, /status ; if (cumul_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; ; restoring device properties SET_PLOT, init_device_mode DEVICE, dec=init_get_dec ; end gdl-0.9.9/testsuite/test_wordexp.pro000066400000000000000000000215271340051421000175760ustar00rootroot00000000000000; ; Alain C., 27 November 2017 ; ; In order to try to avoid to make too much mess, ; we work in IDL_TMPDIR since it does exist ; in IDL, FL & GDL ; ; Before applying patch by Greg Jung (2017-NOV-27), we know that : ; ; Don't work well before 2018-MAR-22 : ; - FILE_LINE, FILE_TEST ; ; May work well (not a garanty it works always well) : ; - CD ; - FILE_DIRNAME, FILE_BASENAME, FILE_MKDIR ; - FILE_INFO, FILE_SEARCH ; ; --------------------------------------- ; Modifications history : ; ; - 2018-MAR-21 : AC. rewriting and expand of initial version ; ; --------------------------------------- ; ; create files with suffix equal to lines number inside ; (for later tests) ; pro TEST_WE_CREATE_FILES, files, test=test, verbose=verbose ; for jj=0, N_ELEMENTS(files)-1 do begin GET_LUN, nblun OPENW, nblun, files[jj] for ii=1, jj+1 do PRINTF, nblun, ii CLOSE, nblun FREE_LUN, nblun endfor ; if KEYWORD_SET(verbose) then begin print, 'Trying to create : ', files print, 'Succeed to create : ', FILE_TEST(files) endif ; if KEYWORD_SET(test) then STOP ; end ; ; ----------------------------------------------- ; ;pro TEST_WE_TEST, nb_errors, fields, flags, test=test, verbose=verbose ; ;for ii=0, N_ELEMENTS(files)-1 do begin ; if flag[ii] EQ 0 then $ ; ERRORS_ADD, nb_errors, 'Problem with subdir : '+subdirs[ii] ;endfor ; ;if KEYWORD_SET(test) then STOP ; ;end ; ----------------------------------------------- pro TEST_WORDEXP, help=help, test=test, verbose=verbose, $ main_subdir=main_subdir ; if KEYWORD_SET(test) then begin print, 'pro TEST_WORDEXP, help=help, test=test, verbose=verbose, $' print, ' main_subdir=main_subdir' return endif ; if STRLOWCASE(!version.os_name) eq 'windows' then begin message, /continue, 'This code is not design for MSwin plateform' message, /continue, 'not sure this code can survive on MS-window OS' message, /continue, 'Please report any problem (or success) and improvments' message, /continue, 'please report bugs on GitHub GDL site' endif ; nb_errors=0 ; tmpdir=GETENV('IDL_TMPDIR') ; ; does this directory realy exist ? ; if not, working in /tmp if ~FILE_TEST(tmpdir, /directory) then begin MESSAGE, 'IDL_TMPDIR dir. does not exist ?! creating a local IDL_TMPDIR',/continue tmpdir = 'IDL_TMPDIR' file_mkdir,tmpdir endif ; CD, tmpdir, current=initial_dir ; if ~KEYWORD_SET(main_subdir) then main_subdir='test_'+GDL_IDL_FL()+'_WordExp' ; FILE_MKDIR, main_subdir CD, main_subdir CD, cur=working_dir print, 'Working here : ', working_dir ; ; creating three SubDirs ; subdirs=['normal','spa ce','q!mark','mix,ing :s'] if(!version.os_family eq 'Windows') then subdirs = subdirs[0:2] FILE_MKDIR, subdirs print, 'creating subdirs : ', subdirs+PATH_SEP() ; ; testing whether the dirs were created ; (but we don't check the names now ...) ; res=FILE_TEST(working_dir+PATH_SEP()+subdirs) ; if TOTAL(res) EQ N_ELEMENTS(subdirs) then begin print, 'All subdirs were created' endif else begin for ii=0, N_ELEMENTS(subdirs)-1 do begin if res[ii] EQ 0 then $ ERRORS_ADD, nb_errors, 'Problem with subdir : '+subdirs[ii] endfor endelse ; ; creating files in those SubDirs ; files=['a1','a 2','a 3','a;4','a.5','a&6'] print, 'Creating some files in each subdirs : ', files ; for ii=0, N_ELEMENTS(subdirs)-1 do begin CD, working_dir+PATH_SEP()+subdirs[ii] TEST_WE_CREATE_FILES, files endfor ; ; testing the created files ; ; 1 Local (going *before* in the sub-dirs ; for ii=0, N_ELEMENTS(subdirs)-1 do begin ;; CD, working_dir+PATH_SEP()+subdirs[ii] ;; ;; do we have created all the files ? ;; or maybe the name(s) is/are wrong res_test=FILE_TEST(files) if TOTAL(res_test) EQ N_ELEMENTS(files) then begin print, 'All files have been created (Local)' endif else begin for ii=0, N_ELEMENTS(files)-1 do begin if res_test[ii] EQ 0 then $ ERRORS_ADD, nb_errors, 'Problem Local with file : '+files[ii] endfor endelse ;; ;; do the files having the good number of lines ?! ;; or maybe the name(s) is/are wrong ok=EXECUTE('res_lines=FILE_LINES(files)') if ~ok then res_lines=REPLICATE(-1, N_ELEMENTS(files)) for ii=0, N_ELEMENTS(files)-1 do begin if res_lines[ii] NE ii+1 then $ ERRORS_ADD, nb_errors, 'Problem NbLines Local with file : '+files[ii] endfor endfor ; CD, working_dir CD, current=current if KEYWORD_SET(verbose) then print, 'We are here : ', current ; ; 2 Global (not going into sub-dirs) ; for ii=0, N_ELEMENTS(subdirs)-1 do begin ;; path=working_dir+PATH_SEP()+subdirs[ii]+PATH_SEP() ;; ;; do we have created all the files ? ;; or maybe the name(s) is/are wrong res_test=FILE_TEST(path+files) if TOTAL(res_test) EQ N_ELEMENTS(files) then begin print, 'All files have been created (Global)' endif else begin for ii=0, N_ELEMENTS(files)-1 do begin if res_test[ii] EQ 0 then $ ERRORS_ADD, nb_errors, 'Problem Global with file : '+files[ii] endfor endelse ;; ;; do the files having the good number of lines ?! ;; or maybe the name(s) is/are wrong ok=EXECUTE('res_lines=FILE_LINES(path+files)') if ~ok then res_lines=REPLICATE(-1, N_ELEMENTS(files)) for ii=0, N_ELEMENTS(files)-1 do begin if res_lines[ii] NE ii+1 then $ ERRORS_ADD, nb_errors, 'Problem NbLines Global with file : '+files[ii] endfor endfor ; ; ---------------------------------- ; testing again FILE_BASENAME ; errors_base=0 base=FILE_BASENAME(files) expected_base=files if ~ARRAY_EQUAL(base,expected_base) then $ ERRORS_ADD, errors_base, 'basic FILE_BASENAME' ; for ii=0, N_ELEMENTS(subdirs)-1 do begin ;; full path=working_dir+PATH_SEP()+subdirs[ii]+PATH_SEP() base=FILE_BASENAME(path+files) if ~ARRAY_EQUAL(base,expected_base) then $ ERRORS_ADD, errors_base, 'full add FILE_BASENAME' ;; relative path=subdirs[ii]+PATH_SEP() base=FILE_BASENAME(path+files) if ~ARRAY_EQUAL(base,expected_base) then $ ERRORS_ADD, errors_base, 'relative add FILE_BASENAME' endfor BANNER_FOR_TESTSUITE, 'testing FILE_BASENAME', errors_base, /short ERRORS_CUMUL, nb_errors, errors_base ; ; ---------------------------------- ; testing again FILE_DIRNAME ; errors_dir=0 dir=FILE_DIRNAME(files) expected_dir=REPLICATE('.',N_ELEMENTS(files)) if ~ARRAY_EQUAL(dir,expected_dir) then $ ERRORS_ADD, errors_dir, 'basic FILE_DIRNAME' ; for ii=0, N_ELEMENTS(subdirs)-1 do begin ;; full path=working_dir+PATH_SEP()+subdirs[ii]+PATH_SEP() dir=FILE_DIRNAME(path+files) expected_dir=REPLICATE(working_dir+PATH_SEP()+subdirs[ii],N_ELEMENTS(files)) if ~ARRAY_EQUAL(dir,expected_dir) then $ ERRORS_ADD, errors_dir, 'full add FILE_DIRNAME '+path ;; relative path=subdirs[ii]+PATH_SEP() dir=FILE_DIRNAME(path+files) expected_dir=REPLICATE(subdirs[ii],N_ELEMENTS(files)) if ~ARRAY_EQUAL(dir,expected_dir) then $ ERRORS_ADD, errors_dir, 'relative add FILE_DIRNAME '+path endfor BANNER_FOR_TESTSUITE, 'testing FILE_DIRNAME', errors_dir, /short ERRORS_CUMUL, nb_errors, errors_dir ; ; ---------------------------------- ; testing again FILE_SEARCH ; errors_search=0 ; for ii=0, N_ELEMENTS(subdirs)-1 do begin ;; path=working_dir+PATH_SEP()+subdirs[ii]+PATH_SEP() res_search=FILE_SEARCH(path, 'a*') exp_search=path+files res_search=res_search(SORT(res_search)) exp_search=exp_search(SORT(exp_search)) ;; if ~ARRAY_EQUAL(res_search,exp_search) then $ ERRORS_ADD, errors_search, 'names in FILE_SEARCH' endfor ; ; global path=working_dir+PATH_SEP() res_search=FILE_SEARCH(path, 'a*2') exp_search=path+subdirs+PATH_SEP()+files[1] res_search=res_search(SORT(res_search)) exp_search=exp_search(SORT(exp_search)) ; if ~ARRAY_EQUAL(res_search,exp_search) then $ ERRORS_ADD, errors_search, 'size in FILE_SEARCH' ; BANNER_FOR_TESTSUITE, 'testing FILE_SEARCH', errors_search, /short ERRORS_CUMUL, nb_errors, errors_search ; ; ---------------------------------- ; testing again FILE_INFO ; errors_info=0 ; for ii=0, N_ELEMENTS(subdirs)-1 do begin ;; full path=working_dir+PATH_SEP()+subdirs[ii]+PATH_SEP() info=FILE_INFO(path+files) ;; res_names=info[*].name res_size=info[*].size expected_names=path+files expected_size=9*(1+L64INDGEN(N_ELEMENTS(files))) ;; if ~ARRAY_EQUAL(res_names,expected_names) then $ ERRORS_ADD, errors_info, 'names in FILE_INFO ' ;; if ~ARRAY_EQUAL(res_size,expected_size,/no_type) then $ ERRORS_ADD, errors_info, 'size in FILE_INFO ' endfor BANNER_FOR_TESTSUITE, 'testing FILE_INFO', errors_info, /short ERRORS_CUMUL, nb_errors, errors_info ; ; ----------------- ; print, 'to be extended ...' ; ; ----------------- final message ---------- ; BANNER_FOR_TESTSUITE, 'TEST_WORDEXP', nb_errors ; if (nb_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then begin print, 'Current Dir. : ', GETENV('PWD') STOP endif ; CD, initial_dir ; end gdl-0.9.9/testsuite/test_wordexp_null_string.pro000066400000000000000000000001111340051421000222000ustar00rootroot00000000000000pro test_wordexp_null_string openr, unit, '', ERROR=error,/get_lun end gdl-0.9.9/testsuite/test_xdr.pro000066400000000000000000000107441340051421000167020ustar00rootroot00000000000000; ; Initial work by Gilles D., March 2015 ; ; --------------------------------- ; ; Modifications history : ; ; - 2015-August : AC. Few cleaning ; (better way to locate the reference file "idl.xdr") ; ; - 2018-02-05 : AC. cleaning ... and working in TMPDIR ; ; ----------------------------------------------- ; pro TEST_XDR_WRITE, file, compress=compress common testxdr,datar,dataw ; GET_LUN, nlun OPENW, nlun, /XDR, file, compress=compress WRITEU, nlun, dataw CLOSE, nlun FREE_LUN, nlun ; if FILE_TEST(file) then MESSAGE, /continue, 'Succesfully write of : '+file ; end ; ; ----------------------------------------------- ; pro TEST_XDR_READ, file, cumul_errors, compress=compress, txt=txt, test=test common testxdr,datar,dataw ; GET_LUN, nlun OPENR, nlun, /XDR, file, compress=compress READU, nlun, datar CLOSE, nlun FREE_LUN, nlun ; ; being able to read does not means the data inside are OK ! if FILE_TEST(file) then MESSAGE, /continue, 'Succesfully read of : '+file ; errors=0 ; for i=0,N_TAGS(dataw)-1 do begin if (TOTAL(dataw.(i) eq datar.(i)) ne N_ELEMENTS(dataw.(i)) ) then begin mess='FAILED at tag #'+string(i)+" in file "+file ERRORS_ADD, errors, mess endif endfor ; BANNER_FOR_TESTSUITE, txt, errors, /short, prefix="TEST_XDR_READ" ERRORS_RESET, cumul_errors, errors ; if KEYWORD_SET(test) then STOP ; end ; ; ----------------------------------------------- ; pro TEST_XDR, help=help, test=test, no_exit=no_exit ; if KEYWORD_SET(help) then begin print, 'pro TEST_XDR, help=help, test=test, no_exit=no_exit' return endif ; common testxdr, datar, dataw ; DATAR={BytesAtStart: BYTARR(13), ShortArray: INTARR(3), $ UnitArray: UINTARR(3), longarray: LONARR(3), $ ulongarray: ULONARR(3), long64array: LON64ARR(3), $ stringarray: STRARR(2), ulong64array: ULON64ARR(3), $ floatarray: FLTARR(3), doublearray: DBLARR(3), $ complexarray: COMPLEXARR(2), doublecomplexarray: DCOMPLEXARR(2),$ finalbytesum: 0b} ; DATAW={ BytesAtStart: BYTE(INDGEN(13)),ShortArray: FIX([-1,-2,-3]), $ UnitArray: UINT([1,2,3]),longarray: LONG([-1,-2,-3]), $ ulongarray: ULONG([1,2,3]),long64array: LONG64([-1,-2,-3]), $ stringarray: ['String1','a Longer String:2'], $ ulong64array: ULONG64([1,2,3]),floatarray: FLOAT([1,2,3]), $ doublearray: DOUBLE([1,2,3]), $ complexarray: [COMPLEX(1,2),COMPLEX(3,4)], $ doublecomplexarray: [DCOMPLEX(12.,13.),DCOMPLEX(14,15.)], $ finalbytesum: 0b} ; dataw.finalbytesum=N_TAGS(dataw) ; ; locating then read back the reference idl xdr: ; filename='idl.xdr' list_of_dirs=STRSPLIT(!PATH, PATH_SEP(/SEARCH_PATH), /EXTRACT) file_idl_xdr=FILE_SEARCH(list_of_dirs+PATH_SEP()+filename) ; if ~FILE_TEST(file_idl_xdr) then begin ;; just in case, testing the current dir. file_idl_xdr=FILE_SEARCH(GETENV('PWD')+PATH_SEP()+filename) endif ; if ~FILE_TEST(file_idl_xdr) then begin MESSAGE, 'file <<'+filename+'>> not found in the !PATH', /continue if KEYWORD_SET(no_exit) OR KEYWORD_SET(test) then STOP EXIT, status=1 endif else begin if (N_ELEMENTS(file_idl_xdr) GT 1) then begin file_idl_xdr=file_idl_xdr[0] print, 'more than one file found, read the first one ...' endif print, 'Reading back : '+file_idl_xdr endelse ; ; counting the errors cumul_errors=0 ; ; test 1 : reading back the reference file, checking content ; do we agree with the content of the input file ? ; txt='Testing reading back the input file' TEST_XDR_READ, file_idl_xdr, cumul_errors, test=test, txt=txt ; ; tmpdir tmpdir=GETENV('IDL_TMPDIR') if STRLEN(tmpdir) GT 0 then begin last=STRMID(tmpdir, STRLEN(tmpdir)-1, 1) if (last NE PATH_SEP()) then tmpdir=tmpdir+PATH_SEP() endif ; radix=GDL_IDL_FL(/lower) ; file_out1=tmpdir+radix+'.xdr' file_out2=tmpdir+radix+'.xdr.gz' ; ; test 2 : writing and reading back a normal one, checking content ; ; WRITE our own XDR files in TMPDIR TEST_XDR_WRITE, file_out1 ; ; reread it and compare txt='Testing the generated XDR file' TEST_XDR_READ, file_out1, cumul_errors, test=test, txt=txt ; ; test 3 : writing and reading back a compressed one, checking content ; ; WRITE our own compressed TEST_XDR_WRITE, file_out2, /compress ; ; reread it and compare txt='Testing the generated XDR (compress) file' TEST_XDR_READ, file_out2, cumul_errors, test=test, txt=txt, /compress ; ; ----------------- final message ---------- ; BANNER_FOR_TESTSUITE, 'TEST_XDR', cumul_errors, short=short ; if (cumul_errors GT 0) AND ~KEYWORD_SET(no_exit) then EXIT, status=1 ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/test_zeropoly.pro000066400000000000000000000031221340051421000177600ustar00rootroot00000000000000; by Sylwester Arabas pro test_zeropoly n = 4 ; number of test polynomials eps = 1e-6 ; a small value used for camparing floating point numbers c = ptrarr(n) ; polynomial coefficients r = ptrarr(n) ; polynomial roots ; IDL-doc example (IMSL_ZEROPOLY) c[0] = ptr_new([-2, 4, -3, 1]) r[0] = ptr_new([1, complex(1,-1), complex(1,1)]) ; GSL-doc example c[1] = ptr_new([-1, 0, 0, 0, 0, 1]) r[1] = ptr_new(exp([0,2,4,6,8] * !PI * complex(0,1) / 5)) ; IDL-doc examples (FZ_ROOTS) c[2] = ptr_new([-2, -9, -7, 6]) r[2] = ptr_new([-.5, -1./3, 2.]) c[3] = ptr_new([2, 0, 3, 0, 1]) r[3] = ptr_new(complex(0,[-sqrt(2), sqrt(2), -1, 1])) ; trying with different input and output types for all test polynomials for double_kw = 0, 1 do for i = 0, n - 1 do for t = 2, 15 do begin if (t ge 6 && t le 11) || t eq 12 || t eq 13 || t eq 15 then continue z = imsl_zeropoly(fix(*c[i], type=t), double=double_kw) nz = n_elements(z) if nz ne n_elements(*r[i]) then begin message, 'TOTAL FAILURE!', /conti exit, status=1 endif ; checking the results (which might be ordered differently) for jz = 0, nz - 1 do for jr = 0, nz - 1 do begin if abs(z[jz] - (*r[i])[jr]) lt eps then begin z[jz] = complex(!VALUES.F_NAN, !VALUES.F_NAN) continue endif endfor wh = where(finite(z), cnt) if cnt ne 0 then begin message, 'FAILED for test ' + string(i), /conti exit, status=1 endif endfor ; freeing heap vars foreach i, c do ptr_free, i foreach i, c do ptr_free, i end gdl-0.9.9/testsuite/test_zip.pro000066400000000000000000000173171340051421000167120ustar00rootroot00000000000000; ; Testing the /compress keyword ! ; ; Maxime Lenoir, June 2010 ; under GNU GPL 2 or later ; ; AC May 2012: ; -- clarification (options, Upcases, identations) ; -- on Linux, "stat --printf=%s " does not work on few systems ... ; ; Some commands called using SPAWN may not work. Please submit ; an alternative via GDL Bug Traker on SourceForge. ; You can see the cammands used by running /verbose ; ; by default, we exit at first pb, maybe to be less strict later ; --but no problem today with /compress files ...-- ; ; GD, Nov 2013: test that seek works ; pro CATCH_EXIT, nb_problems, no_exit=no_exit ; if KEYWORD_SET(no_exit) then begin nb_problems=nb_problems+1 endif else begin EXIT, status=1 endelse end ; ; --------------------------------- ; pro TEST_ZIP, no_exit=no_exit, help=help, test=test, verbose=verbose, quiet=quiet ; if KEYWORD_SET(help) then begin print, 'pro TEST_ZIP, no_exit=no_exit, help=help, test=test, verbose=verbose, quiet=quiet' return end ; if STRLOWCASE(!version.os_family) eq 'windows' then begin MESSAGE, 'We are not ready for MSwin, please help (!fixme!)' endif if STRLOWCASE(!version.os_family) eq 'unix' then begin if ((STRLOWCASE(!version.os) ne 'linux') and (STRLOWCASE(!version.os) ne 'darwin')) then begin MESSAGE, 'We are not ready for this UNIX case, please help (!fixme!)' endif endif ; nb_pbs=0 ; file='test_zip.gz' ; txt='"GDL - GNU Data Language\nA free IDL (Interactive Data Language) compatible incremental\n' txt=txt+'compiler (i. e. runs IDL programs)."' ; ;SPAWN, 'echo -e '+txt+' | gzip > '+file SPAWN, 'printf '+txt+' | gzip > '+file OPENR, fd, file, /get, /compress, /delete ; ; Size test (FSTAT) ; ; tested for Linux if STRLOWCASE(!version.os) eq 'linux' then begin commande='stat --printf=%s '+file if KEYWORD_SET(verbose) then print, 'commande: ', commande SPAWN, commande, size, error_mess, exit_status=exit_status if (exit_status GT 0) then begin commande='stat -c %s '+file if KEYWORD_SET(verbose) then print, 'commande: ', commande SPAWN, 'stat -c %s '+file, size, error_mess, exit_status=exit_status endif endif ; ; tested for OSX ; if STRLOWCASE(!version.os) eq 'darwin' then begin commande='stat -f%z '+file if KEYWORD_SET(verbose) then print, 'commande: ', commande SPAWN, commande, size, error_mess, exit_status=exit_status endif ; if (exit_status GT 0) then begin ;; we skip the test if no result received ! MESSAGE, /continue, 'the option used by STAT is not working, please report' endif else begin if ((FSTAT(fd)).size ne size) then begin MESSAGE, /continue, 'Bad SIZE returned for zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif endelse ; ;; READ TESTS ; ; Readf test ; str='' READF, fd, str ; head1='GDL - GNU Data Language' ; no need to depend on these external commands -- we know the result ;commande='cat '+file+' | gunzip - | head -1' if KEYWORD_SET(verbose) then print, 'simple readf;' ;SPAWN, commande, head1 if (str ne head1) then begin MESSAGE, /continue, 'Readf doesn''t work on zipped file' if ~KEYWORD_SET(no_exit) then EXIT, status=1 endif ; READF, fd, str head2='A free IDL (Interactive Data Language) compatible incremental' ;commande='cat '+file+' | gunzip - | head -2 | tail -1' if KEYWORD_SET(verbose) then print, 'simple readf, twice; ' ;SPAWN, commande, head2 ; if (str ne head2) then begin MESSAGE, /continue, 'Readf doesn''t work twice on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; ; Check that a stat() does not move the pointer position: head3='compiler (i. e. runs IDL programs).' if KEYWORD_SET(verbose) then print, 'check stat() does not move pointer position; ' zz=(FSTAT(fd)).size READF, fd, str if (str ne head3) then begin MESSAGE, /continue, 'stat() on a gzipped file changes pointer position in file --- vey bad!' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; if KEYWORD_SET(verbose) then print, 'readf after point_lun(position=0); ' POINT_LUN, fd, 0 READF, fd, str ; At this point, readf works well, so we can test point_lun (except that stat() uses an equivalent of point_lun!!!) if (str ne head1) then begin MESSAGE, /continue, 'Point_lun doesn''t work on zipped file (read mode)' CATCH_EXIT, nb_pbs, no_exit=no_exit endif if KEYWORD_SET(verbose) then print, 'readf after point_lun(position=end of first line); ' POINT_LUN, fd, strlen(str) ; position at end of first line READF, fd, str ; should return '' since it reads the end of line. READF, fd, str ; should read 2nd line if (str ne head2) then begin MESSAGE, /continue, 'Point_lun doesn''t work on zipped file (read mode) when point is not 0!' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; ; Assoc test POINT_LUN, fd, 0 a=ASSOC(fd, BYTARR(5)) cut15=['GDL -'] ;commande='cat '+file+' | gunzip - | head -1 | cut -b 1-5' ;if KEYWORD_SET(verbose) then print, 'commande: ', commande ;SPAWN, commande, cut15 ; if KEYWORD_SET(verbose) then print, 'test assoc() on zipped file; ' if STRING(a[0]) ne cut15 then begin MESSAGE, /continue, 'Assoc doesn''t work on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit if ~KEYWORD_SET(no_exit) then EXIT, status=1 exit, status=1 endif ; ; ---------- ; if KEYWORD_SET(verbose) then print, 'test assoc() on zipped file when shifting to point_lun(5); ' POINT_LUN, fd, 5 if STRING(a[0]) ne cut15 then begin MESSAGE, /continue, 'Assoc doesn''t work twice on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; ; ---------- ; if KEYWORD_SET(verbose) then print, 'test assoc() (index 1 in table) on zipped file; ' if STRING(a[1]) ne ' GNU ' then begin MESSAGE, /continue, 'ASSOC doesn''t work with differents indexes on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; ; ---------- ; ; Readu test if KEYWORD_SET(verbose) then print, 'test readu on zipped file; ' POINT_LUN, fd, 0 str='123' READU, fd, str ; if (str ne 'GDL') then begin MESSAGE, /continue, 'READU doesn''t work on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; READU, fd, str ; if KEYWORD_SET(verbose) then print, 'test readu (twice) on zipped file; ' if (str ne ' - ') then begin MESSAGE, /continue, 'READU doesn''t work twice on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; CLOSE, fd FREE_LUN, fd ; ; ------------------------------ ; ;; WRITE TESTS ; if KEYWORD_SET(verbose) then print, 'various write tests.' file='test_zipw.gz' OPENW, fd, file, /get, /compress PRINTF, fd, 'GNU Data Language' CLOSE, fd FREE_LUN, fd ; OPENR, fd, file, /get, /compress READF, fd, str ; if (str ne 'GNU Data Language') then begin MESSAGE, /continue, 'Printf doesn''t work on zipped file' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; CLOSE, fd FREE_LUN, fd ; ; ---------- ; OPENW, fd, file, /get, /compress PRINTF, fd, 'GNU Data Language' POINT_LUN, fd, 10 ; point_lun used in write mode is pretty useless cause you can only move forward and it cause premature EOF. ; Also, you can't open a file in write mode, with compress and append keywords. ; So, if you don't specify append, you truncate the file, and point_lun become useless. ; To summarize, you can't write data and go backward to overwrite it. (Just don't use it) ; PRINTF, fd, 'rocks' ; GNU Data Language\nrocks\n CLOSE, fd FREE_LUN, fd ; OPENR, fd, file, /get, /compress, /delete a=ASSOC(fd, BYTARR(10)) ; if (STRING(a[0]) ne 'GNU Data L') OR (STRMID(STRING(a[1]), 0, 7) ne 'anguage') then begin MESSAGE, /continue, 'Point_lun doesn''t work on zipped file (write mode)' CATCH_EXIT, nb_pbs, no_exit=no_exit endif ; CLOSE, fd FREE_LUN, fd ; ; if we are here and nb_pbs > 0 then /No_exit was set. ; if ~KEYWORD_SET(quiet) then begin if (nb_pbs EQ 0) then begin MESSAGE, /continue, 'All ZIP/COMPRESS related tests successful' endif else begin MESSAGE, /continue, STRING(nb_pbs)+' tests failed' endelse endif ; if KEYWORD_SET(test) then STOP ; end gdl-0.9.9/testsuite/tiff/000077500000000000000000000000001340051421000152465ustar00rootroot00000000000000gdl-0.9.9/testsuite/tiff/24bit_color.tif000066400000000000000000030002141340051421000200740ustar00rootroot00000000000000MM* }}߉߈xt{|w~y߂lw߇x݁r݆l݃qފyދrm߄if݆mڃn݅q߂l}b݂y݁oy߃mg߆mj߇zp|h{tpuyy{yywtvztypyvbxinmbgR[VbJ\?TAU?Y=`7PCbH]BRIYEWI[JZI\IXFZN]PXLVKXISHSPYP\NYMWKYKYLVNZNWKTNXN]OVN]NWIRKTIQKVOSOYY\MVQXV[Z\VXNSY]YZ\X__\UZa\V[[e^a_\ZYX^]h`d^e``]heb_`]bhdf_]jolbfegfd^dc`_c[hg[Zba_[ibe\b]e_aVfja]a_igh[inge_[faa]iff_fcgeghc^gf`[jffdcdfde`jfdahigae\fedad\dfhfleghhfcdhccaiejge_idi_ihe\mijehafnifheieffhkpwffccnuhiebd[fcfkb\d^g^g]c]b[dieda_kjigh]jhedd^dhe_c\fgaZb]c^gbifg_e_gbe[idhcmef]cZfagf`a`^ggllmlrmhbfdfca[c\agdaf`b_eafgfgc]b_c_abd`fa]edeibihcbad`[fb`Zeghi^\__ggce_`cg_bfa]caacg\^`__[fk_ZehZ_^b]iY`V\]c[bZ`YaV]S[U[W]JSHRIYGMRRSbXUZYfaj_oenjtnvm}j׀y~pmۈt݈oވmߍuއnڎzڍq݃h݂syezi܁hzkڂj}j{iڃn}fރvځy~jރu߂n݀q݀p܇}߅th݄uށhi|dޅqm~gހk_߁i~peg~g|e|iۈlށjށf݀bh߁a݆o݁j܈p݇lۆqށj܂k܃r߈p݈q݈q܄uބk݄ob؃yنclqƑɐΙϔΝҟԣգӞ՛עҜ̕ŋ緆ޜzσt`_M^MYGVJZLVS]I[UZW^YZ[]X\ZcZ_^^]bee]aXVXa\\`a\WW\^^]fbdek\aZe^iZYY[\[^_X\]`XU[aZZ_b][dfVY]]a`^cac`\ag]c_[^_^[WXV`db\dad`a_del_[ae]]YYed_`aVaiXZ^`R][[TXX`YYTZ[f]^kh吁~{z݂ncZ}}߉߈xt{|w~y߂lw߇x݁r݆l݃qފyދrm߄if݆mڃn݅q߂l}b݂y݁oy߃mg߆mj߇zp|h{tpuyy{yywtvztypyvbxinmbgR[VbJ\?TAU?Y=`7PCbH]BRIYEWI[JZI\IXFZN]PXLVKXISHSPYP\NYMWKYKYLVNZNWKTNXN]OVN]NWIRKTIQKVOSOYY\MVQXV[Z\VXNSY]YZ\X__\UZa\V[[e^a_\ZYX^]h`d^e``]heb_`]bhdf_]jolbfegfd^dc`_c[hg[Zba_[ibe\b]e_aVfja]a_igh[inge_[faa]iff_fcgeghc^gf`[jffdcdfde`jfdahigae\fedad\dfhfleghhfcdhccaiejge_idi_ihe\mijehafnifheieffhkpwffccnuhiebd[fcfkb\d^g^g]c]b[dieda_kjigh]jhedd^dhe_c\fgaZb]c^gbifg_e_gbe[idhcmef]cZfagf`a`^ggllmlrmhbfdfca[c\agdaf`b_eafgfgc]b_c_abd`fa]edeibihcbad`[fb`Zeghi^\__ggce_`cg_bfa]caacg\^`__[fk_ZehZ_^b]iY`V\]c[bZ`YaV]S[U[W]JSHRIYGMRRSbXUZYfaj_oenjtnvm}j׀y~pmۈt݈oވmߍuއnڎzڍq݃h݂syezi܁hzkڂj}j{iڃn}fރvځy~jރu߂n݀q݀p܇}߅th݄uށhi|dޅqm~gހk_߁i~peg~g|e|iۈlށjށf݀bh߁a݆o݁j܈p݇lۆqށj܂k܃r߈p݈q݈q܄uބk݄ob؃yنclqƑɐΙϔΝҟԣգӞ՛עҜ̕ŋ緆ޜzσt`_M^MYGVJZLVS]I[UZW^YZ[]X\ZcZ_^^]bee]aXVXa\\`a\WW\^^]fbdek\aZe^iZYY[\[^_X\]`XU[aZZ_b][dfVY]]a`^cac`\ag]c_[^_^[WXV`db\dad`a_del_[ae]]YYed_`aVaiXZ^`R][[TXX`YYTZ[f]^kh吁~{z݂ncZ}}߉߈xt{|w~y߂lw߇x݁r݆l݃qފyދrm߄if݆mڃn݅q߂l}b݂y݁oy߃mg߆mj߇zp|h{tpuyy{yywtvztypyvbxinmbgR[VbJ\?TAU?Y=`7PCbH]BRIYEWI[JZI\IXFZN]PXLVKXISHSPYP\NYMWKYKYLVNZNWKTNXN]OVN]NWIRKTIQKVOSOYY\MVQXV[Z\VXNSY]YZ\X__\UZa\V[[e^a_\ZYX^]h`d^e``]heb_`]bhdf_]jolbfegfd^dc`_c[hg[Zba_[ibe\b]e_aVfja]a_igh[inge_[faa]iff_fcgeghc^gf`[jffdcdfde`jfdahigae\fedad\dfhfleghhfcdhccaiejge_idi_ihe\mijehafnifheieffhkpwffccnuhiebd[fcfkb\d^g^g]c]b[dieda_kjigh]jhedd^dhe_c\fgaZb]c^gbifg_e_gbe[idhcmef]cZfagf`a`^ggllmlrmhbfdfca[c\agdaf`b_eafgfgc]b_c_abd`fa]edeibihcbad`[fb`Zeghi^\__ggce_`cg_bfa]caacg\^`__[fk_ZehZ_^b]iY`V\]c[bZ`YaV]S[U[W]JSHRIYGMRRSbXUZYfaj_oenjtnvm}j׀y~pmۈt݈oވmߍuއnڎzڍq݃h݂syezi܁hzkڂj}j{iڃn}fރvځy~jރu߂n݀q݀p܇}߅th݄uށhi|dޅqm~gހk_߁i~peg~g|e|iۈlށjށf݀bh߁a݆o݁j܈p݇lۆqށj܂k܃r߈p݈q݈q܄uބk݄ob؃yنclqƑɐΙϔΝҟԣգӞ՛עҜ̕ŋ緆ޜzσt`_M^MYGVJZLVS]I[UZW^YZ[]X\ZcZ_^^]bee]aXVXa\\`a\WW\^^]fbdek\aZe^iZYY[\[^_X\]`XU[aZZ_b][dfVY]]a`^cac`\ag]c_[^_^[WXV`db\dad`a_del_[ae]]YYed_`aVaiXZ^`R][[TXX`YYTZ[f]^kh吁~{z݂ncZ}}߉߈xt{|w~y߂lw߇x݁r݆l݃qފyދrm߄if݆mڃn݅q߂l}b݂y݁oy߃mg߆mj߇zp|h{tpuyy{yywtvztypyvbxinmbgR[VbJ\?TAU?Y=`7PCbH]BRIYEWI[JZI\IXFZN]PXLVKXISHSPYP\NYMWKYKYLVNZNWKTNXN]OVN]NWIRKTIQKVOSOYY\MVQXV[Z\VXNSY]YZ\X__\UZa\V[[e^a_\ZYX^]h`d^e``]heb_`]bhdf_]jolbfegfd^dc`_c[hg[Zba_[ibe\b]e_aVfja]a_igh[inge_[faa]iff_fcgeghc^gf`[jffdcdfde`jfdahigae\fedad\dfhfleghhfcdhccaiejge_idi_ihe\mijehafnifheieffhkpwffccnuhiebd[fcfkb\d^g^g]c]b[dieda_kjigh]jhedd^dhe_c\fgaZb]c^gbifg_e_gbe[idhcmef]cZfagf`a`^ggllmlrmhbfdfca[c\agdaf`b_eafgfgc]b_c_abd`fa]edeibihcbad`[fb`Zeghi^\__ggce_`cg_bfa]caacg\^`__[fk_ZehZ_^b]iY`V\]c[bZ`YaV]S[U[W]JSHRIYGMRRSbXUZYfaj_oenjtnvm}j׀y~pmۈt݈oވmߍuއnڎzڍq݃h݂syezi܁hzkڂj}j{iڃn}fރvځy~jރu߂n݀q݀p܇}߅th݄uށhi|dޅqm~gހk_߁i~peg~g|e|iۈlށjށf݀bh߁a݆o݁j܈p݇lۆqށj܂k܃r߈p݈q݈q܄uބk݄ob؃yنclqƑɐΙϔΝҟԣգӞ՛עҜ̕ŋ緆ޜzσt`_M^MYGVJZLVS]I[UZW^YZ[]X\ZcZ_^^]bee]aXVXa\\`a\WW\^^]fbdek\aZe^iZYY[\[^_X\]`XU[aZZ_b][dfVY]]a`^cac`\ag]c_[^_^[WXV`db\dad`a_del_[ae]]YYed_`aVaiXZ^`R][[TXX`YYTZ[f]^kh吁~{z݂ncZ}}߉߈xt{|w~y߂lw߇x݁r݆l݃qފyދrm߄if݆mڃn݅q߂l}b݂y݁oy߃mg߆mj߇zp|h{tpuyy{yywtvztypyvbxinmbgR[VbJ\?TAU?Y=`7PCbH]BRIYEWI[JZI\IXFZN]PXLVKXISHSPYP\NYMWKYKYLVNZNWKTNXN]OVN]NWIRKTIQKVOSOYY\MVQXV[Z\VXNSY]YZ\X__\UZa\V[[e^a_\ZYX^]h`d^e``]heb_`]bhdf_]jolbfegfd^dc`_c[hg[Zba_[ibe\b]e_aVfja]a_igh[inge_[faa]iff_fcgeghc^gf`[jffdcdfde`jfdahigae\fedad\dfhfleghhfcdhccaiejge_idi_ihe\mijehafnifheieffhkpwffccnuhiebd[fcfkb\d^g^g]c]b[dieda_kjigh]jhedd^dhe_c\fgaZb]c^gbifg_e_gbe[idhcmef]cZfagf`a`^ggllmlrmhbfdfca[c\agdaf`b_eafgfgc]b_c_abd`fa]edeibihcbad`[fb`Zeghi^\__ggce_`cg_bfa]caacg\^`__[fk_ZehZ_^b]iY`V\]c[bZ`YaV]S[U[W]JSHRIYGMRRSbXUZYfaj_oenjtnvm}j׀y~pmۈt݈oވmߍuއnڎzڍq݃h݂syezi܁hzkڂj}j{iڃn}fރvځy~jރu߂n݀q݀p܇}߅th݄uށhi|dޅqm~gހk_߁i~peg~g|e|iۈlށjށf݀bh߁a݆o݁j܈p݇lۆqށj܂k܃r߈p݈q݈q܄uބk݄ob؃yنclqƑɐΙϔΝҟԣգӞ՛עҜ̕ŋ緆ޜzσt`_M^MYGVJZLVS]I[UZW^YZ[]X\ZcZ_^^]bee]aXVXa\\`a\WW\^^]fbdek\aZe^iZYY[\[^_X\]`XU[aZZ_b][dfVY]]a`^cac`\ag]c_[^_^[WXV`db\dad`a_del_[ae]]YYed_`aVaiXZ^`R][[TXX`YYTZ[f]^kh吁~{z݂ncZ{{qނoxsxqmujwe~rkh߄km~ki~ff|lzbr߄li߃d܁~~jރe߅lކm~p~n~d݄vontpuz{w||wyu~ivrcqxhvopm`\Y]U]L]O]F]>WZ@Z6U?\>ZCa;VDY>W?T>PEZH[N\R_GSEV@PKUFPLUCNJYERCQGSIUMWLXNVBLKOEOIRKUGSDOFMT_EQIRKPLRQU[\YZQZX[TWV\V^]ZcZYZ\Y[V_^\TVO^ZZUXS`ag`e_`]bXa^jfjl[Y`X^XhiaZefeca\bfXUd_Zbf`f^b]b]d]`_]Vhhc\^Ya``^a[c_g_cXjligiie^hae_c^f]f\b`d`g]lgbXd]gca[c\gedXdg]Xdg`aac`_cabae`\Xhbedibghead^fkcXkmggf_d]eaa\epeimgfocdlphboldcZ_g_ddcc]]f[gh_\`Wc\d_hgdajeorafb_edgba^^Wd^d\d_e]f]ic`\gcfWjjgf][e^gcc]a^c^jlc]`_ceglggefffb^a\]Za][^`_]`\[bdegek_dZ\fdc``gb__\_^_[ac`^aaaZc]fi\\f__]cd`]]_ce`e`]bgagbZ`]`b[]\`]][_ZZ_\[`]gamX^U_U_Q[RXPUOWHPHTJYGQFMUWUZ[Y_a`Xfaicmjvk{xtd{pۂkلىmۆu݆rnߍvޅrڄmi݁n|ejf}m݀in~o~i~fރ{f݆t{g܁k~i܇oh߃d߁j߀h~_݀k}c߀e~i}g߀d}dbgof߃jڄmno^}g}fށj܀_݁lf݂k܃c݅kڃn܄qۀe܄lބn݂g݄k߂g܁k~d~lـiߌmx‘ʋΙΛҜӝԛԟפ؝֜Әώlj컅{Ԉii]OYM\DVGWGTP_KUU]Y]V]TZZY_eXYQOY]^e\VXe\X^\e]]_\^]]bbcdZ\Y]YW^e`g^^_d\[ccWT^Ze_`_]_]W`^cb[\a_][^c\XVYce`^[Y`Y]b\h][a_[]^aa\XXYY[X^a_db__U_]`a^ZYXZ^UY```e_cebe`adc\^_Ua?M0Kv#Ge#D߅y߅yj݄rxtpj|tzrfc|tzmkj߄ihh߀f|i~`ށk߂hk~c}l}jހfi߄e߄oc݀frctrrvrt~uzxuruklh~dxizsh`ea[UX`R\MX9M:S8O0K5L5K4N;O9PCT>R@SGZNYKWM\JUHPFQBO@RFMHTL[FRGTFO@PJXFQHPLRDOFJKXHPKTHKLYHPNQPSOUPMQVTSSTVWYXZZ_]\Y_Wb]`S[Va\\XYSYY`_VYXV^W^Ze[^\bY`Z``acdZ`\c_b`ef]Sbfhj^^gaced^hce[ffdYd^e^becdbZg\cf_[d[_]c[`dcfecgeeif_h`ecab_[c^gkeebZb\c\`Ya[d[g^d`e[`]abgmd_d^b\dahab\hia^hfdge^digee_c_a\aa][ggfg_^mqkr`fa`qlkmhib]mid]f^cbd\_`a[`[a`cfkhojc^h`deb]b^f]^V[UbWe`e_c[ggggc]g\g_g`fe_\c_e^c`\Y`[ibg\eagahdc_ecd[e_b]c_`\`Z`edga]`^ioda^W`]`^^\\\f]d]ad\\a`^`huaY`bde_\bfdcaeb]`_cd\Xc^a_cdZW`d`_][cc]_^`Z[X`T\Y_[eZ`U\X[SXUXSaMVLQLYO[CPDPV[SR[^Z_a\llkdolsmvizkڃw~o݁lڃnބp܆xߌxx߈p܉vhޅ{݄o{b}izd~aހtkxa~kmh܀p}lہk{fڂu}k}n߉tm~flji݂c߀ddc{cf}ih߂g~e߁j݃m}\}e}`e|f܃j}`ށn݂gf܁oވwކgۄx܄w߃i~rޅiځl܃i~l|c|fmyōɍΖћњћԗӠԢԞ՘ѕˋ|ݚlucccJWCVK]MUUfN[U_TZX\TYYWY^QWV\]`WWYTZeZ]UYa`[]Va[\`c][ab[]ck_c_c_jZ[^]___[a[_Y``__a]^Y]\ec_^Y[][\XXV`c[ZYW`_\_\`V^\^`\]accaqagYY_[bkeabba\^c`a\\^_VZb`af`^`_`_TV>P5Jz,Gq)Q`BcJZ@jjpnvln}qks߈ldkrmjp߅sciu{f݆qn}l~p}l|g߄oo߂gqaknp{lvr왁rwwpssokqkfj{`ucvjk^jfXVV_LRTb?PP>OEYBNF^HZFPFRCMGPMWIPEPEOBNNULUGRERLOHRMZEPMSGNDJNWVZESKOJWFRTVOYS\OYQTMSQVY^UUVZXUX\\]VSYY`]Y]]V^Yef\Y]X]Za]c^WX\\]\bXb[^Yg`f]ebcYgedgcYbg^^aZgb]\`Yeec[cae_a_c_b_f\a^b\ebcWoe_]efdca\f`fbebigcYeeg^lcf_a\e[b`c`c_hbf^jcd[cffcc_^arqe`ij^_eec[e[c[fghbdif^ecffe^cdcab]_dioa`ddhmWYcdcehddamjiccgc_\Tb][Y^\b_b[dcjdlhiapmh^gedc^XaY`W`_f_eZfba[d^gib]ee`Z`\ebbd^[bWd\adf^f]hda^c_c]idc`hced`^_Xc`^[ZZefc^_\dcc_\[[_he[X`_^Wcda][X]]cj[Zc]\bcc`[dcd_cd^W_^^^`[b\`^ge_[_a_[\X`dXW_\b_Z[^\\]Wa\dU\RXSVSYKVNQUUQVIRFXGRMWGQSZUZYWgegihcon{psdՀym}n܀r܄rނsކtߌw߉l߅q߃nނml݂k܀kgl|g}jځg߂lhpdۄp݀qd݂iޅp߁lgނohhxeޅjjch݃o}ceeނq~gނjeb߂pރgނeރr߃n݂_ۂnۄn܃k~s}g߁r܃sہk܃mr܄ok~gقlkzlچns}ƎΚ̚ΘџҟԡҗԜ֚Әϙņ|ӌok^U_KVJTRaOZOSU^QWUWPYWWX[`d[^YYadXS^lW[^ZacY[Y^\^ZbZ]Y_^f^`\_Y\U^Y_[_[_\]^]^ca`^Z\[US\]`]Z_Z^]\aZ\_^`ZV]U``YZ`W\e\Z``cacf\^cg\]cb`aa`f^bb`^_abbcg^]]aaZe`_aMT?M)Iv$Fa=`AYB^B\G߂h߂hmކufmlsx߀hwrmop{bjjijjqdd~kl}kn܁k~blegzfcwpgumosttkrnynitrvh`}hzjman^faVUY\PYIT=O=T;PO6P7M8O8S;S>PCUL]PBQCOEVL[GPDWERGQJYITO\LULYLWJRIVCJDR?JHRFOBKCRHMEPEO?LHRKNSVQUJWT]OQRSPWXRVWWZUVY`Z]Z]\dYT\VbcYUa\cZVU\\^UZQbW]VZX_Y_Wml]V`bbcd[a^`^f_dehbbYi`bda_`Z]\`Yce`\eff_]U\YcYig`X_\^`b`cejaigaZeadac_``d[b[cffYg_`ba]b`aYc_e_gefcjmaceZfd^`cdb^aZ^Teic\e^`Y_f```_ih]d`]e[hc`]dae^d`faiidaeakdb^ebd\a`^b[Vbcc[\Xdbc\edd`a^a`cbe^f^a``Zd\\]`agbb`fa`^jdh`kle`g`dfigfaddcac`ll`\c\b_a[]\c_aaa[ebge_Xabi]egefa[b[a^e_a]`X]Uffa\dcbaccb]\\c]ee`_YXhe_[aa\Y[[\`[\`_a^b\[\ZY`^`\hcei`\\\Z`cd]eWXX_[Y[_[^WcT^P[T]SWSZR[RZJUSYJVGTGXKTO]Y\Xebfgcpsigwsun{m{s}m~kkwqtxrs߇s~j߂kqg݋p݀kinmpdnhprfkrmu߅p߅gndim}fhlހjfgp߀ih݂l݂i~cfށf~jf؇p~g~mo݃kڂpۃs܂l܀c܄saیoۀryf~kjՀn~qlu︉ŏ˖͕ΚԤӠ֧ӝך՜֚Ԝˎ笀ٗxxeYXKXIXLWJUM]OVPYRaSXYVT]SWV[]aYaX\Z^Zc^Y^`]]Z^^Z]ZZbVX]\ajQTUWYZXc]_[Y\^fo[Z]_[[Z][XWYWXZS]cYY[Z`_\XY^\\^[a`aZ]Y\XWX\W`j[]abZ[bchcfae\mn`ZdW^\PVAP*Cn!@_C[JX9[@W;Z=ZDX<\Y>]A[A_Allp߁o^scdr݆g{`pmliiexnj}ajނjj~e߆d}k݁fiiljgnryqluosxe{iwklxffvp^n{dqXtkfW`YZ[`cOVKRBW9M@W8K8MAX?QLAWCPHWEO>MGTETFQKSIVMUGQMTOZLVGQUYKRGMCS@NJOJTNUEHFQ?HELCLIOHROZGOMXSZQTSRQVYXUZUXTQWZZ]]cZY_^_]^[ZXZXYT]Ve`\P^Y\UZRa]cY]X^ZYU\Z\Ugd`Yeeb[hh_Zed_Y`Wffc`a]ad`baYbda\^[eb`Vcbf_^Zc[^\e[a_bY`\b[c\^Uc\mef\ace]d^``a[cY`[h^cdhgb^e]cdbeeeh^c]^V`]`g^]cee`jjgihffefacefchg]Rdlji]Veia]a^ibfb_[f[b^id_Wa\b]dbbXda_\e\c[gdh_^c`]fa^``_`V^\d_d_g`bX_VhebZc^ldead_ij`^ml\[bbc\b[gedae^a^_Ykl_`c\dac`a`a\af\[`gji_[^effb[`_ec^Wbb^\]Zba_\^abf^Y]]]__`bbbb`aZVcd`^d]cb\Zfia``Yf_]^gh]^Z^VZY_Zab^\m]`Z_TaVWZ_XhMXSYQ[QfYaIRP`O\MZFWIXOZR[VdV`_dkjnmtmvmvr{s{m܀vrބm߈yiwqi}upnw߇o߆{rwsoittuhpqogkklhifm}jbtndle{d~ieane}i~b}f}i|i}o}k~gځiۂhnفpفnۀn~uiׅv؂mk؂nyk{do~ŕȋ͚НўԚ֜՜՛՝֟ҟ̌Ò|ݡ{g`_INM_LXP_KSLWNTR[RTQVY\XWSTScV_UV\_WW][][UX[]^^_YY\]^]\VUYXY[SZZ\^a\^`oW[W\ZY\[a``^Y`ZVacb]``db``]\^\`_ZX[Y^_[Ua``bag__ei``gae[mdbe\WQSITb9ZDh3\[CYDZ?]@[ C]C[C\Esskmfpm_߄p߅n`ohphme~remldhlyfm|g݈q{bohfvvkkyouqxw|nkk{ftcmsfcd{hqUqbcO_XU[PUKTT_DV;O?U:L;P;S:K:J:JBNHSFUGQBKGVCMJPISNZFNNTJUHSGQBLKTHOEODQFPJQELMVLOCKAHDMFNITNOOYOTMMNWLMQQY^NPQ\UYWTVTYW\l]\a^^`_W`\]Y^Y``he_V_X_Za\^YaaedeW]a\_f`d]\Yc^dc^\hc`faVh\aY_\ca`]c]`Zaa``]Y`Xfbeaa_d_hafhc\_]hac`b``Yc\jldg[Tgmd^_\d^eebZb^`gb_c]b^fcbdc`li_\c_^Vfg^Xbbdejfa^`dhcddacaa`^gecb_^c`a\cdeg__ifa\fi^We`efa[b_c`cYa]ghb\bXee_]ceebe]e`d^_Z\ZeYfae[dcc^e`d_a\g`hba]h^hikiif`a`]aYijif^Xb]aga\a^ega^gc`_e\ab`_hfgafc]Ya`eb`^ca^Z]^^ZbZ_b]Xa\b_]]`bbcdgd]en[aa_fg]\`[c`dca_^^[Zb`ke_abg`jcgcbgo^`_c\`YXZ[Z^USW[V]KXUaU`ekJYO[R^GVHXKWMYJWOZQ][cajhijeslvsxwzv~m~u~pޅt܂xpoފ}rqvnkxtqktpwkjntpmohigokmegkmhcl|ce}hheapf]re~l~e|l}cyf~g|koـmځs}g݀kقtjn؁m|d}l|nuc݁dr{~ŋɗϓўӘԡ֢םՠؠ՟ϝȑ!孊וnxoRZKYIQP\LOQ[LXLULSNW^]W\XZT`UUY`\c_]TYU\]WYYa_b_[ZZYX[XS\aaa]\]]Y_\`]dZ[[a[aYXY]agZY]W`c]^]cZZ^[bgX[`c_\`\abe`_Ubeh`fdg`bakjq_hc\_OTDQ7K~ Fk=_EX@V=YD[A[@X;Y8[H]:`D[LGLQSPSIONTDNOVLT?KJXCSCSHSFKP[CLCNIODNGPBKAIHPDRJNQRPROTSPQVPTORQPYZYX\VUU`f\a]aWUcb\Z_][[][aa`Ya]_Xb]^Z^_cYd`b^^\^Xc\a[fcaZe`aZffaU`]a^_Xid`_b[d_ec^^fd`V]Z`_f`d`edd^keikc]gaf^aYc\qra_eaife_haa\iegkcgd\glddcZlia\c\j[be_b`Wec_V`ha]]b^\fd`behbbce]^acfgaagdgaebgjabjcfc_^``cWirb`hed^d^_[_aZZ\Z`YfWidd_e\ehd[_\d`bW]fd^`]d\c\hbdZljiac^iapiigdcgYcbedgcd^cX``eZcmg_b^a^hg`Z]^b^bZbbe]c]\\^\_XecdacY`[`d`X^V_aa^ZTW`]\`]]_b[`bb[bfc\^`b]di_c`\ab_b^_`Z^eb__[ab`_``^aacSYWX[Y_gUW[\TWORS]VY`cYfPXHUQUOZM^FYETLZT`W_Yedhkgsnqnvoylrl~s~t܃x݇wktvprupoqnhnumtmpykivpvmqjugxdrlojnnhk}dn}d}d~d|[~m߂kރr݂rze~cڃp{exd~oۀqg{kn{mفl~h|g{gׁnԃoubzgi~ŏȖΒЛѝҗդ֣ץפ՟ՠΓǐwֆk`\UaLXLaCPMZUbLULUUY\^V[TWSXQWRXXb[ZZ^Z^][XX\[Y^WWY\V\__[Y^^XX[ZcfW[Z[aeYX`bag_a]cZ_Z^_W^^efc]ab^Zf^d\dcgj^ZaXffdde`d]gciijiha[[QQ@M3Hy@f;\;]DU:Q:`AW?Y?XAY;Z>Z9^>_Eqqokg}ozefllkeeomfh~f]xm`hmk{f݀p~j{im}pkxytlpksjttqfungtjkngc|iwbtXk\gZaTWSMPJPGR=J5EK@NJNHR@J@MCKEOCJGP@PGMO\HQGSISEQEQKXFNHMIUDMGO@L=IILCMDKHPLTMXJKLRUTMXSX[aPSWcUbVURWTVXaZ_]bV\[^_V_c[ZVVZW`b`^^\^Vak`_]X]\c`\W`_[Yc]d\d^hb`^ge[Vhg_Wc\c`dgcZb`b`eaa^`\`[ed^]fabYbcb]d^gca^a]_X^Zfdc\fjc\hhb[aageaYkgjbecc__Yc``[a`ie_[f_h^b`eWaZfg^V_[db`am^kta^e_aad`b]lkaaa^ce``ca_ajaed`[faona^`^`^a`\`cb^`^c^`jce`kcgc_Xb``_`^\\_^ZUeba[hce`kfgikdigihhbhbgegdcbabe]jhc`eef]cf`\c^f_gdhcacdaa[c`c__Ydb\]YZ`d`\abiceo`Za\bcb]ZY^\`_\Z[d[Y^]a]c^_aabb^a`][defc]\YU\X]a^\bda^cl]gch`i]b]`^fZbTVSVTYOTPZWYW`KRQWMUQ_EQDZKTFZEXO^U\Zifoadkpokplqp|owہx݀n܅xvvoq}srut}nojvnxnvtujjoinrhksga߅xjrnp~ovqbi~if|dma~lچs݀p}ej܀m؂t|i|m~g~vj؂pՂm}l}h~ezf{fyhv_vi݀ij}Æɐ͒ѝաӠ՝Ԛ֣֟՚բϒƋﻑvՈjojLVHYIWJUP]O_NRPWTYX]PT\gQVZ_\dT`X^Y]Z[^[`dbaY]adeb][gga^Z\Z[]c]b]b_ann\Z^a^[YT`]cgXX`\a\fh`d^Y_]db^]hfa\dYd^gjg_kelba^Z_MQM?HMT>LAN@NFPIUMWISEMUXK\JZINFOFZJNGOO]GKGVPSENQ\JVCGCNHOKRNSRYW_LQSTTYSRQU]f\^]`\SXYYXVVSS`\]\][XVYWZTaZaZ`bd][]^XbYb_dbbb_Z`^^_`ZcVc\d`cea^gbcYfikffddgf_fdifc`a^`\bafafd`\`[\beaaZdd\[e\bf_``^ecc[ijg^dac[cb^Ze_`Zc_db`_gc^Yccca_Z^Z`]`Za^ce]]`]`jd`lhekedgga\c\babadgfdaaacbe`^a^_cdchejccfa`ddgjjmdkdgbaafjf`ake`[f[pn`Z]\dd^[aXgdc]bXbai^eid`g`llnlhfdaidjgbbaagca^i`gdfdc\ii_Z]^cZowvn_^_`\Z_^a_\\aY`^dc_`ciebb]agjmcZ^Yec[Ybe^cfj]a_Z]Zdjb\eid]em_eee\b^[\^``b_``ac_^Z_gm^]\b`jZaWXX_X[X^TYP`U[ReMTN`NUT`LRLYDSDSHYM`T\U^Xgcajgpnlivm}xymفw~x݅vsprtrߌ||trznqkplsxmwssloltqmfmlgjsnjnlolcށlmfbnl݀k܁fځx|b}g|i}iۀl}l}fۄt}jyndրrكrـnj|fy_~kxdkjtȎ˖АЛԢӡԞԞ֛֝֝љ˗È촀o}kZ[JTHSINIZMZKTO]S[SWU[VbPUS^YXU_Y^\Y`]ZW`aY[Y_\_]X^X\Z]_\^a`^Y\a]Zad_Z]d[`^^_[eq_\__acd_dj]Y\Xafdeb^gcgdi^jegeh`h^d^_XLXDK,Hy$C\?T 7YWAZC^Ea&M]A`G[8X:]=]9e=ii߁myrmn~kqjn~jiqmuevhk}k|srrozjeun߆mufporknsmvssoimunfimujacks]ugn\g]jod_ahdiZcHVAOFX2F6L9S6G>H?J?HAR?OCLGOHRGLIPJULQISGGOXLQHSFPDMGQDNITESCLDOKOMTBHIOFKDLAKESJRQ]OWMVQWSSNPSM\[TOSUWVSTXVVUXV]ZXX]_QUYW[Ucb[WZY_Y_[\__X`_b_^]bb`b`Xd]cd`_`Z`a[W_\g_dl`Y_]e\gjdba[faebfab`c`diaVc_^]addbb_hee\^_dd]ab^faccaZdbcYfg\Tb``ecW`_dfaaa_a[dcb[c`c^`_je]cab_^cfefffZZ`Zdcbb^Zd]\[`Ykkdi_\cgfd_[^`ee_edfd_`_aannmefm`^e_a`ebb_iabecaeh\Y]Xa[\V_Vhl_Ze`gec[hcgdgfefefnrrrjmficf``hna^d`hic\\Tkl^Z^_aZgepngc\Xg_gd^\Z`_[aX``^^fh`\cba`hld[^b[]YW[`\\^ea`^db^^^a^`ac[bf_`cc\Y^]\^a]\]_X]^cf]]Z`^b\can[gZ\px]bWYZ_U\NWU_U[M[M\JXHZMYIXARERNZR\Wa]fcaihmknlwpxsvk}rtކrރpqi|}uytswulhrsߏ}z抁toossoqktnllqmotukyx}ceuuoeބsހp~jmڀs|h}jځq~j܃qۀj݆o܂n؃nz}dzmۀqmzi~m}iمuylveڀdsxŽǓ˔НқӤӢ֤ן٣٩՟ϐȐzՒkshWYETTXTcMVLUUWVbTZQUMXUYZdV[YcTX[^[^[Z[Z[_][^\\b[Z[\a]UZXYbf_bUT[e\YYX\\ahdiec`db`a`^b`^b_ecdadke]hfffg]nppdhhea]\NSFT3Gq$J_B]HP?P?] I_1TY FWCWAZA^"L_E[?ZF]?]D]=bBlljmmkjlo|dejftdemjtgބo}k~e}mgރw}kqvlߌwr{uoovgpsneuohwniiohvmauwYtgn_kYca\VY\OSISDUP>NAMAL:LERBNDRIRELCR_cISFTJOAJCNJJMVGQNRQUHP=GAOFNAGGLNSBHFQDJGKGPKYPTP_PTOWSVOUSQPQWZNPVUZZZ_WP_][[ZUc^\S]V[X`U\dVUWTaZcd^Z^Xf^_^b_c__]^Vcaecd`ad_^^^eddbek`[][_``Zfj^Zfe`[`]_bgcbab[`W_afed\ccbUaYb]a^aYe[bc`WfadcbZb^dZ_[_[bSb]g]\Zac\Yemgh]`bZidfb`\_\dghcdffae``[^[d]\Z^\]^b^hjsva```][ehc\b`_b`b_ac_dbmmbY`^caibdac`b_^Zddb\^cbc]Z_[bZ^[ea_\b]ada`cbbhhigikhostrlkadjgib`dca^Zdbhj]Wbdhlc\]`ee^\d__W`[`b`^beZ\d]dX_`YXb\[[]Y\[]Qabbg[YYZZU]]b^da]UX\_V]caZcc]Y]V_daZb]__aa_Y_Z]\\a[^[a]gZf\d]ikq]eY^OZMURVS[Q[PYHYOWHWRWN]KWHVOVNXR\SWa^ffoirkumՃxe~t܀p~vނn߇sߊ{yyxwuvzqniynqrssqkktsiyjqll~g߆rmrlp~ojkcqp݄r}d݊uj|l{i~q~j|jig}g}h}epۀqhـkypׁmـnyi|n~mxhvdtdyfh}|ȏʒ͘ΘС՛՝֢ՠף֚ҙѕʼnߡv}h_]LSKRP\UXMVKQQXUYT[PUXZ[aUZ[ZW][\[^UY[\`ib`dnUW^cS^^\eo_Z`c`hX^aaaiae`ffjlslkch_^eia^c`c`ddimccgegckmcdllqffhceMR?O)CtAg>[>U=UFS;W:VCZCW KVEX;XW>\C];\=eE`@rripk{`ioog}`nrrknt{pmlppiyeoemthvlngouvwjswcvpjrxcnglpkh{jx^~lnbj`iregZ_[iKVAP8OS@P=KEM>MAJ@NFP?GHWlmIPBKFOHOGRAJ@NCMHNOWGL@ICJITAHKREJHNGNDMHKFTNRPQMUXYSVMPMOVXZXRWXV^XUUU\XWXWWWST`\]X[U^ZVTZZ[V]^`UY[^W^Ua_`Xe_g_c^bZ]Zd``ZeX_`d`_^^_aYf^_bfa_\`a\`aWe]_bcY`\ff^Yb\e_cfd^c_g[a[bZeb`\b]aegac^^^cccha``^h_c^f_a[aZ`d\Vdga[fZ`XbabVcciccd^aa_c__[bcgb`[XTa^_]d^eba_[__Y\bbcb[``e`c`b__`a^``\]`Ze`a^c]a^`_^Wek]Yb`]`_\a[]X^YcY`e^]f`_ab]eifahbhffekhcacc`_bab`ccb]dacae`aad`fiac_\e`a_ccc_ca[`db`\\Xb[caa`Z]\YZ_[^ZZaa\b][ZTefa`bbad]V^^`W\d^Z`^]][YYZYXca`c_\^Z`\[\^bY[\`Y^__\bY^X`[_[\R^PVWYQ\P\MWS[X`KWJTJYGZITKXO_LXPY`bcejlmgtp|q}tـzx݀w܃p߄|ކvxs|xwo~mosulnpqr߈zpziugnirnudm|euklf߂sk}arh}g܀g݁m|e{m݁l~o~k}o|i}dۃm|g{h~j}o~mzc|i|n~hzi}j}hpbtavhtc}egyˎʏКіҡԙԤ՘ԡ֜רӗΔÎ{ܓiqaPSGQHPJVLROSPYX]W[MR_aSZ\cXVV[WVXXSXSYRX\X_f`ac[]lZW\[]^X[VV_]ZgVZ]]dffecc_`knhmilcbgga\chhhaikagikliXqjf_`ZU[:G&Cj>\@fDW5R>U?U>W=\ G\H^)YY?Z@]GY6\?]<`=e@aAa?ppj~o|gqjp߃ktdsnfriojikrhomނg߂okfxayvtqzqtoitmjmmlxpgndyqfemzi|osdlcc`gg[aU[BPCUBS6F8M7J6J?N>L@JCIEO?LAIKSKSINIRGODMDMDKFQMSDMDIDNGMEIKPMVORFKBICLMVHOHPHPINENHPJMLOJRMPPUOPTUNSSV\\W[SX\WXUUVXT_\WU[W[V`X]b]]^Ycc\]ie`_`Zgb__bV\X_V`[d_dc]]^\cdgjd\jhg^`d`[]Zdk^]_Ya^[^e`a[`b`Xb\c\b[c`gm^[ab_]c\c^f^b`ddc_a\ek`d^^`X^Yc^^Y]Za[dc[W^Uio]VZO`^d``^`_ge]d[Ub`b\e^a_]UZ\^X^Yb]^ab]YYZ[`^]Z^Z_Xb`_[`\[^dc][XTa\cab^e\ie\X`Z^bf_hf_W_\__b]^Y^Xaegbgfljaba^deafb`feddhkb`cdfcbZek]``_\^abc_ceaYc`c``Zb\fbh\b`ed_\`bb]`\fdekYW]V^_^_[T_`_^ZX^[[T^W`_[W]X]Ve_^[ZZ^Y_Z^bXYYY]Xgf_W_\c^[[_[Z]cj[aY``aVeX^YXW[^kRTQTPUS]OZP[S[U_HUMYO^IZOXR]R_S[Zfcefemkxrwlxzun}sۄ|܇sރp߂wtuww}xolrmeusmqouqshnitnpqކgc߁ol}cldiq~cojۂo~e݁on}e}lڃmg{m{fفi~nځn}m~m}j|k|j|hxlmm|hـu׀ps`ugygwp܉lp鴇čɏϒӗӝԚ֡Ԛףם٦יΘLj츆wԆdf^U[MUHQNVWZK[OVPSTXTWQYXZY\U]VR\cQ]XYWX[VX]\]^[[_ZXZ\]_UUYc\Y\aYYZ^^e]^bdcfdg`ackbedeeidbf`hegaebjli^no[^OUBV(EgE\?\$S]$NX?X L[.OYHXC^>Z F[HX=[Aa>^;Z?]?_:b8c7h$Jkkl{n}luoↀpphjmhguklmkprro}oor߅j|mqsowwotkstsrvsl持c߆nlhmphffoygr_m\`X]_XWQWHSDSZA^AcCcCbEg>ee~km{ipq~pf~rdoodqmopjp߄uomކvomvlw|n{wuqsiwknqptjqhrlnpcsg{]|_shq_lYfcZ_WRP[EK@K?K6F4H0K8D8LGT>L9H>L>J=HDPJOMVGQNTFOLUISHXEPBQHSKTOUELGPGNGRDIAFISJQ>HGMFOMPJRPQRUPWLOOUNSTROVXXVY^WX]ZU\XWTTRZV]UWT^T^Z\[`^_^_[[Qa[b__YZQ`[XWhheZ^Wb\a^d[a]d`]\bgbZ^Y``cbc]bbXXa_gn^\`a_\Z\```_\X_Zd^a_``aV]`Z\^Wc]e]hcbf]Vc`dX\]b^\U]S\X[V_Ydb[W`[]Z^[_[aaqtytcafebbe`ila[\[\[][]^[O_[_ZZV]VZPYVVUZTXWa^]W[YZZ`UacZW][\_]Y_`YY`[_XXZa[^W[\^R[Xc_cZ\[XPb`\[]X^W^^]^d_^^_Zfgeka\e`]Ygg``_[a^daa_bad_d```c^bag`YZ_]`\`^]Xbb[XXZ^[YT_[^W_YaZabWR`^`^]ZYYaa[Y_c^]`Z```b^U_c]Y\W[ZZ\[Z\Y]W_[gda``_]Y^^[Z]lbg^eZb\bbphl[bT[UcNXPZITKWOaNSJXITJRG\Q]P]R^[lYiag[einpqpmuswqہxzzu߆z~}wwq|zstyzoxj~jpknslhduenhmij~g߂o}elއjނl|hec߄q|ngoh݀dހjހpe|lkۄmm|g}l~f|j~kp|io}iyl~oxfys|jykyqyayiކmuÁɕϘϗӢԚס֤ڟ٢ء֝ϕʍחjj]MQGVFMKYLYOWMXYWZcSVYW\^[_YV][[ZXZce_T_ba\[][`\T`_^^\ZZ`[Z\[U]XX_gbibk``Zc[Y`_icdmeb]`eoidkinggdcfLU=R)ErB_*Qg8Yj6[U@ZEW 7WDY:W>XDX 7Y 7Y?Z8Y;[8d;a:cAk7f>f=i!>~b~b}rރqjpjlkmmddjlirlnrrjogkrfypmysvpynvprlgmmkslmtmlgnzbyahxfr^mYeZWUQRKJ@N:H2B3I5F+C2I2E@P;K=J?LCLBMGRHLCLFN?MKSBPJUDOFQEQHQKTDMFSFOAICTJRJMETCLAIHPDJKOJQMONVKOIORXPTOPRUVZ\_]ZVVWSVU\aTSXQZW[Y^WYQW\_[\d]]b[d^aba\[RdnYX\Z`U``^]b]bWb`cbYV`ea]ZV`c_`Y\cc`fbdbgb\a^d]a\cc`]bbc`aY^Yaa[T_\\VZZcY^Y\[`gYTik]Y]_baeXaX`^[Xc\a\`[jicajmecen^\kkniad]We_op\]aca\`^_]TP[WWTZW\\ZQ\`__[YXU[X^T`X_]XQb^]U`d^aa\a\c^`XW_[Z\[[Y\^f^_]a]_^\YWR_\a_`\XW]]]^dh\\b_fcegcbfd_bfeec\``__^a`ecabgdb`cbicc_`\^YbZ_\`Z]Z`XZ_\Z]Yaa\_a_[`_[[Rjq\\]^[]^R`Ybi`X[\a\a_XYb^`U]d_[`[`Za]db\c`_]__[_c_g^_]`\^XgY^_``j]_beX`SZO[JVS[QWKVJSIRFQLQI\N\KXTcQ]XcXd]h`djollpirvwqt݁|uzxzyyrrxuvusrppj߈ktrjxrosihjgilg݇p݄tgj߂mo{k߅gfnoރk}in}g݁nk|h{j܀pko܂f{n~b~oq~g~syi؀k}p}e؁ozfrdzoyguqzgw\nqćƐ͓ϙӝәԜלبآ۟ڞ֚ϖNjߧw|kaVEPJMKONTOSPTRVU[UXVTUW`ba]]a]aaaadVX^^_\W\\`]\XUZ]XWZ^ZbXWea_e^ddfXU[_^``abacc`^i`ebhehegfja_VPZAL3Mm?_HU 8[B`%J\HX@T 6R;S 6Y2]K=IGTDOCJLPHRFKHQJMERISJNXcMUGULWLYNVCJHTHMCLIRAQDOFNHMHPJMLOKOKKJKHONYSWUUUXUZX][XWWWZQR\_^^[W\[ae\\XYY]a_ik]\^XaW`d^_^aZ[]b`][Xad[[^\_Ycl^]cg]a`V^^a^^Ycb`]\caf`cef_`cbfcada_aef^cd`\b[cYYX[Ya_bZa]]\ba]Ycc`]e``g`Z[X^[WZ`[]Waaa]cabd[]hscqabdbnloqb`_Wabbb_YYVY[VZZYYV\V[T`bSWTV\YZT[[YT][[Z]Va\ba]\cf^WZ]^_]X\db^\Z[[ZV_^`W_b^a^\aa`^a`hi[WZS\_cdY]^a\```kgegdcbehacbcabfgec_ehcc``fda_ml\[aX[^_a_X^Za`_Z^[`^]`a[`dZ\cfWX^]__`]^cWU`[agZX_cd^a__]]X_VYX]YYZ\Z`Zdeab\W\^^[]][Z[X^`V`ZYYU]h`^Y^`k`bQ[V`JUNZPZMVTYKOMSGPHQH[O[R`Wc]c[c]hchmoijvsupwwuy߅tއ~{~}߅y{vtssߌ~no|oo߃o߇nއrmrbgޅliehj߉ph~aނiqo߆w~dinkmkچoh~kjo|h܃t܄r~i݄nށl܁p~kނg}iփnځmyh܀b}tzf}i}nxkyjyo{mvcsfwcބdwđɘΚєқԣաث؞ڡܠ١Ԕȓ„鷆ՖtzoORKUIQHTSSRTU_X\U^NQSRahce`j]`^``_WaZ_bc\\c`^\[^\cXSfhS\UZ^]cd\_ZbZZa`]`bf^`febbg_fekhlnge_XQO>L%Ao?^8ZFW>W@^KZDWDQ9V>T7U>];[@\=\8`e;g>d9c7rrlujkinhfiknkfitnisiisnl{ktox{ko|xkoqwkk`hluil}hdngjj~`}dw[pYl^_SYUVRNKEN=N4E7C0E5I2G7D@L?NDK=HCRCOELAKIXEQ@NJQENHSLTENGOJWNXIRCLKWMYAOIOHNDUBMISGMGMKWLOKSKLNXMSSVVXRRURSUZ]^ZWV[^VVUT\ZYX[W`^Y[]]]\^\`Z`[`[[W]UVV`Z\S\^hdbW`][[_\^W_a`Y^^\]^_`^ci_Zabb_fda`cafnX]``gh_\ega[`h]]]accb^h__dbd_Z`^`_]Zefjgde]Y^d`^ab\]\Z`]`\`gb[`]]bc_geeae`hjookilje\^^`a^\XW[\XWYU]][T\\ZX]UVWUTXSTP[[WYYVYY^^_\ad``_\`\Z_XS^f\\]W[Z[_\XWVZW^fd_Z__Ybc\Tbb`^^Xaa`^^]^a_]^^fodc_\ablofd`eb\daebggcejfcaa`a\geb``_a\^[ZZ^\a__f]^`]^d^[cm^\YQ]b]X]X]Z_^]Z[T^_^W[U[^\U``]WZ`ZaYUaZcd`j[Y\Y\Z_^ZYX[\b\a^c_hS[VX]dYdQXZiW]W[LUS\PSLWKQHTJOLVLYR]PdYc\ebiblhkhhpqrqsn|{ځu܀{݀p߆y߅wvމ|ᐅzuqvzqouqqߌynk߃ommliffkdnjfijmd߁y߀clnyonqot߃oނp~mހi~p݄x݅p݃qr߀i|j}kk}m~mۀc܀rڂs|e|oygyi|hvcwc{`tjsciqǑˑҞӞҜ֣բ֟ب٤٤מӛʌzΆme_FNFNOUMXRPMYPUY\U[UUV\]_[_[YW`XZ_X\`][^^XYZ[\[]_\XY]Z]_bZ[^]^acg\[f`]]aaabklg_fekfkahmPTQ[4E'Ao=ZNAIHWJQJWEPFKKQFOGRJQIMJPJULSCIJOMSGTDMJOJPJOFPBPGKKNHPMYINLPENLNSWOTRQTUQTQWVPUU^eWVYT[]YYWX\\\V[X^Ye]]U`X_\`Y`X\Yc_WRed^Z[Yc]YVa]^[bZ\Y\Y[`dYd]giZ]aa_Ybe\W`gcj`[[\cd``bc^_dadf_`eb_Yc_cc``bZ_adZ]bff\\afTVdc``]^WXZXah__\[WU][[^^Z_aiid`hkbcdfifbYdlbf\_[`[V\WXY`\\TY\UUZYVSWUYTXQ[\[WWVQWY^]Wbcfj^^\V[[[V\_Z_XX`YY\ZXYYZ_[W\Va``_[XYWaY`^^^hdfed_^^^[a`ac_]^[[``ba`bna^`^a]efidjgie]`aX`_X]XU_Z_bbZ]b[]aeeba]bkb[a\_``\c]ZY^^\Zea[]^TYb^W`W\_\W\bY\Zb_kXT^^bbac^^f`_\_\[^]]]c]_`eV`MRU_V][bTZYgY\MWMTQ]PVQZPVQ[KWLZLWM`QbUbUb_e`jbhemlmtywyuo}zm݂|wނrxwvyu{pxvyߌyxލxsttoވr݉mwrr߉jmnmjofng߈kg߂rjpnnm|nk}a܆vs߃v߇qkކzۃvڄs݅p}oڀl~p|n܂p|c݀o}n{r{fyhyjwqtl|n{irb{kve{asyÐǓΘИқգ՟آ١إ٤٠՗ВÌ}ڝw|kQNGMMTKRMTPWS\UWVTTWQSUTVU^Zae\[]\aa\[[V[d`\]Y^aXVY\\eX[\]_`X\^`\`jg][]]g`ddbYhsmggbekLO9I%Ckc8eBeR;J6J2E7L;J;KBMBPAO>JGNDRJNJUKRFMHQSWDOBHEPHMNZFOFNGRHQEOBNFKIQENATDPLKBOOVHPLPJLGPLLOTRSURRVTZTXUS[dYW]Z[_ZS^aa\]]_`WVYUZP`Y^a\V\W_X^d^[^Z`afcd]\Vb[`^\T]]^_]X^[Z[bYa``a_[`adbce\gaf_e_[aa_a]aa[gb]Z^aa[^^`^ecca\Wa__d]`i_]_`ac^]Za[[Z[Whi_`_`YXbd^`fjdclhgneg__d_`ageaaihbd\a_Wb_ZYTQXX[XWRUYUSZWYU\VUUYV\[bc[\W\_[][ae`Z_`da`^Zb^]^Z^V\VbbY\\_W\]X_a\Z\^a\WQdic\hkbh`a_`d_\\ddbbccbefelsgjfc^\edbccgb][[cc_Z\b\Y`\el^]^Z```^dbbbaeab`_cac]e_^]Y\TU_Yc`VT_\_\XUZ[_\\b]ZYhakY[edeg[Y`]_]a^ch`[fddgX[X^[cQYVVXgS^X]XfU^T[SRQVIRRZJVN\M[K[GYK^Q_UjXg\efkfkkpiinfv~xu|x}q}yvuޅvuu{oፁn|o|oކyy߁lxpvހts{fmchgkhmkhjewegkilws߂sek}lzi~oބhۂnۃv݋rۇr}i܇xޅk݁lzn}l}h~t{gzp~i|hzfyp{otdzkt^shucxlއftȐːΘѠԝӠס٨֥١٨ٟҗ͓Ëy֎kf\HPCJHRVZPTT[SW[]VYTVUTVWUXS[S^_b]^TW`gSWbdYZ]\\_\b[Wbe\\ceW[\Ycj^^d_fhidd_f`ead^[TRY>H&Dl9\8W 8U?XDW@\C^D`@[F]=W;Z?Z>aGY9`=^=b?c@eM?I@SAJ>RGU@KCKCXGPNVKYR^Q]O\PVFQCOJTOYMQBGCOBOFPLNGRNZEGGXIQLXJQIRKLKQORMUMSRSRVVYRQZXUT^Y^d]\\UXY[UYUXS\[]X^YZ\[Y[WdZZW`_aZab^^aa__[Yad^Z\Ual]U^`diZW[^]\]Sadae]b^\^agicddc``\]ce`a`ib\fdcc][f\d`ebb]c_\[ac_\ei`^[\ad`[deaZceZ\aa_[^[[ad\debjeb^[e\ad_ba^^Zdi_[ggacbc_\\\YY\UXY^_VVQRZXYTZPZ]XV]\UR\][c]VUR^___^U]_VZ^`\bY][[\\\W`cZUZZ^[]WY[[Wbc^YWXe``_fi^`fm^_cd[Zc`_\_dde_`badggk]_cbejhk\Z^Zcf`^^a_bc^^b[[ZZVc\\a\aZ]^_\\V^`cc\[^[^ZXW][cj]e___bYW`ab_Y\c_\a]]Z^dc\V^``[`ga]^b`^ad^aY[XaYfMYT[X_TZWYU[XaV`QXO[IXNXPVQZLYL[M[TgLa_pae`rkmhijlkrjhspz~ys}v}xp߇}ysqtn㋁rwzqs߈w߀n}nsy߄w݄ljqoilggifrkfodp}cނerq߂mtrocn}jn߆yޅo߇v߁p߂k|qjmq~i܀j݂lނnقqzjzmڂeـpyoydyjs_yuxiyiodvgzdrpÅő̗КҘՠ֣ܨڧڤ٣ڣ؟ҚɎޡs˅n][OQMULSJPISN[QQRSVXXWYX\YYZXZ\d`\_ba`U\Z[[YYZWZ`^\[a^`d_aZ``___aYdh]`d`kcmpc[[WMQ=I&Ao;] 7Y:V ;U9YC]@\M_;[5Z\E\8Z7Y9]J^G]B`AfFfAeg!8^%>ffptjor}cnoic_xvjsszuopxppqqtsouo}htyonabfgpkulflplaokfd{cwboThUbVZQV]MSBJN:I?L5G=V@Q;N?R@IHV?M=JCNFOLOGSGOERGQLSIRJWKQQYAJCMFJCODMCK@JIVENLVHNKMHSFNIROYOVHPMULNPQURUWSVSVV[Z_[WY]ah\V_bYXUW]W]]\b]_aV__aZ_X_\h^XZa]^\`Z[[a\`Z^d]Yik[Y_U]_aab^^Z`\ab]Ycb_a``a^_Z^beg_``^aZcfbg^[f[bcd_daa_b^becf]]\^^_]]daceagfi]a\Waa]^]Tei]a`]bm`^dihc`i`[ci]_\[\Y\W[XXV]^XRXZWSVX][XX[VYVZZPTRYVRZXY^WVXYXY]Z\aZ[`X]b]_]Xbd[U\W[ZWY]V`]VW]_ZQ^aVT]Z\][[`^be^`b`][dgeeac\a`_\`ac_cjgegc^ccbbae_\be_a_]df[Zcd`X`d]_[ac`eca`\[bb_b_adb^_\a`ZXU^[`aadcccd^aY\[]bZ\_]ZZ[`e\T[_`_`Zcj^XY\aj^\^_]b\]X[S\X_U\W\OYS_MWRbL^L^MWQ\KZFZGXHXKYLYT_UeZd[c_hcdiogpjkpupstnxw{m~|~trt݁}{tvzrouvށx{܈t߆pp߆oރpߊsulpj߈squsl߆w߅rkiqi߁tgr~n߆vmu߄k|clޅm܀mޅvvo߁oqmv߅k܃w߁nހp~ng~n|o؂n~k}i~i{p{o|nr`thpfo]rduhiu‹ɔ̓КҞԘئاۯ۪ڤۦ٠ԖϒÀ҉cfcSRN[LTJTPSMSQQWYTWSVTVUWUVZZW]]YZ\_\`a_]^aZV`i]^a^ba]^_d`[ec`]kkfgi\ge[`JQ=Q$AjB_CW 6V 8Z@YAR:V <]J^KYDYE]M`?^ =_f=c7_^>g"EiN:MAU8E:HITAN?Pe;j=vvgponcrqhoklpptslt}trox{kunrs|opnmxihvjjkuii݈rlkgjtiak|_hr_qWhWgW]RPMPK?N=GJHSIRQZGNIPEQIRGRIRJSIPHKGNJSHLLXIRELHKENFOBNY8W :XAW=T :Y9Z?YBW?]Hc#K_AeAq([dDeBcDcBfQ6GTA[J[G]H` Ld!PfGfDeGdCd@c9c=hCf:a@]=]:e<`=_"EdB`Ae:b>_;ssnljtgmyޗxrmusm厀nq}kr{gtotvennhhhpbjkk~gkmqlmolijpokk~lw]qYm[fUdS\RXQHNDPU>[ <[@Y?Y?[A_@`?Z>`?`Ee>eBd?e?g>a:f#DdO.JkB`8V>[BVGS=S:V=Z:X=W 5Y:`@_EdDaAb@bDaBg&Kg!Db!Bc&MbEdFd@]AaCbGeCb<]9aGa;_?]E^Bvvpsonjdnokdzunshzywuqommgspwfjigbjjbfklimjdqtwnngpkbjg}ls^tej[h`\SUQJK>H4D:G4C/C2J0E3He!Gxxvtkphugolgltqzqrstxxomukrqjerhliocdmeqiropxrnlhijnled}ou^m`fY]SXQSMBKAH=G6I2G-G.E4D:PFW:J6EFP?KKVISGTEMHRANEQ@PBPGLBMKQEIESHODLEOCLBKLVCKAKHQGMNSDOHNGOGNKNWSNWSUTTUUOUOUYUXXT[WZUR\bYZ[[\Y_\XQXb[]ZYYY__b^TSXRXVYZ_V\Z`\ZV[Y[^\_`c\aaa\^^[[YabWWZ[XV\`YZXYVRcj\Z]cW[\Vbc[]b^]^__abXTbb[Z\\dbadY_cb]Y_\[Z`][X\_ddch]b^^dg`]``]Z_b^][f^[bc^]d_Y\[ZZb]]abZ^]][^`\][]`XV^bem]cQQedWXUWUS`ZZSXT^XVRSQPKUZVSY]WVYSYTZ_YZYV\USTWVWUTM]^VXWWVUZ^WSTTZ[\\aZ_b_b\b^``\cgdkb_`ceofedcadac^]a\ajYZ^]`lZ\a^[YWX^h]a^ccb_[`^[\_[__Z\\Y^_VWWW_f__^b[\`^_b_d\d\W__a^WT]][WXZ\X]`[Y`][Y\[Z[Zc]`Y\XdS\RUX\PYP\TaV^VbW_PYNVWaR]OVSXT^I_K[JXS]L\Y[\iZ_^f`cefirknpnrprqwqytxpwqyqx|xy|uq}t܂y݈}݁qށu݀tފo݅u߂sބojމt߇m߇k~l߉mpޅq{de܂lz~bpn}jn{h{h߀l}n~gށqgprvhmllrllnh}p}izeہv~comxg{mym{m}kxovir`vjver`sauctdq^qdnZxfnzč͖ИӘ֣٧٪ڬ٦ݪܮީتԟ̉붅גjl\NSEPGTLUHQVbIQMONTPXKWQXWYVVZj[\]e^[Yfadjfcbfcei[YQU;H,Fs;_?Z>P 9X<_EU>X=X:^7^I[>V:Z;_m@g=`;fBd[<_@_Avvhokrg|jjxtrrzrwuysqwxgppojcqijcbrg_ynjlrdqvclcejjmeg~azevYjTi\\NWQSO@KAHV:XBX>WAT=Y@U?W:\?_FZA\Ce"HdAc@`Bd!Ea=h#I`@_;`<`<`IbA]>aJALNX@JBL?JJMBQHPEJDJGKGOFLMPORLOPQSWRTNUYWVUZRYX[XTTUTW[VPYcccZW\a`^WV[R``UW\YYVYWa\WZWZZY`kZ\c`]_Y\]aXR`f[S`e^[XU]b\Y]j\Z]Z`agiY]be_\XV_aYX[e[Y_W`lY^XR_`a^ab\]YT^_c\aeab]\cd\_cd`]c`\db_Z]hc[^`^b\aba__a`^XZ]^ZcZYbd[XX\]^XWgda^_`^[YVXWXT_[_`XS\WXTZUVV]SXQUMVOWURPVSTNXR[SUS[YWSSOSRTRVLXVUQQPUSVXWUVYUY[[\W^_`]]^aa`a]d__ed`dbi__ce`cgebe`][]_aZ[XY^f`b`]`b[Y_h_cVYY\]g`gedablmcgZ_Y]\]Z^dcaheeY]\Z][_e[_\U_\YY^YZ[YXa]]VbaZZahZ\]^ZZ^^[]Y]Y[Y]VVSWLTXaTYQTQST]X^S[O`[cQYLXRaLSKYNWPZQ]WeU`^gW_\^igikdaqpqqsorjwvvn}tyt{ozo}q~uۀs}r܀w{l݂xuۇtޅs|v߆rxj߀kjgkl|p߁kjj݃m݀z~km}rjf}l߁j~di߁hlk~koiq~l~kontށul|i|q}g|eyhvgyi~l{nvcznylud|wueq\tfvepZtlp]lYq]oYo\pZyaos‹˔ѝ՟פ١ةڪ۬ۦܧܤܨ՜ΓÈzؐro\ORCMHMIROZGPIUNWLSS^OST\LVV[S]][Za]biaf]e`VXQR>E4Ep!I`<]@Y;V?UZ9b=[9X<\>\ ;_@mmqntnvpsjntstuvvy}nnenikdeedcb`mg~flgwe䍁hgehrojhqjmmmbviu]q]{a_Uc\XXJN@LS:K^A[\8`:`Ea7Y 9Z9uungmgrmhnlotorq{ww}jniijchbbjd`~e~]hdagb_sickbqjhhsihoo}b}nx`tecY^UZSRTHM@K@M>L4F,D8F3F9JT9W\@\C]B_?aFc@^ Bd%Je!HbDf"JhCcCn$EcHa$IeC`@_Ac=e?a9_7` 8]>^<^8a;^@a=[<`9llllonjennyrqpt~mu|jomgi}a~fqbflf^s`w`fnekjmfkovkqookukm|]zkycp`gYbU]RORIQ?J@M6J3E)F1D0GBO=J=M@N=L?K@OGMBOCSGNFNIUDIJWFO@JIY=LDPAIFVKKHTFMDLMSCLDOEOKWEMERLORXKQGSKULOVWV^U\RVTUXSVYXZPSUSW_TTYY`YXXYTWU\ZWVUQ]YacYX\TX`X[\X`\^^cg_]WZYZ[W\_UV`]_YW`\Z`_ae`e`]_^is\Y^bly]Z[^a`[\\h^^]bY]\\YVdn^`fgdbb`\]]Y_^`^^_]bfiWX_bad^a[[YV_]``X]XaXV``b_becc`a]_VX[UZWTU\^]]XUSZVT\Y]_VTXd]bXcZ][eYf[^anYgcu|rzyȝϥ΅zvȘͨʓ~Ŕ~t}z~iqYf^h^gWZVUWXXXUTZVZU\Y]_VYTTZ\YUZ[Y\YYV`\[Y]\[U]YTU[ae]]Z]baX[^^]`^caa^c]`\]_aah`bbbchaf^e[[]c[[Y][^_[diYW`dcha_`][PZXaY]Vcd^V[]`aca]^W_^^`_Z^c_]]W`X_S[WeV]O]U^UaMTV`W[RcNRMXNZBQJ\JZHWM\S_M[Q_Ybck[^ffmgkknmmdsewt|vrjwn~ytkzozp}tفt؁y{v{mn}trބxނq݅yނp߀|݂iހpi܂s~f߀s݂qjނpހo܁r߂qiwj~m߂k~cjhl}hic}e{ig߅qpa~mh|e|h|jxdyezfzh{owiuisnoaqaycznsdqgqeoar]wfoco^sct`kZvgumn]seۀdmxǕȋЛԟئ٦٧ڱܤܫܩܤ٢ҙɌՇb[UGVEQLSGRJPLTNSQ\^dQUO]RU\Zghb[a^Y]EL?O2Jr@a>Y:YBY?\EU;V?T>V=U?W@_EX<`Da>fBfC\Be!IgHf!Fk%Jc$Nh KbEbC^@e?[?iHd?e%F^:_;[;]:^=_;a?`;^@]?\;ssmsyjlsdpsornxnhpljo`fm~g~dlc}jy[}[{U}a}g|e\hqhgukihprj~hlkqc`e|q{^p[n`cTZZSOGWFS9F9L6F+I3H1G?W8N6J7I;O;PFL@KLX@LFSBELXINGNL[EPOVHOLO@KM[IQLXDIEKFNCMGVENGMHRDQJOV`MTPWLQVbSYT[QaPWVT\]VRTWYVYTX]VQXZ^^UQXT\UYWWQUT\ZW][TXQabY]aWZ[^aW^]]Z^]gXZ^aWW`[_eZ^^b`]_Za][\]]Ze^Z]edg]_]^aa`a`_Y]\\W[][___ac`yups_^bdba^a^`fc`hmq`dSWZcZVbc]^[VY[dc]bWZ_Y_[j_nijsabSYVSZb`^XaXXVY]c[a^h\\dbzrujrp~r}nvn|iwm|ljvy}˥Ѱыxʈͥر֙͐ɧΦі̖ɣѮРĐÖnr`gan^`SUVXVXUUSUQRV[XXWTVX]`Z^WVV\agZ][XZZ]b\_Z\X^Z^\\UZ]]\c`a[Z`cfh`adf_a]bcn__cg[`^a_`]^]bWX\bYX\``e[W^a]]YY[YVYbb[^]`Z[]YZ[Y`_b[bYY]`[[U[U^T\T`R_OVUZLYMTW`YeQ_KUMWQZLSJVFRLXR^ZcShT^Ub`b_adgi`ihmjnfssqkrnspwiywsjsd{pzvwk{t{s|tzn|ހs݀t݅u߀r}p܄w܅o݂r|a݂ul~j|gk}n{m݀k}x{f߂i}j}m݅nh}mggoijn|m~dj~jy`k~j|my`yhyeviva|lwfxq|lwntctcrayqp\rhrcrbr`Ӏoj]taufvbuisar^pdo_q^juƉ͙К٣ءا٪ܫݪݩܨڧ֝ϓǎ|ڝ}xaPVCRHQ_eMQKTOXWZWcY^WX[jb_ae_`SQJX9G9Ns%Ea7Y;W@T;W=\HYAWAX>Y:X<[AX?Z?\A_GbCaHf#Kh!FeBh!EdEc$P_AdCdHfAe'KbF]7g"I_@`<_BX;]>Z?\;Z:aE]=Z:\@}}kztumnqk|soiszl둆_mjf~a~kxb}`x]|`wZz]v`y[{]{e~icfqnizhc{mutwtfsqe_p{ltcr_usaQef\^KREP?K:NLBP?HGQERENDJMXGXBNKPNVRXLVEKDNGSCOBKDODMKSEMFPJQAIFIJQDMIKSYHPOVNUOWPSRLN]WTVRWUVPW\WWYW]\S[XYZ]YVXW[Y[WXU^\]\\Z]ZZV^`\]_aY^[W`l^[dc\cYW]]Z_XP^e]\\[^Ye^`[_\ZYY[Z\]``^^ebdcgZ^\Z`^\[XcY\]^T_[Ybac^\a^bba^_acecgq]ieb[d]e`a\\Z_WWX\_Z\a^dWTYYX]eYceiw`b[VYe[_[aV\decnn]ldi˂·nrx|yx~|uzƆɪ֩чyʐϭԤԑ̖ЩҥЌѠֵڳ۟գԱڷ׶Ѣșyfg\aY_TYQPRWURMMVZUTNUUU[]VY\cY\[[W]Y\W^XZ\a`dZZW[Za`ea`Y__i`e`ialce_dcmaebbbiadah^eW]Zd\_[\]a[^[\[]XX\\\\W\jgUV\^[^[\[XYZWYWYYhUWVSUXXaS`W`PXU^TbP]U[T^QZN\LSLZGRISOYCOJUOYPZV`S]W^]gckdajimwjgmdw|qjyruxtntsnirltoxpxxyw}uxt{qwۅx~x~qށir߂s݁qށrip߃m}jlznl}n܃p܁x|gހug}no߃ifj}choc}i~kyf{f|i{`~y|bzhwe|tvgraxaxlwftevksjvexgs^xysctdwisoq`ratip]thxauopVqcp`rdrf|kxŽʚϚԗ֧קکݬڧۭ۪۫ء՝ˑć糁ӏsc[RYPUfrS]R^SYR[X_MUSU_cY[adYWKR9J#?l7_=\]@dCa:^Gd E`BfHiCd!Fn'Lf(Gh"Hf"Gc Gf@f;bAdA^:`9[:Y:_=]<^;_<`?Y>^:^@`>[7sskolijomsll蓁ruyvkphhd|f}cy\{ava{^xW{b}fv`w[wXpdktbmygiqnqmqvmtkm`~h{^|jiVib`Wc^^]JNGP:J;R9M3L0I3KO7N:I;GDPAPCSEQLZI]FYIRHRI\N]DMETHPCLLYBHDMDLBOISEMFLGMHNGMHNRRNWPSQ[LSMQMNGRLSRWTPXSY^^YXYWX[Y]\ZZYYYZ`_[]X[\[[Z\T[ZZ\[V^\\X^[]\]\bcTX[`]Y_`YZ[[\_^Za_c_`ZYY_^_ddgcd\aU[YY]d]`^^\_`cZ]ab\^Z\]\`\]\dfYY^Yce\___`^fgbe[Y^hY[`[Y\a^_W^b\[[_]`\\\Y]]]\Z\`\hvbrZcdqpYekwˇqsh~~ȇvyzw{ÄŋȐˋșϡ՚τ}ǟ̱ңΎ̧Ωљ̑˩ӺׯԗХֺݷݧןױ־ۻ֮ΓÓÐ{bf\\[eMSUUVZWWSTTXUVZ`]_WZYc^_X[^aZbZ^YW``VX`_]]\^ehghehfl_e_jdkdndjcfchdh`d[_`d_fcfVW\V^]``\]^[\dZYdba^]`[WY^\^chZ_Z]V[YZX^TRXZX]YcW]S^MXLWNYMWR^KVPXQZPVKVJWIRKZKVOZP\V]YbXgZ[^]mpflsmrnrlqkqpsunkwtsevk{utovm|x{}wq~rـm~p݂xzޅj~u߀rކnurmޅwmymvl|dބu}oh|no߀f݂tphpzhegn~d~k{b{pybzjzi~h}^{jzewbyetcvkqcxl~owlviqcvgvkvbpbwfq\p[t`ukmXxhn^sdo[pdncq^vfsf|azŊʒћԡئثۭکةܩڦۦ֥Лɋo΁dX[JTNXLZEPQ^XYRWR^_Z]`\bQSPRES0Gp Ca=X 8W?S9Q 8V;U6[?W\8[:Z:\9^>b=^:W8[;\:_:^?f>wwrjtdnihnpmzxrltiuedd}aisZu]u[v]kWuavbyftZ{fmehpeldtmmposuxksondh}byemXi\cZ_VUUORBM?IJL-Gl;];T 8TaBbF]AcAcJ_Db>b@l3Yb$Hg(Ra"Gb"F_!Df)Kf(Lb GbEY7a:U :[:Z;[:Z;a8dCceA`=b<[Y8]=VAZ>[ >[Dc>`Bb"Fb=e NdGbDiFgChCeEh"JaD_Bd<_Ic I]>ZB[:U:X9X;[5]9^7_7a;^6c>c ;^;_Bpposdthnwpmsl||rrunk~]}gtcoTr[qXm]q`p`jWm^m`uVxiobpkmighqlviltjmoisc~i{iu]ndnZhZcZPRGNCJ;I4C4K2E4D0C7J8H9IL@PAPBOLUDSERDQIQDNGQGO@IFREMFOIPIOGQNTNQEPENCGKLJKKQKONLNONZLUNUTZSXUWRRY[ZXURSUVRX]TOSSUOUSZX]YXT]S_b]X^YZSYVb\\WZU[^ZU`\`Y]X^]_^UW\X[\ghlr_Y^fYZ``_e^X`^^`U]`_beY[_^giZYaZ_fZ\XWX`Z]ce\[eb^`[Z]]e[n[^bUR^c\X[`ZYX\`[YWZT]`[\Z`[ifukxt}uǀƃ|y|ɀ}‡ps}{„ÀƆÂɏ͚ӣ֢ψʋ̦ϙȐ˗ХКԙկְֻўϰɮϣќ͛άϳЧ͚ɗʧШרլذָڷڳܬ۲زյӷϵͧċyjyfoSZRZLQMXPQWZVZUXZXZZXZUWW\Z[_c[`[a^b`ggrbi^g`c^f`fZ_^b]^XX^`\_`c\fZZ[[[X]_^b_]XS\`_]X^]VYZY\[ZRVRTSUWdQ_Z`UZS\QWQ`U_UYSVP[KQOaOYOWMZMWJZJ]FVKVGUMZP\Q[SYXYgtfbkfoxl`pntpxgumqftrvetpunxnxpvowfsgyoye}s|tyl|m߁u߁q~l݀l}mބv߁ph}p܁fn݀nބzzi}k߁s~fmj|e}t|g}bzk}j{flcyb}kހgzj{ew`vfvgzkr]pfugypt\n\thn]tlqcsal\ndpfmbkYsip]pat]k[ncsflZnbiZq`m]odqdubzfmxʑ͒џգ֤بܬܯݯ߭ݬؤіȇ쵂rva][TZRY[]R[Z]\T^[FOAK,Ho<_8YU:X6ZC[>[YC[<`>eG`A`9eHe?b@b?dDcBb?b@cGbBeEbC]?\8U>V 4Y=\9^9\5b=e;c8\5Z7]AY 9Y3d;pph~kflnunntrwqpjlia}fctbr]s[q[oXk[lYt`m\gQp]vZ{h}^rasgislnkjmpkm|iing}gz^v\p`iY`Q[QTSKKBP?I1G5G3F3L0C6P7N?M9J6E2ICPDPELCN@QIRFPERJNCJFRISFPAOPSIKCQAL?KEPFTMWESFO=JMPCIHPJRDLILRVPNPSRWPVTXQRUVW[TN]`]Q\]RQWWYWWSWSXU[^\V_^_baV\XaZYRVQ[WZWWQ]ZYZWZ^]e\ZZ[U^^`X]\_\_cca^]\Y[_cf`\ac^\gc[\a_bb_`]ZW`fcYUep[\\Y\[]c[\\T`^Z^_Y^\_U_`]hV]^YX_\[Y`Y\W^Xecnqwr{{złNJtuɉǏƁ{ogvƆ{|z~ȂɀϟԠяϚʬˡϏ̕ȠК͓˭ү֮ٝծбװ֡ϚΰεԭύʎĤȤΛͤѪ׹׬آ֠Ӱֳֶڴ߹ỨฦٴԲήȦŏvakX^UfSXYWV\QSSXRWVU]hRXZY^`\c^`Y]_haeZ^\dY^Zc`b\^`c_]V][a]a_b``\abc[^ce\ZWUZ]XXZX]^Z_YX`_YaZcQXXXT_[dWYTYRZZV\iTbV\OXNWRWPcP\PWNXL[FWLYFTHUK[JTNZYeUY^]agglh]ojpkleokԁulpksnrnolpnsgvssprjxp|ztjtszu{|w{p}voމq{k܂}܀m|f܁q}t{dzm|h}gzn}iރom|g|k|o|b|lgzk{a}ghwk~p}h{lrbtbvbxfscsatg|oxhqamcpgm]n`qdrftbm`pfphp_oixenYq`wnv^sitepar`m\ukk[shsfwf~ht{čɑГӟեآשڮܭ߮ףΑœ}ݕtqdXYRUTXXXXTX\WWGW-Eu?b>X;S=S >T>U?Y:UCT;X >X8YB[=Z;X@[<]:_B_@j!FcFeCb?aFc!Fb>aEd>^=`=_Cb=Z@^9\@^AV?Z[>]@X>_=b;dIe!Id@i"He=d?bH_8c:fAg>d?_@aA_>^F\BZ<^A\8`Ea>]IFG]@JCLCTKLGNGR>J:JLUEMHNKNINDKHQ@IHLLSFHBNAIGRDNJMIMLRRYORRaZ[UXUXOMPXVTXPWZTQRQ^cVNYZ\XZ`VOTX[TY_[ZVX\[^[]Ycb^W[YYS\W\YWXYZ\V]Z^^ac`_b`pn[W][WY\^]d_a]f`\^[`c`eSQ[]\^^ZX]XR^]ZUTXVW^W``]X[^WZYV_[]W\XYWYWTZ[[X[\d`iYi_jdmc}ptył}n{yu~v{zz͎ānuq{womx}|ă̇wut́ϛӟѐȍǔ͍͌ϝԟԗϗӥذԟϣ˧ͱԳПΠɢͧɟ̗ɚέңϕԝЯӳ׳խԡѬѲֺ޼ݵݦ۪ݶڸợ߸޸ԪǍkuXaR\OYRZRSOTS^SY\aSTS[^c\^\gY\`m]d[_^d[d[]^cZcbgcn[bZ[]b]eYZSV^h]Z]m\\[Z[]ZX[cSXXZY[X`WYS]WSX\TYORU_JRLOS_T^MXNVLYO[S^TWSYO]IXH\DUGVNZKXQX[Y[h[Wdihcd\lglhqeulrjtkwmneplwotmtrskqoxpwtujwlysyrxsyr|yo~u~v݀r}tޅv|u߁mh߀gylxhylzr~o|d߀syizjzeyjvhvgsfxi{jڀmxguavdxcv_ravfp^n_sep_q`ypweycseobldp_sfn`pdkgjYl]o_p`l_tktanaldpfrhs_i^pcmcp^uikdibm_ބdzÈɎДӣئڬ۩ݩ۬ܲ٣ԗʐzzg\]\Xe`PMCU1Iw#Eb>S c>[<\EV:Y 8X?_C\FbAbG]:f@^>b8`?_=c:]?a?[6`>^>ggpnkltwunui~mrai`e|]vXnTfTkU`P^U\Q`Wd^fYi\q_q^{aeleljmllllkllolnrrdouzbubnWn\fZ\OSNNO?I8F3C%?/D2E7E5I6J6D5H;K9IS@Q8Q>T7W!O\ MX>^@ZAcC_?`Dc?`?gFcAdEeGeBd Dd!I`>d@e9bGe;eG]>]>T:UBWAX@[H[Ie Ha#Pd9aB`:^9^C_<\7\5Z8[7`9d;qqpdrqmvrhnmohl_mc|[|]sRiVgYhT]PYM[T\S\Te\lcs]vX|jagqcnjhmtkhlyumhmwknu|dr\s`iZfUaSUUIK;F:M3H/G.K,I0B5G2A6H4F:G@K?IT@W>V>R 3\?^CUd?eEe>c@eCbGcHa\>W>X?[?^!Ka B`E\B_>\@^:_8]6X8cCW 6Z:[;[;c?e=^8iigvmqronzutgqqbaybxYrXoVhV_N_PWPUOWL^S[Ue`kZrd{a~fhgwgdnfrmnmpovvvloiog}cxfxdaVh]\LV[JO:E8K3G(@.D,B2E3G5F/DY?WAbF`"Hd Fe!Ci!CfBl!Ee>f?g&F_EhGa:`CeB`Y 6W6[=X:[8b<_:_7iikglolnu~ojotpicvc|Zn\p_dS[HZPTNRJTOSOYUj[m`t`|h|rl_vchxgglmnsnn}ejrfmax^zeseeTg]\QOQGJ=G7E2I+A)C-F8K5D3D6K=L@LX=ZERAUBX@U 8TD[JU 9U@Z ;_>V@S?Z>eDe@cDhEa=e:hEfDd B_B_=bEi&IaW=X8[`6b:uusntoxj{zokobp}fwZygqWkUcTXKVJMJVSPPNMTOa]n\}vzkhncnpegkfphmgjjkqepkhcey]xgtaqbcX^RNJGR@O6G2C)@,F,?*H+D6HGeIb9LCQDXAN?N@Q;Ka;bGd>eDh9eCdAf<]>[<^?cEZ@[@\E_?Y:^D`?_>^<^?ZA^$LY>`#G`B]6\8[ 4b<`K=K:K@O=MDMI\K[CLAM?GFRCK@K?J@IDJGR@JALBNDLCL@KHIKXDNISQWLQGTHUKNHQNYOOLSOVFLWcLO^[MQQMPTVXMOTWV[[Z]^SUWVSZZ_QWR^TTUY`jURV]][\XW^XXSR[_VZ]bVZYXYYae[][]Z\^]X\[W_]Z_[TV]YXXZZ[W]Q[Ufhnݝӧ̓s}ӎ҄z~}{wmwbjgjdu`cZj`b]oYe[nbo\hincpipplj|uyklnqllnslphqdlqö́smtvŇzoxuʍǃƁ~ƂΉςv}Ćʒ΁z{ԔآӓљǏɝϠИњΡ̡̞̏̇Ѱէ֠͠Ҭ֤֛֮y՛ղұ۷ᵕާ֪ӰԺٵ⹜ൖச۰ոڼªỠⳜܷܳٴܽ¬áݺְǕp~SdOYMUZe]e\gNVSZXaU[U[U`UV_bZ`SZUU]^]aP\\\X\^cSXX\UZWZZaVXZ_TY\^Z^Y\Q[WYNSQUOXLRMUMTTZOYNXKXO[HYGXKYHQKUCNBR@QHUIZHVLVQWPXTZ]ffia[iiqhvsogwlrqwesosmwhuqlezoshrjqeutrhzkvktquqsnuntkx}vlـ~|j݃}݀txk}nrykzj݀uyj{lzhs^raqewjvaqkthsbncs`o_tet_vfqcumuezkq`qcseugkWoerho^rkparcpesknUmehZmaq`q[n^p_kYs[o]k_o`qhp]qcr]l_tjocnZmbn\m^m`n_wblő̖Ԡթ׫ڰۮߢݟѐlOOh:L 8L7P@M;TYC^>W:[;_@f Ii@c?b@eA`?`?bA_C`@`C`B`<`?[>]?]>\AZA`=]?k:acB]@^@_I_>Y>U:_ C[!C`!Cb=[6^4h Af;b9j>qqjlyqhppzkvcpgiz`y`iYe_WIVYIBEIGM@JIKQLZTf^f[wbydafhbwsilmmljmnonmkbuhnd{bwYoXlc\O[PMO>K=G4E;K5F)?)D(H4H:M/E5K0G;GPAT@YE[BZ?S>X?aDS:^:a@^Ae=fDjGi#FcAc@cEdEd>d'Hi$Kh"Fd=\:`?XAZ=V:X@`D^B`BdAiAbB_>cFY;V ;X;bA]@bC^ 8^:e5a:b >g9d8rrjwoor{nqaifhy[wat[m\eX^JQPIMAHBGANCIPM\T`[eUnaxa}r~dgbwmfog|_sppldqglkpbpzbwcs]f]a[\WXTOYAM4B6P2E)C-E/G/E1J=S9N5G2H@R6FP?OBQANCS;H7HCL?NCN?KFOCM?ECKKOFM?JAKGLDRGOFJHMOUJLU]FPJVNPTZSTQ\QRUZZYLSMS]cRQVUV_YZZcTSX]SPVTVTUWUYXXWR[[UT[WY\^W\VYVVZYSY\ZZVV_^[YXW\cWX[bVVYW[Z_bZbTXXT]_ex[dUY_aeheachv}qtpporlrkpjvbeYddu`lgmXdZiV_YgXaZi]k\tcjoulwr{wmmymrnzjs`v\idtnvlioz{lsahtuvuzy~͇xΊ~łǀzyxˍϕԑϝɔ˓Θˏёӟʇȍḁ̇ѡ̛͖ˢ֪۵ؙӐΩαеڶ׬֢Уֶ۸޹ܭ֘ӢԵۿ۹޹ްצٰڸܾܼṞ߹߸ڸۻ¸ȼç࿪ܼӮŗy^sVhTZVeNUORM\O\V\YcS[V]S]V\QXTXU][_Z^W`R[Y\U[W[RVU\O]VZUWWYS^VZSWS^SVOWPRMPNTMVO[EUJUK]LWPZNSCUHRBOERAIFNGSNUPXMSU\Ua_a_`iffdibm_qeqhuiwmtiwqustjsfuhtlqlqfqluoxwvsvmzrtjvpwutkwpxrvmzk{zuhyo|s|k|n߀swi{owfvfuishsasdn_m]mdodt\ratdtdt_sls`|lzcyetfp^n[skn[n_k^p`thtgsjkeqfoblbuencs_qcpan[o^r_q`sdq_o^o^sludr_pkm_k_pao_sdjbodxjv}ĒϛҦ֨ڰްԌwjUz9O8R =SBOSAR=W?UV>Y?W<^Eb=d!Bd%Ib>cBa<\:_<[CX=W6\9\6b<^:[5d>c AiEg =_=ssoxtpvwowmokgybwaq^p_\NYMNMCIFP7G8GDKOLZSdZfUxvvc~abi_~lmnhifniloppkptpal~cxcw`jZeY]SONJN>G:L2I*C)C6H,F3I5O4K4E;J6G>O4I:J@M?S9F>M>K?OAM=MDLEN>MBO>KGJ@HFMEM?HIS?JFOHJCQFPAJEQIQP[FOQ^N]JTPUKRXYLRSSQSTMKWTYXWWXTV`gZZZ]PQYV[X\^TSXQ^bXWZWUUWZVYXZYTXb[SXWbcYU]\XV^^]_ZXYWUXSRZ]UUVV\^ZWxyͣσuTPY`ai^i_ca`lrlgciddacbl_`Y]dp`g_`^jbf^s`q\ddparew`djwoitfpglgpu|iqfohvmwdldt~stk~hxz{fjvy΅{nuȄ͐̃u}ƕȘ͌ʈϓΖπ}ѐϑ͂tΎТŘ͡ҠϒДӤӯ֭իӨ̤ͦԴٺ۷רլӷյ޶ݭןҟү׸޻⻞ܭءկԵظ޼޽ᷝݰڲڻ߿íìî㿣ṢݳἨ޽ӱ~h{O\HZMUOZOZOUNTU^WXU]SWRZT[SYV_Y^]cU^X\TY[[VWTWV_[cX\XXVXX^T\VZXWS^QZMXMTLUS\PZOWNZGULZGXIVFRHSL\HVHLZJZDVKSR]T\\a]]gekigaqhpgqkviyhvlyttmsislsdvmpisixosirjxsysvrum{utpuruksiuoyr}|xmxiwhvh|t|f݅}lyhvn|lqfpWrno`mbmcm\rgo`pYsitfqUxjqdn]qgp]qctgxprcrbt_yiw_tipbqbo]phngnck`seobrcram`p`n]uhr_vkq^slsbtfofm_m_pfm^rpsdpeuf|eu|̖ѣզ٪ޯ޳ՓŁߕk8FT 4I=M?N8OW=X 5_C^;`=eCaEeAh@cGd EbAf@eHeBbEeBcW;Z:[Z>]6a9]EOJTS\TgRngze}gdndslldjolnngjtgsjehyi{_u^pb`VZOROHI>H?J.E2B'B+@.C+@/E-E6D4C8JAK:FCV=M@M>MCS>L8J@I=LIQCKCMBKBFAKBQDNAJCRIPFSK[IQCRFQGTKQJPMYJRCLJQJRNWV[XZPNT[TXNMLWW^ORY^UUXSTRZYPOWX[VX^UZTQY^^aXXWXSU\XWYVW\^bdZUZ`XTY\VXUVX[[\WYXSYWZZUZX`WYh[t*oRGLOR]l`b`g\fek]dgk`iaf\gV\W]_oY^^fZg]f`ranY[bknucifqomtlqlkjpgofjmrgnhlpvt~ttkrr}{{psq}muywu|ˆ{tq{yṫv҇ΌʉΌ͘ȏˇ||ʕҟw҉~ҟϪѭդ֓ёӝ֭׬۵ٷ۱ղѱڵܷܪآԢӭԵܷݸܲ۫ضֳػ߸ଘߧٱ׷޹㽦߷๪۴ٻڻٽĴ⼙Юg{QcIUM\ITMUOWPZMVPXP]T]SYT\[aWaR\U`U[P\XWX\UVSZSYQUT[TXS\QXR^W\S\T]P]MUHRRXJQLVJVNYO`GUEPL_P[ESHUBSCPJUIPL`O\ScW[^d_`egnpg^qiqlxewguhvkwksisislrauhplqgvouoqgrlyrsqpfuqvopjtovtvousulvjul|kmxq~u|pxfxrzpndnam]tiudndnno[l[odnZrbvqnUrdqgsdpgp_parjp^rpo]vevep\zppeodoZnfj`jbm]rgo_m]k`k_q_r`wisfsmp`uhug|rpdtfphm^rbtglaldl`tco}Ǝ͜ԡܫ޶߶ݧ֖ɇo]Ol:K 7N?PZ>[>W?^?a?a?fBa:b F`>Z=X=[;W:\:\:\=\ 3d=ekkryrnorrsagdz_w_v[hQcTVIILDF7@.A/C3A=KNKVO^Wi\m\x`~fgehinr]pljkhjmmijmimi}_}oy]nXl^]Q^OQNII=I7I+C(D,A+@1H5I7L.F0E2G0I6H6L=K?J?M@J>N?N=I>K@JEPAJ=JKN@KCJFOFO=JFVGSFP?PFHDNJUGQIMDKQZLTCHJHSZQSJQR]OLQS]eQQPSXcV\XXMRRLNPW[SRP[XX^`Y][`Z[\[]`Z_VYZVTY[b[_aZY\\`\]]YZaVV]a[`VWVRXZWYV\V[^T~uyvQAF@OLR`]\`_f]eT[]\[aXUepVVY[_g^i[b`n_hXafm[k_f\a^nZfl|ssouiqklmxjpmxdtXg^ljtsweguzzyfepwqsqvikyz|zpqznvː~w{{͖Ώ~ʂv|ǜʚˌǍ̟֫ԧԐyь̠̥ӣ׬تګ׫ٱشܳ۰٣ҙ԰Զ׷ܱݩڭڱۺ޹޷ݲ֦߫ٞԻٽݻߺḟᵡܶٵټػñߺฤ޸ݹչǦgmMXKXOYKZLSNXITQYU^SZSbcoRXU_UWT^OVVYQ]TURYU_RWTXSRU`Q[XcUVPVOVR_MTT[MTTYNWP[QWQkFMI]HPKVEQHTJ^HO@ODSJUIWLXWY^`baa^ebkmtkqlthvmxl|u|rxnwjwktdujrjogvmqmnbrqukvkogskrnuqtlvqrjtosjtiuxul݁hzr~koq`{stgrdtflarcgZlbjdqcp`raman]l\rfm]s]}lxbqap`m]n^sip[q`ncq`oeniqbo\odl`m\paqdpbk\m\kaodpavctavjobrjp\tjqfvdo`o`rkshqds_n^vivpm~Ɠіӥ٨߮ݡՔ˂wrU$@S S@U=P 9U=T^9\:U6U;Y=T=V9^A`C^>c Bf?_C^:`HX?Yb8fAc=_6_6W 4V 0rrqupmqnmffr~exet\seeW^[RJFL=D3B0D-D4BFGHLUOb\bYpdy_yhhfwnrpmphlipzkolgoocjdwbw^pWj\aWZPPHO[;I4D-A,G+C'C*C4H1K4J6K:U8L:J?P>K;O=K9IAQ9JBM@L>J>M=L>OBOBJ@RFQOV?JCMJP@LHNPVIUGOCNAKLNEMDSEOBHKPQWJPOXSROOU^OPPRYb^]XYOOPTMOSVVYTTW^biYUX\YVXT^f\VX^^_VY[aTU^]UUZV^ZXX\]\X`bVVWPW[V\PV[aVSn`㱞ߕzHD8U4NIUJZ\bYc^kX_\j`aPV^^]d[`UV\f_j\l]a[gXc]i]eO^ao`aowwximfmeiqrnilkcmenk{lqlxpwqnofpotps|oxmrgwwɀywoy}~̏Âǎ˃|q{ÅŎυ~φΓϪӰҥӕ̒őˠӰէ؝՟հӴ׷ִإעְӷԶٷ۴ڬآխڼٸߺ᳒ܢԝӪնڻ⾬ὠߴܳںۼۿ㾬侩޺ڻڹָ׸ݿཡۻײǕdlQXJUITMWEQMSIVS]NVU`bkQVOTQSMPV_SUPZVVPYZgTZV\SVNXTUUgQZJVOWKWLPTbGSJVIVO^JUN_JTJWJOEOCQESBT@LBSIVIVLYPYZc`__biegejanoslvowjvqzpxkpxmxptkrdujvrrkqtsfwxrkzqofsqqnrnsktrniriphxspfupxnypzn|gzk|rweubofutn_ndh_k_napbo_lbqgo]mdtdscs^vcw^soqbpdlbq]rbrhpembpbsdqeqjobp[o]sgojqck]odsknarcwmrcwdsgk[vcucqfugobrhthwgwgqbrgsj{iu͎ϡ٥ݫ߮ڞӓʌxۃ^6@a?K 8LEL :O 9SARASAQ;T>U>X;Z>_I_X;X@Y=aC`?aAc@_AY?W8[Y>YA\=_?\8];gAk@k>m"AdA[5R2O4J1ooꟈspyliuch}ew_qasejZ`O\[KGFH=P9R#<,B:IBFPPWRd[mbn_wc|badknifiqeqdfsgimlgrjg~gs]rYoUfVhd]USLMMAG9M0C2J*F%B.D(E,E0C5I6J9J=LBR:L:H9F;BBNL?J?L>HFRGUBOAP?RARDMI@SMNBNFSGSBMFRHTTWPVOZOSQXUWJPOWOTRPORSXSTMTUTS[TZb_ceX_^]YYW\YY\XZ[YSbeVW]VX]URUZYZWU[YWZ]\UWYWY]OTNVU[ZZ^ȘޚhDLF[8TPYU\be[aX_[^ix[aZ^X[bh\hXfU^gv^]ZdZgabYfYbWcepad`hckdqfejomq]d^dr_dcllomqgxijnulklnwsmdmxƒirjvʂptw|nj}|~Ŋ˗̇|ȄŕЧٯٝӆМЩҮլՠӘЪ԰׮װݭՠϘ֭ٴݷṚ۫֗ة׸ۼݺܴݥڨָ֯ܺ޹ᵗ䶟ܲ׳ۻ޺ݶ޸ܹػؽھݿڼܴݵݽݺָƝ^iFYET?RIXEUKYQ[KYR[PYQXORLVRZNWP[SULRR[UYS[R\SUPVV`T[SZLWKUOTL_JRMXKWLXJ[LYK[LYHRGUGRHTAUAOFRI]TaOZYcX[V]felkjei`smqiwlwhxkyqvkwkvi{owgtftfvqvvoettvvmisevrphqhpqqjqnlkqqmbxxsorntlwmvt|mym߃xvgtfn\njpdk[misfn\ofl]k_qkvdn\sms]sesdt^rjtfmeo^qfujqdrdndo]qbs^mhodo]iZvlojnhrdq`ocsfqjscrfufubn^rkq_|pq^sbskyjpasdtfrevkxim~˔ՠۤ֗Еʒ}Y7Cd?T@O>P=N ;R=QAT>XAUDWAS;X;Y;^HcFb:iDgCfAh Lb=k@df?^C_>Y >T :Y=[>bAb?cBhBb=`#GaA]?X?W7W@^?Z8^@`8e >gAf9j"?k?e>[7T0M 1H/C2qqntp햁k}th}jy`xcrelYeY^RSVLO8C-A'C&@,B2G@KLOTNc`h[nas^{]~ekdmfkdmoodioljpjrjqk{b|br_m\aRdU[SPPJL@H3E6E0D)D#?*A5G1E3C3F:J?K?N=G?LFP;H=KFW;HHV@N@J@P@KCQERHOGS?PANEQFRGSEN@MBMCMBIDTCOHLLWHQJPLUMXORQSLVTTPTOSMNQYIONLWWQSPNSXW]PURWVX][XbUSVXS[[WRSVZ[WV_V]Y]TVY]WaYYXX\]ZYYY[YVTYVVY^\Y\VPySdfRFUS@WET?U>X=V>]DY9YA`=aDc=a>`Ac@c:d>i FeCiBgBh=c Ca=Z?W>\A[>Z=[@]<]?e@b>cA^;X?V;\AU8V=\DX<`;`@b$Ad(B%C1C-?4O;K7L=N1H=K:Q7KCR;O=MCREQASCP?NCQ?MASAOCMANCNERCNIWFREMAJIUDRBINSKSJRIOP[NUKRQZKPOQR[PSJRKOQRTZNQNUSYTSSRVWW\YWSUU^TRT_XYVYW\S[TV\ZYY_^[\WYUW^bg\ZX\YZ[XVYY]WWZY[]X^bWWXU]S^UPPLZQ^T_KZTRWdYaW\X^_`\aU\WcT`Yedp\c`kddXm`jPZ`j]dedctmrclbnikflnvjkeggrsegffcnntjlo{{uyxiojmmzpthjkrqtnkwxwytqpqy†ˆx˂~ƀƉϚӓ}vʉΞӧدןΔҦϮԩեԘ|ҚѭϫӮױ٨ۤ֩Ҫ׮ٸܵ٩ݦ٦٩׳ܿὨ೗߭٭ֲڶ෤طᵔ⺣ޱ۵ػؾóððݻ۹زعŹ÷ݽ¨࿬îӵr{W`FTEUOWJXJYHPKRIPGRHQEPHXOUOSQUPWNXQWQXKWQ\N\LQMVR_HWMUHQO[QWQbKVHYKWM^EQGNK[FTJS@PGXENL[OYMZO]PZ\_cnlfmbmcoetmxp{n}z}nxi|tsaxtzxvixqtislpmskxppfpjqnlhllrivvsoifrlljlcmfmikanjrjxq|k~t}rufqaqdxqrflaoeojpdp`tawdqcr\setesaujxer`sipcr]qdneqfoep]rcq^oaonnck^tnqdrerhrfobqhsbpfuqq_vmh]peo`tfubtdpawowjwiwjyp{xwkyf|wn̕˄u}V;FfBU ;TDSV@UAV]DaBe?eEh@e Ea@]C_CV@]@]E`G_>cJeBb>f!GaG[@UAV9^CZBZ=a<[B_:aAf#Dn!Fi*Ed>fG[6I.A 1C2E2I:~~skqogldi{\}bq`hTa]NGSTCK3>/@+E(@(B0F6HEQPRWKcfcXlXu`t]~aqgcpkduslodm둀j{dnpu~chvVlSj\k]aUZUQSKTBG,@3G1H#BD+B-D1N3L@N1I:GAV4Q>REUBTI]M[GTJ]L]K]HSARKWEPIOALKT@OYFTAXAY@VAU;X9WBV=Z>\AaB_Af?a9h8aBc@`?`eBaAd@_C\R5H4>1?1H 5K 6}}pruhokjju\t_o[hVe]SNFJ+E1F:Q7J7K4J0C:O=P>P?PDSIWKXCSAXER@QN]>L@LDVJS>MCPEQDTJWCMFUCP?JKW>LCPLQKYKSIVMYKULOMPMTX^UTT`HMITJMKNRQR\UWNYV]UTW_V_W\SWUYUWXYSUUYVZYdUVWYSOYY\XUTW\`^USW]VVUWYYWRX\YW^Wيvi]OULOKQU\QSQ`KVP_[`T\W_V\U[Q\OQ]l]^_dZ`T]^jbg`_ambn`g^gYbbpeehouywvlhnnin_lgrpxq}jqr{pz|}plkvmwflX\\bhmsyxzv~oofvgz~nvlẍΏyt}ˎΕӢәԄҙ͡ԪըژӎћϧѶ׳סԓΠɨЯڸݮۡՖРϪֲ۸߿ἡޭ٦׹۾޾ợⰘୗܫٻܼἫ㹟߻ඤܳڼڽıñ߹ݹڴطڿǻòƱ޿ͩQaCX>MBMCOFPEOISFNCOMSISKROUQXPXORTUX`LTPYPWOYQZNXS_GWMWJSL_FYHTJXEWLRKVLXJXNZIU>DANITCRLWNYW[VW[^cfjekdocvrxkxs}syi{z|j}l{qxoyn݁{xrxtyf|vsqscsnfdllfihijiihkfelkgfdfdijlflemktkzkwizpxiunthtcuhnarbran^lXrerimameraskvjpXtjsdlZnepcp]ogtitbsak_mbl`qhofohyoqkpaqeqjs_sisdoeofrescuhukvnzqvosdzoxesnvbwjryqmmwmj{p_bP2Ed?UBT9U@YBWCW=S\?d;k#Jd%Ie@e1;+E5M 8gA{{snpogbmcwZr^jZeW\XPOCJ9H.H)@-G#9+B8G>FCKORVX_XdXnXsZ|q|gmhuiln~ozuslxlnkehvdcv^s]kVj^cVTKNNFG=H/C)@3B'?(=/E0E5F4F2GBTM@MDMCJ;HAMDMFOCOITLRFRQXTXPWLRNRS[PSGTNWIWO[GWKYJNJVLYQaRYPVIXLXEUERCR@TAPJVGXJWLUV]^haeemmjrmpnsixezmr|gzk}k{pzhzswovg{qwluqpeuipmqekjlhcaijc^gi`airdec_ddabhbhekjphpiup~qxpvitdufrcsergj\k_p_ldtno^pkumylvlq`sfs`oYvlobtdpcnapfkXmbndocqbwjlfndsmrercscugodwmtiratc{dvjr\spu_xhvh{l|ovo{hwh}n}ms}i~nmedcUM*@e>ZBRYD]DXEUAR<[ dB^?a7b>bEaiEg6i%DlBc=c@Y9V9T<^@^Di$Le(KcEf@eC_<\BU=WAWCU>X;d"F`E]>c!Gl&Js,Jv2Vx.Rs*KdBZ=X@E 3F6@8J 8c;Ifzzvyiibiewbv`iWaT[VWOMU?L0B8E(A*=&F1D8GCNCJINUS`Sd^mXsaza}eelmolzmvtm{phjpfiehh~fx_u_iXmcaWWSXRJJ=J2F)@-@)F#A%>-F2D4R=K3F8HRF[BVANDPENAQIHQNDPISEODONUKYKTGSMYIPLWV]LRNYMRORU_TZVVORTUTSSaPSTTXWSVTV]]RRX]URYWWSTZVTWVX^SSWU\^[XTXVOZ^TUVXW\]bNVVZkk،iWTUFTPWX_OTQQY[V[SNOPLYTYHRMTQVU`RgPSUeTcU]Y_`f^o^g`fen]^TW]hnzsnXeT_b`jtfov{qjirl~jeplbduuqkYX]jo{jjjp|nnhhntʁ{ufignȂ~|qpxwÄʔΈxˉ͚џՑςz΍͞שکٓυώϩ׵ڴٮ۪ןզ԰صعݷ㲇൤ڱڰ۹߿߽ᴘܭ֭׸߼`伡෠ޮ൬۽ھ߾߿߼޲ٲԽ±ĮݹݺľĶĵŶĬĬ߼ЫW^?PCP?KCQ@L\?Y;gAd>^?a?b?f>j>c>jZ9Y:XQDNKUFUITIRIUERPXLVNUKUScQVP[NVPTOWV_RZMQRYORSXOWQPVUURSR\fURV[UTUYVR\YYVW[T\XU]W[^UVXZ\RY^ZYU]U^SXT[k[㤒䧁ZUJOL`OSQWUWTTMQOSJPKWQ\HQMXJWPVOVQcW]V\[_[Ugudjajnrek^_NWdjxuiadp\_UZ[[qzmddanxqssuaatykl[c\ulumohw}{vqbp`pxyyqcugyysrduōІuwt|‹ɔЗy~ŊőϚ՛ЌzԈѐǛЮׯ٭ݝ{ןըҬ԰ܰಕޭݢݤڷۺۼݼ൞ಢؤسܻ޼Ἢߺ߱ݳٺõ࿮Ὡ⼦ὢෞڷ׺غܾݿ佧ᾬݺټº࿤ݽỡ㼫ű¾\gV^U_P_IRMFQAHESFRCISaKVHRKSOSOXLUNUOZHQIWI[JYIRHYCTGUSgBSEUHXEVET=OG]@XGTLTH]MW\c_efguvvqtjxon{h|oyc}sux{ftzi~kyrtiukxiyl|rsjide_dicccd^__^`f]_YTbgZ]agffdfomngqmzw~tyfxpudsaqdsgocn\mbrZtfygq`teu`vhxgvayfn^icl`p[rdqfn^k[ldngthm_ohrktdqaxlp^pcujqgtlsnwjvbt`scyjwgta|qwixaulwcyk|iwjn}fzch^PO2GnB\AYAW?WCX?U>U 8U 9_=T;Y@U 9V8V>X@^GdCm"Ak#Fr,Ih Cf@cc=^9\>X;X 6VUbiz|qqmqjonc}pqZpbdZXPOUJI9D3E+A.C-I(:)B6I3F8IDOU]VS^Uh_jZs^pcofnmjplrtsyojpmolekdwf{dr[s`k[\OXROPCJBJ0D*A)E&A*@,B2F1D2G9LG[6L?T?Q?PCQE[FVFTCU@NIVIUEUCRAPIUDMHUBQENEVCQ=PCQAMFQFNCOAMDQJQIRIQOWJTOYDMT[LQOTRVQUOYOXJWJNPVMTPUX^TXTRZ[V[STTSQVVRTZUXORY\X^_bV[UTZa[[ZXZTVTWQVVW^\Y\[{mdOOOQMXMWQWUVPQPUTVN[QTGRETR^S[QUUZX`X]U]U\Y]^aZaghdg[^N]bjnpa\^bcbYa\jgkdkZagpvyc_aklk|vqhejvzccqv}{qumvouvutbfrms|{ʁtjtguzɎΆtzx~ɇ̐˅t}č˙ΣΎɆ͞ϡڰۭڤנԖ֬֯۰۵ܣלذֶ׸ݸݸඝܲڭظۻ۽ὤޯ߳ݱطë徭ೠܯݻڿ°⿨ܼݴ߸۵۵۾µڿྫྷڷݯګըԱط˳wO[:K9L?O>O?MI]EWNVM\PXKYNZS_JXHNFSGWLQLYJVEOGSDTFQFXIUETCWDT>QBSCY?NE\K\OXSeQ_X^flkksw{yvxui~s|m}n|lppoq{oz|qurykwkxpukqknekca^db`h^`ScbgVcRSZ_Yd\Z`h^gnondpfocwhyj|tpiufshtdlgl]rfpdphvcsbvrtZ~ttfx\ugl]l_m^pno\p`uglXrdo_vplamep^qmucvjp[qevoq\tdtlsd~mvmylqbtcvmxczmtcyg|oxi{nxl}q|nm~`rjY[7Gv$Ib?V?Y>V;U;S 7[>U=T9\EV:V 5W:V:X=]@a=a>`CdB`@gAf?h@g>`8d@^<^6\:\?Y=V9Z>]?bAc=iAe?kGbGdDZEXBZ;ZB[CX=[CaCdCl(Hh'En+Qp*Ms.Qh#Fa2N9S,C0I2G4D>IIYRPZS`Tg[jVxdwe{^cksehzdppstrtrjrggee}gx[vdn\g[\Q]YOQBF:J0D%@.H&B'A.E3F0E1D5H0L1C?RDYM>M=MEW?OAN?LGW@NCRBTEPANFQDMGSGVCODNJSBJQWCLAHJQGPQXLTKNIMMYQUJRQUVVQ\V_KMT]TVSXT\W[^^YYZ_TPWXMOXVTXTVMP]^SVSW[ZRPY]XXRTVT\`ZXZWU\NW^`}y_`PJXMOQQURXZMOGOGNMWDSHMKUMYRaKTTTX]V]Y[[^QYUZ\adeX`VZTbcric]b_fak`h_bkpekelpwus]c]qjpihhfehrrvtpqqt{usen|vxjchp^qr|x~f^kqquzzΏЃu}r|{ƃӈuwrtxˌїҍv΃}ɂŠ˨өלחԝӨհ׬ֱذکۦѩֱٶݷݴݥڧڶ׷ۺἣ弛㴎۬رܰغ཮⼬㴛߹۵ٻݾὩῨ໠زرַ׻׿ٶ֭أϪϰʰ͹ҿĿY_?Q3J6H=L=PBTGRN[IZHSJPOYATQXLXLPFMJ[DOCPJWBXCQKSJ^N]G[HYERE[?WBSQ\LaLWSYP_\[efmosrrsyjyms|kr~lr~m}ty~dy}p|i{r{q~xznxnocmdg^ba^b^dVa[`VcQUVWUWT`W]accccjf^pcretpxnxfzmveugufn`tfmaqhrdvbnczku_zuqaw`tls_l[plmap]lhpbq\pclbqfphsoogriocrgtbohslubshuitmrmp[pnrbsgsnudxhtfwhzdxc|npznquyg^VKP(?a=]?VDSDT;UBXDU8ZI\@Tf@hDbk$EjAf>ko+ThC]B^DT@WBX>ZG[?[C[AcGdBk#Kp*On2Po)JeGV;Q7O=H:F 7OCX>|1OXnlnz|zllgunfmxcs^iY`OYWUKAN;Q+A3AYp1D.C+D'?.EU>RCWJ\J^U`Tael`cgkoinprgyl|rzayljkms~j|v}l|vxg}p|rwmyiqcndji^Z]^WXWZQ[MZMVQYV[RUR\\Z_]cbidokqrqfwm~qrgveshododtgtavitgr`sbxdyoxjsgsbrbm_m^nfmbq`rgodq]udqem]qasprisevjrgoasfo_rjo_upverkq`sjrexgwisj{myj}r|i}n|rkmoygh^LR7GkFZ=YDR>W;WDXAU6W =W 7Xc?kCeEc @b!DcBeO 'H0D/F(F7JAT8K3C4R:H?NASLYWjAWBMES@OAOKX>NLV?J@RESBLI`DQ@N@QIUDSCNDKCTM[HNHZANIQOPP[LTOWR[LPW]T`OXRSQNOVPSOPMNNXT]RQZ^PXUYVNW^VTSXW[OYUYX^X[XWXVV]VVTVZYPOVUXXTVTWWZZP~ae]UNWOQ[^LPHPITHTLOIODSOYLQLQNSVfV^QX[aU]Q[TUVgVYSQHR`dlkWZSTlr`gT\[n^hVYktnucg\hhrnmbc`hkphqhbkpszggfppvzxnlX_lv|~rsyqws{{{|ux{wwwˍuistˁц΃vǑŔ̛Ӟי҆ҙӬհڵܴ١ԠֱӰ״ۼ㹡ܣؖשյظݻݳިۦٲ׸ײܹ伫ߨקٸپ޿⼫೙ܮٵ۸ؼ۽ٵ׭ըѮϰѹ̾ļ=N9N8O7O9I;IGRKVGUCQKUMZOTJNGSEQBPESBLFQH]ENFQK\CRFVGSK]>U=PKXG[E]M[I`S^bi\gkjrlpmwkvlvmu^yqqo|orpt~r}wwcqzo}xjxklbijb^]fXZUVT^HNHNMVN[QZM[SYY][^d_knplofrqte|txowmrgsmr\rdrkqeuen^qiraxevhshs^p^mjq]mdtfsprhlaoZsinaodpgp^tgsgqhs_uqm\mbrguevdsft\tfvjxivjynynyn}v{qsynllydn`UT9LsD_DTBR>S?ZA\?[EYCV 7V=W=`!KS =V ;^=_>`>^=`Ae=eAh=c>c?d;`9f>]7[8\@W^UHV@X?bG`E\<_Hd$Kb!Gf Ho1Nz7Yu1Vi&LdFR5J:M@QCYHj!IBZ`mojڀwyvqqni~fzgyenYeYd^VMMODG8G0A/F:P3F8I9I3B0H$?4G@REQJLXS][dVldvat^hreson{gstmtsrjkgkgn`~e|^q_qXm^`SVMRVEL>L6H.D(D+D)C3I5C2F5I8H5K7H>IFVIP@RK[?Q=MFX=LCSCOGPJXAL:OGOGR@P@SANGUFSBNBMFIESEQCNJZHRFOFNQ[KYS[LQ[bPTU\\abmLOKNOWSUOVSSJPY]PVR\LT[]ZZSRTV\cV]R\[]\aWTSUV_\]TYU]XZWZZXZZU[`[^Rl[hWTSU]PNQOOXNOIQMU@QDMFWV^O\ENPW_lW^^a[VW`T\SUY_ORIY\dcd[d^h`[hwZaWY\ghqkilr[ZgxkjcaX^Ychhdifkpsotle^hq|pkfk`jmzvxjbdhuqkpwnqs~|}x{spoy~ωzxmyˊВטҏΆΓϟ՟ککޛߠܤٳ۸޸ᷠᯐܧիԩٵܸ⸓ᰒץأڭܹຢ߿ྫⷧۧתڽȳ߽⻧ߵڮ۰׹ڿص۲֦МͪϵʽϽʹdi4Q0H2J2L8JAR@ODML\KULSBQCNBMEPCPCRBNCQATHTDWHRFYH_E\?R>TAVDTEWJ`OXKbT`[[bbjgibtnxfxlwkwiw~kqp{cmrzi{j{mzfwgyj}q|nrntjh\heW_SXOVJVCN?LENIWCRDRMUU]Y[]becmklgoewqulxixrujugt^qdnnubreuercscrdqbviqcumnamZoetimbocqathpjoasjsljaognapcoiq_mbp_n^rguloescwlvrxjwnvnthxozcyoroqgsf]Z8Iz"Ea!IYDUBVAX@T;WV 4W 9X>\>X<^<_BdCc=`?fAfCj?gAc:d>b?e>^7^ 6W7];]7\?Y;f=^Ai>o$Ii E`=_<`B]!LTBYGWBY>]E[=]>_Gf Jl)Ov.Ry8Y}@]x4Yj!I`?S\Tgmù}݉tyzkksdzgy]r_nfeW[UQNKR@H>V/C*@4F1G7G5G6B8L.G2I?QKSRP]Vf_h_r_ra{gelfngmjjtqljmqokhveop}dw^s^oXi[ZNWMNLJI;M7D8G.F*D!A,G-B4I/J/I5P:M>M>K>R>P9K@N>N8NAQ@PAPGUGUCRCPCPi$Da=g=e>cAa:_ NXXBr*JC\Zhpvy{~sއwvxbbz~eydydscdVb]USNMJP8G4F/@.B2H3G3L-D1B4K2G9IDVIPRR[Z`[d]qeyjxe~fajhflklmfutvofpcpjkdc{ewijVi`XORLPMDJ6L6H/C(A)E#<*D0H5K:O6H:L9L=P6J;TDV>PAO=MIVER:J9J;KCJJUGRHX@PHRHWGT=OLUFSCU?KIVFVHUKQINMYNQQYPWKTLTQXLTSSP`ONOZNUMUSTLPZ^X`YYOY[\dbZ_Y^X][Y^cWZVYSUY[ZZV\W_UPQRYVSX[]Z\]_[[cZnn\TRRSXGILVQWBLKRKQQ\KRN[N^MQZgOXTWWcd\_aQXS]PTN[Xbeh`hWfX\\g\bVi_fSXXb`c]dU[kwffclcngjehU\\glmhcanlookl[ekskirofeajs~oxlm]eq{ÆxҎss_asszy{s~u|ΊҔӔws~v̒Ә١יؖ֘ӫذ㶩᳗ޣۙר֬ذ۸߽ܩ֚Ӧծղ߼ཪݶެئ٬ٺڽ߿⽫ೠߪتְشݱשԣҭԺԼſҿͽ˿̾ͼϽٷױnk:K+F2J9O=N=KEXAOCRGVHSDRN_DTBUAUIVIREVGWCODW@QEUH\?R=P9N>\EXL[LZNXP_^ddcehhYojvpvkwh{njm|l}h{eij|qzg}o~m}qv|myntqo_mbcd^^XZMSCI?M=E:Oc?d@f?g?h>dB\>[:YBX@U =[?^>bAk)Qi@o"@g$EhE\@ZAU^F_?aKe$Jp,Py5[}9Wy;\y7]o0Mg$P_BU <\>k#C?^Wdmzy~}{؁nއ}wwxxfmzjq_gXbTVRMRDJS>O=H:L@QFJJ\Te;EBQAKITGV>IGW?KAPAMDOBNBQGSBUIQHSJVHQHRMYEOHRN[KQNWNUMSMTJRNUSWWWOWWYTYPSUZKRQZUWWTYXUSSXUXS\Y]Y]X[X[]`OPTbLRVVZYZVXYZXT[\^V]d]]VXTRVLOHJS[LMFQMSCKS`IQR_NaU\W`QYW\_fSbT\[ZP[OZ]g`j^]_jUWVYaq^_`]\aZe[^W]Xghj`lSRalgm^`V_anps`e[dqwuvdfV^amosfe`bjxmotmhg[]owwvyrsuejnvupsn_awt}zӆσxt|ʎ̢Ԝ֟҄ЕҠӫشܼެڗՕӨڲߵ޹߰ަԘٮ۷ݹḨ޳ب֟֨ӵڻݻ߻߶૓ԤգծԩԦӠέвϿ˿˰ʿʺʴ̹ʸҽɻ]d4K*F6I:K9J@LETDSHV@QERIYEOCOKYCPCLAPDSGTIZAQHSEZDT>SA[?QK[GZKZO]L[_ifemri[oprms^rl}l{g|luzhzgpl{q}myt~l{p}r~vxprlqhtmkkaeZWTYIO6L6H1D8K2G2H6K>UGWLWVRalebmjngohthzqwmumsbpdthpbj[qepbsfr]wmrbs`p`p`ncnaqsm_tmqmn_vjpioetesitkncrjqbqkqdsouewouiwuueyptlte|stis]yvpouemcQT8LkC\ >U>Q8TGU=U :X 9Y6]?X8[9[A[8bCd;\8eD`@c=bc?bFYV<[?g=e@n!;n?jBk!G_EZBT@\ IWB\NZ>_=[EbEbEc$Lk*Nk!Pz5Wt.Pv6[v4Xk)Je I_;a?i#E;TTghpqn|wҀxׅsފywtss{akxfo\jY\TSKNR?I@J2J.F1H-G3H?M5E0F)B2J4J3F+G/N&C0E5F6N9D6I>N@N>U?L>LNGXDMAO=IO5E,J/G4Q/H.I5JDWP]QVcgbnliifrsohqk~pgtiuetnq`l\tlscthudvlpaq]uimar_o`qkl\thoenfo[pajcpmi[pdsnte݀wsgrepfsdncrgofrdpgwmq`umvf|w}q|pnttf__GV|"F_@Y>YJQ:U=T;R ;V4W 7Z 3Y7[ :Z7];`>c;b8hFiDf@e?dCh)Gf=f6e=a=^;a>Y;Z;W;X;W :_;g;h Bi=i#Cd7_@Y;Q7TB[@X;YAV;[F]=bDe"Li)Sm)Pn-Vw2Tl(Pv5Wt-Qb#M]>`:t)Q8UUlghntyt}wӀuևqڅ}ڈvފr|c|c}`ycp\nebMXUPNCP>M5G.B)D6K0E8J3H3G6D3H8M5KMBRBVCOCQET8IFPBMH^AO>IAUKXJ^J\CSDO=QBMHVAMAKFVCQBO?IEPMPNWNVOYNTNRUTU[LTOVQSOT]cVZKYQWVS\cMOX[WVVZYZZXTU]cOZVVXXYY]\W`UW_X[XUWVRVTcc]^k\YSMSMUKLO\KNCNIPJNOYLULTMRVXVZ]a\gU^Q_XbQXO[Uc[e[eVa[_QUN_\fZkSW]h\^UZL[^^a]W`V^bo`iU`aihekq[ilronopngbm}shktejuyw|sl]b_rvptppkeht|tytqhjdjut}ԁ{qripρЏӇ~zˁД՝؜٧ړٟٗݱ߱ᷢܯޱکءڳ޳޾ᷬݩץֶؼٺ߶ݭڭ֢ΜΠқΙȣ̩ջ´Ǵпͻ˾ļȻ;ɾɻ˻Ϻ¶ȴɲηƼMDU@R@R?PF\?Q@T:P?UBYOZL]M_WZ\l]bcgkjokokuqyf|kst{gqzg{k}p{lymxk|o{oryovtrhqpleicd_]UP^IU:I6L7R>$@$C%@2H:THVU\[^befefllhuvqeypwgrc{ruispncqbqaqlucw`ugqetirjnanbuhlbwmocm_qanhl^tmsfsgrfqdmdk_sgpYwtqgqhulvnt_xmuduqumvh~s}n~dwr]SLQ5TdW?T4O 8S 2Q7W 9Y8^@^J\>^:b?aBeAaa?c7^<]BWkAe?iD]AZAX?YBXA]@[@\=^E^E`AaIi$Mp,Qs1Up1Yx3Um)Pj)Nj+Qd&Il&It-K7SOg_lrqwsφ~}wπqفr}sևw؇z|f|fy`vem]h\[QSQFR;K3I/I/D4F4L7O5J2H:M0F6N5G2CN6L2K+D0H0G3K4G2C3H7I9JN8K@PCPANEQ=IFR:M@PDS:KFVKXR_GWJUJTDTFXFRES=OHRNZEQDRIRMTLWPUOVPYMRSVY[TXSUQSJSOVWZR]V\Z]OVSOUY^bMWTVWTWX^`SWVXVSVX\`XRU\[Y_Va_Y\TS`hbUYPTRHPANIRKYNOFPQUNQEOLWLRLWLOQ\]hO[X^X^UcO^`ma]da\aadUSXb`d^]\i`bZ\`dSa\cedTUJ`hl`lcjaehmih^^iqkla_gwch}~qog_esooqo|s]_^isyvmhg`okmʁvuklhprsy|~qqsȂӓՙ}}̃і֕؟ՙ֐Ӛիܵ޶ᯏܢܗ٬ٲ۵ݴṭẫᯑ߰ױܵܶܰݫܟؖѠ͠˜Й̦Ѵս̴ζɺ˶˽ɾ̽Ƽʻƹ;ȸɸ̽;ĻǶɵ̴ּ̿`k8M/B4G7M6O7IQ9N;Ji#If?f?gGh@b@f>hEeAbB`>]@Z=T_B]B^CbAg%Pj#Np.Vq:`v=^y8`n)Ti(OgGf%I}0TA`Sd`oozts|r{u}u}q}~r׋ucucv]paiW]ONJJL@L6E+A-C3I4K2H3G9GAU5G8J2B-B:N;K5HCFORSU_Pn]p]t]{g~ifqiinwmpxpvtwgiqkn_~a`xbp\lWdX`TUMOOIOAM7L3H0J-B6V)E0D7H=M6I9K9M5HPDM@L?OFWBPCNFRO_GTEUENBPFUCR@UDRFRESDNFZITFNISJPIPLZRPKTOWNROTSQOSMSQNSUOSPPPTOWSTSWS^WUV[XVUU[YTTVRXXXaXXVQZZdlYSW\Z\^Y`b`]RZSZFOFPGQDMNVORDKQZITQVQR\oPQZ^ScPYN[SZP`cq`cXX\`X\QX[_^dRV]h\`Z[V\ZdbiUWR[QZacgo\biimlfddpglmibe`fovst}wd_crmislsteiltmoutcjfvsuvq{{imkssuxvwudo{҅|؇uؓzo{Љ}֒՚ևօԝܱٚỦݧڑ؎פ۲ޱᶔݩకڥرݺݹ޻ڮӕӋϜΚΔϗ̩ԴʾȹѾ̭ȮŽŭʽʽɸɿͼȻʷ˾ƻżɵ͸μûīȯϿW_:M+C/I-E5G1DDT7M=KDU@T@N?P=T=NBSK^G]@PAVAZ9N@R4M>S@PHXOYOYMRY]_hdajhkitnzn}t{nr~r~j}x|h{jn~q{m~h~uyl}q|uzsqdroolhd`e_`UZEO@S/E?r7x@sFt< E4E:OTaLXZb[\bkggkhnstkumtmumwjrcngqgoapdmeqfrcuexpqdn`nfnbmfqjxrskj_pfolrgpjqnwhvnsdmeuhrin`n_wpj_oeniqarqyi}g~sp}qs_`agCiBhFk%NgeFc>hEe?dE]G[:V=U :U 8Z>]>a?gBi@jDhC\<[Ca@Y5ZO_ LY>\Da$Kb.Vi=Zf5ab&Ml&Mo%Vn.Rw<_{Gkl"Pn0Vl!Jg"Nz/O3SLg`kmvv|zsҁyЃwyu{t{uzq|mڅxv_v_u[l_cSZNPMGK6E1G0C/B7P:J7J8G6I:J?Q8H4H0B:N=RBWNJTR[`^WfZgVr]yh{gpsigknqdrmqlpktjokflx`xfrdhUdT^U[VPVJQCF;L1H-G)A6M3G2H4G>N9L8M8L>O:O@P=NAOBWBN=MCQGPCPELEQ=IALOWBUNWERCO@NAR>OCTFQBPBNEJDLMUMNNXKOOWIVJMSWMRSUSSOOOQPRSJV]JOOSXXQUWYVZZ[VWTVQQUWNTZYXWRZ\_^_Z\Z[XW[V[^Z[ZQ]W[^P[PWIPHQDMAOKWEKHNS[S]OWUZV`MZZ]XbIRL\`g\b`a[iW]YgW_aj[bWe[d\cS\KWXdbaR[LYX`[d[bWc]mea`bhlqsqlaaXYs}wuxrjqgrtuniopkrmgnmulmd`nwvxvπxzntyyxtxtgkkuЄz}}؃||΃Ԉӄ׏בϒ֝٠ܣڝݡئ֠֫׬ܴۦۜ١اٰܶᵡߵݰӚ̌ˊ΍Гˢеºʳ张Ĭ¹űʼƹʸ˻˶ķưĺǸȵͽϼķǰͶڿ׼ŵT]-I*C.G0F3H7H:I;M>OCSI_CRBXB[BQF]?S>MCTCS>T>S8I@TDWCVIWR[PZWY^_b`gcmnpfykwk|q{o|nj|kuhygzn|d}p{n|r~n}y|wwmqkonl`ljjm__]dLO?P/K!>x?rAh;p:y8,E8KBOLUVUW\msb\iinos_y~yquiynvaskulm\pjmdqhogteskqfl\nnidqetkrgqhnaqirfmbojo_skmakfk`lZogmbnho_ogphsfpi|wzk{ilmrfjfO\'Y;[?Q :S 9U 8[8Z 7Y 3Z =Y9Y 9\=^Ca=c@g!Fj"Eb>hBc@b:dDeBd@bClFi?[>]JU@S;S>ZC^!G`N8M?L=N@R9M;W8L@K=RFT@PHRKRIYGUKWHWFR@NFWFSGR?RGSFSGRIWCQHPPYHSJRIPNYU\DKHQNWKPRXPSSXSWTRU^P[KTWXT[WTZ]Y]WRRVUTUUX]QRWVUYWQbdVR[^Y\ZX^ZddXQPRRZKRNQKROUIIFRQ]GMEMRZMQOUS^LRLXX_NSJWZ^baXX[^[[QR[hT\SS[ffq_WTVO[Ta\_S\NXW^VVVd``iuY]]Zingk[^\hdnhmoslejumnunof`_^inkmvikeb]hvw}zqrifsqwrrvtlyt{·|Ӄ|ԂzsqЅ|Б֋}oӂՐٕաܠړ֏ך٨ۦݰݭ٤וա֮۴޸ݯ٣כԠ͛ˈń̞Զܸù̿͹ǽƹ⾳ųǿ˻ɻŵƺʼʾİǻɿȽƺǼɳϼкǼȮ˸ڻظºNY1G,B,G4N4J,C;OOE[DWAV>T9Q?RDVERHTQ]RZX\]`fdkengtvxm}p~vn|ikqxhlnzh|m~n߀ztgxo{vwusfwupljhdeaj_`OXDV=N$DzAm:f:oBw> A0G5EAPUZRWZdbamkhiodtiy|qg|qzrvhrpm`rho`rjnbrin_xjtgpgnindreq_n`sfm]pjndpin_qaqbsklcnZtilaqiqdpfshxnse|xyp~o}jxdmdOU.Cm=\ 7V=N8Q =X@\C`FV 4[AX6Z=_@_B^iGf@hBbEa@aDZ>S3I8E1H>MO;R;KERPCOM^EL>PEUCKPYBRDUMZCODHEZ@OEM?KFVBMITKONVMSHSPTLRGROWXYKTW]Z[NONVRVV`TSR[PVUUXZSYU_YYWVUWZ^[[\W[[WXUTWZXYXVYXfj_Z^YTWJPLYR\PQ@OMUDJFOScISLQOURUWaSaWWKUOUIZ^gS[U]XYW[WiQZVULTP\c`\dKNTgbiT[QZShWlW^SZ]]ea]f[ihiloaaV`kumpusglipw}mfiqY_amqtqpx|`ekxnoxr~~ftguqnssrnoúwwւyqpekyx΄x~myщՎ٘ؒ{~Ԏѝգܨજߣٗ՝աخ۴޶۟ՓϊˌϏˆǘЯּ߾´;ȽŷƲƴȿű㿨ʵɾ˻źǹȾǽ˿ÿɰǵǼij˶ѿDZ̾ۿػAQ+B4I+A.C3G8N6K7M=KDS@S=P>S>L>P>R>Q?VBT>QBSDQeBgBeM9N=Q?T?U?NAP9P:SAVI_BOGTIYGO@OOXHYIPDTISAJDTFN>HJSDP@PEMHNITLRMTLQHTGPHROWNSRSNPZ[QUQXSPSbKXSQV[PVXUUU\a]l]\ZZZWV[V[MQZ\VWW\STPTYWZPaecY[VRVCMO^HQBPIMKSHQJSP`JUIUT^NYQZRYPXJWYg\Y_bYaYYPTW_Y_QYN\YdbWVVO^T`U\RTJ^]f]_]`VfZ]]Zacckqh`a\^PX_ipuliilruzxpla^anml{~wtqenrsvxlxqsnouuzsuyrsxmnсx|wӁy{qw{zuzzxʆυzԑו~}|ϔԞ٤ܰ޲ܛڛ٦٦ۤߵ۷ڡъ͌ɈÄnj̟ժ޻ƿȾȷǿʬɮȹļ侴ñŽȿʹܽ㿥ɹɿɿǿʼŻȼʺȱ˻ʺǺ»İɸ˽ڷˣXc8N0B0I0K3K5G:MQBUBQ@O@S@S>OARFQO^PZY]`cdgegiaquwkzp|q}rz}l~mp|qi|fxl|k{kzozl{kvozfvymjgdgm_[ZjQUEM>R2Fv;o=_ 5^ 9a8q8>)E:JDPIVN]X_]_f`geunwsvhoj{izmugp^oelapeqaqjocshqipgqcgcpdnhkepgslwpogqhjltmsgqeqkogvhumro|rphxmws~s{o}q~ir_ZXCS%?d@YBS 9W+O](S_;Wb4\^'OZ <]8W=Z<\>aAh"FeCn&CgEh>fCg?fBiBg"Ga?cAc@eF\CZ=WEW?W>XXA[?X;Y7a @c*Od Ie#Ld!Kg#Po+Yr5au6_t2ay5]~7_5Y?bJgZsl{ntyx~v}{Ёyxӆz~vtloqfgql̈́yfTfTbSUIKL@H:I1F5G1F1A=S7D=R5H6E;G9K6D3E6F8K0C4CCNFMLMRPZWdXnYp^u`}dalujoowkmlotglsjlf`e~dyipUl\cV^XVPPLKR?M:N*C&?&B-F.G/F5L5MUEOJYM?R?Q8O?P>Q>P:T5L:NEYHZIXQ_T]YZabcec^ppniuqzo~{q{~nywt~no{gzk|rzp|l}u܁||vvptstpgkff]hPUEUXEVCiDbkGj[(Mb)La#Ha#P\?Z<\:_?cAhC^=iBi?cAc@d=dEj>eAi!BgF_?\>Z:W?V?V9^AaBi?i@kEgEbB_@X>[=VAY?b!D`C]>^9fDf'QbHj%Qk+Pm+Sp4\t5`s2[t3\s(T9]AiLhWnbrp{w{yy||zy~nЅԆrҁyzqhkosqkvՄx^P^PYRQKBJ=G,D1H6JK`>nD)E5PE\CRJVSYQ\agc]noqpqjrovixqytwnpdtljc{oodsgngqjl]sioapdm`kbodqeslibyqsdq]unsjrbqiobqdtbtttmwixg~wkylaTL5Kx ?^ >Z?YGUAU9YAX@Y;Z?Y=_=Z9];a]?U=Y9V=X=c>m#Ck@n!?e?`;^<[@[@Y>]CZ?cEeE_@\AaAd@c&Jb'Pl2ff(Rm-\r9av2^|=`~7]=bIfUn^smqtuwxs˃~sЀqx҂|}xnonoutρt҇֋VMVMTQGK>G7G5L3K4L0D=Q8N>MDP;M5H8K;PL3E.F(F-F2N9M9P;Q=M

M@R=M?PGSFSCO9N9MGON,D/D2H1H*A4F5H8L6H:P6K9KAV=OYX :X7Y<^D^ :g=eAb;i>f>h@iCb:e=hEi?`@e>^>Z=ZnBp#At+Gn*NY;\AVA^@X!De!I]D`F]<[=^E[>]Ee-Nf$Tk+Wm2Yn3^s;b|7h8`=^LkXiatpzyv~{w|{zy~yтu΃{rqmntm̀z҉yԋyՐUVUVLHBG1G/D/A3G6L1E6MNZGQ:LNLYDQANAK=PFSISLXOTEKEIFTOSJPPTKKZ_UbIIScNOScQPO[SQNSZZSRV[SZW^WXYYWWZg[Z][[fWVVW[\ZXac^cXYWT\YSOHQJRFOHSLMNT\`PVR_NYNWNW_lQ[PRSaSY[_V_QZTZT[RVW[OW?IQbYYRaGQPaQ_Q_JSZibm[\TWdqmmfj]eViitldbb\fmmynrmlkfhyxvrsndcelv|ytyqjsvysxr׀{vruwzԂzhjZ[iq}|pk{wklot|wzv{|osw{Ԍ؎ٜؔԁyԎգ۩٢ٛ؝ӌ͏ćvsi|ƍϚٹźȻŹʸɻɽƹṰ濦ݽųȺƳʸƼퟹ࿴߼๤޻ڶẦí޿üᾯʽɯѿȺͻݾƝFR:I7E.F-C)B*D2C0J9Q0D;N9N7LBV:N:I6Q3J=P?PH[DVPWTWbc^Yfbomrgslysymzjrhz}n|i~y|jzg|luxrxyq|vksnokmddh]\agRS>K6H-G}:g8W3S 6R 4];l>q!I,N0JFZGSQeW\X^\_jdnijerrocul}qvqufymsjsfpfullgkhkcsgpfnancxrncnom`qgi[ontelgpfqlqgskqatjthukxgyn}izlrjLM-EoAX 8U :N 6Q >Q :T;X=V:W;Z>\=bB`Ab?k=hBeAh@e@e=e@m&Lm!EbBfBa?b>Z=W:P 5V;]:^:aBgBp BtDm)IhDZ?U;ZC`@^C^:dGaA]A^HaB`?gNhKl(Vk)Ts;fu4ez2d}5aDmPkYtaup~w|z~zĀx{zx~u~v}owvitplzpуwՌ}דv֎~PIPIFM;D1H6F/E9J;F9H5B>N=L;H7E8N6G5KAK6H.A4F4H8H@R?KJHZ[cajekVx_yb{cjdkfnpytnqoxwrnjthjmgyeqeo`cS\QPMLK?G=G7H1G+B%B1I-H/J;R5G8SDP>PDU@N@Q@OU]BOAX>PEQ=OAPDOFX@ODOGL?Q@NFSL[DMCSGPCRAQFPGNKUGLCLKOGMGMIOJLOTKRJPQORTPPWb[TX^VNOQQPQQVYTSRWQWT[SSM]U\W^Xc\\`dZZ[\`eVRPZRYRVORMRLUHNLUKSTXTXM[OWRZHVNYXcIWO]UmW]WaSdV]UW\hZVNRKVOYW^KYAXGZNZQWRddnSYX^S^Xjif[Z[bjmtliYX^hnlfadc_ablpiqqii]bhtvt̀tkpnlrxypi{ywn{΃x}psp]]crz~xqrcgijyyxtvtЀч}ٍ{֖؏Ӏ|Ւۨݰܨ՛xnτxˉ|unxģҶر㺧˻ȺĽôǵȶƶźܽදǼʿ°ſìȷü⿻⻧¯ۿٹ۱׸ٸ໬ʿ̽ǵ̽³ȻȸʾǼǾǻ̺ɷѿԿszO[AJ4I2E0H+A6G5G3H0B6I3F4E5I1K8I7S9O>MAOJSJZNWT]Z[\Vhchdkfqhviyp{uq{iu}o}k{rzgykpwpq~|~kyqvrgqjtigb`[WXLUCM7G-A|Dg8W 4K 7QAVA`Dk?{(D3PH_?UFPSbX[_^h`gjgcptqdtqsdukwqympepfoaoerhlbmdpeqdhakeojmdufqlrllarmo`phvqrfphp\wlqeujwk{g|r}jk]]U@Jw">[9V:Q;R

X=Z>_D`@b?cAeAl Dg?dAj!Af@kEg:e"@h?g?d]>`C`@`=a?f"F]Ai$L`Je"Pi&Vq2^q2^{8ZBkPmZqdvk|x}y}ʀvɆ~~z{xs}uxsplst~sЅvӌ֑zِz؏FGFGEL3G,G4C2MJ8I7F8N4IUGS7J>K?OIQFVHUKERLZFP@MGMHU?KFQHVEM@KEJBTELKOJVQOMUTXGPOSSOUZXdY]Y\NLQPRVPPPVRQTUX[USXZWXR[XbVXZgZ_\]`febUXT_\bS_S`O[JURW\eNVGWT\X^M[NZX^JUNVRcU]V_XU[eU\Zh^XY^MSQ]VVU]O`M]U[V^T_TgZ]^\UeYga`ik[^SZuwrt[VY_\hmprgd`crowrqsfid\ghryr|txueatyz{wiyuzwxp~zxpknhmcnqspywoepcntry|zyjeЄԈ}ه}؀xw҃Ֆܝ٢۩֓҃z}z|quvНܳü࿷ǰŸŰº³¹ùȶȿ羥ɲ˾ེ㼪ٸ޺ƾּ²޽ʺ´Ʋƹϴ˺ȵóªȾĻǺɽǿǽ;ƱfxJ_=N6M5J-C,G5E1C-@7J:I1F?N9G0L1I3HQ@TM[HSPZ`a_]cb_`ngnfthyutjsqtergnbtbi`m_nln_m_l_lekci_lemcqnwspesjnhrkojwirjsb|osdt{q}l~ptge\KK)AhE`EY>P :Q7W5V8W:[AV=Y>_E]?e?h NhEj?hCk(Dh'Kh?e?e=g CdAf;a=b:Y>[Q9H;J;Q7C3H0E0F;P=K8IAJGNY^]VeUj[mYu]{afgnjt|nsxprzvnsn}pniyc|qo`mXejdW[YKMHP?M7G.D.J+F1G.F)F3H@U>N4I?RBMBO@NGQCPEP@QFR8NHTCRDPCO?LDN:HGRHV>HAL@NAODOKSGOKOHYEOKMIRERHTLRHPR[NPRYNOQSRQ]ZX]OPTTZbQPS[XXRYQYVZVWWXU[Y_WWZ_TUSZ`cccg^YXPWQY_aQXMZXcMWMTYeGRGUMUOZKXT]NWJTNT[dNWS^\[SZLRX`NNFQN`PVOTLSct_]QU\bdp^eURTdfu[b[Y\e]gdqkiY^]ej}kjno`^^_wvtplfaeV[mky|mlli\_wqЂpkmgwnyzuywmlbqtyʇvjtuowruyxynsqluntЈ}zvwzђҟٗݤؖՄsͅxĀc^crśӶ׳᭡ªƿº°ྷ´ôĻŸƼĹĽɰǼ߾ڹ㼨­ܾ۶߭⼢ڽ۹޼ǼƼñ̼༱įιĹ濦໭㿧཯ۼܼڼĨǿƸɽɺϽǹi}U\9I/@'@*A*A/?.=,?2H4B:E:M5J;M?R>LHTM[^bZ[a^f\jdmhskvf{l}z{i~lq|n}o{o~rvlmzt}nznq{ozntjxuuopegf_[bcR^BK5G+Ay7k8]?T8R>O=P@QLWQTa`gka\fgqjrjspshvsxdwgr`scoarik]riohmdpjngl`rolkrikhtqpetpuipculnjsh|own|izfxlxihcQR9Gr>Y4XR 9R 9Q:X :S 9V 8S9ZA[=gFb?g#Ei!JlEg$Cl"FfAa9gAdAbDd?a9`:_9^@\AX<[8cEl Fp#Co Bl>k@d>Y;[:W?Y7`AbA`Fa Bh"Je!If"Gd%Hd*Nm%Rf,Rg(Sf Kk#Ss,Y|:`IpUmkxhrrzxvy||{|̂~~z~~~|qopuxszo҇tІwԊ~Վדw׎ؔy?O?O5J/B5E7L9N5F6H8E:JAS;MAR:Hk3;2G=R=MHQ[]WYXX`dgenipiqcslult`shtcsdtgn_pbqem`nmk_pnmfh`pilbsqnfrgssvnogqksisgzozkym{ircoa`\HS{>Y 7Z :P 8S9X =P a9`9[=T=\A^?g=nBv!ElAkGd@bAUDV=W<^Ea!Gc I]C]BdJdC]Db GcIbFd Rk!Rh#Pk/Zv+Q>bMkboi{qox{xvy{{v~{σ΂ẁvyxw~sw}xυw҉֐x՘Ջuא|ؒؐw7J7J3G3G1H9P4B7P;M4G5G+E*B1GCO4L:P?U>MDY9NBN=MAXAMDV?KANI_@O?NEO@M;LBPAPBO>LANCO;OFT?GJ^EIMPFNBNIKJ[LQQXKXITNXMSUZTVNWOUOQ\[MSRTIKWZQYQXSUSW\]UbUZVV\_[\igpjRQUWMRHPSVJSISHQPXWYUZUXNQPVLUMRLST\PUUZTURVU[\a^]SXScRSPSYfYe^cYa^d\h_gW]Ud[k^_\aR^\dopmihkVZ`lkiopY`\`hxpmxyrfx~v}masj{pdhgxuu|wxynfiqtpqjqmkncjvruqnlcj[cipstjlijpĭvmulipprԂ|ӄ}Ԙؗ׊ԅ~͉|qj_ol~гڵܳ䮚Ṷ౧涝íĸ¿ݹݸŰɹʽǽ´߻޴㹤²Ƚķݿٴ׳ܸⵓǽ࿲Ʋ̻ʸ⽭ڷݾݻ޼·ɿķð⿳ź̵ϽϾ˸G[3F5O0G$='C+A4H*C5H/I1F4MAP?LHMJ\RYYZZbjfnfkfvvtgvk~o}r{js}pzjp~mlp|rzh|r{r|tx~yurkmniea\\[NUCO8J3J9jeBeBb<]9UBZ =S 7U?W9c=g=qAo$Cn!De?]B[;[CW:XC`E_9gAb$EbAgE^=bLaMc"Jm'Mg"Pk,Un$Nq*T9`KjUmhsq|{}|}|}zs~|ÿ́wzuxypo{z͆Ւ{֐~Җ֐vӑ֕ؔԕ7K7K-F;H/G=R?N?L6H4K8KJGFTZYS^Wn_o^s`vdokftitig璄qwxut}uxoqm|av_q`oaf[cYVTPOIM;K6I.D*?+D,F/C-C1A6O5BW :fR 8\Aa?d Bv%KpDn?h?_B^>ZfTjd}rqnty}{}ytv{ẃz̓~΃}vtsxz~sҋ~֎ؐ|֒ו~֒׏׏yؔO=J2C/D(E-D'A*D6C8K9B2F8KAP:L?N;O8IDQIVDQ@M?OBL?M@KGSFRCH=MBNEMJV;LEVGZLSU_EOFOANGLHODLIQKUMRKWJRMPNYQUPVY[QVUZSSSSUZS[RYQVTSP[XZ]_PPQSST[_TSidk\cXRVNYFQDOFUJPFULVKOPSYfXVKQL\XcT\PVN^NQNWKSLUMUQVUY[\NWSaPVXbQ]O\^[ZZJ[Xc_jQZOZ]krxdgjr`ebhv}bb\\W`drjnreebihxowusqvstdmgpvwjcnxiiyˀphqtmnskhmesta`jsuyedkfhtqrz}wuictʀ~m}zxpӂvΈ}zrl_gdyÉ͢۱佧㿮㽯޼۲߮ⴒٻٲᷢĨȷ¶߼ඨ纨´ί俭߿༳ܽݽݺ޸²ݼྨܿجڷܽ׼ڷṚĴɽĻȸĹǸŷɾȺƼȻÿ̻__6Cz'C)?(A(C'C1E3C-D1H3G>KETLSPSUXZ[hdheqkvkwt{n}o}opq}r}nuzo|pygzuxgryl zh݀y}ypjh`ibbkV\SYIR7H,IBnS 4W 7Z9]<^:];b:g8hAm!Ck!?mEjFkBj?iCdAeChDe;gDY<\=W;X<_>d=h@kBja@]BZB^?Z:`aBh(Nf"N\Da#R\IgNiOo"O}6_HaTecpous}{w{vvyy|vs}xr΁{}ut{txzЉՒؓב~֓Ւ~ב֓yِ~֐|>M>MK?O>M@KEPBS=MBQBP9K9LAS>JANETEP>O?NETELEQGSEKGS?IDJHQFRBIEHPUILKUIROPLWNMMXUUU]TXVZW\YWUTXUS\TYURY_UT\\Y[TXY^WWWY_Wo]`YZXPVHUKSUZQ[CPJSPXM[KRQURVNXMQS\OWRXPYKOUWOTGUTYRXOVKVS]SXV`T`XdT\OSVWZ_afW[Pa_fifiim{ehn}jjlhWZ[nnsrmsoflhls~{}yvwenaky|otskkabopЁynggljrmmmmkgefirclomhe_ebqptniysehhiyn{tpifjfn~zɁujifpoy™ӥߴ徬༬罢߾߻ܼٻ٪幕ļپ۶展九快ݽݺۺ㶦Ῠ߿߼ὴڹຳݾݽܿ⿲Ȯ¾ݺங㼬ݼ׹ƾܸ彜ȱ̿ůɹŲƹɺȼ˺̿ʸǵͼʷоμƴɯκпϿκDSy%?|">%@#;'C)C0E/B4L9J=PAOHVPS_adajgjgmis_w}}sps~q{|o~p}m}t{mvn~yi}pxruzg~yuqmahcg_[ZWYKSFM;H/F?u8O8IHQBVRWbb^eadghnnwjukxntexmsetgqbthmcj^mfj\j`lbpcphobpetdzowmtmwlyk{r{nvgtbifOM#Ef5cGU:S9U8R 9V=X=T =Y;X9aG_@gFe=ek@f:fBhaCeCd?c@^FaL_E\F^G^ PcKj$Tu5`C`\scwor|svy~wvxzv~{u|t||xxt|{z|w΄ϋԐ{֓~֕ב՘ؑ}Ր֐׍;P;P8K8K5K@O*D1G1D6K/C9FGAKFRBQEKIMILFLLQRQIOLOLOQYTUPSSRTYV_QN[YU]QPYSZ[PVOWSZRUVVU]VX`axgjYTTXXHOISSUPSHSFSAMHSLUKNVYUXUUR\JWPSY`P]NUNTRTV`X`R[ESQ]QTOUX]X]P^IU[b^cNNUjV]eoedcackejhche]^Xd[jv{qoilpujm{zzrrokrmfkwqtzr{{ilbgkp{tou]chxtrssqoddbnpstqlo\e[mnprwvwlmu~xxwiu{X_gqx|ml^ckz|ˎ۱᳣ܸᵣ๨ີᾭວ⿬ܿٶ⫕Ǧķۼ۱ܯᬙẤܻܹ۴޴ߴݴݻߺ߽ݽŶ彣㿱ڶڲ޹ɮʾļ۷幥ţǼȻĺƾǴ̵ǿɼĻƯɻɼ˽ȸ˸ɺð¯ξξ˼ʶϹٿ˿hr/Iy>~%=;%?'=*C-C4M7MK.H"Ar>d7^A]?W<-C9K9M=NJQaZacb`gaheodrfudvipbtatjqeneocm\k^nelbjembkcupsmqjrjqjuhyr{n}y~qufmbRV6Gu;\8W =X8S 6UAU;Y>X:V:\HZ<_D`9c=g?k!Bj>l?g>i:jEg9fBcBg FeBbCa=];\>X<`H^?e?i?h@i=e?aBW 8[=Z?_=d HdFb@cAdA_DhF\EaH`J[F`!ObIg&T{6a}=]Qkg|lxt}z}|~urwxwzv}xxzzxwttu{{y΅ӐԒԔ{֕Փ֒ד{הؔ{Ӌ{ӏ{4K4K@N6F?Q>O;K;Q?O9N7D?O@L9JEK@L9G:F@W=R6K5G7HCUARFKLNWQ\Ug`nbvhs\xdokgrnovq{urꏀpnuxpriogwgtclag^bXYNOTLO=LCT3M*B'F-H.C1D2E:O8H8J=L@NCNKAJ>N8LLKXDPHWEQ?LCMEP>IEWCN@NCPHQHN@S?KKSARGLEMEMFKJQORMTCNIRMXP[TXT[NXS^RVQ]UWXWYZY\RXWXUZRTOVRW\evuڃfUUNRQRMMET;JFM@LCQFRIPCIJRWU]dPUW]Z]OQS^MSMPRXZWPSR`^]X_[jLXSYOVS_SZ`d[^OVN\]j[a`^`_aljeomZ]Wb_rntqnsejiox|}yuojrxlwjxpqlfpxkiq{vwpnfnkxutqnnleihoqyonnvfjputwkgigrrmspxxlh_ldptcacsrŒћץઈ㻤෭ⴝ໩߿ߺð⽯³ۼܯ篊༧ݺ۵۳۲ޱ߻ݻܸٴذݮฮ߿༭ྰຨ๮യ୮ݹ½Ʋ߾徧ɱȽʻž޻巨ƨƾǾƾɷIJοʼŸ濫ƼǴɾɹʻƿĻȽνμݷ׼\kw!Aue@e=d@cAb@o3JbAeE]<[D[9]Ca@fAbAi#De?f@`;Z=V;V<]@a>]BfB`=l%Kk)IeE]CZB]F_I[N^KiOt+W;YOidxm}uzz~{{|zuxwtxxstnvlusttqy҅yԊՎ~ӕ~ԕ֒ԑ}ՓӒ|ؔԎ~֑{4H4H5G4G.C=L:H>Q?N8K@NU?O>SBITd\b_Yb[hUqatbta~itkwovwk}hwpzrhipjfjzayfsbmdaU\UVVKVDT9F?V:O+F+D/P&D'A2L2DQ=M@P9LBK>NCPBOD]=LCM%@,A.I6G=L=LMQP`VX]Zddc^icqnto}qykyezjy{qxn|oxm|pq{zzo}q|p}ws|wtgpkjkhcce]dUUMS?N?R"DtBb;]8ad@g:pCjh>d=dEg Af@eAg"Df@gDc@a=aC`?Y@\Ac>d'Ei"Jk#I_:b9]8XLDS?P@QL9LCRHYKNPWPRbZh_hWo]tcyeljjxkwqqus}tzqhhxvml}jw`v`najbg_URPSKV;L6K7K1G)F/I(E/J4G5K3H4O9LBS=L?M>L:Q8N;MHNEP=I?ODPGQDOIV?KARCP;GCICM=L;HDQENCKGMGPEIHSJQDLIQMSPTNXMUUYJVKWRXKSVXXcU]RYOVTV\aLPR]RWNUMV^VꟄmZY[JO@NBNIT@QEYKXGPAPGUGNJZL[QTNVNRR^QPTYOTLTMTHSOURZHRRYPXJVJ_TXUUR`H\]cb_\^W]YhjhVUXe[_^phvofkpaiYfhnwurqsotrgspu|xe``fc`exqoxpqxqrr|zqtqtnrmlx{nqhigm`lttcfdqQfbqqukibg^e]ngi^fYju}Ɲ֨۳ٰ٤ݛڡݞ⸞޻ᵪ軖Ƹᶦ޶ᷣ߻۵ګ䴐࿨ܾسթլۮ߹޿ݶݤ޲ܮذֱٴຫŶ¹ĴȻŽijƾü߶羧ǵɼ཰ƫ˿üªùſȹ˺ȼɸƹѹ̹˽˼ʼƿĵȹҼ̹ڽٴz&Cq!@z%D!<%B'A.D2E6G@JK[NQXUccc`f`oergtntf}l{s|p}p|k}n}q~ot{r{zxg}o~{ys}rulxrojmpe__a^^STLX?M6F|&Et=f=]8[;Z 7bA^E[ 5]:Z 3^ 6X 5d7i5|!>*C4J:JX;Y>W 9X :U=ZBW 5Y:]!F] 9`8f@hCl\=aCn&EjKe?aAeIWNM@QLAQIPFSCPBNGNCJFSJTGNIPLTIQLTU\HSQWMUTWQXPPX`OPNRQUOTOSLPNUGNJ\QTiaqpeUV@JAKANDLDNIOKSGQBLQWIKLVU[PQFKRXS[KNQWKRMVUURYQQQbWYRUMYNUTcOVKVP]^cZ_Y[U`gxce[^KUXdfovrx{kneo]oilupxttxtsyvxxwme^UXUbnvă~uqgggjx|҂sljljpv{ssxrij[fi{o~`^XcWeemqrooca[ifqbldoatvёౝڻౢݮ؜תۤ٭Ⱈ忢ྐྵ孝¤¶߹ܱ߱ợ޽۸ڭ⨏޽ٽظرݶ޸⹕ݷ١՛שٰݹݼۼྰòžźǿ⿹ƻȻ½Ṷƻܽ彞ƺ·Ȼʾ̻˽λȾǷŵƻǴɸʻƻɸùǺмοׯֻĩ =A!C*@1I:G;I?KHOSR]\_Xg[kfodxrxkzfzq~n|ih|nr|j~tt}x}o|o|q{s~vrvrstlfho\a]ZSXLV?L3G!Az=b=]?^=]?]7_;]CW 4\<] :Y 6f7e 2r 5!@'>3G8ELRVTRRYV_Y`Ykdkao_pazmvgnYj]h[lZg^j`nbnekamaxkohsgswxo}p{pvi`YFI%BgCW8W9[EXAY:W<]@X7]@W?U;`?abf=gBeBbD]A^@[:ZC^?bCdDd>i!Eg>aE`;[:^E\AQ?XCgSk!Ou0Z;dQie|oztzʃЈvt|~s{qporlvjotrɁ΂э}؍wҏ}Տ֏~ӑՑ֐~Ԓב֑|֗yՑ~ג>O>O;H6I?H=OMHNDLHUBKDJBQGTIOIRNUMPMSU[RZORUUU_PVOTT]JKMOSVQRVPNVRUMTP[QRـtfz]QU>J>KKBNBOKRQ`CMGRPaTVU]RSLXRZOYQUITPXQSHNOYY]S[GQLYUhUUPYSbQcbeUXYi[fcgg\\^IXV`gcfcc^__fkmxdjlnqtnn{yҀzummchdU`Uksu|osdfhcasw|tsyirimflwxstca^jnxrnqtZ]Wcenk`fdgk^o\`chZju|Ñў؞⨈庩ݴᩞ٧ޥܴ޳ݫ谍㿰ݸ豋⻜ݾگఏ޷ඨ޽ִתߤߺý׹೟ݮܟ٬ԦԮٰܺ༶ྵἺ㺱ƼĵƷƻŶķȼݾཱུǰ޼ௗ̶̿̾ùǺɿ͹ʿŸȽƿƽɺƽǻŶƺǻɺķüʽ̾ӼغWey@n<_ :];X?[=_8`;d 7T 3] 3X5]/c 2j7v4!@-@:IBIMSSRXZZU]Xg\i`k`n[s`rdr`lZgVk]gZfZi_mZmerdufsotkvmxsk~zd]SV)AiWD^>_B_F^CdDe?p$Fp!Hi!EdC]<`EV>S9RBYB`Iz4b?dQr\tq}x~{~Ѓ|x|yxzwvuvrofrmnxx{|ʂ~͉yҌwՋ~׏~ӏӏuՏ}ד׍wՒԊ|ҒٔՒ~Ք9D9D7L:F5H9O@JIS8H;ICS=I:L8K>L;H9J;L9L7I4H8N4L2@>NFNMQX`XReZmcq^w`|hwjkrknslqyrhunrqrtweryfwgpecg]XVUNTGR>J>T8P.P$E$E1I7L3M1I5J:K5K7I?M%D)>,E3I6F;LKPSXYV_^gYlgodqmyn|ryl}ps}lzn~uv|o}owwruzq|u{j{uwlohgfec_fXZOTHU=N7M?w?k<^;]=]=`>\6^:_;Y7]JFLQVVPXSb[g[lfqkq`pemaj\k_j_j\cUp]sei[m`qdvjsbuixhu\hjVL=St=^;W9U>X9X=Vf=d;h;d;c[A]=^;_G`Ae`H^@dDi@l!DkF_Cc A]BX>T?P?U:a OeI}1ULucou~}ҁzЂ|}wu{rpnpi{zp~{΅͈чwӏz،|בԒӍvՓՋ|ՎwԐ}ґ~Ԑ~ҕؐyՏ{H>OBQ;MHOAN@LEOGSESFYBOESCLCPFOBKBODNCJJU=KEPCLMWLWISOVQSPYLTMSQUQVLVOZUZMURZX\S]XdWaT[SVHTHSOdRSxhk]QBI}=&C*A0D2FBMKUU^WUb^gakgp`sjscwlzhxg|syl{my~s|ms|{vvzp~t|uynutodlo_\b`[^LXGOYY @W9U>[AS=Y8]=aF[?_?bCb:h>n$Li"Ig@c>d@g=iDjCjEi FfBc=bF\BX8`GfDe=c"Lj>gHc!Fa@Y>[B[@\@c?hChCj#Fm!Ae;`@\;X:Q 7J 5P=YB`Ft+QDhY~iwuz{y}}v}xxv|zzq}mmqvst̀wυъ~Ӌ~Ҋyӈ~Ռ֔֒wґxҎՎvӎyԌ|ӏ}Ԏ֐u׎{ю@O@ON9M:C>R@M>L7G9K7J;M>J4N9LETKRLO\[cWm`j]rdwazfqhmhrnuonpmsowjx~yr~e}iubjbh[b\WSRPFSCO9P1K+I'G*J1L0H.H8K=S/D2D4G?N>KNBPFSAL=J>JDNASHWCOCUFPGTI[CPK\DVGSESERBXH_CML_L`LRN[PTIUNSIPIRRULOKQMRQWHRQTPTV^OPLSJRGRDYHVNeVY~ƓZQN>KJO>H`@i@k!@jEh#Fk)JeAl>d:i=i#KgCdg>d H\>X@Y?`EeGfCfaAXAU>U>N ;L :]Fk JDjOogzwz{Ё||}||wv|oxhnnptwutvцҋ{ӍԎ|Ց׊؎zՑ~֏Ս~ԌԐԒՌՋՎxՇz؍x5F5FGSI7H;R>L@SFR@K9KBOR@RGISU^\d^nbl_taxd~flmmsmvvjqxppwlq|pws|eoq^m[e[^\TVPSMV;M;P.J3O'I'C2H6P0I7M7K5J5J7JES?L>M=LzB#A*H8OAPN]SUa__cjde_rivjzs{mvgvhzmylzi|oyo|qyqxzi~w{r~vywoknma`^`\aNNOeEQ4K$Ew AlCc?_7\<[ b ?fGi7jFj Fi;hEhi#BdBcBfC[;WCZ?aFeGgCl#DeCd8hEc?a@a;\DU?QN8N;O9I:I@H;NM?GCWDO>NCOGTMWES@PFTIQAWITM^FVEPN]OZLVKQLSCLNVHQOYSTJQOVKRT_SURXSYPSOUIRKPETP\@TG^\X棅͙uoiWa;TBSESPXHYKWGV?JCUHUFQGOQYNVKXGVMSQZOSPUQTNSMPIPLTZZWVJST^ah`cRWRZTbcg__ZW\[^qehaikkkofmglnmoekdfeckeonttig`mi\cehxk]hk`]lhwknjnvvlouxyyik\^\p]hhza]`fO^I[H`K^_pz֞۬ߤঅ٧߫߶ݮਔ䯈ᶩଭ㩋ⴢⲙܱݟܯ߰۵ܯ٫જἓݺ۫ݠڢќԞլհ޲ⷚ⿰⿶澬´޼ݹ⸭Ứῷں׹۱ᱚᾱ¼Ŷ߿ǽƾʸƶῷ´ǼþIJŴŽƹýıȺ߼ۿֶַȾĻǹȸ̷͹Ÿȴ˽ƼͻϾƪ8Pp:zH#@*F3G?JKWNL\_`fc^farish}w|fwhxiypvkzjp~tzq߀q|xvjyg~uym~vuzpvmkifd]]adUXFRc>_<] 4a>]7Z ;^6[ 1W5Z 6S.[ 7]\ 8^=_dK|3[HiYulyxzz҆}yxwwsxlpqvqzp}vwyɆш~ԑԍՎyԐwӏxӎՏӎӌ|ъ~֎~ԍ{ҋӉuӌ}ՇՉyՎy9N9NCRHU:U7F;JN8I@S=JKEN=LHSMU=PBUAUHY?LEQBT;N?LFUI^KVFX\lScQ]FOMYIQJUGNEVOTIRNQJTNUOUU]QVKPLQMQQVIZJUEXDVe]ˑk_MV@SAQAVMTMZGS@QHTIQITKTLRKVT^LXDSNXTYOYP[TXKQERIVJULS>SQZ^\[fRVO^S`b_^^]^VVZhifeYW[babghfmj`bbeciengrzptkmpihgjpyqaqlc^^eV`tynrlhlltorw][^ZRWN\n|cdafZdVgN]L^VjoȆՊݍߛܮۡެ۰䰘۹ݧ➋宋ෲۤޥॎⲠڱݰܱܱ۵ٶثߢܩڔӏՙթӨ୘߽߳ಬ㸞Ắา弬ܻ޹⵫⺣üܿۼڳ⸡½³京IJȺƽú῵ÿ߼ijݿ⾱ȰȿŹາἭټƼ¿޿űĶýķŽĵ̾Ĺï÷̹ǻ˽ݼ޼ӿLZg=o:#>*F>M:IJUMQ\`b_jclencumzs{kygwiyk{kwg}u}i|oyq{m{mzwymyo}u}wqphjlp\ZccVc@S?N9K)IpAk>f>\ 9V9];\:_=^;Z7_:[>W 7S*Q 9Q .R 6O 3O8\Bx1J\oDZ׼Ҿ̼ɱIJ⺡޸ڽТQb&F_BX>YAUDSCXEV@X <[!Ge,SZ HZ=^DbBi$Ji KnAgEk>gGj@a=gBiHhAi Bi%Pl+Oj+Oa";aE_@]@e#KfDc@c#GaC[=`>\?Y?]BcAeBh@j"Fg?bE`<_CZ<\=Y@[AbNj"Lz2aA]Z|jznx̀΀~~y{x{}x{wwrzoupuzyuІ|́։|ԍ׎Ԓ|Ӎӑԍ|ԇzҎԎ{ӊ}ԊЌ~ӏъtӈ~ҋv։׋w>N>NDS5I6D>M7H9F;R9F5K8J4E6GN3A6J1E3A5D2E0E4F9LAJINSY^U]Tk_pcxd|gwexolpyrsoxsnlortk|m~_uevjnaia^]X\^[PXFT8M/J1J)J*L0I0H/J-C0A5GUKTވr˜ƉkWTAR9N?THWEQCTJWFPGTAQJR?NHUGPN[V[QXMWSZRYNUHOJUN[MPCUDYO^[[XbMRL`agbeVXX`_g_almhea_`nknlrlsllajgrghwhtruvuzsluyndkff^_icrnvrrutpjheqrrjedLUCWMcclbcXZRcRfVdM^[r{Гաݓ׆ي{ঙݸ޵㸡߲⸙ܰᝅᝌஇצמݠ޴⺱۲තݵ޾߼٦ӑӆԐҜܘݲݸܮⲓ෮ܸᴯᷟ໮Ẵ⼭῰½ݹᳯ佤¼úݻڷඪ±Ᾱ¶޺㸮ðŸļƸĿؿ໱Ⱥƽܿ⼰࿯߼۸ٽ۾ڿŬƻ߽ὪǶǿɻɿ˼ƾ˻ͿݿŻͷݼѾz&Ev?} ?-H3F7KJ[VT\[a_i_k`shutulxoye{lxipyf}ozmwlpzlzj|equmyl{u|qxljgf`][Z^SYHQ?L3M,Ir;qBb<`=ZC]8a8aE[6\8Y:V 6U5R 3O 6K 4J 8M>VDm)Hk˾ɷ߿βкʰའگٲջ̽Ϻлк̴ٽ۽Ǽv"EW;UBQBO?Q?SAV>T=Yb?aAcA`!CeGbA\>bBiDe>cFeF`?[J9F:J@S3CAQ5K6F8J6F;G3C@S;E7H2E8J9H3D9MDPIKOPUT`Xngrnq\|poesmqwssrtqu{lq{oupmxa{ft[l]gZ^RWTRPJT@SAU5M&@#G&E,G-E/I.E6I7I8M2J9O6K>L7M>MBN5HCZ9H9L:IBMBWAM@M=RDV?OALF\IWJW>P;JCTEN@OAMEQHSKQELLYQQKPNTQUUVOXLSOZKOR]OQJQGJBSJ_>S]]바Ӣj]SPIY9KAPFVI[BTFR_=\;U5X 7X>R7S 3VGG9G@R=m0NuøϿϼպϵƳ纝ް֬ӸɿɻοնխϢʯ8KI :H @N =N@TBR?YHT?WBZ@^MX;_Ef Ee@j&Il*Ki%HgDf!Cd Ac Io#Ka=d=gE]Bb@fJ^=e%M`Gf DgBiChFi#G^>^D_>\AbB\Eg#Kh=p-Sh&HeA\7X:T :P :O;XB^?j&O@`Qtbyryzр}|~yxwyxzr{nvuuzz͂ч~чҎґ~њՍՋxՍ}ՋzՎ~ӏ|Ӎ{ԏԍyԋ~҉҉{щzՊ}҈|ӉwԌ5L5L:K:J8J5I=L?S:I9MT>L0H#B~$A#A*I.G,F1I1G5F8N;K3I8G4F8K>NMGTKXPVITERGQCOJWDQHYGOO^GYIPLSJRLTIQNOPVHNFO@O>R@[ASp`ϭїetaXWLXBU[@[ 7^?Z 9Y[AaBh@g@gAf@d?fE_>^Dg,Ki*Pq8\eAa?[@]=bB`?c?fI_N5K@O=O;H8I3I5F4A3I;G8J:I8E6I3I0?0C;O-@1DEOHNLQ_XaXe`n`wf{f}gmnlrqixpmwmtvjsvprk|ezeraqbhV`_UVQULS>P0D+J&D#B+E(G0I5J5P1H4J4J>P3F5I=G@S8O>O5JARAN>JAT>IANDQ?LAP;L?N@NFV?MGO>KFRAKIREOCUGUDPGZFOIUKSGRLXHLMXMYPTHPJNJPIKBLAS@VFYMWߎqׯʊr|jv[XXIUIY:NDUFU?M>NHTIQFQDRQSKWIVIVQVQQSRO`LUQSM\NYRRWaRVN\OTafc^UWJ[^h\\a^^`[a``ikiehf\abehiӁ|jbnrjqWdolqoie`^\cR[ajsroqofmgnokjnjaaOXK\R`]`][LW?P?UIZLhbuz{ΖڕՋ؍ڙާݩެڨܝ㭚侵߬ܜݝ֤ܣة֠՝וסڬصީݦ֖Ԛ؟ܮ۷൪த㮗޸گۦঔഏ޴޳߶߿߻޹߳ݹඤ带ܻڴۮ幢Ʒήݸ۶ܷඳᾮ߽޿ٽ޽㾪÷ῷٴٰԲ׹ػݿİɿȽǵǺྴȴþܿöƻȿȺŻʷο̼3Ks="?+G2K;LMZ[XXXa\jno^rusbxkxixj}o|np|l~k}oym{p~t|o~o{p|~u{wrkmehha]VZPVENFS/F|!Bt?h9^<\=W8[9XN7G 7KHZIZy·ʹԻɯìݵ֧ѱǼܹɯVEJFK@LBRDQ@XDVAYAW@[C^CbCi"Ij%Kd>j@f>_?fCcAj#Jh@l$He FcAe!Jh!K_@`EaBc>`;d@dDe#FaDYiFcBcG`Da;VET ;S9U@[Dv)OW;I>MJ?NCL@K;PBJ;K@M?M>H5LAP;OERCQDPDMGXM]HWIVMYJYKSIPGSFSGSGNHTT[GJNZLUVSJODQFQD^IZ[Z춚ԡrgmh\UJXET@T8K.G5ICNEOPQ`Yfea\p]xzucyiyr~q{mxh{jq}q|hyfzryequ{ryixp{kwonihb^bWSKUAMJEMEM=QFS ;V@^HYDW=a>g"DdEf$Go"Ff!>a=gBd?cAk$HgFd@d"Fc>\CbC^@`=bCc Ba@nAb=a=\:Y=a"N\O>L7C8N+E1C8MAHNXSQ[Vg^fZpfrhx_hpokvqfulyovppksnvkl~duaoap_d^USUVORHNMK@HANBJ?JCMAQBMCQR=QDUJVJWJXAVGVJSNXN[NWERGSS\TYPULVLPXYKXISR^a\[_JRQkXa_`YXQ[N^kwgq[\Ze\`gnhnc`kd``eg[`s~rek`VXMZI`Zpjplgjiibdftpig`]Z\W]lsrk^_SXJ[M_NVIZRdqz̑ۚמݐؘٛןᡕᵠ⯧ܗڐږࢃٮۤؠԛܔ՝؟ګڷ׫Ո}рюї֚ݳ޲ݯ᳙ᱝް٥ץߨݷܳدڦޱ޸ິ⻧໭۴ݶۼݺວ㻭ݽصڰ崟޾ܼزܳۺݸ۸ܸݶخզ׵ؽܾľûýͼɽ߿彲ĬȻƽƹݽᾧıƼǶȿʵȽ˹ȼĽĻöƴǼźȷͿͼEU~> ?8N9HLOSPYTaWg]unrlyrynxk߂r{hxgzbx~fvl|mhyj}j}p}noyquftnj_a`YUMSEK=N3D#Ap;^8Y@S 4W]>`BgEiDd?fCfCk BfBj?hGbDcB`B^>[=]B]:eEc?d?eDdE_AR;ZG^@^=dAh!Ca?cAe=o#IeG]AXAYLM?K9Q8H8GI?L=KOALDNAP=O>P=PIT=PAMEXN[FOJVBQITFQHPIPJOGRRVOVSXKQKRKMQZGTNIUASATJVKQSZLQOVEOATLTXZU\R]NSIHO_V^SVWZOOQYX_YhYT[fOZNd]`nnca[X_bbjjehd_WVXV\Vdjiii]aQSBZVgnwnhpenhnscglkiaa`]hXe^_jeYXQ\I\NYL[CYZovց}ߐڒٟןޝݧঔ߫謐⭚ܚ؍~؍Տٌ}اמ٣ѥ٩ةخٝۊ~ҋ͜գڠڡ੆ުگڡ઎߳ۮٰ۰ݰݵݸײڭ೛ݽ߰ݸޱܵΏܺ߳޷ຯݽ۹۫㯞ڹڱޱ۹ڰ٪جְظپྺ¸Ĺ¼ýùıʺ´ڽ߹ʷȸƽܿ۷ΎŶŽȺûǷŸǻƽû·ŷǻo2K(E*A4DIVPO]\aXibqt׃kق|zno|i~lp~ir}f{ono~j}q}n|q~t}szsthood_]^WSIVJQAJ7K%Ck7c>Y9SHBVBMpƸǸϼչεῧԝ͍ʣͼ˸UMHGKDNDN;R=S>Y?Y;[B^=aCaBa?c@h!NiCgBgClAf7i<\=_>\<\>_>`;f D`=cDa>a8^BXAY=WB]P0D8N9M8K6C=QCJGOVS\Z\[cVjVvlyg}fhrutm|rwosxslstwhnlfziwdm`aWcYYSRUBG6I5E,C)I"@%C'D$B(C0D0F/E8J;GW>[>aJY?`>a@eHa@c?gDl#At.La<_7bAcY=b>eAjRAK=J:HHY>R=JAJE7F0B:HAGLKRTTScWiXn\xgsYhdlsonzklolujnpnukng|gqjl]b\bYSOGNBJ9I6F3G$C(C,B%D-@(E'?)B/G5G8J=NFL?O7J:HAILCKFNFR?QDQDNALAL@K@GCP@LEP=JEJGSKQIQLVFPAKIOHPDLONOQPVIMPWPQINZlHVEQ?YCWhaҞʍg{ah\QSDRCMIWAR?N?UHZISFPIUPXEOFUNXKRLTXX\eTXJRLZJRSOJ\SdTW``RYF\Mb\jfmhlYg^dkmf^ghfaTZMWVfbghb_YS\?XSc]egjjhgjc_lti``Zbi`^]bdk`X[UNKGSOXTZBWFYl|΁ْ٘؉؎חۥ᫒ݱޗܣޛݙי܍֕}ԐՄڊ{՗ґڞ޳ܺՐՑԣԱޫ٪ܫۥٜړ۝tجٮޤݰ޵޺ܸگߦܴ޺޵ޯⳢ߷ܵ׭य़庢۸޸༮๪๫۶ثߣڱժӮֲܳྻ缫÷߿忲㿯޻ὮúŸĹŻྯߺᾱö¹۽޸ṙķ۽ݽݼǸƷǿý·ɿƿĹ=Q%D6J>GOJ[W^Yb\h`pnlgx~{lq}rgjo~lju|u}l}tukxorkwpkiig\WY\OR7G8G%=p9e 5Z6L=I 5E 5J7H =JCNHk4TpǹнҷʭժŃ}ćϱͿտͿćL[JFMINGK`E`@e#O_=f#Ek(LfAeBjEgH_>_=d"HdAb?\:^Ad=i"HfBd>^BXYA_B`CbCiGf>`Bf!Ac GaC\C\EZAb!Mn!Q})SNpawqzx}Ђ~~ux|uqxqorv{uьшӌԈ}ֆӌ؏ՊyՈԋ{ԊԎԌԎwӏzщԇwч}Ԍ҅yԌ҇uҊҌ|ԋzԉ}Ջ~цw9P9P?R5F?M@PBS?M;E7J9M=J9E9M>R=J?RR>H?LCLKO?L;EFR?J=MCOHTAMDU?NDOCPCLGVDMCNJQNVEODJLTLONVPTRYQVY`ZbGOBRA^JT~jծϏŋr~ek_SVCVb¹¹շȹݺҝÇȰĹονͼͼ˸߼Ƚ_iJHIDLCVDR>ZFXi Jf@g#Gc@b>eGa7d@];`[=b=eMiElBi EhHfDcN^G_!H\CiH{'VJ7D>P;O=JN:M8D9H7M2D*@8H8J@IHQOWW[]Skfp_xlyd~gfgxopponiu|zkwspnmlc{hzhkbbVeXVQNOFM8F/G'B2F0G*E2J3G.J,H*A7M5J>Q;N@P?N>REOGVBO=ILSCMCTDHAJAP@KHR;G@NBL@KBNBJDK>J?MFLENELEQJPJTHVJPILLXKQJOQVQTU\[`T`SZFNHTDXNUtצʗvs[_TOR

N9P;NJYHSK\LVCTHSHUIODKLQU]NUCNSQ\bJQ8HFXUb__S^EJJ]Zkhja]]bXceabonqacXaU][mgkmlXZNYGYXq]iccamggdbkrh[_Z^`X^\hhof^^[QSHQSUX^Q[FRF`gtʅՓݔܞݓ~ڨ٠ܞܢ߫ۥݐ֛֊ٓ؉ݑԑҕגѠب߫ڒ~Ӕӕמߧگ⥢䮏۴ݥ١ܞמ֚՚۞䭋⾱޺ଧܴ๮ڷֱ۟ާܬٰڲ۪߰޸ܳ٬ਝ㸎¼ַް۫ٚӧ׭ܹ߿¹ݻ㳨伣⿸ߺ㼰࿨߿ݺ߲๤ắີ弱Ÿûݾݺ`»ܾ߿ɾſúǸʽξȾǸ̸ŶƼθOZ,D6DPTUP^Yi_jenctnvut~ovdllp~iv~g}f|pzp{mvnhckfa[]YNSKNDO=J} :h7]aA\;ad;e:e@d=\HBU;ECI>M?N3F2B8I=FHSKLHTWW[WlZmZwiv^~ghmpwvvrsorzxnppquviewbtnocdVcb]VRVKO=D1H.E(@/D.E*B'C0E0G,F6H0D;O9MAPLAOAO?HHQGRCIIO>IEQBIAJ>IDOHIJLBLCPCODKAKENKRIUNXSXPZRTPQJPRQR[QVQY[lMVH]G]SV뜂ҡˌ|ram`cTMM:L:J7LAN?LLYIUBQFVHRIVBROXQXXWMUUXNP?J6GAPRTcdLSHSLY]fca``]a^j`bdegcfaWdT[_iUYZYRWN\VhYjaigmhfounjg^ahUUTTQZ[Ymdmh\WT\PZPVXXKQHVJ_p{~ۅٕٗݙ۞ចگܠ۠ܕە׎؈Ֆي،~Ԑ׎آ٩߫؝ӌѐҟؠٯܜݞ࢒ݧۢݭخ٨՝؞ןة٫ࣖ泒ήڶۮษ༬޸ڲԣާۯߦݯجݲ߻ܺկߝଉ۰՟ՙӧڸ޼俴³߸䶩习᾵ཷᶭ⻬ݾڴܰ߭߳ẬŶ¼±߽ླ»¸øżŸ¹ƾÿƺ̿˼ʾȵĺľĿÿǽָu2G5AFOVS]Xecpfunulzkymri{k~ipul~ll}lgjjwj{ksarkkdbdVSKNHKBEIVw8\5P3G 7? 3F@GEg/N_ֺͶóשΊx˧ҿǼտѾн̺˺̿;̾ιȴ˸ıöRFMGNFOBSl#Be$Hc$E`:a>_>_;\8b=e9a?]>]=U 7Z 7[A`FdBg?dCdeBa?] F`GZCXCcDjNz(TFjUqry~Ёцԁ{|~sszuuyv{uy|{χч֊Ջ׍}Շ|نuׇ~Չu֌wՉ{Ԋ}։vՊzӍևyׇz֋}ԋъ҇zхyՉy҆}҈tЊ·xԋv׉{׉s@P@P7IL?M>M?KALI@KJAMDK@NDQGN@KBL?JHPHRBKAIAIBICLCLJTFJINFOJRMPHQIOQ\ITFHLPQUINMPOYHUKWAYDW_XПņrf݋{`\EP7K7O?KNNNWU[Ta_j\qhzm|imjok~kk}mi}h}n~kdl߆~xjufnZwxha\YRVRP9A4F)MEq9YwջůෞԟŇĠؿԿѾϼ̾˽ʼ˾˽Dz˺ĻŹƽʿƷ}QCGCJ?NCP?Y?YEZDXE_D^=d?_@_:`?dDdBe<\=`<`;`=c=b:`>d@\6^AX^=`;c@e@e@dD_B^EYB\CWC]=q!R<_Uqj~y҂ӊւԁ}с~yyyxxyx}z|uЀψԉvَ،}׊}։{؇x؇{ׅ}׈|Ӈ|ӂzԌ~чՋ|ՋzԈyԆyՋxӅ|ԇ҆|ԇwԏsы҉t҉|Ջ׋y֍~PCN@O?K=I@W>ODQ;IAKM2F/G-E'@0E/L/K"@.G6I8K;II=NAT@N@RBKPJPKTSY6I3KH\RUMSZcX]Yc^aRYY^Xd^]c_]eTYNTZg`e`e[_JWQcNj[tbb^f[ea[eimila]]X]S_[hhgibmdb`[lQW]cLVDUH^^r|{Պކw׊ۇߝޥݙݣ֛ޙטٍ֑ցՀЃڌ؟שަٜ܄ևҕݞٮߨ㩏ݫ᧓ۧܜܟߤ٠ؙݢݵݵ߮୘ٰܽڞ⦍޸ճԧأݹݹگٮ۷޸٪ۣڪ۬૟ީםϟҩ۷޶߲ܲὠ⿶㽹޽⾸Ỳ⾲ྐྵᳵⰨ⸠࿰⾵ῲݽܻײ٭㷣ø߽߻Ⱦ࿷ɺƲڵ׸׼¿ý¼ĽɽǾȹɼǽȽɿUeKRWU\Xa[dXsgvj|jyi|blr{eflj|eflkzj}lua{pr^jcfa[WOLJN:@/D 8g8X:L=L@c*LQs̾οջϳɰܷΚǖʬƿҾϿѿѼоҾѿ̽Ƚȸ±ຩ̽ŹļƳȼѾŵODKGKDPATAY?W@Z=]I`G]Ch'OcfB]B]>YBW>SA^Ki@1XJkc|t~}Ѕրzw}}x}w}qyz}~~͆}ӌ|҈ӎىzՍ׉׋{׍zՌ؉|Շ~Ҋԋ|Չ҈{ՊҎωyԅxӍԊЉ~Ѓ}ՅsՆvӇևz҈Ռy֋{׈yMJbNAM?NDU=GCQ?I?K9N5HBK@IKPWVYO`W]Sn^t_vb`ocvpoqmvjs~qqnknkeqo|ksYqamb^Z[YPTMNDN;Q6N'@-B.C-H2I2F4D,E3E9N5J8IM?M@SBQ=JFOEPANJYAMAJ?LBK=IAO>JBFHSAKEPISEPKWHUCNLSLKJTIOHQKQMUMSORKTNWYWLRGVAP:O>N|eҠЍƝr듃ix\kUMWDT8K>MBNJULUFSFQC[OXEMIRISMX>N/I@YKVVXKQO\S]PSSYYeWa_g`]\_\^X^Q`\gem[^U[ScFZXj`h`g`_\f^jdqidcgfo_i\fmydfcagaik]WdmQNJUMV@QO^og؏ݗܓމۊڑߔ⡅ڣޓה؊؎zҙۋҊ|Έԅ֙ܩ਋֔~ғٟޢݧᤗ٩ᡣᮏڦ៌գזٔڛةڠ߱Ḭޭܨ䮝۶إٛߢݵյסߦಚۭܶݦ۶ٷجٝךԐ׋~٤ٵڷลߺ߶ٳ߭Ṥ㾺⿱߾߾½ྸ۰ܭ㴣⾷`佬ۻٶ߯㵗¸·ö»Ƽ߽ܼἮݿứŸƻඣܸܵپ׹ط»ƺɾ˺Ʒ¹±ǻɾоhlZZRX_Sg\ravfweyfze~of}gsliiogqkv\zkp[pbi_hcQQKOBIBN:P+B`=V;`#J|Acw¾ҿ˹ªڰСƕɢйľнѾοо̷̹̽ϻʵʷڵؼºŷijŵǹŶwMAJCJ@LAX ?]GbG[G\AaEd Le Fa?f#La 8_9\9_;X7\@Z 6Z :]6e?aCc?Z9^F\D`G\Aa;_?nLa?h:f@eD_6Z;Q 7P;T?\E^Iz#R;_Tpmx|σҊ҃҃zy}{p}x}ʀx̓Јԇ~Ԍy،؈|ׇ؉ֈv׎{Ո}ӆyֆ}Ջx֋{Ԉ~Ї~Ӌ|Љ|ӊuӆ}։|Պyчw҈}ӇՊwՇyцЊՉՋzևv>M>M@I=L=K=I@JALEPH?IDOMOOPSP[TkZocp\yd~ghjwqg|wwku{sltdqgkj_ds]s_k_^SW[QSGKDS1E3G-E1F(C(C,D,C5M5H5E8M7M@RCP>JIR=MFP>O;JAJBRCO;LKXAIFQ@M>HGRDMCM@J>KFDK >J@VDXA\C]B[D] Ke#KiGj,Ll$He@f=a?[;_>^5cA_8`9]5]8[:Z 6Y;_E`@_8i@gBc8e>a:cdOdI-QKhi}wҁтԀфyvt|xyvxv|zv΄Ѕ|Ў֋}׋|؎y׏ԋyՉՊx֋ևxֈy֊wԋvԊՋz҆Շ~ч|ӌ~щ|Ӌ~Ӊxψ҄yЈ|ׅxՁЅ~ӇyԎֆyՄx=M=M=SDN=OCM=LAKCRCQIN;LAHMTAPHQ_9U6P 7I 6H8R >\Bv-T=`]ru~Ӏц{|w~wyzu|vy~vՃ}ьԌ~֋ڎxؑ׎؉|׉}։yׅ֍Ԉ}Ոtԉ|ш|ҊuӇҍюӈ{я҇uӄ~Іyч~Ӆyx~u΁φyԆwЋԅx=K=KGT@OBHCOAMF=L?G:K=FEKIKNU]Wc`aSsbr_ylehfsz~qmol됅l|htvmrjn_xb}nwinWgcWXKMHJ@M2E2E,C(C+D0G)A3G.E;M:H@RBN:H:J@V@OBKFR?Q=H=IKQDK?NFP=JEOJPBNQYEIENEK@ICJCKEKFNLXLVGQJOFPQPJSHTNTPOOUKTSVQVQWDREVBV<[XNĠӬ_ujYS^ZAPIY6HAO?M;IAOAREPANIZDP>M:OI[LTNVR]\aVWOWMMV^ZYPTOORTPV[c_YZWRcFUCUO]\dX_Y`^^VhUf[dd^fehoakeggc]a^d`bY_dg`QXXKY7K8PSicoτۈ{؎ԉvs~ut᠊ߧۙֆqlutxrԄzΈ҇֗ץޮޝ}ԇzv~φא֛ݜۣޘ⤃޴ݫޞܣݛ۝ިܰذߨدݖإۣܢ߬ᴣٴܩܦިٲثӣޙެصӫ؞ܤئΉ͐Җۡ㲙ܻڱݱ޶ڳ۬ۦ৘૎ߴ߹ථ㹟⺨޺޸⼶޾߿άݻܹᷧຩߺܷ߻޿ܸ۱⹨ļƺĶܿ۵ܩњ̓˘̞׶ۿúϹܻܽྰǻƹ޿ķýƷļμЊi]dOp`u]z`ubzgy]}a|eyee~bl|by\yiygxco]q[fZXOOXEK:Q8WAZa{̽ϻǬġ۷ңѪϢʢҷƽо˼ɵȵ͸̼ɺżŸǵº÷ĵųĺ˽߽ĭgiG@MIK=OGXIZIY?ZD]BaAdDeDk"DeEc=a<\?bAhb>c8c8`;a<[9[ 8Y>eD[?cCm$Eg>f=k>m&B`U>p%T8^Qolxv{}ւӁ}}~zxywwyzzσԇ}Ռ؈֏}؏ڍy֎؊ՇyՊՉ؇vֆuԋzԈԆyԋ{ӈӇx҉҉zфz҆zՈ|ҍyыyԊӂsʅ}Ї{Ή{ЇxӅzՎ|BQBQHQ?IBJAN7KELAJ@K?KBK@JBM>HAIE>S:AFO8C3B7G?HFNFKKP[Zc\fVlUr`xlj~eutj~lxrywvqpzwtnꐀveezjq_l[]XUVSOJR;N6F2F-H*E+B0G/C-C4F7D8EBNBQ>I:HHQDNGOFSBL?JBKFNHMETKO?LENDVBNLSFFHUCO=FCMDJFSBLJNMRKTPTMSIRKSLNLSTUVUNVPNSZJPIOHR=U?Vc\ƙӐǔryWy_ePVSOSLZEO9K;MAOBP>OAMHRAO=NYCWA\>[D]D`CdDdCg=o/P\Hc:]>d_9_;^9c@\=bE^?a?dJd GfHhCmCiBhDi"Ef^E}0XFjh~uy}xӃ||qyuzv|xw|҄|Չ׎։׋|׉׊|׌Ոx׊ԇՆxֆpӈԄxԃzӊӋv҄}ԉzԃzԃr׃|ՈֈwԇӇuֈx҅{хw҈|΅ՄsӁԇrCNCN@NAGBLBLCNBKBIAOBNAKFPHRBGCQ>MAG@LJK0D4E8J?Q>K@J=LBM:ICQ@KENDSDPEL?LDREOHOANJOGOLQ@MCL?JALBJ@JENEKEMTXFKJJHNNRJLSVMRHIVVLLTROWDPESCXAPvlʰʑnjęqt\nWSFUVOSBRBJ:L;IBL;LCQINKQ?PDQNWIOIXKZOSJRMOK]OZTSQOCF;KMW\_o\SRJU>PIV`p`__aZhSaPa^ia`_bXaRYcghb`[Y^Q^QZ^ldcja]_L\H^>SRi_mqrӁwzۉsݎهؖ|ؐ{skte֊w҇Ճsqvẁ~юڨܣ}x|ӎآᘏݪښښזݔۙܕޠܪح٧اާٳ߲صעՙיۚݞڨٟݣ۶ح٥ٛݣ٬ڦڪ؜ݝӑɀЕآ׫ݥڧۢݠߩܸ߳۴ګٲֱ֧ء೚޷޳ܵ൪ἣ߼ܻ߽޹޳ୣ᾵ùݼݻ༫⿩ۺ࿮ú޿ݻҡǃ͚̊֫޻ܻḬ߿õۿºúȷƽھºļøŻ¼ڽعܿڿƼļȽ֯|roWtYw`}^lc}dy]{b{p|dyaw\}ewanZo[gWg^`ZT_O`]p~ĭҿȱڶҬյڸӧհϿ̾˹ʼɹòóƹȽú¶´ƻǵöǻǼȾۼܼ•?MJDMELCS 9S 8XAYA]=\?^=_=bb@dCc@`8fAg=g;hBf>\6U 8O2F7M;V@oI@f[yj{y~Єӆ{҅ҁ{vu~{̄ӂ|Ԉ{ֆ֊Ԍ،{֎Պ}׌ԍՋyӅ{ՉxԊҒӄ{υuьӉy҄ՋzӇ{ԆӇyֆzӃ{уvш{Ӊ}Ո{Ӊ{~ΉЃrωЅ~AQAQAOCI@VCTAMLO>IEMEPAQCOBPDKKXBMEMJY9F:H:FE8F3H*C(@4G/D4M-F4M1H0D7G?T>L>M8JEOALDL?N?O>L?IBK?IGSAI?NHUKTLM?LHPBMBLAM@GAG@NGNNTU]JQLOLSMMNPPONPKJPYPNOPQUK[?R@`GO|ؿʗ˜|rfVRSTPMSWWVEO?PAQ6G9NCQ?LBLHXRVHOONRaQTGOCPFQOYY\FN:I7KFV`kVWSZUaFTD\YaZe\V\j[d\bcq`e\dcj[c`khaS_PZKZS]Y\\\\^TXJWAXD_Pcfĺӄxs҄}yݎy܍ۈyيywwqpqpupҁuӁ|v|ҏԖk|mv΂җܔ⥈ܡᛖښڙߕ۞۞ڗޔߴش߫՟╁ޮതثڛ٥כړآԦؤݠڬذ֢٪ܤ٨ڢח{}҇Ϥթިݯܫݩ٥ۣ٢ܭݶݵ۳ݰگ׮٦ޮݱݰ޺ݲத෢߹Ἤ޹۸۱⹩⿰ĹûܽڼݸིǺܼ߽øݼۡԙ΄ɘФѭӲݰݴۼݺܾ߾ü¸üǺ¼ùĺù÷ûھپڽվټں³ŽʼоϹĻؗqZs]{dehfa}c}^yjsZzezeygq\s_lYd\cc_bgu~սʽٽزǬ޽֮նԶٴӪԸÿѿʹͼͼ̻ʶʹƷóųƿŶ޽ùĹĸĵǹʻٺ̴t$?EAQHSCT?XB^B[D]F[?_?`CdG_E]E_ EdF]Ch@fCb=_>^9[;_ 7Z<\:^?f-E0M*C1@5M9F4H1GKHVBLEOCMCO@IHOCNANAOKNEN>INAQIUWZ[VT[WZRaX^[aX_VaRYTl\]\^aaff_b`aohb\[PZS\Wi]eZWW^SYLVGZL]Tpn|umـxڍ؃Նׄw؄܋x؏ڃzytrnmq}qo~rӐ՘Ҋ{uvchkw΄}ԑݖ۟ᙙ᠇أݕ۞ۗ㞍ܤܝۢנࢍఔ֪֣Ԕߕݨߩզ֞ܖזښ٬֪؟ޡߴۯبؠךՕ}|ˈӋۨ޵޴౫۬٫ޣ֡ݡۢݱݷ޶ݳٰۨڭ۬㬕߸޹ݵܯୣᲗ߹޸۱ۭڴ⻳ú¸⿶ݽµô⸪ש́v͕֩ٳںշֳضٴݺܽݻøĿ޿߼ûſ⿴ý¸ۿٿۿڼ׽طܾܺþŹɼɽ͵ζٲ{io\wc`c}iy[ve|asZy`|ov\}ixip`kaeempʄ˪ҹȹͱȱῧ߬ױֹعץұּоѿ;ζ̼̺ʷʺɼĶƾɷ·ñݾøŸŹῳźǾܺƦeLICOFTAVIV@]>^H]DZc Fa@d>c=_9b8cY7]@aAd=f>e:h>dDd"?dA`@S7F2K qJ@eWmk|̀}}ЇՀ}~}ˁx~t|~τ|ԍ؏׌{ڏ֊{Ԉ}Ս|ՍՎvՇ|Յ׈y׊؂yӆzՈzՆxцwՆ{ֆx҉xЉxԇwчՀsЅ҉|Ԇ}ՄυzцwчyԅфxwцzHTHTIW?LBL@K>IKPMRHM?GBKAJCOGLCO?IM6BAK@KDKJJSRTNaXniiRwlyb}biifqnsosttznq{lnnsfkmmuah_h_UVSQQOCK8K,B0A&D&@-B1E0C3M9H0EIFK?J?LFJHPEJKOMSCJTWLXMOINPVMOIMFOFV=Q;QHMw٫ϝrf^SlYWT\^TPKUIQDU;MCRCOCTHZLWDOKTPTGMBR9K:LNSKQAO:ICTO[RST[QZS_RTWgWUVXUaQaYdZaX\Xa^\bd`b[][[T[KRQ^aefb`]UVT^L^MYN]Taho{{{{s܏xڕ׋v؇|׃xՄ{}zswreuzmwmwwtנמxupunwv؆wۖ۔♍ݡٛޙݡݟࡋ׬ګԝՑ۔ޝ٦Ӡؖݒٟڨװנݘסޟ٫٩ؚݣܸٲםӍ΁АΝ՝ݣޮ߳۴۩ܫٮܤ٦ݫ٬ܫ޴ܵ۷ׯ୤ޯު᭚޸ܳ۱޳ݭݴܸݵܬߵ཭߼ùż½ིྰ٩͈ȇ˕צٯںܼܶ۴۷ֹػ޾ݼ¶߽ۿ޼öźཻݽ½޾ܿۿ׾׿ٻٹھۼڽڽľȾȳӼĿۓtYyi~_|`gv\dycvZq[݀drgr`ocjhoiӀ֩ؼƼ׿Եȱ俣ݯשճۼڬ֞ӮڿϾͽ̸̾ɺ˻ŹùŹúñ޾õĶĸŴ÷ĺɻɾڿ޸ƹyO@F?JBMCRF[ IYBf Lb%P_=^A`D_AaC^>^Ac>cZBu#M3]Sreur{~уӄՂ~zzzwzwyρwЂ҇|ԇٌxבz֍|Պ}׉|ҍՏ֏uҌ}Ո|ӉՊ~؆vևՉzԋ҉~сzӊ}юьӈՆӆ҂xքyчzуzӃrтzф{քyՅu҃vԆwAQAQJOBMFRBJFOBLFO?J?H@J@NCMCN?JGR>H@XAH@X?N>HBLAGFPIMSLXO`Qj`kSxdwZyh{k|]pzgppkzqrprvzfyvuo}cqs_ma`WZVPQPP?I7G*C.B,C-A0J+D5I6M9I6H;I9H>N=MAI;HBGFLFSDP=JDPCQEHGQFU@J?H@MFJDIJQBN;JGS>DEMFNHJ?GFNEEHTLKGOIRIMSVIRJOGMGLDP@R8P;WQO鳠حɏk}hk`ZWc_fXT[W[OR>SJVJU9M@OKSEREXNYDLAG>TDZGPDN9G5MDNV]VZNTXjQ^X]ZZSYMWIXV__e_`\g[eab]hZ^WXRXKWLYT]_k`YRWWaQTQcHYHVUfhrkkwnۄ||ހjߖِ؂~spzrsv}rzzuyztЄυ΄zvjtdkkvւك݋ܛݡߘݚړܙأߘݧ۟ߥׯؓϝԕ֌۝֛֡Ҕ؍ٝݴڴؚ֯۠ޝܭبޔߣڥҍ͌ϕ٤ڬئ۠ᜎݬ۰ٯܦఠ٫۠ݫڪܥܝޠۮܹݶڰܫܡܩܵ൱ܲڰ߰ݲ޹ڳ޶ºĸļ¼ܽݲۤҙ̓͜Ѥ٧ڱ۳ٱֱݺ߿ڽܿ߼ݼݾݾܼں༥޻߿࿷޾ݼܼڽٿպ۷ٻٷü׼׻ټ¾ŷѸɹ۬sbv[{b{`hgy[yXz`vbx^rapipiz}֘ٸѻ˲ĭܷٮԮپڻؚѥѹμ;˾ɹɷȷʵŸ÷û¸ijĸºĵúŹóɾ̽;ݻǭmkQHJFQFR?R>YA]G\@\@^?^=`@[=Z8]D^ C^c<_:_EY=X9_AiAlI,ZEi^vsx|}}҂ӆ~|{yuzur|~ԃ|Ոօ|ُّyۊԈ}׉{֌yӆ׊sՆ|։wՃuԇw֊rԄӋ{ԅy҅|ӊ}х҇|҉{ύ|ЈwЄyЅ~ӆyԃzՉрtϊ΂yՃwԇ~ՃtՅCXCX@L?NJUFSFPGPESBLCQHZDNDK@NBLIMBT:NDKAN?F?JHOHILRLFTPZUaXnXpWra|ixgg[erkon|ph윀oumyf씄tsc~fxexgk\aWZUXRKM=H6E+?*C2F'B/C/@3J5H5A:PCO9IAL@P8J?MBX;ENEK:HAO?IBL@MKXLNGLFLHLKMJOMKKKNSMMJRHV?O:U>WhVѬ֝_eq^fblbTTW^XWKR@TNZAN@RLXESCOJSGO?J4IDTW^DP5K6JKWOOSRIKNSQZ[]TOKS?QARLWX^_[Y_^i_c^agr]\PWEYIZUg\fV\TYO^T_S\YnHWViv{zmokmg|xԀ{ۄsڌً~pqpnvowvr~zԂՓГ|gjVb]js|ҏԐ܍ړׇނvݒ}ژߕڝڟߤ٫ߡڢڏݚ؟ܒԞя׆׋ם؝֟ٚߢຨืܰۤלܚ٦֗҇ЎҠأݣީܫۢٚۘߡݱ۲ڮޢۨ٦ۨةנԕީݲܱ٩ۥ֛ݘަݱݷ۸۸ܶ޷ܹܴ༰ú¬Ự٭ґ΋ΣӴشױٵٵٵ׷ٯܳ۹߻ںݻݽ޿޸ۼۻܼڼغ۳ཷ۽ڼݽ۽۽޾۽ۿٺּؿԵװغؾؽԼ׺ؿžƽ̹˼๯gyd}d|`~cy`vYy\u^o[i\njsj܅٭ۺžӶ˲Ư޹٩סعñ޲اѳǼϽͼϼ̺ʼʺǻǹǷ´Ĵø³ܾƷźŵŻķùķŹȼͻϿ;ؼ޸SWHBIFQDNbCdC_9b@_]:`<]Af?b:i?_9hG`;cD_AdBc?uB~.PDaVwkxuzσՂzЃ}}}v||{{~vv|}~׋և}ٌՋ֌{؋׋~׍؋|ԅ֎ҊӌӈՈ{։yԋ~ӈ~ӆẍ́yӉ~ӈvՉz҆΃~҅yЊЏ|ӇvІ}ӄrЇ~τ{|vӆvӅzχrт|?Q?QGRCMHEJANGNFM9KFVAMHNBLG[@M:N;J>HFM8E@FIOJIHHRPZYeYgXnawiyi}ti`fyiniyopsswsvsqwigb}kyeo]d\_YVUKPAL?L.A'@/B*A-C(A1D6I9I;ICO8K:M=IP=ZBQtaҪԗȊރfxay`r`]T_Z_[SRISJWIQEWLWDQDSMVGN?R;ICSERDR]?cE_;f Ab?b@gD\8Ya;e>i@f@e@hCaAdHhBiKn@'R4]OhczrwҀԇ{|}{x||z~wuzv}{ӇׄvՊ֎؋~،֍֌Չ؎wԋ׈փ~ֈ}Ӊ؈vӅՌr֊|уxԇ|ֆ}ԊtՆ~ц҆z҆~҈χ~цӆw҇|ӈ}уx·υxӆ~}ӆzGTGTEMGPBMAJ=F;IAN>HBO=JFR?KDPH>GCI?G?IEI?FPLMHSQ\UbRk]r`xkzs}ijncpluesrwpsrmysltkmm~lv_o]f[ZVSMMK>H:F%=-C)=(A(A,CGCLHTCO>IDLBNHRGPDKGRFOIHOJOLUGOHJJLLPDMGOKRDMLUMBTGQKV=P6N7ORXPQNXAV=RRZQWFPAU=YNVXg\\WYScP`Vd[cT\OXM`DUK]_hZ]X[ZcX`SeUbP\M^cwyryuuhցyuqj{jڃnzwysqhzqw{strЁxԋ֎if[lcg̀֊ۉӔډݎyؒڍԄӃ؇ޣڳܣإՐڜҞیԙהؐӎڐםќ׍ْݵװ؟ࢍ۳ޫաՈzy{Ґדݥ۱ݨܦٛەڙڟ٢ҡٖ⛎㮎೪ڨݚܙڥݡۧצס֑ܬܰשآנםڥ߸෭ߴ⹤ೝޭۜऋަڣנӚ˘ңשگٰܲ߳ݵگڭرکԧڬԭ֫ضܸٴմ׸ؾٽڼݽؾױެݶܹ۶۵ֱٯ޻ٺظ¾ؽٹ׹յӪֵ׹ӺѴҲհٺٿɼºءwgrX|Zv`|fxgwi{i~ԚٴߺʽӺЫĬڵݥ֩߭עԬھüпκ̻ʴǶǻŷù޿ĸº῱⾲³ķĹòĻȹźµƼǺƼʺ˿Ϳ̼ܺͱr'SL@KARIQJWGTEZE`!M\DdIaG`?aAcB`C[>^>`8^=[7]:W9V 9] 8Z:cIc=bDd@gDdGe?c Ii$JhCgHo#Ns#M&R,P@c^yl{v}z|}҃}{~zzx|wvyxЀ|ЁӉ։}Ԏև}،֌֏}ב~Չ֋}ׅ{ׅ|։ֈ~ӇzՆ~Յtӌ~֍~ׅx֎֌{Չyҋ~ԃzф}ҁxцӁz̀ыцӄzтzӃyφwЃxx~wCMCMEN>MHS?K@JBL?OAKBI@THT=LAIAMEMFP?K=FCIK5K-A1I/G.E*@,E4E5PNFM?EDIAIBFFODIHLHNPNGPKLIONMHLGOFHHKJVcAdG`;_GFOCCJLONPJ\R]UkWq[v`kpqxllujrszlpqs|xwutd~lvakSg^\PQOIR;K@Q'?-E-A/H1C8L5N;S?TAX5G7MCR?K;KGPDK>JEMJCKCLKXDP=PFYMWKRLVHXMZN_HU>Q?PJ`KRPQLVMWFZY^VYKWLTP]U[giW\MUHXT\MZ[bge]__gch^eZcU`N\L_]oz{zۀr~so|uۃلtxxonnnk`||nuouwjԖՓnsScZpiq~ׂֈ׀ׁ~ل~{׌،܇zؚݛי҇~xٙ~פٜڙْݒӟՕهڔ܌ؕۦܪ֨֍҇|ܲڟڌևЂ}̀ψדܝޟޭأݜؠל١ןמٛܝܧڤءەޙܫةטޒޤ۶ڪק՞֗ڜڭܶگޤ۱ޱضۛؑәӃɈМӨդإۤ۫޲ݵ޴ݭӐ{Ԧҡ֨Ч׫ԴԳײװضۻۿؼٳصܸ޾ܺܺٸֵ֫٬ٲڴصֵٸگֵغصնԳҷӬѨ֯ԵѴϱе׷ֵ׷ڻòۿۦsoq]qcxh݄ژۼůƮɴé೐ٵֳ۾ᾡ䲗ܥڳ¹ǽ;ϻͻʺǾõȷƹ߿¶ĸó¸ôó¸÷õĻŸżĹƸŹĺĶŶŸµñ޽÷~{TMOGPLNEREXCZH^J^Ab#L]CaC_C`BaBc C^A`>e=\=Z?V ;X 5^C`=_AbE^>f>f IdBd@e!Ce Eg Fs"NqGx*P~(U5ZGeVvkvy|{{|wtwzu|vrxz}͂|Ђ|ӋՋ|Ռ؍ֆ׆v؉؊׍ӆ{ՇӊԑzԋԈwӂ~҉}ԇwԇцxӇ؉wׇ~ֆw҉{Ѓzχ{΅}ωӄzуtҊwԅyӂtЇ΂tx҇{х{тzBPBPHN@LAQ@K?JCJIS?HFT?M?J@M?J@JFKDQAIFLBM;G:DCRAFADMJUQXPc^k\p_u`lkoqlnnlturlxv|vvwwq{c}ix`n\hZ_ZMKDFBK;H2C0H&A.F0?0J9FL?N@ICLANCMDR=LEM@J?LEMAIAN@LGK=K;J>JET=KFQKYBQANIODOHNEPCPGRDHHQNSGMHIBQ?T5I:T>Rd\˖Ӝ͗XvܕojYc\b]d_PSHXMW=MCKJ[@L>QEUISFPE_NWLTJTBREXKYSaDT`=Zc@aC`>`Cn$Kr%Ir#W{(M*U:aRnfzrz~р}{πw{rzz}xz~~̆҉ڊ֌|Ռ}ٍ~؍ׇ}֊~ЈҋԈӈ׊}ӈ҈z҇{Ԉ~Ԉ{ԃ҇҆~Ҋ|ӈӇ{ՇyӁẅ́}Ђy҅΄~ӇvхЇx֍x҄{ЅxυЃzυz҆CQCQINHUCOFNBP>FANDNIQCPJPDPDK@MGIDL?H?H?DDM=H=HAJHIMMQMVQcXi_oYyhxblkgtgqpwklypuvxpu|mrsprs\vhk[XSOMOQDO9D0B(<.I3I(?.B4F4F7GCU9D8C8E9I;M=JCMDNIUISCLAJFPAKBJ?J@IAN@IBK@J7FBIOCVNZ[bOYGSDPIV][aXZWO\N]JTZo\]]iX^aedg]^\`RTE\I^Vfrxmqtqrpz{rsԂ||sׁuwsfieffjnssՍЏkkP_X_lp{xtqxm~yݍيօ؃؄ۄןٞۉtЋ}~ψ̃هzؗזڔؠܙަդښ֕׏ٞݥݩҟ́xtՂy}|Ӌזۦ߬ުޜۜՕݐܡتؠܞڢޟओٟٓݒޠݩןٓߖݩتգؗޘڮڲ׮שۮܴݵ۱޳තܫטӚԞףܤ߰ݯްޯۯ۷ܴӬձϬϣӣ٩ܴܲص۳߹ڿַװܹݾܼٲڹܴ޴ݸܷرحԦԦگٮدڰٰװڳԨ֬նֵԳЭѳѪѥӴֹϳѰԱӭ԰խԸ۾ڿد܏٠ݷϸηδŧේרҠ׶߸߬ڠڴøʿǻɹȵƵƻȴijƷüķŷĶ߽ùĶŽƻźʻŻƸùƻ߿޾ݿĺܽ޸ĚKYI9EAMFRBUGZ@]B_B]?`D`De@\@^J_>_I`F^J@H>H?LFHGCHCIKLJMXL^U`Slcm\u]}h~alliptjwpqvpurj{{z{djlu_sacTZQRSKKGN9G3@/F*A$>+>*?-E3D1F/D9J7EP@J=MGOEL>M@HALIVDFHRAJGLCHHKGOFJINCHDK@P/Q3PBPޓխ֩ǕpqwbvnpkmX`]]TWUQMENQS@N@NKVNWHQRWKRKYBO?RASK\KUEMKVKaSUQ^O[RZP`P`TZYSR_PVKUI`V[[WX\ck^j\b\ZWSNYHVH]Vfkv~sxogxyv|zy|مx|rvstrhihioopyynփx͉k]Zaj`lw{tՄx|sxrmچٍ׎֑وڕّӍҀ֔Փى҆ҋ~݄ۜ}֟ݟڪ۠ݤרڕԉ؉ڢܜٞІxxΈ֋؜٣۞ࡈᢌ٩ڝڎӔבְժܡݣڦۚڝן؜ݠ۟כ؎ݖޭڪդЛޚܳ߶۶طണẲ޶ެڡ֚ן؞٦ץםܟޢܧ۪۴ڷܲطԴظԯէװݲسٷַٶܹڻ֯ثܼڸڶֳݮڨڭٲױ֮ҧצڪ׮ׯر۳հ׳ӯҤӱԶسҫӯϮˤѨԷԳѭҭֱӵծӵٹ߿۳ڵ޿Dzȱɷ弧ްײصٽݺ۬ٲֻ߽µȻɸ˺ŵôƴźǸǴø³´úĵĵ޻ݽ߻ῳ࿷߿ĹǷſȺǷúĶĽȽ߿๮ܹ޺ݼȾ̽;߿ݿѾ1AE@F=PCU=U?U6\DZ9Y 8^:]B_CdHf6LfAk'JgD\<\A_DV9W :Y4^@a>a:`<^;c=_FbCdLl)Sl$Sw)P|3a{-XH@I?N3E:GCQBJGSBJIIGP?I>IBU=KAM@HBK:F:HAPDKGOF;K>I@PGNBMJQU\FLIPBHCM=KLCPFQESKSMRDOLXNQOTR^Rc\cXbQRPWRiR\N^\dSQT_\idnXdZYQVFUI\CWXlr{z{ׁ{xzptsq~}{|n|}tkptqistrq{m҈gZW\UiU^qux}rzwrtԁyЁyqpՅuܕۦؘ؀rЂx}АֈێwэԄ؎zЕԉ݉ݟ֬ݪ٫ݢ۲ӪՊЌ܌֔׈{yЃy՜٫۠ݩڞܕܙޠ٧Ԡ؛וڐܐܪۭڞޜמݘبآݙܖ՗Օْݡݫ٨ٟ՝ࡓ߹޾޼ެ଒ݟכӤըت׭٫ۦתլשإޠݭ޷ز׷ܰݶٯհ٪ڭٯײܸչܴڸղбذٺٷ۵ڭڟڣժٯ֪֨իڬ֪׭֮ׯ׫ճְԦ֩ձְͦЧͩ͡ϟӤϭϭΨҢӰӯұײܸ޿ྦéȱǨว۬ײ໠ෝ޶ῲúɼ̻ǵĶóŵ͵õ¸÷޿޾²޽޻޼¸¸ƸĹƺóŸĹٽ߹ܷ߾ȸʺ˺ɾνܻşb@IBLCO ;V@WDW;\;aAaJa?]=\9a?b!F`A_'D1C*A0B-@3D5F9H8D7G>O>J=F:K=E9JBSKM>KGOHLGODN@JBHDGAH>J=I6O5URMڿ̛Ƃsl㜃buZq_ӂslaOS[]\WJXEPTXLLJXJUAQGRI 9M @N>V=V;Y7^>_A^?[:]6^=gH`>d?[:]C_:X:[ 8Y<\9[9^=h=c=c:i#F_@hDdJ_BcDjLm#O}*W?gKqYql|vz|vԁ|~vwyvwz{}zЁщՉ}؇׌~ُ}֌֔׍Տ}׉؆ӌׇ~ԇ؇{ԅֈՌ҆ӆ~҆Ԉ{҅ӆӋ~Չzц{҇zΊшtӅ}҇хІЇԃxχσuЊӅ~Ӈ~цԈyK[K[AP@GFTAQAKCPBL=K1D;K@N=BHW>ICN?RBEDRDMGL?KBIGMIHKQSRWNaYj^o^s[h|cgdnurqivwx{tonepvspnb~qu_n\eSXUNLQR;K:H1C2C)A&<*?4B.C3D7C9E5F>GAQ4D:LJ?I=GFMCIBKAI>HAK^>^ cA_:[:Z?^>\ :^DS6k$P`Bb=aL@MIDCJMBKQPOIYU^UiYnft]ehojx}klplszm픅oqm~xvksd~`xik_gV]ZQNNNBL8G/B&?$<+C(G*D)B7C;M9H4H8H@M@JDP:IBJBMAO;N:GBOALECLCLINMPJODNIPAKCCLV@S9K3L8T\H֣ͩΐctfpW݉}wdxb`aj_bTSVXTd]`RTQQSINPXNXJRKXERGYKSESFTBSLORb_jINDL?OIQPTWTWUQOR[YeX__`a^XYXgQ]DUMddlprv~xrwyxwuw|uqsaginhpsvssԅזm^Y_kwcqiqytՂ~wuytr{xv}ss~uӖЂcngktՌցxu{ׂqٗٓӜژݚ۟֨ҒԒօ؋}ٖ՚ى}x}א٦ۢݔԐޏ~ݢߤܞ֘ޓ٘ۗޘݠߞݦإّٓٗގvޥتޛ٢ژڞաءՖْטיܕݗۭؤ՜ԛ؜ܠܬݴ۰ح֦ܥۜܡ٤ڭٮ՝ח֥֩ըجٮ֪سڸڹնбֱѫۮ۵۷ٯخجڦץנژ٦٧ԣϙؗРΥث֭׭ӰլձПԜϫҦӜϧӧϜɖɒ̕ǓϞѳ׸ƭ亜ᴙݪؠГљկߺ纩ῴ۸߽ݾŽ˺˾ͻϸȹȷȴŴ۲۵ܾ῵࿲㿲ø߿ྱṯ߽޾޻ķ¸ƷûĴƴĺɺۯڪ١֩ܭݹ࿲öǻȸɼ̾Ӿִͯz%ALBG?I7T ^?]@^9e@dAaB\>\ BV>X ;U9X:\?\<_4f@j!>f@f>g@Z8cDV <_@nJ~7^AbTndxwx|׀|{~u}~v}tuu{svy||ԁ|Ԉ~֊Չ~Ջ׍zֈ֊{֌҈{ԋ֌ֆӌ،x֌։Վ}և҈ՈՅ}֋ԊԌψՇ׈~Շ}׉Չ~ӃЉՋҋӈ{҂{Մ}҆~҈vъӇӌxфׇvCNCN@M?NAM=M@MLUGWGP>KER9H?GBM?K?H?L;H=K?MEP;H@H@KISPSSM[W`WhS{ot\yn}iaswnuknuxnxorv}txjpsx`ugm\cYWQNPMNGN7H-B-D&@(A*@1D5J2D3F=M7ECS9G=IBKEDJ=G;DBNAI>KCN@KFT;J?ICVCG;G8FBLCL@KFIALCNEKAHKOELGO?JCHGQEP8L5T^;T:`>\>^=a$O^@`;eBeCd#I]IZ@]BV:\D\=^<_9`9f Bd?j$GiI`@_:Y:V ;_Fj M~.YEe[skwvy{zyyy~xysw{{}ӀЅ}ՈՌ֍֊אؑy׋Տ|Ӈy،֏،}ӄ{Ո{ي؍דՇ~ԅ|ՅzՇԅ}Շ}эԉՊ}֌ӋӄvӇ}ӊ~чӉzՉ{Ӈ҈фՇ}҉{ӈҋx׌yӆxӆ|=P=P?L9PL8B@HKOPROKTNbThVp]u]{icclnqtg홁qmvxpuu|zvvgpty_q^r[bZaWSRQS@L;I4I-D-C)C2A0H3I5D3I=F;D@O9C?I?J=I>LAJAQ@K=GBM=KBK=PBJFNH@LHOEQIP?LDOBKIMJLGP@ECFbJY?W;Q <]Cp$R:cXsj~q|z~؀цҀvzy{svxz|̀ӆЅы؎׍y׊ً{֋~֍׌~؏ԋׅ׌؍׋Չ֎y؉{ՏֈԈԌԃ|ՇՉ~ыՇ{։}ՅxԎ{Ո}Ў֊|Նz҅zӉՈv҈ӆ~Ӈ{Ԉyь~Ӊ֐xՍ҄wERER=H@IBQCQ=JIXGBN?L:I;NBHAN?M=HCSDM=MAJ?IAIEQ@L>KBHLBHGNHO@L@JGQBKMSDHCLHMCS;M6QV?eG~)VDe^zlz{{Ԋӈzyxz{{w}tzy{~΁ӅϋԍՊՋՅ|֌z׎}ӊ׉u֏{Ԍى|׊}։Ԍ}ג֋؊ىz֎׉֊ԇ~ՋzӉ҅ҊyҍՐwԉxӆ|ӇԉuҊՋwҊ~ԊvӇӃ{Ј֊zՈu׋yԍxׄyӄv=K=K@QCNHXEV>KCQ7E@O;I>J>M>N9EFRET=HHRAU;L>ML>J:G;G=H>OCF?RBQ>FDJGOCK=I=E>FCMDN>LCI>HLCMIQEJEMGKFQJOJNEPGQCH=KOBK =P;X>Z?Y?Y;_AbL@JCJGLQMSPYS\SiWp\rc{[w\lkintsuvpvrzvvvswgg{cwaoZj^[XTSSZDO:L3K2E0I.I0J3M5HASHDMH?HDIDO?IBH?N?FELFREFCICMKOGNHP?ICLAI?I;N4PR:VKV;^DWLBK@MAK?UEQAQ?KAPNZ?R>M?H?M=I;GEJ>J;DBQBJAFKVEOIJPP_Rd]j]pYvdzYudrglswpqu{w왁l{zv{tihnwinUgb`ZQQMQBK1G5J,A2I+D+C.D:G:F9H@M>L?OAGBQ=JAKAL>J@KIXENEPaE_?_!B`C`B`%E[AZ;S<[;\6[7b;_7_;^@X<\@aHgPh Oy.Yo'Sz(R;`Xrh~w~}~}Ӂywtz|y|xy{}~҅ЌЃ~ӑ׋؏}Պ،؋َن։~Շً؈x׋؊}֌щ}Փҍ~Ռ{ӄӄ~Ո}Ғ{Ԋ҅}ϋ}Ӎӏ}шzЄy҉{ыzӆ{Ո}ԌԍvҎы{Ոxф|ՆtЅuІ~Ոy֊sԄ{>J>JCJ@HFMK=G@NAP9ICK?J?MJ;C?LFPEJLQSPYYeXldud|f}ejtfosivv윀rsxpztvpw풄mpc~ixim]dTZ`UQMW>K3I/G.D-K,F(H2L3N:K6I@R:K>N>JDM8I>L?LAN>REKM\DODNBO;K>IDOAK?KBKBJ?M>HAKEQ=H>IGPBS?KELBMEOEMDGFLCK?FBICLBP5L4Y:O؃`ٹШd퓅viZwnhe{]]Yobv_jT`YpahW_X]dOSZ^QQQJLKOGT[]UZTTV[QTV_KTEQ;NRk_grqswrorptptmmtY\efjxjngjruyt׎uLjySYJ\N`YaVfpi~xyuyx{z|x}||xyt|yy{ҁoʀdk{s؃xtt~׌ֆق}σrwosivqtي{֖ҎɁjnij}~яوᗃ࢑࢐۟ݒڌڐ؋ڎڑޘ؟ٓٔכܒܗ֛؍ԇچ}ۗۙ٤ךڑՈ~ڄ|׈zՑؙٖڑی{֗Џ؀؄vؗٛ؟٠ڜؓy҅xҊ~ώҍ̜ϟמצ֚؛ۣ֙ؔؤؚ֝ܩدګޭ۱۩թ՚נըآըٟբ՞١ԡ֚ѐٜ֓٫٦է֢֣֥ؠצ͊ӄsԟΑzЙяϕƎ˕ˡѪɵ绖ಖէ֘٧ܸݺ߸ٳ۶޹۷ƼɻǷijî⾰⿲⾬޻߷۱۵ٹ۷ܵݺݺݿݾ޻޸߼ὰཱིݻݽöŸĸúżĶºɽƼȿĴȽܰסӌь΅{̉̅҈͕ԣٴٯ{oso|{ӗڤ޳乧龨ȩҳç_TVDPCO>UDZB\>b+W_#F[>]AgDc@_;aAe)Ha=^Aa?\=ZBV:[ 7]:aJDQFX?K:L=JAP>L@HFDO@KELCNDJW[^Yd[g\s[zjgjfiqoul}zplywp{uz~qlqgev^qfgXf^TQILHO:I.E6I+A,B-D2J1F:J5KBS;O;Q=NK?MCMBJ;JANAI>FCL?LEO=D?I>J?L?NISEO@H>K@JCNEOFO@LFQGLRZlkroxlkvpqloskjqnmq_g`_hlmze`̂҉x|UZM`QdQbcnmmruqn|xzztvzm؂}v~yqnwmrzzxanmm|iӈ~׆|ӌ|wqtok}suvmqt|؋rג{unmv׉tܑٓލ╌ߣޢޚݘؙ݈؏Տ܍ۍۙזٖܙڑՙԎ؉هڒ۟Ӝى׈׌ڐؔߜٔ׈ڐ֜Ҙ̈ۊ֚ٙږՙpuz~ɄьҐܘ؛՞֟ښ՟ۘםؠڡٖۢڟש٭ײ۬׮٫ΠӡמҤؠ֤ؤ؟ԞٟҡҚѐԐ؟ءئ٭רמ֞Ԟ͕Քӎ|ˌ|ƎΏћ׮۹ݿȮ淖ݮ٨֪ժخ׶ްݷ޹ݻ޽¸Ǹ̷ŷƭ⼯༭߼î㾪޾߶ܳׯڶܸڴٻ޸ۺݼܷںᾱ޽ݽ߿޼޾¸㾯·ǻźȼǽɿʱ࿩әҔ·v́χЍԘ֤سުycclqx}֒٨ݮ㼥废Ȩӹѱx#;S?UMTEO 8Q4^&V`!Dd1WX?\?_9_>\7e@^;a>^:_=T6\BY 9\ 6c:c8cA`7Y>_B\C\Id"Pp$Oz(Z3a1\MlYrlqyyx}}{|~zzxv|w{{{ʁЊуӉьԆ֌،z׌ӊՐ؍}׊ՁvԀ|Չ֎؋׊։Ջ؈xՎԋԈ}ЌԉҊ{рt҉ъӊ|ҊԅЇ~ԉ|ч|ӌuՊ֐ч~Ҏ{Ҏ}҇ӆyԉ|ԅtшy֊ԇ{Ӆ{EKEKCPFS?J>O=GL[9H=NCR?PIS?R@L=I>J?HCI?P@ICRIM:H?NCRIQTU\Zfalcvitjflgqtrl뒀m핂oluoznxumhmh~au^r_bTaYRQLO?R8L:M.D2K/F.F(B-E9H1E>P>M@O@OEP?OJVIRKW@PGU>K=KDUAJCPCJ?N?MDPAI@OBQ>I@IEO>JBKCLDMEKGJGM?LHRKRAI;GCLBLBFh@Z8]@^BYBc Qg$Rw3_;^9jCjXqbzv{zx}~z{tzsuswxw~ΆӈӍҋӋь֎{׉׍ՌӋx֋Ԅ|؈ՉՉ֋׉׌։Վ؈Ӊԇ}Љ~Ԏх~Ӑ~ш҄~эҊр{Ӎ҉~ԋ~эՆzӈхЉ{Ӊ{Ӌ|׆rՉ~҇|΅yԇ։wՉ|Ҋ@L@L;IEQBOJ?I?N:K;DI=M@NQY?LFO@LALAI=IAJ=NCOAKAL>IEOS4K3T@Mf۶ňl}{hZ椄u_mVz{cfZm]|ifXa\qlp]m^\VTQKPFOGTBOJRNN 8M ;PAO 9Q 8U9X :X=[B^?_;j6Va.Ib&AaD_9\:\9X 9Z3]C^;bMBL9G3K=JDM=F:F=M?L=RBNAPNKUV`XgZkXtlw\yefjkvvpqxu}otuvylvqtkig|dwas`cW[RTQGMGT:H8J+E*G.I2K*G.K-D5KPES;MBM>GCT=J@MDN?I@NAL?PFDICLFFEMBJBJGPCF=JAH@J>G8P3N4QEMnծ{_m{k^vkscm_oVtjteo\VRmeipZfg]XRTHM@LJ\CNBK6L;N;PT^CJDQJTHQHMHM8M5SXerqvwvpprokkipuhk``nkko`eigtvqvpnqc_]BVZdaf`ogo{tqqmplpjhsnvr؂}׀xwghiey|tvmvikpmԇuׁ\Tʀxz{ۍxًل~҅y~uqfggvww،ߔޝِӄՁڀzڈxّڈՃ}ፃݚܖۚ۝ڍ}ڊڈ~ܘؙْؒޏސҔۇ؋ӎщz}ׂ}{ޜݢ՘ډԐیݑ{ږגՋfЂ̇u~̍ӗטԚלٟ֕֗֟וՕ؏ٖܣۛݧܜԏڈy؟ؙӒ՘ڝ۬ީڧۣؠכؗԕՔҙѝՠҝ՛Њ֏ԞљДԙէҜҚЕʏʎі׬ݹ徨¥齢ަ֔wЦ֨۴޵ܯդֶ޺ܼƽͿ̶DZ¸ñ俰ῶ⾬Ὣټٯتٲܶػݺݺܴݺٰۺະ޺ḳ⻭޼¸ü߿µ俺źῸ㿳¸ƼȺźɾIJʶɻڤʄ~xȆ̐Ւђס׬ܰЁgakhmkpxyҌڔۜݡܫ享Ϭ˳q!AO =T@N9U=V :W=W5Z>]B_;c Db6V_"B`@^:X;]kL@I?J?LALCP?I?JAM?P@H=J?L?GIN9J?IAMHNQYXY_[dWpgqcu_ilhkfuuowm{zoyt}srqjggycuho]^VSNKMAK=N.E%?+E/H+G)G1H2GK=LFP@K>O>KAPGUCPHSALBLDLANHAICGZ;h!Gg=c;b>b<[?]A[Fj#Rp*Wy*]|,WK>KO[LVAH>RHX?MG:FBKK8H?NEO@OIWOYUV\cbXiYpUycgkfktoqvuxmxxm|ruxvortn}ayetanX`XTRIJET8G5H-E,E'C0H5G1H6H>SAO@M9K@NCP=PGYCM?JBT;K?L;LCIFO?M;F>D>HI@MEOBHAMBGIVHO@K;H=I=GEL>JDK:G7F6K0L,JHEׯgd魅t_j~kepQ}t|iuXuZn[tcdWSPfa݁d_MOOHUSMR`?M>LLYHOKXIOJRMRHSAPG[H\VgholdqspgsvjdlihcmhcmV^U[aiptrvm_RNc]lgoagTd[mokoqqsypsrz{nnppmkkiutvyniiks{qfwu|ovV]rxlfvpsЂs،؀ց~}ր}zlvsz҆ӈw{Ԃ}u؃v܍ڒԐ҈ςs~tnֈyْ։فބuۥߤڣۆ؆ҁ|ل؅xՈւى~ԑ݌ڒי܏ٚғچ؅܉ݟݝגhfkk{ɂƐݏ~٥؞ғӍچԍ֔ٓԌڀ|טޓٜԖڇܗܡٚݎؚ؉ىڕ؟֙ؐوܕךՙԕԔآԞӓҍאחԜ՚̕Ύ΃җɑDžʌ˅t͊ΏϐСܯⷠ罢㩋נ֙Ԗգڲۭݮܬۼ޾俩²ijƲǵǶ¬㿬߽ܹܽ۶ڹܳ۶ڼܹ߷ܷٺܶںܷ۶ܷ࿲ݻݾ⾵߿ὲö´³޿öøżƲŻżǹɽʼɸ̿ϴ˳ɻי̈́ͅˉӏ՘٥۬۬~rkorrv̄ȅҘۛיٛݜଢǭٻ¥WRO>P BP S 8X8]=]=c@d!BeG`;];Z@\DbIdMq*Z|:[1\Djayhwx҂؉~|yxwvvxtywwx̀}ρ|фҊՉ~Ԋӌ|Њ֏֎ԎӇӊӊՌ~ՋԆ}ч}ԅ|ҋ~чyҋӈӈхэՊ}ӌЉϏՉ~э}Շ{҅~҇|Ӈ}х{҇ҋv҉}҆sЈҌ{ӊՅxц}ӊψЃzόόӈyӊuҏBIBI>OCSDL8L;IHLZRXSQ``hXk`p[zc}fjkmmumzssl씀yusspxtkvdocveqajXh`SSJOGW=M8O.K+C-G0G4F0F2F1H@I9L;IDSFO8LARBMAJ?O@JDJAJDRL?HGQFNJRJPCIAMDL@L@JKO=FCLAIR7V@\?Y:`<]D]A[9`?b=_Bd3WW]?Z<^<`?fIcD[9Y@\BdNdNq)Ut,[x)VEoSnfq}}}Ո{{y{{zusywwuw|}φЄԊ~֌ֈՎ؍يw؎}הՋ|Ռ}Չ}ՃxӊԈ|Մ{ԆyӅw҃Ӈz҆щҍу}Չ{ӏ}Ӈ~ӆ}ԉӊyӌ~υЇ{҈чтyҌӌy҉{ԇ{Ռzӆzч~ЈՄ|Ћ΃tӈ{τ~ՆqօwЇ;M;M>G@JDNM8G;L?OBTBKFRHLUQd^fZm[nXzkdfohlunuup엁uupnlmqujwkk}gt^rejc_SY^JRATAQ7T1K)H,L4K0N4L:L>O5K;N9KKHR?M@L8LBN=KAM:JAK>ICN9H?J@M=HBMCIAK?O>DCQDKEKFN=FACDPAH=JDNDJCM?K>F:G;I7M/I.K`QǑ͝nih}s[z{obQsqڑ|y[\UVV{aq[nhhfeRXZLPR[SULUOX>ICZGQBQAN:NLAV@YKS<\DX<[=Z?\=`:a"@_G_BY4](M`.SX=S=Y;\;_?hJc@`=bB_F\E[Hg#Sm(Wy*\-\Dh[xjv|~Ӆց|stwxu{}z}|~҆}Ԇӈӊ}ԇԋz֏}Ӎ׉|ԇЊЋԅ}։ъ}҅ҍ}҃{ϊ}хxֈ|ԅ|Ԇ|ӉӉ}Ҍ|҇wӎԊ҂wЈՈЉyщzӈwЇ}όxӌyҋϋwъӅ}ь·y҅wӊtӉ΅vҊ~҉~ш}Ճwь{@R@R=BJXKX:K8HLMCP>KGMMWMRZW]P^XiVpZx]~hqghxquovlsyozuup{jq~mo|f{lxbpkaTVULOIQ6E2F3G#>+F8L.G1C9N=J;PAL8MCMDO?M@KAOCLCRFR>KAN>HDM;J?LBIGOBP>GHS;JHAM?J@F=IN@YY_fmbqXZnjtoqphqkkc_in`ijucgu|lpkgYZK]OcViTcY[Zhmiցz}}skuqnunm{v|t}~rkgghfnytku}SRflapesnlwz|wx~zσu{zxtujn\bpuy{xځ}ن}אځwڍ݆~uuz}wڂܘؔׄy{~rڋwԈm{ooxvnՋۋՌڍߍؘוߐڗ٘؅u~l~ÇՇҎ׍يՉۤڙӎԀ~مېݑ֘֕ܗד֍׉ى؉َ~֟؇ڎ|ؙ֎܈٘זҋ|ٍ~֚ՎΈҊԎІь՗ӘҐы҅ӍґБƊȁzy͎Рܩ޴㺤¤ᵖޝד՜ܭ۪ܧܫ۳ཥ俲߷㻧廧伧ໞ张Ṣ亞ᶞݰܮ٧ذصܼܵڴ۵۴޹ܷݻ߻ݾۺݻ޺ݷݿ޾ὴü´ƻĹƺĸøöĶºúùŻȺ˿ʻȼʻ˺˹˷ǽ۩́{˂Ń͈Ֆפףxqlq|̂Ԓט؛֒҆|}{w|~לҷݾŵHKLCLFMDO ]<_>eBZ<_AT7U9X<[K_"H^>`Da=h!HfI`?[>]HVAcKj1`g!Ox+U6bQiitu{ҀՃ|ҀՃ|{|x{qwvxww~ҁ}҉ьՇІԍыՎԋ}ՊԋՍ҃zЍ~щцӅ{҄ӇxӅ҇ԅvӌԆ|Չ|ԅԉь{ц}І҈{Ӈ~щxԉҎІ|Ҍyσ~Ӈ~ъuЋ|΋ч|Ӈш~҆zщ|чЉ}ЉЉvҊԋԊӆvCXCX?N@LFWCQ>LAR4B5I?K:G>K;E?O@I;M9J?H=I8G@LHQ=LGRKPQS\U^Yk^kYr[ychmhklrhoymmwmvmuxqqsgvgsct_h^^TV\NQGU;R,D1E'A&?0E.E7F8M8G4L8F9GICJAS9L>R?MCSBJ@L>M;FALEEI8H=J@J@JEM:F?E7E9F3G,O2E~Z׼xh꫄pbvrieqbڇk^}_mR܏}geM][vdreTMVYXUgWGFIRMSHMLTcIf"DeAiCc>^E`H]Ef.Ui.Zq,V4_Jpavw~Ӏс|yu}ywqvu}uý{хыьՊ}׉ҎՌ֋~Ԍ֋|׈҆~҈҈}Ѕ|֊|Ԃ~Ԃxӊ{ԈՈzӉԉ|Ҋ}ґЌьӆ{Ћ҈z҅zцщЋtЋΆxЉzч~ҋxЊ{ЉwΊ{ш~ԁtІчyь|ч͇yτ|҉҅{ԉrч{>J>JBK@KFZANBICW?M=O=O;FI[?J>N>LBO;KFN;FAL@N@L>GGRNSQQWWa`fXm`seu`ydmjntsnwvnovztviotmplsmks_thoibbZ]TVOXFV0F,E*C$A8E)@2I:J8M8M:J>J9LAN?KN>J;IbAa?^=c"K`"PYE[H\Fj1Tg0Tk$Mg?cBk$F`;gLaKZF`FmUw/Y:_Rqeuw{}ׂ|y؅yx{z}w|vx|yӃ{Є~֋цwՉ|ӌֆy؉}փ{Պy֋~ԆՄwъӆy҄}ӌֆ׈{ԅՄxшyԇ|ׅzԇ}ӄ}҅zӋ|ԎԊzӈՉxӉ}҇ӆ|ІyԆ}Љzщv҆wҊ|ҊyшzЇuю҈}҇~ь|Չyψч~҈xԉ}чy҄x҂{LALGMSVWP[WfYk\vbylcmjlqtgqusv{sx}rx{rvhhve|gykoe]T[\QRBPBW1E(@'B-?1G&@2D3G3I9GKI9HI=K ;O?S?V?YCSA_@a!J_Gb IbB]Af%R_F`$OX?]G`Ge=i-Pi/PlHf#Ec=_C]@_GdJaGm#U*]GeTslw||yրy}|zyyw}uvut|yрzՄԈ҇ц}֋ֈ~׊׈Սԋ}؋yӆՌ|҉|Չ҉|ԈzшzӄzЇ}Ί}ъ~хtԃԅwш~Ԅ~ԋӊՆzՉ}ԉ}Ԉ|ӄ{ӆшwЈ~ϋЅ|҈|ф}ԉvЍ{Ќчzӈӆ}ӆ}ӉьЊԇ{ԇ}҃~Ԉsх{=H=H?N?HBO=OBK@PCP>RFQ?I?U=K>L=I@N@IBN@JITDNJRHWJLGQWXSS[UbXjdq_zdlkhqxvwyuyxqm뙀owxmpommpixdzgj\haaaIN,D+B0D2II>MAO?LAP;K;MFM?SDLCLAL@N?I?IIQ@KAJ@F>L?J=IG=J/D-H)N0FtfϵłǙ|k{œi~bqrbozoebfTpk|cpXoXxwsatW]NVWfeIO;J4F/M@TXUiv_]nfmollfhmuZiYc_magmfcuypsSXG^WfetdoW\Uegxxozzneoplpiqkhsuuyjelkjsnsttx|XeWodnit]simjqtsvuэ}wyxqw\iQ^`mog{}y|||݌{ٗՑ݂ڈԇvՆtjsĄxow~{NJy|f{cmw{~~}^zTwGx+])CwzܗݐՏՃۃ{ى{ۓډۆ|Յֈ؇zىۇ~ӌׇڐڋ݉yҐىՈۆې݋ג؋Ӎ|wل{ێ։ϋӀՀyђЖ҉؅ҎՋφӀwҒғ·zpq͈͇̂{ȁћ௚乡ö峙奀ۢ֡Ӡןڞبະ⽨ằܮ෠İỨٱݵز۰ٲ۲׶ֳ۵ذ۳سܳ޻۾۷ۻݸܹܺݾڻݾ߽߿߽߿ŴŵĶú⿸óºõļĸļƺŴƹżʼʼ˽οǼӝ}È̕Ԝ֊wutx{ȍϊ~v\[OPVJQ4ID\QZYocrƂڠ仰м޽ġcBK :M:NEN :Q :W>WGTD_H_Ie$Lh%Rc>^@^=]!K[@YC[;\?g Dn3Xm*LeCe E`B_C[D_GdPm$Ru"SNBNFVDQ?LAN>M?P>O=HAI>HBJGPAKAHCHJRCNBOMKNNVW`[aWgUq`v_{^hivkpuprtqsvwpwltojojhivaudkdicSPMNK>M8I?LHCKBJAKAG@G>G>F=E>J:C4C1G+B%O6Fސ`ȏ˦ńm{~Ìk\㞆~axPޔs\nVldߍ}_kUlU{[t\ZXcYhZLI>J2H8KPTc]fj[cbgkghmgknk`pYc[ddsu{lsuegpFXPYh|aeabVegp~vwqoknkfcjenlomidsxjfjgpsop[WV]Zicshqooo{cp]mnxvs؈yϋqkglieojuugptr|uف}߇؄|ڍ؅xxpzrUpQpHlOoLgRoZy]v_{e}ffs͆Ӆ}tc^wӃy{nlʼnu|h}R:sqEap׋ڌ܎֍׋ۃ܋܏ՐوՅԇz}ΆʋЉۏڅލזӇ׌ٍ׍׎ҕԈ~~zօ~}Ғ͒|srϑҖщց|ӔЌ||uє̇s|xuʇ}̈́Ԧౖ嶛¦軙ݜՊy٘ۙܜܞ۵๪ౘ㼭๫乩踝羭辤Ὠ߷ڰ޷ٴٴرٷܴܷ޳۱ٶ۸۹ݸݹڸ߽༯߼޹ܿ޻߽Ἣ޿µ÷õ㾹¶²ƻſùŹļŹȿû¸ǸƼȹĻɷ̾λ˿޶~yć͕՛ъu||ňȐ{k\V\D\AZ@X<^7e$Nl%Ek#EcE`C`Ci*Pn.^cMg!Qq$Rz%TDbclwӀz؄~~{~st|uv}}{сԅ~Є~ՊֈҌ}Ջ}؊א~׊ԍ~ԋы}ׄԏֆ|Ոш҄Ԉvԁ|Յwӆ}҄|ш~υφЋЇՊ}Ӄ}ԄyҌч{ӊ~ч}ԇyцsӈ}щwԇwӆuшЉxшyΌ҅|Ήs΄}щ{Ѐ}͊zчxωΆ|҉{̇̈́}FSFSK=IAOH@P@ODLMMJRFQHSIJNKV[^Ui[jWs_w_}^qeqqrnmvpruruuljtjdqhhj~ns[g^_WWMNT?I8E3L-F&?'C&E3H-@2H5M5N8LFW7GHYER@L@O;L@N=NAK=H?HbNjTsWqdxЀ}izPp[}y{яmtsy|eM3aU`ˍ؋ډٍ؎֌ڈۍޓ֓ی؇|͉xpmpwч؃׆҆؈ڏٍُ؍،ل{xzy}ÂmA\^lΛԓЉ։Д{pẍ́vȈ|ugn˃В٦ᷨ幰絓欀ڤ՜֍١֠ީݸ丧ಥᵫ忭«彬庤㹥彮佤ݸݵۭ߰رٷڴ۸ݷڶ۳ڶٹݸٸ޹ۻݻ޿ཱུܽ߼ݿ߾༴࿴޿ŻἲĺƻŸĹƻĸŸŶĹóǻŹƹɼ˿Ͻ̾˼ՑLjϑљ҆{~znjLJ{cQNI4D1I2I8M?R=YI]etzȊמ¸۳дw+=Q :I5G 9H 4O 8R 6U:\;Y@[=]9^<_GZ7]:_I]>]@Z?[9a@k@p DkAa>^D`H_H^Q^Ij!Sy2[:cSkhnxxل~{zxwx{yqwyzҀ~~~҇Ӄ|Ӊ֎ԇԊ}Յ׋~ً؉{ևք}֌v،vӇӃzӊЈ|ԅxӆzш}Ӈ}чwՈ}ԅw΃Іzӆxӊ~ххzуy҄xԉzЇӇzщwχЅ}Љ|ш}҄yЋxыь{чω}ω|Јzψ}~σx҆v͆uуyЂw͂yAOAO;J@ODPARANDP:I+B)B/G1H6K3H9F6L:L7JCS>LFRDR>KP=FCGFP=KH?EAK[ 7X 8[?]@_CaFb>jBl?gCa>]?\EeN\FjUiL|,WDj]qjtwvց}yمwysvw|wyz~~τπ~҉~ьԌԋ{ҏՋىٍ|ֈ։uՊ|֊ԍ֋{ӆ}ӄzЈ{Յ|ЄxЉϊy҆zӈф|ԃ҉Ӈyԇz։Ӌ|у|Ҍ|ЇЇ}у|Ӈ~І}Ё|уyԃ|ψπtΆЇwҊ~҄w͌ъ|Έ}҆{҃|χ҄yЇr҃sΊ|ɆAPAPFRFV=KAJBRGU&@+>8J9G6K>R9HAKCOGQ?NCLI?HFO>FAH?HJ@G;J;GAMBKEG>GBK8DF_>]FXZ;b>f Dd:i@j@d=]>^D\F[J`Ii"Rk&Q1ZLoguuy|Ԃ~}րw{x{{~wyxy~~҅zӋӋъӉҏև{Ӊ~ԊՍ׏҉{ЉՌ{֋yՈ}Ԇxϊ҆ֈ{ԋь҉ϊ҇Ѓ|ъЈ~ԇxҋ҇zҋ}тwш|͉ЉЂtЉЊ|φz҉z҇zЌ|Ά}ΌΆ{΄zЅˆЄzχ҅xσρy˅΋ϊ}Ѕ~́{CRCRETAJ@M>O?NDQ8L;P6E8L9HANBN;JDR=E>KBO=SDP=IINAKKULAN:F>HBMFR?GAGCT3I=N;IDX:KASK\Si]kqx֓ᰭȽϼططнfa:L7H 6P ;K 5T:R ;X :]?[7bD_9_7a B`BW7X@\?]5]?`:c>d@iOAKIVAMDR@SF?HDHEOILPSZObQg_lWv`x^~ekpjp~tvrlstovrnmlwomokebo^n\_OZTNPCJ9F-@(@#;.M/E,C8D3H1C6G7F8IJ=K>QANHWBP?M8N>HCMFU:G?K:JBL=IEO>F?M?KBRBO=KGJAM@L?B=G@K9IAK=CDO7H3?4<0D'@)I+FpNդֲ֤~zʛ~l쥈l_nmR[Uscg{VfUe`u_jMeTcYg\RQT`OSU\efUkWXYaL`W[_j^g]eoqhmkcU_E`cnZaWdUZcpssvpngoftpjdimfka^jgnoipdf\^faUgO]bn\bhgbhhnkrhkgqptmktuxjgv[dcnlkz~w~w~t~xy~сu]}HlIr]nr~mpvn[je\t[pZzYzHlOhJlRtHk@i5h~0ekU9gkΜ՗َېۑٓۋЂh_lm`U[iag\OI=aPb_ngts}x|xϚɂuiVMpOj?ot'T8PNfChn#[p'PWyiy[}I^VKHX>cyƓƇ{}ύ٢㸮绢ᦉՇ{ԁ}֏ԑxٌٗܨ۳޲᫙ᯡ躡鿤滧俫㽩ൢ߷ݷݷ޻๭ݹܹڸڹ۽ܺ޽عԵ׶ܻٻݺݽټܽ޿·߽࿱߿øǻĶƺǾȻõôóõ¹÷󸟏Žȷʻ϶̺Ŭ㴋՛ʏ̓k{v}oOI9F/A7Q\;_<]<]>\9b:_<_8\:V:ZL?KBTCPCMHWES@M>IAMALAIGWBK>P@Q?IFQALGFQ[HJQRWQaSf\lWpXv\kigfnstp{quqkw{lq|ywknfh}iyck\aRVRPRAN9G/A*C&<$@.B+A1H,D1A3E>L:JCMCQHAICODLBK;Kc?k_KYIcKh)Zl-bWPc?~<`Gno.XQGI@RICV}}̆բᬡ㽪尙ܖւyωЏԅwՉڤԪڳ޽۵߶ⵡ޽໩ཪῲ㻭޸ܵ߸ܹ޸ᾬἪۻݽټܻݷܺۻշٸ۶ݵعڹݼݾ߼ݾº߾÷òὮ°õƽȼȷƶ⾶ŻȸŻŵŹƻļǸϾȳ⸜ڜԐΌok^MNN>P=SFX]kl{҉ڢⴭ´ιյعƵQEQ6TAN=N 9N 4T<[<\?^=_=aAZ9\;a9_ C[;] 8X7]6Y=[9f=a=iDf@^:cAY>WFXF_IfKv+SKg_vmx}ӂ҄}z{r}t}yy|ʃ؋Ԉ֎ъԍ{Փӊӌ~֍~ҌևԊՈ}ҎӊՇ{ՊԋՌzԉ׊~҆Іwх҉Ӄ|ч|І~҉{щӄ{҄|҆ӄ|ψ|χ~шЈ{҈zЁ|χxтw·ρvЇzΆЇ~̈́Їźt̅φ}Є~ЅyЃy΅rЉwьuԄyςvAPAPCRBKHK>OAS?P?T>JGZNa9NBQDTKZOYFOFSJNGMFMDLEHNUOPZUYWf]i`iWsb`}f~jajjxs윁lpuls}ktyustrgfvxbsWi\cWPSMO@Q5I3G*H'A'B&?-C,@1H4D6I9HAMJ?EAN=F?HBRCEJCHAP;D6@6G3I0>+T1S^MֻϤtʠͪ{pﲉkn橁ueugiYwM_[UE߀hanWjVffyQ_XKYISMVCUGR`_]aU^QYOcYahihfgfTZ>TH_U`_f[lbojhsongjgsthlcfmhfkkijlntkiihKZTg^heddpbg_g`hgfovfggpjpccloekY^`omputu{lrlivvxրzk{g|WrTwwwy|tlzkx`}TyKoJeInJjPqIf7S-Ny)Qs"CnHq#Mw-Xs']eNg(SfzzٌُД̍}k`xscllad]VII~Ay8u8wv@}aJz5kk-_m/dvR8GBQE\EWNchẍ́٢⬠辮ζϹִʴrc5M=J7K6S ;Q 4Q 2[>aD^@^9c>bBW9X7aHY:Y6U5^ 3\ 5`7b6a?i;gCeD\>XGRFWHaGz4b<`Nifwty{~{Ӄw{uyxwuvvxx||҂؄֎|ԏӏՎԌщ֎ّגՇև~юӌь}؇Ӈ׍|ԉӅӆ}҇|чՆyΆԇֈẋԆщwшӉԅzϋφ·҅xх{Ԅ|Ђ|Άwч~·zυyˈ΄{υ{҄zЊrЄ|Άτxщyͅ{цÿ́~х{Ѕ}ӂpуw?K?KHZCKDL@OGP@PBQ?IHOIOEQ@P=MAKDU=NHPEMFPFHGRNWLLSTXUYU_Ui^mZ|f{dlmijotsxrqosqvtx|pnzhcjzbr\o^eYYWNOGUBO3I&C0G#=!>(D.D4G0F0C8K=P9HHR=O>L;E7JCR=G>HENCPDI@LAS8G=HBP>LCQ;I>J?H?J?LET=IBN@H?J@F>D:D?D:C:D8A@G1B)D,N)Kc@вͧƢѢ|g“Íeg`vpqRUCbenSdVkLYUـeX^OPVUcCSKSQ[O[V\d_bjWeX]cjgcbaLW:LNdRbYfPYWiipllnkomppbfjdmvigmwoqnnikU^PaT_Zj_acikr`h^bltfmiflxcdcgeqfkYb`uouu|Ѕyjngnnturx}vfzMk:c\zs~ǂs}mxcw[uLr=c;fKkOxFiUoI=MM;S:NAO 7TAX:XA]A]CaA]<_Ba;Z:\>aIV6Y;[<_:`6cLJUEPINAEDNBMCHTYPLXOaZm`mTu_k}eimiqrrtslvq{w~qytyprkfqzdt`hYbYYSONFK:L3B'D,E!A)C.I-G4K/@.J=I@M>KNBN@J=PCNAK@OGSaEqFlJfTpFiFc=\8^A`NpQrDr3o}(_;=GildĂvmsxvrkX{1gp+\c&^m1nj*_m0`k*hf#abZq5kKioN}aR^#Vb-ZyC{f'_j&_bRbJ_I]K^I_MW?RAUCSJTO:L7G7H_>\BX>Z<\ER 8VBc>lLjCj?e?fMARGO@QDMDNHKGLGELXFGNRMLYVaTq`s[vV}a]blkkrnrkluzusytspvnvgtgx_yim^d[XQTOHO1D1F3H0I!<,C(@3G3G.B2J>P@I>N;JAN;J?KEP>NEV?L>GIYJNJHRERJS>I=I>L>ICPAKH@H?K:JBM@J;E;G4D1D/J&L@Elњxǟxj¢ӥj`뫈iVsPb{Pm\UGDMh`|[sZhVZRUaI^DUOVR_KSNUTaTYX]`i]`clKN:TBVIaYbXeXfcjyompgmnchigfjgngbkimnqqW\Xmfp`dim_fdfgmjx`mjviinkjrjphlbjVcU]mwxxmtuwuzlmrusxrj}VqHhHmdynsnk|j~m~eUmy2lr3lm0ec#WYR^Pd!\k.pu8{VolT~g&Vc!Ze^a!TFt5og)Z_NWFX?SBR[BdF`:eCbBdC^@_Ba>Y>["LWJ=Ivp/_SDUEXJRBH =L ;K J;J=F;K>QATAL>N8H?O4E9G=J7GFOGWQ_Rk\fw҉ۣߤᩞ㵤軤ĮαжϬAFY?P 9YFPDZAU 5Y @[9a?`;fEgB\9e!D_B^E^`<]>V=U@Z QM ?SFcM~0VAects|xwz{~}xzyzxv~vy{~|zӆԍҊזґԉՋъҏxԎՑӈ{֏׆{ӉӉӊ׏Ջ|֌ϊӌ҉ԅҋӈ~Ԉ~όӊ͉ьόψ~Έzс΄~́~΄̃|στz΃~Ѕцx҇|͇zσ}Їzυχ~ψwЈφwχ́yЄr΃Ҋvυ|҄yψv҃{цx=M=MGMBMDOCNIOITLWEM@QAL>MDN>KCMCIFRALAMEOHMIQIQHIPQROXQ]Yi[lXua}Xbgdgos}lsoxopzquyrnpqjlpvcm`dW[NTVAK0H,D$A$@*@+H1F1C1I8D5N=QK@OFWAKISL=IBJ;HFTFMDMAG@G@J@D=G7DBF6A4E,B'H4LlHʊ˧Ϥˊu’ϧvsŗk_lfg[NQPQMRTVUKPTYRna_iOWUSWdS_PWWhKZS]SfZed[bqKZAPT`\mTdQ\[jlsisklkgjt`dhjiofijfijo}TUM]Pc\`bgaiejgjelgqnthlft_fdkdkiw[i`edtsur|kpuvqontlzmuksapQdBh[[y^we}pyl~fsa]NqMtXxhj|beD_>^HjLaqs[_\7os"X4w6ly.^PG{4jt2bGx_kXBp}4m|:sq-dy>vy>n[G]Ip)ll%er,fXv^i,PZHe"Sl0nr5om5tu7wd$Rj-ew?wg(U^[UGO=QCVGM>I6F6MCMEI ?C BC>c5qvwשᱏޖzӍuqtĈЈة¿ò±ȲȰƳ㿣⼭仩Ἤߺ߸ܳݺ޹ܹܷݶܴ߸ܹ޸޻۷޻ອ໧޼۶۹ڹٸٸַݽ߽ݼۻۺݽ߼޽޼`Ὧ߾໰±ܶ߻߸ȺȺŶĹȷɹȵʷ⿡ըˇd\UDQ>I>P:M=K6L7N=GP=RGWJZU`bnkyyyϋܚ毠宙鶟ØȒs??]7M 5T@W@S@P7W9aA_DeDaAd @aD_8a>[>]DY!G`%Q^B\CY:eBa?m#Gi?hB`?[@SDKS?L?E=LANCOCJ?FDI?FAM?HDKHQCNI;H7@@LlΥܸ᥍ۋhtmyvryǂɎ٪ߴᾩ俳帛ë´侮仨ẫ⸫溬༫ݷ޹޹޸ܸۺ۷ܹݸڶݶ޸߾໯޹ܴܶۺݹعٹٶ۽޽ܷ۷ٷݼ࿲ݹܼܻܼ༷Ǵŵ´´ʺ̾ŷǹ̸ȳ̰ħӢzhQOQDN?N6M?M9N6EU 4T8`E`>cBfG\>eBbA`;cEa?_!FX:^F`F[D_;f Ce;l#?mJdB[?T>P?N ?PFYEs"QGj]tqρ~с}πz{y}zzx{ww{zшӋ׍ێב׌Ռב֒׎uՌҋֈӍэ֏֏ЋԍԊ|֎ҏӍь|΋z͉Љыьψ}Ӈ~І|̄ψφyΊць~χ~Љ|φ{φ·Є}φ}Ӆyψ҇|·}φu͉ч{ЂwͅzΈЄxχχv΄v}z˂}҃xԅuՃyEOEOGLFTGREQCOBLHNK7G-B-G(B#@*H5K*A6F7HL?JDQBN=G@RDK>GK7A8C6?3D,B(E-VIFÚٽǓΘ|wŗwv}l[{ZjX^`TSJNCMVW؅{wlcinV~v]nPVVaWTk{\bUcY^UXI[=NJXWaWdN]^dclf_nnrmkpcmliiskt`eoqkjN[L\_n[_^f\g\Yfslveenpixfjinl{lifsUhQZZhgoekrorrrujomtfjipo{h}LiGlfewnxkxf|^kbuOtNw@nUtccVVbh]SMtNm:Xx/Ul(Uu6`n%_h"UcMiReJo'Qr#Ys'is)c{9kKx[N}Dpdn@pEGAALQmZo"Vi*Q}9rBQv;feO`Q^IVDi?avK|MZGVDUD]MTDJMOCO>NWQ5X=^@d?bFcAb;a=c?`=Z8`?V9^?Y;` G`=cf"A\?^@UARBOHQCdE:cZpkovz|||wzyu{vvutyςyυԇԊyՏ֏זِ֍֐؎،}ӌӊՈxԑ֎ԑ~ӊև~Ԑ҉ՄыՍ}ψύ~΅҉}ы҆ӂ҅|ЊΉЉыυЉчЈ҈{шΈІ~ʀ|ρ~Ѐy΅҇xхЈτwЉΈˁ|̆}͂}Ѕ΀yϊτͅzЄ|́z΄?S?SBOCQN[ERCOGRJTEPHRDPDS9IFM9FM=O?O:G;E@M8NAMJBJDV=NENJX`Rtdkgplfxj|etZvRIyNzdlma[a`Lr7a}4^j!Ho.[iPf#QeQd&UdRePhSfSmRs#_p)ez,eEQKDumMs?~]WNPmXt,_A|[x[aIYB]Se!`WKVK^ T{Rdc!SUORFUII7W!UQO= :@ ;< >BB^'RVǥෛݣ{uSXUfin…ұھຫ஠ߪⴜ߰㳛䴛ഞݸܹݹྫྷ㻫޺޸۲ڵ۸ᷨݷ۴ڰذ෪ݷܴ߲ڳۺۼܼẬܸ۷۸ڹط׷ٸڸڻ۹ܻ߾޺۽۾ܿŵ·ŷùñ佴Ȼȳ˻Ưŭ¬ӡ]VMYBR;I?N=LHY;K=OBUS>U 9T;[`=a<]=]:`<]IW;V8c ?hHb@k?j=m"Fe=dJ[CUBSFVM\Kr(V@bUtktt~|tvxxzt{szsxyӄӄѐՎא׏ԍؐ~Ҍ~َ{֏֌эԈЇ؉}ЏҒӄԋՏՍӉԐԊшэ҈Ҍш}чΌщͅΈыυш}ЉЅ҇|φ~҃wӃ}Άz·~͇ЇхЁu΅}ɅɂΆzɈ΃xχ}͇}̓{цwΉ̇τwЃv·EPEPEQGZ>IEPIVHRGSDL?LEQBI=G>G9I>HFNAOIQDIFOCGHKPWOMNJ`]dWgWo^q^wbncnrovtszisqrnuqlrsinyffkrWjVd]\YIK=H>I,A&C*E+@-B1H/I%B1C4E;E7JCJ9K?L:K?K@MFNFTFL=KBKDLAL>M=DGUAKBLEM=H@M;EF?NH?K;FBH=F9B9H8C:B?D5C0C)G*L0B܈L΢Է͌oyƘ͢{uկtew~`x[^WT`FRS_pptݍyz|hebRٍhj|LS]_]e[^TTU_Lc;RRY\nO\`h`dgckhnt^chiolkofnkjl{omXYS^^h_p_iX\bg`efl^jhlhmjuiqel]m``_bXbYcihpwmhomtzilijmucnSjOdOmBgPwgwdti~jsfvevb{Y}I}Fw[k\\SGvOHt8dm+WjPg Nm&XhSdEh SeNcJg SfPkVgOjQs/iCTMCzkUqz5hSVMWMAM@ECJ=G5G:I;ABAK?I;K2G-I0N.NYJάwq͚Ňϑ{xuYY^RQQdXWV}o|enqsZ؆viuSXiXq^m]Z`oR]IXENF[EXMYXkOTaeeccgc]qtbkckqtieqwlmcvU_KYTb]q\faqX_\_chqyancjeqlqhtfpei^kXgXdgfqxqtiplpnllugxcp`oWu?^Dlc`~htcuoyu^m[s^~^FxDsV\KzHr~5bv4_x5b{/iv)\v+^w5hy4gq,]s"WfMeKfNf(Rk$Tm'ZmTl$Ys&bvq']cxaJz`Im+nl1mr7quE ;@ ACBJOg.xx@sd|ݹ᭎׊qi]S`TiYiȆ֧ߵ⹩侣溘ᵣ߭߰ۮۮڰ٩ٯسݸݹ޷ܵݷݲٵ۲ݵ޻ߺ߲֫٭ղ۴ݼ޸ݺۯڳۺ۷دصعڻٺ۹ععٻݿغۺܻں޼ݾݾະ޽ù²ٰ߽˗~w|fub{Tj8P=WS=I>L:O=N?O:J9I=UX8]9^;_<_=fPiAd?d>gBiFb;\6b@_?[9X>\<_9a?a>c8m Bs'Ie >a!M\&Q^TZQVO_%Vn*WDhVpi{yx~}vpπ~}zyw}w{wxхш{ӑՑ֗Ւؔ֓ԒӏӍ}ԎԔؑҏӇ}ӏ׍ӋvЎъԍ}эՓъ~ωё҈Ӈ}Ӈ|Љшшю҇|ό̊Όц·͆Ή͋щyщˆЉщw҈ӄwτ|Їzш~·{ψ}҉}ͅωy̆΄}΃΁t΅̃ͅˀt΀|KXKXKSDLFQFOCKELGTGQ?LCP=H:I>JAM@N;K?KHSDKJNIQHRCFKKRR\RaSfUves[yd{dldryjmwirunvvnwplsrmv`jer`mYc[^UONM>KFN9K>N;N;G?GBN;GAJCO=G?IBK>LFSEOBJ8EJIR@FGP9B@IBL:BEO;C?M@H9EAKNE-B0O-JSLƖ֭ˑzuŖ~o쫁WqXkf_YaRfavnmZowegbσYeecybvagYiEQ;T?PWeQbQgM^Zcelglfnc_okpxgtehdeben|]tO[Qfbkbq^kdrV[^a_djriphrdgingugj`gYcXablopsxoncchnhgptkrfs\pKk9\`j~favawg~nwiwefSHuLuGyKpt-ad%Pn!ViWv0fCz0p|/jz2o{4es$Yl!Sj MaHd"Qi ReVeMhRs'f=mSlKyEvp^~8h~A{}=~i%QfQdRn#UAqE~|7c~DnHkAuy1[p0u|GM~Jr7nZMO GS7njM?J T;UE_I_?_B]<[<`A`DbEb<`Cd@e@c>d>b=];\=_;W8V8V;[<_AgKg$Nk'Kk%Hi*Kh*Ej;]XDTFSDZP_Ex0XNm`qqwv}}|xzu{u}}rrqẁyӈ}ғԈғ֔ؐג֍ԕ֓ѐՏzًӍԎӇ}ؔ}ՐӐ͊֍ь~ԉ؍ϋˈюЊЎАЋ}͈͇χЉЉϊΌ҅̉~̅·ҍ~хЊỷЈ΍}҇}Ԉw͊уuˈw̆yʆщ͇Ђyχ|͆|Љ̄˃̉Έźvπ{J[J[I[LVIQQeBRBLDTDT=J;LDN?LDRIELAQ=ECJBH:G=KEP=GAOJVBMCSCJAO?HO?H=D/G%C(J=Ge͞ˮΦsĜfÌdxgt[߅_u]gS`Sgr`cykw}i_݌rtmtc\uifpXhAN?TF^S^VcLZUge_t|dka^iraijfq{dlildcjpSYSd\l`c_hao^f_h]f_hbhgcq~gjbl[j\i\aP^fwqnw}q}jgejknfjaido]e\|Fk%Tisgvi{kxd}Yk_rVyBkBt1cx0h~>ok&Sd"Rh\x+ds,bLG|8nz;kBqr+W_FeH_G^?dFiTbLgOl"[y-eRw]Am]gEqOs3geL[?ZRe!ZbKt-]>rQWz8_w/g}4ey5qyIWw6fe(U^JJCUJN6gVI >D =@>= ;: >A ?LAFpx͙ᴠxՅsmqSiXeo~ɐ۪᪏ⶕ䶖丣ⲑஓܩ٤צצըԧ׮ײܵ޳ܵڵ۵ڳܵݶݵݴۮ۲ۮرڳܷڶ۰ܱݷܶݳܳ۰ڷعٷٵطٹڹٷٷڼۻݺں޽༱㿴ù²߷ֱǔvahA]}@\c{wvmhuZmLWFRCLAPAT5J?P:SAXIXXn[o`iox~~Ӄ}ىzڄzޏx{{垏外뤉骒궜ɲΡEBa=T 9O?X<\?\=`DY=c;]a?eAg>i Ja=`=c=\5[;^>X7X:[5_7c3f>gc!K`7`c@dQK]Ho*Z7^Yqj|{с||}~Ёyzywuyuzςӆ{Րԏבԑؐ}֖֓ЏҌ}Ҍ֋Ցԍ׌ՉՌӋӍҊՌ}֊}ӉҌЎˏzҍ}ԌщЏы΋͒ЊόύЌЊщІ}̇΄~ЊЇ{ԊхуwψЇvЅ|҃}͆{ˈʇzʈ҈{φ|с|ӆv͈ςwρzʃ̂|~w{{σzETETGWHRDPO[DSHOGZLY@J9MDNCPDSBJFO@E=PEUDF>IHRCSGNHIVW\O`VgYmSvg|j{_pmtnꕂu|xvurqltpqtuslltmdxbpZcWZSOTDLL=JCL8D=IEQ@J=HAKAM>IDIG=G9FFM=KAO>N=H?H@E;JBMAJAF=F7?5=1F&D(K1EhFϨ۽ɇyǩyqɝrfgZpXTWUNafhqloۀ}a\nݑsӍbcZS^hO]?QQ`YmPbQcH[]idbibimaeng_k]_miom\i]bY_NbU_ck`lbnZc\acjZgapkmfijpfl_kZfVcQ^XhlhuwyvmjxhqkjpsaabmdwcvDh,X^{ksphsgpiyTnEm7gBp6sw3ekX`Kp$[z,h;nHRPB{t*Xk$Q_Kf"O]H_FbJaQdPcQ]GgVy,hF|lqCoTnQwIt2^_C^CV B`Q_O\DxEv^bm'[bTy3g@uWN{Brf%OYSZ'TE BQEN@pk1YNMFF> <; ;?>VKCl~ͧܯۇqshca]o]msΟضಚ㫕嵝㵡㷦ުۦآ֢֫آפٰ۴ٱصٶڰ۳ܱڳ۴ߴݴܵתٯ۴ٳ޳ٯݰڲܲ۴۳ݲٵۼܸ۷ٴۼܸ۸ٹٻۺڽ߾޽޻߽޻ἭźëݾشƒxY]QfOkHqGd\zr{s~ew`uQbCT>O@MHZ?ZE[Re[hmyw|w{tڈ}ܒ{ߎ}~}{擂攁疅枅螇蜌髓鹡¦ȬҤ>=]8YAT jHj&Ff#FhEj>i!?j&K]7Z;^@X8\<]DX?Z9a9eBk#Hl-Lo2Ve#O`F`$O\#U[H`$Wb$T~:[Njk}nt{zx~|xz|uɀtr{|~тy֋֎֖֔ٓڎ֌אՍאӐՐ׈ԎӎғՎ։ԌzԑӐ֏Ռ֍ҋӍՋ{Ջӎ{ЌЌ̉ЊЌόЌ҈̆̋χτ͇̆ц~҉΅{͇}΁{΅|τ{ЈΊyц|΅x̆Јyˆ}Ά~ϋzχ}ͅ}|xͅ|ɂ{·{̀{KVKVIYGMI\KRHUFTHPEQERCOIVAOIX=JHS?GDNCNCICFHNBNLPLKPMYQ]Zsjq_s^xc}`ccqluqfrtnsjkoqtsitskfdhy^lZe[]QLNLW9I7I.H.C.H)E/G7H2I/D5E9E3B=G8JAM@PIHR@N?N@HLOCJ=E>G?F>HCJ?IALAF@DT9QOTWdX`Vk\nnohpaamnhvbeihgofmlpTc?VScZsZl`a_qfnXcbnZc`d`eekgo_fjp`jZeS_P^drjikthgnpjkloifnmcmiqhpfIk:`jgyk|js^xOjEoY>Z FWD`S]Gn(Vfsy>ifVb&Yx8lTlHvd!SX?M =KME IF7c5lmb*[pmBn"=n*Pn6WeD_JTC\MaJjJ>cVmjzu|t~z}y{x|rlvqvсuԊՏ}ؔ֔}ז֎Ւٕג~ՏӒӖד{֒ԒӐԔ֎ӐԍύԑђԏԊԎэԈъӑΌэɇх~Іيόьˆͅщ΄΅̉ЈyӉ{͌·{ʇ|ψЉЃv͇χ~̉ъτΈ~·{ЉͅzΉ΃z͉̅w~w˄zɀxN]N]HRBIIWJSKVITBQENGPHOIUIQGX9KCL>KGT;J=HENCEFPLLMPVP[U_Th]wnvYzbhcftmsrjrv{xvumrtwploskc}eu]q]h_\TRVHP7K7G-B%B,E)D,=.A1H4K1B7F9H>K9JMAQ7HEO?IEP?F?K?GBKFO?GCMAP=MFJDSDI@F>EFMEQEL?MFL?GAJ9H?H9B3K-B&M@N[Ӥɦ̟uwynyÐt]weߘnՑsfrN[bW~yހjYVeXp`ԁ{W\M^MaCZJZVbRdaehmtqowbnfbouhifgqodo_lXdQbPb_japWe^tdi_j_e_j[cXcbegfi|^hW^^o\qZhnjlugqcibhhgoriljrgmr}m~gvOu'R`wpgz[mCeDuBnz5ks'ZdNeSePg[s2eY\Kqy3]aD^G\C]EaSZG]KcM_GWFbKjYbQ[G{1h]^f[bMkGn}7d`=]EdUY GT EZGk'X^Ctm"]m,g|A}GR~Kwv3fUBQFF AJIE KN;uMlvJ|SONGBj*Z`wӟᣅقnlf_henpx̌ԟߵ¸㻣ඣ⶝ⵧݱ٨إج֤֨٨תٱۯٰڲٮݰۨڴۮش٬ֱڲڱٮ۫٤رڮڱ۰ٳ۴۵ڷ߸ٲ۴ܷܶٵصݹۺݷڻڹۻݺ߿ݾߺܸ֯kRY8Wu.Wz7SPrXvXsNq_~pzun}wxjorpzxxjv݇zxxvuvtyt}ߔ|zz|闂ꡏ飌볕ŪեcH\;Y>W6W?\ 8b3gEBJJOLKQR_S\Vmam[pZx`hctslrsosnl|rtqsrpvqpsyhht`tgbUVUHOEO=K4J-D$A*A'B*F1D6M1C/C2E5ENDOCV?M?R=G?OHSH=G=OEM?ODS?L=G>L>IIBJ?JAJCKFMCLCJO5O]?bB`Aa=f"Lf@jBo*IbFb@i"Mc@e;g@a<[9^Ba?a<]?bC`8e?e8i;r Bb8`7\J@N9G>G>P=K>FAP=I9L@KAJLS:HANEO?IBJGPCLHRCM8HGHCPBH:GCJ:I:E=IKGN@FCKAL7A-B-E(F1RL=ĐٿɣwněĆl}괁벍ozde۔kqXMth~~oTP^_WYHUCRQWWiO_MW[lhjkmcchijpls\eb_frS`CP>QTlP[esYebf`oX^ggetafdrcdaj[oU^YdY^YeIjPehzmydoescsfv`efuemmrqxup{gyX{?`Oip[u9\s'Wh NhWh"XiVi"Uv0ePX8_iGc"OZIZGUIZC_IWAdPg&S]@YP 4O =R=S 4Z;`<\^?e?c6g;h!Cc=^9W:S?VEYD]Gp+VJl`so{{}|yytxsxu}xxqzys΀zԉԑؘّ֕ӏ~Ӑאْ֓Րؗ٘ؖ֐ӏҒӏԏԌԎ֐|אьӏӎӎЎ͌ҋЉёϊыҌЌ҈~ω͇͊ІАφ΅˄}͊}ΊyЋ̉ͅvΆ}χ~ω}цЂv̍vφy΅z̈ϊ|ˇ̉·Ȇ{̄ýςy΅~ʀ~P\P\JVMWGWJSHUETHRCQKYIVIRCN@L@OERGODHLQFJ>GHJEIJLHMOJW[ZPa`m\s\{kybdmhkvhouwkovpqvxqlvhslc{^qXjZfY[QLKDO9D2C,D"=#@.J)B8K9F6K3I7JJGOEM@HGMCO?IFL;D@M=K?H>LBL@K:H>M?J@LHQAIGV?JHN?J7E2B/G-H)L>?~կƟǕt{Ĕǒjorހ{ioٔ~hgz[sݓdYSWCL>LIXQ][j_i]fckgmkmdjeol`s|huZ`V[GVAUAWVhQ_[_br\cdo[n^a_iasejcm\d_mZfQdM[UchephzXkEa;Z:VJ_Xe_nizhpmw}|oul}Qe5\8ZXiAeq+Sd(Vh)Ze[f$XcS{;jPO{}7`cB]JaQZMZ GT@U@`Fg Nm*\cD[=T 7X;aPaW^N^LI^K{m%N4a:hr(Q^@XGZG`ShZr*jWutMAwu-nv3k{B{Ti'YM R9YDS 6Z:Y 5Y8a9`=d=d>g?c]7`?]Ca:b=f=i?h>_:_CR 9Z>b&][E`G|7]Mggsz}{z|wxy|tqw}yӉyԋԔ|ّْ׏֓֔֏~ْؑґՒהӖבדԍҏԒ}ӌ֐אԐщҔԎ~ҍԐ̇}яЈxЊ~ϋφ~ҋ{ՎҊ{Ќ͈Ή~ьԊ͉Έ͊{ώˇЇ{̅ȇΉχЊʆχʃ}·Έ{ɂ̃|˄|Ί{΄φ̂}́Ѓ{˅|vITITLYPZIRIUFPGTIMEUJ\AIIUK[>MEKCQ=N>IEKANAFCKIMIKPPLJ]T`UcYmZt`ua~chdgnq욀mp~kvqsrm|lprhtod{bv_m`e[\TOMP[;H:J3P#@#A/D*E1F8J5H6K8J>O3L:L?P=I?PEP:J7F=Nmf+[l$\w;jJz>_u'YfQ_Lc,Rf+]^I[GZEX@h#Ro+\q-Y_DX?N 6X@bNfV^Do+jakf1\eAu4^y/UaE^IaI]FcUt1`Z`R?uEOPpxCsQ AG ?K ;THtOs9}F>8<@ 4d3aw4]Il~ɌިىlwbcjYcgnv|љװݦ᭓渥羥忦߸ݲب٬׬ե֟ԣتժӤձ֯ٮ׬תժթեѫҨխҧФԧԩ׬ը׫԰Ѫجڱگڳ෨޹߶޻޸ܳݲ޸ۺ۹ۺ῰ἤݹṗ޹ЬiQt(9e 8~8SLoo#QaHp*JLa~kb~JqNjYscNuIgo}ێސxwyxwqvtw{r똅饒쪕ﱔß˥ܱ]Ka1Xc9lAgDj$JbBb!?f$IfDe Ca;\7]9Z5^7Y;] 4\@d>i"Dj@`#E`*O[ HVKUF\!KaOhM>^Wmir||Ҁysxxz|styxwyxx}wӈҊԔېא~ٗԓ|Ֆ֓Ւ֐ҐԒטԕ֑ӕ؍}Պ֓֐֏׋эԑӑԏӋ~҉ϊΊъҋЉЋЉчӌҎы΍чЈφ͊̊҇~ц|·Іˉ͉|͊Ή͇ˇˉфz͇ʆʆ}ÄІ|́~΁tͅyʆͅ{́yʂxJXJXIOJPNUDQIQFOGPIVHTBOJUCNAMGQALGNEHFN?LAGAHFLFNONTT^W_Xf`k]sby`~gilhpjzpzsyxwi~wmvtulflj~ctWm`cUYXPSIR8MMQ4E@N;P;IFL:GCH>NK>L;LFMAJPDLEP@K=LAKACEIADFMAKBE>LALJUAIPFWWXcr\]\`cfjsnndljfjjgigccl[gGSTl[oWdZkY\\e\bbg`janWl[jVdahfn^e_kV_S\ZamspmpxiknspxhoZqRnGo2_+R8^XsXeew`sYo=]`NgRo.fNW{]Btj!Ih Mm!MiJZ@_HeS^JdVKh]{3iy3l@de\{Gw]HIEJDOArOhh4g;76>;hAdCbc;a@_=e8jEf=]?`CW>^G[L`LbG.SJi^oovx}{|xvuvt{tvuuu~z{Ӄ}ՍՑًؗ}גؙ֔ؓՓדӑҏ|؍כוؐӒՏ{Ӑ|֒ՐՎ{ՎՖԒэҕ֓|Ӎ~Ћԍ|ьϊύӎьՊϏюӉ|͉͆̆~Ή̉Ήыψϊ{τ}ͅz͇xφzЇˉʆ͈΁{ω˄~ʅͅ|͉~͉˃wυυ|΄}ȁ~ʃKVKVIOMXKRFQKVIPCLDRGREMEQCPCPHS>GHJ>FKSHM=G?JBEFJHLNNWX\ReRk_s^uWyhgvsmsjsuqzw{muukklpnthfiyfp`gUeaUTJP7G7G+?'?+F(H'D0G;Q5Q:H?O?RM@O>HBL:QDZAJ8J=IBL>H=LAI@KBOCLIOI@NEKCN?H?GCIDJAEISHLLPGOEN@CEQ;F;C5K.L0OEJޗaРɬӱˑvΛntuqpx宅★jbۍ{cTcR_TDL@MAZKWel_bXmWb[[emlsoshq^aag]fGQOc\ggrcl_l[\fm[i^[ekYiW_Zd[n[qfk\fVfScWalxnqlmdohckpin`l\rd|`oQqQw;e7^-SBZRgNo3YnMgPl(]h'Zk(^n+ax0d=ox,dq)\v6fi#XfUfVb$Pe!W`IiMh#Ny8i{5kcEZCQ7Q=T 8U `!OU:X<]d C]5eBd8hAkC`A[Db!PYEg!MdKk!O<\Pgoynvyxw|{zr|trwxvҁzӊԌّٕ֔ؔ؎ٓyווגאy֔ב}әؘՖ֓~֑~ғ֏ԍ֍Ҏ؍yԓԏ|ґՋ}֒zԍԏҎ͌ώӌ~ЉԆ|ҋ|Ѕχ~ΰʉΈ~ˉ}҈|эˈyϏψ}͋҇Ίω΅͊̆~Ї˄ˆ}ƈɀ}ˆΊ͆{̓{ͅzɇ|Ɇ{DODOHQGPEPIUIULSGQHUESDMGQDPCQCOEU@GCKCPBMBHQG=DAHHLKIOO\U\Hk[p]v\}jfdkqlqrqrsrynnwrsv|r푀hdrs\o`mb__QUAJ=N.G%A@+D=0H0J2G0N>S3K8L6E>G9J=L>J>J=Q?G=K:K:H8MJ;E:DCI:G?K?G9FDJHNHMGKHIILFPDJ@CCKCP>F=DCV7H8N7QVKqۿեŝԜxu璃ow~v魐ڊZzb[FK>F6G@OT`^ai`ds^hXaTa\[lqhgfiWbV]AT;P`q_kbk]n_kZ^iecmQ_V^[lQ`O^[j\iYeTb]n\eemlphhsxnkjwgjhjh|MjIfC_>SWnTv=e4X1Z~+Q6]u6ar1er/en.cl*Yk%]w.b9pB~y:mt7or5gk$[i&Ui$]bOaO]Km"NCuJs2XW;U @O 7R >R ;WHjYk"PJt2IJ_o Q\@fMi QeLgMlYaMt5fpK{y-do'b{:yYcFwz:oj,cVJP E\Uk6oryqLj<^>`@a=i?FfTk\mOx|0]l#JHdq}uYtSli{s\Yso~xʃz}}}}s─zy{wr땀vퟄ꣄<Ɵ굅ϊ[L@j!4X6R 3S 6T7Z6V6[9^<\a=bCd?h@c[8cCd\?[D`K`?w.VEfTqmuoyz}wxxu|p{mnx~ytԆ{ً~Վۗ׏ؗזԕ֔Օ}יהؓՑ֒~אՒٔؐ՗ӓוӕՏԏ}ґՋՐ~ӏэю}эҌӊΏщ{Ή{Ҋч{эҍы̊΋{ˆ̍ъӍы{ϊΆ|ъ|υ}ϊ~̋͆΅·}͇yϊ̆}̊z˂}ˆΆz͍ˁz̄{χ{ʇɁ|˅yIRIRLVLRJSEUGWGQLYETDRAQCO@QAK?MFS?N?G@LBIJUEGFKEGHINNUU]T_RgVvbxb}ejmpnrwntoxz왂ttzquivoyjotsarblf]OQPJR7E5F+F'?"A%>"C/A-F0G7H>N9J9GJCM@KCM?N@N;K=K?RBJCMBLBKJNAPBFHLFNDN=FAN8H2I:L-O=Qߖ`ױ׳Τե}m{k߇^䙄tॎqgΆvNX6I4LEN`hno\^fhhnfoZhW`c\k{^iSeGYC^NXdsfmZhej`m[dZb`cZcYg\n\_RhWgX`^iQ\YhakjpajcnjonqvziqlvmtSn6\|EnC.G@^>i|)Us(Yn+Zy6fxGswAvs?km,_p)\{0kJ{Lz6po-bd&Vn+_g&Yi$V\DXF_JfIEtdIy[>T]B] BY@aHl&OGo~8ky-eo(]|;r~?gIvFu;ib$bP KL Al7ounOFBB@BPM\Ԉypep[mZ_dszӛ۴䶞廟澪漧幪⶟߰ݵ޳ٳױ֭ӮԪլУժըڧةѡҨ֬֩ӪթϦѡ͢ӠџХԡԨԬӤ͝ѣ֪زֳִմٸත۹۸ݵݴ౤ೠ⺧ݹة֬ύTS6G3E*H'OpFe>iAz-NQiSl^iVz5d|)ML`{mSp`qxcWvPoew~v}r䒇xxwyzw뜈뢆ÖேhNw1_;[7T2W!?R0T 7X 7Z8]8_:b9e:`=h=k?ibDeXA\D_ KcNe!N9bJg^tl|wusuwwx~xummx||{Մ~֌~֒|٘ד~ٕږ~ؓ֏ҋ~ז֘֎אz֑Ր֒׍ؖѐ֍ӕ׌ՒՏѐ~ђӕՔёґϏӆx֎ӎ~щЃ~Ϗэ҉͋}ω͉ҋωω҈ӊΊ͋Ήъ~҄І͉͌̊{ό}͊Іʇ}΅z͆Ƀ~̈~̅̄|~y͆v΂ɂIWIWNVJSHRLWTbK[LVCRHSDQGSBNCMDNIP>I@JDNJTDLCJ9F=FMMPRSU`V\_jZr\yb~dkkolpsp}rzvpoourmmi폀mcl~ivciYe\_WUSBJ;E2F&E =#A,G(?8R5F7H6C6J7J7E7E;Q>K=N6D6I?LAK>L6G=D?IJ?I;H=IBKEN=IH?JkP>THU@ZHy9i?sT_>F}w(TY CV?V ;^G^EfPkRm Ob:b?fBe8f>h I`?WJZG[Cn%Pu*Q<[Qfetpzwrqvpwprsxili{yvуӎܓזْؑؔێ~ِԐՐؘ֖{ؑי}ӒהԎ֑؎~ӍԒҏՏԏגՖӏԏӏ}ѐҏ|ԓь֊ՑҋΌҋщЋЎ·ЋӉьЋ̅Ѕ͊~͌{Ҍω}ϊΆzΈ͇ΈzΉ΋φˆ{̈́{΅xЁxʃz͇Ȃvʆʃφwσ|΅S]S]HRMWGRRXLVBSOUEXJRIQPYJTAPBN>M?J@KALEOAJDJCJ?HHLMSRK_TZQi\nZua|aookyqorwt|tq옂u헀zolrygkj}hvcm\h\[UWSEI:J+B.H,C"B&C-B.L4M3F0H>P?Q=OGOAMBQJ@K=G?N=H:J7B9H?J@BFI?M;G>H?F@LHL>J=MDIBJIO@GCICLFLKJGMFOCNAJHLAE;F7F1H3K;L؅NŐϚΠȊ妑uڊoxzzt洆yocEO?MM]\^omkkeg`kcfhnci]^]mU]SZN[I\P[]qSd]cbk_j`lah`k\mWdXlWoThXh]j`xOcXmeooqjq^jW[UZJ]F^6UGeEhOp=f9g1_v,Vq!Tu Rw%U8jx+^p0ai/ah(\n&ZJx@vu6dq.ap)[b'Pc%Vc'T\I[ESBXKYNg#SG~k\aHR>S :Q >VDS =X@`N};eF~Fr_9LfFW;W?]EaGp!L5^z.ap!Ol&Iq&TcJ_GZCcR{AnXEzW FQ HL I\Km}Z$KF BSHj.gPy`qAbTz\jkЁש⼭Ẳ氟帡缪幦޸ൣܶܳ޲۱ڵٵ׮٭Ӧ׫֪֯ԦҥӬЯѰծׯϥҝԣҠњјНը֪֧ҫԧҫУ׮ررڸشڸٲٵڵޮ۳ܰާگ۫ݢ⡖ڏwz[j=Z,L*IBZPjFh4_r!Gz,ITmOjPgOiIv1Hn}qYr[mn`TsNmn|~Ń}u{xw䏅{{욅똅졌Ǣ켕ЊYEFd8W6T;W8V9YC]DT9X 8W5Z9^5d;ec>^=]9Z;`>W9_7Y4^9] 4a8l8eAeA]A_C]@`Gh(Sr$Rz0W;\Wjiwrwqskvmqmuq{ounuy~Ճ|Ԋ|ؑؓӒהٚٚטיԗב֒yՏו՘|ӖՖӐӐӉӎՑՓӔԒԏҍӐՏӎא~Ԑ֌ӏԍ~ь}όЉӑ҈ъ~·~ш҈|ωЍ͇Ίϊ|͍Ί·zΉ͇ϋІˌ͇|̇͆̅̄ͅ{΁w̅͆΃x́yɂ}z΅{́xERERLUNVNUMWQ`GSU^JTOXLQGRKRFVCM=IAKBDAKDN?BDK@GBLGIQRRO^V]RlenXu_fnnklwqmpwwqqꘁqry{rwjiki{cvcq^fXZWQM?J3G9I,J-B+D#>,I/D3I3A/B7H;J6HI@FBM@J?K>G>I9I>I9HEU8J=E9JAM?G@LAL>IDKCOBKCIJRFKLWOOGKCLEMAI?HAECK]FWFWETIXMn#cEz]sSYEz^B\>Z>e'KlSjIgDgHjSeCfI[JYLS @f&RR~av4jQ KJ DH Ac*]|[H>d(bAxNwk[s\sD`LtpŒլᵡ꽞漦㹦⸤㺬สߵ߸ݸ۶ٮٯװׯժӧիӫѨգҞժ֮٬ԭԮӬѬΥўϔЗ̚ЦթدիԩԧЬЦӱְسڳױׯڵ׷ծ۳ڪۡߩ㳨谭询誣䙎ےimCY0H+L*K;FYkT5^~3TA]GcCaIbIh=aFY{~g\s^a{OlIhcwɅ~{{ㅃy疃뗄쟅Ġ괉zc/;bBT9Vc8f?^;k ?kGh;gCj(Ni@i=dNSAMCOFQ:IM>K?GDM?K?M?K>IqX{qSuX@TpLxCq^=L`C[ 9[@g?e$MkHaDaAe"QhRbN`W\L]Kf&T^ej)]WNIGLGk4puz~Bsg,XZjfz6WJhVkEdU~ڲủⲒ滦彧㺦ᳩᶥ޶ݷݹڶڮ٬װԬԮիѬԭҥ̥ϧϨթԩԭҥկԪԡМ͗˖љʠңժ׬ԥѣҫձΨӮִկճұ԰ֲتעץרޡ汥벪뵪찥眗甉w~WggYi}nh`vhQvHkep|}ↀ品졉ퟎ碑⫃iWz$7\7Vh=k Ah@f?e>b;kAf?fCe#Bp%Gh`6f Ei#>cBi#T_D[Gb Nx,Zx)Vx'R?X\raoqyosl{jvlmkqgvlry}ЄӍ֗ؕ֘՘ؒے{ٖڎ}ՑԘ׎~ՐӒ~Րԓԑz׍ՐՏԏ~Ս֍{֎Ր׏{֑ԐՑ؍ԑ֌׎ԍՍъՎӔэҐψшҐҏЋҎΈЉϊ~ӊъч|яш}҄υϊ̈͊|͋}̈͆~ʅʄ{̉цy̅ǁ~͊yɀ|tˀ|ʀM[M[NRKPLUJXDQOUGQAOHSFNIUGODNEN?ECLBPAR7EAJ:@ALAGAEJLONXKg[f]mWvh}fdpzlyt~uv듀rpyrrnoyjshfkwZregR]_STJP7K0D'D&<+B'E-D/E1C3E6P1A:K9L;IP@M>LALJ;G?J8P2I1NAX~PʥʃĘ}~v{soB?8Fg]ߍ]kdRVSXZ[djesfubqcjbsUfWpWb\k\l`gabgs_r`}i{qa\~\Y~R~XzQuJzQvamdzg}a{\r]u]k_tbpUgVe[s[p>\>aChCe;e1\{0\k"]o0bs+]Q 9TATD\F\FX C^D~=sy0^@kd$D?sgKV =[;][8ekAl!Cj >h9h=c5eAl#Fa9h@g=i>k Da:_@`>\@\@Z;dF^;]9]8e>a;h ;jO_@f K`Jh Mm.Qv-Z4SIb\nhmxwtvirhncs_j`njv|΅֔֔ؕ}ٔהؘ֔՗ؓѐՔ֍֔}ԐՏ~֊zҘҖԎ{֍֋{ב{֑ړzזב֓ՐבyՐ}ԏҏԑ֍эъьҌΎБΊΈэЄщϏ}χΏώѐыЏxэҋ}ц}ӊ҉̉̊΋|͋ˉʀʇ~ϊΆʈσȄx˄ɉz΅{΀O]O]NRMTMXKSKQM^GOENCREVHRGQFRDOGQCLAJGS=FAI:IAK=D?DFIOMUN^Wi\nZxd|oglysqpꘁl}wryzwrpy}iluditan_fP_aQREO5J0I)E-G#@+B+C0K(?/B7G6G7J>GLCP@O@OK@IKCQAODOCS?I>MAL5IGOCIBLDNDNEJHMILNYJJEJFKFMLOHOIMGPEO@JBJ?N6K+I7YSFwƐˍ”~}UV3GHNypx_hYRYSWV\X^chdk\nW`O^WfUgYeVc]ibfdqf}[x[uiusl^iqha]_^\LtYyggc\nanYkE[1M'H-G.O6\8d-[&Q,aw-_u-f7l5lL~DnSPm)ReR]NZKVESDSES @S CV D`Kv)bShhn'JU ;O ;P =R ;cHdPm%[k(Xs-`l$Um"Ll$Tt1`iPbIbFq,\z0btInRaF_FdNlZ\N[OVDr7i]}?tq-z\VOKl6tsnTc{ɐu}Sx*XOkf{zЭᳪ嬓㴟嶥೤޶޲޷߸ܶڴٲرثկԬ֭ӫҢӥΧԫףӨթְ֧ץԥԞКΠѤϡРԥϫҫ֭ղӪӫҧίֱ״ҫխҥԩۥ᫥槥禥鯥곱鲱簧鳨緫紦㪖⠑ފlsXfCQ;HBeZ;ZAY@X;Y=W9Z=_9]c9c>iBbf E_^8_6`@fBd@g!@gF`;[?a Jg"Og O{/R@cVlbnnwrxpnkujsesdokzpqʃωՔ֒טחؚ֓לו֖ԔѐҎԐԌԏ׏{Փ}Ցא}ғԌ֍~Տ׏؊֑ؓ}ӐՔՍՌ~ӍӖӎюАЉώыӉѐ~ΈωЈ}ъҎЈАЏЍюы~Њъ̓Ћyχ̉ˇ~͆{͍͇{ɃɊ|͉х{Ά·}Ȇ~ʈ͈y͉σwK[K[IQJTOXJWITN\HTDQGUKWISFSESBK=M?OAGEO?JL?O6D?N=OCLEO?NhVemdUtMtEi;dr*Xl#Qx&SAk;l+Zr%N5j;j7iFn;pDvGxO~7cl-ZaMaIYGWD[FWEWGR?[OfLz8rdX~[eDP8O :T C] Ka9|F|IZ;h LbId"QiMfLiLgYo!]k Q|1gY>YCY<]:X7Z ;Z5e9gCe;p!Gd6g!Cg"Fk@e=h>^8b=a!@e=f;d:lCk<_;a5X:]@\=Z9b7cD_=af=bF^GaEb#Nj#Rk)V{.PFa^oktosvtqugqiy`hdunztxφ{ь֘֕ט؜ؔՕ֗՘ӑzғՐ~אԑ~Ւ~ӑђԐӐԏ}Վӕ֒֓֐֕ԕӌՋԏ֐~ӏԑՏӐzҌzΌώ~΍Ҏ}ҍҍώ~ЍҋӌӌьӍ҈ьыχψ}ϐΊϋͅɇ~ɋ}͊Ɇ̋˄̄|̇}̆ψyʁxɀvɈ͂y~|΃~KQKQJWKUKSLXHVNWCMJTGRGQAKETCMCOAK?OGSCL>JADJ?PEP?T?KCSGRDLHSGSGPANHNGLKPEQOQMUMWJPHNLUJLGJCI8E:I5H6R-PQLuڽŪ{qysKQUPגf[gbZdNWV_MTTU\iPbOZH`OaXcnn`w]mbjceg{bqc|Ui\rYoWmMgJhMiTpZvdjf\_\\TzZPI{EzXF^Jr$]c?vBlDm[=\@`E\B^C_EbJk$Xi"Tp"W|3lDr>wIEzDK?6wy1rKi~Axv7oq4zp3ko+Zka{:GKibqfS^ҭџƓղگ௔㰦ૐۯ٫۬ܰرڳձԯ֨خҪӤҦЧѥԧԦӢϦѤԢԥҢҜҤѠӡԣԥҜԘԥѬЯҧְ֩ԮЩѪծרܬ簩볡뫝篩릚첥걫貫￰뻩귮䫛宗ᡚ݆hjXgCN8G;Ng<\A_9[ 7Y 8Yg!DnAf=d9e!HaA[ 2U 6^ ;`8eA^9c7l>a?l$C`?[C_D]Ik+Vq0_u(M4ZSk`kisptnlhmeqgp^fi~ps}Ј~ӑ֘Ֆחٔ؛ؘ֛Ցԕԏ׌|׏ԎՑԒדӓӔԓՎՐԐ}׏ԑגՎԈ֐֎~ӍόՏ|ӒёщӍАҋЍχ|ҍ΍ьщyЏӏьэ~Ήωь{͉щ|ϊxЅ~Ћẋ͈ʑ|̌Ɇ~΋Ɉ˄zʆ͊ɇχ|͆}́{̓tȀ̂xIRIRJPLZMSP\LWHOGYHTAN?RIJEOKPEODMFUBS;E=P;L;G=I;M=FCIKLZY`WbWraujirtlmwvqusu쟃prurywyptphe}jxgoXl]e[QQBK8H.>+B#A?!<)E.F*A5E0FMJJO?M@KHOFQGSCRKQCMFPUYMTKOPVMSGMJNMSGLINJ6H6N0QARފ^ְٯѷﳃr×كf`bfSi_[\V[[WdQZS`TWW`S]C\CPKcRd\c`q^dcncph{arTjMeYcQkH_A]Ni[{[t^obsiyf|axggsobToUlT}?no&\o!XpMs%W{6h8k{/dt'[+]:f>k'Zz2`DqP}DuLr/Ym(Zk/WbNi&QbMl)V_MRIUFVFbKp'`z8i:px.YPs,^VDWCePjPl*MTr.OX=_C]@cAbDbG[<_D\=f,RcHh"Hh'Nv/Vn)Se"LaCn.TjPi"Sz=pSe Np1fq4rn#_g%W[S{8}:}Gy|cQίѝʊʗٰٰ߫ݭޥڧڢ׭֬ڰذ֪԰שըӡҘ՞ҡ١ӣРѧѣԟӡѠҨӜҧСѡөҟѢҜѡѣӨΧҪЩϧҥ٨ۮⰲ谭鰪밪鲣궪벧뱤쵳쳥イM궮챡橛㏋{vmkJU=M5D=H:^2cf!Ns&DV^n>c9Z>\|:hx+Yn'Jryqrptjtɂ؄ގtrffWPV4Jm9\ :Z:[B[:Z 6V;YAW@X=[A`@[A]@aAd9d8d9j@k?d;l@f;eAf>gAk!>h?k$FnBj >k"Gf!;\8\4Y7Z9Y9^;`:`=`9e;h@d:b=dE\N:I];_a!H^A[:dFb Gc"Id%RU=VCZF[=e,]G}aMq4hp3fk%Zm,VWLi-f~Hi|y`f—әŊΚ٨ګۡܤ۠ա֧֮שٲװӫԪӡПϝϝҞћΚОѨѦћНИϡҟԢҨբӞ֡ӦѢϡӥѢХϤ͠Ҧ֤۬ᱣ鶮붧鰣絭갪谟쯭鮠췬볭궰鲬ﻳ벤埏⅁opSXAS8F1I4M8Vt*WWI`!5nvj:Y8];\Ali(UD[r}spvm{чҐr|]bTPXbe5h:fAh=i@l ?l$El"Bh9i>l#Dm#Fd=g?jAg@f Bc<\<\9Z :X7^B]+B3C6Kwy3hq(U_A[=V9\CeB^@b;^9]?_;_<^A^B^@bC[@^;]=[>S;U;Q 9VB]&S~X?V :Y:Y?`>\9bAiCi;f>h=h9j!CkEnDk#Do>d?hCd;i?iBk$Dd?f ?_>\:[6\9W 2X8\:`;_;m;j!?l:eD`>^@[@c Ks&Sm'Q/UIdTdl}lrptntgjdm_n]jjtjnvxDž҆|ٔ֕֔ڕӒӘ֗ז{єה֕Ւ~֓ґԖ{̓яЏՑՓӔюӓ}ՒՒՍҖӑӎԑӊ~֓Ԑ֕ԑӎ}ҒВҍӐяՓԌӐԔ~ԑҐӎЌьІzҋϊ}фvАЅэΉ·{ЇΊ{҉Їω|φ{̂}Έ}φzʄ́x́zʃ͆y΀xGTGTPXPVOTIWIVEQGREPISEKCOFMKFNBK7I9FAN8E;EFJPLVSb^`UnZwj|h~ggsyxxtwkztxysvyt{nvnvgudn\kZ_VVVIL?K/@%D"? =(A&D1I,C8K:J1GL=NBO>L=KCSN@N=K@L?NCNAI@LAQELCOIPHOEMINMXGRTYST[eFRX`IOOSHREM@I?O1J4N:QePƨ˟͉Քӥ{wrvsd]XdYc^a\_[darQhTFXTpRa[hht[l`k[gUeXhSj`yQfM^\lkpmohi`dckgz\n^nPr]AX6XCWDQ 9QBRB\Mw6or+\6`P|S8g{9s}>^Vk6pPR`fy|Ȕқ٩کؤ՞ӛեզ֪ӦԮҨңϜ̜Ϧ̝̘˓Мѩ֣ў͟ϢϞПӨӤէԥҝפͤͥ͜Ф͠˓ɛ͜ٮ氣뷪긥컫컰충뮩鵫質걯밢촯붭쵲쳬츧ﺪﶡﰛ뤘꓁|wcaMR@J>H:O.K}0F+SgQS=m&;XvA_C`8[3_fFJYpojo{}Ņ|}qz_bUYIQ2Bu:aCU?T 5V 8Y>X@S:W9Z?Z=^@\;fFj:f#Jj>jCd?i?j>lAl!Em!Bj%MhChAiBk Ed=`=a<^:c>^;X=\ 9U 3]5aLDPCJDMBOBQIQEWEO@OFQJ?M`EZ=Y>\=`@Z<]B]=_F`%Q]EY?T>VCV@TEQGT=g'`DwY9V 7U =Y;^A`cHW6aES4Z3\:^8\6b8g=b<`>\?UCbMbHo!Sw,PA_Tphxhrtwksillwbh\hgtnvuvǀ΄yЋҐԕזәՔי֖֑֕֓הӗԖՑ֓ӏҍ|ӖԓՓ~ґ}Ցҏ֑ӎוԏՕ֔{ՕӐԑӌҏ~ґӎѐђΈҍ}ЊӋҍӇԐ֏ҏӌ}ϋ~ъΎЎΆ|Ά~ь|φ~ы|Њ|ωϊ}ю}ш{Њ}͆{ʄwσω͆ŷyІzˋ͂ͅ~~JYJYKTFPLWGUEOJRGWFUFPHZETDKAO@N>HDJAR>K@K9A8E7C4CBRCINM^^XQk[n^sZzdkfkrwtwwp{zzvy{sx~unpsjpyaqbcYcVSOEL9H)A.C#?#>'@,E.H+E/E1D1G7Q;H9I5L5L9HCQCOAO=KJ@V?JBKFL>KGTHPGPAKDOLTQYONPWORQYLQJSOQIJLIIKHOBK@L9O5P/KbUʩئԮȕБҬƋő{}]fSUZOWTOS_[nWb_dRbV^Q`[qVn[h_dZ\\nUcN_XmPeUk[k^xchmqrtcedefedl_n\oYfVmKj:Y=ZcpSfL_8W6U2U%O,X3]z0pu2ch#Rd'Of S]DVIPAUAbNc Kn-az1ap/by3hr'\m%Zo*^p+^:n3kq.[h#We!VX @_Mx0g{6vh[TD[OXApd`FrZ@_I]A\<_$L\@T=R6U9S?P ?RAWEh)VEsO{lOa9Y7_i:mAk"Ck@j>t2Om!>o'Rj >gAe7`8b:e=Y:Z=W6Z6]9V2aZD^I`NiKv.Qz-XHd]l]nowropvjlgtguafbmty}}ʇӌ}ΉӑyӓՏՔ՛ؑ|ؔԒؔՓՐ՘Ӗ֑֙ё}ՒҊԑxҎӑҎՒՓՐ~ՍԔӏ~ՕՍzЌՒuҋ~БѐӎԐ~֑҇yԈӍӐӏ͏ԉӐϏϊы|Ҍԑ{ЍzӊЈΐ~ш~ҍ~ыՎ҇|όщЎ~Ї̋}ьτ}̃yщ~ˆ˃x̅x̃˃yN_N_OVFOL[HZFUKVBRFQISIPGKIRAJ;GAL@C;MDL@F6D5G:G9MEPHKNQ\[]ReZk]p_|d|i`h딂lwvwqw}zvvzv{s|in}e{gmal^daVTHK:M*B(E&D#D/J)C/F,F:J3I7M=L@Q8J6J@R?N=M8L=LBT@K;MFS?LBNES?M=J@QBMO9J>L@LDM@LBMENMXDMHOFPM[LQPTKVNTQTLYQPNPDJFKBIFO@HwgkVExcGU=[;Z?]E]<^D[?[B]F\DX;W6YFZES=VAN5N9UBM<\Pg#S8^Yzt[b5L)P5\?kQLi‡rɕ߲ު٨ڞۤ۩٪٨׫׭زٶز֪֮Ҭ̢ҟΖ̑΍͚Ι͚ТԟңӦԤԭӢѠҦ͝ʈȌϜϡ͕͗̚՚㡛諛밦붭춬골뷫輳콱컫볭귪췪곪쳧췮귶볫ﺮ﷪쭟줗镇~}zdfKN:H2B,E/J~)KiAaAWFQ=d:XkLg;[x,[Nu Ae@[:[CQ 7Z?[;Y ;V9[BXkAh#Ah>h"Ao+FjAhCe;b=`=_=s+Q[bTkfpmywswppkqek`ekwfny{ƃˋҎь}ӎґ|ҏ}Ք~֖~֓ג֐ד{ՔԑzԑՑԖԎ}ѐ׎ԓ}Տzԉӓ|ՍyԐו~Վԓ֊{ӑӐy֐Ӑԗԓґ~ӌӖ|ՎԐՌ}ѐӎ~Ԑђ͑ώΌҊϊόЎҎъՋЍ}ЗҊ}ԊЌԈwшΊЉЅzъΈщ~Έ˄ςyɁ|y}{ʁ|ˁIXIXAPJSDWHPFSJSHSJUMUJSKUEM>J>JAR?BALO=N:K:LFQBTANDRCR@O?QBNFWCQCMKS@MHUBMAO>MAO?IBO>L>N@M;IkCf?{.\N~?ot/Zk(S]@[C[GR>QfBc<^AWA\Bz6TFb:]|0V8eu-QZlvoei}˂zvnnOR1EoAf=]>[?Yd:gi;k#Dh?cDr+Rf=j>h[8] :]<`=j?h>c?eDX:Z>XE_FhK};^Jh\no|qzuspvkooxlnfqflvzywƒϊ}҉|ώ~ӔӎҏԑՓՖ{ՔؖדӐՓx֍ԓՑԓӔՖ}ӕyҎяΏҍx׌~ԍ|ՌєӔӔђ։~َז֑֓}ԏ~Ր|Ӓ}ь}ґ֑~ҎԊzэҎҍzӌҍ~ЌӐՊщ҈ычь~Ҍэ҉҆|ЉъzьЊzӉzЉ΃}ψvˈЄqɂ́{̀x͂v~MSMSMVGRFTCRNZLYMXJRKSPUBJHVFQCTGW=GFNBQ>E:D?F9I6H:GDMJQ]Y^XaQlkrX{h~motwpsyytvyx|uxvyxvkppt}l{hrkiXYQSNHP7J.E.B&G'D*C&F'B8H7K2I>U?R:NJBQ?NGU>IEP>KBMGO@L@M@NBNBNGRCPFNBRJMGQLTJORTRXUZVVPXOZPVOWORDLGLOZ;M;L/N6N`[ѫЖգʫƂғբukNSUCM>KLSWWZ\^`UdS`]j[n[dX__mYn`lL_G_BXQcQi]jkedu`jjlmuakbhjsSeP[R[\lcnYuA_$Cg;r;vBlDaBXBc Ew5eHvx0UgEdFY>WAZGYCT=YFXI\K[N] Ns0]H?rs1]j#Wm,_t,]}8g|bCY9]=T=VBN 8O7N3L ;J@RCfKFf_{cVs^;b+QQ'Da>mBaHV@X`>`9Z:c:g8fDh:j;iAj#Bn$Jl$GoHj!Fh#Ho3Ro)Fn(Kl%Ij'Ik&Ff=aBc<^=`;X 4aBdg:b=_@U7YA\HeMi HA^Si`nns|txxskiriodmckmsv{Ɓ̆·͆vΌҏyЈ~ӑzӕԑ~ח|ԙؓՖԑԔז֑ؕՑ֕Ւ}ԕҏ~Џ}БэяЏӍӓԕҒЍҏԑՒԐԍ{֑ԓ|ӕЍӎ{ӏыьҍϊԋՊюЋӎӉцzщч͋|Њz҉ыъх{Њ|ЋЏэ~ч|·͇ӆ~̉}ЉwЅx͆{φ{͂||IZIZQ^JSFRDSISIZGQJ]GQETIOITO^>I>IEKBN>I>O5@7D+D/C4J+G@T:LAVIMGVKDNDL>IDOHPLXBKGMJWORPRRWPUPZRORYOZQQJOQUKJGKLW>LXETA\HUBZITDXGf%L?qHl?on&]jRl'W}hEe#GZD[I\<^;X9`>[<^7cAf>e;n?n@nEm:mCh?g?n FlIl!Fr%Mr.Po CkHp*NjAfB_?[8^>_?\5]6Y 5^=h;c9h:a:c;\:T>YJ^MiMv'N?bQggqttrotyswuwapirkmquz΀ȳ}͈{˃̀|}yІь}ӎ}ӔՓՒٖ֒ՐӎՓ|Ֆ֙֕Քґҏ}ԏӖ}яЊzԎՋ{ьԊ|֏ԆՏzӐԉ|Ԑԕ֐֍y֎֒~Փ{ҐэӎՎёЊЎՊՑҎыχόъ~ӊЋόҋч|щ͊Ўӌъ~χ҆̅zψ}ՆyցtІsχ{̈́́}ǀ~}|EYEYIVKWFOH[ISMbELQhINFUO]AQDR>I?L=L>IBM@I:DN?S>N:JBT@MCNEVGVBR9OHTHVAMBS>J>R?Q>LCO?K>KFOES?N8LBMAQINN^HMISEJLRJUKSJPRVQWKRLTO]PSLNMSHRKMIT?H=P6Q6\JNxپӫ͎ԣ͞ʅє}mSMLBNELCNFLOQVaRUT^M^S]Q`Q^YgR`Q]Q`P`OaV[^h\dZeXe^f_`UZclmtbcP^Oc`n`tWkZoWd@a`?[;Q AU?g?i!U_Bn*Y?tw-Pq%RbB]?XDW@^;^EVCZA\H_PWD[I]Hn,]Aw~5f6siTi%Sx/c{4`Bpu1gf#TSKUG`$FN}8oR =N ;QI`YZJu;v^vpQNCEwA~p.caLR;M 8O N 9G 7Kg4_IcXwӦ۪Вvb}ɝۯڰ׫գ٧ױׯٱܸܶܺ޷ڲתצ͘ЙДȕƓ̐э̕ϓΝӠўϪѭӬӦПЖ˖Ύّ䔌蕎꓊蜐觕ꡟ饝騠謠貣븥촤믣괧ᆵﻯﺪ﹬ﴠ옍燂uq]\IR7J3D3M(Kj:U@Ud=e<\;Y=U<]>]<`A\<^?aAa?g:di;n(LlAj=l@m'Gn$Gm$Eo$Il"Bp#Ej"Ea6_;];Z6Z9[9\8[8^8g4fDb>b9\;Z>ZFZFbIo$J6ZOh_onsxyv{tqpnnsgpipup{~}}ʅzʆtˆv~{DŽ~́sυφЉzӐ֘|ӑؒz֕֔}Ԕ}Ւ֗דҖՓՓԐӑӑЏю}Ҕ|ҒԎӎ~ӍՏ֍~׌ԌՓא֓א֒ՏԒӎԏՎωЎӋԏ{ӏ҇|҇̉ЊЉҋ{щыЎ}Ύ΋yχщ}ы~·~ы̃}ͅ~̋ӄwώ|·wЅx~z҆x~zLXLXKVHWLPQZJRO_FKJY@OEPGTAOFUEOCNDTCQADAJBK?J8D8FCLHOIKX[_Zf_kYqc{i}jgy鑀{듀p{uzzz|zwvy{{uonoxho_oe[RSQEKDJ6F1J*C;+B)=*C/C1F/C5A=ZGXP^hghXgMcKfObYhbrbt^oOnvDhYCSCR ;YEhEp$LEoGriC_>Z>\AY;^KW@Y8V;[7]BVE\HTD]Og,Sv3b:iw7l/liTq"Uq0Z=l~7Q9Y/Ys$Tw)Q[qʊ̐՗͉\y,Fe>]H_A]h@h =d=fEmAr'Mk&FjBl%Cn%Fk!Ah;jC\7[:gF[5_=`9\ 4a;^2g>f9dB^;`EX?b"KbOhHu/T>WZohmru|yznpupujmkkotyx}~ʀ}ʆ}ˉ}ɁyɈyȀ}āvȄ{Ʌy͊˄ˌЋ}ыzԒӌԔҘ֙ӓԔՔӔҘґԔӔ|Ҏ~Ԓѓ{ґ~ԊюЎ{ՐՍ֌~эҔӐ{֑֒{ՏԘҏՌԌՌ~ёӌцyҋҍҊ~Ўόzщч}ҍ~Ҋ~Ԍ}ώ}ϊ{ΈЉyό͎~Ѝ}Ί̆~΅zΉ΂yϋ|́w̄|υzЈy~{~{BNBNMYIYLRP]DRJTIRFO?NGPFXBOATDLEKFRGQBR9JCK8G9J9GCMEQQVYU]ZfaiYtc}rsk|un}{swspq}yxxy}{qxrhn}kseic_WXXCODS*B&?(D(B#?2L4C1G3B4H;EM8JGX@JDOFP@MCMAO?OGQIQDU=MM?P?M>MCPCOFMGNFQGREPFMLQLSJSLRRVHPTVUUUXSVKQLMJPMWJRHOFL9LEV=V?WrSƕڰүΈӢќ~_GKHKGSGKILHNGSHWJRN[XYTcS\\^[mWhO]Tj\k`e\cb_dcf{_bhlK\4LXiYjO[O`RcPhYrJ^MZX|Oi}+I[>V =ZB\@q O=dJv=^_:\;W7[DU 9Z>^BaJbD_9Y;bI\DVHSH^IbKt2W|{Y=SAh \e"ZTM^Mq=fq>i_Gj%Kl&Pq4Vl)Pg&MWAQ>N ;H7G 7I :H8I=O8=bnΆyڈinOdN]Ii\znj٩۩ڈՓԎŃli~Ӳ֯Ԣآ٩ݱ޹ܱڳ߲ީըџΛНΐ˔̐ɏȐȌǎəͦҩӬ׳ҤӥҌzցቆ䏉双錈晑虒硒騟쥖ꧤ쪦뭢쮥붩붦볨Iカ콵MŸƷƺŹĮŴŵ´ﰝ뗉䈎gbMQDK2B4O*D{>g;S :V?ZCYC_Bv%M~.M:c+ap"MJf~}džНӎ˅cw-Kd<];a:^@^@[=Y9]>`B]] 9^;YCYEcJm#S4SE[^tks{}vsqpmllrgqgmqx{ȃ}ʈ΄͇{Ȁ˂uȅ{Ȃwˁ̈|͂xȅ}ʇ͇ЋъЉxюӋԏ~ӕ՗Ԕ}ёԒҎ|՗ԏՔ{Ցzג}הԎӌҌюԋԍӑ~ѐӏ֑~юԐ}֖ӏyԏՌՋБӎЍ~ӎ|ЍϊΌ͏ψ҆чψwӌόыЉ~ЌyЌюwԐyьЅvЉxΈ|φxЇ̓tЃφ}ςy}{΁tETETEXCOBMGX@SHQJUITIQ@NDRDQHQ=GAKHPEMGWCN?J7D5E9C@KBLMNTTa^fZo`uezd~pszulxvwyttwutztyn|tvxgkxwnf[^[XfMVNY5F0I+G"<=,C)A+D4J.H6H:LBX9I?N7JEVEOARAN>HCP:J=DCODN=JGOQANDPEPAPESAR?PGOANFR@KCMEKGOLQHPGRLUKSOWU^TUV\ONNTMQLNNUIMIHFR>O9L9USPzհ׮Γ֔ԟlVGQDMOTNTPSLXSWJZITQXWSQbLZOYVcOZTakugr_cU]\d\e^b`k`bSf5SF^SkPmMhQbO`E^5O5Q2G?Wn$O_F\DaHbD|8dFpGz3VbEW=UH 5D3E7G>N 8x0Tu˖ڄvknL[KaRih~ʌحಙے܍܏Ԑ̐sksɣШӨ՜׏צݷܶګڮڦٯӧљҔѕΌʘƐɖʐɕ˓ͣ͢өرթї{Ӆ{Ӆ㈁匉蔑䕇閆蟞夘垘譜馜촧볥췧쵩칪츯뵩óﺮ°¶ǹʼȼȺ÷ǹǸö輪臀vrV[DK:J>I0D>j 6T?O;R?WC\Ak?v'H}1Y)[s"P;arŎΛДƂ[m0Kh>W:f@a;b;W;Y9c@iAb=]:b;dCi@e@fDk Bq%GgAm!?i?iEi?gCh Cp(Bq(Jn%Gk?c8c;^;Y8\:[ 1Y3Z 3\ 5^9c;h[<[M8JX ;YBbDmLc?\?aKm#L^@^DY>\LYCaEk'Q{7hw1bs1]n%Yf$Rm*`cRi'Zz0oq-Z}Avy5oW >P?q1nd!VVXWFyDny{BvS :U=Q :Q 3V>M;M 6M 6J2E3C7B;MI8F-@$Bq6X 5L 9Q =W?[?_Bv"Hx)Q|3W|'Zk#H\qʇۡםʈf}.Oa?\>e?d;fEY@d:g;u)Cz)Fi>i?k&Ik>cCc EiGk=hN?GCO@M?JNFS?J?OEPCMGOCPCNDRGYAQDQFLCMBTR:PCT|Sɘٺب֤Κ褃WOOUU`HPMRSS\]ViTUT]NWJQN[BP?QH^[ig`llbd\]`kV`T\IUCNL\1Ss%Mk&QoEx.Q;e2X4a*Q,V-R@^?_=dy%PlK\DaJ9eQBneDZ@T7UV \D_GX?`Ad!Nd$Kh*Rz/mhIf Qn&Z]P_Ps.`;n~G{z6k]LZ!I}Lb [WPTMh'U`|YVA[BU>R8R 9M;M3L 6H 7G4D 6Ke>n;g=d_?^9^9_A^:`=a<`Ag>h;h@f9b EY@V?ZE_KfG7XQibhsx|}otqlqlneifxxuǀz΃wЍԒώyщρyʅʌʃy~{˅΃}ąɂyɆ~{|~ăʇ˂˃}͇ρ}ˈ͉̉Ќ|ҍ~ϊϐ~̍zЌ~ђ}ԏюАӌzԋ֐ԍԑҎ{яՑ~ЎЌՒ~ӏґӌϋЌ|ЎэԌӌԓ~я҈~҈Љ{Џы~҇}цzъ|҇u҉҉w҅ь҅s҈}тxЅyщ΂~΂{΅|͂}}t?N?NDTQXOZIWCJ@TP^FPJTMYCMFPGNBJESAIBR@JEU;K?K:G=S@FCMLNSP^Xe_uktb{hmunsvstx{}xl}~xxw}vqpmqoxmnci_c^SYHUDQ8K7N(C%?+B,C.E)D3I1B3L;K4E7G?OAL@P=KGWJSBSCOHRDWCQMZK\CQGYKTCR?LAPFW=LAPDMAS=NDL>K?L>QGYFZJWsxݬTJLIQHOQXUZPTTRJOOONRGILTJPGJKTAU?RD^^Yp߽۵ڡ̞kOIQQQVFRSSTV_[W_S^S`S]DQCSAWG]dgo}dfcccf]iccju\pV>\D_A]@d"QcH]E_Dm*Xh%Qi)\a R_S`Gp)]@uH~Kh Oh,TSdPUMZRdOt<\lhMS=Y=R:Q :S 1I:K 9G8H=I ;aCRqۊxqsZcIcH_\qЃۥॕޚݗِ֒ؓڐؓЏq}ɥá̤ذٸ׶ԳծکգϗϖϕјԙҜϝΜќҝџԜЙՆvvzytވ}冂䑋搆故㘓噑晉碚騜髠誝ﯡ쵢ﵣᄈﺮﺬ컲ñƻ¹Ǹɼó¯dzȼ蜑片ghU]GI=K4J*?z?b@X@S?T;U :Z<^ :jDt,P7bu Sv&FwdžБؖΕoHfiGXGn&Pg(LfFbCW8`Eg#IiBc7d6l FgCcBhCh @kFfCiGl Hi"Cl&Iq+Km"Eq+Mk-Mp$DeCcJbBZ?Z;\;Z6^?f<`@i?k=m%IhF^7R=YAXEUBjJ5[\kjuzt|}wqqinolpkrouzxɆҌzԍӐՉ{ωω˃w͇ʃ{Ȉɂȃˀ~t}DŽɂ~Łývʃ}Ȁ}ȅ}Ɂ{͂y̅̄}͆˂}Ћϒ|͑э}Ԏ~Ӎ~͊ҏՑ|ԍ~ЋґΌՌ|ԏ}щ|ϏЎ~ԌӐГΒύ~΋Љώщ|ІЊҎϋЅwψЌ|Ї~҉}ч{чxчyъΌuЉ΄ӂzч|ԈІ҃˅~̈́~~тvDTDTJTEQDRGOCJGRGTDOCOBQHM@OFKBNJQBM@MCQMIXFUFTDVHR=QJRLRBPCR@L=QBRIT=M@M@JAO?L=MATBQOZxl`QNHPLPPYLPU[SWPOMOMOQHNQQTKMMMKPCTJ[D[NXVרڛ̥lLMFNUTP[PWURZ`TV_[SaK[?SW@WGZCl!MRWx4YY=XBVDWBS=\Je&Os,[l%O^B^Ki McEYE\F]DdEbGs(V[EWEXCd#Mk#Qi&VeR^NZPeWv7iLUMDsen#V^VUMaQe%?tzo.[N ;M 7PiA}0[%^^<`rǐםјozOmq'IXGcB]=g CZ?V?\<^;f>eCf;ih"Gi ?l"Dn!KlAi!Hq+OkDq Gq(Kp)Jm#An"Cj>f>e?[:Z;Z<]6^;_>c9`K9M9N9M@JAJQ[TQ_]h]ncrht_jlotrvt얄vvx{w}trmvqrqhgydsdiac\YZQVGV9P3O$B.G.H!>0G,B4H4H6G?O;KBSV;ZDW?j(Uy0cy+WeJW>fLm S]CYA[K_K`Fo'UdJcLUBZ@cJi(Zh!ReJcR`S_Pj%XJ|XPbjw7ih%_UGdXaD~Yzy|CiR=I6N 9D5E 9F >?;H <\GD`~ڙzzqdm]fUe[l|٪ݭߗٗ٩ޡۜ֗גՎ؞͐x~̙֪֞ОΣџح۳޻ܶ԰իѝіНϝЗўР͙Кӛѓҍ{}wnuqxxw抄包告擐双甌斑柖额觚ꮞꮢ鮡鮥맜캨イアッﺯŲźùŹɹŶźƼɵȹ˺Ÿ鍁{r__MR9E-C)B:v8a>P;O5Q:V <[7aEbCx1[2j_CMaȇȋښЕsz[k}/Q_K`A_@b!Eb'HTA`B^>eBd;e>g>h?hBhBk>jFl"Eh Fg%Em#?p#Nn+Iq/Ol)Gl#Eh;k>a?i=Y8Y;Z4a?_=_6eAh9p!Ad;b!DW5Y=UBY=_Fy1XHecnuttvxxtxtujlkouu{zΆ~ІԑxИє͍|ύ͈̉}ωx·xˆ̅yȅDŽ~˄zɃ˅tȇǀyȅɆ{Ɂ~|x~wȃ{́{ȆȈ|ʁ|ʅyŃyɈ̀{Ѕˇ|΅wσŭ{Ѕzыϊ}Ί~Ҋъ|ӌzӍҏ}ϓҏyΌҐЍЎҏҒьА}Ҋ|Ό}ъ҇}͉̏І{Ί|ш{ЈyΉωzцvцy҅|̃Ќ{π~шzЃ~΂wІxρ~҂}v~qFNFNNTRWKRGUIQNTJZESDOCPCRGUJRFQBUALJTERAH=G;E:E6D=GFHQURN_^eam^tgxjjmrxzuu{w{u~uzyvsm}nnugxen]a\a[NWKWCS:R3M(G&C$F1J6H1D6I3E=N>P:M=SISDUCX@OFTERCREUHSJTKVKWHQ>OJTFQGUAKFP=JCQAKAM=Q?PDUEP>NDRKMl_fbNMQVOSNQSTNVQTNQQVOTRYQWPPSZRUPSRZMOJOKZKRH[SaSԡ޳ֱ䰕^WKLNRRPSUKNNUKPPRPZSZQ\\e`c[g_hL[SVfeeyaicvcmak_pSaG\D[J^IdA\9[5UjFbI`GaAcFf!CT :S>O ;\@fWd@EfPo'KV aKaHhIcKXAUb@];W7^`DT7TAYD`Ik"LA`Rfiupn~{ymxooggfgzr}ˌԌӗѕБό~̎ьzЈzɋzˉ{ˊ͆}͇ȆxʆȄ~ɌǂʂȆŃ~ɀvƄ}ǀȳ}ȁ~{wɅwˌɀzɄŅʁ{ǁDžɅvǂʄ{̈́}Љ΋~ҏϏ|ъ{ҍҏ}ӌҏьύЏыϑЊЎ}щΉ͋҉ы͉͉~·zψ}ҋ{ω|σ~ыyчẇЄ|·vΉЀ}τẗ́z̓y|{ς~{}uytIRIRFQKVKTKRFQBNESFRGM:MBRDLGM>M@M@IBSCPAL9GRFUFTBVFTCOIUEM@QEOOR@WCMAKFSAJ?KDNAM?N?JAIP<]C\ AZ9@dYm$IT=W>WBV>bMm&Sh(H^B]AdIn*XeE[?X@^FdIc'LdJZFZGWF[Cn)`g!T[EXG\If#Pw0f:u/^}@~?yu)[Q|LEx7}}6|k aR~YcGM7A3?6A >PA8[ur}ۅeb\YtO]]ts؟ߵ⨐ߐૠߦܭ؟٢ڠ֤٤Ӣ|ΗҔәף۩޵߾۽¸ڴԢӗϖПӠМ͖ˑ̐˖шyzrr~xyツ䆅挀撊唉攊撌反甁Ꞝ꥗驡쫞ꯨ찧챥ﻧﻫŷƶûĶȶƺĹƵǶƿŴű虍ulhMR=J1?4G%A:h :W 5H4K :N7X :U >`Dp(J=n{%_p%GΘȏԐΜkrFZ?VgJlD^IaD_Bc0UiIbGm!Gm FfZAR>XD_IhK}7aFd`nostszvyxsrpsilijy~ɁΉ~Ւי|֘זҕԉzђψ҈|Ά{͈uˇx͇|Ƀx́vńɂx˅yń~ǁyńȄ}ƀx||ŀ}z}ȁƁyȁ~ǂxvƄ{ń{Ɂz„~z{~|uɁzɂ̄˄{ʄ̋{шyы΋ώҌϏЏϏ͍~ϋь΋щzΆωyЊ~͆zϊ|ψЇuцуu̅҅|̈z΄|ω·{ф{уx˂rɂz}t}yсw~t|p|uBQBQKUETJSERHSHTGPCO@N9O?JCHALCSENENBP>L9E6G7N;JL[DPDLCKSOXS`Yk[r\wd~hczs{vrup~p움{q~ps}xrznqmv`o^o^b]MUSU?Q;U3N/O1M3N6Q4P2N2M3N;NEUBTBQBWCUDQALCQ?O@RESBQBRCM@QBOCQEPFUBN@LASGS=LBLAQBMITDSALFQGOHLS[S^NQQXPWPQW`PWOTQQTZORSXXWX]RTU[QVPPQUPUJOOWFQF]PWZգŖ}gQOZYTTUUPQRSGSFNPXcd][YZZ^WZgemxXkT]gmgqby\gPWHWDY@SBY>^'McAaD`A\F^Fl&Ru8cm$QY:R =M5VEU?V F]Ex7[Zs3XWD[I_GdMi%P_EYBZ?\He%Oo.[^F\AYGfKdDjIk)Y\EZC^Hc"Pv-[i"RdMR =QD\Gq/XP?ov5cHjVr4_?uI}C8}8|c{GiQ7@4B9B :R>y)RcfɇօoceY\]hXqclԘ౤㧎⌃ᕆ♄߫ݣᬎگةۥ؛רӥΖόҏҟԫ޹߾ܼӬҞ͓ҖӖњБόˏ͕zwuny||z⃁凇y担薉┉琈獁昆眖ꠙꞔꨘ멜뫠첢볫챣︨ﻮᆴ²´ñŵżóǵƽȶǹʶʵɻʻݱ鞓znnWUAO;I2G+CAj;VV=U =ZEl!C:`0hgCo՞̗ؖљasCX=Xs%KiFaEb#H\;X?]=`CjGk#Ba?g#Je?iDj,Mn'If>o'Fu!Go!BoFt(Hn$Et+Jp,Eg"AhBc;_=\9]8aB`>^:`Q<[EfI7Z\sp{z|vxvwpqummhisyzuˁ͌|֔~Ր|ՑӐՔӐӑ|Жό~Ў΋Љ~ˊxψͅ}āɅ{DŽɀyȃzƂɃ}}t}Â|~|yȄ|łzƃ{ȉv|ły}{zu}~~}}uÄzƃ~}x˂w͈͊~Ώ͇эzόΉʈ΍}ό̇·ω̇·zΈ~͍Ή}ˊx͇̅Ί|ψ{υ~́z΄ΆЅż̂y˂΄~xЀwӁvЁzrҁwJUJUJUMVGTMUMUKVEMDP=N=LAP:KHKKX;GAKGS7F?L=H;LIBLKNPT]Y^UgXrevc|fjt|yyy~y{svwvu|qy왆rztyqwjpbk_e`Z_MW@T7O6P/M3P.M4Nd?^>\8^;bAc>c?_=g@c L@N@I:KLJXDSISBLHNIV>PDQ@JFPAMITBODTGRIUCPCOISFPTSkj_mGQMONZNVKOW\^\\YQNW\VUQTWZTVSWUSTbQZNMNRPVJQMa[_TқҴ{^TST_]XXNOJM;MQ[c]icgoV[Ybahemeils^tR`UcdeSg8Q8M?O6M Cb=cM[J\LfSy9tFrDxz3ZU%@z:`;R>R=P=R?V@XFYQ\v4V\BWA`E_B[@c@fEh@lDgBj#EgFaBe"EdAg!Bj&Ij"DgFl#DoEk#By1Ok#Ch#Fn*Qb?]@dCY7a<]?h9dAgAf!>fHO?M>KM=PBSAVQ?XIX @Z EVG_Jp3PWGwqL^?Z?YCXEZBs6`Duo.Z_G^@[@cHeHfOaB[BZF^Fr1d:m\?bMe#JT A_J[LbBp?h}=pTC^Ev3d}5pn%XUFODK =K>TDf3Ngv.lF:Y@Obrx؋}uhYbX``oci}ءݘۆuۓݓܠܜܠᰚ๨ܮ۪ٯ԰ԯȠ|kwuˣќԣ֯ܵ޼ٷ٪ТΚϔΎˉljјՎvpxႀ߄z叕㎐䑉叒钌痍旎疊땎閌瞔皒陇ꦖ륒饛ꨛﳦ쮛ﵫ︨ïPij÷ƶóŴƻ´Ƹ˿̷˻̻̾ʽô利瑄zxkkQV?M:K5F*C?gCXBXHO?S CU7WC\Lg?8e|#U{.Kј՘֡ʉ>KZrAa?P9b>cAeFa>iEh"Mi@gDf!FkHc,KfFh!Be@g\7c@g"Bh?e>d?`=S;\DZB]CkF8Y\qmt||{oxsuxssoumhv|̉Ό֔yԗ֖֙їѐ~Ӓԓ}ҏАԐ{ҍ~͒я̌̐}ɋˍ̈ʎȏʈύ}̅ʆʆʆljȄ΄u˃xLJƅɆx||Ãxǃz}u|~}|}|w}w~q}~{}ÂȂ|Ȁ{̃˂yʁ·~̂z΄͉ẅ́ÿɃ{˅}̈́{̂w˅}ʆy˂yЄx̆yΆӅuΆ}сyЀywуn͂{~t~q{sBNBNN_GSHNEOKV=KDRNUCTDVEN=JJ_@MI3D4E4J6I@GNN_Z[`cYiXpa|jimuqtyuos|u着ꕀuwy{qmujqpwftkl^jjQVGL?Q6N*J(L,K.G,N0I7MCS9N:O;O?RNGSGQEQLVIQELJRPRZSHSKQUV\[QTRSXXSWXURWVXT^XZUWTWY^V[UTUXPVJPRYT_TV[Sfv{\SL_VX]OVDMLWbZhs__^a_bchf|[p^tcwbwj{m|e~M]9RT@YEYEbBq3WQw{/`cMO 9WTY@j$R|?pw5_eKcF[?i RdE[?iQYA]HUC_I~@vx0a_>i"Y}2fZG]FfT[FZ@k*ZUI^Cx4h{:kk$UP 5N9G;JI9J3E)B#Dm@\@T?WBPAS>Q 8]Hc;;a=qo!GfsЖԖݜϐ@ITrrAe?Y@g@c@W :\@cCc Cj?g%Ei@k(Lh'Cn+Ll(Qg!Ck IgEg$Fi%Hl&Ho"Cg>m@aCaDd?]:`AZ>a;]8bBff;b@^>P6SDV=aEz)RGg[npvuuƀzyvwnopptmmyqā|͌ГՖוғҔϑ}юЕӏ~ҔϓюӏzЏ|юɋΑ|ϏΕϓӒ̏ϋ̋~ˆ͉{̈҇{Ʌ}͇zˇ~Ίˇ{ˈ~ʈƆ~ʂz~~{~~{t~x~~Â{|}yw}}{}zuzxʀ}}|́x̓}{z̈́̓Όɂ̀~ˉ}ˀx΁wΆ̄΃|ͅЁv·uІρu{Ӏq~v~tERERFSGOJNDO?RFOCPGTFS@SANBMBW>IBKDKCN=G9D=NR=Q7MCPCVAS:KIZJVASFS@PFQ@S>NIWDOHSEPIWNPHU?OBSCTFSEOCXGLEUCQCRDOKVKWDPJSR\S\UYMXSYNSMPSQOXWXYXXYQNVYTSWYYVXW_aXVXVUZSSWW\g\Z`SnUۃiiaLQPRXRV^HUXYg[cejuhv^eckuj`a[]{_XoA]3W)Mk>[=aIn3jo(c`IV ?P DY>c*QXq-Z_JWDSBZBj,d_CW ;[H]GT ?Z=]@t2VHzlQWLV=e"O~nx/Yc!G\@[<_AgF\FfKW@XFW?d$LG~p$WY7o*bBtaEZBdQQ =VBWEh"c`Kv7gMh%VN >F5I?Gg Ee@f;d=]8W;V=XCbLr+QD_[yfwqnwxsskqimofpsxwyʀy̒ҏАؘԓюҒђѐёӓғѓДэ{͍͑̍yΕ}ԕӗӔЋϏyϒΎϑьΏ͉|Ȍˋˊz͂}̅̊~ɆxɋƆĈy|zyz||y{~Ɓ}„}{{xw{xwx|}yxxzo|v~t΀ũ{˄~͂x̅}ʄ˂yɀwǂ~ʈzЅẋ|χ{ϋͅ~τyҀ|φ{ЀwЁs~swAMAMEPJTANHUBQCOBNGPFQCOAJFQBN7E?JEK;HER@KM?O=N?QBOGSCQBLENEZCNGTCRDSCSJWFOMX?O?PFUCS@RFP?OBR@NGRKWKSDSITMOMZQZQSXZTWOXMQLPMTONFIPPFIQSLSMMLLNJFH@JAGXT]VgcofdUOCNJeQsYNPINTQLPY^ZX[X`ckpnxkxne_dg_eQmC_:_2SrD^DU=m-Y@rjM]DKcF|9fw,al"VfHAxI}7gj$H^FU ;Z ;W;bAdPaMU>W DV[Po*laIu8^g}7uL4G /I ];k@d'Oo'FjAj >k$@m&Hi DhEm'Jl'Ml+Nn&Hi(Jn3Ml'IfDa<_>`@c?b;^?e!=fHcM4J/G*D3L-I0K1K0M2J8L>RRBQ>RGWETv@yaDR @I @P GL0m:nhp,YaLYBc!QMaCS5P>dKW 9T ;R 9R ;XEeMk#Rw3fLSIvq#OcEeJX 9Z iGm!J_?_=\;^Cd!BnDb>dDp!GgDgDg#Iq,Ll&En&Lq&Fp)Ln(Dj DgH_=]:\9\8bA]9a?a>e >c?iB`;`=\AU:WD^Jf M:V^wdtoyvvywylmipontlgwr}w΅wӌӑ֐|ז֕}ёӏxҎӏюЍЎЌ|͍}ϋ~̍Ώ͐zѐϑҕԏ~ҒӓҎԑҗѐҒђόό|Ό|ʈ{ΉωʆωDŽLj~y|~|y}v~{yv}}}~v{}{|zzw}z{vxvt{|vwxr|~u~{}|Ȁy~{Ȉ˂̉}ˆ̀n˂̃{ʀ{ςvЀxẃv}yр{DMDMDPHYCNALJSIVFNAK@IKSCLEIK;M8F9H3B?PDTGLZ\URdTlgtkxk|gnr~xzx똁vt|s뛃qrzowpsetftdp]g\bYWRJSDS5F+I*I+H$E.E3F8K4K1F1I=O>UASBSJWATBRCTEUCV@SFVITJYDTKRFQBQDRJREOAN@NCQ>ODSHTCQIQHUEUEPHRKQOPOTPTUWSSPRZTTXQXSTRTV_RTUWPSQQQ]NWSRWVUO\\kipON>7H:S6DC][Z[VW`9HLNela^U[[o^z^_da^aic]qQiKa:U&K\CUAd&PM~CqZAN@KAJBL 7m;ljz9kj'V\Ji&Xt8fV@M 7^ObMh#OZHbKYHVNfVo(VUUPsv-TiEd#L[ nG`:_Dg#KdHk"Ei=g IiEdBg Jj%Jh"Di%Ip*Kp0Kr&Dm"Dm Fj'HgE]B\?Z=b:d@dAc4a=g@f>c]S_Ko)V?`_wlwnxwxypwovnomuopyṽ~шג{Քԏ}Ր֓ґՎяь~ՍԐҍϐΑЌϑЏwϑ͒Β{՗ϕґԗϓӑՕӐҕї~ѐ}͍΍~Ј}ͅzΆ͋yϊˉǁ~ƃ‚|‚yzńyÄvyÇu}|}}v~{{{|uxzxzzvvw|{{~}}y{vxs}|yx|zʂ̅ẗ{˄~ǁ|Ɓ~~xɃ}σw΂x͂}΀wЃxEPEPENPWFSBJCQFM?LDQCT:KGNEM=I?LAJ=O@OJWFNN6H5P.L$F*E/E0K5J=Q1L4M@PNAPMW>PFSHTDRBNCP>IEOFRIRCQESEQBTJOIVJWGLLVINJKMSQPSUTSRMUUQTTZUSRUSRRR\]QQTTVTVUZ]QVZV]XyS^%@)KCXVZ|mzmqsDPJV\dZcWm`_\mqg\t[kQY_b\hQ]Ib5OsM]L[L{JtYy2cR AN V?V;h NgRW?U DX :cBVx5WV @TGUCk#XDzCgQe Vf RT CU:xJfl$ISD ;KBQDv/Ufmr^lKa>YHe\h΂ׯڡٍwىُێّ؎օ~ՈЋӐЕՠײݳܹױԬרٱԬլϧȞ͢ѯթӝ͚͗ѕіՅw|~{ↄ≉␏光分⌎⋐㈍㇁ߍ䈁収厇鋎甉瓍ꠑ霗薊陓陏뗓ꛕ螈ꛔ럎땒핍뚏ퟘ몚쫜춢ﳧ곤걥ijIJȸôĶȺȼǺɸŴǸ©燀ggOX>HS;Q>Q>_Dg:4`)X1Q^rԙיڟ}C_>[bJ\Js'GcFiFg Kk&Gs1Vk!Ei%Dk&Lk&Fl Gh#HoFi Do-Pp,Nm*Ik(JiCl"Ae B] F[A]<^^8fJ?K@L@H?I@L8F8E3I9G;LBPEISV\Ycakbynzurzxq璂瘁|z~qv횁uyꚂzsptlrvetdk^^[POKPCS6L-J(F'F)D.F+E/M5K5O:R5LAYOESEYEUCLBRGRFSJRHSEQEVGRBMGRCREMIQFPJSPTPTJKPPFPNISYOSOOPUXWYXUWV[RPWWW[RTQTTTVRQVORQQf_ӗsx~CSRjXaicbߔtޱ֬\`FVUeNb[gafnh`uPbM\Y^eaS]J]5OsG^KYRe+^{Dpfu3_RGL BC =L FTFm6dvHow7wr(bR :TBS=YRbJPcq2Yx5hv.VgD^DV ;S<\EY dEe9X>]AUBW@cOn'S;[Soctssyuxtqsnmisdllo}}{tфyҐԓsҍ҉Ւ}ؓԑ}юvҙԎѐюΈЋuϏ΍uюΎДyҎӐ}ԓЕҙԐҖԗӕёӓЖԖГϐЇ}Ώ΋z͍|͈ω}ʉ~dž˄~{|w}v~ńu}zā~v{w~|}|w{~y}zsx}~}wxuuy}{z~|x}yv{||}wz~~w~|zt}q~vσx΂Ɉ|̓xBNBNENNX@K>HBM;GG]ALALGJ>E;K=P:N6M:M;JCPGRT`\Sgcskrp}qtl猄}~uwu{w}|vxqyr}rwpbk|kp\j\aTQQLLDU0B4P/I%E.K0H,J1J7K7K>M?S>QM@UIV>VNXFYFYJXEVANARAPGKCSGTEOGS>QBMFNLWKPHOLRHMOWOTNRQUWYPPLQVWQQLTTVSRWSXXW\UPVUOMTXQWPSeTeעq_gUcQdcfV]u{oN_Q^QwYZgjh^k[hRcRc^aaaK^;PuC[FYIb`g'Z{Epfo$TL 6I?GBL CUBn9eyJsK_HR ;R.M :bPW8U GWIfLt-\8mMX=b{6ax@lo*Sk%M\DY?V>UAXE[S L^vӃwOS9S8QIYզ߭ޜ}ي~ޔڒߟڙ؝ؘԓԊЌՊ}Ֆעޱ۵صհװ׬صٱҬΦҫҦӣҩҞ͓}ucZ`dilotz{{yz߃ㆇᅈ㈉䉈厑≊⏌䘘珊茐嘑昚薔雓ꚒꛘꙔꞐ롗Ꚏ힕隚蚈젛롛좔뤒ꤑﳢﴨ볪벡ﵩﴭ﷧ヲïóƳŰȷɹȹº¶|uu[bCMU ?R ;R 9S@T?X dBj Ck Dm*Fp%Jj#Cq+Ll(Fm$Hj!CfAc=^>\=_FcA^>i(La=f@i)Kd Dg@Z@WDRA[Ij!Mv1XFg]qgtq{spstqqnjlshlpx|zȃ~ωӓёюvϔ֕ӏ~ӐӓёҐՌyҒҔ΍|ҋ|͐{ӎΐ{όϓ|Ϗ~ώіғАӏԕ՚ӘԖғԒ~ӑѓғ|ϐ{΋ш̉|ʈ|ˋˊ}̇{ƈÅÃw~‡|tĉuzz||t|{z}|{}{}xvvxw|}v~wz|zwz~uwx}ywux}yyyuxr|ówȀ|Ђv}{ˀwЀvK=HFPHQ@KAKBJ?KAFGW?L>M8G;G7F:T9KIYGOJX`Yh`okqh{l}hfmyuwtyqxuzz혃w|{tqpmi{dvelWc\URHN@I2M3S)B&F+K,E+G3M2G7JK@K>NBKEMGNEOGPNVNNQWNRMSLSSTUUMQMNTU^YQPYSRSTSST\aRS\VbecrZc]PqjcE3>M@UIUHjOWSs^\mYr`bechwcr^kR`QZUdmgaoGc}!G[CYJbXv9m3\X]_>L9R GJ BPL\Hh4`zP{DsX EP3U=RD_HU?Y IbGm%S@wIsIp~6as'Tt+\jHb"I`>Z=W 7V;X=X@\=`DeKbNY @_;|FjBgYAOUtϕڥ٣˂zfz/Oy%H1L,KdEbDo&Gl&Il(Mg#Gf!DcEc(Qh IhDm(Fu-OnDr.Il&@g@jAb:_@c>Y?^>g#D]>a:fGe8fFe>_?VJ@NBM@N8H@HJ3E>PGSFQOS\Tjjppg^xmqox}}qꖂz완wvxt~yvysorssw_uak[[TSQEL;H4K0O)G&F5M1L1G5R5O/K4N7K@Q?VBN>P@QALGUBPGRNZEQDQITAYGVDPDVFRCNCPCLFPCQHQ?IHQKSELGREOOTLXNQLRSWKSSPUVY\OQSOV[T[RUUUQNTYNXPZYc}ԗӫт~m`܊mhB9gC79#7*=4;@ET]]tiadig~bg_`VbOWIS`g^WQ_=_nC[L[Pr3sEn0TgxBmR5J >QJK FTNc!T{ErrUe KS:P >O2\F`K^DbKt-`~1]w+Wk'Hl!E_>f&Pk,Na>X 6_;Z ;T 8V;Z <[Ca@XF_CeQ^GZ3x@st,YQ ;P =UCT;tI#>Bu>n?c>`@X9X 9VAV7VCS ;e9t.W:i^?E`١ۣ˅nE[{%Lt)H{%FkIeGl&Kl)Mg"Ik-To4_f+Ki%Mj)Jk$Ho.Pr)Kt9[z=_l&Dk(Ci^AbF`?j?l%IiC^@SKESBMEPCPDQJAJANEMDRDT:F=F6K8D7G=KKQNR\Y`Ylgphufriyrw{{z{{읁t띂wtxpztprpmzlsek_aVVUIVCM6P/J0P!H*D1N/L8Q6N;O@QBS8L@S?TBPGSJQHTHRITBVBP>OFU?O3HHSDNCM?QHT@QbD^D`K`?V2p.^fIR@U GU BXBOw@eTiT[ A^G}D|DwcK[HSAQ?B8H 6e"JfrupӎuY^>PD`Qeỷ⯆ݗޙےݒܡݬܮڪؚϓ̅Є}ӄӑե۱ܺ۷ٷܸ޼ܵܲسհͦ|K/5!:&@1B:N=UDQHfNaFWUcWe[n^lZhcngokju|w݃㍉䋍唔曓땕럘띖랑ꢚ렒렐뜖間꜎뜏떏똋뜑ꗎꡉ뢗죚쩔벢鵢쮞﫡뵨춢쳥ﴚFµı떈~|sceKR->:xGt?i9a;a 8Y 3T 8S s$JBt]A7Wݪکǎpy>Zx"GjBiAn$Gm'Nt+LhFcJc?d Fg$Ni$Li Gf#Fo2Xr3Rs.Qr.Mr1Rh%Hf;c>e>aA\?b@`?^Ca7c=g@d>_B]EW@[JV@_Hy-VDa[rjorrt|rmotlpfjhpnl{{ȄzӊՎxҋ}ѐԌyӌ}юҊzԋЌ{͎ԊyΎφ|щ}ϋ}ҕ}ЋuГ{ό|ЌΉ|ъ}ϊzБ}ΎЎyӋЎґzϕъ~ђљӏ~ЏД̐ь|̈z͈ˇ|·y͌̉~˅{NJ͉vǎɈŇzdž…ńt‡x†}}zƁ}ăāƒŊ{|~|}{yvy|z|||~w~}{x|w{v{|{tvvvs~twrqtw?L?LFRAKCPAHEV=JDMDRDL=P@K?KFUCNDQBL@MJCNFMQS^Zhag`tp|m~lswsxuyu~z}~wy|vowsokkzftkl`]QXYIPBM6PI :PERJO J`"TErqRM3J4V 6W9j(Z[?Z<]@fIc@`Fc"IW;aL\Bf!K_BX=YCUu0]r+\YGZ JYHbMFq1YUk!^^D\EJg,STAQ 8I:C4K =V5XrtwԃsfeBQ;OM^w~ڥ䷝ޙ~ߐ|ߛߜܥۥ㵑ൢܰםЄ}ΊЁ͈ΊԞک۲ഫ߸ڼ߼ݻݷ۷ٵ˞bO5B1F7M7QAT@N?QDVAP9G?OI[DRDX4FBXMcRaYkZkfsqr܁ߎ☎虏鞔靓ꢘ졗잚왑훓隍엏뗎쟘閅鑈뙄ꡐ꧕쨐ﱠ벢鰫괟骟쮟뵣ﴠ﹧į韋晆{tfgkOQDL(D~ g6c 9[ 3Z 4W =U 9OZ?`;d=_BeCc?b@jHcLWBW@WH\Kf!Q9XKj_wnsvtuyssosnygehwwvy|̂{ҏ|בvҐ֌|ӏь{΋ҍzҎ}ΉxЊ~ҋzьtяяЍ}ӌz΍{Љuϊ|ҊxΈ|όw͇yόx͍͌{ЌЏ{ӓzҌ|Ўѓ|ҐёӔ{Ґӓ|ѐ}ώz͈{ʆż{΋ǃ|Όvˋʈuˈʏʇ~ˊ}‡Ʌ|ʼnsɆ}ƅ{{ƒ}}}~Ą~~Ń|~}w|||{}}uw}}ww{}wxw}yw{zs|}twvxrurwqjpp@T@TGT?HCR@PCPERCNGTHWDRHZ=G@J@MIQCHDT?H?J9IPIVBSGTHTCMEPHQHLLRKSISKRNSSXUWWZUTQNPUS_VVYZVYXWTZT\Qc_\׾~LSZCW ?Z BdNFhu~֚ͽзܯWXTWFX/F.BO\5J$Im@bMcQe$LBv+MtEtuw/YTGLIXNNISNn-eH~ox^O3L 7X 8X >eB^>T 7]G]B^=cSeG_ QbEc)No3_fP_KS:Z=ZCbGe JX~E|aKF5M@KEB :O9~2SsqדiRN];SEUmwԢᴔޝ~ޔݖݞܦݫᲞ๢ܱՙ΀~υ|̃Ήϋ֩ۯܲٴ޸ۼ޸ܷڻعˑnZUCOG_LaVg[iYlWcVeL^DW>KIVC`6J1H.>9R3F[:a@`De?dBg!D`?eCeBeE_CSDX;_Hn(R9aPkcwnyorwuyqtqvewgnu}̄~ψ}ӑ|ՐՐ׍~ՌuԐxэ|ӋՌ|ψ|юό{ЊyыԆpю}Ќx΋ъy̍z͌̌zϐϏ}Ќ|ʉ͈zҍ{ϏБґϑ͏}щ~Ѝ|ёϑ}Ӎϓ͉ẇ|Ɇz̅xɅʈ͍~Ό}ϊ~ʋzʉ{ȉ}ȉ}NjyŌɊzƈ~LjȆ‡ƉÇÆÁÁ}u|{{}ztz{zywz{v}uvz|sv}z~t|x~u|srntBQBQFR@JFYDSBTCSHXCOCVFSIZBM?Q=KCMAKCLAT;J;M?K:U7K8M?LBLQQZ`bSnctg|l~ipsqxzzx얀xt}r|xqtojkw^n]_WQPGJ=Q1F.I)H.M0S0Q.J9N8S4L5OCQF[@O;OCUEXFSGXBPFVCQGZDNCZHQBQHWLUKUHWEQENELDRHKDNBL9OGKETGRGQFRKRTQXZP\QSQUXXQRW^Y\WYW[[ZW^WbZefaxȟߡopvISg;k@n>g8a;S <] ;fExK6]bt~憐r箆]ZNT5K'C$C7P1R|!GkL]Qg&Xf(eJn2Spg[=KETLQ GPIc#a|@}Mi_N:L9R 4T;^LO 6T?`OcJd$MuCtc-V^Ea$Q\?l0\n.]fMXAV?V=h KbHY@[AT?VNXK^>n'[EO{2lu(b]Db$WI\8{D}~7sO :TAt=|^HB 7M@L BJ 9t!F`f͂vԋyM[:OAU`lԖ߬ߜۑۜߛݦߡܭߵร໧שҔЃψрщԖ٨ܰذֲٸٻۺ۹ׯˉgZ\QaYbbljrr{lmownzkl_sWfU]MaLZEZ;T1H :~=&B(A+B+C7HHZL[Ydprނው厊蛊ꞏꙑꗑ虓꜎ꞗꞓ쟎癔蔆嗇蓍예꜓쟏즡챟곥객쥓쩠ꮟ뮛ﰝ@꬗晊ޑ{ہ{ona`[fL\GX=H2N#A}=w@q:k6e 5[ 1_ 9W 7U]"Fd"L\EaEX9fNc G_Ad;e;g#Ie&BeBb7^@Z@]?\Eu,OHiRei|nsuupuqypthnfvmu{̓xЇtՎטړՐzӌwӊҊ{ӌzԏ|ьЉ~ш|Ҋ|ΉϊzΌ~Ίԉu҈zэ{Ό|ˆ}Ќ{ъ~ψΌ΋ЌzϏˎʌˏ͎ϐ~ώяю}͑Ћ}Ή|͈{łzˋŇ|ɇ~ˋƃɍ{ˈÿ~Ƅ}ʋȉɇp̊yȉ~ˇÃƉLjĈńĈ|ƒĀ…~~~yz~x}y}wyw~uxxyw{txrwpznyp|nwprAMAMITIVBSGSDP@OEMDNEP=LGVCO@FCMANBKKQ@T:L;S=O:NBTFNQaEO?KGQAPBU@PBSGQIUCTFQ@OEQFMERBO=IBHHSGOHRHRBNOTLQQXVZPPOUHUTTOWRTOS]kaoZYX[bf_bldoq݆gу~OV)I)Ks@o"G\?S g Xq4dj)Wr;]m9Z\'S^IW?c#Nt:\r0W\JWAW=nNY;V 9X ;S :Y;P 8X C_;r2YXEhTU1n7rMO5k5dAVA^Pt4oTDHA@6QH`%EXlzoوvdeDWCV^sʆݳࠅ܊yݘޟޟުܭ߬ວ㿩ಜ֠х~́|ͅΈҙҝذڱٮܾ޺ٻٷذ|oXd\fddgkpmwt}wzuzx~xxxxtznweq^eT`I[=T)B?~6(E;7%@.=8M:TOZflot݀z⏈䑌阐옐閉虀砘虑ꗉ蔌瘌藊ꚓ옆엊웏쭚ﯜﴡ鴨쫟벥쬥쬟ﰝ骏⛈܀swjbfSYKPDU@UBKesٙޮٕ|twCceFi"KY?fI`GkD}-Lo$Iv/Pp+Gm!Cj"Dr.Kq'Dn$Ij"Dh#DeD\Cc@e$HaC]LAJBLCMHSKVDQAODH8J@O:G;MY5P;M7LCM9M;O=IM?MCS?QR=O AQ;WKq6ek&Pn(WjNY8_*TgCnU?]Hn5Z{R IN CQ<5UqtԍuhSaCXWeDžڳ೘ړۇvޖޣᨢܸ߰⽫޽֧ϖ̈x|ЇГКӦֱ״׷߻ۼֵӧodSUS`akkgszpwzy{v{x}rm|㇃~|xvvpq^fWdJZ?G;U1E%<,C!>|#B8|7'?/H8KETde{y߆~Ⓠ瘏蒋摃敋葉덇瓍ꑆ瓇阖陉藔죎쯝쭡쥙뫟쵣뭢쪔靌~ڃkwkcYUTNQ;I.H8K|%?+D5L6J;O=O8J5G4F3G#>w6k:b7d>W=W?SC]B[Ad @o%SlO[?arОݨ׏{nw[ul'Jl#M_FiEaId$C}5Xk$Gr)L}9Ty)Ks'Gq)Iw-Ps&Jk$Bg=dFW;Z:a@`<^?[;^C^;_=e:gCh IfC`@]?`L^EiN3TSllu~usoooqludmipmtwr~{͉֒}ԏ~؊{׍{ב~Ԏ}Ռ|Ӎ~Սwӌ{ьuυ~ъxΉ͉ҍЇtЏ͋ҏyюr΋̉vΆpцxΆ}΄~Ɉ͊|̇}ɍɌ}͐͋ˌϏΐ~͎vΐ{͉ʅ~χ|ˉʋʋ~LJ{Ά}ˉ|NJ~ɇzˊyʇȈ~Ʉwɏ}̆xƇʉɊɇ{ʆ͋ʉɍɇÉą|ʼn~~}}|{z~z}z|vvs{{pyotrzqssyqwmlFQFQFQI[DLASDTCLGMJSFSIRGQ?NAOALHRCKCKCK>G?L=G>L7H9IO2C;KAM?U@NF[?QHUL\INBQFSDLFVFRBL=IAL?JCQ8DETDU>KMW?L?OFKCOLULYIMIPGQOWKNNOS]WXORWZNRRYPS^fkkxmpgpgibg[iau]t~]'5z#Dl@c8Y9N :N9OIK ;8]if^ZinCU9L9I;OE^'M{C/L>X6ZlPgUj)ZIGzw8r|CtcK]HSLW KV Di,e}HF{Mq"^[;rsj&OH5S @N >UIVHd0]|Owq6_o.^i!QX!N^(S|Q|f3Sh'NDrEss'UR4`Hi!IW:U8U ;T=S4P 7T ?QX8bC^>^>cBbD^:eAhGf>l,RgDcGaGZ>eJkR<\Umixtvztum}iqjsizrrzz΂sӉՑ|؉y֒{؍}׎}ՌwԌՈ}Պ{҉ґ}ц~ӊ~чyωЋ~΍wωъ~Іpωx̆чzЋvЉ~Ήωỷ~эύ}ϋ~͋}ΌˋБ̆xЍ͊ύzύx͊Έt͊wЊΉvͅv̓}džˆyɊˏ̄tljǍ{ɋ~Ɍvljʇȉ~͈{Ȏ͇}ʋʊˌňɇŋLJĄÄ|ˆ}}|}|y}v~~}zu{tyw}qzws{pvkvDPDPAM@REKGP@YANJSGWO[EQFRCL@NFOFN=H>IBJBODS;K9M4J;J>JCPQNTZaUe]vkxh|xwdoxn였vvqs휂{|p|~~}zrvzlg~ir^lafZ\SDNQDO9GBKERDN>GALFNFMHODLHQHOINQ]GRKOBNKSMRNSV^LYX^efps{t߀uyjrkjhqdi]lY܀wes#?d@c=s";j#Di'IP@D DJA}8`og\]qBW,L2U-FXxOd2R)L+KqHkTj%Yo-`PGrFf#N_TUIVRYUZN}D_Fx6rXIP5`zF{S?M :RAXHO <[En/[kLk&PcKWEQFTH]IbP}EtGpIxj!NcK_?P 5U8Q 7X9T 9U :R 9Z C\G\GpInpC\Lpt|7mO CY4k4`A|S N3G2C-G'C.E&F+F-D=PRagnxzፁ名捋狅莈猇폊鑆ꔎ꓊옌퓃정쟖쥖쮜ﭨﬥ릞ꤔ렌ـqphWM@P3E8M2LD_?T6SPaIbVrF]\mmqakVYKONM?Ik_5s%Rx(W^FQj՚ۦёālXp:Yi!HdHcEfJ`?n1N}<[e!Dl"Hn#Eo Jm#Gw)Nt(Ln$AgDe#I`@[:[;^?_9_;cCc:i EfDhCeDc!Ff JfE]GdGt#TB`Wrmyqsrqsuloipeplnuxʂ}хtԐ׌z؏xגؑ{׈zԍҌyֆ~ՐvԉӉ{щ|ЈЍԇ{ш~ωzЈvц~ύ͇~ЄxЇЈ{҈t̉yφu̍҅pΆ}Άz͋ϊ{͇Ѝ͊ϊzЍ|Ί}ΈφzΊtэẗ́}˅v̌v̌†}ˆv̅|ʇ|ˉzɇ|ʇ|ʊ~̋wˋ͈ɇĊˋ{Ɋ̊ȌDžňƅDžƃDŽňƂzł}ŀ|}~x}~}x{yy}tvs|q}rwnxq}p~@J@JFYAQIRGUGUCQFQO^KWLVFTIQHRHQCN@LLHOPP]cYRhathyewrguoy~z{px~s~wz}s{zyxmn~ltbi[c[VSOTGV7P+L-J,H0L/O3M8MSBUCQ@O=XCQBQYjLTGVFOBV=PDPCOCSCOAOCOBP?O3H:I@P?L>M>ECQM[=KFOBM?HFOGNFNEHKLNSOUQYMSMcglrsۀs}uwoigphojpVٗ?V.Pj FG\^|]uo)OMHL ;y*Znl^WҀTcN >WHQ?]Bv1go$QeGY=S?P=WNS >^!H|?sO}M}y2_eCW;R3P0X9[6Z6\6^?Z 8V 9UC\L]Eg/I`qYk&_P8X=Z;K 7H2E 8K 0|0PehҊvbZVOUfsΐ޲ᬏzݔۖۛߢ۩ݲݸྭܾ۶֪ҙ҂э·֢ѩܳݼڳɅ]KOMXLQUWZ_X^Y\XYknfhcd`fjn`iOa*HZ^ۃpz}vheKYcnilSS6NKT@XIS@P:L3G?PZNYQ]ps}刅刁䇈苌鐊鄀ꉂ珈ꖍ얐맛쥚ﰡ쫥즚졙랕ꠍꤏ䘉}|^fMY:L3Q9O@[I\VrMbG^W^\hYgLVkmokU_NN?C>FAM8C*>|#9pAs@qcEm)G{2Rb@hDt&Ll!Ln$Hv1Oo&Fn.Ri<_>_#GX@Z:k*P`Bd>e&GdAe=e=f9f#Rd?bHaFk#Rk"O~-VOn`wozyzvrsuknmtjonk|v΂ԋzՉ|юzՌ֎wՌ~ԍ}ъ|Ԍvӏ֏ՉuԎ҅zυֆsԉrӉЉэxъ}щs͉ҋ}Їr΂{ϊ̉υu΅}ͅwΈ|ΉzА|ъЋyӇyҎЌzэ|Έzэu͉wΊ|̓t͌xͅ{̉xΉwŀ}Ƀvnj}ˊ{ˉ˄y͊zɌ~ˌtȏˈ}Dž{ɋȇ~ĉȊȊ˅ȇȇɊȇƄÆƅ|‚y}wzxoso{tysrulslyAPAPJ[BOBXHZBTJSMVLXANKZEPLWBN=JBJ?IAJ=F@K5G8C5D0A3@=IHNNPX_\Vpeu_wc}q~luyvzw{tp{sxxxuwplduw_m]fXX]QYAK4H1G)F&J'D7L1J6N9L9M8PHW=S\BVDaLgXs,dz9oXeNs+cl$dk"bi*hr1g{BxkL`QI ?P@Q Bg(P_lo*UUHXCQDS=b%MyQFXMZDy>jM{Q}Aq\9R ;Q9S7S 6\ 3[6\?`=\ 5V 8Y8W ;_EZBa!?s>dJg$RY @K8O V>`LXAUAS@`=q,V{.\VC@^ȈۨјjnUj@S5WgA`9_@fAd A|3SfBe!Bn*Nm!Co&Fv.Iq&Fk Bd;_?a!D]=`?c=e@a8c>cGHTDJCK?L@JDMHYCJIKCHLRFLGMLZMXIVGVS[MZ`^zl{j}uކv܆~}zk}v~ouoqa{춏x΢xurᗋ܇k~[qasmayI[SUb^`^MU~:a Cd$Hm$IS;ZLa Yq+gt2r~4uBti[o St)er$ex0no,pw8bPaHR@I ?KAP<`PzIjW|?qUCTF\HTG[>DpM \Fr5eR|WI}eER7Z=S 3[ 9W 2X:`=b>`;^?T 7V=WFNHMHNAF9M>B?IDECLGKLGLK6B;j9$;PPymfT^d+z >~#?0KkBZ AY :P8WI9G0C5J,E8C=MELQU\W]Xnfsizp}kmskywwuxwur|ytsmz횁sxuuu~kzenbjgUSDPDO2G,E1N'I+K-B=V3J2D1I4M;PIS;L:O?OBNBTEPHX?LCRDNBK@N@KKEIHJBH7HJAIGUCOHTHWOfQf\nkxivjephugyl܆x߅r݂}~tyryiypvbpmqvڒy㘐䎋~nsiiHY7W0S2B:A&?wD\7\'R^/VV;OBYPi'fy7p:xMent-\YBv.hQ <&<;":*B#><}'E+C}#;d;Y?Z;S ;T 8\CaBs0R.\a?@\ˈڨѣ~X^TqNbG;I7CPDL?MGUCUMbZobe~p~ʄ{~r{rixo{n݄t݀x߀yރu߄߀w|qyf}ijex^jW{k斁♂~t[e*Do6t(Mo@g9b@[@WBVFZ'QfIsoOoaXn2oq1t|6qDv]hHzcGVLl$[y+f=;zr3]Vax5gO@F XXfgr\dXbSXS]V\WcPXTX`jdqiinmu|}s愁|t~}膂딏헏樂ﱡ﫛멝頍}}{khnhdmJNMXAG'47v9u3u4l8k5m8o:k:r@s>r BuFz$CwH&B)?A :)B3En7^ 5Z9b:S>N 5WE[=s0U5aZB9YÇަԙŇT__s[g6Ty(LcEbDb@f%@Eao(MiDm!Kr,Ol!ChBh=b?b:`7a>a?_9a@e;^@^?e?c;b>^AX;S >V?\Lg"H8XXmo|zxsususymrflrz}n̄|ψyՎӐ֓}ԋ~ՋyӒՌ~ԉ{Ո{щtӆӃqψфvφv҇yҌzҊ|ՈrӋzӅsԈv͊zҁwχ{ӄvтvу{ЉwшΌцx҆sΆz΋xʊъqΉ}ϋ|̋xЊv͐vЄrЇ̓vɅ{σz͇rˈ}̀zʆw͈|͌ʈ}ʌx͈yŃDž|ɇ}ˌ|̈yƉ~ʉˇʋ͉ʇȆ~ɋƆƃ~ā|ă|z~}Â|}}}|v{z{syy{sov@O@OIOCODMCLESALCSBL>MGU>L>R@KFPDKBI?N=GAN3@8F1E0F0D;IGNSTZ[e_l_rZxq}h{httwttswtw}|rtvswxtovieselZbW[TMTEQ1F2J3L5I$@(A)?-B1G4I7K:J;JIKAZ(XY%Sh7pp0ky7s|>r7k>o=l5k:k_OCPELHRCKDMDM@K>F@J@J>EAPDJ=NPCO=F;H>E=I:D8G8F?Q:PJ`itƄˀЎӱٴlSj[tixhxhxj}h߁~jr|wwcuswnwsZj?VC_DN^ij~CU~%Na 9S;X?E;I;FN_J] Dr0gu+_RDXJY>}QxNZ>X?R9VBR 9Qr?s:{9)E+Dl?` 7] 3a=[ 9T;S >V>W={0Y3_aD+OËۚ֡ӌgxPeO\:T~3Ou'IfF_=fBy5Zw.Ph!Im Fj As-If]9_@_=dE_8\;a%Nf"@h Bf ?fD]EU>P 8N O;L;J?LDP;HHAH?MAJAM;K>LCL?H=NBQ@M7EHl"RW BbF|zDl]aBP:QBS=Q 8O9O 9Q CG;[RaF]d]^Gi'UO:O 5Q 1[ 4[5]:c;aCW:N0I8LE>3E:Q 7AU{؜WQFPZḧ́۸幙ޓyޑ~ᙀݢڞާޤ⪞㺨࿴·ݻ۸޸ܮس޳ܮຝݾ̘j<;$=?:)A9~5y3s?v:n6nj5pEi8i8l7m7g5e:g4d@e 7e=gAq&=}>Zt1Fj;g=s4i?a4e;d:[9XAS 6X[@}.RNclty{|tsslmrpxnqwq}ψzԐ}ӏՎ|ӏӐuԆ{Ӈ҉xӈ҉wԌ~Ԉ|тx΃}ҋ{φvЄӆr΅|πu˂{΅{΂|Ӌ|vyэхtчxъv΃~΃tуsπyЈtфxЂtˊ}шv΃yψv̇Їq͊uІv͈͆v˅zdžzʂ|ΊwɃzɆv͊{Ʉ|ɈxƇȉƈȅ{ɉȂ{ƅ{̇ɇxƅɅȊ~ăwÆÄ{}„}À|}~}}z{|}|~|zz{|t|v~yzt{pz;M;M@JBNCOBM>P>L?MGT=Q=I?N;F9L?M:J1C+A+C4F8I@LJOQRb\fZqaykj~gspztyvvqqnzw{vsz{tfozercseldXTNOEQ0F,E%A"B%>/G'=/H4E6E5E0F9H1E7DAO8KFCHHAK9F>JAL>L>J>J>G@S9H8H1F3R6UK @H CE @OEb'gxCb`N|1mo)Wi!XQpMydEh)YP{:xz1ls5pLm+dw6hYav5gJ V=g'R|9~f"^U<}KrogGS>VEV@SI;K :t,ImlԎɄgCOCXw۬㼪ߡ{ݓܐ|ᘅݢޠߨ߫൨߹ķ޻޸޴ܰ೨ᴜ۴ݽϜwBI+<@ :!A >x:v;o7h5g9md:aDr9an*LI\`rWoAX(Kl=[9X5T 8aE\ 9\ 4f=>1=Nd`bjvf`eq^kW]^c\d^fkqkpmivrrsuyw}ꌄ쏁휙﬚òᮔ҇wZX(;xAp?fAg"IaE`<_Cf%IjAp>)H8P?T.Fv!@tBh?c8d=h=n;n)Gk#DmBo!@s>zJ8EAN3>8E3?-@)?+E,D0E8JLNQW]VfYpcxfzeeo|o|wzrlimqz}|spttmkcj}dtbi\_VY[PS>L3G,G%?-G$A)@)C2H2D6H8M5E6G8G;GAN:D>M>HM=J;I>KAK=I=N>D4C3F3I1J.P/PLVΟǧ綗✉ȋʃtgRWTl_q\o\pdr`xjxflpmvlmmntp}w]l>NkAbGz)P4HsD_?U :J=F CEDK FXRfqWDoq+bgN\Cx;tm{Nkh0[\Ua Q{Cv}?|y4gGz=m*cv7rv\q5^MGF :K >UPc&Js:rj&SQIUJa#Lu9t};}[FxKitu-WN =U@\K\BZ?R 6S>R;VDQEWId(OZeZZ~M}6qc S^>W 5W 6`:^ 4N 3I :I?G@I7^DSd|՗QX?Qbl֚㲏ޒݗ╂ڞޣܮટṦ±Ĺ޷໪߱޴޼ݸ޽ϛr;C#:)B'?8};#=o9h5f;h=dnKvRn=7ZhdP_?U#Ck:b8a5`9ku>m;f6d:g=k7cC]9S=W>ZF`Cw5Y,]a G}#F~׌ޫ՛CW@U>\{,Md>s%KfAh&E|3Xw3Mk'Fp Gk!Cg Cg?a<_9_>[=]=c:a9eHAJ:FBMFP9H8F:D@O9G5H5CBK7H0H+G,Q0IaUħ맋ʇy^QNZPhgsfo]xhuf{e߂qlnvd[cFTlxrw^cHj;Wt!M>g5Od;Z 8WuN~;}z2pIMuXCL?M VHYGa Gl&U`Er;X:aR6WHZ@Y>\:Vo9qGm=gDc:` 3h7h=b=a;\8S8`<]:}5Yw"Me E|$E͍ܩՕ{B^9HMk0Qp)Ku#Qm!Bo&E;]8Ql"Ip"Ii$@j Dc;c;`@`9^:`A`>aA_]>Z@^FUB^HcJ0VQffrsu~vv|xtrtpunpƀσ{Ά{яxӎzדxӊ}Ӈzҋ}ϋψ}ωщxфwъцyԇuфwІvу}τtЀvЃt{фxц}ςvӂzυwυwЀ~ЄtЄ|Ԉ{Ђvπẍ́|τwӈw͊Јy͉Ӂwˈ{́΀wͅ}σy҅u΅|υzφ{Άv͈tΉyЅ~͇x͂{̓v˂ʁtʇɉȂwÄÀuzĄą|ŅŅƄ||}xw}zt~ywywzy|u|qttvus~txxsyx|svo~zzq~pys}=O=OBM@LAOBV=I:M;I8D?N?Q9M9I9G4I8K>F6J5E->6GNBN=M?K>M>HBO?M@K9BAJFO=N9D@KBL;J=I8G4E5D2F3L2G-R3KfYè硆em[VW_Wigocs`ye{ix^dn~efkC]<[cmekeyRj4R1X;[n?YDN ZCc$Gh!G[=X?a(OqvAa:V >R5W2@_=d{!Je?_FY=Y>YJ^BTEaVlIF[h{)IʐoL\/IqBa6b :a7a 4l4n>o7p>qBg@e:e?d:c:`;e?S 5U 3b9]<4Uu!Pb Fn@vxӍܩ֗|A]=NIf?bu+Ko'Jp%Kl'CA\s)In!Dr Do/Hl"F`@c=`=^8a@a?b=c>cAc C_?_=_=[>[?W:XD^In%ND^Wfhuw}zm}{tosxntppyẃшz֍{ӌՌs׉҈uԋ~Ӈ{Ί}ԇw͉|҅rՋwфrхrρ{ЃzӇtԆzψ~΃mӆuσ{Єx~sԁrτwуw̆zЀÿ́~υz΃vІyԃuЄw͋ʃ|tуw̓}Ѕvσuχu͆~Έy΅tʅ˃rЅtͅwΉxρr͉zˉ}ʈ}ψ̈́y˅sƅƆ{Ɂ{Āƀzǀ}Ņ}Ƈņ…}„z|}t|xxzwvzyxy~w|wvt|zt{punwqxvs~s{q~t|t~v}tulx@K@KGMLZJS;KJ>IALFP9F:H@P:HBIGP>EXAR [>V6U=\>[ 8dCYBX7[C^>_:T=V=Z@^.Nh5Zh*NbWf OW6S BQ EK?L 95N{u؊ab@SM`ʼnἰ展ܑtڝܝࠏ੓ݣۡܩڬڻǼ÷Ὧ߷⾠ŷӰUB3I/A6F4B-??}4j4i<\<^ 6e ;j7w%C6L=T1Ne>q C6O2Wf=V 7P8S 3g>A]z!QfH{.JŖἿܴڵѰvPk)L}Cz!6KgNh1N%G@IZ]WgSWU`PXTWYdchZ``dgihgtkcpj{z臂돉·ŹͼʹͲ˩洢{d;D!@j>b@`Cj!MdCWGXCVCf$KnL1Io/OΠɋ|_q>T$Ep>^6b ^9^8b>g&E`?d$F]?\>_A[DTCYIgK|.YFg_lqyxyyrywsquvpmts{~·vӊ|Ӌ}Ӈw֎{׋{ԉ}Іwևv҈{׋xчzӉ|щv΋}~wʃxΉ~Ή{Ѓ{Ӄ|ԁvЂvЁ~ΉxͅxԅrЅ{ρvЃuъχ{χ҃tЂzЂt͆}҅z΃}́{Άz̄yЃy·wӅs̈́Έ{̈́}NJ̇v͈zуyɀr}ȆxɄ}΅wσrɃ˂|Ɂvŀ}}ˆvƒ|Ā~Ɂ|ƆĄ|~||w}xvz}|xxxuxtuvzpuuvvrxqrs}w{qwxnwqzqxp{quo|ANANDJBP?IET;JCQDQO>L9J8K4H3D0C/F4E3F(@%;)C0A>LMMXWf]fZk[wfghoyovuvy~zvqtry란|j~o}ip`k_`RZSFN?M8Q+G&=)C+C0F2G4G0C=K@K@O?MBP;G;GBKCN@GDJ=J8JDN?J9H?MCLFN>GFO>C=I:H8G5F:A7B2F5G.K"F:E׋x㴥㣑밎뺟घӕwxidjdwmvozpxevbxfyg|hauH_frm~iei%KZ9.U5UYAKIK CK@h(`p.fw>rZEpo!OYG[IS A] Kr5hR{m1Ug(VXIMII GNKYUu;m~=rsaVAU@W?S :P 8S>cGTASFVG]@Ux|r3Y]?e&QbGX BY 7U?W ;\A_?\?Z:^$I`@[@U7U;U7WCZ&KZFSFUAYEp-pu-xhUoK]fЁywcDR:Rv}ܹ⦇ې|ݟߩݤݬ૟ڬ֬۵ĵǻ߿庞ĩ׶cU2B=L=J5B/G =~3q?r=k:] 'F?ML_:Vm:k?BbCd0SaBT =X7x)EZ/XgQp*Iʼn渾湶ߴ͝yC[#M=8DfkJ^+E5Vn%Ll'Hk Di Be>b;d<_8_8b Je'Ia:`c@\:X?W:VBZC[Ko(Q6PSodquvuturoqxymoturr̄ЈvӒ֋z҇yՌ{ׄuю{҅{҆vӈv؈|ՈyӈyЅy͂w̄́ÿ́tς|΅zՂqҁyсt͂ωz̃vӋ|фxЄwтutЅu҃rЁ{Ҁsч}υ}͂x΂ẁwσuυzЂ{σuЅ{}vЀvϋz̄t̂ỹz΅{̄o̓̈́{Ʉ}΁wuăȀu~~}u}}wǂ}ǀ}ŀz{Ăy|}wy|}}}y|{}zxx~z~u}t{muotqvs{sowqyt~owk{kwnzpxpyFOFODO@O>LCT:KEXMDR;MBS:N;H;P3H4G8F2E1D-C(A#A+?6FL2D,K%='?)@+B2D2B4G8M6DCPDU8IAN@KBN@JDKDLCPBR@KAL@PCNAONPALEOAJBJDU>L:F:F:F9I.FCzD,DzsީڄwLJXצhⰅ䷠ޝڌ|y{wvol`}pwsvmyixtWcGZwudqfDWh?T:\7` 6Q 9K CPFTEp2iYRGqt([X?P BZPWAp5r~@yj!NcGo*ed \SGYTX Mf]r-byAvxEk)VH|Ery\o'S^N`KVFT>W>UAXDRXx|Y6d;_ 4_=h8Z\/MX>b@k%EGloG^ CsFm~ΜޟПbr'F>WPs?[y+Nv+JA^?WgBm Bo*HeCcCc`=^:]?U@ZC\A^N`!Iv%J<\Zqgpy~wnyzttphx}qtts~zυzӇԎЉӉӉsҊ~҉~щ|҇yԊՆ~Ԏǔ̈́yχẅ́́t̂|~y҄vҀoЇ}πuЁqЂyӄmЃwˁ}΀uсxӀoтuфЃx҄q́yυuрt΃tɂ}Ѓvuτ̓|{хo΅сv͈xͅ~˃x̓yʆȂ}́r̈~u|ǂ|{~|z}Àzz~|zzz}|zxxwtx{u|szsuq~mrr}r}psntmwnohtryftlxvyy~}AMAMBU?PCMK\9H@RERDQ:GER=K8JNLPUNb^dTlZzn|ktusq|~{{wz~|}rp}punz`p^la`TXRMRHK;O0A$>$A'B)H4J6J-E>O@N9MHNCOBJCLG?LJOHNCKCJESNT=J>G?IEOCR:FDZB\B\GR@` K]?V?QBTD[Lm.Qkcp,\l&O[=Y >U8ZAU<[9Y=X6Z>b#I`>\6U 3U 3W 8V8V?N2N=H N =Y@y/ZPxhV\6RMp|ܳ⶚ۖ~֌Հx}zՀוڜܢܳڼøùĸۼݷ߿࿫ŃeKXEYFRQZKXHQ;F1H0C0C"?w;n 2j 4o 3@(E>RY`^rEc{&GqB:[Gj8U9RC]7V(LxGr'OgοĽ漶ৢ|~Kc(G#CIL[dCS5E8BLWHRFSI^Q\T`SeTY^`cafscijqt}~|~눇Ⱥͼʹ˰ٗ^b5L5KJ`BcyCo!GEcKe?^-O#J?RSd7[+WrD9h؞ُ׃pwUX+B@u9k 4e3b3^ 2_1f4e9e7a<`@` 4\5b:[6T 9Y=]=j#EHkmHb GfAcrЗٞӦʄkx0P7UNlCa1Uo*FB_>[g>h!Cu+Km#Ia<\8\9`;c@`9]>aBe=bAc>b=`@aGX?_I^HfIz-NHf\oorvx{wvjt{noqqux||˂{Ј|ыΑҍ|Όxӎ~Պ|ч~ӊzІ~Љӌxъwχ̓sτψ{ˉv~mtЃtцsσxрrȂyu}s͂ẍ́΂m҄~уvuӃ~фuΆхtρ{̓vρt̓vЇyφvхxσsЃxЃoтr҆w͂vʃ{̀t̀z~sɄ{Âv~u˅ɀzŊ~zÁy~~|}~z|z{xw{||{wyvv~xwzuyvyovpwp}kqnmnygmmvpwnsmrlwvzw||ňAPAPALBRHUET>G>MDM@P?I8HHN?Q=N;J;K7F;KAN1B/>,F+A"='>)A:EEOUV`YbTnbvcjqoyux~xz}s쥂yrv}t}홃rxsr}dmXlZbVYSPP?K6H,E,D0H.B.D9G/B5G8F@JCPAOfEoB`EӰ9_y%K9\P\xǙʨ봜鞉╀oycomGU0>j3n:p:dF`GO@N>M @PGNJWQg+b{@vZKwy1Z_HaIVJT?l4ox>ra!Pp'\^U`#Oq2m|Cv_VZ I]Sh%bp2ehsQ>z{>tj\jNVAREM?UC\ G`G[BX F1N:LOOgkXp:_l Bl"E5O;h1j 5a5a3` 1a 1h7h:] 4Y8fA];[7_>WdEd?g!HeAeCb?]Y>WDZ?kC9XO_hnvl{}skujqrntknstȀ́ͅyΊzЊ}ц}ф}щrԈ{ӊΉzυwшҋ}҈x̀y΂z΅oҁv̊̀tЈ{ˆw΀q΅xτxŃy΂wσt̀~ʁxтs҄x҇}ωЃuԅ{цu҉~τzЃtʄẋtΊЉxυ|̓Јyr΁yw˃r·|́t́s~vʀnzz~y˂}ÂyɃ{xxwÂ~{x~||y}{v|}{}z}}uwsuy|xvqtwurjmpxlstukrhkkxlwkumzxy~Ëɕ̏IRIR@LEUCRDR@K?KCQN6F6D0B1C,E(@#?%?.F3AEPVV^WcYqfxbfttltw|vw{n~vvs|xxrqrzer^hXe`XQOOBK9G6J-G%B2I2G7D.D7E5I=I?H9E?KCMBJGKHLJNBJ_=\ =\=x$5ÌvȟWzVjwў˝Œǽ좋xم_NZrFY5S7S=S@WC]GK >J =P CUMXJd%TE|Iu~8fs*SeJbT_N\Rh"Vj)fy9if#ao2ecRf#Ti,[|=odYeUf"ao.gv>vty^C{?rpaj%YSEN@ZER@\D`K[DWA]Kg*O\?UEN=UEU @f!Jy>aby4[\;[:dD]DbCY=[;W;V;_?bEb?X9\>X9R8R :UEN4QHL>I DQBr$JkzwL[4SLcv”ɜќױཱིܹ۬޼߾໮޻ںۻƉoO\DSPcO[Ya]`ae\lRaS_YeNXFOBT*Cu6k 4w8A8OJ\UYccVr>^p#Dm8h?o!BnFm%T}2^QӾƾ콵쯦眆݅{bmOf7S>JZVY^PZ>KJSJWP[YgOYGXScYjYh`bengkkjsr|}焇ꎊʼʼѼѴЯ⳨gjFQH_KWejl{[0Xv$Gd 2h2e 4k5d3Z 6`;d7X 7Y9Z |9[NmfBa IcDOlԠړڬˆj8Wm&KBb=_0U}.L=_7QfDg?c?hA`@\5i'Ja$F^9d?_?a:h&Jk#BdBb:[7`>W>\=ZEfB?^Tgjzy{~swvsnrtpsswynʂ|фsҊzЉьxь}҉zЊ}҅yӉ|φ{͋~̓|φz̉|˂y΄x΅uЂśz{t˂wЋ|̈}o΁v˅{͇~̃z͂w΂wЀsӂzЅyЃu|uπyӉuχyЃsςyyςxˁy΄wЅz~zφvЈxшx΃w΃rʀ{̀p̄{ʁyx{o~{ū{wz{uÀ|с{zz{~wz}w{rwtyruxr{xvr{p~otjnnovmwgrlqp{rzux|uxƈ̍ϒԗ՞CPCPCPCQ?OBQAIAKBFEU?M+E7M7DHNPR_]g_n^vjk~nwp{{st}tuz좇~wz}|shrxcs\j^ZSUQPRFK{8q5t3q7g9\:aHeFx,GpzЙksvӪߺ鰔ݾ̮專]Gv!Nk&[RERBP@UKS?Sn8n4'H@XQcM`U^_jWwCm5]xPz!P}.^;hgʳꫛ~uwimamPeAPMM[VVcIPKRLQV\YcS[O]TaQ^`n__ipgnmrsr|y抅듁얔¶Ӽտзƭܦ_l?WPcQ_dmyQyX?^<^|/[.ZYΧק۞ݏ~_sGW+C?u4n9l7l1h6o2n7k7f;X3`9`8Z7[9Z?Y:[Ba>7RFkhMaRpKNbҘח٫‹q>`i&M=dFd@`9TDc7Wj Gi"BhAc!BgA[`Do!AH`\iltz{}}sktv|ytvx|w΅yЋ}эyҏӍuЈvЉ~Їvωuщu~y҄Ӆrш|̈ʄvˀvΈsυ{̃ρs΅ρwπsʄź|χτyЃςvΆx}̂{Є{σtˀ΄v΁s΂цxΉ{΃uρz̓}̓zуsπ|̓{Ѐvp̀ẃw̓yсp͉x̀vŁxrȂ~~ǁ{Ăz}v~z|x{}y{~~x~{}~tytyrswq|uvryrwslyoun{pujotxsy{x~}ĉ{NJ̊ϓє֛۟ܤBMBMJRHVCO:I>OCL=EBPCMAPFPIBKGQANGLnl-gj.`v]EXB[>]9dDi%Fi"GdG[CV 8bBm&Lb?U 5U :[ 7[>^8_AgBZ 6O .UAQBM5N YsʂwBP9RIVǔۻٟ~}tՅyڜݦۣڨ߱ำ๭ྴڿݿݹܼٸ͍`LSJ]O]R]YhK\OWYeUbbblz`aqzhk[^U^B_-D~$J$A2S@VNaTiUn]pi^yMxFxG}[vͰḽƽ½콲캤癒ywffpunhuGYFPSRbl\bMRIUSaNTW\U\V]Z_]f[c]hagcdntsr先ꐉ죛αƲڝ^a?Y_dC_NiI>\͆ؕ۫ǒxGqo"G6^Hd=a:WHex3Mu.Ob>fC\>a<`@`@bD^9aAZ7a\BY>W@^Cu?^L]fprvttsvturlu{msuv~wΉґҍyъ}Ί|҉}҈wӄt҅qӆ}Їu҉xцt̅~Ѕ~͇wυ|ͅq΁z˃ṽw҃xфvЄq̂̀w·}ΒʋΉ~ǃ}ƈzʅtІvχ{͊̃u͇~Άxцu͈xЊ{Ήsʅ~ˇxЅ}˂uψ|Ή̈́{Ѐu~~̓tˆrЅy̅{wĂxzą}ǀw~xp}v{zxux{yy{wvyxsxzxuyuuus|qtqwnxqvnskul{lvuzst}|Å|„Ŏ~ϑђԒԟכ١ީު?P?PCLCOFTJTEQAMAHASBKCR@N?QAO3GLGAICLHMELEIQYJSMUDIIQKTJRHKINGOKO?B.? 5/{'Bi8nBf7DjIz8i,YEfaziՕ㨙ӝ{}땋쩎_ItD^Jn,[Ni*bOK?MEOJ[Pp/jNWUI~@vm1eh0[[K_KUIWB]Ywwx(jh']RwU\bSx9v]™s|Aq/gYA_%Sl%O`BTAS6VBg(M`=[;Y 2X 8V3\ 8`?d#Ga"K^CWAcHm*So#M\>Z;_K`:Y9X8]@gEX 9O 4P?M 4N=N5C 8W#[PA}4Pt~̇`bF[G[o{ڹ޾ԇ~t׊ݚޟٮܨܶ߾߽ݾܽں׻׳Ă^GOGXMXajW]WcW^X]WjU`eeorjokqfqdletReH^=\7O;S:S7HI`Reasnrfis|̈٨ݮᵯ๸༼꿵ºƸ¯祋mvgosm{qhhKWIXWaaa^^YWS\HTOVQ\VX_q\a\cYc`o_aisjnyx應鏈Ÿϵٓ^cCR5K6H@[\c_tp~pi`TZs|ͥ۫פԛԚԈqUYAS2I"n_bG]MkJ?`Ɗٙ۳ˑsKgu+O}/TLiy6VJi;W|6Mu0Ne A`>]8a@`=[8`=\9Y:[>bBi:o@j ?]8[8^>\BZ=b@2SO_hnvyyqktunppruwwnȀ΅~ԉҐ~шtЉzΈ|ьvь{Ј}ωz͆{ЈsЂzρẇ{Єr̃xЇ{΂qʂyˀwӁś~́tσxρỷzБғυw˄~sЀlЃv΅{~ʀ{чsЁv͈̇ȳv͆yɃy˅x˅z΁w}v~wẃwwɆ{s˂o~tʀuĂy{{uǀxÁ{wq|zz{~{vz|~txtq~~xotz|ztqwpopqvmtmylxlut{|yƇ~Ȋ{͏ϒӘ|יٞڟ}ܦޤݪૌ㮊AKAK>LEMGNFRBNAL?LCOERBMBM9K9I:L9M4H:M?J9E.D'>(@*H'>1H4CJL[\]QiblWugetpswsntv|u~zy{}z~o镀qv}kuffTd[^[OOCN:I4H-E4O4I.D6C8F8J3E?I@K=LBMFNFNIQKPIVCKNVJOEQFLSRajLV7t7e9] 6a 6b 8kCmI|0Ih^`l~݀z䐄颖⮥іׄᤙйܒݺyvK>@f&JTIWPc#HZ|=yNEIAMBRJSMVVd'k@con_V{?k\ERBVFP @LCQ?d+bMbHj#YApG{9qw2nj'Y|=xw/wl2nTdc_Uv5nb̙tRAp/Vu2]]AWBYEQ 5U@a!IZ;X 7V3T 9] 6]?]HZ?]>\>`Fk!Ll'NlAeJ]<[>`>]Ab2P`&Ea<[JT9L 4Q;K 5G 9QEO=e#FX\y{|q=OBT^yΝƹݴՈ}׏ےܜܤݯۯݼùڽ׸Ѷ~dBP?NTWW^W\X^[g_b_d]fZ^feqqtznxlqmtnm`g]jSeGX?NCd-F%AJbVfdskot{ҁցڅݒݛܠ୦஛賢춟ꙉ㍒ߑ~s}mt`iT_L]O[_`[YbiYZXaQ\QWS[VZYc\a]bakY`]elwrz~苌蕑óͶ֒^lQcBX<[:YHhWj^rspprvƍГۙؤԞБӇrs[[>I=I+?z7i4kA|'=|!?w Bq:s=q9r?k<_=Z@[FdE^B^D`Gh?CY=^hJbOgKA`Ɗِ̤߱vSi8X=\B_`_pozsywsqsrqnqjruoyɈ͇ЊwҌцzψx̄wхyӇtҍxͅŵxЄqwτv͇yˆt̀u΄}υt~uʀv΃|ψu͆x̅sτ|ˇ}΄|ААȋǂz̈{фqчs΀vЂz΄xх~ф~̃v͇|ʇz΃|΃xx˃v~v̀yx̀q˅y}t|q|q}{v|v|tyu}wŀ{z|}wy{xqyvyt}stx{xxtzwxtvotq}rxr{qvouu{{zōyɍϒ~Ґӕ}؝ڡ٣ۣާ|߫⪃㯇䰉鳎GWGWHQHWFPFRDP>MDPAOBO?JAMCN4I8PQCKJPLRDMKUOTFLLZITOV?G]]̏7?b9c:[5\8^?f@uG&NFemyvЁڇ؄v|ބ眊ݳۑãĐ礄}g;:f^?gCc@];d Jd@a=X7X2]#E_9U 7R 0V;I 5C 7G8L :W;8NpsԉIR3LNeɆ޸}ۍڔ۞ݨܭܱݳùݾܽڿոƂjAF:JGYUXXbY[Wb_hfoZ_]eWa`htuuwpuppoxnrekir_jM_LZQfI]LgWlLZG^M_bdckpw{}{zمڐܑ㛬嚫吖㙭ࠫܬ᭮ݞ؆|zuh}ewhoaf^aX\Q[N]T_JTP]X]\g[_ZgOZ[hiotqvx~鎌젘辴ٖ΃x`{\VW{Oq\slz}wuyyՆӃք{m{fjadMW9F*@}7i /k6x#<+D%Xą֊ᬪԩWq9X0W>YBUUqy&Jj@s*Mo&On0UZ@[?[6]A^#O\9W7`=iF;LCOGPITJ[HPOUPUGSLVN[LRFVHCu^ԟs6[0`9W3_ 9pCw I.PGehąˈxtyՃمցzԇڐ}ԉ{ߣvm5CU;Q!ISKOIPFM EYLj2b\Er7zER_uvXzZ;b$E[<[$LZ ;V5P :N 3L 9I GFQO[R^_d`kWa_hip^fds]gblqumrnslvnnmumxnqenThT`]s^l_fZjFUIXD\UdJW;CXdcnfpupЁnwp{lٕԋthԊ݊܌ᘤܗٕؕۛڛ؇v{lm_fWa\aV^YjMVUa\nSWVdX^\d\j`ikmpqty|璏ꢙûξ꼶ޡۛלёNjuh{jqy}nwck_fpuт͇ІlrgmVa@F9F+?q,Ls'Ja@W@_>[<_?a=]9W7Y 4i=h En!EhE]BYEjAg Hs>_Sd`rpszrwmipxloqquvƀ}͊~Ћ}Њ͊Јq̇~шwЈІwщЃ|͋x̓zyˆw̅Άw}v́x}yƃ|tˁr͆΂{~{΄sυ|͋ЗЧȐǂ~˃΁xσ{|v̉Έ΅x͉˂s̅{ˆvϊ~΄x͆vˀũ~Ёy~oxysÀ}ǁrɁ{~wzmyuvyuwyx~sxt{wwvrqt}ntowyzxpvyvr{uyozptrvz{sƅ|͐ҍ}Җ֟~ןܤޣᦃੇଁ⭆㰍z䫊糁箇資絍GSGSHPLTDVJZHUDQNXMVGO?J>L>K8C9H8L8I5H.F-B.D0G2D">&>(<9LEI[__Uhco_wbhlwovzu}}uw}yy拓tvuplovcmZi]^UOUDJ8N2J2B8F2F7I9J7E>JAK>GCQIRHLBIOSPPNTKLTYOYOSJQHJrTӆxBYG 9K @I@TE\Uc&NvP}eP?YTvEzM~@r-h]Rm*lk+lz=zM`eLNqĒVq8bYr*Yj.`WJtaHO =SCX>XBS 9S=W=VBY9Z?\=^>_>a@bAd@`<_DbA`9b!Jd9Z@]5bBR 3Q 2L1L 6H7G3X6FUtzЊtKU5NH^Ɗ۷෨ڍ{ב۔ݟ۠ݰޱ޸޿޽ֻÉe?L=PFLERMZS^[ibl_mbkjt`idofneqosjwqwrzoosmssyfmcmckhuhv_fTbIUE^TcZo>X5RTn^p_lcr[tFSHS_nNoAV`tՃόԔّޠܞថ㐍vpleoW^O]Y`O^YeWd\l[g\e\f]bam[cYbetmruy~z鋊랖쨝÷⢞⒆敉ᑄ܅ywxz|t~cn]oXmNT`cURTO`]5C0888=?"A{!?~&=8C>P8C&8u8u^=Z@cG_8_G\9d>n Cl"Bn*PbE[;_@hDt(G3PAb]gg|qqrkuymhknogqwxpσzҊzԉxϋ|Ӊ~҄u͈zщzщx҈yІzͅφxЀrτЀx΃|χv́}DŽ{|v~x~~|Ѓxсv˅zρu͎Њ|І~ʌƃȄpȆ~ʃy̅y̓˃ẃt˄y̆z˄}͈̉vψwς{͂wɃs̃{tm{{ǀw|{tvǀr{s{vwvvvrnuuwzvwytvyquw}s{ruqtrvt{v|vxs|ssx{~Ƃz̈vϒxؘ֘~ۜڧݨ᪄䬎㫃䬄㯇寉汆泄䮃䱋氃賉곇CRCRFRGRFTPaHQER?I?MIR?O9J=L5H9D6H9I1D4F,B0@0F(@"D%='>7FBGOS[Skksbs`hzm{pxzyv}v}yyz~{|xymtuwim[bU_USXFN@M2I*A.C-C0Bg@~(JNfhlp~㊂ࣟفl{i|fcigoØҫɍoFKn'Mb!Qi&Xr0ln,ai&X^GaTWRd^cYp8Wcvb|7ghPj$ZWP[Sj.jRhn/\O@H ;N =OFMHWKeV_CvItd^W[!Vp9mXU}C}RQXPq4rzATcnSX[uJo1o}FyF{qso7VV@N 7V =YCZ ;T=XBR ;Xe:hAbI7N/F0E5E4H,D/B#<#@ >(=+A6BAGMN]Sh^r[t`zhhmx~{쟅}zu~||}vwzkvjkXe[[LRYEM?H6H+D/E6L5C9HBKBLMT=GENAOIKDJHSKPKZGTLPJLIPFNJNVHЋjGUpBu%L*NBUhpldtbs}|؋tYgquiyZ|]{boUcCg7al-[l%]m1^o.\d PZ;U?U?ZLYNXOXKsp[9\;Z8^A_aCW:V6R 1U 6L 5H6G ?K :]>Sdv~}sJQ>RKQy|رګՎ֍ܡ؟ܨ۬ޱ席߻Ķôٿڿƍf8B.KP0N*F.FaBc>_?U 6`>d9l$Il(Eb>Y=Z:dGd?z)INeVdjxvxw~stmoptkqqtx|ˁxϋҎφԊ{Ջzԍ~Ћ|ӂuɇ{ц}ͅzІx΅~͂ǘoЅzͅzɃuȆ͆ҁtʅ}ƅ{Ȃ{͆x|t̀ú~˅w̄{ǃxˁx́}΄wʃs͆{ˇy}vŃ~ǀÿ́xȂz˄tʃ̄sɁ}v}ʆvȅ{Ƀz}t}zƁx{vytsy}zuyuylyvrswpjqpptmrsvpkxxoznwrvvx|~Ą~ˊΒё{՚֡ܤݥᬅ~Ⰳஆ欁鶆洂汋嶄緊粆糂寍䱆鰐篆賉DPDPHSJUGMLZKNCO?RCKHV@M9I7O8D5O0G4G5K6H3F1D)A(E'@(A#@3CBJSR_Vd[m`vhoinr~zzx{r||{{x}q{kxep`eS`OQQIMEN7G'@-A5L1@0G9D8E=I@JDNJQLOGMLRNPPWRSSZJNGOLSIWLLsih|G^Ut\t[zmk{_O]bxntVc0Mx#M|/S=jR?VNWOM IK K_&Tb~mDs5rTplPu3ut5qs9o.oS@[R`#ZS HMBn;d^h(]` cn3it>pWQs4rOTVMwG\OL]du^c\dzcu\EN :O :[Id!O^EZ>V:S;YAWBcF`D[:Z=`@_D`>_>\=]8^C_EbL1:$:8w 4w8x5e:\3X3g:h?^7b>kF|5Wz-J8X\KWJcQ5Ruτᰯɓz\{CdfE9SNlw%GnB\:d@kC[:[8b<_=] `<]B[C[;b9}7WJbcup}rtqrnpkphngrso}u΍x̆юzԉ|ԄoшvԊz͈Ά{σ{Άwч~̂|΁uχyͅʄy~vʇy΃}Ʌvρtljƀǂẋ{ςvȆ}̆|̈́tt~n̓ẁux΃ȯvDžʄxǂzɂ|ȃyʂ~DŽuʅ|ȅ|ˀtwɃszsȁt~yuq€y~yxvyzvnwywuvtxyx}ntqrszv{roo|m}qvr~}Ȇ}̑ϐyԛ؞|ڥ۪᫂䯆䰃|終紉豇괂貌涉糅趀鵇贇浄䮂氈}籉DSDSJVCKBHFP@P>ICWFPCN?NAOVScnTǜs|vsʂpmvȞ‹tR_6Xx*Ri0^c0Vj,Vm-[p,TKoR~:chI]GYHT;T>RCLE[OS BPJUXZ\d.aaĖjds{t[N^aw6mV@ZRdPMCOI`#NQp)ae+il,ci*Y[_Af'dWL|ZUw8qv:r]axpuwka?P>M?TCWCY CbS`QX;U>b@a@`@`>Z[AU 2G0L5D5Fb]:Y4S 9[=kF0PGbekptssptpmkmiuhltvzωzя}Δ҉yяЉ΋{͆|ẗ{σ}Έu΃yˆ}΁{фv̀ỳvͅu}qʀ|xɆ˅ʂx́z̅}ʃ~rΉ~σẁŕzȂzʂxɅy~wƀ˂tɆśxȁ~}uɄ~rɆtń~ʄy}wt~~v}wz~rxv{t{{uwuwwuyw{rlu{vrvupuxrounrlvxz~zNj|ωyӖ֝ݠߦᮈⲇ㯃籅貃綁紊踅賀鷄趋䰄洆紌貊鲀粉籆鱀淃CQCQETFOAKFTBP@N?LDS?K;R>I4E;K6L3G0?6HOIYRKށ`Ԉfvmu|~֊َ֛֌sx`lQi?iw*Tm5bq=hj8ddOf)Q;fPg=`y9aaLQCVEYGP >LA`%\_RUBO ;^Z[Q_^f&YV||nplhl]p-Y^P]O]JN ELHYFyAv}H:O6H^or׎rfZIYDS`bҕ޷חՋٚߣݪ۫ب۸ŪĴ͟E?&C2J7GL@E:A+@4v9}!=w9g 8V 8U 9kgCa?iAl"={4M{+M]CWLdP|-Oyʃݖମ͔upEbq#Il#CAd|1NiBk"Ja:iD_6[EcM`AVA[?`;q+Er+Ag?\4[=Q<_Dc;3V\hmwuvqqpopslqknkizq~xύyӇӋuЇxҌyЉuц|Ή~ȁz̀z̉zъ΅xтyц}~w~zʂz}̃Ɓ|̃~·υz˂ŵxЁvuɁ˂{́tł}ẍ́w˃sɁv|tǀsˁ{ɀs̆~́rȃ{DŽzƃy˅~}ǀvzz|x~uv~t|pyxszzyz{jzz{{suuuvqsxuv{ornuslqq}tw~̍Ҕ~מڠݧᯄ䭀䱃涊終鶀불귇괆븇鴄崁沈䲋糃籅貇鵄泈汊鱂豇CQCQJXGSBNESE[FVP?P8J9M2G2E5M1B2F2C,E.C%='B~<9(A1EAKLL\VdVmfrgzpxwvzx랅{z|w{t}~{|xprozhsaj`dTQQCJ=G1C'B-B/C0D>PCKV=[<\=Z;_@`D]C]9W7[=^>fEdD]B]=]>]9[:X=S6K 2L :Q 9K 7H 9p$@cgцu_QUHTOQටݥܙٓۘܡ۪ڰ۶¶ĵ̰ȴԯE?&;.I7F7E?QGVJVTXS`Tc]iindqn}rtuyy|{~xwxsyvtts~~₁|w}|~vry}qxlrqupsswm{lqnurpvp{yxv~߃߅⎕᎖ፑ߉݂߇މtwcpacar`m^hbqgqhqam^eWgZiR_^iR]Yf\hjw䁉舍菏릮ûʽ彵ணଥਣݙ~xy{u|mrmfg`h]gXeY]X]W]PYLQQYITGVLTNRLQHTDM1?0?9};&BxkG\;iDj C\>eI[@Z=_?b4m'@k">c;\>U 6V R9H>M9H;H9G3F0E3C4H+@/E%<;8FOMb]b[iauhwg|rtxz|vu~vv~}{rttnioZj[`OWQDH9G-B0E4G+B.F;I;ILFb$Yg$Wt3al/ok-i_[ZYo:eboaLp3gz@zGFQI|AlsDtS_$Pc*KyDyGsd&Gp7UbDbB[CZAX>W9Y8W:[;Z>[8Z=]=[ 9aBeF\=ZB\FT;Y>VDPK ?VIGRJVQXSVQW\idkdjaqkpmuwu|zvy{zy{yz||䇏⃁懇恉|{~|~xsxvx|z}t|{ނ|~ߋޅ⋍㌖ᒗ≒䆏⁍ߏntit]kWg_gcjhnhpcedlU_V_Zd\k[d[g[h_qin|僋和硢뱵軬ᯭ⬠䩦✝߄݋|}~}{uwqyin`e]m\fX`[b]dVXRSIPV]MVWgP[KPJXAG@K0C7~97t6o;V 7`7pX5]?_=e;k =g:_;X7U9]G[:u)HL^`jjp|swqsljtfitrwtʅ~ш͍{ЋԋuφyσΆx˅}΅Ј}̂t~{̉ʀw{˂}̇yzʁzʁw̃{˃|ɁȅxɀvЄt˃|̅y̅uˉʃ{ˆỳxƅ|ɀ{̂ǘxʁȄwɁ|ɀźtɁyāsŅ~ā~}s}t{rwr{u|y~t|xq{u{vzps|un{uvyomoxsuluimnsinnuyʼnΔ֗ݤ୎㲊経浈綉緋鸈빅빃긄츈븃終분鵄~鲂賃賂곈괂沄糅貂粂贂AOAO?MEVAM6G=H:E>L;G8I1E0B4G0G3F2G1E2E-?.H#;#=7y9v:!;,@?IMOZUd[l^{gwctn}ttysww{u|~|tsc~azaq\kV\QSMCF8G4J)>/?-B:G5E4C7C>E?KCKALFL=HHNEKLQHLGJHMIPEMIRIUJWQ^K[eqׁx߃ud{PgOmRd\uPg=ah&Ja#YcQj%T6jRN|=ed Kg#Rc(V]ORGIAPNTCl9m{BqiYbTi(\~<~C|z>XN_u5^d,`g6fi1^f*XQSu9ok2b_@SDTHM :L ;\S`T^Tj%Rw>wu;u_YUSXRn;b^oibiebYs0fo3^V^k&Yh'U}J{xm1SU 9WA_@[@X?[?XD3K'D~>+Nt9q;U6a4q?lC^YRAO2G8N3E4E.G+C.E3E5F0C)@$9$<<<:<'@6CHRYUd[lYxn~dmszzꞂ}yxr{vppvgw_rcaO\QSLDG6I:I.A'?(B,@:K;H;I=G?I>JDNOQDLMTNRKPIKHPGLQVEMJUI[IZUgUkce|hQsNmIdTdQjOj/Sk%Q`$Tm3fo.`{6dCtYKso'UYE\Fg"S[MRDRJZId&Qx=}y;oq+hg \w3oOS]ZyiYq+a_#bZO]Pq;fYLzwR=\B]@aE[;\A`=WBW=^?\?U ;]BXB^B]Ih'OWCXEXDWCSGNCKCIEPF` @U\yp~gMN=OBUYbόۨݘޡݦ߭ݲఢὭ­˱̬{S}"=;'A1As9[9e=nDj7f!Hs%Bo Du>|-Pu%HaBRDaSs#Li͋Ս㬢ؠ‚wFbjMl%C;Q:Z]:[>gD`>i ?]B[@U 9]:b:e:c 5b@Y3W9Z:Y8gG4MR`elplnsqrljpslwnu||ʃuЌ΋}͇υtψ҄vЈыw҈|͂ẅ́{Ʌ΃{ʅxІxӃsɃ{̅}͂zʃ}~x˄zDŽ|Łr̓z·uǂ~ƃ|ȁȳ|˅˂uʀy~qɁy˂x̂|̀vƁz|r~s|x~r{uŁz|~~{xĂ~x~wǁzuuu}yztzyzsxpzwuku|ppoppsp|opms|~ˏԗzٜܥ⩉氍緊깎鼏칉켍ﺅ까깉춇볂跐z鷇{뵂鶁粂䰎糆沄紂豀泇簇벆궇BVBV:H>MWA`D^@^@\=]>_F[EX :[6X:[@V#A-@5H7FFPLKOVQ[V^WY\gW[bdmwesjpmsvxuywzx{xyႊ悄|挒損䏍~剌䅆摑畆蔎眗璌呈㏎㈇匆䓇⊇㌋䏋♔囗嚗⚎䕑勇搎䊐⌌⌌拓⎉ፏ⇆參Ⴠvxkrelgihplissoyhhcdal]f\faiW^ZgXeZc_kckxめ卌磩걲̽Ż嵪孧⣡⤗ᝠܙߒ݌ބy}w~ztwlsivhncn`m_e[hU_TfX_TdWbN^MZHQFXEO8Q!::{:s=r7\?fu)DuDu:|,Jv%G_CR=\FqFo}ȋڕᤡڠȔ}QqkCg$?9S~,K\8Z 3j9b9r,DV7S8T 9]7g:h:f<^8Y;Y;X8`J;S5J4F9GCJ?EBM;ICOEMBOGKMSOWEMIRJNOUS]KTL[QaZmXvOvBeP|RzduYOGWqqcCwi%S`RbOfS]I[N]P\ReRu7fXG{0mu8gTr`Fx^SDh#`h'bl.jXoXv8lVHL=I DK>LEVI^MYN]!Vu5tI\nR{>vr8ua$]]&Yf3cn7drNKUJMQVWcSZR[ZeXbX[itgxgqdnryqvuvw|vw灁僀獆哐菑郀刂煅䒎敇ꕕ鞙畆䒔㑐㇇匊剃卋前揋㖍閍間喐䖊㎑卖揘⍍厎▓㐋哐ሃ߆{wu{luijdlksjjjpgiah^bdb[dXd_f_mWW^kWfW^cniuw|扎硛鵸Ǽƺ繰ᨧ㡛ߣᢛޝކۋ}{zwwy|q}llnqhmdhik^b[cYcWaY]VcXb[]QVQ[IS@Q0F"g;sBqDt:s ;7N.J`>Od?b=^>Y7Z:\=b@{'MJ\Yekkuqvvnwqnnoo|uvʁtˊՉϓwϊuГ}цvω}ӄzЈuφy͈zφx҃{̓~~t~úz~z΄y}x˄Ʌ{ǃʀ}ǁvŇˀ̂u˂vʅʁsˆy~ùy}xɃrɋy΁o˂r̃|ăȀz|r}t{z|zwt{{|wv|wv{sutvqyxtnvryvspxttrrquwttowlquz}vɍ}ӗ}۠ਂ㬇峋鴏黈켍쾉콆칄긂趁~鶉~鷈|诀x䲇鲇貀賆糈緉贏賈8J8J7EO5J:K0K1F3J7E0E7M0D*C1H%>-?+E&?#: 9}:|8v9$B(<5@LNYNddh^m^|nyjswu}zwru}wt{~xrvqoiv^t]h_`]TLMQ:G6D+B->.A.?3@8H3E5AFIODIJLOYJTJRKTKXK^SbMlSf[QHJVqА˘w{}eJsv8ei,]aSe$Xd R`"Qe*[l#bg!ZeSw8pdK{1no-d`mSf[Ay=y9zu0vPsbExe*YL 9H ;G[AY=aI`BYBYBU;X9V<[DYDTCUKVD\ NUCMBQGMIU;8Lurד{`RDRDWQYs޴ޣݘ㥌ᮢⱠ߲޸ὯĩŭѴC9k?y;!;.J->;MENJVLVISSZZ^PZ`g\h\ahohrgriskjrnu{u䅁}}倅怄脅撋琋戋手勇葊斏ꏄ蚖敏嗋啍䓒斑琐擔唒䒖䒋铑锑吇䐌⏐提叏噝嚓◔␍㖗߆ހ~}u}wwqs~jschltmovfohvfjY[YfYcXbYdPO`pQ[UZapjwv}扎旘鴳Ǽ기嬠⨝ޥߟᚔݑ܇}~}y{vvnrkmfn`eefaj`g^ibhXcU\VfV`T`MYORMSCM?L)@=o5uAk=T>f6mEp$Kw%@j6x!Ds#E:Rz&Fc?WH\ LmCcΊדߝکґ{\xgGhB}2N{1I] 9W 3c9p'Oh >`=VAW8^9d=c:c:Z:\9]E_>p D:TRebitswrtypqkjktnqwtɃ̅{ҐӌxϊvЋ}фyΉ̀tшuˈ|v΄yЁ{ʆ̀uʅ|ʃ{uˆʅvɅw͂wȁ|˄{ȃyʀxȄ|˅x˂wʁ||x̂}́ṕ}xʁzuȂw~vyu{v~|}u~vȂ|}v|r}zj}vu~y}ywt}}wtqpxtwuqpsnpttvppoypoouwƌі؛ާ㰊峈궆츃켅뼍ﻃ0뼋금뷅}쵁굃|굄|鰉泉}讂豉봄뷅~紆絁鷄緕5G5G|@#=0D6IFOQN\Yf[scyuopm떃yu}zwvtxzzs|uvumh|hlZjY^SJHCI9D8H.D->+C,=3Ewq,aw8sZg_h?nDzYFPh^Err1bSBJBI /AARGUNYJTNYR^U`S\^k[lZ``lckjomwmlr~yx{vq{~~恁還削拁揎菂蒘玂痃旊铑阗ꕉ斕疊阘雙똘铒㙎瓑琏蔊铔䏉㊉啔癛曖睕䘒㝛甎䏋߈}zzuws{pogmlsiksouftdf]h`oY_[a`mSPXjQWV`[ffi}册虛箩ȿ鿴篨㥠᜖ᘏ☗ᕋߊ~wru{opjroriteldeixen`f^jXdU`[fU`WcR]QRKMKX=J,J&GwAvAk=^Ec@hBnDl@j4|*Ko7?\w!B_ 8Savˊيڙڤϕat{)Nf?z-Cq!?\ ;V 3X7r(Hg9Z9P;\9a?hLRZHX?P:J8J>Q6H6M8L4H9K.C->.B0?-D/B"9$<~8~<{="9-A9FEHSTd[kduk}ioop{zw}|p~v|||yzvtrgj}kq\kY\VNPFMNAS@R >J7R9_QYJSMSKTH[Qp2mv=mUO[cgi[RC}z:t@vCe>Zh<-Kr=8QmB[?TFYFe;[ňֆߞܛԈËbw-Kbn;X.Q/X1v)Em"Ga7O 4[7d"Ak6eBc>_<^:\C[ 9z(HKe]bmxwustqtlnloliqrˇzщ}Ռ|Ҍ~Ύ}Ќ}І{υẅz͇|·}ȇwˆυu͂̀v̓wˇ˅|́|˄}ʂwwŃ{Ȁ̈́tˈyʂɇ{zʅvʅȂwÀzŃwuÁ|ŋ{~w€zyu}v{yƀzǀ|xx~u}|vxz{vntvqvrpvs|rrwqrqxqvsru{sztyʊҔz֚ܥ嫆䳏赉躆ﻉ긃~}鵃쳅鲄鱅鲈浌붂굈뷂뱉鷅鸒鸏깐8L8L;O@LJcGS6L9G4F1G5J,E5G3D3F)@*@+E'?$A&? ==z;z6w8$=/>DQJIZSd_l^wg}iވponw|{r|su{~|}vojk|kkYjVc[RRIO8M1J*B+?*B3A8FHAZD_>^FgN~c{Ŋǎ‰Éʌqрь{wu|3Ua&Nk,]XN]"Rl0hJ~y@ke#V_T]"Rh!Ve%\g%Tk"^i)Zq+`q+]gPv8rXRR?T A]CSBPDXJTLa(Uu=sq8sl)Zl/dZ`hjhhaWl;WZ)EW!ERNWKZ=FmszplxXjH[EcFa-L]BPG\GZJ_@W<^%EV;Y>S>YDWDV?RBVGT2H5C=LLSNYNWNPS[X^X`XbU^[ddefukmipowmsrmxzxzts⁂膇瀂拁菂藏铊蔒뎉锒虍롗ꠘ痍獎鏍ꐍ욒雙曛蚇類ꛛ蛐囔皑斑薒闕盕皓曏呋响㋆~߄{rqppt|uzropq|nxjnjt\l_g]_]hakTZZ_\eZe_hfoow~厍訪껵紭⨞ݙ㊅߈ޅރvvtqjvfjdm_c[lai\g\lVb]j[c^gVUPWSYIUHU3F#CwBu?vBgA\>h9j(L|/Kl:jD{)Fu ?d?\5[:^@_>j>9MN[bjuvwzojoossjkjl~tυ|фzьuҌЌ~·|͋xЄΈx̉}ɃxȂ|̅}ЅuЋyʇ~ʂ{zʃ̅~ɀwDŽxłɁw˂wŃ~{Ȃ}ȁyŀljˊɄ~˃wȃzɃszz|v}t́zvwłz|w~y~|{xʂyȂ}s{xt|u|wywsqv}vwrwvws|usmm|mpprr{vyņ{Ҕ{כަᮁ泅浉跆꺄뻄﹌캊빁칈쵃궆鶄鷃鴄굇}鳁鴁~봄뷈봀鷌궆緑縌꺏6L6L6H9R'?,=>~;{;t;x6?,@?TTXWW[Ui[titclxf蕁zs띀}wzwvy}~y||znomw`o\h]]YSOGK9G,G':(>+A*?.A1C6E6D6J:ODPIfBnQepψσkkguwqdZdm`ogsb{Y\t(KYEYSTM`%Xu8rv;rw?hd'R`O^Pe"Rh&Xi+Yf'Yl+_cOb Tm&\p)at9wSG|5wv5m{Fq|Dxt9uXlrmEkn0Wa%S_EXIZH] O\HUAT@P>RBU?YATDUJTITM[ Ia$Tv5wt5wh%[o4`U`^}\s7TK?F9@ @KFRGfGJfrzveq^hSf;Yt N]GSFT@YD\>[U>WFVDVEUDTDQESGONOCNLX!K~UGZ EcDD`ڒ⣕ؑʂ}˗}G_c#Cz(@fBU9V9Z6g:j<^7a>`@g>j =]7`9W7Z7b7h?=SU^hnyuqpwzpmpuggolǂтyӌ}ьyΑӏzΊЍφ}͍zτuɃΉ|ʇżx͇z͈yɃʂt}wɀ~vȆȂʅ̀sʊ~Â||xȀx~|ˈȆwÃwɁw~|́kx|w~{|x}zƒw|{qwt|vzz~txy|sxw|yuwxwxvvtrnqnsxopqqlsnwnqrt{sАՕzܢୄ㰀鶉궇鸐켆켇콍칅븋|빈鵂궂굋鴆寄赂赅鷊빋빏鸒븙뷑輘齘缘:K:K1L4K9KBY:O5H2I.F(E+@.FC_,F+E,G/E'?%@*D$??x/I;DJWXU``scwj{l߂sxs|u}웂xq{}vv{~z劉xxnpm`vkk\^SOMGH8H3D(A-?&<2D,B1D6B6D7SCTAVWmfqqlkcj^eUcP`[vchiadbT}Aa3]{)UcSaTZQk(_C}Cut5gs3cd&Xh(V`*Xh([h#Vb Mk2jg#XaOc&^r.a~WGSFXR\Hn/^Hwy?f)X^Cg(Me+FvBSXfz6O`;G VBTAZAZ=V=X?U=V@Z>S=TDXHQGODNHSJd"JX_}zЄgTPVcYiUXwױڗߨ䵟ᶥ๧޺ǮЯƯoKY8H 7_ 4i9y;'<5G?K>DGMLMR\XUUZU]Y][`YbZWcjYjgkbplosxsvplqwvxxt~}~與拌猇茉萍闇蕐꓉Ꙍ뙔ꞏ陑럖蘓限韔蜋衜矘闍昏癌堘蝕盍ꜗ靏霑疋瑈掊匆憃䅄|q{x|lvrsovsymqr{eoklfkX_ba`obb[h[`[eRZVgcolx䁊䍆騦ᄚŽļ黯㥡㝓ݒތދህwyzvsvppcmfm`obham^nV`]l]kYb\gTRVdX[R^GQ9M$BuAw#Bx$DbB]=g9x&Eo!EiBd>3Px$C>Wp=`EQDXCcAC]ƀ׊ܘӐ|ӔOki?t*M>tYBXAUCXGVAUL[TUK^ Ld$?KtJc!USBV>q3KHX7O^:K>> 9C;N ;iF;[Ec]dx}w}dlVd?Pv,R~8Vi BUEVCO =[>T]DT?WCS@VDS>M@JBLCMGYKD`uyӅ|beJV[j\chnӡݫޚ߲߮⴨ⴗβɹi^=KaAXCi;u(Ct"Fl?i?9K/J:Uj>V;V CW F^@B\~Ւ֛ˋuyόÓaqq!Aa8e7V 7W 1Z/] 6_7f<] 7a9h!u"Av@:(H8CIHXVaZl`ufxlhppxꛁ{힂s}~~{}뜃z}wwhwfpbeY[[PTKL=H9F*C%:.B2F7F2F0H=I?M?OKXHXY[L[JULSQYS`MXS]_qdzj\zKlJiLoOCtPFB9u9q9l@zDrDtg%ThNq&Zv&WfKXMb Xg!`n(]u1mK[]d#^\Yn2qv:o[kibv7_p1Xa'HvCrz?{WBXH\Ig%N_IZ?[;XAXBXFUAXDZ@X@ZIXEY F["TUCTCVFk*F~CnEd%XQ?m*DGU}!?`9I9GAJ>M 6`;D]F\PXv~xwdsQ_?[MnG`h=YHU?M 7S8S=V@R>U 9Q:XGZFSDH>H>LHPFj"Gdrǁ~wY_K_\eX]˒ޥ᧔ത௛ݲ޳ŨиȨs+S=a9p?u>w9%?6K>HEPFPQ_TVS^QWVcSUS\R\SV^d^`_jfhnnprjupmwwyyz}wx{煂千덇蘍藎ꖉ痊ꛌ협Ꞛꜙꟑ蠒뚛꟒Ꙕ隍嘐畇衛痉瘐看矏ꖋꗙ蒄斈嘓掅千~|||xw{qq{xzzrtqpu{sxmohmirgj^fef^cXhR[Z__f[denqt|憋螔굳ǽɾ輲䥚ߜޓߏވ߈ވ߈zႂ~ssq~kpmpiuan_m`u]h^kT`^hX\[Y]cRRMQ=M3F}=m>v=s?\>\Ap?pBmCdAo<~-F9N6NjB]EYB\ @b C7Pv֒ܙѐdo~Ǐg|&F]4iGT6R.Y<^8`y6t=rBu8?!=7IHMZUcYgarg~ppsntxx|vz}yvz|{zuunl{_tasdg\ZQLKGI?G5H$='<-G1G_Cix5aq/YCjI}?vz?g@oQG|t1`w9[h!Qr-\2dhKaI^Re*bq.nx=rI\c|Au^U^$bm/gx?rstuuYJfV` T]!Uo8dScKYHcKZI]BZE[@Y;ZC[HWAXDWCV@VA^"M] I_LSB\GUEy.We=t=`}?wi Mf =@M.De>R?I 9F7P DT=@^IZQc}w{qxNch{ev6S\BY<\"HWGYJQ 5S>U>SAQ8XDV^:f6w<#C&F3J;GBQPYPWTRS_QYW[[eZ`Y\SSX]^daggnhhjtiqoqxvyywzvv}v{w}℃熂鋅薇蕎ꘒ瘋뗄졏웗ꗋ랤鞔饟ꧢꠓ矚蔒Ꝕ璐蔅铊眈镋뒍琂癒銇|艇u~~ztxvr|srtvostptuvtijlqjheg_dccZeTb\^`a``\bdivxxw僆阖긳÷˽꼳姞ᘕޕߏ݈ڇxuv|vysqopgp^ibj^m]i_eVg_aZ_RSY\LPJS@L1Fv#Du>zCmFU:_;r"Co8j?cEl?+AEV0Hk?[/G-E&A|(?#C}1Pr?w9u"I%D&>6GGJYS\`g]si{llpq|p|럁|{x졆y~}|x}pquzgr`r`g`i^VSDJZ b"M[J[D]B[JZD]E[B\"MZBV:\Et'GXBZ=a#Bf K]6;G8Oj:SG9F6M 5mFb^}qkOYU\[dWcˊ㳙㫓ⶩ൧ݱݰƫǴ[\@G 9L >T>X=d8pC&A+C8J>JCNRYLUTWMYV[W_Xd\f\_PT]i[d`l^e__dobaqrvruutxqrvwy{䂀⃂抑茆鍉돇痄꒎ꛙ퓍왏Ꚍ癜잕잓죗ꯔꤙ砒藓蕏薐王瓋钋鏅瓈菅蚃叇vx}t}sz{rutqwtmtuvqmjgknirgd^d`bbgRYZ_Zdah^kcp`ilusy㉍眖찫ᤔޠݓ܎ߋ⋉዆ႅ}yxxvxyqyioltcs]nbt]mZ_Yi]e^`\_ZZRWBK=M(@sAx'GCW+Bh;X 6[ 9T:eC~0FpzъڜҍatuvҒ8SU5c9V:X=^6W 6b={5Oj!Ac8c@c@cAZ6d;^3y%@>RY]mdnoswrkslmnstzt̂wӏ{ѐ~ӏЎҏzъʼnzΉr΄ũvɂxρs͈|̓vˈ͂w΃{̈́zɆςzʀtɀv~x|pʄŵzυyɁxȀyDžyʀn|~sǀ}yʄqÀ~}yȁwȂw~wzt}vyoxp}r~{{y|yz{{z|{zsrxsuvtrknmsfmptolŅӔw؜~곃켅}|뺅|캅黊깅캄컋뼌빋붊黇콘꾒꼔śƚŸÝŝØĨã0I0I3J.I/J/I-E0J0E.D-E2E&F)?'?)B*G,B*C&@$>~?y9v<|As<~>#?:FFGWPb]g_tlwgzlsmwvy~uw~{y~}z}kn|jxiz^^\_WILGP9E6N-@(<6G+@6G3H8EBPDO?R?LJWKSNYLVJTTUL\NWPVR]\^`pHf2Z3Zu>@-E6GCNIONTKWOVOXVYUX]k\bW[\`fo_hdk`h^_gklroqmjqrnjnpuqxtzt}}ꋇꏁ{茏铇뒋똓횒띗颛훙헍ꕏꝐ룕鞔閆阍薎撀曅暔虎蒌蕊撁净膁{~|~zvuxqrlqsroohnsquxkgpxcdel`cbbW[XYTY\c_b_h^leklqw|⍑疔驚Ǽ»㦞ޞݔጊ܌ፏ߆݊}|{|wvrqnomtkocs^l_ndu[a]g\e\`[ZU]NSGK>O$={Cx?r>c?S7gxWAU=`Cg%S^CZA\L^E`H\@U=ZFYBVE]HX?W8i6WQ>U=X@S =Y=t'_A/M;SJ[ThlOtRkƒ}͕x^l=Y^9K4O 3I6N 5M 6L )F6JBLJRKTPOVZSWPWQVY^\dag\dae\c`^_gcdhrlwqnopkkptnsrpus{u煀u珅늃쓇똋엏蚗뙊꣝藌ꚗ靓頍飛癔闐떏藔ꒄ螊蕐瑁搄|叁|wyzxpuxgolhpwjkimsxsnlphkijaa`f[gYUZWXW^cXaciZeitqzzy䄁搓읠履ޛߔݓ␉އވ߀~|}{ptuxnvmmfn`g]j\jW`XiVeV^\_T_SUIU3F"Av@&Cl?\@Y?f=j=h>iBb?x@0LDV.Cl7Y 8\ =Y=` ArDu{җٛڒv}{ӎWnk?]:K8X 7a 7U :ef#Aa=[;a;a>m=;LPXkkpbumpksoxvkh{|̇ӃyВҗғՏrҋΌ}χỷЅzυ|Єs͉}·yʇyɊσq́{Ƀ˃ùz̄}Ђxʇ|ˁvŃɀuȀv{xǀ{˄{z}w|ÅyɁyńÁ{s}{|wtŃyzrz}ytzuy~xqzw}xxvuvtutynommoimqlokogkx{˅uՑݣ~泀뵁분ﻆ}컁}뼅וÔÛĘȞƢƕƠşǝà2J2J*G1J)A0K&B(@(C)A1K'B"D)D*D$B$C0H%<#?z:~ @v$Cx;r7v;#=%A1AAHOPaZmlqgvisn莁v{r얀wuu~yx|{z{zsvuoghxdtaaR^VZWFJ;G0E,?.C6L1B3D4F>S^Cl$Q^?`BYFT;c(O_CW?[HZG[D\C^*O[#MX IT<`#Pi(W\CZA^4.C~'?W >N :K:pE DCWJ`WccxI~>QhXԤυ{{zcuv+JO;G 4NDSCPN?NEP;XIj.P`7k7uE~7)A3H;B@LHLNR]`T\PUQ\QXTc]aZhig^l]e_abndgkljqnwiousvzywxx||rm|vzz{s腀茄{ꋆ펄뎌뛐蘎Ꝓ뗏똎ꗔ霄ꥏ雑때疑鐅攋虐痋犄猁抅{wptッsoqrhhmhlxemhmihqphgfkfefe]Z[dUYML`mZ^YX^jdmknn|v~ゅ䍕馧ĺ㫦ݕޑ݋ޖڂ߃|{z|x|pru}noksfofqck[k]j]i_c^aQZX[OSDQ2G%Gy BsDg>U7X 6m#Cg;l7d9a?m<(AAW-Ji 6Z<[ >W;^ Cw"L_hԝڥ؝zmxϊˌg{u?X:R$>#@1@CHSO`bqjtrxkmnr{딃zxz~t{u|y}w{usꔂrgy_qahUc^UOCJ` 52LSeVgTxCm,N7IΈ`ԑҝÅ}Tjx(JQ>L?Pf<^[wpwaGPRSTf\Xw}ݼݰ⭤个佬¶˳Ͻ˭r.?J?H 9J ;NAT@k$Mf:m:w? F.L,DALDRHQHNV\WWV^U[SYV_\[^cce\^[aabhoehijlmlqpnxtuy|xrxvv{t}~z前拂鉃딏슉镐ꚏ暘ꔆ똌띕뛎왍ꗒꕈ蒉萈钇鑃ꕃ蒄獄荁}v愀{~xqnsoqslpikeffpefmvccopce`g^V[[\kTYV]RR\e\d\geqnq{}~拊囙»尩ۙܐܑތ߉݅܁ق}yzy{trux|nojzhkep_l[bbg[kW[YYUYW`IP?M*Ez={ BicBk>0CGW2Gi9Q 7T @V >V=jA`jіנڙ}nw˄ɉ})IW >TGS9T@M 6X^Cb:m;'ADV_imhxwresoqnlknwwmђ؟֦֧ӊ|҇vЈxшyϊыzσy˄sΎy̋υy̓z̄yψpȃ|͂v̅{˅zʆ~ʁs~tǀyuƀyǂ~sȀ|yˁz}uƁ{}p}|v~|zu|qvr{vxy€z}t|~~yzw||}p{zwyussrqurxiorqoonr|wψrؘߢ櫁겊z︆~~y~ﶂ뷉켑칇뺉꼉黊쿓뿊ÕŕŔǜǣƙƟƗĠǝşƟţšę¥0H0H-K+I*J/P0I(G6N/F,I,I0K-K.M$F%Dy#?}%D&Ev >w:p8p;m8o6;$@0CFLVRcipnurwhrtqv{uxx~u|t{y{y}szqzm|`zimXi[`SRMBP:L/C'B%D&@)F8S4NHaQyMzAS>MCOAKDMIKHSMQFOI[IaGhI{XXly`Kgo%Zx.lp*e|4iWeNQr+_iSFuljIqc"T`!YZX` Ui0ss5n^Uq;z]UTTV[b)`xJ~mQn9_pI`SZG` Lm.Xg"PgP]C`VeK]?q+VcC^FUCU?VCYAXCT8[@^EZFT?UFU=f7MX{QbYBP 8P 3`8|*>h9Q;UAW >^B/MWlUpgWu2U(HYR؛ؓuцpYkw0QRBN :H 6C 6H9OZB]31ElcӀnZT@RPRZb`cӛĵ߮⸩罰IJʱӽƷiIZHKCG 8O ;N8d)Pu*Ll8o6u9<%A/ACTESEPJRQXSWSU\c[`ZaW][gX\__eeihirgfhiqposnqx|kvyuwyx{yw~x|ゆ熀捁䑊鉂ꔒ鍉둆웗ꗉꕒ땆隓Ꙇꚏ엑際鐌菁쑈閇썂ꍄ珇牂z~y~{ynxzuurnopgkiphsgbejikhhd``fWUY]TeV[\_TU^d[`]gcporru{ノ鐓½ϿȺ嶰ޔއⅆ߇ߌxy{~swu{w{݁nwoqdqire{^e^b]o^cZ^VVT`MR;H1J~;w!Ee 6V =[AaBlCchBp"Iq#B2G=N)Dc5V 9U ;X BX7lE\nϏ؞ؑˀr}˅̀}z9OcIk$GO 9P1Q 8d@n;n&Fg!C`BZ"B[;_Hp<,FJ]ghrhpkscronligxv}{Ћ|ҒӐwԕӏxӈxӊzԈ}ӄvψ{χx̓wΈ́{͇{˃{ˈv̄zˇ|v̄z˄ˉzȃ|}oƂ|x̀ʀv}}~xx{{~xǀv~}r}}}w{u}t{w{t{uyy{y~u{{xt|wzx{|w{uywvsopjqulpmjkulqrp̄w֓ݣ|豈봆칂캊ﶁﴂ}~xﲀzz뻆칒—ÔƝȣƚǗȤǢśțŞŘġĖÝà)H)H.L2M6W0M.P-I.J,D1P/M0L7U(K'E+L|+K-Jz&Kv?x"Dt>o>iNIOIVBRHYAYHlScoet}=`t-]\Bl#`u/a>lVqhQ}5ej%]z?qry}Bkg#OXR\U]Rd"YMu-md$bw>xt+pc$dZ^j6w`oZzDgxkm+_R CWMk(Re Nj)X]%Nj&\dIcFs/]fF\MU>XC["IXS8V@j9\r5DtDY_AR9Z?b;t!=p:Y>a=a>uLC\Qj_u~mtJU-I0@s\]T}aҧąWj^b"E},Kp=lAx@'B-G0Efa"OW\cXܫԠuy5KS=I 9H6S5O 7J5P>M :s;el҃vgeN]R]LUet͎佦潯ôĵǭ̵ջFAO6F 7L=K :M :T 3m(C2Ku=l7{=:+F0H7B=Q>KENKRIVSXV_XWTX`aXXah_`ad_c_\kjkqdnfmlnqsxu|yzyz}{{y~|}舀~銈쐄쒍ꝉꓒ铎꓊땎蕌鑇뒌蘊疏ꌉꍊ钍鋂鋋玄{|t{xup{owwqnffcn`dfl_daabmced`hmVYSYZ`XZYeQQR^WW[caddocjl|y⌓旖ޘ݁}݉z݈ށ݂}|swowtytisiufrelenY\`nZbYa_fSYX[JS6K#B{Cf>`GW6VDcBl >`Bt"BqBkZ9m?N_˂ԐԑЁbnŀuyipLgj$Ej@N3K 6VBXaljjwitlpftppksj˄~̇ӒzՋyՌ{Ӑ|ҏyҊxԇs҆wϊ}ЍvΉpτ~ЇxЈ~ȇ|̇yˌ}φx}tͅ|˃tɀztʁ|wrx~tĀy~v}~~p{uzx~{~}zv{svyys}|u|tyzywrt{s|txvtxvpvwsrqlfknqilkvoʉu֓uݡs~鰈귀~﹁xxxﶂﶁ}뾌Ŕǚŗʠʡ˦˦ɤʢŢŠśŸÜ¤Óâ8L8L1L4J)I2J,M+M-G-K7M*I+H.K.I0M~(Gy$@|!C~#Cy>s=j8m:n:h:}"E*F=GILUU`\mingwdrpvw|铂ꙁuvtt{}~젂syvzkvm}cxfobl[[XRPMN=R,D)E,H*K)K'G?Oa|oW};V9L]`YSpBɗys~pC|yHfYbIbM\FdRhJ\"Cp?hf&Q_ Gm*UgFY@V@P 9TAQ :N9T?Q 7OAZFT =SAW6w$H6S1M0E&<(E0Mr?_;nD*R,U>f?`aՍzpv?ZwFj<3OW\هaۡtĉrJbT :H3F 7L3L ?E=J9T 3BMv|e`cN[LXWayڦƷ纰ıǻưɯƺUZ@H 8O>M>L :TBT 5q+K9Nt>i:z=6(C2F5HBN?KKOKULVOZZfOW]_ceX^\gbc`f_c`ga`hjelnorqjpstwuxszyv℆~{懊}{u肁ꅆꎅ釄蕏眐ꏇ鏍꓋莉ꕏ뙏钇鐊蔆铊芀ꌂ}}挃z|{x}nvvqogdagbfcfao`aelcf\^aeZZZXZcTQSXPQS\UY^b\e[h\fhv}⌑敘Ͻࢣ݌ދތဂހxဂvwqtrsrntinku`iaian`c[`]p[aZ`W[UTBN-H#Cq=`AZ =W :UDfEhCh?|(DnAhT4T 5P@ZF`;I^}~эГσbiłuTu~1Qa@PBK 5Z@gAk?c!G^B];[DU 6a<4JLXafnjt`pnpjpnousmˀЉ{ҔzՓ{ϋ~Ӓ{Ԏu֎ӎԈt΄yҋyӊtφ{Ќžy˅x̓xφwʅ}ɇ~фͅ{̈~ˆxʃuƁƁ}ƀtŃ~|}y|wǂ}~v{w|{vzx|v{u~uz|zsv|wxwy{vsxwxrsxxwz|rxorowmljrmjo||sҐy۝y}~鸃y{{xv~}~︁u~x컉mᅨĐǝŘǜʜ̠̥ʝ˦ʞɝʟȚĖ鿙à2I2I*K&H-J0J+G6P1L4T2N+L-J)J)J|%F|)L}'Hw#D|+Iy$Fu=p>k=l6o8|#A+E?MFKVR_\k`pnyipnv{u엃}vvu똂ww즋z휀xvrlim{jtfoXc`^_NOAL6G#>(B#;-ND.J9Keqz_?`B_6W?hQzjÐɎ~l~[xd\|Hlq$UR ?TGaY^Ol#^TctkGnF|fit/Xc%W^N_"ca#`RSUVj=xlNe.\{WyBZ\^![xN}dnwEo*Xotu1g`I]Je#TbL`&Kk1`j#U\Df!Ol#N[?V?S 9N8PAL;M@K:M?WDV=bBq$@7M@Q=R1J0B9M3Nm>\;*KHd6^1[F{vϒݑԙɏZf'DaH$GDW`^}ef[CWU ;E0D6J ?F4B;N =i#>nxɉcVWaPXP\dnЌ仴澦îöūɫǺßro'9N9K 7O 4L 7M0E:RI4G 2\;i!>e;a=`=[9^@Qr=n9h7k9f 4t@/I3ICDWS`ckanbtknqt}}w{x||zp}홄zqvvisgfs_nVm__^UT@H2F)A(A(<&G%D(K3OSZ~vM7aAcXvƐˑƀb~QrT}`si8_bITBcXfSn[Cfixl7^6begq/Ye Wg$Z\ Y`&cX#\WVY VzN^}Gyo7oUh%mk6rjfOaYm'W_G^"Hc$Pl)\e'V^(Gl5`cK\@e!Nj!RY>T:Q 8P;M:J3I 3F 7H7XAaJw(K.EGSQfIV7J6H.D+Cd?\:5U@`+QHkyޓ夊䣏ٟpw-JTAdA3IKKu}`f4A2F:P4@L~}̎uRTRaQYSXknՒ伦濭ññǦʷ̰z01P4G 7L4O 5S;N 8K 7V4x.E?O} ?v;z<: :1G1ADRAFDOJOPXQZXdU``f[b\\_aXb[b\X]baibfinehlwmqpytt|wx{xt}}y切慈|净~鑄䎆鏎片燅葃ꐎꍃ鑃鑋鍎菇芄}犃|zp|z{pxvsvlfejc\fi`^^h^`]jbh]`]a\fV[\`UbVYPVRXWcTZV]\egjpsz~ㅎ瓊꣜￶ʾп絴ڄ}܀y߈zᆂ}܀v|vvwuvtvpvotjhr|ck_m\j[bbiZd]^Z]QYAL:J)I(CeAQ>\IU=[DdAdEkA{3Kq%Kw)E4R*A:JCRd 9V 2V [?V>W 7U 5w@AVWYlowp{qlgxotsopyt͊ՇwԒҌ҉vҏwы{҈s·xЉ}ՉoχwΈzЄvЀs̓|чūzΊwͅ}σrʂvʁwȂzƈ~͊wʃ~ʁu|ƅ{Džz}r}ÃĀuŃ}~‚s~vyzv}yqzwwt{vtuyswvvkuqopuxwutspskhqrjkospnɁqԍ|ٜxz}贀뺃컆zz{~}z}|콑ŒǢȖȜɢʟ˟ˡˠˠ̢̝ȣƚȣĢ™Ĝ¤,D,D6O/L*H2P+K2N4Q;U(G5O1T-O*F|$F|%Ix!C}%Gv!Dx%GqEnO2Q9Q=K8K;H6U=cEYFwD&BX]kzcgIQ4H$:w=iC^C1T6cKydnqm߭姑㩐ܨ{?SQ=[P{=@Fstaiy,GN 3G7A2?4B8Q7fAXZэtmPQfnXgX^{zٲ⻟µŭ˵ҿSCT9I 2J 7N 6R =K5K2R 8Z:|1P;R$@s4~;#<';.D4BDJFTCJINGRU_Z]X\TZ[d_bY_`cXdW[eifkfn`iahiiptxmtvqt~yz{sr}t悈v膁{y{~䁀}刊擇呎瑂~돆珆鑂范莆鉉xyꈂ~s~ywk{{prkdilgma`afZc_^bicgab^kU[XVYcV[PRS^V\VUUVW_Y`egjqv|䂇掊ꛚʼһ轻ۅ}pށރ~}~|zztsuspyqwnyitgv`m`o^l^j]a[]VXLPBR4H&Hy@Z>Q?S;UA^@`@Z>q;$Do$Du+G2J$>2C?Qc8W3N3K4O2CDG\a`Wjhul}htuq{~s蓀}y|wuqzyvu|pqektfkThc]ORI?H6D1C#@!>$A&D(E'HU?fOcK[GaHe FY@V7R 9P 3U=Q?M 9Q:o!L~,K_NoKw DCFX\ibPT/G>s?oIu"Ty*NLs_{`|ZiSOڦ䬢㪕ߦ˅JZ^=S =o40?]`1D[ 2K6I5B1C7E5R 25Looр`\XNR\kWbYgҐཹ忪ƴȭɰɿ}W[I:N 9T ;O8N 7S?P ?Z2z1H@b)At6{:#?&A)D6H=M@MEHKOMZNQ_b`gUWQcY`^_bbVd^bb`diejei]peflnx}nunqvwvv|}ywuw~愄y}䃀~x}z넄y~掍~|鎇ꎇ掍~狀王}捂挂{}|{zoqgprgajehc_\_g^d]^^k`c\_]dT^UTW_QVQTQ\TXU[WYU^[bekiotv⁇㇅镔줣ʼÿܓ~|߇ޅ}yڀyz}}uppuqtpzhninjoemZo^g]__bXZTUHOFP7H&Ck@U >T >V?[Ec!C\@]7oB~%Fx(Jw&B1H}.G(==[k7U 0Q 9Q8N ;iC+Hbn΃ԐՒ‚ihϖvrt~?YW<@4L9X:f#EV9V8Z:]>]7`B6JGUd_wrxusirlpmoiwxу~Ѕzҏ{؊wыxӋxщyӎrӋyьӋlςv|q|kυoχw͉wωyωx̆ü|̇~˅}ɊɄv́w͇}̅x̄vƄ}x|}|w}~~vÂzā|Łyx|w}wu||{u~|txwwurz|urwzww{vywvqovpspsmsoopw|vЎzݠ}w츁︀{ﺀ~쵃~칀︀﵇츄ŗǖțɚɛʙɣʙ˞ʚ˟ˡɥʟʜˤƙȡƞŜȝġÝŠȧ1M1M4K0F1H4J-G-H-J-L,I}-N|*F)J(F}%D&Fu$@z$>z?o:u9p;g;d 8b 4u9;8GDMXT`\bZm\x]uuoxꗋz뗃v얁욄ys~tw|{}ronukz`xiqXmb_WNLDJ6G1B&=(E1D'A&>-E4J:PKWg_ushTO{EtIqN|KqRv]Ww[wAq'^jQy"co LQ{mSYy9aa,ZTLu@xt,hp2hHwCc^Se&`n-s{JJA}q;j_pSq1q^"X|Mx[SUh@m+WxMf{w.WL ?WBS=P<_!G`#Hh(Q^ Fg"JZEU=U 9T9W>S=L7Q?`?kAYHp*_l"Hs%A7ULRLW/PyAqH1UXKvVm^d[lCZ)Ct^ݱ㯡ޫЋ_px>N 9e7p"@6Gf>N 7H5@,F7@5I9c7UXzwlWT\PZSbY]v۲ļïűǮ˵d":M ;L 9K7SP6M ?W .4JL^/Gv9#A&?!:&<3B=EBLEJMMMVRYXZ[^RXW`Y^Z^\e\]cfdiegdifiiskslnqsrrlonnxu}~wwtvx{|x}|z{|y傂傀{z憀{揈|芆~ㆄx芃|担}y|zrvsqjrmi`iba`aac[^[d]eacW]`^\iTXZcUZT_QZTTQ\UZVd\g`giopxဂヅ琕잝촰Ǽۜvt܉ކ{{~z}zyyuorvvzotjrepdn`lep`e\eZ_T[QRJQBQ4O#J`DZBT=XD`NaEb>`=o%F{#Fw#=r E5G#=8H:Ki2Y 2W5M.XN:YA]DcFkC>RXhhpsnsftopkldttvjҀv҆vՑ}֎zՍy΍xЍ{ҏuӆxӌvӇuЃz|ryqЉsρuυtφuЃpΈtʃ{n·q|ʂ{tʁu˂{̈xƄ}ʅ{ʃw~s{zŀyŃtɁ|zu|{s}€{|}uo‚y{p}zvsvtvuus|xqsuprvuwrlmpworxq҅xؘyz嫄}~~ﺅy︁v︃~캈z뺋껊”ŒȘ˜Ȟˡɝʛɛʠʞ̣ȡȠ̦˟ɤȤȚɪǡŝƜŢťȧ1J1J9O1K9P0F,I(L1K}0L&I'G-F)H/M~.M}&D|%D{&Bq9s=l8k6f7a>f:s87/AGLU[Z[f_tizo~sywx}tyx똂mz{{q{u}rznmnbzap[j[\NLFGM4B/?)?)A ?"?-C*D:L;KK\O_NdVdauXY_XQUageaGo|+bfRcMdNG_VOs9^r2pK8u}>sx9vFn1kZLbZw>|?yAz>q5iyGvgNw9a%[wEkKxC\jAeTd2Lk|:gJ7O>PPpV˖zɕuyV`t9O 5S 2c4h@\=XDASDKLPPSPXS\NWX]ZaZ^__YaY^af\f`d`hflhhx}egnpltlzutxvroy}xuyvxwzy|wx{y}v䁄zx偂凃獂鈁}肀}y膄}tw{vuvqiqtgje`dc`aW\^][bXZVW_d`dcm_dU\T]S^X][fQVMPNT\fX^flept{㇇铕隝첨ɾǻ⫣uo܁~܄}}y|zvzxy~gmhmenmy[hdj[d^f\_WYUWBQ=M(Iw?Y>Q8R@VAZ<`?fC]An#D,Fv#Au!@/?,A2G5Ji7X 8U0M;P7eA-MQgǂՓ֘fjѓ{su|Uk\:R V <_:k GtGGYXXvsvrpgvosppjqp{hӊzЊ}Аyъ{ӌwЉqЋwэwӆ~чr͉yˇ{qЄrЉẗ́w}lʅ|΅xΆṽ|̄~̈́x΄xNJ}Ƃyȁ̀uȁ|ȃrǂ}ā|ʃsǁxǁ{Ńvƅyȃu€v}s{zzoyw{{ww|{zŀy}}ltwuw}wxurntvklnlovmkxuȀqՖ{ޡ⫀範v︆}u|﵁wﶊ}췉뻍뾉ĒÔƘ˝ˠ˝˝̝ȝȜʟɠɡǜȚʠȦʠȠɤǥɢǨƟɨǟǟ.K.K2K.K6M/G-K.N,M2S'H+I-K*H0N%Az(C|(Fv&>o:i>l8o:eN 5X4hJbGL.K 9Q?I 7XDX 2@Stir^URYgYbZe|߰ŦƭĦ޺°uVS;K9M7N9U;U9O4V ?T 9U 7T>\<=VL[=U!;z:(C"9.A1B8D9I@FLPPSRWR\YZ[a[cY^ac_c^c]abb`gdm`bgnlt_alrkomrvyyqkvytqwussut{x~}u}z}xxy{慀䆄{犆劃~{䉄劂懂牃v倁}{~tjt}pkmpojggagY[XZVYV\VWT^[d_^kraeU]WdS[TXY^QSLTS`X^^d^jbiqvz}₈鋋똖žɶ᭨zo݁|x܁}z{uyxux{tukyhnhtingk`j[e\_^h\^K[FK3H%@h;R>RTuzӐѓ̄iqЌ}|tt[tdWFW@U8Z;]GdD\?`"K]JTIZB_EY @_9v=fQ{~/Hv#>t+M3V(K3OGWl}^[RI=AED8A"Hi?t*I@dHdw.Nf"K_CT7N 1[FV7eB_@J1A/L 0T94U~1ISZm_YQQ[dg\\`lΉ忳¦°ןt͍Řyi&6K7M9I0O 6N;Y9U U 5V 9X5@VRiCV}<#<#9+>/C3C0DAKFHGPOUOUQTWaXZU]Z\X\[\_d`e_^iob^Yc^idgcggprtpovusrpyxtrwzxsywvuru{{y~脄{~恀儂鉅抆}剀犃愉yu|}zy{siuvlmompnih^cV[QXKRRXV]]dbebdijcc^bY^VaSTUXSYWZR^Xb_dboahqwwㅊ鍔Ꙕꞛ˴ⴱtl|tzw{zzyzyxx{x}qpjneofqdg`o[h]eZ][cabL^JW1IrCY7PAQ?U@UC[@b?`?_>nB}%By$B|'C7M}#Bz%?(9|(E^9Z :U5R5d<~&O;Upz·Аɇp{̈Ƃ|ulwy(F[8S6Y>S:M@M 2O 6]>|'L1NNYgdumvlzlxhqjoptpЀyчvђ|ՊuЎ҆xъЉvψ|Їv̓t̂zΉ͇{ςẗ́vɁp̓sȆxˀy˄z}yˁv˅ʅpɈ}ǃ˄tˁȁyoˀ|qwÀy~Áły}wąt~y|t{s{s|w{xzt}|}vvxysxtrvonkmrqmjmvjmuwĄՐqܝ䧁賉ﺉx﹃yv﹃•Ėǘ˟ʣˡ˞ˠˠ˚ʗƞƔȚśȚǙȠɧʢȟɡʡˢʡȤɤȬƨ1J1J0G0L3M-I0K7N1K-I4J0N7Q,F,J2K~!?|C{!Bud 6^ 2o17+=>EWX^TdVpaufsv}|z|였욀{|욃}|xw{z|q|mkav\oWjYYUSLLP7F*E'A"='J+G+D/F5K>X<\EkVcf{WsIgHnOxQuYr[o`}\xNyjJhSz0b;jLwBs={nUp)_M]]NCj&Wi Vt9xR~Fs4il&kg(oc!X~P]c WVQ[V`-[zVb|>c&^Pz”Yp*l]Id5R}z:kO?R CO 7VFn&UUAO >Z@U_9`%@IoA^87]2S.]C[^mʜwjV_,H~#?wt5s;l9g8b2e 5]+r48/B=CTTVOaVpgyt}mnmyy{|z}zyuz|yxztrrh{cpYcVXQSLHL:I,<(@"<<&C1N3M5TEk`]`a~YqKfH_NjNqMmQlPgRfOn5egMt$`~&^7lO@XJXJVC`Ql7as5co%NZ9S6N 3E1M 9P 5hJm=["B{AgnIk9^iWy%H0QfogݑǎziUqLhDdLdS_PZC\s+D`?P 8M 8O 8M 5]DO6K=E9H 2u5Zf~m~\i\_`aJSIVPoQhzrիӣ~͖zvv~t?hr)T\:N ;K 5T:X5\9V4Z 7R3R6\5ARVl=N#=6'>*A,=-F=HUBR >X:]Ca"Ea?T?_<{(@{ A|*G-F/Dz+E+>(Fd6i;U.T4R6cCj8(HjxɅњȆĊ|ҋ~xs}CZZ 1o"BV7D 5H 7QBV?Z:6QO\\lqgzs}vuytsnxnukӆ}҉xӎ~ҋxчvω}̌}χy̅xφz̅˅x͂ṕs͆yrȅzƅyŁ{·tʁxurr˄s̈́uɀv}rƂuȂ~˃xɆqƊƄy…ząuɂ{„ssȇv|u|{l}}yvyxypx~vqtvunwprsnniispkrpoʀ|Ҍqۜ{宁뷈뷈z~︇}~}ﺌiᅮÓđƝɝɟ˙ʡˡșʛȓȗŕĒǜȠʤɞşˤǥȣɪϫɣȨɥɥȩɨ5H5H8P3J6O2L-F0L3J-E3N-H&B'E#>#C?};|!=t=};u8i;f5c7] 3i6;+A@BWY\Uf\l\xlpvpuwzs후w|홃xzy}|}{k~mczht^i_ZWXUHK9I/A&H#A$C)I4T=ZY|_npe{OfG_DXF[KjMp\{PqTlQlCm(^u(`0f-c*\BsI?k!VD_hcv6is*[t1mzCz6og(Zo4xn-qa!^_!S~Ojt0oURMLXYwAh|Ge^q>xxyy7v^Q]"J|Ywoi%SSBWBOEYL]Nc$Po2hk.Rg#I^KV9S<\@I 6L=K5s/U3Qk#TAb?sTyna=W&C4N=LNOˇVϓ{„njkGR}2Fp!;o/LeJ7H CF=p1Q|ňƃsyi{_gPbVbK^^dkpmtzǔWfi6W4Q 3Q 7K 7S0Y 2]?T 5W:g0]Q <`6?KYj?O.C$;"9$;,?9J3A>KEKRSLPRXUYTY]`XZWY^[W][]]aad_i`chhbclhkononrhhkkmlpw~wqmzxuvtyspuw|s}}}x{~xzz怀}煄zv~~恁}{zqprolmjioljkWZLXBNCQLSW\^`aeglkjgkcfejntjmmjdgam[XZdV[W]\l^ffmsw怀锔ξʷ䵭tpqjvwx}tjuwtqsxqumqiyhmcm]g\gadW_[\S_RcIZ+GhdT 5S4M3i@c9w!Ao~|ϟˌɍ~ш~ǀzx|Dbg=l"CcCL =I 6J 6R ?`9>XXcchuptoЁkqd~qsnrf|rшwϏ}ӎuІtьyͅz͈sхẍ́w·u˃xψs΅u˄wt|q˅z̀y~uˆtˈ}ǃuˀqʀyŁv΃wʆ{ͅyʃ|ƃxʆyDž{ŁsɆ~|zvɀu|}ɂvzƁ~}t|~nĀ~~s|wspupyuokovlkmolomntrхו{}ﶂ︀xz}ﺄノđ×řȜʟ˙ʙʟʞȚǖɗǕŕŕƖřŘŠȞɡȫʢʦ̢˩ʪǧǣȦȧ8P8P7Q9O1H6M1H3G0I4I3I-C-H+E(D!>"<} ?W;[;W 4cFfIN 3H6N 9dCr@o&[7LQj~g֌mKRz!Fl9t$K2Q:ILFT\CWw#=`O"8$?'E';;N5CGMIPIOOPR^VW\fOUUYZ_^eWb[b`aZ]\`bgaacegjflooknmkosnpnnrktswxvwvtzttoxsᆄ}rzむ~x~{x}|}}|䁇~||~wkrpqyqqkjmjY[R[>HHNMYVXag_dkijlkpdhgliijkmgllfi^]U[QTV\W[\[hjrx}钏래ɺ׿ָ˹㱥uqniunx{wsqrusnsmrejiwehbi]dZg^gTYZ[ZaU[=Gv"B[AQ ;Q=R=T7R 8[A^9`C[Ag?x"As =v$D-J+C~.L-Ht>b;m;[6T2S0gCa :n?_oӝЏ΋~xt}srVdw%Ab=c?H :F 6N@M vC{:h 3cA^ 2` 6n9#>3HKQTS[WcXrltm}pvz대~홅z혂y왃u|혀wu}zxxjtpeygoZfX]ONQHN6K0O*P4][8g"N{.G"CYPgIW=K%;!:4/G5C9CDKKXMTOSO[PQ`kQ[X^b^ZeY\XZ[f[cac`a`^agimhoiekwikpwijpwltomsl}~wwusxv}}{}}xq|~w{~wz{v抉ぁ{}x慂~y{wywvkxnosrsv`hMVBKJRObUX`fmoikhkedakgaqpjlljnqhm]\VZPXNWRSXYfaqz|p荃잔±˰ӴѴŴީnjql}zwrpy}v~swiklqipjmaf_h[bYdZ^]^MYHR.JoKV@R>U:XCT?S9b@_?`B[Zn{֒ΓЊɁy{hoXk6Q]>Y9I 6B5J 7Q >i<6Lmyqo{qwhyl}rvbsuupу~Ԏ{Ҏ{ҌwΉxюü|Έwϊтq΀t̆ẘxІx̂xʀwʂtɁzs˂qÃźuʆtwˆr̂rĀxǃ{~xȂv}w~x~uuË}~x{rņz{Ń}}wt~szoyyp}u}|x~|qorquutsl}hmotuɅwדx۟x嬃촃{~}qﴂ{ŠśșǔȟɛǙǚəȘɔɜƞƙŘƚĘƚřɢɣɣʣ˨ɪʦɥͣʥʧƤǧ=O=O7O7J3N.H-G:N1J+D+A5K/B+A)A <#B#>#=!8w">yDh4f 3f 3b 7z;.I5JKPSR_Wb[rexk~mmwvxuzx{w蘀yꙁ휁t|xttv훃tkqo^fV\YSRO[@X8Z6XPpee]rdiL[GS9P;OBPCRASCUH_QnW{VtYxUtIu:l|']z2dj#V^&Uh)\?yC~DYP{cY8w;tz4in/ai+aaW[La Ut/{d(]xQVwt5kg%^WUPUQU[#TYrNt.yf'irC)Ljʋљ՛ؓӠٖݚړ㝕㣗ᥖ⩘氕֝us`a1Bo6R8O 6Q 4P ;N6X8[/c:WBZB[8Y 7bFHSOTOMObW^XTX]]eVW^iYfV]ZlXb_g_i[\elnojjanifjmujqisw~lkurx|qqu~tnuxwwrr{}||u偁zws~{|灀Ⴠ}zz~v|{~ywtqjryrojixw[`LXCMLWUbT\aefec^afd^ab]XaUkve[^Zgh_eW`NWN`KSRT_cpnto灃ꖈɱȱ꿸ٔtnurvwrovxrtooolprpzjqgikz\^^b]\]ZWYMW9Jy&Q_BT@T>SERAP?RB\He G]GbEi;y"BvA{/F6Ps!=)B1BxBd 5e:f<[ 7S :hD[ ?Z:Ne|ӒБӕʍxobo\j2R^;Y>S=E=H=R SBnKd?VH]DY:T:L8L>T=O;L@VAT>SAUEXOhY`~Se[}Ep;m:e|.beJ`Nq0mBuGNKyRiSQ>sv2bi'^n3mXRL EWRu7xVx}Bzy:rb%Zc*cTUOSZRyMo[|6p,tv=yeȝpn'b\][GrŇGvZJM@W=^H[=VE^FX?d;l =Gc*GR 7G5K=MDN?_$Gq5^j+Ug'Pa"JW9LQ<^Ci,Sv3V\Ke4C):i8X 7V :P;N:J5Q 4[;T;J2FBD:M,ʣΔ֖חۥۥ֘ء٠ݥޫަګ٨Œogv19^;X3S 8L2O0Q/O1Z9^7`4X 6Z 9Y ?U:e7H_XjI\@U#;(=)=1E7A7DAEFLPSJOTYTSYTX^VVVX`eX]U]]d\`Z_ap``fpfbnwhthjlklnjlpnsttswrvxts{zxzsxv}suwwxyr}x⃂w{|}|{|僀w~ywsxxootyhbjm`hH]CMGO[dW]dibXaS```SSIHBQG[bZT]P^c`hY\SVS_PXPQYk]anlsoꌁ⭔׀xwmz~pnqqz{x{qvotsuryhlfsktb_ad\WV^X\HS'@e?^}-L*@oAy;-Fx;^ 4c1jA_ 7U2b:Z C[=;Sv͐ҘϚ͎tsv|rz`l9QY 9P 1WCF 8L3X;"HIQjn~tyn΃hwbuntovjɀzчԍvԌ{Ϗ΋̋ω~·ʅ{˂w̓ỹ|φyˆsɂo~v~̈vǃr˂y͆̄uń~ǁvˇyLJyʄt͂sƇ}Ăńy~x|yrŁyʃxǀ}r~{ˀpDŽy|uvyu{yvz~wsyxxvyssmmtoonumtml}tԐyܞ~⨁尌w{h|y|y~テ&ŒŕŐĕŗǙǔŝșȞǣǝƚǟɢˡɛɢȟɣʪʥǡɥ˥ͬ͢˥ʤɡʨȣǬȟ8P8P?Q0J0G.G5M,D2F/J/C)B/D1L2I&>#C;"?"Cy?x9y7q:lS@WCTKbVyTx^{:mAj1e~*a~"Wq [v2i;rLD}F[n`J5lw3`j*ff%^N@G FY!ZsDzYGz6oa%Vu8~ZYVWWSqDxsXD{:x<`ЭBf$i[ N`[aOPDVI[HUFZAv3cg#Jl?e9F`3JQ7I4J 9OAO!BU=b!Cg(Lr2]h"W`KTEXQdK;`pz_u*F_ 5X 3R 4P 4U:M 4Q=V9Q8P 3I6B5CJ?[&@.B'@4?7E?H?NEGUVOUTRPNX\UWPVUT\^YYY\UW\Y]d`bekilgkfmeeksmhlwlnmosn|tqwnpzvpwvr{xurzrzv||xyz}{ぁ}z}x||w{tႅz{xsqrtqjekjdi\rNXOUcg_]`[_Ri`TJ173{34$51=A>MMKHQLZ[QTSYPUX[^_]^ji烀똒ﴥ豚ܐׁzuyxxtxqsswsoupknotgegvajZ^[^Zc^`[_Rc=LsCe>RP =VCTCVDSF^Ii"D`Mc@q#B{'?}!E4F/Ao<}!<2Dr@g7a8j7d6R 9` :[ @W 6>Z~ЅؗѕȎvusoxyfkG__:N9ZEM>SDb;:SRXsuzvxe|k{gw`zryḿ{ԈwҌvҏ|ҍ͍x̊y͇w˃z͇zɉ̊vȆw͉~σs~wy}|ǀqɂDžy˂s~΀yʃuʁy˄x΃~ǀ}Ƃ{~sʁuwtwt{|~w{vxŇ|srz}l}v{s|twm~{{o||tnwvy{sqtsppnrktforu΄rؓߞ|y벂}xyﺁc~トƗǖǔƗǘȔƙĔȤƜƝǜǟǟɠˠɡȜɤɠ̡˪̪ˤ̧ʨ̩̪ʧ̦ȨʤȯǢ,D,D6J0J1J-E-J4M4J'E1F'@'?-E+B&?#?!?#@w;&=|"Ht?s>i5t;<1J@MNR\\a_jhvixn{nnys~}鐅yꝀꚁ|뛆{웂|swxwrrkzdk[qj``[hPfIe?a2T"D.L*F-I2N3H=M7K=P?QJWFWEUFWG\MpRvOqJu?p2U/a4k)^o$U;nK>wz7jMfeG{yf!Rg'\{Ff#aOQ[!^n=thWFF|=WƑO`UVGn@^ig"LO>TBYJZF`Ex.L1Uq)Gg&C6Pv =R 3L 2K 7P;K7J8I7T:\=e"Ku4si'j^Q`GOiɤdm>K 4Q 9G :L:T:S?V>U8[:P4L >I>F@G 6A\æӥԝڦݰⸯڦީధ߲߯٬ΣÖf_d0V7W9R5P/P 6U 3V 1U 7S 3^2eGd<\:]QQgGYCX+D$8*<HLJOMSTYYQURZW]jk倄ꏅ줣ﺫ츲㙆ۆۄysvyxxut{{wzruqomwinjsal]j\`]`\[S^KQ+Ad?W;T @TA^GX@V?P}&@4IwEf8e9h9b;a8_;V cGS @nDGX`lid̂p̈́r}v{p}hunytψ{ԎӎҊ{цwщy΃~Љ{͈ψxʅyЄz̊Ȃ˂syʇtɊʂpʁuȀ}~tˀuu~wȂsȀ{ztŃ{Džwʁ|y|yy|ŀ{~{{nzrǂxÀyvoqmŁt}o}}y{nx{}}}tsrpnnrsqzkoqoxu҅sّ{诇찃{{}{~~}ᅧ‹ŜƐĖȜǛȕƚƙŞěƜȗƟʛʟ˥̦͜ʢʨ̦˟̧̧̥̪ʤΦΪ̪ˣʣɤɬȦ2L2L2F/H6P0B4N%B*C1J.G4M1F6K)A(A%? <$A{"=%?9x5t6u6|>"95HEKT[^\eamjyl|p|vqrx{|w|t}}뚀와sz}yvsmrnyas\hd\a]iO]CW:T&C)C%G,D.@6I=FNELCPGVARM\LlQ{RwN~.WvK6\;i3epQBrD{~;s9mUy}Z@w|2br3ld$US BECPS]#[p\y8pm"]aEj7nXm%iTN_8ih2hgX}DK~?^x˞co#fXTg7Zrj!RG n0^Ev0ys&VJcУƘ_kp!IUBWQ5J 8C =A5H@X;qǘҖך٥᧎߽ݩݲ޵㵩ݴسǢLCg2Q2N2S5T4R5R 5S 1Q 7W8V5b>c;h>`9^=\S?IADDHFPNLLOTYXXPTYWWVVXXV\c[^Y_Z[]b`caeaieihrfgqssvstimroqkyywstrurq}xtv{surtx{}u|}}~}w}~uws~߈vqxnxvuqtpomgk`fT_LTRS_a]Z^Z__FR5L#I{@%A.F>Q9J7N1B,D497@LTOLOPSaVYebut~研뫟긭察ᕇ߇ޏۈuvprw{rstyoreglrkpjsehfr]g^][[V^>Uw=a>XBVFXEYBY@VCVET>hGd?\?e@t<~&A)A,Fy#=o(A~/G4FuO 7S7t#Ic={$CFWbbvm|t~gysyht`uh~qц|Չ{Ӈ|ϊuω}щ}ˉ̅vȅˇzʁrˈȃsɄ}Džuxʆuʃ{ǂyƂwȀ~~q̂}˂t}{ƅ}Ƀwā~Ɂ~ˁxȃvÀxȁ}úu~vāu|s}z}r|tvv€q|s}v}rp~yr{vyvuruxtvpnpiowsxpn|rԇyޔ}}||~x＀jĊƕǓŗƟǕșɞǜŞȢȟǣȤȪɞɠͤͨ˦̥ɧ̣ʨ̧̫Ϊ̨ͫά̬ɝʤǤƨǟ-H-H6S)D.J(A0G,D)D3F'C/D0D.H)=)J'A=$>? 9+E)By<|;~!=.D7IFPWb[\ljsnyk|rysuty땆畃~}z}xz||y{씇qtozdrajaa`YfKQ!<,C0L/A1C8G:FAP=LAI=PCTEPMaMiPxQzLq4X},ZGp>n+_m WDvFuE|zI8K >J >SBU8p,\9w}4``bl7QnB\AX;[>\HaCcEaBP:J6A 8E >F:J 5}8bƄ͋ҏٌạ᪜Პ㴦߿޾Ӵx6O 3R 2O 2Y 6U /V6S6S 8X 5Z8]7`<^8d8_:^;\ ;X5_ 1FbQdZ]Ha,@)<-<:GCL?@EQFLJKGKRSNORXPWPRT[WUXX\b\a\a__[de`cfegcfnplnmlpxnnqpnrmqxvvtxwutvtpqszyyvq{{}}{yz||v}|x䁁}}|~|vsvntoustpkiguT[OZS\WWZV\_QTMTHU=U:R@YHXUaPWKYEO;SAR.F9BKJRRRXSV``cf|x䒊뫤鮡曏▏ސ߉ᅀ}rtpptxrvksonkpfohhaf`hbcca^[KU7KdA]A\IVAV@ZFYEQAQBW?k!IdA[AhAs!F'I(?6MtAo:x,A9Dz>k7b7a4k;">!<'E1F:ILTX_a_mmvk}jyjsp}vtꗈs虂vw|씁{w~~|}rt|ilYjca[XZGJ5I4K)E)C*G2N4I1I@Q:K7I?JDHEMBPLYFSLfKiS~U~Ls(V~-ZIoBt+_p%TG{Cv;ix8t|4_3ZT>wr0Vt8op,nO EG IZ\sB||]Yo#g\Ni0k}[\w9z\\WPp4dfdOvT|?xeefKd"ak-XDwD 5C6NDN ;I 5[=d?f=eJ?]LXbrHQ`:YBLBK?KCF NEV>~AuQpq8]fEZa?k&Lj%Hi@a):BK@J@GEJP[RNINNONQV^TSOUV[Y[[Z]d[[\ga_^cclbh^edkkintmjsvgpokkpmkssxwvuwrtxxm~wv{z|~~ys{t|}zw}y{x|zzvx㇄vxqy|rmwuurotos]bT_JWPSTWW]X__cZ\Z^T^Xb\gYY[YWZRTGVHVAW:IEKT^RZSYUf`i|团諥桙㞍喀ފ߁z{yvsuwotkpmrlpmvq}blZh^fda_nQ`AOy#Cf@[BZCXBY"G_!HTANCUAS>l+Ka@^An!Co>(?+D8NrBo>y'D0C}*Cg6e5e7m=x$BZ 9X ?M@d@K`~Ւטˋ{gqŇ|yWfv0O[CL;W83R;LYcnj|t|n|dkԀf{p}s{|ω}Ҍzҋ{͋}щ}χ{Ϗ͈yυqφwʆ{̆vȄ}ˁy}ŕy}x΂wɁoʃy~yƄ|Ȁ}ƃ{ȁw˄}Ȁv}z{~zxxƁz}Āx}}|wtstyryuwnǀnvuupsq|syt|yy{ulpmpymnkonlyv҄sڏwy~{{~}~ĘȜȒȜȞțʡȞșˢȤʡɠǝˠȟǠ̧̦ͤЮ̧̦ͥͨϫ̦˥̦̤ʥɟȥǟȨǧʤ.F.F:K0L/F.B,A/F,E)A-A/E)A$?$@*B*A&D$<%C*G#?%>*A#@"=1G?NKQ]ccmnfwx{ours}}v閅閄x엃~윃}~z{uwupdksYcW`UTSGF;F3J(?#A"?/H3E5K=FAO?QFP=LCPFSH]L_ImU|[[{Qw3W;hDi7_s'Yn SJz?uz9nx3sp&Vx8dLuy7ggTf#U^MRSLEf,js`Ovx<|w1sb!Wq@|N{~Ot7rfjYP`'^hs[MrF6C:I@QCSCNDR?ZH`Zw_QlPnBf8cJm7_tKpLl"U;hBz}@nz=tl#Ov6`=km-Y]JY KJ AQFp0o[x^Vu5hg-`|Fl/gxB~xAnw9um2jl%r]Wf/cgtSt.sk+nQf\r¥|?w|>nj]JG?A3F;T>fKlEY ;a3FEJ@F FH @WI_kVz3aU=UDI =E 4q3ZAfz'N|1UKdOsF`KcUiD[TgcOVSZ`pf_iehk^gqsLJɫǬòQCZ:S4N 6N 5Q 9U ;a 8`'EgAkd9Yf:[f2Xg1T]5[9_9b9Z /`B`$R]L]3=TWhdiKa=Q3B-=9J:ECODJIJOWOVNMNUX\W^X[W_PTXWWVckZi`aVY_^`d`i`bfnachlpspnnpomoox{posrltromruvssppwu~zz}pruuyu}~{{z|熉yt~v{{{wxtqwx{}sirtkicjedcm[cT^QUSRWWZ_XV`a_Xbf`\[[TUJQNTM[ReXreqՁّߡ嫥谢嬙䢓喌㑅߉݆؁݀vsuyy~lwllhpgudn`dfhej]^X\KY}C`DZ2PzҒՠϋx~bj||JW?_h!LQEBS9I@N@VGPVlZwXkT_XpH^>h7^a;bPcPi$R;nG~=w~f!`c'^ZnI|>s=z}Nt[NxđVMmxvv5gL ;G6D 5O=f%JiB\ Da>[spm룂ԇd\i]cg7G1=6<5?;D=M:pDthEfs0DF{v4rR>G >M:t2WHZFdIjN]ZoTjWlZzqFFQT[YKRLRR\XmopѲϰ¼w[8S=J9T=P:Rc9c 2^ .g6W1\8\?_Cc>Ldg]cGXFY,=-D4CCJLTKSIRIJOQRYP[SRUXRXX[Y^\UXS[`a`W[[\_k^fahhigq`dhipnppjnmpjmsrsmrwnutuqvvo||qwvs~w|y~vs~{僁|~x偀{䂂}t|{vxzztsmvpsuvoltjnfgkzdrY_V]X[VZUXX[WZ__cbbh[fKVPdYgmـٙڥ߱㱰鱤诤笡槛枑珇䍆~w~wyqttys}kvgphlamdl]bccVXW]6MeGX;\EWCU=XGZCT?SIUDVBXCj"C]AiGrGn!H+HAKGdy/Is"A.C'C| =jc2[<`@S7_C*PpyБף̐tacv|yyHYKegEVAU79Lcggjxh{h}rumv_thwmˁsӈtՍzҍyы|·uЋ҉tфt҇΅uρq͆}Ѕsˁ}ˉxʃy˃qȈzʁwˁvsŁ{x̃xǁvń}āwƒɀz}w{sxĀŀsȅw{uyzxy}ā||urxw{wwryyyxws|vzp{{rvqlonnqnnqtnö́{׏~{|볆ﷃ~x%‘ÑƖœŘɘʟʙɝǚǞǝɡɟʠȟɛȟɘɞɢ̜ϥʤΥϩ̢̢̢̦ͨɝʠɣǠɦɢŞʧʭͰ(F(F3E1K5G0E0F)A)B&<4F/A4C)C)C-G#C"A=%D*E-G,G+?6P1K8MGR\a\fkwpgxsۀyvws{{sz꓃ssz攄~|{z{{{ruulzdp]o^cWTRLL>H0E.H*C$@-F3J4J9I=J8G>K>I>QAPEPTjXeMeNYScLjAsy%VVAUIQ @`Gx4hH~?oAsr.^v3dg!Ue"YXQK FZO|AmfGpo1Z[KWMg&_l1_ME|k(dn-dq9uTk)ch1l\^I|:u@sdvQ9owǙcHus}I}VCI 5@8BBD .Z$PkKgn8f@?Rt,U_A`Gp-PBSCWPlSiKc\tdz}ˡYJHM[[INDXObXcluʐϵֶ׺7:N ;LZ 7`5Pf_f`sAPET'@1D4?@KCKMMOTLOMTNSLMUSRTWTWaVV[W\W]cS\W[]Y_jdh_abjcgbdfeiviepwlflmoolfowqmqostwtxyppso{xsyxz}{{{yvzzuyz{䆂~yo}|{yဃ~{zvxvypytymmrvjriqam]ditY`Yb_^aekeoev~ouagaur}ބ䓎驥뷭軮紮鳦跥筣䩝嗓哇㌃ኅ݁vvyyxwuvs|ssnukrckggdo_g\UW_MXw!B\GVC[GY>Z>\JYDTCWDQCWF]Fi&LaIlCp%Gk!B6G=K3F8Jy4L8H%;)>q\7_?a :QLL]X[`amrspwpހruz⍁n|vqswo}urxv}y}}tyj}`wfi^bUTTGM8G5@2M)>$D1D2E3H4I9K;ICT=LQAWAV=V@Y:c;e@_A[8q/Kf+TdEg:hF^?g:^GX :T:[Bd:PVajcy9NIR*F3A7F;GHQFPMQKOV^QTUYXdTRTYTWUYRZ\VZb`iV\TZ\]Z_X[eicf]_c`lkefmmtwmsnnlqpsltnqsvququruuo}zyzw}v||xs}x||y䄂||s~|~w~{~{၁~|yzxwrtxpmqjnqkkudpae`m^ncmholsuvzq቎xzs}uw~甒걩黭趬鵤赥沪䤓矗唒䐌߈|{yyzxxzx}nrnyqvjmflfjbiam__Wa7JcWUF]Ck!Hf"Ln#HqHu,GETCT(B{$Cu-F7N#@}"Gw7g9p"@3I_9]:d=Y DY At#I^k՚њ|[_nx;PLd})GbAuAISebumxgҁ|zkuh׀r|t{j΄tЉyю{Љxцzˆwхw͆vʇ|Іuˊ˄|˅t΂wˁx̄|ʂxʀx΅tȁ{ǀxǂyɄ|~śwɂx~ÃzzȄzĆy~xƃvÂzā~ǁ{yoyƁoɆs}{vzp~x|{~txxxuwtwuxmvqrsrqunmqsivsvvЇlܗীyzw}|ËƙŕȝǛʝʟɗȜƟǖʦɟǚȡȞƙɟț̠ˡΥʛ͡˩ͥʧʞΤΣͤʨ˧ʢͣʣ˩ʭ̱ʯϮ*B*B/A1L+C(C+E$:5K4J/@0C2G0D/A(>%C.E(J%H$E(@*E2H9L?YBZO][dbkhpzu~y}t߁w߄z}yz~sqy엀tꚂyt}z휂u}zosk|cwag]eVTOMP9GJ:HAR@MATBUBaNeUlrte;kZ@T FR D[Ms6_By=pn$Un'\q*fi%ei!lXEn6vtY~t8_[IRLNIYPc%Xy5tt3ly;xi#hd&]l:|cz>w^nRTV]hTw:{o.mw>nYr|w|BrXIULO=^Ap$Rh BcH~5ZWal~[iPLHF}+OdHC>JGNB`0]vCje'KRHR!R|3U{/XKkSqJbYhXpPwRs[~uңԣӰɑso=h4s#>}5E\ 5_:`?X :P=n?Xi}ԕ՛S[yzs8JF^+MtC-KHRie}wzhwjwazevith{nЈrюxԉwЇw҅t˃xΆy΁s̃Ήvˈÿrʃzɀ{Έw˂|̅y͇{̓v}x~rɁxɄuȂzywxuĀx|t~xtɆwƒ~vÀx|w|y{vzq|y|{ƀwǂs}z|t}sÁ|tx}}zn{zuvtoomusllonro{nӆwۚ~妁yﲄ}|{﹀|ﺃĎŎƘɕ˝̢șɛəʞɡȟƙǚŝȚ˦ʕʡ˛ˣ̣ͩ̚͟͞˧˥̤̣͡ʥʠ̥̫ͣά̮̭ʳΰ3M3M4N:P2M2L3I7L6K0K0J3K1I,L,D(B(@(>*C#@!@!8&D-F3L@UEYIW[aaemn{u{mރ}ux|w}xp{qw|{u위vw{yvoiyqgfhb^`LT?P5J.I*B.H/I2H3G3GRE`F?\jg~\|Vo_~hpy̌֟׵ΨKH:LVaPYF[Yhlr|Ɣ׼δеy7=VEY?UEYFVE[CZC[F^=`8d@^E`7l(Jh;jAi?fAc@d=_AX@ZBcGcBD[\o[oBSLb1F1G@P=EDMKYHWOWQ\WTWZYdY_SUZ[ZYX[TU\[W[_`Z`^bfjgmcificehgntihnpkjljorkkrusthklrprpvyuyt{um}zv}}}刉z~y|}~}{x~{zv{{vzrlqrxvprprlonhjlkdstru{w劅蟋窙该䜗y{懈隒鬘뼮꼳貥絣篤嶪䧚垎䕏|݃݁wwsxsyqrrxprgm`mbj^bco\fXdBQk JYGXIZJYLZBTEXHWDR@V>UF[GZGl+Ly/PpCfEw!EILBU-Dn ?{-A@U'?t:z#Cj:w%C{%Da;fE_ 8X >O>e@Q]ҍ֦ÄUZwzq6IB\8Qt!K@[OYjcwtym|oybwmznyfʀrьqЎԉrԇuΌzΌ̅r̋̇zЄwɈˋ~͉~~ŵr͂}̉úw̅|Ί~t|qǁu{wǁɀtɄ|ÂwŁ~~zȆȂzx}tǁ~oz}wɁv~p|zxǀt~yxzxvrzrwwwwzpyxy|psokszlismnl̄sՑ~u|믁y|~z}{}ŒǗǔʜʞ˜Ǟʜ˟ʠʟǘěƓȞǚʠʙ̩˝ɜɟ̢̠̣ͧͤΧΧ˪̤ͭͦɥͪΧ˫ͮѭαʹ7A7A.J/D,D(D&A-C1F4G4D)?.K!@'A*<#@*@#9~:{>@&;/A:JE_DOLY[c_lkpxyth݁~my|svxtwtwwy{|{wn앀sp}`w_jYi]\XIMAI3D/G(A0K+D6N5N>UDS>SAS@N>SL`G\LbSwfnԄxSm8gh&^[RYVfVo3pMCx3ei-iv:wv4{GZmDl`&Z`$SVSPRUURW`,_n3fk4hx?oo7me.gf.jl8fxG}V^UyEx]ZndTo/si6dŌTGwsnn?vq2f`(Xb*Wn$Pz3_y1]o/XSmP_QbRhx'O[ Js(Se&Po3bu8]e"GOABFHJVO\ Q;Xlrwoe~n~ljϙ͟ΦЯյj2KFYGR:TD_Z`~ƊԾʱeO\#GWOX"L^OZMb+Ya+U_)UZ"K_G_CeCb"I`?k#Gs$Ej?gDg=c4g6g@W ;XC]=`tlljN{6lk$Zt,c~0[@j/_u,Q9_@a7SJf*Tw.`t&PlEp(Iw,OX>L 6@ ;TK`Jt1U`~mzquˆʕ՘՗ڭթ̟?C0GNX6F/P7XHV̀lХæqTb#AQ=O ;[;Z?T>YAaHgD`!Cf#HfLe*Of%Mg,Ol+Nt6Pr%Ni,Mo(Qg#Mf LgK]C\#K`"Qe!ND[Zq\pLcWjBX;O?QHUGYJSMWS\W][fZ^Y_W^Xa\b`_`g_a^^bcZ[`dakdkdkjocmlompfjgefhghgogikhiqhmnqlptwniy{ysxvzx{|yyyy}zxwyvt䂃xy|}||wyzyvxw||zyvvx{vtrktwsqpslmlivtxrむ慆蛏ꮤ콯뻫沥✘⋋界柏ꭟ꼪깮趯粥븥縯糧圏ᑍ߇ށ|oznrswqwwwm|dqglkmjsd`\c=LjAX?WC\BXETGSCXGYGVAVDTDWB\Ea"E;U}+MmIi;8LCO9M}">p >)A/D)Cw;p7t!8z#FmZGcD4Int΍ןɅowtq}CQCaJ\0LX^_auiyjфtx_rgsb|u}voԈyҊ~ґ҅|̆rɇy͌χw˅|̈yˌ΅rǁrǁ}ʆvȅ~wɀ|ȇy΂uʁ{ɀqÂuƃz˂{ɂy~wȁ{ȅ}{sÃ~zzx}|qx|z{tą~z{~x}{|}t~xtxqwlvkutywwpxxotlhmnruvlЂnבvyzzu{~ˆÏƔɓụ̏˟ʜ˚ʜɚǘȖɚƖŚǗƛǘȞȝ˝̢ˤʞ˜̞˥ˡˤΪͦͥ˩ϤӪ̥̲ͯѱͫβͭͰ-E-E/C,A$=$C)@,A*E*C&?'A.I+D+?)C%= B|"7z6};;"<&?6O7JDYUaaijoksy||q߀u}xy|y{zsxy}uw}휂ut~{|rzjlu^oc`Y\WHM@L9J.G.G/F+D1K8G6J7G8N9G?Z;M;SH^byrЀrQkNsGw:gn&W[HkWi!Ws3g}?um#]o$eI^ql`LseGZ IcS\DQGWMTQTM^Qk4lo-\k(\n3ho5gm-fd"Ys;q|Iw9yp.kg,]xApczHp]bx<u6{m8]wl}C{]te]:nl*^l(_~=oDx>u:lEoIpEeCe~3Wl%F]>Z=f(Jq'NX>E?CGZPu/aksuǍǖɏћϗԞִΣz_7G=QPV9M9VEXHYsnڼĴYc!8V7\CR :[9ZDW 6]G_?`GJPINMTMTFSPLYfSXQQ^_RUVXWUVUW_PQU\]Y]e_e[W_\ihefdepkfbjnmjlqgkdcgiimjlgljnojklputlttxqwvwzws|}|vszuryv~yz|~~{w~{zzz{wsrq~}zrwqsqrptsttvrqlojurwxwp~|㐇顒겦壦呋搇砐밧뼵黯귮鵨꺨軧糟㙍⏅~~z}v{stpzxysukverdlkmhj]_Wd}$A_MX>[K\FXDXGTAX;UDWAT@WAVH]?fH|3Kv*HnJh>6N?M7M+Eu<.E3J{%E?t;y"=~'Ar8c:g9U 8W #@(@.F(C&<#?-B-C%=)@-F9";|=z7|?">)C0J3J?XK`V\`ldmossvytځxz}vy葁|z|juxxyu~|~t~kpm~dt[l]a\VQNLzy;j0_S|zVJqgcG}h#]k#X~@gSrVEr:g2Xz1U6Yz0Q[9Q d9f7eDk!@i$@{4Ju&;m#Ev*@a"L_>c;^7_DZD^:}1KcuRaVgCVI]*?WGXFWKYHX@WG[FXBUDUAVDWFl&Fw,Fr(PgBn@&A)@.G,E'?";*C*;*C#=:8=$?="@@!@,C6N=OFYT`]beupxpp{ty{vzqt|ozwxv휃ysxzv|plevckWkdXNKLAG;M&;!<-C+=,D0D5H,D8I6Pss7[m\]Wb(`n2m}FQxz\edmiw,b_B|/Sw}GSs(Ke#N[:`9b6n!D\?P9U7l>|*L>b=SJ``tfwt}w|ÃłȖўԣٺټֵɕgM?P 8T=W=Z:[7q"?s&C_;^?d:d8g8b 4b2g=q#Fd74M|(Ep$>p H^=\5gU@S@^EcCo(I{-Lt'MjI.K3E|(?p;k9e6f9[6\8P :YEo$FYoyvՎΑhr\cuO[0LScdpY\m_uiy_yb{jvcvc{lЃj҆vьz·wӂq΄x̃u˄wʏ|ˇ̇˂zƃ~ƅr̅}ɂsˁx{xȁxƂ|ˁpɀ}vyƃǀqȀyȂvǂy~ǃ|~ys}rxvzu~qÆ||vxyxr}vzvyw{r~{}~Äzt~rwnxrxmyitnqotsgjppnjzs֌lۙyzwz}~y{ŒÌʕɖ˚Τ̝ʕȚɟɝ̜ǖǗɞʟ˜ɟɚʜɠʜ̘ʤǚɣɞͦɥˣ̪ϳΩϧϨͪͤʮ̢ϰ˨̫δͲͮί*B*B'@*?(>(B)>!=%?'@!;:"<$=%?#=!@<&J}<$@"?$A1G0C;OEYQY]gemqqtxxu}t߀zusqvzxvrttw~w~vyxzyyik~gx`i[aUVRKK;B2F,D&;&@,D,>6F@T-J0M0PDc[tqwSpOlE^XdfsX}HwqLs&ar%^sTt(]C~VPgq\h#QK?[N]NaP_#VxOd^$Vu:qn+cd#Z_"Pd&Xn0hg)b^$T]!D}F|{9pk'[e'Qi,ds4mn,cp,no$_vjX>h6l;l;_9e:r"@iy%He6`:b=f9\7X >[ ;z#BIfLVMcFTbw9Q,B:JFQTdHRGNSXPXPTTZVXY[Y_[b[ZX[dd]aV_\`\b\Tfjaf`bbjdflnhgllfmelcdcggnrqdffcknnlijffjkkfuwqlpotxtsrptytpwrpqrpxtxyqotpz{toxutpnyuvuv|ڀ~|zw}v刁呎阐춤ɺɽóõ繫盒㎊镑ꤑ¯뷥鳥粟笚嚑ፄ}wwoxpwsut{kqi|fvloikel]m.G`AUD_ HVAXEV@U@` G\?W>a C\FV=TA_Ce%Jx+Is(OhEgB9I4P?Q-?*Bz'E)>5M=l7z,E{&Ii7w%Bf7dBX 4_9Q AQ =z*MVstuюОnZ^tK[2O]gkrf`l]visat]ya{gxk}j͆ЌsωwˆŝvІwχ{˃uˋ|͇|ʀzʉȉzɄ~ˁz΁qȉw~t~t}x̀o˂}ʃ}ytĀȃ}ȃ|~yŃy~wx|z~v|y{x~w}uÂ}|vy|Åuƒ~uzq~zup|pzmynpmwlpsopnjpksmkvih̀vԒ}ܝtr{ﺋ~xyĐƏƐƏ̙̕͝˚ȓȔɜȚȚɞɜɟ̞ɥʤɜȗɠʠȣǙɜɠɦ̤ͩΫѲѰϭϮͧΫͤ˧ͪή̮ʭάΰϰ,A,A$D,E(C)>(F,F:+C!<%@'9(?*E&>,E!Az%Bz =|<-B.H3I.C7QBRQ`Ve]hkpqkyx݀x݀xxvsxvvy~rru뙇y혃yzoy|{ywrpkzcwraXXQJL=I3M'@'@!>/I/F-G-G,G8V:UZqoxRrSoLeHZ[ok{X~@tgOk#Xo%]s [9vVVYjpRcGOEZJdXd"S]S]%Os>rz8vn0be-^f.]b*Wv7oi']cRWGy?aH}r3ct0^[#Ug5`p8qn(ji%Yv6pS{c{8}VRk/ri)cp=chleeV`Zpa:bqӗ|f7Q +YBi"KT ?N6Z8x'C=bAiFfK_D\PcEYMf`vsÂȌɅ̗Ӫոӱ`U8HKWHV?O9Q9RVb̾bq%=N:VFNAU 4Wk=e;g@m;hFhD\8c=s|)=3F~4L}$Bi>dDb?c5d?Z=] 7x%FShGYJ^ASapG]%>9J>FDTFLQVOVMPX`SZV`RZ\\\bXZXVU]XcWX_c^g`dfgggafbkdgemnmnr`cgbemllgalm`bbcfajfelkjhthflqonrpuuvwpwloolpspnnpvqyvy{qetzuuunpzrrtoyzz|vyy~~|w㍁䐎嗔봨óƽ³沦喐吒蜑ꦥþ鷮笖诜坕㋅܀pukrmpkpqzovjxjvovamdiRfq GVIX@Z>UAXHY@VF\C[CRDW?T=[I^ LaJcBo"Jr%Mj%Kq/R/C4H3I3Q2H%E1B-Ix7d7{)At:nd>Y8Y@X %>$>$B|(<&C ?~<{ 9w!<";$:0G/I3G6J?RQdWc_kdqptz{vބw߅{zyvwyyutyyzv}횀}|~wopmiu^uocSYNRJAG3F(@">!;.A3G4K2K6M:VOflƄdzFeF^CSKYires[8icMl\u'd6pJNFqVif|AmhTVEaQf W_MWMc'YzAsu6fc&Vh-al5lj0`h/dk.]b%V`$Zf*WJzw3_u5hf1\f)Zl5ih,bi(`h2d|JxV|Lg*d[!X[TYVr9j`tw`W[gvhӉ~d\q 6O/T7f)QYBL9T28O\sXqPgReC\C_BYWgkvu~ɍ΢ӵԸc5DHTDK6J7N=TGXqo̵ͱw'2P;Q=K8OPVfGb1H9C?E?JBKMRGOON_cV]QS\c\bRS]_UW[][^WT]d_^c`debhaiagbdgmkgrrefkjelnngjbkchffffkmehdlhoimfhoxljknqspurqporrnnkloovrsmnlnmsqqzvxospm{wstpxz~}zt~}~}䀅呕癖趬ij殩✞晡饛껻ɿƵ쿯걡ꮫ柛ኆ}xmzhlrtoxirlwjykrooakap/K^CR?UAZ@ZBWBWE_$LdG]HUG[BWBT@^Ci-Pe@o%Fk"Hl Dx(E,G3K/B0N*B}%?~.F'?t7k@x'Dp6s>v7^:e7Z6X :[ :T ?eDWlfnˊ؞tZY~\v&CWbihd[sdqbtcr_vf|mqˋvӆp̈ϐz͇tч|Њwуu̐ʂuˉ}ь}ʁwˀwˆzχs̃}x́nȀyvƂ{ǂ}qsŀ~ɀ|ŃxDŽ{v}zy{uǀu|v{zzx~{}z~wzu|}|v|uwoo|rwwxstqvoqkmnquoqoolhnj̅vؑwwzx~~ÉŐőǔ˜̙˞˘˗ɗȗɜ˚ʗșȗ̝ʡ͠ʟʙʞǘɖɗɠəɢ˨ЧͦΩϯѯϮͬЮέϫ̭ͨͬͨͪβάίͱ#@#@'?!B%>">8+K#A(>%?%B!<+A&E ?|<@|$?{;,@(B">+E0FBZARJf\p`hlktymہyyzyuvꑁyxr욂藀{v웉z{{uostfx^ob`S\XIJ@H3B =#B%=,C(E0P/M4PHgdy}lLeNaEVAQK\cr`sX7ggOw1b9r?w},bs,Zw7ddT|Mwn+[WC_LbSh WUI_Qj,bn+de&[d!Wh.`o8yj-ed"\i,\q8jm7nh0Z~;n?os4ee.]a!Ve&[h.dn-fg0^t?n~Kr}IuLb [UOTVa%crY =bEw/SOgcunwthWrRmNbYsjuȗ̕їתڽֹ˝:B;LZ`6J7PE\H_^[ʗӸcAO:I9O;K 9Q 9Qa9_w.F}.G~,G+Cx$Ge6aeAbDl#Hq&Eu,N0J/G6L,E<[$>~"=2K/Iw$;v'Fw%Cw >|-Ds7`9d:[?W 5V =P A_9UkcoNJԞy\Zwe|-G]iehpclatcr_{exhρsysɀlωxчr̊yЉt̃sΆwЃrЉyΆu͊|͂sЂs̄uʃv̇|~sĀ{~u}q}y}rwt~~z~{rǂzń|{v~{~yu~xʇ|€v~y~t}z}~}wzz|yv}|y{x{rwovtyrssvoxorkntomlmgetqσnڑrzwx{ÏǛȐ˛ʘ˚˚ʗ̚˞ȗʟʓ˚ʓ̝˞̞˝ɜ͜ɞɚʚǗțɝˠͧЦШϮЬϫάϦЯϩϲΦϫγͭϴвϭͯγ.A.A!Bu?{=| =;'@<$<{!D(C$B*C,N~#A"D"B ;} =&D$D ;(D0H7P?PH\\gcrioqsysۂ}݁zv|xsuzzyyxs~鹿z}~z~rl|dxdrac\[XSSHU.G)C%F#@'D-I/R1Npl,WQC_Nd$PaJXMi3cu:mh)WcVa)V`'Zq=uf-ge _d)[s;iJq7kq1aExr2hv5jg)_a#Zj0fl1ho6lo>vr;lx>m_~Gb%fSPXYb!^|AtpqZjvB_S3@:< 6DAM 8cF;^Srh{i{wʑwqe}sȒ֬ӬѬ׼ٽҨMHQEQBQDL ?T?t$D;EHX'Ce@j EaC_A\9Y7p$Gj5h<^6g;l*@.Jz(B/J~(Fr8+A}9i9a6S 2S9Z =T DU9FcdrȈӠͅabmtgw.FijibtmkWx^q`s\{d}ftḡk͈шyωpϊtσvχẘΆzΈv̓vʂ{Ђ|ɀr̅{~r˄rˁʆvŀx{p|Ȁy}oƁzŃ}ȈzvŃ}zrāw}{}qǀu~uozs}zv|wzsywŁ|{t|s}vuo{v|pxmxruovpqurmnkrnhjilqn͂n٘tzyﷂŒÉđŐɜə˚ԠͤȔ̔˘ʛǚȖəɜ˝˝̝̣͢ʘˣʠˣɚɡɡ̫ͤΧ̪ͮӮίѬϯάϫΩͭЬʣͭЮͫΫͫϰ)D)D"Dy;x"=}#A9|"<"?'E/F-B,D!@!A!>B#B}>~!@ ;#A(H(;4M8O@VJ[Ueasjtuy~~݀z݂vyyz~xw~w}띄q~{~}|wqxo|fwejXaSYSHHCK1F"@%?(C"E(I)K4QVnuPe=Z=OBS?QGRLY\mYwLy+VkOu+eq*WbSR D\DVfQ>yg!IWK_Ti*\_Jd(Vn6jj0]a-V`$]_ Y\'XwGk4hb'`s?osRVZ8H?POdY]tyȬȱr0U?w&DFMO`+Ea=`=e?`;Y 8[6m>ieCf>v$@y)Hy)CT?^C\GaD^#KVBX>XC\?X=c!B_@d@u,Iw+Mv!Cz-L-L9K3HBX+G|$@+>?P~9Q#<}#Bt:.>)?d8e4S 0W 9X v#B~:y;}%B%B<%?%C-E|&E#@}&F!?@#A!@%C#>/G5I7NCTK\_oaklkqtyy݁|rߌ}t|yvzzꖂ|wy흂}|{ryrih|ftgbTXSGH?M0@)I*H'M(L,Q1THZh}|XtBX>R=L9NAW?VO\d}hLy5^j+Sj#UfSW NLIc#V^ekWq,W^%I[#Ti-\]Ma$Wc&[h0\g)\d!VaUV#Ml8kg-jc(_e$ci(\}N`|;y|9mH~G~z>t{>q5it8pr9lu7om+hi&^m0`[_uu[sqs}HLD= ;@?H;9PWn?[E\OchЍ۞޼ݺѲݳƲ೪ӧkT;FBMR]OX_ieɜhQT;M?O:TEO :QgCt!>v!@},C}-Ey.E%?i9\=eCc7`8b 7s>:KMg3C>KQ^FR;N#;1E:C{#Eu8*A,Do;c7W 3T 6U 5W;YEw%JizІѓʌ[g]an{FRcUogrmrZ`wdwdsf{lyn~vϋϋn̊ф}Єsϊ}̅wˆrɆvʄyψt̀{ɂsˈy|tȄzɀză||tŀxɀw|x|r~zāxƅzɇ{}x}|y}}Ãwņ~Ńt~z}}z}}||~w|v{kxs{lwnxqxnuovtqlsqssooilgejpvoщtՑy밇zuÆÎŏƖȜˠ͟͝ˠʟɗ̠ʖȜǖɚ̛ʛ˞̡̢̠͠˜̡Ƞʟʤ̨̞͡ϰͧΥϭЫάЬҰѱάЬа̬ίЪϫѭέͩϯ(B(By>w @y>w;w4~%@~"?{;'> < ?(F#?#?'C$>|:{9<<.A0E*B3K8LPa`hallovv|wہvu}y珄z門|{~{혈u|z}{|}t~payekaYPTQJIpU|nĒҡ޻ƿŽĬʳپְzY3@>KNRHM9O;SDXcYʄ¹]_8I0Q 9Q :Pk6o9o9x(?/G7E{+E,H0Jo;aC`=ad7uBH[Xk0I=LKTAP5H(@/>3A4DGPKRHLKLUQS[U[XT\^\Z_X_Z[[YZZS_[\W_Xaf_\b``ecfegbainhllslqgif_hhgjdcgjlplcgj_Yb]YTYTYSXV]W_]YT_aac`^gbomoredg`kinbibfdkbhgdY^YaeagboXVanWVY\WcQXX`ggfucrcfmsux{nuiqem_l`jbibimploabQRBNCXT]cphupxpwnplwWdu>YDYEZGU@TC[DT?\?]B_AXBdG\A^D_J\>lB`Af!@|+H|1Lt*Hl&By+L;L,?T!?}"@xCo8u>+Dh=c5U 1Q 9^?ZBZGt%Ae{ʃӑŽZeTWm~HWe`tkziva{ayrxaxb|pzmΆwЋ~ϋ{Έẏϊsъw͊z͈ṫ~r̄~ˀpȃyȃ~s|uÄ|oz{ʀnr~yynā~ȂwƄt|āxŀuƀvÁ{āwyv~}|z}w{y}}zx|{qvr{rzuzsuqxyxxynrnrsplklmmihgotlЇvޗt|~ﴂ﹃ŏŒƕǘ͚̟̟̚͢͟͜˝ɟɗɡʠʓ͡ʙșɥ̟ˢ͢˟ʣ̤̥ϨͩͥѩϬͨгЩѱЯϨϲЪαЯϪЭЯѰΦγϨЫu"Eu"Ev%AsBz=p:v:y!Bx >z7y?|<%A,B#A)D}#9}"=z:{:}:">'@,C0D9I?MKb\bfmostvڀuځ~yᐄ{yꒅ}}~x葀ꝃ{}~{~kyncwhp^dXXMML:L5I(I'EA-O1ONevuLm9V6P2F:OFTH`PibyvmGqw%V_K`N[OUI[E}HzEzrԂj[]oӵܯ役źʹŦֵŕ}9C@LLSSV7L9TFV\c~{˷ͯu)9Q9J 5N9J0T@W;\7WX\ 4] 5_6\QCSTZijkqrvuukteq=KiB[IVCXCUaH_d BgB`Bf:8P7HnIj?y&A>I">9N|'=3C6H?Ky>{'>n5k7y*A~)B|'Bc5W 7M 2^:Y 9\@p$HXkÀӎnjbqM]rV\i_yo}n{[v[zg}iuhtfupωw͈vЌq̄v̈y΋t͇zˌz̄rɃyʀũvʈ|˃v€vŀtDŽsDž|ń{w~vɀo{~y~tDŽwy|}xȆuǀ}ʀqǃvĀ}xx}tw}vz}x{p}{}wynzt~v~pzzzvvsvxtnttogmrjlcmgb{xҋxݙyqxÌƐɑȑɗΟ΢ϡɠ˟ˠ̟͞͞˟̤̜ʚəɠțʛ̝ˢɠțʟʥ̧̠̩ΧЭѬϪЮѰίЮҸЮϮϮϱϯͦвϬϪгҭϬq9q9m=p7v?x=q8r:s?s=x<}!>!@|%B$B!=~:8~@:=&=)A,A.G7LV>^C]?V?W ;Y.r">6H2Be>X 4]7]:i9_'@j:+H{&=.F8J'Ea4`9^<^ 8_>n6n#D+E7Jx:6Jw#?,B6O7K{#=},Ak=h9s7'Fz(@er;x#Fx@v!Ey _Kj.Ti,Wg"Rb#Me'\f,[^Ti3\p5jw8mc*Uc%[b&XVOVZb"c[Xl8k[qhOXU}G}PSN~Czp5fo4so7pb'b_'`m5rzClfaLxght5mb Wl/^xQ{d~Jq/lgRCcq|ƃŅzd}XwuŸۨ۴׮Ṽȷɺ˷ܷͬe[/DCLRYLRCR3Bq!D\<] 9a1fBd 6Z3e:a6n:k:y#Ee7y(Fy&B1J4N.Gh 2]5Z 8W 8_6?498@3;67-8(7/91=0@9B?FFIKULLOSV\SPML:F6G4D/C3N>N?LJ\P`MYJWNZ]altjpq}vvmmntFQgCN?_EZFRDN 9^BY.E}(G6E;L6K)Dz#=h 5g5w%6~'==<>|!D?} D@.E/G1H1NF[G[Ub\`glsxzw}y}߃s{yvz얂zy랁쟀좀휀z~|{ws{ol}jsbgU`ZQKMN;P6O*OM8\fŊnyIk9M*K1L.N9YD\]~}uׄmY};moRaQ^Qm'T~@v{Aer)RYFN ?P>YAZH`Qf(Vp8jh;b[Qh)]n4h|;s]M]No.j\W]!g]dZ2ddqvXVM@zQ[^Ky?wzJt?ug+b]"[d(^p6k~Hpgqwkm0di.g`'ZxI}k7gg*Xd)`h&Z8dRa}a`\s^nvuݠy߱ۼݽκȵֹÖ:N7KJTUV8PAZD]\f~зNAQ5Q ;Q:\?^=`p0E8Q1Cl3[3Z 0] 6\ 8m68LUi}C7Q8BIZ;K*D)B+>:DBGGLALTTSNPXSPY`^V]b\S\[UPYR`jSQWN^`\^_Z]]ccb]ike_eckqfbnwhjrrqundmjrlncli\ZMNDY?VM]=N=N2>3E+<+:/A-<+<.84G1=3@?J8FFFGVBJBKALAL8J>F>K1I3B2B:B5G>HFNEOFPLWITJXSZJYB^IaHe=`;^E_Pecq^l\jR^Z]lqhppmvwvtoxY]z!E[>T?Z?XHQ?[B\=`DdCnA`BU;[ W>_Ck Hh@_?t&F|3Mt(BuBfAn!<8M>Kv%@4Fz.H6?5A3G|;r;` 7f 2s4@P3Lv$Cf:P9[BbDWBbI@XkyʏΒsep{wygWwjԃj~ey]|a{d|j̀rzvАv͋̉vˉ|̗ˊ~͈wȆxʊ̀q͇wɆsͅzȅsˈmʃ}ʆz̄wɃyȁúv}~y{mÇÃ~xƂu}y{w}xȄ|ăxu|wr}q}vyu{uƀp}s{z~x{rzxut{tyqvzzrqhmnmokikjbbqm{m׈rv|wŔɕ˟̝Ҫ̞̝̝̙ͣ͟͢Σ͝˛˟ʞ˜ˤȑɞˢʠˣΡ̢͞˟̣̥ͫͦάϫϬЭϭѰѱҮӮدҰЭϭаӱέϬϯίϪqCqCp;j=p6t=n;v=v;u|C C~ F!:{?A!=?'@5G2L6P>ZG]Qa[mdgrwvy{r݃v߇tu}rꗀ후x|~}휃zz}{y}w|roo~dsiiYabSPM\LJS7G5T?VXjϬyWXBSBXKVBZ5c@b?c:b8Z8R:V;X6f5m>|0A~'?f>];aGcDc8b9m9h9lCp9p&Kns"B~0G9F9Ku=\:^8aA`9e;QA[;[AYEa:h!HY=R?V>T>T8];lAj=e=x-H}0Ju&En@k@w 8=P/F+G5I| ;-A8D6F'@u9b 6g9n46M5Mw!Ae9Q 6T 8`BU@c?6Rdq̅ӌxgitp΂o^wcցv{lvYzaԀmm|t{lыv҉vЉxЊxҋrч~Ѕv̇}̈́rȆ{ˆv̓}͇zǁyDžyʆ~Ƀx̃w~vʃwʆtā}Ă|}s|oDŽ|ăy„ăw}zyÂy‚~{s|w|u~w|vzwɀqxv~}~o|{{x~u}vwovuuyvhoonpjnlkjhph΀oْsr竁ﴄÔșʔ̝͜ФϣϧΛΞ̟̠͛͢͝ʛɞ̛ʟʞǚˡ˟ͦϧФ̞ͤ͢ϧͤˢͧΨЫϭϬШЮҮϫӰӲЬЭаШϪѮϬЫͯάg>g>j El?l@q#Do@qDv#CxAz;~!@(@*D|$@~<!A;z!D#D"=*C>T=V9Uc:Z;VBS6Z4j7i8y(?y!LCPBLFTHPGRKWR^SaQaQXXcUdVcXeXlRbSgRZYiVlUgQnWo\va~hmmpx{y^v\vYq[sgsjukljjoognompprunjjsYWs>\FXDUES?VIRD\F^@` Ci!G]EYEVFW?YF[Da=l"Df#Jg Az,I-GlBpBk?{(E?Q+C1L.G0N.D7I:N(IpAe@pX;bg>k>n>p=q=s>pAt=z#@x>{:#?|:}%@}=:z;v:"@%>*CA^BUEc7QNbYr^hiuqlwv}q}x|uywzz띃zyy}{s~x~xzhkrvci`_bN\Da6YCb`†υZu=R0E)G)F3O7T:TOvfwtXw^~`uInBov)XbKp0`s.]g#Kl(Uo+[`RSBV@c WcLY>`Oa#TTGYJa)Uv?yn+]]Xa"Tj5dM_ [Z![ZaY$[xà~Ss1nq8nM~KM~FIy?~PJ{TZQIIwMw>hDly<_WOe#U\([{Mk0iPMg{}mp\lU\[acY]Wdugȵμغȗdk:JO[RW7S?VVdwۈα?IM=OBPBXCf!H^@dCdEf;]@U=T=R K?JKLOROMRPSX[XWW]USPTTUUUWYTXYZ`W\Y[XX_dcb`fcdgedhbnfbqooluqrlsrslqohcmogieb`cWVW]Y[UUZZT_QVVcOeJ^KVN\KUN\S[T\\pYb`rYoUiXkbwkifdhqspsz뇮놨阺铭꘬뛳葡炙j`\vZucspqtrv|rqnqniwwoqpo`].A_@S>W9VCYESAU@dD[:fHh#GZ?[DVB[B\HZAc?j"Fg%Kn$E7Gz"Ch;i EkC|+DIV-C&:0I7J,F7J8H2Ly*Ih9e\D}4LOhƁ}ΑʃeelhՎq\tdփxՀltb{g{éźźnыtЊwˉtˈv͋vɇ{̆yɃwtLJzɋ͂q͉vɇ|Ȅu~tLJz˄zʁv˄|τtɄȀy}wǁt~ŀw~|}y{o}x|o}yƒzs}wā{z|}wtyws||xwyn}vÄ}yzvsus{yrtpmookhegeawjуxےwy뭄”őʚΤΗѢϠΣѡ͠ϡˡʟ΢˛͠͝Φ͘͠˙ʝ̘ӧ΢ɤϥΦͮˡΧЫЫϩϬЯЪѭϴѫаϫͭЮϩϭϫͩͧϩΪϫͥͣhAhAfEl#Cp&Am@s!?n;t!>u=z?xF|"?|<~@z9~@y?sA}.L,G4Kwu?y~JQVOYKKzIs{?g|BlMx|>qa'Y_!Vc*UTzc}9v[$V~N}Fhch~~subeZ`]fa[cM_ZaߢǷ͡|DK@TSYH[E]RbvyϤԨӸo_\#KQFQHSIWBdDf!Bf@`Be@a>V>\?S ;T :e9u'Fj=r!=n8d;\8`8c;e?p!B|"@n"Bm'Jm>v&Fi@n>s?z+F4G(B_B`CbAcAj>@WG\x$Ex(F-F8O6T6G3K4H-I@L@IBHLNOWMIOWKNSUXUYTSRUPS\TU\\SX\UY`]`XWW\ba\]eahbcgimjcrsoounqoptmgstoqsppnjjibYZb]WWTUUOUWTVX][bRbOYORGRMUMPY`[nYcer^o[s_zj|胞劥芧閱蒝暫蟶ꎟ떨쭹ﷸ췽횥넘le\ua{lsqvqttuvvmjntsjikhjDGrBXBVCVCYCW@\JTf<] AZ@ZAU@U;[@b;n"Db=iA{%Cl>kEjCn!C/BBT.D{'C6M(@.K;Q+J~ @y%Hi"Gk=q9:HGY|)Fh=R 9\ 2c>\C_E9UNdąЗ̊khpiՋrdt^րy܁gs_{g}`΄{yiЌyҋmNJ{ʉ͊pʅ{̈́z̃s˅ẃwɁuˋ̊Ȃwʃz͉yɈ{Ȇ{Ƃz˅tˇ˂vȅw{ŁrxÄ}Łst|{yÃv~x‚wvw~s~tyyxuzĀwzqyy{sƒ|~vxpuowqvoxwrolqopekfiefsh~pۘwvÍɖ՝͞˟ϢϣҦΠ̛̟͡͝͡ϠΣ̟ϣ̡̢̣ͨ͟ΡΠϥΥϬҪѪѪЪЦ֫ЭѮЭѰҫѱϫѪέШͫΦͫͪΨϫϦϤͪ͜jCjCi"AiDu"ClBp?sBt?t!BvCx=#E)H} =(G|>v>x<~(C#A0M:P6HDZAXGYN_Ziiqonyv|v߁wyvvt|t|zvyzퟂ롇t~~vyꕄsr}yugkZnSjSnizЌd}AU.E+F(>1M-M3O9TOrfz}qOsQfSpQnCkDp7fp+^n.Yg&Vh'N};iKt3_a%Pk*Y[JSAL=[NVHQGTHg/`~Nt1`e Xd#Z_$L|LCVXXcZ)Y|ϪvPo2k[#^a"^n4jzKYZTXTB{w8ru4iy=oP{@i[%XX$_^$]u>Z^Zw;ua\dl^uxmg]`Zd]UXKaX^ۏͿҲǀwQJ>NOXIMPc]cgpఋ߯صuk,BU HRBW!N[HY=aEeCeq=o5n:sA]7]5a7c;f;v$=q$Ch6m6z%Cn!Fq:s 7{$I-Iz@f9[7`8d@k B|7JE_~0Ky"@:M9O1K8K.F&A,C6C>I=MFMOQLOOWNUJNOM[cNSOLQZOR`bSX\]UXU[_eZdXT]^[`bbaffphnpupku|roprmtnkmjuzthkmej^__[^fX_USXWYZURSRY_SVPZJWJQLVT]QVPeal\u^opt}鏖衞줞몟直螚냏fu_v_tcqfnp}xwpiz}lnlhkgcf[^%<\>U@X>U=WAT=_FXIb=d>f;i@Xn>v$C1CM[.C%=,D3C/D4T+Ly:r8i8n7(A}-@BL1Me@U 7X7dAZAdD4UG`Ȉ͘ϊjssgՉ{iu]~u؀kt\|o~n̂pˀv΄m͇v͊uʋ{͉rɏ͉yϊrˈ~Łzȃqɉ~dž~ΆȈsʀxʇ{˃sΈz̆tɉ~ʃxdžrȂ{ƒvzƃq‹ÁrńsÄx|uˆÄtytu~w}~}~ńuĂuu{yu|~ry~}q|ttpppoirsptmvejjqunӄhے|{|ǚ͠Ϝ̞ПѢ̝Р͛͛͝΢̞͙̞̝ͣ͜͢͝ˣʞͤͩϧϤΤͤΪϯΥЮΪϬЭүϪӭЪЩϪЬϪϨΥҧͧΣ̟ͦ͡Ϥʚɝi:i:hDi=qAm{"@}%D~'?z=">} =~!Dv5x?~>*D-E8P7IAU3@;HEKJJKLIOMUGNMTYUQQQYWUSWWSQ[YYTWXT\jZ\YW^fZZ[X`dijdhddsnlkminjoipsogrjsflmf\eg^_]Z]^TTWWZ\U`LMY]\XZaQcIQJ]LWQ\OWXkShZglz{y}풒쟐膆率镙p`yYwi{jxorx|y}zx|kimqnskq?JjFY?WEYGVAQ>TDX?WDiDb;e@i@];V>Z:V;Y5eAdnDx,@2HTg/G|:2G0?0L0K,C|Br?l;x'@1Eu=AQ=Rq?[A^9d>XE_D2]L\ȍϓˌ{mhՈyfwZ؄pՁxvZxjҀrЀw̃v̄tʋΎx̋y͉͊|΄yΊsΌxŊƅvʋ{ˉ{ʃvȂv̂rΆw΂sˈỷȂvÀzΈ{ʃuƅ{Ʉtņ}ăz~x}v†|ƅwzrĀvtāq~{~wz}}s|yƄzÃxwt}twt{s~wwu}w||~zpttmnnkododkc[ynՈrߚx秀{ċ̟̍ОϟϦϦ˙ϟϟ͟ΣѠɝΝΠϠЧ̣ΠΩϮϥͥϩЩΩϣΪϰϫѦЧѫӱФҮϫѫѥѩϭϡХϣˠˣ̢̡̥ͥ̚͢͟əh@h@lBl AkAl;v;q"@q;w x9}5{ 9{!B{"Au:q:{<'B8O:Q@O?TEXGUNWXd_mphvuu~w݅pvt{vx}s웁zw럀z{yx|t{|莂~∝}]_gtv_{?S*B%D&A&F+I*K2V:XKne~}wIrH\FXJhCfMu8^n(Oz-ey.fgNu8`~uq-Un(ZZ?L8M>WC]RP APEe+^PNo+Zr+`f]b!Kl>lWf#hQV^/^ʪoWt5sUVTLg(ht9uw@zxC|{CyZhfU~F~E|Kq/]\%Pq[9^;c6h>rFmr%?{,E0Ex*=v"@_7[ 9_ 8k;w'A8J)Gk5AU5J?N6Qt>&@/J7P6ADKEMFNILMOPQKMQZSUQSSWQMOPSRZ[OQU\QQYdVX\SblW[[X^\dk`cecngcaooojljpiustlpjsglggahigebbW]SWSVQaMPSXYZ]aX^Ub\lQVO^R]QaN`Udfumtspzuy}~{슍퀇uzwry||퇖ꂏk]rc~q~qzqtz|x}yxrrqklrnrVYw@Z:V:YCS7X@V@W@V>X?s*Hbi=n>r:o:pBsAv?|"Eu#A}"?~$?{9y=r:y>v B&?8W5K;Q=U@R@[L[^jdglsunyq~qwvv}였靁yyퟍp||ux|z{{똇}荅䔐ݜяˆ}mvanB^'A#BAB&A+I-P0PJndlˇe}LmH^J\JmDj{x9gs=sg8pn/aw7m?}w9sSuwopԈs`aYaJcU]͎Ѷʾʹvi0LH[X^[ao~؀`䖉}ׅ~Ðz_Fc&FSATDUHZ!MZDW>\BbDaFg#If"Fb@c>]=Y5[=Y 9g2[ 6`9n;b9k?l9d>`?_>`;a9o;|%@lAr9mDr!Du#Ez*Bz*Fx+Kx(IlC\?[>hDq">+B+Kl:8R0F2J1Gy<-A3I3E7H>N8BFNHICHNRJPRWNNNZPUQQPZY^RUVVU`QST[X[ZYbbU^TZW``f`]kisnggnplkmetrurmoommgjceakkbh_a\[]\bcVVSWVUTXPWOQYf[\]fV[S\NWSZRgbzewdufyl}pn~pxyslcfb|qpvgy^vYpizowrwrqytuwyunpntkmee3Be9\DR;S;UT@Y@^;n<[<^=d;U9[?Z=R 4];g<`9m7~1Lq8d?d:` 7sGu%B6GTi/Ez ?3L/=AXD\)B{"Av>s$@+Hu?v'p=k;l!Bt=s9u7}=v9u6{ =y8t;s:p@|;(F3M1JYV]Vn3it@ovE{x>`)ca*XrEkop\zByT\u;syIv1jPKLW{|mۀepO[GbZeܠӼմ>LAYYj`]nuvxdⱋŃgY`@YHVCWKXEU?[Z7c@\C`AkBc>p"Ff=f>b@`@bBc>g"By1Dr+Hl DmDq?o%By)Ht%B}.Ir?h;^?]?gFu3P=S=WwA1J:H;O.Cr=$;*D-F8J_>a=ZAf=g=`3j>{*Fi;e7`=a9t@#B6ARn%CvC)C*9G^8O)E$;y"=~&D-As Gr8:OHZmA_9c:`o;q@v:z7s4z;v;y9s9q:u;p6q:!;#E1E;H:MX:LITR^cdlprn{t݀ttwuwx~陀陀{}~|z{}{z흌ꖇꔐ䍅爉ᇂ剀߂jp`kPSAN.F C?"B#F)N*Q8SNyqɋ|HfD`>^D\OaW}Jg&T\KdPcVeIu9a@hiDYDW@YF]KUGUMPGY"UwByZy8m\Ne+\S:^!T}KBj(fl֦_YW~}Yk"fa!\r8lq:rzGNe(gVYg7d{NwplVcz2n`UlaUJtmɊ͇yxтgoJ[G\fm㝠ȨļǏATP_acffuh뚆ћ٧y7MWJW%O\K[%R\%N_!I^$O^Ic$Jc!DbFi)Kd!@kBd@f A[=]?XmBb>f?i:cx(?n:kAhAq*E~,Gz.F~4Io Bh>]?_Fj Aw2Q8Q:Sz%=a?e;\=\;m%Gd8b4l <{)Dh?f7dCb:u>&=9GM`!?w C.G(?F]4L/F3N&E'Cw#Fs?s8FYFZg;`9hC_<\C[Cu,TUm}ԓΉԉykׁ{֍sZ؉yԅyf}jцuɁqʉv͈tʇ΋x̎yNJx̋w̆|ʊz˅tŁvʇu͈xńw͉zɉȃx̅vЇx˃pˉ|Ƀp͉{Ɔxȉ}łtłpÊĂuńv}yÈ{Áyy|{|}~ƒy{~}~}r}sxl}vyoxrsqosnkrrklenbjecwp؋}r}Ȍ͙УѤӥңѢЦОϢϡ͞ϝΤ̛ͤϩΞѨѩҨөѨѧҬҪѨѪҬѫЮ԰ҰӭѧЦΦ͚ʞ͝Ξ˝ɛɗșǚǔȐǗĎđnjǗÚǙƖeBeBb8`:h;p:o;n9m8j@rtBq;}#B-C6N1E:LETSjo1px=Dj2`}٣WUx?r|}?m0vs5n~H\_o7lb#b]"^r>pt@hmn[\~z;qxtxkd|7fXͅїĔr|brH^E[]^գ״ؼy{Faccknۇ]蔉đz~sQQaHQHWI`"N^JTDV IYI[DYA_Fg%HgCbGcDc,G]Ad"HY<]HbBd"D^G`DdE]?d@ay-Hy-Du%C|+Ft>g>cD`=Iy*>2Hy;x!B}#=-E,D/78BAHCIEKDGJPFIEGIPNONPSRNLXdTRUU^aXUWWVSab_^chciadelc]ekcjdj`dhmfngikiimniidmfmkdec^gh___`__^^_]YYSU]fW[Y[WZPUOOUZV\SaP[V^_a^dYi]o`qf|f|h{`rdsav]kXpZcU`Xdaxfuvp{|xwrnusstxvnkifafEL-Fd@V :YAX>ZBU>]JYDU?ZGd'FiG^@_>bGm'@fAWBcDo@d=c>l>v'Cj(==HMb'?t<-M+?KSy;|7BNI`r<_8i?a LdJ[Jr&Q\wzyіɍՏ|oрp׉vVمzԆo_~qцtɁlʑxɆuʇtˇwˎȊu˅uɊẘv͎|˃yȆwɆylj{͉zȇ~ˇuɉ}͇|ˊtLjɁsȊ|ǃvȈ{ĀpLJwxÂzĄ}DžxÂ~zĄ{Ƅvx~}wzzrx}yx|wzqxx|ptpyr|xynyyvwqpsgplikdoguegso؆u~촇ŎʙТӬңҥӤПРҤОϜѩϤϟ͠ФТЧΣөѮӥҫӪѯѫөԪѦѩҰҤЧϦΡ˜ʖǙȝɕȔŘƐǛŖőśǖǓǒȗĔƖĘǛe9e9f=f7i8h3J:I=R?P)AE!D'J'Q,RPksψfvOwB]G_DXQb_xVy>^w,Z]McP^Rg&T_|~7^X@S@^E\J^QTLSMQNo=s[Vk.`RPY T^$R~A~v6n{>~;r=l՝l\Rh+_`a~C|@QhiF~i,jd&ab%aZ$VsGfxuUJ~tqjlJK~f۞ԛasunNhNdczЗԾytkt̀rᏓrm˪}a?Lf$RY"MWNZ!P\"NZ$KY!J\L[H]F^ Hc%Lf'Mi%MfFdAk9\^%JX!IZE\HbGgJa>d"JeK_C\Ge%Kf&Hj&Lj#Fd%Gg&IaFl'Iu'Fq'Hh>q$Ir.I{2J|1M{1Nm&Gh$Lc@`@k(Kx+E>U|#Fq&B@P6H6Q)Bs B)A5O.H+B4K?J>KCK?IAP@LCHINNNIPS]IQYbV]QPWcSW[^XZaebc_a_`^`badhc`fnjihnhikniiddlpkhkbkmokeibcba`f^_^_bc^`[Z]`^dZ]VTYZTURYNOLVOVSTSTYT\eVYY__aaodqYYTWVbT[RXTgOaYfbpw}zuzxtrmmyxswpnjmfk=>+E1B_FO U@X=Z=YX 7^=`!Cr%E\<[@j!Bk;d;hDs%?q?o"@f@cjNNeq{ѕΑЍyh~n׍uVމx׃oaҀwχv̀u͉wɄvˏy̋sljyNJvΌqΆw͈ͅnƋ~ljxʄwɅ{͌{ʈ|͐vʋ|˅t͊xLJyDžwǃwƄ}ƄxʅxǂwƆyňtÆĄrz{wƁqÅxƒw~}r}zyw|z}x|}|ux|{vuut{rvpuqnnpoonruggfs\ecctl׎v㡃츈ɎМӥѣլԪӣңѢҢΟ͠РϥСϥϠѤΥШҨӱѰխӭԱԮҤҩѧϥџϠϟ̔ΤʙəȓȗƖǛǒǔÔǘĖƕȘǛ˛ƓǙƕǘǜf+Qf+Qa>e8a9i4g;e8jo9>+A3FDMBL:J3N5KISP]]acbrpuhzs~znwzzx鞀w|y}}x~{鹿t萊szpxiomaSXVGR:H1F"C$G"HO%M9\hyń‚LrEdA^BZE^Tg^rMhz/TlQ^Qe YeTy0`g~y1YR AO;O9Nz'Cl>}+G+G)A%>0@3H=G@IJSHSAOEODIEHLTOWJQSURXQROVNXT\VWY\_b__YYZa]]dfei``cm`jifmx_chtpllijlfhgfgkem_adc``_d[Ycb\_[Yaeac[U\V_aSXNROSPSIMIPOOPRMPOQTQQVX_OQLMLVS[ESQ`Zpdrxۃ{y{ڀvupsnromoorjeeNM{28N#>[HUAT=T:TBS>S \?`?d:W>c@iBjA_!Cj!GmAf9d=ge?i6g;w"?5EFZg>h=f8i;p :m6r>l7o=o6q Ao;q9| <2HYJ^F]QfPl=]l%R`C_Ni [fPx1_`|vw,QY?M >_DbJXNOKE>_&ZT|Ezi-TaQ[NTJLMXPn8vD~={aԶ̡{y}=u_\l4m[kKZkwPi)da'[e-dq/wT\c-hyM{iE>gbp[VNf~mJfz{Wu\n|իയޗkqf[琈ذ滆bNmF^JXHULY LWC[C\D\G_"Pa$P_ LfAd@a9j=g:k@a9[7XB[;X 9d?j8e#G]8`@c@[?Y;dBr!CuAqFs)Cf!Co=m;q*Fv(Ej">u*Eq%=q%B~'Dk=i>_>`DiDq&=8R3Qo?2A8M.Eu!>r;w$Cw%@)@&A2>0?5A@GAIINHLCLAE?DKSGNJLIQUXNTQZWVPVVXUW^]\_Z\]`\cdbaf_caejtgjchgjfqklmrimghgnlqkkhpcf`hai_^ac\]\\Z^]_ZVY\XYWX\WYb^]NTOVMVNVKQQ[PTFSNaJXLXR[ObW\criswxyyyzu~n{jlqlxxtoom_U!9r:;IuDU=UCYET?S=Q j:`6y>>IUd?T'@%B5N(m=h:k=j:i2l9i4f5i4j;n7rA(>4Lp^bq&OZAWAXI[EQOQKGAj0hOFi'Yb#S]SWPLMKL_(^y3xIxߴzMg*e_$duG~^`hqYm.hm4sj5pw:X"Yf6ug~uudQHhZpKl^#SZwc7TbtPgYdƑּ۝hY{}jك’Ç{Sw>WCSHTEUEVFYFXAVA\DZ@[A_DdDf=g!Fm#?hDr(Bh!>a"FU;V=W5c>jAh@`B`EeB^E^7UbFlCiFjDv*E,Kn>f:t*Hm!Cn!?s!Dl=s&Fs%@j>lbEhCo%F1Q~/Qq!C.GAU8Uu$Do>rA{-F-H.E,A,B/D:C?IGJDFCGDGFJLNDHCLELPQP\PXQRPU[^VYZ]\]``^_\^^a^gck^dkvgifikphcsvlkphklkmdkejagbicmcf`cZ`Z]_jac\^[b\fcib`\]cf][YaWXR]PWS\WjNZY\XjZhY^Zjekox}zxyz{n~ixejljmonhosACl8t<8Hs?X=Yd @dAc:y4Os+Dj=b>i)Eh9hQ~?'H/H#=FNMf/?*E~)C @{:|!By"<2GAT|&Bh2wHf8NlHeLh#LLiqДԣԏ}}}bڎ~k؄lur|kˀo͏zˌzɂu̇ύǔuʉwƆzɊϑs̋ˋrǁ~Іwˇ{͇w̅|LjȌ̇|·̃yˈzȌz͈̍~͌yˍ|ȊLJɈ}ȄvÅz~Ā~v{||}uzxx{v~y|u{s{xqyzyrwpwsllrsleilgnbiX]_fnkՉpy̖ѧլ׭֮էԥТСѦѢעҡңПӦШϩҫҭԯӪԮծիӫѦЧП̙̞͡͝˚ɔȒȕɒʘȗ˘ʚ̝˞ˡʙ̣ʜ˞ʟ͢͡˜ͣʢʤaCaCaCf;c=g@jDl An=a7h:e;i=h7d7g:hlAg@p#BhDa=W=[FV=dAkDn;\>X;f>a>`Fc<^AcAkAh?m @j@eAki=pu Bf@l@a@g@l@z+Ez(EkCz(@5J;Vu'Fv&Di<+G&B.F1B(=3C:D3@5B:BAJ?GCGMT@FILCLMQMOMUORUWSVX\ZXZb[YY`_^dk\c`kbkijfjgjbfelfkkljo`himnqdtdgbkjk^gdmcaag``fq^_Z`acad`jdglr_beoep]e]e\hdlai_ffzjkjltpqz~su{xwswy}r}duiukptvqkloej?d=uA:Gi?WDXBP=X?R;TBW@V>[@\Fk'GgGd"JcIcAa"Eq;Vq(De!F^=g!B_?dBhd>rB2D\jCW-D1L0I*ALRCU/D|">.Mo;w<{.Kz$?3@KW*Ej<{!Be;dCfH^FHbn|әךԏ~n}l݌|sԅzwf{qwh̓t͈zʋ{ˆwˋvɊː{ʊ|DŽyȉ~ˊ{ʈɉ}Ȉ|ʌȋǍ~̅zŃyʋ͊}ʇ~Ȍyˋʌ˄|̉xˌ}Ȉ}ČɅx‡lj}Çv†{…y{Æ~{y}xu{~y~w~u~xxs}{xrwwvslppjjttkbfnafaicfojԆo~﷋đ͝Ѡԧ׫ԦӧԦҥϡѡϣӤРѣЦѢҥҩԫӬҫӪҭҪѬҧѮ͡ζ˜˜˛˜ȚȘʜɝɚ˜ɡ̞̟˝˞Р̤͜ɨ̦ˣ̥ͤϦΧ˦Χ`;`;a;b:f:f>i?g;i;f?kAkI'> AEE M-RC`pU>Y>U@\FgBb3\y0Xq&Vp2a\O\S[Ok0\Adimq'QeJ^D[IZGSEH @HFPKl;g|Ass6caN\Ii(\`$[Z#TPTD PTVX¸zlugw9]']{Vzk|gaI|LS^haQ}u?ozPdkbpS};ep1jw>rd|tROiJOú˓ݓw愈ԟӓg6GYIW!LUM[!O[IYL[K[F]EYE\KYIYFcFd"Jk#KiBi Cf#Jx%Dh%D`E]F\C^BdCeDk#EgG]FgEk#J^HaKbDbEh#Gi(Mk%En!Dn IlDl&Dp&Hu(Dm >s"Et)D{*El+In Bb?g=gAz'Cz&Gl@u&G5H;Ry.Fm$Ff?v!@|,F9G4H,C7F;E:L4BAJALFMCIJTJRHQKSLVLSWXRXXXU]Xa^a]cW^[[^gaketdi`idnbhiqmjbminglbchogniichc`lsah`fioeediikeo_dbaeedglflnnkkdqrmsouqxsuyljqoqswtyux|v{{xq׆݁t~gohyksrtmkqnkr?Fl 7b9w"@6G`HV:XHXBSV=j$FcG_?kBbCe;o&Kx+Hc?`Dd=a;d9f2e:v?] 5d=r=+>Yd=T(?.H*C(@CKFX,E~$:,C{9z;|HO6Od7p7g7fEdH\EB\sјӖӒф~xbېֆsՂu{p{o|mˉslj}ʃuɄ~Ήy͌v̋{LJ|ʇwʉwɋ~ʅ}ƅ{LJzdžwɅ}̊zƉzˌ{ʅ~ˆ}̋|ȅx˃|͈ωỷ}ȉ{lj|ƈ{Ň{ÇĂzzĆztƒ}~z}{}|}v|x{w~u}z}w{yzy{t}vuvynqxlikhimiihp__ckolӉtzƓ͜Ҧ֩թجթקףҫСѤӥӡХӧԤխҦҭҤӫӦԭҦѥҩѢЧͧ͟ʙʜ̣əʡΡʠ̝ˤ˛ˠʚ˟̡ʡ̤̩ͧͬΥϡ̦ͥͣ͢΢e'Me'M_B^e9f=j4n?}!>8MJ^CQJPBNO_AOHZLWV[^[biidqiqmwi{m}tn}xꝀꟀuyz{}z|弄x{syou_r^`U\[MR5E7O&C}B!IH%PCbk[Ck2N@bCf7_;d;^x5[s0YfSgUm)\o+av3S`QuaHh N]D[NVFQHE AHEV#Qn=l|L~x\@X>]?Y>b9gb:o?n =]CZ?WAZA_>h#Ej!Ff@`CbAg@^?]@dGaAb?g"Fk@h=m@jBlBh;nDq;w2Gw*G{-Ep;i?l>x9*D)=#;0?2B6A4A8E6ADJ@D@M?EFIKNJWHQMXSTQ`W_X^^m[`UWZ^^ebe\f\]^^fmceiifhcjhjjrgjfpdidmfgfohchlbndgcneiiuajdjefinsxprvnszxtstv|}zッ~|zu|{〄vwzy~}䀄xy|ہ~vrsk}erppvurlkl^_=] 8b90H}'D^?d'QWCW7S=S?O@[@\AT@XCg"AaC\Am#Dd@dCdAj%@aH[=c=c!b:b6e+A:JFTLQQ]JTHWBMH^OROXbggfjgi`uspczqpzn疀ꗀw~rퟀ{{{휅s{{xw|uvyirbg^VVJH9F-H&EB(L!L'M7[ZvteMm7TBiDg;eJl>bz0Vp'Ti Qt,_}4fu0]s8XSz~@dZ>`J`IV@RERILBLFUNqDlLp2bXJZ#Nd([p-e^SY!`Z1_a)qY~ڡusyGwey_o?o\ätmRVQptWd,^d2ht>oDuos`|ZlPaVY"OHvuiMmZx`j̞pΡ칂fC4I_!FQCT@SBUAU@YF[$M^I^DY@[D]=U@_9b;t!HiCm=b;i"@p=\?[ES :^C^Am)Nf?f;^;a?d>cB]>^@\F]>fBfDm?p Dl%Co?k"Ck>s >s>u'Fo `:\:c=lDHKCSAFHTGMKTJLL\NQS[ZbVV\`[YOU^babglbied^bklnode`oaecchhfoijjneihgoqlsghelftalkjlsmtmnlsmrsqy{ywzy}|働䁅兂猄~冄vu~}x}}||{tvzr|ptpzqsplsion;s+DhGaAk>k%Ep&F`@`=e:l>\7i9r"JZ9gBu<6J]hFT(>.I$?#3B9I/Hr@g>e;rIlNW :4VwђלڔՏ}bٍyٌ~ktcxoͅoΊy̋|ˇt̉u͎wɊ{ɋyȍ}Ȏxˍx͊yΊ{Lj{Ɖń|ɊĊ|ņÉɈỷ|ȇ}ăwȇ~ǁwňązŇ~ƈćxĊ~}{ą{ƃ{||…|Â~y~zŀ{u~x~}y}z|vv||orqsptlwhmlkjq_hbl`hhhӌrᬊƗ͗Өէװ֨׫֦ԧӣԥԧҥҫХҩӳѧҧЭѣџѧأΤΦΤΥͦ˛̠ˤ̟˝ϢͥШϧΣΣ΢Τ̥̚͢͞ˠ̡̡̛̣ͣ̚͞ʞɠʝ_>_>`=eD`Ai>f=g:]P:W@_=fBg!@d>\?d@dDm A_?Z;]@bE`H_x)Ct#Ar&@nAd 8`?c;l4q#?v#w 9n#=|6Is#;v<_En8*G'>"=5,71@8D5B5BVDSAX@TBY?\@XAZD\D^=]BcBy5KaChBj!@l&Kt'E`;`7q%Fk;\8c=m?Wt<`c;_9`Ac?iEy"H1GALHUFJGTGNHRERJWKPXace][f`ncvrp]xnqn}s{|阃웂y{x|v{{yyz{gzipdaWVSJQAN8J.P'F#E H,R7SIh\d\LmLoTt=h1X}2`r+\k)Sy-aFoQ}@hx8]Hrk'M_K`I]GQCNEGDMGKEd)VyCpDtn.`RDPHWGm+\g#[bYXVW[f3\~ȏW~[fM`Qhc~DfrV[gTRGr5ms5svCxs>tsBr{Nucb6[>cAl^uTzUGQxlAgYdјtɪջƮΜϖ_8B\H\F`IUFVCXE[KZI[K`&Gc$Nb'JYD_EWGW?dCa=k?pAe$Eh@p"Eg?`:Y?U=_Ac;h)Dl;`>`?i;f?r"Ad>_B_>_<^j:gEc8bq<~0E~-Dl~'<(By9!; 6-@5B1?=ECN?G?AEUGMHKHOLQHKIPPTWWYbWW\^Yf_h^acfhh`efhgfcmfpjmgrhkeilnnjmrlrjlmwhhprprquwx|twvyplyotzwz~}愃喓銂芁玄蒍ꎒ鐎䄀z郁||{xჂ~|~{ys}ruvt{yvittGIe 3] 9Y 5g:*Aj>YGTAW@WDUCW@VET@RER@[Ag#H`Ii$Ju)Ee=n(Hy/Jp=e Fc7h6o;f9^=c9j?a@a>w#BFRdpEV)>,E2G,@L\/=,C/F+F&A$;0H&BiAp%CiEiAs%Li =bF\GS=[FcCg?o%B_@^Ee:djB`=X=[6ZA^;cg@o9nk8e>`:i@p>v(Ax%Jj"Bo ?u'?|,Am=d>h=u"9,>0E#;{;26);1=5C9E8F-@hGV@S@WIU=TAXDYEVFVD]E]IjCd"Iv.In"Di"Dm(Hz2Pf=\Ci=es@nJkJ[B~-Jyәա֐ь~pܒz׍zcom̈|ɋw˂yɃw˒~̎xЏ}ˇyǍynjzLj{ɈɊɌNjy‰Ȃyˊ|ˊ|Ċ|ăąȄȉłzĄ~ŃÄyŇÉƇyňĀxz{{Å{ņxŀ|}~y{vt}xtvz~~vy{sy}xqxqnqoqmnikfoaqYdagrpؖ崈̙ѩդ׬֪ӦԦ֣שӢԠѤϠΡОϥϡУϢϥ͜ϡϤΟϤШϡͥϦϞͤҧΦΡϣͦΣЫ̣̥ͤˣƟɗəəȟȑȜəƞȡȘȞĎŘØ]8]8`?a:f<_>_9a>d!Ed?dEa@b>`=_Gb?hA{@0E:IJUDNIQHUES=MGUP[Y\cbd`e`nanc}w~tqnqy{}yx휂~v蠇x|{~|}t鎂x~hxeoab[VSLL:L3H)EC?$F+K0M?UJgRpOuGiC`QuHux-Yv/[{5_r)[zDfEjHjGiIr{Adh!M`G`(R[JRGQCJFKHSDi3dO{Cqm&ZPGKFRK`Ih!Tk&^h&cd"cf*StωIo{HNs=yS_heYT\|iZfmZUX~Fp6pi2qi5xqaIZAY=Y!I[:` 6gEk$>t(Dh>k7w'CeB]D]:T<_BgBi%@v#?]:a@aAd;g ;s"Db9]h;d8b=b8m?t!;x#=kf8t8)>1E';w5p4x7#9#8):5>8B8@:?>IBICFGOIIGNOROQ]aVW]]][cj^d[^^bc`dhdhgkehijekjkktjjrqonhujiqqtxpuumz~|}䁄~|⁂}၇䂀牌厍午菓鎈萉蕌~甋덅䊎倅煆ኌ䏈≁܅ބywvy~yy|}xissW[k9R9V:Y 9t"B0GfAU>T=VDTk9l=j<'AAQWhH`&B4J4O2GOb8A=[0Iz!?&A'=/F.B@N1Fh80Q|#Hy!Bob=_>d>_>^=_#O_Dl:">1I?KJ]PQLRLTOWAQHSPTVTeicbd]nfoj{l{yރrruzv~{xꘀ癁uxwz윃wx}qxpo|mxbk]`SSSEH@I3J*C!C!A+G.H3L:ZCXSsOs=]DaNn@lz-^o-U{*Xs3[u4gw,Yy2XClJn}?nj(Q]Id*Z_#LUJVKHCG BOHe,XQ~Dqn+aVLOLWW]N`Pg%Xo,mo0st8aiBqSZwDk5nyHVapi\hhzcnrkc\TxFh6qg1rn5edb\>Y@]D[C]A_@XA]CXCb?^=f;l3Vt1Hm&Lg:o;d?[?Wa>`;`@cCe9o>m>j=k9p=k9jp!@q?i3D,Dy7m5s6w93$<3?(:0>1>@C=K>G6ACJHIJMKSORNQUX]cbiccdh^bdi\ebb`hlofnehenjmmtrzpunzfquuw~tuqy}恁拄㈉ᇈ}~偄灅烁捆㓉痋睈鐍菁元鎇鏋昔則㍅䊈凄݉܁v{u{ssz|xnqn@JhF_G[=^>2J4Fd?VHQ@UATDWCYBWFO?ZCj#M\Ai$Dr-IgFa?g@o)Ep)C_@^9k:w-J{(BW 7g<`6h8q>rA/FCOafN`&@0I3B-HSe6A;X*F} >*B}&=.D/E5D%Fi57I2R{ ?hAdEdE0Q{ҍѝ׋ՍՃdۑՋm_xo{yvȄsȉy͏Αy·p͋{ˍ|͊wɇ}˃w̋zǏxɄdž~ɇz…yƃz…{‚yʁyÄ|ÄyƄ}Ȉ~ʼn~ÇzňwƉ…~Ǎuĉ||||}}~~|wyv}qzoxyt{sqvxpwxswtsprpwjlpzds^langk~zݤ黐ȞѢ֦٬٭ة֨׫ؤҦӟУѥΠϞΦͦ͛ϤΧͤΟϡХϢѫҢӫѩҩСХЦ͚̜̣͠͡ʘɜɝɚ̤̟əȞǛȚȠȢȜƝȢǚǚěėĐ]<]<\;];\9]=_9_;]#C6L3P9RJ`ZxOnCiMdRu9]jIbFp+T{9hg$YeLw/[Jo_Gr^!ITHf*TbI[O\HJ@L FVCc*VQv}:oj%\VHJCVN^"S]Ue'Ur1pw4wz4k[~?h[\l.jXOd*ik*if0_{J{ktgZvulhgpfaUtm$C^;`B\Aa8_9s$>h=^@X@[?^:cF`D_;g:q?ht*Ap"Fp>i>u)Gy&=y#9@BBa;8P|'DU@WCUCYF^$K_FXFYFPB\Ga!IZ@h#Iu/FgHh Ch">o)Fi=[:`>f;?Xr"AV1G,E(@,A0C"Dg?3KJGMITGPEWAOFUKV[]aegckgninauj{or{z{ꛃ蟀zq~}vt{~욅ty{|rxorvt]oa^S[VQU8F1H'HBD'F0M,K9XGZMgKc?e?\On,UiK`!Iw9iv.acSWLm,S[znz:_XKPF`Me!La$X_&NPMORJC_(TNz>ph,\XHMF\$Te+[WVYPi*ey9z=mgw?^YRg*WWO[#S`#]_'Ye,`v>nfvjv—t`qifaQvEr6pXNCzNf{ʇc:ah._q6]}8VvQk9@Üt(R[#Mw;XFSgJSMQH\MWE\ FaE]J\G^F]FZF\E^F^<_;l!Eo&Du%Dj DkAp@hA\CZBY9e?gCkBo*E]@Z@W7]?_>gCm$@fCY^=_8`>b>`>b6l:m;n;p!?i8hkCo@ru&>u$La=m<'?,B3G+>u9m8i2m3u.{=$;'?)=-=7>=E5=AB:BIJJPRUTQY`WW[`XcVbXYbmdkahgkblabagpwlmussrs|vzssuy}z|v} {䆄㑓卋瑉㐒捐艇切憁挅玎琈摇叇䉉劋抌璒瓐掊䓖铎撉ށ~܀ltuyz|~{zvpuKHy8R 6S ;ZCg;4Br#FY@QBPASH\A[DWETJWDYDc B\Ib Es%?i*Kp$Am%?p'?m<\;b;b90Hm;_6mCb>`:t>nI1GHTitQc2F/N,C/B[n.@i9.d?Z?a8\:^>[9^J`Ib9k>&D8I7I9J=MAR?QCRALEWLO[\]Ydaj]i\ncxlljuz{阁|띀oxtou{xqx}upqjt_o_dXa]NO>K3G'E'E$D(G2M3N>WB`FZC^Fs7`|0Uz.Uh"Md$Pt+\l-[`RWMp1Tgpz;bSKSNc(Sa'Rc(R^LMKSLTQ^,X|Fh;no*]RISN[Nf%T]WSMc!\s8xEpn|?l}PyOi.d]!UWN_Y]_VQi3pu@o\v{ywU`oqrfSNObWZtcrMjCtv4^s1OhqAXf-O~DM{c>hDo$Fl @^=^A_!I_F_:_>r#Bi=a?]:a@_9g;c?bAcAi#Bm?i=v(Fs@i>n:l=o=k@q;kAn >rBn!?j;n=s*Er&?v'Bh?d>r =3K-@0@z#Fj:g9c6h3n1t-~/ 8):/<6=1:1;7A8CCIKNQRO^RWUbZfad___bcjencicihhipcnjoolovorquqvxyrty|{zxက烀掍瑖㚗卉挋䔐拊拋捍ꐊ苈猋挋ፊ劆與掎镑䗋杘皑搋܋܄ڀnst|{vՀ{xxjk5?qBO?\>Z=n;-HeCWEWHTG]$I[H[ISHWLWB\Ke'Q\F` Dn&El&Ev1Le!_;aBbAg BaBZ?Z 8V;];]ChC]@bOl)Ix$F5J1F;J@KDTBMDOCQCMMOV\b\jeg\jfqovmހkmwwy{훃qw雀q똀|yzz{~}spmrjx\n]aZTQON9G-D$?BB'G/L1J;WNfFUYq]}=YeJfJcMaLe!Qa O] VQKq9^scz>iYIOH_%NYCe&U` ORJVNUL_%Ts7bv6dj+\UKOERId([_ULK_%^s4sHv|N~\gu7r]LQHa-^e&g\Yd&io;ys>uYd|sbZXp|sb[Xow\mywp7U6QTK{u5TWj_r{3R\ K]#H^%Lx3Rw1Gi"MTKT!MVGYE]K^Bp(GpB_C^AWA]JVDY H_FbBk!Cy'Es%Gt&Av'Aq#HeAZD[^AaDd@`Bm:qAe:Y9Z:^=c=d<\:`=h"Dni9p9z)@p'Fv*En?e:r?0A|&>.Fz:l7c:c2ab=j!=j =pBa 9c>cAc9sAnB0DNX_cNa";4S8I4DVo-D8L5M&=9C6I.G-D1G#Af7>R:U~)EpCu+LZD}*Rkנآؔ؇{ىxևx֕}sun}ʁrȅyȆ{ˋyȇwɇʍˉ}ʋ{ɍƃvNjwć~v{tLJwdžÄÇ~„}}xy|ƈw}}Ã{~z~~t~}v~x{|xr}~wruu{~yrutytwtrqlphefl\gakjutzΕ{寊ĒΜԦܩکݶ۲֦֡ӝЛϔ˙ΚɕϖϠ͛ϟѡѧϥУѣѩѫҪѧѣЩУ΢̜ˑʗ̚ɜęƑęȔƓŕőĖÒĎÖÑÌ豇襆s_@_@\<\;_;bIcE^CZB^CZC^BXAW>Y>[Dp$FqC.C1G5KBM?MDQGRENEQRXY_eeg]mhphogtj߁pp|r~xw|v}ꝁ|윆w{~{|x{zrupjyejYaX[TGM8G-I+H#B!H'E+F1H8U@XHX^pOjpF`FaN^GeLc#R\SQMWMq8apXxLuk)POF]L`#Kh)Vk+\]#RSNRFa Q{?gp-]l'[[MMASLf&UVOQQPK`"bNp^lw}?uaOXQ_!Rk-if$c`)]vDyHyEUZpkfmowr]X[^k[rzwJ0NOvOw?^bqis7UX"LZ!Ki-Rx/IeAY GXFY$OSEV@_I_ Jc FgH^$J[G[GXA[DYD[?f>j<{"@rCw=v$Ar%E_?ZCT>YX>]>b?b>mEi#@p#Dm!Ee;m@u)Bf>c?c>mFv"BoBiCj9s%Bx,Jn!ClBa>l70Dz&E+C&By&Aj7_=e:`6`.k=w95;"8/=1?2?3>8AGOGMLRSYWXUVT_W]Y^`h\]bicicbgodmckfjolwwqwiqrxqnyzv{y}vyvw|掉⌉䉄儁舉掍拌授攍擑搑琐抄䋍珇琐獌䑒吊㐒勁ހ܁qzsyur{ynljmRK0?e ;O 9X>`s(E~4Gc Ba;i9a=i=l?a>h>f>e;lCd;u@{ C/DPW_gNZ)=+F/D0BYf(<1J'C":4B;P1F*>/H,Go;(J=N+GfBoKUFx*Jq|؝֠ӑٍz؅t։ՕztxqwɃxȅvÉyĊ|ƃxŋ{̏zɋzĈ}ō|ćÅx„|ɇŅɂ|ÆÇ|~~Ƈw‰~~…xzƒ}{}||yy{}xq}|z{wvvtwpuxysuxumywtvsulromilhffj]kcldhso֕y괍ƓΞժ߬۰ۮݭ֨ԣѥКΠ͛͘˙С͘ΠϞНҡӢѣөѫӧԩЫЦϡϞϣʚəȔȗƙÓǗƖșȗĖ’ヘ'︉찄遲榁zޖt݌`vV]D]D]?\D`HaCdA[BYD[>^BZ=\BZ?\>\8g>m>y(D0G8I8NCLBTFOJWRSWba^ddg`h_gbtkym߄pnuu}{|{뚁햃}wq{|}y~|~rxlsxcl]eXY[LP7I+E&DwB~ D|$F,N/L9N?YTn\e5Jb$IZHZC_EcJ\Gb#ZTPQHzEqmFhNsz-WTLXKb Od$Nn0Xm'Z[KXIg.]y:ii'[i.aWMJ ASG]PVKPPDJZ&]DqhrvSgSUM[Rm.hq+tc*^xKVvAw[YX]dqxz~_T]f^hpuuqEh7e<[w4XN^X`@Yf+Sa&Oq-Ri#IU KZ-VZ#LVLWJUE[DY@_B\A[C\A[CV?VDWEYBkCj"Dw%ApAv%={&Dq!=bC_;V?T?e?b<+@q'C]A_b:gE]7b5e?a;h@n&Am%?nBc:j;o =g!=d;d;`?oc=e>[;\3^ 5d 1p5x7~ ;?#?/D.D:H@IGGMKRTMRQXQ]OUQWZ_[_Yaap`b`f^khrgjpmlltwsuuxtox{q{z{ttz}}ႄ~䉉揌勊吐唓甍皗ꌌ唉捎䌄勆玅猅勌⎄⅃ތ}}فs|r{wv|utyg_NR.G_=Q^:v"GiEYMXFZ#OZ(R_(P_MY%RX"MX%S^IZJa#KaF["Lm$>q&D;Pp(Jc=auE+J4BN^^jKU5E/K4F1JS`+C3O-B-A.A=S1D1G>J'Cl9/B>V&DjDkG\Cs'NntԜښՌxنx؅uڍ֑~wvƂŀv€rŁrÃzĆxDžxȈwƆ}|ƅć{Ĉā{ƒ{{ƃĈăwÉ}}|Â|ĉyňx{~w~x~~wz{x~{|}}zzy{ws{vvxwxysrvqxpulokljodjaqaigp}}ע췋ǐОԡتۮڮٯ֦өўΜΚ˘͓˛ПΙϟҚϤѣҦѢѤӦӦϭОЧΟΥʝəʟɞŖƝǐǒƜȚĕϑ츄볊걌twr{ًhzZgMWFD@`D`D_B[A_;^@_@[;Z;Z8^>X>\9]!?` F[AcAi:t@0J5E8K>LH[CTGTO_Ycb`giaWfflhsgzs}yrt{x쓀隂wxv闀|x}|훃|}~}stozcnZi]WYJO9I1E @w@{B~'G~%D!H7JLdcEYr*Sf%G]E\A]G[HWJh*_bTY#KRTl:[Fiv&UYGULc'Wd%Pl.Ts.beRXFp2fs.Zf+Vh,[WLLFPGaSVPONIUMJm4fxsi~`w2l]!XUKs5px8{m2qni>iD^?[>^:^=h?c:]?_=]9b=l>k$>m @j=i?n#Bk&Am-Gi Cb=i>k#Em#Gk#En!At+Mk@jDbAj#H}/I5P~*C,E,Gz Aq"FjGAACNALHSLTLUVTZg]gY^^lcgap]iblimglghmrkkqstpqzqzqtyuy~~~~⊍捌狇珇戈揊蔃畒戌}䊄㉁劆持㋉Ⴤ߁{zsuyvstqp{`RKU7I\EWE]K^Ds'Le IXLXJY$O]&P]'QX!MY&OX%RY)U^!H["M_ Ie"IUGf?x,F~5Nk#BdBcDhDp(F_@a=c>jDiGlGg@iA~'I;PK\Z`Ma4KY@_<[=T :X;Vby(WaMVL`!Mg+Wf Pm%Tn)[f)Vo.]m*Sh0\h*Z[JMBIEZ"LWRWSGPMR`*WtƜvglA{i"_`Vh.azH}v3rk3nr;qz?v}EzeUzHoY|EZvjf]eyѨBwg0ao;\WZyYfdyB\[#MM MQIPIW"LPFUGVHXH^JYC_B_EYF_!LZ IXJ\#LaMhKk$Is'Is)Lw/K6Lt%IeFb CXDWEc Di!B~.Hn%G_ E[>]C[De'La?h!Ee Ej#Dd#HWE]CaC`?eCbGaDdBaDg>h"?pBj Gl&En#Cp)Fn)EhBo>hAo>s?r!AkFr$Ej@j@fBf

'6:D2D:E5@7D>EGGOMRWMOPZXbU]P`ci]a\kdlcgadikptjipyuwt|wpxwx|z~茌䉉獊狇匌鏐揊凇ႃ၂䁀}{݄߆z}tzp|owpqquno^VHS6G^BYBT?cEn'Kb#O\*PY/WX&P\ G\'P\*PWLU&N](N[F` Hc(Rf"L]Hk(G=Uy0Kf Fc"H^@g#Et1N]Cf?i#Hc>h?_?_=p EyD9JHSWeN]-CWl@v @-J6EBSCPGRMWLZRQYYba_\ngmh{mvq}xr~x蘃떁yvꘁ꓀}~w~uwvnyht[pd`UXSDM:H2J~&Dp@kHz"H,KIa[zhCf:fu-O?eNr\GOGPIPIh,Z|6_HpUx4Wh&N{3Zy5[i%R]Ia!Pj'Yl/\a$Qj$Pl(Uz>ih$R`!Mm,`YKMAODZ!OXO]#ZK KCPPJjƝxe|s?mj'^\!Sd)[u9jr4qi0gj-bd(h{>sXdUo[{C{G~Sywv]\hmgy̏Ó\\eua~_mnUse-QMILMNINHPIUJV!L[)P[KYEYG\GZGdEXEUDbEhDk?m@z+Cz%F6H4Ip@]?V@\@Z?c>n&D}3Gp#C]BdF^B]GbA`@mCc>fBiCaE\@c>aBgA_i@s#Cr=m"Di?hCg?l#Dr%Ct'EnAx(Hm&ElGaAjFl?y#F5K,F(B*D&GxAz9r=q De9m<`6n7n9{:~<}6"?':%@'9';#8!6$=*;4BM*Dt:0B@K*NrGj!OZBYAZ>Y:U>T;T;Z?X7ZD_@]@`A[7^?Wc?kAu='A;GCLHPBNDP>LIRRXak`_lepn|j~xyuxvz|z{x喂}ꕃ럁z{w{}zwu{js}mt^k]^WVQJK]>^=\=]>\8_=g@h Cl"@k?_;^>^;[:e?a=X?Z9b@bBc@gAh?hAj?m&Ft"?l El%FnCq&Cu0Ov+Fs&Ho*Gt'Fs&Id?k"Cq#Fr#C1G}-G+@0D0E*B|=t >}9s#?~&Ct =u?v%> =w 7z3&={6763"A)B*=1D0@=G8DAK=PERKSK`\e[nWXW`^jcggqlsjpozmqu~{~wrnvwswvvw|㇋䆇䉂~⋉ᄆz{{{xurz}xu}w|xwxpnmvqzqhegnbhTNN8D*C[BYCRS@Y?Y?[CZ7Z<\:[@\;X9`?[8U=]AQ9LCRAQDP?R;LENTXYYc_jck^yfyrvqtu씃{}}}|镃w|x|x|sqjjucm[_WLJEI9K!AoEq&O+[Pv{âؿ϶|s:mInZ|at[BPHNBODXIt,V6[~>dv/Pj"Se"Kl Nk)Wh Fi"OhQ\K_ Nj0Ut0Zg"OVCVDd(V]ISENDYEUIZPS KC PHGxR{i}Bw4pz6zOKyu7wg(a]`e(d}Gxas_Vv8oq5j~Sx\uEYpv~~{yoõưsm9WO#NT"PLNMKOHPKVIV!MZ"PXFZH]"N]#NZF\ J\H[C|#G,M,C~(H7L1HhC]@S=P?U>Y\=dDkCiAbAZ=_>dCc?f>Z=`Af@_8c?cg>l?o!=q%@v(Ew%EkBr(Hu/Ip"B{,It#Fv*Gs%EmBg,F)H%@3Ds;x >w">">{?#>~#?~(E%B*F/J3PCX;N5SAVAYAVGT9ZFYOYNhVcWhQ]RX[e^b_c\gaoanc}httqtznus~utt{|ᇅ䋏ㆂ⃎yyu{vwm{z~y{stuskphnbbinebh^p[^TKR=Pt$D[$NXG]G` H[JZJ]NY'QY"LV$MU$NWN]#NTHa*Q`K\Ia Lc"F]EcH{5Nm&Bb?` ?mAg?a<\_;^<_p(Is$Cu!F7J@YZcUg5G5QT1J>R,H?S3Ju9f?]5X5U4V5U9T5T;Y7Y=]=YAYA[?\=`=h%P^A^<[>W:Y;Y:\CU6T;U 7\ ;]=h7x#=)@-F;JITFS;G?ODOJR[UaVfei[un{vlntn~s똄y엃{ts|{v|y}ojqq_g_XPOO@G2H%Jo O0R[αѓm5ZF{?]r̕I`^HLBOJPMWDi&P~8iy5Z|Eoh)SaKeDk"Ir0[e'Sj%QcQf)Pq-\s.]\D[HYK_M]KO@MIYMRD[RNNOYTTqLxs~gM~N\H{r3jh)fZ![a!YISxw`w8qb$]rAvY_~T[atypzcj[f3\V+QR"OX"OSLX!LUKS LVGXIXI\HYHX?VI_JbCx'F8N8Tz)C9N8Jj@^;XKS;WAY8r$@1Ep!@\G_9]=` >`AX>[=a=h Ae@eCX<\=a>co%Bl!Co!s'Eh;d9h;iAn#=(A$<1E9I=G*A!:{"=|#F}?&?+E9X?VAY<^CZI_E^AWHpLaNeRmQi[pUiYsXoTmVmXnZuVocxgu`xSjYff}j|hef~{}yx݅݃߀߂߆₁㊌␓㎓⌎ቍᅒわዛ߈|vl}ohvl~jpmlle^XOUDOo)HXCX>W@Z#H]HY#S]&N^!M\1XX%J]*Z\3UWG[$S^!Ff+Q\&N]"KXD_La$R~8Qt3Qf Fa#Ih Gj!G]?[Cj&D^"E`B`:fAy(Ej@w$I4HCZ\hN`/I`=a@`@`@\:^=`A\S 9U :b;j7z#>,A.?9FBL@P:KAL=NERRT]Zf]qhp_yunzzzuy~w뜁xrq~zty럄wwv|ympfqeh]VNLL:L1P(Q8b^“н͓e6H-Y+\}+Hi|Ie\LLGKEQ DLA`#Ox1]FtClj-Q^H]AfIp.Tl,SfM`Mg"Qq1\l'Pe#OS?[E`IVFOBQCXFSEXJMHI PPDnHxtul{Zw;bzAs{=lu4om*k^[]+c}Cpc~fk(gc)cs>{}VqpQm9qzO|ld}7kk0YJnXmtzYw=l])OWISELENAR@QCREVFXF[DUFWF_J_Bu&H7J1G{,C>K1IgD[@R8T?T ;Z@w,G-Ci>cD`AbC_=d>[?Y>aDe?jAj!D`BY=bAa9e?jF^=]b@b@_?hAh?h#Cj!Do*Fl"Ck*Jl$Hi ?n(Ds#Ch>o"@m!Cl!Ae!Dk=i>n'F(:-C6G5B2D)>%@-C*B2K6K>MQcP\N\L_OaM\TfYherZfYegvfpgpepx}pltfqksfolpkhnrsiyimvzwvy}ryxُۏ܀~܃ދߊ߄~≁߄y݌ᎆ␎ߔݒܔޔ✙ޘ♘ߘڗיьЇΎˋ̑Ґ؇}kTf{1Ic.Ke)E\)BU$JW!G\ HZ!LY)S_/T]%M['T^'NW&JZ!K\H_%L]#O_M[F`"Fe Gq(Dn'Ga@^!Cl'Kf>];T>h!@\<`A^:c@|.Dg?qC3ICO[g\j9K5NCQ1N,K.Kv#I|1]k!KFf‚ݪܞtZڈwчtgmpceVWik\bW\SST]YaZ[\[akejcacldbeffikszsjmksijoupuvvxutx~xtwzxx{x{xzÄ{~x|y~z|x~}wyxyv~uxvvusrtputmqsprjljsfn_i`d`m\hrpіⲉʗҡժרأԟҞϚ̐ʘ̖͘Ο˓͙ɛ̡̚ʜɗȝ˞˙ȘʘʗƐɑ˗ƒė鴉魋|䝀ޖr؉ts\]NED2>t"1E?I9BRPR\[d_qiqd{mlxxzwzzyyum}r{}윁{|}pli|gskbZXQLV>X4W=fgšƍb7Nz)SsUtT4Uz)P^CLGMEK?NEYGs3`Mk}8ep*Rg(Uc Ne!So&On-Vh(Td Hm,Zr2UdJ_HWJc KaPZJOEMFWDPEVKUQMRSHvJ~iu`sRr3`n0]|;jw7ho1l`#W]Z_\o0aJohmTk)ge*n|Fbp{?l0h~UxmG]Mm.X}3^:]Zu~oM~g*NM>J?JGK :RBQEQ>W?[J\IW@]?f?wB1M&A~(D=O4LgBW=M :R=N=]Dt @})Ah HZC[?W=cDZ?\A]CaBc=cAb>a9U>a?^=cBc=b<[=a=jBf@a:ZAe;g ?m$An"@n#FbAj:d;o?l>mDl$Bo!Dm=j:c:f8j3s ;'$=-A-D5E:K-B;ODPCNJVFTQTQ[VgSZ`iadchajadgncjenlvvosurnjdomkphhlsllrurujlosqqtoqz~߀|~y܆݂}އۈ݀w݄߄݁~ނމۉ{ᎆފߎ~⏅㔑┉␈♎ߞ࡛ާߧްخЭƦr^Ni{;Zi1OV*MT FU'N[+U[-PS!IWIY#O[&PW!MYHY F[$M` N\FbKk!@m#Go(McCeCd@^B]?[E`"EcEdA_:a"?0InBnB7L@QS_Uf6I6I3Md:t;p@ua@a@e$Bh&JaDhZ;X :S >T=R 5S:V@XO ;Q:ZA\?z2K4Cf<^?_B[:_Bc9\;^?e=c@dAh>fCZ>Y;a;^;a9f=Z@[9^;eCd9cDb@e DgBh Cn"AmAk;i;t$Dz&?fAi?h;f8i;e6c8e6o6/G{)F'C4D=M:E3I9KGPK`IOMZNZXaT`Yc^\ad\W`h_h_\bfefchsqojkljkkgfflljnjkopompljnjhmtjrkqy{zw|z~{݀{݅~w~}w{|xxxzwۃ܂}ۃ|܁يۄ݃{݈ލ{ߋ⒊㗓妖棙窢鮛괚鸥軣ݸ˰~^zGic2P_.OT$MU(KR IX"PW"KSJ[!H[+OZ!O\F_C\K^Cj"Kk=k%Bi%J_;`E]DU=Q=Z;eFeA`9aAz0Mr"CoI3J>L[jUa8Q8Q6I=PLW5K?W/L7N7O;I5RDUEV0L/J,F3M*F'Pq Nu)MLbΉ١шwu[܎ӂyjgdlYcIO`[[[Z`NUKWR`VWQUSYW^W]`bbbY[aa`cabbrVX`ieldmejgjimglkslppvssrox~uyuq|r|}zx|yvzux{~~{x|}{yvw|{wv}vstnmtnknohohpeifk[f^hglxݨ붎ÔΙҡբՠաѠ˔˔Ȗʑʘ͛˓ʗɕ˚ќ˚ʘȕȔǙȖɓȏɓř’ŏᅨ굄譑{ޝzڗ{чqtj]TIO5Hs;a9^>W?XETEP>N;W'LT 2^3a9j8v#:(C|)A~$>|)EiFiFaBhBdDi!Bi!Ge?_@Z<]>T=V=U;S;N:Y;V:b;y;~'?);-@5H0F1@,D4GCOWYa]jak^sfwn~ovvr蔅u}{u~w~~yw~r햁wtvqesbj]ehRaTpNqxͣбʊV2Dv+BbShy-]j"Ez4KwlK_n5X_FNB\!GIANFNzUsNyv?yvAk7qevƧ}`Iu-^UHTN}ZAN_De$Fh=i=_=\@dAa@\^;_@cF]w.Kv"B.H?MSbTi:S6Q8QG]J\5NA[4K/M6O-B0JBMAK*E%A3I2L} @-Nm"Jv!HTd̈y١φq|cۇ{a[hhUVNV\cYWe[W`HSXhRZTVPXYdZbVZUcXY[b^e_fZdXa_k^a_i_f_c`chqgjlkghgglxjhqqqrvsxvqwwtrv{uzyvwwz}xwxzw{y{yvxtzqqtnlixhngngphrZfckhoό~ݪ켑ɛΤԟӢզќϙɕȑƌʖɒʗ̔ɖ̞˔Рʚɛˣɘ˞ǗȒȞŐĔƒÑ뼏寋妊ߝےvӉ|kkcW\=Hz%Bh:^9V?P;Q 9O~$>*;0B-A2I*C3ECPTT``gdjZpd{jހxrw菁yxx薂疀~tu阅{{螉{Ꞃ}|ynrhtfjdjm_{]yŅݬ͝ˌ[1Er$Ikc"MYIRE^LYC\V\TWOd$^Xqwho[J}{r|Fsj3^g0]`)WQIOIONa"Zs9mglO[_Wt>|o;wzJ`mqaU_wpAs1ahWl(O{AbȚȟӥãa]+VGIQILNRHTCWFTBfE_@lCw(L{(E4I=K5Iz"?cEaEOEZFS`?^A^?a?cC^>cD]=cA^<`Ac!Dn?kDg!=s!Aj=h;lg:h Ba7b6g>b:a5w$>'B-;3K1G5DBOFLFSNZNSU\[fag`l_d[]_feiY`V_`_^e`\b`cfacfjfef_daltcgjdiiimounpmknsutwru{{xts{x|܀}|zxvxp}x{rutxzunyrwsyx{w{zۂۆۈޓߕ⚎䤋⢌᫛紣賤鳡鸦컡鿧ݼ˰{W}l8XV.MW(KSJS)LU"KY&OZD[EU@eFbAl@` @e^=_9gB_?h98Xv#F4I>NQ[[n6R.J:K:X?L3LMg*H8N2L(E2N?K?V,G,E0F5P|#@+Ou.Xs#LWdՎܢ҃nۂnي{ubbbf\`MY_iSU_^baT]HTU[TRX^[dT_PY]fW\S[YbY\WhYeZb\aadYb^k`b]d\i\a`ifmfnfioshhmwinpmpurmu{vttxtsywzw{r|ut{}sqrlrukonnlwmphqbsal\i^ohj͊uਇマȒ̛КԚӦК͛ɑƍȎȖȋǒȘɚ̟̝ʓɘȚɚțȕǚʓÍĎēwᅳ跍뵏㭍⡌ڝ׏|uobYVCJ~(Dk;b;YGO9Q 7P 6W7[ 8]>a;j!>p F~)@)D/H3E,D3N,Fk@k@l&Hm)Fl#Dv'Ae@fCf>c;_B]<^>XBY?R :T dBi#Co$Fs&Hu$Gf!EoCh#Cu%DiCa@e AgAh?hGeAiCr B,F4H5I1B5H;L=ON_SWTZSYU_^f__be`jXb]k\_X[^f`b]_aj^\dgdcgcegejfmhhkmfhgiirksoqmororoxxuvtox~tqxp{qntu{yuurpuxtrsvtpz}yyztzwڌ׊އޕᕆߞ⡎⦏䭠紛渣綧缧궢뼧뽨뿤¬ĴὫй}cuDdb9_X.NW0UW(PVMZ!L_&L]LbJcJf%Mb"L`J\CVGTGZIVF`'PYIf#LfFk%G>^5P9O@TNV]m:X~+L5K5P?K:XK_1L9Q6R0M4NDU?R/I3K4L:S}+Q|2Yl#Tt+QUjԙ֜yk؂qՁs|}e``dcl\dgrZd`ckpjpbgWaV`XbX`S_Q\_c[aY]YdT`U[[bWdV]W`WeU_Y`Y`]f]l_a_k`ddjinbeellnkmipkpmphppwwtouvzqurqtxtysxrutvs|omiwkqhogu`jcu_pkqГ}ⲉʘΔџқљΘʑŏőȑƏƑȔǐĖ˙ʛɟʝʚʛəʜɚŕŏ﷎칐鵈겊婉ࡋژ~эxyu`]EK/Gn'HfB\BWCW=U=\BZ>eDh?o#Ds"B~(B3I8G5I;K6J1K,Co'Fo'Fo%Is-Ns2Oq(Kj*Ni DiHf@f>g@a>^@X?R 7V9T6`;ky"E2S=_w/_XH[A@\^rfEO=I=I@L@I ?G=N Db!K;bBm@g{/Xu*Sp+VaJg$Mf'Wm-Ug%RZHa LcUgSh-PbAoj%O_%Sd#PX=a!V_LXMd"]m*dv?tV}snslPY~vxcp5iOIKLTO^$YwGzyBq\pq]c*_o8mzNQu>yxAyL~OerrYz9_RqZE{w2l[Pp5ZUmuquRNGICPDTDNDXC_Ij;r3`s(E~)E1HGN3IpEbCZBQ?Y?^Ia Ds%D9PbDfLdEYDa&NbFc@]J]E\?Y>dCb=h FfIe B`Fe=]@gE]A`Hf"Hh%HiFc C^=bAi!Bp#Io#Gs'Gl.NiEl?j?lDa>g@m%@gAd=e=f?n"Q/P.N1L6S3W9_o'T}-Q\jأؗ{h؄n}tqpih^ahoZ_opgoddeblnchZfY[ah`mW^X[X^Y]ZbRUXfT_WYUdYdU[VcOZVaSaUbPZWaU`V^adWeZ]algm_fdgblajipescjcihsmopsosqnqxnmowmpjqhpkrivgn`jbq]ljtєu⮉ŕ˕ӟҞњΐȎNjÒƌÎǎǖȑʛ̡̚ȔțǛ˚ɘʜ˖țgﶊ갌氉嫅㟈֋i~t^\NX.CoB_:_=W 5Y>[?Y=`qEw!={%A,B/G8M-F9J1J.E.G0I0Iu)G|-Kn#Go%@q)Mp!Ek"Ee>h Ge@dF_I\HT@[KXDf@iB}%A~'E$A}$>%>#;'>,BAPCNNT^baXi^odyony|v~uz}zwxz옆xv욀~ri㇀}y|ـٗåܑlNJ/Hw&Mp!G7WBf|/Tl!X^Rp(QrTmXKIDNMNJOIKEKIPH^Mx1]Pp@e~3]jG_H`F]Hr0\q1^^G_ Q`S`WiPd+PZSw5ch#XhRZJ^!W`SUM^Uk2hf,gj6bVoqy_yCu~M{p_s:q;p=}w>{x;H[uwv@km5rc,hg2d|XXv@wt;w|D~Rm|zWm0[q3\q-ZK~H{9gbuax_itĤ~p;eKFIDPEW!PZBaGm%Hs!It)Qz%K0J>P.Km!Cc!H^ISBTCVCb Fr.K=Sj(Oj'KbFZ?\"Hf$K^ A\@Z>`BU=`EeFh Dj'J]A_?`=^?d Fa@`?dBeEd>c>^Ae=d CiDl(Dm!Dh!Ag@mCk"Jp%@g!Bd?h@g#Ce?h9k>v>-B4I8I:K5J=MGSQdPXSZ[^WV^^]f\Z_c^eW`Y^_c_d_fac`ibeeracbckucblpfmlhovjrijeldljmpzokvyvuuquuuvqoonoruznksrqrstmpptptwtvtwv}}݁rۈߒ㘊⚊ត⢇㫖⫕䰚洞幣滤滠麦輥辦꾧é꾫íٻfKpd4QX,MS#HTFYGZDTGZDd%G^EUT-P@S6MGY6K:Y*H2O2L.@;MDR6F.O&D&>9Y=X2ZmK}-Mhq٪Օyj؃e{vonifYfdib_uqikkklgpiih\_^[cg`abaZ^Y[Y]YaSVR[W_VaNYR`OZM[N\T^Q^U^R\S^WcPUU`NXOXT_[_X`]gYb^c_j[fco`bbhikim`ielikhifuegivbnbdhkai^kZa]plsԒt㮅ŏ˘ϔϘ̗ʑƍőđËÐƑʐȖɚỤ̌ɝɗʜ̚ə˒ɜȔ”캏鳌鱆檇⤃ៅݓwՉyxciiKN8Nn8c8[6Z6U 6a>a8gDk"GoEr@z%C2E4I1E4O=PXFn2TBj?i3^o!QUDU;]Fl.Xh$IWA^KaF\"VfPn+PgQ|:gu,]o&Vf%Up6cg(VaO_Sb&X[U] \g2]^rvjLv8v|Gquvehcejdp{Iol1at9{o6zn8vrArhXwAJwF}Wpl}=vh*ge%W{Kv]ct~`_>b{F\ěne7[S)SNDND]CbLdEsCnDw$B-D5M&BeA[d"E1NESo#F_A]>[?\Ag IaA`CZCc>YCYhEl"HcA]@\@dDa GdAbCbBb>idEi$Ak$?h"Cj Aj@k Dp?p ?l!CdBe>gDj?c:h:m7&C+B6H:NX0EFWaoAS(I0J1M@Y6L:U.N.J5Pz(E6JAU5O2L(Iz$F5RC_}0QjG|0Oquݧӑoրl{qlkgeahmsjesmmpmilmnfutmhhggfbaghfgab`jejZ_W]X]VbIZNUTcSYLWLZV\T\IRQXR[NVRbR]KZU_S_[bZhX[cfaj_h_aZd_bX^`g^a]ddnaj^j_gglfsZe\hZcXf[m^kefӒ䱄ĒȍМ͑ˑǏ‰ŊĉǐÍƏǖȖ˗ʝʙ̚ɗȗʛʛ̗ɟƙŘﺌ캋챈謄妀}ޑyinUVLGG+Bm9Z2]7T 5]5_T?N.Mx'Cx,Fw'Eo$@i>i>h@a@^;^>hAi7x'@}(@|"<{&@w8p9s>v!:#>,E6DIOPW]UcYqfwk}qysp镂vz}|zty葃p|ꒆ菇䑐撜曚뷓݁g^^LU9I$E?u$Jy#H}/]:ls"MFl|ϘikcFR >C =J@J ;I?OFL@K?RDYBs-R=i}4^w0W]BT@b!Mf'NhRUDVHaQ[HdRl4TW}[Q6ghQkPm+_n)Xc%Nc&Yd%_NCOOTLo9by}p]C}}CzY~c]bzx~Yb([e*fsaA`:c@]?^@]7^n;}*E/B9T8L:L;DFMT\S`NWW_VWX]S\Z_^_]e]\\aZXZh[_V`ZbY`dgclafju^flqmhiqelgfifonhphamsmiroqrmrnmppijmlsmoshikfnrnsrrrxpssn|y{w{t߇{ᙃ㣍㣓㨗孕峝贠绠溣绝黝뾥轟꿫켠꿡©ǪĴʰfLef,KT;M=T?ZM4I ;J:Q9L 9Y6i>k C}%DN^m?Y~+I8K0ME[1I>S,H3L8Q}%EkCt:w#B{;CMPSN^Uhaqh~ivvuwuyw}}vo}oz|x웆훐ꙛ硦譯歊䡆q|k`cUTKU6K,O~#E})Pz%HB{H_:_tlnd Lz3`=a;ep#ZX;o/]z=kU:L ue%_g/lr8nQU{Fp2ovAp_cZOU[cLLKbkԾƻd|kCub!Zc,H{@gTIQ>\F_>jFl:kB}#D/G;L/GfD^SHYFg?X=T?^;g9iDj=c?aB]?\_?bB^>aAaA`DeMi$Ft'Kn%Du.GhAk!AmCx#Ch>c?f>kAk!CbR;T;M9L 6K?K7L 7Q 6S8m>c=x&C7C0N0E6L_kGW%E.H6NAT2J})F&B+C7J5I3D3F1G5P9K;M8F?Sppk~fr\lXmOh?PODQAWEXDXMg#Tx.SDn4eq3Y|Cqy=aO 9E;L=SAaK]Qf"R~:fYOtE{y8bv1fu1fs,Vg#PtGtt>lNDIB@>WWg3VshwdIo/eXM`&Ue.Tn8b}?vo0Zx@ij4Xh1fwHy?xE~xLZK|@~}I|Owr\^VeXPYeh[sŦ֪bwF]9TEoy2ck&aj2NpnhUCRA[?b?pGq#Em!H}(D)A=Q|,GbA[=THPAU>Y@h >;IASo%F_?]BY=dBfC^=^CW;_?VGT?c7p"Dj%Je>d=c<`:]CcA[?^?\<]A]?dKGWLRU]]^Z_QXY_X_U[[[XY[dabZ]\i\^^i\jT`eo_b`lkkggmifchqhfdedliogmlqinjmr|mlhmirnxklmnjlihnxjmsnpjprpnxqvo~y~u݄~ފ}▁ᘌ㙊䣍樔篞诟谝鴟浟踟賣꺡껫麢뻟뿣뾨꿥í￧«çĮǬȪīXk5OV=H?I8L9K?J :L 5J 8T:j9d;y'G3I*PH_W4L1H1Kx(D6B7K)G*Az$@3K%@pB5`b@BZr{ߣՄo҃zqd}sqtfiw|tqvkuzsrqlxzsmsjzluzndmhnpg`fjnlfhinlrgkdj`i[a\fclY_W_ScSWDSNYOULRJWFUHTJQO]EXEVEOEZMXJZIXHSMaETJ]McFSKXVcV`V^Y]YfNVDYDT@W:S?X_g̈́lޜ|쵄ȔˎȚƎÄŊ‹ÍŏǐǘțǘǠš̜ɚșȔʘǑĔĒÒ殉ࣅۙzЅimeEK)s Dt%A'D'@|!>x=u5mJ =J9L@L=P=J:N=P >W@WCSHVCi)S=hJrIu\s7]M8G8F ;VBZJ`YeRw3abWJy;ku4ew1ao(Ru:jYi+XN >H EF>P L^ Tn8\ursjdQs@zk3jo5fxis3R{6jw3om7VY`J]CYAgBmBhDh;x!B1J?Rx#EdA\@Y=M9R 8Z>g!A6DGQm cCVHWEa;h@l#EeDg@g@c#E^Ab?^@[@]?\<]?g$Fd ^;g=i<+?1E5J>O9CJTINLSQUQ\R[V_]Z\_WWVV\a[]T\YaZk]aY]`iae^cagdlhhfalka_gfcicgheghmkfjnnkkgfnstsvnqhklijlmfnovonhqlvywqsq}~ރ|vߖះ䦊婑㯒孔沚紖沓浡絝帛긙귤긚깝쿨ᆲ鿡쿦íūƮɭɲ|IkS&DJ">M>F9G~,N/H.JC[:IVhOey&G6R~1I@O|1I:P.L0J/Ey$D3J7G.C-D&C)D-Ht%H5WaFB[{zܞm|x}t}psji}zuxqwtuqsqtjumxrsj{wrmoisurupnmoohhrfdijnwaegc`l^afmTaT]YbQYNZV`PYRZGRIWHSFVGUGSGSDPKUGTGVMW?SDWHSNcESO[WZRZ[^W]ORLUCS=S2I1I>XRRyuߞt궆ƓɛɖƈƍʼnÇÌŖȓȞʜ˝ɜǠƘȝʗŚȔƗ–굍䦑ܕy΋qtlOO0Ef8[ 2_=_;d:m?w&@z@~#>z&=)G(B&A+F~2F2F4J0B8I7H5C5M2F;I5K3F4H6Mttrs|pk|ktfsVkI\BT:R>K7Nz-Gy%Ew(Dx"?3K/Gx;w#;vO;M>J?L8S@Y>ODPINE_Hx5ZFofcq/UG9A4G ;O ;RD`QjPm+XdcS9dt.e|4hy2[M|al'UL >F =F >K ESKZ"Ur>dd|rtdOyDuVCg'Y|CvnY}c%fWSqAmhnQRPUaRy=jvFtypj[`XYckSqzgAbQ}w'TcEy9uCp?V~?l`DgCiDfGkD$B'C6M{%AaC^9XGS?S UC`kAl?h?f;aI>F 9J =M 9hCa:4L*H}-I8K1F(D/H~,G3R1Tm I~.]fAG`uvۚԁzxhwqyzstnwɂ|v{w{xwtwrxqzsmf{ovorkqmnrorommnnsmnjjilgogojgeoan^b^eWcYoW]YfSbL]MZRaISHTGVERGU@OIYKVLX?P@TBYMW?SGUOZVV]cYWUWZZRTFQ6M1I~-N3OO]vm۟|촆ǏȍȒljÎĊƕƎʙ̜͜˛ɔƓɕƒƑŐƔ칋秇v׉oxb\W9Ep9[:W5`P6J?N?V;K:I7T||uwosxxn~^pXeUfJZ@V@T9M4O~,J~*E2J7N},Iy#@r:p?i@eAc8j8w$C/EYKcOj)QgmY}4et0i{2`w7^dgg.SRGMJPLK CLC[Sc$Vx@hms|gSM|D}yB|c~t-Yf*jg+rZ \sFqkoZMRagCm0^aa]gar{jizxze~6QfIXJk'KQI~QUlfIhAeEeChF~">-C7FsAg@ZCQ9O ;M :V;g#D>K2FkEbCb@_D`"Ff$D\C\]:hCq'Ay(I.F3H/E3J5M.I)D2I4H,H7K6G7G=N9J5JBN5J=L=PAW=P;P{{st|tsqizgr`uPbB`A\9P5M6P8Q8J/J-F&Bw=q>f6b@gBj:y!E.E9DELKOXSg^tc~izrtx璁q|y|qz~}w|w뙄wwtl|ku`pefa\cO`=]?\PtÍEeFZⵢ۹=FT8P=VLN>M=M=TGRASgv6[ZtueKP|pol-\b-^q7zc'l]'\p?gqmX\\hSw0is=jzÝfdsxv`ScOoXkN~aJ[Q\DAhnLm?c_C^CcElC*@)D4Li<`@Y>Y@O7L :U>k&?LVANo&DeE`DY?fDj"Ff$F`BX@a@V@W=Z;\Fk%KeEaAh!>p<]j3O^Aa>`A_BZA_>_EcCg?i FcCf!FiGq!Bi!Ft&E}*H1Lz'Ek@s'CkBiDcCb;q:u!E3K7FTK?Mk6_,D5CHSLKZYh[tk߀i|u玃u{wvvw|r~z}y뙀y}wutojydqbadQWOe]Wlyȏ3[Qe㴟ƌnHSCQFP?I:OAOAO;XBQ?N@PAVFTKN ]B\@Z<_@bCc@i=e?g>n$Iq#Ej"Dy+G~3I8N/HlCj?i@f Da?a?h@x)F:M6IVDOAP?R 5L :L>P=N9I BPI[LVgb\eV~?yn(dQMLKMOXZp2mZwau,Zh Sr.d~CsAou1Zc&Oa*^]OOCTLPIa$TP^Iwy3gl']_Va!Uh-dSWuyq}?kg'W]!U\"Xj.mk3es8vv5|c&fi,dzMzrkjc\QMaxlgovtIo0M[aM\cjv1^HCRNWGt6bXlmŽMqbJcAfDw"Cx@t"DfG]?PDRES@QB[>o#D?K5J{-Lj F`@^Dh!K_B\AhD]EcAZ@ZD[AZH\?j#JaIbCn&Im8Pm.M^B]D] IaBb#I\A`?g#Ck%Ji$J`@n*Iv%IjBv!E1I5L5Hy*Fh#FiB`Ac @aEiCs>5K4HHT>UHVJUMVPRQWOXW[TXTZY_X\^c\``dZa[``a\_[_[dceabdkehhhjnjlfjnlntkmlluugopnjmlnccjrhndlc`isvuttrrvyvpwx{u܀zބ}݆ގ~⒆ᘄព㜊⠊夌䪐㨌孚鱙沜毕毓岚箓糘豗赗蹟趟跥鶞鴗뽧꺠쿦¥êéDZƬƮɮDZɵʱεϯƮjt2LN@T>a=iF`?d?e G?TO]L]{,Lo$F}6N{,Ky.H6Oz$Fw%B5G})C3H6O{'C~'Cy+D(Jk:eMx*RqDcmܕׁl؄~upersy|{s͆{o͉zy}{{y~~w}xyo{{vmyzxtuwwwrlxtqvy}wusxrpv{otrwnlnrdkltfldkakfjcnbmejYk]gWaVcW\Xd]dM`MYNZ?UI\HSRY[`^XgZpahYcYVSSJIR:K2L&I:P\Xшq櫁ﻆʕɘʘ˕˙Ɨɒ˕̞ϠМ͗͜ʞ˛țǕȖŖ贈w؆joXNS8Gs ?`>X :Z<] 5f;r"@2J3H4F:L8P8F,B2F+H2E0J>T?N=O>K=OBP=KBMAQBJ4G:L,D3H:LSGPERDN>O?R@P-D4H3C*EjAcYA\;4MFU?Tw$Hn"Gx-Gt*Iw+Hy+IuL1O/OEXm]֋v峄ᅬĖɐΠ̔˞ʗ̞͙̕͘͞ΞϘ͠ʑʖȚȗƓŕ쿍zےixcUV7Btx$Bj;c;c6j>n9!?8KCGPY_Ynnvkyp{~呃t쑄{xs~z|xv~q혁w~zrpqzlrchg`derڎњ鬧ܮ5ODeTj^u?ba MRBP@RAM=O;XEU>Q?K 4L:O:P-D=O0D6Kl=i@f@gAh@d?v'F;N2H:L?PIUM[NWVTUaSURZUUVbWY[cbcX\_c[^\cXX[\cgai`aa`hndahdjqnovxpooonmhlgphinnnkeeegb_greggaorqqpfsowoxm݂x~x߆|߀tދ߈}~ߎᔄ❌壑㥑䥑禓孒㭓䩖櫚欍箓籖紛豜泒粛谎豔鱙鵖친⦅⦅¢ĩŬǫĮ˳Ǭȴɲ˹̴вʫsu8UT!>b;W@RD\?y.JEReEkMt"Dltқ{fׂt|vljwvykˁ{̆ozȆ|yvÁ{{r|zyǀx}q~y~yz{|{}yxtowxxvyzx|syqttwvxsvsqoppuimmumsmhmrgg`b`h`d_ccp]cZ_]p[bViS`KXL[KTSW\\]UiRnSslbO^QVRMU;K5O4IMPweݘy赅Íȓɖʘ˕̛ʓ̓͟ʜΙϚΞ͛ʙ˖ɔőƒƗ븊хeg^g:tC.E6JCM>FPppo|z{tm|iw\g\_RbGT?O8H,>{(Bm;f?]8b8n<'F7HBEUX\Tmjqi|k㉁v锁xꗁx{u}|~vxwqzvtsojqzkqjihao{䴳ݿ￱эs&OY|E\Xp9`r*UcN\!PVJJ9K:R>SBW=O7P:VCTDL:RDL;XGf$Pk+Sk,Vf$Hm0Q{?[FoTyboi_|Jst0Xs1dw;ey;oBwe$Ua"S_%Ua)Zg/\ZS_#\o0nPqrRvl$MZEVJ[Jh%_p3\l~@ao7bb!SZ"Vb0di,d\V_#]]!\_']n8mSNHk6pl6lzO|hanlkvuyr~rUaMNJI OX"N~JOORDk(UAwIWm*M`Bp$GpFkAXDVDN>UERBSIVGa?EP.Iw)Hn*LcB\9o'IcGbBcEbDaB[ES?SB\D^9b>n)Fg&Fn'Ig#Hi%Ha"Kc"Dd B`D]D\BZGd;k#Ez'EjGn)J1Hv"Kn"C1J:M9KBIy%Ce!AjGc>i>_@z!E`;x'E>P;Nk"Dd=prD-D.B7O+Dx#@5Fv#A%Cb <`@lC{+IpqҖhօ~snvooxsyŃ||vƀ}Ƃ|t}{}|wƂx|vytvo}v~zvsw|xuu}}zuwrtustuwvovqsvyswpskkknnzhejodjgkcqemdl\h_kcmWcltSaOYP_XYZa\RfVlWoVqXgO^SOJGS:I5M?O\Xԃh龇ŖǙϞϠ̛˚̜˘͛ΠΛ͞Ϟ͝ʝȔɐÏÑ~ٓt|^_^7MkC[=WU7J0H6H1G>Q?Ml{l{r~~~s~lfraiYmLU?Q7E'A}'?s =d<[ :\ 2j7(F6IEMWX]Vfhul|lx~u홁zv|{~v흁up{w흀}o얁msvyfkffpmwतϳ嵛SP|'INa&D=X3S.\j'Uf!S[BSEWEL M>V@` Ap2Wz?g|HZy5Tz5Xm%Rh$QgRi-Pl.[s3_d"Wa[c$[f,cq7oy=|SZgnYoy2\ZBWLM FSHd"RPyqf QaN` U[$Z]%Rn6lk-b^ X\!Y\!^b*\xC~QSyA}vAuzF|~KY`juqs{tkuy0[K C? ML=Z\u6_PIbH:sz9WɃGebGdGk>fAW%GRFQATFO;NBO>d?@N2Jp&Hj Be>fBgA]D`@d!Kf&KgFW$MRFS"Ka)L_Fb@l$Gg)Ks-Ng&Io*@aH\>b>a!MaK`C]IdEjG3NiAp%Ey&Hw!Dt#Fi:Z:m:>R6N=Pc:oA)E3G>M>ICK=L;J3G8NOERCMIWGMRXGTDN?R?M=I@S@M5J:I@IATk}k}wu{}uq}fn_iS`LW;L+E}%@m!;fB[<[ 4k>)F5HCNNTZ]gavlw}ux떂}|wx|vꘂyyxszzs|h掀o}gmhiplnϩܚFbYh Cf Lj%Mm%Q` N[JZCXAZCbEO:UCT;L9UBZA^Jj+Tz:_x;ecNI9I@I;ZIm/Uu7`p)Ri%Np'Pl&Vm*Ya"Ob$S[JaPf!\r/c}:w|GSW_XyWzH_o1WeMW@GBM KULx}c%Zd)bd!gb']h7oPTRtx#E}+G7KF@M7Gx&DfI]8bA\?f91L9N*ADRR_RWRVOXNRP\VVTYc_e__gOWLXO_R^W`bhbbgjgljflmehjife`fbehogfjiedhhlknglid_hjgjgklsjkmzlatunxwy|{|s}ކށލ߅zx⎀㒊㙉䟉ញ堓奍䤋墐磏窕橓誎簕櫗歕诙诖鮑鳕곖귗빕뷚븢¤ĪŪƳƮƮdzʲ͹ʹϺϻѰͯŷuu7YW G^Hs-P{6R?Vq)Nk)Ow+Lj'Oo,Mq$Jo$K.P4O6O;O-J0P/Kp$L}.O\FeNgO;V|}֞xhՃ{͂pit{}uɂz~xÈ|zĄłv}v~}|{x}xzr|z|z|}yz}~}{vy{wtwxyu|sovvrtxwy{vsvrqonpgllskqpvqskvcteheuelcqfq\iYdZb]__SdYnUlYhVnReTYKWOTUIN@IRZs]ޚu벁Ô˘ΘΞΠ͗̔Ϝ͘͜КΛ͝ϝ̖ƛĈ쵀|oegY;Hw?[:T 8]?q=|,F1I5J-G6E@ELP[Zg]uo~ro䊀xzv}t}雁~}{{x웁wx|rppxkvmmuw븴̶łWz^m~Mz9WXCXDWCdFcI_E]F\IbIj&VaI[G_N\#U[@d!Qm$Yn'Rr2[v7^cMSGPMOLa Kx2^Alv3]s-Ym)Sm*NgOd#RbF]M]DXDg&Ii&Ti+Oj2Rp2Ui,Ri*Hb$Ji(Pc!N\LL @M FQJb$^L{^g'\NPPEd0ee&_d)ZtDyk2df/bg+gb#`d(ai8gT`Sw?wz?sg>b=T?S?OAWBOHPEXH_E:S|-Ko.DcCgAfDj@^EZBbB^Db D\ GXGUD^I]!G_Kh$Aj%Ip.Kr(Ju+F`B^ F^@`A]EdE[Ha!Ih#@:Ql!@u,G|%Er=0N1K@NCFHMGL-Bi=`:a8a=Z7y'B/F.G5ESaV_NOV[NVSXQN\a\Z_]X]NYPYRcV\]cbd_afnfgiktpijflehdjgngnhhntolgjlmojoqiiqmmphnkiptt{sorwvpzwyqz~vxzz዆}㍃㌅ᔂ㍀䖊ᕂ⛎㟒堇䛏墒䠎埋秕壑楐槎筏檗氘쯒谑鵓粑붚굗쵚칞￞âã©ƯɬDzǫ˶ʷɰ˷͸ηʹѶ̭ðc~f1J[7g Du'>5Lv#?^O@MFOWa_gfqc}roz|u{鞀qvu뚂zuzyou~unyxfvvlx{ĺӿɿm~`xuC^O ;H :S=aMQ 6Ykr9rl7kj0gk1gf&ih,^qAr[Y{Cy|Ezr8qt@m~EyTl}xnn{~Ilw]k-mY`_X+OБ~ͳ|Bhe~r#@h9e;x#A~'?4K(GqA0L/H3R{,KQD_HfFET֐֔r_wmyqosl|{ȁ{~t~r€ȁkÈĀu€uĀu}~~{xry{ui~z{xs|wywytzvxwwvzxtsvwutv|xxvyyyturwv|nrowpsjrnnmjlomojtjvlwepdpdjfs^e`baagadVhZlVl[iSfTdPSQQRPNjWًo婁ÐʔΟΗ͙НЙ̙̚ΕϛˠОЛΞɘNj‹뺋zxݗlֆbn_LN)FkTc"Ky<]t/Sk(Ni!NcFVHZFc"Lj)Wj)Ti'Vj,Xg(V]Jc'KU?Q@SAUFTJRFb'Rh,W["RQMRR]#Pi=a`\v_Q_&WOELFX!Wf1jp>jk4ep3ns=ni1eo8ri6li:n|LgSPOva8aCa;r;e7h<{,F~+A-C{!Cu!C+H2E3NsDPCcEoENZٚҐvcui{prqvsvnvz|ā~Ɋzȃt}nwrā}s|xztwo{v~{yn}t{~yw{zx{yzuw{v|wvzsusuuot|uuprx~rynonsosjumnktkvepnoindqbedieh_c^[cYcTkWhPmYcMiT_JYNUQROoXޖu~Ǘ̟Λ͙ΛКϖϞΠΗΣПϕΜΞ˒ő}}r׎ix\eSAM#?hBeOh+Lr8Ym0Yu-To(Lm*Qn'SYEYBaEe>]!I_%N_EYCZL]Mp.[w?lDqp2\l0Vh+P`"J_IYAM =QDO>RBTDe(Qr5b\NSEPLYKXNf3_r>bTcDu^TRLTO\%Rk.fg,`a(Vi0fl,ht?sk0nh2ok6f\bOHy=ys6o~E~cx~r{uolNTpz`UG~bdekxDqWMZSi+@ă?b\>VDTHSLVISDUHQDUGg HEPz-Hq$Jk*Ng&C`!Ix-I^Ed?["Hc<_BZFTAYG\Da>ZEe&Dg$Fn(H|-Nq&I\C_!N`$Ib!IcA` >`Db?iB,Dz+D{)Hz'Ir!E.KDWJSJQMPHP>I-Eo!@d:` 4\MR?O;N@QARKQMYX\W\UYRXLSJVFTDWBP?O7J;QAOFTESKZGZC^C^H_QniyntyowbeJ_4E}%>k9b9d 6n3.A6JGLSW`bg]xk}owsz{yx~x}z~v}~{}|rmw~jvrhall܎鬘׫NtI;L?L8R>XGR;U>[CWg)SOsr:bVEM BKAMF["Xg/]xH|_S{Ez[ RUJTEf+]g$^`%[h([j1cxzՠ^[ DQGOARKPBQDLDPBS>l&GHZy)In%HlfAZ@_=bDXFTHSB]Ci!E]Lj%IjGk"E;Sn$C\"IcFe Ea9_Aa>\;dBg?y%D{+Cv(Ez'Ev!F*H>MIQVTVVEICJ0Hq=] 6c@[?k>4R,G9JTf\eRS\_NRKUL^IVOU^e`d_gZ^_c\\ejamejkmmpklfdhpfcgbtwgcjfike^speacfnlstlkghppojjjplojwvsoxpyyw{m~uw~|xw߉ኆ~⑁~䏃㙄䞅ᜍ㜏❁㝃坎⡇䜉嫌椉䡒娋竕꣎禍訊鬒ꮓ붐축츗C§İɲĬƯ˲ȶȳͺ̻ϽϿпҹպӱŰ~q0L_:q?e>\7[ 3a8i0C{&>p BtA$@u9(D^?Q =dDw$@cdڞӉpaqazjq{{qł}ǃ{ŀ}ȇwɇsƀuŀt{x{q~wyw~t{t}xwp|z{{sq{rwqzryy{tvtztx~|yvww{trxvxt}txprqxswqnswptqvspitkxovospscifnkschhif]eam\qYu_kNmRgOfQ^S_RgVڏq}Ëɔ͛ҢϞ͜ΝџЛΛИѡМЛϝɗœ깇}sېsz_cQGR7J~#?vJv"B0H4LCQCVAQ=M?W8J:LPMGV=PANCV@MFRL[KVJZs/Rs/Rz6XHfYneymsz}w|hnXf?K-El:^ 6a9m='>9L?FOVYYkazupsv~yyv{|y뜁}x~~|{|w|rs~ktenhmbؘޏ|iVIcp&J3MCSU7LVDWA^!Cq.Xo+Sa=`Ec!Do(Ik&OZAT=R?XDVBSCP >WK]Hx7bROzFzk(R]Ih)Ob&QaNQ ?H=JDSIRB_#J]{Esc$SMJKAJGNO^&YouUING]#Qg([g6lq4hl5cq8lo.fb%]l/on5mzQebN{>ws9p_|{mnsp{v^zQj"?Q|h2ccJS`Ƕ|=kUV^C\\ѾcKM :N:N;L =SAKDN<[Bl#@HS~-Kl Ap BmdA\BbBd!GY;U=TF]?e=^De>r&Is+Kz0Hk-MaJ^I_?^=YA^AZ>a>g=y'G0Iv'G.Np@0J?QINS[YbJLL[?K!>];e@[>d:2U9O=WM^\gJO]bOYCSK^IRYZgkddig`]ZeZY_\gogggcljkkg`lsjmhbhfnkhfiqd_fckpglkndfcjhpptrnppnkmnpmvnxt|pymxwzp~tyq~{|z}{㔃┇䙆䞌⟉ᚁ◄㝅⠅䜐硏䞉䣑姌觑覌穑奌歏簘뱚뷓춝블ﺘンŤƮƯĩɱɳȴɱ͹ѻоҼֺԲѻlg&?i @a;^9U8^5h;j9v:|)C{%>mAr?v?m%Ev=^@N CfB|"Cgkڟҋr]wgxnvn|s{lĀƄqƁuĄwȁu}vÂs~{wxā||t||zr~w~yvvqvpx{~txu{~txxu~zwtvyxwwyxssuurntqpvyu{oknsturpjtitmxjrcpiojkkpgkejjcj_pWs\s\oPoVgMgV]ObUkRݖ|첀ǖ˟ϟϠРΖϜΛЗЛΙ͚͚͗͜ɠŗÏ赇~ތjԁdiVQM:M,Dy&I|#E0H.K8JEOERBLGSW^Zn`yrrozx}읁~띀y{|~|zw{oujewmmhmZتԕZbc~^xz%P>\g>VUDT ?V8k/U~Jri*TWBY>_ Kd$JkFc IYIQFSBT@RGPDQGj&SItXL{KkN^ Ls2bp2Yf*[XCKAOKLFTF\"@NwO~m&YO BHDRKMJY'Xp:jNO~|AfKl1fVOQHc-Zg)`r5tn.ar2fj.lf0gl2ps=j0\^gL}A}yBtaqvkpguwd~d>]pe{0UWRj%;¦Ϭma[]ILVͰz5WL@J ;M8S@TLK;M 7T?h?CHw$Eg"@p!Ai?hAy"Ae?g@b@`@d?WAS@THaDfA^EcDmDq'G~5On&G_@]<_<`=V9\Q?PBQDQBNCWGZFVEVM[QQY^SYSRPZMSFSGVDU;NCN:PASCPFSEVK`K[JZ_>_>eC}5[KgSlczj~vwy{szfdQ^#@5GP;QyaNU^s+\[AO;MDPGNAUHt>be};oVKGHTKOGWIo>t}G{u3ex>k}DoOi*bTM^ Qb,Xr7ss4kr3ip2hl1hc3as>zf+drJxcUD{Avfcg`bZdc~jctMgu LQPX%RQNʿŅ?ta#V;R̼ЖNaNANAM :R 8P;L=N=YDgA?Hr)Ij$Iq&FeFh!Eu*KcHfDfIcBb G\ERBXD`F`F`#JeEg'Gp'Ht*Ig#F`Da&Hf$K^J\F\j:l:jAy)Gz$D[BTBkA2Pxq٘}tn_n`sqwtxjzsuŁw}qă{ǀpÃzɂqǁrnÂu}u}x}jvw|oă~ƒw|wuyxzs}u~{zsxqzszvxy~~vty~wyswv}mlvuvry}sunsl|nmlrjslmlrnortimjkhbjdoWwTuSpTwUsWrPgPk_gU؀[}~˚ѝԣ֩ЛО͜ΛϛϕΝΙϗњʔƖĒ籇o^mZLG7L)H%H(K,H6HCSFS>N?Q;O:K>PHX?Q>Q?MFTDZN\M]S\SZZ\X]U\LRFSAUAR?OBS>K=VFRK\L^GXGaLXF\U;U;`]=f=!>6H>MTXa`j]wx}m}{x~좂|z}~{zyvz씃wtp{jtnqriZ믐z~Og[f{,Q3L5b`EOCMR>M7QCS=N;Q 4V?c#IW@WHU>i.US{m+KZDQ?XH^&QV?W<_Ed!N]CZCRDSJS BTNy8`Lv`Tv-gXGP9s9`~Ehu4\fJSF 6L 7N 9M6L :L:Q ;b9@En Gn">y&?d8s$Ew%Ai7e8d?g=b>[4YCS9`W8^9f7x(=}0Gq=o;.F6FOVRR]`SSNQJRCH+>m6c;[ 9^7/H0D;HEaPY9NS^IWW[W`[a[Ycdbe^_ae]a\`^]agcdcbccglimoimhnrmmkkkjghealmjkgcikiollmgqrjhoqnnwtokpnyqztylwnvpys{pvtxsw~x~|㏃䑀㖄~♄䚆⠎|栉堄裊堊枏餈꣑簎嬊欑ꬊ찖鰛魑붔친칙îêƵǹƴȴͺ̹κԼ׾׷Դлl~/FW8V5\9a7l6i4t?l4e8fTFWEVG[CVHRDYKUOZRVWUXc[\NZJUCS?O9K@M?PAU=SDRBUMYM^MaM^O_O\O 8O 8Y?gDy7ZGc\vasorwmn[j=Ls:]8U3c:!>6ILD_)LLqX~;o^%WPGKLMF^%RVu6lk$`d Lr=g[Hl,g\Nh*_}JxPIvu;to>sk/fc(c[%[uDzuH|MHydoEy{:gTa[qxdf_3WV?EBIEKDz>A}1f~8NʯӯwI9J 7H 7K5L 6E 3M 9S6d@5Bl#>s4Sz)EeDv&A|-Bi=a;c=hC`c5e6g:|,Bn=Q ;S n*P{<^Mm\nd~w¢wwqw_fE[s#Ba8X 6b:u=*E@RPPb]rgyqtp|y웂}|x}{~}|~zy|zwtr^fvdrbf`mX謎xmlU~/@gnS;F4K;E 6Q?Q>XHO:S9P>] D[AQ >P:k0VP{|;[^EV@Q>WEXLP=QG]-RUDa!N^C^FZGXO[J;g_k[{8lVGQ:^%Lr9\f&Of!NX 3N 6SW9d:4Hq @h!?p=^:~'Fw)Ei:_Aa0AA5Dt7h9[ 7V 8s@0F1LKaIYR\]]STSVX`]X]cdgiaca``_ebiaeZc\`a`cfdleeddgpjeqtlfiemeorjcjdlhnejlkjmkmmlgqqpqjdtvwx|uws|uyvu}||s߆}{{u~܊vy{␃{▊噁┅◆ᙇ嚈坐㟅堎䥎磏檘槏䩋槏ꬉ谙믒걔범괖§ƲǮƳèdz˸˻̷γغٶǴo$AP 9P 7Z ;a7e @asl?] 3b9iJ 8TGW FR[CZEX@ZDEow=\o)M[FS>RCS@XL]JVGZJ[@XFR=_C]H[G`Oy2[Z{s_v2gO>J:YIq4^h"Hr0X[=O6VHO =H I AS@P 8e#@5Hz*Eq#Cs >e;{,Gw*Hc=[8_?dBb=]9Y>Z9`BcBZFcFm;w2UBZl AW=d$KfCc J`=`&KZ9`=g=v"Fp?s?'G7IESRUV\TYUVVSGPBG2Cs8a <[:RE`MhJURWUTJOUV]]\]`ffcf]`e\cdheo_e`lfh^[ideggbjdeenolckjkmeglikkkemkiemhniwsejlorusmqkqsvryqxornwtwmt{q߃v߁tvr݇|ޅwߏސw⍁|䌂䓂⑆ᚃᙆᜃ㟈㢈桐䞄䟍規騒楐䢊櫌篖糚鸡봑굍봙궓캝₩īŭŮưůȹ̼dz˺̹иӾӿع׺ҬϱPbS7U=X 4` 4f:j3o?` 3_:j=w?a 5S =W ;pMDV7J8LBR?P@LNULYERNYOWKXQVT]TUIMEWHQ=N6JTAP?XAZB^EYGi-Xzeq,Pt+Xe#PJ:X>PY?`@jcCl!KCgUmràorjvM[o<[ 4S.V 5_4$=3@W[b[nbwgun~ꏁyu}tzqsv웄|z|~zwme{isfj[^`IZ``Ĵƃox-Ju,Gl%ET@L=IBR?YGVCTAR;S?U?^*ZWE_"Jp5_k&N_E[?VDT=VAYCYFXGUFZFV@R?WHU=\E^H]K|;Z`v^p)ZQDRGUDs/Z}<`w3Zl%RR;M9UXEv0ZI}LzAxe$Uc(SSq3d^SVH`#Yt8ct4g~C}~Cz?~m7d~H~`b`a[[o3sc([rv4dg#VH @LCiWw8\t֪iȬ˵3OICF 4F@H>G >L>O 7p =8L,Di;v>u>2E-EcAbF];cC`EW?SAZ@_F[?WGb"Fl#Fv6L{*LfC^D\FbE[?\E_?\9^6j;m=m9v =9GAM=GGKEIEKSOZeKJ@J>Gt7aM[ :Z %AoqӅvӂtЇiYnoxtuíqɂoʁvŁ{{l~u|j€w|rǁrn}rmyp}yxqƁrw~}|twwxr}wwxxn{wtyztrtuptroxpqxw|uuvtzpvwtswsqqtnoiseinrknbekmbmaZjicbmgxbւi݈pjtvq~붂フǑʘΖҝПќќҗϜКΖΚΕ˗ɋČŏvݚk|V]ODH5I0L4G:Q=QBNCT>O>P9M;TYHS:XI_#FT?U=T>RYDZJa!QAfdydcQQ >Q B`#Nq1VAkq1UgIU>G 5Q :K 6PBYLI CL >b"Pr0YMuQ6qk/cQ{?{p'^VHZRs4pj&Vp6g~FJu1ll5fjWXYb\{>wb(^l6lu@x~C{uA{m3iM~vucqUcKU >Z!>k,b]OXGq^w)V\zȻ۾ɦǯo%FKDNEJBKEB 7P9S7w*C]>cAe@`DX>U@`B[Ce FYGf#Gk;y.Fv'CgBY;_@b:\=a=`D_?d:m>l9l>s :1D?J>NKIFIUZPIMP8ABL:G|7g9_7`;w$?3DGbCSEPYZUYKOPQ_`WQ[\b`VXROZb`\efgde_[a_]`b`_a^iidabeeheiheqmkgljjijejhg^mhqkmftpqoskyuvytiqi|zrmvj{tyl}uouzkw{݃y߄x߃|y}⑁㒃㕌㘄䘅䚎㗇埊⦑壏塐栉㥌㫏穐櫗譎籒櫗감겕츢췚칚뼞ﻡᄄéƴʯȰƳȴʼʸ˻̾пҿӿֿڻصʺk!;R3_;V 5e9g;] 3[ 0^7b 3XBU ?a7*@ssЀjՅrҒl`qsvj{lLJx̃nɃxǂr|pŁx{l{rzp|lǀwp|w}p{l|u}q{r{{yrxp|ur}{wyvv}vqvouvxvsvutoqwtsuwylgrurmqurvnqjjmrnkfhacphbbafYWa]qpzl׃lۉwss橄|~{ÇÒǗ̝ϟӜեӟҙњњЛϖΓ̘˔ȏň~ﻆoڋ_tOONN6H4K:N9MBPAQIYJUK\JRQdLbGZHcQ_J[M9M9P>N 7[CaIgKz:_Yxn~Š|zeiAOf9R*Q>U5b:~ 8:HMO`RrlvdkpquꟁꞀq||sx~xwvvsjhg{ghXYYG\MdboQO\_}Y?LS>]HYB_$Gn.Vd$D\I`#K\?Y@WAYBZMZCQ@WJQAS;VCW;UHVGRKgQIts`\CRBVIWAc'DHnz5UaEX@M 9K 6PAQ:k0\N @PF]Qd&To6gDmPH|UIl+\VGXIr5mi&`a#RuAoUxJ=a"Rz;su-feWiNVwɼŸ˭ãlA@/L=D 5A 9A :K :P<},C1Hv Aa=h?1@>S5M_=\Ed<]8aI[AT9f@\>c'I_Kg=i;s,Cr*EaB^?[?^>_Gd"Ih2Tf(Qh?mAr?p:0J:I?LMTKMPKIKDFBH?>BL;C~ x:4GEZAONXX`TWWWYd_^ZW[Za_Z_TWUW\cbedh^_feeheadjednje_hfhilnkqg[mijhholhjeiemqonopnixyxp|qjqknjqi{qsoywztzvzlys{x܅r߇{ޅr⊂y~ߌ}Ꮕ☀○喊㗆䚊嚋䝉䥊䛎李堂姑䧏嬓橎謑峔気謔沓걖뺝빜빜­İȰǴǶư̺Ͷɴ˻˻λ;п־ٹմгIYW5X 8Y9b:c=S 6Z 2[2g5K5K4d 4,Eҁ{yj~p֐umgigvhxɆsȀpƁuƅt|mĆpyx{pÄzytÁ{|j|zsÀt~vĂw~xxq~vyouvyuzzvwq{vyuqusmv}pkqwrsw|tqt{vrmxqoppuxpplmjndiedehdca_`bc_g^wpքqqxxꨂ뱈ᅦÏŒʘ͕ҝӣգӛӜϝќҜҚ̕ɚǎ̕Ŏ~iՂ\cOEJ;M;Q?O8F=NDQEM?M>Q8K:KAIEUFTDLHYLUJXS\PURSOXPXJNIYAS>O?P;LAQER:KDLITRZESLWHXHZK`BULeOfQaJ 2J 2J ?M>S <] JjFy>`Rrj|{yju:I_7M0P:S 5gA*@6BKTe[pgxa}gwr閁蜀ퟁx짃q{|}}{zw}|pwrazbwfk[aaJ`OoLhUcxraGLBICQAYCYGWDTDRVAZ>U?UEZ$SR?`!OZHQDPFRI[Px4`U]aLN :M?U?d"Gz>_v8W]B\DO9M?Pg~Cym3d_"SXExDxt5p[Og3`}DyL|>t~Kz`WVzFzzJ{uR@Dv{4feVaKR|Ȳǩ˭ɷ^>E;K=H ~6Ho#Ea=[GY@]=Y?c"C^:b9hApFrR@SBQGRLYDSHNOVMQPTRVWZQSKTJRDMFR=Q;NM :T ;e8)G;FPUh\qcyh߀nzyx와}{|}젂yu}vrtxg|iygrjbaSb]La`pΨOSVIO#ORNUKZJUJRFRDOEXG]%M_+Pe*O`#JV>XE_H]?YD\DW=ZEXHS=VDZDYC];UIRQO J^Tx7ahyX}dHN =M CO=Y?y1VAfj,NaCN ;N 5P~z?nS]Qt;hNt?qk/bs:vyHzB}r1qs@xLc}iQO?B 6PDk,QfL\Q_JQqĵȭѿVBA 9L 8O?I?LCN :S:2E6H2H`=gD,AOaDU_CY=e@j=[DY;UCd$N^>`<[Ai!Ej$>7Mm D`CZ@Z;X5]BbB^8`7t=r">o:&>6KAOLIPNII@En4\;c>x"D6I=K7LLTPVQVWYb^fh`]d\_baX^k[Ybdbabieakkhcgejeihffmdgff`hcmie`h_kfielfi^odqjkfroomphlgrwsntothrlwvvm|q{s}tqsw~w߄~wމw߉}xߊ~⒃|yᜉ♌ᗄ~㠎❋㜅▌⟍㧘䫚宑姑欗䭒櫓毘孏屖겙봜뷙꼛ᄅ¦±ƳDZɶIJDzɷϺ˴̷̻;νѻҾֵӵʧ6KZ 5V 2] 7a 3T-S-a 1\3O3O5d5AQoykׄs׆k|shh~Ȁuɂrˆt̄sŁsÅvƒvˉwryj}uŁy|h~xŀw~s{ksyu{q}q|u~{}p|wuxxyvo~wwxxwurtywowvtpuusqsupnmvmlrppngpi_jtegfed`c^cbuklݏu䜁|﯅ÔǗɓΜҙѣեТӚӛҟϐӡϖ˔ɊđÈzoفV]NFL;J?O4L@JVCX=VBYE] L[J^$GYDSJLHQXa!SCnynLxf#NPDK ?H =S?r0N@hq5Tj$TP 9M<]Dq.[h&U\EQ ;YId'Pc1W[!RV CL 4ZIa&VZLVKWMa IOu7o]Om9fQOHw@qWW|D|uDwzDo4gl5mwC}r:sp;rq;zL^~quW}^IJuco7gH?SBUDVEZQdVD`ðǸIJ³_wL?ECI 9ICJHNDUF\"K>L8O;McDkC*EEX3Fc#J` Je@h H\G`K[IbDcBdG`Ah%Hh!J{&Bl JaCX=Y:X;ZI@L@JLXQPPQVT=C!:j9e?]7x"=FZ>OEWDRLXSTWZ[Z`^_a_ZYS\_XWY`[abbecd\jbgbfff[hhifgajacabVb_haleiej`ljlglbilrmnpc_lpssphujvqpllnojqnwowu|ruqv~tw}px}ty~}⑃⒇⏃⒅ᕅ╁㙉ᝌ䚒ᝓ㠏埍姎嫒䪐欔姐娔歒寚毗粓괚긜鶞뼦¨¬ůƬƯŰŴ˷˾ɸɻʵϽξϾۿ׳ƴq~i;N.U2^ 5Q,U 2W 2\ 6N5Q;c7KWynziه}kxoinzq~qwɀpłwɁtDžwʃrdžvuv|rp|pʃso{pÅ{zryu‚vvq{u}|{q{rutrkzxuxkhvuqptrptqxnoxrrjvxnlmnnjlcjgmoeidgdchj`^g\jbzkݎjz~ﳁÎNj˖НќӤԝԟӢҜРҚС͗Ζ̑ƃsqےcrVVMEJ8G;K4OCL:M=J>I=M;K>JFQCOLQK]NUN]NRQVRWVWTVLUIUENBK=TCQ>P>MAS>S>RLXCPMUU_EXM]AUCW@\ReLaTdOhI 2I 2I 4O 7UC_If(Vr0YKdc|~ǥģrq`j9OdRYE^F[AYBTDTNOJWYf(YUmLtfHM 8K =J zb%Yb,\|QXOyEpbdMuDo}Q{Ed,eoF=I 6E4F4K ?S:fF>H;E;TX7n A.B;G3Ka>`a@b?iBk*Hy/Hd&Kh*GZFY;X?^<\9bLQAJU\_\XWSVAH(AkBa=e9v;K_?T@ULVPQ\a\cZW^\]b\Z]^Y\\Z\]_`fcfddbfed]gfheldfclgkga``^b\ebdbd`kekhh\dgjgf_lrrnjgzvrlupqjtqjfrovswvwryo}r~t{w{tv}wu߄s}⑃ߍᎈ⑁㕁ᙀᖄ䓈㘃❋䝉棍墋䤐㡌䥗歘櫕嫕汘嬓岗紓赛뵚鸞커§ĮĮűııȷɸͷʻ̽;ιо׿׳Ѱʟ'CK-V 5T 5T7P0T0[ 7E:Q>h7[d{jwhՀu~iykxywnʇtĂu~n|jŃxÁupɇxŇāmƀvĂwŃkzl|p|s}mznxrynyzzvzs{wssxuxuxvrsqopsqulnsqpsqstrpstzrolmknkkkoghbgjgljel_`edphՃqy氂ėُƑʔЛӤ֤ҢԡҚӟҞѣњϗ̓NJƌogهdmXIH>P8M;H?N>J>O:K:EBT6H=IHPGWGWJRLTQZSVOSVUY[SSPWCT?NAN@MBSQ ?VL]$WWDZN\ Lq8eHzd$\`!SjArR}@yIVh]K{O{GxsCyn9sn,tY ^sCzUj~iSrTTvnt5_S?PMMGV Q^L2L7F/Ma;`=g El"@]=]>\9_4_?cC^9j@l&Or(Cg%Ed,V_'LY;^<];f9c:i Bq>p:y8;M8B;DAK?GGNNVNP\bVOQQQTDM*Cp7a8f:z!=?S=OCNQaLLQP]a`\gd^[[W\a^X``bde`ogf`jfcda_ddhfb_daihmeffabe^jbd_ecjbkfe^haofkajiklmfqluqofoksluypfwjxpyp{p|rn}wz|yރ{rw~w⏐ߌxᓃᏃᔀޕ◇♄䘆㚊䝐均䢎桓⣏㢔嫔櫐絣䭖欛気継鶚鴡궣뺡ァᆬè©Ȳòǵʹɹ̹ͺ˶λ̾ͼνѼص԰۾J][ 2Y>[AI 2R1X 0[ 8N8S1r8mh|gyc|huko_zlƅ}ŅzȆvņtĀr}nÀnɁq|t|p~q}n~răw}n|nquo~nzxvq}y{xsxutu{zpitxlikpoosqtoojrwlortqspqlrmtovhleggd`ec]_c]_fbxpޖ{歃칍Ǘɓȓŗƈ˒МӡסըңѣҜѠјҘЛɋƒyeܑ[{]]QEG@P8J9J=G>I=KZ:L7K:KFWIPMTIPKUOZIYG^F^OaHdNiSfQiOaJ3J3G -Q8K0W;X@l.WEd`v{¡xueoE^i =V 1M5S 2g<<4CKK]ZhZzjolv~yꠂs|z}{|uz|}zx|mkj}jt_kb^Tx֝Ye_d_vRKHBS?c"L]GWHSCU?^Gi+Qi'RcE]GYAP>W;YFcDX<]DaKR=V8a"J^JT:LWDP?Q9_!Jj-N^OWBM 7d$M}=im M]G^LSEZI_GZ$MZ(USDPBSCZKWI\KWGb$Qy4mr-e[Pp@sTn._J|Z`^MzFum:fq_g-IYTS?A dAj;]:d@^;b?cA`>\O5F>K?J?N=L;H9M8KCOFOCKDSEOJORPSUSUOXVVSZSXHTHTCR;P=O;R=NCSEUESMXMUJSOYO\M[J_F]CWL[NcScLaH\H/H/K6H0H8R 9\@f%O|Bccvyåy{^dSQ6YGYwmn~Xx@tk$GSJNLJBTEWH\Cc-OYFWFS:l/X|?adI^K]KWNXJXL[F^,W^MM9T M`QSCVKRG\"Ot7mp3ge%RsAtIk*]zCu^kdVo8gf.^l4kf/bh-l[!ca&fu:ib©nwm}ivHga`Aw5wh"_u-Wxɮph#O^Y@;:GCG1M 90J=L5I.G`Ay)N0E|$=u#Ec>`Fh Af=[=o%=n!Ca?c9b@_DhAf?c@bG_{<+>3E@LFHPTLRVTRU_c[_UPWSQUCF/Kg 8]9d92N=OEOJVGOIPTQXX`aba_e]baecb_^`]ZYbepgddgiec^bgekbjccgb]gmc^bXhqfedZgnh`cdfbhgigjgpk{}qpohsjvxshqqrmuovlvrxn|wwk|{w|uބy߃xzq~}߆x|㒂ߏޑ㔆㖃㚆㠌朊䠌㠌䢓㢍夌穒氓孕歚籗粒跚칦괛뻤ィĬŲƵȳͳȶǸƹǴͻоؾ۵նϭunvntWsivuof˂yƁy|g‚~Ɓs~x}n|oƁs~rÁy{nvxs|s{r}j|svmyo||}p|xppunys|sxurmumrkxtrqvmnhporrknijmrlmhsmnrugoeesssrejcc^agZtgܚv겈Ĕ̛СЧУΠ̕ƒŏƑōƋ͝ϜѠԢԠաԞӡΜϙ͓ˍŇzsYuXeUPLCG>I>G9JAH=KO 6b I_BW=MM;X>_B\G^ IX=p,Ty3UdE\Dg!Q_LR >Z@ZL\OWDSAZKd(VVDSEWMWGk1^q+abMg3bzMc*dk6i[yfczHw_#O[SZ"We!^Y^]&bm5jp~{yxQ]Nm)S~{\aTaXq"FkAcAl"Dc?`=r(Fs$?`9b@fE]?e:kDdAf?_B]Ca%Jg N`=i"GhAs>xA+F/D=LFRNRPORUV[VT\`d`UOPPVWEF-Gl=e6iI?G@O=H;G=JTF-F-G0K1D2P1V?d!Lw4Z^up¢ťǢşhpIZjAP 4P2S2_ 3r42JLP``oXv[usox{}z|||}x}x{{rxqrnZmsYi_c]jZƈ]yx&IQ=M =PFTF^NgG^NaNj(T`"I[BV>X?\FW:Q;Q 8^C^DQ 8YDZBXG^CVCRCF9K CGDK EZ!S{P~VnivPo{9a_CN?J?OEPFO:UA^Hf&Q\G^Bp.Rn&QZ;\@eI[CO 9RXI_"QgQ[GYNVLMBg)Xm)Zd+W](Vf0ge)]cN~R{munNc$SYQ_ Y[!]b'hk.ktAvz|{z~g~4r^Bk}qk#RtCjjƴƨnys-MH ;G >F=P7x,J/Hq#>s$BZ@p$@|+Dp=r*Mt'Cg!BiDc;d Eq)Gp,FbB^<\w?0D4GJ[NUWVRUYZ]`Y_X_[[TSURVQAG4Kh8b 8rC9J8KELFSQXOUSQ]Vcc]Xeed_[]gbjighe`cfol`Xhdgbbbeae_baiageb]cZlld\im_Xihb[iahbjdmfmgpqnilbslqipmodnivrulukrp{uwk}w|xs~t{tuނz|{≀~zy⎅ߎ~䚃⤋❌㕅㞇⠊᠋䣔䩑笉䮚樖㰙⯖籕鳝鴛踤鴜ðªíƴƲɵŴɷȳкʼκʼ̾;ٽسϱmZCV:\BV>VBK :KDFAQH] Ow:ql_{6Qac{<^h'M_HL >OCL@N?QCQ>ZF]Ha"Nm/Pv4^i$MS 8U4b"LaBN4N>M>RAXES@^Ml0Y[!I`USCP u*Iq"Bl!JbA^Aq(Fu.DdGh=`=e:gEfJNUVOV`NPY[YXY^^aTUUOY_RQ8G#An:e@|1N>LCW?IN\NXRUVYWR]Xbc\Y[^\[h`fmkelflff]`ahmi[ihgde`f^d\e]c_eeaXh`dkgbhfd^hgfiibgcjhikkjlgojoimkpjtmsvskruvpvxshyqzwށ~~sw߁u}w߁{ގ|߈{⌁㑃㚄䗋䜍❎䕄䗍⥌㡏契䧍媑䩒笙㱜宗笝粙贚洞赞붣«ƷưĴįȽƱƷȴ̻ͽ˸ξѾٳӴЬ3LH 5@ FE6K0E4I7e6APxdnfqdt]|stt}pΏ|ȁw|lymŅ}Ă}n€wÀn}ttm|pzqr~s|x}x}s{uwr}xxtwm~rwm}xynrqys|wpkqonmppyrrnmsqjpwmhksghfhknhhdf_`^`^[^ai]؍vŽ˞Ѥԩ֦֬ӧҥ͛˙ː˘͙ΣϙҠԠդԣՙӢ՘Лϕˉƅuf݇WkR[KDHCQ?F?CBI=COU :aJv0YQlhĤƤȢ~|}kvNYv)E[3S 6U 9b 1z80@KOXWgWw^tpwuv|{}x|w}xxw}uoqpcixgiYcabWvkrq+LYGWFVId#Oh,Ug$Ne)LaKdJT?N 9P 6R^<[?T<[GW@]JT>PAJ CRHQHd$X~@rfo\y.Yl%IZ~]o)OeI^GN?ODK@N>PIQDS@b Kj!Mo3Uv1\m'IT6WAb'HcKN 5Q:L ;R;UEW"Ke'Mp0_`%Nd#UT?K 9a&Tx=nj%YcQe1k^2cZXc*d|Wio_y>}c#^f%ck8r}SwN|M}zwwzy_Gugx?oJıhyq;Mv@G~QMm>Ia'>O@RA_?V=e>~,E/Eu=f@[?o%Iv?c5|6Tp-Fu$Af@`=]?l&Co Dg:f!Fc@j(Ii'Fh:_8d9gE^:b:_=f=-H}#@v B3K1DCMPQZRU]ST]^XX[\XW[^WWZZMM5D%BrJ7CUDPITL\OYJ[M_LZL\ThFZK]MbIZGeEW>U>V;QH/H/J2L ;I6VCT>h"Rt3XQli¦ǪĩƦhlS^.G[3N1U 8c 0t8-W9a(KX>R6a=[:X@Y?[?V>O>M @JBTK`HIzpiIgh+RcNg(LiY{u3Zg&R\GXHPGOCOAO?WMWG^Fp.Tz8ar.QhDR6S6YBh IV@M;V?P;[B]D^!Cj.\a"O^IS BK6Qi <4J2Im=\A[Cq#A{%CdAr$t,Jd;\>^Ao&Cj >g@a9bCm(Ag!Ac9a;gC_Ab9_!I`;qH2I|#@,K1D7FOQWVYSVYYW[[]]YZWUQUTOQRPQJEP;CATAJBHGPHRKOTTWRZZSYHMKVFTBNAW;M>O>N>U@QGWLZLXKZO\P[KYPZMbP_DXBZHZL]DbGN\VgYwemquztvyw|yyw}}ywtmeji|lskfk\Ybi]|t(Vj ScQh#Rj.Wp,X^HZCVE\KSBR;W:YFX6P8p:g~Iyb"Ue(^_[]*WpLkZUZdgbU_U^txuw^u(Qa+Od|zʮִ¨I^`#GO?E7Ag=W=e@t Du"A`=s?g>q&CmE[=b Ai"Cc%Be;`A`>q%Ak Ae;fP^=c>bCe@q={'D*>!?,F,C8DPRTQXR]\\TVU]\W_W\STWVMO@I-;9n:_86HAU>K;NFTLWYVYZZZ\U`bZUa\^`aY_]dWdgghhii_lgh^i_medbf`i]gid_g_c]ijf^oogcecg`mcknf_jbokoymcpiplogndvopkphrmxstg{|tjumu}r~s|v}t߆|݆y{|㈁~䌄⊃㍁ፂ█♎䛌䘎䣋➇⢑⣏㡍䤐奐㮝㯛籝絙浔峛귡縟깣꼥쾩ɵëöİǴǷǴȸʻͺǹ˽̺ξͿμѾտվհͱ͠'>@-B0L.D8N=z=hhtgiUrata~oxuyoDžwʼnDŽo~yāsxp|uÀp~~uq|v~uzzzu{qzovwwto{{tmxsxv{rxrywzwspypwyxuoqvyppontvqwnngjhmjhgdffd`___\_^e]|nwŗ˛НբէӟЙ͍ɐɐǙƏ˕ΟНԢՠԧӥӜӠП̑ɋąob}XoY`QQUNLGPLIKNFLCLEM?GF=LAM?HOUSQXUXPWSPTJPKZGPIR?RCQ9K:MO?U;R:Y@W?Z=X?S;[<\;]HUDQ?TEUF^ Nc"Pd"Po4Z}E`q8UYEMBRJYHHq~<^v9eu?af#OZGTCX?MAQFUEUBe(Qy=dz9Yo,MfIU?P=U:`FX?QBPAM?W@[I^El)Zo5e`%XN DG AMfKxu-aYGa V[QT%Ih8^uCzq;f|Gz^goiqg]tsnY}4qj#Wv=[qqhtȠɯwcwAxd)VI@C=I;Y>Dc?Sb7P=q+C~-Bu IeC_En"H5MvCZh>b>g:p<$D&B(>2G6MCMLNUPYRXU_aUWZYX[Y]\^XZRTKF)C}7m8a::J@Q:H?[FQLUSW`\]___[_`X`cge[]_X`bekkcluibe`ifkbpihdc]dfc_cfmgc\hbfeilcYebiig`gefcnld^iiicnjoji]gepjpiqqskvwpbrpskxkzl߀z{r~q~߂x߃y~u}x߈⏂ᎀ㑈ߕᖄ䕈䙆䛇朒➇⟐㟌䡑䢒禖㮙䭔籘箢泘賞鷝浘궦뻦븦꿪ǯĵųƱǶĵǷɺ̵ʾϽ˽̺μϿӽԽָԮٻO[D-D/G0G7I5}NAJOZUWPSTXVWTYPSJWLUNXBRDP>S=NAO?QCRBVK]J]Q\G[QaM_OdIXRb@TGXD\;N=V7S8U4UG-G-J 4N2E0L `Bo4S]|l~¡nm[fCQh:T 6Z 2b3|B-@CJ_^hZwh|jqrzsy{}v}yttnptuwvxqyrv{mulno^pYv[Iuv1_d$Qg(PdIg!J^NUBQ ?U?T@QCY>]?XAU9V=T>`?[9RP<\GW:SCPARAU>^Ib!Jk1^g+SaMS DJ p8eNw}=sc Q^OSGMDYLa%[b%[g)^~UZhmzyjkwpm[D~?zy3hLnmndxn~Cl0j^(GCefgdAP9]Dr*=0Hk?c<[;j$@,Cq>\Ap'Cq!Ep&Cu)Fh"DdFu*?g@c"F]]>bffpkm^o^qeǁu{uwvĄvˌsɐ|j}yzqvyq}uymw|q}rwlytoyvygy|umxg{uzsuoznxttvtvwuvqqvulqqsytqv{prpokzqvknjimskpe`dgabfYnzh^Մk婃*ǜΞљӣϡΔʏNjČŇȊ˝͘РӝԨעԠԣӛМ̐˔Ŋqw]ۂ_jTaR[WWUSSJLNMDGEMEKCN>J?DCMBJCJFOEKJPJKRPPMPWQUNTJMEPAO>M;O=JAP?R=NIWNXKTMYJXKXOaJ]@YDSH\HW>S>NCX9O6N7U2IJ 2J 2I 4F.L ;L 5RD]Ci)PWupx¦mncoFWi>] 5X/b8xB,BDJZXeXxo}nmpv{}|yy蕇wzy}t{╀}y|瓁tyހu}l|~o^nxeyawi`q.Ye!QVCSA^#JUHTDTFYJT>YDWA[;XBX\7c=g8}$D,?#@/C2G7EEFNPUUYT]\^_SRfaWcUXYYXV[aOJKDOHVAMCLEJOQTVSQPPTST_FLBOY?WCX;U;Y4S9OG4G4G0D-E.Q4R ;Z;m0VOmbvģ£tyipCOj6]=\ 0`3t5;BNWRgcwd}omq픂w퟇ꟃ癃瘃昂㙆}~ݖݒ⛅䠀㙇}yvoހiyum\arj}hw}fo)Ug&Va#PUEW!I[LPX>VU?R>YIUJXNWIh%MBu{1Xy3bDgEc~.\^CK_&Nk(QaDY>]En.VbIRDUBR<\HUESDWG[L^Gc-Jq=n_QM >^Qb%\d!MxgGq(K~-HC^CYz2Fi?q;f?c>e>j=g?g;f4c?a?b=bF@ICJFSEGKTP[KOGLNRN`TZLLRREMAOES>KBQ;J>N>MJ;O 6]He*ODfZn{äâu}egIUh=S 6S0d1t6->>LRPdWtdlrr{vyzy}~蚀喁♄㕋㟋睁癆mxsq~jvji_hrmq~|Wwi#Fs,`s7\S?RCUDRDU?XB\@W=Te>`G[$EW?VA^ Fq9Xp1P\BTBV?VD\F\HYKZH`%JHx=cCfBf?^y6\g!MP>TEQFT?]Lc%O_BV>YAXCh"Ng MRT 5[/~LpAjb8d%9g+:^;` :a5deO9I>O;K9LBPFS?OT_Q`L\L\ObGVN_GVCZ@XKaDY8O9W=TF_?ZC\@ZG/G/G1A3E4M ;P ,@@JYTcWwbfnxwꝂ|vzꣀ~|硁{~{|ꠂ}}ltkh{btembs~lwg~Ou`Kr,Xx8XRBQ@NAW=YIY?T<\$IV?V@WAV=S;_Bd L_ F[>XAZFVDo3S[<\%OQAXA_Hb"MZG[QSGXGFm?e|?hx7\u+Yi(HeK[IS>RIf&Re,Tm8Y\ SWLWA[!Gg/Ok#KVAVA_Ld$SS>_!OYGYDSGU?m8fo'\L EVHaQzBkUv]m'WM 3Z(Ud'WHBF |#?(C%B2H>N:IKTLKSV][^ZXXV[X[_\X]cj]VUUTS:F1Pr7b=+G>MASDPDPNP[`[W`V`c``b]dgdfc\ge[Y_Xdge]hhd_h_jfmnifg_heidhakcgeifjeaa`Xiib\db_Vb_g\d`lhi`daidkjoepipdkgmfjdomtnzsypxqwn{l}x~x|w{t~|}v~݃{z݅w݁}~⒂~㐁㓉ᕉ┇䒇ߛޒᡏ✉䤍㨍櫗⩔䫘媓気氟尚綤蹨輣躥漦輬黧ðóŲƲǵķʳɸʺͿ̾ο;ͽпһӼҸӭɷ] 6E6G>X 2P`i\l^ulugul}yl|yŁo|pgƑ~r}vƅu{{{u}w~yzr}yo|r}wtrvspwtxqtnvmxsysqowqwoynwuxoqsoosrtluuppijotghkngchhecibdac`c]b\vhޕrǘΕћԙўˑƍƈǘɔ˖ѝդ׭ԡѡҞΑʒō~wY}[oY^SVVTRSQ\VSULMCNKNFTAMBO>MEOLR@NH]PYO]MYN_IY@RE^FY@UIXBZ:S:Q>VC\EYFZGZ:QF2F2G5C.D5L =Q>XIh.Tz<]ZttèĦȧě{vfqAQj>X 6Y6^>v?+GDNZYeVqhklr阂usw|vz럀럁}zꢂ{훁uzril~gn`lc؁}_mPkEpi!Mf%Vx*NRCR?Y"K[FY>T;VD]'KW@YAY9`FY:^@dA]@Y>S=S;WB^?YFXGWJ[Gf&O_G`ITC[L[Ev6`Bdw>fw7^o1Rk'UcDh(RbMM?d,Rj'WaG^HP:YKV=h0Pj&MX=[!Ja G\>X>UAN 7P :N?^ Ij(Z`$NZTND_!M{>g[}TcNL9W Eg2m[UDj`~X|FvWuKuNl_z6fPFH 9P ;W8n0Jkb?I 9QEYAP4w6Q6>X 6F 3G 4T=x5O~0FFYy0Hs)Q{.KeamwZdRnPwv+Sg#Kw)Ky*CcDdBd:g(PcCi9i@X;fCg?m9sF-D*B-E5G8FJV8PCUH\FYE[:P=R;WIWD]B[ASD`M 7M 7K1L 5B/I 9L 5U;]$Hw7ZWhk¤ĢŠä}aeCYq>X .ZY>XBXAWD`EY?V;R?[ GVCZDRBUC` Jb&Li,U]GWDVEL@]#Fu2Yr2Um1\o/Vf(Hf%Q]?^CYE[Jb)Qm+SV DWLXDTC\Dg/Lo.Q\ES<\:W ;XBTBUDK :[L^!Kk.\^'M_WXL[EBkaQ_FE hGe @j$Kb@V8c>bBc:~+C&@,D4H7B5DBJFJPRXXY]WZ^dZ[\_ch`_`^[W[d>E-F)Jd 7tC/D4HHWv7ZNinåĤ¥Ĥ}acAUs,CX ;Z 0e 2~*N%>>BQUkaqa|ipm핅vxv}ꠂp}w|y{zrmsmiu_lhuxЂbsPs:]_E`G_=M=V?a?^Db JdDU?S<[BY=W@W;W]!QWFUB^"Nf*Sb'Q_FWFWIP>`"Pl(Qr/Vt4[n0Zg,Mc Ie!L^HR>[EaMb&J[C\FVBTEb$P_Jk/Kp.X["FW;YBR8W=O?L 7J :Y@c$Tg&VM=SIXJ]M~EnaOyd,bH FH >N;u@|u>~b#bf)\q.lr`<_7u$@.D$>,C;G7DENFLINTSXXUPW]_bX]\``_`d`^dX][FK4H}Cc>.L6MEVGNDNRV]Z_ac_b]`\`_e]cf\[ekhpe`henlgglihae`c_kdjbfdnledlcigpjdge_dm_`geaUfjcfe^hcb_kih_ghihjdmrjdkmkfkpierpulssqkwqvmsqxyxrvqy߄}݆z݅{ޅ~߃z܅xރ}܈y܍xߋ~~~Ꮔ▂ᕂ䙄ߘ✋㝈ៈ㦐䦒䫎諘粓贙泞䴜泗赡鷩鷣躥踮꾭뿲¶³ȵŸĵŵȻȶɺǶȽ˿Ϳ̻˺̾Ϳ̻μμѶӰűjuJ7G6q5bae_aTxgwbqlńyvyƅzƁwzÁxpōÀs{uyvzqzvzr…z}n|xkxu|twltt|rvn{tutslvqzuzyttywvkuvxwwmz}rmpvmnolqjprhgiijkjfkggcf_dSibpZޒxyÉȘ̙і͎ǍŌƊ˘Κԟը֢ӠєΙȊÈ|ujف]dNXMYRUUZSRQSQTUR[NUIKIRJM@NAM>H5F>FENGQIHAJJSHIBN@J9P5G:M1L6DR:U>VGbJaFXKcL5L5G4F.M7H 3O=X?[Dq,TRno}åŧyzkqH]v.BW 0W 4g&>ISVXaZqb{krm~}|x||uv|twtzq{ipkipXd`xʈarPr;_dKgHkEVDX@^Cf#Pk(R^7S:VCT=V;U <[FU<]!L`LZGWAVGVFUD[F^#Le'Vd'Pg(N\IWDQFVIZIeNj,Pt:bi)Zk2S`!Lc"K\EYC^'P`&O[HVATEX"NTEVBg-Tk1Pp4`g/QT@ZDV@L 6R>J?O5_Gp0^bDPEMCWKc(UxBpWyn0Vt9|`\D FB ;\,NX{Eg(]n3iq9tyEIPieje`Lvfs_S]sver'ZVo*Fy/Ix0Qm(Lb@Y?VCv6Pp-G]@aBq%EpDw ?,iB~$E)?.D3J:F;M:JHJMOUWW\WV^a`a[a]b`b^g`__ZV_@D5Lr=d>2O8MG]GSGRW]`bcb`Ya^`Y_X^]dlaYkifghd`\gnifshkof`c`kegegdojmglih\hih]b^`YaXgk_^hfdac]ikgbg`rlkcibmekef`jjncmknfklsinerrystuurxtvmwrvރ|߂y}uއ}|܇x܇yމ~ݍދ{ݍᓎ᐀z┅☇ߕᛈ䠇䦒䦒䪕寑歏続㴙䱠峚鼩纪躣輩黭콫鼮뾶ƶǺƱƳźųdzǷɷ˼ϼȹ̿˹̽ͻɼϽӷѭȲÊZ 9J3~8icZRhVylzguqń|tÇqąsŀwÆtpāw}|{zwwy{oxyst|nv€yztwpwkypws{uzs|vwnxn}zz{um|ywvuu~sxtqissqsrlmvoshmoolqqnmtsmjfcRh\pjs`ڊhtĐȉˎˍɆƇÆǕȑΘӞ֡ԝԣϏϘȍﷀqfwZ`OUNXWUXRMSSORQUNSNPKJERELCOL?NGPDNL[CQM[LYLaM_K[JbFY?RDaM_?SA\D^>XBZI]BYEZHbIeP9P9J 8J5P=O?V@V?Y@v5WWlf|££}glLbl8Y8Y7a9})K#UCXCW>PBWAS;_!N^BU?T@VIRCYKf%Lp2[s4Wl,Qd%TXGQ?XMUIVIY>h(Vl*Vd)Kg,Oc%Hp2\dCe(Pe+UYBR;S>S@QBTBSA] Nc"En5Tz?kS>R >R9Q=VBOCP6`$Lq5^U@QCL E["Tu:l}Ivq7^d(NvKxyFXOEJODoDpV|<|k/ep8d{M_LuYceglMWUKv_abg|S]HRFb3Z{fTq;X7M=K;R3In#A`9j#Co&@m#Be$Ka:2?=Ax+Jq)HbG]8`@^?^ 9Y7]:b9p@&<+?5F6G9G>LCOELRVTQYZ^][YYYZ`cj_^cecZ_]SW5@/GkCh>5L8OK^KQIUX^][\^a_^fbY^ac^krgelhferqg`hefaeej`jmleigljf^qopflekceee]_UplcUdad\hkb\e`leddeekaibkbjch^kan`mhpcl]ujssmcsorqom|w|psj{v~zypށz݄{w߂y|܃߅}߉݌ߍ|Ꮑᒄ}~{ᝊ㝉㡎䦍㪐妓檐䱑崕䴢谛趩굡縨꼪껪꺪뼮齮꾪ïƹŵóŴŶǰĹȼʶǽʿϻ̽̿ʺͺѿгҵϮЦ$FK4;h`\Sl_}cym{uƅzsÆvĊz|}z|tq~{k{orzrÀpxwÁwÅs}yxqyoxxpzv|tzrwovqyzpz{wovssursxvqrumorqklnhlmpnnqxrhttlggblVgXf]pa׀`uwyňċ„Å…ƋʗП֣ר֞љЖ͗Ō~xfdsUXQSTVVURW[OQPNKUOQHNPYGQJOBN:IGSAJ?GBNBJJSJS?I;I@O3E-A0D8N7HKVGWHRL\LTLdFVG\GZPcCSB^A^GXJdEZCYE]?X>\DZ=VB`D^G_DdP 9P 9I;Q=G ;L5N =U Q>VCY@U?P?R<\J]"M_CW@SDYHUFc!Qm-Wp,Sq*Rc'Li,PZBT DUD\QTG[Nf(Wm0Zc&Nd%J\#Ek$Ni&Ni,Rh(VSASBQ@W@YMUHSGYI[Dm7ZDl^FQBOm#>x)Ep#;g4bCi(JW:^@x,@p#Df#Cq%Ci=n=^;``Y`Uncucwq{uŀ{qmƋqvywÄuzs|o{p|w|v{q|zyn|ys|uys}svwutvz{yuzwx}~yypxq}vyvvtrjuosumlonknstvrkjomtqpol[sokVncl]u^ފ]n묁ww{ɍ˓Ҡբ֢ԥӝГ˕Ōrc߃VlS\SUTRPSRNQOQNPQTPQCJL[LQBKBMAL?K5GEQDKFMMOGL=F7J->)A+B.B5K@RFTK[KVL[KOOpI[GSHUH\DX?Q9VH[IZ@XC]IXDZJcD\=YBaLdJZL`K0K0L 6K 6I ;J2O:SIYGi)QHi`v{¢}iqN\x2KbB^:i9z>)I9BSY_Xuezlgo铁s|vv{{w|{z}y}xytzjgizgk`{v݌چl~^qYsnMeChJl!OZ8R@` K^=XCM8S?S [If%GUBNBOBa$Qq.\7h=_v/Sh,Lc#H^?WBRB[JO@WCVEg/Wj'Qb#O`G_Eg)Pg,Kh(M^L[!LXF[LZFYDTMZ KRE[$M^(Hp4]bKO ?T AOd(Vk.\TLONQIp;`\~f*[xJzkaWLg*\d#Zf)[Rr]qvo|5kd:xDrZq\ A[(H`?V :H 9L=J7^3Rr.Dr6w'Dd;]g=g@\Ca9e;g"Ce?r,Ia9^C`7^B]5_?e;k9y8(>0I.C2D>JHNJPAMLSSVYdONX[`g^[^\^_\_]YZdGM-Ft?a>yG2H>QEUEOQYUUa[`\b^__^[befcggjfiihelkifjjgkghg^hdnkhimgijmjmffbichikmijc`fbghiid]`Zdjdef_oiijj]f_e\gfmedalbj`jjlgurzyslqhvqvnqoxpvuxnxvނsv{v݄wz{䎇߈}ፆ㑁ߏ㐄Ⓣߒޔ☋㢈⨋㧏䥋橖⬏㰙籝浜締淣崤縣潭座뾭뺬辪龭쿯µõųĮŲ˾Ƹʽʿͼ̿ʼͽͻθθѩȱ}d30H]T[Mrh{hvkxiylŀswrÄ{w|r{|{ozy{o|zzn}q}py|vl}y|o}ux}w~xyt{r}s}xyvxowuxuzyyuyz{wvzyuppipsomnrpoqirninqdqamal[m]k[oVz\އbip~qs}}{vŌ̗і֣՝ԜМ̋ȊƄsd݁WgO^TSPSTOOLKMQRSINJUCKHPCI:EBI>K8G8FAPHLGMGKAH:F0F&A;-H1D?RGSKWLXKWJYJTHTLWEPLW?PAV=SBWBWCVB\;TD[HWA`LgC_EaMeG[B\M 7M 7M7K2L9M8N>T 5[Ej!RE\fvtmnYnw/Ic7]d&N_CP9PBWBK :O ;P;OE[$O]E\PYP^Oz>iMtNq=\k!GcI]EY?R@SBTCPEXHc'Sk,Wc$Ma%Me%Qc!Mh(J_ @[E\?WAi'U[BXA^(MUES"ML?TKX>h.Y{?xR=G 5R@X>XG\Ee&La'VYSM CS?z>qMzn.\c(`[Sd/]o8\T{Mi(]LEG DV+LokQ|SqqxG`|nzw[{Bks8rk+hYVd)Yy>l^dyU8[{DmJrW=a#Es.Xh#ML 8N AI5]?t(Fo"Ak#>bEc>]>W9m @s"Ed>{0Hi!BiF(Hj@bD}-H5JDUIVP]SWZVca[\c]gfe^bemplcphjkfakiliiljgdjqelmf`lgmdhbififhch`ilhchda]g`e^oxa[dckie_jdk_haeYf[g]g`lbh_k^qjnhlbtpnavlvnxqqpulurtp{qyg߅||r}vm߁vvއ݆~y܋ߕx|}xތ~▄ᖅᙈ~់⧏⣌婕嫓䭕䭗歚浠淤絟崣罭羨꾭齪꺬꿱īƶǵȴòǵǸƴǺʹͶ˾ɿʽʿμʼ˸ϼѼϬʰҝ+G0I_VfXvgx_}d{qxwlh{lxxux|qyw~}t|w~wr|Ăsuv{x}t{txysxr}uyu~{qwpyxurssvqyvpquvtvmllvrkuoqmmjpgphrcpcn^oYp]s[xZچ]bfpsrlywȐΣң׬֞ӛѕ͐LJÅn`z\eRWTJQQUKOGMNROPGKIQBKAHBL2FCO=L=IBRHQHTIUAHQh8bBp;$>-G:GQPg_l`zfepw얃xz{wy{w}韀z{{towhltl]jjځފguLgiGbF=a2aaEYEe$LR=QCH=PDL=QEOEVA^DaIfNq0[z9bMsEdu0Oh @a@[BW@WAN@QDM@YO^"Kd.Vm,\h'Kd&Pj9_f!IXCZFVDRCTHf$Nf$S[I_$IZ"OT#OSJRJ\#He0TS\MPCPA[EcO_MRB]$Qa*gYO_"RyCqn3Uc%Wg,c` Xl,ap4\W|_t5gICDNCFc6Yy“Ù̑sZevGn}qbVLyC}]#bc*md+]`kX|sLyUYb#K}JqscWAI;OCh!Mm#?v$FiA_Eg#JVEX?u*Eq Bk%By+EmDeB_>]>eAdB_9d>f Bd=Z=R 5_4\9b8j;r'E,A1?8C2B9E>FLPIOJSRXRQX`Y`YW[\\VWV^[ZVUVUY9G~'HdEm#L1H=NBTGTS]W\^b^W[Zaehe`\ikigiekjfapgmhifnnibsvmkpmhhlbd\h^g^g`jeh^e[idg]f`fdiccab^hch_kh_XbWh^i]dZi^i]j_jjmgnhpephspqktmtjwuxw}xxt}p}~|lۃzx}rxނw݄z܇}ޅzx⍅ߊwyᑁ~㒉䖃ᗄ✅㣌➎㪒㬓殑䩕䬕紟浠岢洢左翭꺦뽬鸯¯쾸ƷŻõð³ʷɸɺɽ̺̺̿˽˼̻̿ͼͻϴܷͭLW:I[Pf[sgycwbzmtlgjsivvwp|m}x~w{wxww}}n}yyt|uÁn„w~u{z~w|z}yyyqywr{s|uz}|r}zvwvsyrtvuopojmtmoqsopiqopkqbqhrcxhq\pYtav]rSwcكYۍe[lmfk~ʒОљݧԛӟϑ͕ȇ|e`qZbSYWKNMLFMKPFQFNFOMU=EBG@R7JIBMFWLVBQCJ@N?MT:UTDZFXDZMfS>W@SDL^ơ͐b[ƕqWu_yHkQzx?mm/c`#Yf(ke/[Wp[d×gclv4`yS 9F 9V@`>g?o Ai!AbG[AZA^At$Ae=h'Cq$Eh:a=Y9`"Ed=_<`?b;`;f@X]9]9h?m8x$?.D8F8G3D2ADIHRQQTSPRVVXY_e[[\Y][WW]ZX\SSLO7Kv?_@w$G8KEWBWIQN_Y[a_`f_]kgegfhlhfghfmmnlgfefb_iekelhrptwmldbigf_h]fm`Zf\kdc`gYeciehfc[dhh_mifbiaeleaa^f_c\e[jbjcmei\jfoknkmcqqzwsmuf~yxowrwkyn|r~yunwswwyۄvzކy|ߌ}━⏃ߘ|ᜄ㘁⚉ᚈឍឈ椐䫒㭔䩖宙汙左沞洞湪鷦繦鼩羯麭꿩õñôƷĵǶƺ˻ȷȹɸʻ̺̿ʺ̻ͼͿλιϷ̩俶m~EOXQl]ymygwjvelk^\fenkomslqhpfrrsm~yzvyq|s~rzqy}uy~u{y}u|r|x|zyq{}|u~u{zvpvvxttnvxrtoqvxsopnwnxuuqyjtjvjnerYtcveqXrVwerQ{W؅_ۈc݉cޏcvŎɒϙӖ٨՞ϖΖʉƅ‚xaZqV`SUONMOPQOPQLREHCOFR>IQ@NCNIUDL?P>KBR5G-B+E*D:S6H@PDYKOT`R]LWLXM]EVBUHX=TCT>Q9VBTLO=RCSETAf+Wo1adG` Mm1aj!N\I[BVFaF^Na%Kl-^o%Qn*Uo.Vh5Z`%NWILBODO?i1]m&PY@\Ne%P[DVIPHTFs?iK}Lj#KZGUBYK_G]ObTk/R}VxnyDrY\G ?ECKFh6Q{Vjbu@j[|c_oty@ru?hp3ed"QTPd&^YNuKjm^ƙff_EYN :N 7^G_;c;nCd:[s!?f?d:d;f8`6Z;d;hA]:_=^6X6`:[Aa@[ 6c9h;w@| =+F.B;K?F>NEPJLRYRXY[VWUW\^\^WVZWV_]YX`PSAM3Mm>b8|%C6J@OETRcUZW^_Zcgaceahfefebfpjjnhrvlcjlbilqngndqktupsh_kbjbi_dgihiehcfagcf_hcgi`Zfaibaec``U`fgbf]cb`Vb\h_mcprjehkljnisswrqkrgqf}wrisp|k}zzn~|zoހ~zp߀s߄x߈|݃z߅zߊ{ߎx~ߊzߎݔޓᛂߛᜒ৉媐⩑㩐䫓気氚粢豣紤润踬绥뾭齬轲齯²ŵĵĸƶǸʷ;ʼ;ɸ˾ʻ̻ʾ̽ιϴñ՘JVXRnWycx]yssjcX[`a``ejgmplemmnopiwwqjtnw|xnym{xy~sz{xy„v|tx}y{us{uxw~sxq}y|zupztusqr|rwuoxsjujulviun|qufqbucq]u]t]oZhRmRt^zY{aވdk}Ï͑ԛ֢٢աӓяˋĆ~j^ޅZkP^OTOLNLMLNKQOMCK=HYBWBWIZH`I]D_@YI]QfCS=O7I{-KP9P9O9MlzOxZdoWq>kh/Xh [PLaUVOh2otDiaoiȪťơc!GH8R@c]@\9`8`;c;j:u =%=(C1EAK?EIQKOOLRUSUSRTWXWb^]`XY[XW[Y^Z_NT2B%?dFkA2KCP@KDUSY[\\^bZ]bdbbbdfgdhiffgdi_nil`rrolmgibmhnipkrmjcohjeh_i_kkjbh`nok\i^j`fbb_d^gefdjbdZb]i_iad\e[h^onoeumoemrnfqfnjqmtgtmtkymsmukzl{v|m|n߀xszkv݀s݁x߂}ނoހtއ݊}߅sފz}ޏ|ᡃᝋ➄᧐㦋娋㪑䦌㮛鰚객津淥趥軡鼧鸦繪龯꽳꾱IJƹźȹƸʻɼ˽̾ɸȼɼҽȺʶ̿ɼϸкͮ౭`gZQx`|_~]pXmkPTRWXV]afj[[chbbflhdjfmmnhkeqksjy||p}s}sw|y}t~vwzvxs}tv|w~||rzszn}v~u{vpoylz~rhwo{z|kwk̀uzjyk|oxcxbpUpaqakXeNhRu]|Zېst&ƍ˔֤٦ס֘ԘϒȎvf_vXgYTOQUQPSSOQKOEN9E@FGRCP} 9.A4BNMaSmcvcfrrv|x~xywyyxs롋v{렇|vznq}tuefamrxwܝyzNqnC|5WCfHh]H_ HdKUYILCF=TQb(NuAg^{An`IW>SDNBQF^UZJl0`X[Ij(Re-^p6zNFD 7VKSDQG\T^!Nc0^}OqtZv;i_"MUEXOZLb%lm,]g3`siͱ̦[oSf:_Ci"Bn#F[=UGQ<]@v$@m7e!@f+MbAaDY=`;eC]r*I8TEW6HNZST[]_Z_Xeggda]fibanpjfegjghlkdhhljlhhehamfvmyposqgkbcgjie]fejckghfj`oijZf\idebddbZgldfi^lakcgbd[iilfnlmhjnploireuttpulyqwlzhvswnzp{s~q}ls}rރ~߃t݄}~q܅݆}ޅz܊~wu}⚁ޛᝄᛅᛌᣆ䠈⧐㥎䫕䥆官寙洟浢䴞幫縣綨罧轲龭쾭￱ķƸɸȸɻǷǻʾɾ˷ʽͼ̻̼Ϳ˼νѹѷ翶|[St\dsUdW^YHKHRPXVW[dQTVbYY_i^acbjmnojpmhpnqluyywxy~v|t|{u}wyz{~~{zyxxwq|vyqvr}v|vpvth{x|q}|sǂwyd̃vxl}]ybxhu]rYvapclZl\lSykx_ڎt~ᅣǖїٟ٢٣՜Ғ͎ȎqaitUdPXONKIJPQLOLRIPMSDN;P@L/F=S;N=LGSERIV@O7E5M9N4E,G0H6IRFUK\KRNZDUISBVBRAVE_;U5KWFO@[FST=`&SXBUATEWKe"Mf$T[Ac$Wt2Wf%Ii+L`M_%OXK_/Te&Nt8ae!Ka&UU@bIc%J`BcBb!HbGe)Mg Ki'L\=Q6VAD @J >ND]'KxHuS}l'T`IWFOCRJTMaRq4jx@xggZ?\@s;os3sN dfyGse"SRF_S^$Zu;vv4pXGvFs]elyZAI;R;a5d5e=ro={#>0D+A-B9MGLMLMVRWSWQPQUVV]Ycdab]XY`YXVSMO9A;dAbAx(I6LBPBMMV[\a\_X^Xf^_a`\afdeihlhgggfc`i_lkikjbhhkbnpnjsnqhkijgkghijekkh]nbnlo_mfjZkig_kdeaaWef`_phi\mid`khn_lpmakcgholkesmplrkszznwqtnyozpzrvvzmvryqzs~tnۄxރwބvޅz݇ކݍߑᑂ⒂ޝ㖈㝅ߢ࢏㥈㥎᧒⬓㥓Ⱍ䱢崝泣嵝羨鹨繦约ðƳȼƶȼǺȼɻ˿ŷʻͺ˿˸ͼѶѸȸߘ^UmWzcpS^`XT?N9O?KENZ^DHRVSYY\UZ\^af`d`^edjioklpiorpwvtgzvt|m~yt{xt}{t{|~u{uxxzuytslpv}lzs}s|p}mˀl·wnjtdxlwct`xpq^gZmasZɂiےp|Ǖј۬؟٤җϔΊƇ}oZ^lN]KTMRRMIORIPHMAHDT=L;L9H3I>O?HGTJYCHAN:I0C)A-E+A0G7G@N?QFQBYM^O[KYHXN_IgOVEXC]@[:WFXCY?SIaG]L_G\G[CXDXHZ=WBN8I~-Jz*@k!@M;M;O2Q@O?L3H 8MW>\>[F[@X;\EZB]!HWBQAUBW?TBW#Ib(TYFQC[Ea&Ut2_^G^"Lk+Uj)P`"M^NW I]KY"Jb*Pq6_w9\i,Va!KSEQA[G` Q^@_Dj(Rk/U_ G]:Q@P:N>O >OES@n0UW}t:a^C_E`KWHLIQI`Pn/dWkgfYg,_^!<~Hd#_S;_)N]'MVKOILKH Ba(VxMhE|]IYQU Mh*]wAq?{m,X|Fzi)S{Cass~GhO 7H 5\=cCc:i =j:^N;MJTTQZ\c[`X`Yl`ffhee]chtjheeefcigfbmffhe\lilepdkljbp_pjtml[limbj]j`k^jcpbk^i_icj`gZd\gZhbd`mci]f^japskfhepinctrojmgqknfrktoxltousqf{nxswnzl{vxxuzpo݁{߄tރx߇{ᇀ}}{yߓ~ߕޔᘈ⚁㛇ᦏ㝈⡈⥓㩌⪖殞筙氛䴝䶥繤湤縪置翭õķŸĴǶɻȼ̾ȸ˽ʸϾͼ͸˺˸ϼҶί㮫ofoSo]WNSUPSS=F7M?M=J>K@ICOELBQCZ1I0@-J5Q/A4IT 8T 8N9K /E0J3K 4OEO=\Fz5XVnm}|xz_hDXw0Bq?w$>#<,AVIN=V?UBY@Z>cDXB_'JYDW@YEUGRSBSA\ IVDS=_%No4_g&MY?f)Vr.Xh"OZLTGZ)V`"T]"Pf/ULg}>cp6Sc#LVGP@N9ZDWQ:t`GbL\JVKTL\Rj.`MihfwR[#Id0Qv>wd#WT?ZIQ@F @OEOUT"Ph/Wm|_b#TSPUN`)PQXXQ|r1aq4cxCXkw3WR;S `6f?v+Ak"Dbk?z*A)?*B4G;DAHGKKKNSQTQWRSPRX\X\[]^]XYVWUXTWIU%DiIaCjB5L8K@HGS\a`[c]caaYeeebiba_ediegggfougdcdmlggmdqilikgpnlgpepqj^hgjckdhckfobjhndkelfniicdWfah_fcd_ieh`f[fXnfh`fYldqsmbllqhnppeusxk{oxowyqczpwqm~vykus}yzmށq߄{|z~xޏyxᔃz~ᘆߕᕆ✅䘀䢋⪓稒嬔気嬚䰛綢洛洟賠黨縪껪뾮鿭ĻĵǺʻȺȺ˼ʽɻɽ̿˷̾̿ʼ;νϿӹѴ㿷ځujUf[HJ=IBG0G0?5G:HP[8@5A?GDJEMFOKMJQVTY`Y[al\_c```knjlhnsxstoptquptwwjvyrnz}yu{v}{~xzpzqxlxmwnk΃tΉ}ӊfшlւfԀc|^qUz[tQoVmTn]s`oXzaۅh{ƍ̘ћ֣ٟףғϒ}uaYsUaPYNNLMRFHDJ@I>H6G4G:I0D3E5G@NAKELIO=L9L2F/B#>'?)F6I=TGWPeRfLZJZJXCW>PCSEUJZ>V9L:N?XDZDVLYShNcN^DWEYAP?^AS=U}3J}+H{&@u"?f>N :N :M7I 0L 7J7L :K 6TC[Fr,MQnasx¨ŧ|z_fFYw+Fr!Av>}#<1I;IHCb^g_x`hot욃zr{}}zw{{{잁s~yv|wjogvYk^_[[ajgp}Ed{,Q{4XIdy0Pm!Mq+P]>N ?K;PFO?VE[FZF]B\E[EW=^!MXDW@X@S?YFQAVE[CYHVEa'Tq0Wa!HVDj.Yq3Yg$RYHSGPIXK[$Og3Vv:Zx;bp2Sb$KTAP=R9YHT?V=V?^!H\!JWESBQASBQFQ ?\Fr;g{Di\GN:YAh)Vi)W\NRM]Vg"Wq8hhmgnyk2cVAh1Rs5_g(WRCK>D 9J?SMZ R_(Im4VxMZ}Pvp,iOLQHa(L~Eyfla@@ww?W|omDP 5X6j:g9m"Aq AfBU 0W HR9]@h:c5];b9]<^=[<]:_9V8S 1Y 2U ;\ 2[9ds#@p#At+B)C&0@7?QGVH_CP@WDZ=TE[?SG\O_M`ObJ\>TE[FU;Q>V7Q|3Ku%@p#@m)If;N 0N 0N 4J.L4QP=XC[Fe"Hc$Kh*S_LTCVEX!GRA^$LR?TDUGT@a#O_Na%Om.[i+LZEY#Km-Wk&Sc"NWHVNWO^!M^#Qn8]h+Oq3Sx6[e I] HUIO8VFQ:Q9Y#OZ!D];[CYCR=T@O:S>`$Mo8^l-XTQD\"L`-Rl;]k.T[%Di(^SJPHa*XuBokYFiLyOGipd{\8N9] 7d:f8g:jBa:Z 9Y>S7_8b=[7[9]9^!6\Fb"Aa 2Y2T2S 5S 3]6b;\7d>q;y'Gx+D~&B&D,D.B=JGJMMSSMNQURNUURQ\\XXXR[\\Y]VYSWL?J+:j>^=j>3N9LBLCQTXe`dhfahbf`cW_\fdcefdnkiikdkdkhldpmmgnjj`ogmqphopmgndrmhglgkgmejgl_minhgdihf\fbdZb\ige_ibi_`beafbf[iemckcidhgogrfnjshqjvuqhqiwnustkykyrwi}v߀uzr|q{o}t߄܈v܇ۈv߉{ދy~|ߓ}ߘ㓋ᔃߔߚᙁ❆㝈ᥐ⩈⮖䱚㱞䯙䳟洤絟糠涤庨軮ıöµǺźƶȹDzɻͼ̺ʼʼ̽;νξյӹݬc_GK4H7J4E.Fy9<,<0@(<':5C8D4B4H@N?JBQ=P:DESHQMXHUPWX^Z[]e`c_m[]]dnkljknhppnnuipsqtvvw{{xq~sDŽ{ψs҈rЉ{ӆoАo҃m|^w[x`nUgRbNfVfOhTnX{_؆kz췃Ï˛ϗ֩ڣٞ֗Ή|we\tOdRXQSNOOCIDM6CN?FEP?M@M9H+A)H(B,A.I7J5KHTO_N]LZHSASDTCWKYHYB\BQGY@^9T@VBYOcSbQaPgGXE^E^E\7SFX6E{6Sv+Es!9jI4I4L7J8K 5J 2I ;M 8W=[Bh#J>\Vom~åt{Wi}3Lq&?n!Bt@#<1AJKYQi^n^|homl{ut{}v|z~xx}uypogc}bt`aX\bcnRfT|3Yv*N7a8[9ajIT?I@J=M@[EYEf Ml+N_@[FZ?UDU>SASBSEVGTEUF\Gd&Qj&Qj-Xj.T]FUEZ$Rm+Wh*Vb+OSISJVNWG]#Kn(Qd!Fj*N>hg"K`DWGVBWBX?XGSN;^"Q`$F]B\!RQ=Z!j\"Pc,XRJH~H~D|=ygt`r=tS!K\JZAf*PyB|n1jO?O=^"Mh*S^<`$H[K]GYA\ T`"It]9f7j5d9Y/K|'=*C+>0E4C:HHJLORROOLMVSPTMVNURI\\\]VSYSZZMJ2Dw5[ ;a@+G5PL:J9K*A=(B/G5I?RDVIQK`IaET?RDVDVH]AUAUAX=TDW?\DYAVB[K[WpSdN`H^CZDW=QD^5N3Hv.Hr=l=l ;n=O 4O 4N:L4H/J1N 5K 2U<\G^Cu5YXx~ƞƨĤŨ£|st\j7Ml;o?u=#B.>MR]OdUsf}hmqmxwzx堊yvꝀx{霃yw휁ysmh|`~gqag__\aiOkMlS?R7i#TX?OBYLWFi>d1gRDh4[ciYR~DOwu{bc-a\$TYO]Ok6VMq3pU?WCn.]_D_Je&Zc#SVMb#Zp0\Yx3ee$L@rRt\ul&GR 6Z=Y8^U :T4]9H4B8@3H:F=HEM=H@KBMDQGOHVDWMTK\SZX\YbXcXb[e_fgkqvkmsqxr~{{pʁ}͋tыyӕ|ԓrҋtЇp|jilXi_iWo_lXl_iRՃhߐc˒ϞҤڣ٦֟ґʅseVvWkT[QPMIP=H5DG>L3I1D&@'C0E9L9HIWEXLX[mK]CTCVBT=WC[APEYF]GWTg8Zgb,WA =OJi6Sie\~KL}ioUtgz>q`#[VI`#Qn3Ty=uq-i]Gj*Wq2[p-Sp2`s2gbWh,WUh'NS>i$Hr.H?TKUc@\A_8[ 6d9f8e5_ 6R 3O6VAf!?a7\AV:Y7[:\CYY5Uq9S =\9p#I;W9KBJPXXY]PdicYcd]W_^ibhe_\bc^[bigbf[twdblijbmkmckem]mdqomfmif\iampjZqhndlbk]gYd_g_jfe^c_c]jhe`hbk_e\jebWgdbUd_i_m_f[lgi^lbqemanfiaujqiskniuguezutexq{j|gw|y܁w߁t߁x߃wބx߆w߆x|}ߍߐyߔᙅ{ᜊ㗈㛉⚄⚅㝏奋䯐䮓㮖㫗㱝履岡嶢巬继缮껮쾱´ôŵƻýǻżɼ̺˽̾ͺ̾ͿнӼӽԹϽϔAQ*A4M9F>MEQ:L,C6J4K4K2J1H5L-B8H,G,E0F6E5F>K:G8J6I6D4CAJ:I@NEPERNRIVQZLXL[OXYeXdgkddrzsrxivˀnόvҍqӐl׉gЄf|fye\a̅Z΁k{Yu^{]~Zߒu~̖ӥբգ؟ҔΊǀzuY[nSdKXSJL>G-H4G:MEMFXBKBK)C%C3J=PEOIbDTK_QdKY@TARC\@XHWFTCXAP@Q9PETFUL_GeQcKcL]F]AYM`FX>V0L0It.Il!K3K3H1J 8I 8I;N9I 6K8P 9^Gp,S]s|ǨŬŧĥwrikI]s =i9{:0E4CEE[YdRqdxeisvxs靀wvꞆxzrwu|o}qll|\~_remg[[K]Nkc?fw)I:ZAbGimFR;RGL@SAU?m%Lh#GX 6W;TD DCDPAzKc}Ewu7o}EWqYiģ\yZ;\@R:UB\8`?] .i"CnAo>x">+?7J2H2A>ECIRONTVWNNXUYV[VNRSXRTUXSQXOPXST;I|9_=VDd9|(FM8K?LDQ7K5H3O7K6H3G6L7M-C:E8V3D.F-B-B)>2B-@-A4E2D4G7D:F7G:I>P3EH[IUCWJ\LZYiW`Z^ijllrjxq΀jЅnшkЊiӄrxWwfҁaԐ}ؐ_و[ӇcՀXт^}cԇesÈ͔Ԟاإמѐˎ{qxWuVeQYJII?E?K5D0=+C*@#:-C0I6H7CAQEL9G8J7E/C.F,F-D4K6IBTIXL[N`J`GXI`FRCZ=OE\F\DS>S?T?SCWP^@SMdP^WsScC^OhJZHcAU>Z5Tv,E{2Iw'>i!Ae8j6j8Q:Q:M 9H8F 7F3D-G1H 6O<[Dr,V]u~¡ǧǧȩƥàymvWh{(>s>{#;'D6JEGVReYtaz]nqzuxyxp은ttv{wzxy|skbfqag^NQ?YVtlCev(SBdC`GoeFK>K 8F ;U;\GeB`9V ;M7VBX@V@O=U@TBQETGXDe*Rn,Xp/Xj)LXIQHTESFh%Lq/Th*UTJRFPJZLU Fd)Sm,Tl'Qi.Pt.Vf(SaGe&NdDi+Rf#LYQ 6XFYCWA`IZ D^IYEWA`!QYA`0RrCfQ ;Bc?X&=DMO`MXXY^X^[aZbaf]c[ccc]bb`[ccgtca_`ikfejcslh`i`hfkcf`omthiff_ckhehhjglilekfoflhh`h^rijjgff]g_i_dWlkeYe_bY_UaWged]cUg_icjcn`mdh^igrjsig\kbqmseujtgxownrh~r{q|k|rzj}qކv܆zߊu߉xzߎ~ߎ|y~ᖃ~☄ᓂ㚄䞍䤉䥉⬙⦓⮖欟尣䰢浦嵪纪绯述µĸƵŻĺǻȽʺ̾ʽʼɾ̺˾нкӽԷԬ༲_c0N-A:J;L4EFYGM;I>LDZ=L9I|"@2?*?/Lx&>x"@{)B}+B{2G|.B2D},D3Bx/I}:P8N{2Mz2E9P>NIZOUbeadhcrhw_vczbzdтfπZЉiۏeޘvdݎfن_؂\ԁ^׆dؒpxƔ͚֢٣ף՝ΏɅutc^pS_KOJAD5B/C,?%=:~8~:&>)?/D4G:F>I:O5F:G0F)@-M,H2G@OGQFYRZR`AO8NBQ>UDPFYCYESKXCZ:N?ThcDeFlfIM ?J 9P=XDf"LcET@T7QJUBUAT?PAS=OBRAUCp0]t/Vn2Wi'KaLUFPBUKXEr6Zq4Zc!HRFQBSKWGYGfLm/Sj)Me#Mq/Tn*OgQ^!Hi/Xk+Og$IaER=P;P :Z H_H\DX@]Ad QcL\J]J[>T;W@O >H@J FLCQFiq=';9L8I/@=HCHFKMOTZUOSTU\TQTVSZa`XZWTQRXNHK/Av:U 6T 7]9z)G4EOaN_SX^\bYcWfZedc]gZc]dd`]digcccgehgejnklgjdijlbmfjljdnhmgk_olkilekmkeqpogqjmhi`jbgYgdd^i`haedl_d]kbe]dYcXaWb\iee\cadZpnhZkcndogl_qgqfqipgnesdtplvjxh{mzpzkxm~r{hut܂p݅~މ{݁s݋z߇t|sጃ}z~ߓ─┆㜆ᜍ㢆ᢋ嫒䪕䪘嫚䳞䳢沧浨軨귧绩齰뼬µôƺ÷ƶǶɹƲȸ˸ɼ̾ʸʼ˸ϽοѻҾ԰Źw,E(D1H?K5BHSBLETDOHXBLAU7E1H=L2DEW4K5L1F0H(?-Hz'?q >q$@|&?t-Bs%@u+Gs!@v#?s%Bv*Cp%Es)|;%A)>-A6J7F2E,F-B3H/E,C8Q4L;IEZK^O^S_TcAP:R>P8P@Z=OCVCTA\BT;U@R=WDSI_L`NdMdOgI^E]BWE`?W?Z1Jw*Ak#@l Bj!@k;k@o HU=U=O 2M>K3K0L1M 2L3O>[Bm,VSiũȨȯǧßlvhvz-Ap8p<'=1DBHTUhYmeyotuvttxv|xzyz쟀|{ytxgljo\MS)D5QcvfHf6_7Y?]Ah_DQ BK 9SBb#Od"KZS>SFXFe%TBim&Le%Jc"NbIUFQCSHSCt:dt6a`MW"ORJVLRC^ Om(Tm,Ph"Ld%Np/Ug&Qi)Uh0Xi,Ug$Q_Ce!H[IS:Q@Y=aIk"OX;` K[HaH_FW?ZDN :H :QBD ?PBXSYMQ@\&T|MO{C{Rfk]lsNw2^Zl=jP]:];V1P@U=`>f5Z6S4W6T 5V 7Z8Z6X7U1X7Z8Wl;q?u8)?N>NHNBNFWHN@RGP9JBLBPHR9I:F5C?J.G;J,E1G'@1Fz)Ds$Du*@o&EoAq#@g>n :i;f7f8g6_8h8g6n"=t(A|1I8GCKNQPLVSYR[RndՅt۠y{~wuݤk؏h{^Մ_ۓgu뵀ʖ͕ӘԘՔόɄ}q[dpS\OIF>F3@/G'?| ?|Bvq;-D>HAJYQfTr`qmrwywy}yu{zt~ꢁ||ퟅ}uimdre?I!EE_`s^vC`9]:]6Z;bcML@QBVCdG_"BQ;L9T ;O;XMFe3cXT}G\o|h`|zS^wyFkP}F{5ex6XOm]Fxt0ZVDJ?SAU 7V?XD`:c:g=k$Bg=]5X;U:P7X;e>^9V?Q=U 5T 4U7W 0V8V 3T 9W:]5V 9[9a4h:n"@~&H}+>*@:C:DQ2H8DMRIWIS[[{mޠt泄y}|vߥjژjՂ`ڌefsÏːє՝Ӛӑόƅsbi{WiSOM:H;?+F/C|"@uDt>r:y:(C2J.B0I8N4H-F.K3E,H6M?UCOFUO\N`ReMZP_GV>Z>R?Y:K8O?V9L8O=TASEYBV?VI]J]MaLeNcJdI\J_B]FT5W2Kq">l?p"?n:j8h=j[;[8e@`=cH`DfAx8WVmxzƨ˭ɬŧŤÜYc}3Kr#Ap @3F7EHS\]k_t_{puj揂sv|w|vxyvszxwv}}wmf~^odAQ+P@Scti?aw,Or)Mv,Pr+Z[CKBPA[Fd&Q]?LFQ=N:R>XATAO>XBSEcIo4\o/Vm&Gb MTD]Fc'Q\JRDOBV@g+Nh)PaIQANDSAUEe0Ru;Wn-Ze)M]Dd"Hf'SbDa!P]"Ih&U`M]Bg%Kd!K]BY@V@XBREP8S;Y?^"Ea*Oe&L]GSAR@XF\"LRCUFM ALGOAj8h~OZX]zdP}gsT{WxXy9_@pEdOk-I[[|>nk,YR:P;NPJSSUYZbZc^_W`\d[e_earf`\e[d`geebifjfhjfgibnii`jhjfece]igllnoncfdolnkkeibpirhmig[milekek`med\lbk\maeRhgkggcf`g`d^f]a]fckajXhakah]e[jdjbleqjleo`qiwjsgxhۀt|qys}u}lo~nv}p߀orm߅r߈݄q݌|߇y|ߎy{|ᙁ⚅㞐㛊㣊ਖ਼㦕㭑⫖䯗㮝䮢縤縡绪蹤轪黫³öĵĶǹŸƸɸǹʾ˽ͽʹ˿ͿοпжжҮĴrw/E3F8LEQGRGPJVMYIVLTMRQYEN;PIP?N>I>R=L=L7K4G1G1F(A|'D| @v#Ao#>pAl>e>a#A]@[6\=U<\;W8X9Y5_=c;k"=s(BDV9MV^qeؕu{빉~츃tqnݚbڎaڏfߕič̌БјӔщ̍{qbXrP\HLK6C.A+=$Aw=q}Az<+B1D-D3F4G/?2H-H)B/B?VCSGPMfHRVbRaXdOYK_CU@Q@TP:S7LAV@XDS?UGYJ]HVPhQhI]K`L_HZ?R;R}3Pz1Gj$9k!=p!@m9i7i7g6f8a=a=_:d5h=j=n!Em!Cj>qBkAy3UXrqxţǫɬˮʭǧ|yYc5Ks">w<)B;KEJTTe]pa~pwuszzs{|vzt嚇xy롁t|횂zqlqamc?L8]ARgxqBbv)Nm#Mk"Gh!H`FL>J8ZHYDS;VAS=V?V@`"GUAS?]Ed+SaDd H]Gf$HXGP=_!Mj*Wb#HUVGR?J;NIP ?X@c&Pc'Pb!I`'RQHWA`N]JQARCL>OJKGe,]{FxUPY˛eOc~~rQ~~CjFq6aJ@{p3dMtJgt7_t2d[9S?P;X9_7d=e=d?]6X 8[:Y9WE[Gg%P]%RY&VX'PT>V>\9`|'?.I'?4G:GDOGKFDNWILWNNUOPU[TUXTWNTQZUUNHH*={/]9X 9Y =g>|%@6IFTOY^]YYdWbZ\VbZllj_g]fbe_``hcg`gbehjbnpc^lai`f`fbj_hffadcdalgmeghmippopignntmifhapkqhqiohn_i\hZlgich]`\icbYlln_d[b[g^e\h_j[lagYdXbYj\kfldnemhkaqasnxnwh|tzouixn{k~mރwl߃tn܁wrށvw݉{އyzߍ㐅wⓀ}䞉⤑㝆㛋⣋㤉㣎㧒ᨒ䩖孜㳦洦幪踨縤꽥鼬´²´Ƹ¶ĺžƺŶɺ̿ͿϾоѻлѵӯ˵˖=N/CQ7S 6U6^Bd=iAx&IDXc`υnߠ붅ツsw]܎k܎gߗp}Ȑ˕͍Ԟωύljvf_SkPLH9G2A%=+C}$=s;q>y=+K*F,A0B3GMB[HVRhS[L]M]CNEU=O:K?YCS3M5OES8S9Rn8f7f9gOq$Y;Ui|~Liv-Pm'Rf$L]Fh$NT>RD^CcGO :VBR;V?L<\@\Hc!Li&OeG]AW>Z>]FWDT@]!Ej%S[=S;QDPBYC] Lf%RfOSCQ>^Ol1Wk,Uk2U_"Ee(Pc(Ta Ie!Lc KdGf$Pg(S] PWE_!Ge,VbDWGQ 8Q;RBK 9Of>_=X9T 6U /[.J':-B6G:GCLGNLJLNQMOPOSSORUPRPMagWNYWJG3>z6]9SHLSSSbZ_T\X`]_bd_g^kbe^g_lieadbf`h_chc[e]fcg^ede]hghahfbbidjrmgmgjbnetrldkjloteplkbnkl]lcl_jhg`g`k[ipj[e_ebd_e\gXedb]b^g^idjcmdi^b\j`h`h_jbqiplmjl_r`phynuhvqrevp}swqxlowބy߁p~l߄v݀wxuދ}ޏ{zߎz㗅埅埐癄⟍⣊䧒⧘⩖ᩗ䬝宠㳨㵥淟繨赩级滫龧ïôõŷǷȺŽŷɼɽͺ̽ͻͿϿμѼжѵά֫IY6C:JANESLRJVR]Q[LTMUHQKRMWKVMUOYDTGVAMN8P3E5I6G,A1Fw+Dp"?u =h@b>b@_>Z>Y?N8Q2L7N 0N 4M6[AcCv$HIWtnݘu赆ÃÇÆ{y[ލXځ^ۊbzÇɏЗЕӐЎ̇ŀskZwSZOAF/?%B~@yv'Cl:jh6o=p 9p 93J7I2D1H0I~0D|(Ez.G|*J=VQjivɨŨɰȱ̰ɭƫãyyakCUz*Dp!B0I;JJNTL`Vodyfnmqwx~pyuvxuz~szw~z|vkj{aXT@fLY9ToyOn~,Qp)Od@_GeKOS@YIYDY D_%Pg"IY?TATBVKTD] Mg1Zm%UZETCc"Ps.Xg'Of(J]Ik-Vg&TbG`Dd%H`!Kc%Mk'S[DZ?VGXAU9T>N6M:[NSAM:NCT8a&It2VfJ]FN4`Kx7ga#JWDYFY>^DTOJEUHp=pOn|vxt^r8vx7oM^gTazO}7bU=KAM7S 6cp Cz&Jw<)E%?,K3@7I1B2E,H,C"F&C*O9T?RCXTiViUaPYG_DX?R=W9J2R;S:L\7M5Q=SBVI\KeR^VpUc[sPaIfHYA[-F-F:JV;R:VAP>YDU?XFd)Qf%M[ GVFSAW"OZH[Ff'Sg&QaE[!Kf'Sp+V`&NZ I[Ff+Qq3`fH^Iq9^]!Ek,Rm#R^DY@XCWEUBT:SDN:YJZATBQ=K7T9_9e#NcQT=Z"ADso-Sa@d#RYGYBZJH DE AXJq8^UsogtxfQ}FuIriK{r#IDOjr`UT>IDM=Y:b;gC\6X=XDX5_?R:[7V5Y?R7R:X5^BS 3R ;N 5S=U<_@W6[ 8`L@SHQLXGVNRSbL[NYRVWWMVX_JWMSLQFRIVJX?P:L;QLAL =G 7D 8L =U>&IYYڄ[射dʼnDžɅȈui܇Sւ`܈Wߞ|{ǐˊ΍БΈʅylމRlQCC+>*B}$:s$Dr;l=t#Bs!?z!B+E(D0G-E/C1F4K(C~&J/H.J6N=PBWJ]SdWhVd\h>R?W5NA[5G:T6UOR|/K|/Ky.Dw+Hq'Dq&Ij#Ee=j=n!En'>?L?LBV?L=K?N6K6O>T>WD`I_]qh||~áƭβΰвͯȤfjO]|1Mx(A,D:HHMQHk[n^|kyo}r}wq}yy~{y}{{wvqmhp]JXPe;KRpqmRhEez1Y^>W>T?R 7\J\F]AWG`L]Le#Lg+Pw8^dBaEXFWCWEWJRUBM>P7`Gq,ZcP[:s5]v3[f%P`HS>U@P;PGIIMBb#`l3Z[ycuț]V\RIB~~?mZqi^^>N=VEaAd:_CW?Q4X=W;V5Q;V;R 5R 6O 5V4V:R 8P7U 1WLU?]>_3]8Z?b7i:|)F3E.@.G.C=HBMCKIMONSPR[ZUPUQORR^_VPRLXV.C8MOWXOZ]]Ye^^WYObWece\ebd[aXc[e^geeYmeobjfdahgkib]jdidhig]kdicjcjig^gcjcmfromjlasoploblji\pwj_mupfrikaphi_fZf_g[ljibiag`mheaj^i`f\gbfWl`gck[ohg\i^h\ljhcofrfmfrotevnqgrfvkxd~n~i}qށr߅v߀u݀y~xރv݅w|߉{ލ߉xߐyᕄߖ㙄哆㞇墏⦔ᡋ⥎㬕䭝尢崠粡鶦鸪輫纭绰潨翮龳òûŹɼȽɾŷƵɿʻ̽ͿϾҸӷδϢKX5E5JFTDMNYGSKRR[O\Q]NVX\KYVXITMZHZEQBRFUG]ATBPDVAN>X~4J,E-Gu&@p"Ct-MjHb:_3_9XP 4T>%DLL؉cwċǂɁǁk]ډT݂[fqyyČǏ̋͏̅ŎmqߘdwTQJ2?}88w3m7sCr&@*G)B0C/G2C,D*H~(J,J,I5PATCTL]M_P][kNcJWDVk#DFSFSCQFX?N:H9J@RBY;VAWQg^vfwyŸ˪ʮ̯Ͱʭǭ{rrWb6Ix)C5K8LIMTPgcpVypsxxys|wxtvwuxw}xqxrrm^M\`hCXTij}b{Ca;\=^\BO :O:SCZG\JQ9a$Gm)Td(Na"Df%Ff GWC_!DW?X?ZDU?WBW>^IVDY@VD_GU>XFTC[#IXB_Hb LW Gi+Tm0Vj*S`LZJa'Pl,Vu4gd He"Lk,Xa$Jg*Ng$N[DTDQ9XGTBTATGN>RBX E_I_JV@K ;H d%Hv7ci L_I\FYISBUMXRKBf,fg,ai-U`pirt_xGuKv=uN_h{a^@PAW?cA_;Y9V8Z8V8Y7Z8V8[:TAR9P5V9W9X2O 8L/V/U 3Z 4Z6]6`4j8v!?-?2E'<+C/<5F@LGLPOPOUNMKUWOKWOSP[XYQOKFK5e7] =T0d)Tc9r:2K9NBIUVWSb^_VaUb\\Xe]pibXh]dbcXba`\gce[ndn]lglfdVooe^ibdgj`mkjgfdibhchba^jfrmpihfl`ohkfnfigmindjblfnfqoj[jdf`e[kggXpnnhf`h]jaf]dZich^lhkXfcl_mdqigZc[i_hek^nhtnvqomxbuiqithrgyu~k~x݀s݀o݃xu߃v~x}v~uދzyߊu㗈ᓂ㖃⛁㜄䜏䦈⥍㪒孛屛䱙岠䵡紥綥漩纫缱滭辳°øĵĴȺűǴǹɼƹŽʽ̿ʺθɿопѻӲҵڼ[^1G8K:P[;Q=T>J7P?QDZ>$AMKقkm{ŀ}}n_܉_ފajty}ƊNJɄɎx~w[vWVH8D :n5|!?o=k;nE{#Gw"@-F&@,B+F/F$=}'@'@)A#A.L7PU>S?UJbQa_rZl[qVoPeQaKbHV@Z7S3K~-L7N~,I{)Ap$?p#@mRFM];\A[AWBW?U=XD[CUBZA^D^CZ@V<]H`GZFWFXF[E_KYDYJYAh/Tf+MfFY@VCf%Sm3\v9df"Oc*Qq0]g#Mf'Kj)Qk+QR@PCSCVEQ>QU>]Ba>Z*=3BR7K.G9Oz2Ow'Fq*Bn(Aj!D\<^=T9Y9R>P=TAb9*ESV~bi{z|ŀ~xqktjzﺁÄł{xdjZ[J4B'?{6e?u:p:j;n=u!>}%C{!>%>5D6J#? ;)@$<(@0G1I6NEODZJaTbQ_UgScJZ>O5R5L;K1I5Q1G3O3L1J4J>V>SE\G\MdMgXk^m`uJ\G_GZH^?X;R5T;R6O;Wx)Kx'Bo%BjVAXCW>VA_ L]NZFg-Uh(LXDZIXHXDUBW?X:W>b$D]D[DVY=W 9P 1M 2M 4O 4S 4Y7]:aDb7c5g;u8~)=*<.A0B0<1AINHGFGQVYZ^XPPTSKJYYRGUKC?4a1S 6Q 4P4^;r">,H8IBHMVYX\ZYS[V]Z^]a^a_aUc`g^e\ceiac^aWi_hfghhbmcied^kniZhgdanhkdoog[qob`nikskfplmcn_mmklmgpfmnjgnctkniqjohi[h]nll^mfldj[faiajXddechWa`ifk^j[gelamikblfg[kih^ienho]rkuipeunsgsjyh|k~|{k|qsyn|qrރsޅx߆u߉~|ߊz߇vߎ~|uxߒ㔂䗁✐❊㣊婖䦖妏㯠欙岡賥給洤湩滥罪轲꿶ŶƺĺǾĹƺǻƹλ̼ʺȶ˺ϼ̻Ϲѱɲ˒EW.B5D>LGUFPMYUXLXTaRSPVRUTXYYQRSXOVHRIU=RM]@QGV?N:P1H5H7N6I-I~-Cr%>v-Hn"@a?c?\>W6YI[Bb!IkI)EOOx^cu|~vqvxn|Êwxa_؂U^I=A!=w:q:kAm;c7m>p=tC&C~*B&A1F2E~)B!@~">(A0N+C6HU9K|4Lo%Cr"Am!?i=j"Au+Hs(F;O;OAVFTBR@PARK^H_NfXj^pixs¦ūưʱƳɬƧ|ugoGV+A4BAKENRS`Rm\zjprryt{z~t죃}}~xwtmulnmk^ENVnGgZkaj]yAdAa5__C`HS?ZEeK[9S7UCZGX?YD[BVBXBW>V=ZCR;YDX=YA\J]DY Ij)Nf$J\GWDUC[ITFVDUDS>SCR=^JXC]%Kp0Yj0UwUBXAWHJ ?O:_Je Jf)Mk/\d"KN 8OAY?c"Ij(Mn3]v1[SEZ M[HZFg'Th-Vz?r^#Qa$Qn&Uq2\x^=`>^A\FZDTcC`3iBr ?+A+A-E6K;O5J:FEHHKNNOP\\XOVQVZOKRPLF:<0b9O 2O 4P3`5l75H:EEMHLSV]W^S`\]`[V_Z^W]Ya^c]f^e\ccjkc[b]eahainijfelmldeinajchhfdj\kngahagcgidae`ldpii`uknqlajcfaj_lbpgiesoodj^e^h\j_nhlggckifecXhhdcg^b_j^kllagdphj`n_skmimekdibi^nhqct`odrepdtgya|o|szgxizm}q}stw݆x߆~އ|܋x݈{ݑ{ߊxw~ޔ{ᚇ圊㞒ᛆᤈᮗ㦗䩘娘䪖㰠浢崞層淧纨罫鼳´ijùŸȽŸȽȷżŸʼ˼˿ǸıǼ̾пһеήԩOV0C9F;MFRGSNTQ`W^PWWYR[RWQ_NVJUOTFNP^HRCTLRCS@QERT=O3Hy.@y.Ey'Aq%=k!?g=h8e;`9b*LDQlX܌o|}È{xu~sxqnygcyU_I>C%?x!;p:g;d8g@e&B0J1J7L?R?UHVPZOeQeCRJVNc8R6O0O0K1L5O8N8N1K2F5T4M:P>WI]PnSdYr\r\wMlPaQlNiCU=W;R5T8SR>RD[?W;MK^JYJ^M^VmWmbqrz¨ɭɱ˰ʫƩĠ||fnGV}-D@R>OEJSJdSl_xklᐄuvy띀zwꞃyut|v}vxvtykgsmk;GsWFYJd"SUJ`Nn0TVzE}_RZLm.Uw>lyC}l/[i9hgl/^g3fRzgzq[YFSaB[;ZS:W:X8W9T@Q=J9M 4R3W8Z7]3b7h2E/A)>#<6B=NCEFCEOKIURWWSOOLQLRLOQ7>w:b7N4O 9U=^;v A/GL@MLRLWRTV\W^Z]TVT]NZQUMPM[HRHLHUCR?PFU=P:P>K=V6I3H{5K|3I~1Mv*Dw(?p*Et$?m5oBn9s=x!?+G{!?!?z$B(G)E^DW@XB\@\BaKZ@WEV<`CW>ZFk)Lf#O`#FSFXCVA]FZDVDXGVEYLP?_Lq9_d#I`&Pi0WaMSIP@VKXKo4bx;\}En}?gWCO;[G\!I\NPAG ;JBg!Sg)P~AnKss-\[CSDTC_Ng(DGxu3eR@a!UXPTGb*U{IrYq1nZMbUg*US~G~U~kq;ge,Yw=xPhan&K]?bD]?X:ZT>TEV=R<]:\@U8UW7]C]8\4c5o-A&?0C3B@JFRCE?NN[NGW_ZWWLLMOHED,?c 3Y:N4Oa;u&D,A-EBEAKPSXTZV[RVTV[ZVXV_Xa]`][W_]gca[g]b]_Sebmig_iahak`l]gbf\g_hgjj`di`piihgggbihfdhghcrmroogspj`neh[iekelpncokphmctnkbliibnhqfnfnjfZh`h^jdedi_pjjeicohpjhbkbqfnflek\icpjseqawkuosgrewdpjtjwmwoxl|n}t{p}rރ܃{pzߋxߌ⑁vߊ|ߎ㓄䘃盋⚈㜃⟋㞓ᣍ⦖䪖㭝䲠岢波峤嶪溧滩软缶°ööĵŹȸǸ˾̾ʺȼν̿˻ǺѼ͸μϸѲƯʍDR4F8H;FARIWEIN\MUOUUUQ[XVQWQVPXNVQ]COBHISLXDPJYFV?SHU9R;H8N0F,E=T}0F}-Iv/Fx'Dy%D}'@1Q/G0I1JBPd]ۉp|ǏŎŒȍ€}ygig_dۃUrXWFDL;E.Gz"?|#B~#<0H6NY@X3L8O5I~1E9R0E0M0K8N2J4PR@Y8T~.Js+Iy)En&GgYM]PZ"Lt:gFf}AbAd]GRASBVCXGWEHCH ;]Oq0]}CbZ~Ddo*Y\JXG\M]>s=bKYFSB`"aY!WW&NnHj\G]Xb^j+gR}an}G^ Jh/Wy;ku@ZzMb`mT{{6bi#?\M 4O5SEY 1]9k*L_?c5k$I0F/H2M3G1D@KEFCMFH=GKLIEVXRQPGE@7=x7Z 0I 3N9N1Y 2l7,B8E:EFJFKGLPMXUZZWTYYab]ZVR^_]\``^Y``eafdf]e`d\ddndj`g^iej[hankg]hehbjchce\hcieiekggahdielglaqisrnglbqegcpmg_mioiqjqjocpdl_h`lciakemdrol^mke\fcknm`n_jogbskj_m]i^iciYf\aZg\r_qgrfrlner[sixhriwivmwcwj}l~s|qހl|}v߄v߉vތ~zߋ||ᓅ㘇Ⓜ㒆ᒂߞ䙉ធ㩗㫒㪕㰞汞㱪㴦䴯丨溥彲辰輱¸ŹƸȺżǽȵ̾Ⱥμ˼ɼ˸ɿ˷гѴήբMU.DKMSORf^sjylotux蓌s鞀q韉|y뢂}歷yvy띂svogyl@S1V_{eqVmTq@h}8Y_ER@XLO@b"J_FQ@QBTG]L^LT?ZC]"JV?ZF^Hm&QeKaDV@XM[A_Fa!Hj,QdL[CQ@TATDT=XLRIRG[Hc3]e'Px9i|8_i,Qo9ik8_a&STCRDa O_(Rr5[yAh{Cdz?hg$RU=QBQ>\!G[LRIJ >VGv=pq0UzFcQ}y9bf$T`M^!T]"Qb(HXn(^L9\ Sj5ga"U]1UtGfx@uo;fi(fr8o{Aig|bl&S_#Lu6k_C[@g3O~PxLp%H]8[=Y;V=T@T@Q=R;]7`;[CX;U>T9L :O7Q1P 1P 7S ,X>^Ac9a:h#@y)M&C0A-B4M9MFK@ECJKNHJKGIEUGEI/7w2^ .O ,RCH 4YO6G1Qn8m;u%Iw"D{'B1G5L-@+A)@|)@"?&D,@6K:N=RGVLcQ^PhScI[R^GYBX9L.I-J}1P~-B|/O-H3L8R1L=QCW>\G\NbQgUl_pZiTjKaPjJ_E^>QKbDO?X8H6N|0Kt+GoCr"Cs+Gw/It-Jn+Gn$Fgh(O_FUBV@`"Jf*TeFZGR<]E]E_B^Fd Dg$O_GYETHUCP;SBTDWHQEZ!Lh0TBr9hd&J}JwNs^'RUNQGh&Ya"Ql/X|:byAcFp{l+W~Dvq;Zp1Ox}JhLWFQ@k,]j.[b SYFs;ls9iu3gi.dt:n}Gtu|So8_>xgSL ;WBo9ZTw+Ya5ZCWCN2XKW?S=U?_=`=ZM9O>R;S7R?N;PAS>Q?S9J4I3H?PXYsh׎}}ƒ͔ϖ̏ʊ|mVxViVRG?G8G0=.G%Az!SDZ@[C\UdYk^l\nZgReJdPaSgD]>XD^JYAW/H=Sy/Hk>j!Bp(Er!Fy.H|6P{5Lq.Kp(Ch?i^"Mc5Qc"Dq0Sf(Q]GQ@R 7N@UDOAZJOBZFk/Z|:hw)Pf+Pix>k`$RVJPJf)[f(NsIn~RnFs~Eb|?aq1_RDI;RFO>WFVGSDd.LLx~Aoh)T]a$Mh+Sr4q[KYI{Fuz8so1hf'i~@tV~sl5OD}r0^O ;\Kn2UwEj}Foa>T4O

U?Q@S:P;R?WFVEVN:M9O[Zs[֌~~ŕʙ̏ɏ‡znޓgyNeSMM6B2E'=z$=} @r"}HnGsq.\U7T;bP[LWLVKeIADAFGIKRNOSWTQSZQTUTZVYUXSZWWPdaa[^\`Y`^aY^Ve`iUefeWf_h_cZd^b[jc`Xc^ccd[pjh\hbldmnf[idmdegkcriohmakgjfodoinjm`vkselcxoogsfvdxqpfriolshrmmephndrllcpcnjc\inidjfk^m`medYkfkYj_mbndiad[l^h\petkrfpetcyowjynul|kymxp}t}r݀l݂|m߃|݄u݆v݈wކ|▁⑂䘌ᘑ┃➌䜍♎⢊⥒㪚䢔欗䫜ᰠ⳥㹧洧淫仰輬缹齪齮ĽøŷŸɾƿ˻μͿлϯ˫ҧMU~0B3A:F@HJTIPFMJQPXIRLUPOITPRJQNVOZOSHXDNQ`LSI^K\QWNYM[;J>T>N>YAO=RKVBSCREQER?P:K;QRUn`ىl㡂긑ŐŐ~mւa]KFK@Q.E/F-D2Jx#@y$D~'GtAs=u'E+A-M2B:V1C.A4F,C(B.D'D>O4RF_LcRcOaTbWqP^R`O[AU?TBR/E0Iw.Jx"?u(Ew0Rt$?&F2N9OWF[Q]RdMcQcPiPePkeupȬǭǫyzhoQ[AN;KDQMQQJ]Ujgs\jluuz~~uꟃvx}ꣁ좃|{|qqfpقuVZ/Y7aUkPcVxAc_?RAM;PR;XFYH_HYAu3do1Xo/XX JS?VAYDXHZHR@c#P{=f~\QZV^$G~PhBR;WJg*^aVTBj3ho7_t=l}As5xUgX|@qi.[\!Gb(Tv:n[>f1\i*UWEO=OFN1VH\ EX6[@U9O 6Q9R;X>T9Z:`F[BZ7\4f6j6r4}&;&8-72<3=&8z2n6i9e:\2YEO4J8W@\9j>r<,B2C2@6A@DDI@GFLJLPPRSZXY[\XSWWRYYY_[UcZu{d_`Zb`[Xaa^Zhhg`i_e_f]`YbZm^hel`gcb[eihck_rkhclal`loa]e]higaf`qmnenemdk^nbkfpdpao_rdrewftkrjufqhqjtjpdrgpjtipim_j`lbl`qhpekgqnkdhgiXgjibkcnee\jbm_kakem^g]k\skqkk\m]znsasfvkymvhym|l܂r݂u}x~r݃v߃w߆މ|{߆z}|ᓀ㖉z☋㛊㚅✋⛋⠍⤕৕妗䨚㬛屢㴪㴢峬巬漭罯潫罭¶Ƕ¸ǸķƸǶȽ˿ɾǿȹɾϾκϰв۸qr7I3I6H8F@PLTHWO\LYKYK]JPW\OUOSQZQ\KTKTJXO^PXJ\O_NYFWIVDTGYJ[G^MSH]H[O[JZ@SBN=TBTDZOTebكjw뫄ネ欂k؂ThWCI:I6H*?5O=T3F|.G}+G|*HzC|+D3I,C~+>.H0B/D)B.F}%B0J1K3L:P>TE^UZ\mT\Wh[lQ[EVGW6M4F2C6M2Gz,Ky"Eu#At&Er!;,G/M4IAYHWEXJbSfYmZeYoWhUhQdPgOaM]I`KV@]~7My*Gv)Ah;q&Mp&p1`p+Xe&KbF]DWD\GXHVCX:s6bv;f^FM?QAYCWFZHS?VD_Ft3ZKAb&Pg'e]Ld3Hyk(]S;o2oOGZQ_ Tp8rk0dXPV]j=gY;WAi-XV4WFv>iZ>K >P 0N 8VSLU^Zvgٍq❁s{}nܙgς^dMAH9R9O9VEV;PHT3L5M~'@}+F/I3G5J/I1H1J-E1E.G)E)B1M+I@XDY?WN]P\\rYaP_T\FWAR@U2J6L7N{=Y8T|.G)Ft&@r)Mq"?/H3Mr,Du2N9L>TIdCPB]M_JdZpe{jz{çǪƫʫƦá}qwWgBM;HCIKUPL]XfQym~jqrzus휁ywtxxvv~voꢂ~jlm߅negA[/Q/S?]Gay2UX=O>UFZGS?S>\FZGUCZ#JbG[D]%M_%L\BQ _0Te|;__MPFD >VNn3ay;ow;bWeQ}S{SBkh-]^KTDUINJSIQBo9X^{AtSBGO9QZ7X>U3a_#Fj'Hu*J8S5P:RBSIaI\M[MUMXISLLOUUYUW[XUPXZ]]]aVWZ[[\WXXQZ]_]YRZXc^`W^a\X`_bYcggfhd`hg_f\idcaabhaf_icf]icnah_micjidf`a[icqplcibjmlciamgpenhqhlemeqeuproolqhthugtrpith{vkbpnignfskiZqkmenfmag`mfine[kakesdobq^m`lbsgl\lbn\pfqbnhpgskpasd|ptjxhxloxoހtޅ{t߃u݄q߄}߄vޅz~}zᏂ}⑃ᘈ᠏⟈㠎ង㟑㣙⢖ᣕ㬘䭖㯜婚岢嶦䲤䳥繬缫鼪迯ƹź¹̿ʾ˾̿˻ιϱ̧ʴӝDN3D8I9G?NAOAHJUGULUERMVGOT^MXU^P\R^JXNUSVR_LWNVJXNXDWGVKXI[N]K[UcPXNcPYSYLVGXM[ESMVS\fUׁnڐuޒcޒpُgՉeuWSLCD>P2M:J*D8I2F2A&B3H,A0G-D/E0A'>3J4K3G,F,F'C-E5U6Q=OH\N^Ne[e\j\kISGV?P>LQ9Jw,Fu'Fs&Aq&Fs*Jk"As-C|*Fr!Cx'Er-Hm#Gb>kB_:WJBOGQMIcbfZth|goxvvz을y|{|y~y~x~~ynsmmkF]|(Hv/U@bz3Yg?UCSGWCWKP9P:TAV>V?S;\DZDV?VHb#I[#OdQl/Xi(Lw.WaHZBYGYE\H_LXAo;hN~`KOAN<[FYJZKQC]#N`Kn-Tq*\XDi5c\u6Yg#YNBJ HXQo:_K~9wVndPyaHsv/]aK^'NY0fS$JWPVI_!EVwQg*UDi/VaEK 9H /TBX@Y9Q9P ;K8Z>\DZ>Z?Y7Xh Ds@}#?&?/F;G)?1@9@=K5D=ILWNRQUSWW[X\[d`acf\X_`a`Y`[__bbcbd]X\\aV^\^VXW`^`Zd]bagYd^gebcaSccpnfYcYghcYb[lbh_mif[keg\jhgceZlifal`h^hhjbkjf_dckcldtgmetjiendmermqdqhqjsgrgpmsrncopvnfbkeq`lfoenek`rfnccdi`i`kdj_i\qglYocmak^lbmekapepgvkobscwusfzmxnypymwlكu~sv߃v݄|߉zބ}݇ވuzߌ{~ᘈᝊ᠈⠏➐᠏ᢎ⧒⤙䨖䪚ᬛ⭔㳠㴢䲥涨湨麬鼩缱´õùƵɸ˾ʾʽ̽ϾϿκͲ˨ְUc-@8G:GAN9LBJBTCNLXGXISJNMTOYX\Q_XcM[T_T]TZSbSYN`M\NZTdKUVdP]O`Q\TVWbQVU^PYHTNTK]GSNVb]p\ԃv^xevbk\]TKUj$En,L~C[}:QEXD[HdDdKe\ui~s©ŦƦŧŸžs{ilQ_?MBML[OJ[Sh^wcނjއuqwv{q||v|}}qlzkmsoI_t Es$J5Vz1_dHUWBQ:T?\=_NUCa!MUIWBa Go$Qg"Lk"NZ@\Ja!P_E]#P`F[Cp?eS[HO@SB[JaIUBVIXJWHk#Sm!X\!GuHs^r4Y_SRGKJYN`OEK~WacM{XOs3^\JSFMII@\Xm'hW;Nq^{HRFM 2KQH 8O;p4saOf-Ewdd,Ql9\s3k_"Xc%Wk3fsAnoZfeOumu\~Hr4e]CTGo4[O4N@Q>R9U7T5V?T6T5X6\>]8\=d"HZ7[0Z3\;X6T ,R 6Q2U5S5hHh8l>|!=2A1C0C1@3@3C7D;B9CBOAM?JFJLONSSVRTUSQQVXZRZTVRYQYT^\`Uaa_Y^[\T`[]]^WWQaY]RcV`\`Zb[b[dba`ZUd^igg]bXomg[jch]kce_j]bWb[aYfalim]idj`mgfigbngnelgl`newktljgnflcrnrnpgrormvknlumtqpgooqbmhodnan`pilaodp`lfkbibg_mih[lfsdn]l`pfl\pdrilcrlkdpdqkvgrnsiwk~|yi~o}r|t~pq~ވ{uw|━~Ⓞޔ~⠈⟏ᡌߡ⢗䫘⧘⫠婙䩥㭝㲢㰢䳣䷧䷢漫纫庯辰ó³ŵƲƹƻʻ˼ɽͽξѼҵб޼oy/B3E7L:J:NO}0H|1Gv/Ll!j'DkAp-F=WB]:SCaC_CdVoarl~¦ȥèsthockCKISQ\UTUQgWp\}opr~{{{ꠂ준wz저~}}vmms|kN`w!En&Fv7Xx3[Z@N :RA]"EQFQb"Ld Hf$Nh&Tg%O[Fh'YXFY=i-YbNYAs@`Vl$RP=S;`!NaJUE[MVLd0Vj.`r0_d$M{NxZk+Q_OQ ;RHXQ^KDF{U\bXOxVr7]\OSDLJG :PHxDg)Y|<`^wlp3_E 9J EA9S?d$Yv4ybGo:L^M^#Gf+Ws4w]V[Kp:gpcV{rOk7TStkX[{R~fOR;e!NQ?K>P?WDRDXCQ;O9W?W7W8X;R -S 5Z6S 3X6V 0W 2\:_6g?e6n!>u$<68(82?1=1=9C8F5>4C:D?IENISHOW\OSS[SUXVYZRTXVUPUUTWVUXU\\\U]X`UVU]Z_X]b\Z`V`Va^bU[VZPd`bZbXb_[Wf[e\b\cYfhh\i`k\fdf^f\d^c[jce]dai]j\njlameptl\ohg`iaqgsiolpknksithtoussdrhvnuorikiololmewomcocujpgk^mftcrgpeogg`kamarjj^pdqfqioZk\mbocqpkbnjmipdvoxh|cyq{hzsxh}szr~rނzuw݇|wz߈|~Ⓟwጁ{♉䜍⟑៎⨎⩘夓媕⭚岙㬞氞㰚崢䴨幬浪滦廯齲迳迳óôĶźɼ˽̿̽ɾ̼̿˿;θѳаǰQHSFRAOL\KYJPQWLZP\SPVfPWT]S^Xc[lR`RbP^QaN]K\[dXgZZ\`ccV^VYWUSXP\XXVZOXPTTTQTTUZ\V]TTMWIOAR?W6H:Oj%Co)Fp"AeZ:X>X>d!Ceo*Hv1L|8R~9P@W=[BcNfbwmy¨ä|qyfiXYINDMMR[R\VgUm_y`st||w{蚇힀뢁y}죁{||~阄txn|{hM\{FjCp/Wx<^YDPASI\GQ?UKSD`!Cb:_`7WV?\=V?S?_!IWD[ Jh(Pk/Wi.Vh L^!Oc'R^ NcLj&Zh&R\Jm6Zgw7dT?L;XFYFUA\LZH_'Rd$Tt+[p3\|Fr{Lle!I\JJ?PIRI^Lo1i|CpPNxXiZiO{YNMATLI CKAp:dGt/[VssY[GFK:ICMLSQYOWONSSUP]YYXUOVNTTTVVPZ_UR]YWX_Z_S`[[V`Tce[RYX_\^R[Y]W]TZR]W\]i]g]ic]Ya\cYa\fegff^k_gf]VfaegbYjbdcieqkrsh_llkkmehjf[nhj\molak`helbyypiruvvoguoulshslqblrhapisrxmmgqarmtepbqdtjofmefaleoasjocobiak[ognkj_mdncuhtgodofsirevh{k|m{rxnuhym~sq~v߂su߀wsށxrޒᆀ㍂ᔂގߙ⚉㟐➊⣕⩎⥍娛㬖䬠㭕寝㯟㭠ⷢ䳡嶪㺪庬迮輬龵Ļ÷ĴʼϾ̼˿˾ʿ˾˺̵ϰʬџIS,<8O6G5J9MIMCQETNZHUHMJPN[LVU\VfTTZbZeXU[lV_M\SaVcUdWiR\ayX_\\\d[W_\TW[XSYRSTSQZNTKTTWUWPUR\LXIXDU=Q:L;Q>Q?MFS?M9P@NHXGRAN5I?K?L9K0F&?,E(A1H.F2Nr Bn#XkGmCw&C'F*L,E,E5G9I8L5EAMBOEODE@BIQINJNSKNRV]PPSSURSNTWWUTNXSXWZ[ZX\Z]YZYYT`XYcb`e[bW_[Z\^U`W^T[XXR]S_aXV`ai`g`fZdbhdc[bZdddWg]cZb^ab`af^gbpcqjmapgeZmihbidjenimcofljh^hlialdkokctqsgpmo_ttnepfpnlmh]slunuklcphqkqhl]thykthncjhhepblcpbi\mangjfjem`nettkasjmcqbq_upylterdxszltitj~u}nsr߄t߀v}oކy߅߈yފ~ގᐃᓁᖌᑅߕៈ❇ᝈ⠌᧖㢎䩗歙㮦㱞㱞㮤尡䲡帪淭漬羮湰潱°¶öƻɺ˽ɼʽɽ˼˼Ͽ;ѹ̺̱ΰ׳dm5E3Q0I:L?S9G;NEUFMIWLXLUM[O[U^S^W`P^_dX\XhXaUaR_WfU^[iYf_b\]Z^Y`UWUUQUV\WVX\YXQULQJPRWGQHQKOKTFTETES@O=Q?SUATNcM^MaLbKZPc:R5CEZ3J6O?V/F~1G.Hv$Ev(Er(Bs#Ct D4L9XBWMfPcRgTg_yaybsexjw\g\lTeRgPeOeO_;U;Sy*I{2Jw.Hr)Bl"Dk>i9n#Fm%Jr(Fn#AlBdGa"@b!:h!H]=`&A`&Ad$Dc @g"Ef"Bi%El'Gu2P{7Q~9Uz:^{;[>a[vczȩˮɭƭƧ¢wzkr]cLTHZP[PT\WdWq[njzr~uy{z|y}|zxowބqjb?Vz'JoJw0Rw-Xb EV!LYGc GV<`"VL7[=\HU>UBb$IP 5Qd!Oo,WgJdCb#Wk8\]H[Gd$QbL]O]%Gs=XMe%QPB[LU@MEU KUI]He Oq5RLpXj+SS=WLPGMEIHWEh$XO{]~Ab&WYlldr8fQCO BMF@DG ;l-]WRy\v}Owf LB9C @@8H@d'Hy2lt0]~@TbI|U?X Fj-ge,gg3b_P[fqPm5is>hT{y:ZFoi.SVFO :M?L 6QO=OAVp%Dp b@\>\>k,Oe#Ai'Og)Ii)Ik%Cn,Mu7Rw7Sx9]u6VFa]pd~~ŦʫвҸϴ̴Ƭ{{v~htW^DTPVOQcafTsa}fowy|{y힄졅}q|뢃zymoӈqYW=Y|*Mk Kp.Nq/[a'F`<[_4VUGV=TBO<\GaCU=S;_MWBW<[L^#J]Gd!Jm*Zd)M`!L]Fb#Na$Mc'Rd'Mc&UYL[Kc-JPy7jTCYGTBM>QGQDVDg$Xk/LT}KzdESEO?TERMJFWQf.\M~[Qf$Un4`erlR_MF 9MBHEH LVEMUQlXr*USDG <; ;@ APbbbo0[I @PDe,`l/lS]WbfcSx=su4]m.Hl4Vo/WPW6E9L2H'D);0H1C1F~(>:Mz2Oy0H2Ky&F5L:N?RIXPdXh\oZkandscucv`sUgUf[gXkI^GZ;P4Lw-F{.Io Co@iCk$>i;u&Ba#?o9d;i7e9f i.Qi+If$Ak#@k)Mj&Gn,Mr0Tt3T;\Sn`sɱ϶ּ׽ٸԻҶ̰¥yxbgOZEONTWX\UgXrillpzr|}}z{t|wzwsفX\M1Ay*QoGXDn(Hr1]i(O[+NWLZ LN>UHSF^H`ET=ZF[CXBQAa$Vb I[Cg"Nl)UaKZ#L\H\N_NcEi(Ui/Zc"SXN\ ByHnIaIZHP?TFWMN BPFg+Vq3U\N}_GUIL RJQ 4V@UCT=S;X@[D_?^1k2kj#Eh;n!Fn!>l?g!Ac=c9e;dc#Q^&NV@T@X#K`*N`$MWBRAWDV@WJc P`A]Jg(Vm+S^D\ Ka Oc!I]KaIe&Oj,Wc&Q^NTBh=ZR~y=rZFR>SBUH^RS Ch$PxCgmZd"Re.\K HVJVXRGS Lc STVdo%f^My=f|rtO`$OY"PTQLHO>i@jfPogco0Qu4di"RF ;A@F ?ZGn+U6nq6Oqu=tRCG @NA^Lz@lv;o~IyX|eUi)WWGXAL4c'N^IM9SEY@U:T8[EQ2W!F[AZ5]4e7k6i9p2m1y3~60=1E1?:E:KBJ@G@HLQKLJEMIPLNJSROKNOMHPRSOTNSUWX[X[[\VYVYVZZXWUPa_XW^Y_Va]^^XRc_da\Q^U`V]Q`T`UYR^T_V^[f[ga\[dWfcichc`Wc\g\hd_Qf^mhi_e]gbd]gblchbmhgXh]bVe\njobi\lgmeoiplormbodmfvmqhphkgrmmerlprnon^tutkvqrtpiohslperjultltipeqgpgshpcofmbqeqgpioesg{sqdtjtdsptgvithwdvg{sxlxh|pylykxn݀wmކyއu݂y܉ݎxwߍ~}揁~ᑀᗂߔញߟ័⥛ᤏ⥓ੑަ⬛㬣⫞ᮤߪᱤ㵦巤漴溱漳轫翰鿱羰ĺķķɹƼɹʻȻʾǻʼολ˵ͯ˱ն_i*Bz'A3J>N8K@NMgFPEUPZRYS`RYRVOZYbZ`Y^XeVc]f]gkq_cel`j`e\[`\_`XVQPWUYTWXSSYYRTSXRUPRLOR[KSHVIUFMAQAUBQDQPXSXPVRSRYHPKOCTN;N;M6J8S0K@S@Q?RH[LfGZH`DUE^=O?R0H2I{*=v'Aw#A/D|-H1G)?y(?z=Ky'A|-G~6Q1L=NLbQfYjZcasZmbf]g`n_oZoQdJ^I_Xj:a">i:g P@P ;T 8YB_!DWAZ%I\#I_;d8f>j5m>r/t/~3.<-;4?X>X>a"Bi(Ge'F_?]9aFh&>j&Pg$Lg%Lp3Zs2\Voj~ɢָöųŴô²۹Ұƣ|Z\MVVXWXa[e\r\ppuqt례x{t龜z{{y֌usnXlNm@bs$JnNd GbK[!EV@`Fg!Ed'RYAV<]E\DX?P>VDZAS@`JZF`Hh$Jg$ObFd#Mb K`EbPf Hm3Xg+Rf&T[IUR[%Mf4QXu5_L CK?REQDVPj1V`Mrn(W\APFWIXK[SUAi$XbRlx0_k!fk&XRy|wWd'OZ?RGK @I>V&Mv9lUoe?uW5t5cf*[K :F y;m[BK9QFN+Y?@9@BFEHBDHENJRMOJTXSLPJVNRJSKPKNOQISNYNTTZR[SRP[Q`W\UZYZRUP^Z[T\T`WXTYS_\YRaZWUaX]S_Vf^e\_T_]\T^^_X_\aT_XcXcSggcX`Xd]lfiah`ibi]b]g^cfc`fZihi[eWm_kfe]iid^ike^njg[kfikibnaqltmpoh`o`qtrkwrqdvsqmsdxrujnhsjnhvmsg|wvkplqjvutjvdtjpaveysviumuen`vutjqisdsq{ozpvlsgvkxkvn}p|hzlxkym~r|n߂nދrxr~⌂wߍ|ᎂߓᛋߕߓᗅ࢓ࢌ᧎䤚࢏⠒ড়⩜㮞૝⫝̸ୠ尦丬繫羰罭繪輬µ辭ºðòŸƴƹɽɸȾƹ̿ʷϺͽ͹̲îő:K3M3L7G8G=L@GV@Q8M8R9N@QGaCYFYI]NcL_Oe@T=V;M4J{)A~'>{1J}'>y(B5Mx'?z%<{.D}0O|+Dz-J5OI^?OM`Q[Vc]hdieybsdu`pctWoUiWjSeH]CVDV3R6My,Gu1Rg!Dl(Jf9e#Ff!:h*@i!Bj =j9c7jt>*73Q\>\>c=c ;gC]<^@_Beer+\]HQEVTXTUMS@p,gbXqm'Qm%gs.ixsSGQ@a#X?pf Ux@o~Pw^u>_kAh{J{Em4\}Ag\9M@TAN5P 5V 3T 3U7Y -bZOR GS?y=f~rv9fj%R`KO?VNVCYNZCwN CPGTIZGx;gSn`s2jL?b&Eo6hj#UP@Q9i!D~7_*40=.83<3?>;CQGELIFMJKLJNHMKINHDLIQRTOUP[SOLSLTQLJWYXOVK]W[W`Va^]XYN[U\X_U[WXKYS\T\^ZU]X\WadaX\\]VigaXb[_Xa\ZQbTdd^V`UaScZeXbVa_^Vg^iaf]h^lfcWedf]jaf]sqk\m`gallg`g]megckZe`lcl`efohqnpjkbokmimfqjtvmdohndqr{qtfplsjqismsivfnftrvovdvjtfsfumle{lviwpsasmqnqhtftbzpqcso|mxdypxn{t|pp~rxrvk}qyooބzyp||{Ꮓ|}╄ᓃސ|ᓅޞᜋࡏ⠇❌ᤆߡ࣑⨒㧙᭚⮞᳣௛㰛嵡峤湬㸪帮ź轰ºµ´¸ĶŶŷɼȻɺʿ˾˽ȹ̶̺ϱήٴeoy&Gx/H{1L7P7JBMFL[cWfSYO\HUVbR[G[NRYh[mS[bedlVZ^db_bj]_YU_e]T[a\ZZOTSUPURSYRWURMLRWPWHSOPQRPYQNRYXXTRZV\U\W^YW[TRMUHOFR@OTJbPjTd`qdrgtgogul}hsbo_pObTkVmGaH`=S9Sz3Iu.Mk!>k&Gc8gBa6`9j9f=m 8i >i$7g:]k=f9n#@+H|,?)A-D7IY8Y8a ?a=_9_ Ca=`=a!Bd%JdEcGe#Oq0QVpnڻܼ۾ñ÷dzòݺۺֳѮ˟k]LUS[YW_]g`vf{groutu휀uxu|wz{yx~{n|vdk~jzX^Aen&Eh!Q`F`EWCS9bKi$IS>N?[AbL^HR=M@e/ZW?XCb*Ri+Sf'RdHj"S` Jk)[gNk'Mz4^n(Uq/Tn0[z7e\GXLRBf.MXu,b`T]OQLPHNpUsw5at4^f!UWGUPUH]\`!LBuc`kZGgW:xw-ms:a~Ji[k%RSCNCVSQ GVAy?nTmjOSMV9f&Zv6kcPPD\Cz4ZBlo/Ym/Wy9VKu=wXEYHl2]y3jf!UxBngg{;{PZpey9dVAK5O 8M 4Q4S 3` /c6i1s0~8 9)>,A2=;A9@4>@E?IGFIDDP?FHBFHWRLMKGNHVSTORNVWLLUQZVRMRQWSUNYMVX_ZaV_Z\S][^WYS`ZYQZYXQ]T]U`TbSej^Rc[\S[Pa_b\`Xba[OaU^X\R__]Oc\gbb[`Xe[g^b\i\b[a^_YbWb^iambmhkWgcgahdh^ldngjbf[ebl_kgpokckguonnqknkqipjvnqcodtjpdrlskpitfwovhsirjqqqbshzkwszqxjocwnwjyk{qpjuqsmvnxhrgq`shqg{m{l{ouf|r}u݁wr}w~t|qvi|tv}|ވވq{~~yޒޑ}ߏߒ~}ᙆ㕆⡈㞈✅ߜ࣏⣐妛婐䫥㭕ଜᮙ㱡㲧㴩丩亮伮꾩⺫辴罬ıƹŸķƺʺǼɸȸɽʻɼɵγͱὭw}0G~6RzQ?JAN[9R?Y;VC^>Q>V1PBX;T.G5I5J~)A2K2F3I5J>SIYNaWg_ibkgvlwhsasft`kaqP`UhTiLb?[@Y:S~c<^5\5c4d6f7h?f ^@b"Bh'Ka>aBd"Kk'Mr-WTloÑڽڼ۾ۿïƷõܿมضԱϞmgPUPZYZ`[fWui{fuswvvo{xxwy}}}xrጄeX\pfnK`BfbDcG]BaEYFV>ZAc GU:SC_@f"O_IPh$?k*Ka >[7[4\8f#De^=b?c Cf%G]@aHcLh(OJdcwĐظۺٺڻ÷޺ߺ׵ЭɥqnPVYjYYXSi^slzgkm}vxyu|s{{y{}vrݢzpZWIiN_:]Q=ZHS:T>V?`AcFd#LTGO<\!L`#Lb%S]$Ij*[bDgNr/Ze!Kk'Oi$P}2]~<]t0W?ht/Ww7ao/W[BXJ^Lc(Nk(U{7gf#WYL`&Nx}x5Xg#Mp,Wl"T\C\PaOj"\n"Tx2bY`gQEQAz>pGxu-no0[`~^n)WTJL =WRfYr5>:C7BGHNR@EEDGDILSONPJHTUGFWWSKUXUOVYTRUQ\aXT[T`WWSXK]Z_W]V[RYUXV\V]V^UcVhd^Y_R`Wa[bWZQ]]dX_T`]aWg_^T[Q`UcWaWh\cWb^g^kul\cWhncXjZ`]`]_Z^Wecibmegdkcmejje_njqlmemiihd^hdh`oflckhqep_ofpeukrordpksftrpblnmjodpdwkmeplshsnqgscun{s{o{mwmwfsfugrhxktisfudsnudumuetl|vzmxhvqznk|l~nyks{k|qlކwuvs{}}~x߉|܍މ|ᔃ㚊ߕޜߗࠐਖ਼⤏⭜㰠⫛᭛㱟Ნ䴤絨綨工廫庱轴羷·ú±Ǹŷƺ˽Ⱦŷ;ʾʷ̳βͯҥOYz/H-D5K@Q?J@JFLEQEO>JLTOVGWJZQXQZT_T\\a[b^f[\Y^VVX_]Y^aeZbSbZ`\^T_ZQPYSUTTRNLWTZVZWUT\WYX\W`ZgY^Ua[\W^YTOTQPSCRJSHV;LBPJb:SERCUJ\@U=`7S>Y}5O=R}3K2J;O;SR:W9S8K9M4K0D8KCT:REZWhVd\s\qhnktntp{gthxgvbrVjWiReJY;S:N{c7daBa9c?bO;F=H?M8HV_=^R?O 3P>W8d!Ji'Nd!HRGQ<]%Lo1_e#NWFn9`e%GdNr)S`Gn+Wg'Py2]~3^p%NFiv,Ow3Zx5h_JWE`IdKc'X|;pn*bYJp9^yo&Q]Gj.\i$PZGWHo(ek$SjRz9cdddTGM=s2cHuv0er1fn7cWqjvOg#VOBTJa Vq9]telU|^"IZES ANAM7d Pf#Ox5[C_>du1_g$N]Ij-aRBNEO<`MeLf$S~LtDo2kr5p?kQxsyoBw`7^D_Bh7w5*?(=+:.6@S0=.=7@:B9B=IGEIPKKIFMHLJORVRRGU^MIRQQLUV\WRNVR\UWSST^U\RVTXK^aYW[S[W]X\\[R]SbZ[OYQbW]Sa^`UcV[R^Y[U\VcY\Z_[_W[Vc`c\^Sf^hZbg`\c\kacWhbg\e^i_bW`Y\PaTe[f[cYf]dYlkgaiYmdghhaneibkdpelerksooaoZrlphrilgrfpgulwktkmjkivpkjslneuxtkvttqp_tlwkwlxhuovjpbrqqg|itfwpyl|wvgoctqucvi}zwfwmwjxh|q}srv{rtlvlt|}ᑈጂzߌz~ᓂޒ╋ᝌᚉݛ⠎ࢋ⣕᧔㪖ଚଖ䴣㰝䱡浧沧䵪廱湰幫翱ó꽬²µĶƹĺɻƼø˾̶кгбݶck;V|2P9M;O>IERGSFMIQAK=FIQ;KEXMWX[YjRUck\c]d[_RU]\^fdbd]dZj^_XWR_UZW]UYWWRZUWQYUZYWUa]`Wd\g[kXiXdTbZ]V\USNVYSYFT?MY:S=R?Y=R8J;G:S2K0I;PM]BVOcVb]qhuiqnwlmtkvgvjvgmYpObH[@W9O}6Nw0Gj#=iAf?^7g<_4c?a8`>a3b\;`8Z6c&H`?Z<`L^ Mf)Ox<`\r׸ٹڽۼ޾ݿ޾ٺٵ԰ҫțl[NVQV\ZfZkbrZ܁pqoyxw}}죄}|뤆}ywn}Ցv\_-D?[Aav"HZ>a!Kn0Vj$L\DR X@i(Gl(Rg%GMBO7[Hu4fZAWLi(VfJn-Qr-VaNn&Rg(Pz4Zv-Tg#Ot5]t,Us4W;n_!IZQ`RbMg"U{;yz?sf1ZW|cm P\@f#Nt-efSP ;l1]l#WdNv.Vca}aUFJ 8d&N@rt1`{;lm,fu7gKa{eA{a$L\[WIn1WlzRmLwZGNaOR9R9` >]>aA^9\>]WCq3_t-Sh&P}>ffLp'Nl&Nv/^v,PdKq,[w.Tp,U;gl'W_#G_UeQr0_QGo/RxGcd O`H_Du3dm)]O 9^Jc!UfOw.V`_]ZLOCY@y9hv6`r3am*^r,kl&KgzcC{b \TRe)JlIkwAeUAF9WF[FWOOFYG\Ar)`l*Ov8a|;_j,T`.Rp.[ZEOh&N|LnMu2O~3?UDPJYBMFOGQJQR9R9` >]>aA^9\>]WCq3_t-Sh&P}>ffLp'Nl&Nv/^v,PdKq,[w.Tp,U;gl'W_#G_UeQr0_QGo/RxGcd O`H_Du3dm)]O 9^Jc!UfOw.V`_]ZLOCY@y9hv6`r3am*^r,kl&KgzcC{b \TRe)JlIkwAeUAF9WF[FWOOFYG\Ar)`l*Ov8a|;_j,T`.Rp.[ZEOh&N|LnMu2O~3?UDPJYBMFOGQJQ   gdl-0.9.9/testsuite/tiff/24bit_color.txt000066400000000000000000000010171340051421000201300ustar00rootroot00000000000000Magic: 0x4d4d Version: 0x2a Directory 0: offset 786440 (0xc0008) next 0 (0) SubFileType (254) LONG (4) 1<0> ImageWidth (256) SHORT (3) 1<512> ImageLength (257) SHORT (3) 1<512> BitsPerSample (258) SHORT (3) 3<8 8 8> Compression (259) SHORT (3) 1<1> Photometric (262) SHORT (3) 1<2> StripOffsets (273) LONG (4) 1<8> SamplesPerPixel (277) SHORT (3) 1<3> StripByteCounts (279) LONG (4) 1<786432> PlanarConfig (284) SHORT (3) 1<1> gdl-0.9.9/testsuite/tiff/8bit_gray_geo.tif000066400000000000000000010010221340051421000204700ustar00rootroot00000000000000II*k{skkk{skksc{cJsRssk{{c{{sskZckkc{k{{sc{ss{s{֜sŜŌֵέ֭֭޵Ŝέ極ޭsνŜcksks{s{ksZsssscs{{s{Žc֥kkccJֽŭ挽Υֽs攜νεcRZBRRBJBRcJR{kZR{ZJBBJkkcBkcBkJ{{R:JZZscRRkJBZ:RR)JB:J{BRBBcJZZRJkksZ{Μk{csk{c{kc{cZsskckccskޥZkZZs1!:)!J1)scΜZ{kcZc{sc{k{sRsRsk{ssk{{c{c{sssckkskcZssk{cs{ssssk{ssk{kcsk{s{Ŕεޭޥ޽ΥŽ֥޵ťŜccsks{{kkέ{ssk{{޵Δs֥ޥŽs{{{{k{ss{ŵ֜Δ攭ν樂֭޽ޭ{cΔ{ZBJJRJRBZ1scBksZZRRJcJkZk:kRkBZJ{Z1ZZ:cRZJZJR:JJRJBRBJJ:BcBcJcc:J1RsZk{ckRJksssskkksZcsksskk{scc{ckΌsZsJss1!):)11:ZJkZcsckZkkJJZ{s{sks{kssksk{kZ{ckcsZcsksZ{c{{kk{{{ks{{{{{Žέ֭ΔŵޥֽνŭŔssΔތ{{Ž{sscZ{ssRΌc{c{{ޭֵ֭֌{Υޥkkssk{{kŭֽŜŔ{έŽ{kֽťޜ{BB{BRRZJRJJsZRBBZsscckZRBRccRRcRJZcR:BRkZ{RJRRcBkckBcZ1JRZB:BB:J!RBBZJc:BB:Bcsk֌ss{{{kcR{s{kcRsZ{s{ZZ{{{kkskk֌{sZBk1:)!:!)1sc{ZckkZkkkRsŜ{kkk{kks{{s{s{s{kskssckkksssssksc{Zkckss{kk{{{{ss{kέńBΥννΜνť΄ΌsΜ{k{{{{{{k{{s{ޜRޜޥΌRŵc{{{ޜޜ{ֵŌ֌ֵŽťcckZskŭZZBccťkBksc{JZR:JJsΔ֥Bkk{scsJBRRZckZRcB{ZkRcJZZscksJRcksZsZZckkcZkccZssZss{RJZ{R{kksJkc{{{{֜Δ֜k{kŭcJJBRRc)c1RB:1J)J1Z1JJ)Zkkc{ksss{{{kk{sckc{csscksZsZcsk{kccs{ss{{{s{{k{ccť{ŵֽŜ楌s{ks{{Zs΄{{{{{ss{Žń֔Ž|޵ΥsŔssΜ{ΜŜޥֵc޵ֽν{Jk{R{ssJskkssJBkΔ֥cZJJJJ:R{cńZZZsc{BRJRRRZcZRcJZkJsZckcZks:c{sk{JJZJkJB::J:BcBJB:ZJ:cBZ:1Bkss{{R{Υs{ccc{cksckcs޽ZkkJZ{s{kńJ!:BR:!1)J:!11)!))!1skks{ksc{skscZk{cs{Zcccc{kskk{kssk{ZsΔŽޜZkŭ{挌ﭜŜޜޭΔֵkkkޭsksΌksֽŭsΌΔε{ŭ֭Ŝcks{s֥cν޽ޜ޵ޥνcc{JRsZRZkJks{kc{ŽscBB:JZkcskJZJc{cBRJB1sZkZkRBJcZRskccRJJB:J{ksB1BR:s:B:!J:B::J:RRRR:cBBkkRބ{ޥ޵skc{ks{RZBZcck{k{֥s{sRέkc{{!B:!R1::1111!1:!:)1!1!sRckZZcŭc{sc{{ssckk{ckkcsccZcsZss{{{sνﵔťsޥ֥΄Ō{{{{{cs{ŭŜ֥ΔŭεcΌΜŔνŌ{k{Ŕc΄ֵ|ޥ{RR:JkcZ{sk:kޜRRJZJRcsckc{scs1ZscZJRJJBRJJRkJZRRcJZR:1ZJkccR)J:1ck1BBBJ):JZRZBRRB:c:J{sŭ{ksZŌ΄cZsk{kBsZkcZkΔενΔֵ޽ΔΌ{:B!B11{!:BB:)1!!!)1J)sccs{s{s{{kssksc{cck{kcccsZ{sksskss{sc{ŔŭŌΜŔ{sks{{{{Δ֜k・Ž{Υ{{εŽsRZB{kkkssccsRZZ{k{JJkRZRkcZkZ{ssckRJRJZc:ZJZRJJRscRcc{B)JBkJck{sB1B:BBR:::J::kB:c:c:B:B:1BBs{s{֥ZsZZZscs{{kssk愥{kkcscs挄{{{ޭ{{)B1!!!)1)1BB1J!1!!)cksssk{ss{s{{csc{sskcscJ{sZskskssk{{{c{s{{Rcֵ֌{֜{ks{{֭ńs{{s֔ŭΔέޭńבֿ֥֜{k朵{ν{:Z::kZZRckcZkZcRs{skZBJRckRk{{ks{kcRJRBBZZ:BRZBRRsRkZksZJcJckRZRcBZB:JBR)Z)BJ:)BkB:J::B:):BZ:scsk{{sksccZZZs{scZksc{sΥB{Όs{{{{k)!11)11:!11B!:c))11BcksZckccs{kksks{{k{kskscskkssks{Zֽ楌ΜΥŌsk{{s{csks{s{Δcνޥ΄ֵ֭ŭΜΜオŭޔ歔{{ތJZBJRckZcks{΄Zk{RRZBcJscZBJssޔsks{RcJJZZZZRBRBZZcccscsRRRJBJBZZRc:BBBBBRR:1:R!cBJcJ:J)R::{{{ssc{ssc{ksk{ZZJs{kkZsενk{B)1B!::)RZ::B1:1:B))):!!ksskkk{{c{kcs{{k{{{ksks{ks{{c{cc{{ss{{ksέέ{֔極{ε֔΄֌sk{{{k{{{{ΜΌk֥ε֔έ֭潌skkck{ZJBRkkRZJccsΌsRkJZckscZJJcJJJRJs:JsckkZk1cZBkJJJJBccskRcZZcRJRB::JBcBJskkksBJJR:ZR)Jc!R1JRJkΔs{{ssss{B:JsJ{ΥcŌńkZ:B)Bε֌s{ŵsB)!)!J1!:!):):):Z!1:1{k{{{{k{{ssZkkkkkc{ss{kc{c{{Zk{{s{ckc{ť{kέ޽{ޥΥŔε{{kֵ挜s{s{kkkk{{֌΄֌֭ŌΔޭŔ֔挭{kkc{ss{cBZkZkcJJcZRck{JRJJ{{RZJZRcZcBRRBBJckkcJRRskBsZR:BsckZJ:RRJB)BZRcRZc{RZckkBB::1R)BBJJ:B:R)Jssccsքk{֌ccscsZJZR:{朄Υs֥:)):!ﭜέ{sΥΔc!B):1)1!!!))11!!!:R:::!!{c{{k{ckksskckZ{ksss{ss{ksssε{Δ楥ޥŜŭΜŜ{֥ťsńkŌksk{ksŽ歜ޥ֭εέΔńֽŭεޜ޵skZZZc{{RZRBkJRsscRskZcZBJJJRk{kZJJRJk{ZB֔RRJJZBRsJcBcRJcRBJ1J1kRZs{ZRsRZZJZBJ111::BBR)Jkssc{kskνބcsJ{k{Z1kŔkRs֌k!)11νksZ{sR{kBBZ11R1:1!)))!!!):)11!{k{ccsccs{c{ssc{kkcs{s{{skk{֜Žֵ޽Žŭޥεk朔{Ž{{έkŵ{{k{c{s{sŌέ֔{֌ν΄޽ΔŌŽŵ{s籠s{{ccZBZkJRJsZs{RkkJsksZZRBJZBkkcRZcZεRsssc{JRRBRkkkJRccJckBJ:1ZBksckZcssZcRB)B1JBB11BZŭ{JssR޵{{ZskRZc{sZ{ŜkRR{JcB!ńޜŔތ)1)1))))1))J1))!kZkskZc{sss{{sc{kckk{{ssŵ{{νΜֽεΔŽŵ֥ťޭŜ歭{ﭵk֥޵ތ{{ss{֭ΔŌޭ޵{ZZ{{RcsBJss{ssJZJcRZkJJRccRskRRkZ{kcBZ{ccJsBRBRBJRZkJs{cZkk:BsJRkcckcRsRkkc{JJ1R::B:JcRc{kńcckk{{s{kZcޥέksJRsc{{c1s:!{{ksŽ{csk1)R::!:{)B!:11J1:!)){kkkscscckssZ{s{{k{{{Zk{kkńŵsc{ŽŭŌkŭsν楜sֵ{sc{kskRssss{浥{εŽޭŵ攵ޜέs{kkZJZcck{s{{{ckRZJcc{ZBRRRJJc:JcsJRJ1Zsskc{ck:JkBskRkZkBRZJ:Rc{kkkZZsZscRkscc1RJRB1ZZ{skc{skZޔccksRcZZZc{scscksR{1)1ZcZs{sk{ZkZk)kZBs):11:)!)R1:)!):1)k{sssZcsZcckccksZs{skskssֵŭΜεΌŔ޽ŭε֥ťsŜcskssc{έ{Zťs֥έŜΥ省޽ŭތsք{RcscJBRBBkcZskkJkcJRZZJޥ{kcZcc:kcRZRJk{ssZcBZBccRkRBBB:cJRJkcR{sZZssZkJckkckc{RkcZZscsk{cksZc֌scZ{ck{scZssZJkR{ZksB!B!!ZŌŌŔ֔ssΌsńB:1B!RRc))!JB1)!J:)ń{cs{Jsc{ckkskksŽ{εŵν֭Μks֥{{{s{ssckR{k{ŵ{{s{Ŕ{֥{c֭凜Ž޽νťskΥť{sskckJJJcZZscsJcZJcZZZZcsk{RRZRccJkRJJBJ{ֵJkcRcZZcJck{JJBcZBBJJ:ZZJB:ZkckssckZR{cRsccZZRZk{ZscZ{sk{{RkkksZscskk΄cskcJR{c1B1!1J!:B:!!::kތ愌Z:kŵJ1!J:!!11!Z!!B!1:B)):!1!Rsk΄k{{k{k{RccZŭŜΥε浌ŭ{{ޭΔ{Ό|ޭŵs{{{{{{ks歭Μֵֵ{s֜Z潵ޥ֔νZZcRJRRRRRksZZRRJRcJBcZZsZRkRRBR{JJBBJťޜcZRRRRkJcZZJksB:JJZ:sR)RZkkkZRkJcZkJZZccZskk{ֽskΔkcBcckk{ZRkkZsckkkR:J1))1)1k))B{{ńJ1sR{sJ{)))R):)):R:!:1!:1!!!)ZkskkkkksckZsccέޭ޵ֵ֥s{Ŝ{ޭތΥ֥{sk{{έkŜޥŭֽ֥ť֌ZJޜ{R{kέkZRJ{JZRBcZcZRcRZZJkkZZJRBccRBZZJ:c):skk{{kZ{RZZccZk{ZcZJB!ZBkRZBck{ckcskBJZkZZcZsZkc{kk{{{Jckckcc{kZ{ss{scckkk1JR1:1!::R)R{1::!sssքc{k{JBB))1J:!:)B{)!1:B)::!)ksks{{sZcsZkccZckcc{ε朔ŭŽŵŭŵŵΜ֭Žsk{s{ޥ{{{ťŜ֭ޭﵭ֜{{{{Ŕ愌ckŽ{JZkZcZεZBJRZkZRJRRsRJRZZRRcZJckkBJZs{:cRJJR:sk)kscZ:c:kZJc{sBBJ:ZB:{k{{skkcsJs{Zskk{cccsֵ{Zkckks{RsńckkkskRkc::!:1:){JJ{ssZZJ)Jscckkc111)!1:1:1!))cZ)1111!){ssk{{{kcRkkkcckŭŭ֥ޭ֔Ŝ{ޔν攥s{{ŽέΔ{{kքΥ֌{Zc{΄֥Μ{{{挭{RcJcksJΌZkBRk:ZJckBskZRJBRckJkJRRcJsZkRkJRJ:sRZ愄k{Zkkk{k{JkkZRkcפּckRRB{ZJRskss{kZskk{{{c{s{kJckBs{s{֜skc{{R:{kZBR1kkcsccskZZskRJ1BB)k1BBBZk{sss{{)1BJkR)1k{cscB::!):!J)):11)J11:1B):!1kޜZckcRss޽έބεޔֽŭs{csޜ{֔֜s{sބ{ŔΌkZcs޵ֵ֌{s֥RJkccckcJsRRJBZRRcJcJZBBZcckRcs{JJJ{cJJ1{kskkZsRZskkk{kkRkkZcJJJBcB:JcJ)k{{scskkk{csJJs{ZsZsΌsޜRZΜ{B!RkcskcZRscZZsRB)J{))ZR:sŔkRބkkRRRscJR{c:1!!1):!B11)c1))!!!:{業{Z{k{ŽŭŌŵŜ֥έބΜŜZŜ{Ž֔ť{{sssŭk{ssńZss֔sccޔsRksRcZcc{ccZRcZZcBBRJBZBJBRJcRŔks{kkZ:Rc{{kcccksk{kckkkZZJRJBcBJkRZBJΜs{scssccsJkskZcsZk{sccRs{{::{sJRc:Bc{scZck{k{B))B))ޥRsZZ޽Z{Z1B!!c:B)):)R:R)sk:J)!1!11Z11B1::ŭc{{kޔŽťΌֵťskֵŽνsk{ބŜŜ{{Υ{k֭ޭ{RZ:sskRRccRZZkRskRBZZJJRB:R:ZRJBc1cZss{scZ{c{{kkccs{kkcZksscck{sZs)RBckkc{c{s{ksskkkkR{sccs{{Z歭ޔscJ{cJ޽ZkkZRsckZcZZcc1RRc1B1B)RsRk{քRskZ:kk{{R1)!11::!))B:)Z11!!1!):)1)))B1{{sR{֜{s{{{sֵޥֽs{֥ŵֽνΥ΄޵ŭ{{s{{{{ތŜޭ愄Ōs{ckc֭֭֌{kZB{ZΥ朌JRBRRRcZRRkckZsBcRkJJRRJJsJ)RBsZRccR{քkkscskkcs{sss{sckZcRRkRcZJBckcccsssk{kZsRsk{scJs:sssZZskk{JkkZkkZkZskccR1k:::B11RZ֌RsRBBRB!B:)!!!!!R:::J1!B):)!::1)1{{{Zc楜{έ{ŽΔΜΥΥŜs{Ž޽攽sk{k{ťŌŽν浭{{skskJs朽ZZZJJRkνZJJRZkJRRZcsRZcJJRcJkBBBscRkJRkc{RR:kBcks{sk{csssc{Zc極ZkkkZJsskcZR{ckZZ{s{sskkRssքZkքZ{Zk{έ{Bc{RsRΜcRZsckkksck{R))R1)BBccsssJscsc{ssZB1)))::::RcJkRsJB1sccc{c{εk΄省ΜΜ֭ΌcΥsŽΜ{ks{s{s{s{s{{ֵ֥{s{R{sB{s{ޔ޽ޥ{sRkRRRJBޥ{BZRJJJJRckJZJRZcZRZJZZcRZZZBJkRZZZJk{cZkks{sRskB{ŵ֜kkscskkJRcs{ksc{ksJ{kck{k{RccRքťssBքs{cs{cJc:kZRscskB):Z:1!::B{{ZsZB{sJkcc:Z)J)1JB!BZŜR:::Jk:Bkc{Υsks{{Ō攜ޥνΥ{ֵֽέŜs{{{{{kťŔscZkZJJsBck{cs{{ŵ֥RkkJRZRZJsRRckZBBRR:JkJRZkcksB{:Z{ckZJRZRJ{cRkZZ{ksks{Zsss{{{ss{scks{kc{k{cJ{k{RZsc{sZs{kkkc{JsRkcscŔ楔skޜJkΌssc{ksZsJ11R!1!J1)k{{sZJZs{k{k1):RR޽sB!1))1)11ck֔ŔskޜŔs{εޭńŽ֭ŵŔ֭ŌŽ޵ֵޭ{s{s{{ksk{{Δޔޭŵ{sZckB:ZsksBck{ބZsZBZJZBRJkss{JZRscZBRsRsBBRsJRZRsZccRccccJBckkkscsckRcsZc{ZZZJscZs{ssskkcs{kZZcZZckkkZ{{csZk{{skckk֜֔cscZcskRcZRs{k1)c):!!))k{J{sBs{R!R:))B):::!)B!)!1ֽﭥ{֔{{ťs{{Ό޽֭ŵ֭ν挭ŔŌ{k{{{{Ŝ{ŭ֥ss{sskJckBJsRRcccsJksRsJBZR:J)ccťBR{RsRB:1cZRBZRBJ֭{{R{{kccsZssRkRRcJ{:JssccZJscs{Z{ck{skkR:JkZ{kss{s{Zc{kεks{sέsΥRkk{ZkZRsޭŵkν朔省scsR111BR!))!!:!)1B:!)!Jk{Z{ŵŵŌťŽŌ{{sֵŔ޵ֽŵֵŜŔֵť{{ck{{{ťֵ֌Jkksc{skZsJssZ{RcckcsZZcJJJRZJJBkkŭRZ1BJRJZBRJJJcZkcRRJRssZskJRZBR::cJJRZZ{s{RRB{BkZscskŽksk{RJRBckkkscck{޽kcŭ{sﵭ{Rޭk{RŌk{sk֌Z{{{kJ!)Z)B!1B):RJcBJB))!RŔssŌsνť挥ť޵޽֔ŽεŽν{޵֔s΄s{{s{{ޥﵵŜsRֵkskkZkRcŌRkskcsRZ{c{kBRRBc1JR)sR{sJZRRBJ1ZJZBcJ{kcRJJJZRJJRsZZcks1JBcRJcRJZBR{{sc{sk{sRkcZZc潥c{sk:B:ZBJRBsc{Ό{k{RŌք{sޥޔc֭֜ε{RkskΜs{޽{kcZ{{sR{1)!1B)1!B)!1R1BJR)B:11)1B{{ν{ŵεŽŜεskŜckks{{νεťΔֵkkk{{csccRsc{{{kkccc{:R)BRB{JBZBRRRBJZcsRcRcJJZ1kRZR)JRRRZ:scsBZs{JZ:JBRBc1:JBBR:kZccscksRZsksŭŽ浵cZccRBJJ:RZckcksťkc{{skskck֭έޭckR{ssckkkkssckcZ{ΔcRZRcJRRZJJcR)1J!!)!))c!!:B)1)sZBs潔޽朔Υ{ֽŭ֌ތνŽΌ{ŭ{s{{ŭνŜֽ{ν{ť޽΄cZ{kZkkcRRRcc{JBJ1RRB:BR1J:J{JZRJZRcZZR{kZRRJs{{R1ZBZR:JkRZcZZ:kBZB:R1JZcZZZR{{{{{BcsZkRs{cc{s挵{ΔcR{sks޵{kJJJ:c{{skťΌscŽ{kRŭνΔZ{s{Zcޥ{ccJ{R{k1B!!)1cZk{Rs{B!))11!BB):))!)J)):k{RJsk{攔քŭεքΜέޜ{Μ步޽֔s{浔ޜksc{ckc{ZkBRRckkJRBBZJB:R:BRB:BcsJkZkc:JBZBJsJ{BJscJRRkZsJkZBZRRBJ:BBZkcks{kkscZZcccRkc΄Zsŭ{{{kZsRBRksssksk攄scskkΥֵkkkcs֌kkŔsssc{RZcΌc:!!:!sBsskcR)1!))!:)1))!)!11)k{Z)kks{{RkŵޔsﭽŽֵ޽{ť{εsŵ޽ֵkcsRss{kZR{s{sZc{ń:B:JRBBBBRBcJJsŵcRk{sJB1JR{ckkRcZckRk1JRRBJJ{:cBJZkckkkJsZBskk{skkZ֌ֽńνc{s{{{{Rs{JZ{sssZ{{ބ{s攜skkޜޭsRRŭcssťks{sk{ssZc{)1):)kRZscssZ!!!)R!)B!!1JBRJkRc!)!cks:k{ks{ZŽ楔ޭs歔掠έΥ֌{kΌ{步{{潜Ž樓{scskkkskccRR{{{Rk{{RBkBZBBJ1B:JsΥkZRBBkcckBJJsBZcsBRs{cJRRJZJBJZBkZ{kscksssZZZZZ{c{{kŭεs{{ťs{{Rcckssck{c{籠{cŌskksck{ŵ޵{s1kZccsskRkRB):)!:!))1!11!!)!RcZcZZBJ1!!:!!)!)11:)1!ssJ!{{ť{k{kscsc{ť֜c{kޜs歜ťέέֵ֭s{Ž{ť{歭Μ{凜Ž省{{ks{kskccBk{{k{{kJckJRZ1JJRZRcZZ:RJZJ1ZZ:R1kkcJ{BBBcRBsJRBJ{skscJBZ{Rscck{Z{sέέRJR{kssssk{ss{{޵s朽֔skk{νބZs{BRBB1c:))))1!!!)))))RckksJc1B1BB1)!1)1BB:!!1{s{{{J{c{Rcs{kΥέŔťŵνΜsk{s޽{{攥Δオν朜{ŽΔ֥ν޽ﵵťﭭΜŵޜcskccsk{scsRsֵZޥ{֭kkZRZs{kJ:cc{BZBsZ::ZJBBcBBRJks{sZkcsc{Rc:B:RJZckJskkcBBŔckcJksk{sR{{ksΌkRkZckssŌ{޽k{Žޜތ{skBk:sֽΜJ֔{{{֔Z)R)!!!!):c!!)!)kkkckksc111))!!1!1!:!B))!:1kZ{sskk{skscRcJk{sέ{Ŝ֌޽έޭޥ{kέֵޔkޜ楜ބε֌ΥΜޜ{ńRBZRZJsZc1B:kkc攭Zk{Zkk)JksksZc{sZBcBsZRZZ:kc{kkJkJ{cZZZ{B{εZJcZscZkRskssksskcZ֌{skksk֭scZZR{c{s{cΔΜΥֵΔsscskccB1BŌ{sZ1{sZkcRsks{csc)B1:)B:R)))))RJ:BBBcR)1::1):B!!):B!!)Jsksk{{Rk{kZ{RťŭνŵΜŌέŭ޵քΜ޵ń{ֵέֵ޵{ޭŭŭ΄kkcscsB:JBRkB{cB{ksssccsZc{kskckkZ{sJJZJB:JZJ{{kZcZJcscRck{cBs{{Jk{cccc{kRkssέZsޜ΄k1Rk{{sֵﭵŭέksckcֽZRBBޥkskZsŔscB):)!))!:1)!1!1)1):Jc1!1!)!111))!)))1B1!)!:ks{sskck{ֵŜsZŭ֔εŵεJkքŵޭ歵{֌攥{{քŌ޵Ŝ֭֜ŜޭŜΥŭťssskRJccRk{kJcRkZ!RBZsŜ:ZJZcckckcZ{{sc:1JJsRJ{{JRsZsZZ:JksRssscZZccZZs{{{RkssZscֽkcέcRsRJZ{R歭ŵ{s{kss{{s{s{::!JŽkŜ{sťks{ބc{Rc:!1:)!::)1)))11B!:Js:))!)))1!!):!11)11!Zk{kss{{s{c{ŌޥŜsk歜֜{޽s֭{{{sֽŽŭsνέk潽Ŝ֭Žť֭Ž{{sތcsZJkZZZcRR)Z1cBckkŜRJBZcsŵ{sRcsscR{JZBRBkk{ckc::BRJJ1BB{kk֭{{ksZքńR{k{{sssŭks{RRsBkk:skν潜{{c{kskkssk{ZsRsZť֭ΜΜs֭ŵ{cB:BJ:RBJ1Z:!B):!!BB:)B):)JZsRsk{sccZZJZ{s{{Ŝ{s{k{{ckkŜ浌c潥ޔޥs{{s֔{{ŵΜkֽŜޔֵ֔ބֽ֜ΜέΥkksZksskssRRkBk:kkJJcZ{ΜskckZB:R:cŜZs{{sZcssBB:k:kZk{{kJJskksB:cJR{{{k{{k{{sckkcccsk{scssksZsckZsk:s1kZŭZc{kcskck:)1B::sZcs{sŜcc{νscR{ŌZJ))1:!1!B)J!)))J)c1:B:)RcJRsk!):)!1sB!s)!:{s{s{c{ks{s{s{εέֵŌ{ֵֵﭜνޭενťŽńΜֵ֥֔֜k{ZcsJJcBcskkBJ{s{kZ{ֽckZZJ1!cRZcksZބJc{kkBRk{RJs{kk{c{sZ{{JRJRRcńssksZ{{k{cRs{kss{{{cssRJZ1JskJ{Zޭksc{ΌckcR!B:J11sk{{Z:cZRkZsR{kZsZJ1:!)!1)!)!B111):)1!BBB!:!1JkJJkss))J)):s1!!:{k{{ssss{{kskkュ{ssތŌޜֵ攔ŭŜﭵބֽŽsޥέ֔΄ֽ޵ŌŔZkcc{sJRcsJޔcccsޜsk{kkZkRkBB{kBk{Rs{Z{ck֥ZkBRsR{skZkZcJcsJB)skskckc{֔ksュZcs{c{Zk{sZcZZZ{kRkcsRZBkscޥkks֔JcRZRBB:)skkskksZk)R:!ccŜ{Z:Js!1J!1))!1!)111))1!1!!)!BZB{sc:B1JcRRs111)):{kckckcsksks{{ss{{Ό{sŽ歵{΄֜ޔέŽέ極Υ֌ޔﵭ޵ŽΥ֥{JccccJB{cJscޜRc!ZcRZBBJJsBskc{{Zck1kZcc{c{sRcJc֜cJ11Bsssc{ZssZZkkRsk{k{{cks{{s{k{kcJ:Js:B1RsޜksZcJs{{ckBcc{Zss{cksssZcsssc1:)J{:1B!:)!:)!!!)ŵc:1s{::BR!{{{)))1ksckkk{{{{sks{{ťck{޵޽{έޥޭΔ޵޵{޽ck{ksΔŽ֜ޭ{֭֌Ō{ZkkZksssZ{{ZZk֥ŭZ{νssRB)J:JcZscZJccs{cJ{kBJkk{{kkkRZRc{cJskcskccssBccsccJ{{kcss{s{{{kZZks1BBsJ1B{{ks{sskkc֥ﵜcc{cc1k{s{ks{{k{kcRk{k{:)1s11B:::)!!B!:)1B֜kR1kk:1)1k{k1:)B))B{kksssssc{kc{ccsބŌcsޥŭs{ΔksŜ{ss֔s޽Ŕ֔{ֵ޵ŭŔ{RsRZ{sc{ZRťﭭsޭksZ1!BR:{J{1kkR{{Z{k{Z{kkcJ{sckccZΜ{ccZJkJ{kkk{ccscRk{{{Rkc{{s{Zc{{kccsBZ:kR{ksZ{Δks{sss1BJ{Rcssc{sckcΜ{k!:BR)B)R)!!):!))!BBŌkRk)k{R!BJJsZZk!111R{sR{c{sZks{ss{kcs{kZ{ޔޔkޥ{ŔֽŔŵ{޽ńքk{{ﭜ{sֽR֭業札֌{JsJRZ{ssńkZcRkkcRcBJsk)Jť:cscZRJks{{{JcZcsZZR{ŵ֜{{kcBc{{kcss{k{scέssRc{Rcksk{k{k{ckZ{Z1cc)RsRkkޥ{ks{k{skZŽ札cs{k{Μŭ{ZJ:1B{ZRBB111Z1))!s1ksck{s{ŭkk{{{sJBZ)B{kkskskZ{sZksssZRk{kc{{ńs{k潌֭s֭kޜ歭޵ťֽ{kΥs{ŭ攄{޵ޔޥ޽ތsBJޥ޽֌֌{kc{cckRksRsc֜)ZBRRcR:kcR:k{R{ZsZ:c{:B1ZJ{skRcRcs{Zk{ck{ccs{skk{kss΄{sskc{ssks{ckZkksksks{{{ckR{Z11:cRRsBkZckBk{Δ{{cscc{cckֽ֜s{Ŕ{ֽs:)BB:)1:1)!kcs{R1:Rccsks!c{{R:c:B){csZsc{{ckcs{c{skRk{RZsťŭ{ssŽνΜ֭潽޽ŭޭ{sֽŵ޵֔ť޽歭ֽνŜޔ{scR攽Žޥ֌Μ{{kkkcckJJZ)J:{ckRZ{kB{kZBRs{kRcskks:Js:RεcBksRkkksskss{cZk{cRkZJZZ{{sskc{c{sބZsBsskssń{ZskcskskkksksZR{c1:BR:R1cRB{ZRZ{RkcskRkޜsssksksŭsks޽s{JZZRBJ)J:B1Z:JB:B:)1!ksZJBR{s{s{sk{:c{RcRZB!)ksRssssk{{sksc{{kRBνŽ{{ťŭ޵ŔνޥΥ֭֜έ޽ssskks{ťJZcZcJZ{Z΄ksZJ{kc{{cBcέkc{kťZksZsRֽJ1JBcss{ssscJZck{RZZc{c{Zcckkkk{{cscJsRZsk{sksss{{k{sk{csskJ)RJRB11BJc!kcskZ:kscΌŵ{k{ssks{Zk{s{έsJc1kRZ:B:JBkBZ:kkRJ1RBBc{ZsZksR{ss{scJkBsc1{{!!:{JkJ{kRZksRkkss֭kcŜksέΥ޽֜ŔνŌŽ{έkŭccck{ckŔcZ{RZRccksk{cRsksccs:R:kc{ﭵ{{{sޭk!JZk)ZkkcZkckkkkRZ{ޥ{kcc{s{c{{ss{kckkckc{{JJZkZskcck{s{cscks{{cJZBJ1{::cBkkkcs{kJZskkk{s{scskkkZZJkskkk޽歜{sťJJ:RsZJ11RJRksJ::1{sks・{ckss)11cck!֜!!BskZk:ccRs{kskkscΥŌc{s{Ž޽֜ޔք{νŔŭ{ŭνŭތRk{{kkŔck{k{ssZBkkZRc{kc{{scscZ{BsZR{cZccΥks{ބ:11R)1kck{s{scJck{ZZsBcccss{{kZZk{k{sZkcZJskZRZBR{Rccs{{{{ksBRBJR1B1:)JBRcJ{c{ccνZZBs{sckkckks{s{攽ť{ssssssk11!)1J:JR1)))c{{sk{{ŵs{{k)B!!kZZ){c!!1BBk)ZJcZsc{ksck{k{{{{ccﵭss{{ŭέޜ{ť歵s{έŔ޵{ŽֵνŭΔcc{{kksksscsckscsZRsZcR:Zcc{ޭs{sZJZBZckZs{sZ{c{Z{k1)J{{B:Δkssc{֌{c{{k{ccc{k{{{Zcs{ck{Rkssccks{cskkkckccZkkck{scksck{scZBB:!1BJRkk{Bcccckkέńk޽ŭsksckŭk{{{ssZńk{csB!!1!J1)11ks{{{ssRB{Zksccc{{RJsJkc)kkJcR{cksssckZcRRksk{{{ΌŔޥΔ޵քkŭνֵŭsތν֭RcsZs{cc{RccskcscksccJZcsk{s{kkskksscksΥs{{{{kZkZ{1)1Jc1ss{kRkZ{s{֭{{:JR:{sJcR:R1RB::B:J:J)J)ksJZB:):BJZJZsRZJ1)1!BBJ{Z1Jkc1JZZJZBckkR{RZssskZRs{ZkΜsc{sc{ssŽ{sss{ck{sZZ{ŔsckΜ{sޔ{sŜ{{քckֵZcZJ:JRsJRscs{ZR{Z{J{kk挭k{{ތŵ{ֽνŵε{ޔބ{Μŵ֭޵ν{{scs{kcsk:sRsck{skcsskkcBcsk{kZ{sZs{Zks{ZsscssJR:ZsckcsRZc1:{cJJc{kkZRcscBZ)JZck:{JJc)Z)B:JBJ:):BsZkkR1cB)s1JJ1::Bc:BsB1:JZJ1))cZBB!BJRRZJkR{BcRZ{c{kc{Ŕl{ssk{Z{ssc{s{{cZJcsk{Rc{΄{s{{k{Zބc{k{s{νkcŭk{kBsc{cZZcks{ck{kZkkZkJsk֜s{kŵΔŽޜ{֜ޔΌέksέskŽť֔ŭ޽ŵ޵ŜsZZRkRZJZkskccksskZZBZZcc{cssZcss{cksZsRc{{BZssckkssBcZZJ:BZkkﭜk{kZB:RR:sks{:c:J:){:!kBBJ1:B1JZ{!kJJZZ:RB)1cJB1Z)11)BcB11scc11!RkssJcksRRkZkRkc{ccscss:csskscRJkssRk{Zs{s{{RkZ{քΔc{kZcs{{{scks:1{ZcRBJBRcc{sZsJcJsZcޥsZ・潭ń1skń{{sΌŭ﵌֭Όscޥﵽ֌ŜΔŜνRs{{s{JZJJsZJcRZccRRkRskZks{{ZRZRckcc{k:cRBcZs{{{cckc޵ŵR{{Zs:kckcsR:ZB!c{BZ11RcJ:B)11BZŭR)1:JRRk{BB!1ZcJRZB1k)kckBkckssccB:BRRZckcRJkZkk{{ŭń{{ckkkskk{kkR:!sJZRZcZRcs{cssskkZkss{k攄{s{ޭ{s{{ZcscュB:!ZJZ{kkZRcskkŵJkB{cZcέ{ֽΔŭΥ޵sZBcťkc֔s{{kcń޽֥Δ挄{εŜŭ{ZkεRRZBJZk{ccZk{{ZJcZBkcZRRZRkskcRcks{JBZ{kkΥR1JckkskťcRcBcR:1c:Z!:Rc:RZcJZ)R1Z1:k{JB:)J)s11JBR!:J:Jk11J:Zsc1c{ZJJk:::!:::{Zs{cBRJRc{kcs֔ksֵRΔsZ{ZssZ{cZZ{{{1J:{sRskkc{Ž{c{s{sޔ֌{Μksޜ{޽Js{BJBRkRkJ:BskRBscZBcJkZ{{ť浜s޵樂c֜ťŽŵ潭Z{{֥ťs{cޭsŭ֭s{tޭ֜ŭޥs{c{:ZBR{ZcskRZBkcB{sJkRkkc{{ccZJ{ZքRJJޔk{{{{ޥs{s):Zkcc{cc{RJ::RBBJcJ)Zc:RJk:B:BBBJJcZ{Z:k!BB1)):RZRBJ)))JJsZk{{scﵔBB!:11BskkťcsJsJks{ss{s{Zsk{cksc{{kZk{sccsk{cRJB{ބZޜkZs{ks{{{kk{{c{s{{{kcscބkc{c{c{ZRc{BRZRkZZJscZ{s{{JZsss{s{{ZkZss{Ό{νsޭŜέkε֥ŭεέsck{ν֌{Žޜέ{{ťֵﵵ挽{{s{RksJ{s1ZRckkk:RRνBkc:ksRckkZ){sc{kZksZs{cޭsZJRs{skssccks֜B:BkR1RZR1J1RZcBB!B!BBRkJBkB!1BBZ:RcRJ!ZRBJ1:{c{k1ZB:1:R{ZJ{ckskRZ{sťssc{ssccs:scBc:{s{:RZcs֌kc1B)Bc{sŌ{s{s{攭kkZkZ{JccZsc::cksŌksR{JJJBBksckssZkZZ{k{s{Ό֔{{ΔŜ֭ZsΜ{{֭֜{ֵ֜{ŵ{kcsk{sckRsccs{ޥ1ZZ{sZcZJcssZRRkJskcckZZccŵBRJZ{kkssέRťskkk{s{ZcckRsZ:B1:Jc):k:JJ:ZBJ:Z:)B1R:J{R{))!J1kJR{:1!B!11BZ:1!Jc1BZR{B:1B!:{J:1kck{ZBcZk{sRs{s֌Zsŵk{kkZ{:JR1::B))!:1RZsk{k֜Rs1))ŵs{{޵{c{{Z{k愌ss΄!)1)R:BB)Zkkss:ksJ{{kRR{{cZRsRZJZ:Zkc{sBZ{sccֵ{skŵsZ{ΥŽ浵Υֽ֭{ΔŌs{{s֭֔νν{{εΌΜŜ޽{kkZkskkZJRccZZ{BZ:BRk:RcB11ZB){kkZ:R1{ss{sŵs1{ŌkΥs{Zc{:JJc)J1:R{RJJBkRZZc::1c:R))JBZB1JJ:RZ1)BsZ1BsJ1B{)BJ{cksR:ZB1JZcR{ZsZRJkRcskޔcν{{BRJR::RRBZR:1s{cc):{ŽŌ{cJJ1Rcs{{k{s{csΌέ{!R!)1:11J)!JRkksRskssk)sckcskRc{JJsc{{ssΌ޵sc潜ŵΌュ֭νέεΌŜŵΌ֔kν֥Žks{ޭ֜ŽZ{s{{sk1:BZ{cR!s{!sB)B1)Js{RR{sRssJkc{!cBZc{{c!Zν{{ccŭ{skB1sB1Rs1)J)JB{kscs1:1Z)B:B)R!BJ:B1cJ1csZRcJRsR)c1JksR{J{1:!k{{cskkkssc޽{ŌBs{RRs:)BckJ:BR1R):kcsZks1R֌ΔcRB:RB{{k{ť{ńc{cJ1:):BcB:J!!Jcc{{kZJksBZRB{JZB)s{sJ!Zsc{kkJss{s{kkֽ{{ޥ{֔ŭֵΔ֭֌ﵽΌ֜愽εΜŭŔΌεŽsޥŭŔΜ{{s1cBR:sJ::sc{!):Z{sRskcZBZs{J:֌cs{εJ:BssֽkkssZJkBc1)sc):){11:1B1sZc)!11:1c1!1k:BJk!111Zc1ZJJ):R1:1R)JRZ:cc{Z1:!BBJBBJ1JBZssskZJsZkc{{scZsŜ{kccJ:)B:B)R)1!!::kZkk{ss))JRB1cs{潔ZJsŭs{sޥ{ksZ{{sR!:R!1!1)c{1RksccBkRkBB:JR{s{kZRkcZkcBcssssR֥ν{ތkc֔޵ΜŽΔέ{{ޭťŭŔތkckΌsk)J:{RR)JcBcccťkZZc֭ťRJ1:B::RccBksνBJZkέcs{c{ZRs1!:J1c1Rk::1!BR{sckZkkJ1J:J:!R!:RB::c:JRJ)RZJR:kZRkJZ1BRB!Bc1J!BkZcRR::Ō{{ks{ΔRŭJssZZZ{ZZB):RJJ)BJJ1){{s::R1JJ:RRքsc1Z{k{c{sތ{kcńńsc{k{ssJ!:1Z:B)11!)ck:JcZRZJ:Js:Z:k{RRBkZkc:J1ZR{{kJc!{cssΔΜ歌cޔťŭޭތέ歵ֽŵťckť{k潽ޭs{cΔZΥ:RŽk):1!{BB{ֵޔ:sskRJ֌sJ1BBJZZJBk1{kJZ{kֵk{scRskZkB:RRZ)){cJ!{1Rs{kRsc){c!)!1::J:!J))B:Z!1JZJZ1:)BJ:J!:)Rk)B)k:::B)ZccRZcŌsZcsJs{R{s{{ccssRcscs)ZkkJ11:):RkccZR{!JJJ1:Z1ccŭ{{s:{{ssŽk{kss{{k{{c{cskcR{{1))!:))J:BJss:kZZ)BR!{c1:BZZJRZsRB1{kZ1kcJB{cckRcRέ{ޭ朄޵浵sֵkŜ步ֽŜŜ֭ńsΜΌޥťޭ֥քνk{ZBkR:Js{sJJ1:RscJscJBc{skkk{޽kZBRZBZBJ1:kJ!s{c{Μ{֥ks{{ZJJ!B)cBR:RBc{cZJBc{ZB)B:1R1)1B::J1!)RB{:B1):Z:Rc):)1J{RJZ{{{ZkcsŌRBcR{sRks:{{Jss{{{ksZ)BRB::ZJZ:JcBRcRssc{JRZcRcsZss{{k{Zs{ckֽ{{sΥ:cJZBkc{:1c!ck:JZ:JskZ{csRc:scJŵŔcŔε֜ŭsŵŵťsΔ֭ŵ֜Ŕŵŵkŭޭν֜ŭskZkJZBccZJs浜{{{{JZcZkJRJkcZZssRcJR{R)RR)))11{s{Zńs{ބsRk{csR1J)1):Z:sJ))Z{Js:J)ZZ1kcZ1BkB:))11Js1:Z:Z)))):)B!!!:1):R{s:J)kksZ:Z:sZZccsJ)Zkk1scckZk{c)1JBkcRRZZ)J:)1)!::JB:!JB){::Zc:1)ZBBB)kck{Z1k{J{Z{s{Z{Z{cZBBkJJBsJR)ssk11R{cR1J:ZJck:cRRRέŭֽZքŵŭť΄ﭵέ{ŽֵŽŭ{ޭŵޔssބνJkkRZcRBZBkB:):1)εsJcZcJRc:Zsk{s{JcRZ1J!JZJ)R1J!JBB{!!)RkksZckkssBRsZ)1:)BB:BcRBB:BssJ))JZB!1J))1:JR{R:JkB!1c):)))11!!!1)1!!!)B{sk))1ks{Z{JJRsRR:RRBRsskRk{RBksZZRZss{c)1!:)1:J{:!!:11J::::1Z)J:B1)::Zs!1:BZJB1B1)Z!ZZss)kJ1Μ{ZZ֭sss{Z{BRB1JBRscsk)RZ1JJBJ:kkk)cc)k)RZZB{֜ŵŭŜ{{ZεŔŜŵﭭֽΔ諒ֽŵŽ΄k{֭ŭŭֵkRJ:RJZJ)BJ!RRνk{ֽsJ:cZskkcJc1ZsJB1JBJBZccJR{B:B:1JkckJRs{Bcksk{c{RZkZckkkcsB::J1:B:BZ{J)::kcsss:c)1BccB1!)1!!ZB:):)B)Z!1)1)!1!))Z)!11):Bks:)1Z{ckscJBRcsRJJZRJsskZkZJcsskscZ:B:1RRB!!BR:)B):)Jc)cR1Z!1c1B1!1cssBB11R1:ks:)BRRތs)s::k{{c{k{{{{kkskֵZB:J11B1J:1ks1BRcBB:ťkJBc11R{JJ{Bť޵Zťֵ޽ŭ{ss֜ޥΥŌs{ޔΔֵֽskk{Z{ťŽ֜sRRcks{cs{{ss{Υ{ckkk{{cc{:Bsc{JRRccB1c!))cZRs:B):JJBJJ!1csc{ccRcZ{sJkRkccs1JB)BBBB1c)BJs)J){)::J:1!:cR)1B)RBR)){R:!!)B1RZJJJ:1:1!1!):{:J:{ZskRZJJksŭkZckkZkZkckk{:scscR:BBkB)!)11!B1BB1BB)B)!BBB::B:1ZcR1kJ1)Rc:cB!Z!:JBBBs{!BB{{スZ{sŔss{{sk{֥1)RRZB:!BRRcJ1Bk:RsJccZRBBc{R{1BŽﭔťŵν{{s֭c歵֥֭{s޵εֽεsֽޭֽ֔ŽsZccZ{ޭέ歜{便kޜskc֥֭ksks{kkk{:)!B:{BJε::R1JBB:{JJBckcRkkZJ1{{k{Z{ZkRskksckZcks::1::111BJc):Jk:R{JB1RB!:JB1:)!J!RRJc)kB!Z)!J{R)!)1:!J1!B!!!))ckZޥsk)1ZsΥ{{kZkJscsscZRc:Z{{ckkcB))1BR!)!1)1R:B)1:1)))ZJ1:RJ:1JRJ1c)!J:1B:B1R1):B:ޥ{J:1:cssZs{֔skks{css{k)))1)Rc{R11Rc!:JJR!cZZ!R{BJJ:֥s1Jsތkksŭ֭kΥŭskֵΜŭ֔Ž޵Ŝ歽朔ŭZBZBRs{{sZ{νεsJsBZckJBJ!!1BŜsc{sscRcJJR:c{ckZJ::Z)s::JBZR1RR1k)ZZckJRRkZsťsRk:{R{{ksRskνsBBBBJBBJ:RB)JB{:B:R):1:BBZ1ZB:1))ZsJR!::)cB!1R!B)1JB!B)BJ):k{{{{{ss{1BckJZcsscZcskc{{:Z):JB)!!)1)J!:1B)BBB!!::Bc:Z:)B111B1:BB)JJ))BZ!1!1:΄1R1JJZέkkZksc{{kcc{ֽB:B)!){s1)ks{ssBBZBZBJ1{R:11ZΌZs{Δﭜŵ{{s{sťﵵΔ֜sΥŭ{εﵥέΔ:JJRB{Ōޥs{sskc{ΥZRJR:!!::J{ޥskkkZk:k::B:1{11):J1)Rc1:kBksJJcR{RZsZBZJ1BRޭssR{ZRss{cccJJB::BBBBRRJBB:B{ZJ1):B)BΌsccJRkBs{Z:!cZ::1J{:)!:B!!1R{Rcs)Jkks{{kksޔk{kcckcksJcZ{sJ{1RckJ):1RRBZRB1)Z)R1:Js:ZBccJZ1:1JJkZZZ::sJZZZBcB!Z{s{{k{{{s{s:kksk1)!)1J!ssRcc:R1RksZBk1RJZ)ֵkscJJRZs{sťޥΔŽ{k{{{֜ޜ޵攵sΜΜΥֵskdֽZkJBJBJB{έ{{{{kccsŭΔŜŜssksZZcń{cs{cRc{c):):ccR1JcR1Rcc{JB){k:Zcc{ssJcc֭{sc{s!{Z{sksksB:JJJ:J1Bc:kJ::kR!):!ZJsBB:Z:ZckZZ{!!1JR)J)!)1ZsZckBZskkk{k{JscsJ1ck{JsZJ{Z{Rc{skZ{B1:Bc11:::1c)B:)kBBB::RcBB1:11):BJ!)BJBcRBZR)c::::{sZ{sccscJssZZksŔs)1::B1:11s{!J:JssBscJkZBJR1ZZJc{ckΔޭֽkss΄ޔŵέkkkֵsZ{c{ńJJRcBZZRc{ތ{{{{csss޽{Z֔ksέZkskckccsJZJ:ZcZ1:1!!Zc{!RZ:{1JB:R1!:::ZkscRs{J{c{)!B{Z:c1cJkBRJsZJR1)kcR1!J)1BBsR:BBJBB)J):!JJ)ksZ{:sksk):1kZ:Z:RZ{kckckZ{kskRkk::)BJ1:Rk1B!1:1Z)BBs:1J!1)1):Z)Z:)BZB{ZBRR::BJB){kkc{{ss{{cc{{ޜΌsεksֽB:!ZR{)BJ:JRcZ1Z:R{cBZJc{sZZ:J{Bε{Z{ޭŽﵜޭkkΥck{{攽ŭ޵{Ŕތk{RJB:ZJ:RBs{{skcssks{Ŕcsc޵ZŜ{{skZsckBZ{sJRRRJB:BB1ZRZRJ1cJRR!sB!R1:BsJkBBZc{ZkssssskscJskkcZ)J)ss΄cRssB)1:11)JJ1)cBJ:B1Z)BB!:1{BcccskBR1֥{s)sRJZBss{ZsZZZ{s:RBZB!:JZkkcBRBBB1R1R)JB)RBB:J:RcBZ:JBJksZkJ{J{kZ{{{s{{c{kޥsń{{csZޥ)1)11k1:Bkk)s1!s:cskZZ1Zk޵ŽRBc{kֽέk{{ksR:ZcRZZR歌νŭֵŔ{{Žŭνc֜JBJRJJBcJBc{JZcZ{kk֥csRJΔB1ZkΜ{kccsJB)kcRR{RRk)1RJ{s)B:1Z)R:)c!J)!RR)ZJZsJ{c{Rkskcc{ks{sZ{{ckcc{)c:ckk{c{{sZB:)Z)Z1BRR)))BB)B:)B)::kcsscsRsZ)c))B{!BZJ{ss{cJ:1Rk)R)!))1)J1::Z1J1)B)B1):BJBZ)kJ1B)s{ckssks{{{s{k΄kk{s{Ō{k{sތŭcB:){)JskscJ)JkBJ{sssc{kcJZBk{έ{֭csscZZsckZZBZ攜潽ŌΔ֭{քc{ΜRcRJZks{ZcέRc{sJsޔ֜csk{sZ޵{kckcJ:JRkccc1{)RRBsR1k{Jk:!k:11R1)J)1BJBB1:{ZcRc{skcsssZskZcJJRscRc{{ޭ{kkB1R:){!1):!11:s1!B)1)::{ssks{sZB):!JZcscZRccR{c:JRB:B1)1)Bc::11B:!J11J)B::R)RZBkB:sRk{k{ZcZsZZJRޜ{{k{c{{k{kkkcZ1scBsscZRRk{BBk::{csksJZ1BJBRsZZRk:c{֔skcZRcskc{ccքŌZR{便ss{ŜΔŭ{{{{ZRRZckkkBc{{ssssZsZ{Rc{sŭZR1ֵRsZBJ{s{kRBcc1BR:!BkJ1Z:Z!1:JcB1cZ:ZJ:Z1BsJZJJR攔sskΥֽ{{Js{{{{sŽťkRބkZZsskZRsckZcZsskcccRRZ:BB֥BZńcsc{sssBsZ1::)RB!1B:R!):::1)11::J))JB1c)ZJRkkksssZsscccJBk{{s{k֭k{kνΌk{sBkkcc)B{RZk{sZBRcs{{:RcZsŔskckZsJRkcZZޔZsZkccBJc{{k{Rk{ZkZZkJJBZRkcεs{sŵs{{BkRRs{cJ:kŔZZksZRcssRŽc{ZRB::RRť{c{ν1scB!B)1B)1RR1RJ:BJ!kcBB:)1!BkJJcJ{s{ZZk{{Jcsccksscsss{ks{sk{B!ZB1)Zs{ZB1{{sc{s!B)J:B1RRJR1B:J{sRRZZ{c{c{JcŽŭZ{sc{kk{s{ZsZks{Z1ck:JZBRJ):JBc֜1c!BBJc1s)):Ŕ{sZ1Zk{k1B:ZJk{{R1RZRRssZŔkŔ{Zkccccs{{k1JBRcRZZss{{JRZ:ZJ{kcJZRk֔ΔńŔ֔έ{{skk{kZBZcksJ:R{ZssscZccRRc:sZ1:ΜkJŔ{):ZZ:J1c:ccB1BB1):ZZB:J):)kBckRRJ{{Zk{ss{s{Rcssֵ֥s{k{{ޥsc{ks{{{s))B):kkkRB{{{sk{ssssBZ!B:B:1BB{!Rc{{s֔k):J{RkckkskcssssZkքkZJs{kcss{Jssε{kcsskZ{sńcRsskcs1!:J)BR1cR!B!B:1{1kcBkJkk{!!BRB)BBRBRJZskRk{ckBkR)RZkkJ:::Zk:Jsބkk{kťŭ{kRBcZBcc{ZZRZcRZBBcsBZB:֌{ZskRJBJ{ssZJ:ss{{c1Bccssֽ{kΜεZR{ssRkť{:::sZJ{!J1BZsZBJ:JBc{Jsksc:JR:{ksRkRsťs{s{sZkss{{k{έ{RkŽsZRBBJ:1)sRRBssk{{css11{ZR1J{k{sJssŌs!RsZscskcksskcc{{{sBRk{csRc{ZkcZ{sskk1):B:!RRJZ!B)R))Js{1ZcJcssޔ{RcJ{::ckZR::JJckcR1{{c{ck:J:s1Z!1{{RsJ:kZkΜkZk֥kJkss{{cs{ZBR:J:BBZs{{JZRskkŭεŽcs{cskc{s{{kJss֜{kRccZsZcΌsB掠sﭜJ:1Jc{{BB{::{BkZJ{B1s1{1JZBBBB::cZkkB:BZ:JZ{sRR:kk{{{ksscsޥޔcccŽs֥Z{ckR{B!:)ZJss{k{s{{{k{kc{R:RBRcsck{skέRc{{kk{{cťskJkkssJZscRssRRBRBk{k{sks{{sssk:1B!:Z1JZ)):::)1kk{{ksk{:BkkZk)1JZcRkZJs{sZcJBcBcZ:RZs{cޔŔ{s{{skZRc1J:ZZBJJ)BJB:ccsc{sZks{ck{k{skskZ1JRJssνckZk{ZRkc{cB֔{sRkc֭kcťRBRcs{Z1)B:B!JkJJZc{!::!JJJ!c1ZBB)cJ!kBZssksJ{{{sZ{{sksskk{{{Υ{攌{ksJBB)քs{s{))!1:)RkZk{sskkss{ń{ss{R):))RBRBBZccsscJJsRcsZkskZkskcRZ)JBBRJJZZRJs{Z{{Z)1R{ckss!1!)1R:JJ!1)JB:R{挭ks{{kJ!)kΜR!BkssJJ)J1ZkZcB1JJBJ֜{ZkkBR:Z{ťcZkZJRsΔssBk{sBJ1J:BJ:JRBRk{csRc{{{{ss{{歄kZkZs{kkZkB:BB{s֔sZcZ{sRkskcޜJZZŌŽRskcZ:cZ{kcJ:BJBscRRc!)):JRRR):JRZ{BJBBZZ{JZRcc{s{{{{s֜΄ޜkŔsBJB::BRBB{{{ss{)!B11)ssccńs{{{{{{{sZks11B{JB))1)JZJkRZ{֥ssscBc{{Μ攜Zsk{s{Z{kcRBJBZRs{scZRs{sssJ)1{k{s{k{1::!:JZRR1JBB:1R1{s{c!!!kZB!!!{c)Z:1cJZJR1ZB:BccBc{cc{RJs1RBkcŜΜcZZkcscR1{{Z{{sBRRBB1BRRJ:Z{ŭ{ks{{{{{s{cBBJ{BZZZ{k{{{sk{{{ckkRsk{kkJ{JνŭνRBZ!R:BcRckscc)!ZZsRRc)1k1BZ1:R1{ZB)BBB{BkR{ssRs{{朌ť޽)BBBJ:RJ:::BB:Bέ{scscskc{cckccss{{kk{skk)B:{Z{{c{s{ksŌcc{:sc{֥樂{s1JJBR{skZZs{kkk{{s:)ssss)!BB))RB:JB!Z::R1J1)sﵜ!sscR:Bc1cscZk!sBs1cB:BJ1RR{Jc){ccsZsŭsRR:kZ:{kRRsksRJJBB1J)JZkRk{RcBB{k{ckk:::ZcZJccJkJJckss:BJ:BRBBsJBZJsRck{cJZkcJ޽{ﭽ1ZZBsJcJ1:BRJJJc!BZ:cRBcs:cZRBJRZ:!kRkkJR{Z{c{ε{cBZ)BJ:J!RJJBJJJBJBBssss{k{{kscRkcZc1kZ{kk{sccքkRscRcskkZBRcZsZsZkckk{{ccZ{ckkssք:B))!J!):BB!R)J1BR:{cZΥ{!JsZ)kBRZsJZ{c::ZBZZZck:11):sBRs)JsZcRޭν{s{cRRZJsRRZcs{kcRR1BJBB{kŵscs)JJBcJRcJZJ1RBRJc{:sBRBB{RRkkBB:JJRR:sZcJBkcRskRccckBkέֽ:1):J))RńcsksBcB)RB{R:1Z:kBB:Bc:RkJsJcB1ccZs֌{BsZkŌZsskťZJ!JB1::!B!JJB:BJB:Z1J:Bk{s{{{{{s{ss{{c{{skksskksť{֜sťkcccJcsskZ{cskkcccss{skks{{kckkscsscZsscs{{{{k{B1!)::!!1R))sZskss{΄{ŔJ11!!:BBB::sB!RZs{kBJBcss)B::)JB挜έcZk:k{ksZZ{{RsJ{cZJRZ)BBBsccckcccRcRJBckZ::BJBsZRJ:cJJk{{cJRJBBJB{kkcZcckk{cZZRccBZ{{ss{{Z1:{BkkckkcZBcRJ1k1J):JJJZck!sZRBZZZRR:J1J{cs{ssJscsZscs{kތZJ!B:1JBJ:J1BB1BBB1B1BBBBBBńcs{{{ccks{c{{{ccsk{ZR{s{ksskkk{{Z{{{cJ{sZsckZ{sޭkskc{scRcRJJkRcΜ{kscssk{R{kk{{c{sc{{kk{J!:J!:B)BBB):RB:R:RkcckZ1Rs!1JBc:)J:ZkZRR:R!BJZR{Zs{{攜{sJJJR{cJBRBZRkZkRJBZBBBBcscRcc{ޥsscBRBssRJ1:BB:::BZBBJRccJ:JBRJB{sJB:JJckkZccZssscs攌BέRRcZss{Zk:cZRJJ)k1JZJk)k{ZRJR:J:R:BJc{ssss:skkcJssť{1:B:J:RJ1J:::)BJ1B:BBB:BB:JBJcεk{ZZ{scks{ckkkckkkkkscZk{ss{Z:c{sZ:kJ{{{Zk{cZk{sssksk{{kss{kss{sksc{k)))ZZJJJZcc{BcZs:!J:Z!1J)R!B)::ZcR1BcsZ:1Z:kskJΌJssJsccsRckJJRJJcJ{sskkkc)JBZskRRJ1ks{sքkRRRJBckJ)JJR:JZRBRR1BBJJk:JJRBRB:{sJJ1BssZk{{ZcRZsckcZcJŭs{Rssk{{ccR1RckJZ1cB1:JkRkRRR1R1:1kRksc{cssckR{c{{s11)BBJ1R:::11::J:Z:J1::1BBB1BBJ::JB1Ŝs{sc{{{s{k{s{kkccZkkcckcs{{kcscJΌkscΌ֭ŵc{޵Z{樓kccskkkZ{ck{kscs{kk{c{skk{kkssk{kkBZc1)))!:R:RR)R{{s{{挄!Zc{!)::Z)R)1:BsckssZZ1:BBJJR!B֌JBcRs{cJBZsZ:ssJRJZ{kZ{Zk{{{ZRR1ccc{RRRRJBcRJZB:BRRckBRR:JJB::{R{ss{{ZJB:R{{֭s޵ZRJsZscs{ssBckŽR{Z:1ZkZkkssBkccc!)kZ:R!Z{sRZ::11Bc{{{cskksccJR{ssŔBRkRc::1R:1B1JJJJ::B:B1:BB:BR:1BBB:JJBJB{s{{s޽sRcs{sccZck{ZkcsRsssksŌZcRZsBskZRޔkscZ{޵ss{{{ks{cs{kckZkkscs{kcsk{sc{sckZ{ksRcR!)1B:BJZkJZsccֵBs1BJR11BR{{s{)ZcZR))!B)sŔZc):s{ZJkkRsBJ1ccBkZZB1ssskZkR{:RRZks{Zkcc{s{{cZRkkBB:JBBRBZBcJRc:JB:sZcB1k{{{c)BBZkkΌ{BJRZkZZJccsR:1:{s֭Ŕ{{Z:JR:Jk{ZBcck{k{ss1J!{kZR1{Z{sRc1:1ckc{ss{kckRk:R{cskksBB:R1RB!:1BB:B:J)RJ:B)B:BBB1JZ:1J:BB:B:֜ńν{sc{{{s{Z{{{{{s{{skk{s{ZZR{{Z֜k{c֔s{ssssZks{Zss{s{cΜsksss{k{{BJ1J)!BB1)R!1)!!!{ck{sBs:)!:kcsތRRkZ:))!!):JRkB11{{1cskRRRZ!cRsZ:k1{J:1ksJZ{k{JZ{:skccRZZk{)k{ccBJJJBZ:B1BJJRBBBcsR:RB{scksZZcJckk{skJZZckZRcRֽcZBZ{JkJJ1Z1Jc:Zck{{{cs{Z!R:Bccs{{kscckkcck{Rck{JZ{kB1ޥJJBB:1B:1B:BJ:Z1c1:BBB1ZBB:1)11RJRBBB1:J挭ŭέΜsskk{ksskkkJZZssksk{{{skkcskks{{kBccscZRŵֵsckskssk{kZ{ZZ{sJ΄kJZsksc{Ō)1!!!::1))!1k):!!:c{΄愭)JRk1ccBckssZ!11cJ)JJB)RRs{R:){k1:JJ):)kR{sJJZkBkBJBZ:R1:ZcccsJRRskk:{sscRZ{{ZR:JBckZBR:B1:cJ1JZBBJ1BkJRRZ{sskkJk{s{s{ZJ1R{cskksZcZRkscZ1B:B:1kZ:ssRssckJccŽZ):{RRZk{skcc{Zcs{kkcBRcsskcRZkRZcޔs{cJZ1JJ1:R!1JB::1:BJBJ:::BJJ1:1J1ZB:JBB:1B:RJ1R:{Υ֔{ksckkZZsskccRcskkccs{s{s{{cskk{{ťkkRkZcsscޜ֥ޔΔ޽scsksťֵk{{ssR{{ksss{Υkkks!!11B1:!!)!Z)!)!c{ss{k{s{k!BZcck:sB!1J)!J1c:!B)J)1Z:Z!:::k:Jsc1RsJZJcksc:JքZRBsc:cZZ1cZ:ssֵskZkZ{BRZssJRJRBcJkJRRBJRZJBRcJJksc:R:s{{{skB)Js{k{ckŽsJRkRZ:Bck{{R{BBc)ZB:ZZZJcZs{{Zks{!R):JZRkJksssccRZkcJ{ckB{ksRRJ)B:B)B:)B1::1:1:B):B1:::::R:)J:J)R:::BB1:B1B:1JZńsk{k{kZcc{{kcJcZss{sZkkks{k{{s{Zckksck{֥{Zks{k{便{{c{kscs{{{c{{k{{ssZ{{c{s{skZss11BB:111:)))J)){{ssk{k{cZ)ss{kJRJRks1)1k11{R1!:::RZcJ!):)kZ1sRZZ1R{քkB:RcJ:Z{{JJ1c:)Jc{ssB{csss{JJJc:BJZRJRJRBkRJJ1JR1RJJB{BJJ1{:R)1RcksZsJksk{c{޵֔Δ{cBscZsΌRRscZkcc1ZcZcck{{ssJBk{ccZkkZ{cZckZJkZZcRscR:11:):BJ)JB:)BB:JJ1:B1J:11::B)R)BB1BBBR1R:RB1J:BRsc{s{{{{ssskcZZckZsckZB{Rk{s{ccck{ck{c{ss{sZ{ńR{kkcRk{sk{kkέc֜Zskcskkk{cZ1J1J)B1)B11)Z!1BZcsk{csks:kJJR{)JZJ!!BR!cZ)JZkckJ!)1:!RR{JcB{s1BJJcscZJZBcZcRk1RRR{k)Bs{c{RJJssJJcRB{sJZBJJBZBRR1:JBZBk{R:sJB{:ZB:JRcB:{{RZZ潵έsk{Zs{k{skkcksZZsss{{k{1:!JJ:kcc{sc{kcc{{sss){{R:{sZJJs{cc{s!B:B)JB:)::B1JB:J:J)BB:::J1111::1:BJ:JJJ:Z1J)ZB1s{kss{s{skZcZcZJkcssZkcksscZkc{cckkssskcksss{kֽkskkRńŌkZŽkcc{scskk{ks{kk{潭c{sccB!)!BJ1B):)1Z!!)!ssss{kccksssJsJ))R!Z1)!)1RR)cJ:)1)ZkBks{kc{RR!scRZscR֥޽{{kkscc:Zss{JJ{ssk{kޥR:JccZJsR:BsRR11JJRB:J:RBBJJJ):J1s:ZJ:ZZJZJsc{Z1JsssތŌ{{Ŝc{kckZkBss{kR֜ZZ{sssZs{{s{J))cBZR{Z{csksccRZBckJckcJZJcBss{{ޭ)1Js:B1:::):R):111B:B1BB)RJ::BBB)B:B)BJ:):BJ1JJ)B)Ό{cs{c{ZkRRRR{{{Z{kRccsZ{s{kssRkscŵZ{cs{ť{ccsތcZZޭR{sskZskc﵄skkkk{kk{ŜksέJBZ:cZZcsssRZ{c{kk{ksck{)JJ!JkŔ:J)sR!BR):BZZJJBcZ{Rck{cRcskk{ޜ{{{sBJ:kRc{ss{Z{{:B:J1JJB1s:cBJRkZJJJ)J:RJ{{{{JJJcZJBJJ:RJRZ{ZBBcRc:{{k{kksc1kkZckcJc:Jcss{kkks{{Rk{)JBBkR{sZ{sssccZRRsscs{{JkkkkŽk{քJ{sB1Z:B:B)B1)JB:B1::)::B:)Z)::1J1::::B:BB11BBJBŔkk{kZs{{{k{{cks{{{skkkk{kcsckc{ssŽ{s{s{{k{kRJJBJBJs{Z{cs{skB{k{ք{k1)B!JZ{ss{skRc{kc{csZc!s))J!!!!1:{ckJRZRJ{k1R{{{Z攽ŭ{s{kZ{Z:BRJk{{{sss{JckJJBZR{ZJR11R1Zkc:BcJk:RRZZBRRJkJZJRZkc{kJsk{{ck{kc{޵cJRscZc{{kk{kJJ1{ksBZ{k{JJcRc{kJscRJ:J{ssksRZ{kksk)11)BBJ!::1R:B1J!BB:B:1:11):Z!BJBJBB1::RJ:11:){֔{c{kk{Jk{{cckk{cckssssk{{{ckckss{εskŽccRscB1)1!)cZkc{{kskskZcRkΌkε޽skRB1B::RcRcs{{ksZc{ckkZscR!!!kB:k{cB):!1ZBB{{ZJZRR1)cZJkksB{sssk{c潌Μ֥Rk{kk:JsckZZBJ1ccRJJ)Bk{1RBcc{ksJJZBJkJkscB:ZBkJBJB:JZBJZJ:RJRR:cc{Δ֔{{{c{sΥRBRk{ZscsZcZZJBRs{RscsccZ{{kJcRB::Zss{skZZ1:1B::)1:R!JBBB)B1BB::1R11B:):)JBBB!JBJB:B))B1BRcŜZcZZZskk{s{{{{ksk{kksscsRsks{s{c{sεZ֭{ck{cks{skRkcZkkBRRcZZsZcs{{{RŵsJ):!::kc{skkZk{{kRssskks{s!!Js!{c!))sR)!:)cZsssZsR{sJkZkR)1Jcc:))B1RZ{Jޭs{:cksZ{R:csJB1JR::J)J:{BJJJc{:ZkcZJBs{J:)ZZJJ!JR:BBBcZBR:RRBB:Z֌νssέބZ{c{kJJ:{k{c{cRccs{kkRkZJs{{Z{s{k:{{sZ{sZs1{kc{kscŭ{1:::):B::111:)B!B1BB1Z!BR)JB:B1B1JB::B1B1J::J:J!JBsńkZJkkcscs{{{sZsk{{{{ssRc{scs{sc{ssބsss{kcZ{ZkkcckssskkZZc{cJRkBkssRkZZ{ssck潭cs{Z))):Bkss{ccZkcs{{sJBk{B1Δ{k!!1cc::J{c:BcckB):Rsk:B)1RkJJs){c{sscZsksBB:Rc{ccBZ)1BZZk1JB1R!RRJJJZJZB{s楌{cZssJB1k{Zk)RBJJJZJ:k::::BRZJ){{ք愜c{kcs{kŔkkRcsŭcckRk{ksBB1Rk{sZJcscccssZkcJZksR11B!::!:1B1JB!1:)::!):BJ)R)BB:J:::B1JZ:B:B::BB1:::JބZ{cs{sksk{{kskck{{c{kk{{kks{sskc{{k{ks{{{ZsZ{sR{s楄kkRskskRZ!)Js{sc{JJckZJkZccskkkkkkRB)11)Rsskkk{ZksssskZkŌ{)R{B1!!B1c)Bk{:!kc1::RJ!:Z:B:R!BckBsRZB{ksks{kRJB:{cZBBB:RJ::J:J::JBR:)J1B11R1JcJBk{ŭRR::R:sZBZcJ::RBRJJJRR:ZZBB:1Jk֭{Zޜŭs{c{sZBck{ZR{{:ZkkJkkRBsk{ZZB{scc{ZssccskkZ1JJJBRsZRsZB{111)!)1:BB):B:1::B:B)1::)B:B:B1)RB:J:R)RBZ1BRBB1)BBs֥kcs{{skck{ss{ks{{{ksssZkcs{skRkkskksZs{c֔skJcs1)1Rkkk{s{RBsskZRsZ{{{{skk{R::1B1Bks{kssckkckk{{k{kΔZkJZB!1!:{:c{!BR!RZsJ1)JZ!1BZJJJ)sJ:sBBcJc)s{{skZcJckBR:RJ:J:ZRZBBBBBZRRBJJJRBJs{{ZZBRBcsckJk{s:BJJJ1ZckZ!JZRBBJk:ZBJ1BJ)RֽޔcŽ{{{{{cs{sZεR{έ{ccR{{JRks{kc{BcsZcscZcsZc{skΜckR:{!B1:1J:111:1)11:::J!BB)BB)B1)::1:BBBR1BBBJJ:BBR)JBJkcc{c{skcRZZc{{k{ks{k{{skc{{{ssksk{ksRss{sZk{kssc{)1{))!R{kkccsscsR1cZZ{{ss{sR{{楥Δޔ{s{k{ťťRZZ):!!:)Rsks)Z11:k!BBc{cc:JBZkc{cck{{:Rs:R:R{kZJkkkZccR)1J1:BJZBJB1JJsJRBRJB:BR{s{1JcZJ::cB:BJJBJB{J:BR)J)B:Z)BBJR:JJBkcέεΜŵ{c{{k{{sZ{JJRsťckskksksZcskތZ{ZZcsZJZJc{{cBkckkBckZ:::1B1B::J!::1!JR1B!Bc)J11:B::1:B)B::::B)JJ)R1::1R:::{cscssck{k{s{{{{sck{s{ks{skcZsckcs{RssB΄sk{ZcRkskkc{kBRBBRZJ:BksZRscRkssskccZ1{kZksֵŭs{cscs{֌{{朌c1JB!R1ޜ{!cssR1!k1:BJ)::Zk:)k:Js:J)k:kssckc{Bc{JBJc1JB1{1)J:RBR:Z:1JJJ1Bcc{:B)JR:)1:cZ:B:BJZRcBBRBBZ)cB:::cJ1RJs{޵Μť֔{cssŽc{:Jc{k{kkscksZ{kkZZRkJRZkZsRcck{ks{Z{RR{{:{1)R):)1:)BJ)J11!1B:!)11JJ1R1):B:B:B:JB:BBB:B::BR:B:ZŔ΄{kk{kks{s{{sskk{k{kskksss{c{{{kcc{ssc{kk{sZ{RZckskk{11):ZJ1B{k޵c{ֵk{ZsZ)1ks{{cs{ΜŽZŭkks{cZZBBZsk))ckJRcsc:kR!BZ:JR)k):J:{Bc{{sJkkkBJBBJZRJ:ZcJZsZZBZ)J::{BRJRB:)BJBBJk{kν):1Jc{1J::R)BJ{{k:{BJZBR1:BBBRJBJBRBc{ZޜŵŵťΔcsŜkk1k֭{s{Z{{{sZ{cZsc{skZ{{ZJJZskcJskcB{{Jcc{ckcsBB1!B!!:)B)J1)B::1BR):1:B1B:::B:):::R:1:B1)JBJ:1JR):1B::B1RRŵZ{{RJZkks{{ss{kssskssssk{k{skkZ{kJckk{k{Rs{sZskkRscs{kBcs{{:!:s)RB!Bckֵ֥:sssssR:Rc1sŔcks{sֵ{֜Ŕ{ֵ{Rks!!11Rck{1)J{!)k!RJ:1:k11{ZckZ{J{ksB:Z::RRRBZRccssRsc{{JcJ:BJZ:J!sޭJ1k:{{sZ11Z)ŽZ1::)J11:1JBBkk:J:RRJJJJB:R)JJs{{sބ֜޵֭skքckk{Μ)Rs{kk{{Zs{c{kZcsssJk{cRZkRRs{ZkJR{scscs{))ZZ)J!1:!11:::B)B1):)B:):1R)RB:))!B):B)J:BBBBB1:B::1:)::1:B֔Z{Jsc{{kkkc{cssss{k{cks{kcsZkZk{{ss{kc{{csRJkk{{ssskZ{ss{cńkks{ksk{skkBRŜk{εΥťΥs:cŭ!!J!!!JŵZJk)kkR)BcR:1cBcks{sZcR!B1ksR1c{Bc:BJsZ{cRcJk:kJ!J:JJ:B{޵JJZ{kss)1RBs:B!B:1)B:1B:)1kkkcBJBJR):R1:RBRRcRkZs{Zޭs{kń{s{޽R1BBskk{ZZRkkscZJc{kckcRc{kkZs{JBJksss{{B1)B):):11):1:::1J::B1B:1B1:)J1B11:1:B1R1BB::JZ11R)111:JRksk{Z{s{{kssc{{{ss{ssss{{s{c{csck{kkcZZkZkkkkckc{{έ{{kcs{{c{{JccksZ{k{cssޜsksťŵք΄Ō:!kc!J!{Rs!sss{){!BJZc!cR)1Jk{ZB1JRZsc1:{JB1skckkJ{cBZ1kB:BB1::JsŵRkR{JJJJZB)1JJs:B!B1:BB1B1)BJks:RB1Jc11::::B:Jkskkksŵ޵քssscε{kRB1c:BRR{Jksk{Rs{{{sRkZsksR{{{{kkkcZZsk{:{ssJck޽J:):):1)1)1B11))):!1)!B)BBBB:BB:B1B:J11:11J11):BB1:::)B11BB:1RskksŜskc{k{{Zkkss{{{cscZccssBkRskckZkkkkΌkssk{{sJRR11ŵs{c{Zk:)kZ{ֵ޽k朽ŜΌ{RRR!!1!{B:ŭsRJ:kskJ:JBJ1cRcB:sBJJ{s{cs{:BJsBR:BJRR::skZJBJkkB1BB::)RZ1cc!:1!B!1B::!B:)cc)ZcZ):1RR:B1BsskR{sŜޜޥ{RZ{sZRZsksB{{{ss{ބkZk{cZ1RkJkssks{JB{ZJBckք)1)1)):):B!1!1:)::)::J::1B)::JB1B!111J:B1J!:J!!:!::11)B:1J)R1:k{skZcccsZ{skks{{sk{k{k{kscs{c{ccZ{c{sksZsZc{ZcRRRJkνν{csscsssssZBRZssŔkkcckZccs΄))R))s{)scks:sΔޥ֥cZR{sc{sJ!)11Rs{cRJ!kBBscsZ{B1RJBBJ:J1JBZR:BZZckZ1ZBJ:J)):R!1)cR!)1!B11J!11):RJs{JZR:1:R){{{Rcť諒ssZΔ{cΔRs潜kΌJ{skkRcckZ{sk{skkJ1BJRZskksksZZksR:JsssRZ:B11!:J))11:):::1)B!B)1)1B):::!)11:B)1B)11!J!B!)B:R)1B))1)B)B1ZsJkcskRJssksk{c{cscssksc{{kckk{s{kk֥k{Zs{{kZckZkJcsRskZΌJ{{:Ŝs{ssssZZZcJJZZJkť))!!BB1!!1BB!)cc!ZkΌkcZsZZsc{sc{ZR)JZRkZcskZscRBBBJJRR)ZRs{sBRB:::JBB1)1R{::)B!1):BZsc::)1:B!11B1:k:{1:B!Z{{kBΥ޽ŵcZccssskcť֭kkc{{{{ss{{sck{{ZRZ{k{{sks֔ZJZc:JZBs::)B1:11:11B!)!):1J:BJ):!B)!B1::!B:):1)):R):1!:::11R!:1BJ!B1:11:Js{csε{s{{c{{sssZkkc{kccRZs{s{{{{kksksssޔ{ssZckk{sssk{ssk{{ZJsZs{{JJRJBRRRckŜ{R:)J{J11R!!!kZc{Z!J{kRk1ZcZ{c{kkZRcR1ZsJ:BckkBks{kZs{:1!:!))BkZZJ1::R1J:BZJ:J:J:)1:Jc:11)::1kkJJ1)B)1B):1!)Rk{ZBs!1:sZBkŔssssZ{ksk{k{{{Όs{ss{ŌkBcBRs{cksskRcZJckc111)11::B1BJ!B:1J1)B)11)1)B1:B11J)BB):):)1J1)1))::::B111!::1:::Z:)Jޭs{{k{ksssksRZsJkZsZ{skkkkssBss{{skkZssskk{kk{kc{{s{s{BZRZJRBJJcť{{{!!kZ))11JJ!1!{νRss֜sss{{歭ck11)R{ZkssRRZJBB:1:BBRR:ZJBBRZJB)1:BkZ)1:1Bc)))!)J1)1)BZRJ:1:!:B)11B{B:!)J1B{{sBRJscks{{kkZccs{:{ssk{ss{ťkkk{{Z{JJ:JZkRs{cZcssk{sJRsskc!:1)111))B)1::1)B!BB1J)JB1)B)1:1BJ)1J)1)::11J)1:::!11B)B)!B111:J)11R:)c{k{s{ccZ{ckέZ)ޜRkscs{kk{cJJk{ks{c{Zքsssssk{c{sssskތZ֜֜sRcZkZJRBZZJJcRss{ks1))Zs{1J1!)1Υ潔kZ{kJsskZ:{cJJ1Zk!)BBJ:R)RRckssZ{RcBBk))1)JcRZZ)::1:1BkRBJ1:!JJkB1)1::1:)ZcB)111B1c)11!11c{J:cRsΥ֥ΜkŵZccsޭZk{c{kcJ{s{cs{ccZ{s{RkZJsc{k{ZB{kkZ::))!11:::!):):kZ:BB!:)!B!B1)11)11):1::1B):):1)1B!B!1J)))1B)::11B!B:Ōc{kskksck1ZRcckk{{{{cscs{c{kkccskcZRsssck{s{sks{cs΄{{k::{{J{s{ssZJZBccRJsss{{k11k{B)!!1RJ{{k:R!)):!)R1ZB:Z)::k1)J)111:Rc1:{ZRcscZc{kkk1Zc)ccJBRcJRJ11:RJ1:Jc)BBZcZsRZc:))!:!BJ!1)!)))1){Z:11:B1B)1B!:1scsks{{Ō{ŵ{Z{s{ccRkc{sZޜ{k{kskZcskkcs{k{ssJ{RcccZRZΔ{ŜB11:J):)!1!:!1)s{B!J):B:B1BJ111B)!B:!:1B::11B)J!:B)))JB!1):)):)B1):)R{ckŭ)ksc{sskkkcscs{sksss{{Rk{k{skcssckkkc{ZZ{ssŔń{{s{{1Jkc{{֭ΥŵZsc{ΜZksc{c):BRR)!!R{ޭksZR)!)R:!!R!!R)B1R:RB1c:)R!:RBZks1:)JBBZkcscRkR{Z1RR1!!sRJZZRckc1JZBB1ZR:R{Zkk)s!cJccR)J)::1)11):)1BZB1BZ):J1:)1Js{{{c{k{{{ZJRkkskŵkRs{{k{ZRkﵔRk{k{Rc{ֽZZssRssJZZZZZc{J{Zcs:1sν{{1B!B1):1B1!11:BZ{J):::J:B):::J:B11)JB!:1:))1B:1R:1:)J1:))B11)!):!B11B)ΌkkckŽs{JcR1{ބkR{{{ssZsk{kkkkkssk{kss޽s{sk{sέc{sZ޽Ž޽ΌέΜΌs{RZ{{JskkcJBR)!!R:!):Z֜ތZc{!Bs1Z1)1k11B)BB1Rk!c:JRRJ:cR):)1::cskRkJJ!sJJccR){kkR)B{JRBR1JJ:BJssZs{Z:Z!)))!:JZJ))1:1:R1B):Jc!)!J1J!JZJc:cksk{kB:1BZZ{s{ŵŜŜ֔Rs{Zkkkcsssk{{sZs步scccBZkZk{{Z挄kRR1ZB1B{)1)!)1:!)B)ck1){kZJ)1))11:1B:B:B1ZRB11)J)1:B):)B:::)BRJ):!)B)1:)1)1)޽{{:)BR1k{kZkkZs{k{cscs{Zsk{{{Z{c{s{{RBZ:BB{cskcsscZJR{ń{sssŽs{{kc{{{!!!!!ssccss{{{ZJk!)ccc!Jks{kkB!!ZRJJ))RJ)RR!kB1)RJBR1cZ!:Rc:11))scZkcsRBkR:BJR{BB:JJJcZZkkRRR)J1:R{Z{sJZ:)):11))::cJR1)BB)R11::BkZBBJBJR1RRZsscksB)J1RZskk{ckccsssZk{ss{csBZkc{{ZscRRJk{sRZ):!RJcs1!:J!):1!BRZckBsB)B111BB:1:):1:::1)BB:B1:1::1Z))B):!!1)B1J:)B))B)::)1kRŽ::1skRskckkc{{kkkZ{s{k{cskckscsksRcRBkJZ{{kZ:RsckZ{kJkkkRkck{{ss{cŔk{{{BB:)B1:{s{c{k{sBRck):!Jc)BBkk:Jss)!!RRJB:1R{k!Z1sJ)!RRBB:Jk!:R{BJ:1!:cB1s1JksR{c:1RJs{cRBZBZRcsJcB{RkBk1!!1!!))B1))J:sZJ)1)1J::BB1BJ1c:B1:1s{RkRB)BJc{{ssބ{{{s札΄B{sskcsk{k{{sZŜ{kskR{JscRZcsRRJRRkkskckc:kcRZ:11)B:111ZsskssZR:BB!::):!BB)::1)1B11B!J:):111!B!J!B:!11!)!B1B11:!:1B:)cc{1k1::{kΜksckZ{kk{sR{Zk{Zss{c朽ŽkJskkR{cssZsssޥs{{k΄kkc{ks{Z)1JR:BJB))::11)))ZkkcckcR1R1RRJ潽kc!:B1)RB!1B!1JZ:B!:k:1Z:J11B1k:BR)c!BZRcZk1Z:c1c{ZB)RZZ:BkcZBZ1B:R{{)!cs1BRJ:1:1B)!1))11)):BJs:!11B1:1)1k!J:BJB:R:Jsssc{JR::kZ{{{Z{RRcskRRsBJRcRc{k{{֔sBBJRRBss{{ccZBkJJJJkRJRBk{{{Rck)B:!:B1)):Zs{B{ckB::::1:)B:1)BB11:)11)::11RB1:):1B):):BZJ)1:!)::BJ1JBR1JZRRJBB){kkc{{{{ZZ{k{sk{{sR{kcRkc{kεsRZkJZJ:cZ{ckckν{{ksZcsskZRR・J!c{1:B!B11cB)Bskskks!!:)J:1RkΌŭέ!!J)ZJ1B)J:cZc!:{ZR!:B:1!ckckRR1{Z!:cZBBk:sR!RJ1J!Z{c:JJJJZ:֔)R:Z)1Jc)1)!J1)1)11R)BB:JJ:J::1:B::JkJ!B:RBB:s{cRZB:RkkތsZŭŔޔckckRckJc{:JckcsΌskRcc::!1RRckkcJ{Zc1!::kZJRRk:RZ{Rcck{{J:111B:1){ZZ{k{kck1:)111BJZJJB:1:J1!::)B!1::)::1!B:J1:!:JB:))):JBRJRcRZJJZRskcRcks{k{skskc֭{Zs{JZR{cckRsc{Zk{kBJkkZc{ssskZΥ{k{ks{skskss{ΔR{k{!::J11)J!:)c{{Ό1Jc):11!cŽsc!B)1J!)!!BRJ{JBR1!!)Bk:1R{R:J:BRZcJBZ:)B!JZJ1ZR)R1BkJBcscsν)RcJ):sBJ{111!!:1!1)RBRJZsck:!1:!!):ZR1JB:RRkkZ{s!s{޵{{{ń޽Ŕ{s{{kcccskskksk{cńcRcR{{kc{RckRcR1RZJB::::c{scR{11:11JJBZcs{cs{s::1B):J1J)Z1:)B:)1)::!11:B!:c::11::B:RJBB!:1BJJRJBB:JRBcRRZZck{kRs{c{{s{ZZބs{cRkZ{Rsk{kR{scskcs{{{Jcccsk{ν朥skkޭk{k{sk{sc{!J:Zc!kRRZJk{{sss1k)RB!J֌֔s)B1!)1!!!!B))cR)J!!Z!!)1kZRBZB!):!!RBsc:1ZBR1kJBkRJBZs{kZBR:BBc1:ks:1Bk{k:B:))))B)JZssksBBZB1)B1kBB:):B)s{{ZZ{s{ޜ{{Z֔挵sss{{kkZsZk{{ccs{{Rkc))RR{{{Zkk攄ŽZ:RRkRk11)ZRBJ{k{{ccksk:11::1):ck{s޽R):B1B!1B:))ŽB!sRJ:J:):JB)BcJ::JB1Bc11!sk1):BsR{RJRRck޵sckkcRBkssRks{sŜ{Z{{scckZsscsc{{ks{Zcss{kB{k{cZksk֔{Z{skJ{kޥ{sc{{Z{{{sZ{kccJkk{cֵs1!JB1)cBcJ)1{kkB!1:)c{s{{νRZ:!:!)J1::JJ):))!:):ss{cRkB)1)BZZ)RR{)JRJk!BZ1BZJkJRRkJRR1JBJ:J{{s1R))):!1:Zkk):1BJBBJ!RZc:!BRkJ!s:::kRB)skkZZk{skcs潜{{ŭ{skkck:Z)cRcZJc{kcB{ΜތBJ1JRRRc{sΔΥsRkscZZ{JJJcZc{cZ:!11R!:c{s{{c::BZB:B1BΌ֭:::BBBB)J1JBZcBBs{kRBJZ!ޥskssccccsRcckkք{ssc{{s{{s{skkRkcs{Rk{kkskJkkscc{sZZs{ss{ks{{{{s{{BB)!1sRJ1!B1):BcBJ!!Rsc:RJkZsZk{s΄kc)!J{!1JB)B!:1J)R1BB!1RJ)kŔkc1!!:1R1J))ZRZRkRZJZ11)Z{!!ZB))JJJkZcZ1B11){kss!11!:!1)Zs{{R:1!1B111)1cRB:RZJkBZJJR{kskΔsBքskֽkkk{kc{{ssRk{kZ{ZkssBJΜkscBcssscc{Jck:cR)kZ{{sBJ):s޵R{B)֭c1ZZc{))!s:1J:J:B!){浽cޭ)Zkkk{sZZcksZ{ksk{{{c{{{kZ1{Zk{{kkkk{挔ccZZs{Rskccc{ccksZJkssc{skkk{RJ:)kskJsk!)B!:Rcc:)!s{{k޵ssŔRk)!!cZB!!J11!BJ!11)kZcss{ŵ!)1)!!:JsccZZ1BR!cZ!1kZ)cc!JR)ZscBRJBBZZ{k{c)!):)111:!11ksJ1B!B1:!J)cJ:)!R)Zcc:JZBJ{s޽{ŵ{ޔ朜skJc{Zckc{{csk{έRcc:ν޽ksBZkJ:J:k{cZRZckk{cs:Jk{ck{BJ::Bs֭{֭ZcccJR{ksc)J!Z!{!Js:RsュkkkskZRskޔ{cccZks{{{sksk{{{{֥skk{{ssscck{{csssskkcksZkccsRk{{ksssc{k{csRR1{{JkJ:)):!)kJRJ!Z{֭ťBJZZkJ!:!)R!)1RBJ:BBcZR{ck{ckB{skk{kJ):)))1Js11J:)::1J)RRsJc):1:JBBZ{sZkZZ!BBRkJ):B)Z))111):11!1c{Zc:!:!B:)B1J1:cZ!BJ111cJBZRBŌksZ{k浌΄sΥŜ{RskcZcRcksZs{sc:sc:)ZkR:BR֔{1ZcJ!BcJ1k{RRsck{Z{{cskcJZc潥{{cBRksc{cccR֜kŭ)!R:k!JֵΥkkk{ZΌ{Z{skZ{Zkk{sskcsckcks{{{kks1s{Zc{R{kc)JkcΔJ:)kZ:sssZsksc{k{kccccsZ{ZccsZcZ{{ckB))BZ{sZZ1J)!J1)cRkJ))Jksk{R{{!1):c{B)!)J!))ZRJ1{{sťssk{ksBBRcss1)))!)J)JJ1))JcJ)!:1s1:1c{1RJ))ckZ1kk{Jsk1)1JZ))cZJB):B)))11:Z):)!)):1!:kc1BB)1:Zk{{{{ccsֵ֔s{sޥkcs{sRkkRkkssZ:JJ11ZRBB1R1RJ:s:RJBBZkc{RJcc{{{{k{sRkscŭ{ssZ{kZsZssssss:BZ֌:{{kksńcs{ssssZZ{kkkZcccR{{Rcss{c{kkJcskBsZ{sνZRsB1JBskJ{kB1JŽs{k{skJcZZcskkZ{JZkcZ{)JB{J11:kk!{kcB:{k֜k{cs{:1BBJJ1RZ!!1B))!B)c1kJsks{:!)Jc!)1B:B:ZR)B))1{RBc)J:RJRksc{{{1BJBkcB)R)kJJ:B))))!:k{BR{B:1)!B)1:):B!:J:JZ1cZ{Δ攭挥{c{ﵽ޽sZ{ssZckccZc{cZJcZBBc{RBJZRc!1JBRB:Z愥BJcRJR{s{Ό{Όss{Rŭνk{Zs{s{s{kZscs{{s{k{:Δ挄sc{ks{skRcksk{ZZscskss{c{sskΜkRJs{kks{޽kRJJZZRZJkc{{RRJkZJ{ksRsssZck{kks{kkscscZckRsccksc{s{Zs{Zk1J:sZ::ckkZZkRZ1R:1JkRR!)!:)1J::1csck{ckkcsc{1!!1Bk!)!RRcBZ!:BJ)c:1J:BJZJR1sJBsZRB!!:!J{JJ1ZkB!!)!!)!B1JBsk:1:)1!):skJBB!::scsk{s{ޔcc{{בֿ{kkcckssRscZkkJ1)RJ{skZJkJ{sJksJk{朜k{{kcsk{{scksccckRsc{sRkkck{kccZsΌ:ŵ{s楌kk{{s{{{skskk{c{ZcZc{kk{sssckkc{ޔckks{{ZcJcc{Bc{:kkkJccJkscJsskcks{kJZRZJc{ss{{kscskkZk{kcZ{{kkkJZscsZZs:1):c!Z1Zsckcs!sŵ{!!:B1!JR:1!kRZB{sckB::BB:1ZssJ!)!)1c)!11ZR)1:c1)k1::R!!Zs!Z{sZZc{cB1J{Jc{BBBRJ1JBBcBJ11c{BcckBZRRZR)1)::::ZB:cB1B!J{בֿs֌sk{c:Jksέs{{sRcsccccsBssŵޭ{ZZ{{JkZs{ksΜΔskkckZ{kcsk{{sskZkkks{Zs{{ks{JZcks{scޜ{քkscs{Z{{kssZcJZkńcZcZskRssskscscZR{scskkc{{1Z{ZJ:ZkBBRkss{ssskkBBR)BkJcsksRkss{kck:{kB:ckc{sBJkkc{ZsBJ1:J:)Jsssskcccck:)s{:JBcBZ:1BB11)B11kscRZRJB:ZZBJBBRk!1!!!)R11!!skkc:J11)1):J:RRB:JJ{c{kZRB1BJ1!:)Z!)!1Bk11J{:B1!s{ZkRJB:BJB1{Z)1):BBZ:1ZR1!!c{JsŽkńss{֌֥ZcRcskZ{sssZcssńZ{sk{kZZZc!Z{kss{{kkRs{ńckkskssc{kssscckccZskkkscBsk{{ck{ssZsss{{{sŌkccskk{kssssccΜcRZcRs{c{ńk{c{cJJcskkkkRR{cJ:s{ZcJs{{sksccsZcBJBJRRRZkckkscskZkskssRckRR:Rkscck{c:Bk):1:ZZs{c)J{:!:RkkZ!!R1B))!R{J)B!J:)k1)J:RkJRJBRJ1)JsZ!!)!)!1B:)!BcZc!!J:!B!1))1J1Rc1Zsk{RkJJJJ:11:!Z!1::!Z!1B{J):!:kccR!B:):B11RZ:)c1R)JB!cB:RkB:1R{kέޜcsc{Jck{scsks{{s{cJRB:ssk{c{ks{{Zcs{ccZ{Zc{{sssskc{{{kkscskZcJ{{csք{skckckk{skk{{{{k{kkcsRkRZksskkckkssksJRskZ{ZsZscckkc{sZBJZc{cZcRccR{{JB){ssk{cRcRZJ:Z:ccJZZRZck{ss{JZssZccc{R{{ZcJ{cckRckZ:)::{kZ{ksJR1c:!1Z)1!scssBZsBZBB:Z)BssRcsJ1ZcJ)B)1:ssZ11:JBk)B!)!:RJR:)!JJ1k!!cc!)s{cccJBsc)1)1BRk:):)Z):B1:cB)!RB)ZZ)))J:kRB)1!1ksJ:1BJc{ŵ֌Ŕk{{{֔νks{Zk{sckckZkcBsJBc{s{{ksck{{kkkkc{{ss{s{Υ{ksskssskk{kk{kk{{cs{{scR{c{{cRkck{csscck{s{{skZsZ{{ssZ{sŌRRkZRBZZccRscZJ{R{skZss{{{ŌZkťcZJZsRkZcZs:sRkkJkZZks{{{֥csZcRkcs{RckkZkZs1Jskks{{))ZkZ)R)1BcR:!)::J1!R1R{BR111RB:1BZc{Zss1:k{kRZRJJ::JZcks))!!):))B!B1)ck1JJk{R{kJ)1RcZBBB::)Zc!:Z:RRJ:!:1B:::1)JB)R{BBBR{J1BsRRRksΜΜք{{Z{έc{sss{c{sssccRBBBR{sckRc{R{skZkJJΔ1:BZRJc{c{ssccckks{kkss֔Zs{kBssZ{{{{cZ{{Ōcksssk{ssZc{cksks{{k{ZZZskkcks{s{{ksZskZJZsZsZ{ZZBRZk{R1Zss{Rk{{RZcZcJZss{ZRkRZsZJZ:Z{cZk{ssssss歜Z:ckZccs{sskk1))RZ{cks)Bkc{k!1R11R)B11!!:!J!1J:B:R)J:!))!1!BB1Z!!1RRBZ1!JsksZZ1::JZZZ:k:B)!R)!1BBc:ZZ:RZkR))BcBJZ:BR:)c!:BJBBR::1):R1):Z{:1RZR)cBskB::ZRRRck{s{ss{sss{{歔Ŕ֔sc{cZRRJkkcccZcR!ZZsJkJk{{c{BBBJcZZRcckkZckJRccsk{kssk{kcsckck{cB{{{ckc{Υ{{kkcksk{ksc{{s{{Z{{{k{{sk{kk{sksccZcs{skZssssZ:BcńRRcc֌ZcZJJRcB{BZBk{:kRZZ{{{ss:ZJcRRZJJZccJ{Rsc{kZkZRZcc{ZZR{ZkJBRBckZZZccZsBs1)))kkkckc){k:c1!Z:ccB1:J1JJ1)JRRsR1)!)1:R!BJ:B!B)!RZsk1sZBZcR1Z!1:)!:!:BBRR!BsZ{RcJ{scRJRBRkck1J)1BB!)Bs)B1):1Z:BB:B)cBcZ)1B::{Rs:s1B{Zs{kcs{k{{k֥Žskŭ楜cJJcRJJkk{ZcskkJ:{JR{{RZRJZckcJc:kJ{{ZZZJZBckJck{{skkk{{kZk{{{k{{k{{kk{Rks{ք{{ks{sk{ks{ks{{{cskccc{k{k{csR{Δc{c{cc{kkkcsRckcJB)ZR{:{k{Rsssc1BZsZ:JsRcZZcskZc:kkRk1JRZsJRkscBcRJsckJZZcZcZckccRZcZRJccZZcckssRscskJ)1!{kkkcsR:skks:JBB:RBsk:):1!Rs{:)!11c{!!!B{Zccc!!!1!ZRJc{Z11BRB1!B)J!ZZs!cJB!)1JR:11JZc:!!RkR{B1)R:)111B11!:!JJ1J)J:JkJ::)1B{{{R{{RJkRZ愔{BJBckZ{s{cJ{ssޥ攄ksZkkkZRcJRRkkJ{cccckB:ZcZkZ:kZZ1Zk{kRsBBքc{{sZZ{{sskc{ckck{sc{skksk{{s{cZsk{{scks{{cksk{{sks{kcZs{Zs{k{{kkkkZBRZcZZZJ1))BR:RZkZ)JZ1ZZ{{c{sRZcZck{JcZcZZ{s:c{JBcRssBJcc:kcRJcZcJcck:)JsRc{ZcssckZss:cc{sscssRcckkJRkc:cc{csZ:sR)Z{c1)kRZR!)!BRc)!!!ZJ!!)R{{sc{J:::!!:!{sJB)1)):)R:!1BRRR{:)BRJcsccZ!)!):1:1:B:cJ1:B1B:):!BJ:1:11J:):J)ZR:ZJZBBk{ZJsBkcZRskksRZBBZ{{{cks{1RZk΄sZBBsck{ZcJ:cRcB{{cc{ZJZc{cksR:JckZcsss{skB{cZJZZkskkRc{cs{s{k{{skks{{Z{ksc{kc{{s{Ŕk{ss{R{{ks{scss{k{{s{sZss{csk{c{:RkJBRkR!:kskkR!JJZccR{scBcZ1{cksZc)cccZsZZksRZZ:RJk1JJZJ{JRkkscZRc)Bkk{RccskskckRsJZJRZR{RRRskcZ:kccBcskck:֌Z1skc):{J:)J:!)):1)!)!RRcsccZ!)))B!B1Zsk!!)!sJk{JZ)cBJcksJB)1!!:)!)Rc!1B1:ZB::!1J!B)))1!11BR)RZ1J1B:JcscRBcckZZssRZRks{BsRkkc{ZJ1:{{{ckssk:JJ{kcckB{kRBkRJZkZRZZR:kJ{skRkcscsc{{{{ZcsksksZccs{ckcc{Zsk{{csk{{ZZcsk{{{{s{Rs{R{s{k{kcsk{Zck{ZZ{kŔkkskcBkkB:{Zs{RR:RJZsRZ:kc){ccsJB:sckk{J:RRZ:{JB:Z{RRRJZkcRBJJ{RJcRkkkZcZJR:RJBRsZJskcZ{Bk:ZJRss{RJR!1)!)!{Zc))B)!)!B1kJcccRB:kccRsZccRZ)1cRB!RR)BJ!B)!RZ1)J{kJRcRZB:!11111!R:J:J!kcc))B)B1!1)1JBB)!J!:RRJRRB:RRsZRckckkcksŭ{sBRBB:R{sssc{c{sŌ{{sBkRBZJ{ZcskcJZZkcss1RkZ1Z:ZJcBJZZkRRkkccsk{s֌ֽRcss{scc{sssskkkss{{{sc{ckΌssRckcs{{{ssZkksZֵŭsJ{c{sc{ZssRcck֔RB֥JZckcJRBRRcZksBZ{{{RccJs:J{ZcRJBBRkJZZBkZ:J:cZcRJssRJBccskZskJZZZR:kZRBBcZc{ZRkZkcZJcZBcsZRZck!Rsc:sscc)!)!!)))cs{kckkcccZ{{JBR:!!:!)1ZJ!11:!Zc!k{ZckZ{ZRk)!:BBRJR)B)B{R:B!!JB!11)B)))ZR1BcBZ!R:RR{kJcRkRcccZc{s{ss{1JJB::J1kZ{kZBBZRkk:Z{BR1cRck{{{sZBs{ZBkZss{ZZRcZRJsc{kJcssscŜ{Z1RBBBcJJJBJZR:J:JRc{ccksss{{Zc{ckRs{ŭ{s{sks{sc{csks{sZckskRkkRkcsksZcRZ{csJJc)1RJss!ZZkcks1R{R{BZkBZkZkR11BBcRkcεZ)1:ks{sJcJ:kBBkRJ{sRkkJ{RsJZccRkkkZZZcZkZ{BJZRcJR{ZRZJRZckkBccZJ:BR))Jsc11)!!11)k{Z{ksscZR{ss{BB:!!))RJc)):B1!)R)1csJcc:kJBcZ)))cJB!1J!J1kBJRJJ!1!11B):)::)!R!J))c:JRRR:{JBRkR{ss{BRk楄{ksRJJ1:JJ1s{J:ck1:J:sskBJBcR:scBk{ks:cZ:kB1Jccc{s)cJ{JsJ1)cJJZJJcZc{k!:BB)!Z::)J)::)!)B!k::Zskksss{sZkccRcck{{cRZcsc{Όs{{ssťνcZ{kckskccccJZc1cBZRބ{sť{JR֥RRsc{ZRssk1R:J:11{J1RBB{RssRcBZ:))RJZZRkkZZcRskZJkcBZ)k{cZcZZJ1JRscZZJZBJZkR:ZRZJ11B1JJZJ!RZJ!)Js{R!::)!!!!!)J1B{ssJk{{k{sZsk!!:B!!JZcBB!)1):Z:RZZcc:sRRskk!1):)J1R1::BJ:Z)s:ckZ::!)11))1:1JR11)J1BJJ1BR:{s{k{ZBBZB:JRksB:RZB)::BJk:Z1)JJsk{J:1B{{{cB!Jc::ZkscRkkR{JZkRZR)JR1RskZsk{{{RRZBcZs1BRJ1!B!B)!J)1!B!)1!B)ZB:Bkcs{kskksZ{sssk{RJ{k{{sckŭ{cŽs{skk{kkJ{{cR{c֌Ōs{kJBc{):BB1ńRc:Z{{kZscRJ:):RZBZkRZ::)ssk!)JZZZc:ZcRcZZZsBZJRJRBRJcRBRJRkZZss:BckRJBJR1)cBZJ{)JBs{)B1RJ:J11!B11ckss{kBZ{1:cskk:sc{s!!!1JJRBR{k)1!!:RZ{Zs{kRZJ):!BB1::J)RRRRZRZsZ)1)1)::1B!):1JkBBRJsJkZkBkJ:R{ZsέŔscssRBBc11B1BBZJRRJJRRBRskk){{sZRBBB:JB!Zck{Bksֽs{ksBskZJRRŭRJRkRs{֭sRck1{ZZBRc1k!1)!::1:1J!1B)B):1)ZJZ{s{ތsk{{{c{skJZsksZssksk{Z{kŜsńssRkJRk!c:{c{ZckR޵Z{ckJJBkkc{R{R֭{sccRJsZcZccBkkcZ)!:R{ccRcZZZckkRBBZZZk1JRJcZBZ{BZR:sBZR1):RJRJBRJ)!cJ)1BRkBZR!1k:B)sk)!B1{ZkR)1!k)1))):11:J:)::!!:RR::B!!ZB1JBsBRkJ1)B)!k!1BR:cRJJs:BB:R1RJJ)Z)Rk)!))JRscRckJBsZZsZJcZsck{ss{R{{cJ!k11B:Zs{B1BJBZR1cJRkskRRkcZB)1:ZZZc:c{k{kkccsRkcJZssc{:ZZZZZ{cRJJJRJBBcBBZ)kZ1!::R11c!1:1)))11c::R{sބs{kskcss{RsssZZss{ZZZscsscksJRZJskRsRJRcŌ{scRkŔRB!)ksZkZks{kssk{BZZJ::RJkZZ:ks{{1ZZBR{c):ZZk!!Zkcskcc{{)cRRBRcZkZBRcJJRcZ:J:s!ZJ:BR11BZ{JZkB!cZckJJ))):Z)B:Bc:1RRB1):RZ!RJ!!)):BB:!BRsZRsJ):1)B!!!!:RcccZ{JJ:!:BB)1RJBcJ{:))RBRkkZB{JJJsZRskcckck{Jcck1:1c:BJBcsB1J:J1BJ)RBJssZskcskssJJ:RRJZRZ1ZJRk{ńcZZcZZRkJ:1RkR:ZkcsJs{{cR::RB:R)1R111)B!:J)):111:!1!1:cRcR{cc{{k{ckcc{֌ksksskckZkJckccR1JcJRJkZ:skc1:RZs)sΔcksŭŔ)!JZRR{cs{kZkkZJBsZJ{cJ:Jckk:!BcZRkJkRZZk{B::BZ{kB1)1c:JcsBRkB)!B{{kk1!11B1Rc1{c{Zk{)!BcZZsc:JkR{B!ZR!!)!!JBB::1k{kccsZc1RZB1Js1)))JRR1:ks:):Zc)1::)ZcZ:cccRkcZRc{{{Μ{kkccBJR:BZ1B1:JcBBR)J)1J!RRZcsskssRJ):ssssRs֥B{JZc{Z{{R1kkZRsΜsssckk{sJ{k:{kZks:BB:1):RJ!1R)1)::::)::)1kBBZ{{{k{s{{skkkkZޜkJks{kcssZc{ccZ{cZJZΔscZBZkc)J{J:1R:JckZkkcέք{ńֵΜ{BJ1cZR{ZsskkZc:ZkJ:sJBJ11BsccJ{kRcsZRkJk!JZsZ:cBkckc1BJ:cJBkB1RŜZs1ccZss{)!1J))BZ:{:{){ckcsJkRsc{sskc)Z!:!!))!)Z:!1RB1J{kJsZΔJscs{R!!!BBZsccZk!!!!1!:JZRc1JRR!!)!sc1Bk{::BkkcRBcJ{{sscs{{s{s{s{{sskZJ111s!B:s{BBBB1:JRBBB:ZRkk{kތJZscsckc1J:JRRZ::cRskRscRk{Z{k{BsBJZksZBRR:RJsZkc1ZJk1sJB{k{{c{ZZZckJkRRcRcks{c{csks{{s{RsZk{css{ksZ{kZkcJksccJc΄kRRJJcZZkBJ{kJs::sRBRc{֭s!ksk{sέ{kZskZZss{cRkJ)BsRccBZZRs{ZcZckcRR{cc)Z{RcJcJZsZZ1BkJ{:::ckccRRJRc{J!J:R1:Zc!ccJBR!!1)!!1):sBBkR{cRRRRsJ!1Bskkk11:c!)!:!):{{ZkRc{sZZR))1!:J::1)R:1ks1!!1:BcJ1RBZZB:JRc!RcB11s{{1{sJRZ{ckJkkZRZksssk{{J:JJ1!1k:RsBR)1BJc11BcZsJkc{{{{{kZc{:J:Z{kRJkZZR{sksRJsJRRZskcscRsZ{RZJJRcRB11)J):1Bks{{c:RZJR!)!:1BB::):!)ss{{cΔޥ業kޥkkZR{s{kZZkJBBR:ZkcsJ:kscŭZssccsJBB1Rs)k):k)cc{ZΔΌ潜ss{{kZsJkcsZBZ{RRJZZJR{kJskccJZZkRcs{k{{cZ{BZ{:)ZckZcscRRcRJscc{kkZBJJcsZR{BJckc)c{cJ:kRBsscs1!B!!Bs:BRsk{ckkJ)))1):!!B1B1cJ!B:)sskcZRB:ZZkkkkZRc!1!!!1:!:)1ks!)B!skc1BRJZc{sRZZsBRRskcRZkksZZ::1)!!Bs{kZ{sc1!R)B:1BZBB!B!BBJB1BJkJBJZRRsεքsksν{{{:BcRck{ZkRRcBZ{s{JZ!1{{kss{{RsRcZccsc:1BZ:Zk1:1{{ksRRRBZcs)1B11)1B)B1!)1Bk{{{ks{sZZkֽscRkJscskBkk{BsJ{cBs{1Z:{kΔRRcBJ1BBB)R{BkRR{R1潌sZc{Jcs{cJccRRcR:BJkckskRkcRBJZJksckZRZZksJR{ZRJZccZŭ:B1kB)ccc{:RsskR:c{J1ZBRk{1kRckRskB!)!):)ZRBksZZc{1RkB)B!B)11)1))!!BJ:Z)cZ:RcJZ)RR:R!R::{sZR)1)!:BJckZ1BBB!cZ:cBB):Z:kcRZRkc{{{s{c{Z:JBJR1:!)ss{::Bc::J!RR1B1::ss1B:B:J:J1B:BRJcRcŔkksc{kckJ{kkskRcRkZks{{ccsֵZRZk{JRRBZBcJRRRZB1)RkRBBcR{sJcsZR!1)RJR1R1)))JB{s{{{sťsk{{RRssJZRcRsZ{{kJZcscBJk{R{RBBZRcZRJs1k:J)J:cB1ckRR{ss{֭Zk!skkk{kcZRckBc{ZJ{cZJJB1cJRJkRRZRkkJkRcRRRs:kZZZcsBs{JsZZJBcZ{JB1RZkcJss)ssBkRkZ1BJ{csBJs:RZ):sRB!)!kZkZZ{kJkJ)!!!1J:JR)B!!)11RJRZc)::BRRJ::JJc:!)1!!)cRkkZ1B1BZZRBBJ)1JJcRkRks{ckZkJ11!!)!J{cc{RZRR!R{)1Zc:!:J1B1:R{s:)JB1Z:JRB{RsBZZkZk{{֌΄ckk޽JZsR{c{{kskkkZJZskc:skťs{sccJ1ZRkcRkJc1J)kZsJBk{{Jk{J1Z:!ZBB111!1):):skck{k{cscc{scZsskJ{Zkccks)):1csZ{cJB:B{{R1)B{ckkRkkZs:J1Jc1ZRRJcs{ŭckksZkscks{ZJsc)cckZkssBB:cRcsZZkcc:cccskBJkZkcZRRJ::Bcc::BJcZk::R:ZkZZksZRBBZkkk!J)ZBk!csZB1JR{kZk!1:!Z{R:))::1sk)!1!!:RB1BR:1:!!sRBZZJB::kJcZkJRZc!B):!)BZkcZZ:RJRJ:R:!!!::{{{!kJJJcc{JkJ!!JBZ!sc{Rcc)):1R):s1:1R1)J1Js:B):Z)JJ:Z{kZ{{Jc{k{{ŔsZs{ZZsZ楥JcskkcsRcsccZR{{{ckssJB:1JkRss:!:cZRJkZkZZscZZB:Z!B::11:1:1)B1:{{{c{c{sZRsc{sskk{Z{kc{c{ksc{cZ)R:1cZ:{1B:ckc!JBJJZ)JZBBJ!kkJZkBcZBssJR:B{νޭZBsk{csk{{kcRBZJ{cBB1Rk:cJBJRRRccJZJRZkR{Jk:BB{scRksR{k{ZRR::R)BckBRJRJJ)JcBJZscRckJ:RR:Z::))!!!ZsZs:sJJs{:R))))JkBRZ)!):!BZJ!cRZZsJBBZJcckcsks:!)R!)!RRkRR!JcZ:BBZB)111JcRkJ1:!B!!ZkkJ!B::Rkks{J:c)Z{BJs{sksB)::11:!Zssk!Bss{cscs1Bccs{kZZkBZ{ks{kcJRZ::RZkBRBBkkcJcZsksc{c{{ZRk{kŌŜ{{s{k{cssZkksRRsBRJ1:BRBJ1BB!ZR{{kkc{k{k{{{ck{{sRckkk{sscsZsk{{J1)1RcZ)JRkkJ::)1J1B1J)sJJ{!)1RRR{:ZJcRsB:kZ{kk{{Bc{ssJZRJZccZZZk{cRcRZR{BRJsZkRZJccRZRZJRs{1ksJJc)cJccZ!RRcckZRBkRJZkccJZZ)JRZZBJB!!JB:!!1:{kBZB{B:c::BJ!1!1J1ZkcR!1cRB1ZZkkBJ:JkZcR!!:!)J!sk!1Z!RB1:1!Z:BZ)B:BR:ZJkZ)kJB)RZ)1)Bcks!RcB1)BJ!:kcJkksc:ZkJ)BJ):)1cRs:BsksccR{cBckcscc{{Jk{{kJZc޽cR{k{ksBBc{RkcRZkRZcZkcέscRkss{kckk{{RccJ:BRZcRR::cRkcJ::::1B1!1!J)Jksk{Zck{{ssZk{s{ssRcZsJcRcs)BZskckB1B:BsRs{sk!:)11!)1skc1kks1JZ)RJJR1RcsscBJRJ1:!11B!Zc1ޭRksZZ1RkJkJkJcRJkccJ:ZJRsB{RZkZc{ZkJk:s{Zkcs{{cc{{s::JBcRssZRJcscJZBRRc:k1::JJc:RJ:!!Z1Z)!!R:RckcRsc)JB!Js!:RssZRk!!)sJ{JR)JZckc:BJJ1!R):B!!1cBsR1c!JR:kZJcJ:BZcJRZ!{JJ!11!1JZckcJcZ)J1Z{{{kksZJ1ZJZRc1:B)B))JZks)1kckkk{RBZRJccssZŌ1{k{sZZckBZJZRBksRJsŌZkJ{kkJcsccZsk{scckRJB1ZksZBZBRBZkZ:J:::B!)!1)!11kk{{Zkcsck{{kskksccc:Rc11J)Rs:kZޭޔk޵{1:ބcsZc{ssJBcc))JB!cZc)ZJ:ccR!B!1)11!kZZZ{ZZ1Rss!11JZ:ZckcJZZZccB{cB{RJRJcZ{kksZZs{kkkk{sJ)::::Z:BZkcBJBJkBRsJcBZBRJssJ::1))!:!BBBkZk){JB:BZ{1:cR)!:J::cRZR:Zscckc:R!!1!!!c!)1)!BBR)BcckZc!){RJBc:s{cRckk!))B)):1Z{c{{kkZ::Rs11RRk:RkB:):!R)1c{Z1:sRscc{c:{R1kksskΜRkkZck{cckJZssBkﵜkcZkZsk{s1ZZssJRscsZsZcsJ{J::cZJBZZcRcRRJ1B:1J)1:!!)!JB{{{{cZ{{sc{ssckR:BskkR)JJJBkZZc1{sֽ{JsBB{kscsckc{JR:1BkZ)ZcscZ::ccs)1!!:!)!!{kscksBJsc1scJc:s{skskkcRcJkZRBsZcZBJkscJkskZZscZBJ!1)::J1)BBcR:BZkRcJJkBRZ1scBk)!:)!!!:{sc{ZkB)JkcJ!kZ!)s{kss{{Z{JBkR{kkkk:))JB!)!))))1!kk!!B!!1J:JJccRRZJ!!:ccc)!!1!)1Zs!:1B1R)J))JRccRJk11ZkBk):kZcRB)B)1):s{c!JJssR{:RRsJsc{RRRsRZބkcsssR:Bc{sc{sk{scŌsBk{skckc{ńZBcJ{RZRJBJkkB:JRkRB:B)R):!!)))RJsZksk{{sk{k{ssRZcR:cRcZc{ZεkkBRZc{{JJ{{s{{Z1ZRRRRJZZsk{sJ)R)JRJs{sB!J!:Zc)!1))!)!)1sZRss{cccRsJ:{ZsZkJRcJJJRRsccJkR{ZJ{{{cRBR:cRR):kB1JRccccJZRJJRZRRk{:)!:{{{J))1):{R{ZB:{{s{kB)!cR)J:B!B:Z1!)1!))!:))k!1:JJ:1B:ck{kZ)!R!1Z)!!!:B!J)BZ))):!):)J1c!Jcks{BJJR)kJ{BJ!)))1BBsZskkZcRcc:{RRsssR)ZJc{Z{cŔss:Rs{ZJ{c{{kkckRJkskZsRkkkRck{sRccssk:R1{J:RR)ZZB:)::Z:111::)Bks{kJkks{cc{kZ)JRB1Z{c{ֽRscsޥsZkRJs::cB::cJk{ZJB:BRssJsZcZRk:k1J:cB:!:!!!)!ZRc{kBRZcZJkZ)csJkcJsckcc:ZcZZRR{Rck{{ssRssZc{kssckBZRJR{JRBskJZJJskcc1{ccBcBB))!:1:k){s:1!:{{cRBsJ:!::!Z)JZJBcss:11!:1c1111!)1::BB{B!B1Zckck:)!:):)11!!RR)!B{)!!)1B):::!J:!B:kZZ1BZs:c:ccBJ:!){sB:BB1ckkccR)kBkk::ZZkcJs{{cBkkޥŽ{RZ:1:1::):1Bcc{sJJ:kc{scsJkc{s{{:Rs{ksJR{ZZ11::ZR:11):JB)):!B1)Zcs{ΌkscskZks{cJsksskJŭscB朔ZZ)c1cR:JZs{s1RJcRc1RZBZ1B{{csJ!1s{!!!!!!)!sJBBZccRZRc)Zc1ZscJcZJcZkRcRJkJJZZk{k{Zcc{sJZRcsRsskc11RRRJk1k1cZJRJRRckJR:ZBR1!J!RsR{:{ZJJ1Jsskkck:1:!!!RRcss:J)){BB:JRZc!1:1!:J:)))1!!JZZ)BJBBsB!JksJ:!!!):BcZc)!!BBZck!!))1!BBkZRR:B:ZkZ){Z1:sZkBJZB)BckJ:BBZkZck!s{1kskRkZZcs:楄{skRcJZZkkksRcZsskkZkBc{kŵkk{kZkkcks{c{s{{{ZskZccssksks{sZccRRZRBZ:c{sŜ{{scRkkk{kss{kRksskc{c{:kJccBcBRkZc1!11BJZB)J:JZssk1:BR)!1))B1!1cssRkRccBRcBJ1ZJRssR{{cZcc:kRRkRJRkk{s{{ssRsRcRRc1Z){R!cJcJ{cc1RZRkckRZkkc{Z:s{JBc{Z:BRBBcsRkB:ZRZZJckk:!BkJ)1BZJ::)JB)J11!:Z!!!1)1ZcZB1BBRBJZ)B!1cskR)):JJcc)!!:1JR1:JBkk{{kkJZssJJcsRZ1)c!J)1::)11)R:RkckZ!ZZZkcsZ{Zskk{{{cZRZccsc{:JRRkkk{k{RJk{sscZk{sscssksZk{scskc{JkZkRBcZ{ckRZkcZJ:RZssssZcck{{skcJckJscŔsB:{!ZJRJ1:RBB:Z1ZBR:1ZZJRBJs!)Jks1):1!!JJkZkccJJZkRBk1cR{kRkc{R{c{cZJZk:RkcZZ֥skcZc:JZBBBJBB{kc:1BRZBcRJBBZJsZZ:cZkkcs!1ckRRcJJs{cZkc1!!)BJJc!BJJR:RJRZkkZ!:B!!Jcs{B1!BZ::JBB!)1)!{sBs)!)ZRR{11)):ZZ!)cBB11)R1)k:Zk:cJRZkR1BR)!1R1J!BJRR{ZsBBkRk{{{BRZsss{Ŕk{cs{{Rk{ksZZBBRs:sΥ{Z{Ŕֽs{ΥcckRcZsRsZcckcssZcRkZckkkk{k{JcRRs{kkccs:RRJZkZZcZcRRZBcR:s{Ōk{:Zs{{s:!)!):c)!c:JcksRcZcZR11))Rs!)!!)))!ZRZ{JJJsZJkRsZZZZ{ZcsZBRR{cJcBZZ{kkkcB{{RZkBR)cc!)J::1RsJBJJ)BBZ{JkŜc{cZkBRkk1c)!!RZZ:JJJZZ{scJJcsR1!:RBR:JJsZcc:ZJ1)BZcJ!:Z1JBBJZ:cZkks{R:1):ZckZ11Bks::1:kBRRR!!Z!1)J:1!{kskR):Z))ck:B!R1::ZZJB{{kkJZk{k1s{c{kZ{{ksZJsZsk{kJcBBBs{ΜkΌ{RJsksksZRc{kkJZRskR{sssccscskk{skkZZ{RssRJJBR)JRcs{{csZk:cBBZ:B{c{Zccscc{kkZkssZBJBJZcJ:Bk1{)::1):JcZZ:Bc:s:sBB!1)BkcRZRRsB:1RkcJ{RJcs:1kc{cR::1sRŌsc{sskŌΌscBJc:RcJ)B::)kR1B)11!:)Z{RZkBJk{{R:))!B!ssZcJJR{!!1)1):RB!JBJk{ckssc1:ZJRB!JBcsZsccZRRkck:)!B:kZk!B:1Zks1B!R1c1kkZ!))BRB)!1JBkcJ1c:)RkRBR1JB1)Js{sJ!c{{RZZcc)skckR{k{cBcBRJkRsZRZJs{ZJkcsc{scks{εs{s{{RsscZB{ks{ckZkkkskckksks{ť{k{ccJskB1sscssccscZc{kkR)Zc{ZkRcBRZŽέk{B):ZJRsRkB):c1!!!1ck)JBZ1!Jc1)1))1ksJkBRJ1RRc)ZBZ)BcR{ssZckZJR1JRJZk{k{ŜJkcZ)RZZRZR:!JB)J!!))!1!kss:!!!)k{c:1:sBB{k{s)kcZZsJ!1Jk{RJRJRBcZ{R)!!!ZB:!kR1RR1BZRsksckJ!!):BR{k):::BZB!RcB)k1JZ:!BJB)RJ)B:JJRssBcJ::):ZZ1BBJ1BRck)cZ{JJZRBZscsΜcB!c{{{k{{cksksc:ZR{kskB{sZ)cZZsk{{ZkccRs{sZssssk{cskc{{{kk{{{sss{{kssssZBcZ{k{Zk{kZcRskZsc{kksRc{RŌk1Zck:s:ck))::)Z)))!)!):RRRZBkR:)cBc:!1)1!)!{kZRB1c{ZJZcZ{s{kRBR{BZJBZBcRRcccc1JRcZRZJ{cR:R:1B1))RB)!BJc{{{B{11s{)ccJcJ:B:sZZJR1R:ssk{{{1!)))BZ!sRJcBZ{BZZ::))1!))BscRRkcJkJJJZJcBJJsc!)1s:B:!!:RcR)1B:Z)))cc))J1B:ZcksssBk1BB1):JcB1RZZcRc:BJ1J:cRBcZJZkB1sssZZ֜kZskJ{sssccZcs{sZRss{sssc{ZBRBk{csRkZ{:JRRk{{kk{s{s{skkscsskc{ZsZŵkskkkkk{RZ{kckBRsc{kc{kcs{ZRJZ1:B1:1ZcZBs:JZ{Bc1!1)11cBcRkJcRJBZZ!:!1!cZsZR:1RZJckR)BZkccBZJRccZsZ{c{Zńkk{JkRRkZZJŔR1R)B:JccscskcZcckkBZs1BJk1c:kZk{c1))11)1!!1sB!BZRB:ks{cc11)!!!B!B:ZJ:JJ)Z{{J:kJcJ)1:!))1J1kJ!Bck!BJR1J:cZ{1!)1!J1J!)J!)1BB)::!ZB!cBcZ:R:JJ1JJB1:B1BsZc{JZ{ZJJckkkB{{步֌csscRRRcccZs{ss{RkckBck1{BRBcRsk{{R1Zks{{{ssk{sksksss{{c{RkRckksJcJkZ!:JcJ{Jskc:JRJ:kR:B1B)BBZcJ1JJ:{cZZ!BckRkRZRRRRBBRJ))!!)!!!cRJBcBJBZJRŜkRcJJRZsRBJskckksŔk{JkJsscBskZRc)Rkc11Bk{cs{ZJsBRRJcZ:!JJR!1!Zsk{kBRc!1!Z!!!c)BsZ)B!:B:J:J1:J!!J!:R1cZkkJcBZ)1)1k:!!:B)BBBR{)ZRZ:!RZ{BBkZ!11JB:ZkRJ!::s!!kc1::R)J:R1)BBB):R:sskkkcBJcZJsֵ{ZRkcsssJJckJ{JcskZZ{cZs{{{kssksssR:kk{kk{s{s{{skkkssscsk{{kscc{kkRccZkkRBBssk{J1sń{scZB:JJZ1::!Z::1csJBBcRB{B1:R)JRBsBRkRB:JZJR!)!!kZRcZB:BZ:ZBBsB:JkJsRcBcZZsskkZ{ssk{JRRBRkcckJkZJ1JRR11)Z{kBkJBR:cc{)c)BR{Z1:ZB:BBkBs1!:ckJ!)J1)BsJZB1))kB:cRZ!!!BJ)B))1R!ZkkcZRB1ckRZ11!!!!RJJk!!)Bk!!Bc!!sR!Rc{sBJ{s{RR{ZkJ:kR{k{!B::ZkR{1Z):B!J1JRkZJcZRcZk{s{Zsŵ{{ŵcs{R{cZkBB{ckcc{ZŭZť{k{k{{cRZccskc{s{ss{{{{ZsRZssssc{{cc{sZksc{kskkZRRcJBZRBBB:B)sRssJ:kRB:Z:!!RJR))RJB:Z)1s)J!ssJkkR:Z:BB:!!kB)!1JJRZ:J:ZBkZBJcs:kZRZcksksZRZZRkk{s{ks{scZ:RRZRBsRZZJ{BRkJkckcZBB1ZcJZ):B)!!!RB!11J!J{k!1J:)1BB1RJ1RRJ{BJZRZ:Jk!!J1):B:kZkZcB:R1JZZ!)s{sk!)1):J!!):c!kcRck{cJ)JBJRZckZń{:!c)BJkJR1J:R)B)1BRZRsks{{sk{Δ{ss{{k{k{csZ:Jk{{JΥ步1BBֽŽcc{ZcssRccs{ssck{kkskcZZcscc{ssk{csZZckk:ZBB11)ssJcB:JBkcRJRsBsk1JRZB:cR!!)::J:)!JRkZR1!1!!!1JZ:BZccs)J1):RZ)B!)ZcJJRJRJRcckJB΄{ZZZJsRZcZBcRRsks{k{Rs{c{sJ)cJJJkcccBscZssZRRkkBBkR:JJRkc1cB):):R:1cskZ!!J1)!JB!)Jkc!!BJZcZR):11)scZsc{{J1BB)!JZkcZ))))B:))1)1Z1RRB:))JB11J1k1:BcRZkksB::):J1kRJB!):)B:BZk1{Bs{{ZŜ΄{sccRk:RckcքkcksRcsJZsJJRBsťRB步cZkZ{cc{kZkZckZs{sk{kckkRk{s{s{cscsRRcJJcJkZZkRZZcsR:!!:)1ckkccsZB:{k΄kBR:Z!B!J{R):1ZRB:!!:!B)1:ZRJRcZZc!B11B:ZZ))!)cc:cssJBJJJRkkcBcJJscZkcZ{JBkcJ{s{ZZRεcZZJJcccZZRRckccBJ:ks{BsRkkcZZ{c!:ZB1Z!:1cBRB)BsR{kB)JsJk!!)1R:!!!)BB1ZZJ!)B1)1{cc1B1ZZkZRR!)J!!)1!!:):!!1sBB!BkZ)Z::111):!ZZ::cBJBJck1):11B1B:sJJ)1:RJ{kkB{s{cRBscccZcsJﭔ{{s{JRBJ֜kε֌Z11)R!cZkss:JJkksRc{{sksZccJccckkk{{kkcs{{JRcRZccscc{JBJR:B:c1)):1ckk:11{c朽{:k:J)BRB:R!Bc:)ZssJ{k!)1)!):!):1ZRJZBscZcB1B):B!ZZ1!B!!)kccJckBcZBBsc:kcJcRcRsZs{ckZ{{{kks{{kc{ckssRRccBZZcR:ZksJkZRRRJkBRcRccsRRZZZJBB)JB!1)ZkJ1B!ssZ)!!Zc:BcJ1)cB!1!B!RRJ!1ZZRs)!::))!)1!Z:R!:!:kRJB:ZJ:)BZ!1)sBZRs΄c:J:RZ)):B1BR1cccscRsJR1cBB:!1BJB)!B!:!:!JsZ1c)RcRsRJZskJZckR{Ŝcks{kRJJc{c{skΜskkRZ1BZJ!!JcZkksBZ{kcsk{Zs{k{s{ZkRckZkRkkkcZscccZkJssZs)BRJBBB:!:)!)1)kZRZkk{ZRRkR:cJ:RB)J:ks:cJR)cZk{:)!!!!B!!BJZZsZJZ1!ZBRkkkcc!):!1{JJJk{BRRcRcsRckJcJBBcBskBZc:cZ{ZR{JkJkJkJZcsZRZZckkZRkkBRRccRJRRZRsk:JBR:BJZ!)B1BcR!csR1J:Jc:ZZ1RB1!1!)::!J:!JBRccZ)J1)1kJ:!!R)1!J:B1JZZ))c1)!BJ:ksR歭sB:!kkR:R1ZRRBBcJ{!JkZcJB!:)1)!1J1)s1J1BB:{)R)kRkkkk{ccsssB{ck{RsΔŜZ{{ssksksJcckss{sޥ)kcR11:JR:JscssksscZckk{cBc{s{sZRskckZkscZckcR{{{ZBR{ckksZRRBJBk:!J)B:)J1J!!!Bc΄ZZkBssބJ:1:BRsR1c)J!:{sJ{scs:{k1)!)!1J:)1:cccc{RcJ{BJޜ1!!)JJ{J1BJJJsccJRZBZZZJs1kBsJJRJZckk{k{s{scccZ{kZJJRZRJBBcR{kZ:1!1BRZsZZkJJ:)Bc{B!1BR:Rs::!JJJ1JZ)J!J))1:BBcJ)11ZJZkBRZ1!J)!!:B!)!ksZc{J1!))::!)1JJ{1B:BRJcBsR:cR1ck:JcR)1))!)1B1:c::!1B:kB1:!{JZRBckk{֥ssckcZ{{ΌscJcJkR{c{ZcΌ1!:BkJJR{c1RZ!:Z{JkcB{sZ{{{s{ss{RkZskkcRJccsZR1)1ZRR:J!1)BR1)1{Jc:Rccksޥssc1)BJJBJ):J1B{RckcscZc))!):)!!!!!)RRkckkJcJJ֌s:)):JkkZJRR!)BJBRccRJJR:RRJckckRZ{JskkkkkcckksscskRskJBJBRBJZRJJBRJB!:B1JBcc:BRR!1))!cB))kBBRRcc:B!R:RBB1:J!!ZJkR{Z):!RB1:!JBB!ZksRkBcZccB1BB1!!B)ccsZRRZZZZZBkk1ZJRJBBR:Jc{B{:1:!1:11B::ks:B)R)!JJ:1)cJRkZcJckcŵŵŵťZ1{ΌZZsscssccskkJ:1:Jc1J!BcBZZccRsksRkZkkss{kZ{cssRskc{ks{csc{kB1ZJBJB:BRBB{1Z{ccBRBZsc1Rc:Z{:)B:BkssB{J{֔{{BBBJsc1))))!1!J:RcZkZB)s֜{:!B!!:!{kRRJk1cJsJJJ::1JJc:sRsZRkJcRcRck{ksss{ZckRkkk{ssRc:!:):R1ZcRZRkZZRcB1:{Z:)1Jk!!1ZcJ):1)B))R)Z:c:JR:1:))B:R)1R11Rc:ZZZ:!!)!JRcBZkZRkJ:)))!!::JR:R:RZZscZJk:sZBBBR:ZZJ:!){{::1)1)RRR1BBRBc1)Z:!1!RR1Rs{{ZJZZRBcRŵ֭kccZsŔckkkskc{kssBcťsJ{{ZRk{{skJJc{ZZcs{RZsscskZJc{Zkckk{RB:sRBcBJJ1ZZ1:Js{ks{sZcRZscc{BZJ{kR:RkJJRcJ)k)Rk{BJ:RZ):!))):B!!cZccZcc)!J1!!R))!!skJJskkZcc{RJJ{::cJk1RcZcZJJc{ZJkscksJc{cscksc11RBZRBBBcZcZZZR):Rcsssk!c!Rkk)BRJJB1sB1:!!!)sR)BRJB!)1)RJ:)!!)::J{cJBRBsJcJ!:)::!!RZBBRR:):)Z{Z:1ZZ!ksZksJs{kBZ:1R:1:Rkcs!R1kRc::::!cB!1B1ZZc11)JcZsckcZs{ZRRRRBZ΄k{Rkk{R{{sccsk)JŭkcZZssc{{ZZZsscccZksZcsJck:J{{ZkBBZsŭJcJZ{BcckJJ{ZkJZRsk1RJZk޵RJskk{{Z{)cBB{Zssc)Zss1!1:cc:)1)11)):)RcZ!!11!))!1B!!:ZRcskkcRJBRZZkc:cJcRsc:cJJRZc{sck:JcΥJss{Zck{{kBJ:RJZJRBRkRcJJk:J1:BcZRZZJ!J)!!{R:s)JB)11::):Z::B:B1R1!BJR1R!)):R))!Z:J:cksBJR:!!R1)::RZZZ)1!:J)Jk{ZBRRcc):BZZcsZZskkcZskZZc!1)B:1:):BRccJRccc{cZcksscssZZscB{ΥsńkΜZ{kRRRRc!Z1)):JJBcRcRcZRJJZss{scZRZ{JJJk{RZZZkcks{JRZ{ޜZkJJcksZBZZ:RB:Rss::c{RZ:BBR:!c1ksJ{JkcńJZZ{{B))1!1!1)))ckZc!):)!)B!!BR!!!ZcJckksckJ{JRkcccss1RRRJBcBBZZJJR1RZc)BccŭBkc{k{ssZsZJR1ZcZ:BJ{BBRBBZZZ{BZJ)JZZ::1!k{!ZR{Z)!BJ:B)sB:::!::!!1J!ssc1B::1ZBJ1B1BZB1J11RZ:c11!!1BB:J1BJ!1R1RZJB1Js:RksssRJ)BZkZBkkkksBB!!1!1B!B1ZJJZJ:{RZcJťsZRk{s֭札kJJ:Z1Z{sJJB:J:Rck::Z{ZJJsZk{kZkk{RJcZZZZ{{JZ{c{RcssZcc1sscZ{cZkkZBRRksZBcZkRBsR1R{Bck{ZJ11ccZJ{kBZBR1Z1!R{BBZJZkccJkZ{1:֔ZJB!!1!))!B!:k{kR!B!)1!1))RΔZJRZkcckJcccZZk{R:cZcR)JBJ::BBZ:s1Z:ZcZc{{{{skZJBcBBJRBJ:BkZ{ZJcssZc{kcRssRRZJsZ)1Rc1:!ZRJZ:):!:!::)1!B:cc{kBR))B!)B1:11))1RZB:R!B1::::))Jkk:1Z!)!1B::RZB!):JB{ck{sJJJ:sscsRcssZs:):!!J!))!:RBRJZcsZ!)cskc{kkcέsJJ:RJJJΥk{BZc{k{cJ)R{kZsńsckss{{{cRJcZckcB{ckBZZcsJRkBRcZkck{R:kkcBZck{kJkZc!Rk{ZZ{ZBkZcBcRZZZZZkkRZJcZ1Z:c)s)JB)J:{J11)1!11!B)!R!1)!:!)R:BZJZ1JckskcRscJZccZ{kZRc{kks{ZsBJZ{c{k{kcZkZcBBc:JJJBZZcZ{ZBRRJRZZRR:J1ZJ))sZcJZc:1)!B)1B):B))RcRk1)11!)!))BkBJ{kk{BkR!B)1BcBccB!11cZkZR:1J)kcZcRcJ:1BZcskRRZ!!)1!)ZJJ:B:Rcck{ŜJ))ss):kR{{Ŝ{{J:R֜B:JRRBBέΔc{ZcJ:Z{ccR{JkkRcJZccZkckcRkssckcskkcZBkZsc{scR:JBRckZcZZkRRkRRBZ{Z::ΥJ:1{{!ZεŜ{!RRJ{s:Zk{B:k{RZ!!))11ckZsJ!)!1!!!!:!!!!!B!!)!:!!):!Z)Rkck{1J:sZkZZRc{kkZZ1):BJZZcRcRkcR1cRRRkBcck{RkkRZB:)ZJBJJR1ZsZcckcJBJcsRBkZB)!!ZB!!:111R::R1JZkJB!!:BZ!:ZZ:!1):!:sRkJssksJ):1J:)R1BZBB1RckJ:)JJR)!1B:ZZZscBR)BsckRc1)!!)!)Rc)!)J))!RkZZ::RRBJBB{:Jc1Z{{{RR1!:J:B1kJB޽ťsssZcZk:JZJ)s:BZ1BkZZJZksJZk{浔Ōs{kkkkkZR{ccsB1RJZcZkZkZ{{Zck:B{cR){֭cεk{BB)Z1c:RZBZ:JBRsc11)!)k!)J))ks:)R!!))!!!J!!1:1!!J)1::!!)1:::skR{{kZscZB{RBZ{ZcZkZsZJJBJ1RkZRZcsc{RkRccZJZRccZk{RBJRJsR:ZRB:{:1JZckcJZskkBcJ:sZcRJRc1)RZ)!Z{R1J:R1!!ZkJJ1JRsk:1Z:Z1)1JJ:1sRRB{kZsk))JB)B1sscRRJ:JB!!B!1)ccc::BB)R!B!1:R)))R::ZZkRRR{scRRcskRJB1!cR)J!:!Jc:1!BccR{RZ1s1εcZJ{ťBBRR{RRkkZ1JJ{ccssťRJ1ZB:{ΌckZJR{s{Όc{JJsť{cJ{scZsZsޥ{k{sk{kcckcc{{{k{R:1c1:BRssk{{{sZkJZ{RZ!ccZkֽ{:sc:){c1JZ{1kJcc)1ZR1B1!!ZB)cR!:B::)):J)!)B:1!11:!))))!1){JcRRc{k{Jk:B{ZRB)RBZRR:BZJ:RkcRJkZZBZZRJ::::JZsJkssRRZJ)B֜cRcs)B:::JkZZsJJckR1ZJ)!sBBRk!!!s:!):JJJ)1JBk:1:1!!:Zk{cZ!Rc)Zsc1!:)):BRBR!!!:)B11!skZZRJR:B1:!1!JJZJkksB1:R:BJ{sZsZ:!B!:1:BBB1B!JJ:B)cBZZBc{Z1ckJRBΌJsRcRZRss)Zֵ{B:Bc)s֥έckZZRcc{Zkckk:s΄ZR{{{{kRckŽcsk{JkkkZ:1)):{sksBZJ:cJJkkRscsZΥ{Žks!RJkc1B):ZRk{1!):!:JJ!J:1޵RR1)1!J!!:1)!B!!J:))!:JB!1!!!!!ccJZks{kk{cskBkR:BRB:BBBJBRJJkcJkZJRBB:1ZBRJ:BJJB:ckZkJRBJRJ1B{c!ZR{{cR:)ZcJc{JJRZJ1):sks!1!!RZB!B1BJJ::)R:!!Bc1!11ZcRR:sR:!)Z!!B!:!!!c)11!RRB)!:1!!1{kkccJkRcRZ11B:::)B))!::B1JJ:kZJBJB)!11!!BR1JB:BR11:JZZJRkZJsskscs{RZkkBcJccckRZ:Jc:cZZZkZksRJ11B:RkZ1kc{Z:JZŔ{{ZcޭZckskcRskkRZs:1B:JJRRkssR{ss{RcBBJ1!Zkc{c{RsZkkZcsR:)sssJsks1!:RJZRsޭ)11!)R!!!!1k1!:Z!1!!:!!1!1{sZJBRcZ):JZRB:ccZZRJZZBRRJJZ:ZkcskscRkJBZBJRRBJcB:B:k{BRZscJ::B{{Jc{ZcZZ1RRRJZc{ZZJBkBZsk{{!!)!1:B:):BBc!B1)k:::J:B!1sJccR1)1!1:Rc)RBB)!B!:Z{JR:RsZccZBsRRcR1J1J):J)::JRJB:)R1R:RJBBJ!!!!)R!:BJRJB:{cRkscsZkskBkkk{ck:{BB:11ZZsBZ)JsJJJJkRs{{ccsk{{ZJJJ)cZks{s{Z{JZkZZs{ZZBk{kcZskscZkJRc{cRckscJR:RsJRs{sskZss{Jkﭜ{s)!:1{kZ:1s{s:Zss{:::B1::{cBޭk)!!!s)!)!:)!):J)!:)11))!!!):!1B!:!))!kBJJsRsJRBRcc{JccZBcZ)ZRZcJJZccRc:J:ZccBZRJR:JZ:B1BsJBsRcZZRks{{Rss{JkZZZ{sZRB:B΄B)RZJB!)JZJZR:ZB1:sJ!:RR:BcBJBRksscskZRB!):)1RZ!c1BJ!B!1B)11:J:::)ZRR)1!BZcJsJkkRRc1:::Bkk!1)Z!B11!!!RBJ)!)!1J))B:RJsB:)!B:1!1kZccsZsZcc{kcB1R{{Js{kJ:kBckkkcJBJJ:cRZc1sBsŌ֔s{csRZZkkkZ{RcssccRJZsJ:cZRRkcck{Zssss{{ZZRRRBBJ޵ޥ{ZsŜ!ZRJcsRcZJZ!1!:!)Z・B1!1!J!!)))1!:1)JR:1))1::!!!)!111:))RZZJ:Jk111Zkk{cJJJ:{ZscZcc:cZcJRZJJR:ZBJBJcRBJRRJRRcZZJ:!:ZRckksZ)sc{k{cZcJJscBR1JRc!)1!kJs)Js))kJ))!J!1{c!B:BJ{RB:ckRkBcskscc:1JZcB1ckRsB1:!:!!)BBZ:1B)c!J1))::1!BccZ:kkcBR:ZJ!!J:!11:::Jc{RBB1!!::)c1))kBR!:!JZJB1B{csR:Rcsޔ{ckZcΜsZ1JccccZsss{cZckBBZk{k潌ks{{Z!JJBkZZŜŽsscs{ckJB)RťkkZsJc1:RZkRBJΌcν{BZ{:{Js{ks{:{!):!:)kŵń!1)!1)!1!)J!)JBR1B:!)!kJ!1B1R!!!!!ZckJZ:ZZk{Zccc֜{B:JRckcZZZcRZZBcBcBkBB1:RRZ1:BBB:JZkJZZBZB1JkJJZ{{{kRsJcZkcZcRZsksBRR::1J!BsZkRR)RJBR1B11::ZBBJRJB!kŭBJk:1ZsJZJRJkZ)!RB1)1BBZ1!)1!)!s:RRJBRJJ)kZ1:sZZZ!BR:!))111BJ:cR:c:R!!!:J:!!ZJR1BJBsk:JZc{{{kkkB1):ZRRkkŭsŜ{ZBcťB)BkZkRs{ZέkksZkkRc֥Rcs{cckZJs{cs{֥{cεcZ{ֽޭ1B:ZRkc{skckބcR֥s{1浜RJZ:!1JccR!BZ1)::)BJ):):1Ό))))1BJ!)!11))))Z!::)!:11R:1RB1!!!J)B!)ZZR:RZsksRc{kZތJBBRRkRRZJRcBkZkBRZ:R:RR:kZZcBJJBJ1cckkZ:)J{Zcc{{{{Rs{cZscZskBJscR1c:ZZ)!Bkkk!BZRRJR:Z)B::!:BZJJR:!c:B::RsJ:JkB1kc:RJR!:B1B:!))!B1kJRJ::1:BkRcRcccsk:cJJ:):::BJZR::1JJ::cB11B)))kJZcJc{{scRR:1)Bs!)!):cZsBs朥cRŭRJs{kksR:RZ{RsRkZJcskRsńcskcks1JRRkskk{cs{Μ{ZZBֵc{kRZRJk:R{sRcֵ{s{ssck:)B!sssZ{k)!)1:J111)!Zs):)B:1)::!11!!11cZ:)1)1BJs)))::BsBJskZRcRcZ{ksssk:c:BJZZJkBkRJ{sZccZJBRJcZ:R:JJRRJcR{ZZZcޥ{kkk֌{RsssZsZRBBZRcJ:Bc:Z11k:kZ::B1:J!Jk1{{s1:R{ZRs1:BRZs{Jk{1)11))!!:J:ZRJcJ1:1cRBJ11RcsRcBsBZZRJZRRZZZJRJskRZJR:!k:)J))!skkccs{kRJJZkcB)ZJJ)kJcZńc{kJ{R){sŌBJkZ{ZZ{挜sΌ{{sRccRkRޭΥsZ:R:RRskŭsk{k::{νZ::JRRRskZJRZcRsscsccΌŌsޔ{{)Jc{{cJRcsk{kscsRB:!1!R!:1)B)!1))B!)!):!!B)B)111)111:RB!BB)1JR)!!)!B!:1)!)kZcZ{JccZB{{csRBJBBRkZZcJJckscskRccJZZs1:RBZZZZRZksckcks{cssBRc{{ZZJkZcssccRsscBRJRRc)csZ:!ccRB)B1BZ{R:cJBkc1c{c!J::BR{sB1sk)cRJcRk!B:)!!!1)R!cssZkJcBcJ:BRZ1:Js{RBZ{kk{sZccs{kRZkZskksR1:BB!B1!:!!!ckcJ{sccJk{sZR::)!1Rks)!)RR:Zs{ΥRRccR!kRZssJs{Jsss{BZZ)RsZkRBJB)BZc{Zk1RZckkkRޜcsskZBkRRBRBJJŌRsﭔJ1!1BR11::1csscZkcRskJ1J11:R)1!J{sBJZJ!1:!)))R)Jc)!11:)Z11)!!))kkBRkscJRk{BBB11J{kckccRcZkZZkkRRcZ{Z:BZBRcRJZssRJ{{RsksJ!RcckZRZ!cZ{ssZcs:RZRs!!R!)BZBcRc:)!RsZRc:c:!RcB!RRsJ:!BBBBc1:RRs)11!JsJZ{1sJ{ZB!1!!!:)1!!Z{RRBJBBcsscZkJkZ{:s{{Js{kZcRZ{RccZckssRZ:!1):1:!B)1){:s{{{JRBBBkRB))ssZ!11BRJck:Zksss{RRJsRkkkRRcZcZsJBZksZsZcssRc֥{sscs֜ssJ1!B:cZRJsJΌνZBRν{ŭc1:BZ:ckkcZJkBJsZk{{{Zc{kRRs{sR{ŽcŜ{R潽JRR)έckssBZkskJB{sRkskcJsRZRRZRBBc:JBRJJBBJkk{Zs{{ck{skBccRsBRckcsRJBJ){{ZBJZ:)s{!BcZ:s1k!:1::):J1:)RZkR1!1JBJ!J::J1))!:Z{{c1{csJZ)!!!!JRRJBRBBRk{ssZsss:!:JJZRZkksZs{JZksR1!)!1111!!k{ksJJ{sZR!!R:RJJBkRJkJRR:RRRkcks{ťkkZZc{RֵsΥZ:RBs{k1{sBs{sZcRk:1B:{sŵֵέ浽c1!B:1RJ:RZBνJks֭cZŽs{{csckkRckRBBZZRZcss{kksss{{{kZ1{Bcsck{{{k{kc{{!csRccccckZRkZZJckc{ZkRBk{::RB)Bk{{ZZscZRBckcJZBcRJJ:BBBZkksckcR{cJ{RcsksZJBsZJRk1cRkBJZJBRkk)!J{BJZZ)!JRJ:ZBB!c1)BZJsR{sZB)kB!1B1:B:B:cc!)!BZc{RZZZ{sJ11!))cZRkscJck{c1B1Bcc{ZkkcsZs{JJcB!!!)B!!ckRkZZR!)c:JBksRcksZ1!!J!!JBRJBZZB)ssRZkBRZR1ssޭsc{kc{Z{Z{Rc{c{{RνZJZc:)RkcckέZ1)Rc{{{{skŜJccJ:1)ޜ֜ŵk:ZZ{{JZ{kskc{{csZBJJBccJccZsskc{ZskZ{{ssRccZRssk{{{cc!sscZJcRcZZsccRkJ{ZRsZZBJ)Zk:11BkkskZJ:JRRZRJZZsZJ1BZJRssc{sckckR:kcZssZ:JRkkcscZBZkckckk{:JJR:!ZJ)!R)JB:cZcJ1B:BJBcJZ))Z))RBRZ:ZJZR!:R:ZckB:RZ{cB:!1:1)!1R:s{kRk{s:)!!ZJ!1ZRkkkRBBJB:c:1!)RccBcJ!!Bc)!!1:B)11:1J11JJcJJR:J)kZJcBB1Bk{sssk{c{RJsJccZcR{csk{Rcťέ{ZRZRR{ŵRc:{sŽŽ{ZkZ΄֔{:J){ZR֭ΜΔsJcB!Jk:1)BZ{{cc{Jk{s{Z{ZsRs{ZRZ:ckcssRJBRJ1B:JZkkkss{{{sŜ)k{kk{kskckZZZZZkccsskkJkkJRRZs{skcc1cJJsZZJc{sscZBJBJ{{J{cJJ1BZkZkskkcRZkkJcRJRcsZJRRc:Jc11cskB!ZJJZZBkkkc):Zck1sZ)R!:JBJBBRRZJ)ksR)R{{J!!!ckBR{ZR)J!1:))1kZ::k1:!!)))):Z!)J::R{ZcJJZ1B!1:)!!1R!ZZRZ1BBRJ:1):))!!cBBJBBJkRJ:kR1B:c!R:ZssccsRkk{RcRBZZRRŔc{:1BŽŔsJJ:c֥ŜkΌ{Ŝk{ބޜֵZcΥέΌc:JsB!:R{sńsJsεZ{J{ckccZckkckJJZc{csZkZ))BkJJkJZcskks{{B){ss{cRZc{sckZscJk{c{ZkcRJJZssBsskRJkZcR{ssJkJZskkB1RZZJJR)kJckcZ{kccs{RkZ{cccsBkZcZZZ:J1B)JJk!Bk!{c!J1cB:):B){!J{kJJ1BR!Z::JBBJ1:){ckc!{Rc)sR:1:!:)Z)R)):B!::B)1sJ!ZRkR):J))BB::JJ!RkZ:JRJR!!!1!)1:BBJ:B):BZ)sB11cRsskkk:ccssssccRcZkkJJs{:s:Bkkcs{ń{c1ks{s浭Ŝޥ{s{{kcJνZs:Bcŭ{kccsJcsc1kZsֽc{kR1kkZ{{{kkRcskk{{scJcRJkBRB{s{R{{{s΄JssBc{kZZk{ZZkRZccZsRZccRZJRkkRJ{{cJcscRZsscsZkkccJJ:RssscBkc{{sZkccRJck:BkccBZRBZRRZ1JZZc)!JRB:ZZ11B1ZBccBJZZBBBZ)RBR:B::1B1)RskZk{1{Zk1JJZcc)))!)BJB)1!11:!))1!1)Rk1B):ZB1::!!)!1!)!RR1Zc:1)ZR!))):!!)J:J):k)!ZJZBcJ{{))):BkZckZ{ksJBJZRRZccZccscksk{k{sRZk{{sk{Rkk{Zc{ks{ޥk֔ΌޜR:)J!BcZscε{kc֭Bc:sR{kk!sZZ{{ZsR{Zs{kJJJkskcckRcc{Z:RBZ:kksZssc{k{ks{sks{RckZBccZRRZkk{{JZcs:skRcskZ:R:cRkcskksckBZJRBRZZkkRZ11)RRRkZBkcc{JZJJkJZ{:JksJJZJBJR!JJRJZRZZB:11B::ckkkckRBBZJBZcZBR:)R{:c!!cRJB!:ZsksRk:):!!:cBJ1R1:):)!))Z!1)::)!!1BJ!!!!!!)1BRsBZc!))!:)!J{ZcJJJJB)1BkscJk!BBJJ1JsBJJBkRJRBRJZJ1csJZJRJ{{{sscs{{cc{Rsc{Z!)1RBcZ浥Z޵Ž!!11J:1B)RkkZ{:RksJZkJ{{Bュքk:JB!!R1kZ)RB:B!cJ{ccs{sksJkcccJRZZR{kssZ{JBZBccZJcskZ{Z{ksks{s{Zńc{kkZsc{Jks1{BZޭRkJkRsR::1BRZBJRcZJsssss{kccsZccZRZJZBs):ZcJJJkcJJBJZJ1{cZcBJkZRRJ:ckJB!!BJcJBJJJZZZZRRZcJ{k::)::)ccckJc:kccsBB1:kcZcccZBJ{csc)!BJ)k1):!!1)1:11!:!BBR!)1!:1)ZR:J)B!BZJcJZJRJZRJ1RZ!BR)1!JR!RB1Rc1BZs1cRRR1{BZJR)!)1BJk{sRkRcZskkkZskkZ{ksRcRJ:ZkBcsc{RŽŭJcc!!BB)Z):RskRZZ{BJR:Z::11kBJkֵRRZZJskZZcscJ:cJRRZRk{k{kc{{sZccZscksssZZJ:ZZJ1JRBZsksk{s:Zss{sc{{sscc{sckc{sssRccRZcsZZRBccJsccs{c{RskRRBJZRRcJZ)sRZJB{{JcssJkkZcZ{kZZcR{JskcRRBc1BcksRJZB{1JRZBss{k{!!!!BBZZJRBR!JJ{BRJ:RBsk!1kZZJ)1:::::sBRBB{{kZ1!!ZsJJBs1ZZR)s)!1)!:!:):J!!BZ!))BJR)ZR:):B!!)11c11JBcRcZBZZBRc:cJJJcc!:!cεkssZBc:1kZcJRZB)!:)1Rsc{sBΥ{{sccZJkkZkZccRZkRk{cΔB)!ks{k:)R!kkRJ)B):RJJJc:{1s:{cZkRR:Z{sRBsskcs{J)J!:ZkssRsZkkkscZ{ZkJcs{cJkc:BcsBcZ{sZ{cccZZZR{{kZJssJ:1kkcsJZBkskBR{ŌkZkJ1:ZBRkZRB1ZBZJJJR{{sskkkRZkZJJ)JcJccR1kBZZckR1:ZJZcZRZcRRZ)))!!))JJcZkZZJBBZccRR1c{c!JBRZRRJZRRRkBBJB1:BB:{sB1{{ksB:B:k:1BJZcB!:cc::!!1)1:)!)BB:!B::)1BJ:cBB:!)J1)B)sscBBJBckcBJcRR:cBcJBs!:ZJR!):JZ1JZ:BcskRcsB1)JZkBBRs{ŭck{kkcc{{ZccZBJsRB:kkssssZc{Zk{{c{Zs֥{ZsRB!!!):1JZ:{Z)1!)1JRsJRZBZkcZkc{sRs{Jss{ZsssZRscsR{BJZccZ:{kZc:RRcR{ks{ޜŔ{{{{kss1:BZs{{{ckksssRRJ:BZ{JcR{Rc!kZRJRcJRZJB:k:ccJ{k{{:)):1)s{kc1Z1{RJZBRcsR)JZ{kRsJ1ZJ{ZBZc:B!!1kRkcBcR!:k:Zc1:)11sB1!JBJ)ccZJBR)):1:Z1R{c):1BZ::B:Rc{Z!)BR:c!1:)!1)!)1R)R:JJ1:B1J:cRccJRB)!1)111cckRsc:1B:sRcZcccZcJcJ1!ZZZ1s1JZB::111B!)ckJ:Z1:!1sk1)Z{sk歭RRBsckkRZkkRckcZRsRRZkZksckRcJkkJZJ{Zckk!BΥsZ1))):!)!1!:ZcsZkŜJcckR1JssJk1!Zkc{cZ{{sBZkZZccJZcssRJcJ{J{ss{{{{ksZcJ!B:cZ{kcRc{ZZZkJcc):ZckscZ{kskcZJRsR{:BZRBJ1J1R:cB)!RZ{{{JJRRcckkk1RRk{scZ:ccBB1Bc:BZRsRJ1BR1:!)cRRJRkB1:cBJRJ):R1BZZRB):1:1!:JJ{ssB)J1J!BcRRB:JZcBsJ1!1Z!:BJB!)!111:RR{ZRkkscRcRZZ{kkJ:!:c:J:!B!Bckccs{kcZ)!)!s{ZcRJ1!c)JkscJR1)):ZRsB::c{{sc޽s{kΜkssZkccckRkRk{ccRsJB{RssŜk{JZZ޽֭攽Z!)!!)!:!1):JJ!::RZR{ZJsksBc:!ZJZk{ksRJsccR:cBckkJR)B:sscZcs{k攌{scB)Bs{ksޔcsRcscsRkR:RRRsZkRk{BBkk)JRRBBBZcZkBkZ{{cksBcRBRRcsJRkRcRRccBsscccBsJ!)ZZsk){ZB1ZBBZBsZZZ!!!)!JR1RZZR1:RB:B11!1:RJZkJJ1B)JJB1J1k:JcB{J11RRJ)J:c!cR!JsR{{csRcZk11ZZck:{RR{kcBRRBJ)!)1J)){cJB1BZJBR!!!!!)ZcJc֌Z{:::k{s{{RJRRBBkZ{cRRBRk{{ss{s{JZk{cckksBB{ZJBkZJc{c{Zcscc{kJR{{scJJ!:ckBsk))1111!!11):):!1{!{RskkssRZ1JssBBRskJRRR{csRccJZZR{ss{J{Zs{s{c{ksk{Z1)RZ֜skkk{ss::1)ckcRJZkRcZZRksss{RccskkJBZBJBcRZ1B:RJ:ZZBB1!JRkcccksskcJZ{ksRZcZRcZcJ:ZB!B:!k)JRZcJsR{R)B1)1BccskJRR)):J!1R11Z1R{k)RkB)ZsZJc{sB:)RJc:c:kccZZJRscsRZRRcRZRRZ{k{skcRZ1!1J1:RZZs)1sZ:RRJBJ1!BBB)!JZkJB!R֔Δ:!!)s)ZZRJRc:Z)scRJBkc{Μ{ss{kZR{s:R{ZB{Zc{{sRRRZZ{csskZRcZ{{cB1RJkR!1!)!B!:1:!!R{Ό{ZJkc1c1!::BJRccZRZZk{cZskRRZssk:)B1:Z{{Rsk{ssRckk{c:ckk{c{1!)1sZcRZ{Z{cs:s{c)RBRR1Bcc:JJBZc)RcJBJJ:R::BBJBBB):RRZk{{cZskεkscJBkJZcsssRRZR1:!1{{cR))JJJBRRskBcRJ1:ZB:ck)!s!!))J1:!:):R!!)J!:1ks:Bcc!B)1BJJJ!!cR!1BRk{kZBRJcBRcZBcRkk{{kRBZ{ZkB{Rccs{c)!JJ)JRZ)BB:ZJ)R!B))kZksBRJ1RskZ!!1s{)!kJ!)cB1ZB{skscsZcZkcRν{sckcB1Z{c{sscskRcťsΜ{JZs{{Rkck{Bs!cJ{ZZsJ)Υ{Υss:B1c)k!kZ1:BRkssBZkk1ZZkkRZBJBsZcsΔ1J{RZscBZ1skRc{{sJB1)1{{Zέ{ckc)!1)!1)kcZ{sskZZBkckckRcJRJZkRBJJcBB:)JBJBJBJBB!:J))1BZs:RJZZRJ:B:RkZRsZcZBsRs:B)BR:c{RR!!JRRRBcRcZ{::1)!1B:JRZJ::!)!1J)Z)B:RR)Zck:ZJZ!11)B1:J)ZRZJ:JB1BZ{ZsJkZBRJ1{BJJksR!ZcscsRskR!)):kZkJcRRc)cB)1B)::1):cZJJJJs)Zc{R1sRRRB:J::kc{{kRkRBksBkcZcń޽kJ!cs)::k1)k{kZkkscsޔ{Zkscs!R1k{{ތ{kc{ZR{cRRJ1kZBRB)RB:!JZkBkZccckB1ksJccRcZscB!JZkBkJRs{cks:ZZ){Rkksk{!!!1!!1!:{RcJJs֜kcR{{:ZsJRR:sskZJZ:R:!11J1)BB1::BJ1!J!BJsskRJ::1BBJ1B)1sJsJcZk{sR{:!:!!JRR!!BJ)RZJRZRcJ:)1BJ{cks!BkBZBBRJkZZRBcZ:){BssZ1JJR1k{Bs)!!)ZRZc)!RRRBkZBJBZJkkcs{Z1B1Z)k:BsZ!JJZsZB!):R:BJ)Zccs1J:)1Z1:)!):1)c1RZRJc{{c:):{{B{:cs:s1J:R{{Zcc{kRsskZs֥ZŽssck)ńk֔1:B1))BBR{{Ŕskk{ZRZk1:)ck!sZJksccZZRJsZRsBsBZssc:J1Zk:RJ:kJccB11:JZcJR{BRBRkZ:sZkcRZZZRJBcJc:RkJRJckk{sZ{:)::1:!B!!ZcR:cťcskZscZJRcJR:Z{kZJBB11!!1:11!)1!)::B:)cBkk!B:B:BB1c:J:::RkRZck):1)R1sZ))!Rk{ZJcBcB)JR:)!):BRBRkRZB!:BZRRZ)kkc)B)!){RsccB!1::1JZZ:!!11:R:R1:BkJRZcRJRsZJkZckckkkBkk{{!!)!BssJkkB:RJcJkR!!)11)!))!::B:RkkckR1:::c!!!R{RZBk)s{kZ{csBBBc{{JJkkZZֵ{{k{kcJkΔJ:J:)!)sk{ΥZc:RcRRck{Bc:!1:Z:!scsޭ:cεJ)!k{k{k{s):)):R)Rk)BBB11:sJRZZ):kRB)RcJsk)BRsksccckZJcc1BZBs{{RJc{ksZk{Jc)!sccZBZ{s{kkcccckcsZBRBckRB11R!:::1c)!:):cZJ!JcsZJ{Z1BRRc1:)RZB:RkRZZ:ckZsscJBR)B!!:cJ))!kJJR))!1)JJ1:{sJ:)):scskcRB):R:1111)1):B1{scR!1sBZ:ZJ{Z:JcZZJB!1cR{sJZB1J)1RsZ{kscBJBRss:)1!B)JJJkBkZR1cc{Z!!)::11B)JsskZkcZcZkRRkkss)BskccJ!ZZZZ:{ccJ{kkRŜ籠Jsť1kZBscsZkskcR{sRss{ss{cJc)1)!)JޥJ1Jkkkckcksk1{1sZ1:!c):B1RsJskJkkZ1Z)kcRkRkJsssscskkZcZ1RZZRֽ{Bck{kZJcRkRc{)!kZZccckZsskcskkckckBRR:cB:BRJBBs1Z1)):1kRcZkcRR{{JZJBRcRR:RRJJssBZR{ZkZcJZkR!!RJkc!:J:B!!1!!J11!1:)BRsJ{:cZ{RZJJR:!cRJ1)Zk)1Z!!)1RRZZBZ!B1):1!1cZJckZB)RJ1R1Rck{kssscJBk)!1:):sB:Z!)JZcZ1{BkZ1RJBJZZsscZZs{Zc{ss{{Jss)!)RZBcskcJJ)1:)JkcRkksccBJ:ZcRRJcJ|sk{sZssckJ:Zc{{ZcR:RŽkRcZZc1:ZJ1Z1Z:11)!!11sc!!R{kZRskccR:1k{!1:)JkkB::!!Z:Zs{cRBckZRBRkZR{Z:JkkcBRZBsckRZZBRޜJJJs{ΔskcksZ)1))kJckkJRckssZB{ckkck:BBZkRkk:ZscZcޜ{{sksRJZJcZBJ):Bss֥RcBkRc{cZs:J!!)):B:ZJZRJR1!!1)J:B:)!BB11Z!{:)B:R:BR:ZJcckk)ck1!1JZkkk)BJRB!1sBBJJs{kZ:::1):ZskksZ!J!JcB)RZ{{RRJRkJsssB:BRRBB)::ZR1Zc{J{sc11R{sB{ZsBJsB::)Jkcc{kJRckk{kZsk{B歔{BB{{{{ccs1ZŌ{s!sJŌޜkscBJ1cRZBBZ1)R)1:!)1!sBR{111ks:cZcJs1cR!BZcZsR1J{kJ)!!1B!{ccZkkJ1:R{Zc:kk:B1:1J!J)1RZc֜RR֥kkRZkkkkRkZ:!Zc:ccJkccsRsZsZckcsJJRRcssckZZJccs{ss{k{{sk{1Jc:Z::BZ1:cZZcZkRJkZkscRRssc!1!!1R)ZJ)):)J))!)!)1skJB:11J!):cs:RkR)!):sJ:BJRJ:BJR:!!BRZJJBk:1kBcZ:J!J1Z:::!R1ccB{{J:!JJ:RBcsk{)!!J1)R:JkcR!!))JcZRBc)!1!)11!!1ZJk:)11)!Jkkέޔ{!scRBRk)::sZc֌cB{sZZcJZcsZZckBc{c{s楔B)JccJ1ťsks:B:ssscJBR1:Z:{JBJ!!:!1)1:!Rk)B:RJ:ZRRB1RR!BJskZ!)!1BRRBZZkZsRkZkZZRcRkRZcsskR{BŌ{kŽZ{RZ!s)B:!{cssRkkc{cRsZRRs{sBJs{ksscccs{c{kZksBkc{ckkBcJs{sR:ZR{kJcccks:!1Bc)!!!)1!RRZZckcBRJkc:1!:k!J::BBJBZRJBcck:)!!!!B)JZR:1Bk11B!BJBZZsJJ)!!kcksJkkkc{Jckkk{kRJR)!:!1!!Bc)kZB1!!:!!1{k:))1):1!ZZ{1!11!1s{1cR{ZcJJZJ1R:))JkZs{:kZZ{sJZsZ{s{kcs1ZkZkZksBJk{{JsJZ{cB{{skccť{:{s{k֥c1JֵRBs!)))kkc)!)!kRc!s:)J:RZ:))11R:BJ:1B)1Rc{cck{ckcckJJ{sBsRJB:kkkskcRR{{k:!)skŭ֔scss{sscBcc{{Zk:RckkcZZk{{kZk{kccJ{k{k{s{k{{skkksckBRc{c{ccc:Z{cRJB:ksZscZ:))!11JB!B:!!:cZRZckZ{RB)B:B):)k1J:BRRJBJZJB11!!1J{k{cJsR1RRss!1:Zkkckk)sccRJ:kZk{ks{kZ1!B:J))!!J)1JR!:1BR!!RJR{s{:!!11!!BRB)1JZ1B:ck:kJBJBRJRkk)JZJ1cckZsksZJsZcJZZkkRZs1RkcsksZ{Z:kJ!::)ZRR޵֔ZkJ)J!1:B{ssB!sc:{cBJJ!!)RsZ)Z1JJZ)Z)JBBcB:B))1kck):{JccckRJkRJcZkBZ1RRccJRRsZRRBJkB{潌s{s֜kZkkcc1c{sksZ{sZJZZRkccZkc{k{ckscJZkckss{s{sZcBJZksZ{ckZRsRBJR:::cRZs)1JsB:JJ1:RB:R:cRBZ::R1:BcJBRkk{cRJR)BkZRcJBJkk{{{RZ:!:{{RJ):)JBZsc!)RkR{BB{ssksckRks{::))!1:B!))1BBB!c)B1:)B1kkZ:)JZ)B!)Zc!Jk{kZ{s!{sR{ZB):11:RZ{RcBZcsscks{JkBc){{kJ{ZZsέk{{sskc{cR){kRkkk:Rk{ccc!BcRRkJcZ!B)1!Jc::B:Z{{έ{RB!ZBkccksRJZB1RZ1BsZ)J1JRRk)!:1cZ)B:RR1):cR1!cZcRk{:JRRRJBJcJ::1RRBޭZ{{kcsskJJ{{skckZcscccsk{:RkR{skcRskkks{k{sssZRk{ZccscZk{k{sJcJ1:1JJRs!!BJR:k)ccB:J1:JRBZ1JkBBRJ1:J:B1B:cZ)Bksck)!scc:cJZRBZZ1ss!B1sZkZk1ZcZk11{{skcsscsRss::111!:!)B:R1!!!R)1B):!RJBZ{!:))J1!!{{1!:JB:ksskc1::J:JJ1JJBcZkck{sR!ZBkRkss֜kckckkkZck{{ńRJsŽJsB:JZ1RRB:s)J{ZZR:11:JsJ:BZs!!:1Z:1:{ssck{ks{sss:Z!kBRJsckJ{k:k:BBksZ!1RRJJZRkJJBc{kcRkssBJ1ZJRc)1歄{s{{sc{ks{csss))1):R)):!)!s{cZRcRc{JBJkcZss{sZkJB)){cssk{{{sccZs1ZJ:!!BJcZc11sRBZBBZRRRJ)1JRRBk1))J:R1BR:RJ!::11B{{Z)!!):BBR)cZkcBc!:111)!cccZBcBB1RkJRZZBZkRBkRB11)J)!!1RJJ:ZB1!):1!)Jc1):J:!)!BkksR1kBBZZcJ{:1ksJ::1)JB:RBBB1J:{{{sk:ZRZkskޭZRc{{cŭscsRŭs!))BBsJZkkJkksR:c{B1::BBcss:1:JRRJ1JJR1ck{c:cZ{ZJ:BRB11RcR:BRBcR1:1cc:B!B)JskBJBBJJ{k{JBccBJsc1ZsZZsZ{ZkkZssRk{kcRs{cckk{!!)!!)!))!BskZccBccRRRRRRsc:Zsk{{!!!!kkRs{{sksZRc!ZB::1:R:k{R1Zs::B))s:R:!!!1RZ1)!1kRJ1J::ZRZZsBJZ)RZ11!:RBZZZBBR{kR)BBZ)J!:JJJ:ckksJcc:):kZc{1):1RZRk!!R:Rk!)1:c!))B:R1:s)1)!J1ZB)Zskc!!c!)JcZRsscR!1R:!1BRRB1::1:sJksc:J{1s{{kk{ZckZsk{JR{ŜZ:JsZsJc{ք{ŜRskRsk{JR:RRRZZ{Z)11JBRscB)ZBkJckZťJBksJBB)Zc{{kB:ZZBZRJRsRB1!1!BZZRckRkZJZRRJcRJ{1kkJ11:ZsRkkJBRZskRsBJZBkckccc{{!!1!)!JkZckkkkRJRkZcscsccZkJJsZsRJ!1)!:kkkk{kcck{kcRBc::BBJ1JJckB:!BsZ1:11B!J:1B))Rc:kZ:1:))1:k:JJJJck!!RcJBJ1:BBk:1JJ:11!RkkJ!1ZBZJcscs:!JcksJ):R1)1!):)Z{)J)11)!B:BJRJcJ11!1!!1Jc:k{cssJ1!!!):J1!):Z{ZcRssskZ11B1J!):1Zs:B1B)BJcksk!ńR{εZcR!ccJRscs{ZRcsscsJJcBkZBŌZkZ:cRBZJZcJ:BZkksZ1!1JJcsZ)JJ{R:{::csZkckcc1kZkJRRcB:1BccBB)!!RcBBcJZRkckkc{ss){k{sckRJJRBJ!:cckJZJcccJ:ZJs{ss{c{k!))!!!!!!Zk{cckZZkJkcckccsBkZRccZsB1):!kkZZkk{sZBB!1BBkcZ{ZJJ)R{kJRRRkRBBJ1:BRR!c!!)Jc:ZcZcJ:B!JBRBsZ{cJZc)ZkJ:BJJBRJRBBcBBRRk1R!):JJJsscZksJJk)1RZ11B::!JJZ!B:R:!1:1!::RRR{JJk!Z11J))c)B1R{:!!!!)BJkck{{cs{sRZRZB)!1B!RRRc:BBJR1JRBJksk֜kΌ愭Rskk:sksZ{JZ{ZֽJkJR{ޥJ{΄ޔJ)ŵ:R:Bk:JB{ckRs{RBsRJ:::)c)k!1kZJZcsR:cRcsskZ{:Rsss{cZkcZJ:11JJZ:):BJRZJc1:{cZkkss1kRRcZcZRJ{1BZ1:ZBsRZBJZRZBcZck{kk{1!)):!!!ZsccsskcRcsZJRkZkJBBJJsks::J1!!kkcccsZRZJ1R:{k:R)JJ::scJ1{cR)!)))1BZB::)R!R:s))!1:BRBZ:RckcZ!Rk!)!B:BB)1R)J:R:kR)B!!)!k{JksZZJc{kB:k{kkRJksss{c{JJ1BZ!)1):BRJkBcR1)JR))!1kRZ:BJ!:)!)!ZJZkcZ{kkkc!)ZcR1sJ:J1::BB:J:B:sBB{sskkť{{Zcc{cskccZRkck{{ZRs֭11ťcRJR{JBJ1Z:ck:kcJcRZsJkkJkR):!JZ!Zc{Z!cΥcs{{RRksJ)Zcck{k:BR{ZRRZBJ1Rc{R1))ZRJJZk)sZ{ZRckcsJkR)JB{kscZZZkR{RJZRZc1Jkckck1!!)!{cRJZc{sZkBZZJcZcccJJJBZckZ)!c!!cRJRR:B1BJ1:B::1):Zs:RZk{JJ:RZJZ:B:!R!Z:BcJ)J!ZR)B!!1)kk1kc)J1RBJJZRJZBBkcRksBRsZRZJR1skkkBZ:Zss{{kB11JBk1!)!1J:JRJ1BcB:!:BZB)!!:J11:kkJRZRZRZR{kscRkRss{{s:!B:1:Z1!J!1)1BBcBB:))1s{{έRZZkk{{{ckkcZkkJ{{cZBcB{ֵBcŵcksscJBBRssksBJ1JZ:c{skcckkc))cRBZZ11cRRk{ތsJkccZJkcBkc)BJZsksZRZ:B1BJRJcB1c{JsZksB{RkZ{JRJŽ{֭kcZccsk{cRBcsksRJRkc{Rks:!!!!)!1:BJRRkZRsss{cJRc:BkZRZ:RRRkk!!)!!JRRJZR)ksRRB)JR1!BZsZZckRBk:J:ccRZBJ1)!JBR):1BRRJc1J1ZJZJRss!):!cZskZkJckRR)cckkB)ckkk{)Rs{J)BZB!1:J1k:!!1RZsRBR!)):J!!JBcs)):!!)J1:BJ)JkRccBcB{Z{ZkkZRckssJcJ!!1JZ{sJ!BBs{cJBRR{Z1!)!Rs{{sk{{sZZksBccJs{sk{cJc֜{RZBRZ:1kJJ{JcRZcscscR{RRR)kcscZJBJc1ck֥ΥŌ{:kZc)B:ZBc{{sRcskJkZsZRRRcsscRZkskJcZccBsքޜ!:1:1BR{RJscZZcZkcRccsckkscRckZcZJcc{kckZBJ:R:cR:BZckkJZ!!!))J!!!R:Jkk{Rk{kkkk{B:Zk{JBcZ{Z)!:Rs)JcZZ:RBRJ:JJBBBBRBskRkZZksRJ:!kRJcZkR1B{ZR:Rs!):kR{kRZ!RB)!1cJ:1cJJZJ))kckc!1ZRZ)B::RZR:!)!!c{ks{kB:s{k{{sJJkccscc:!!):ccZRJ!!!::ZJJJ)cJcZ!1)11ckޥ{kŭ{ccZsskZ{skJ{{{J!:):R{ckRRsέJcssZk{{cZZZs{ZR:Z1kB)Zskŭc{BJk{cJ):J)::c{ss:!ZR:BBJ:JksccRck{kkZsskZ!1:ckBB:cBBBRJ֔11:RZRkJcBRssckskc!JkJRBRJkkZk{kZRkRsk:c:cJBZskckZR1s!!!!)!)BBBBZRBRkkc{skJk{{B{sJ{ZBBcJJBRZJ!Z!R)JJ:!1Zs:B:cssJZB:ZZJ)ZRJJZsR:cJRRR:B!))JRJc1RBR)c1!!Z{ZZB:kR:c:Rc!!!ZBJB!)RJ)!)B)J!BckcscRcsk{kkZB{cc1{sZB!!k{ZcZskRZc:R1BccZRc)s!)1):Rޭ{ŭsޜc)JcŔskkscscνΥńB)k:!)kkBBckRRs)::s΄sZ޵sŔZJcs{ksRcZBsBBR1BZJZckεJR::::J:J1B1ZJcB:kcs{sJZ{ZkckskRkss:!)!!:JckZRkJRcRc)sBRk){BBJRZkkRsk{c)!BZJR:)c1ckkkJsRkR{B:R:JJZscsJkZJRJJB1!!!!11cBRk{::JBJBckkZckcBckkkR1!BZR))11J:):R:!!1RBsZZRBBZBZRsZ1B))BBkkZkBJkkBB1Z:R))1BRRcZkskZ!R!))J1kB!BJJZc:!)!:Z:!:B!JRR)Z111::!1kRBRJBJRkcc{ksccccB{ksJ)!!cZZs{B1cs):Zc:RZBZR:s))!1)Bkksk:R!sBJ1)c{k{cscRZssZ{:Zk{cBZck:ssZZsZńksBRZkskRcss11!!):ccJRJZks{kBRRBkcc1Z1):BJRsJcZZZcc{skckZRBJB1RZB1)B1cJccZk{:Z1:Z)ZcJZ{BRcZZZ!!:RJJZZJJZskkZ{kRBZ:RRRRkRZZBRJZJckRJZZ{BRkcJBkcsksskkcZRccZk{{ccZksJZJkB)!ZR!)1RB:)BR!!:ZJBJZscsJcJJJR1)ZJRcZJkRksJZBBB:!!!cZcRZkZs!ZBB!BBRR{R!J)!BJk1)!Z)!!R::!!!1)kk1JJBJBZRZc{sZJcsRkc{{!)):kRksJ!)J{{R)){RRsJR):!!:kkcs:sB111JsRcΌ{s{{skc{skJskZJkBcBZBBB!:BRsŭRsJBZ{ťc1ks{RJJk{RcJZs)B))cJBJJ:ZBJRs{Z{Rs{Zccsc1:1:RZ{k{sŭs{s1RcRR!)Rc{scZ)1))1cssckssZJRZRJ1skRRRJcs!)ZZRRcRZB{kc{s{kkc11BZZZcRcZc1Zs:cckZJkcs{{RRB1)Jcc1:ZJBRskcck{s{kcBckR):ZJZkR:1RcRZJ:)JRk)BRBRBZsJ!:cJcR{ZZRcZRZZ:kR!ZZcJJRk)RsB1:BkJZJkc1))!!BsBB!)B!1)))B{R:RBJZ:JJRccBcccckZZ{ckR!JcRkB!Z1)1!)Zs֔RΌkRBkkRR)c{sss)!11kRŌksZsZkRJZk{{ŌkJJZssRR{R{csZs::1ք{ZBk{:R{csc{s:1)B:cRcR:RskRccc{Jcs1ZkJBccsRkRsRk{{kk{{JkcRBcRsZc:B:!!!cssskkkkBBcc:RcJJZR1)RRk)!!1:kRRZkRRkcscZsckck{ZZB1B!JBBJZ:kJZBkc{JZZkJR11BZcBR{R!RRZBsc:RRBkks{ccskcZ1JJR:J:BJBB!1)Z{JBR!ZRRZBJR{k!!!)BJ:RB:ZBZRkJRBRs)ZZccRcB!!1:!1RRZJJ)!B:!!1!R!1!)::Z{JJBJRJBZ:kR{s{BZJss{Z1)!!!)RZZBJ!!JZRJJBRJ{c:!{sRRBJBJ:Bkckk{kscZńs{{{{Rk{k{ZŽJZ֥ccsckksZ{JcZ{BBcZ{{skZck{cskcR{kJ:!:RJRc{k{BccZskB:k{ks{J{εc{c{J{{kk{s{ssRcBR:)1csZ1B:B!!{{kc{{RZBZZRsk:R1cZ1RZc1RRBZRssJRJZcBkskZssZkZ{kB:1::1)ZBBccJBsZ:J:c1Z{Rksks{ZkBRZkc{ksJccB:R{s)J{RcJBJ!B:!RRcZ:!ZB{1JBJcJZ:cJZB)):R:cRcRZsRkJcB!c!ssckkJ))J1RB1RJJR)1sRB!B)!)!1!B:J!BR1!)):RkscJZBZcskR!)!!!:Rc{1!sB)JJ:)sZ1JRJR:Z!:1!!scオcJ1kťﵽkJ{Rss{{{{kέcZcscR:JJ{sccBk{{R)::BZsεJck{sZ:ZckZcsskRcJZJ:c{{R{ckcRckJcscksJBBcZckcRscskZBZJB:ZJkc{ZcRRcck{{sJRB{Zck{cZZRcccZBskkJccJZc:JJ1{kZc{JkJ:c)JBBR::B)ZR:BZ)1)1:ZkkRRs{kRc:k{{ZZZcc{!!!RZRckssBscJcJBBB1!c{R!!)JZJ::RBJ:Rcckc!JZJ)JJcBJBZBZBcZJB1!RRksckB1{kB)BJ!)::!!BBJkskcZBR!!1))))BJ:!)!!1!)J)Bc!J1!):)BR!!)!!1)!RB!!!!RBZk1)!kk:ksRkZs{kJ:RBBR1!)R:)1J)111kkJJ{c{sskkkŔssc{cc{ZcRsc:RsJ{c{{c{cc{:kcJBsZ{Bsc֭cJs{{kkc{s{ZRcZsc{JRkssRkksJRZk{ZscZRZ:{RckscZ{{ZZBBBRRZ1J:sZkc{)ZJJBBBJk{scscJJcRcsJZJBR1R)JJJZcJRRk1JZ)B!):!BJ11!:ZBB)BR:)cJZRcZJ)Z:JccZZkRBkk!!!kkkk{kkkť:RRZZcRJcsc!)BB)ccR)RcR::B1cZRZZR)sZBBc{ZJ){11BR!1Zckkc{!)kRZ):)1R):!1B1ZksZZ{J!!!J)1)BkJ:!))ZZB1)!B::1)!:!RZJZ))!Bk{1!Z1BRB!Js{JR!:sR11!1B1JB:)c)c:)!)R1::1{ccB:css{{{{Zsc{c{s{sssֽkscc{{kR{R{JZ{sZZk{Ž΄ֽk:cZc{c{csZskJcsc{cBkcsscs{sJRJZRsZRkJkcskkkcJRcsR{{skJB:RcJ{R1B1cJέRń{scRJcJs{sRcssssBscJBJcBBZR:kJ1R1kJBZBRBZRJJ1)))!1B11RRkZZcZB1c))ZZJ)BZBJBZkccssB!11k{sskkŵZBsRkRZ)::JccJ{Bcc:cJRZZZkJRRkJ)!!!1cJ1Zkck):ZJc!:ckcsZ)!BcB1ZJJ1!:B)1c1cZR{c:Z)!!!!)!B!:ZcRcB)1:J!1BZ1JJ1BB:::1B:BJcR1Bs{:BRJ{c111JZ{{ZJ)!Rckc)ZB:J1B)BBJB:B):BJB1Bs{kZ1k{ssk{{{{sckckkZc)J{Rssk{ZkBk{BkcccJŵΔΜ:kŌk{ssZ{sskcJ)Zk{ZRZBRkcZZc{ssJJRZkRsJccck:ZZRksBss{R1R!:cBZk{ccΜsRRkέ{sZRkckBJRRcJRccR1BBRJZRss{JJcR:ZBJ{BR!!!)kRJJcRksRcZk:R!ZRssk{c{RcRcRkccB!):Rsskkc:ccZcJBBBckJRc:1:ckZJkZJkkZRR)!B{{sJJBR:ZR:kZksJ)BsJ)!!R{Rk:)!!1!1:)B)BRc)!!!!:!:B!!B:!!ZRBRRR:J1JRRRRkZ{k:1)JZcscc)JZ{ZJkJckZJ1J:kR1)1):!1BR)::1:J:B:JscJ:RsŜkc{k{skkcs{{sJRZJcRcŔRscs{kJ{{Rc)11!!BZńΥssk{sckk{cJ{{{{B{kJJZJscBZ:k{ZcsZZcsZBJsR:kZZZB!:cc1J:1ckc{s{BRR{{J:Ŕ{s{kZk֌kZRZRRRRZRJkcckkcckkskZJRJ)!1)R1{{{ZBJZ{ckZZsJkRc{{{B:BBZcZZ{1))1):ZBc)RcRZRcRJJ1Z1!RZRkcZkcZRJZskJ!1JRkRBkZ)1B:{)JJss{ck1RJZJBk!ZB:{1R!)1R)B!!1:!!11ZBJ)!B:::BRJBBBJ1JcZJZJc!RkZB)ZscRJ!))RckR::!:JRk1!B:1!1J{:111cB)1BJ::1B1R{ZZB:RssZk{{ksk{cR{k)cZ{kssss{kcsZRcccRBZs:Jk1))R{cBsJ::k{k{{kck{{ZsZ޽kccRsssZRscZJssR{J{sRBZRRkkkkJ)B1!)JBsss{{{cskRBR{ZscksJBZRRJccBZRBBRkkks{ZRJ::B:ZZZ1Ŝť{cBcZ{sZsZZ{cJBZZkRJRJRZR)))!ccZJ:kJRRZJBckZB:!!1sJcc:RsJ{JZsZJ{:)R1JRJRZcBZJss!)c{Rc!)J)!!)kscBc:J!)!!1!!11B!JRRJ)J))::c:!RccJ)ZJBZZJkZsBcJZkBBcsZR!)kcsk:!JR::)!:1s)BRs{B1c!BsRBJBB:J1RR{ccRc{kkcZRk:RRZsR{kJsks{sksc{{skk{{sZ{BJZcc{Ŝ{kŵZ:1:JkΌ{΄cRkkscssskRkk{sZ{sZkccsRsR{scR):cBBJJkcsssckZRJBRs{R{{{cZZskZcRBZJ11B:)J:BcZkRscRRJBB)))νsεkcR))RZssJ1Zss{sZZRZccJB)!!)!)!JRsJ1kkJR)JBZZB1RBZcJc11RRJZkZcB:ZkZ1:c:1ZJRR{RBskB1B!!RZkcR)JZZc1!!{BsB:{R!!):)BR!11:RJB)!!JBJBJ!BRksJJ)B:JR{k:Z1!)Z:J)!1)!)1s:1!:J:!):{:!!kskRRkkskB11J):B:1J{cBRcsk{JBJ!cJcZRR{R:sksRkZRs{RcccZskksckŽ:B{ŔR1))!):cs{sŭssss{ssks{BZckcks{ksRR1!cs{JcZksccZJZZ{{sc{sZkcJkJkRsB::RJRZBZc)R)B:JZZJZRs{cŽ{B1BB)kBRBRޥ{kZZkZ:ckssc!1)!!RB1ssBccBBBZkZ:R)BB:RZBJRZ:Js1RRBcBJ:JZBZcJcRZZRkk{s{:!k{!BBkZc)ZccZJ:ccJ{Jc!:1B11:1)):Z!ZBkk)!)ZJZZJJ1)R:B):skk1!RRZJ):J1!R1R1Z11RcR1))ssssJJRRR:s{k!J):))BB1BssZss{cs:BB1JcRBcB{JZscZcksksJ{B{ZJkssk{ŭ޽ֵ)BcJZJ:Rc))cc1)1)RRRsZJcRZZkޥckJcsRcc{kέkJ!1s{BR{Z1JJ{εZsJZRk:BZkJZJ:BJJBkZsRkkck:sskR1:{kZBkcZcckRֽΜBsZJJBscsR)!!!!!!!BRJc11Z:cRBZZcJ))!1!RZJRcRkRZJZJ1Rcc:JRZZZccc{BkkkZ)!J!)ZR:))!scsZ{!RsRs1BB1!1BJJ1B1!!!RcR):!B1BBZRkskR:kk!)::)!ZJ1!!11)BJZ{{Jkc)::Z{k1R1J:1cskZ:1J):BB!JkckssZRJBJkZ:ZBcs{Zssscsc!Z{kֽޥcs{:{R)!))!):ZJcJ)):JZZZZcRsk֭ZsZcJkkc!1BJcc{޽{{{{B1::{ŵsZc!cRRRZZBkR{ZZs{::JBJsc{k1BcskcRZZksckRstscZkkZ{sZBcssJcRBJRcksZ!!))!ZJJBZcZB)JZ:ZR!!::Z!RJRsZJZRJkZJJcBJsRRc{{ckZcRJ))!JRcB1{JckZRcBcccc)1kRZ))1JJ)J!)J)Z{sskkkk)!JJ::B)!!11!!RsBJ!1BBB)JZc1!!Rsc{kZsc{k{k{kBJJ::c)!1:BJ):J1J!ZkZcZks{sJ1J1J:)BBc{scs{{cc{ZRRkZޭ{k!)!!J{RZ{{B)!111B:k{ZRRcJRskZZcsέ{ksΌ:cZB:JZZJkk{s)!R111:cZ)::{ssJRcťsccJBRkZZ{BBJscRcZZZ{ssBJZRJΔkRB{{k!RBR{k:JRcccZZRcks:!:!!!)!)RZZJkRsJB:R1J:!11BRkRZZs{R:ZZBRZJc1JkZcsZckccZ!!1!!1JBR!B):{scc1JBBk{ZZZck)c:Δ)!ZBB1:!!BcRc1scZZsJ)BB1):::R1c)Z!RkZc!!!!cBZZRRBB!BB{{ck:1JBRk:1BJJZ:))BsRZZZJ1kBRB:)J:J1)Bs{ksc{ksksJ:BBRJ:R:1ZsZkcń攌εZZ!)B:1B!!:)1BskscZZ1ss{BBssscZskcksksccscBBk:{{{{ZksZkBZZckޜJRΜR1!:{ŽB1sŵ{1Υ{skBcJckckZksZskRkc{BZBR:c:ZkBc{Zckֽssss{ks֌1BBZR{ss:cs{JRZBRsJJ11!)11!)1skckRZJ:RcJ::ZB1:BRcZRZsZRkcccZRkR{ZksksckZRB!1!)!JBcZ:!)BkRJBJZsRJcRRcRcscRRssRJscc:B1sZ::JJRR:1c1B!RJBss!ZBs{)B1BB)11JcsRRBJBRkJBccJk:sBkJ{JRRJZBRB1J:s֔RsR:::B:BJ1Jss{kksŵ{֥sZZBccJcB:JB!BBRcc1B{޵ks{{sskJ{{εcc1RRcBsZRJZcsRksskcRs{:kBsR1)BZ{{{s{{cJRŜsJ::Jc:ZZZRJJs)R{JkZs::sJBZ{sZsk{ޥZkZksR{歄kkcJBkcBBRkJsZ1)1:!ck{{kcBJJkZ)1)1ZJZkBZZZZRkck{{RB1sZZsk{{JcR1)!1!)RZ1J!RJRkcssJZJJBs{RBZsR!ckkRkJ1Zccc:BRBkBkRs!1B1:sB1:BJ!RBs)):sk)):)k:J:kBJ{RBRcksZB!)Z)!1Bk!:ZccRc{cs{:R!1Bń{ZŽ{s{sŵ{Δ{ksZskZR:::kJ:BckckZR:{s{sskJc{cεJZc{{R{ZJ{kZ1cJZZscBk1BJ{c֭{J:ޥc:)sRΜk:BR)BRJBBsRZsB)!B{sJ{cJkB)))!RZkZkkťބJJJsBJs΄JkkRkBJR:Jk1!):)!)1)JZcZBJZZ1ZR:1JB!1)Jc!ZZR:RsBsJkckksR!ZscRRcsJkB:!)1!!!!)R)sRB:ZskskZJB1s:Rcks1!ZZs:11ccsJkZZBJcJR:B1Jkck)RZsJcBBJ1:))RRR1J)c)!R1:!!B:BkkkJc{{cssZs:!JJ!BB:JZZRZkRccJckB!J:B:cc{kR{Bkck{{{έ{Rk{s{R{ks{skcZRcksZ:BZsckŭRZRk{ŭsk{ckskkcBRJ{kcR:Z{ZsZZBsscJBRkބZc{:JŽcŜkRccBJcR1RRs:1c{{Jk{Z1::))RsscZksZss{kkckskBJB!΄kń{kkR1ZJRBJR!!!)JskR{ZBck)!!)BJRJ){ZZkJcZRcZBBZk:ZZRsccsR)!:!1)!!)RcR))JRkc{{RcJRRJZ1kB{c!):RRRBJRZcZZcJ111R1Zk1!::{B))!1Rk1B))R)!::ZRRRcckRkksBJZ1)c)!!1:BcZc)!skZ{skk:1RBJR{ckRsZ{cJcsk{c֔kkcssŭք{B{ZZRZZJRJssRJZ1BJRkZZk{R:s{εZŵ{kŭZ{BcRcZcZZc{cRsZZk)Rs:kZ{J:B:1!csε!Zk:kńBJsZZZcJ{{RBR{RJBkZZ:ZsZkRcZ1ksck{k{cscJJZcsZsJBc:1:k{ZkBcZBcRZB:))!!!))!!!JZsZZcsRR:!)!)!Jsk{Zskckkk{R!!!!)1!!J1RkZ{k{k{cB)ckkscJRRZc:!BcB1kR:ZZccBZcZJRJJJBRRBJ!1B)J)!:!BBcR!11!)1RB1J)1JJZkRJJcZJRkkB)!))ZkkcR!)1:ZBscZRkccs{JssZJsk{{{{{ŌZ{ksZŌkcZ޵s{BZJ{ZcJZ{ޔRRks{c{c{sŔŌkRk1ckŵJ{{RRRccֽc{R{BJZk{BB!:B!Js{:kc:Rs:J޽{kcJZskcB)kJZkR:{1R:csZR)Rsc{RcRkk{sssk{ZskJ1ZJ1ŭZcBBJJJcRJR:!!:!1!BZssR1:cJ11!11!1RB:cR{kskJc)!k!!!)11!ckZJc1!{{sJ{cs{Zc!1ksRkRcJJ:RRsZZ)cR{sRsBZZ:JZBB!)k{k!)J!!)RB:)Z:!!J)!B)B1RckRBJ1JJ)ckcBscB1kB)J:RBR{RcRcscs{ckskŌksΥk{ŽskssRss{sΜs{ZRRZcZRZBkRksZ{ckccBZJcZքcksR):kRJ)Rk{Z:kc{Μssk{!J11!!B11{RRR浭{!:RJkcZRB{sZ:BccZZcRBR)1)1BZZJskZkcBZkkk:RքŌkJkZcJBZcJ)))1!!BJcccR:1:1BRBJcZJ{scZZR{sR!!)1kZZ1:!!cJB:ZkkRcs{)cs{sJ{!!1JZ)cBcRJ:RJ:RJcZsB)!BsZ:)!!cR!!!!11)1!!k))!B))!:ZZscJRBB!!BB!)1JcJsRB!JkB1):BkkRBBRBkkkc{Rŭs޵֭{skΔZR{{R{ssńsksc{s{k{Ό{scRZkŭ:ޭJZsR)R)kkckkŵsc֜cks{Z::B!:֥JkνcZRcεZJJZZ1R:Bsc11:k{ŔZBkJ:JZ1:1RBsk{ck{scskkRJcRkccsR{s浵{kRkRJBZZBRcJJ!:!!1B1ccc){RZRkJsk!1{kZcsks:!))!:)JR:Z)1)BkJ{ksksJBskkc:Z:kRc)BJ)JcJZZRJRZ{RB!ZkZRJ1B{skBJZR:{{c:11!:RJ)J)JZsks{{Rcs))!J!kJ1J:cJckRJ{B:J::Rck!JRJk{scc{朥{Z{sZZRksc{sŜRJkkRZs{ŵscޔތk֌{{Bsńk1ssεJcs1RsZ:BcskZŜBބRkRBB1c{ŵ:J{Bk)BZRŽ{{RckkcJs{sksJJ1kcJsJskRsZccJBkR{sB{{{kccJR)sRZRZskRR省c{sckkޭZksc{BJ:11!1:!JscRZ{RkcRcR1!!)!RZc{scR)R:)!!)11!!Jks:B:!!!B:ckZ{έ{RkZkc:R{JJJscsRB:Zc{!)1ZcRck)1!:{B:s:RZ1:ZZZ1):1)1ZZ{JRcRZJ)cs{{{kJJ))B!cZskkJR1RcBR1)!!JRZZ1J{RB1Rc{ŭ{kŭRscZkksksccZZskJck޵ssνk:ckss֜cJc{ֽZR)cΜcք{cεRBZccR{kBkcJεJJRZZ{s1Zޭ1))JRkŔkZBRkR{{{{s{sZJk:J{JZBcRkccks{Z:JRRR1ZRRJRcc{sRRRsk{νތskscsJZ1))1!:BcRccRJZJJJRR:Bތsks{:!!:!!!1R)1)cR{ZsJJRssZsR{ckRZ!)ZZs{{Rk{sRkB:BZckc:ZkkJsRJs1cBk!BR{11)BJZBkkkZkc:!1JR!!BcZs:Jk:J!BRJ!:!1kkBBJckJJcZ{֥ŜsZZ{cJckJsccs{ŭZ歌{c!1Bs:JssJŔB{sJkcRZsJBZss{R!JB)樂B)!!!kc:Jss{{έZRZsck{Rkk{{kccBZs{{RJkkkZRs1kRZ{JR{ZZkZc{ksֵ{ޥ{k{{cBB)1JB)sss{ssRBJRZ))!{kskR!!)!))1!:!:k1)1!)JRk{֥sskck޵R){1)!1JRZkZRJ{{{kk!Rc{Z:RkB1c::BBRRJsJBJRZk{11csJ!!):):BZB)Rk{Z!)!)ZZ):ssZR{Z)JRBBR!!c1!1JJBBZkks{sk{ckssZ{Jk{sZc1Bk{ŵ޵c{sJss{B:{c{Bε)scsks)scZ:JccJccZZccBBccs{JcZ!1c{{sZ:){kkckRksZRccZkk{R1!1BR)Jk{JRkRkZkJkRZ{skss{֭ssŔέkkkZZcssc:!BBJJBksJBkZ:kR:Zc{)!!!!!)))!!!)!)!1))!!!JkRRRsJkZ{cBJ{J:kkkss!1:RsJZBJkRJRBZckskZ)1JkR{k:BRRBccB1B1kRs1B{)JB!k:11)!)c)!BRsJ)!k!B!cZZR1::Zscs{JJ)!sJckk{ֽsέkckk{s:cJkZ{ք{{sR{RRcs֜Όs)!):ZsŵJRޥŽέ֔{{ck)JcZ)1Z):B{cRsJ:ZcJcBscRZccν{1Zckk{޽BcBZcRck{cZcsss{sZJc{JcRZ!J1RZcZkJ{R{skZJcR:JckckscckŜ֥{ckkkkkRBc{kkcBJBcBBRckk{RRJBksR!)))J!J1B!!)!:)1!!:BJRckkRRc1kc1kRRckssBRJ:RZkcJBkks))BZ:k{cRcJkkRZs:BJ:!R11)RZscccBs:JJRZ){BZ1J:J:)B!))11)!!BRBRRJJJJ!!BJkkckkZR11BcJ1BB1:1ZB1B{ksε潵΄cJJcZkR:B:{ZZksZ{{:RJJΌ{1:))!:)Rkss::Jޭ޵浜ŵJRBBs)JBZRRRkJ11J!RJJR:kkJ11RcZcZckcs1!)1!:c{ZBJ!BcBBRkZZZJRR:ZskRJZZRsR11ZJZcJ:ZcZksc1)JRRkcZkss{ZBZJkZc{c{cR:JB!csZZ:kkZsRkJRk{R))1!1Z)RcZsss!:)!1)!!:BB:RJs{sscZsRJkZ{Jss{sc{Bsck:JJZ:!cskBk:sJsZZ{!BckBZBZ!:RkkckZ:k!ZJcJRssBZR1:J1R1ZJ))BB)!1))!!!:c{{kskR!!!::kkB1)Rkskc)))JZ{sJ:ZB)!)RBk{sޔ޵ޜ{JBZRB:1ZscBR1:Js)!))!:ZR{JBsssޥέ{ZZ1JRΜZ1:JJ1:BB:!:1ŽZ{csZscsJBBcck֜!BJkkssc:{::)B::1scc:kZ:BRRJRckcJ{kRZBc{ccBk1kcJccޜ{ksccZksZތJ֌k{kskcJZkRZR)BsckRccc1kscskkcRsc)1!!!ckccsZ:!1::R)!!)B))kkckccsZZ:Rk{Z{scc{ksJkZZskccc{RZ)ck11)!JsJkcJcB:RkBZRZ{{k):1ZJJkJkcJB!kJRBJB{ZsBkZ{:)ZBJ11JBB!11{ckcc{c{Z1J{kZ1J1ZsJkBB!1RZR!!:)1:BZ)s{{޵)sZkksBkZRkRsk{Zs:Bc1RBB:J!:sZssε{{Μcޥskc!1Υ:ZZcBB1:)kcJR{kscc:B)Bk{:s:BRBkB֭kJ)B1JckZcccRRcsJ{RZcZs1JBBBJsBJs{sZR{ckkRc1Z{kck{{k{cRcJZZRRkskRkssR)BkJccZZBZ1!!!:ZRscc)1:JJBkR1))cJRkcJRRck{ZskZRkRccckcZ{sJccks{cBcZZkkk)B!1R1:J{ccBZ{s1Z1JcJcJJ)!ZRZBk:)RsBBkBRZ!k{{kZJZ:!1)::Rcks:R)!1R{RJB!BkZ):cJJZBť֭޽sBRRB{1Rk:{cR{){kskR{scJJJ1!))JJkss::Rť{sJ!B{))J!RssZBZ:1BJε!JνބcJ!)sJ!{))!)1ks{{{֭BBRBJ{ŭZ{ks{skscZZJk{s1k{RBB{Z:BB{sc{{ckZRcksZRZ1BJsZsZskR)Bkc:!!!!!!:1))!JJJ1JJkcJZc)1k{s11BZJZsZ{kkZssR!RRZJZ{kcZRkkJ{JsZBZs΄{kcZ:Jscc))cRZ!B:J:ZJZ{sJJRc{ck{Js)cRkss{!kJ{kJc1{)sk)1csJRZJ:1!ssZs:kkք))1)Bc{cR1)!!c!ZR:BB)Rss:kJRJBc:Ŝ1sRcZkccs{ZRJcJ1JJ:RR))J1!Z֜BRR:BZs)!JscBB{:Bcέc!kJB:1!R֜cR{cccJ1Zs{{sJJ!1)kŵŌcR!ŔccsZR{kRk{JZ)R:RkŔ֥{scJRBcskcskkR{kZBR1kkZkRZkRZ:JskJBcB):1:!!!!BBZccs:R1)ZZRJ1kkccJJZJRksksckR!RsZRkZJcBBZRJsZRks{csZR{scBZBRJ{J):skBJ)BJsJ:ZcRcssZcsJ!!sBBcksZksRJZJ!c{scsZRcBZ:BZkk{cck{R:1!!ZkZkRkJ{RJ)!!!:R1!J1B:JZksB:)Μ޽ޭޔ{ZBBRZZZkZssskcRBsZRZBZRBRZkJkBJJ:ckcޭZB!c{RΌs1)Bkk{ZRRJ)JZ1c{k:B֭{1:BR1:cZ{{kZk{JRεcJJ1ťkcckksRZRJcsJBB:Jcs{{kB{{:ZJRZccRks極ŌZ{skcskc{ZBk1:Z{Z{ZRsckZ:cs1Jcc1)::!)))ZJcZ{kcsJ:kJZ!B)Z{)c{sZZJkR{sZR!kskZRRZ{c1J{ssBcsk{{s:Jc:JJZ!1ccJJsBcsRkZ111kkcck)BJRZkZ:BkZ:ckk)c{kkBZsR!1B)kc)BRkkskccR11)R!B)ZsscZJ)J)11)BRc{cJJJ!Zs)JZ)RBBRcŔ޵kcsJ:J::RB{:skkJ1)RB){kZ{Z:{Js:!:RksR1B)sΥs1)!ΌkRsZJB:!!k:ZJBťZsks{B)11JcR!Jskk{Rŵ1ZB{skk{Zsk{s{ZRRcBJ:sZZJRc:kJRskBs{Rsc浥{֔kR{cssZc:Bcs{{cZ{k:BJ:!Bk11:)1!1)RcJckRccJRk1!!BcZZZZJBRZcsR!{{{{1{{RRZkRcBJ{ssJJJssRs:cŔ{J:c:c1!c{ŽkcJ):JBZkckkZ11sZBkkJ:J!)1:)):1!1R::!:ZJscsk{s{!Z{Zksskk{J:{1B:Bk{BZkBJ1:kJB{c11kZ:!scRcckskέs{BRJkcskkB1Rֽ::B{1B1{11s{{ZsŔ{kRB:)JJ):{ŔZ{ZŽޔﵔ{c1c޵s{ZJΜk{kRZkZ{1kscRJZZ:RJZsckJkJR{kk{ν{Rs{sk{B{RksZsk{ZkkkB{JZB{kk{kR1BJB1:))1111!)JkBcsR::c!:sBR{RJJkkRBRkR1sc{k{RJcRZJ{kksccs{Bs{1cR:cJֽZR1RRZBssR:cZssJ:kckZ!):!!))1!B1J1:kkcsc11BskccZksRkcss)))11kRJccBc{νkJ:RkcZkB!:1c:c1:)RkBBZkcތ{{{νΥs!!)Jk{kZZ!1{BֵZB!J{Bﵽ:ZcJZ:1!Bsc{sεZ{R!c!)ޥk{kc{c1:B:BsZZJJRRZ!ZZsc{skkcskkZ{s{Ō{{kZkRsR:cBs{k{sJkB!J1!J!B)11!kcRckBBZ1JZ1BBRs)1cZsJR111{cZZJk{1JkRB{1ZkcssR{R{ZRR{{kks)kZRk1kks1JcJksJZcZBRkckR1)1!R!:JRJ){cssks:!:{{cJkscZB:ZZ1)1:Rcc!ZckkJR{ֵkBZń{Z11:B1RJZc:ZcR1έcZJ11:﵄ZkֽJk1JcJ{ޥcŵ֜{sRΌJZ{ތkRRkRBZscR{cRs{ZB){Rs޽kRcZksZsJB:1:RZRBJB:RJ1)kskRskΜsckkZBZ:skssBkRZZcZJcJk{RZBZZc!B)J)!!J)!)!ZZRZcscJcJ!!1!{sZ!:Jkckcssc1:1kk{ZZ{J{s{::{{sJZsscJ:cJZcZZcJ)k{Jk1Jc!)!))!Jc1))!!)!B:1kBJRc1s{sscc!1JsscskRBB!BBkscBRZB!:ZkRRcs:֌Rk1:kJ1R:1JJ)ZRBcB1浵RsZkccťB!)RR޽csֵޔތk!)sJޔέZ:Z1cRcskŭZZZ:ޜR{JccZZkssZsR{kkZcťŔ{{scŜscZRsss{ccJJ1B{k{skΔcs{{BkZk{ńkZ{ZZkkckRkJBcsRcRsk)BRJRR{)JB:)!)1kJcRRJ1J::)J{kkZ)ckk{!Z{{Z{ccR1!ss{:cs{{ssRcńk{sZ))1):1)!RJ!:)!BB)B))RRBcRJ1:BJ)!!1kZB!cksss{{ZZJZ:){cckk{BkR{ZRkcJ)!))Zc)RJ:{{{ŭ{{ckBcc))RR!c1!JRBJsRBBR1JJc{楄֌:))B֔BB潔֔Ό1!:ΌcBJޭZεJJkcB)1!֭)Z{sνJRŔcR޵sR11Jck1skcsRRRZcks{cRssέ1B1:{s)Jcs{֥{ZcZֽέkZ{cRcRckRsRZRRBJcZccscBRJ)JBBB1:!:B!ZkscsZZkRRJR!1Bc{cs{Rksk{{1ckkJkkcBBB{csZ1BcscsckJkZck!!1:J:R)1)!!!B!))1!ZZRk)!!{ZJZZskksk{Jc1!Bk{skZksZk{Bss{1k):B!!BZs:kcs1J:s)11RBZc1BB1:Zk)RR:1cssks{ssεc:1:{΄ֵ֥sŭB:1{sJ{k{ބ:cs{kZsRsc{{R{c{sks歌Όs{RB1B{ksBsŔkZsJ!BZJZB)11cssccskkk1{{֭sJZJcZ֜ZksZk{Rc{{kRksZJc{skRcckR::BZRR!JBRkJkcZk{ccccZJB)ZZkZs!Zkkk{kkcR!:1JkBs{1Rkk{:RJsk{JsBRJkk{ck{s!!))J:c)B)1!:!!)1BBB)1JZZJRB:Z!)RB:R!!JJc1scBsZ!:{Rkcs{sccs{kcR!B)!Z!)B!1R)J{1:kRZBRZRR{))B1Jc{J)k:1c:1Zk1Z::1scRRkŭcJŜ޵s{޵cssBZ֥ssR)ckckc!Rֵ{kssRcΜsJc{:cs1s:֔{k){1:RcZ1Bk{JJRkkBsZkc:{kŜskk{֔c{kkZBZk{csckZkZ{{c{BJcZcB:RRc{ssk{{kckcck!R:ks{skJs{Z{sJB:{ZcZRcss)!ZRcZkcs))kZs{cc{ZJZJss)!!B)BJB!B::!)11!1!!:BJ:))))ssZkkRc:!!:RZ!)1BR:kk{ccZZ{ksRR):!Z)BsBBR!!1RJsRcR)kB:)BB1Z:k1::J:B)B1B{sss{ŵ{{c{֜ޜ:νB:1cބ浌ŽZsֵc)޵c::քJZŔBε֥kssc{cc֥kskZZ{kZ1sRccc{ckcZcRksssBs{Zsε{Ŕcք{{cssRkcRJss֌kkBcRkRZkJJ1R{BZBRZRcs{kJkcsR)Jkcsc{1{ZJ!{kkRkcRJZBRZcBkkRssB{sksccRscJ{k11!!!!!!!!:Jk1!ZR1B111!!:1)Jc1BBZ1B!JkcsJ!ccckJB!skcBZcssc)B1!1)!:B!!!Z{kR!!BRkk:ZckﵵR:BBJZcJkcZZcJB:sJkΥsckΜ֥֭ޔ1B挔Rsޥs{kBBB{sֽ挭{1!ZZBscsŜs֔{sc{ֽֽŜΥcskZŔsZ{cJJR{sJZckZŜRJZ{s{cs{sRkcBJZRs{ksccskΥ{s{kk{sccskk:1kcsBBRJZsk{c{kcJBkck{k{{sΌ:Rsc{RRZBBZkkBkB:Zc)Z{ZkkcR{Z{RR!!)!1!B:R:Jc!:1B)!1R!B)Bss!cJBB!!)!)JJR)B11):1RBRB1R)1cs{k:R1!)!)kZkccRRJBc):!1!)JJRJRZ{B1!)!JZZkkBJJkB:1sJBs{B{cΜ{csssk{ŔssΌޜscJ{֌ZRR:R:R))cRRֽֽJckcc1ń{Z{s{cBs{֔ńs{{cs֭:R{Ž{RJ:cRB{JBc{J{kkR)ks)cs{ZZ{{RcZ{cc{s{sZZZZsZBZsc{cZ{Bccs{{cRR{c{c)!{J{Z{:R{{JkZZZkJc{ccZcZ)!BBB:R!)JZJ1))1):J1:Z!JkB!R!:RZskJ1B!:)):J!1::B1kscJZcJscBBB!!k1:BB:!1ZckZsccZB:J1)B{)!J)B)Bk:s{{::!:):Z1c:sZB1:B)kJ::{Ō)sťscksތť:!Rcń))B1Ŕ{1:BZΥcޭ{ZkkkssΥ1JZ浵Υs)ZŔ{sZsJZ{ŌsBέZJcZ1:BBkRRRRsRkkcskcBŌ!Bsޜ{ckskZsc{{{{Bscsss{cskZc{s{{ssccc{s:1!:B)Bs1sRkRsRsk{c{Rc{Zkks{kk:::sB!)cZZsBk:):!RJ)))Rk!):B)!1!:J))c::1cZkRR!):RJ)!)1:):RZRR!!s{skRZkJB!:)1R!!!)Zk1BJksc1)JcJ1)J1JJZkJ1c:!:Rssk:Jsc:BJBRkJB!s1{k֭ZR{kss{kk{BR޽k):R:)sZkZ޽浜Jk1sJkB)Bk{k1)!11)R{kJkZZ:){B:Rs:)Z1JJk{ckZcR{ccJZRcZ:JR{sccJcRRkckkk{{cJ{RkskcsRcs{!!)ZZcRckJJ1RRsc)RJR))))!))1BcsZBR{ZJ{skcsc{Z{{ZkcZkc)))!BcccB!!:!::B1c)!J:kB1!!Js:B:1sBZJR{::)B):1B1ssZZ!!c{sksJJJ!!)!c!){RZJBc1)RJ:))RJ!JR1ZkJ{{)!{c!Zc{1ksRJkBc1έJ{քZ{{ckkRsεŜ{JsΜ{RΔ޽)!!!Ŝތsss:sZkZsZkckskksJRŜZJB1!!11!Jk11)JZBRBBΔc)::ZBcZ{JsBRZ:scssBsscs{ŵ֜kZZBR{s{{ZcksZ{s{BRBZZsBZ!!)!1!!:JRJB1c))1BB:J1)B!!)!!R:J::)1Rk)JBk{kBcJR1)RR))1k{cc)!1J1)c1!:Bc!)!cZ!!R!):B!{kkZkJ!JBsRcsR:))):޽sJRsZkc{ssR!:JJ!JZBRsR)!JZ:!)1)RBR!1!ZkB)ckc:!!BR{JJs1!kkkBJ)B{k{k{skkssckckZRR{Rc{Rֽ{Z1cפּֽscRsZccB{s{քsŭZ1BJ{scsZ1JcRJRJksZ!)J:BsJ)ZsJkRRJcs{c1!:BsksJBJε):sks{{kքkcscRs!B{JJR)!!!1)!!):!11)11{1:JJc11!))!1!!!!!c:!!1)1)!!!!!BBZcs:RBJ)!R1R:))1B::BB!BB1!:1B:1!):JRBkZ!!!ZkJZkZRcRc:!cRsŌńkZ):cc{kcR!1B{{J))1B:1!)1ZZ)1::JJBB)sc:J1Z:1B11kckc!)s{Jk{Zcc:ssZkkskRkZRJ1{c֜ΜZ)ŭk1)ksŽBR{:{R{RksZJZֵZkskk{Z:B1{{ZkckRRk{ZcJ:):)JBR{kZB!:k)Zck{{B!):1J愜ZkRBscZkZֽsέssc愭{RBsJckJ1ZsRkB::!!!))!:))!!RBJsBRB!):!!!1!:!!!!!!!:!!!!!))!B111:{:B!!JB)ZJBBk:RB1!B1JJ)!11c!)!1sJBZ)kZJ:RsZ:B))JZ1cννZkkJ{scZRkJk!RRJ1:!B!1)1):R1!)::11)!BBc1BB11!111Rss{ck:{cssss{Rks{kJsk{RRZZJJRJcsZcRŜk{ޭ{R!R{ŜJJ޽޵ֵZJkkckJZŜZc֥{ck1Jsֵck{skRRsέŌs{{JJcBcJskZc:Z{cccs{ck1!!:kJ{εk{{cckބk{ssRZscs1R)Z1JBBBB)B)!:!B11)!)Jc)1k11kJB)1!)!J:))c!!!J!c1:s)!!!RBB!):!Z:!11BBZRk):)J11):J{Jc:JkZJZ:JB!!)1)!11)ck!kk{ss{Zc1!J:1!B))11BB:JB)!)!1:))ZBR!::!)1::):JsB:::kJBJR{kcks{{{skRkssZkc:RkZcccs{ΌkJ:B!)c֥{֥R{sRcs{s޽scksskk{sccss{kckJJkkRR))BR)RkJZR:sB1:Zcsck{Όk!1Zk{RZRZkJkΌ{ss{cssZ1BZ)JJJ111BBB)!JR)!::)!R)){Zs:)cBZB:!!!!!!!J)!!!)sc:!!)))!1B:!)!J:J!))B::BZR!:JJ)B)!!BBJJ11:ZBB)!!!:RJBBkB)JRk!)!):{s:1sJJJcck{kkBBR!:kRRBRck1!):!!!)1!JZ:!Zk!1!1:)1)JB:B11J:JZkZJkZsZZRZsskε{{kZs{:RŔZޔJ)))1έŽJskRBBZsc:sRcsΜssJΥ{{εsJcc֜c{c{Z:!:J:))Rc{ccZR1J!JR):BB1:BcJJ)1{ZRJ:Rs{kΌk{sskZZJJk)B!!J1RkJ:JB!BR1)!:BB:c!!ZBRRB1:RJ)1)!)!J:J:!)!)!!!JJ):scsJ1!)RZ:!!)JJ)J)1!RJ)!:1)11!BJ!!)1:JsRBRJBB:JB!B:)!!!!){Z)ss1B)::cs!RRZJ1:RckcZ1!!!B)1Zc!)c:R)!))1!B1!B)RJJBk1{s1{{ckRkZcscksssRޥRZsZZZcŜs楜νsJ:11Bsk֔k::ŵΔֵ!JsνsΥZcR:RkkRZkZks޵JckZRJJJ:)sk{{ZBJc)1RZR)B1RB1BRJJťsŌccZcZsֵsRc{s{{RJ)BBB)BJJJ!1BZ1J:RB!!BBBJ!:cRJ1JcR1RRJ)1)!)1:!))1BZ!1B!11!!R)B!Zks{{BBcs!!JJ1)B))!:11)!!1!):B1)J)B!!1:Jk:JZ:Z::B:BRJZ!RBJsRcZ!1cZckBBB1JJ1!!B1R!J1)B!1Zkk!))B)cs!)::1):1)BB1sRJBBZZZ)11{kZR:ks{{{{֔cs諒{kkss{kΔތZ11!skŌ:RZcRތ{BsŵR{{Όsc:B)RBRkskk{ńŭ{ck1):1kBZJcccZBsJ!J:Js)R!RJRJ:cޥkRcs{JZ{ksZcRssR)s)::ZR:1:JJ)JBBJ1B1BB:RB)RZBJsckc1:1))!)11)J1:R!:!J!B1:!:!!1)::!JsJ!J)c:)B{))11B!!1:1BZ!1)!!!:!)BZ:BJ)BJ1BBZcB)J:BZJ:{kBZBcs{ccskB:B))B!)):!BBB!B:)ckkJ)):))B޽BJ)!)JJ:11)BBJ{cZBks){c:sZs{k{{{{{sk{cRskJcεR{s֭ńkJ{R:B1s޵k::kZ{cs{Z{浥BRZZckRR{kέΜ:1!!cBZkRccRs{c1JRcB:):J:kJccsZscJŜ{RR!1cs{{c{s{ŵkcc{Z){ccssBRRRJRck))R:1BJR)11:Z)J:cZJRJ:c:ckR:111)!)!))JJB)!)!!:J)!1R:J!!!{BJ))1!1B1)!1BZB:RRBZ:!))!!)))J1)!B1!J!!:kZBJ))Z1{{{{ZRcs{cB1!!R:{))R)!!ZB:)Rskks:!!!BJBZ1:BsB)11!)1::11RB)B1Zc{BB1kkRsRkkks{ksZ{{BZJB:JRΌk{kRc{sŔŜcsΌ֭ZBkkZZΌcֵk{c{s{skk֥֭{{kk11:kk{ckJ:cJJ:kZ1))B{kJc{RcRs΄ZZBBJZ1Z{skk{1skkJkRkkc{{JRJJJcRZ1BZ!)ZZZcR))J1cc:)J!1B!kkk)B!B1B1:))!):):1B11!Bc!!!:JRBs!Z))B1!!!)sk!1R:)1!))B1R))!!1BB:JBJ)RcsB)B:kJk{Z!c{sksZRRck{R!!:BsJ:!!)1!ZZRk)1J)!1!)B!1B!1BB!JkkskZkRc{RR11BB)ssR)JRJ{ZsskssccZJ{cZcBJBJkRZcs֔kc{Rs{s޵ŭcss{挄RέRk{Όk֔sccs潭kkcJZ{JR:1::J:RZc{RBskc)RRk:Μ{Zc{cJZsk{ccRZΜsck{Rk{{Bs::JskR!J)B1RJ:Z:Zcckcc:1BkksJR:):)1JR:!B1!)):)1B:!!1BB:11:!)::1J:!BscZ1))!:))Z!1BB1R)J:1:{)c1JR::!:::BZBRcscB:sskk{RJZ!1)BJc!::1ckB!!B111J!J:!!!R:1cZkskk):c)1:ZBkkJZB{RJ)!11R{JBcJ{{ZBZ{skZ{{kRcRZ{cJ1c{Rk:kkkk)愜{c{{ss֜{֌k{{΄B:BJZRsJcskkń)BRZk{νJc{JRcZcRcR1k:J:RckZ1R{ޜJR{kck֔kBkJcJZcsksZBsss{cRsk{:B::JJ)RBJR:RJckRsk{{Rc1Bc1JZJ!!:)kJB!B!1:1J:!1!1:B)!)1!Rc:!)!!:kBZkJ!!1!:))s1)1)c!)11!1:ZcBBJ:JB1)!)1J)Z{{{csss!)1:!RR)!)1JBJB:1!!):Zc{s:B:kkZcsc))))k{cs!!B:BBB1B!BJR):!:BB)cBBRckR:RkkRkBZk:BZRcs֜scJs{Z:!:{sckc{csss޽s{{kΥ֭ksν{JJB:1kν{kccZZc1ŭcJ):cRBssΥεRJ!:BBJcZkJcZs{cc{cBkcZss:ssΥ{ccńc{JRkŜscs{{sk{{{{{s{{sZ:BJJ:1kBJsRkZkJkRsB)kR1:!!1B1Jcccck!!)!))1111!!1:B1!J1Rk)11!:Bs1!JR!J!!)::kRJ!1!B1J11!1R)::!!JRJJJJcZ:R:!:ZZ{cJs:))!!!1Z!:!1)B1)::!1JJZJZss{kRRs{scB1BRBRJ1B:)):):1JcZB!):BRsZ:RZc::cJJ)::::JZ:J){ccZR1:!ZBJsZZks札c{{εΜkkJJ!Ō{1cckŌZcBkŔsJ:ZZRsRs{εޜZ)!R1Z!ccZ{{kR{sJc!:s{c:{s{kZέkZ֥޽Ŝ{kRZsskksRk{k{Zkc{ZJ!B!{RRZ:RksJR{kkRJcRZR:JRscZZ:!B1RZcBkJ!!1B11))!::!!!!)BB!!JBRs1!))){111:Zss:J:!)!!kR1!!)!:1:)JR::)B:J:!JJ)1Zk{{cksB1):{)!:JJ!1J!1)!!)RscRkcck{Zk{ccJ::ssR)):1!!RZkRcZ1J!:c1B::){Jss{sZskkZ1ZB1B:JZcZ{!B1BkZ)cZJcZkc{ΥZsŭ֥kkJZBŔc{JŌs{JkJcsŌ֭scΌZ{kZRRcRZkk{s潜J)!:):RZcZJRJsccRJJkZ{cRﭔZŭRcRkR{{kZkJ1!R!JRZ)1JB:kRkcZkBsZJZs!)Z)Z))!!1RZ{ZJR)c!B!!1)BR!)!1:B1)1kRBc1BJ1!1)ZkZ):B:1B)):1!Jk:BBB)!)J::J!::!R1sc{cJJZZcB)1R)!JB1JJ):)!:)!Z:Z)!1)BRckZckZBsccJB!!!::::1:)ZZZ1Z:){ckZRR){kZ:scJ1ZJJkZRZRB:k{1::JBRcJRkJŵs{Zs{{sskssεńsR1kkZcBZBJkscB1sZJRR1Rk֭Z:)!!1)ssscZ:RcBk1Bskk{Zkk{k{k{k{{{s{cckk::1!c)s1)ZJJ11sRRBcs{Z{J:Jk)RBJJRsZJ:)R)B!):Z)::1)):R1J!!1!!:!B1!)1RBZJJ!):!B!!!:Rk:R)JR))!:J!1J:)!BR!!)B)!)Z1ckZc:!JskRJBZk{R:J)1)!J1111!Z!)!J{RB!BZks)!Z:ss{cc!!1!cR1!)s!css!{Rs1::11k{s{cR{kJsRBBBRZR{R:RRZRsssΔkŽބZk{Z{cs{{kkJRkŜk)BJk֭Όkscc޽J{ssZZcέk{Ŝ֭k!ZBRR:k{JZckckZ{{ք{cZsZcRcZRZZsŵ{ZsRk{{{scskkc1:ZcRR1B!1!1{RckZRcksRZckcBkBRB!1JB:RZ!)!!:111)::1:BRBB:JBRRJkRB11!JB:cB)!!R!!!!!!JZRBJ1):BZ!))B:RBB1!1:1)))B:cBJ)!:R{ckk1Bk{{)!!BBB1c1:Z1!ZBBkksc{Z!::BBJscR)cZJJk:JkcJkB){1JB:1Z1ZJk){s{kcŭsJs:RkcJ!BBRB)Zc{ť֜ssckc:)ZkΔkssZcB:ťέsk:R{νŵŽkc:޵{JcB!s{B1R:R1{kskksZń{kRRZkc{{R1ccc֌kJ{{kks1c{ss{cRBJs{kB1)B):kRkcZ{kcBB))!R1J1BJRJ)RZJJB!1J!J1Z1B!1B)!Z))JRZcsJ{Z1)csJZJ1)J)1BJ1:J)Z1B1111!:B)!J)!!:!Bk)!RRcJ1!ZR!)!)JJ{kcJ1Z1Z!))J:J1!J)!JJcRZZ)!))B))B:!!))1R!RJcJsB):JccB{Zc1ccZ1R1BcJckksBJJc{k::1:RB:RRk{{kcέcc{{Rs{Ŝ΄:RscJ:{ΔJJ:sck{sZ{Όޭtskk{s)RsssB!ZZB{ccJBc{sZZZc{B:{{ŭŔk{kssckRJR{ksZ:cBk{{ZcBkJR1ckkckRks1ZccZJ!!1k1BB:B:JBBJ:B:::JB!)c1!1:J:11)JcZRkBBZks:B)J:1R:1:11)!!:!:!!!B!B1B!!!B)!)JZcֽscRc{kskk)!:!BB1!)!Js!1JRRZJkk!c!{{cB!JZ)!!1BJ:)k::R:ckB1)JsJ{JcRJRŽ{sBscB:ZZc:1JZJZJ:JRBc΄cΜ֭έεcs挭RJ1:J:ޥ{:1)RZ)RRJccccssŽ֥ŵskZJk{kRsZJ:)sBR:kkR:Z{RZsRckkk1kΥkksޥ֔csBcZB{kckc{kJ{JRZcsck{{cZZskB1!)BJRR11R1RR!1B:1R:)B:RJ1JJRc{Rc1RB)1!J)B!Rs{Zs1:::1!J!)!:))1Z!!))!BB)1:)!BJBJskJBR:BJ!JZ)BJRJJ11!1B:ccB:sc1cks{1J:Rk!!1!)1::::1J1BJk)1ZZs:RZcJBRB!RcZZscc{RkZ)cZc:)BBJZJJcJB{kcZkks潔{{ZssJksތsRJs):BRZcRsZZJ:ZkνΜ1BB)J޵1!RZsZcRssscs{RR:ZsRkkֵŵsk{ksssckk{cZcsZkR:JR{kJBksBRk11)B:11)1J1BBRkZ!!!)c:ZkkB:ZB!:JkkRBJ:BJ)1!J{sc!!!):!:):B1!B1)B!R!!11!)):)!)!!B1ZcR:)JJsccRsZRBRBcks:1J)!1{B!c)!!1ZJJZZkZkB)R!1Bk1:!R):1csc:!B!)!Z!!Z!BsJkkscss{JsBcksRkcckRZ1:sZcR)ZBJ1RkR:ssk{kZccZ{ބsZ{sRR{ZZJ1JJޔ))R!!B)Rk:Jsc)B֌{{֔{{{Zs{ks{sJcsskkRsBBk{sRcB{BŌcJsΌskkss{k{{kkkscs{{{c{!RJk{cRcRJc:)J:RR1:!)1:{)JZJ):kJB)R:BB:Z:RBZRB:B)!1!:Z:)1Z!!1)!:)))!))!!)1!)!)1!)!!B:1)BZJRccBB1RJZBZkR1cc{k{{{k::1!))R!JJ1)RksJkJ{sk{JZ1)!!ck:!1)c!)!!B!Z1BksJBRBk:BkJk:ZBccJBJJBRJBZcBZcRcJ:B11BBJkscBskscscZsZR޵s)1:JsνZBs֭:)!!c:Js!cZJc{{ŭŔ!1ZsBc1:k!:ssckc{{ZkZ{{c{ckBZ{ZssZZBcRJcs{1BZZs{csR:B)BkckR:RkkkJJZk):J::!)Rsc1ZJ)1RB:!:11:sBZB)!!!1!1J!:B!RZJJ!::BB::!:1!!11:!!:11:1!ZJcR{R{RZR:kscRJRccRkkkcc)!1cB!!1!)JJckRcJZBZc:scsZ::B)Z:)!BZ)!RJJR:!R!c!:)!R)!ZJ1JkskRRZ{R{ZJZJRBZcBZJZRJkcksRZJB:朽{ccνBR{ŽssRcRRJ{1JJBZkksZ:kcZ֥ŔB)1!!:J11sRs:{{RRsJsscJkRkc{ZZkksZքŌ{ZssssR{kRccZRcZsc{JJB!RccZkR1JZkRJ1!RRB)RR:1!:ksBk::R::Bcs1!!!BJR!:B{RB!):!:B1::))J1)1!!:J1):1)kcsJZZ11BZRkkck{{BRksc1!B!)!1)::BJ:cckJcZRcJkkc!BBB)R:J1)JZ{B!)B))JkJR!J1ZJ!RJ:!J{RRskޜs1JRB{ck{cB){JZZcRBRsB)k1Z1BB{Rc:Z΄sskέ޽Ō:{ޥŽ{RZJ΄B1RkތBRZs))έJk1ssŜ{R)11!R{Jcc:)s{s:ck{B{csc{1J{cskRJJŌZ:kkcRZccss{sckRcsZc11Bs{sZskZRBBJ1JJBRZskRZJ{k{kZ:)Jk{BsB1R1Jc:)11JJ!BJB!1)!B)!::1)B:!1!:!:!J)!!BJJcc:B{ks{ZR:)!BsZRcc1Z!:JB:!!):ZZc{Jc:RBRBsskkJZZcZB!11!)J!skkc!)cJ))B!:!Z1)ccskksRks:{:kZ:RBZ1JRcR!Bccc{kskkZ!J{::)R{1BsZcZs޽Z{k޵ֵ:BZRR))cŜk΄1Zť{!k{cZ:BBZť{cs{{scJskc{ZkJkZsJ{c{{֭{kZ{skcc{RkBJ{{BskR:sJZ1csRZcBBZ!csZZ:J{:ZB:ZZRR!!!RBBRRkc)1!!1BZ))!!Z{1R)!1ZJBc)!!!!BcJ:c1RJ)):1:c1!J1BRJkkkJskcRRJBΔR1J1)c!!!!!1!:JR{k:!RkZZBJJB)!1)B!!))RR{{1:BBk{sB{kkkB!RZBZR{sksJkZ:R:1::JRB:))1RBsRsJR{RRc1k1):!){BcJcBεZŭZBBcΔss{1JB{kŌccRRZέJcRk{RsRcks1J:s{֜J{{skBRkk{{s{cZsJ޵kkJZsRcJZksBJBkc:JBB1!kcc1)1Z{ckkJRZ:)1{BR1RkZc)!1!B:!!!Z:R)RRJcJBZJJ)!!)!B:JRZcRBJJBJ:Z!!!JZJ:BBk{{ńJc{RsR1!)111!!!)1::)B:c)c!!1JBcZ:1RRRRRZ1!:J!)1)Bkk攭JkRcsc{J:{s{{Ŕ:k1cRskZc!::ccRJcB:!1ZcZsZkZcR1)JZB1BR1kkZcBc{Jޔ:Bcť愥)BB1JJRckc{k{ks{s{֭֜c!1{:s{Jcc{RJ11B1k{kk{{BJkcBZccc{kBRkc{{{{scR{cZsckRs{{kZkkRZckcRRk{sZR1scRkZ)ksscZJs:k1)JBRccZJ1{Zk!!))!!BZZ:cZ::B:JJ1RR1ZsJB!!ZZRBBZJZkZ):JJBR:ZZ)!!!!!1::RZ)cŽks{s!!11!!!!cJB:csJ!1:!B:JJkB:J:JBBZ)RB1!!:Rc)!k11111{:c{c朥s{JZ{{{k:)JRB11Bs)1RJcZZZBsZJ)!)1:!JsZRRRs{BRkJJcνΥ֭JJZΥ֜{cZcބνńZ{ŭ{{sŽs:ޜ{c{JRB)!:cޥc:cZ{ZkcRk{BB{ZZ{:RBcc{Jk{νskcssRk{ZkZRRZZcc{RcZB1JBcc:JBRksRkJ1ZZcJZk:RBsB!11)):)!)c1JBsRBBJ!JBBB)BJ1J:R:)RR1:1:1!!!JRBJJZBJk)RZ))JkBJJ:11!)1)!::1Zŭksc{c!))!)J)1)B1)!!B:RsRcB)):))1RB1kR:cB)1!cRkc1)s:J1ZR:)J!!B)!Bs{ZJ:JBBRck!skZRBΜs)B:)kBk:){RJ:cRkZRZk1!:J!BJ)ZsBJJJZBZ!cZJcsRRcckŽRksνkֵŽ札ތΔcRsc{ńcscֽR:1:1::Z:RZ{{kskc֜skkR)ssRcsRֵRZZcsscsck{JRRRkkRZZRRZ{c{1ssZcc))JkcccR:scR!JskRk!1:!1:J))!1kkJBcRZ{1R:BBsRcB:)RJB::Z:1RB!R!JRB::)1))BcRR:J!ZR:{ZR):{Z{JJ!!!1:!RksBRBZJZBskc{JBk1JB1!:):!1!R)B:)JRBRkZJ::ZZckscJR)!))sc!Zs{sc:J)1s)BR!!!1J{ZkZcJZJ1)1:ssss:1csJkcBZRRJJ:1:)sRskkkRZBs{s)Js:)RcJcsR{1cRJc:楄JZJJJZ{ε{{ss֥ks{:ZZkkZkJZ!1)!B1cscRkRRR)k{Δ{{RZs{֌kJcR{R{{ŵBckRcsZc{JsRkJZsZskckck)!):1Bk{sB11))ZJcBJ!R!{JZ:)RRZsBBR:B::1JBBJcJRR1BJJJJ:1R!JB1:k::11)1BJZJ1:1cJcBc11cRsk!!1JkJR!!!:k:sk1sB!1B)JBc{cJ!ZJ!!))!!!1)BB:!Rs:kZ:ccZJkcksk:)Z11Z1s!!:{Rs)J):΄քZcZ!J:sccZckJZZJRk{Zk)kZckZBRRZRscJkR{RZB))BR:ZJBZ:R)!sc!kZ{JRZcscZck{ssc{Υ{Rcޥ{ccńcJŜRZ)!!!!JcBksc)1Js{kkscsc{cskZs{{ބ{{RB)ckkckRscsc{{{{sksZckcZB:)1RRcZBc:Bs{)!!:Jkk)1B!)!!1:11Zkc!1JB1JkJJBJRJ)1JBR)R!ZRJBcZZR)R1!:::)))J1)!:ZZk1!BBR:cZ1s{J::)cc)!)cZZk{ޔcRkR!)))1::!)!))!1JZkckZ:Js{:s{ccZRRBsZ!)Zs:::1Rsk!RJ)kRJk{BkB1!!1Bs{ZsR:ccRB!JRkZ{skskB{k{ZZkcccZkZks1!:):kkB!:1:{k::skc֭R:cs{sksskZcﭔΜ{c{{{޵έ{RkRZ1RZ{BRRcBJ))!s{:{c!{kJc朔kJk{sńcsk{csskR)sssccZkRc{{cZZccsRZsZk:11B11R!!::1:css{::1ccZZJ!!11B1:1RR)!Z{c)JZ!JRcBR:ZBZ1cZBR:ZRBZsk1BJB1k:1):B))1JJ1:R)BBR:cRZsZ!::JJBBR:!!!:Bk{R1sR)!Z):)B):!)JZ)k{Z:s))scBJR11:1!1c!1RBJs1!BZ!):{RsccB!)!!BJ{kcskZR:R1RR::BkcRZZkcRs{csscksR!JB!1BZJZJ11:R!cZJkc{Rskss{sc:Zkﭔ{RkΥťJccRsZk޽{ZkB:kcRkRJcJRkJBsBJkcR{c)sޥk{RZckcs{skkck{Z:ŔkkccR)1):)!1kcBZJ::J1R!:B)!)R)1sks{c1{J11:!!J!!cBcsc1BZc)!kBB1ZRBZs{s:ckJs{c1RksBkJcJBZ!))!Z:c)B:1RJBBZR1:BcB:J)JJcJJZkZ!R:cc{J!1ZcBZ!):JB:ZccskBB:BccZ)k1:!JRB!Bs:)!):!!):R:cZJJ!sc{Rs{kZ))11cZkBBJcZ)JRRJΌZk1))s)!Jc:1!cR!cBRRB{Z{sc{c{{kJZJJssJcťŽŜ{{B:{Zc){kB)scksRBRcskZksRsZB{{ckZskZZ{sk{{{sBJ{{Jcck{Z{kkBB1JJB1:kJcB:RRR1J)){B)c1!B!c:BZBkcRkkJZ:!1:):!:)RJBJcRRRRccBcRcB{ޜc{ZZ{{sskc)1RR1):R11)B:1BR1BRRBB11!RBRR)RBJskJ)!RcZZ{J1R11!kk1!!B)ZZZJJJ:R:cJB)JcJcBkkk1!Rs)!!1::c!s::kJk:BBkRZkscscR:BRcscB):ks{Z{ZZ1!k1!BBR)!c!:1!:c{s1JBcckkkssk{cckZcBJZRR)ckŌk{cs֜s{kJRZ)JR{csJZsBs{kckkssZJ:cskkccsZZk{ccZkZsskkZZsss{JZkZc{:ks{s111B:RR:J:R:RJ:BJ1:RJ:BB!J)1ZZJZJ1{B:sB!k1J:BJ1!!!!!JJBZBBRJRBZ{BcRkc1cZcBcs:::R)k)J1JBJZJ:RBJ)B:BJcZJRJJ:kcBZ!)ZJ)R1!!1c))!!:BRRZRR!1)::BRRRR1{RZ:RJRZ!)1kΜ)1!B!JJJ:!J1J:1:RZRJ1)Jks{ΥkcJskcc!11ZZ{Zc!1){kR)B:s)::B:!)1:B1JRcBZZcBsssscckcZJRRBBZZsZ{{Ŝss{sBBZJ{c{ΔJZZ{R{s)BkkJ1{ŜZJcRZR{{{cc1RJZ{ZcRRRZ{kZ1Bs{scRJ{ckc{s{!1s))1R11ZJJ:J:BJBJBJk!!1)!!BZ1!JcJ!!J!B!)!!!BR:ZkRRR{ZckBBBZRkJ{RsZs{{{ks::JBJsB:B1:1)1Bc!)):!cscR)JBRJJR!!BR!)11scR1!11!B1BZRZcJJZJBR):ckZ:JBZZJZ:J!:1RRckJ!c:)ZJ1kRJc{ZkZBRBZcJk{kZRckRJsZRks{RťkkZBŌ)B1R:s:ZB:!B:{RJcscJ)RRRJRB{kRJZBkŵŵkń{ZRJJZsZkŔ{c1ZRkJR1ssZZŜsRcckZRRkc1kŌŌkRR1cJJcckR{BRkRkcZ{{skRksJ:csZk{{!!J1B)cJR:B:))1JZJ)RR{Z11::)1:)!cckJ1J!JBJ1)):1ZJc:c:BRcRJRJR{Jskkc{c)ZJ:ZcR)RJBB:!1:)!cck{JBJB!::1!)R!)))1BBZRkccRJJ::BZ1sc:{)c)Z1)cŭ:!)1!!1ssssJR{ksZscJRZZ:::JRkŌ{J:c{{)B{sRRRJcJRJ1B:)Jc1R11!B!::1Zk1BsJ{RsB)ksRZRssc{{{sskcc1B{B)J!)JJcRcJBscJkJc޽k:JZ{k1{{{cZ:cZcBRsc֔cZc{Zk{{sss{scc:ZZZRscccΔskRBR1:)!JBB):)JZ{Z):)):ZRR:))J11)!!)!!::J)1::JRJJRZRJZJBRRZZsJkcZc1Bs)s{c)!:Jk{R:BJZR!kZc1:ccJ1JBBB:Z{{cB:B))B:RkZZBZJkZ{ccBBcR{Z!Jkε!:Zc!:J)RcŜBZJ{sksZZZksRZ11RBZ1:{s{cR:)BJsc{RJRBcBZB:!:!)ck!B1:!:)JRBZ:B{{ZRZkRZR{֭scJZcs::cJ)JRcRk:B1JBcRksskBR{cJZJB:s{kZZ!{{sJJJ{ZޭskBsŜsckZRZZsJJ֔sRcssJ{ŌZsssZZ):B)!J)R:::J:B1JBsk):J!)1!!!))!ZcscBRBB)!))JJ{cBckccJkZBRZ!J)ckBR:1RsssRks!!):)1J{kkkR!1Z!))k:kscssZRJRRZZRZ)cJ!cskk1Zޥc:JZR޽JkckRs1B11:J:11)ccsBZBcZRRBZRZR))!kR:cR::::B)Jc:RRskJ1BJZksBJJRkŭޜޜJJZkRcBRZ1ZBBsBRZZk{ZR{{J:BRJ{kckRsZZRkRJ::sεJJΌZckRBcsBBJs{s:Rń{:Jss:ckBZ)!1Z)J1:BR!kBcBJ)k1)B1kRccJZRZR:!!B)))ZkRccJckZJRsckBBk:1!)1):!!1):1JRZJZ!RkskR!R!!{BRR1JB)cZB{kR!!):!):B):!!!sZZ!ksZBZ:RBBsskZRBR:cJZkJJ{ks!1::JccZBJ:BRR:!!B:11ZB11!11)BBZ)BRc:BZ)JR:{JJńJkcJck攜{{ZZ{Zk:JkJJkBJJRsŽZZZZ:Z)s{{sskkֽscZBc)RR1cŭ{sskZ{sJ{J1:{ތ{R:Rscc{c{ZBsZccRkR111):!11!!:1k111B:Zk1:kkZRJJ1Z1csc1kJJRB!JsJss1BRkZskckZJk!!!!!1)J!)1!1B1R1!1JJkc)BBRZ!!)Jsﵥkk1)!!Z!JscckBZJRRZsZkcJ!1c!R!1R!R:k{:R):c1sccscRBc:::)))1BJ11)k{RssJRJ:RkBZ:JRBJ{s1BJ))cR)11:!:ZR:JZRRcJJRRJsJkc{ckkkkcZksRB):B:R:BRZkcBBBB{ZssΥν::RBk:RBBBRBck{ΜsZcZ{Z1c֥{{ksRJk{sskZcRc޵)::BJ1R!!J!!)R1)!))))!:s{JRRZ:JJJ:cBRRZBZ!)Bs!!sskk{)ZZsssckBc:)!!JRcZsJRZJ1:sBBsBZJRJ:ZZZB:!)csc愄1)B)11JkB)cc::!!Z{ckc)!!!J1!!1:1!)ΥcΜ{sޭskZccJRZkBJBJZc1B11Z֜c1B1JBRZcJ::RJRs!):!1!1Z:1!:1)!Bc:R1ZBBRJZccsB{s{sZ:k{愽cR{Z{J:JcJRcs1BRJcs{sBcks{s!c{BBZ{ckZkZkkssckc朵kJs{scRs1ZcJZc))!1!::B{Z1R)!!!Rk{ZZc!Z{ZRBRZ1cBk:{cJ!{BJZ:s{{cc{J{Rks{ssZ)!)))R1!!JRRBkBsJZZ1:sckB!ZcZkR!RJR)BZ{Zs{k1)1:BZJRZskBJkJ1))kskZJ:)1B!))R))scJ)ޔֽ{{ŭkcs{s):c{cZ))JsZks)JkR1R:ZcBcJZBBZ!))!!)BB):)B1!!ZZRRJZZBJJckZc{֭{1ޭcޜss{{RRsk޵1Z)cR{B!)kRR{{kcskRZ):Jc{RZֵs{k{skskc{c{Z޽:Μcc޽kR{RBB{c{ss{R{sZkB)J!::!{skc1::!!:RR:ckkRRc:!JRJRBBZ)sc:Z1:cRZRJskssZ!!!!!)!:JR))c!Jk:Rc1!RsRJBscksB)!)cccck)))J!kkZccJJcZJssBJR!!!)))!1:)cތ:νޜsRsRc!Rk{:{ޭ{cskR)1{c{)!1!::!c:ZcRkZk{JkBJZJJ:JR:111J1)1ZB:!:11JZ:BJJ:RRZcRRŽRRZsR{kR1k{Rscks{kJZ:kB1RZZRBB:{B1Rksk{::B)RRJB)RJJkcc{ΌJRk{{ss{kkkZc{kscsRcZscZBZZccksRBJ!)RR:RsccZRRRRkcJkZJs:JRkBsks:RBJsBRks:Z{Υ:{Z{{kJ!B!!!)R)JBRRR!JZRck1BZkJsJ11B)BRccR1B!!Z!:cRJk)c:::B1::J:J)!!!J1)c)k)!!֥11111B:)!{{ތ))!Jk1R1)!11))1kcZccsZcJBsJ{ckBRcBBR:!11!c:)!1B)JJRBRRBRRRcJcsZs{kscBZssJckRks{Jss:B111JRc{:BkZB1)!)JRJcks֥c{ZkkŜJcZssZJ:攥sskB:kkcJBZJ{kkŭB1!cc:JRc{))J1:s:BRJRRR){1!BBZRRJZkRZRkJ)!Jεkss{B!!1!111BsBZRZJck:!Z)1)!Rkss1R!J)1:J:!)cJRZ1s{JZ{1J!1:!1B!cRBJBJJcޜ!:!:)B!:B!:1::1BBR:):!:!:BJ{c!:B)!ZksZRZJJB1:B)RR))!!:)!1:cZ1Z:JRRcks{cJ{sckcZRRssޥΔ{cB1:sZZ!JZs{ޔRkBkcZBJJkk{{ޔc{cΥ{sZ{ksc{J{skZ{ccks{{sk{k:BZks{k)!Rk)):!csB{ZRZZBB1ZkccZRs)!RZcJZ)!k{ֽ{kZks{csZJ)))B!RZ:JZB)kZR)11!JR)ZZB:R)!BB:!:B1)JsJR)!!:c::)JJZs!B{ZRR:J)!1ZsB!)1)B)JJ)!!R!)!R!!c:BkBkJcJ1B):JBB!!!!!!!)!sJ:J:BsJc:Js{kBR{{kZsZkZkR{kcsŔ{RkZ:kcsscc{BR!JBZRcZcJ{sk{΄kRssk{浜ss)11ssRkcsZR{sk!1:Zscs{BJccBB1BR{kkc{JRJJR1J::JRRcBsBR:cZ:!)kk{{RcJZJskJ:)1):!!!)!!)1)BB!)ZJ!1!)1:JZcB):1Z:sJRkJ!!RR):))1B1:::1:)R::!!ZŜ1ZŌ1:BRc!k)1)J1):)))1Z111)!B:1Z1R1JJJZBRRBJ):11R1J)!))!)!::1BRJBJRskZZBkkε{ZkRsRBkscsccc{kkscJ΄ZZJRBkkJcRBBB1cJ:!cJ!1JRZZ:cZZ{k:cs{ks֌ŔZ{{c:s{R{{{cZ{BkRJRsk{{{sRZsR1!!{kssBcZcZcJB1s{BkZ:)Jksc)Jc{{s)!B1)!)!!)1B)RRR1:!!!)RJk:kZ1):)J11BksJc1)1!!)1!R!s{!!{Z)JJ!)ck)cZc)RcJR)!cc)!))!B!ccR:Z:k{sks1J:1:11)1R:B!))))1)RJk1BsZkkkZccssc{楔RcBBcJsskcRk{ZkRc{ZBcB)1BB{Rkskkk:ZJB:B1ZZc::kkskkk{s{cJ֥kńsss{cR{B{kBks)ckZZZ{cJs:!!1:csk)sJk{cJZRJkckZcBkBB)kk1!ZZ!:))1J)!!B!1)1!!)BRBZc:1))!RZZsB!!1):::!JJJ!1skZZ!1)RZRBRZ1))Bŵν{k:Z)ZR)R!Rc)!1:cR):):1!)!:cB1RJBJ11!1Bk1)cc1B!)!!!!ZJJJBck:JZkZ{cskkε{ΔJJkJJsRssssZJJJZJ1JsZ:cZ1Z{scJs:11c1BsZBZRBR֥ZńssJ{sޥkkksZcs{ν{BcJc{kJ{Z1ssRkZJ)R11:1J{kk:JsRc{JJZkBBc{{{BJJZJssk)!!!!!!!:1BBB)ZZBJ{BZ!:JBJ)!!!B)1)1!!Rc:BJ!!)!ZB!:JR!JRcsZsk:)!1:!1Jń֜kֽkJZkB:1B:B:k1sJZ)1):!:J)c::):c))JcJBcsRBBRJB)B)ZcRJc:c1:)::B)R:JJR1JcR:JRcZkk:cZ{Z{ŭŭ:Z{{RsckRΥZŜ)kRZZ1{s{ťskccJRkޭZJB1:k{JZ:k{ck{քssŔcJRZsRZZRZZkkc{kZcZ!))!11{JJBkRssskZkBJsR:cRssJZ!!!!BBJZc{Z1JcJBB!!1BB:)11J!1!!ZssRB!!:1)ZJcZRJ1!k{cZc1R1!!!s1!ZBJB!!11J:c!)k:k{!ZJR!!{Bs:!!Z:JZcŌJ!sZs1:Z:B)R:R)::11ZB!:1JRJJ:R:RRJBcRZZkkBZc{Zskkcŵŵ朄scRk1J޵{skcZJZkcckZJc1{{{cB):BJJR{{ֵZkkskksZcc{JBBk{B{kťŌZZŌ:kk{skRskcZcRc1ZB)){c{R::cRJsBR:Zs!{kBJkk:RZkZkc1!))!)RRZ:Z::1):k:{)1::)Z:J!1!!1:!:ZsRk{J!1JRBZR{:1))k{sR:R:R1c{sB:JkR)B:)R:)BZ)k)!J)ŵcB)11!)!Bkssc:cZRk!k::B1!:1J1::)1Z:))J::J:RB1RJ!RBZs{ZcJcZkBJZZcc:R浔sJB޽JJZJBcsބkccZBRc{csckc::)1)!11Z{BZJc{skZZkZc֥scZ΄Zc֔skk{scck1)skc{sZJRsckB1!1!ZkcccBJZBsRRRBckZRZ11)J1:JkRk:!1))!)!!:JcRckBkB:B!!B!!!ZZ!11):J!1B!)))!R歌ssRcs!1:BJRRZkkRs{Bk!)!k:))1{{:J)!{BsJc)B1J)1k1kkJ:B!1ck)))JJkccB1Bks:Jcsk)1cB!Z1JB1JB):R):J1!JJJJRR1kJcRBcBcB{{RccBJBRB!J:RRB{{ֽ{kZZRRJRRcRskcscJ1JsR1cRRZJ{1B!!:::J:J!JZR1B1ccsc{RZc{skkcZkZJkc{ZR{֌ŜZBJ1RJcR{kkkcBkcR:)JR!)!scsJBBRZRJssZJZsksJ11!!:!!::1!!!1!!1))1RkZcs{s11::)Z))BRsJ!):1:)!!!!1!1c{Ōkc{:1:BZ!BcR!ZJcZJ)!:11JcJRkBZB!!::1!)BέťJ!RB{J1J1sk::Μk)R1:J:R!!1!ZZsR!RBZkskJ))kZ::J1!:Z:BcB1s1:R)1cZZJRJZZRk:R{s!)!JRRB:BRBBZJ:JBJk浵ckkcJkc֜JJRJkBRsΜsZsZR::JJ):{J)BckZkBJRJBkc{{{RBBksZ:1RscsZsskc֌kRcck{BJcΌRZsZRRRJ{)k:J:1ZccRks{ZBc1cZB{kZRBkkZ)B!)1B1!!!)!!!!BcksZJ:BZ1:1!B{:JsB1!!1RZ11J!{{ccŔR:RcZk{!cZkksRJcZBsss:!):)kZR!!)1)!!!ccZcJkZŌss:)!JcRJ)J)1)!!1JssńBJkccckcsk:::1::Rkc1:JR)Js1:s1Zcksk1)):)RsZRZRR):kck!BBBJ!BZBZ!!ckR{潜ZZZscZ{sBcZ{kRc{ZBsťk{{BcRBJ)ZcRJ)R1:kBRcsssJZ{ZcZZkRcZRJ:)JBcť{sscΔZJkZsZ{ZΌ:1JcZRcR{{{ccJB!JBBJ)!cZkckck{RBZZ{c{ZJB::J)1!!11!1)))!)!))R{sRcZRs{)!B1)R!:J{RJJJZ))1)1)1Zss{JRRcsc)!!csccZBJRsRkRJcZcZ1csRR!!:BJŜJR))1cBcB)R!B!)Zk11ޜ{)R:JBkεJ):BRR1){cJ1:RJ1:1:1:::)1ZcZB)Z)1!){ZJ{sJBB1BJZ1J:B)BBBBZJRcsBBkֽkZ{{sss)kZsZRkB{JZs{c{ZsJ:ssk)J:1:BJkZckks{ssBB1Bs{cskskkcs{R{s{ZZk{ŵs:{kB{sssR:RBc{R{{cZR)ckJ{kRkkkBRJBs{c:!11:1BBkJJ:B))))!)))!::!1JBkRB)!JZskZ{BB{Z1!))!B:)B)1B!B)JcJ))!sBc{BJc!{::BJZ!:csks1քsZ){R:ZcRZJcJc)!)!1c֌k{{{{sk1sB֭c1:!{sJ!!)11::cBΌsZ1R)BR:ZJ:)JJBJJJ!R)1JkB:B1Jk{sZJck:1:ck:RR!Z:::1JBJcRB:ccJsޜsksc{cc{ZcBkcRkBckskk)BZZB{JRR)JcJJkk{ssJkksŜskkcsss{sskZsJ{ckJBΔcŜkBc{RcZޜZZBZ:scs!Z{ccskBBskZ!!J):csZB11B1B1B!!!Bkk1{BkRR!1:BZZccJ{kkkZsc)J)))ZB1!!!!Z!!)!1s11!!!JZքc{kZ:R{)J!1!R{BR{RkZZJ:)RcRBBJ1ZJ:!!!!!:R!ZkcZRJ)!)JsZkRc)R:!J)!k1c):k))!BJ:Rk:)ZkR:)J1)B:::1kZ):ZJ!ss)J{1cJ1)B1)))11J:1JB::JZBJc{:skcR{ssZZJkRZZkkZsZZJcJJBJJB::1BJkkZc{Zs{{Bs{ssc{kRZRBRcńkccc挌RkcZssńskRccscZZcֽkZ1)Bkk!RkRckZcJR!sZ{c1!)1!BkcsBBkJJ:11B1cB{Z1:{RkZ{RBJZZR{{kcssZBR!BR!Z)BBJ!B1!J)J:::1)B)!{{ckJZs1ZR1!:)RRRJk{ss{s֔BJJ)1ccsBB!JZRJ1!Zsބ{Rs{B֔s:!1c:BkB)!!1)ks1ZR))c:::!!cJ:!sR!)JJBJ!Z1:JRR))ZB):!::BJ)JJcBZ1)J)1!1B!!Bk:!BBB)B:BRJR1R֭ZkcRc{s:ZZcJZk{sc{sk{{sΔZcZkJZJBc):)BBRB{cRksZcRZckť{kB!ZZkZsJsZcs{sŔ:{ZBJkss{RRcR1RJJΌk)1Bk1RRccJkccZcB{s)!)B:kZ:R{BZRBk{sRJRscZs::!1kB1s{sc{csJ1:Rk)1R1))!)1RJ)R1!)1!!!kssRBBZR{B1))):)!!:!cZc:cZ1!!sք1)BZ:!!1!{c)B)))BRscRR::!!)JJc!R)c11k!RޜZ!!)):J)1kJ11!!Z)Zc1J1)11Rk1B!!):B1JBkR1B::BBZ{RJ:1)J!)!RBZJk)JJB:cZs{ΜΌkcRRcBJkZ{ckZskRZkcZcscZcRRBBJcJcZ::JcZk:JB:{Rc{֭cRBε愄{{kRRB:c֥{cZ:ZkRZZc{ks{J1BkRZJB:){sBRZsZJ{sksJRs):1ZJ{kR:cR1))J{kcB))))!)!kkk:))!Zkk:!1ZJk)JB!RB111)Z1BZR!!!!1!scc֌ckkZ1!1ZcZB!)!!1:)Jkks{:)kεc)!B:1B:)k)Jc1R)RcJBBB))B)1{kZ!!sB)!!)ZΥ!)JBBBcB):!B)RZ):1!)Bc1k:))B:)ZZZsB!B!BB))::B:1B!)JZRJ)1)J):BJcccR:kkcssJRJBJJsJ{Rccs{sZJskRkZJssZZRscZsckZccJRRZ):c{c!ZcŌRJRέsŔkksRssR:ZJscZJZZRk{JZRk{{:kccZZs{:{s{ZZ::JZk{{JsccZ:scs:RRZcBJ)J):1RckccscB)!!!sRRRRJ1BZ!J!:!B!1ZJcBR):1)))!)!歭cs{{Zk:1!)!cB)!B1)1JBksJkJsť:)BB!!:k:!JJ!!1:ck!)!)R!1!!歜J::1!):Jc1::J))JB1J))J:ccB1)B1ZJ)!BJ)JsckJZBBZ)1BZB1:BcB!)1)11:::B)RJJJR{cZJZRJŔRkJJkcc{kksZR{Z{{kcZ{ckZR{k{J:Jccέsskkc1JRR֔{ss{cBRRcJRs{{s{scccRZsksBRsZkZkZ:ZkRJ:)Rc{scZZsJJ:ZJ{k:1BJ)1:JB!!!1!kcs{Rc{!!::!:J1JB)))JB):R!)Rc1:)J1!ssZsB1JZ!R:BscZBJ)BBJBsk{{{!ֽ{))!)!!JZB:)csc:Bs1BJ1!s籠!)R!1))JR1R:!s!!1JR)B)))))1BRk11:BB1R!!B:):!B!1J1J1J:111R:JJ:RBBc:1!:1:Rs{cZsZJRRRJB֌ŽZ΄kRJRcskZ{BJkscs{ksssssZcRsk{{֜k{:Bc:kŜkZss{ZZs{ZcsJZsJk)s{s{sscZsRJsc)sZ!JsZcJB)kckZRJJcckscR1:R)Rk1cRR)s1!ZJBcks{sk:)))!)B1JB!!1)!JZ1!!!!!Zcs1!1:RsRRBRBB!RskJJ{B{)1!{skJsBcccJR:ZZJ!{R1JB)!:)B)Rs!!J{{Z)!!R1!R:!sR:))!1!RcR)1Bs!BZ:J1cZs)!sR)1c)ZsB!1:R!)::)ksB1c:1k11!c):ZJ1::ZJRZ:ZJcRJRcZJRJJcJRcZBJkscR{RJcJc{ZZ{1R{kkkkksZkkks{ssc{ck{k:Z{s{skBB{ks֜skk{cRsRk{Jk{ssskJZ{BJZRskJZ:skBBkZZs:k)JZB:{Z!)BsZs:!B!!1::JZRksccscs!!!)1!):1:)1R!ssZRJsRB{c{RZsJ)!:Zk{1BJksJ)1:!J:1{sJcZZB1:::!)))B:{kcc:k1!!!)!1:B!kR!!Z!1J{Z!:1:))JJZ{))!!BBB!)R1ckk֜!1!)B!!JJJkc:R!!1)R11::)::RRRRckJZJkZkRRZR!J)J)BJ{RR{1kcZscc{kkksckskcBcZBZkks{JsZk{ZJJcνsŵ{ss{ck{{﵌sckkJ{ccc΄JcRBc:ZZ{{ckRcccZ{11)ckBs:ZsBkRsRJ1BJk:B:sskc:11BB1!!!!)RcJ!)cZcBksZZk{)!R{JR))JBskZZJBJRZZcJB1::!:ńޥscc::!!J1JZ:RRBB{ZkRc!:):1!!!1!!!ZRk1B:Z))::!)JBBR:R:BJ)ZsR:JŔBs{:)R1!1:1JBJssBBJ!)1c)!R):BJJZBBcJJZJ::B)R1!:BZZcRR1c:sc{BΔBZck{Zs{ckccssc{cksZ{{{cZsk{cssk{{Δs歄ť֭Ŝ{sJ֭֜Υ{{kνŵcc{sZ{Z{{ss{Rcssck{sZR!kJJ:Rs1!1!BBZJ:{scJZBRRZ:sR)Jks{!!!!))!!))!BB!!:Z:!Z{{RkkΜcJc1B1ZccRJ{!!!RR::ZkBs:Z1{Ŕc!ŭs{cJ1!s1k{k1!)):1!!!1!Js)!:ZR)!Zk11J!!!!c1BcRZ:!:Z:!1:cJk)!s{kŵZ1!!:!B!RJ{!k:JB1Rk1!JJkkJ)BZBcZcckcRcZccRJkRBRBc1BBBcksRsRcJckcR{k{kcck{kss{skkcńk{{ks{k{cΜֽνc{cΥc֭΄{s{sk{{Rks{{ֵkRRcBcRskZBJJ:B1k1):!1)!!!1!1::ckJR{BJR)c1:BB)Z:BJs{J!:)!)BB:BRBRJBZJ!sks{sֵZ:)BZέcRssks1JZ:JJBJ)JRRJcscB!1:cc{R:Z!RR))!)!R)1B)Bk!1!1B!sŵR:ccck!)1sk{{c1ZskRR{1J:1B1!):1)!):ބBR!):!:)JRJ!Bcsc11R{ZRRJsZJZck{sccBkBJZ:BcBRBccZBZk{BsZR{{ZsRkkksk{cs{{scskc{{޽ֵֵskRZck挌Zs{kss{{ZcsR{{kťJ:kBs11JRJZJ:::cBc1)!Z!:RJ::B:B11JB!:J)BBBBs{sJ{B)k:c{sZR))!!:J!!RJ1ZRJ1kcsRk:){{{ֽ{:!Js:B{cB:֥cRk!1!Bc!)Z:1RsބkŔ΄c::BckB1ccZZ!sZ)))1{ZZ!:k!!)BB!))!!Zck1!RJc!!J111R1:1ck:ZRR11!!)1!!1J)c)1sk:!:BBB1J))Bk11B1c:sZRkJJBc{RcZ1cZZ:1RB:ZZZZ:RRBcs{{{{ckRcscsk{{{kk{{k{k{k{sބ{ŽJŵ{{ssk֌{{Rk{sk{ksRc:Z:B!):)J:RRJR1:1!)1)))R)cR1JJB:!!!B!1JR:!kJ1{R:ZZZkZs1RZRccRcR1R:cRccRck1!!:{ZscZZ1ccZΜ{{s{Z::BB:!)1޵{c1!!1:Bsc1!1c{ksk{kRJZ{)R{{){1Z!!)1ZZk):1ZR:!BcsZ11!!k{:1cs{Z!!k{sJZZZ!B:RBJBc:1!JcR)c)!ZB)B1)1cs:1)1kJRJ)11RsRcJZBcJJ!RcBcsBcZsR!:ZJc:Jֵkck{ZJ{s{s{{{Jkc{s{έss{skkk{{R֌sk{sss{csťkckcccscJ)BB!B!1:c)!!B:J))1!:J!)1)1)!:ZJ:)J:JZcs:R{kRBR:!1sRR:JsBZs{kJ:!)JckJ1R:RR1{kZks{!s:RZ:Z!!)R޵!B!BkZsŔ{RJ{ccJJB:R{c11k:ZRZ:)J!!))cR:Z))!R{RZεsZ1ZscZR))!)!Bs1BJJ!B1B)!!!!B!)Jcss)c1)BR:!1)1J1kJ:R{sJ:kJJR:kZJZ1ZB:cBR:cBkZckscsZcJ{k{k{skkk{ks{sk{kss{ZssΜk{sZs{Ōcc{sk{|:B)J:!!Z11)!1RJ!k1)!JZ!c:J)BZ1!11:R:1BJsksZR{ZZk!ZkZZc:))1ZZJ{Z!!kcckskRckscZZBckBc!Z!{{k!BJ1RkJssŜ{!RsZcsRRZB1!s!1::J)!!cJ1BB){1!1:11!Z::))k11sŔB:ckRs:!::csRBBZc){)!BBBJccB:B)11!J::k1)sJ{{:ssZJ1R1kBc{Z::BRRBJkB:R{s{ZcccZ{{skRBsscsc{{skޥ{{{cքskŵΔsޭ{k{ޜssskZBckss{kR)J:JB:!)!)J!J1B)RJ::Js1!RZBBcR!!))!JcZJB{cc1{{{{{R)1Z{sJ!!!!))!!kBBZckZBcZsRcZBJZkss{kBJscsc{)1{ZRcB:!)JJJZ:::{ŔR{ΔBRRR{{k:R:ZBcZR::Z{cBJc)Z)BZR!)JJ!1R1cJ1RJscR:Js:ŔsBRRs!ZJ!:R{Z11!!1B:)sB1BJJkB)JB1J:{J)J)BJJBsBZBRBZJ1RJBJBJc:)J{:kRc{RkkkJRJksksksssŔ{քsZkckcZZޔkkkc愜ssskkkBc{JJkZs{k!::1J1!B!J)1J1)B:RZ:R1!)!:B1cB:1BR{cB!):{{Rs{{k{s!)1)))JJRBZkZ1BJ1:1!Bc{scJ{RZkBZBcŭck!{{k:1!):JssBssk{RZkZZk{νޥkZZBkBJkZs!1kťZs1ccJZZ1!!RZ:!RZs):!ZBkkkR:BR1:!B:!)JZB11k1c!:)!ZZ:1):1BJ:kZ1:RJRBJB{s:Z:JBBJ!RZBJZsc:B!::ZcZccRRBRcckskskŌs{s{{kJcssk{R{έkJksssބk{sZccބs{sRBZss{skJss:1)RJk:)!)!:BBJBBJ1:1)B!k!!!R!ZRB)):B!!1!RBkZ{cZ!)B)!))ks)kZZRZ1c:k)skZkRZJc{!!Z!B{sR:!R!::Zks)1)!cZֵkkքckkńsc)JRs1:)J:cRJkkkB!!!!J)Z1)!BJ!BBJ::ZsB)c{s:sŌsJcRZ!!11:!:1)c))):!:cRRc:RscZZB!1)1!1kkckcBBZ::J1k:JcRJZBcBkZkRRJZBcZZRJcJkccZscckΥskk{skscs{{ssc{kskR{cs{s{kkcRkckkcsJc{Zks:kkRZB)cZRB:!)Bc1))):R!cB):R11{:)!:BB1!::1)kR!)!1Rc1JZkR)ZR!B)B{RsksRkcBJ1ZckJ!֜BRZJ!B{B))!!BΜscs{R{޽ksssŌsRkZRJkRﵜR1JZckJZ!!!))):BJB1RBks)cB1{RRkk{kckcR!)!):cBZR:kckBZ:kJ:)1BR):kk!)BRZB:B1!1kZ֌B11:R:BRB1k:{sJk{ZR:JB1JBcBJ:BJJJkcZ{ssŜkssckksc{k{sŭZR:B1c)B1֭skZcksssZckksk{ŔR:JB{BJ{BckcRRJ)))ssB)BkZ1JJ1R)!1B1B1)Z1!!!!1c{{{!RJ1Bs{cRk{{R{:J{B1Z:1JBJ:ckJ1Jcs1B:Zk1{{cZsRcks:cR)))!kskck!!))1!B1)JBRRJ)J1Δ{kJskcZZ!{Z1:R!111!)cJBRBJZ):JZR:1)RJRck::)BRZcsB::Bc{RkkJ:)1::JB:Jss{sJZ)Zcŭ1sRJcJBsBBBJ!Rsc:ZZs{skcs{{քkZΜŌssc{{ckJBcBsBZZ΄{cRc{cZ{ZJskR{sZBRR)Rk{RRkkBRJ!1)ZJc{sR:ZJ{kss!!JJ))))B::J{B:)B!!1!!ZRsZcJ!!:{sk{ZcRZ{kc:BcckcBZJcZ޵sk1)!!J!ksZsRcB{R{c1JcB{:{{s{JcBcR)sJ1Ŝs!!R:!::!RR!:kZ:ccck{sZc{{s{):)!B:Jcc:B)RJ:RRJJ:)J::c)R!)RB:c:ksZJZcRksZ)!c:ZB)RRkc:JZBBkZRBs:Zc{sRsBJR{cZ:)ZscB1{Zk{kkksscs{{{sޔŜ{{ZR{ZZZJRZ{csckk{{skBJ{Zkcc{{cRssB{scJsBkB:JBBBkk)sRcB{kcBskckB::1)11:B:!{k!k:!1!)B:{RsRc!BB{c11{kJ:1ccJsBJ{B!JJ1JcRZk{scRŔ:1BRZ1!)kZJZkksck{{)1cJ)!!kcRck!!ZJZ{cB:RZJs1c{BJZ)!)!kZR{ZZ!!!)sŭ{cZBJR:ťkccRBJk1:!B!J)B:kJBc1BJB:k:1)))1B:)1)RsJ{scBBBBs{ccsJB1!)):BZ{csk:BJŔRZsBBJ::BsZZZBZB1:Rs:B1ZZ{s{sZsJ{k{J{s{ŜkJ{sksks{sJ{sssք{kk{ZkcsB{{Ŝ{{{RcRR1{kRkRcZ{kZksk{skR:cckcZB1J1c1!J:1RZ1skJJkBckZ:1):)!)!Jkcksk:JJΜs1Rc:sssk:BRsscZR!c{s)Rkcs::!1J:BZs{BBBRBcksJ:BkB)ZR:ZŜքRc1!cBc1RBZJRkkJ!::kc!cJRZ111)!RRkZBνބc:BΌs{1朌Z{JBsֵ{)R!)1!1:BZRZJ:RB)!ZR)1Z)c!!!1k1B:R{R::kRJZkJBZ{Jss{BZscJcRZ{c{sZs:JJŔcZcccZJRZcs:{R:Rk{R{ŭss{s֌sZscRRZ!kRJkc{{k{k{sscsZsZskZkcZckkkcRssR!BBkkJcZsk::scZsB:ZZ{{1Rs{ZBkRRJskZkJJ1)B1BJBJZ:)R!ccscBBRB)1:BBBcs{JcB1)c:JcJZΔ{kcBRckB{c:Rcc{):!:1)RsJ:1!::BZJRRkJ)!BZkkRJ!Rń:1J{BBBccckZc:!R:s1R11csk:JZkckJZŽ{{cJs:cZZssck))c֔kcR{Ŕ{s{ZRRZ:!)!)ZR:)))R!Bc!!):)B:ZJs1!!)c1JkkJk{1R:J:{ZZZs{ckcJZRB:B{k{BcZRBJcJZsccsk{s{cR{ksJŭcZsR{sZRRkk{B{kΌcckZkZ{cc{c{ksBZks{cZ:csRRcJkRZRkccRRkZJs{R!1cBZkc):)1)R:RRZBsBJsZ1kZRJRZJ:RkR{c!!{cBsB{Rck{sck!RZc1Z:Rc{ZR!!!:Z:!kkcRJ)1!!B1BRZRRs!sc!BRssνkBBkkkRJZ{cRR:c1sZ:cZ1:k)R{!!ZckRR)JB1Jk{kcZJB::1kZskR{)R:)ΥΥsB{ν{:k{kcńB1B)!!:J11ccJ:J)1!1))B:BB:11c)1:B!:111BcR{{JcJZBBJZksscJsR{kc{JRsJcBBJ1BB)JRsBJsŵsR{ťsRRsRŜŵR{RRBZZccRRZZcRZk{R֥{Jkkccsc{{skZc1BBsZscJJ{k{JRJR::ccs)1kZBJ:ZZ!!Jss{BRskZ{csZ:11!BJ:s)Z!):!:scsck)BR1ksssZZs:))cZ:Z{)JkBc)!J{JRkcJ1!cZcZ!R:ZZ1BBZ:Zc!BZsR!)BkkR!1!:k֭c{k{kssRk:!:kc֌s:JBJRBR{!!)csZJ!!1:ZRJBRR1sc1BZR:ΔJZ:kBZk{{:Jk::Rc޽{Z:ks)1BkJJRB))!!!B!!!BBB!B:1)JcR{ZRJc{{{kRsZB11ZssZskRZBBZssZ{:JRJ)!)B:!B::kc{ZJJB::)BRkRc{{sR{k{ﵵsk{{{ŵ{歔{ZRB֥{sZkZscJkkckZksckZZkcBZc:cscRc{Bk1JcBc!RB{c)11ksssZZR!!Bsk:k!ZRZZZZcBB!!!1ZZB:1JBk{kkJsc:RJRBJkZ{1!s{{R)J1RZΥ{{Z)1BJ)kkkJZ)1Rkks{csB1:)ZZB{R1:)JJZs:!):cZcRs{skc{:111:11RBJZ{{ckkBZkRJ{BJB!ZkZk1ZcksJsJ!B:kcckkJZZR{楔քRJ{{ZR{{ZkkRk:ZRZRR::)1)11BckccRBB)1)B:JBJBRZZ{kkcZ{kJkk{Z{1:JRscZsRc{cZkk{cJcRZZB:BBRBJkk{{Z:BJZc1ZsZ{cε{kc{kc{{J攌{scRBkRZR{Z{ޔscskkc{sssks{k1:csRsZZZZs{s1c{sZ1BcRcBkJZksZ{1){{{){:ZJcRJJJk!B)!B:RBBJ){scJBsZ{sJZRcZ{!J{R:))J:ksc::1ZkRs{B))kcZ{JccRBBBR::B::1kc{J!RZkc{ss{cskskZJBB:JkcJBsskkss1skkRcJ!sc{!:cssB{sck))BcJkJs1:s{RZk{{JsJscBZs:Z{skJksRk!1::1BR1)BJRRRR1:BZBZ:JZsR:!:::cR)!BcBck1!):1J!:BRRZ):)1B1JkBsJk1B1B1BskJBZ{{kZBB)!!:cs{RZk{{{{kkZskcs{kk{Ό{kZRcRJssRޜsֽkRs{c{kssZc{{sZ:{RRkBBks{kcBBRR!R:BscckR!)1skJB!:Bk{s)JR1JJ::!JBB:1:)1J{kkcsZkcs{RBB:cJ{ssB!):cZc{sRk11J):cc!!kss{kZZZRJck:Z!JJBBJ)c:)kBJ1csRcZccckkskss{c:ZkZkBRsskZ)RZB)kJJBZ)1B:1!cZJBBckc{k:!1:!ZcZ!B1J{B:RBkRRkR1Z1:!Zc{B)!!1k1)JsZ:k1:BJ:BJJkcRcJ1:):k1Z1!BRksB)Bk)JZcZssZ{cRB:B1BBcJ{k{BZJB):JJ)BZRscsZ{Rs{skckkB{JRc{֜sssZZsZ{{Z{csZ{s{{sckZcksZccRcZksc):cBk)!R{J:JJsJZc)cZ!1kkcZ:RBZ:JBB:)!c:c:cR)!!kB:kcckkB:JZsZR)::ZkRZssR:1!:!Jc:)Z1R))cssccZJcJBZcBksRBsscB!JcJJB)k{{BRŌksZJ1RZB:cscsBcsccc11JZZ{1sk!JJ:skRRJZ:Zsc:Zk:1ZBZB1!))!Bc!B!:kZ1:)sBJR!B!::)):!!111)JZZRBZ{:J:RZ{k1ZZ{kcskR1{J1B1cBcJ!BZckZRRZBBJBRRsJsZcBB)::JkRJksZkcZJJBR{sZJRk{{sB{sJk{{έckBc{JsRZkޥŌŭ{cssBkRk{kRZRJBRRkRBkkΥ1{s::JcZ1!B{{s:){sR:cR1:)cZZRR::BZ:::!!:11ccZBc{)!R{skZRBkcZZZsZ!1ZsZRs1JZBZ!{RBZcBRJJBkBkJkZZckZ))))sZ11!sZ1R֭ckkskkcB)11:Z1s{JB1Rkc{sRB!kZJJJR1ZsJc!1kkJscck!cZ!Bk{)1:)B)1:ZJ)B1)cZRRB1JJ1)Jk{RZZZJZ::sRR1skRk:1BRR:R{ckcRBRJJ)cBk{R:)RZJZkJRcZkJB1cRZcZ{sZJk{RcZ)Jcńs{{ksRckΌkkcZR{kJ!stRZ:c{cRR1ZcJRJZc{cc{ŵ΄kR{ZJJckZZcZkŜJJJ{BcBk:csk)Rck{RJkZss1!{s{ckcB1!)Z{cBBsBJ)1B):BBR)RJJ{{BkcJ:cRsRRkks{kZRZcB1ccBcccJsRkkkZZ:1JBBJ)!skcBZք{kscsֵ{{R11)JBJBRR{R{ZkZZ{sZcRJkscB{JkcRJ1ZR:RkR1sJsZ!1:)Zs:Jc{s):!)c!BZcR!:Z{JkZ):1)JRBRcJ:c):sZsZJBZJR1cJZc::{R)Z)JZJRBZkZ{{{sΌsZZZc{kRk{kksksΌ{cJZsck{{J{cBJ{ksJkńcJJc{RZcZsZRk:ZkŭΜss{JkJBkJRZZck{R{Jk{)ss{cZcZJ{{ZRR)skZRkJZcZckksZ1:cc{cZB!!:s{JRZskZ:BR1)!BcB:)!)BB1{{BkcscRZ{BcJc{k{Z!cZ:J)!:B!JZscc!!sBcc{Rcss{RR::J!RJ1{skcRBZssބcskZ{ťss{sRJ::)BBJ:kJRJBZ{ZRZBR!BJJRcc1!:ZJ1BJJs)Zk{R{{B111BJ1R)!JZJ!)BBRB)c:kB:RJJ!JRRRJBcRZZRkZskB:!c{:):kBJk)1Z{)B:JJB!ccRZsZkBZskkksZZkZ!)B:1::kZZsc:JΌ֜{csskZkZkss{sBkRZskkJcJkZ֜JεRZRZscε޵ޥ{{sZccccskJJ:RZ{cksRJ:BZZJRRcsRBZ!JcZ{kk1BJZk{{1J:J{kR!1BJZcc:1ss{ss1R1R)):B!)!!1BcZkZZZ{ckRZcRR1R{)1:ZRsk1sB!JBZckZk!ZZRksZ:cR{ZBcR))!)sRk{sJkRBcZ1RťRkccŔ{sssZsBJJ:BcBJksZcsν!Z{sckZ!!!:JZB!!BJJZRZc{{RΥ{BJs)!!cJ:R1BJBB)!ZZ!!k{ZZ1skBZJZJJZJ){BJ!sZksZ):!:):JRZZJ:J:RZssk)1):!!cZksskRJRB:J:1JZ1c{Z1֌kZc{{k{ZkRks{ckcJck{Žkk{JRkBZJcJc{浔k{{s{cBJBRZkkkkB:{ńRZJ)RZBZJsJccckRkkń:1)kc1B!:BkJ{kJRsc)R:)k{:)1ZcZc:cRZcJBcRcZkc1cJ)BcB{JJkJ)ZkRk:)ťc1kcZZRZs!:R:R!:RZZsBJ)R){攔cνkJ!1{J)R)!!:sk::!!)!:JcscJ{BJkccsRB!BZ:Bc:!)::kRsZ{JR{c!)!)RJsŵkk!1ccB{{!))1BkBccZsk{JB)Rc:BR11ZBB!Z1kZ1ZJsJRBBBckZ1JR:!!!!J)1JRBBRcRRZR::J:1:!sJRkZ{{{kkZRkkksRkk{R:B)sŵ{J{ﭥcckcBsRccJJ{Žkŭcsscccs{R{cZZ{ZZRBBZ:Rc{ssZZZ{s{B1!:1RckRZ1JcJZk1)k{{cs:ccB)B:)sksZJcR1kR1))ZRkZR{Zkkk{Jk{:BBBcBR1kJ:)::!Z{:::kRcZkJkcZJBB1!cckBsk{s:!1kc{{c::sR1ZRZ):Jks{{cscZRBkBJJ!)JZ{RsJZRsc{Bk!1!):RssΜsZsJc:!!!RZ{1)!!ZRJB1ZJcJckBBBBBkJRBRR::BJc:1R:1c{ck)!)!!)B)::!!)1!)skB:ZJZZZB1BBB)JB1Z{ss{ss{:1JJJcs{ΥsksZkR{Js{{{J{cskkkcs{{sk{J:Rccs{skB֥{ccckc{cs{ZkRkkckZ{kkRksc{1:JksZ1Rcsc{cJZcRRJ:BRssRR{cRRcJZ:B1JRsJZ!)!)!)!!)BJ)Z{sJ1BkZJ:ZBJRcs!JJ!Zcs:1!cZJB:)Jc{kJ1!!c{kZJkBBckJ1ZkZ:BJs{kc{1ck{JBccBZ{ccZBcJs{kcBscR!R{JJk{1J1BJ{kk{!1ε:c:scR))kksRscR1!:k{s{!!)!!1R::!:c1RZcJR1kkkRRkcB:kZRcJZkR))R11!:B)B!:11))kB!)!):JRJcBkRBJZ))B!Z:BZkZsk{sJBBkZ{c{sŭck{BsRk{{ZZkkcccR11R{Z{kJBRJss{{ksZJZJ:cZk{{:JZcZccccZR{kJsk{ckscZcZJ):kBk{s1!!RcccR:ksBR:RskkcZ{J1)!:):11!kk:c:cZksRcBJZB:B{))s:!))sk{:1:{kcZRZ::ckkB!){kskZkRR!))!RJscccZ)c:!Z11!:1):1!)!)BRcBc{BRcZ!):):s{scZ{s::R)!k:!R{Zkc{{ZBkRsJR:::B)JJc1)!JBB!!R)B1kZsRJJ{c:::{!)Rccc:RZ!!B::!):)1))1)J1!k!:k::ZRsBBJ1B::1csZsssc{{sJJέZ{k{cRs{s{{ss{楥skJskŜB{ťkkBsJBBkRckcc:BZ:kJss{{kŔքkk{BRZZ{sZckkJJkRksk::B!:!1RZss:cZZcccZ{cBZ{J!B1!!!!))!RJRJ1Z1BB)Rc:!::JJJZ1kckRZBckB!)RZZksskZR1!!1BR:JJ:{Js{B!!kRR::BZJ1ZkRBR)!c:kZ)c{ccs)BRcR:1:RRJ)1{{cskBk{sJRs:Zs{cc{R{ŭ)RZc!J!:!!kZskRkJskB:J):1Zc:kJJcRcsJ)1!:JcsR1)J)::!)1)BZ::BB:!RBckkcRBRckZk{k{c֜ΥΥΥ{J挜{{{RR{ΔZ{Z{cs﵄kJs{cZsskRksZBJRs{{ssRks{εsJck{J:R:::kkR{BBBBR{c{ssBBkR:)skJ!!B1ks{cZckcJZZJRZkkJZ:cBcsRRBB:R11!)!:)1!!1)!Zc:1:JcJZJsc{!RRcRssRRRRskR{sZJ!!BcJ)RJ1ccRJR{B::kZJJB!!JRR::)k:)::Bss{cs:JJZ{{ZZc:Z:1cZRc{JBB{cB)BscscBs{ZkkR:R1!RJ!1!{BJ1Z1:c)1cZJ)JJ!:Zcs:ΔcBRBk1!)B!!:1!1!:RJRZBR1RBBcJ:s{s:kcZZsZZ{Jsskks{{Žνޥc{Ŕs{c֜ޥs{kZs{JRs楔Rkkksk{{sŔ{ZBZ{{Z{s{sZZkZcťŵ{Zk{Z:1JBZcckkB:1ZRZckkJJRkZZR1JskZk{kBckZkZ!R{cZs)J:Jkcck)kkR:J)!!!1!!:!1c::JssJ:BZc{)!:skZRZJcBs!1ckk{{Rkc)!BJkck{kZ:Z1JZRBRZskcRRZZR)Rcs:BkZcJJ!))B1:k:J!1!1B:1c:Z:B{k{JBJc{{c!1:ZB)sR1cssZk{J1J1B!)kZRB:!)B:BZ:JcR{cJ::ccJ1!!1!J!:ZB:)!:)JJZsRcRZRRZc)ZJcs{{RccRB11ZJZck{s{{s{{Zc{פּńŵkkZZΔŵ{ssZsssťB{Zޥ{{RŔssZJsssscZRkֽcRRBkcRR{cZ{RcJZRsscccR1JkJkcs{Z{cRJk1RJcBcc{cZRsc{kZBZsccs!!)s{Z:sZZJkkB1):)1:!11111)ckRZJJkc{))!kcZkk{c:):k{Zsckk:))!:)1k{Z):JJR:BB:kBZ1css:c1RcBB:ZBZsRR1!J!!)BRJ!)))cZJc:c:R:k{c!)!1)1k:)):kJ)1Bc1:ZBBkk)BJJ:1B)!)1))JBJZ)ZB1{J:ZR!)R:J!))RJZ11))11!!:ZJZ:J:c1ZBZskJk:)JkJRBJ:{k{kcZ޵kR{{kέ浥ckZs{֌kŽRֽ{s{:cZk{ckk{JBkJ1R1:kBťJZZk{ZJcRBcscck:kZkk{k)sckJBkcZJRcZ):Z{{B)1kZZ):ZkJs{ccsckJB:BBZ!!B)!B!RJJRJckB!!)!{{RBRZ)!csZk{k:cB!cZ):RJBc{kZRRRcBsRZR)BB)RRkkcJBZscsJ:!!BJRs!JR{ŌBJ:RRcJ{k1JZZJJ:!RZcsZRRc){BskJZBc)ZRZBRc)!1)B::)!!1:!JBsJ1c)J{cs:!)R!:1BJZ)B!!:):1:!c1R11JZZ)BkZJZscBcRJRkcsk!!ZZJsssskkkRcccεss{{kkksBBŽs{sskccޥ{:JRZ{css{{Jcs:JcsΥRkcZZsRkcBZRcZJksJZRRscJZJZkckR:sJZJR)1JckZJJs{kc1B)::ZRkkckRsskcJZRR!J!11BBZ)))11BZc!JB{cskk1B1Rk{k{1)!R::::ZJcZRcJcJ!Jc1:BR:1BBRZkcs:skJcR1:J!cJRcRcJ1{)1Z:ZBBsΜ{{sJB!!cRJJJZs:!1Z:!BJ!!:)JJBBZsB!)c!RJ1!!1J:cRs!J1!J!)1JBBJ)JBR11!!)JsZ1R!!)!BR)Bk:)B:sc{cRBJ{ssssRΜsRJťksZRZΜֽ޽Μ{sεֵkZB{k{s{歌Z΄Μ{sBk{cRccRZsB1:1ZRBRBJ1kcsscckJZsksRBcBkBRcJR{cJ1ckskR!!ckkZBJZ{RJZZ{{scsR{:cRkJBJcJ{RBc)Z))!J:R{!JcRkBk{sckcc!!:scck{{cJ):))c{::ccssckkRJs!)B1RZs{scJZssRZ1k!!)RkssscJskZ:{sB:!Z{)!!)J::kJ1sB))1)J::BJk:)1))J:1)!:JZkRZ))))JRBBJ:J1BJcZRJ)J:R)!:J:)!R!JZccB{ckRkskZks{s{skssŭޭ楔֜c{sccŵŵέskkZ{Ž{ބsksskZ{{Zŵ{kR:kskkZscZscJB:Z:1JZB!cRZcZפּ{kJBBBJs{:Rs1{1{c)BJJkRJ:))c{ZZJk1:{sZ:{kcsBk:1cJJZ1JBRRcB:!J1R::)J{ZRB{RRZk):ck{cJZc!BskZBJkR:cB{kcccRkJZ:))BJZZBJ:Rkssks{1!:)1J{RR!1!Js)!Zsc{kZZZRcscZ)R{!:::RZc1cJ1sZR)Rkcc::1)11RRJBZBR1JR1c:{!)!:!!!BBckcZJB1cBR{::)J!cR{c:k:B{sJJ:JRB:ZJZZ{RZckcs朌kŵ{kssJkֵ{c{kkJ{{{Z{sZ֔{sJsJkZsksk{Rkk:cRZRJ{RRk:kcs1s֌Rcsk!JkkskJZ{c{cBsR1RR{s)!BBkRZ1B1sRZRs{sRckccZ1BR:JBcZcJcJBcsZ)B!:JsZkZs:!{kZJRZ1kRZRc{))Bs11cZc{ZRck)!1:cZkJkcRcJ!cZk{kZ:11RcRc:R1)!!RRksZJcBkc:ZkZZkRB)!)ZsZ:{sB)BJJ:1!!:R{s{1B)!:BZBB!1R:JB)RB:ZZRcc1Js)B1cBBJRcB)1{sB111::BJ!):))1:ckJR:kJRJ!)RJJ1Zs:J:BJsBccZRZ:Zs朽{Z{ք:ZkJ朥JZsssckΜssks{ksk{ZBcR{{{RJsck{ckscccsRBRBBs{JRZB!Rkc)JsksZsBccB:{k{kRkZB!ZkZ1B1sc1):Bc:ZkRs{ZkckZZc{:{kZ1JZZJZsZ!sc1sZcZ1))1!ZcZcR1)Bs{BkBkR)!kskRB)!1s{c!)1Zss:k:Z1:JBckZsksZZZkkZR{{{sRJc)!)ZskkZkc1JskkBRR)BBB:1s:{::JJR):1)!JskBB:Z:)R1!J1B)))!!:)!)!)R!1RJRR!JkZ:JJZZkJ{J1{R:RBsBRRRcZBZZRZJcJ)JcJBR1sRRZk1JRRcR{cZRRZ{skks{ŔŌs歜cs{ks΄J{RsRZk֭ZZքs{{c{{ZZc{քksJR1kBZkcs:kB{ssJcR:1ZkRBkcsc{RBZcJksRBcJ:skcssBRkc:ZZ)J{{:11BkZ)c{ccJRZscRsJBJBJkR{R1:JRZ)Z:JJ!!!!1)k))JZkBBc!!ZBc{kޔ)!J:)Zks!1!ZJZkRZZkk{Z!!)JBkcR1s{ZJ!{ckkc!!1kscscZc:s::sB:k{Zcks)!BRZkkkJ{skR1{:!cJ))!:{c{cRZ!)ZRZZR1)J:cB:BJZB!!1B!R1!1RB!:RR:!BkRBRkkR:RBR:JJB{B:Z:1:c{{J:{B:kJ:Z{::)RBBZkJRRRBJcskskcJkJc{{{kk{ޥ{{RRńk֭{ss{cssk{1kŜkŵcs{scs{{{:RBJRJZsZZcss)Bskck{R1)1RckZsk{k)Zk{ZJskssscssJRZ!11!JRccRJsk:cZRc1Z{cJBc{{csk:J:cZskBkBccBBck{)Z11:BRBsJZJ1:!1BBZBJsJ{RcZ:1cs֔J1RB)Zc{::BR1cZkck{kcJ)1:JkRcssJ{kss{skJ:kskccsBkksZ{ZBBcZcB):JBcJ{c1Zcc{{kk1{sJ!1)B{JkJRkk)!::ZZcB:11!:)!s!)!J111ccJRJJB1B:!1RZ:k{cJRZkZR))kkcBBZ1c:cB)1!RZcRRJJJZcs{kkZZRkkskksc{BޥkRsŔ{{cZZckk{kkk{sR֭Όs{s֜ks{cs{k)kBJ)J:c!kZcccR)cs)BssskR{ZskRsscRZRcBZRZJZ:RJskcckJ:1))ZcsRRZZc:!:JkkZs1!1BJkk{{c!1kR))1:)!RkRJZ):RBB:!!)!:cskZkkJ!)1)!:kB{楌)!:JsJ1J))BZskcRRBB!B::!!kB:1:)kZ!RcR{{:!!!B{kJskscc:{cZc{{k:1s{1{Jsckc!):1s:ZJc1ZRJBBJ!:Bcc:c1Bc)RR1:!1!!)!::B:)Z)RkkckZsRssc{s{!Z1!!RJZskZR:ssR֭ΔcsJZkkksRBRBZRcBk{ZsZkZcZRR{kcckc{s{Zsޭ{{k{cZ{ńs{kssks{ZZ{sεޔֵcBJB!Zk!1Z!BZckckck::JcRskRJZk{֥cBkkJRkcsZskBkcRJcs{{kckBcZkZRJ:)R{kRZk!Zks!)Z!1J1k{cZ:Zs)J:1)!:c:{)::sZR:!:!!)kJksJ){sJ{RRcB)JZksR1{ZZs{RcRB:RRR)kZss{Z::11)))JZZ{k!!::11))kZsŔsRcRssB)ZRcZcR!skRs:RBc{kcZ)111::)c1cBJZB1!!!c:ZRB:BBJB!:1!:R:::ZBZJ11!!!B::BBB1JR!ZRksZRRsZc:B)BRBBsc{cŭJJŽŔ֭ޭJZZBBRJB:RZs֜kΔ{{{{{kkskcJkckccs{{kkksZsZkZsksJss{ZεΔk:R޽ckcB::ck)RZRZRcBBR)k{sZZR:s{ckcckB:ZJ:!Zc{B)R{sJ:JcscJJZk):J:)BRkcRsk11:)1RJR11cBZRZ1))!!RksZckkZ1Rk!{ZsBRRR1csZZ:{J{c:kck{ks):c1{έsscRJc:k{R))1!cckZB!!cJckks:s{s1)1s!1JJ:ZBB!RcZZ!BZZJ:ck)1BR1JRssZJcBRZZ:11:JRRBkR:JBBJB)1))J1ZRs1RcBB1::BJ{BsJJsBJ11)JRk΄1)!1)kέRRBZJ:JRcRZkJZkks{Ō{ZRJJsRJZ1BcJk{k{kZscZkcsss1kcZc{:ŵ֌BRB1::ZBB!J1R޵ޔcsss:JZkRZ:JZcss111:B1ZkZcRk{JZcZ1Js{΄:1)BZ{cZRkJBkZsc{B)B)1)RJs:ZJBJBRcJ!1!1:sZ!)ZsBZ{sZcR!1):ZJk{ZBs{s1ZJk{RR)RBJs{{JRJRc)!sskk{R֥s{RcZ)!Z{{s1cskssZsk{ckBZZkR{Rk!)RscJ!)ZBRcBJ)kJ:))!Bkc{):1:B1:Bc1:RRJZR)ZZJc1BB:1B1JccRBJ{kksB:RJRJB!!R1)1ZJck)1111!)޽{:RBRJRRRBcZcRksŌkkkޭΔ{kscBkBZZ:cJRJZZJ:JcskkR{kccZJν{ޭsޜŔ1))BBkc{BJc{sk{ńRkJZ)J1)RkR)B11:1ZZBkB1J)kkRR{::k{JBcRcJ!csR)!:{c{ccZcJR!:BJk:R1)!:k{1cŔ֔ZcBRc1{Z:11J:RJcJkJJB1Jck)!Rkcsssk{sc{s:1!!{k{Z{kJ{1!1Rcs1JZ{{ks{kZRBBBcRc1){kR:Z:!BJRJBB1)!!::1Zs{!)!):!1RBJRJB:!!R1ZR{JBB)BB!:1Jck:1BRRccZR!):Zk{J)!!::1)RBZ):BBkŜcBJB::JJJRZJJkRsc{kޜZckRRJkRsRZkZc1ZZRRBZs{sŜ1k{ZZc{Z{kΌR):RkΌ1sJc:)RZcsR{{{c:B{RB:B1ZBBB::BsJ:)::Rk:JZ1cR{BcZ{{!!)BJcZJZc:{))!1RkJJR{kZRZBJ1RcZ:Zk:JJ)1B!BsR{:RksRssk:!)1cskJ1))BR:B:BRZBJJR)B1JRRRkskkB!!JBksR!):ccքskZkZc!ss{skRZck{cskR)1sks!BskcZc1RZc:R1{JJJ:11:1c1BR!Jc1B)JRBRZB:Zk1J1ZJJZcJ!)cJZcRZ{R)!)1Z)B1!):BBJkJJ:1:ksBcJc:cBJJZZRc{Zc{Δ֥εֵ֥kZkBBsJB:kRsk{kZJBsŽ{Ō{Jkc{{k{{{Bk:J!!1){JkZZJBB:kssssZk{ZcscsZ{c{:B1B1!1)J)11J1JZ1kZZ1Jckccs1ZBc:ZJsk1ccskckBk))JsZkkc{cBZ!{1{RRBkZZJkZ:BZssJZZBZJsRcJRJZckkZZ1J:csssc)BR:::RBR!BkRcs{skcBkZJccJZ1!!kcsZsck1{Zcss{k:ZRc{Rck:!JBZ{!R{ZRR))ccZZBs1J!1!RJ)R!B):)::JBcsk:RR:cJ1c::!RcJkcZ:1ckBR:BJR{BJRRR:BZZ)c1)))!B:JZRZ1kJRkRZksscJZJJJ:ZkJJRJss{cťŜŭΥkcJZcZ1:1c{RkkkJ{s{cskcŜJkkRBcZkkkk{{ZΔ!)k{k{)Jcsc{kksscZsksckZc{ZJkJ1ZR1:::skc{BJJJJ1J:ZcZZ1RJJZ){skcR:!kJ{kcBZRc))!R:ccBJJcBJkcckRc:kks!BdJssJJssc:BZ{ckc)ZsZkZsscZskZZ!!1ZZcss)JBcZ{kBsBZńckZ{Rckks{kJkB:cJJZBB1)B):{skkkRJ1sRRB{Z{sk{ZJZ1BB1)J!)k))!))!JJBRs!kJBB)111k1::ZRkcRRcR1:sc)ZRZR1)!)BsRRZc{kR!)Bc!)JB:BB:JZRc{RRscJcZkZkBkZBRBZZRRkck{εŽŭs{kRcsJRcJZZZJsZ{sRsŵJJkքkRR:JJ΄ssJRRskRkcc{sk{c{cZ{c{RssBskksc{sBZckB!1:)RZR{R{R)111RZZ)!scZc{{JkJck)ccR{ZR:ZkR:B:sJRRJsJ{cZ:JsB)sskZ)!Ōk1RcZJsB:Z{R:RR!1)!!{csRRZ:)RcRJJkkR1BZBRskc:Z{RZssk::1))!1!RZBBZ))sc11:Z1cJBsRRJ)BB!!BBJJB1!)cRJJ)1)B11cR{k:RJRBkZJc:RssRsJBBRRBJskZBkkBZsks1)JZRZk{kRZ1c1JJ:cRRRB:JZJZk:JZ:kc:BBJJJZZcRkkZcZ{ss֭޽k{Žsk:RZk:sRBBk{cskB{ZZcckcB1BsBkJ:ks:sssskcc{ksRR޵sZkZBJJR{c{kc{{{{JRJJ)BkcRs1::{ks:R:kkkkcskcJR::!1BZ1ZkR1{{ckc:RRcRJkc)cZZsk)cBscksJcRBks1ccsJ)ccR!!!:{ZcksJ1Bss::)JZcRc{{JRJZsJ1sZZ{kc::)!)1)k:skksBsR1{1ZckkB1)BRcccc{c!BJ::1J)::!))BR1R:Rc{csZZJJZkksBBJBccBZZ)kRk:ZcJR{R!)!ckskZcJ:{RZk:c:c{!Zc:BJRJ:cRJ1c:BZBJZBB:BZBJJZZccssks{޽{sRkε֔1RRc{:Jk攌k{Zŭ1{sZcsskkkJJZckJB!!cRcBRkk{Jsk{ZZZskRkZRZJZZs{cBJZRckZk{kBsRR{RJRk)kZkkB1{kcsskR!!JR{scJRJcZRB1{kZJ1B{ssRRJB{ZsBksRZ{s{))B1:1B{{ss1Rs)1JZc{RcZR{sZs{s1)J{ssBBR)1R)!Z1!)RR1!Jscs{k!)RRks{cJJ)sBJRBZ:JZ1:R)B)Jckckc):!)!BBZR:1B1kBk1kZsZc{BZ1!JkBssscJZkskc:ccskR!){RRRsJRZ:B:cJJ):ZRJ1BR:BR:sJcc{s)J{sss攄{֌ֽ{JssJRJRJBcZJ{cksckJsB{:cscBkZcZkJcssBZ1cRscB::csZc{{scsR{Z{kcc{֭kΜkccks{kRZkck{JZ!Z11ŌkR{cJZ):s{kJ1:kZRkcJBkRZkRJcB)JZJk{sZckssJscZZ{s{J!11B!)!)!1RRc{cZssc)R!!k1:BJBRZ{kc:)Jc{{{Rk:!!!!1!:!)J!1ZJ{s{JZ1kZ!1::BRkZs11{RJJ1RR{Bk{R!!1JkcRkRRZZs)BkZs{kkss:ccBRJZ!kRR)RckckkZckZRJJZJcZBJcBBZ:R1cs{{ss{scs{JZcZsRsRs޽ŵJcs{k{{BZkkZkεcBcZkckRJBkcBJkcZJk1JkksRccsRJcRZRJkc業k{kss:{ZBZ{kkkRBskZ:sksZJZ1cΌkZ:k)csJkR:Z{ckcRJ1)BckB!{kέ{ZJ):Js{{ss{kέ1!)B::)Bcks{c{B:!RkJ1JB:)1B{JcBc{c{{R!1JJ!:B!!)!cc!B:!1sk!kZ{cRBJkBR)!ZBJ)!!!):)JZc)ZssskksJZkJ:R:Js)JJBks:JZkZZRBccJJJZBRRJB:1BRRZJ:!cZs{ckk浜挥΄:sc{sޭքsk:Jc{kZccck{R{Z{ZJRsZc!{JcBJ{c΄{Rs{sckZ{c{sRsޥZZZksRZ1RkZssk{Z:::BsJBkJR{Zs{s:{{Bs)RR{:JBRZckRcJRsckZZk)ZB!ZkR{Bcssc:ck{cs1ZkB!!)B1:ń{ck{:Rc)k{B:BB)kBZ1JZs{BJ:B{kRks!!1)!!RJ)R!!)BZZJJc!BJ!!1)Z1BZZZB1RBcZRZ!)J)!):1:Z))sZ1JsskcZJZZZZ!1JJ:ZkJZ{k:BJJ1ZBkcsZRBZRBc1J1:JZJBc)1)ccsc{s֔kcksŜťJ{):sskksc{{ckskckk{{ŵccc1:BBJŵsc:kŵsZkRs{k{RRkkBZR{kťc޵:kZskB!kksRZkRZscccB:1J:s1Bsk{R{Bk{1cBBJcBRRZ11{kJcBR{Z!):kJZJ:Bs:cccksBcJckcJcJsBRsc:!::1)!sZksJ!s::)RJ1B:ccRR1ZJsZJZ1!!)!:)))1c)BZ:):Rc)1s:Rk1!BJ:::JZkZsBRkJJJ11!J)1BcZkBBR1{BJ):J)!ZkZcsBZcZskskcBR:BR:JJZc!k:ccB:cccZR{Jc{sZcBRBBB1RcRRsBJ:scRc{ޔń{k޵scss{{Δ{{cskccJck{sZRΌ{{Zckބޔ{:1:{:{քνŵsZBRkcZZZcJscB::Z{ZZkkcRJ1JB!:1!:RscB1:cJ)1!kZcBJJ{kkJcR1{RZs::Z:BcZB:Z:)!!B)BkZc!Js)JkRsc{cZ{Zޥ{J:J{kR:!!!)JJJRJZkkZcksZ!)sk{kJ:::BB1RJRB1BRkJJ)!11!!!)BJJZ))!BBZcRRR!1)!J11)1B{!!1c1ZB:cJBZJck:RccJkcBcRR:BJckRJBRkJBJ)kcZJRsckcRJB!)1J:JkJRRRcRcc!ZRkRJZZksZcBRRZBRR1JcJJc:JsJsk޽s{ZJRJJJνZ1B1!k{BRRsskkss{csﵥ{s{kkZZkZssΌRcŭΌR:Μckkkkks{Z{kcs{ccRskkBBJkRsRJJkskccZ):BRRc:)kkcZB{RZcJcJ)csBk)sR):c{sR:!!JJZsss)ss1cJc{1R{k:RRc!BR1:ZccŔRksscRs{sBkŔ{JBskc::B11kZ!!)!1:)!)RkR!kZR!:B!)!!)R:cZR{sksJ{kJ{ks{cRRBBk{s{RZccRcZRsBZZ:kZZRRRcJBRJJ:JRJsJZ::RsBskc{cRBZ:RRZkZkRZ:::BJBRJZRZsRcֵ֜kkBJJJJJRJRcΔ潭k{RB{csZcZ{{JZRsR{RΥkJ!ΥkZJss{{kŽksRZkss{kksZRcZkZcBkJk{JZZkcRZ{Z{JcRB:BBk1JZ{{BZBB{ZRJkZJcZ:)k:RkJJ)1:sc1ZZZcJkkZRsccsZZcRks:kckBsck)BR1BZ{Rsk{R{Z{{!!c{Zkcs)1RZ!)!)!))))))1:1!!!)ZZJR)J!J!1J!!:))!JRRcBcskZ)cksccZRs1JRck{{{RcBZZZc:11JBB{:J)1:1!ZRZZ1ZRJJsckc{JZZZckkZZZcJJZ{sRRcJR:::JssZZcŔ{s{kތ΄愜JZ:BB1BJ:RRRBZ֜{ckc{R)RJBBRkZZŜŵZs{{{kskkkssk{RsZ{kkcc{Rsk{skZcsk1:csZcRZZsksZJRJ:BRB)1{BZcRZRcssJ!ccBk:ZkkJB:s::1)BZkksc1cR)cZk:Z)R{JssZcRs1kkZZkJk1ZRs!Zsk{Rss{{Z{skZs{k{{kcZR)s{1Z!1!1!1!!!!1!JcsB!Z)!)!):)Z:B:{BskcZcJRckkZ:ZkRRRks1RkcJc!)ZZscBRRZJskZRsJ::B)!JZBRJssZ:JZJJ:JkJRJBR{ccks{cZZsRkZ{RŽR{sΜ{ŔRޜsZBJZRRRRBJBJ:JJRZ{{sZ1Jkk{{{kk{c1k{:ZZBkkksޥsscksRskBZcs{c{BRBZkc{{sZc{{ZcsskkJkcZ{ZZZs{kkZ{{{cc:1JJJBk!::)!1ZJJksR::RZRZ!{:RJJsRk!R)sZ!Bs:s1:B{J{{{scZJkRZk{sB!s{k{s!)c{sscss{{:kk{):!Zc{cZcss{ks1ZcJZk!!!!)1)Z1BZR1)!!:))JZ!)!:1)1ZB:Rsc)BcRR{JRZkRkRRccBJZk):RB{sZRRZRcc:k)R::R)J!!1!!):JBZRRBJB:JJ:J:sZ1kc{{ZBc{ssc{Z{sRkΥ{J{ֵ{{kssZ:ZJ:B1JBJJRRR:ZBBJRRJss{sZJ1J{{sc{sssŭ{Zs{c{s{kccc{RRZ{{{{{JZkZ{ksZZcZcJJJcRZsZR{cZZBs:J)Zsccc1{!)Js:s)ZkkRZ{JsZZZ)ss)ZsRc!)Z{B)R{c{kRcsZR1RZZ{sk:k{1kJ:{scsscck){k{cZB1Z{skZ1Bss{ssRcB:ZckJ:!)1cck:11!)BBB)1cJcB!:B)J!1!R:k{BZBks:BsB1))BRBkR{k:!JBZkJ:cR:1)c)cc:k!c1J11:1B:::Bcs)!R!J1RJBRBJJBRsskJkZk{ZZZֽsJΜk{έk::JBJBJ:BRBJZBJRBZBcBRcRc֔s{{kcc{c{R֔{kkkJk{ssRcskskkkckkcJsskk{kZZks{{skcZZ:kcBscsZ{:JckJ{k:ZksJ:Bc:RcBBRBR1RBkcsB::ZZcRJ1ZJ!ZkJsZRc{kcBJZRZRs)cscBscBJsZ{ZsssZ:1cc{cZcRsB:RkJRR1Z:J:B1!!!!!:!Z1J!B{1kRB:R!!BJ))B)1ccs!):R!!:B)!:11:RccZ)1B1JRBBccB:1)B1!:B1:1:Bc:1s:1):1BRRZRZJcֽskkB{{Zkތ愽kZ{{極R:RJBRJBB:BJZRBJJBZBRRBJΜ֌kkskckΌťΌ愵ZJ{k{{BRcRRJckcc{sZs{{kckZc{ZRssRJsZZB:ZkJkRcsccBskZJ1{{kRsZcsRZZBZZ:JBBJcJB{{JR:kcBk::::{RkRk{sRBJk{cBB!{!1:kc{kskcsZssk!R{ks{kBZZBR:1::B)JckR!!!!!!B1!cRR!:11JJB1B::!1!Bkc):)!R:c))))JBJ:Zk:!!c1BB!R)1B)R)B1)1:1!)J)J::JZBRR֜{JcńcccsksRJBRJBJBBJJBR::B1RJJBRJJZBޔ{cֵskks{kބkֵ愔Rc{skZR1skZZ{cZscsR1k{ZRBRk{ZJZJcZ:RR:RZ{ss)sJZJ!B11R1R:cBJscBkBRkkRZJcR:B1BZksJkkBs1)ZRZssRckR1kc{s::))1:!!BkkkkBZck{BJsskk{{kBB:kJ!1)!)!:JRBc1))!1)Z!JBZcR:!J1:B1:1!!)kJR!11skJ:1Z1!)1):JRJRkBR!ZZ1J1)!):c)BB)1!1BB):)!:11J)BB:BBRZRB:skck{Z{ckŭskZRJŵJ:BJBZBB:JB:BJBBR:ZR:B:BJ:RBcŽ楄{Zs֔scsΜ{ZsZ{Bcֵk{{sRJ:sckŌkkssskscccBskRJ)kksJZJ:JRZZ{ks{1RkkckBkJsRZckkJcBZRR{sBB{JcB1Zcsc{ZkBBcZRZskJcs:kcc{{:ZssZ1!ZcZkckJk{kckkss{BkRR:B:)!!):BZRkZ{:k{BZ:))!!!Z:)1!):::)))!1!1)1!)):k!::RkZ)Rsc!:BJ)BZRJsRkB!)c):B:!BRRB)1::1)!:J)B:)BcR1JJ)B)B:1c:JRk{{sss{kcs{֌ŭ֜cZZcZcJBBJ:BBBJ:JJJRBBBJRcJRZZBJZB)Jť{ք{sssŭs޵ssksc{{{cZkc{kk{s{kkss{sccRskJ:JBZZ{ssc{ބckccsZZkJJ:JJBk:cBskBksZJ{cskJJB{kkZ1RRk1:ZJkck!BJs{RsZRBk{:RskRk1):!JBJcR{:)1:)!)::B1:1)k)1:!)!!J!))::B1:!!ckJZ!BR:)1!B!!)J11J!!RB1!!!::R!1)!)!:J)k!)RB!c:B!):R:11)RJJ:ZZJ)JBB::JJB{ŵs{{kRsŵ{sRc{{{JBBJJBBRR1RBBBB1RJRJ:R1RJJZJJRBcB{޵޽{{c{ֽcΥZsck{RJZcckckkcZscέ{νs֥RJ{k:Z{k:c{csk{cZZ1kB1BRJBsRZJZkZJJJZRRZJJZcRR!k{{BBckB!c{{sBkJZ1JRs{{{k{sΥccsR!:))!)!B!!)1!!)!1)!)!)1:)1!B!)!:!JkJ))):1):)!!1)R:)BJJJkc1BB!!11BcksZB11:!::ZB!1))BBJ:!JRB)!R:11B)R1BJ:ZcRBZccZ{cŽcΌkss{cckJJ:BRBBJBRJJJ:JBBJ:JJBZJZBBZR:RJRZJR{Ō楥֥s{s޵{c֥sksskscZZc:s{kkťkcsc{ΌZcބs{cBJ1RRk)RskcsscckZZkk:ZR:kkRJ:kZkkRcscZBc:kkZsB!B)ZskkkBZkRJZkZkcckBJ1c{Z{csZcZ{!1:!1:!!11)11!)1)!1!!!J:JJ{RZ)ZJ1!JsZR:B1!::B)BBB!c):!:!!1!Jc111!1!:B!1)RcZ:sZkRsJJRc:cc{ZR::B1J!B)1))B11B!RB!1BB!)1)B)JJBBcB{εksccskcJ{k֜BB:B:J:JZBJ:1R1RBZBBZB:cB::BJJRJJRJJJJ{ŭ޵愽sν歄{csk{s{ccs{ckk{kŽ{ŭcsŔRsc{R{cks{{kcR{cJJBs:JB:k{kcksJsBc:cBk)JB1ckskccscBscZkksss{{)RZ{{{Z{k֭kJ!!))!!!11!!:)!R11)B!)!!:B)Z{cZRBRk{kRkk11:::!R1J!JB!:))B)1!B)):B!!BZJkcJkk{Z:::!:kkRZRRs!:)11!)1!B11B1J!RJ1RZBZ!JR1Bcŭ﵄Z֥1:cccsŵcksJ:1cB:::BBBJRJZJ:Z1RR:cBZ:ZZJZZ)J:RBZZBJssޔ楜Δ{Rssk{s{R{sZkքsk{{{kc{s{{{ssJcRskJk)BZk{sZk)kkRRkZsRc1BRB{kZs{{sJRcZ){ssRcB:{{kcs{R:Z1!!!!)))!1!11):B!B:!)!!!111!!))!kccsZ:skscsJ1sB)sZ:BB!Zk))!!:!!B!))1:B)!RBJ1ZJRZZJ)JcZcZ1!!:)B1JJ1)1!!1B!!:B))ZZZBJJB:1)B:1:RBkcŭsRssZsk:ckRZ޵{cZBBR!JR1J:RR1::B1BJBRR:BZBR:JJ:BJZ:JRBBRBRJֽŵ{ΜŽΔޜcJkB{Z{ss{sc{kBk{{{ksBcsZ極{RcJc{s{ssZc{{ZBBs{ksRR:1cR1:)BcsscsRJR{sZcBR{cJZcB{JZssB{{)k浽Z{sk{BBcRB!B1!)!)!!)B))))B!1)))1B11!B)!!!B!R!Z{!1:)JΜsck)Rs1:Zťk{c)B1)1!)JcB!):{)RBc1)B:1B!)!:Z:)1!::J!!R1)J:):B:)!:J1!!:BB:JJB޵εks{sBνckR{R:RkkcZBZ1:BRBRJJZ)JBJBBJ::ZRBR:BBBJJRJRBRBBBZJJBRR:JRBΜΜ{ΌsֽcsRsZZkskks{cΌskkk{kJZZ{Js{{ss{{B{sZBZcB1RcR:kscZsZkcZR:sZZcZsks{:Rc{ZR:1ck{ckcBZc{ks!):!)!:!)!)!!!::1!!1JB1!)!)1))!)B!:!1)J:1ss{BJksk:1ZRsRkZkcc)1!BJ)!!!JBB!)BB11Zc)))BBBZc!!:!1ZBB1:Z:!1R:1!11)RBBB!)1B11ZBJ1BRJcs{k{cksksskcZRccc{s:RcBB:BB:BZ1J:ZJBJBBBB:BBJB:J:BRBJRZBBJBRBJRBZRJJRŭ{{kskZRccRcJk{kZck{J{RssksZc{{{{{s::Rscc{RcRBJZJc!B:R{RcJJZccck֥ZRBJckŌR:{kckcc{skkBJsZskk{cB:111!!1)!)1!)!!!)!!1R!!!)):1!11)!:1!)))!!sskk:)))!1cckRZZJcJkJZc!!JJB1:BJ1B!:1!1R)c1J)):11B:B1)11JJR))R:ZJJRBJ):)B:)!)!!!c1B!!RRkcJ!1RRJ!BBZscskRZck{s{sc{ΌsckZJJR:1JRZJ:B1JB1JJRBRZ::BB::BJJJRJJJ1ZBRJZBZBBRRBcBŽsބŭťޔkZZckckZJZsk{{skZZccss{kcs{k{{kRJcZk{{kkkkJJRBcZ)ckZsJ{{cZRRZsZckk{RZJskkZ1cJ{ckBJkckskk{BB)!:)B)B:1!!!11))B1!!:))!R!)!)!sZskkZBZ!ZJsck1scB1R:B)!B!11)!!:B:1)RZRB!)1B!))!:kk{cZJJJcRRJZckRBR)!)JB:B)!!):::ZZBB)1)1BR:BJRR!:J)cssZscZsRcRscZ{Zkc{έ{ksJBZR1J:R1BBRJ:RJBJ:1B1J:JJJZJ1ZBR:BJJJ:JRBBBRJBRJBZR:ŭJR歜քkޭ޵sֽJkZkBZk・{s{{{kZJkc{΄{ckcsZRBRkkR{s{RcZskZB{BJcRkZkk!RcJ:kscsΌs{sJRJ:B{ZsccJc:RBkcBs{{k{{kJ:R:))1)B1B:1):!!1)1!!!:)1!)!)1)R!)1!!Bs{s{RZ!)!ZJcc)k{J!B)Bk!)!))))1)!RBJJ:J!BJ)1:)!!!))!)BR{sRkZccZJ:B)RR1)!1)11BR1!)JZZcZJ1BJRsZ))!R)Z)!:kJRsJkksZkZZ{ksskJJBBRJJ:RJB:JJRBR:JJJR1RJJ:BJ:RRBc:ZZ:ZJBJJJJJ:cJ1JBJJJ{浵ŽΜkνskJ11c{kZc{{{{ksR{{c{֌sZs{ssskk{kBBJscsZ{:ssk:cR)Zc{Z{Bc{cck{sZscsRRRBkcR{{{c:kZB1JRJ)1):1!BB:!1)):!)1B!1!)!!:1:)1skssc)1)Jk!BZcZcRBJZ:RB1JRJJR):c1!!)!)R:ZB1!cJs)RJ::)::!1!1JJ)1J1B!1:::R1))!1!J:B):B!!1!J!:RJ!!J:JcB!JZkcJ):1!Jck1!:BJc1Rc1{{Bckc{RccJsRcZRZB:BZ)ZJJBZB:BBBZ:JJJBBR1BR):JBJBBJ:ZBRcBJBBcRJRJZ:BBZ{sŔcs{::Jkk{sΔkZ{{ck{c{cksΔkssk1cZRJRcsZs{s{JJk)kRZ1kcckkJJkťscR:c{ZZccckJkZZkZJs{{{{scskR1:BJ1R:csB:)!):!)!!!1):!):1!!1!!!!11:!B!ckkkRscZ:RZRcBZcRsRsR:kJBJZ)BZ)!ks:!!:!11:B))RZ!)1!!){BRJ!:!:1!!)J1BBB1)!BBR)!)!11)B1Z1BJk!!JBRZcRJ1!1:J!:)1B::kkZsk{Z{B{kcΔ1R:RBBBB:RBBRJZJJJ1JJJJ:RRBRBBZRR1ZJBBRBJJcBJR:RJRJBJBBZBR޽޵ŵcBc:!)skRcŵkkkZkck֭֜{kkֽkJZ:ZZcZ{Zs{{JJkBB1J:{B{sBscscckccskR{RBs1ss{s{s:B!:1!J!ZcZkcB:::1!!!!!!BcJ:!:1!))1))R)))!!)1!!ckZR{sRR1)B:RBR:RZ)Z1ks1BsBBR::Z1))1BkcB!B!::1!))BBBR:s{:1J)JJR1B!!R!!!)!J!RkR)1:)1!!)B)B!:Rk:!kcZJ)1):BBBJ:Z::ZZkZބsJRR{s{sc{sJRJR:JJRJBJR)JJ:RRBkBJJZ:JJBc:RJBRZ:JBR:RZB:RJ:RJRRJJRR:ZJJRń֥JZ:BB{cBkk{kεkss{kkcsZc{sck{sRk1cBZsRRJZZ{k{ZBRcZRBBJcZBsk{RJZkZcskcc{kc:!Jk{Z:1Bck{Z:J11sJ!:!!1:cRB!:!1!R)!Z{c{J))!:!!B!1!1!!1):!!!)))B{{cJkscck!ZBJJckcR!!RZ::):BB:J:ZRJ:kB)J1BJ1:JJJZcZ{J{R:J)::J:R)::1B!B!:!!1B!)Bk:)!!ZRB)BZ{RcJ:B:1)1))RBc:k{{RRcsccJZR:JJsskZ֥޵ބZBJBJZRJJBJBZ1RZBZJBJBZJ:JRBRcBZJc:RJ:RJBRBJRZBJcB1B:J1JJRZRJcJŽ{Žss{:!B){{Rssk{{k{sRkcRZk1Rk{ssksBZs)B1RZ{:BB)1!RBs1JBBcs{Jks{{1ksRJBBc{cZJJsBsZBJ{{11Z:!RBBJ!1RRJ1):):BB1!)1:B)1!1!)J)J1)1))1:JcJR{k{skZBR:J1ckJJB{J))Z::Rc{s!BZBJR1J1:)B::BRccRRB:1:B1:JBR:!:!!!!J1!BB)!R1!!!)B))!!B1kZRJ:)1)J!B)!1))JJcRk{kRR!:cccs{cZRJBJBR:Z)ZJBJZBR1J:RZ)RRBZ:RBBRBJRJZRRJRRRRJBBR:Z:BRRZJZcBB1BBBJRckkΥŌŭc{)11{Ŕsks{cs{Z{skŔ{ZcֵJRJ1Jck{{RkkRZksRs)JcRssZ1BB{ccsR:sZJZck{ksk:ZZ{{Jcks΄{ccc{BZZJ:kBk{c{RR{:JBsZ1{sJB!kRRB1J))!1J)!1!)1JJcc1)cssJ)):J!RZR{sc{s{kkZckcsZsR)))Rk:JRBk{1Bc!kk!1ZcJ)))BBJ)::BRBskc1J!1)JJ11!1:1BJ1JBJJ))!BJ!J11!1!)!!1!!BJ:!11111!!cR1BBBB{քJ{RJZBJJBZRJBBRBBBJJJJ:ZBJZBZBRJJJBBR:JJJkJJBJZZJZJZJRZBBcJZ:JBZJRcJZ:JBkΌZZ:RR:s֭{{kck{ckRcccs{νťkJ:RZ1RJBBJs{k1ZJJRssZZcs{c{{cR{kZsBcscs{{!!ckscZcB:::BR:ZRckkc!JcJ!B)kZ))!!ŔZ:1RkBR)c!BZR)):JsZkJ)c{Zkc1sccBkńkkRsc{ccRRRsJRkcc:))kscks:B))BJc!:B!:1JRBJ:)1cBcc:!BJ)B:R!!)!)!:11JJJc{{1))BZ1!)R!Bc1!!!!!)1k1111RJJ!BZ:)!JB:k!ssk!R1ss攵ZRŭZccB)JJRRRZJBRBRJJJBJJJZJBRJJRJRJBJ:BJZZBJZJRJJRR1c:RRJRJRJZRBRBJRJRRcJ愌kBk:)Zs{sss{{R{s{ΜkRRR:BJRcsJRRJ{RBsRRR:ZJskk{RZRR:BksRcBskRJB)ZcZŭ{cck{kJ1!)1!::ccZsscskBRRc1:1)JB1!J:{c1!kskk1B{{ksks{)!sksJ{kZRZRRZsJR{kccscsZccB{sJsss::11!sk1:k{c)!)BB:11c):::BJBBZJZ))!kRRc1BJ!)B!B)))J::ZJ)B))B11JkBs!kJB11R!!)J:ZRcsssksRR11))1)):!kR!!)!:Z!sބk{cJkZJRkJBRJB1R:RBZJZBBR:BJ1BZBJ1BRJBRBJRBBBJJJRJBBJR:RJBZRJZZZJJJJRRR:BRJBZB浭{:BJks{skck{ZֵZcZsZk:J:Jsk{{ZsJ{ckZk{sBBBsZ{BB):ccskBZc{Z{JkZsBcc{kkc1JcscŵccckcR1:ZJkZZZcskZsRk!B!)!)BR:!)Zk))!sJs{{{{kB{s{c1R{kRc:k{{Rc{kRJ:1JBZRcsZsZZ!1c{1:kc{kk{!):ZRZRZ)1!!!cB:B)JR::)11)J!kZB:1!:!c)!!c:Z:1::!1!!)J1!J)B::J:B:cRRJssZ))!!))!1Z1))):!:BkBB:1kscs:sJB:J:R1BJ1JRB1RJBRRBZJBcBZJ)JRBZJBRRJRRJJJc:RR:ZBZBJJRZRJJJBRBJRRkJRRJZνsZBJ:cŵ{ŌŵΥŭޭscc{kss֥JJBkRcc{{kZZ::c{{kcskZZsk{cc{cZRRJcZkckR{ZRkZckR:c{sRcZckkcsRJ){ZZcZZsskZBBkRBB!1:!1Jkcc1!1kkskZ{1cJckJ!!Rc{{)JRRscssc{{Zks{RZc{cJ!{{cBkZsBkZ!JB:B!cB:JcJ!!)1:kZ:1:RJ)RB)BBBBB):1)!!:!!)!BRRBZB1:!JB)1)1!)Z11!:c:ZR)JJBR:Jkss):!11ZJR)::!11)1!:))ZR)JJBsk朽kccZZRRBJJZB1::R:RZB:JBZBZJ:JBZR:RRJBJRBJJcZRZRZJRBRcBRJRcJJBJZJBJRZRRJ:ZBŽ{{{kcscc愽{kZR{kcsZBJ1JR1JskkZkRZ{J{k{Zsck{cs{c{kRJcBJcc1ssRZRRRRsJckBckckRJkތZBscckcR)JkRRB{Zsscc!11)kc{Z1!)))!RZ)cRJZc{1csckBJcZ1:)::sJJcJ{Bsss{scB{kss1kRkcss{)Bs{{sZkZc{ZscR!J:cs:k:1!!ZZJ::1:::)J!!Z:B:1c1B!1)1JB!BR!::B1Z1!:B1R))BB:1B1!Z1JJR:ZBZ1cZ!::RBRBJ!!k))BsB{{ccR):{RBBZΥJ攭sk!sskRJJBJR:BRJR1RJBB1RBBRB:BBBBJZBZBRZ:RJRBRJJJRcBBRBZJZRBZRJRJBBRJJZBJZZZkJń{ŭŔŔŔ΄΄ֽ{kkZsRks1BBR:1s{{s{skkkJZkcckkZksZBcBRkZRBRRkc!:ckR{c{scssRJBsRRJkRcֵ{cc{BB:RcssckkJRcZZcZB11ZR:BJBRJ)!1:kJZ!ck{ccc)!ckkZ)s1{ss1{R!ZJ{{Bs{kkkc1Rs{{cBc{scccRsR{ZRJZB){cR!{{ccsJkJ::RckZZ1{)JJZ!BRRJBJRB!:))Rck1ZZcBRZB)::)!:1)1JRRkRB:BR)!kJZ1J))!1R1!JB11RB)1B::BZ1JJRB!B)!:BRsc{{{!)1:!J:Z{c{k{{sRRBB1RBBJBJRJRR)c::RJBBJZ:BBJ:BBRBZB:JJc:JRJRRBRRBRJJRcRRJcJRJJcJRZBZRZRRB{kΔ{ΥΜ{JZccs{RBRJBRJRJcsZZc{RscksJ{cJkk{cJRckcBJkkkkk{Zkk{k{c)JJcJkcRΥŵkssZ1!1scJskcRRsRcsk1ckk1B1:1))cZB!R1ksR!11ss{BBRZcZ)JJskk1{{:cRJssskRsscJsZsZZsBZ!!)cRZcs:1):ccc1ZZcJ{BB1cBJBR)RJZ:):R:B1)1R)RZR!)B:)))!J::B)kB1BZ:B)!111k1k!B)J1!!:1{1BBJJJ:!RBRJJ)!RZJ11JB)1:c1JsJ)!::RJ1RZsνΔZkJsckscJsJ:JBRJB:BJ:JJBZJJZJBRRR:JZB:RBRJBBJJZJcBJBRR:ZJRJJ:k:JZBBkJcJRJZJRJJBZBZcΌ֜έńsc{ccks{s{J{JZB:B:1B:ck{{ssckcJ{kc{kksk{{kk:BRJZJZR)1BZ{JksZ{{kZRZRZsR{Ž{ZsZkZc{s{{skcRkJssRZZB!:BkcJ1RBkJZscZ{ZJJZB)ZcJZJRJ{1!:RcskJZJ!ckkcZJ1cckZZRcZZkJZkB1B1:R1JRZZ!:{Jk)cRB:RR)!R)RRsc:1!{))!!1!1):J1!:J:1!k)!1B!J1B:JZkB!!:R1!):JJRJ!!!J):JJRB:J:JBcZ11!R!)ZJ!:Z{kJkc1)!B)J:)BJZRsޔsRsR:kŔkR{s{J1ZBJ1JJBJB:BJBJRR:RRRR1JJBBJ:R:cJ1BZ:RBZBBZ:JJJR:JZ:cJBJRBRRRJRJBZBcZŵΜńk{{޽Z{ssk{ss{ťcR:JB:Z:B:Rcsks:ks{{{scsBcsRkJskkssRkJB:JsRRRRscRZJskskcBJssB{ksk{ck:)!{cJkkcZkkJc{cskc{JRRRJ1{c)c::BZZcRkRBkBZc{cc1!RRZkcRcck:JJ{cs{c::sRkRZ{kskZRRBB!!)))JRJZk)s1kc)cRR11))B:)Rs{1)1:JB!JBRJ1J:!B)::B:)!J:R:)))!!!)RB:RJJ)Z:R1))1!!:1B1!)JZRB1Z1:1BR11B:1RR)JJ)R)1!)!1J:)::!:1RJskB֔ccR{skJJBR:ZBBRBR:ZRB:B:JBRJ:JBRZ:BR:RBBZJB::BBJJRRRJcBcBZBBRBRRBJRJcJcRJZJB{ֽ{{{sssέ{ﭔs{c{ŭBRJJR:R1BJkkZkcZZskJZcskksscksRckskkssRJJZZ{scsZ1Rk{RsZcJ:BJŵZRssJ1!!R:BR{{scBZksskZZ1RZ)JssBkB1BJcZcBZBRJZBJkk1ZBks1:{RBΥkckB)Z{ZJksJckJR1JZc{RcRc{{J1)))!!!ZJ))BZRJ1J)!BZ)!BBJJ::::)!:BJJJ:)R:)!B:ZkkR1JB:BZZBBkB1BB1J!!)!Z)):!1BsBRR:J!JZ:R)JBB!!!!1R:!sBB!!:))!J1:J)ŽsRRck֭{΄RcJJRJBBBR1JRJJBZJJJJBBJJJJc1ZBJRJRBRRJBBJJBBBJBBJJJZZ:ZJRsBRZ:JJBRRBZJZ֜s{cֵ{kss޵ޭs:J:BBBBJsŔscss{kkc{RckckJskBcs{skZsJRckZZB1B{c{kkcRZ:RJ{ŽssccRk{B1)1BZ{scZZccs{kZscZkc:1:JB:!1BZ1:Rssccs:RkkRB{sckZk:JsZ!JB1cέcZs:JsZ{){RkkBk{sRkZRJZZsJsZsk{J!!)!:sRJ)1!!!JJB!!R:Js:)BR1!)Z)1B1B!1)B:BZR1Z!Z!cJZB:BBJ:JRB1B1!J!JBR:RkZB!!!BBcJ!JBc::!!B)R{kB)!)1!)J1J:J)1sRޭk{JΥc޵εŭskZ{R1BJJ:BJJRB:cBZ:JJBJBRJ::JBZJRRBZ:ZBRJ)RZBRB)RRB:ZBRBZJcJcZJRBJZJZZ:Js{{cssֵ֥BBBB1BBRskkcccccZR{s{RksZk{cBJs{s{ksBJRsBc:BccZRRcRkk{JRB1:::::BJkcZJJccskcZZ{ZcksRJZs1Jc{):!):RRJ{k{:{ksss))JcZkBJZssc:B:k{ZcsZ::sJcZck:{csZc{{)BJkk:!))J!)1!BZcscs{cJ:1!k)JBJk1J)J)1::))):)J1JJ:!BZRRJ:)!!RB!1J)JBZRBR)1B!!Zc!BR!!1JZ{kRJB!!:!JJssRBRBJc!):R!))BBc!1Z{{cRcRksΜ{ޔkk֜k{sRscBRJJBBBZBk:ZJ:cBJBBZBRJJJBJRBBBBRJRJBJRZJBJJJJBZJRRB:RRZJRRRcZBZZJZBέkk{sk{{{ŵ޵έR::BB{s{cscZcc{kksJZRcscc:BBR1Z{RRRkJR)ss{BRJRkkZť{ńZJ:J)1:c11B!kRRkkZJcsssJsJkZ1skkks{ZccB:J1RRcJccBkZJJJ:c:RZJJJZcsk{1:kssZRJRZsZk{ZBRks!!kc1!)!:Rc!!B11!BBJ!:):)11BBB:B)J1:BJ)!J!!))1!)))Zc1J)1B)!ZJZR!))RZZ1:1BJ!:J11JZJ!!1:!:1:s!11:R:JRRB!!!c:!!)!R!:J1)1))JB!J!!sksB)BZckksνΥŵsZkccks{RkkBRBBJBZJB:BBJRRJJBZBZRJJJJJ:RJR:JBBJRJBRBZRRZJBJ:R::JJBBB:BRRJRBBJJZsΥ֌ckkkscsޜֽkB1Bc{Rck{R:sskscskckJRZJcckZkB:cBcJ1BRk:skZZskZZsR{B)JZZ1RcZ1)kZksBkkZkJkcŌkZJsssZ{c1!!!11cs{:ZJJksRZcZZ{RckZBcZRŜkŌcscB)s)sskRZZZ{{BR!)!1BRR:RZ!!:1c!1R!:B:!:cBB:B):)::cBB)kZZ!)):!:)R)c)BR!B1:Z:cZc1J))J!!!::RcRJ)1B)1)R)JccJ!BJ::1!cks:1JBc:cs{{{kskskZcZZJJJZJJJJJJRB:JBJJR:RRBZ:RRBBBZJZZJJ:BB:BZJZJRRJJJRR1ZZBRRBJB:ZBRJZJZ潭s{{{sc{sﵜ{{{{{kJBccskk{JccZcJcJJccZ{kkZk{R:k{s{ZRRJJ1:kRckkJcZZZ1BR:ccc{{cc{{cR֔kcRB{Zsckck){RJZc{{:B)1k{{ssZJ:{ZJZZ1Bk:Zc{sksRs{{{ZZcks!):))B))kRJJB:):!!:::)1:1R)RJk:1J)J1J))))1J:!B::1)!J1!::1:kB1:JBB!!)!:1JskR:sc)cRBJ:))1BBc:)):1!:J:!R1RRcZ!):cBZ{ŽcssZZ{kc{kcs{cJR:JZ:BJJJBJBJR:BJB:B:BRJBRZZBRJZBZBBRZRJRJJB:BJRZRBZJJJBJBJRJJRBR:::R{歔csccskZsk{{ZZZsccJkcJ{{s{{ksRs:sk{cBJsRJ1JBB)ZRJJsJck{ZcB:Rckck{s{Z{s֥{skJBJsZBkRJcBZJR:Bckc{ΜJJR{c{1BRJsZ{kckks{Rkk{{Z!)):1BR!)B:R:RJ)1!!)!cJ:B1B:ZR)J)1!JR)!)!):1:::ZJ!JR:1!1ZB:B1RB)!1)!B:skkRJR111BZ)1JcJZB1)R)J1!)JJ)RkckJB!RkB{kR:)k1ssZZ{kcsRk{cք1JJRJRcBBZBRJRRBJB:RJBJ:1JBR:cR:RJRJ1ZJcBZRJZBBRRJJRRJZJJZBRJJRZBBJB֔{s{Jc{{cΜֽ{{ss{ZkRRkcZcsZs{{sckcJJRJRZsZJ{ZJcskcέBBB!kskskkkR{RkkŽ֥cΌJksRcJRRŽ:BcRcc{{ck{RsΥskR1:s{BZckcZ{cc{{ssR:!)ZZ1!)!B:!!1R!!)1:1!)::B:JBJJ1J1JJ)!:B:!)!:1!ZZZk)!!BJRB:):B!!)BR)J!)J)11B:Zc:BcJc{cJJZ))!1::ZJJJB1:R!!11R1JZJ!!)JsRZ:{1!ZcccZccscc{sε:cR:R:BZBRBJJRZJ1JBBBJRBJBRBJJ:JJRBZRJBJZBZJJJRRJJZBJR:ZBZRJZJBZRR1JJcksc{{Δ{{{{cZccZZ{cZkZsRRBJ!1ck{c{kskRZcZRcJRZkc:JJkcc{ksJRkRRscc{sŭscsŭŵZRRc:!Jck!!!BZJ:BBRBJZsR)JJ)1!))))1s{ZZkJkBkB)!):!:!!!!)J!1:!!!1B1JB)B1:1Bc:B1:Z!:)!:B)J1)!:!:BcJc:1!1RcJBBB)!kk:)JB1B1RB:!Z):B:J{JksR::1!B:BJBR11BJ!:B)!ccŭ{sR)RJ{ZJBB)B!sJ!{cJk{ŜkZs{cs{ŵŭs1JJJRRRBJB::JJJBcRBZ:cBJRBJcBcB:J:BRBRRZ:RJBcBRZ1JZJJRRJJBBBJJZJZZBRJsŽ{ks{k{{{k޽cJ)k{c{cJRcccksZR:BkkZ{s{JRJkR{skkB{R{ssR!1{skZscZZZsJkkZZRZsŽޥޔֽքZZR{s{RR{k1:)!::JRBRZZBRZkcB!)!!))!R!!Rs:1B!)!!!!!!11BB11!k)!BZR1RB)J)1!!ZJZkcZ)1!JBBB1))!1)):R)!:!BJ!)1)!11)kJR)J)1:BJ1)cRZZk::cRck1)J:1R11BB:JRkc1!!!RcB:RBZ)!))J1!)J:1Z:Js{ZkZcs{{k歄ŵsRBZRJBRJJJcB::B1R:BBJJJRRJRJRB:RBBRBJB:RBRRRZJJBRJBZ:RJRcJZRB:JJ:JJRRŽνsss{kkZc樓s:Zsޭscskkcs{Js{k{kskcZkZZcsck{Bkk1sZcsRJ1Zk{k{kkcZRkZcZRcRkZkkΥs{RJJZckRBkc{{cZZskRRBZZRB{sJckRs)!!!::!!)!1!))!:))!)!B1)!1))!:!))ZZJ)1RsJ1)::1Jk{sJ:!!JJJJ1:!B::1!scR!!!):RRR)!!B:RJ!!)::R!J::JBJZ)JRcBJRB{)BZZ{JJZZBBR:RJ1:1)RB1!kR1:R!B!!ZkZB!J{J1:):c{sccskRc{{{{sZZJRJZB:cBJ:JJJZRJJJ:JBBRBc1ZRZRBJB:RB:Z:BZB::RJRZJJJZRJZZBBRRJJcJ:BJ{sss{sskk{֥scέs{kccs{{RskcZZBRB1kc{R{c:cZskkRs{νB:Bs{s{k{ssZckZZZccRZRZ֥BZkRksJ{kJJkkc:1Js!Bkcs{ssck)!1))J!B:!1B!!!!!!!!)!:R!!1)Zs{{֭ZJBJ))Rc1kBB!1)B):J1k)1Z)))R!!ZZk{{:!)!RJJZ:J::1))R)))RR:c)ccRZ1B::B1:kk1Z)ΌZRBB:B1B!!!B!)!1):)))ZJRB:!kR)1):B1BZ1BRksRsccR{kc{ŭJJRZZBRBR)1R1RJBJ:RBJRJBJB:Z1RBJRJ:ZRJ:JJJJJBJBRZBB1ZJZcJRBJZ:c:BJ:RRޔ{skcsŵֵZc{JsskRZRss{sJc{ZkkZcZ{ckkBBkskB))J:s{scckZcJZcZckcZc޽{:kJkkckkZs1k{J:!Js:kkskZ:!!)!))J!))s1)!Z!!!J)):!J)!:!!)!BRsťcRcZ!RZJ:BJ)RJ:!!!J)11JZ:R!11!)s:k{B:JZ:)!:1)J1!:k!1BZkJR:ZsR:Z1:Z!BcsZk!1cZ:RB1R):B11RBJ1B!))R::1JB1sB:k!J!ccJ:JckJccksZZksk{s{{cRZRJBRRBRJJBJRZZZZ:JJ:RRJZBR:J:JBRJRJZZ)RRBRJBBBBBRJ:JRJJBZJRJ:c1RJZ{ss{{攭ŭ攜JZcŜcsZZJ{cckcckZsZBRkkcJ1{{s{s{ZZkJRRkcJkcJkkޥZk{s֌BŔkckcBJBJJRΥkRZB1kB:B!1)!BB11:B:1::1)))!!!11)B)Ŝs{ZRRkk:!ZJJB){R1Z!1!!11Jk1!):!!)!s{kB1):!)JJRBBB11ZJcc:RkR::R:RcRZRBRBsRc{{cBB{!)BZB!):1::JJ::1{c)!kBZ!!1JJRRRB{RZcJZs{{{{BJB:JJJRJJJJBZJR:ZJRJBJRBZBR1RZBZRBRRJJBZBRRJRR:RB:RRJJBJB:BBR1RZBJJkε޽νέc{{֭:sk{sZ{kRZkRcR{J:sR{kքcZńքBB{k{scsJ{kZRkRRckZZ{kcR{ZJs{kŜkZZc{JZcB)Z޵{s{c)))1))!:!!!:!:1::!)!1!::!)!!)11:!!1kkZs{cJŭkJskk!Jc{Rk{!BcB)11J)JJ!!1)!!)k1BB)B:c11!RJZ):R1)BckZ!BRcsJB:ZRk1JJ1R!kJJsZRZJRkZ{k:)BcJRZJZ!)1BJ1!B1:J:cRckZB{JZs{)!1:RkRkkkcRcRcZ{sk{ZJZBRJJRJ)BJBJRBJJ:ZcRJJRBZJJZ:ZJBRJR1ZJR1JBJRBBBZJJRBRBJJBRJJJR1BB:BBsνťΌs֌ޥRRksk֔Zskskkc{{ksccsccJ{kkc{{ks{:!Zc{{kkksZkRkRZZckkckkkkŵs{{{JRRcZ1cs֔s{c{JR{s:)!!!)):!!11:::!RJ:))!11ZskJcRkRc{c)!BkkkJBRR):R)!BBJc:))!111B)JB:BR1))ZB:1B:!)B:sZR{JRRB))1c1BBBZJZZJRR!cZkscJB:kcs:ZZ11RRBR!1)1B:RRJ:k:!B:k1JZkscRJJ{cccZkZsBZ{{J{s{cZc{RBBBJJBcBJBJZRJRJRJJBkJZBZBRZBcJJRJR:ZJJR:BJJ)RBJJRJJZRJJJJZJZ:JBBJ{ZZkkk{kZckk朌RRsZccZ{RJJkkskJJ)kssk{{kccRsckkcsZkZcsss{Δs{Js{sksJ{{JJJ):)R朄B1)cB)1!1!!1!)!1!!J))!!)Z!1!!!!)!BJcscΔcZZc:Zckk{Z:J{csB1cJJJJBR)Z:)!!!!))!:1)!!JB1BB1J11BcJcRZ1J1BJRZB{RkRRc)JJ1kR:!BBkZZBcZ1J)kJRc:)!1ck:BJ1:11B::RJ)R)ZcZk!:cc)R1cZR)1:JRJ{ZkZZRRJkks{{sZ{{sBJBJZBJBRBRBJRBJJRZBJJJJcJJRZZRZJRBJRJJZBRJcZR:BBBJBRJZR1ZJBRRZBBBބ朌RskRkRZZkccc{RZBZcs{JJ:J1J{k{sskZsZZcRcckkccZ{{Zkkks{:RJZ{{kZJZcR{s{Zkk{kZ1!BZ:1!!)))))!!J1)!1R!!!!)))1{ss֌Ŕ{Zkk{1RsB)1kkk1BBRJBJB:J!:BB1::RJJJJk1:kZZ)1Bc:)R:BBJcRcZJc)!!:BJJJcZkcRZBJZ:::1J1JkJRJ:1BcRRRk!))1B)!1B1!J!BJ:BJJBks1::ZZ!1JB))s))JkkBcJkckZkZ1BccsZkssR!kJ:JBZJZ:JBJJJJRRBRR:J:Z:ZZJJRZRJJcBZR:BJBBBJ:RBRRBBJBBRJRJJZBJBBRsŽťťssskΜskkJsccsk{ZkkssccZ{RBJkֽ)1k{s{{kscccZckcskkZscccťk{ޜ{kJc{J{kRsk{RJsRskZ1)1!{kJ:!!!)!))!::!)!!!!!)!B!c:kRckZZ:R΄kZ{Js{)RcJs{)kB)::cBRB)1B:):B!)1c!k{:R:BBR1!kkZJRB)1JBJ:RBJR:cJBJRJR!BJB::1cJRsZcsRR!!)1!1)11:!1B111):):1J)!R)1kRB!1scB1!!!1{ZJJ1BZckk1JJR1s{ZRZkBJ{R{:JBRJBRBRJRR:Z1BR:ZJJZBJRJZJRZ:ZZZRRJRRZB:BBZ:JZ:ZBRZ:JJBJBRRRZ:ֽΔskc{k֭sccRZkckkskZZksckkc:s{ckkֽ1J{ssss{scscZccZZcss{kksccs{{kkJcks{skZc{cZccRs1J!!R{{{c))!1!B!::))!1!)1:!!1Zs1ZkֵŭJsBcckssBkZc{BZkkc1BB11Z!)BJ!:1kJB):R!Zs{RRJ:BZR):R1R1RcJR:1JZZRcZRRZ::BRZ)::1:BBJ:ckRc!!R)1B1:1!11:1:kc):1)B:1BRJ)ccRJ)!!1J!s!!1B:BkJR)JBkcZkތkcskJ:ZJ:JJBRBBBJJJBRJJBJRRJBJJJJJBJ:kJRBRBcJZRRJBJJJR:RBJRJsBJR)JRޔ{sŌkskJ{sc{ckkcZkcsZsZ{J{{cZkεJBs{s{ZRRcRkRZcZskssss{{s{{{c{1R:1)BBJcBRk!!1BZքk1!!))!kRcBcZ:cJ:!!!!!)!!!:ZksBk΄sŽքRkcΥ{ccsJ:RsBRZs!B!J:s:1JJ:J!::cZJ1BBc:RkZkR{B)!!R::J:)cJRZJc:RZBJck:!BJB:JRRR1s))R1!!JJ:RJ)1)::{1Bc!Z1!1)!)RBBJB)!)1RJ:1kcBRJ:RZBRJRkk{{ΌksskJJRJBBB:J:JJBZ:RRBRZRZJJBJR:RBZJJJBRRJZRRJRJRRcJBcRRcRJBRRRJJkJRΌŵέskŵΜ{ksRkZk{ks{skJRZkskZsRkc{JBk{skksZcckZJJZZcss{Zk{B{ksZkZksR{JRckRRc{JJ1c!JcZRZ1!!!11)BkZZZ!1!1!!!!:ksskZ{cs֌ťJεksBBB1sZZZRkZJ:sc!::k)):::B1!)cs:Zk:RB)1{ZRss{J)!s)R!:B:BRR)B1kRZ:Rk!BBRJR:::JBZJ!kB:!11ZBRsJ1!c)B:JR!)!J1:::)RZ!1):BcJcBJJRR:{RZB1!JR)ZcZcZkkB{Zs:B:BBZJRJBJZRZ1RRJZBR:ZRcJRJZJcB:ZJRJJJ1RRZkJJRZJJZRRZRcZZJZBk:cŵέZ޵΄ń{kckJRsk{ckRcJskccc{sc֔Js1{sks{{{skcsZZRksk{k{֔ksZcksksRkBRRZ1)B{J{sck:1!)csJ1B:Bs{sZZ!:!J))1JJcRZZsJ{ksZcs{cRBR)JR)JcRZBR:!:cZ)1:Z::1!)J))Bc!!:sckZJc{kkZkJ1::1)RJ1J)1)sZJJJB:BJ::JBB)1B)ZRk{R{JRB!!):RJ1JJ)1!!1BB)JJR:):11)1::B)1!))!kR)RBccBR::J::1Bk:1:ZJRkckskZZRJsJBJ:BB)1BJc:RJ1c:RRJJJZBZBJJRJJZBJcB1ZRRRBJZJcRZRZRBRZZRRBcJckBZkkń挜kZsckks{sccckc愔RJR{{sckckcZskkcksR{c{k{cskRRs{kRsJRksZckBJZΜskBZkJ1!1B:Z!BsskZZsZ1!cZJcB!:BB)1::!)ZkBRkckksJZZcs:{:kZB{ΌR)1RRJ11:1kZk{scRsc!!)))11B:1!JB11!)ck!BkcJsk!s{{sskB:JJcRR11!:!R1JJssc:!)RR!ZRRBRkZ)B1kB))JJ)))c:c!!:BBR1JBZRJJ!!R)))1):)RJ){cBJ!k{ZJ:!):1Rk!ZR)ZkckR:cB:ZRBJcRkckskZJBJJJRJBBJ:BBZRZJBBJRR:s:Z:RJRZJJJZJRJR:JZJkJRZBRRRZJJZJBRRJJZcέΥ{sΌŭΥ{s{{sZZ{{c{{{kckޔ{{ZJZs{sssskckkkckRckckkss{{kRc{{k{kc{J{sck:c:kk{Zkc:RckZZRsR{ccZ)!1c{RkR{{1!!)BRRJk!!)!JB)1J!):BRJRcs{JRBBB:csJs)k)!{cckR{{cťR:RBBcZsZc)J!:BJBRc:RB1!kskcBZ{JJcc{ccs:Z{R:BBkJJ)1B)!1:)ZB1!JRk1sJBBBZJ{JZBBR1J)):scJ1!B:BcBcsJR:JRJ::):!)):)!!!!1B1ccsBB11!ZkRBB1JJJR{B)R1Z!::cRRksJscZRcJBRBB:JBR:JBBR::BJRJZB:JBcJZBRRRRRBBZJkZRRRZRRcJRBRRRZJRJRcJRc{ֵssތέŜscs{{kkZs{ck{cZc{{csBJssskccksZksc{kss{{k{Rc{kZcJZckŌs{Z:έR{Z:1kR)Rk)1B)k{!!)!JRcZZ{11!)1:1!1kk1BRB1)JJB)ks{cRkZJZZkkc!!kR{{kJkk{ckc{{RccZc)11):!JJ1k1BJ:!)s1){sBcsZRZR):JccRs11B::JcZZ)BB:))ZBB:{JBJ1RRcJRRcBJJ1{Jk:1!R!)!!)BcZJ:!:RRR::cJJJ:1JRc!!:!)BB111J{BRRBJJ1!)B)1:):ZBJR!))RcRZBBkJsBJks:JBJJRc)RJJRBBZBRBBB:BRBRRJJJRBRBJZJcBZRBBRZJJRZJc1ZBJRBJJRRRJcZŭތ{k{֜ťsk{ZsRkZkRJkJRcskckksckkksk{ks{{{kcsss{:cs{s{1:skZRZB!JRRsJB!!!):!!)cs{J!B:RB1:!)RJskJ:)!Bc:B1BBcsc{JskcZkc)!)BcRBBsBJkZckRc!{cR1!!)1)JR!:Z::JRZc!RZJ!cZ)J::!cRs{sRkJsB:c:!::J!:B)scB1BckZBJc:J!1BB1kZc::k)BJ:BRBR!1cR!:B:RBcB)::ZZR!1)R)!):1c{Rskk:J1)1!111B!:J)BkRRkRZcZJRcŜccBBBJJJJJJZ:JBRB:BJJJJJJBBBJZBZJBJBcBZJBRBJRJZRZsBRZRJRRRBZZckΔ﵌ŵΥ挵ֵńkZc{s{cRZsZcsJRB:scsckkZcss{{{{{sZcRsR{cssJsks{k:c{{ccRcJk1ZBRk1!):1)!!!1B!cBkc:k)!)!!ZcZZZ1)!ksckcZ1ckcs:kBJkZkZ)Rk)))BJRc{BsZZckZk!!::!RB!!!)JZBsZZ{ZcR1)::cJkBk!):kkc1:):ZJBJJs{ZcRBŌZJRkcBsRBB1Rkk)Z:)BBB!:JBJ)1:Z1:cZ!JZ1!Z1RJ{B!!:)!!)B!Bsskks{RkJcZR1BJ:!)!)1JR!RRBcksRJJRRZZ֜ccks:kZBBRB:JZJZJBRBcBJZJBZ:JJBJRJJBRJZ)RZJJZRRJZZZZ:RRBBJcRJcJc֌֥ν{{kksR{{{JRkBkBZJkc{Z{ksksc{{s{{s{kZZcRsskRcs:ssskBkcRcksskBkB:BJ1:R!:!)B!))RR:kJk!:!!:BB:RRJ{c1!)cksk1ckskk)BRsZZ)Zs)!1{JBJRZk1BscZZk{kRs{c!c{)!!k!)RRZJ!1kcR!ZZ{cs)s:sŜ:1R!JkZRZRR!1J:)Jckc{sZkcJZBJRBBZB1BBB!BRc:1::):JRB:::1ZZRZ:J!1J1BR:s)!!)JZJZcBkJBJ:RZc:B!B)!1)1ZZk{ksJRRccRcckcRkRJR:RJ:JR:BZRZJJRJRRRBBRBJJRBRBBBJJRc)ZcBJRZZJcBRBRRBZk{Ō{cνŽΜs{sRks{kccs{k:JZss{{k{Zkss{cs{RcZBkksscRcsB΄1JkRsJkcskJRZJޜc!111!!!JZ!!!1!)!B!!1)!BBB1:BBRJ)B{s{Z1Jcksk:Zsssk)JBZc1!{:ZcJZs{{sJkccZ{{k:{!1JJRZskZ{BZJJRs:::c)R1Jks1JcZk::J!1B:JkcZBB)RR1:BkRRsZJ:JZ1B1RBBJJss!:Z:)ZB:R)ZB::J::JBR!BB!J!)BkR))))1BBRskkcRB11JBR1))!!))k{ss{cJZZZ!)JkZkkkRΌsZZckBRBB:ZJ:ZRBB:JJRRJRcRJJRZ:Bc:RRJRB1JBJJZJRcBBZRRJZJJk֭Žŵ{Z޵c{BRk֭c{kRZcsRRBBs{ks{{{{kscssJZ1ss{{{skB{RŵZkskR{Zk!Zss1!1:!!R{Z:!1:))1!:BBZR!)BB:R1)!!!!BJJskR!kJJckRBRkZJZZkRs1!:cccsk{J{{::Z!R!JsBR)k{sJ:csJRZ!)kcJc1BR1c:JZJk11B!::cJ:JZZRRBcRBR:ZJBJ)JkRRJBZ:R)JJ11B:!BRB)RcJ!ZRJJB:)JZkRZB!)ZZZsc))kk{kk{sJB:J:RB!1B)cZ:J{Zc1JRZk:cccckcZsk{BJRkc{c1BR:ZBJRBZJRRBB:JJRRJBRZR::ZJJZBZBBRZ:ZJJJBZJZZBZRs΄sε{kkֵ{{kRZsZcZscJBBskŌέ{{{ss{sckk{{csJJJksJccJskssBZZscRRkk{!)Js!)1!):)::!ZJB1RR!J1):ZJZcc:ZZ{sRZZR{csJJ1sccBs)sB{{csJZssZ)!)ksB:)Bc)kZcsB!1k!JZ:JBRcB)R!Rs!1!)1!c1J1s:kkZZBRsRJRRBJBBB!ZR1JkRccZRBRBR1J:c:JcJ1RRRZ:BBZBJB:RcZJcBk!!:1RJRRJJJRRB:)))Zcs{s):B:ZBk:)):!):kkkRJJJ:JBBcR!Z{cZkRJ!:)RZRZZ{cZkJJscBBB:BcBZBB:BZJBRRBRB:ZBRJZZRJZ:JJJJBBcBBJBBB:JRRk{ֵŽť{Rs޵s{{kcsťJRBkkkRBk{ŭ{{{{c{kk{RJJJkksJZcZcB֭{{ΜBRRcskcs)R)!!!!)J{s{1!)BB)1::1)B!):ck)::ZR)JR1Z1cckRBRZccR{kJc{Zck{ZJRcB::!RBs1)csJRZccs)!JJZJB!BkBJcsRc)Rc1sBBc!!BBJ:::R:Rc11:R:J11έkRRZJckRc{sZsRZB):Bkkcs{c:RJRBJJ!ZRBJ1!J)JZ1BJ1RJBR:R1RcBR:RZZZB:cJkkB:BZJRZc:J:ZR)JJcZZZ1BRBc::R!!!1!RcJssBRBBBRZ!1R:1:JkR:csBZJ:)cZkRB{{1:BZRRRBJc1ZJRcBRRRJ:J:BBJZBBc1ZZJcBJZBJRJJc:cRcck{νŵ޽sB֔skZέ{sJsZks{ֽkRJc{Ōss{kssssskkc{ZJsZkZkk{c{sc{ΌssRZsJkskJJc{k{ZJ:1B)1J111)JZ{)cJss!:BJcZ11:)c:1B:BRBBBJB):B!JJcck:Js1JZ{{RcZ)ZBR1!J!sB:BRcBRkZckB!!)1)BcJR!J:R)JBkB:J!JsB::)sB:)))R1R1:))BJZ{RRkJBJ:ZsBcsscJR1)R{sZZ1:BcBZB:::RRc1RJR1):):B:!)R!:BJB1ZkkJJB1kcsZZ11BJ)RZcRcRZc{{{RR1RB1BcBcB)1))1:JZcRB!1BJBJ!!)J!JRBJcs:JR:RcJsZZRkRk:::Z)BRZBcBJJRZJ:J:BJJJRBRJBJJJZZJBJJZZJRJRZZckksťŽsֽsZk{{k{s{skΥs!Jsss{s{{{{{sss{sscckZJcZRcZcksZccsccZsZkZ:kJc{Zss1::1Zs::JZ{ŔBZk{1)!:Z!BJ:JRc!)BB::RJJ1!:ZJZcZRsc:ZccJ:Rcc{kBJ:!:kZkc::R{{RsZZBc):!1:kBBZ:RJRB!11J!c:RcR!!1{R1B:1BB)1!cBB1)11Zc1kk)sZsJJJk:ZsZZBJ:!Js{{R:ZJRB1J):))sB)J:JRBBJ:cBRJ:!RZJ:JZkZ1!)RcBJRB!ZB1RRֽ!JBkRZR!!BZZZ)BRs))!:!!Zksk)!!!Z:J:!)kskcJccBZRZ:JJkcZckJJ:Bc:BcBBRR:ZR:ZJJZ:RBRRZcZBc:JRRJRZRJJcRcZckcŽksŌkc{s֭ccssckRZc{s{sc{{{s{{csss{cs{kZc΄kJ{sRZckZR{ΜsJkZR{sskRs{JBcsB!JRJsŌc{޵BBJB)B!!:)JBZ!RRJBBB1)!1:R!11!JccZcZ{)RZRcskkkksc)!JJsJRBck{{kccZRR!!:Z)RBJJJBZ))!11:)BZ!!!Z)!!)!B:BJ)):)B:B:B{JRR{sBcJRR!cBcRBZBJ:BJ1kRk1RJJZJBJZB)JRB:!1:BZJJJBJ:))RR1:BcB:)1ZZJZc1:R111J)JRk)1)J1B:1!Zs1!BRB:):J:!){cZ::B1R1RksRkRJBZ{cJ:kkskB:BJRJ:ZZ:BJBJJJRJZJZRBcBRcJRJRcRJJ1BJJZZccZsc{{ZνkέscscscZ޵JRs{csZ:B{k{{{k{kkcs{css{k{{{ZcZ{cZsZk{Z{{kcJ1JcZZB))BBc::):!))B!JZBB:):BJB)Zk11B1R1:)!1J:Bc!1RcJcksk1Jk:Z:RJcRZsRkBkZ{cZZZcsZZZR1J1B:c1BB:J:::B!)!!)BJ)!1:JJ:!!)BJB:)!R!R)Z:B!BJZJB1)!1{R1RJ)k1Z:1)::BBJBBcJ):R!::B)Z1BBBJR:JJ1JBR)ZJZ:!c:B)BJB!1BJRBc!J:JcRB:J:ZsJ:Z))!11B1RRJ11BR11{{cZZJZ1BBBZRZBJs{ν:kBRBJRRBRBBB:RJJZJBJ:RRcZBZBBZBZBBBBccRccRkRcksksks{Rkk{cŔsZRsŜ{kR{cJZBs{{sscsksZs{{ccRRsk{{{cZckc{c{Z1k:RJ:Rccc)1::1!)!1B)::JcJR::ZJ11!!JR11RJ:JJ:J1cR!ss{{1Js:J:RB:JR{:BBcBRJZZ1!!:ŵZccRc!)ZsZRkR:JRB1!!:J1!1R)1B)!!!))1Bk)1:11BBJB)B:J)B!1RBc1JcJR))B)cZB)1BZ11!BRRJBJRBR!R)!RB1JBRcBJ1JRB:kJccJkR1B:J!ZZR!)J)J:)JkR{BZBB!!:1R:BZc{k1:B!JJBJJkcR!)sckB1JJZJB1RRZcZRkZ{s{JJBJZ:RJJZJJJ1RJJRBBBc:JBRJcBRRJk:ZJRJcskk{sckcRsk{kk{{ތkֵŜs{΄ŔkcksZcJRc{{{skkskZsRkZsR{cc:kcބcJc{sŔsZkssJ1Bk{ZR)1)B1!c))!B)!!)!!B1):BRRRJk:JR)J:JZ1ZJ!BRJR11{ZkckJR:csBBZZcJZRs!)cBkcsRc1BskskBkZsJJ1!!!!{ZRZ!!ZJJ))):BB1R!!!)1!)1B!)RcZR1))BcZR1ZRB:J:RRc)c:ZJRBcJR1):JRkB)JJ:BRRB1R))R::!1!:1JRcZZ11c{){{kZBB:)!)RcB:BZ1:!1c{kR!)::ZJ:B)k:)):):kB)scJJ1sBB)1c{BRB!Bk{{s{:ks{Z{kZ{BBB)J)JJZJ:BRJJRR1RR:ZRJJ:RJBRBRJRZBRkZsckssskkkskZkk{ť{ksk֜cB1R޵{cRJJBBss{ssscscs{Z{{ks{{kskcZR{{ZJZsR:1s:1!cZ)JRkZ1J!1!1!11:)1skJJB{cccZJ):RJR)1)JRR:))::ckJJ1RJcsBBZZ{s{){{J):kRkRB!Bk{cR)!)!)!BZcB1)RR1)!)!1)!!1)1JJJcRJJ1J:J!!BsR)):)B1{JR!kޔsJRJJ::c1:RB1BRk:B1RR1RJJ!11:1!B11JJRJcRk1cccZB1!:ccZ1J::)BRBJJ!1!RB:ZRBcscJJs1JB!kR!1J!sZ:1:)!kZZJ:)))){s:RscBJksccsZ{sBZR{:ZJJJB1:J:JRJBRRcBRB:JZJRRJRRBJ:RRcccssZ{cssZsckks{ksZZZBc{{{s{{ctc֜kcssBJc{scccsskk{sń{css{cckZRkŜkkkZBcRJJk:1)BB:scJ1!!B!RJcJBJ{kc:sZJ:)11cBZZ!JZJB1:JJ)J:1B11JsRRJBRRc1J:JBcc!Rcck{Rc:ŜΜsZk{J!11{JcBssZ!1J:J!!!!)!))1)!)J:{J::Z1)1BcB!!)):J:kJRsJcsBRBJRBR:ZR1:)B!ckZJJ:B1JBJBcBB:sBBZRkkR::{RZ:ssJcBkJ:)1)1!11RJRRBRksJc1B1!RZ!)1JZJ:J!B)!sZB)1JJBZs{kRsks{{{cZcZJRBJJ)RJR:B:R:R1JB:Z)cJJRJBRcZRBcZZcckccksskcsZkZεŜ{νsk{sccscc{{RRJR{{sss{{kcJR{{ssckZ{sBskJB{{{ZJJRZckZc:1c)sRR:))JRck:1!sccR):ZZcJZZ!:JBZBcRBJ)J:1cZ:1!:!:1R:kkkcJ1JsZJB:!1!JJ:RckJcBcBֵBR)!1)R1B)JJBJ1!!!)!)1B):):JBRZ):1!RB)B:1!!J!J1BRZZJsRR::JZZBcZR:)):::JJkRBR1)11:sBRRRZcB1RsJRR1BZssJR1!)B1!!::::BBZRBRB1Jքk:1!!111)1B1RkkBZ!!11k{s!:J{{ZJkcR{kkcs浵sJssJJJBJZB:RBJRJZJBBRBBJZJkBRJBZBBZBcRcckskcck{{Rcksŵ{RRkŌ{{{cZ{{cŜ{kRZR{ss{ZkcZkck{kZskkRkk{:ZJkk{{ZkkZ:JZccJkcB{ks{Zk:)1ZJcRBZZR)!)JskB1):J1!!)1RZR1:Z{BRkkJJRcZJ{ZksZckBcRRZkRZZs1s֥{kkcBJRBB:B1R!!!!!!)!)B))RJ!c)1B:R)!J:!JR:BZJ1:BRBZR)cRBJZZB:BBkJJBR:B::1::k:)RB):JsBkJJRkccZcJB{:BJ{B!1!):):!))1!J!!B1BBJZ:):B1ZńJ))B!!!k{sJ!))1k!1:!cskkkR{{cRsZc{c{{csBJRRRZ:RBJB:JBRRBRR1:BJRJcBJccRRJccckkkkscckskZk{ޜ{kRk޽s浌kR:RJB:{kkcRk{ks{kk{ss{RRcBskscss{{skk{{Z)Z{BRRkcJ:B:s::JskBBBR{c!BJ:J!!)))R:J:JBJ:))BR1R:ZcJJBk{)ŭckZRcJs:RZ{)cZssJJk1!)JZ!:!!)!!):J:!!!)1:cZJJRcBB!!!!B1:B:BJ)cc:R):ZJ:BRRsJJR:1ZZJJ:!1)1:BRZB::RR:ZJsc1BcJRBcsJ{1cR)Js:!1)1:1)!B)!:J!:JJRBJ1BJBRZs:s!1R!!))sssJRJ)!)!J1!)ccRR{kJZ{{{ŜZオksB:J1JRRJJJZBkJZJBJJZ1RRBJBBBRRRZcRZcRccksskckscs{ֵŌ{֥JkkZZcť{RRBZ{{c{skskccsckcckskss{Rc{c{cs{csksc{{ZRkZsR1JcsZsR:{ZBBc{:Bk)J)!R1)!!)))1))!BBB)!)ZRR:JZ1RcZJ:)kkZ)JRBBs:1ZRc)!1BRsR!B!B!)!1!)!!1BJR1:B)JRRJ)B)J1JJRcBJZkB:1RZZsJ:cJR:RR:::J1ZBZJ::JZ)):J)s!1::R:Zk{1JcBk:ssB1!!1)!!)RJZJZ:Z1BB:JBJ11:1BR1!B)JRZ{11s)J1)):Bs{sckZֵkބ{{sքRBJBB:BBBRBRBRJRR:RBBZZJZRRRRJJ:ZJkkccckZZcc{ccŽŽkΔŽcZJccBckֵ{kscss{sRsssksZRs{kcks{ss{ksksskZR)BR:JRB)11!J!RRZk:ccc1Js:c:R1!11B)1::)!!:)1JBB:!))1R1cc{cBBkJ:)!ZZRk:)cRBJ)!!!)1!::c!::J)JB1))!!1)1sBBcRc:BB::)1))1B)RRRkRZJZR1{Bc1ZZRJJRBJB!1JJ::BBRBRR1:1J)!)!JRkkckB1s::c1k!B):!:1J:JRR:J11J1B11J:)B1!)1:1):1)!ck:JZBZ1BRJc{ΥkRskksŌks{kZBBZB::JB:BR:JBRJRRZRRRZ:BZcBZRcRccJJcccckkkccνkcZ挭Žޔsk{k{ZsZc:ŵkcs{{{s{kk{{cZkcs{潜{ZR{{sck{{cc{scJcsRZR1JRkZB:RJc{ksZJRZkJJB{{sRRJ)1)J)B)1)))RcZRJ:!!BZkssk{kJJ:B:)!Z{s{cBBZs{!)):!1!!1!!!!)!)!:!ZBJR)1J:B!BB)J1BJB)B11BBJ)skJcBJZ:ZZ:)JBBBBBJB:)Z11!))1)1)!BB1BRZ:Z:JkBJ:s):!)!!1BcRJ1JZJZJ!R:RJBZBB11!:1!1B:J):c!B:11k:cc1))sŌcRkkkkR:JkscZ:JŔ{skBcBBJBkZRBJ::Z:RB:ZJZJRRRcBJZJRZRkZRJckZRcc޽{ŭΜksckc{sksRcRRRcέ{ssss{sssssRkZ{{ck{{{{{sssZsZ:cZBRZsc1J1BZR{kZJsZZc{JR{BBcJB:RRJ:1!BZ:JJ)BBcBZk!!c{sRBZJZ{JsB)1{Z{k)!!!!J{Z!1!B1:):B:J!!))J)!1:BB1:::J::))!!)RZ:Jc1ZBBBJkJ{ZZsRZBB:BR:)RB):)1:)ZB!!Z!c1B1):1RZJkRJs1scZc!!k:B:BBJJZ)JZBksB:JJRZZ!J)!!!))!:kZc!kB1BRJ:BR{J:)c{{RJ1B)ksZs)RRJkk1skc{Zk{J{sŜZJ|B:JJBJJ:RJZJZcJRZcZRZcJZRRkRccֵ{sscsskZ{JBkkŔcJZ{s{{{s{{RRZJJZRΔŔŵŜ{cs{s{sc{{ck{kJZJRc1Z{kcRkR{kBJZZsck)::!)1::!JRRR:c::JBJBcJR:sJRs{ks{JJ1J{{kc{k:ks:c!!!!:1)1J!!!)1:1!!!B!!B1JJBJ1R:)1)11J:ZJ1JRB:BB:Z:ZsJcJJc:cskB):J1B!Z:B):BZB:Rc1!:ZB:ZJ)ZkZRBRskccJc)1!!R:JcRBRJRJZ1::R:cJZR))!)!!!1)ZJ{!!1)1)J:ZZ:J!:!!))1!{ZJRBs{ZZ:):cccZ{cksBZJ{楥{ޜތksBcc1BZ{{BRBBZJcJJcJJRJZRZRRcZZZZkRRkޥŜRcksks{RJRcֽsν{{s{{ksZ{ksskŔJcBs{ssss{skscsckskJZc{sR:RB{sZZ:BB:RZJkRJJsB!J)!)BZZ1cJJJBB!)J)ZBBc)!ZkRsZ{s{B)R1JcJcRs!))!!!11!)1:11J)1!!!!B):1Z))B:BB:RR1!!B!)BB)Bc1J1JZJBJJJZZZ)RBcBZJJ:ZRZBJ1::BJJ:)c):BR!JRRJc:RRcBRB:{:)!JBkBBZcBkRBRBR:ccJ:R:!1))!!:!1:1ccZ:cBB1:B:J)Bc!!Rs{sR:RRscBZZZcJccJJR潜Jssޥ{s:Rccs{έkZJBRRJ:cJZJBZBZRBZZZZccZk{ZcŜޥťތcksRckccRkcťsֵ{{k{sskkssZZZ{sssZ:R{{RZJZB{{sJJ{ckksk1ZkccRccBJJcRRZJkZcBZJk::!!!!JJRB1!1:R:!JJJ:Z1RRs!!!BZJ:1Z{sB:BBZkksc{{):!!))11:!B1:)!!:)1!!1::!1:1:BZJ1B)::!1:1JcZZRR:)B{J:ZZ:BRBR!:sc:!JJJ{RBJJB:B)Bk:::)1!1)1:BBJRR:1ccc1J)JB:BJ1)RZBZRJB1JRRZZB:!:)B1R1B1!1R)RBBRJJ)1):)1)11!JΥcRZBBJRk:)Jks{sZťcksR{{{Ŕ{ckB{sc:kRBBZZkZZZRJJcRRRZZ:cZRZRcRc{޽Ŝkք{ZcZZkcBkť{ŭ{{s{{s{{{kJRZcJccJ{sŜkZZZ{kތsssk{s{kssB{ZJ:ZkRksR)cR1kscRZc{{B:B!):11B1!!!!B:JBRBZJRJ1RZZ!)J{sR::!Zc{{{R:BRJJcccc11)!)!!!{c!!11)!:)!::)!)1::1cJJ1ZB1:B:J:!:!):)Z{ZJJ)!!{{cB)cJRB:s:s)!RR:kBB:J!1JkJJR!!!::J)JsRBJJ:RZc:!!)1B:BcJsBBZ!:B:)R:)):::BB11ZBJ1JB:BBJkZ11ZR)Z!:1::!kRcJcΔc1::JJ))1:s{cJZsRZZZc{JkZk{cR{{Rccs{B!Z{cZRRRRJcRcccccsZRZŔťsksssZs:έ{ss֭֌{{s{{{ssskccRBsJ{kέsZZBsk֥cskkkkk{JRcR:JRkkZZBRZ1kJcks{cJkRR1111)::!1))1))!:JRBBZ)c:RJZZcZJkJZZs{cRJBRk{ccc{sk:kkB{kZR)!JJ{Ό)!:!))11JJ:)1)1!!))11B)RcJ)BBR:))1:)ZJRRJ:J:!s{cJB1BB:RZJ:ZJBBJ{:BR!JBRJZ))J)JBBkJJ:RJZRRkskc!)1sBJ)cckR:B!:JRJ1!!:J1BJ!:BBB1BR1J!c11:)!BRRkkkB!111B!JRkssR:11J)Zc!RJ!1BB{Bk{cJRJRcRJk{{kkZ{{cJ:1!BB)ńZZRkcRcRRZRcRZΥ凜ޔkksRcJRssJssέֵŔ{k{kskkZcBZs{kޥJZsε{֥c{ZsJk{ssRRs{Zk:ccJ:ZZZcBB)Z))1:RZZkB)111):!11RBJZBZJJB1c:R{BR11ZsRs{s:cckZkRc{JBB1:!)!!!kkk1!11:!!!:!)1!!)!!!11JJJBRRJJc:!))J!1:)JJ):B1BRkkZZR!1Rc)ZJBB!:BRBBcJRRsJ!BcBkJ)BB:B:Z:JJJZJcR)cJcR:)cBJ:R{cR!!!)))!!)1):B1BJZ)!R:J)BZ1BJ:cssJ{R:BB)::J:{kZJ{sZB))RB!{BJ!::!sR:R{sRZJB1B:JBJJB{)kkֽ֔kks{kJ:JRR:BZJccJRRZcRZkckkZ޵ֵ{RsZ1Js{ckZΔss{Z޽Ό{k{{kZJJ{kk{cޔŭR֌ތ{{cZcRs{ck{::{cBRcZZ{ZcskR:RB)BJJsZkB{1:!:)1B!BJcBJZ)!:1ccZBJ11!)!JB1JRJ!:kcZ{ksJJRZs1:ZZs{:kB!!!!!)!!1:kZ!1B1)!!!1)::):!B!!BBB::B::sB:!Bs1JZ):JB)B:1)BkZB1sJ1:Bc:))1){1cBRckJkRR)RZR:ZJJBJB)1RB::B1RccZkcckJ1c1!)!ksJ1!1!!)1))1R!11:)!):JBBBR::BB1)!:11!:kRJR1R!1Jc{RJZBR1))RB!c1Zss:JcBJ)JZZJ:11BBJJJZkcccńcZń{έccckBccZccJŵZRJkRZRs{ZscRsťkscεs{{s{kZckk{{sZ攥s{scZνsRscZkscJZ{B:cR{{޵J1J1kscckR:J:J{k{cRkkBcJJJ:ZB)1!)ZR:1R:)kJZccc!BBBZkkkscZckcJc1!!J!!B1J1Z:)!)1!!!!1R)::BRBc)BRBRRBJJ))R!)JZRk1)R:1!Z:BBksBZBB!::k1)::c:c:J:cs:k:)B:{JZ1Bck:ZZ1J):JRZcBsckJ:J:1ZcZ!J1{:):!))!1:1:1):J1JBRBJJZJ)))1BcsR)B!B!:ZssJ!)1B))1sZB)cBRcZBJZ::1::1B:B:ckBZJŭccεŜΌZkkJRRsk{kkcccscZޔsccZs{ބskkBŵ楜ťńsks{{k{{{{kRRsZR:1{kcs{{s{sskskkcZccJZJ::BJRRRccRBkZZk1JBssRscZskckRRcZJBRBRJ:1ZckRkB)!BZBRkcRJkZZR:JckckkR:1!!)1!!1)!)1!cscJ)))!!!!):)!1ZZRJZcsZJcJ1:B1:BB!JZBB1)!B1:JZ11cBBJ)RR::11JZ1R:BsRR:1:RJRsZ!:ZJ:RB:RB1B:k:kcR1!!))cs{R1!J!!)!1)!B)!!):!1)J:JZ1BJ1!)))B):{kZk1:ZZBJJ1!J:!JZZsB:)1{BZ:J:B:JB:BZ:B:kRRZRR朔{{{kc{skkck{kZcRs޵ޔkkk{sRBZZkRRJŽν歵{{scscZsckkkkk{Jck{{s{sZs{sk{k{Z{{kccskZRJZRRBZs{kRRssRkcskΌJ11c1:!!)BBcs{cJ)BZRZJ11ZJkcJcR:RBs1cRRB)s{JZBJBcBkkck!:)B:!1!!J!!)1c{!1Z!)11)!!1!::)JJZBRBBRRccBRR1JRRB:1RJsRcJc:R))!1RskBBZJ:)!BJZc1:JBccZRkZ))1R)R{k)BBcZBBJ!cJRkRcR)))!1csZ!:!)!!:!J))!)Z)1)!!1!11Rk):B!B!1!!B1!))RBZcccJ)R:!1!1R!)csZkR1B11Z1BR:11R11:JBZZRJB:{{c{֜sε{{{Jkssֵέ凜{sc{kccZZΥένs{ksZs{{sJkckBcsZRJcZ::sckcńk{s{ޥ{{ssscssRJJZ{RZs{cscksZcJRBcckZZJ:1cssZ1ksZZkskRk:cJZ::BZkRJ:::1R:cZZss{sZZ{{cZR!!!!1!)!)!ΔZJZJJ11!!!!BB1B!1!!):RB:Bc1):BcBJZ:ZB:::)JcBkc:c!RJ1!)B:k)!)!:1:BJBZB{BR))JJZJJR:JJJZ:B1:kBJR::Rc{{cR:!J!!:B1kk!!)1)!:J!))))::1!)1B1ZJJ:BBB1!)B!B1!1::BRRJ):!J!1:ZkssscZJZ)BJZ!)ZJ11)B)BB:kkcJ:JB:ZJsc{)1Jcs{Z΄k{εcccs{޽kss潭RkRZZ{ssֽΔcssc{J{RkkRsckRZsck{{{k{s{ֽ{{s{k{skkkRBJZJZccss{kRJsJZJRccs::)Jcc{Js{RJsRcccB!1!RZZJBBJRB)BZcJJJ::kRk{ck:!1!!1!1!)!)ksRBs:!)RBB!!:!RR:!JJ1Z:)cJRBJZJR):cBBBBZ1Z:):!1B)kBB:B1!!ZJZcRJ:Z!)RRc1cB)))11:ZBBcRkJ1{1{kkJsZBJZB!:R::k{!!!!)1!1J!)11)J!!!1)))!BBB1:BBB1)!1!1:!)!!:1Z1ZkJBZscsZsJRB:1!)B::1J!1)!!JB:JkRB:)))ZRJk!ZcBRť{sΜsޜ{sΌk{ksc{ZZ{{ŽνZRsZk{ZcRZZcZZRZ{ks{BsJk{{ss{{{s{RJ{kkRRkccJccJsBJccZZZ{{kkkJckB)RR{ZBZkRRsZRcZZ1!1)1!BR::c111)):BR:1BsRJBcR1:!!!))!!J:B)R!1έZ::B::!!1B1!)!RcBZ:JB)RsRJ)1JJ)1BJR11RBZJBBRZ)B1R!cB):1)1ccZB:RB:::Rc:{R)B:B1RJJJc!)R:c{RcsJRZ)ZRc!)R1R)csB1!)))!!)!)B1!B!:!:1J1!B:1:R:JB1!!!)1)!!)!1!1!1B!BZ::!k)1!RZB!)R1B1)BJ1!B)BBZJ:J)Z1:ZR)!Bccc)Z{挔scZ{kŭ{ތŵ{νcRΜ{{ťޭcZ:ZJssRkRRc{{ccksk{skcs{sk{{sks{kZZ{cksZZZZŭcc::Rcc{kJ1c11:RZ{BBcBsJZRkkskR:ZZZJscJJs:Z:)11)!:{ksssRsJ:!!!)1J::::J!1Z):BkkZs:RB:1!J!B)1::Rc1R!ZRBJ{k)))BZR!B)Z1)BB{J!JR::1BB1)BB!11::c{{JcZB:Z)s)JRR!11))1cJRckRck:RJcZ:1sZcJ1J1!B{:!)!B!:)))!)B11R:JJB1ZcJ:!)1111)B)1!JZ!1B:)R)1{JB){:!)kk:1!1J:1::Z!BJR!1))J1BB1sccksRZsZkRRZ֥{sŽńŽνRZJsscέ{sc޽޽kZ:BcBskJccssRkRBccssssJs{s{s{s{k{kk{ZZkkZscZs{ZBRJZZ::!1s:B:JZRkZ{k:JZ{JBZJ!J!!)BscsRZk):JkZZRBsscZJkck{Z:1R:1J1)JRBJ:J::RRBBR:!{cZJcJJRJRJ1)))))11kJB1JcR1J)RcJcsB!)BRRB!J1J:JcZJZ{:Js))1)B1!B:ZZRkZ{JBJskJ:kBJ1!)!!JJZZJZBRR{J1RcZ!JBcZZk::1B))1!!1)1!J)!)):!):1!)!1!)J1Z)1R)!):)!)11::)J111B!BJsc)c:1:{ZB!Z:B):!1JRRB)!))!)):1kZsBRs1ccc{JJ{{ŵksŜ{scsscRccΥ{{JJJRJRkkkZZskRcZ{{cJkZk{{c{{{sskΜ{Zskks{RZkk{Jk{ccBR:{R1:1ks)RccZ{c{1!:kkJR:RcJJR:kZc11!JZ{cZ11ZZcJkRsJBBJJZ{BR!:1kcRZckZ:1J!)::JBssk){JZBRc!J1B!:11:J1:Bc1JBR!JcJ1JJB:Bk1J)!Bc:JJcccRRRB!)1B1Z!)c!!R{cJZ:RJJZkJBZRJB1!1:BJJJ:kRZsZ:RRBBZJRRkkJ!)11J!:)1:1JBJ!)!:!)J!RJ)1!BcZ)JBB!!::1!!:BZk)!:!1!J):JZ1{c1Rckk1!J{k1!:1JkR:1:!!)Z1sRcBJccJRZ֥kJ{νތkŜ{步kJkֵŭ֜{scRZJJBZRJZRkc{Z{sZRssskZZ::ck{c{sέ{εΌssk{{kkc{s{ZJ{BJJBcR1ZkRRBRssBB:{{sBB!::ZJ:Zk::R):JRsk!BscZ{sJskssZBZJB!!::k{skRc:1B:):)1:sJ!c:)Z{cZRkZZ::J!:RBJBJBRRRJJ:BBJ1RB11JBR:::BR1::sscZ!J:JRBB)Js:BZRJBRJBRZsckRB1BB!11c{cZJZRJRZB:BRBBRc:JZ1:!!11111)Z):1!)1):!1)1B):11!!J111JRkBJc1)!!!)B1)BB)!1J)B!!!:B!B1J)RB{kk{c1BRkZ))BR{k1)!!J1BBs:RJcRZR{ZJc{R{k{ssŌ   *   @` @` @` @` N@N@@Aj@ Ugdl-0.9.9/testsuite/tiff/8bit_gray_geo.txt000066400000000000000000000013231340051421000205300ustar00rootroot00000000000000Magic: 0x4949 Version: 0x2a Directory 0: offset 262152 (0x40008) next 0 (0) ImageWidth (256) SHORT (3) 1<512> ImageLength (257) SHORT (3) 1<512> BitsPerSample (258) SHORT (3) 1<8> Compression (259) SHORT (3) 1<1> Photometric (262) SHORT (3) 1<1> StripOffsets (273) LONG (4) 32<...> SamplesPerPixel (277) SHORT (3) 1<1> RowsPerStrip (278) SHORT (3) 1<16> StripByteCounts (279) LONG (4) 32<...> PlanarConfig (284) SHORT (3) 1<1> 33550 (0x830e) DOUBLE (12) 3<60 60 0> 33922 (0x8482) DOUBLE (12) 6<0 0 0 440720 100000 0> 34735 (0x87af) SHORT (3) 16<1 1 0 3 1024 0 1 1 1025 0 1 1 3072 0 1 21892> gdl-0.9.9/testsuite/tiff/8bit_gray_tiled.tif000066400000000000000000043007221340051421000210330ustar00rootroot00000000000000II*oioiio[ou˖iϢĪķi9(Kc 9Ki[91Kz[cc[B991199Kczo11B[zu[B1    191BK9991BKSSii[KBBKKSio[1(1919BSKKSSKBB9BBKB9991111BBB1(  ( (( ( 1[uo1(Bizi[SK1 1cǖ[[o[BK[iuououcKKK[oiuzi[S[zzuKz[iэo­Ħ­uu( Kc19Bo[(1KzuɳuicSK99SS91SciccoucSB1     99119BSSKKSououK[[[cioocKKK9999BBBBBB9BBBSSBB991919991(( (((  i[B[ouoKK9B[K(((1111տB[[zKczzzzzcc[ioouKKKiKu[[zzuoԼ’oiizBB[zc19Bc[1BSuc[¢zouuozziKB1     (( 1999B9BK[iSK[uuzzzoSKSKKKKB9911BKKSSKBB11911199( ((( (( K9BK[oui[K1(9111111(9ѳuS[KuBuozucS[[ioucuBcoziuccĒuooҹK[izKScui191SuS19[ic[ɿiK9(       (BK19KSKB11Bc¢zc[uS[cSSKKB9BK9K[KBKKKK9111((191((91(  ccK1KS[izuzK (((1(1(1o͚c[[Sz[ocioSKKSccizzuzoczoiozzzĪKBcu11Bii1((BocBczuiiɒuzuc[uzScuoSKK(      (99KSKB9999BoɳS[iooSco[SKBBSSSS[ocKKKB919((1(199(19  BcSKS[SSuzB(((((((1‰cc[uiiiSKKKB1BB[iiuzozuuuzuuzouuǖ[oK cuB19Koo[z¹zcouoicuiSSKSKKKK1       (1BKKB99B999KɭzBSiiicSKKBKKKSuuiicSSSSKB1((1((19B9 (1 BSSSS[[[[[K1  Bբ[S[ozc[cK[KKSBS[couzzuuzzccuzuuuoǚS( (coB19Suɢ[KouuzoizccSS[[KK1        (119KBKBB19(9S[c[SKKKSSSKczziccSSSB1( ( ((19KB1 Kzz[[[icSc[999( (11(( SɀBizoS19BSS[[io[[S[ouzuuzuzoKizi[ccuuozuiiuz[(Su[BB[i[ioiǹǞcBcS1B[ic[SK[K9(      ((19SBBB19KKSzuuocicSKKB99K[ozui[KBB999911(  (111 B[[[[oc[Sii[ooSB1 ( (91(zѰ[iz[991(9KK[iccSKB[iuzuiozoucScoccz[cuScucSiio[KBcc1 Sz[BKuoocSKSSİzuczc9 BS[KKK91(      (19KKScizucSB19[i[SKSKK9B[[S[SKBBS[SK999111(((((((1Sozu[919oc[uzziB((1(199(KɍiS91199K[[[KBKB9Kcozocuizuoccuuic[ioSScS9Suuu[919[[(1 Kociccc[S[[Sɭcuu[S[ooocSB999(      (BizuooocSK119KicSSKBB9BKKB99BBK[ocicS9((  9[uiSSB999SziozoS9(199(9ѳzuKKKKK[SKB9999BKcouuiSciizzu[[SS[[SBKSSSBizuoKz9(1[i11 Kuouҷ[[S(9[c[SBB1        BozcSSSSKSK991(9z’[cSKB9B111119BSccccS91 ( BSSK991B9919ouiccozzzo[[SB1Sš[SSSBBK99K9BB99ScoocS[[ioicScuc[iiSzziSKB19BK9( uziB11Si( ([i[[uɍS[9 191 K(       9coK91BBKKSSK1 ( (SocB99B(11(( ((19KB9B(  ic99999991999[oiKKBBSS[uz[Կ[KKKSKKKBB999BBSciucSSBBSiu[KozoS1B[BSo[izKKBK19  zzK1(KzB[oi[SB11BScui[[cͦBc           Kc9(( 11B9BKB9(1(((9ic999((((((( (1999991( 1[[K((99B99(1999BS[K91K91KcuԷKKSKSKBKKKBBBBK[ciucS[SK[ccKSSB((911BKBBKK1BKK   [uciuouSBSKB1119KBBB[„zB[            (11( 1SS( 1((11111((9[io99( (((( 1((111 1[KK919BBK19B9BB9SucScSKB19KicѭuBKSSKKBKK999BBKS[icS[c[KcccSu(9  1BB1(19( 1( ( Sziio[KB9991BBSBuĖziB9B          1KKK9 KcB ( (1BK99Kc[BBiB9(( ((((1(  (( oz9BBBBKSS1((1SSB[uuoc[KB9BKS9iǒuu[[SSBKKBB9B9BKKKS[KScc[izu[BBSB((SB1(111((  (ĭioziizzzoicciioͦuzciS9S          (BKSK (Sc9 ( 1B1( 9couu19BKSSSSB9911 ( (1( ozB19BBSBBB1(1KK[ocBociicSB9KBS˳icSKKKS[[KK119SBKKcS[S[[cizu[91991((  (oBKKBBBK[izziouooSiSBB         (BS[99BKioKKB1((9B11zuuB1BK[ccSSSKKB91(((1((1uuic99SK[KKcB (1[[B9Kuc[uuoSKKSKɭuzS[[SKSKKK99BBSKSScKSK[ciccK911(((1uB   zccS9((9B9119BSSKBKSczizSKcBS1        9Kiii[iucoc919KK9(iz91BBKKBB919K[[SK9BBBB9BB991 Buz[Kou9KSKSSSoS( 1iiB9B9uuScuzSBS[SĞozBS[[SSKKB9BSKKK[[c[S[iccB9(9KB91((K    ( (Ǧi1191199(((919BB9991c¦SozBK[BB9             9iz[Sco[S[SK9uiiziB9( 9BBB99BKBB919BBBB9999((zzK1cSBcSKKKSB11Kc19BK[SSiz[cKKSuiS[i[SKB11BSSSKK[c[KKSci[911KSKBB(1oo1  ( 9žcScS91(((1B1BS9991KcSz[BB[B9B         (((  (oii[11KK[i[ciKizoB19KSBB99BBB91(1B99BB919 KuiziB9SKBB9S[SB19SB9ScKKSi[91BužuiS[[[[SB99K[BBKB[c[c[SSSBBBKSSSK9( [[iK(  BzioiiiciicSK[[Sizz[[KKi99B         (KcS991   ([1KcK(((9Kc[19[c[9S[[KBKBBB9((9991999911(iS[cKKBBz[BBccB1(9[K(9ScoSBcS91Kcccc[KK11BSSK99BS[[cicKBBKKKKKKSKKB[ouKcc1  Socooz³9cKKSBKoBBK        ([o[91BK[[K( S[B(BSK1(( 1cu[( ((KoKcS[[KKB999B9(1191(1111(91ii9BB9BKBci[[K999[S((9B9BSSKBBSļzK[[cSK99KSKK99[cicicc9BSKKSS[c[SSBKocuoi1  (( 9SK˹o1(BB99KK9[ui(BKKKBBcB9S         Kui[B111BKKBS919o1 9KB911BzzS( ((19SB9cSSKBK9119911119911( 111B91911(9SoziK91(KK(9B9(BSSKK9[˼KzcKSSKBK[cc[[iuoioo[KKS[BSSSS[[S[[uucSSoB91(Bi˿119   9(BcBK9BcK9c        (SiSSK9BB911111Soz( ( (Su9( 11(11KB1SiBBB9BB91B999B9999991( BS(1KB11(199BcuzocK9[S1[[91BBSS9(S˹[KBK[ccc[ciccooc[K9(1BKKKS[S[SSKKKoiiBɭzu·oc[SK91( 19BuiKS9BiS1i         9KB9SS911BB9( 1[zi9  ([i  ( BB1(9ciK9BBBS9(1919BB9B99(19 9z99KB(1KSBBSKK[ouuz9BK19BBKS[(9˷KBoc[cooiciuiSKKB99(1BBKKK[SKSKSSSc[czɪuS 1oɳuzuc[91cS z         BK11S[B119B11 ([c9 (cz 119((KB((1Sco[BBBBSB91119B119(1199 9S99BBBouS[u[Bc[SSiB(19S[BB1SɪccϰzBB[o[czzzuocBBKK99991(1BBS[SSSSSSKuoo[czuccoS(1KSSSSKiuccK9[[1       (KK(1BSS1(((  (9[B  (9[(119911SS9((199SiK9BBKK991119991 ( c[KS[KizzouuB99SzuB(1K[[SB1cķѪoKKSuB[ui[o[KKKSSSK99BKKKKSSKKKKS[SKoiouiciu[SS[icSScSB˷Sc[B9c[1z     (S91KK9B1(1cS  1[99B99K[B(119BB19c[BB9KK99111191(11(99Ko[[iizoBBB1Ku[((BKKK911cհoKK[u9KS[KKK9BKKKKBKSSKSSKKSSSKKSSBBuuuzuzc[[cSKBBKBBzĪ[KS[cizzi9ioK9[S1z       B1 (BKB   1S[( 1oK( 1[K111B19111KcS9BKB19119111(((Sc[zuoo[9(9B9cuK(9BB9(1BKKzҭoSSioKKK[[[c[SK9(19B[i[ccSSKKKKKSKBSouzzKKSKS[[[c9B9KѿS1K[SB111BK911KS[c11ouK1[i1       1 (9BK9  9cB 1Ku[9 Si(1(19111999[[19BB99991(  9zcozuzuccoiB19B9Koi99B9K1(999oɞoSBocS[[[cccSB9919SScuo[BBKSSSSSKKKKuzuuKBiooiiui999[ݪB99K911B9BB1 ( 1B( coS1Sc1u        9KB( 19 191BB(11 (  BK( (9Koc11u99B99911199KcSK9BBB9911( KuzcciziiioziK11KSBcuK91B19B9K͹SSSuKKS[S[SSKBB99KS[[c[SKBBKKBBBBKSSzzzuzoiu[c[KSoii[K91KۀoBSKK91191911(((11K (ciB1[cBi       Koi[9 1( 1199B9  ((  1K9(9B[uuioK99BB11((9BK[SB9BK9919KSuzouzouiuzS((BB9Szi9119BB9uɢoKczSKKS[SKBK991BK[[c[SSSSSSKBB9BKKKBozuouuuzzoic[Sccc[S[SKS99[ĒoKKKKBB999B11991BKccSuoKB[c9i       1KK[u[  (119(1199 ( (( KS( 1KSB11SiuiB991(199BBBScK99911BiKii[ozSBcouB(19KBBKicB919B[i׷[[[SKS[KBBB99BBKKKKSSSS[[[c[SSKSKKKBocouooz[ioi[S[S91KSKK91[ĢSBBKKBBKKccczc191Kicuc99[oBz        (991(11 19  (11((BB( (1(( (B[1(11(119SSKKic1(99BBBBB99[iKB91KiK˷ziSKco[KciҹuS[SS99K1BK99[zK1199Kˢo[z[[SS[SSKBB11BKKBKKSKKKKS[[ccoi[B9KBzoiuzoicioicccS((KKKB9ozdziKSKKizi1 (BcuoS11S[(u      BK((B9K (99((BB1 9S[B919K911((1SB(9B 99911119oiB99999KB99BooSBcSKiuoi[BS[zؿuSSB9BBB9BKBKcS99K9[ɷzc[[[[SKSKBBB99BKBBBKKBKKK[SKBSio[99KKzzoczzccoi[cioocic919KBKzɪ[cķoKBBii[BB911SK1u 1 9K(    (1cK99S[oS ScB( (KS1(9SicKBSSBKB1((S[119((KSB9999BiiKBBBBB9111[cKKSS[SKKcoҷcSSBSSS9199Kci1BcBԿi[[KKKKSKBKBB9BKKKSKKKBB9BKBBBSioSB9KKouzzzo[[ooc[cuuuo[B1BScɿ˳͹oociB911(9S[ouc1BicScu1    BSK1BccccS iu9(11i[11Kiuc[cSKK1 1 9cKBK11BKBS[SK[[oz[BBBB9BB19cͰuccSKKc[couou˚cKSSSS[SBBBK[u9SciϞuc[SSSSKKBBBBKSSKKSKBBBBB9B9991BBKBKBBBuiiiouuiioo[SizcSc[KS[ѿ˳¼ucKK9B[ii[BKSS1 BK[[o1 Bi[BKKuuS[i[ uS(19Bi9BKuzui[SB(((( 9[SB999KSSiicc[SouK999BKK9SǿouzzoiSS[coc[uҪcBB[cB9KSKBSoS9Kѳzc[c[S[SKKBBKKSSSKBKSKK919999991B911KKB(uozooiouccooiuzoi[[ciKKϼziK9((BccoozziSB ( 1BK9K9 ((9SSKSozB1BBccB9ci (K (BKu[((9[oooSSS( (9ozK9B1SSSc[[[SBBo[19K[cicoϹiuoiouK[zoB9B[B9KKKK[izi1SǒiKS[[[[SSKBKS[c[SKBBB99119BBBB99BB99SK91izziuzoiuuocizciuoiiozcuɿK9uuc9((1 (9KKB1( ((  9K[[9B9( 9KBSic[ozK199BBBB[oB1SK 19iuicS[couSB1B( ( (S[[oK1B9KKBB(1K999ouSSciioiuzccuioozzcS9SK9B9BSKKi[Ǫc[[S[[KKSKBBScic[SKKBBB99KB99999BKSSKK91(uzoiouocouuuzuii[cooiĹ[K[[K[uu[K( 19( (((11   [c((991B9( (K9((1(1cB(919B9BSzoS[B 1KS[zzczc91( (((KiS1SucB19KB919B119[zooi[K[uK[cozoououɰziSKK911KSKB[ɭiSSSS[[SKKKKS[[[[c[SKKBKBBSK999BBKK[c[K91(uccooiouucczuioocciuiuĭc9BB9[uK((  1 (((( ((   9B((1991 9[B  K1(99B99([K( ( (11Bioc[SKu911(1BBKS9(BS919SB9B99919z[B11cuKSBiocc[[cicSSKciɦcKK91(KSSKcɷicc[SSSSSKSSS[cc[[[[SKKS[KKS[KKKBKKK[[SSB1(uociucccoooocioc[ii͚cBBS[oz[11((((19( 11  KcB1( (119  99  (c9199BBB9i[ (1 (9KK9B919(BizK1999SK1119Kzc111991(9K91BuK119oS9BBKcSSB9BScSKKuKBBB[K­o[SSB9KSSS[˪[Suc[c[[SSSBBS[cccii[[[c[[SS[SSSS9BBK[SSKSB9ccoocoouoioucioiciui[o˷uz9B[c[B119( (1 ((  1i[111((1((9  91 oBKK19KKBozS1B11SK9((BK99B[zB11B9KK91BBKSiui[B1B((1KBKczu9(1[zB99B1oc[ccKBBKBB[ci[SKBBKKcoScK9KSc[iiĚSBzu[c[SKKSKK[[c[[cSK[iiic[[[[[SB9BBS[[[SSB1iiooiicoiouoccoccioo͖[zcB919B91((1 11  (SS9991( (SB 9  119B1B91BKKSooS9BB( (  B[io[B11199BKKKB1Bczo[S[9KBiSSK19S1(9zizK199(Ki[iiS19BBK[SKK[KBKSKSĉKSu[KoouoozdzzK[iiccSKKSK9BKS[[ci[[ioic[cc[SSKB9BSccc[S9(oiciiooioiozo[cuuiic[9 ( KoiB(9 1ziB999911(1[K 11   (9uoKBB9BBBB[uc((  1B9S[B999((BKB(( 9SuocKKKSKS9 1K1BcKicSB91((o[cS9(19SccSciS9BKB9KS[cKKuzozǞ[Kizu[[SKSKKKBKKSKScc[[ii[S[[[[[SBBK[c[[SB1 iuoccioizuiiuuiiououĿɭԭocK1 (B[oKBK9 1SKK91191((S[9(BB  111cB(9BBSK9Sc9    (1B[K911( 191(((1BSB(  (  9[K[z[9ziSS9[B1zoSSKBKK9KiccuuK1BK991uoB9KczoϿ[[icSKSKKKKKBKKBKS[[SKSSKK[ciic[KBKKS[[[S9(iiiccciuoouuiiuzcicizĹ͹ԭoSBB(((1SuocSB9B1S[B9(1199(Su[(1B1 (11 B1 199K[[Si9   9[K911((( (( (99   1BSK[S(BuzS[Bc9 Su[c[SSKKB[cocK19B111(c¦uK[iozuuzϭoio[[KKKKBBKKBSBKKBBBKKS[[S[iic[SS[SKSSSS9(uiccocizziiizzuozuuSKozٷ[KSKB19SzoccucouSB999119 KS(11( ((((19oB(19BSii[iB  ( (1SB1(111(   ((991911SicKB(1SuKSSKS[KKS[KS91BB1911SuocScccɚiiSSSSKKKKKKKBKBBB11BBB9KSS[cicc[S[KBKcc[KBioicouzuiuociouiiSBSoɉzi9BSSBKzSic[Szɚ[99BSKK9(9iS9  (1((1SzSB11KB9BScK   99( (BK1(1BK1(  11  (BB1  BuoS[S999SzcSSBBSSSSoocB99B11B9SoziSSKzͼ[oic[S[SKBBBSKKSKB9B91 11(1KSS[[c[cc[SKB9KS[ciiiuoozoioooiououzBKcouuҼǀzi99[[SSuSKSii[[˭c9B[oSK919uu[9 (19 (KuiSBKKB1(BBB   1KK999KoiK9KS1 ( 11(111BK9  ciBBK999Bz[KKKSicS[io[11199BK9ciuiSSKҿoci[SKSKKKKKKKBBKKKSK911((BSSSS[[[[[SK99BBScioiizzccuoioooco[KK[c[o³˷׍ci9B[uzc[Kc[9[[9KizcKK1(BSB9 ((((1ucSScK119B9B9((S[[KSSSz[SK99B1 (((19  (K9   1BuSK9(119zo[KKS[ouoouoS((11BKB9cuoiciKͳScucSSKSKKBKBBKK9BS[SSSKKB(1BSKSSSScioc[KKKBBSSuuuoccioiiooooKS[ccSc·¹հKiBSoK[uuKBSi[[cS[S11Buu9  111oSB[S91KKK9B9  (((Kiiiiiouu[B91(1 (BK9   ( 9[zzS9919iucoKK[ooiB111BBB11ooiozĿiSiuiKSKSKSKS91KK11KK9SS[cSSKKKKKSSScioic[KBBKS[iuuouociiiiou[[[S[cSKļ¼Ͽ9oooB9SiKi[oiSKuuc[SSKBBzS((1( 1ooS[[KKccK1Sc 1( (99KB[iiu͹zzcSK(1KS9  (9izo[uzK99Bcocu[SizicB91(191 KzoziSoª[iiooSSSKKSSK919B11(119B[[c[S[SBBKKK[SiiicSBK[iiizicouocozu[Sci[io[S¿¿ɦ9[9K[SK[iccoiicKK[³i[[[S[z9(   ( 1[ziS[[[ocSBK[9(111KSK[KB[i·iK(1K91( (Szc[KBocBKooiziBS[KKSSSSB99911(1uiozzcSui[iuoiSS[SKSKKB9B911((((9Sci[c[[SKKKBKK[S[[ciuioc[uuouuozuoo³[ziiiiicuǹ˄1ڿzoc[SKBK[zz[(KiѰzc[cz(1(( (   1Bczoi[BSo[KBBS9(19BKK[S91Kco׿˿zKBBB((11(((( (1zSBBBB[zzuuc91SS99919999B9(icSci[iz·i[ciuuzz[Scc[SSKBBB911991 1S[Sccc[KKBBKKKSSSozzuScSScozzouzzčKKuiic[i¼˞[K°ocSBBic91[ͼuizi(  11KzcSii[91(B((9BBB9911(9czϳѹuui[[[SSS[S[zcB19B99KcuziBci[KB99B99B9 ([czicii¢z[couzuziBK[cc[K99999999BK9( ((KccicSKKKKBBSczzScK1K[ozuuzͿSccczz[KKoɿ¿Ҧ[̈́SBS[cSB9Kuoi(11(  (9iKKKKBBKK911B(((1119SuͿǹĹuiuziSKB99B[SBuzoccucSSSKK9999 BciuiSB[ķoiouzzzcSSS[[SB919BBB199KKB91 1KK[[SSKSBKKKSizuSiSBBKcozoĪu[KBKuzocuļԿu1ǿo[KB9BBKiz[K[uķo991  (9K[iziSK1999B[K9B91(1(11Szzuoi[cozɷiS9199KocKSouuiuocccc[KBB9(cocS[ciªuciu[KSSS[KB9199991999BS[SBKSSSKKKKKBKBK[iuiBc[SKBcozzͭoi[KBSou¼հo[uij˼¼ucKBSK9KuoB9coizǼo[99( 9((9Ku[BBBioB1B[KBS1(BB1999BK[czzuooiScuz’ccK19K9Kuc99B[cciicc[[[KBBKuocS[coizuKBKKKKB999BBKK9BB99KSKKSKSSKBBKBKKB[iizuoiKiiccKB[iԼuc[[u[K[czoSiiicic[SKzzǞo99KKK[K9K[[BBzouicB(91Bcoo[919119ouK9911B999119919K[cizoozuoo[cciu­z[KBB19(9zoBBB1ioioo[KBScK9BBiic[[[oziuzzucB( (919999BB9BBBS[KKKBBBBBBKKKBBBKSiooc[KiuuiocBuǖKS[KSuic[[z·˷u[[S1BSKczuu͢c19SSSSSSKBKcoS(9ScoiiS9KizoB9KS9999zzucK91B11(((199BKBcoououiiizžoS9KK191SuBB9BSuiuu[SS[i[9BBzĉuo[ciiz[11( (1((119BKKBKSSBBKKKBBBB9999B[iouucSouuoiiSǚuc[SK[uuccuoSzooѢuoccizoSK9(Kuc1 (1111Suoii[K9BBB99Bioo[B1B9(91( (1((1Suzuczuzɞ[K9BB999KiuKBBKSzcicSKBB[cSS[Ēi9uǦo[uoK1  (11 (111BBBBKKKKKKKBBKBBB99KcocizzoSuoouuoɞcio[S[[ioooiuϢui[K9BBKS1 (( (B[[B9B99BKKB9[zS[cuucKScK1( (((((BKziuzo’199BB99B9[oKBS[išu[KSSSKKKSS[[cѳ[K׼[coS9((( (((11111B9999K99BBBBBBBKB[iiicSK[ozu[zzooĞ[[czzu[SSS[oui[cooϼiB991BK9 991BSK9BB1111zzBS[KSciiuz[1(19111B[uժzzuiio(B9B919BKczSKiiK[ucSSSS[KK[[K[iϭ͢ucicB1  ((11((1(((9K911991((1119BBSiucSSSB9Kiuu[ouuuϪiK[[c[oicSiccczoc[izǰoK1KoK9 (  ((9cS19BBBBKB9(BK1SSKBK[iouuK9B9BBB[Ւzzuzuzzo€B919999BSSc[iu[KSSSSKSSKBS[BKѳ˳ciuu1 ((( (19BB9111( 191(11(19((119KB[icSBBKBBScuz[uuzԹuBS[SSS[ooiciiizi[iuzzuuzҿu[B911(1((99KcB9B9BKKB991ciB9S[SK9S[SKKSc[KBBKuѼuoiiuzzuzooz˿K99(9BBBS[[ouScϰoSSBKSSKKKKKu޹ѷ[couo1( 1( 1(9BB9991( (19991191919KKSSSSKBBBB9K[iuizuzˍSSSSS[[[czccc[[z[ciozuiϰK9BB((11BKKKK[[B19BKKBKzcBB9[cSS9BSB999Scc[cuͭoiiczzu 9KB9BBK[c[oiz̀K[SSK[i[[KiҢҼicioioiiS (19B9999B9991 (((9B9BBSSSKKSB9BBKKBBKBBScozzczoic[ccccccuzuoi[[ci[SScoϹB(9K99KSKKKKSiiKB91999SzK1BKKi[S19cK(19[[Soذocouzu(991BKKScozuiuz˦[[SKScc[SiˢͰz[ioicciu9 (9BB99B9BB9( 199BKK[[iii[BBB9BKKBKKSSKcuz[uѼuzzuiiccciiuoiuucSKSSccSKzzziɭK(9SBBiocKSS[i[BB19B9Su19BBKicK99[K (BKBBuճozzi1B9B[[[ccizcBBcc[cc[KSĖiioiiicuo(  9KKB9919999999BK[[iuouzi[KBKBKKc[[[c[[ouuS۹c[zociioi[Sizz[SSKSSSzoioSKljK(Siccuciciiuz[B9BSKBi[( KKK[[BB1BK999BB[ϳuzuuǚ911KiSKiuuSBSoSS[[[SoǭucoouzzcS9 1KSSBBK91B111BKSczuzz[SBKSK[occcc[ozz[Kɉciizzooccciiczo[SS[SzcBcuuS1coĿuSBSccocuoc99BKKSKoiB9 BB9KSBS99S9(9KK¼͖uzzuB1KciKK[[izzSK[z[i[SB[˹ciiu[  B[iccSSB9199BBScuzoc[KSKKiuiic[SizzSSύS[cooioi[SciiiouSKKi[c[ozzouc(KuǭoSSSucioKBB9KSS[izS9B19K19B9BB9K9BKB[˷ǒzuz¦SBS[SSKKS[coiz¦cSuͭcS[[Si¢uuzuiK( K[c[iioocBB99KScouzoccccccuzic[SScuzuiKBҞ[S[iucczoiiiioiccizzcKciii[izzouzc(BzučcKS[cSKocKB99K[[izoB1991B999(BB9KB9BKͼǰooļcc[KKBBBK[cuc[[[[˰zuzu( ([oiSBSioo[BBBKczciooic[iiiiooooiSS[iiSKScKKK[co[zzuicc[[[iicicozo[cuzu[izoS 1u˭uKKSBBBK[[BB9Sio[ic99BK[KKK1(9KBK[cBScѷĿucouԷuccSBSSS[[uSoi[ccͿzzB1iziKBSoocSBKBczcczuouciooc[ciiouu[SK[[BBBcBBSSciuui[[uzuoccKKKSS[[[uc[ui[KBSozzzi9(uĖSKBKKBKK999K[[[z[1BKBBBB9119BS[Sc[coˢɷu[c[zĞi[K9ScKSouuuzϚ[oǖcSuǦoS( 19KuzcB99Sii[BB99ooii[i[ccuuoicuuiouoSKSSSBKi[SKKBKccSSco[Siuccc[SSKKBzzzoioiS99K[[[o9 [zѰcKKKKBKBB9BKBSouK(9K911991199ScScuio–ѷicoiucSKSB1BicKBi¢zzɒuǹooK1111BS[ooS1199SSK999BSSicSuSSizzzcSSKBKcc9SKBBS[KSKSoiBKuzuocKKSKuiiuzuo[BKB[iS9czB(SǚSSKBBKK9999BicB11B9KB9BB9BBSKBSuocĞ­ĭɿczouz[B(11KoSKScizdzuzoSB9BBBBB[ccB(1BB[cK91(9ocoocB[z[ScziKBBSi[1SK9BBBBK[S[cicKBuocSKBooiuzzic[KBKoo[BK9c[BzѳKBKSKSKKBBc9111KBB991B99K[SS[cuco¹¢˭ɰzuzKBB11KuSK[[oizҰoSKB1  (9SKB91(1Sc[919oKSSKBB[uuozziz¼ªzui[[SScS99o[BBKBBBKBB9K[o[[ci[KBSuzzi[co[KBB9BcoBBz˭uciic[K9Kc1 9BSB1111BK[ic[c[[uouĿٰ°cKSKBBKiuS[c[izzzcSo˚zo[KSK9(( 199( 9KS[9 KoKKBKK91uicouzɿcS[KS[[BKBooK1BB1BKKB1BB[[[BK[i[uzzoioiSB11(BiK[zzcK[SKK[uB19B9199B99KKSS[cKKcozܷǹiS[c[B9[uSS[ScS[S[zzcϷucSSSK1 (1BKBB1 (B[[KKiziSSuzo[Kozcociˢzzo[[KSSB99B9[cK9BKKBBB9KBBSiSKSi[SizucSB1(1SzuKKzciccuuSBB11B9991S[KKKSSBBSۿǪocuuSKBB91[z[KKBB9B[[BBKuĚii[[[SK911(1K9BB9111K[[KciciiizziSu[czzKKK91999(1B[SBBBBBBBK9BK[[iSuSioS[uzcS9111SBizuKB91SKBB19SKBK[[KBBzѼuiuzuKKKSKBKz[999919B1999Siǰzooucc[[SKB11(B[SK9(((9KKK[oc[cc°˹zziooi[[B91(1(((9ccBBB99BBBKSKSiziSKS[ozooicio[[KBKBBiuzzcuuiB1(BB9BKKKSKBKSKKKi­zuicuzzuzoBSKBB9So[KBBB999K[99KKҷzuc[SSSKSSBK[[KK911BBBKB[cSiioķϦuouzzuSBKB991((1B[iSBBBKBB9BBBi1Bci[ozo[KcKBK[KKScczuouuɷzuoccǰS999BBBS[BSSBKKS[S[zz¼°uuiizzi9KKSK[o[BB9B9BKiS99SǞui[SSKBKSKS[KKKBBBBBKKSic[iii˿ڳzuoozuzuSBK91111((1KccSBBSKSKKKSK 9izuooi[SKSK[ocS[[uzzzocǪoKBB9BBKcSS[B99ScSuzuzzuccuzuoBKKS[ioc999KBK[iSuǪuzuicSSB91BBBBKBKBBKKKKSS[cKKS[SzϦouzouuoiiioS9BBBBB11(((19[iSBSKKBB[[(( 1czļzuii[KS[cioozoiiSK9111BSKBKS[S[[ozuicuzoozuzcB[[cccoucBKciKuͰciic[KKKB191919KBKKSKKS[[[oiSB9BBizuuouoiiic[oziSBB991B[(1((((1(KocKKKK[o ( 9i³uoo[SSScuuzuzzuzz[9119KKS91[[KKS[ozzzzic[[ooiu[B[[iozzϼicoocKKKBB9BB9BBB9BBKKKS[cio[KB19B[uozzzooooizuS1BBB999Sc1(( 11(1SicSBK  9ouuocSKS[izzu[iSK99BB919SSKBKSizoii[cooozzzzSScioljoco˭zoiioi[KBBBB9BKB9999KKKBBS[[icSB9199SǼuouuzoSBBBBBB9BS[9191191(((KccKo9 ((( 9uozzoSKcizuoouzSKiKK119BK9BBBK9[iooouuiouzzuuuzuBKci٪i[KϹicciooi[SBBB9BKKBBB99BBBKKS[[c[K (((9S˹uzoiiuccSKKKKKKK[i111((111111BSuK  (((  Kzouɰzc[uzcBSozoKucKBB91BB9BKSKozzouuoo[iuzzucczoSizԪuSBo˰ucccoiiSSKKKKBBKKB9B99BKBBKK[c[cK1(((11Kuİzuiioouuoi[[[[[[K[iK11((1(((((1K[  19[zzoi˹zoB9B[uiSz[SK9KB1(199Kzouiizzuozz¼ĿzcBS˼c[[cuucKKK9BB9BKSKB9999BKKS[cc[[KBKBBBB1BcϹuiciououiKSSSKKBiucK1111(((1(Bu( (((  (cc19SozuicoͿ[KKB[z³zKuiSB1991999Bc­oouooci‰zzioKBǭoucciiSBBSSKBBKB99B9999BKKK[cciocoooi[SBS[iѦ[[iuziSoz[9BKKBBKiKcS111111((ui9   ((((cu[1(([uooiSczİo[oKSiS(19B9K[[uoiuoouzz۰oic[iz[9o˹zuoccicK9BSK99KSKBBKKB99BKSSccizocozuu[SKScoɄcozo[oSB1((119c BcK((119([K1B1 (  [oicK((9ccco[oiijoķ[B9 1B9ioiuoozzzz͢ui[SSocK1ҹzuccccKBBSS99BKKBBKKKBK[SSSciuo[KSccooi[[[[u԰ii[ioSB1((((9KuKBSuz[KK(B9ioK ((( KuucS[i[19cozc[[oouķiBu999SSBz˚uuuĪuuɰoooiScoz[9Bc˚zicii[BBBKKKKKKKS[[SKSozccozcK9B[ciocSSS[c͢c[[c9KB19BKcuuzS( ( Boocc[B[oS( (cu[Szuuķzu·zzu9iK(1[i[Ǧzoozzo˷ucouuzK9cͰoiicSKBKBKKKSKBBS[[Scio[K91BSSS[c[K[zԿSzc(B9B[zuozzļѪS1 (BzcucKKKK[K1 (coBSzouczzz9[i91[ooĦɹuozzzu˼¢ozuioɚS[’icci[SB9B9BBB9BBKS[SSoBzzSKK99BBB[icBSz˼cKB9K[uocz9K[SiuĪi9BuoKKBScK(1iozuuzzczuzu9[i91B[iϭɼzuzuzouuozuǷouuoͭͪuiz[ii[K9999BBB999BSucԭzoc[B919cuuoSSSčSBK19Scciouuuc[uK[[[oc1uijoiooooc[Suuizocoiizzu˿zui(KoKSo[cͿϿzouozzucozocouoԿoѷuoo[ccSSKB9BB9BBBBB[ooժoouoocSBSzuuo[ciiiK91BS[[[[[cuicuccİzcɭzoic[couuiiuɼu1[o[Ku¹uzzoiouoozuiozuzѷučuiiiu[ccKK99BKKBBBKBSc[zzuuuic[BSuu[ccu[[ouBB(1Sc[[iocuuoķuzzooioizzuoioz¹u([z[czzouzicozzuuioͭcɭioiciui[[SKSKKKBKKBKK[cuz[Szoo[SiuoKSuu[c[ ( 9iociuǿǒcuzzocciuǿ·u([uzzzuuiouuiozuտuoĭٿcuuuzi[cSKBKB9BBSS[SScozSccicB[[czSoS( (Biooɼzoǿuzzoicioi[uzuouz[ScoozĦz(KuuzzuzzziouuuzzzzzuoۭzuĭҹiuociSKKSKKKKS[SczoKuui[KiĄ[coz[( 9[cz³z˪zooc[cuzɹѿuzi[Scoizizdz¼zzu(SuuiiuuoizziiuzuˍijǞzooc[SKSSBBS[iozziSuzK[oѪiuS(((1SSSouzouBSǿijҿzo[Sccoooi̳zuzi cuzzzoiuuuzzzuuzطoo˿ѿuucSKSSS[SS[czicoiiuļuouz[( 9Sic[cuuiuzuozuozzzucļzuzz¼zi[[ozoio·zzo([o[iiuoiiozuuziuoǍdzҼooocc[SSKK[[czuiicczoKizz[(9KS[Sc[SiooczouuouczzizzozcizzǚĿziiiocizc9BuuuuzuicouuuziizͰɼͳzuiicSSS[ciicizicioSczzuzKu[(9KS[SK[cizuiiiĉuiziiuuuziczzc99[oziScuzzoɹzczccczu9Bzzuiuuzuozcii[uϿ¿͹zoic[[[[ciiiuzooccccizcozuzi[SKS[cozouٷoczSKczoucSzzuuiS11K[ocKKcicɹouocuzo9KiªzuouzuiuiiuoԿdzªuooi[SSSSciuzouzoii[coSii[K[uušzo[99SuuzzizuoioKBKK( B[uoc[[uzɹuouzzzzSKuuzoooociuuĹͰzui[ouc[[cciiouzuoicizoiciiidzo[oui99Bcuouzoooo[[K9SS99K[uzcucuuiuu¹ķou­zzS9ɒKuǪzuiooѪĪϷoiciooi[S[[iiuuuzocczuuzuzǭzuuoiucizzoccS9BKcozzc1(Kuu[((  [ªzzK(((9cczi91Sz‰i ((1c[Kzo99BS[BS[couicSB9S[cSBBB9iiK9( (K9KKB19911(BS1  9B1(      (( (9BB9911111((   ( 191BKcic[[ooiS9((1((((1BBSSKB91(((  (19uzo[BBKS[[Szo91B[K9( Suc[9  ([icuzucK1Buoi9uK1((Kocii( Bi[9BSiozzii[B1BS[SSKSSiicSS(   (KBSBK911999K1 ( ( (1      ((9911      1(z199coiooioi[B91911119KKSSSBBB919( 1 11919ziK9KSS[KBo[(    KzK  1Ǫz[S[ziB9(Si[K1zK ( 9ozcooK19So[BK[ucciicS9BS[SKB1BSSSSKSK9  (  KKB9B91(9B9     19((( (((     1SK(    ((((111[99B[ic[cciocSKKBB911BS[cc[SKB919B91((91919uzoiB9KSSSSSB1 izzuK 1119­SSczuS99[[B(1u( (ScK99c[ScSBKiccoicB(9KS[SKB[[B1((1KB   KSKB991(BB(   ((1111 (((9B99(     1cc9   111BB9BK[ccS[io[Sc[[SKK999BKScii[9BKKBB91(9991Buiic9B[c[S[K9 ( (i[KBB91KoiB( ([iuSBKo[91iuK KS((S[SKSKczuSoocK(9BccBBBB1((((191( 9SSK91111BB(  (( (( ( (9KKK99 (   1B11( (( (  1(   1SuK99K[c[S[c[K[cicS9B91119K[[[SBKcSKK91199911zuoioiS9SSBSK9(  (([(((11BBB((99czccuuiciioc czK ([oS99[[BK[ioizc99KScK1B1( (1(9BB999(BS[SKB999SK(  (( (( (1BSKKSB99   111(1 (      9iiK919Sicci[KB[[ci[KK91119BBSiic[[[KB99BBB1((uozouoiSBSSBK1  1uuS( (1K[ziciiooi[uuoiS (oo1 KzizuBBKKKcS9Scc[KK9(999911(   9KSK919BKK[B(1991( (( (1BBBBKKKKB11   (((11(  (   ( ((   1SucBSKB[iccc[K9S[[icSK9(1(BS[zzo[KKK9(19991((1uuzuuicKSK91 9coK1  ((Bi[99BKSKzooi[[zziS(B[S (ocSuoKK[[[ziciBSKSoi[S1 1(  (KS[[SBKKB91  (( (199((((((BKKBBBSKKB(  (((111 (  ( ( B9 (9S[[BKBKcicioi[KBBKSS[SK919SooS119( (( ( (zuuuoii[KK1((((1( 1So9 9KiKSSSSBicoiS[[[ocB(1cc9BcKccSuc[[uui9  (((919BB(  1K[KK[[B99BK1  ((9999(  ((BSKSKK[S9BB9(    ((111(( (     111 (9BBKS[cuSBBS[oc[ciic[B119BSSK91BcoK1 ( (1( (uuoiic[SK( ((( 9iB( 19[zo999KSKSzuoz[KSooioi9(BcS (ozcB[SK[BK[SSSS     ( 1S[BKSSB1991   ((1111( 1KSKSSciS9BSoK(   (((((  ( (9BKSSKS[coS99BSc[ccc[KB91 19KKK99KiS( (( (((1(((((zuc[SSB( ((  BzzK91Scz ((9BBuzi[ziKczucc[99K9(1coccK[K(((B[ccK        ( B[SKB9BB9KK(  199B9(  (1S[[c[ScK9Bcuc9  ((( (    ((1( (1((KKBS[KSSKSzKKKS[S9919KKB9(119911BSzoK (1111(11 (1( (zcKB91( (  [z[B1K(((( SuzcKciS[ii[SK(( KicSi[B1 ((Suzo1 ((      9[[[KB99KSK9(  (999111((( (9K[i[[[B99KSB91((9(9111111(  (919199KB1BSSKKS[[[KBczSBBKB11((B1199191199Scz9( 1(99((111((1(((1SK9(  (((((1SzzcS9((SuzB  9zoz[B[zcc[[S1  ([[SK[[B9( 9u9 (   (K[ccSBBBSSK9  ((19B91(( ((((1B[cS99119BB1(9BKK9BBB9191(  ( (9BBKKSKKB99SSBKSS[SS[Szz[KKBB91(1 (1BB91(1KoiK(111(1911919(( ((11(  ((( ( (Kc919( (91(11(  ([uz[9[oc[[[B(  ([iccSBS1 1o(  (1(((1BK[[[B99(  (K[[[SSSKSSK1 (19991111((11((19B111((111( 1KccK9911199B9(((( ((11BS[c[[SKB9BBSB[[[SciioozucSKSKK1(((((1999BSiK(19999991(111(1(11((1( (( 1co[[iczi((1(    ( 9zSBiiSSS1  Bouiic[KK1(BoiK (199BBKK[iciuo[SKB1( 1[[[[KB99KSSB ( ((999B991(1(( (  (1191(99KKB9BB9BB91(((1991( ((9SSS[ic[S9911KS9[iciciiiiouuo[SKKB991 1(19KB1(111111199111((((((1((((((  1BzKK[[S1(1(( (((((cc99icKSK( 1BizzuooicK1(1ci(  (19KSccouuciuuSKB9B( 1(( ( 1BKSB9BKKKSB( ((((119BBBB9( (   (((( 191KS99119BKB99111(((( BSci[S[icK911 1BBSiooui[ciioi[[[KB(  (( 11( (((9111119(1(11911(1(((((BSizB191(((1((99( 1 9ooiuoK(9io[K9 ([ozuiii[[S91Ki9 1KBBKSciizziS991(   B((  (BKBK99BKKKSB1 199BKKKKB111(  (1(11((1(1B9BKBSSKKB91BKSKBBK[oiSSSS[SBB91( 9SKKcouzzc[ouicoui[c[9191(( 1(((1(1(119(11B9B11191119 ((1BKSocK[uz[19(  (B[[K919B(  1ozuooo[9((Si[K1 (czuzooi[SK1(BB((9BioSK[ici[KB(    ( (B99BBBBccSSB 1199BBBKBBKKKKB( ( (1( (111 (11(99911K[Sc[[SKSoicoooocBKSB9B9B911(1BK99[ouzu[SciSScuziicSBB1 1B91( ((19B9B11191911999919((9cciiiK9BB99(( 1199BKB999KiS1  KuouzzoS9 (iziK( 9izc[uzoiccSB( (S[ozccc9    1BB999BBSicSB9( ((19BBBSKBBKK9 (1( ( (11((1(((1919BBS[[[SSKScccoiKSKK[cKBKSK99((9KSS[iouzocc[SKS[ozoioi[K1((1BB111111111919BK9B9919119B 1BSS[oK1((( 1(11( 11((1111B11BB1 (zcSoocS1 9oocK( (Boz[Kczuii[S1 1S[cS9     ( 9B19BBBBKSK9911(1191B9BBBKKBKB9(((1(( 1( ((11 (11119119B9ScSS[SKSKKS[iccciicB9KKB9119Kcouzzzzcc[BKS[uzuiuiSK(19KB11111111(19999B19919BB99B911( 191((99( (91111(91((( (((111(9zcSizi[K( Sici[( 9czcS[uzzo[SB      (      1KBBKK9BKKB911((1((9BBKKSSKKKB91BBK9K9999B99((9111119BBKBSSKS[SKSS[iccoociocSKK1 (( 1Kcoicuo[[KBK[coozoSB9BK9(11199119119BB11919119B99BB9999999199 (99((11(( ( (( 1occS[[K(1czicS9(Bzocc[cuzocK1((1999(11  ((     9KBBBB9KSKB9111119119BBKSSSSSS[cziBBS[oi[ccB911(9199B9BKKS[SiiSKS[iiooiccSKB91((1((1S[zz[ciic[K9S[uiuziK9KSB911111911B9119B919(99B9999BSKSKBBK9BSK1((191111(( (11( (ciS1BSB [zuo[9(([iii[[uoK1 1BB9BB19B99(  (((((   (K[KK91199B9B9119(1119BBBBBBKSiuucKSc[[S[cSK9B1119BB99BKS[SScSSSiuouzucK9((1( ((1Kiozu[KBS[ci[[[izccui[[[SK119991999191111KB9B119B1119B[KSKSKK9KKKB9191999( ( (91(  SuziSKScK1iz[[S9(9uS[cS[zz[B(  (199BBKK91(       9KSKBB99BB9191((919BBBBBKKBK[izocczucizoiicK911BBKKBBB9BKS[i[SKKS[[ouuK (99119((Siuzzzo[KBS[[SSSiucooccc[SB99BBBBB9999B11(9B99((11(119B[[SBB9KSSB9BB(((((1191( B9  Scccziiic[S9BuziSS( Bzz[Scc[[icB ( (1(9BKKKB1(1   (   (1( (KcSKKB99BB9B99111(199BBBBScizzziSBciooi[[cSBBBBBKK99BKS[[[icK99BKS[iou[  1B9111(9[iuioocKBBBSS[cS[cSciuoocSBB9999BKKKKBB919BB91 ((119BBKKSKBBBB111111911((( 11 ((( 9S[[cozzuiiuziS1Suic[1 (SocKKSSSccK9 (9BB91 ( ((11111 ( 1SSBBKBBKKKK9999991BB9911BcuuzzucSKBS[[SSBBBBB9BBKSSKSSSS[ciiSBKSSS[iuzzuc1 (BBB911911SoucSc[K9KBKcooooiiooi[cKBKBKKBBBBBSSSSKKKBBK999BKSooSKKSS19911991((1(((1119911(ci[cciiozuoiScouiK9cuicB 9Sc[SSS[ciS1    (1(  ( (1 BK91 ( ((9KKB9B99BSKBBB9919BB9999KciouzocKB99KKKKB91B9BBSKK[S[c[iioiioSKBSciiuoc1 (1BKK9111(1Szu[B9BK[c[[[[iuocoocio[[cS[icc[c[cKSccSSSSc[SSBKSui[[S[B911BB911111(( (1BB(((1[oc[cicSScuzzi[ScziS9Ki[9(1S[[cSSScicK9    (((( (1(9B( ((9KB19B91(  (119BBKSKKKBKSK9B9999BSK999BScciiccS911(1KKKB119BBBK[ooiciouzu[[ciozoB(1B9B9919(99KoiS91KoiSKS[KKS[cciccizuzoc[S[SK[K[ioiii[[KB91BBKcc[KSKKBBKKB9(( (11( 1Sioicccc[[KKcioii[[zoK1KcB( 9K[[c[cciiSB( 1(( 1( (99BSKKKB99B9BS91991((((19119BKK[[S[KKKBBBBB9K9BB919[ooccSBB99B91BSK11((9BBScou[ooKczi91BBB19(99K9B99KSBBSc[KBiuuKB99KK[iiicioocKKBScSS[[cooioocSBBB(19B[oz[[SSSKBBBBK911 (11( ( (9zuiccccSB1(9KS[[oziBKS1 (B[ioi[[c[KB9 ((1KSc[KK9   (BKKK9(199SK9B1(19K[iucB999KSSci[BBB9KBBKKSKK91Kzzcc[SSK99B99KKB9991199KiiBouzB(KKB1 (9KSKKBBBBK[cBBSBozoKB99SSizziiouocSK[i[[iiuuoicSB999BBB9KccSSKBBKKKBBBB911 (19199(( (izoiSKB111999KKio9KS1 (Souc[S[cS991119KSSoS199((  ((1BB1(1( ( 1Sccou[KBBK[cci[B999KSS[SSKK9BczucSKSSKKKKB[K19999B9BKczuuzS9[ozoz11SSB1111BKKK[ccciiiKBccBScK91BKuiozic[[Siooiciouo[SB99199(1[[S[91BKKKKB119B9111 (1( 9cuc[K9191(99cc9[K ([oiSBBBB( 9KBKBKKB9 1B9991(   9[[Scczoui[KKScccSBK91BSSccSKBBKoz[KBBSK[cBBzcBKKKBKS[cuuccocioSK[cooo[(1S9(9999BSSSiicozi[[[c[K[cB1Kcizzuui[cc[couoiuzoKB11199KBBSKBK999BBBKB9991111(  9[uziS91119SS[oK( (Sc[K9191(9BK9B911 (1119KB1   cuu[c[i[cuocSSK[cSBBBB9K[cicSKBBSoccSKKBciB[ͼKBBScoiicc[KSc99S[oiuc BB ((1KS[iicuiSSSSK[uoSSuuuzuooiK[ccuoiouzoiuu[B111999999B9BBSSKBKKB1(( 19(( 1cuSBKBB9B[i1 BciSB(9BB9B9BB99( 19991991    ScBSSKKci[9(BBSc[SSKKKKSioc[[SSSuzuouoSBBSS9SіicciucoocSB9[oKBSSccouc9(1KB  (BKS[cc[ciiciocKzKoziKB99K[izuzuuuuS119BKKK9B11(1[cSK9SKB11  1999999Kizz[BB919B1 (KSSKBBcc919BB9111( (9119(199     (1iocoiSB( ( (919KKKciSKBKSK[iii[c[[[uzuouiS9BBKS[uuzuooii[SciSKSS[ozu[(9cK(BB99KBBKS[[KSci[coiiiuuzB91BBB[zicouzo9BKSooSKBB1191S[KBBKK99( (9KKSS[[uuuc9K[SB11 1KSSB9KK1(9KKB9991( 1BB99199(    ((9cS[iKS91(19BB9BKcui[KSKS[Scicciozuoo[SBB919Scuˉ˼cS[iccc[SSSKcoi9(1( 19BScSKSSS[[cicuu[iiuicz11B[KSuiciiuS1Kou[K9((1191(1BBBB9((19BKS[oooiuouzzzoB[iSB191 (BKKKSSB11BKKB91991111BB99B99(  (B[[occociSS (11BBBSSS[iuuc[[[ccciiuzc99B991SuzoϼĿϚuB[[SocSSSSSzS 1BS[cooK1BioiiuzzK[iuzu[SzoozBS[K9iz[[cS(BoS99999(199BB999 (KS[[[ozuuuuzuzuzoSccS9(1( 9Sccoc[9(9KKBKBBB9(91(BBKSKKB( (1B[uoooiSo[1 (11 1B9BKKScozzui[SS[iooS9KKKSczoz¹žoiBBScuo[S[SK[S  19K[[S[[B1B[ioouzǦuiSKK[i[ci[S[99B9Bozuocczz[[cS9cozzz[B99191(BB1BB991(9KSccizzuzuzuuoc[SS911((SocciiS9B[c[KKBBB1( ((KSSSKB1 (19Sizuuo(   1K[c[cccioioocS[ciuuic[[[[oizzcoİioo[KB[K[[cK9KSKB[K 199B[c[S[99BiooiǹuSKKczo[SSS[K9191 1izc[[ccioiozuzuii[19911BB19K1B91999KScouzzzuoouizzoi[[[K9911Kco[KocK9ScciSSK91  1[ocKK9(  1K[ozzc (9SizuuuoiozuiS[izuzzio[icooozzoSSKB(KccBBKBBKSi[9 19KicBSKBB[izϚucB9SocKKSKK91(1(K[KKS[ciuzzzucKK[9919K19919BKBBBSScuzzzozoiziKKK91119Sccc[ccBBSccSB9((( (BSczoB9SSSKKBBS[cozzS19KSiuuoouooicuiuouiizuzoSKSB(9uzcB11KozzS9KS[SK1KKK[iozuzzzuozSBB[K91KB11B1(( Su[SSSSKScoo[czc9KccBBBK[1(11BSKB9BS[uzzuzcooSKK91199SS[ciicKBSSK1(111(9Siouu[S[ouuuucSoiiiiioioi[[(  1K[c[S[izuouicozczziiciSKozzzoc[[[KSK99BK[u[99Koc[SSSSB1199BBSiouziuͳc[uo[BBKK9BB(((1(((9ziSBBBB9BKS[KKcoocSccBBBBc( (1BKKKKSizzuuozicucozcBB11BBBKSc[ccc[BK[B111199[oizz[SiuuuucociiSc[cK  1cuKSiccuzoiiuuuioooocziocuzi[[[[KKSi[S[iooSKKSB9BB99B9KSi19SiSKuS(1 9911Kcuuzuozcz¼oSocSKBBBB99K1((11BiBBKSB9BBBKKKSSSK[icSB9KKSo ((119BKBB[ozzciouiS[cozzuzoKB999119KcoiciiS9K(119BB[ouuz[uiiozuozuiiiiS[[B   1BizoSSoicuiS[cc[uuuBcu[oiKiiSKBBS[SSKB[iiSBBBKBBKB91111B9K[SB9S1(91111(B9[zoozzocucoѼiSi[KB9BSSB91(1BBKBci9991119KSBKBKBBK[[B999KSKS ( (19KSBKcozi[cccic[ozuuoooK919919SczzoccicKS19111[icoo[ocS[[ciiiiccciicS( 1KK[zo[uuKSuoK9[icozzuc9zziziScuuiSco[KKKcouuSBSSc[[SKB99BB((19(9(B[iS1 ((111BKco[zzzouicciϭicicB9199B1 (BSSKKBSziB999111BB1BSSSKKKBBBBBKSSS ((BScKS[izzzSKB[zi[iiiooiiiSBB91BouuuiiiiSSB119KocSiiSK[Sc[BSSS[coiiiuc(9[[iuuucSizK9o[ 1S[cuuui1zui[[ziB[ioiKciSK[iuiiSBK[SSSKKBKB(11( 1SKcuB (9BB11K[iouuozoccuooz[B9(999(((9BKBK9Boc991111BB99KK9BBBBBKK[SKSKS(( (9ScSSS[izzzzSSBKzzciciiocccSBBBBi[BouciozocB1(9cu[[ciiBBKK[[KKK[Sczzouz9(1KocK[zu[izc99czc1(c[iui[[cS(zo[KSiiccoucKizzociozuuoouKBKcc[SKKBB119 (((oiBcS9((( (9SK9BKizuc[cuuc[i҄i[ioSK9(919999B999119KK9B919199119919BB999K[KKSS[1111 (9K[KKcouoiuu[[[zo[[cicccK9B9KuoKKccSS[c[K1( BzoS[ciSBBSKSSB19BKizz 1KSS[KScc[[iiKBSSB(9oozuK1(ozuiSKKBBciozocouuuuuicc[[[B99[ii[BKS9( (9BocBS1(1191(19BB9B[ozocciuccĪcSio[B119BB999B111119BK1999BKKKB9(199KB919B999BKSKB( (BSSKSiuooiiuic[cuo[ouicccBBKBozuiKBKKKKBKKB119[zuccc[[B11(9BB91Kccuz1ScSBBBBK[K[iB1[KBi[11KzuS BzcKB9BBBciou[cuouzoiiS1119BK[c[[SB( (((9SzzK9KB1((199111S[ScicSiuzzĢzzoS99199999BB999911BSKSSKS[[SB[BBBKSB911BcK9KK[ccB(19BKKSczzzicouSKS[oo[[ooiioSBS[ui[cBBKKKKKKSBKSiouiSS[[11119BBB1S[iu1BSK9( ((9BBB9 (K9KS19zoK  9uic[KKKSKBc[[uuiuzziouS1(((9BSciiS( 1111BiuK99( 9ScSB99KSBSK[izzB99BKKB1191(99911K[[[iuzi[[SSK[oi91((1K(9SSci[B1BKSKScozioz[KK[[c[couoio[BczzcSSK919KK[SSBcuuozicKScS(99KS[[KB[ouz[B99(   ( (([i( Bou[[cKSS[SKooizcuu1  (BS[icB( 9B9BizzS99( 1B[oiSKKBBB9BBSuuccKu㒒91KKKB99B119B119Kcuzz[iic(( B[iuo[ccSKSKBK[cuouozzc[S[[[ccouzociucSSSKB9BKKSSBKiuziou[K[K( 9Kci[cBBScS91B9      BuS  1[ou[SS[Scc[[Suo[uzziozK  BK[ciB 19BizucSB9( 9K[ouo[B919999Siuu[KS[[zB99BKSSB9199B9BKSoozouzczi[B ((Bzcou[ccc[[SKBKizouzizzzi[KK[oiciuocoo[KKK99KKBBKKSSBBS[[SB1  ( ( 1(     (ic1 9B[oz[BBS[uucuuiuoiciuuzc[B  (KScoS (1Succ[919919KioB1KKBBBBBKSocBBBB[ɖS9BBSKBB9999KSKcuoc[iBS[[cuzoSB Ki[SzooooiSKKKKczuzzzoizouu[[cccoicczzouoSKBBBKSK911111(11(((           9ozi9 (BocuuoSSKccoo[zozoSioc[cuS 9BS[c9 (((19KzKKcB99B999KzzozuiK199BBScoz[999KBSԿ۪K99BKBSK99Kc[BKcui[KBKSK[oziB1(B9BB1Kcczcuuc[KSK[ouozozzzuiozu[[ioouuiiuzouziSKK9BSSB91111(     ( (19B19Sc[zoocBB[zouiuSS[S[[c[ooc[[BS[SBS[1 1K[cSB1 (9BSuocKS[1(1111Kciizɭo9999KSKS[K999BB9oג(1KB9BKSKBKB1KuuicKSKKKSozc((S[ (9Kizcooc[Siioocoouoiiozc[zzuoiouzzzziBBK9BSSSB991      (   9KB1KcS[Scc99oouKB9BKccozc[SBKBB999B9 19KK[i[9( (11Bz[BKScK91((1K[S[iB99B[KczS1919B[oiB[9KB11B[KBKB(1coc[[[[[KB[cS91(KB(1KBc[c[Siu[SSiiouzzzzuuuuouzoKBKSSSSB999KB( (    (1     K[SBKSKSSuzK1[oiKSKuc11BSBcuiKBBB99999K1 (BSi[SzuS1  [o[SKK[K11919[SScݳ[99Koozc1((9KiziK1؞BSSK919999( 1[uuicSB999BocB KcB(9iSKSozSSK[ooouuzzuzzSBKKSS[SKKBBK91(     (   (199  ([uiczzB[c[ou91KcS1BS[uBB[SBK[SK9919KBB9KKS1 (9SccSSzc1 (9uS[KKKSS91B99[[K[KҒ[[uooiS9(1B[ciicccKBzSB911 (9( (9Sci[B9KK99SB Kci(9coi9[zzioucS[iiozzzzucouzoSSKSSKKS9SKKKKB99   (( B[ccKB9BKiuiuĉSSiicoc(1K[9K[SKzSScB1BK9SS9(1999BKSK1(19KKKKBBKSB (cS[ucS[[S9199[i[BS1KoͭziioSBB9BKKS[[ccS9(ύB99KB111 ((1B[[[S9BSB11K9BK9911KcuiS[iKzoSKucKK[iuzuuzoouuoiiooSKKBSK9BS9[KSBB91(    (( (BKS[[iiizuiiooB[cicoi99iuKSS99uccSBB[SBKSK19BKSBBB((9KK[[KK1 (  KSo[zS9(999KK[S[cѰoc[SBBBB9BBBKBBKB9(cǿ[9SSSSBB9 1K[SK[[KB1 ((( Bu[99B1B[icB[oSBczc99zio[ciooouoiucouuoiSBKKBKKBBBBSKBB999 (    ((  (1Kciooccc[B1B[iic[cS19[ccB191BzcK99BKc[KBB9B9999K1 9SKKKiiK1 (BioczzzzoccS9B99BSczci[SBB11119KB9B9BKB1ҒKK[[SBB1(BS[KBBB91(((91(Sz[ 19SccS9KKSozcBBoucSS[iouuuouuuzi[[KBBKSBKSKKBBKKB9119((11(         S[SScSB1SoocioS( 19KSBBBBB19uz[BB9BKic91KSK919SS1(1K[KBKSB( (B9S[zcSccozozK999BKSKozzcuKKKBBK9119BB9911BKK1u9SKKBB91(1BKKKKB9991((19K[B( 1BB[[K99KoziB([oi[Sioiouiiouzzo[SK9BSSSKSSSSB9BKB19BKK9991((  ((      (K911zciu9 1KB((1B[i[SKu[9991KSK1(B[SKKBSB 9K[K9  (B((1ii[[[[ouKouB199BBBBK[izoiuoKBKSic1(9B9BBB999919iܰK9KB9B9( (199BBB99B9111199( (S[czi1Siu[ci9Kzui[iiiio[[ozzzoooi[[[SKS[SKSKKBSB9BB919B[cS[[K9199  1999(  (Szc(KKBB Koiiicc[cKBB1191((1BSco[S9 9ccB((  KocSSKSi[9SS9BSKKBBBB9B[oooS9KSoc( 191919199B9Kcz9BBBB(((91119999( 91((9(( Bo[SSKBii9BuS[couoc[ozoioouz[[SSKSKSS[SKKK91B1(1KBK[iuui[S[S111(111KcuuoSB9KK91   1uč( (cSKSBco[KSKSSKc111191(((11Souc11SiK 1Boo[SSScuz191KiiKKoiKKKSciKBKoocciiioouc 1119BB99919BKS˭91919 (9B111(9(((1111( (((1[ziKKB[zc91Bziioouicciu[izzucS[SKBKS[S[[KSB9BBB11BBBKco[icSB919S[[ozuii[iociS1   S[B9KSKSB11119Buc19991(( (99[uoB 9o[( (SuuozSK[c[izcSB9B[ouuiS[[oz[[i[KS[ooBBB9B9B991919BB99o 99(111KS99111(11911(91 ((BuuiuKBSczoB BzzuooouoccouciiSS[[KKSSSS[[SKB9BBKB999KS[coiooKB91(BKiuuiuii[cuSciSK[[B1     [iK9BK[B991111KKB[S1(((1(( ((9[i[9(1cc19( 1[KSSK9K[SK[cS[uoiiiici[cc[izoSBKKKSiK[[KBKKBBB9119B9Bu1(9(119Sc[K1((119B119B1 ( Kuu[zKKSizS(( Kzouzzuzzuc[izouzu[[SSSKKKSSKSKBSKBKSSB91199BBB[c9 1BS[zozuuoc[[S[BKuiK91  191(9(BcoiB11B[K1(1199191KiB (19( (9S[[9((cz[BB9(1 9i[19BBKKKKK[cSSciozziKSuuicc[Soo[BBKB9S99KSB9B9BKKB199B1BBc19(( 19SSSBKBBB99119KB91Su[SBBKKBKozuiK9((cuuuuzzc[uoizzcSSS[SKSKKKKKKSSKKSSKB1191((  1[oozouzzi[SBKKccB9119KcS[S[S[cocKKBBB91( (1911BBiS(((((( ((1[u[ ([iSKB( (ioK11BB9KKBSc[SScicuiSBBcucSKKK[c[B999B19ii9(991999BKB9(9KSBKS9( (BSc[S[BBSBB91K[K(1S[K9191KS[iiSSB1(1uzouuzi[uzozzSKKSSSSKB9BKKSKBKSSKBB11( (  9[zzuzu[czoSS9K[[iuiKB19KSKc[[[[[[ci[B9BKBB91119991B KB11 ((11Kuc 1uzK11 (uiB919KKSK1ciBSiiicSSccioc[KKSSB1(11111Szzc999111119B9911KK9BB[1( 9BKucBBKK999KKB(1(K[SS[S[9[u[91 9zuzzouuiuuoiKS[SBKKKBBKSBKK9BSKB99111(  BKczzouoocSKB19Kcoczu911((coS[[[SS[c[ccSBKSB99(BKK9K9B(SBB9((191B9B( Bu1 BoB999KS[K1Sz[9KSciSBSzo[BBBBB9991( (1[zizK1( (999991999B999KKci((  9[K1BKSB91B99( 1BSioc[B z[B((([zziuuoooiuuiucS[[K99KB9KSKBBBBKK999(  9cuuuuouoii[919[iuzoooK(BB(9ucSK[SBS[[c[K9BK91B9BBB(1911SSKB1(1(9BKKS(19B[i9  9zcB9BKKS[B9KSSKSSiu[9SiKBKBB99B9 ((Kizi[K1( (1911199BBB9B9B9(˞(19 ( (99BSKKK91191((19KcicK9cuzoK1( 9uuiioioioioouuioc[[[KBB911BKKKKBKKB111 (  ((9KciziciuzuouooiB9cuK11(11Kzu[KKKKKKSSSKBBB11BB1(1((911BK919999BBK[cK99SiB (1 9cKBBBBKKBBSKKSSBKc[KSozi[K919BBB9( (9S[SSou9 1B9919B9BK9999B9(Ku9B(191( (19KKKKKB9111Bc[[c[S1SSK91(((([zuioooooooiiuooiu[[SB99K999BKBBBBKB9991 (((11Bcuzuuzoc[cuouiB[zuKKS9 Kizzzuoi[KBKBSBBB91999( ((1SK19KSK9Bcuozo1KiS KKB9BczS99BB9BSKKSiouucc[SSB1BB9(1(( 1B99KSSSc[B( 199911BSKSK1111119SϪB9((19111((B9BKK[[SKizo[BKK9 KSB91(9B9[uziciiiioziuuuoiiiSK991(BBBBSKKKKBB(((( 119S[ozzoozzzzzc[ciuuzcSccS1   [uuoiuicSKBBBB9B1(  ((BKKSuuiouBiu9(iu9B99K[919KKBSS[[u[[[B19BKB1199KSKSoiSS[c9 9K99B9BKKKK911191BBSu19919111 (BSBK[cuScziiKK9  i[KB99BBBiuuuuoiiiiiiouuiioS1((( 9SSSSSSB191 (  (9Kizu[iuziccioo[9   SuKcǰiocS91111(   (1B[czzoSo[ (Bo[191BKKB1BSSKicci¹uuoiSBKB199[icK[ooiSzzK11BB9191BSKBKB1991199 ٷ1(11(191 1BKcc[zcB[oicK1(1(9BBKKKBKSiuuooouzoooo[cuiB1(( (BKBKKKB9(( 1BSczzouciuzuiuz[9   1ui(ĦiiSB999(  1K[uo[[ooz9  ((1Si919BBB99KcccuiuzSSKBK[zi[Kco[cooB9SK9111BK999911111199Bф (1((1((( (SuoBSo[ScuuK 19(999B[iiuoozzzoooociuc9( (BSSKKBB91(  (1B[iuzoiiSizcoK  9izoK9ziouooi[9  1[uoc[S[(99BKou99Sc[SKS[c[[uuuKKBKScic[KciSKcziK1SB11199SB911(1(11(9B1Sc111199((( (Si[KcoSoo191199BS[couzioozouooiciooK ((9SSSBKKKK91(( (B[uoouicuuczcKo[( (( (B[uzou19zzccccuzzi1 9ouzuzzoii[KKc19BK[SSzu[[cizzzzz99ioSS[[BSc[BBKuuB19K99B999BKBB91911((9911ϖBBBB1((11( (911oSKB  BBKSKBK[cz[czizzuooiocizzK(11BKSccKSSKB9(1(((K[cuuoii[cuzocuz[ioS   ((1( 9c[iuc[[Suu[K[Sizo19uuoouiccii[Kc[ 9B9KSczoSoououzScui[uuBuطcKSKKSoiKBii 9i[9BB9BBBSKBB91(((119B1K[BKB119(  Szi9( (11KKSKKBKciuciocouooouo[ci  KSiicii[SS[KB199KKiouzzuici[[cccSiziciS1  (11(9[ocou[[c((uSSSS[[coB 1zouzciuuiouziS  ((11BK9SSuczzoiocSiouSKKcocS܄BKKSuK9[[BBSSSSKB[[KSB1111119911c1B1((( (((( (1KK  11((BBKKKScuzoiuzocouoioo[SizB 1[ooic[SKS[[[KB[ciooouoK[cicciii[ScooK91( (1(1KScioo[B(Bo[KBBSSSi((iciizi[Sooou˳K (99B9(9uSuzoz[ciuuc[SKKKKKBB9KSSBSz9KuɼiSKB9BBBS[SKSiiiS1 11919999(u(111( (111119BKB19 (1 ((119BK[o’iuoouooccuzoiooSSou1 1B[uui[KBKSSKKSScouioiouoouuuoooioccc9 119919[icci[9(1zi[[SKSKKu(Kuuoozzuiccooci˭B (1KK9111iKBcoiuiSKSccSSSB9BKKKS[[SKS[S9Buo[K BSBBKK19Sio9((11(1BBKK91[1111(1BBBB99KSB19B( ((1K[izzoiiouoouuci[[Scuc(9BBSc[cSKSSSK19S[[ioiuoioozzuuocK( ( ((9BBBBKiziocS1 Bouccii[KB11cc( zzziuuiicooSu9(1KKBB911[KBSioc[[KBS[[SK1119[o[ScicS9uuc91K99BB9BKcuzB((((((9K[[B99Ǣ[K9919991BKKBK9119(1( (((119BiiououzuccciouiB 1BS[cSSKSBB9B99SioizuiocizouzzuS  (  BSc[KSK99[zo[cS11ozi[izcS1 uuuuuoc[iuSu  191((BS9 9z9KKKuoccSKKKKK1(999Kͳu[SoSSuKzoc[1((9K9K[SK9((((1( 11BSKB9BKzuKB999199BKK11((19S[B (11KBB9izuooouzuicuoB(99B[c[KKKKKB(19S[cozzoccooouuou[  (((Bczzocc[[c[iucB1 1iuoo[Kc[1(   1zicooSS[iBi  (11BB1BB9 (žciS9[iKKSiouu[9BB11cz[ScoKocB1 (Si[cc9( (((((((1BS99BBBiύK[SKKBBBBB9(9(111(1(( 9([SS[zouuiozuiuouziB(9K9Bcc[[SSKB1(Bio[S[ouzui[[cuciSB(1BKKBcuzzzcuoiiiS1  czici[K[[1((1(((( Szzc[iuzocKSKoǞ9 (9KB1BB( (KϹBBB9B[iuicocB9izcizocc[zooS9 Su9(  (1(1BB911BKK91BBBKɪ9B[S[[[SB9((99B9B( (([KScozziouzzooio[91BSS[[ccS[[SBB91KouSBScoi[[iuciiB9( (1Sio[K[[BK9KSSocccS1[zi[[ciS[K( (1((1(11(((9ioicSSczoiooo[S[K (BBBBBBB  (SڰSKKBBSuuc[[ccSSSB9B[ooi[iuio1 11B[1  199BBcuocSc[SBBBKB9BuB9[[SSSSK919B991 (9991[[uzououzoccooiuuczoKBKSicicc[S[[SSB19Sic[S[io[SouiB (KiziKKB1 1911111BB9 1BzocSSccB1(  (((1111991izc[[KK[icSScooSĒ BSSBB999  ((zKSKKSozuiS99BKS[SB999Soi[SizS9 1991Kuc(11991BcouuiS91KBKB9BSi1BKS[[SSK1(111( 1BK[B1Bozuzuooic[cozuooiczc9SS[[ciii[SS[[SB99S[KSiuuuuuzouu[(  B[io[BKB1(199( (1(111((1Sozuc[S[[B  ( ((B99ocKSSK[icS[coiSɀ KSBB91 (( BzizĒucBK[iicSBKK9B9K[SKB9B9BKK[iuS(111([u((1111Kczi[BSSSKK9119u999KKBBKSB9991((1BKSB19zzuuuoioiiuuccoouuB9KKB[iuic[Sc[K911K[KKuzzzzoo[1 B[cK1 (((9BB1 (111((9[uoc[K[i[( ( ((1((1((1[zcKSSK[[[cioou[ 19((( (( [KKcciͳcuuzc[KBKKBKSoc[[B99 1BSuK 19B91So9 BuuzK9cc[[[S9(9Җ(19KB99999BB11 (99919uiooiiizuciuicB9cSKci[KK9B[cB9999KKSuuuuizzS9(  Kc[[9(19199BBB91(((1B1(1Bcuo[[ccoS ( 1991 ( (1 1Su[SBKBKS[oiozS1(    11 oB9KKK۷o[[KKBiuSSc[SSKBKKB9BKK1B11(Bz9  (((BiuoouoKBizucSSKK11zc91191( 119( (((1B9zuuuoouuccic[iBKcK1S[SK[SKSB11199KuucSc[ic( 1KiucK((KS[S[cii[K99119911Bcuzzouu[[S (1((199911 1So[KBKBBBSiiui ((( (( ( (zoScuioѭzoSSKBcS[[KKKBSc[SSc[(1B91Sio9(99Kcuzuuu[B9SoicS9Ki[BKiǪc9(( (( (99111Sio[uuiuzicicSSoz[(coSBKK[BS[KKB99991Sii[S[S1 (9ccoui9(Kiicoiooo[SKSSKK919czicB9B 11(( (19111  19Kc[BBKKKK[izu ((( 1( (((((1SSoɒoSKBiu9Kcc[SKKBB[i[cҚ11B9(9ci9((BB99[iiozoo[99BK[SB91ScccouǰK (((111991( 9iuocouozuc[cSSoBBooc9BS[KicSK999999ioSocB11 111Kcioi[91[c[cooocccS[cccccc[zzizi9( 19(9B( ((1(1B( ((BicKBS[SBB[Ğ(( (   1((((cciiSKBz[K9B[c[KSK9Si[cω(BSB99c[ (9KKB99[o[SoiSKBKKBB99KBSui[ouiozocԞ1( (119BB1 (B[KKuoouo[S[S[[Siouoc[SB9ciccSBBBBBo[K9KK91  (9BK[iocK119BB9Kcic[coicc[[czi[K1 (B1 111((111(111((( (B[KBKSS[S9zu ( (11 (dzĞ[BSi[KBzuc91B9BScSBKi[o1i[B1BcS 1ioS91(Bcoicc[KBBB99BBKSSiu[[oo[SSS9KS (9BKKB1(( ((1BKcuizzcKKScuziSiuiicci[KSouii[[[ccc[KB((  (9KKScccS111(1(S[SSSiicii[SK[ouB( BS1(1((  (((1111  (9KK[[BKSKBҞ1 (( (((1˷‰cuSi˷ucozcSK9BBBKKSuuiKuiS9K[1 1zK11Soi[[[SBKB11BKBKScoiScoi[SSBBB͒((99BK9 9111(1SSzuouoSScozoSSioooccuiSSiiciocSoo[K991( ( 19BS[ciKK( (1Kzzizzociz9  KcB11(  (((((1((1KS[cSBS[[cc(((( (( (( uɷuuci°ucoo[K99BSuSKuuK9919coK1SzzioiS99B9BKKKKSco[KS[SSKKBBBSu 19911 (B9119B1 zzzuoouzicS[ozcSKcociicci[BS[SSSou[[[KB9( (BSSci[[K1 (9Souuzz( 19K9111  11((( (1BKKKSKK[c[i ((1( (1( 1ټiziooǹziizoKiui[1 [ĹoBKcioiBBBBB[SKB9ciiccSKKKBB9BBBoS1B91((99((91( c[zuouoiuiciooK[i[SK[ici[99Kcii[iocSiK1(( 1BK1B[SK[SKB1(([ioziScoS( [ɹǼǭ[1911 1((11 (1(11111(1BBKBBBK[i[iK  ((((1( (ܳuuucozuzzoǢuooٖSiz 1S19coo[BBBKS[KBBSccc[S[SKKizcSBBBiSBB9(((911999 [[ozuoooocoiKiiccc[[SSKBczcB9SB99999KSBKSSKK91 [uc[c[[cK1( (1Bo¿1(1(9( ((11((((((1BKK9999KKKSKSSS9i1 (11( (9([ͷɳouzocioi[cS[˳uzݷcǒ1(u99Kzzi[BBBBK911BS[SucSS[SiiKBBKu91( 91199B11 u[cuzuuoioco[cuoc[ccSS[cuziSK911(9B99B911(1(1KiB(9991B[S1 (11B[¿S1(19KB91(119911(99KSSS[[S[[SSS[SSKz[(BB1111(( ( [Ėu([zuc[cuuSS9[([BKzѢ[ coK[SBB[uS911 (9S[S[uSBK[oKBB9SK(((11(1BBB1 1zicciuuoSi[iouzzc[K9SioiS((11(11(( 9So[((9K9111B[K1BBSi¹¿i1(( 9KKB99999BBBBKSSSccciciiic[[c[[  9B9(((((1(1( šouݍ czicci[91(K99BBSK(9KiҒ([i99BBKBzzK(11( 19SKK[ocB99SoKB1BK19111919((((1zuooocczziiSSu[SB119[zoiBBccK11 (Bco[ (99((((19KiKKKcǿiB99BKK99BBB9K[SBKSSS[ccciiuic[[ciK 1(991((11 ( ɦcozBSooci[111(9S(11199B9SǍɷi9S9BB911BzoiS9(1(11[SBKiui9 (9cS911c111((11911(19zuiouuuoi[[zKcuB(11(1KicB9KKKuicSSS1191991111BS9(1Bi¼K9BBK[[9KB9(9KSSS[[SSSciicicci[Bu[1(9199( ((((9ɦccozouz⿄cuoc[B(111(uB((119KB1SϖͼKzc(9BBBSooKSuu999KciBKuB 1Szo19BBS(991119B1 1iiiiucB9[iSS[ziSSoK1111 (KB9111(ciK ((11191199991( ((S¿¼B9(999(919BK9BcKBSSSSS[cccc[c[Kui1(111((11(11 ˢc[[iuoc҉SooS911199(io1(1999999K˷ѿzc9 BoicozuzzSc[ScicoB(9i19KBu91(11(91( iooozocooucSizzoK((KuS1 (1(111((9oS(( 91 (((9999B911(9S[zĿĿiKKBBBBBSB91Su[KSKB999Scci[SSSu[ 191111((111cu[SBBSozzSziS(( (11Kc91BKKSK9BKBzu1Buuizczǖ9 [[BBBi19191(1( coiuzuSiuuoouc[SB19uo1 ((((111991[o((BBB1 (((1119KBBK[zǿij[BKSKBBScciSBKcc(1((11(1(111۪[SBBBKzߦizi[9 (119KoS(Bciii[[SKKɿK [oiizzuϹo 1cĹϢzBB1S999911111(iiouzc[[SzziSK9 ((19[iB(( 191199BB919KBKB(1B111111(9KBBo˭cKBB19[ccc[KKc(1999((((1(1BKSBBScSڳٷouB( 9ioKSuzooiic[SKͭu(cu[iioooҷi1Ki¹ҚcB9(SԒ1B911(   cciizoSKSzziB1( (( 199[S9((991((B[cSKcB 199KcBBSB11((9[oɼ¦zB999Kci[BKKK[ѿB ((1(11(119iuBKKS[uKSۿK(( 1ioi[Souuuo[[c[oĚ9KzuK[ziuͭuǿҍ9919[199((( [[[iiBBSzoi11(1( 11KBK[S1(1(191(9couuzzc1199KSBKoS11 BcziS[z–[(Bi[BKciSKSB9zi(11(( ((9iBBKBoٹz[[ٹB(((1uo[ic[izuicSS[ožS9iuzo[KuǹĹժB91 Sڒ9BB199 KKKz[Bcuo[B1( (BB19KSSKSS[icBSiii[[BSi[ooiSc( 1B[[KSoS1Szociicozzu[99BSoozϿSii[S[SKKSB9iˀ(199111119Sio9KKzѷ[Sݷ11iSioi[[oicSc[KuۿǦc((uu[cuoiɼdz[ҹBKKٿSBBBK9BKc[KSccB9KKK9     ( (1111( (  19BB19B9BBBBKSK9SSSSB9KKSSS[iccc[[[S[[S[iiicou[( ( (111 119191119BKScc[ciooc[SSSKSSSSSSBBBKSK1(((1(1(9S[SKBK[i[iiSKSS[KBSK9BKKSS911(1[ccuzS[oc[S9  19 1K[ui1   1119BSKBBB[[B99(   ((   19((1991( ((  1 1(1BBBKKK9B[oziS[ccooouuuoc[S[[[[S[[ciiS9(((1((11119B99111BS[cc[cii[[[[[[[SKKKS[SKKKBKK911(11((( (1(1K[[[SKKKSSKKKSKKKKBSB119K[ocSKccSczzc1  B9 11 (ciuS (9BK1  KK9919[9(          (1919BK91(  ( 1(  (1999BB99[uzioiciouuoouucccccS[[[iio[1((1(11119999BKB99B[c[SSSioicSSSS[SSSS[[[SKB91999KB1111( ((((((19KKKSSKS[KKKSSSK99K9((BS[iu[BBSK[oi1 (19BSK1 9c[ou9 9[iiK  B1111BB(  (    19BKKKK91    ( (   (1(19999Kcioc[iuuuzoioucSS[S[[SS[ccK11111(111999BKSKBKS[cccS[ioo[KSSS[[[SSK[SSKB191119111911(91999111BB99KK[[SScc[KK99991(1K[couo[[SS[B 1BK[[[[S111( 91ui( 9izoS( ((  9B9199(   (      19BKSSSB  (11(  ( (((  ( (11119KciS[uuccicS[KB11BKK[SKSSS9((199199B9BBBKSS[[[c[cccciuui[[[[S[cSSSS[[B9KKKKB99BBB19199B9BB91B919KSSSS[iic[SSK9KK1(9K[cuuc[SS[B(9SS[ioS999BSB  [S  [uz[KKBBB9(  (11BB9    (((  (99SKKKK9  111991 (( ((1(11(  (9919KSKB[ziSSBBBB9919BKKKKBKSB91999B9999BKSSc[S[ccc[ciccicoc[ccccciucKSciKBiooicc[[[[KK999B9KKKKSKBBBKKKK[c[Kc[KSKcSB1119Bc[KK[ccKB[c[couS(9919( 1u9 ([i9KS[SK19KBB11(1B9BK1 (     11KKBBK1 (1B9(BB9 ( (9991B9((( ((11((1 9KSSS[iSBKKKKKKB9BKKKKSSS[9199BBBBBBBK[[cccccc[cicccioiiccc[ccci[c[KSuuozoSSBBKSKSKBKSSSKKBSSKS[SKK[S[ccB911(1B[K9BS[c[SSooo[oicK9(1   SS [u[S[[SKKioi[SSS(119K9    ((   19KK9B91199BB1BB1 (((19199B9B9911(1199911 ( 9KSSc[[[KKSSKBBBBK[[[[ccSB99KSB9BKBBB[iicciuoicouuuouoiic[[ccio[SKBSzzoKBBKcc[SSSiiSKB9K[[SS[[KK[[[iiS1( (1K99KKSccciozuBcoS9    91 cB ioSK9BSSciuo[KKSi(999K9 (( ( ((   (9KKK9BB99BBBKBBB( 11119B99BB999999B9B11( (BBBBS[[KBBKSSKKKS[SiiioocK999KKBKSSKS[couzuzzzzuzoioic[[S[iiªKKBB[uzz[B9K[uiSBScocSSSS[S[[SSKKS[[iioc9(  9B9B[cc[ouuKS9   (991Bz[((ScSc9199BSc[[c[KKSS((99KB   (    ((  9BKSSKB99BKSSSKBB ( (1199911BBBB9BBBB9199B919B91(BScSKBK[SSS[[ccicioo[B9BKKSKKSSS[ccuzozuzicouuiciciooKKK[iuuuuuzzcK9KS[SKK[co[S[cKSSS[[SBKKK[cioicS9(1BS[[SSS[ccciSS9  B11BK[19KB1 19co[[SSSS[[((99B9  ((((   ((((9BSSSSSKKSKKSSKKKB( ( 1119999BBB9BBKBB919999119KKKBK[SKKS[[S[cccccccou[BB9BBKKSc[S[iuzzuzzzuzzzuoiozuiii[K[ouoicScoocKBK[[[[SSS[[[Siii[SSKKSSSKK[[co[[o[SBSioccoucSioSSK1(  1B9B9BuK1B1  9[i[[BKSK[[1199K9  (1(    (( (((BKS[[ccc[[SSSKKSK9(  BKKBBBB9B9999B9K99B99999BS[cccoo[S[SSS[iouuiccoiKB919BKKSc[ScuuuuozzzoouuouozuiicS[ioocB9KKKSB9[c[[[S[[ccccouu[KSSK[SKSSSS[ccioouciuoc9S[cuiicB  (S[KKBSo[BB9(  (99B[[K9BS[11BBB1  ( ( (  ((((1BKSS[iii[[[SSSKK9( (S[[SB9BB991119BKBK91111BSiizzzi[[[c[couuuicco[BB91199BSccczuiiuoozzuuo[K[[[Scuzi[SKSScoocSB11(19S[cc[[cSKKK[[ioS19KSKKS[SSSSScicozuiSK9KS(Szc[S1   Bc[BKizoB 1B( ( 11((Kii9(9KK1199991  (   ((((19BBS[[[[[[[[SBKKK1  1ScSB9BB999991B9BBB1(1(9Scoc[ioucSSc[[uzuoc[ccB1B9B11BBBScuoiuuoouczzuuiSBB[cccczuoccKBSciiccKKB((9BSSKBBB((199111( BKKKSSKSSS[ccc[[K99BBciB1SKBKB1   1SSB1Bcoi1 191119B[SK9K[K9  99B919(((((1 ((((   (119BKS[[c[[S[[[KBB1(1( 1( (999BBBB999999KKBK91911SiouiBSSizziccccooiic[ScK9999911KK[iuzuuuooiiozizzoouiS[oc[KB[iuzuoio[KS[cicuuu[9B11B1  1((  (KKKS[[SSSS[[cc919KSSccB 9KKKB1 ( (  BKKB19S[  BS[ciKK(( 1(1111191 1(((( 11(( ( ((11BKSciiSSKSKKKK91(1( ((919KBB9999991BB9KB999BcuiuoB9Bczoi[ccSiucS[K(99BBK99KKooouuuzoociiouzzuuuui[uuSKKBBSuoiouc[[ciicuz[911   (1(1 ( 19BKSKBSSSS[[ic[SBBSKBKBBKB1   ( (KccK Bo(911KS[ozB1 1 (( B91919  191(11( (((((1(((((9BKKSKS[[KSSSSSS919(  (  (99KK9BB11111BK9BB19BSoucioB(9Siu[ScSKoucSK1(99BBBBK[uu[izuouooiiioooouozuouo[SKKKSizzuuzo[S[ciozoK    ((1 ( ((119BS[KS[SKScoooK ((9BKKKKB   (( (K[[SB1(BS[K1 1KK1 19KBSiiK B9B99B1((((1111((((( ((((((19BKBBKKSS[[S[[SS[[BKS9( 1   119991(99BK9999K[[ioi[K1(9[[[ui[cS[iicK1199((99KSu[[ozuiouiciiiouuoizo[cS[[[KKB9[ouzzzi[9BSc[1  ((  199919((1S[SSc[S[ciiB911KBKK9(    1coo[KB119uo[B (1BBB99Sc[B(KBB1BK1(199199 1(( ((( 1((1S[S[SKKScSKcc[[ccS9B999( (9B91111SS[[KKKK[[S[[9111BSK9Kuuc[[[ccS9((((((99B[occouuoiouuuociuuiizo[[SK[SSKKKiScuzocK (1    ((1( 91 91(1 (SK9K[[K1Bc[  9( 9B9  1SKK[uoiciSBK[ozc9(1   BB99BB911119191111(((( (11BBKSSSSBK[cSSS[SScSB9BKK[(   1B99BBKcSS[i[cccSBK1119B1((9cucSSSc[B1 (( (1999occiiooiouuuuoiiououo[KBSicciiKBzcoSS1   (119( (  KB( 1((19B91BSS1 1919K( (9zioiSK[iK9BSuzcK1(    SKB111((1199111(1( 11( (1119BBSSc[BKKSKKBSS[[KBKKKBB  ((((1BBScSScic[ccK(  (((9Kcc[SKSK9(((( (9KiĪzi[[c[oooociuzuuoicoui[[ouSKiuK1[S[K9     (((((  19(1KS9(1(   9SS1111BBK11K[K99 (SzuucB19B1 (icB     BB99911(1111((11( ( ((1199KSKKS[SKSSSBBKSSS[SS[K9(     19Kcc[[KBBKBBB  (11BS[c[[SB1( 1[ozcocciciic[KK[uociicozzoS9K[B191KcS( ( (11( 119BBcucKB(  9SK1 (9BBK[S[[[SK1 BizzziK9911 9ou9    KBBB911(1191( (((19KS[[BBKSSS[cc[SSKS[ccc[SSSK9(  ((9KSB((    (((11BScoicSB(((((1SciuiKBuuiic[KBKKSciiS[cScio[B((9c[[KSK  (  ((  (((119KSSBio[B1 ((1119B( 19BBKBKS[c[[[K1 BKcou[BKc[[o   ((  ((  BKKKB99((111 (1( Suoc[SSSciiiccc[[ccccSSKKB    ( (B9     (99B999BB[icSK91( KzzS[oSBcuiccSKK[[cccozuSKS[91191(1Siuz[B1   ((19KSSSScS1 (9K919B1(BKBBS[SS[[[SSSS911ScioSuzozcSB[cczc (  Kouoooi[KKB9 KKKB99911991(( 9o[[ciiou[Scc[ccoocS[S99   11 BB    B9K9B199KBSc[KB91 K[BiucSScicc[S[[[cciicSSSKKB(9B9ScocKB9(     ((( 1BS[SK99(  1K[K  19B19KKKKKKKS[cSKK[oio9KccooziSci[io(19(Kczucioi[SKB1 KKSKBB9119B11((1SzzcK[ccS[ccciocSSS[[[[c[[[S9  (1 (B9 (( ((1( (1BBKKB99BKKKK[SBBB(i[[iuSSK[ciic[c[S[c[[S[[S[[[[ciiic[B(    ( ((9SKB1 ((( 1BKB   BB1199 1KKS[[[occBBSio[ciSBSScoi 19 KKBocSSSBB91(9BBBBKKB91119999((Kzciuicou[ScooccccSKSBB99KKBB1    ((1 199119B911( (119BKB1(9B[cSKSSBBKSz[[cooSSK[iocccSSBK[S1Szu[c[S[ccSKKSK(     191  9KKK9( (1(19B91(1  (1 (KcS[c[1(BBB91( 9Ku[ ( 199 ( (  1KSiBKBB9119B91Suizo[SoiKioccoicSK9( 11911   (  (9199BBKB999119BBB919B[[SSKKK9KocScioKBBSiuoccSSBBKBKouSSKBS[SKKSc[(   (19B1(11BSS91191Bcc9111119119 1 9iiScK1 (    1oc11   1BcSK9111BBBoooz[S[cciSozooui[SKKB999BB    ( 11(  B9999BB99KKB199KS919cci[SSK99czozS[ooB9SciuucSSSKBBSi[SBBBBS[SBBScc9(1(    1KKKBBK[[[c[BBKKcziK91111((  1B1 ( ( 1B[oo[SSB1(1( (91cucSB(    cKK999SczuzzuzuzzcSc[uzuuui[ocKSB9KS9  (((((11   1(((BBBBBKB1119B[BBSu[SKKc[KSocciBB[ozzo[[c[SSciK1999BKSB9coK 11 ((   (KS[icSozio[[ScocB11 (( (11  (9[SSzo[iK111( ((1((KcSK191   ucKKSSiuooiuzcS[iuzzo[coi[[SSK1 ((99191( (1B91BKBKB119BSKKiuSKKSioicuoozziS[iziiuuocKBKB19BKKK9BcoB (B111    1[zuzi[ozc[SSKBB1999(  (91  (9SoicuuuooiSB1(( (KcS B[SSBKS(11     [zzui[[[cioĢiziccuzo[Siiccc[S9    (((99999( 119K99BBB9119KKKKioK9K[[iocoiciicSciouozuzzoiS11119K[SBB9[c9 (BB91(  [uSScuc[K[SKB9KBB  191   K[Soi[i[izooiicSSS9BcoS (SSS[coB(1(1 ( 191  [uooic[Siuiozzi9oSci[BK[KBS[cS(   ( (1BBB9   9B919BKB9BBBBK[cKBKKBKoiiu[9119BKS[iicccozzoi[K11999KccSBB[B( 9BBB1((   1BuoKScccSK[cSBK[S9((  19   Bzz[iicKKooouuouzuoK9S[K(1SKSiiB (KScoS9B( BoicccSScoouzzzS(SzcioiccK99B9( (  (1(((111(  9119KKBKKKSKKSSB(9999iz[c[B91(1999Scc[SScuicSKB(9BSSc[cK9KS( (19991(  (1BSizuicouzz[c[SiucS[[9(91 (1  (19iiScoiKSziouuiizo[1BSK1(1 KK(BS1 (KS[cSKSS9((9[B1B[Scouuzozuzozi9 (9ouoci[B1((1  ( (((1111191(    191BKKKKK9999B1(((1( KuccSKKKBBKKSS[[KK[ioi[KKBKSKBS[KKB9KB11(9B999((  (9K[couzzzuiioozi[iicuoSKB1   (( 1[oooi[[iooSKuucuuiSBB[iSii91BB[S9S( 9B[KS9 1911(BSKBK[ccciuzuuuSB1 9BɪuuiuiiB1999(( ((((111(119911(   (9BBKKK1  (111(1[ccKSSciooiciSKBK[ciooi[SKS[[KKBB99999999B9911 KcoouzioSiuiuuoiS[izzziK  ((1( czuiKB[coc[iiciocS91[zoouocKS[ii(1KB9BS91   ( BSSSS[c[cuzzzz11  9BioiiccSKKKK11  (11(1((((1BB11(  (    (KK1  (99( 1Siuioouzuzzc[BSS[[iouzuuiccSK99BB9119199999( 9ioouzuzzuBi[K[[KKS[SS[uoiS1  (9KK91 (ouzzcS[KSuuccuziSB1[zi9BiiSSSB( S[    (1(S[cS[cSKK[iicoiSB9 (( 1KKSuouoiiSBKB11( (1((((((11199(  ( (1  99  (99111[ouuzzzocSKScuuciuzzocSB91(1(11991991 (9Kiuoozzuic9S[SS[B9BSKSKSS9( (((( 11KSSSK1(KuzuzoooSBuziicci9 KuS1cc[[i[1(cB  (B91cii[[[SKSScSSK[c[9  (9S[B9ciiic[S[B1(  (191(1((191911   (19(11( 11  111( (1([ziozuuzzuicSScozoozziiuiKBBB91( (9K9991 (9Bcouuzuoi[icSSSKSKBS[SSB99( (( (  (BB[[[cuzoiiozuuBKoo[SSS[K(SooK1iziciB Boc1 ( 191BiuucSKc[SSSiccKK( 111BScuK1(B[uic[SKKB911( 9BKB19KKKBB991( (  (19BB99(91  (99( 99iuuoouuzuooc[cicciiiii[Scoi[SSK9(119SK991  1Siuzuiuzi[KB[uoSciSKKSKSK11B9((((B1((91SzuooocouK1BKSSKBKuozuK[SuoSKic1 Bc[( (  99( 1iuzuiiicS[iucK9(KzcKc[11KB[[iS[[SKB91(((9SS9999KSKKKKK1 ((  (9BBB1((11  (119BB111ouoooiiccic[KSSBBBKSSizuoo[K[ii[S[cSKKBKSSKB( (1B[uzuuzzzicSKKiuic[cSBKSS[B119(  (1B9(( (Boc[[ioiizicSBKB[uoSKzuzu[[couK( ( 1K[[[( (KKKK( KozzoouoiuziSB1KiS[z[1(191SioSSBKK9BBBS[9(1(BBSSS[[[SB1(( (  (((9BB91 (11(11((99B1 (9Kzzuoi[SK9BB91( 1 1BK[iciiiSK[i[BBSccSKSuz[KB((BKS[ouozuKKBKSc[[i[SKKSK91B9  (1((9(19cuiSKK[cSSKKKSK[zuicuuicSKSK((SBcui[S9191 (SSB(  [oioooioou[9119zzc1 9K99KiuzoKKBBB9K[zK1BK[i[S[[[iicKBB9(  (9BBBB91(11( (  99B911KoooocK1 (  ((119SSKcc[KK[SK9Kcicc[cio[S[B9Sc[[[izzuoi[9BBKS[[SSKBKKB9((9(  (( (1KuzcKBB9(1((9BKBiuzc119( 1[B[iSKKBSB 9[B(  1[[Buuzuccouzi9(1Kz 9[o[BBB[uuSBBBKcc[occozicoouoc[BBKB911  199KKB91 (1111 (( 99BK9Biuccii[91111  (1199999Kccc[K[SSSKSiiic[ciiccKBiu[KSiozuzu[K[KBKSKBS[[B19( (    ([uzu[KB1 (1(1KKKzuic[B9 (119 1KSSB1(  SK1 1S[KBiuuzzzuuouui9   ciB91KozoBKooooooicciouiiiSSKBB99( 1KKKSB11 11911 (1(BKKKKuzicouuSB9(9B99B119B9191(9SzzoSS[KKBKBBKSKS[Scicoou[9Sozi[uuzc99KSSSKKKKKKB(( (    (K[oicocK9BBS[SSS9SicocKSS[S KS[9((1KS9  1K9  So[99uzzzzuozuuuzuoS( KizK( (1cuoozuocSioc[iouoc[K[[S[[KK91SSS[B1 (1111 (19KSS[zoouuocK1 1BKSSKBKKKKKKBB[uzi[ciS99B19[c[SSKSi[couc9KioSB[zoKBKBSccKS[K1 (11(    1BKBKizo[io[cozuzzSKiuiS[c[KS[[SBi[[9(K91 1 11 9ic91ouuuozuiiiiuoSB  Kzuoi[9( 9coooi[izi[ozoSK[ccciuuoc[KSc[SSBB9((B[[SK1  1BB91  (19Kcouzuic9111K[[ccciSSKKKB[uzicciSB19KS[icSKKS[ccizziKBcoSB[oB 1KKScc[K9  (1(  (  (B[[[cc[cozzuocS[zuz[[cc[SciiSBS[K1oB911BSS  (B((( 1K[ioK cuoooziSciioz[1 zc1(  BciouoKBcoziScuiSKSSccciocSK9BSicSK91((9Scc[B(( 19BKB(1ouuuo[KSS[ccoiioic[c[ccSK9KScK1919K[cc[S[[[ciuzui[S[[91B1 (B911  191(((  (( 1KSSKKBKBBciioi[czc[cic[[91BS[cSKci[9[i[oczo9KoS K[(1((B[iucB[iicouzu[[iuuo[1 9u9  ( (9SccoucSizzc9KicKKSS[SS[iSK99BBccSSB19BK[i[B(1(1BKS[S1  Bzczuuc[oiciiuoiuuciioz[9119Kc99KKKS[[[KKSKBKooi[[[BKK9  ( (( 1K9 (((  (SK1( 1(199K[[K[oouuc[c[K1(19BK[cicczziuz1BcS 111SS111Bo[ 1[ccoiuiiK[uc91izS  ((1BcoozziouucKSi[BBBKK[[SSB9KSSBKcocKB99K[i[S9999S[ci[(  BoiiuziKKioocoucio[cii[9111BKS9BKKK9B[SKKSSB9K99[[[91  ( (9BK9  ( 1B1  ((BSSS[c[cuci[K11 Bcuiiio[cS1(1S11B1(99(999Kuc((1SoiiiicocuSB9[[9(((  ((1B[iuuSS[[K[ocKBBBBBKSK99BSSSSScc[BB99B[c[SBBBScoocB 9oocccoozzK9Bozo[cuic[[SKK9199BKBBBKBBB99SScSSc[KK(9[K1  (   19BBB (11(  (  B9 (((K[[SS[SSS[[[B   (BcocoocBBS1(K19B11[cBSKBScK 1(couoooio[uuc(   ((9KcuzoSBBKKKizB9B9BBSSKBKc[SSKSccSKKKBK[cc[SKK[ciiS 1io[coiouui1BcocSSicS[KBKBBBKS[SK9KS9(199BzKcSBSS[K(     (99( ((( (  BK1 91 1((9SicS99B9119S9   1SccKccBc[KBBB9(B(1B 1cucS119( 1ouuoK   1K[SiuocKBBKK9[u9B[[SSSKKBSoiccKKS[SBK[couuocSS[[SKB K[ciiiozuou[KcoczuiuoiSBBBBKciocc[S9BB99S[KBizK[[KS[K(    (9991( (  9[K9(1(19Bcii[B( (((9[S( (BKS[9BS91(9B(SK199B[S(1[S  (( uuzccB   1BS[SiiK9999BBBK Kic[[c[KK[SSoiSS[[SKK[cuo[Sc[9((  iuiuzuuuooicB[oicoii[BBSKB[ooicc[KBB19BccSKBzz[KSSKKB91(   (9K91B9  (  (9B[K99191 (9KSiS91((BS[[9(  9[B1111S[9(1BBSSK9(1ccK19BK   ( uuoi[K1    1BSSKKSK19BBB9BS[ 9cuicciKK[cS[o[K911KS[iici[S1 (  [uuuzuoozzc[i[9[zuuoK9KKKS[uoi[KBKB91BSS[[B[[KS[[SSKB1   ((KccK1K1    ((BKBBKKB1(1Sccci9 ((19SK9(  (B[c9(1((io[[SS[[SKKKB[[99BKSSKB9(1 zooziioi9 (   (1(9K[[SKKKKKSKK[BKcozK(KizuiouSKSBBSB9((11KS[[[[iiS1(1(Szuzzuuuozo[SBSuui[[ozucScooi[[oicS[[[K9(1BSicBKKScc[KKBB1  1BKcc[K11 ((9KB19BB99Sii[SSKBBSS[91   BocB(99Bio[ccKooKKKSKBB (KSS[SKK[cS1119zu[(   (9SKK[ic[SB1K[oiizSS[ci1(KciicicSBKKB9( 199B[cS[oziS9Bczoooizuouzzo[S[oi[[[[Scooiuzuoiuzo[KKKB999B[[B9BBS[[cSK99(  (S[SK[KSB( ( (   19KKBBKKSKScc[[[SSS[[S91(  BziS[ooioSBcSccKS[cS1( 19BS9Suoi[S[Suiooc9 9KSS[c[[[KBBccoooicicKBSKKKSi[SKKK((((9119999BB[uou[Suzuuzo[Siuuz[BSuuc[c[KSiuuzuicooo[S[[BB9(199BBKKS[SSS919BK91 (1SocBBB 1(  ((  ((19BKSK[[[[S[cc[[[SS[SKKB(  9czzzoouziiB1uuS[SKKSK1((9K[1Boi[[iiSSzuu[KKB1  (BKSS[c[[[9BKcciiuo[[oo[c[SSSccKB1 1 (((999Scoczuoiiouo[Sou[Sczuo[coi[ioouuouocBBSoc[SK999991(999BKScccK9BKSK911BS[iS99((   ((19BS[K[S[[SKcc[SSKK99KB1  BccSS[uuuzzzzoK9o9[[KS[[S9 9ioK9[cSKKS[K[KKK911BKKB1 9Sc[[SKKSS99Kizo[Kozi[[[SSSuzi1   9KKSKioiziiuucSooSScouzocS[cooioccS11Soc[SK91((B919BBKBKKS[cSK[cK999KS[c[K9 (   ((9BKSSKS[c[[KSSSKKK[K9K((19KK19BKSSuuciu[KKccKBBS[B ( KK 1KSc[BS1[S9BB9B119KB( (KSS[[[KKSB19Su19iuuS[icSKSou[(  1BBBcS[oiui[czu[ooSK[iozuiioicouuoic[KBS[[icSK999S[9( 199S[c[cS9BB99K[cKS[SB1(11     19KS[SSSS[[cS[c[KKBK1(9(  9B99KBKKK9BKKB11[[[icc[KKB  (( 1[S9B1KK9B91B99( ( 9uoS[ccKBB19B[iS([ouiKKSSKBK[cB  1KB999BiocizĒozzicccScuu[ouKKcciciizo[S[iuuoiSSoi[izoSBSSKc[9(119[icKKKBB911K[[KB[i[9 BKB( ((1  (1BKSBKKKSSccSS[cSKKKKB1( 1K991BcK191991  1ii[SSKBB  9B((9BB99BSS9 1K9((((cz[zi[B9(99K[zi9BoKK[KBSSBBK[9(((9S[B19K[ioocic[SKB9B9[ccc[S[cioo[[ii[cocuuucKKccuo[[[ouciuoc[c[[ccB(1BKioK9KSKSK9BooSS[[BK[cSBK99BSKKB99919BK[[[[SSSKScScccSBBKKK( 911(191K[S9BB9( (Bcocci91(BB   (1ccKB9BBB9  (  1uuiK9(19BKSczzS SiBBKSB[[BB[S  (Bc[B9BS[cciicczucKB99911(1119BBBcoooicSScc[ciS[ooccS[cou[cuooccoioic[SK[B(BS[iS11SozuBBzic[[[KB9BS[iocSS91BSKKScc[c[KKSS[[ScSKKKBSKK( (91999ouiSSK9((B[uo[[o(9((   ooKBBKKK  (( 1izzuiS1(1KSBBBKcuuK9KK9BKS[[K9B[9 19K9[[91BS[ioiocBSĪiKKB1(((999B99BBBSKK[[[[SBK[SScuiSBB[iziuz[c[[iS[iii[Sc[KBSciS19Su9[uiS[cc[K91Kciic[K99KK9B[ccc[SSS[SSSS[SSKSKKBK919B9(((9SiS1(KiSczcBzBS9     ic[KB1  ( SuB 1K[[[SSBSz[BKKSSS[[9 9KK1 (BcooBKKKS[SSuuc[BBušoi[[[SSS[ocSS[SSKKK[c[B9919BBcoK(1BSSKKciBS[Soi[[S[[[[[SBKSSKK[uu[K1oiozcS[S[iS9BKcouo[9(BK1(Kuuc[[SSci[SKBKKSKKKKKKBBBKB19BSczozc9 S[[9So[BziS (1B99(  zoS(   1(((9ouiK((9K[SSSSKBKoziSK[c[[o[((BK( 9KS[iS Kiu[Kuc9 Bzzzzuu[[[[SiccSKK9 ( 19BK1 ((9ccBB[ccoo[Scic[KKSBSS[[SuuSB9Bzc[ccc[SKiiK[c[izucBB[S99Kci[cic[ciSKKKKKSSSKKKBBBBcuu[SozKSiB1((BcKKKccSBoS9 ((Si[KB9B9(  [icS9 (1[zc1 9[SSS[i[KKcuoSSzoiS(BB111191( 1ozS([i1Soioo[SSK99BKB1SSK9((  (1(1(((1  1BSB9Bcoiuu[[ioic[c[BSc[91[o[S9Ko[[ccicc[icSuziB1[cSS[[cc[c[KScocSSSBB9BBBSSBBS[zuScuzoSizoo[Kc[9BSi[[cB(  Kc[K[KSSB911(   (((( (1BuuS119S[S[[[[KK[iii[ScSK( 9K1  (Bii9 BzzB czuccoc[S( (1119B999KBB(  (1191((1 (B[B1 1Koouuzuiiio[cSBKKKKBciKBSoic[iiiioozzoK1BccKK[S[[Sccc[[[SKK99BBKSSuioSKiiccczz[[icKK[c[[SzB (  (1(KS[i[KB1(1  (111( (1B[oK1BKSSSSS[SBBKcucBKziB(((  9[oo9 Szo9 (1czuK(  11BK[iiou[1  19((( ((((1BK9  BS[cScuo[ciuuocB9[cSKKS[KB[zzcii[ooiuzzuzoKBK[SKSSS[SKSSSS[ccSK91KcucBK[SSc[uiScoiSBSc[SKiB(1  (BBKBBB(  (  B[[c99cc[SSKSKBBKKSzo(1[9 1   (((BciK1Suo9 (iuzzS( ((1Kcooioiiuzc9( (11(91 1KB119BK[SKB9SS[[c[[czuSBoiSB9BBBSuuc[[S[cuuuoci[KSKBKKKKKSKSSS[SSSSKBBBczouoSK[[9ccSiuu[Sioi[BKSKKKc[ 9 1(    11(((((((119911Biz°[99cc[[SS[[SSc[[oS1BB((( 199911119SSBSi[9 (1[i[B911K[[[czzzuSK[[K( (9BBBK 1111B[SKBK[[[SK99Scc[c[cuS1B9KSSK[Souoi[[KK[iS[ccuucKoc[K99BSKKBBKKSSKS[[SBKB1Kuo[ooKK[B1B99BBSiiKKcSSS[cccSSB9KB[91 1((19B(( 99((99BB(BB91B1111(Bo99Koo[ccc[cccoi[iS9B ((1911(1B9919B1( (((1czcc[S[ciouuuzziS9(9S9(  1BSKSK919119BSSBBSc[KK91BScc[cccu[111Sc[S[ioic[( (B[ooK9SiuiBBBSSBBBKBK[[KS[SSSSK9K[K1(   1( (9SozzcBSSKS[[[cc[S1(BccS9 91((BBB91(9K[B11K[K1KB( (((111Biuu1[o9SiccocczcS[[ (   (( (( (1(ooii[cooozzuiS( 1SS1 ( 1BS[SK91111BB9BS[SSSKSSKBKS[SSSS[iuz[BBK[cc[[izi[SB(( 1KBSSKBioziBK[S[BKBKKS[ccc[SS[SKBBBKB (( 111Soic[BKcKK[i[SSKSB111B[u1(B91BKBBB99B1B9 1ci[99( (11((11ouo oSSooouo[coSBB9      ((  ( [uuoiiuuiiuziS(1B[S9 (99BS[[K11(((((1B[c[[SKSSKKS[c[SKS[K1BSS[cKK[SSiuuc[B( (1B[cSKSSBSci[KS[c[9BKK[iuzoc[[KK[S[BB1 (( 9SSB19[[KS[c[KBSoi[[SSKB( 1czK9SKBSB1BKSBBB1( KooS1( (1( (K[zc(uK9cuouiSKB(      ((SouoiizuoiS9(KScS1 (BBBKSSB111((19KSSSKBBK[[SS[[[[S[[cK9KBK[9KKSSiooic[9((9B[ooSS[SK[ccSBSSSKKKSczzicSKSK[iS9(( ( 9ioccS11199cuSKK[ucSKBBBKBK[9(19[ociiB9B99BKK1(9[iS( (11(( 9ouĉ 1zB9iiKBB1(      ( (((Kozo[czzu[B (19S[i[91111999BKK9111119KccSSSKKKSSKKScc[S[SSB 19KB9KccSScoi[[K99Kcizi[S9BS[c[Sci[BKSiziSKBKSB[uSBB9(1(9ioc9(1( (BBci11Kcuc[cooB99KiB 1ci[icK[S9(K[B(9S[SB (1( ((1SzzocSu1cuS1(19         119(119Boo[BBSuoS1  B[iiuu[((9B1199BB111119BK[ccKK[[[SK[SSSSSKK[cc[S9 119iuicic[KK9S[uz[iooKKSK[ii[Scoz[BBKSS[SKoucc[K9BSSS9(  (11K[KSciuiKSocBKB9cK BB(ciBcK(1BKBBK[SKB((111(( 1KcuScicu[Bu9KicB           91(1(9zzoiSK99(  19Bccico[9((1((1BBK91B9111BSS[[KS[ccSKS[[cSK[[[coic[9((1ouiiiic[S[[[zz9(19S[[SczucK1BS[iciccizziSBBSSB( (((119BK99ScooocKBB(1KB[[1 i1 1u1BK91111BKKKB9B11(((1((B[icKKSSBKS9[o 9[[9          ( 9Sci[S9 (9BKicccoK(((1((9BSSK991(9BS[c[SS[cc[S[[[[c[[[[[ioi[c[1 (KSK[iiccicciuzuzic(((19Scou[ouKBB[iouoo[KuzooiK1KB111(119111K9119KSKK9(SS9B9(B(9 (9KB911BSccB1(K(1((1199[[SKKSB991919SB1KcK           BSuicSB1(19[KScSSciB 1BB91B9KKKB99Kcccc[S[ciic[SSKSci[S[cccic[[[19BBS[i[SSciiozouu[B ((1199[iuuuzSBKuouzc[cczucKSSS[B11(( (119B(( ((  BK199K[1 BSKccS((9B99K[(1( ((B[c[KKiuS99BB1BB BSB        K[ccBKBB( BBB[SSS[co[9((1B99BBS[BBK[iuouiiccicccoc[[cii[[ScuiSS[SK1 K[Sci[BBBK[ciKoS((19999B91Bii[izuuKKiuco9[zocuiSBKcSS1( (1991(BKKKBKc( c19B  (SSBS[cK11((1BB9 1( 9Sui[SczSBKcS991 11(           BK[izKK[B9BKSK[S[KccS1((199999BSSBSizzouzuooouoouo[[izui[cou[(1BKS11ScS[[KBB9Kcco[KKcc9(19K[[SSKBKSoS (9K[oui[coc[oz(cioiccoiic9  (( 1KK9BK[[[cuBBc111( 11B1B[cScSSK1(11111( (SuziSSciS191       (9SSKo[SBKKS[[cSSKcS9(((19991BKKKKcuouzuiuuoizzuoiouoiiouuc1((199KKB1BSKB99Sc[[[[[cKB19[ciiocSKS[SBB99B919KK[ucioz[(c[Sco[cooz[9 (9119BB9Kc[BSc[iicKcS1S9((((1B19ouooiccSB9 ((919SuuiozoizoK((        ((( ((1KSSKcoBBKSS[ciS[iiB(19BB9K911BKS[iuooi[[iooozzoiicozzu[99[9 (1B99SKBBBSc[K[ccicSKSii[SSSKS[SB99999B9BSSKcSK[SSB1iu9BKizSScizoS99Kc[SK[ocKScicccciicS[B1c9((9B[iozu[[SSK9(1(9Sioiic[coozuc(    11( (19( ((   (1((((1111KSSSccSBBizoc[[SS[c[izi99BB9999BBBK[[S[cS[[SSooSzuui[iouoS1BzS(11 ((9SSSBKBB[[K[iooicSci[B11999B9((1BB9KB1999BKSKBK91ii1cc[u9BScoocKczzu[ozocKcouoicioi[co1   9BKSSKB[B(11([1Kccc[i[SioiiK(    ( (99999ScoB((( 11(199BB91BBB9Kc[S[oucKSSiSKS[iciuuK(9B99919BKK[ccc[K9BBKoiczuzuoi[iccoouocKBz[B99 1B[SSKKBKSSKS[cooicuc9((1((1KB( (911BK919919BBcuK1ciKzcBuo91S[coo[uuooSBBKizzzo[K[KcoK1   B9( 9BcS 1[BKSSSKSKSuiSKK(       199KScoouzc911 (BKB19K[iiSKSSKBSc[[S[ocKBBKiicc[SccS((19BB1 (BKKK[[ccSK9B[iouuiiiooocioiciiooiiizoS1(((BciccKKBSBSSKSiouiciK((19111BB91119(19B9BK1(9B[uK1ouczcSo1 9K[ioiuoouuuiB99K[uzuoB9[BiucS( 1  BKcioB ( BBSKBBB9SicooBB(     11199SSScuc99B99BK[[KKSci[[cccSSc[KK99[cBBKKS[[[ciK( 119BK191BBK[c[coicczucSKc[ci[[cicouoiuuooiciuoB19B11[[c[S[KSBSS[SuuuzoB1(1 (999BBBK911(91999B1 ((((1ciSSSzc11S[[cc[ccououc999Kiuzzc19i[ozc9c( 19(9S1 19K[S(( B9991BB9BSSSB      1KBBBKBKKS[oiS999SK[SKScccciccc[c[[icKBB99SKBSSiSS[[SK9 1SK9KSB9(1BS[cciouooS[KKK[ccuuooiiozoioiiiS 9KBK[c[[[cSKBKcoizuo191919BB1B199B991991(1B9 (BK9BSi[BBKiiciocS[oiSc[BBB[zzoiSKScuB  1BSK1BB1B9B11BS9 BK191111BKKS9 (  (19[zKS[SSccoSBB((K[cic[S[cicS[iioccicS9999Kcc[SKiS[SSB919S[KS[SKB9BK[ciouzuocicc[c[ouuuoouucBcic[119KB119K[ccicKBSuzouzui[S[B9BKKB99((19(1(199(B9911(( 1(1(999BS[o[[cii[[c[KKB9S[ozo[[ccKSzz[K1 (( 9KKKccK9BKB1[K  9B111119BBBS1  (BcouSiucK[iu[(  K[ooocSKK[iccououu[[[B9B999S[[c[ocSBB9B99S[SSSKKB9K[[iooiuuuzui[[[[izz[iziiuuS9io[KBSSS((KS[[[izSK[ioucB9[icBKK999(((9911111 ((9111( ( (((119Kc[[ioiSB[KB9BK[iuucKS[K(1cS9S1(9919KB9KB119K[9(Kc[91 1BKB1119BKKB  ((((SizuiSzScuo9 BS[cciiKKKKK[iouuou[KK9B91((9K[cccz[[SBKKKS[SK[SSSKS[ciuiSczzoi[KKSKKBKS1(ci[c1BKKocK[uSK(9[ioizS[ooucSBSSK19119B1119(11((11( (1((11 ( 1 99KSSKBSoiKK[KSKS[coii[S[[9(B1B9(119 (9B1((9B1B19couc1BKSSB9199KB1  991(SiccBKuc   9SSc[SKK999BScuuuzucB9BKB1((19ScoouiSKKc[S[[SBKS[iicScoiSScc[S[SSKKB  ( 9S919(111ozicc99B(BcSioii[S[[SK11(111((11191(91111(1111  ((( (999KKB19ccS[[[cic[ccSKKS[c99 ((  (1BB9991(11BcicB [[[[KBBS[S1  9B99[[SKKBKci[SSiK  (9BKKKKK9(9119Sco91B9 (111SiooccKK[SBBKKS[ioiicK[oi[[[B9BKKK99(   (1191 9[KSzoSK11[uuiczzooiiuiK( (199111(  1111((91(1(( (11(1(19KK9 1BKcuzc[K9KKB9[zzS( BK1(  11919BB9919[c[1cKBBBSouiK   (9BccBS[SB11cc(    1 9BS[ucSB9 (19BScoiic9((( 11 (SozuoozSBKKBBKKKSioioiS[iiS9( ((   (( ( 1(  1 Kzu[S(co[ScuSiuoiuucB(19BB( (  (( ( 199(119( (( 91(91BK991(1BiiiKB99KBBS[B((  K[[K[S11B1(9K[S9(BcB( 99KBKco[B( BizS[cK((SoK  (BSKK[oi(( (1BBBS[ziSKB  91(KozouzuzcSSKBKKBKiioucSK[[9(   (99BKK((BccSB 1zzB99KcocSoocuucK11S[B1111  ((1B11( 9B991 (1111111919KBBSi[S9BBSKKSB1BzcS 19S[[BBS[KSK( 1BSS9(1SK(( K[[ccS1  9czzcB((99   9BKSK[uo9( (19BBKicS1   1991KozioziozzocSK[KSiicioi[K9( 1KKB91(199BBKKKB(((1 ((9K11cuS19BBSic[uzuoii[[KBcoB1(11  ((((1111(9911( 9KB99( 1919KSKSKKB99KKSKSB (coo1( BiK9 (1B9[9991((9KB9111BB( B[i[K9 9[[cc[[zcB((9KS[KKizK (((1999B[iuz[B ((9B9999BScoozo[ozzuui[KcSSoii[[i[9  9BB99B9  19919KBBBSS( ((BB 1K[1 1BBKSS[cc[[ouuoSBcoiciK91(1 KiSB9(((1(99BB11B[[K99119B991B9KKBB99BBBBKB9119o[ K[BBB1( ((9911(  1 ( (KS[[KB(9zc[S((91 (  BS[[[ioiK1 ( (119K[iouuS  19KSSK91BS[coouoiiSSiii[S[SS[ScKSK1((1KSSB1( (99BKKSB111BB999BK( 199KB99BS[[[cSS[izcSSSzucB1111 (B[ouBSSB99B9KSKSSSouocSKKB991919SSK99BBBBKBB9KK(Bi( 9(((BK9(19  (1   BK99BKS9  9[oS    (((11BioiiiB ((119SK[io[1  (11BSK[ouoiiiuuKS[S[SKS[ccc[K1  (9B[SSB9 1 1[iB1B9BK9(BKSS91B( 919BK[cciiKKSco[[izi[K91(1Boz[SBKi[S[S[iicciizic[[c[SSSBK91BKKBKKBKB9KB(K[B[K 9iB((( (9BB11991   SSKBKS[1 (SuzS     11B[ooiouu[ (1KSB[[B   1[ociuiiioz[BKSSS[[S[[ccSB9(1119KKK1( (919BKK1(11SK[KSSScSBK 911SKKSScoiico[K[iuc9( (BSiu[BKSSSczoo[[ccozioiioc[[cicK9BK919KBSKS[K9c9(B BBK1 BKKSKKSB9(  (K[ui[SK1 1SouoK    (1111(199K[c[cuz[  ((((9SS1B1   ( 1ooK[ouioiuuczziKKKKS[SB[[[SKBB9(1BKB1 KouiicSS1(SKBS[[S[[ioS ( KBBS[ciii[cS[i[Kui91(1SSScoic[K[zouoiiicooiiozoiuuo[BKB99ScSSKK[[1BoK S(9Kc919(BKBKSKKB  (19BSc[cSS9((9co[9  11Siu[SKBK[iocKSic9(((1(((1SS1(((((BS[iS9KScouoozuiKSSKSccKBBKKKKSB999BB  cuc9(9ccS[ccc¼z[(1( 1119BScoicS[uiu[9[uK9BSioKB[cKBBiuzziciicioouuui[ioicci[BK[[S[iioc99i[K[19uccB1 (9BB9((1  ( BK999B9K[K9((BK9  BK[uzoi[S[iuooSKcS( ((199999S[B((1( 1[uzzuuo9(BB[zuoiocBBBBSK[iSKBBBSKKSKBBB1([c[KBKizzzoooiicɰ[( (1(KSKS[ooicScicouiBKcoizuo[ScSKKKiuuzoiiii[Sciii[KSSS[[Sioc[[KKcouiKB1KKK19zo[B (1BB99111ccB11 BciB 119KSB1 1( (KSK[cS[KooSSioouu[cK1 119B9(999BKB1(99((1[i1 11(Suicccou[BBBKSKKKSKBBKKS[[SB91 K[919BKBKKBSuucicuKBBS1(1BBBKSBBcuuo[1[oB9KoKBiuǚiBBBczo[B19B9919K919KSSSSKBKScicBKouo[9KB99(cc9  9SKKS911BizocB9(KzS[K 119B1 1(   Bci[[SS91BKc[c[[ciciS99119BSBBBBBB( ( 1119SuuiB ((1Kcii[SScSB99BK[SKK[[SKK[i[KKB1(BK (KS[SKBKKoiiooK[icS999BB[SKKScoooSBzo(9Scoz[Sco٦oBBBBSB( ( ( (B[c[cKB919[uiScoi[SKSSK[B9i9( ((1( (999Kuo[KSB99i9BK  (19991(    S[Sio[SB( K[[[c[KKcoc1(19B[[SK[[[SB  ((1K[izziSB (9BSccicKKS9119BS[[SKBS[[ccccSK911(1[c[[K9Kiuooi[[zuo91K1BSc[BS[ciuiSizc9[cKKuzuS[zˢo[B9( 19119K[[S[c[cK119[iioo[KKKKSciS9KuS1(B9((9[S9B119[KBK ( (99B9( ( 19zzuoiiK(9uiccSSio9((BKKScouucK1( BczzK((BScSBSSKSSKKB1 19BSii[SKS[[cicicKBB 1Sioi[KKiuuoooc[czzzB B1B[S[S[iccS9Kc[i[cicizizSSuoK[S9(  ((99BS[cc[ic[SSS9(B[cocBBSSS[[9([uiB  (9((99Kic1 (oo[SB (  1BB  (1911BBSou[ (Kiuc[oiuSB1K[SSiouccS1  (KizzS  9KBBKKBKSBBScK1( 119SicKKSK[iuuoc[SSK9BB9Kcooc[[iuuuociciiuuui(KS[[SSS[ci[BK[S9BBKiczzBKB[iziS9(19  (  (19KS[Scccic[[[cS9(BcicKK[[[[S19ccB (BB((11 BB(  czSKSB (K[9(1BKS[[[SouuiSSKSizSSoc( Kczzi[ic[B( (B[ii[1(91Bc[9 ((9BKKSc[9 (11(1Sc[[[[Scccooic[cScc[iiouoc[[oi[iocuuuuuzz BcKBKioiiS9B911(KS[KcS1 9SizucSS( (11 ((19K[[[ciicS[[[[c[BKccKKKSSS[9 9K   191 (1 1B9  B[SKB9S(19B(1K[ioic[occocSKKKiiccSK 1[couoKB(  19K[BB1(Kioi[9BccciS9 (99(B[[SciccioiccicS[ciiccizi[[S[[[[ocuB19B9KSizcK111 ((91 ( (Kuu[SB    (((1K[S[[c[iocioicSSS[[[SKKKKSS[1(9( ((( ( 199((1BB 9zBBB[(zuoouuiSB991 1ic[SBB9BB91(  (( (9119KizB111( 1( 9 BzuoozuzuzԍKoSKBBBBBBKK99BSc[coKB19Bii[S91oiBScBz[  (B[S1 ( (11((Kuzњ°zzoiS1 (( ([[  ( (BziiK1((9911[SB1((19B1 ( (111  (9[uo (9( (B1((((  (B  9uzozzuzzzԳKc[KK9(199BKBBBSKSKKSu91KcuocKKKoo9B[K991BKSci[1 11199( 1ucSɢzoK (( ((Kc  (zu[ 9SSB( (1BK9( (BBB1( (BKB( (Sozocuzc 1BB999(1BK9(119    (([zoouiioouiBSBK1(BK9BB11BBBSSS9BiKSuu[B99SK[9B׷( ([zi[iccciS( 1B9((iK(Ƿoczouo[9  (( c  ([uzzzS 1S[SB( 99B9(((9KBBB9(( BS[SK  Bcccoc[( ((911((9((B9 (BKKB9   ((9B919uociuc[iiuύK[KK11BB999999BBBBKB9[zccK91((K[ii[[ڳ(1ouc[ucc[S9 1B (iiB ªzK1ooiiicB  o (SuzzuooiK 1KSB9B9(BBBB19SSSKKSK11BcSKKS1(BSSzc1 1K[K    ([oiuoB  (9KSSBBBuzccuicozϰ[cBKBBBB119199BKBBKSSiK((( (iuizocccǢK(SiuiiKSo[[KB 1B9( SzcS1 ҭzzS1SuSS[i[( i  9[ozoocKBK1 199919B11BKKSKScii[S[K11KS9BKSSSSB9( 9KBSB1iucB  1( 9uoczc1  (B[[KB99Boicouioc[ooKKSB999B999B9BBKKizzS9B9Buu[ccSK[BKououizoB91 9SS1([zc999č[uuzB9i[[[S1   SScc[cicuu[cui[K1( (BBB99SS1(1K[uicciicc[9( (19BKBcocS( B9(  1KuuK   ( ( So[1B1    19BSS99911cuc[[[iz[Bɒc[BKB999991BB99BS[z–uzcioi[occccKozc119BBKB(1zuiSK9oSiizB9oucc[1 (1KKuuuoc99uoccS91(9KSKKS[S( (S[uccccoc[B  199BcoiK9119919B( 9BBKcc9(  (  1(1BiK ( KKSBBSS91( 1ocS[iiuzSѳoS9BB999BB9BBBBSS[zB[iioozҼļS9BKKB  iizuB((u[S[i(Koziioi[1  1BBK[S[ooooiczu1 B[i[K((9BS[[ccSB 9S[iic[[cS9   1BB( BuuoS(  1999BSKBB(   ((9[( (1 KzSK9BB91 ([zc[c[izcoɖSBKBB99BB1B[SKBScc99zuušϼS9B1( 9o[u[ oucSou91[ciic[cc[9(BKKS[[czccccu[1ScSooSB19BBBScicB9((9K[ouuoicK(  1 ((BiozzK( 19KKB9BS[9  (91B1  z’[[SKK9( 9izuouuuccciuc9ϦcKBBB99BB9KK91BcoB(9Bozio٭ԿK( (SuuzKS1 Szui[cS(KoiS[[SS[S(  1BSSKBBBiooccioiBKcK1ccB19KKS[[cSB9 (9[zuS1(   ((9Kcuz[S9((9KScoB1B[S9( 191(    (K1 ذiKBKS9((9KiScico[(ɖ[c[B99BSK9B99[[ic (91ouuuiiicc[izoB9KB[u[9BzҪĚ9 [i[Kc9( 9couuooc[K(9ouocK[SKS1  (19[KBK99KcizccSKKSc[BKK19ciuiKK[S[[c[SSB KzzK9999( (199BK[o1(((9c[SKS 1K[K9999K[K9( 9   9B  (SoKBSK9( (Bcu[S[SKSBiϞcicKB9K[SBKS[iccS ((SzuzicSBB91B[S( ( (1(B[zBKioziK19cS((B[c[SSc[cK9[oio[KSSKB (9KKKKcK999Bz919(1(  119KiicSiu[[cSccccS[B [u[[((19B1(( ( (19Kiu[((1ScB919(1BBB99KKSciS9((SK 11( SzuSKS99919oiioziScSBKKcϪSSii[BBK91BKS[[i[1(cooo[[SSSSKB9SS9199191(BKB119S[KSizKciuu[iu[B9Bcuuoic[Scuzzui[K9(9BS[SK[SK(19i   (BKB9(9zicSKSS[cS[9(czK( Bc9191 ((111( (9SS1 911KS919BBBBBBB9BccS[SKB1io1(1SB(  (1Siբc[S[B9BKBzoozoz[BS[B1ҳo[cc[KKB99BBBKuo99KS[[19S[[SS[[[[BKKB( (1(11 ( 91 (Kozi ouui[K9BKS[S9(9[  11    (([zcSS[[[c[B( 1KcB19coc1(99 ((1B1 (999((9ccBSzcKK[iK999B91KiSBKcK(z[ 9z (Kcccuu͍1BBSB9KB9ozii[[ic[S[[S(ĉc[S[K9(999KouB B91(K[[KBSuzc[SK9      SiouzcB1oziB9BBKB1Bi  (191( (  9ziSK[[[[K1((1Kcicuzc919( 9cS(  (1K[cuK9[z[Scc9 1991 BSKK11([([ۄ9SSocoˍ (  Kuuiccuoouo9KcS̀ciS[KK9SKKcz9 B11KSKKB9[z[KB1   (1911B9KiSK9(Kiz[[[[c[S[Sizc91(1czi  (  919(B91(91(izcSKS[S[K111KouoouuiK99B((BKS[[1 (((  1[iKB[izo[SB9 9B1 BB99(1BKic[uzՀ 9izuuuziSK9zɒcc[ozoBiBzKS19[SBKKcuB(     ( 11S[BooKKB11191(B9BSSBcizo1([iu(11( ( (9S1((9( 1iuu[SK[KSSB19ii[SSK911191199B9BKKB(( 1KcKBS[[icKB1 991 (KS1 19cooSzou1  19uoSizzu[91[ҰoS([dzSSccou[B9(        1cuSB1SuoS91(1KBKoz[K1Kuz(1(  (19( 1cozic[cSSKB(9iic[B1 ( 191( 9KSSS1 ((111(9SSBS[9 (KB  1[c(9KouSSiu͞9ouuc9 Kci[izuoi۪zǖc³B((     9cu[9(KuK((KBBoBS[[cz (1( (  1 1iuzoc[[[SKK9SiKK1 19(((19((1B[SK[S1 11  ((9S9 (B1(9iu1 1B( 999Bڭ1[[ui    ((11icKiuzzooҼǢļĿͷ[cK(         1u[cicuS1BSKK[ooucKoiKKioS1S[iu11((  ( 9uouuic[[[KBBScSK( KS1  (1(9[SSKKKB1((9   (99  19( (([o9 (S߷c[[oz9   (1(((zziiuooiS1cĹc‰щK        B[K(c[SB199coBSuzSBBciKSc[B1(Kcu  (    1[o[oiicc[SKK[SK(KiB( (991(1911999111(11  (191 191 ((1Biu9  Kذc     1((oicuc99i˿[[uzBzucoĹ9       B9 (B[S[i[S[SKui[[[9Sooo   9K9 (KcicSizoic[KS[[K9(KB 19BB9   (1B[K1 ( (19(((19Ko    ijK  (9( B9  [zioioS1[˼Suu91(((    (9      (Szo[9SocKczozu   (9B11Succ[coc[c[c[[[[[S9 (BKKB   (9KK1    91 (B[o ɰu[1B(  99BB (  uoSSoK1„io°ĚSoS((    19  (   (Su[KK[zc[u(1KK9Bcz[SBKicSoiSS[[[[SB( 19B[i[B1  BKK1( (  (1BBBBu1( u·K(1   ((c[ ( 9zuKSio¼[ S˚cK[zzcBzBizziK    9(     11 9SK(9cucci91( 1((9KKKScz[BKBB[i[Suu[[SSS[S919[oozu[B( ( 119(1(((  1Sui[S1  cocK 9 9( (Si1  9[Sciu[SҰ9Kc¿oBBcuiB1    1(    ([BKzK1cSS[[KSuuK BB99BB1(1BBKScuoK9999BciScuic[S[cSBKcuiKS[K1(99 (1  ((    1[ziic  (1z(  BK 191(1KS[K   (Bu[ccuz’zcoĪSKScu[SSciuK   (   BuoS 19BBBBB91(19K[ScSKB999BB[i[Biuc[cic[S[[S9(1B9((1(     Bozu1 11 (zB(  [K  BciocSocS1  ( ((9zu[Bzϼui¹9BBB1 (1Ki[          (1uzzSzc1 (9BB9(( (9Sc[S[cK99911BSSSozic[[[cciuiSKS[S( 1(9K(    Kiuo 1B1BzcB1 ((19[1 KizzSBSB11  BuSzzzķzzz99 1( 1u[    (B(      9(1iuuiuoB(uoi(  11( 1K[cc[[K1 (1((BBBS[ouic[ccozcio[9 (9c[K9    (SozuB(((1SoK1(9SS 1ciii1  ( (( ouϰiB9 (B9B9 Bui (BScB( 1B9BS[K   SoKKzziuuB iiu1    11K[c[[K1 1K9(Kiozo[[[cucB1( (91Bii[S[K(  BSzBBS1   Bu911 (BSK9  1 (  1coѷ[Kczo[B 9B191(( Ku 9Sc[91K[[[cS    1uuBBK iĢoioBKu9  9B[ccSB ((1 (9K1(1couoccicuS  (11 (911[cK1B9  ( (Kouu[zS9 1SK1   (u1  1BKB 11 B9  1SzzĞzB9Kc[1 (1  19Bc 191((Bui    [u[ ³KcczK1z1   1KS[[[iK(((  19KSSS[iziccSScB 9K9 ( (  BcuziSB9K[B[o[uo199 BK9(    ii  (9B9( 1[cB 11  (( (Bz€ScuBScSuo1(9K1 cz[1iϹ[B9B11ccizuS    9[B [iS9S[o  (ioB( (1( (9S[[[ccc1 (  (1BSuzcKiiSB1 (BKSS1  (  (Bcco[99B1BcK99 (9B9(   1ui  (1((i9  9K((19B91SouDŽcSBǦScoS11B[iB 1uĀu[ouuoɢzizoou[S1  SS19io[S99Kcuo (K1 (991(BSS[S9K[[[K 991(9BKKczcSKiu[S ((11io[[S(11  (9Kiz[(  ((B99K1 (1 19 (991  9 (111 (1ci9  KS11((((BK919oiiccўKK19ɦziS ic9BS99cǖicBoϼSKKBBK[S[iiSSB(  1K9( 1czo[KB[uz[(( KzK1((9B9(9[iiS99KccS9 191((Kccii[BBKczo[99Kicc[coi[1 ( 9[cozu[K(  B9((( 1(  1(1991  Bo(1BSK91BB9B9  1SB11( 9((( Scuoi991SɦiS1KB1cocuĿc9( iǰ¢S ([[99K[[[SSK1   (11 ((Kcoouozz1 ( 1K9B911(9[ccK9BK[[9 (( (cuiccSB9B[zzc[[iooic[[[11( ((BSKKBK(  9[KK91 (9(  ( ((  (( iK1BKSB99S[B9(  1cK(9( Biu99KKuǍK(9ǦS (oziK ([ªz((Si[BKSBB9(  ((   (11(9 (cB ((izS111(Bc[999BKcK( ((([cSK99BKSoo[KScoiouiB 91     BuzB  (1((    (91( ( BcKKK919S[91 9oc(  ( [zɖBKKKS˿uBBĭi( [9[c (uzK9BSKBKSK1  9K1 (((9  99BoS1(( (119  ccK19KK[K( (1B[ouKK99KK[[ouSKKS[KciK 9B1(    zK9(  ScB991ScSKBB99BK119B   9oi1(B9Bioz˭KBKKBoϞBcB[i[1cB iožc1Koi[SSB  1oB( ((  KK BS[i(   zcB9BS[S9 (9[iuuiS91(BSBS[ozS9 11 (9B1 B1(( (((   19uSoz(    ciKBKSSKKB91SuoB  Kiuu   9KSczozouѿo1B91Bķczͪzo9(uuiouBBiuccS(  [oB  91  BK(  uS9BKc[9  9Siuu[1(9SSK[[c9(99((KS1 (991( (   1[[9(19iuio ScK[KSSKB(9zc1 BcuS  ((BSSczuooz͍BBBB(K‰uuؼi[uK[uuiB[SK91 ((1ooou  ((   B9     cB19S[B( (1KKKK1  (9S[SS[iuS9B9B[iS11911 ((  (9[iK99919 19cKK ( 9S[ozSSSBB9KziocScuB (9B99KououcuͰS1KS99zS9ϰciu9KouiSKSB    1[zooczK((   (91(    B19[[K(19BBKB91 1((1B[[c[Sczuo[S[c[K 1991     KzKcBB9K9BBBoSSB BiSSzcc[BKBSz[SiK[cBBBBBB9( Su[icoouBScS9K91[9BzcuK9[K(   9uzoiiiioo[1 ( 1 19(    B9KSK19KSB9(  9B919BB91BBcoizi[S99( ((1B1(  (   ( 9ozuKBKBBB9Koэii[[zSKBu[[S99BiuSB[o9cizooi[cicK191 KSiiccoǖBKSB9Sc[i1 coSK   9izuouuiKB[cK(( ((  19(   KSSS1(11(   ( (9S[[oSKK9(19KB91  1B9  1Kczuzz[9BBBKKS[Kzķzzo[B9KooSK999KcSKz9oc(Koi[ic99ciccK99119SuzzSKoѳcSS91S˞SizK[ciiuicS  (uzzo[K119S1 (  191    B9((  11   119SzuicS   1BKKKK9(  9B1((Sizo[coS9BSSKKc[BBdzziKBKBBuz[K1((9SBBi[Ko( uoi[B (BS[[KK1BSK[uuuzDŽK99BiĀ[uucSziKB (1   9[zzzucK9(1 9[K(  11     (( (1(199(1B91((11(111KiicK(9K[SSK(   K[uoKBSB1BSSS[iK11[uzi[SK9Buzo[SB111BB 1KcS [[i[1(919BKKKSBczK9ooizuϪS9BBcɞĦzoS(    (S’occK1(1( ([zK        (( (  ((19B91((((1199BKKKuz[K(  9Sc[[B( ioBczo[KB91BKSiic((BKBBBu[iziSSB1Kuc[[SKKB99999BKcK9iuo[[[K1((((9K[KcK 9coccuuou9BBcװ˰[(    KoϿzz[B1 ((1K[u[1     19((( (  ( (919BB99[zzoB ( Bc[KK9(  B[KiiSoiB119Sczu9 99BBB[iSKucS[iS[u[[B9BBSSK911KKKco[u[19cS((1119999KoS1 (uuciuc͒991SzҪϹzc1111   1BB99cͿ91(((( (B[cSSzi1       91  ((9 1B91BKB1BBczz[9(1((9KSKB911   1ziSSu[Koi[91B[ouB1KBB11ou[9So[couocSKBB9BK[[999SSBKuB[u9(Bo[9(1BKS[9 9oS1(1oooioozͪSBBSͿDŽiu9KcSSB9KB99BKci[c (9(( 1cuiKKzi    (       (BK9(BKKSSSB991Suzi99( 1SSKB99( ( ((czc[SKio[[c[KB9K[oi( 9BS1 [ui[S K[cuuccKK919KcoS919B1 1[[9iz11icSKBSSKKSB cS9(( SuocozͷuBBBzԞ͒iiK99[cSBKcB1KKKcioi 9ouoccoucczo9  (       (KSSS1 19K[[[[KB9BK[uucc[KK[SKB9( (  1zSSS[1(BS[[SBS[SS[9(9B91 9zBKBKc[SSc[iiK9919cucB999111BKSzu9ic1KzoccSSSB(([K1(1( [cuiciuɉKSBz؞iԭzS91 (99( (( (9uoS  Suzociuzi[Biui[[SSKB    (Kc[[SBK1(1BSc[SSB9KKB9Sozo[[[K1( (( ((Sc99KS11BSKK( 9SS[K9119 [zKB1BzSSSKKKccBB9BKS[K99119KSKczo[c 1ucKBKB11([iS((  (BzzooiϞcKKzحu՞oiB11(( 1ªuzB 9zzi[ozoociui(    ( (BciiSKB99BKBKKSKKKKBSKBBBcu[K1   (1 1K19BKB( (( ((BS91( 9czK  KzoSKK9BB[uKBB991BSKBB9111(1Sic9 cuK(19BB9 Kzi1(((9zzouɷcB[ٷ۰[9SiK1( ( ((zc1  9uzoozo[SSizS1 ((1119B99Sioc[K9111KKK9KKBBKKS[[SSSozcioS9 (coB9BB1  9BB1((9Koi11[zicS9BSSccB9BB9(9[[BKKB1(( (9B9[ziK99BB9K11KKBBB( (9zo[iiKcǞ˹SBczB1((BBB91Si( BozuK99KuScioS   BBBBB99SScc[[SB1119BB9BKBKSS[ioSKK[c[BSiS(  (uoS1 (11BKB1((999iuK  9czz[co[KKSS[K9Kc[9BccKSSKBB9111BSii91SKB9B( (9S[B(91(BzoK[ϒ9[uҹճzSSuu911(1(((uoS  (9BiouzoK11B[c19[ozo[SSB91B9(SKBSB19KK[[ccK91(19SKBKKKBKSioB9BSB11BSzB( ( 9z[((  (SSKScK91((( Kc9 1SiiBKzuK99ScKBiiB[iKS[SSSK9999SiK B[oS999  ( 11((991 (czocuҰBSoԹĒSScBB( (uzzzS  [ozzu[9(9KKiuc91Kcc[[[iouzzzo[BSBBKS[SSSSSSB91119KSB9BB9BK[ouS919B1 (1KuiSS[ccuuuuccizi[B Kc[cK91B9(119BKKB( 9[cSKKooS91KcKSoocci[KSKK[ccSKB[c9(B[uo[B9919B1 111 1((  ciuKcԭϷo[[cSK 1uiuouB(  (Buo9BBB9Kz[9BS[SBKS[SK[iooicccio[SKK[[SSKK[K99((9KSKB9111Sci[SKK99(1KScicoucSKSoozcz[9 ( 9BKcS1 19cuSBBccK1 KiSc[czo[SSSSSSoucSB9KKB9[iBBSB[oi[SB9 ( B991( 1o͖K[zҹ͢oS((1B91uuoiS( 1cuuS1BBB[uSBS[cKBBBBBSSS99199BK[KB9B[cKSSKK11119B[cSK9(19[o[11Si91 9[cKczuuucBSiicSKKSSKKizS( 9B19BB[91SKciKBBK1(1co[[[Kiic[c[KBKiuzo[B9B99ciKK[[zuSSKB1 ((91111((9zϰ[[cҹɿcoi(1((KzuS (9BcozcB999KcuKBB[cKBBKSS[[[KBB9B9BBB9BK[cKSK1(19919B[i[B99BSK99(1Kc9( BKSSB[iKSc[SBB[ii[KB9B[KBBKuB11911999BS[B 1KK[cSK9(1ScKKu[BKcoc[[SScoooiiK9BS[zuKB[[uc9KK1  (11( (( KzϿSBuču 9Kci9BoouuocoBK9919[ozzuuSSSccKB[icScoiSKKB999991B[cSBB9 (((19Sou[1(9[[1 11111  1119BiK9KKciSBKiiciSKKS[B19[zuiKB1 1B9B[iK((11S[[ziSK9 (S[[KKuc9B[icSSSK[iccc[KB1Biu9B[ciS99991    (( 9uuouў91oҚ¼oSociciiouuzB1KzzziioioiizS11KB9[iSczzziciocKBSiio[B[c[SK911911B9(BB9((11 (99SouS1Kc[1  9z(KKK[cK1BocSicK9KK91[uo[o[S1 ( 11 B[999B9iS[zu[K9 Si[SSSuc9Bcoi[KKKKKB9 19KKKuu9K[[c[KBKK( ((11  9uzzԷԭɢcSK([u[oi99ScK1 1B1BizoccK[izcSuB(K1B9Sz[BcoB[SKKK9KzzSKBBS[ccK119911(1 9991((9KKciK((ci9     9K KB9KcS(So[BioSBB91BccKi[B991( 1 (19B9KSz[iociS99(cSBSo[cucK[oi[B991( (99BSiuiKS[SSSB19   ((( (czհu[(SziB1BK9   (BScK(KouSKSzi99K1SSio([ouKB(1BK[uoBBBBK[[SBB9B9(B (999BBB91(B9([S  [u91BKBBSS9cuS9io[K999Sc99ioiuS99SS9( ( 19[[uS[[KKSBK9K9ii[[iBSc[[iiK11( (1(1SSKBK[[S9 (   1(( ((Sҹzzuoio[     9K11[o[BizzS99BKKKSccuuzi(9iuzzB1(1KSSBKB9119Bo  (BBB( 1( (91 (( Bc11BSB9BB9[i9BicS91BBKS1BicioK9BSuuB((  BBBBKKKKKBS9Scoi[SiS(9BKcciS1(((111( (1(9BK9     9B9( Bzu͹ǍS1B[cS1   ((1Kiuc[izuKB9(BSzc91BzuoS9 (K[BB9K91((Bco  (( (11( 199K[S9((zK911  (1BK9Kc[B9KSKSS1Si[oi911Sc1(1( ( 11119SSK9SiiSKooSB19BS[Sii99(1 911(( ((   1((1K9((( Kuucѹu[˷o(19(9(    1K[KBBB[S19 [iBuz[[B [zoKBBK1 1[ii     ( 1BB99BKK9((Scu9(  ((119K[[S[SBBB9ccSiS19KoiS( 91  (BSKBKKBBKozSBBBBKSKciSKBK9BBB9 (      9BB91(( BuzzoiԹǼBBz      (  (( (BiBKoocSzzB(( 1Kc9BKB((19iuo    (111BK9991SucKoS  (11919KSKKKBB9K[KKcK9[uiBK9B1 (KSKSB9BKBKi[KB9BBBBco[[[KBBK[K91((((     9K1(B191Kzozi[ªz1 (1(         Bo[(9[[K[oB9ioB1(11(1KcB99111199[uo   ((  1999((9Kizc9cu( (( ( 1119BSK1 19KSic9BizS1B[B    ((19KBB[icSSKK9BB9Kii[[c[KKKKKKBBBB91     1111KKB9[ziuizϒ1       ((   1 (KK(( 1999BB19KocB9 (19119BKS(   (   B91((99K[SBBoB91B99KKBBBB1  (999KKKczzuuK( 19K[SB1( ( 1BScBBB9999BKKKK[SKKBBKSS[[BBS1     ((((1BSc[oSiuҒ           (9BBB99KuzB(11BB9((9BBK1((  11( (((199BSBB[[cciSSS9 (191(1K[[[oo[9  KuucKB9((9(191( (BSziB999BB9919BBBSSSSKKKSS[[[o[  (199BBB[[z[czuo͒(       1(        19BB[u1(19B9111BKKKB9 1991((       (  9SBBKK[icocKB  9911(19B9BS[B( 1 SuKKBKK1[zSBBB91 1BBK[BBKKB9BBBSSBKKKBKS[SKKSKK(     11 199cczuSSioSɄ(            (11 (1KSBuo(19BB((9BKKciBB1Sui[B(( 9B1(   9Kuu199BSc[[[9  (KB( (( ((1KK9(9(SicB99[KSzK9[S(( (9BS[KB[SB999B[[BSSKBBKKKBBB( (  (1(   (11(9BBKicz[cuu[oǚS   (         1B991(9iicB(91111BKKS[oo99BuzS919((9iiS1( 1B9( (  9BSz19  119(1BK[iiS1((( (9KB9(( (ocBBSKSBioB19cc91 (19KSSBKKBKBBBSc[[S999BKKK91(   19B((((991B9KSKK[[uo[coSiz11(1(1(1           9B9SB(SziSiS(9B99BKSK9[ioi(KccSB19999cocKKSB9Sou[B99    KKS1   9SouioocS[SBB(( (9BBB1(1KiK1BSKKczK1(9ii[[BBB9BBKBBK[cSB9BBSSKKB9999B911 (99 ([i[KBSS[[KKSziciKoɉBKB9BBKB((S9B9  (      (1BcBK[919(1B9BSc[[S[occc1[ocK1(919ozi[KccS[uui[co[1(  9BK[9 1iuoo[[ccKc[[oSBSSKKSBB19KSB1BB1[zouB 1[izooc[SBBK[[ccSKKB9KS[SK9BBKKB1  9ouK9KK[oc9(oocSiljKS99K[[9Bcc99111Bcc9       (1   9919Sc[BSuoK99Bcc[S1(( 9uzc[S[B1[ziBSuiSB( ((9KS19Bi11  9cooi[S9BBK[czuouzcKBSSS9BSS11BBBuuioS((Su[uuzoSKSoc[[KKBBBS[SKKSKKB91    9[coSKKKK[[1 [o[[ɀ1KK9KSK19[cKKKSiuo( ((          (19BK[S1ccSSB((K[[[9 (coKBciS111  [oS19K[B19999KSco[[c[[BKSKc[iccuoi[KBKK9BSSBBKKci[c[B9izo[uuoioiKKcuoSS[SKKSKSccizcBBKB91 BK1BBBB91BS1(1o[SϚS(1B9B9( 1(((9BScK   (        ((1(cc[c9Bc[KB  9c[KSzz[19[9 ( 9ioB(9KKuiKKSSSciocKKc[SK999[ScicucciSBBBBSSS9BKScucSc[KSzouczz[SKiiK9BK[[KKBKcccciiz[19K9(B91KK1( (1 1SB11KSSҼc (1((  ((               [cK1 1cocB1 1[o[K[ocB(1izi[o[K[S99BKSuK1BSSS[[SB91BB91 (11KScociiccKK9KSSKK[icoSB[cSi[iSuiKKKS[[KBBKKKKBSccocoiiS(1SB 91 ( (( 1BBB91( ((9KSB91(zSS°[ 1   (1( 11B(       (    Sc9 (1ScKK911(1SioiSSK( (izic[iiioSB9B9K 9KB9K9  1K[S9BS[[KBBKB99BKiiucKSSKouSSB[SSS9BScBKSSKKSKSKi[K[[S9(BK 1 19 (9[SB9K[[KB1(( (19BKBBSK9ocK°o KK (((1((1(19KB19Sii        (    ( S[( 9S[K91( (9SiooS1 Kz[999([oB9999S(9KBB1  ( (11( 19B911119B9BS[[[SKKBciKKBBKSS9KcS11BKS[cc[KK1199((((  1((1(1SiiBKS[S9((9KB91ScKBSKSuoK[uoSĚz[SB  ( 1B(( (9BK[K9BocSB9        9K9(1(9SK911(1KSci[B (BSuoB991KoziK11BB[c199KS1( ((91  BB1  111( B[[SKBKK1BSSK9119111991 ((B[SB9 ((  1( (1K9( 111 9[[[SozcKS[czKB[SS˭c (( (91 (99KSBBKKBczzzooouz[B1      9SB(((9KKB9119B[i[K9 (Scozc91BKoi[cK(1SBSu[( 999SB19( ( ( ((  BKS (1 1SccK9(11(1  ( ((9(  ((((  (11( (    9KccSBcuc[[ScocKS[c[oˍuך  (91 ( (1KoS9i·ķoSBKSSiB 1        (ciS9911111((KSiicB9 (SuooiB(1Bci[[cK(([Ko91BBB9B[B(( (191(  1BKB9(1((19KB91 ( (91( 91   ((( (199( ( 9KSc[BK[cBKS1SzuoiKSu э1(    1coucKǰiKocB        oocK[c[SB(1(9Sic[K9( 9iu[91(1KcSBKSB19cKuzB (KSS9BBSS9(1KSK[[B1(B[cccB  ((91   9BB (91 (K[1  (11 (1((99( (1( (KSKccS[S9 99 BcuoiBKuKzKKuB   (ouSBKccc·iic1     (KucKczoSBB[K9BKSB1(1SooK  9cS9BScK999Biuc99SSK1S[K[B9SuuioiS[S[iicS1  (  SiS( 1B91coK ( ( (BB 1(199( ( (((91 19BciccB   (19iu[KK[coS oz( 9i1911Buͼzziio[oc     1 B(1oiScuoSBBBK( 19S[KB (Kiu[99[iKKKB9[iB11BKB9[[B[SSiuuuu[BSiiii[B  19BB ((  Koc( 9K 9i[(1( (Ki(( (111 ( (91( (919B991 (11 (((iSSSBšciB zu  Kz1(91Biͼoozciuouo1 1      11KKS[[ouoKScSB(1K[ic9((BK[uuo[SocKSK1(9zK9B( (9[SScKKSScocS9ciSSK9  9[[ciK   (9KccB ( BSK    9i ((119((  19 1999((( BB19((9c[SKK1uu9 1i [K99Bcu„zSzzzzuuizuiizcBK(       9[K ( KciB(SSS19cuoKBBcuiuiKiu[[icK99ii91 BKSKuSKKKS[S[KSSKB1  SicciS 9K[[[B(    9[SB  KizB(((1(1( ( (199( Ko[B91(KiiKK[[cui [K Bc[91KuuzSio[ccioozic[iocic(    1(19 BcS9iiS(Sic[Kiziocuuoi[oi[iiK[KKSSS ((9BSuucicKBKS[KKKK1 9cc[[[B 1KKSB9   (iucB  1S(991(((  119911(9o[B11BScSKBSSuǼcS  SB[cozcK99uoiuz[9SS[[Sczzoic[[[[ui[9   ( (1 (  1cicuuK99Souzo[ccic[[B111KB(1KKS[i9(1((9KKS[iocSSSB1( (1  9ci[c[SB 1KKBK1   (SB9(  [zoiB  ((((((11  BSK99999SuuK111KKSSSSic[Ƿ[( 99oэiiui[K1[iSzouuBKoc[K9KiooiK9BSScoK1     (  1 (B9(9S[iiocKcuc[[[KB9KSSS[SSBSioouB( ((BB91BKSKB9 (9 1[ooc[[1  9SSK(  BiS1 BzoK1  ((((((1( SoSBBS[cocSK119Scc[ccc[[ļc Kiް9iczo[[BBzS[cci[SKSooiooo[99KczooucSSK( (1BSScS( 119B9Bcuzzuuociuuuooui[Bi[B1(9B(1    (( (1[cio[[c9  (BcKB(  (( 9iK  [c  (((((199 BocBB[iuuic[B11[coioc[Soc c1BziKoi[SBiuuKouiSSB[[oziK[icKB[ouciSiuoucizS9(  91 B[SSB  (919KS[S[ciiu[S[SSKS[SBBuS991  (9   Koici[iS9(  1KS[KS1 (1(Bc[zo1 KiS  (11((((( 1BcKSBScioi[oK( (Soooi[[[i¿i B[1KcBKcKKKSiuouioKzicK( Ki[BcocccouzuB1ioK1[zzoc[Kiico[uoK9 9199 BccB ( (999KSKBSizK (( (9S[KBKzBB1((   ( (BSB199[S9( 9[[[icc111 9S1B( BcK( (  ((((((( 9cozuSSKBK[S9 ( 1[iiuuoccozS˭uS1KS9SS9KS[cciSBK[u1(ic1   B[[[[iiS9(9iS(9zio[KKuo[iz[K[S99 9iSBK (99Sui(    199BKKB1( 1BKKoiSBB ( (  (1 9B9919K9 ( 1Kc[iiSS( 11 (BSB[(1ic1 ( ((( (1(KoozzSB919K9  (11KiooziSiuǍ1[KKKBBBBS9(BS[c9(1Buc (  (19Sc[1 (1BSzoiiKB9BSSK9999K1(B[B99BK[K9B BBco9 (9S1 (SSBB11BB1 ((19KcBB1 ((  (11( ([[99BSSS911( (Kccc[K9 (11(( (oiB( B[( ( ( ((1Kicio91119199BB9(BiouzoiouǖBϦ9K91  11(99((9     ( 1( 19KcoB99999K[K1  91(1999SSKB991 Sioo[1 19 9S(   (9919ioK((( B[    1(11(1((Kouc[[K9B((( (S[SK11  1B1(1(1o9 9K  1B( (9(( (1119B[[io[1 1ScSKKB11BizuoiiouǪKu1((     1((9((1cooouoK19BSozzK(1B919B99911((Bi[SK 9B(BK1    ((((9K9  19K(   (( 1991BBKBSiiooi[K1  9KKSK19(91((1B9Bcz[ uo1(co[K1((1KB9( 199B99B[iouS (ci[io[KB9Koozzociİ[uB       B(1 (BSiBKK ( (991Bc[B[999   ((911(9B9SSKS( K[(((  (B[  1( 1KBo(1 ((1(9c[S[[[SK[oicSS91( (BK[K9(1 (9B1(1(B99S (Bzc1z[Sc[KScK9999KSKSSKiuooS(KcSK[cK119[ouuuucoĹo[c (1(     1   9B( (9i9(   1(( SK9K[[c9 KK  (  KiB1 1(BozK1 9B((99Bcozu[SS[[S[ccSBB  ( 111ScK9( 191(BBBSBK[B19iKK[[SicouiSSSBKiocioSSS[iozo99[cK1191 1[ozuuuic’ScB9ScoziK1   ( (1(1( 11     1 (( ( 9KBScc[1  9K  ((ɼi  BSi[ 1BooK999cuiuuiui[[[ccKK[9(  19KSS[SB1  9B11BKKKBK[B 9SczBKSSo[[ioc[SKBuzooc[KKSKcS S[[S99999 9cuuzuiuuociĿ9couucKB9   (((1199(99 (  11    ((  ((((9KB[c[S 99(cǰϦ9  (izBSiocii[oiSi[K[cK1    (BSS[SKKKB(1SB Bci[SKKSB1iziB9Bioiiiuo[999[ooocSKK[[1(Sccc[K[SB19[iozioi[ͳuS[ocS919KB(     11( (((  (  (9B1    11 ( 11( 199SKSK B1  ͹͹S   ѦiizioiucKioiuo[SBBK[(  (S[c[SS[[[KKK[zo[[c[SoziuuB1Kc[c[Si[1(B[iooiSSK[S1 1BiucocS[[9BKSiiuuuoio¢K9KKB19BBBii91B1      91  1(911 (1( (1((( 9 ( B91KBSS9 (( B˹iS1 zݿzSS[SKiccciuS9BKSB  9S[[cicuiioozoS[c[ii[cB1B[oi[[cB 1Si[iziiS[[i[99KSou[cSB[S19BSozzozǒS (9KK9[uc[SB  191  1( 1[SBKB99SKKKS9BBKB(99BB11 K919 9K(9(  KտiSu ( 1( ڭzuiS[i[BcoziS[oi99((  BozioicKSSczzzzc[[S9B[u[BBKBB[uuziKKzoc[ic[S9BKKio[SKBS[K[ciĦcoc9  ( (1B9B9B1     (1(     (  (B[uoocS[SKcoc91B[[S9( 1((  BB[oB199(Kiɷi(9[[ɦczoSKBcKKoci[K[ioSBK   (Bozozic[KKcoii[cuoSicS9SSBB[zoBKKKB[i[u[BSuo[cc[ScBSSS[ccSKS[SBciiiiuuuzzǿoBu[   9B9BB(       (9  (1SzoKKiocicS[iiB1BS[SB9( 9 9i[BB( (͹׿i[(1Kcu˳uzzzcBKB9911 191K919   Bi[[KKooozoccic[iiSi[SzziKKcKBSziSKKBciKozcSczoc[cB91KK[cccS91(1(SB91Koui[ɖBii    (9BB[SSSB ((     (1  BB(19B[oioocc[K9KS9 (KK1o[9K[ҼİSSzB19K้oiSicSSK9     9zzi[Kc[B1S[Sc[S[[[oiKKS[[ioBccioSKBB[uuSSKSiSKzo[[izc[[cKB999KS[[K( (91SK( 1ccc[uϹiKuK   (Kooc[KKBBcc9  1(  (  (( (BKKco[SB99B1 1SK հzKBcɖciͭzKSz[(9SKu1c9iKcuocSB9[c9(   9cuzSB9KS[SK9SBB9B91KK[SB9BS[[cKoz9Ki[SKKczocKSiS[iKK[ui[[SBBKS9ScS1 1KB[[1 (KouiouĖSi  ( ( (9SuSKBB9ScooBBB   1       (Si[ic91  191(c9BS[uooouoozzoiuiB9[o[SccioouoouuzĹǿzuc1˳SBS¼zozͿĭɭoiiic[[[ciozzzoiiuz¿oizzc[[SzzuSScouooSoziozuocizoSSiuKBKSzicooiouzzİzĦ¢zKϒKBSiizռǷªuic[[[[izuouiiu¼z˚[[iu[couuzoiiouozzocizoiciuiSK[icSuo[ozoizzuuİuzĭ’[K[ioo[ccozzĿĹzi[S[couociz˿icuiz[oouoizuzzzuouoouocucSSSczocuuiiiuuuǿzǰǖSSic[uzccSSccioiouǰdzui[cuzzoo¿[[iǰǦuSczuiizziouuiizucKuc[[iziiuzzzzzʼnSoiS[ozociS[oS9iuzɷ¦zzz¹oizɼcouuoucoozuiuoczo[[iucozzzuuǹuioco[[uuiiS[S99SzĭzǼĪzzuuzzzz¹Ƿiiuucuuzicouoiui[uoS[czoSoziSoo[SczoccK(9BKͼɼɳǰķɼzzzzuuzuĿ°·İ͹zcK[cioicuuuBKozuScozuzzicccii[[ioziǿǷzBSuicciuuSccB9B99ɼϷɹiji°ǿzzķĹɪucSciKizzuuzocKKSuzcciiuozuzi[oocccizzzu¹°cKiiiScuuBBB9KS9(S¿·z˰i1oݪ­͹¹ǿuciiKcuzzuzuuicScuociouoicizz[[SuǼѿ[ioooi[SioK((9S[S9(Ͽ¿Ĺzͪ­i(1ooϹĹɪ˪ǿĦzizoo[K[ouozoczui[iuuziou[uuzzciiKBB͹u[zziS[iiS9BKKK91ĹĹǼ͖S–cK999z[žɪ¼ɿĭuzzzzucSizozKScuuiSuzzoiiuou[ouSczɭɹiiuSBBci[[[[SBBuɿ͹¼Ǽ[ooK( ([ScѼDŽzɹzoSS[coɳcKuzzzzu[SKSczziuozuuucuzzccciǿ¹oiK9K[cioicSBBͷ˳oS[B (( (1oS׍ĹĦiSS[KKSoKiizuzKKioS1Bouczoziiuziizizzzuziɿ͹ouS[[c[ccou[ccϿ³iSKK1  (1iuݷļ˷zzucKSSKBB[zi[uzzuuucKB[cc[B[uouiKuziooS[ozzzuuco¦zozzuozocozuiSBBB99 (( (KۄɿļiiSSKKBBScicczuuouzuzuS[uuK9SozSBcuzzzi[uziizozzouuuou¹ijzSouziSKKBBKKKSB  (1BoSϹĦuocSBBSS[ioiouuoiozozocizzic[cuoiSK[uuzuczzcouuzzzo1Kuzzzzѿ¹S[ķzzzĖiu[BBBBSKBBKBBB((((1KuђzSװzɳǷuzuuz[cc[iioozu[ozouociuuc[oucicSKciuzzz[coouuuzuzB(1Biuѹļuušu9iiKKKKBB9KKKKKKK9BKiiךuѰĿo˿uooouoozz[SK99KKKSzzzzzouz[Scoziu[Sco[S[ozzooicouooouoiuzzzzK1911B[zzuҪķ¼iBB999BBBKKS[SKcicܭɒzicKB9Sǹzzo[99(1999KooouziSizoi[SSo[io[KSiocS[iziiui[oiiiizucuuc9999991[zչª¿ɼ³ɿc9B999BKSBBKScܪհ[[cu[1111(19Bi˰oc[ciuo1191(9BBKouiiuucic[uzzoui[uoSKciSBKozcSSicczzoioc[cuzuzozS19BKKB91Sμļ¹zķ˹BB9B99BKSizϳu˚cSKB9oc911(((((9BBKoz9KKK999BKcB1((1BB9([iziizciS[[[izuzzzouuiii[[cK9K[iiuzoiiooouuoicoouuzu[9999BB9BKzѼǪǹǞSKKKSSoiuuªzKSSSKBKioc[c[cioiS11111(1119B9BKKz1(9BB9999KB(((1KBciozozzSS[[cScuzuzuio[cc[SSSKKcozoouoiuuzo[ioiioc9KB9BBBBSϪzĞ[Kcu所iuu[S[[[B9Su[K9BSccoiSS[SBKBBK999BKB91111 19BBSBBo119BB911Bci1 SǷoccoz[9KKKScioouzzzuuoc[SocicSBKiKKcouiccuuooicuzoB999BK9BѿzzzdzoBcuzcB9zĢ˷u’zu[uuǭi9( (1999991(191B9BB91(111 (911KSK(1u91KB991(ci͹uiccoo19BBKKSc[coiozcouuccooi[i[c[ (BcozcozouozKczB99111i˰uu1(9K[zzoSScSBBo°ݞuzɹuiuuiS9( (1([[K99BS911(ciK91  KuSciSB1BzİzuuiiioiB999BBK[iiouuS[uouuiuuic[uo ( (9[ouiizS(BccB99(uҰuz119919Kiz[BBS[SBBoϼڞzzii[B (uuS(( oo[B19oi[occui[ciozoicK99BK[KKSouooiouozuiou[[zo( ((9[zui[oS1((1Suo[9SѹB1((1(19[zooSBKSciKKcԭzz°u[Ko[[[³zu„cuui[[ScoozuzioucBBBBK[SSz[[[ciciuouooiii1(( (( 1Sicioozi(( 1BizuiiҹcS999991(KuuSBcoSKBKioSBc˚u[ouiiiooiouzzzzǷzi[cSScizuo[ccoui[SKKK[iozoKKK[iciuiciuuB   ((1B[iiizB 11 (9SuͦiBB1199(9ioSBBcicKBKco[cݢzo[SSo[[cizzzuoiiiic[coϳzzzuuzzoiiouoouzzo[cozuc[S99KoziSSSciiiiiozu[9(( ( ( 1K[[uiS1 ((((11BoĉĦ[99919B9(iocioc[[cocKBB[cۿc[czc[ooozuooouzzzzҢzicccci[[iuuziuzc[uz[[[KSiiooSKSciiuoozcB1 (( ( ((KuzKS[1( (1(1Biϒzİc99991199ci[[cicSScooiSBzԹcSiuozozoozۭiS[[SS[[[iioiuziiiouuuoozuc[coiS[iKBSozz[Boou[1 ( ( (cuS9SB1(((111BzĿҢco˹i(999B999[z[KKScucSSiuoSoǍ[[Ĺzuuuoiouuzɷ۷o[ocSKScooozSciuzoiiuziczzoKS[izucSS[cuzc11ciooK (11((SccuSKSB91(111iɹɉcuzĒB9B99999[uocoo[[S[oiSScz˖ucczuououĿ¼Ŀҿuiizzuozzǀعcoicciuuzzi[[zzucozzuuzuzzzcKSS[[ozoc[[SKii9( (1S[SKK9( ((1i 9[cSSSKc[1((1[ɷѿĀ[u[1999B9BS[B[oocSScuoc[ozĞo[uzccoioi¼ѳzuioiiij˄coc[couzcccczoozo[ioozuiSKKS[[iziccoc9(((1(9SB(BSB1(( uo9 (1K[S[[KS[9 K˚z˒[(19B9999izuiK[iuucKK[zozݚuio˿ocoic[ooocɷouz˼zzϹizcciozSouzzuiouuzuiiozziiicSSS[cuS (((((1BSKBK[B((oz111( (KSS[[KB[Bբ[c–ǭK(((1999BizouiS[izuiccozicuķcizoiiuzuccuoouuuͿz˿ĿϹo[[iuzc[ouocououuuczzc[ScSBBSSczziB1191((( 1KK[iB[1((( (11BS9BcKKz͖c˿ҹͳi((1199Bizoozc[couocizc[·iiuciiuoiSSozuciicizļǿĒ[[[[ozcSco[czcciizzic[S[KKKKKSSozooB199(( (KiK[S 11((((( 9KB9[zɼϹ¼z1(( (119izzuS[ozcSiuҒǼ[oi[iuiSKBKozzoouoiuuouzzķǹҹ͹[Kcociuzc19cccuu[oz[ccSSKcKKS[ScuiiS1999 9[oz1(1((199( 9K19lj„1((( 111[zS[u[BSiooicci˭ĪɖzKSzuoouziSSBSSizuzooouuioccoicizz¼͖ѦB[zKccK(1[iu[couuziKS[[KcKKKKKuuzzicoB(991( 19[B(1(1(111(((1B[iԼѿǒ9((1( ((Bucccc[S[coziuĪSB[uzciou[[ouoɪzzzzoc[S[cSSS[io˿ǿuǪ҉[zSS919SizoiiccKB[[[SS[Sozuzzuoi[9119 19zS11 (((11((919uzͿѿ͖B ((( (1Koozuo[[cuuc[oz˪u[SzucozĞzzzzzoc[[[SSB9BSScoǿ·cĉɚicK9BK[uuuzuzi[SucKSoocS[ouozzzizuo[B9K99K99991111(11(11uɰ¹ǹ˪S( ( 9ioSKizzoSKiuc[oԷicozuɼzzzuoc[[[[[[SKBSKioǿĿuBiժĚiS[BBKKizuzzouzocz[KS[zuiS[uucouiiuiouicB(1oSBBB91(((199119c˼cҿϷo(  ( (cz[KKSou[BSiz–zuzicuoccouuzzuzoooiicci[KKKBSKKSozļĹcK9[ҞҍKBKBBKScozciooooco[9Szzi[ozzuouzoiiouzoouS[c911BB1111((1(([˹99Bzɿѷz( ( SiciucKKcoiS9KiѰcBKcoocioozzuuoiiozzooouuicii[KKKKBKK[izuǿc[ucĦǒccc[KB9ccuKoiiouzuoiKioouzKcuzooiuozzuz[(9119B19111119KĖK9999cɢuB(  BuoKSuo[KSizu[Siǀ1K[izoi[ciizuuzuoioouzouzzuiccSKSSKSKS[iouz¹ucczi޼z[[[ccSScii9Kic[zocuuoui[oiccuoiiozzo1 (19BB1111(BǪ[19(((9Sļؼ1   9uuc[K[ioiccuzuouі9BiucuoKSciuzzuzuouzzuccizzooouuuoooicSSSSKKKSiuuuzļo[ozuKuѪu[SSzuiooiKSiczo[cccooozoiooizzuzzociizozi[((((((111999Bĭo99111111S˳͞B 1iu[io[SK[iuiiciڰc[uzou[SSS[ciozzuooziooouzuouzooiiiic[S[[S[cioouuz[KozԭoizzicBBzuoc[[cuoouocuuouzzuioozzzuS( (99B9B9SzĦo(9111(19BB[ԼѪ[  ccKKcicS[coui[c۹zzzoziic[[ciiiooc[iiooiozzzocccoooiicSS[ccozzzuǼu[uҿžzucccouzuuzzoccizziuooziziciB 1111BSǢu((((19111119Bz˷c   Siuic[[iocKK[ouo˒zzuoooiioic[ciiccioiozzuzuic[cioioiicc[ccuķKzšo·zui[oiiuuiuccoziccozoooiuzocooi[ccK((((1BİuB11(1(( (199B1K°(  [ciuoiS[coc[S[uԹuzouo[couiiicccccouoioociooooiioooiiuu¹S˼1S¹cuuuiiocii[cuzo[czuiuzoz[[[Sio[[B ( (uǷu1(1(1999(((1919uϪ111( (9ScozzoiSS[i[[uɪzzuiiocoiicicciiccooozzzoioiiuoouooouzi[io¢9cziK[uzuiccouucSouiccizuSSSBiiciS1 S9(1((((( ((9B99uǷK991( 9ouiccooSK[ouѷǚouuzuiiouuoiiicc[couzoouuuoiiu°uicK[zzuzzɭc1Kciu[cozzu[S[ioKBSciiuSBScc[ciiioccK (((1(111((1((Su919(19( 1iuuui[[oui[Sc°zouzzucioccicozǿzz[[iouzi˹zK 1o[uzcSuuzzuziBK[ouSBKKi[[oS1Sciziož[((11((( (((111[oK199( 1((cououucS[ozzuoɢuzuzzoiciuzǷϳzouiS¢Kozc19iuciouociouzuuiSSccK[oiczziic[9KuoouĪo1(1( (111((((Kɚ[(1(((((Bco[couuiciuzzzמiuǹuzzuuu·ռǭzuucS11[ocB(u[ozoououuucScucuKSuoc[iuB1iuoiİu9 (1911(( 11(KzĦo199( ([zzuuoiuzoiiz͖oKoĹɹzuϿ˭ĭzzuzoS119SioB9cɼuioouui[iii[9BouiScuKcuķK( (((1((1(9uu1 1(( (SooiizozuiܭzzҖS[z¿ǿϳzciz¿¿ļѹzzucĿz((((Koc9iiiozooouzziSuucKS[[oi[izoz¼B1(((((111( ( oz9 (111( BooouuiioccuzšϹiKc¼տSiɼ¿¼¼ͳzcz[1111 9izS9z¼uoiuiizzozuouoozuK9SouicuoĖK(((( ((((1(SzziSS11((11(Buo[iooziSSi񼢪o͍K[zĹ³͢BSҷ¹Ϳǹi9 (( (9cu[cocouuoioou[9Koc[oɭc1( (((11((((((BzoSo((((99BozzuccuzocuooՉڰSSuBKǰļ˳¢[i1(91((1(( ([io[uzozcSKSooczijz1((11(((((((11[zۼSҿ9(( (co[izi[ozoiz㰍zzKi1S˷Ŀ³˦ucǰzB(( ( 11(1uu(izoiuciiS[ozǷK  ( (1(((9zԢİijS (KcB9KczociuԳu޳c[o¹¿91c˼˳ѷSuzĪuB1(((((( ((iiB1zuic[[[icS[ɷ1((( ( ((1(uu׹ĚK ¢K9Kioi[cuzɦuǼ؞[co 1KĞԿռi[zzzu[ccB11(( (1  cB(KuoK 1o[zzzcczocu„B(( (((11(9Suo³oziS(BczuiocozuԳɄ[(1[Ǣ˪Ҽz[ozzuoo[S1Ko[9911(11((( S[191Sou[(9zzizzzzuizioĒ9 (((((1 (([dzǭcSu9(BcizczԖzҪٞ[9(Sĭ¼ͭ[SzoouoiB BB9B99B1119( ( Su199(1Kizi19zuoizocªu91( (( ((((11KzɼoozocziiSiuzװoiǰ޷°iu[1BzļɪĪĭǹzuouoou[9ozzzuoiS9((B999(111191(1( 1zB119B999[u99o¿izuzcɳzB (((1((((9o³ucSSuܰ9KizѢ¦ziccBǿ˭ˢ˷¼ǷuuuuoouzzSSzuouiK11991991((11111 11 uB19919BB19[c(BĚ[uuozzɼz[( ( (((1BioijiicBu9BԹķٿo[ScoɹɭԪĪuouzzuoozui9cuuccB9B9199( (((1((91io1( 1919KB991c[19zouªi1(((( 9cio³uzzuzz˒׿ݷu˷uiS[ozciļĿĹ˦ˢzuic[cooBKuuiK( 1B9( ((((((11((B([9 (((((9B9999ScouS coizzĦc9 1(9iuzļKczoii[ozǚ[SKcuɳzuziScicKBuijǼɭϦoB1B9ScSKoz[ (9B1 ( 1 ((19c[K1( ( (99111B999Bc1o¼oozuzǰzz9( (SuɄB[ziSSczoݼͭ؞1KKKBScoiozicii[ioİoBK[ɼǪɿij˰zuoSK91KB119B[c91911 (1((((19Ki[19B91 (11((99BB9o[9czzǰzK S‰zucSSiuuݼռҷcS[SSKKBBKKzuoc[c[coziKSc³¹ǢѿzuiK(19BBBBB9(9SSK1((((   ( (B[oi[B1911911111(199(ouBcu(Bɰuzijuzziijɼɹccozu[KSczzɞϦoSKSKKKKBKuoc[S[S[uSB[iuĹoɭͳoK 1B999999B9BB9K9(11(  9[uocBK1119911(19(9B9SSBK[c(KijzBĭzuɿ¦ˢuc[[cuiKK[ouͭuˢcSKKKKKBSui[SSSSco˷iSiiiuѿocĭzzo9 9BBB9111111919BBB1 (1191B91  SiiicBBB99B99191((199BKKKB9Szi(Ŀ͹uzļɢuzĭoiiic[cuuo[KKzԿ’oɉ9KBKKKSoi[[SSSczªiBScoozSic 1SK1(((1BB1(((111((((1111SSSB11SuoSS[9BBB9B99919(((9Kz91B9919Sɷĭz͢oiuuSKcuoci[iuBSo׼ѼucoҼBBBBB9Szzi[[cccoİ[Sccoiiu[[1 19111((111((19991( (111B[[K9Kzccc9BKBBB9999991 SK(1119991KcˢoİѰzccozuuɉ9B[izu[[zizչɦcSuu1KKKBSoi[Scoozoooizo[o(111(1911BB999919911911(1(((19BK[iic(19KKB9991991Buc((1((1999BBcɚzuzļͷuS[ozzouuuɒKBcuu[[[uo[oչ¼ĢcSljBB999[ucS[iuzoSoi 19(19BBKSKKBBBBBB91(1(((1(( (KSBozioo(11BKKB999119o[( (11(999999KSoѿɪozǹuu[uouiiizc¦uSSiooizoo­ɿϞǀKzKBBKKooc[iioccļS99(19BKS[KKSKKKK[KB99(( (9S[SK[cSScc (199KKB9911So( 1(1((991(B99Bcu˳zzzɿizSizuouio[oİz[ccoiiuzz¼ϿuuˢizB99BBucccizoi͹zcB((9KS[[SBKKS[cc[KK99B99B9Sc[KB9BKBK[i( (1(1KKBBBSzu (((( 1911(9199[զo˼uuĖcooouzzooozcocuɳuB9ocSci[u¿ѰzKB[u˳z1BKKSziiciui¿zzzoiS1 19S[KS[Sc[S[[KKKKKKB[[[ccSSBK[[[[[ ( (((9KKK[zu9((1(((( (1B11cϳԭzo¿c͚uuiozzuouzioucic͹Kioo[czSKiͪSo[BBKo¢€9KKBSouo[cuzz¿Ē[uuziiccc[K99B999B9BKSSSSKKKSSKSuo[ccSSKSiuuoc((  (9BcK ((1((((1111Kuš˒Ϧuuuzocouiiouicoužo9Szucouzzɳ[[³iSKS[ͪS[[S[coiioz¿ɰ[9iSB9BBioc[[[K19191919((9919KS[KBcucS[SKScic[S[c (((( (9ui9((((1( (11KuԹuuǭzܪzuuozuocuouooi[iiozͰ[9Suz[[iuoSĭcBKKSc¹Ǣiciiioioooo³¦zB9i[(911119coc[K99B11(91B1111(( 1119oo[[[BBKoo[SS[i ((( 9uiK99( (((1( Bz[[SBoҷu߰zuzzoicuo[zioSoiooiuuչo9KuzK9[o[c¦iiҰiSKS[[ijoouzzuoiɿ°ǹoB999zi(1911119czc( 9B1((199911111(1 (KicSKK9ScuoKBBK[ (Si119SK9 ( ( ˿S9KBKc͞ioi[oo[oi[KKciuSoz„BKcu[[uoSɭouհ¢zSS[Kiɉiozzzicc[i[ͼķĹɼzoo[KBSKBBBczK99991( (19[K 1K9111911999991( 1Scc[991Kco[BBKKS 1i[1(9KKKBB(((((([ĞoBSi[1Soilj( o͢uiiuciucKKiiuiSozǒ[KizziiѼooۭzc[Kiouշocoo[BBBB9Soicķuioz³Ŀzic[9(1KKBBBB99SK9( (919911((1( (1911111111(111BS[[K(19B[cS9(1BK (  [[((BBBS[K ( Sˢc9Kcuu[KKSSªK u۹ziic[uzucK[iiccoucѪi[uucuzoz᭭i[KcoSuSSK99B99(1K[iii[o[KKKKcuicc[SSSS9( 19191 19BKu1(1111191(9991((( ((1111191(99BKKS[B(111KKB91BKS(((K[1  (1BBSSSK9Kͳu9Sc[coo[KSScc(9ڼoiiSoucSKciSKciouiciҰocoSzioɉzপic[ciiScoKKB99BB911BS[[[[cuiB9B919SozuS[SBKK[[[SKKKB99(( 99KSB19999BKoK (( 1119B11(( (11111((( 1199BKcKK[cB1(1BBSB1(9KS( (1[o9  ((99KKiuB’cBBS[Sc[ScSBSKcoB–iioS[ccccSB9K[iiozoiiiuz„[o°z͢cުĖzcoc[iooͪBBBBBKBB9BBB[[S[[S[ccccoB( 11(99 (9KBK9B9  ( (91KK99SKBB9BKSB(1111119999(1111(19911(199119KSSKSizS111B[cSB9KKS( 1iS ((( (1KK[ouušu[KBKKS[cK9BSoizѢo[oiizi[izo91KKczooic[[iiioĖuzĭǿzఢšiucccuiKSKBBKKB9S[S[[[SSKKSK[icS1   BB11(   ((KB9BKB11BKB9911(((11B999199(((19991(999BBKSKS[cuoK (1B[[SBBKu (Szi (  ((9K[SuĢouiccSBKo[iiK999[coķozucooizziSKic99BK[uziicS[SiozϰĦϢz෢ozzicoϚ(KKKKSc[SKScSS[SSKSKSKSccioK(   9B   K9KKBB999B9(991191911(1111911(((11919KS[SKSSS[izo9 (BKSSKBKi(Buc1((((  (9SzĞ[K9[icB9BoSKScic9(BS[Suuuzo[ozuiKBcici[BKcic[[cccozѹuzz„عccc(Scc[ciicSScic[KKKSKSKKS[cuiSK(      9KK(19B9BB99B1((9BKKKBB991((( ((199BSSS[[ci[SiuiB(1SSKSKBSou1ioB( ((  (SǢzi1(9SiS99BKK9S[cS((K[S9Szz[iuzouoioz[co[cioiS[i[Kizzu׿ouɪžɷio9K[ccoui[SSKS[[KKSSKSKKSKSS[[B1      1B99BKKB9999BBBKKKSSSKKBKBB91( (19KSSKSccc[[ozcB19KKK[[KKK9iu91(1 ((( ( 1˦i[iiSKBKSSSKKSKKSScoK((ci9BuizzoooououcoiozzocSScSKoucizĖccuǚšɼ­c˼ziiciooic[KKB[iKBBKKKKKKKK[[SS(       ( 1999BBKBBKKB9BBKS[[[SSK9((11 1BKKSKKcic[iuuc99BKS[SSK1SB 911 (  1((((9zǹi[SS[c[B1KiSK[S[[BBK[SKuz(Bzzuizouuo[c[ciuuccSSKKKcu[[uͪz[ou[iͷͳzͦגoioouuo[[KB9KiSBKBKKBKBBKS[[S1     B1((19199999BKBBKBBKSSSKB(((1KSS[SKKSS[ozocBB9BSSSSK B[ (99((((( (1 uɼzSuo[SSuoiBBS[KK[ccSB9Kczzozz19uzoiozzc[iiiii[cKBKBSSoi[uѭzuSBuǭİiϰ͖cooi[SBKBBBBK[S9BBKBKKKKKKSSSB    911((((199911(9999KBB999BBB9991(19SSKSSSSS[iiiiS9BBBSS[S1BK( 111(((( (9iͼ11[zoicoooK9K[ii[S[KBKKczcci11uiccuicciiiocccKSBKS[uoz‰[BozoucccSB991999BK[[KKKSBKSKKKSS[S9   (9911(111((191(9999BB1(119KKBB1B[KScc[[SSK99KSSKB999BBKS19SK1(111991(((cĦiB1(izcSicK9[cSSBBB1[ci[Scuuo[9cucii[ciiiooocKS[KKS[iuzouiϼiziǹzizuco˚[K[[KBKBB9KSci[KKKSKSSSKKKKK(     (1(((11(111(1111(1199B91(((199K[uc[[KS[[[9(1BK9(( 19KK[91iu[[S9(1((11(( SĞuouS1oo[cuiK[[BSKBSSuz1K[ccSoǿouocc[[S[ooo[cci[SSK[zozczuozɢĹccizucccѭ[K[c[KKKKK[iooiSSSSSKKSKK[[S9  ((1((1((1((111(191919991(((1111[oo[[cSSc[[K1[zoozzS9BK[S9zcSS[KSS9((199B9KĭuK[ioKKzuioocu[1Siuuu(B[KSiiǰooSi[ccicciccucc[iSc[ozzouzoozɪi[[ii[[[ԷcBK91(1KSS[ioicS[[S[[[[SKKKKK1    9111191191(111(11((19991(1(((1Bciccc[KKSSSBKzui[[KcKB[9[c[SB((119S˭[99Bcu[KcuicKiS Bu„199Biziiuc[i[SSiSiocuozi[i[ucocozzizu˰[[ǹuS[ci[SBϞK111119SS[[iiccSSii[[S[SKKKSS9  1911119BBB91191911((((1( 11119K[cS[[SKK[[B1ciSocSio[[Sc9io[[S99 1uͳiuiK9Sci[SSS[ouc1 KK 9u’SBKcuuu[u[SB1ScizouzuuuczouuzizzzzczͳK[Ī[[[[SB1KBB999SScoici[SKK[ucSc[KBSKBKK(   9999111119BBKKB191111((( ((119SK[S[SKKBBKK9uS9BBBKuuSBScciK9Biici[(1uKKcoiS9B[iiS99ooS(19(cčB1Sioz³B(9[[[ooiuuczuioicuooozͭžcSSS[KBuS[SKKSc[cuocc[SSKSooc[[SSSSSKK1 (1((1((11BBBBBBBB99911(11( ((11BSB991BKSKSSSKKzo119KB1BoKK9KicSzc11B[oo[išoKBKSciK99SouS9couoS11Su˞[B[oc[uzuͪuBSSKKKSczziuiouuicuiuɹco˷iSKKSKKocKBK[iiuuoic[KB9Koo[[cc[BBKK1    (( (1111119B9BKKKKKB9(((11((1(9KcS (1 BKKK[S[BSc1BKK91Kuuc[K[KKSSK[1 So[uɿiSccK99ciS19Kuo91[uzoSKoǢuzo[[Siii͹zzcK9cuiuouuzuuziiuoiiioouɷocϿzSSKKKK[ϢK9SiuouuuoocSBBK[iuucciicSKSK( (11( (11991119BKSKKSSK919BB1((1BSS9BozSBKKKSB1i1BScKBBKSK9iSScKBBBi91[zɞi99SooS9BBi[B1uzoSKKSiz[zɼzo[[SSiiizBuzzc[uuuoouuzzuiccuzzziooiozҷǚ[[SKBKSϭ(BcoouuzicBBKSciouuoc[[[SBK1 (((1(((1119111199BKKKKKKBBScK9(1BKB99oB9KKSS991BKKK919[[B9K[SBSiuK1cѹoSB9BciSBB[iiK[oc9BBczocu[oc[ucKzzBS[uo[ciouozuSBSozzuuouuoϪoBBKKKS˚1[coiuzuzuiiBBK[icioiic[S[K9S1    1911((1((9BB999119999BK[[[cci[9BKKBB9KzuiB9KK[K9i9Sci[119KK1B9SBBKic[͚SSi[BBKSc[9BSci[Szoo[uozzioiSS[czzS[ouzzucBKciooooouozzzzҼo[˚S9KKBco9iiiioiiu[9K[cioooicc[SSBSK     ((1111((1(9999999999B1BKKKS[SciKSKB1911[ccK9B9B91oKciuiK11BK1zo9[[B9[uo(1ScS9(BSicB19[o[[uizuzSKcSuoziizzcKKciiczuozzoScњu¼KKB1o[[oouuc[couiKS[ciciiooc[SSSS[     1911 (1(1999991((119BKSKBKKSSK[BBBB1(9KK[KKBB(KccoziK91K[B[iiBK[ucuK 1BK9(1B[SB(1Si[B9Kzuzz[ScSBiicziBBcoiizicu[9Bcu˪zɦSB91ĒB[iicSizcBScciciuoi[S[c[S9   ( ((1(( ((11999991111(199BB9BBKBBKKB99B((BBSB9B9(ozuuzcKBBKS9io[ccioɭc991S 9K91 (Ko[91B[[9[zzzziooSKcSBKoi[uuo[K[iicizoouozzcSKKicǖKKB͹ǭoccciooic[iccciS      11111 (((999911(1111919(11(1BBBKBKS1 B9BKBB(1z[coiiKB99K19zccczzS[oSKSccBKSBKSKKK99K[cc[SSooScoiS[SS[SS1(9BoSSco¦zuiB111BSioK 191czuu·ɿcic[icSSB9SϭSKB11(((1[uooBBKu˹[1Ҫ (B[oc[SSBK[[SuɭcK9cz[[co¿Ĺɹi9oɼB1BiעljKKB9( zoo[SK[uiSK91KK9B99911919SSSKB[uKS[BS9coK[Sui1(SKKҰizzS9111( 19(1BB99ououu޳oS[SSzc[SBKɄ( ((111KuoociىKBiɷiz’ (1S[u[B9SKBSSSKiɢB 9iuKScu˿³ij[ 9K (S¢KBB1 z[BK9[o[9((( ( ( (((11BSKBKB9zKBK9BzKioBKSļc9Ī9cĞzozK(1(( ((((191((KzzuiciKcicS91ѭ9 9BKBKiuzocߞ1c³o(1(9zuzoS91K[S[[BBKScu˦K1Ku[9BcuɹܿiS([K( zܞz[B99(((111zS19BciS91( 1((  (1((9BBKBBBKBco[B99[oSKK׳uװzzoozK(( ( (1111((1ioiuzuoiScuicB1KĄ9Kii[SzoS[Bi[B(SҷB ((KԷu[KB9Sc[SK111(19[ͭ[BKcucBKiu͹ڪ[99u( oٳSKB199((19Bc11BizSB1111(  (((1BKKKBBBBBcoS9BSKBK¹ɹuzzzozzS( ((((11((11((Kuzo׍KSzzocS9(cҷcScSKS[S1([99˭Ǟ( iªcKKKSciK111(119i˦[KS[zz[ScoѼz͍zzS9ouB [ǖuBS[K911 (9B[91[[9(111911(1( ((1( 9KKSSK99BBK[ozcK9BSSBcļɹuzioiB1((19( (1111 (19[cizٰzi[SS9KˍSKBSocB1c1(1¢Җ 9zͰS1BBKScK991991cĄ(Buczzo[cɳccǼǒՖoccKcB(Buڄ1BBBK[BB9((91S99zB1B91199B11911(9SizoSSccKKSK[cuzui[[z­ic¿ҹuoui9(((11B919((1BB91[uzic[SBBԦ[B[ouz[91 ((19Ұzі B[oK((19SSSKS[K[ii9Kucozco˿c1oioԼɰšcSKS 1SSu׉KKBBK[SB1(19Bz9(ooK[oc[c[SKKKB9[͹o[Scz¼ѼŰucc1(1(( 1 (1 119((1cicےzzSB9zѼu[occzuK(9[cuB9KϭB(Soiuzc( 1SSKKKK[cBo BciuzS(Sz[9cѷcc[BBuc[[ciu٪B9SK9Si[9(1B9zz(Bžcou[[SS˰[oļ¿uSK (((((1(( (Kioiizocu꿀uKBBcͪucBKc9SiiKicKcњSSc[iio9(BKK[[ScoB9z(9czzzi 9io(9uܷc9BK((Bzzi[zժKBKB11u[BS[[ooiѰķSSĢļiB99BSci[BBBKKB911((((    9K[[KKozooՒocSKBoͳu1[zBBicB19܉S¢oi[cB1K[c[SizicKz( [ 1ou[cҖ9SoS1cuz[Ki–K9KK9(ccccS[ĪտϹǼωBBScK1 1( (((199(((((11  9KK[KB9BBcoucSSKKϞcoo[[[91(1oɍ[[i¼zBK[S[Sio[SK[B9cuczܭKuiiuz9[[S11Bo(9KKS[·ccci[ǭԿտ¢BKSSSB1 ( 1111(((((  1BKB91199BBB[ع[[[KKcuͳS91(( SǖoS[ļziKSKBSic[c[c19Kz٦SB  (1o(199Sπcicic˿­o[Si[1BK9BKB1( (1((((11( (( (KK99S[cciicB9BSocc[[iuɹS(((  oBKܼccͼcS[[Sco[ScS[B99ϹͰK(  (1o1B91SuSc[ciɼdzDŽB999KSKSB(1BS[cS1(   1111  (SiB9BiiuuiSc[޹o[c[[oҷ[(( (cSBKBѭzǞKoKKSicS[i[BB9uzSuѷS(( (((1uo 11Bu9KK[cĢoouzciuuoioioi[coҚS999B9S[9( 1Scci[K9 ( ((( (( (( 1[i[9BSic[ciiuoouעoc[[izԉ (( (S‰[BKBiۼž[oKBSocS[[[B[cKBziBzz˦9 ( (9SiK1BKz1BBS[ϭSBciicSKKcuucc[BKB[oڷoK9KSBSS1 191BicB((( (1111((((((9cucBBKS[K9BBB[эuciozؒ1(  u[BBK·ScBB[oi[SSS9iiSBuSKzoio¹Ͱi 1o[BK[cKBKKϰziz[BKB119BK[uiK99KS9KBBSiڷ[SSSoo[B199KKB19B91((((((1((((1BBKcuiKBS[ou[B991BݹzzzښB9B91 (cSzSBBiɖu1BBii[SSS[KSu1€KKz[izz[ɪ¼žS(SooiKczѰoiSҳziooSB9K91KK[cK999BBKB9999BBBBS–BK[Boc19cuoc[K991((  111( (1B[iii[SS[ciouiKKBBSئui9KB91 KSB[zoSK[ҍzc1(KoiSSK[c[czcKBouuuzoտ’S( [SciozoϢuѿucuiSK99B1119KKKKBKKBKBB9BB99999K[BSzoSSS[[cS9Kocc[c[K1(111 (  (B[ocScSS[coiioiciucSzђoτ (9(([9B9SozzڢuS99SuKKBK[ScuiKzizuoizĚђB(1[cBiuSտi°[[oĞzicccSSc[[SB9B91199BB991Sc[[SSK9911199B919919K[ozzicK1 (BSKB991 ( (( (1Kc[KSSS[cizzoooouoܼzٚ  ( SčKKB91BSuܚoB9o[Ku[[SKKKSzouiiuі[91 (u[[zcªooiϿҭ[S[K999999K[KKB1((19BBBBBSicSK[SBBBBKK911(11(1KK[uuzuzK( (11991(11 Bii[KS[Sc[couuuzzעS  ( (–BKKB999B[uuKKKiuo[z[SKKSKSizcoi[zDŽ9 ((KicccuocuuziocKSSB9BBB999BK911(19999B9BSc[KKKB919KKK[K9(11( 9(BS[SKKcuS9(((111 ( ( (iuSBSc[ouuocccͼc (( BoBSKB999BScSSizՀiuzzSo[S[SSKK[iciic[cڷu91911[B[ocuziuoc[cizouooBSSKB9BB9B99BBB9(( (((1BBBK[SKKB9999BBBKou9(BBB9B ( 1B1999911191( 9c[B[oucucz˹Ϲc(  (oSKSKKKBBBS[SBB99Kᷭ­ozco[KKBBScSzuSžicS¼Ս9B9111(SBKKB[cSz919B[zuicS99B1119BBBBB991191111111KBBK[KBBB11119BB[uuK(9B199 ((9[c[S991((( 1KKB9S[cczo߹u1911 1zBKSKKKB91BS[[B119Kͷcciuic9KBKKKKzicئ[zuB9911(11[SK9S[Sc1K[[ouozuiK99111111199BB999B991( ((((BKS[K91((1(19KKKccKBB9K9(((   19KK9911(( 1BcBBKcSS[zzݰަ[9991 (((1uz1B99BKB9BBKS[K99KKc߳K1B[ooK[[KB99oĪ[͢ѭ11uڢK1111(11BiSK9KocicBKciioccK999111 (111BB91191111((((BSSKBB911( ((9K[o[BBSSB9( 1(    (((( (1KcBBScSScuzբύK991111(1B9u9BKKKBB9KSKS[KBKKBKۚ11Bcoi[KBKK1SўBў( K[ (199B91i[KB9Ki[S91(9B[zioucBcK1199111(((1(((111111((1((B[cccK991111119BKS[KBK[cB(((( 1BBK[SB(  111((((9SS99S[KS[iuoBzўע[991 1( 9S[oKBKBBKKKS[[[cKSccSBBi9KoooK11KKB1B˰[KҒ9KiBcǪK(11119(9uSKBBKc[(  1[uci[[SB(cB1911111( 11((111(1( (19[zzzoK9911199BBKKKKSSSKBB( (1119KccouB((19(((((BBc[B9K9199B[S((SڹzSS9BBB1B99B[[[cKKBBSSKS[[[SBKS[c[K9S(SzoK[u[KSSK919Boϳo1 9SBK[[K99BSiooK (1191 1iBKSSS[K( (9Kiuic[B91(1[911199911(1111(11199(((19[zuSB91((9KKBBBBK[SKBBBB( (( 9KS[iuzc11BB9111KS[[KSKB9B119  (9iܹzSB919B99199B[ccuuSKSSS[SSSKSB9BBSuKSՖ KiB1SzSc[[SBBi1ҭ1119KB9B999  ((( KKBKKKKK9 9iiizu[[S11199cSKBB9991111((11(1191(9SuuzuiS11(9KBBBKSSSSB99999991  (9KB1BuiB19B119Siu[SBBBB999(((((1[מcS99111(191(9KS[ci[SKKK[SSScSBBBKoz[KڳSSucK [zzuiSB(ž؀BB[c( (((((  (    1ocB[SKKKB9(9ii[ou[SK91191zcizzcSKB991(119B911( 9uzu[KBSSSKSKSSSB911(9[K( (11(  ( (1BKKKS[oooi[S99999Kic[[ScǼo991BB99( ((9K[[cSi[91KSSSSSKBBBKcz[[cϳo(Bui[K(uzucK1i˿11ic(   (1((9K[ozBK[KBKK9B9Ki[K[[B199((( uooiB99B9BBKK9((1B[uSKBBKSSSKB9911 (KK11 (( (1((BKS[[KB9KzozuiSS[[cuoiԷټB1((1911 (999K[[ccczcKSSKKKSKB99B[SS[o˼oB(9iS[SB9zoucK9[Լoic1 (11 SڹK9KK9B9B9BB[cKKSB9 (1ocoi[9BBBcociiuouzouiSBBBS[K9111 (((911 ( (1BBco[KBKB9( 9cKKcuoccuoo¦˪SB[9( (19(((((BBSouzuoc[SKBBBK99BKSSScu9 9KSKB9SzoiiS9Kռdz[1(  (1( i°zǪozKKKBKSB9K999((( 9cccuicczuuccuzuzooi[cuuouuiK1B[[SK91  9B1 S9 (((1S[[B99KSB11cSBBBBK[[ccoˢҿ91[9((((911999BBczcoi[cSccSSBBKSS[S[z(1[oKcK11oic[KKcˀzoK11119(( (19B1u°[1SooiSK9((191((( (([u[czcS[uouzzocioizziuzuoccouzzcSSSSK11(  9B91(K[9((( (1 19999( 9uziSBBB99919uԭɢB 19BB1111199(9SoSSSccKiuiSS[i[[Sc­o91ozooicK1uSSS[͍uc9111(11([ziiczzzK1 Buuu911(BS911   1ciuziuzoozcS[[[iiuccouo[iciiozoSSS1(1BKB91BBBB9 (((((1999((Szou[BBBBBB9B[cK[ͰѭSBK[S91(((191(Bozu[cKKS[coicc[[[c۰cSSz[KB1ucSSؼ[11(191((iuuzcK9( czo[iouS (1(19((( Bzczuouuc[SSoouuuozz[S[SciooooSB( (((9999( 111B[B( (1999991(So[cocSK99B9((1( 119[ɼuScҳiooSBKKB91((((Souzĉ[oSSKK[c[[[[SuǷSSoĹo[KuuiczĪz1(11( 1ucSS[ªz[9 1SiiccicBB( 111919119BKB[oBzoozz[99[uuzzuS[izuS[iuoiiiuiBKic[K9B9(11((BKB9(11(911(1oSKiuK(11( 11((19S[[uiS[˖i[9(9KBB9(1(Bcccuuٿu[SSS[[[S99ޒiSočoSi͢ziiؿ[( (((SǪzc[SB99iz¼cK(SiKizoi[B(1c[SKKSKBBBBBSi[BiiiouiB1coui[cccBcuzziooouou[[[B1B9((99B1(  (11Soc[ciuiK9(( (((  9119B[iuuziuzz՞9BS[u[BB9oz׳iSSSS[ioS9ozBuĒiѷioǰB1(911Sɢuii[B1 1KcǞc91(ooKozuui9(Si[[SKB1  (9Suu[KzcSB9SzzouuoozzocSSSc[oziooiuzzuizuiuziSKB((9( (1B[B91(1oooizocccocB1(( (191BB[[ouuooiSBKcuui׼i[uͷiju[KKBB[ioicuz9[oڼ͹ĭ[91119SĚuc[B((((BižoB (S[SiiiS1K[911(( ((((1BScc[[iB19Kiic[BBiuzzcSc[SBKziiouoccuuooiciiic[K9B1  (KSSScoiiuouoc[icSK11(BS[KK[zziKB99(199BKBcԦǿѷozc[KBKS[i跞K9c¹Ұ99B91cuoS( (((9iuK(( BSoSSS91KB1 91(( (  B[iicc[c991KuzK999[zuzcSBB[uzuzuiciooouuiiouuiKS9 ( (1(Buzuci[S[SoiS91[[SKKcicK1 ((9BKB9KҳocSiզcczucSK[[[ϼui߿ĹϒB991SѦioi1 1B9Su[9 1SiiK9 9KB ((( 1(9K[[[[[ccS99BzcB9K[zuoo[B9iizuzoiiiiozzicicozuo[K1((couS[cKSicBBc[B9BB991 (((1BK[c[[Գo[[uՖS[ouiiiicc[SװijˉK99BѰuocB((BSSKcuc1 KouozK1KS1 (( 1SiicSc[ci[u[99SuKKK[izzo[9 9o[[io[[uzoc[SiuzuuccSScuz[B9BizciuuzozKK[SKBB9B1111( 1KcouoicѪzoioizҒ[Souoouoi[Kcܪuzπ119uļuK(9B9119SҍB9czuozSKB(1cuuic[S[ciciS99Ki[9K[Scouzou[(1(SuuzĒcSKSKKiiozi[[iociic[SSS[zucoozzcSSoiSK91 ( ( 9[iuzucɹuoҢic[Scoouuo[Ϣɳ[1cˍccS1199(1c[ɳocuuiico[ziS9  1ioccio[[iic[SSScuuciiouocuo1(czi919oiBK[iciic[SKBBKizzSuo[oziiiSKS[cuui[SS11((  ( Suo[[ɹzټ˷icSK[c[ouɪɦK 1c[KB((  9BcozciBK[S1(   (czucciocSKccccSS[uzzz[[ioic9ooiui[zSSSS[i[BKKBKSS[[oozˍKiSKiiBKK[[((B[ciSB1( 19BizocccSizԪuzo׷׍[KBBKBi།عS c[K ((((9KcoioooSSSK9    Bcocciicoc[[SS[ucSBBKKBKuoKKciuoouio¼ozuccoziK( 1919B[i[ziB[KcS199(1BB(9BK[uo[[c[B9iiuuz˒oc–ۢoc[SK9Ğɪɷճouc[B((( ( 9SouoK[c9  (( 9ciSS[icciKSS[KouocK1((B(SicS9BK9ScSciou˒[ciK  (9KS[cccoziK1BS[S111(1B9 (19BSi[[cioocozzuzܼz͹i՚zi[zמoˢǼϭu[B991(199Bizzz€KB ((   1[uiSKScciicc[c[izuu[911B9S[zSB99BBK[BBKK[ozҳiSSoc (19BKK[iScc9(9cK[[SB919B1 (1999KS[i[iiSzzuicizݰǚiSSҳ෉Լ¿¢ziSB11B9BBB[izzuioc9  ((  1[ic[ciiiicic[[iizic[[ciiiiK[K1BSS9911(ciKzǦK19KKK  99BBBS[ScK (KSS[SKBK[S1((1(19Ku[[cBiSKSK9KuѰSSSoɦuzԢĿٿc[[K9 1(9BSouozuoi[z9  (  1ii[[ccS[cSKS[ccScS[[[[BB[B(1(B[S9K9B1SK iB  (11BKBScc[Soo1 (9cocc[[S[SB119111BKiucii[cdzuuSBBB99[ˢcc[’[cɿۿ¹͹KBB91199199cozuououo[zu  (((( (91 1ioSScc[[[S99K[SS[SSSKKBB911((199119[9B9 oB  (1KKSKuoS[uuK 1KKBoSS[[[[K911 (9K[ciucozz1BBBBBKcɿ¼ڹi99KגKBĹͼ˼ҷB9B9191B99SiuuzoiS[[S[S  (1KSKKKBBB1(919uu[cccSKS[SSS[[Szoi[[9KKBBS[[K9B991 (19111 9K9iu[K19 1KcicKSuz[9uuK( 9B99oucicSKSK9((1111BSciuzo[S[uoi[KKcɰզɄ(9BSoSǷͳɷђc1999991B99BKB[oiiS9BSB11 (  1BBKSKBBB(119oi[ici[S[[KSKKc[icoi[S[[K c[[[[9911KB911111191((1KBoioKScouKBciS9KoK( 1B911SiSSi[KK[KB91 (11K[izoic[SBBiz[uݹϚoiiu¹ҹǹɷK1(9B9(( (1(99S[BB9BSB1 (   1KK91(( (Buo[c[[[[[[[SSK[oc19SK[cSSucic[B19BK9(( ((91991111c[ϢSSzuiioooi[cu[1BK1 ( 99((9SiSccKKBB991((119Koccio[[KBSciuiǿަuuɉzԼĭ·B(( ( (11 ((( BKKBSBB(  (((  ( Szoii[[[[SSKKS[[oB(99BcS9cķc[[SBBB1K991(( (1 (1119B[KS¹[BKK[iuoK9BSKK1((( (((11 (KuocSSSSKKKB  1KuuouoKKSKScioozzɳ˭oKհozԿռĭǦucSBKKKSSKB9KKSSKKK1(1991(   ((19(  (izuic[[ccccc[[[K[ (11111BBS„SSBBBBBB9B1((1((( ( ((111 [1K1BBKSK1(  ((991(( (Soi[SSSKBKSK1( ((BozoicKKSSSc[iouuɷĪҿoԒiuɪĄi˿oS[B9[uozzziS[S9111( 11911 (((11BB9(  ( (ioicccciiS[cii[SS((((1991u˹[KK99KB1(1B119BKK919((99((oc91B19911(  ( 1(((B[SSSSKBBKBSSB( (Kooc[[[BKS[iuziuuuϿ­˪ĚњziϷ¿°i9cu[KSS9( 9[SB19BK1(11( ((  (1 (((9BBBK9(  (1[ooic[[[SS[cic[SK1((1(9BKɍSK9919[B191ScK[KBSSSSB9B1 ccB(19111(( (   ( ( ( (BS[ccSKBBB9KKK1 (19ic[[oiSSSSSii[ozĹǪzɳ’zuzɳǷc1Szu1((9KB1991111(1B19(1((1(  ((19BKBBB91((9Kiuociicii[SSSKSKSSK 199Scİc9B9KSBB991BouK1((1(((1( (ic9(119911(  ((( ( 1KSSK9BBSKKKKSS9((1(1[c[icSBKKKKcc[ooļϼ⚉ķ˭uzzͼ·͖oouoccSzc( (19KBB111111(99B19(((((( (( 11BKB99911Kcuzoicc[[c[S[KBBBKB9( 1B[KS[1KBBK11BKS[[B(11( (((( K[1(11(111( ((  (((1( (9BKB9BKKKKKBBBK999919Si[cSSBBBBK[[iouzļͿښطĪzoļǼ‰9 19B[[BoS(((1BKS9((111999991191(((1((1( 1199BB9((1SizzooiiccccicS9B9(9KSS( ((Kci9oK9SKBKKSK9KK1(BB1111B9(([S1(((( (1((( 11( (  9KKKBBKKSKB999BB11KKBK[uicciKB9BKKiioz[oɿǷܞ˦uuǢԪuB111BBSSB[oB1 Bci[91((111919999( 1991BB1 ( 19B1BBB9B[uouicio[[ci[ccc[SS9(919B1((BSSSBoSKS9BK9BBBSK( 199K[co[ (c[1 (191(((((( (191( ( ( (9B99KcccSBB99BBBBS[ScizozuiSBB9KSiuKuԖz˿[z˳ĄK9((9izo[9[c99((1SiiK9111999B((991 (119991(1911BBB9(1Bouo[[SKK[[SSccccic[KK9BBKB BcS[K[zcKBKKSS9111B9 (BKKBScK((ic9 ((99(((((( ((11((((( (  1991KBSKSBKKKBBKB9B[iiizzzuuuSBB99[cBiަuϢoi͍B19999S99ii91((9KKSK91((19B9((11((( (1BBKB91999( 9cuiSKKBBK[i[S[cc[cccccSSKSB1iiS[9oi[[S91BB99SScB ((  Bui9 (1((11( 1911(( (( (( (1111B[SSSKBKB999991Bco[ouciS91(1Kzocc޼uu՚oђKKcouizo1iuK9((9919B91((1111 (1( (1BKB19BKB( Bozc[[[K1([c[[[cooic[ccc[[K99(SoicKSKKSB(1BK99[KK (9BBiK11((((((1( ((((11 (((((((  1999BBKKSKBKK9B9111(9[uuzoBBSSB119BouoiuђzͪzuҿڦoouuocK[(c[9((91((1991  (911KB( (11B9BKKSB1Bo[[[[K(9i[BS[[cooiiiicc[B11[ocSS1coKBB9111BBB9  (Bcozucoz[91(((11991((( 1(((( ((((( (1(199BKB99BB999B91119KzuzcB9K[K19BKiuo[Sc[zٷϭ˿ۚi[SKK[BSۼKzKB199( (11(19(1BB9  (1BKSKBBuui[SS[B(ScB9Kccioocc[SK[cc[SucSS1ziB9BB9BBBK( (1BcccccK19KSc[BB1((11(111(( (1 ( (  ((9BKSSBBB9119BB91999BioiB9K[[SS[ci[[KBu[SK[uؼͿǀ[SKB9991ܹuK11( (1((9(B9( (( (((19((ciicSSB( B[11SoiiiccccSBBcoc[zc[SBKuSKBB99BBB1 9[K9( (1( (11KccK1111911191(( (((( (((( (KSKSSKKK9(1B9919B9BBB9BScciuc91BSciioooiS99[cSS[u˳ǿ¿ɄS19BB19B[iǿuB1 (9119B((1Koc9((( 991   icic[SS9(Sc11[i[ccKS[c[KBScic[KS[SoB9B999BBBK cS1(  ((19K[KB9111((199((111( 11(1(  (( (Bc[SS[SSSKBKSK19999BKB911B9KSK99SiuuiiioiB1BSiic[iİ˼ɹ˳oKKKKBKScucz°c((9BBKBKcB91BuuiB  99((( ((ou[[SKK9(1[S(1[cSSK1B[oo[KK[c[SBKK[uu9BKB[SSK1 (KS((1( (((199[SK999B9111(((19911191((( (11 (Kc[cc[[[c[SSK99BKBKSK9(1BKKBBBBK[izoccic1(99Bc[cz˼˹ĪiB9BK[[[i[KSKcǪB(91(19BcooicK91 199KB (19Szzc[SB999(9[K19S[SS[SS[iuic[SSScSKKSi9BBBSSKB9S[( (91(( (( (9KSKB911((((91111(11119991((11(Kc[[[[KKKKKKKB99BBBBB999KS[[KB91KicuzoiccK91BB99zcoz˹ɿķªo[BKKKKSKBKB[[19i(( 9cococB1  19[S999( 9iuc[c[KKB91K[S(9K[[[cccccciocKKSc[SBou(BSKBSK9 KoS (1(B9(( ((119(9911 (((119999999119991BBK19ic[SKSKKBBKB9999999991(1KKKSS[K9BSKiziciu[B119KSSoϷ¼ɿu1BcK9B9KBBB9B9B[zcB[u[9 1[ccSKScK( 11(1K[B99991BizoS[[[[SS11SSK(9[ccc[KS[[[[oiS[[[[SBo[BKBK[K1 o[( (9KS9 (( ((((11(( (9B99BB9B991999BSBK9B1Bi[ccSSSBBBKKB99B991999119999BKSSBBKcoiicK99KS[KiuczdzǷ׳[B(KKB99111199BB9BSKK11(1Kci911(B999 1(((Ki[SSB1Bouiicc[[SB(1S[K(9cccc[SS[[ccic[KK[SBKoKKSS9 Bu9 (  1SS1(((( (( ((1(((9BKBBBB99911911BSKKKB(S[ic[KSS[[cSS99BBBB99119B119BB9KK999Kozicoo[99BK[iiuKzļ׳uS9Bi[11B1((1991119z[91((91[SB1((KKB 1 19BBBSKBoccoiiii[B11KS19[cci[SSS[c[c[cK1cSB[ǖzzocS9(Kc(  ((9KB1( ((((111(111BKKBBKKSB1199119KKB91Su[[cc[c[SS[KB91 (119B9BK991KB199KK[[S[uc999Kcooo[u¿cKSiS9ScS(1KK911B9( (KiB ((19KK( 1S[c[[9   1BB[SiSc[cioc[9(1BSB11BS[[[SSSK[i[SK[K(c[BKɉSuziK cc((( ( (199B9((1(( (1199199KBBBKSSB9911919S[[iļzucSKSS99(1(99((91BKKKSKB1(19BKK[So[BBBK[coooiļu1KSBBBKB119KKScS91(((99( 11 1911KScc[KKKB( (  19Siu[[BBK[SK119KK1(9KKcc[[cSBK[[[KBB1S[1KcooouB1z111199BKK[ouS9111(1(1BK((19KKBKBB999911BKcz˼izzi[SB99(( 1119BBKK[[[KSK9999B9BKcBBKKBKScScļĿo[1199BKB9119SSKKB1(1991 99  9BKSB1((1BBK91(  9iicS[KSKK[[K1(1991Sc[c[S[ccKKS[KSSB1cS1SoocKS[oSK19BB[cc[S[zoSKKKKB9KSB ((((1(11BKKB9KSuϒՖciuzuS(1BSK99199BKK[ocKKKK9B1191KBB99BB9BS[ccu۳i(9111BB111((19K[S9BBKSB((1(9191 ((11111111iui[SSSSSScuziS9111S[[ci[[icSSK[S[[B9[K9z[SK9BK[uScu( 9SouocizucSciuuK9( (11( ((B[[[S[i–­[KBiuoKKSiicSKS[S[[[[KKBBKBB9919B9BSKKBBKS[[SzļسS(1(19B9991 19KSSKKSo (1B9191  ((191 czccSSKSc[[izoKB9B9BKKSc[[icccK[SBKKB[9(iSB9KKK1Sczu9(9[iououoozc[czic[9( (119BKSS[[[oouocB9Kciiiiouic[cioo[SBBBB9KB9KKSB1BKK91KScicKɿ׷zS919911BB1((( 9K911uS(11991119B1(  (((1 1zuiiicScoiciuziSSS911BS[cciicc[SSSKKSKcBSzK19B99B[iSci9 KK9K[ciouoiiS9( (BB9BBKS[cccSuzccSKBB[iicoiouiScuouccKB9BKBKKBKSSB999B99B9Si[[ڼ՞ucuzc9(199KKB1 (1( S9(1B9((9KK919199  (Kcuiccioozuouo[ScoSB1BKKSiiiiccc[[K9B[[KuoooKKB1(1BS[KBuiB99BSizzozuiB1(99B9BKKKSSSooo99uuBK[[SB[oociiii[Siucc[BBBBB9K9K[cKB99991BBcioҿբuuiSS[B ((9991((11( 119Buz91K1(191( (B9BB( Bcoc[iouuouoooccciS91K[S[iic[Scic[SSSc[cz[K[B( 1K[Sc[SSiuozuuoi[uc[ouu[[B911119999BB[zocooBcuS1Sooo[SuzuuocSSozcS[[[KKKBB9BBKBBBBB99BSiۼĿ׿¼ĞucK1BSS( 11( 19B9(1991BK11B9 (( 1BB11(1Թoooccozzuuuoccccc[cS99BKSKS[[[coic[SKKS[ouiK[B11B[[KS[uzoi[SSic[ccz[Souz[91911(1(((1 9Siicii[KKBiuK[uuuooiiuzoi[K[ioic[cccKB9999BSSB999199Ku޳ɿͪͷļi[o1(Kcoi91119B1 (91 19119KK1 991(( ( (1 ҦuuouoS[izzzzuuoiii[S[[B99K[SKKSS[cii[[S1K[zuS1(((9Ki[KKK[o[[SKKKKScuzoci[[[9((1(( (( (111KcKKBB9BBS[K[oicozuc[ouSBSSSScccooicKBB999KKKB919BBB9coۦͷ[KBSi1KuuiSB1BBB9( (11  1((1KB (1999 1( KcozzzucS[iozzzuicccSccKB99KSSKK[iioi[SSKK[[SBK91 1BKKBS[izcKSSSSKBSSiiioiSK91  ( (11[zu[[S919BB1(9S[SSouoi[[[KBKSKSS[S[iSK999999KSK91119BBBiSˢĭĒc[S[ciooo[Scoc[KB(19B9911(1( ( ((11 99K9 199(9ucuzcouo[couzuuoiiicciic[KKK[[99[[K[oicccSoiK9SS( 9KSSSB9BKz9SKKSK9K[icK11( 11 ( (( 111BSSKSSK99BKKB1((19Siiioooc[[SSSSSK9BK1(1119BSKB91199BB9BSτoܼ¹˹[BK[io[oB911((11BKK91(( ( (1(  ((99((9BB(BBB1( i[uzzcSuzzzuzozo[cccc[iiiiSSSSKBScoK9[[K[ciĦ[Kcc1(9KKBK99SB[K9BK[SBSooK991( ((1BcSBKB1[K9BBKKBBKKKB99911KS[[S[c[SS9BK9BBKK99((((19KSKB99BBKK91B׼uѹ¿o[zoSK[[u9SS111( (99BB9991((((( (( ( 1119KB9  ((((Bzuzzuouuo[[SK[[S[SSc[cc[S[B9SiziKSSKSKcĢS[cS(99KKBKBB[9ScKK[cK[z[SS9(1((1999((BiiKSBBicB99B99BKKBBB91991111(((((1(((19BSSB91(11BBKB99919BSK99B[ҿuoļѿS99KccSBB[19B19B91199BBSK91(((1 ( 119K[K9  [ooiizu[KKKKKBKScicii[SB9Bcui[[SSKSoiiu[199Kc[SBS[9[BKuKiKB991199BBBBB9KozcSSKKczSB99B9BB9B9BBKKB(( (((19B9( ( 1BBBBB11BSSBBB9KSKSKKBK[KiĭcSϳǷuK11(9S[KSSco[B11(9K[SBBKKKK99( ((  (9KS[B1  (oooo[[[[uzziicouoocSSBKcciiioi[KKS[ouiic[[uuzioS19BS[BKSKBBS9[cSozSKK991((BKKBK[iz[BKSouiuo911(1BBBB99BBBB1199B999BB99 (1111(9B9K[oiSSSKioi[S[[[S9uªzi[cɰ¹u[K911(1KK9BBoK1( 9BB99991199( ((  1BKKK( (ou[icSciiuzo[SKKiiu[[iSScc[ci[[[KS[czoccS[iS¹zciS9KSSBKiu[SSSB[ič9KB91991(999Kc[SSS[uzK9KczcBcS(119911119B919119B999KKB11 (1911(BSS[iioi[[oooicc[KSBKշi[BĿ[9( 191KcB19Su9 11(   1(((   19111((  Su[ci[cccuz[9B9B9S[zciS9Bcu[cuucc9ScSSc[[oicSBoKBBBSSK[iuoSKSSS[c9 (111119KBcScccooK(9BciBBocB99B91((((( (((1B91(1911((1BBB111KK[ooioi[SSS[cuo[cSBBBKc˳¢uc[[ǰS1(1991(1BB9Szi (1((  ( 1K91(11(iuK[[K[couuuc9BSSS111coiKBK9BK[zuouoiiBK[K119SicSB9oKSKBSc[[Bc[B[[KKKK9z((((( (9ScSS[occo[B9BKSiK9BiucKSK( ( (((((( ((1 9999919B99BBB99Kci[[ciSKK[ccSKSKKS[[[ǼucSĪuozK ((1( 199KooB99((     9B1(111 1uo[i[K[[[cSB9BSS[S9119919KcuoS9ozcccSKS[B 9S[i[B11zSc[B[ooc9SSBKBKB[ (111( 1BS[KKciuzc9(BSKS[BScuSKKB (1(11 ( ((1((9(1BBBSKKSKK91(1BSSKS[[[SSiiSS[SKSSScĹz[SoǞzicozi1(SiB(( (9( (19KcS9     99999BB (9uiScSSSK[SS91BKBSBBSK91BScoziBcucKKKBK[K((K[[iSK91¦uiiKSoo[S[S[KBSSzo99911(119KKKcooooS1B[KBSK9BSzzBB1 ((1911(((  (1BBBBSBSKS[SKKB1((991BBKKBSc[SSc[K[cciz˹iKSԿccc[cB (BcB111 (1 ( (1[S(   9BBKB19191  1ioK[S[KSSSSKK[SSSKKKSBKScc[S[S9BK91BSKKB1 9cuuc[K9³zSKBKuuciSScBB[ozB1 (19B99BSSB[zzoS9BK911B919KuB((9111( (((( 1119B9[SS[[SKKKB9199BB91111BKKSKccK1ccuuSicKo˪oK[[[S[ (9SS911(1((((  1[K     (((1  1KKKKKB9(  1uzS[[[[coouo[SSSSSSSSKSKSSKB999BB9199BS1(B[oSK[[BzS9KuucK1ScKKozouS11((((((BKiiiccK1 1( ((( 1 KǷoSB( ((11  199BKKSKBKB9BKBBBB199B199191991S[BB[cuoSScuѭz[BB9BK[ic9111(BK9 (1((191( (B9    ( 19BKBB91( 1( ( (uoccccioouuicSSSKSKKSSKSSK991BB9111(BBB( 1Sio[BBK(uiB9iuo91SS1KuSiBKz  (111BSc[B1    BĪ[1  1( (1((1BBKKSK9119BK[SB11999999BSK91(1K[ozS[Ko˄S1 (19B[S91(( (BB((( (11((1BB(   (1111111(( (1((( (1[u[[c[[[ciccic[[[SKSSSSKSKBKKKK9(11(1KB9(1K[[K91K9iuSBSou1BKB9uiBK1i( ( ((1BB(   oijciiS1 (1((1B9B99B11BBKSSKK9(19999BSc[K1(KcoiKB(խK911((11(1111( ( 1S9(((  99991     ((((((1( 11191 ((11S[SSKKS[[[couuocSKKS[KSSKKSSSKScS(1cS1((BKK9111BooiK[zoK[BBcuSKB9S ((1(   (( B˳zi[cicoo9   ((199B1911999BKB911KKB99SciiiSBSzuB9€(9(1 ((( (  1BS111( (99(    (1((191((19911(((1((SB9KKBci[S[ciouoouiccSBKS[ccc[cc[BBcoK9BKcS(1K[zouccouioBcoB99Kz1(991   ( 191(((1((  cuzocic[iozzoc1 ((((111(((1B9(1B1 (9SSBBKBSS[uoSoci[KǼ˄1 (191111  ( ((11K9(99(9911(    9991111((1B91((((( [u91911K[KBS[cc[cioouuiciuzuzuiSciB(9Si[1(9[[czuoicioc9oiK91cK( (191B  (111 ( (  9zuoouoi[coiuiKc[( (191( ( 1999BKKK99BBBBSoi[cuuc¿Ϛ[191BSSSSK1(((1( ((11KK111(9B9(    (((B9911111111(   [oc9((119B9BBS[SSS[[cozuiizicicSB1(1Bic9KccccuiuiciScziS1uB 1B1119 (  ( ((( ( 1Kiooi[ScizcBSoo1((( (((((((((((1KSSKBBBBBK[ozz¦oѢiBBSS[cicS[S9111(((1((1SS1(199      Kco[99B99111 (991( 1iicB (111BKKKB911B[KKcoiciozzo[[[ciS 1BBcoK[Sccuoui[SuiiK9Ko( (9911999(  (91( ( 9[[KSz[S[izi99K[uiozz9(( ((( 11(111BKKK999BS[[ѭijiSSBK[SK[ic[[K11( (((1K[11999(    1czc9911( (91(   9ocB((1199911111 (B[[S[ii[cciouuuucc[SK9(BS9KucKKcizzozzSuSiSSSB9SS999911119B1((  19991(BczucSSz[9BcoK(9K[u[Si[[i9(( (((11911 (99BB9(9BB9cҦijzSS[KBBBBKSS[SKKK((9B91 (uoS9(11 (( (   Buzi99    1SB9B9199(((( 9BKSSKBKKS[[ioooiS99919B BoBSc[zuccuB1BKB9u99BB999BBK919911( ((199B(1Siuucc[BBciSBSoc9(9B[z[[cccKSz9(((1(((1111(((111(((KSKBĹu111 (9BK91(111999B1(111(111(9عzK1 ((  (11[oozuzocK1111   z[KK[K911  ( (( (BKKS[S[SKBKKKSK91 [cK[ccczo[i[Su KS1 z1BBKKKK9S[BSSKKB9B91BBBoSS[[S[SSB9BKBBB[o[19KK[cSS[SBK[91911199111((111((1K[cKSҰ99BB9((1( (( 1919999ݼoK919(( (czzzcczciuc(  uS[[K[SKKB11(  (19Bcc[SS[SKSKKB9BBKKKB(1ozcc[BSozio[oK1SS(1BKKB[uziicSKSSKK[oBK[KBoKKKSK[i[BBBB999SiK19SSSi[KSB9BBKB(11((11(119191((9KcoSK¢S99999(191   (11(191iouzuocou[KBKuuSScoioz[cuui¹oK zK9KSKBKciSKSB19BBKS[[[[[SSSSSSKBBB9BBKS[i[B9cuc[[SSzuoi[[9BK((KSSKozo[[ouo[[izzSKSSKcKBKKK[o[KS[SB9(BB((BKKKzicSBBSS99Bi(191( (91(11((19B9KS99ϼBBKK91111   (11(11(iii[SKiuc[ouzuoo[SSozociooiuoĿzB9SSK91K[KBK[[[ccicioiiiooc[SBKSSKKKKKBScSKK[ocK[SK  (((919BSciic[iSKuB9izcB[B9B91 K[9((  ((BKSSK9(9SioiB( ( (KioSSS9(1(11(BS[[iuuoccccciiiccS[[cioS[KBBB9KKizoS99KBSKK[B (    (KoiB 1(  (1919Sc[Sccccicioc[S[[[[SKBKKKSScB(19( (((1     1 1  (( (1KSi[c[SS[KcczK(KiiS1(   (19KSSSB B[[S91(1919SoiKKS9( (9(BSccouziciiiiccccS[ioizzcSSKKB99Siz[z91 BK[S991  (    1Soc9(1991   ((99B[iSSciccciiocSKSSS[S[SSSSc[S(1BB1   (B9((((   [[ 1(((((9K[BKKKSui[S[Bczo9   1B99K[[S9(1KiK9(91KKSSozSBSKB( (9BBS[izzcS[cii[coSKii[[iocSSSKKK[ciBB[[o[11BK[SBB  (111( (BB11K[[B( 1BB1  ( (( 119B9S[ciouiiciii[KK[[[[SSSSSci[91Sci( ( (111(   (9(ݭ1(11( (1( ((BK9119[zucKK[[91B[[1    1S[[ioSSK19B[c9 199[SS[zSK[K1 (BKB[[coziS[ciicco[iic[[c[c[S[[z[icS[[[SSK(9SB(   (1BSK1B[cK(1K[K1191  11KB(1BB[KS[coicooiioi[SSSSS[ic[[[c[[9Kizc (((((1(    i19BSKB((1( (1((( 9ioiS9(    (   1Kc[[cuSB99BSiK((9Kc[SSozc[[K99BKKBS[SizuoSS[iiiio[SSS[c[SiicciucucicSoS11 K[1 (1((999SSKioS ((BiS9(19(  (19KSBKSK[BK[coiciciii[c[K9Sciii[cc[cc[119c[ 99111( (( 919KKKB991((1( 11( (KicK1    19K[[cccz[(9[[911SSKBKS[ozcS[KS[SKKB91KouzucSccccou[BK[S[SSczo[SSKS[uiSiui9Bcocczc1(1B99( 19KB91199[iKSc9 19B[SB999( (BBBSKBBKBKK[iio[Koccic[cS Bccciicc[S991 9K((1((((1(1((( iBKSKSSKB99B91((9B1 1Si[1  19S[[ccccizo9 (1KKB 9S[B19S[[iic[KSKKB9(((1[uzzocS[coiozcBKB9[iiiziK9KcKS[cSBBiuc11BB9SzuS111B[B 19KSSSSSSci[(1K(1BB9KKB111 (9BKScS9K[SKScciuicoccc[ccB1Siicc[cco((1( 1(  (9( 119191( ((1BKSSicK[SBK9919BB 9SB1     ( 1BKci[[ciic[[cooK( 1S[B919B(9KScizucK1( ( 1((coiSSSciuuuiScKBS[Sczc[ccK9BKSicouoK1B91SocS99SiB11BBBB[[ScicB((1  9B9BS9( 1SSczu[9Bciccccio[SiiiooocB1Kcoc[[[[cuK91  9 (19(1B9B91111(9BB[[[KSoiScuc[KB199B 11(    9[iSciuoc[ioS1( 1[iB((  1BKScccuz[9(((  9uoiiK[cozzocKcBBBK9SouioiSSiuzzcSciSKc[[coouc9[i[S9So[K[SBKccB ( 1( 11(19( 111BK9ouSKKSccc[S[[[[couoouc1SouoB1BBKczc1  91 B91(B11(1 9B9BS[Kucicouiiuzo[SB911BB(     1uu[[iozzuzuS((ci9  1BBBK[c[cu[1 (91((((1[[ccuuoiuuc[BBB99B19Sozc[ozzoc[[ioooiicizi9KiocKKozucciz[((((191(11(9((9919KKS[KKKSSSSSS[Scoi[[ooziBSoo[11B[ou9  11 B9(1B ((99[ooK1iouiiuooo[K91(9K   9[ozoKiuzzzK Bi[ (19KKBBBS[[i[1(1991119KuccuouziSio[SBKS9BKB9BSizzcozc[[SScuuooiiouK SoSBKKSoi1 (((111( 1(1KB9BBSiiSKSS[[SKBSS[iio[((K[c[[ioKBKScuu[  11 91 (191(9c[(Ϣcouuciuoii[KKBBBK    1[iccSKKci[[iooc[c[K(19K[1 9BBK[[K99KSccB (1(((9BKozuiciuocBBKSSBBKKKB999Si[czuo[[icicuioioouK 1K(BiciccScuoKKoiKSKB19BKB11(1B91BS[[SBBBKSKBBBKKicB11 19KSK[iK (KSoi9   1 ( 1((11  ǚzccou[S[[S[c[KSBB1K((911SiioiK( 1iu[[[B1 1KSKB(1BBBS[SSS9119K9 ( 1BKKciioiczioK19BBBBKSKBBBB[couiiicccccioiuoioiiiozc( (1 Bici[BKicB1BSKzozo[9( (BB9K[SB99919111((19B1  9B99KS[[1 (11     ( (9  (ԒciuuiS9BKK[cKKBB9B1   9cSozuS( SK( 1[oS999K[[uiB9KB9199( 1SKKSS[[ioooozoiiBBBKS[cS9BKBBKSizzzccouocciicciiiioizc99( B[[[S9[c119BBBSuzicB1((999KSB9991 111  9S[SBKKBB99     (((B1    (uu[ioii[B9KSS[[SB19B   (Kciuo9((Boc 1KKBSSoz[B9BS[KB9( 1Suo[cioiuzuuzzzcKBS[Sc[KKK9BBKicSciioicciccooB([K9ciciK KiS9KSScicS1B9K99K9BBK99B91 ((91( 199KS[K1B9((9cK   11 (( (u[[oS[cii[S9BBKKccSBK9 ( BKcuui[[c9 BKK[uzK B[uiB( 1S[[iK1BSS[SSSK1 1B[iiuuuzuKKco[S[KKKKKK[ušoSS[iiooiiiicu( Ku[iicc9(Suociocio[S9119B9191KBB111 (111(9KSKKK[[KBSK99KBK9     (( ( զicc[cccocSKKKB9SSB(91 (( 1SSScuu[SB(1i[99[c[[B 1SocS1 SSScSKB(1BBK11BB9(19K[iuzu[cuzucSK[[KKK[iicSSScoioiiouozzSBKiicKKiS19ScS[ciiouiK9B[S99B9S[SS9(( 991(9[cS[SKSSKS[SScuB1(     9ڪ[ui[oiccSKB9KSB(1  ((1( (( ((Bcii[[cc[S91(Sz[11BBBB9(zoB 9K911 (  (1   1BKiouuªoiouo[KKSKSccccozz[[ic[SS[cccioouozcB1  1SuSS[oi[SS[coSSioKKKBS[[o[1( (1BKB99Sc[SKKSS[[cK[icB9           BĖ[uuoooouoc[[SSSK1  ((( ( 1K[uzi[KBBSB9BcuK1Si[K1 1Sic(          1SciouĢucioouocKBKBKScccuzzuo[K[cS[iiiicciicio[K( 1zoizzooiouoKiu[BB[[[ccuuc11 (999BB99KccSSS[[[S[SBcoKB9Ku[o[     ϞSuS[[iuzzuicciuz[1((  ( 9iu[BBSS(19c[BizK( 9B9(      (19Sozuuzzijicioooi[S[SKSScuooiiui[cccioi[SooiooooocS1(zucSKKSic9BKSSScczi[[9(1B9(19KK[oc[SSS[[[S91uiB91( oؼu(   uܷiS11[Kiooiooc[[ioc9(((( ((1czcSoz[(1Kuc[9(1111( 1   (9K[ouoiouo¼uuocououoi[SScSS[cuuouuzc[ioiuuuicouoouuoiiS1 [uScB1[zoi[SBSKS[cKSK99BB9999KS[ccSSSKSKSK9B[K1(1 cڪK 99(  ɖc[K 99uzoozzcicc[ciS1(((  (Szoozi9BzcooK (  (    Kooouuzozcozzuiciuuouoi[[S[[[[cioooiciuouic[ioiouuzuoicS1 KiSKK9ozSKBB9999K[K99B99B9KKSci[[[KBSSBB[SKczKKK[[Sٷu1  ((1BB1(  K㰄SSK1 (1oiccoocioi[cic911  (9oic[Kuuc1 c[c[((((      Bcziuczuzuiuu[uouiiiizzoiiic[c[[[c[S[cicccooc[[K9cuuuuuzozo[1 KS19K9SzcBizcKSB9B999KB111BBBBKBS[c[[c[[KS[SSSSSuoKiͼ׹ucuK( (((( 199919( ՍcKKBKB((9iS[uocuc[oc[ci[B1((((( (1SzzuooicKBiuiS(9zoSK1   (  (1(9BSczzuocKBKuuozuccciiuuiii[KKSS[iiS[[[[iccciK9KS[iuuuuuuzoS1 9B((KBBzziBBuoSSSK99999K99BBBKB99BScccci[KKScoiSKiuccس˳o (((9911999((zSB9(1B1(91o[K[[SuSSi[KBBBBB911((((1[zzuouzcBSizi11KcS1(    (1  (9KKBKScouzuo9(1Suzi[[[ioiuuooiicSSSKKScKB9KBKBKSi[S[[[[iuuuoiuuouo[B1 ( 1SSBizS[icuuSK9KKKBBBB9BSS9999BK[[[ciiic[S[zo9KzciժuKB(( (9( (B99(SS1B9(11(99[[B99BciKK[[SKB9BB1 1 9ic[oiK9czuB   BiucSS[iuzc[9 BuiKS[ui[[ouii[iuoicc[[SS[cSK1999 B[i[icciiiuuzzoiccoucc[SK1  9BKcuuK1SuziiiKKSB999999BKB9119ScicccooicciiiB(izSzѷiB͢9  ( 11 9B1(([( 1(11 1991B( BziBKKSB9B991((1( Kucc[KB[c1   (Szi[coiuoS1 iKB1(KSSii[ioooociicSScc[SS[[[cB11((BccScizuzzuuzuoicioozoccicB(1( 1(1[iK11BK1Bi[S[KKB1111199919Kcoiiicco[ScoiS9BuiKcuۭɢi( 19(((19( Kuuiz 1(19((((9S9111S[B19[KK91191(1(19iuui[SB1(     1BcuiKKSizzS(1zz1 (B[[K[[[[iuoocSBBBB99BBKSKS[B 1[oiKBouuzzuzzuzocciouocc9(B 111KS( BB(1Soc[SBB9999KSKBKSS[cccioicK9Sc[S9[iK9Kǹ޼ټS 9oooiK91(  (B[[KBKocB9KBBB199KK1111Kuuuuuoc9     (9Scc[[Siiozoc9  9ozB B[[SS[coiBBBBBB991BB91999B99BS[[KKccciouuoioiiooouzuS1 ((1 11(( 1K[BKBSuo[[SSSKKSSKBK[[[izuiiocK9BSSB9ccKSSɹڿǪK91u˷ļў[91(( ( (1coS9SouK9KSBBK91(BK19K[czuiSSSS1     1K[cc[[[czzzzuocK (c[( ((Kcc[[SS[ui[[KB99BB9BB9999119KKSKSSSKBBKScci[KKcciooi[1((11  (( 1KBKKKczuiSSSS[[[KBSS[[uziicSBBKB(Boi[SSc[԰oSiB So ((99((9ioKBSou[KSS[SBBBBBKBBKKKoocKSS9( (    9KKSozouoi[1(KuoB((11(9SKKS[[c[[SBK9999BB9BBBBBBB9BBKSSKKKBKSKBBB(111ciiocS  (BB91 (1((91 (BKiuoc[[SKSS[ccizoc[[SB99Bcu[iiS9[װiizKK9(9  B[[((oucKBcucSSK[B9BBBKScc[KSii[KB1( (1( (   ( [ziuuz[ (Kczi9111119BB19K[[KKBBB9999BB9B99999B9BBKKSSKSSKKBBBKBKB9K[[cSK  99 ((19(191 191KiozzziciicoouziSB1[uzzuKoo1ҒBB91(B˰ĪǷz  ioK ziii[[izcSS1B99BKK[ozuiKSiccS9     (Buiiiouzzuuz[999S[ozS9(((11119((B[cSKB999BBBBBB9B99B9KKBBKKKBSSKKBKSSSSSS99BS91  (   119((191 (1S[oz[SiS[cˢ߰(  i˭SSiouzdzo1(((SuoS1uiuzzuSKBBKBBKSKiozucS[SK1     ( 9iz[[ciuzi99BKS[zc1  (1 (( 9K[uoSKKKBBB9BBBBBB99KSKK[[[BBBKKKKKKBKS[cS91(    (( 1( (11(   19K[cci[[oi[ocKBK҉9(BKѪzuiSSSSczzoicKBB99B9 (9uzK1uuuzzz[9BB199ScccuuocoiBK9      cciccɹ[ BKBSczo1  BcziKKBBKKKKK99999BB[SS[SSK9BBSSSKBBKSiiB19(((    ((99   (9 ((9BKKiiicB1[i[S99Bzωiحz[[cSS[S[iuocco9 9KKKB1(KzK[SS[[SB99KK99BSciiuoSSi[B9         999Bcii[KKzdzo (SSKS[ouS( (iuicSSKKBBB9KKBBBBBKKKBKSSKKKKS[SSS[[SciKBB199(   9KB   (1((((B(1B1Kzui[KKB9BKSՀ˿99ɀiciocc[Kci[Scu–(11BB1BKB1K1KSBBBKKKBB919BBS[cic[SSB(   ((  ((9KK[ouoc[KSSic1 1S[SSczo9 (SicSBSKSSKK9BK99BKKKSSKKKBBKKS[[[ccccci[SKB199(( 11  (9B9    ((((1KKoiSSKSKK 9Kcؼi1BS9ǒiiuzzSBcuucciS9SS9(9KB9S[ KKKKKBK99B1BK9BBBBKKSK11(    (91  119K[KSccuoooccK9BB(  1B[SBczK   9u[KSi[[SKKB9KKBKKBBKKKKKSSSKS[[cicicccSSKBB99(( (1B99(     119BKSiuSSSK[K9( (KϖuuB119[cB͒o[SKcoKcouiSizi91BKSB((9So[9BKS[[SKKK999BB9BB999999199(  11  (19BS[[[cii[cuooSKB9 19BSSii[[K (uSSccSSSKKKBKKB9BBKKSKSKKKS[cc[[[[S[[[KBKKB911  1((11B9911  ((  1BBKKSuzcSKK[KK1([э[[( 9BKcoշSSSSzScc[SKuB (B111 1KuouSS[cc[KKK99K[SB191191111(11  11( (K[KS[SKScoi[[coucB1((K[oiccic9  1zu[S[K9BK9BKKSSKBBKKSS[ccSS[[[[S[[[cci[KBKB99B( 1991BBB991(      (  1K[S[[couS99KK[S1 1iἀoBK99K[ϞBKSizcSSSSKSu9 19 (1(1SiuzcSSSS[[SB19B91(199191  (1(  ((((((1BcoccicSKK[[c[9S9 (9[oiciB   1cu[cozo[KB(1B99BKSSSKKKSBBS[c[KS[[c[S[[[SSoiSKKKB91 199BBBB9(111 ((11B19BBKcui[ciiiiK99B9191((1KѷzǒK19B1Ֆ1S[o9KKBKS[[K((((S[izc[[S[SK9(11 (1B9(((( (1((   (191 19Scicou[KKBS[[S99cS [iB  KuSBKS[iuiK9B(111(9BSSSKKSKK[[[[SK[c[[[[[ccScuoK99BBBB1(9KKB9B1(91    199K[[SK[c[ci[[[SScoB9111BKK9(((B‰ 191B’uoizK1KB9BS[i (1( [oܼSKSS[[KKB991 (199(  (((11 (BKSK9199BS[ccKSiSKBBBBKKSK9( 1Biiz[   Bzz[91BS[ci[1 ( ( ((BKSSSKKSS[cc[[SBSc[c[[[[[ScziS99BBB91 1KKS99911K9  coB9SKBBKK9SSKKB9Bii9999B9BBBKKKBii[S1S˰zuzuoKKBBKKS[BK9 11 (cuۭo1[[[cS9919B119999  1(((1(    9[ooi[[c[BBSSScKBSB((BKBBBS[B 111((1  Sz[B19BK[c9(11  1KS[SS[S[cic[[SS[[[c[[[[cccoSK999BBB1 ((9BKBBKB9K1 cuB1BBB991(11(9B9Boc9999BBKKK[iiiS[KoݿĞi[[SKKKKSKBSB1111119iziocBcS[c[SB19B1((9BB11 111( 19((( 9[oiicScooc[SS[[[BBSKB9K[K11K[9((   Szc9999KcK1   (9KKS[SS[[ioii[[[[[S[cc[[cc[cSBBKBBB91 (9KSB91((11  BS9BBB9(( ( 199B[[KKKBBK[B9Siciu[[צ[[zzB9SBKK[[KSu[K1B919Bczѷz9oc[SKB19B919BBBB111BBBB1(11   (19BczucciuuucBSooucSSSc[B9SccS9BK(((1(9uzzoo[BB19BS191( KS[c[S[SScciiciicc[[[cc[c[[[SBBKKBB11 9B[B(  (ucB1KKK( ((((19BB[SScSBKSSB19KB[ioݳco9KiuB(19SS[SKKuioK99119[uݷBoiSKKBBK9(9BKBB9( 1BBBB9999(  (1BKcouooziKBSouocc[[cS[cc[[K91   (( ((((1( (czui[[KB99Kc[(  9cKSSSKKScicoicS[c[ccciiccc[[SKKSKB91( (9BKB(  SuB99KK1(1111119BKciSc[KBKSK99BBSzo[גBiܹcScc91KKSSSSciuo1 11K[oْ91occKB99K1(KBB91 ( (9BKKBBB1(9cc[SSiocozu[9KBKcicicK[[[cSSSK91 ( (1KK1 (1(((Kuzzzo[SKBBBB[cS(199991(1999BSSKB[[ccooiccc[[SScci[[[[K9BBKKB9( (9B9B11(  uSB[[[1191((BKBKK[ui[[SKS[[BKBKSiKBSuuҳuoi9(BSKKKBKSBc991BKSKBҢB iK[KSB9B99911( ( 119KKBKKB9(9iuc[SSccoiciouoB1(1K[i[icB[iSS[K9BB91(  9B( (( 19 ([uozz[KKK9KS[cK19K[[c[c[9 9BKKBKciiiicicS[[[[KK[SSSSSKKKBKB9  (1911(91 (SKccS 1BKKB1KSB9K[uo[c[[cciSSBKSSo9cc¹[ǼcBB( (1KKKKKKKBKuzcSS[[KB9SˉKi[[[cSB11BB9B( (119BKSSBKBKKSSiS[[S[c[i[Sci[9 (S[[[ccBKcSS[B9KK9( (1Kc[[B(1( 1B19icSiziSSKB9KK[[KBKBB[z[99KBKSKK[icciuui[[[[SKS[[[[SK9BKBKKB(((1(((1((  SB[icc9BKBBKKKSKS[Kcu[[[[zo[KKKSBioSoɖKc[  1BB9BBKKBKSKcuoicoS1BKS[uK[[K91BKB(( (BKKSKKSSKSKiuu[[KKSSccii[[SS1(((1KicS[SK19[cSSKBKKB( 1919KuS119(1KBKiKB[S9991(199KK9BB19cKBKSS[iuoccccciicc[SKS[[S[SBBKBBB1( 11911(1  zzK[c[S99K9KK9BKBSSKczocScu[BBSK99B9iٳo[K 191111BBKKBBKB[uccSKSco1[c[KB99KKKB1 1BKS[[KSccSSSoocSSKBK[iuoucS(1((1Soo[[SS1KS[SKi[S[B 11( (SK( 9991KBScB9BB11991(((199199BKBBcB9KSS[iuoccccioic[SSS[[[[[KBBBKBB9  ((1911( BcB[iiS91BBB91K[SSKSSicSooSB99B11( o㳚o1 19111111BBB99BBSScuizc1[[[BBBKKKK1 (B[coo[SS[ciiozzui[[[B9B[ouuo[919( ([uo[SS[9ci[[izo[K1((( (99[[B9BKB1BKSBBK1 (991 ((99111( (B9BK9BBSSScuuc[[cooiiccSSS[[[[K9BKBBB((1(19(( (( cSBB[iiS99ScSBBK[[S[[[z[[uz[[KK11( KiĿ  191 ((1199919919BczouuuuK911SSB99BBB1( 1K[icKKcciouuzzc[SSc[99[cccoiB11((BooiS[o[9S[Sizui9 ( 9KK[[KS[iKB1BBBK9(1999(191991 ( (19[cKKKKS[izzi[ciicii[[SKKSSKK919BBK9(  ((((1( (((  9coK9K[icSBK[icKSc[c[[S[uzccozu[[KB191(991Scݳc1 91((((( (9911919919Kiuozz[BB[[9cKBBKBB9( 1K[ccS99KBK[c[ioi[SKS[iKKi[KKSS1(19Souic[ScS9SScuucS[ B91((9K119ooSKS1 1KSKSB1BKB91BSKB9( (19BKSSBKSKBKciuzi[ccccci[[SKKKKS[SK9991( ( ( 19B9 9S[S[[[[[[KS[c[SSccSS[cczic[ozc[S919BB119BK¦9  11(11(1(((11((111B91[ooiSKB1(11ucS[[KB91 1BScccS119BKBB1BS[[[[[[icS[K[[SB9199KciccS[cS9BScoiSB9 11 (9B9111o9  1K[BB(9ccK9BKKBB1( ((BSS9 ( KcSBBKScuzociicii[SSKKKSS[KBKBBB(  ((11((199 (9[zBS[[ciccc[S[[[KS[SSuozc[cuo[B1119KS91((([9   1991111 (1(1((( 1919ScccccK11( uo[ciSBK9(9K[cccS9119B119B[[[[SS[[ciioc[B11911Kuoo[[ou[9[uoii1  11B9  (BBBB(Kcc[KS[[KK1((((B1  ( BBKKKKKKSuzi[[ciiccSKKKKSSSSKKB9K1 ((11( ((( (((1  (1SB[ccccS[c[[[[[SK[S[uKBKiiK11999KBB( (1[z[ 9oo991( 11(111 19 K[[[[[K(cc9uzSKK99K9 9SiooiK9B9((119BSS[ccccc[izoSKKK91 BooziBKuucS   (K1 (1BBBB9K[[[SSSK991((1(((19191BSKBBKSouiic[i[KKKKKSS[[SSKKKKBB91( 11(199111( (9B[u[BS[[ci[[cSKKKciioiciBSiuiK9(199BBK((((19[1 9Ǫ[99((((11(( 11(1B[cKSiSKu[cziB1BBB9(9B[ioocB9119BKS[c[[[S[[[[ziKKKB1 (cocuozcBoo1 1ic9(( 9BKKKKKBKSKBBB91( ( (1199( 19B9BBK[ioiccco[SKSKKS[S[[[SSSKKKB9( ((1(119B9(  19ScKKc[ccccS[cSSccccicoucizuzocSKBB99B91991(B(1ªu99(1(111( 199919SS19[zo[cSiu[199BB9BBBSiiS9(BBBKBKS[cic[c[[SiKSSB1 9iiKK[[iuKczc1   (9B9((199KS[S[cc[K99((((   (191(11((199BKSoocc[[KKBKK[[[SSKKKKSSKSKB( (91(91B9911(999KKB9B[ciic[cc[[[ccc[cooKKSizuicKSBB1199911SS19uķicS11 ((1(11((911199911Kiu(9KBKuo9999B991BzoK111((BBKScooi[[[cicSSK1 (Ki[KKSK[ocKSS(      (9Kozzo[cSB919(1(( ((1 ( 199BKSioicS[[KKKS[SSSS[[SSKBKSKB(((19119B9B9919KKSc[KBSiioiSB[icciii[[[uuKBS[ii[[ciooocSB111BKSKBocSiiiiB( 991(111(( 9119K(999BcoS1 SKSii9(99B9( Bc91KBBBB91K[cicccciocS[B1(9KSKBBB9KK999      (SoKKS1( ( (     111BK[ciii[SSKKSSSSS[c[SSKSKKSKB1 (((1B91B911BK[c[[SS[uuuoSSc[cc[iiccizKK[[ccSKKBKSS[B19KK[[SB1icSB9K(i[ (119((19K91919(BKK[cccB[KS[ui[[S9 KooK99KKKKB9B[ic[SS[S[c[BK911KB9191(     (ii11119119B((11((9BB[ii[cc[[SKKKKKS[c[c[KKKKKKSSB1 (( 9c[BBK[i[S[[iuicSS[[[occc[SSuSScicSBB199[SSB99BS[SK[K[z[B1KicB((((1(191911B119KKKSSB[[9KKKSiuioK1 (ciS19KSSKB99KciiciiccSKuSB[B1B9( (       SoK11991(((( ((( (11(   9BKciuuuc[S[K[[SS[[[[SKKBKSSSSKS9 ( ((Ki[KSSioc[[KcuccS[c[[cccooi[iiSci[KSK111KBBBKKKSB11KSSSzcB˦uzuc1(19( (919K999119119KSSK9KB9BBBSizo[(((99oi[9KSSK11(BS[cSc[[[icSicKK  ((     (19ccB1111( ( 191((   1ScciouuziKKSSc[SSSScS[SKBKS[KKS[B1(((((9[ccc[Sci[ic[zoccKSc[[cciuoi[cocBBB99KKKKKK999(1SSouoz[BԚKK1(191199BBBB9B1111((K[B9BBB[[BBB[uS9(1199SKB1Ki[KBB9KSKSK[c[[iS[[ziSB(    [zzK99111  ( (1(11(((  (( (9ciozuuoSKSK[[[[[[SKSKBBKScSSKSB( (((Koci[[ccc[oozciiS[[[SiuuzuucSzoSKKKSKKKKSKKKK1(119zzuKK( ( 1K1119BBB99191(11BB 1BBSS9BSKSiB1( ( 1K[K1KcK119Sii[[KS[KKcK[SucK( (1 (     Kzzo911(  ( ( (1((((((BSuuuooc[SS[cc[[SS[[KBBBK[SSKSK1( (9ouccic[KSScuuc[SK[iczuzoci[zoSKKKKS[[SS91BSKB911BuzuK9B ((BzK(9919BBB99(11B19BB9(BB1SB9S[SBcKBB  BScS1S[B19BK[SKKSc[[[iSSSiK( (    (    Kuucuzzc9 (9(  ((( (((1199BBizocSS[iicc[SKSKKKKK[SSKSKKB1( 1ui[ii[S[c[czzucc[Scicozuuocic[c[c[SSSKKSSSSKBKSKSK9((([zSB91KSc9(9(9BBBKKKKB9999BBBB1BB1BK1[c[KicB  9cci[9SS119BKKKSKKSKKci[Sco9  ((uS1199BKB1 9Suo[[couu[K1 11(((1( (9((  919BBK[uzui[K[ic[[[SSSSSKKKBBKBSKKS( (KooocSS[SKSiuuzo[SSScoiiicocSKKic[[cSKSS[[[[cKKKSKSSB1919iiK9Sc119 (B9BKBKKKKBB99BBB991191(9S9SSSSiB(9[ccc[KBSKBBBKBBBSKSSS[cSSS[K(  ( (19111KizošcKK[ziB1BSczuiccciccS9 91(((1(((((1(( ((1( Bc[KKKSSSozo[KKS[icicSSKKKKS[SSK9KBBK( (ozi[S[[[SKSSSciii[SSSS[[SS[ccSBBoSS[c[c[[cc[S[S[[[SK91B111(SKBB9 111BKS[SB999((BB9B11KB1K[SS[ccz99czuiiSSSK99BBB99BSKKSS[c[ciS1  ( ((B[u¿Կu[[[BSiooiuoouicS1 (  9(111(1(((1191(KicKS[[[[couuzucSKKSS[[cc[[[SSKKKSKBBKKBB(9zouc[S[SKBSScic[S[S[SKKK[[[c[KBBBuz[[cc[KKSccSS[SBKSKBBB9(  cSKB(   19BKKKBB9BBK99B119(1KK91K[[cKKz[[iuocSBBKK199B11999BScc[SSK9( (1 (( 9SSKi˼zi[cBSccSKScozoicB ( 1(((((( 111111(1(((KiuicSS[[[ccoucSBBKKS[cicc[SS[S[[SKBBB9BK91Sz[[[[SKKKB[[ic[[SKK[c[[S[SiuiS[K9io[[c[SBBB[cKS[B(19BK9(11 BiS91  (((1BBK[SKK9BB19(9B(111( 9ccS9Buo[SSSB99KK9119BB999KKK911(((( 9BKB1(11BKKKizҷc999BKBBKS[[ScocB9(19B919911111((111( 1Bcou[S[[[SKSSSBBKBKKS[[[[c[K[cS[[KKKBBBKSB9SzzSKci[9(19BKKBKKBBKScc[S[[iuc[KBBcc[cK911BKSSK1((1 (11991([oK1(   11191BB9BBB91BK9((1( 1BBK19cS999oicK9911BKBB919KK9BBK9(111 1SSKciS999KScSBBScouiSK1((99BSSKKS[SSc[B9BSSKSK9B9991(911  KS[iu[ci[S[KSSB9BB9BK[[[coi[SSSS[SSKB999S[SKo[KSSB1 (BB1(19BBKK[[[[K[KBKKBS9KcuiocKB9KK991( ( ((B1(KciS( (11((BKBBB9999111(19((9B9B11i91BBucB991911BBB99B99999((1991((1( 9iziSiiB9B9KiuS9BKKSozzi9  KBKBBBKKcccKB99(BScoo[KBB91(999919S[K[iizzi[[[S919BKKKSSS[iui[[[[S[SKKBBBBBKKKz[KSK91199B9KS[cSBBKK[iiocKSSKKBKcouiiSKSSKBB1( (119KK SSSB 1K(( (1(BKBK9B11BKK9911(((1K9 o(19KzzKBBB9919199((( 1 1111 (9i[SSB((11SuzcK91KuĦ[ 9( BcKB99KSK[[K9BBBBKS[ic[B9BB999BKi[K[ocS[iioiSS[B((B91KKKSS[iocSSSKS[[[SKKB9B9BiuSS[SK9K[K9BSS[SSKSSB[ucccS[ccKKS[uoc[[SS[SKSSB99K[K[io99KSB1 1(i191B19K[SKBKK999BK9B9( (9 (BBKuuB9BKKBBB1(  1B9( (19SioiB1( (1KcccoocB1ciu   1iuKBB9BKSSKB9KSKB9SSic[B999119KSuiScooi[ooc9 (1BK[SKS[[ccccSS[SSSKSSSKB9BcocS[cocKKSSB9KSSSBKBScKSc[[S[[[SSS[Kz[i[[ccii[[KKSSSSBKSKBSSB9B9Biz[1(9BSSSKBBKBB99BSKB1 (1K9((1[uK1KSK999(   1BK9( 1SS[[cS99Kcic[izzB[i[1B[S1 Kc[SBK[[ccSK9((9BKBKKSKKBKBB9K[[[cKiouicuzS91111(9Kc[KK[[[[cccSS[[[SSKBBBBS[[cc[[iiS[[K91BBSSKKSScc[SBB[iic[c[K9ocicciiic[SBBScSBK91BBK[SBSczc11 911KcSKBKKKBKB19KK1( (91KB9(9BiuS919KBBBBB91( ( (19BBBBB99Sico[9(  K[cc[ccoooKScB   1( (Kci[KBKcciic[B( 9K119BKSKB99Kuuz[SSoiuc[SKSS91191KKS[KKKKSKiucS[[[SSSSS[SScc[cccccc[SKB(1BSccSKSKcoi[SSii[[BKcK1ii[ccccooc[K9B[[B91(1 199BSuS (99BS[[KBBBKBBB91(1  1BKKBSi19BcB(BKSKSSSBKSSBBKK9Bci[[ccc[[iuoc9 (SicSSciSS[K  (   BiociSKS[uocccS9 (BKB99199BBBK[ucKKiiBB[uucB9B1B9S[SSSKSKS[SSiciii[SKKK[iiic[[cc[cSKK99BBScSKB99KB99[ooicBS[KBoS[coiiouoc[SKK[B( BK9BSS (BB9SSSSBKBBB1991( 199B1[KKS[B(9K19[S[KKKKBKS[SioiiooooiozuiB  [o[KKKocBK9(1(BuoSSciciicc[[c[B ((1BB919KB19KSS[u³iK[oK1Kc[ocKKB1BBKKKSS[SS[[SSiuzzuicSS[coooicciic[[K[KBKBKKKB9( ((9BSiic[S[c[KzoKcioooozzi[S91SK1  (((((11BK9B[SSSKK99(1911((( (19K1[c(KScB ((1KBBBB9KKS[[[oc[iiozoicuuc9( (1KiiSBBKuzSBB(   (cuiSBKSciioic[SScB119BB1(11(1KS[cS[icuc9BB((( 1KS[B((99B[icc[KKSSizzzcc[[ouuocccc[S[[S[SKBBBB1( 19KB9Bcc[c[[SBizciiioociuoiiK9KSB( (9K[S1 coB91(KSSKSB1(119((11191((9(19[K9( [cc1(19BB[[KBKSSSSKoizzuiui[KioS(  9ii[SSBSi9((     [icKBSccccccc[cS[[111 1B99999B9BKc[[icKB( (  1S[1(119BKKKSKScizzuuuiioouzicccicSS[[K[[SBBBB((( (BBBK9B[S[[[[SSuooiuocioicK19KS99S[[ii1 1K[K(11(1Kc[K9 (1(11999((1B91KiS ciK 1BKBBS[S[[S[KS[cioiuuucB[zzc9((KSccicS[ci9(    B[[SBK[[ccccccic[iS (1((119B91KK9BSicc[1 (91(   99 (11(BKKBBBcozzuuiouioo[[i[KSS[[SSSBB99111(1BB9K91Sc[[SSKSuooczcSSuuic999SKBKSScK (KB991 BcK99119991(19BB 9B11i9ci[ 1SBBBKSSKSKSKS[oouSBcccKBizB19KK[ioocoi9(  ((( ( 1KK9BBSc[S[cii[[S[u1( ((999KSKBBSS[oS1((  11   ((119BSKKSuuzzuuuouuuuiuu[[icSBBKKBBBBBB11((9KS99KB19SSSSSSS[o[[SiuccSB9[SS[[B11(BKB(9B1 1BSB99991KK9((KS99B(S[cc[ (BBBKBKKKBSSKK[coiuSBBSKB[iuoS1(BScoiioioS ( (9(  (BKB9SSKKKK[coic[[Si[1( (11(119991999uu1 ((11(  91   (19KS[couuuouiiciciouuc[[[[SKSSSB9((1(199BSSSKBKSB1KSSc[KBBSzuc[SS[uoc[K19Scoo[KB1(((1B9(91B9911119BSK1(9KK(1BB1Ko[Scc 1111BBBKKKKKBSSciooocK119BKio[K1B[ccic[o[B( 111 (BKKBBBBBBBKK[ccccSSS1((((BB19[[SBB1Kc(1((   ((1B9   (9KKSiozzouuzoic[[ccc[SS[cicSBKKK9B1(((999KSSc[SK[S(B[[c[[SBK[cciicioocioSKS91S[S[c[B  ((9999B99B99BK91BSK((9Bic( SoB1((1999(1BBBB[ccioioiS19199ScSB9[cS[SB99  ((11((K[SSKBBSK119K[cc[S[9 199BS99[iiKBB9(ii1   (1991(  ((9KKKKSiooiiuzucSS[cc[SSSSS[[KKKS[BB99 BBB9B199BSSScBB[[[SKB9K[[SSK[cuzzzc[SB(BSKKBBB1 (11B91119KBBSK91B[[( BKK1  zi((B((1BBB1(999Siccuzzu[99999KSSB9B[19(1   9[iSKSK9KB999BKKK[z91B919BBSicKB999KoiB(   (  91  ((19KK[[ciooicioiS[[S[SS[[[S[icKBK[iSKK99SSB119B99KKBS99KSS[[B99KKKBBSSczocSK(9KK91(19191(11(1KKBBBKKKBSSK99BB 1KK[i  (oK(KK9BBBB999BS[ioi[ccuui[SSB99BB1 (11((    (  B[c[KBK9911(999BKco191((11Si[S9199Kc[1  1   (  (19BBSSSS[iouuuoc[KKKBKSSSSSS[ii[KSii[KB99KKB99KSB9KSSS19K[KS[B99BSSB999S[occK(1KB9119K1 ((91(KSKSKKKKKSSSK1 ((BBii  ((((c9B9((1KSKKKS[c[SBBBKSiocKK[S999(  ( (11 (B[cSc[SBB999991 9B[[SK9111(1SiS191(BcS( (91 ((    (99BBKKS[coooouuui[SS[SKKBBBS[[iuoSSS[[SKKBBKB99SSKKScc[K1(BSS[KBB9BSB199BBc[ciS1(KSB1(BS1 (1K(9KKB[cK9[i[S[S9(((9ioic( 9 (K(99199KSBBBB[KKKBB99S[c[BB[[S9  (9BKSKB9199B[SSc[[SK919B111BKB9B91BBKKB[[K99(([B  (1(( ((  (9BKKKSSS[iuuuzcSKSSSSSSSKKS[iiciic[KKBKBKSSK[SK1Bcc[[B1SS[[[SSBB91B911KzS[i[91BSKB Bic1(1B1BSSBK[Kcio[cicSK 19 (999BB11B[SBBKK[S1199B19Si[KBSc[( (((1( 1B[c[K11B[[KKcSKSSKKSB9KKBBKSB91B11KKBBScKSB91Si 11 ((   1KKBBSSSS[cuuoiuSK[[KKKKSSS[[[couzuic[SSBK[[Scc[BB[[KKB(BS[cc[SSSKBKccB9Bic[oc919KS9 Kui 199B[[SS[uciɼ­c B9(((19BB911K[SKKSKK[cK19B911KicKScc9 99BBB1((  1KSSKBBBSooSKSSSccSKKB99K[SKSS91919BBSSSSB9((Bu1 (11   (Scc[S[SKSSScc[cucK[c[[[[SS[[[czzzoS[ic[K9B[KKB9BB9S[c[c[[SKScSK9Kzuci[K919[K1BB  9KScSBK[KSz1 999 91BKKB919KK99Kc[ScicBBKB99ScS19KB( 1SKB9BK91(( (Kc[SK99BKK[i[SKKS[SKBBBBKSSBBBB9119KKKSKBB9(([z[       K[icc[S[[[[S[[S[ciciic[SS[cozuu[ciicSKS[SK99BBKSKSS[[[SccciS9KizuicS9 1SB11( (KS[B1Sc¦¼uB1 (1911  BB1119BKB9K[icSciic[[SB9SK9((( (1BSSK[c[B1(  ([i[SSB99BKKB[[SBBS[[BSBB11991199((1BBSccKB9919c[    9Scioi[[SSSSSS[Suzz[cicSSS[cuzcSKSccSB9BBB(1S[iic[S[[[[S[[cozocB(1BSKB11  99SB1SS [iB 1KS9(  BK111(11BBSco[[ccccSccSKSB((9BBS[SSSSK9((1 1[SBS[B119999BSc[KKKB9B9KB911(1(((99KKKi[11191KK  (  (KcoiocKKKKSS[SScĦiSizoK9BScoozocccicKB9BKB( K[[ccc[iiic[cSKS[oucK9BBKKBKB1(( (9SSco(1BB ( (BB1  9B1111(19KKSS9([[cucScSSB9( 1B9BKS[SSKKK911( (11S[B9BB999991(1KS[SKKSBBBB9((99991BK9KSKcSB9BB99  (((((    ((1Sioic[SKKKKSSS[фcc[SuS1Bcicozcuǒui[KSKKB9((BS[c[S[ccccc[[[K[ocB 1BBBBBKSKB((Suoo9BB9B911((9BKB1  19B9(9B9199KKB1 (KK[zcKSKKB9 (19KKKSSSSSSSKK1B9999B[[BBKSB9((( (1BS[[SBBBBBB99B9((9BBKK[[SK9K[S1  ( ((    (1[iiic[[KKKBBSKcڷi9KzBB[uzoiuuǿcKK[[[[SB1(1KKSSS[c[[c[io[SoiK( (9BSSK19SuoK1B1 191991999191 1 BBB99((19K[[K (Bcciuic[K9( 9B19KK999BBKSSKKBBBSKBBi[9KSSB9111(911[iicSSK9999199119BB9KS[c[B[c     1Koc[[cSSKKBKKSKͰi1€[S[uzi[cuuzu¼dzuS[ccS[SKB9KKSSSKSccc[[oo[SiicK11 1KKS[1cKBSKB1(((91(1(9BB(( (1BBBB199KKKB9 (SiozzzzuicS9  9B9191(( 19KB99BBBKKBSz[Scc[K1(199KBKcuuSBKSKB9(191(1BKSBKBSiSKS9     (1Suu[SSKKBBKSS[[zz[KճoK[izzoc[c[iičciiicic[SKBBBK[[ci[SSSSKK[ii[[K911( 9B9K[(cSKc[B1  (111B9(  99((9999BKciS[1 KSouzzzccS9  999   9KB1(99BKKBSi[[c[SB(9K[SKBBKcic[Kcc91(9999B9B[SBBK[B9B   (1(   (BucBBKSSKBSSSS[z¢oScuSSuziccc¹uciѪi[zuzuuocccc[[S[KBKKS[[[[[SB9Sc[Scc[K9119BB1BcKSuoSS[91  11KB(((1B1 (1BB1SuucSB((1[cziiiuu[SS9 1  (111119BKKBBSKK[[SSB11SicSSSBBK[cK[cB(9SKKKBBKc[KBBB91     11(111  (czuc91KSSKSKS[[S[i[coBiccooǰz[SB[uziS[iSS[ouuiccii[[SS[KSccSKK[[SK9SoiS[ccSBBS[SK11S[K[uucK19((11B9((1BK99( [ocSS9(1B[izoiiouzcK(( 1((((11( (111((91BKSSSKBKK9KB19SccK9BB91Ki[KB9(9ccScicSB9911BKB  (  (B9111((KzuS( BKSSSSSS[SK[cozcooccicicuoizoSK[K[S9BSSSiuuii[[[[[[S[KBSS[[S[[[K1Koc[ccccSSSSSB19ci[cB1BB9SS (1(1191(19B((  cc[SK11[iozoccuc9  (9B99B1199KB11B1BBKSSBBBK9BBB9KKKBBB9119ccK99BKciS[iiSB9911BK9   (19991( (  (BioK(9KKKBBKSSci[SScucKBKSS[occiucoioc[oSKciocBcSB9czouuzucSSSSKSKBSS[SSSS[KKSi[SSS[c[SSc[9 K[S[iS1K[K9SuS(991(19((( (c[[SB Bciouuicic9  1999111((9KSSBKSS[[SSK11(1(9B91K9BKK91191SSBKSBK[i[KK[KB1119S[9 9ic91(1czK( (  (9[uo[9 9Sc[SSS[[SicS[ic[SB9BKoKBi[9ziiiS[c[co[SizzoSiS19iziccccS[[SSSSB19KBKKS[SSKco[[cSSSKKS[SB9coui S99919BK1(1((9B9(  ( [SK9(([icuzzii[[K9 9BB911(( (999[ioiic[SB911(1B111919B191111KKS[[BBKSSKBB9BBB9SiK9iSBBSoc1(  (( ( 1K[ii[K(1B[[SK[iuooo[ciSBBKSS[ooo[9Bzc[K[ouuoccooKK[K(1iu[KSc[KSSSKSSSSKSB99KSKS[uo[K999BSS9BKK9iz[B[1( (     SSB1 Bcoouuoi[[[9   19B991(1( ( (1(9uo[ii[KK[SK99KK999911((((11BSSc[SK99Sc[K99KK9Scc1(Sicuo[99KSSB9(( 9ouuocK11BK[c[izzcK[ouiKBKKS[S[oSBScc[coiioouuuzu[1B1(1ci[[[SKKSS[SSS[SKKSKK[[KSci[S9199KSK99BS[ouB    ((11  [K1 1Siozuii[KKS9((11KKK91(((( ( ((KzcS[K9(1Sc[[ci[K91(1( 1(((((BS[cicBK[cSB19K[SB1 (BoiioK9K[[KKB( (11(((([zzuiSBKK99S[iuSKczuSBS[[[c[ScuuKBSizouiicic[iuzoooc9919BKS[[[SSKKKKSSS[SSKKKKS[ioo[SS99BBBSSSBBioK   KBB1  S1( 9ScozoccSSK9((9KKKKK9  (((9S[BB991(Bc[B9KcSK91191((( (((BSKSccKKS[K99B9  (S[icB(19B99K91(1(1 (oc9KSK99K[izi[ooc[KBKSKKSSSK[oo[BKou[K[iuui[cS[izSKK19BSKKSccSKSKKKKSSKSK9KKKKKiucc[SSSSK999(9[z19(  ((( (BSK1  (((( (K(19K[oo[SSK1 (((   1SSBBB919cc999KSB9B999(111911[oKK[[[KK9(991 ((( 1S9((((( (( (9BB9( 9zcio[119KSozouucSSKSKBKSKS[BKiiSKcz[BS[ouioiiuK(9SK99B99Sccc[[[S[S[SKS[KSKBS[u[SSSSSKKSBBB(KK     1BB((991(1119B1(91B9SK[ouziSKSK1 (((1BKScK11[iK99KKBKc[B9B9991Bcu[KKK9B99(9(    (1  1BSKB1(((Si[uu9 (9S[couocKK[[icKScou[KSiiKBiSKSiuzc[ooooio[919SiS919K[[S[[[[ciic[[[[KKB9Sou9SSSSKS[KBKB9oS(1( (  (  991119911( (BS99KK‰iozzcKSSciuoc[[(([z͖B[iBKKou1 9BKKuuB(SiB1BScicSKKSK91(BSKKSiicSK[[9BBSSBoi[SKiuSSc[ozcSK[oc[ouicSBKic1 ( 99(1((9[zzizɷcK 9((199SKiocBK9919BSouK9B9 (9(   B[BK[S1  B¦zͳBc[9BK[[z1(K9KԢc19B(1((9SS Sz1(K[KBBK[[S[[S[c[S1(1KoiSozicKS[KBKKK[iuzioiio[cizozzi[Scz[( Si( ((9B9   (9[ozuuĖK1  1B9K[i[[S[S[SB( 1B[KSuK((919(       (  išuS[SB9 Koc([ޢ(  ((9 1 (9BuoS91((cuc1(9K[SB91199S[SS99BSouicuuocSSS99BKcouuuoiucSccSS[[[[izS((BK1 KK9[uB ((19K[uuo˷o9(9 1BB9KciKBBSB9(( (1( KocccSK91       (( 1ijiKzcKB19B[[(o¹u ( (B[B 9B[[BSB1([[cuc1B[SS9B9BB9   19BKB199B[uucozucc[c[9KS[oozouuuoiS9 1BScuzcS[SB99 1SB 9K(  1KouciǒB 1K((11BSi[( (( 1cizi1K9      (͚c[couKBBKooc91Suzi(1(  1[z99[ciiuiK(((11K[BKKBKK999(  (( (19KBBBBBSciSuuoooiiSBBSico[uoozuzuiS1(1((9uiK9i[  (     (( 19Suciĭ1B[9 9Sc9 991(11 1Kcoociu[         ĒiBcuSBSozcio999S[K[iiKcc(( 1( (9iSiucS[zcii[SKKBSiou[K91((1((1119B9BBBBBK[c[SuzoiiouuB1Kocziooczzc99B1 BzK1 SB  (( ((( (( 9zu[[cSK 9cui((19BK9111199[iooiucuc1       ͿǦS9ocBSciScocSKB(1KK9B1 Sizc   1B1[cSKSuzc[[[iiK9199K[SB999199BKSSSSSKBczouicuKBSccozzooiSiizzciizui[uK 1( KK (11 ( (((( Su[KcBoB 9ciB( ( 1[zzzouzziKSSK191     ((((BǼK9B[iSSBB[B9Sii[( cK19 9o9 ( 1 ĦSK[ci[czo[c[S[ciiiuoiSBKSciKKK99119K[SS[SB[uuooicoiBKBSccuzoKBSc1[oiuiuuiK  9S B 9K1 1  1(((11(KicocSSǦ9K[( 1(1B9 ( ( 1cucuzuuuzK(1SK[zoiBBBB9( (111( (B9 111BSciɷcB99SKK[S9K9 iozz19ii9(9B((  SK i[1KScSKcSBco[SSiuc[i[BSSSioSB9( 1199BSS9Kiuiiiiiou[BSozcoic91K111B[cc9 9B(  (9 11BK( (1( ((( BuzuuuoiKuoo( ( (  1B[uucBB[SSczzzoKBK BBBocuiii1 BBccci[K[[119KSKKK19 iczS99K[1(1Ko[(99111 Bc1 9oS99B91K[SScSKSooSKSBBc[KBBSz[111991( 9KBK[iiciuozzzuocoouuu9(1B9BK1 (  1B1 1[9   (  1999KzziozzzccS  1coSizBSuoi[SB( [¼dz[1(9[SzozzSu9(1((BKK9((1iouS((B1K(19[[[uB(99( BK(K[B 19Kii[[K1BooKB99BScS9BB[cB9B[[9111KKS[[coiiuuuzuooiou[1(BB((K   ([S(99   (9SB9B1[oiu[oĀ1  1SBK[iSSzzuK1 1Sij­uui[ccSciuzu[KBz11999KSS( Kiczo S[11(19[[[ouB (( ((991S (1BcuuS91[u[91BScoK(19KKBBScS111BKSSS9cziouzoSiK[c1KB9(   (   (9cS (    1uKBBBooiuii€    iuuzo[ozi[K1   19SĪz[uuoK[i[K1919((K[K((izcui 9[K1(9BK[SiK  9KK SKB911K[KK[S9So[11BSiiB99Bc[91KKKBKKBBBB99iu9(SiSS1B1 (B9     (KSc9  (1((11( BcS1 BizuzuuoB ˦[Bc[1((  (9Ku³zǦzoSBSiizoc1((( (KKB1(9ci[[B9B9( 1SSooKB(1KS[iB ucScK[[KSB99111( (1((9[S[S9991ScB1KS[c[SK99KBKioS1 1911  (B9 ((    (B[SB  (99BBB91 9KcB9(Sciuoiuouzi  oͷz9 ( (91KoİiKuuzcBBKooBBi[ii1 (  (11BKSciBKKB911 (SKKoc[B19cu[9 iiB(((BKBS9  ((( 199SS9BBBK[K(Bciioi[BSSK[oc   (BK 91  ((((1B[K9   19BK19B9(KSSc1 Sc[cocouuuz  ҷךzu  (( (11((19BSoǭK9o˷zocKKKzuB(1B9Su9( 1 19( (991BicB1(1BcKSouuK(iu (oucS9  19199((199919c[919KS[[99[[S[i[[ozozoi[B 1 1KSB  199(  (1199BS919 1((11 (9K1BBB( (( BKSc[cuuzzB 漉zi[ 1911 119BB1SKKcɚcicouK9 (1B19oK  11(BK9KiS1Bou( 1[S99[z[1( K 1iu[c[9 (BBK[[c[SKKKKSB(1BKBBKSKKSB1[SSioccuzi1(1(    (K[[K((99  1919BScBBB (((91( 9B1BK9199(1SSiuooz¿z1( cϭ˦[[[B99(   [cKicuuzoco[u[ ((19B19[[B9(1B9K[Kcz[1[o  KiK((K( 9B  1[uiooc9 (B[ciic[[cSB9BccB9(1KBKSKSSKScSSiucSc91 111( B[ooi[( (((KSBKS[ccK1 (111(((9BBK[[KKB99Scuzuouǹi ѹ[„99((    9SKccuzzcKuoSioc9 (11SS9c9czi11SSBKKizcKz KicS11cc(19(  19[zzoooiS11B91991(9B[BBBKc[SSSKBS[KKc[cccuo[KiK1 ( ( 1ScioiK( 1( (9K[[cc[ccB  11(111(1KKKSccS[[B9BSuuccu˚ 9ҦizB  (9[cKSSiccou[uziS9( (((( BS(S(1KKBK[iS[Soo9(BK9 (KoucB19ic 1B1Buoooc[11(  ([KBBKKK1SB99KK9K[KKKioBScS9( B[[KK[K  91   199Kcii[[K  19( ((19KKSKKSSciK9(czuuciozzouKcҷuc[   1oKcczϼSiuzocociu[B(  SS(c1((9KSouocKuo BiiiiB SuB   9S91iuiic[911( BB1(KSKKK1(( 1KBK[ouiK1    9iiB9KB 1B9( 1K919K[[SB( (1B1 (BBKKBBB91119uuucuiuzzz1oĹz(  99ScS9119KzSoiljKSBKozioS( (  (1BBz (9 9cSu ((SocK[S9oK   1(KiS[[K911BKBSS91SKBB1 (1[izz[1 (( 9uicSBB1 (KK9 19KB119SK1  1111  (119BBB((1111B[uzoozuuooo1[[Su9 ( (SuoicKSciuucooĉBS[zzciK 191[ 9(ooB[iS9(1SciSKKKcB 1( 9 ( ( 1uiScccK99KK9KSBK[B1  (9[ozzucciiiS9KB( (( (1( Bzzo[[KB((  99((9KKSB1 BK(  ((1B( (11111((1KB11(1ozzz[iuuuuouiicKSiz  (99c[iioic[ooocuiuoK1Soi[SK1(o 19uiczBBKK9 (((coSKB999919((SzS   cociicK(9K9BKBKK1((1BSouoiS[S999( ( ( (( ((((  [oS9BBSK(1( (  (1(19BKKB191BS (11(1(  ((11(((9KKB1( (Sozu[izzoc[ioiuoBo1  ioioi[uizuouoz9( (u 999BB9(cSBKB(  [oSB91  9K 9iz[   9uooiS99BKK1 111BSiuiK[cK1  (11( (( (  [o[B911KK111((  ((9999K99BBKSS 1B (((19(9( ( (99KKBB1((1Bczo[iuuocooooiĒ ([1((Siuiuc[ o99B9BKBBS9(1   (ScKKB( 9uc  KiS   (ozoiSB1111((99Kziccic[1  1B9( (( 9c[9(( (((BB( (99BS9(1BBB[[SK9(9991 (1B(1 (19BBB911( ([occoozuuuoi[zϿo(K1( 9Bo˪z[Ҟzɚoiziu9  1(1K9BSKSc9(1( BSiK[K 9c(o1 ( ([zzzc1((1Sou[SS[zK 11(19( (1B1 ((199  [iB(1111BB9 (11119S[K19[oc[SB1(1BB   199(  (9BKBB9( (( ([uS[uzuzui[iɰS1KB91BuljSSڷoҼucuzuuo9  u( 199K[c[119 9[SKBB91Bico1 (Sc ( ((( 1Soiciuc[ccuo[KS[cz[ 9[[SK( (191(((BSK((9KczcBBBKB911 (1919K[SSBSio[K1991 ( (11 KSKB99B9119( (Buo[ozuzuocoͼo 9SK99[žiS1cc[ĉ9[cocK    S (SKBBKSK9KK9( (11Si[99911BB 1K9 (( (9[cc[couzzuooi[SK9BKccioK (KS[[1(11191((19BcuKScc[iuuzzuiiS11 (911(1K[SSKScS919BBB (  9K9 Buoi[KioS9( (Soccuiuiuzzi[ɳo9 9[[19BzoBBǖB1BBSoo[9     ([ 9[B1 (11KB((( (1cz[191(  (91 (99Sc[KKS[[[[[[K99((BS[K1 1coi[B (99((1[zuoSKiiSBKSiuzo[B Sz[KBSSc[ccS1 (111BB9BBiS co[cizc1 (SicizcouzuS˄(1KSBBcB (ci1SB(9BKcSK[  (919BK1B9BS19((9(K919 1B[o[9cB       (911K[SKBKKS[SSK9((1BBK9 9[uoSB11 (( 9oKBSc[K91KcouziiK   (uzSSS[izo[S1 (9(11Bic((cccS[i9  (1(Suoizzzz[ذS(199[i9 (9 BSKB[c    (SoKSicBKBK11KSKB9K99K99Koc[SS1B   (9B9((1S[K99BBSK9( 1cc1  [occB 1  (1iu[[oiccK9[iciicc[(  ciBKScoc91( ((((( (KcB9Szo1( (9  KzioziczϹo1 BB(  9uS119SK9BcS    ([zoiS[iSBSz99119KSBSS(1KKK[oKBSc   ((91 (K[S999BB1  9iz[  (KS991 1  9zoic[BBBKcooccS1 KzB9K[c[( ( ((  1S[c[uc1  (  BuuoocicouzĒu9 1(  ([c[B19K1    S[ozccicB Kzuiic1((1KKKKK9(((((B[B9S9 91    9( 11BKSB119(B (1SB(( 1B9(((9  1 9iuooii[cccooic[[K(  (cBK9K9  (   1[KKScuz[( 1((((  Suiuzuc[uozɿķK 91  1B( Kc[S9(   (1KB(11 (uzzoiSB1KziKB91 119BKKB1( 1K(19 ui    (1 11BKKKB919( 1Bc  (( 1K9 B9 ((11Sc[[Sci[KK[oc[c[9  KBK[S9 11 (((  (Sc919B[i9 1ScK9(1( (1[coucccouuuѿĹz1((11Bii (1(   (BKSSi[991BzuiKBK9SzoiuiS KK11K[K(11  KSBB9 [iziB1  (  1B9B1BKBBKK91BS11  19B((S( 1coziS[[B911BKK((1( ( u9KK9 (991((   9B((9KKS[oi[SSB9(1(11(SooiiiciuouͷǰS19Bطi(  ((9[[[S[KB9KKKB[zuiB11(KKcS99K[S9S99iSKi9(( 9izziz[1   (( 9911(119SicK1BKiS (991( (9B1 Kc9((Szuc[S1 91  B9  (((9([K[1 9SSB99((1(   9iicozKK9999B( Biciuuuzozz͹ϖB(1KKݚKKS9((B[oiczcKB911SS[cuzzoS9(1( c[SB91BSKKuS1iz[1K9 9[ziizucB  ((   1BoocBBKB 1911(1KK9 BiB 1coi[KB  9[K( BB(   9BSS(  BiicS9(((1(   [zc9BB( (1BB1  Kccccooouzuozͼͦ˞K19BiĖzcczo[91(Boo[uS1  (zoo[[9( (9B[z((Si[B((1 1ocB[zziS1   (  1Biuo[KS9 11 (1(SS 1[K19KKKB9 (Sic9KK9 ((  Sc1K[SBKB[c[ScS999BB1  ((1KciozoS9  (1( 9[cccououou[SҿzKoϹ9 1K۪oo[9119[zc[cK  9ooSK1( 1B9KSBB[[[cK( 1oi11o9BB    9Scuucc9( (1((1 c[   BB11K[[BKcc[B KSB1  9B( 1iocKSozcoouoouiK11KSK1 (( (B[iicoicSKSS11 1KSciooiouuio¿BcSǹ9 1cǞiozoK991BSS[cu[( SucK[B1 9K9BuB B9KcKBKc[((Soc BҷS   (BS9 (K[[ioiiS( ( (11c1 1SS9S[K1K[[K1 BS911 ((1( (cc[cSSouooooo[BSocK  ((1K[KBB[c[[B991 ((9B[icouzzuuuDŽKoSiˢoK1i׿BuuiczzicozKBBSKBBczK111(  czKc KB(1ioK( SSBSBBSS9 KS9(([[   9[K(KKSiioc[[B(( (1 9z1  9cSKcB( 9[c[S K[B ((( 9zicK1(9Kii[[c[[SBSi[9 (BB91((91 (K91(( Sicozzuzzz[i˿i[i[[ڷ[(cҿS[19KK1BS[S9KK9iu( (((199(1zuzouz(ф(K(  (KS[K9B(19K9  (11       19(1B99cuoc[KBB( ((1( (u9  1cSKK11SuiK99SB( 1   1uz[91 1(1((( 91((9SK   (99((((  (B91( BoiuzzuiiKSĿoccSSu1[dzSoc1 (Scc[( 1SKuu   SzziuzπKB   Ko9(((1(([B    (( (1111KuzcSKBB1(1(( K[  KKBK9SuBB[KB(((   1c[K9  9B9 (191( (9  ((  11((BSK1((  (11( (1(KcccozziSiĿuS[[ciщ(o¦c (9KcuuocS9 (Siic   cizoz9¹u9 co9 (1BKK 1(  ( (( (  ((19BiiSSKB911( 1S BBKB9ciK 9SK11 (  1ouKB (B[iSB1K91(  ( ( 1BBBB9SSB( (11( (((K[[uuc[u˿oB[co[ͦSiz  Kiocuu[9  Sou(    (((9oucioozcSiuKS( K[B11( Bc9  (B9(((11( ((1199BKco[SKB99B9 ( (9ci9 (KBS1(cc(KcSB1   1uK11SSSicB(B9( (1(( (9(KB1((   (  ((1[uuzzuiciǼi9[ui1KհuS 1ciSS1 1ScK[z (19B9999KuuiiuoiSKSKcu9  oS1 199B    (  (( 1BB991 (9BcuiS91BKK9(((1BB 9KB9(1BB(Kc[SSB   (uB (KSKKKB1(  111  ( 1BB11((   ((( 1  Buzo[[c[¢iK[cB(9Ǫou( 99KociiS (SK9BSKBSuz[  ( 11BBBSK(11BSuuoiooii[S1( 9cB 1(((       ((  999B911(919SicKBKS[S( (( 9B9(((999[[KK9BB(    [i  9K9199( 1KK9( (99(((   ((K1( 1iuuo[9KcS¼zzuiSKBSi[ĉB1(9BBBB1( K[K1BKB9Suo[B 1B9119BSK1(((1czzuioiicc[( 1SB 1B9    1 1 1B1 (1SSK99(9 ((9Sic[SccicK((  1BB1 9S[cSBBS9    u( ((1B9199   (((1BSS1  (1(1( ((B991( 1(1ouicc[[SSɳuzuucBBSB9[9 11((  ( (BKB1BSKB[[K9  (K[K1((11  (Bπooouooic[  1Biu1( (1(   B[((19((1(1 (BKSKBKKBK9 9BSKSSuzoc911(  99 9K[oc9((1(  KS 9BBBK9 ((  9(1KKK9( ( 19(  19((991( ((1[uoouuoS[ǭozuB9BBB9KuB ( 99 (1(9KKBSB1( 9B1 (  (KcčuoB9(([ooiozB( 99(  1K91(99  ((BS[SSBKK9B919S9B9BKczoS11( ((11(9KcKB1   uu( (BSB1KB11(   BBScK( 1B99  9cc( ((11B9111BK9 (9[ciiouooi˳iooiu[1K[99S(((ioiB1 (999( ((  (  (1Kozzuzic99BuzKci111B(  (SK99KK1  19B9ScK99B99B9B91(9BB9cuoc91(  ( (9SK99 (  1i1KicSSB1((  ((ScS[B 19BK11 (BizSBBBKKSSSK9911Soi( 9iSKcizou[¹ooioziK[c  SK 9ii (11SS1     1 1KSK[ouoziccBϚ((9SzuKK 1((   9S99BKS( (11SB B[SBBB119BK9( 1BKSScoS1( 19SSB (    cS 9ScoiSB1 (91   1ci[S((((( ( 9ciicSKBKcouo[K91Boc1((1[[cuuzcSSͼzuuiSS[19((S( 99Bic919SSScS     111BBKS[cccccucSKz19S˞S1 19(   999BK(( 11K9(9K91BB999BB1(((9KKBB[ucK9(  9911 (((  S1 o(9SicS[K11 (1( Bc[K( (1  1uKKKBBKS[uu[KB1[o1( 1Kcuuiuo[uϳzzcKS1z99K cBK[[SK1   11B[c[ciSKcSS[BuSo1˄B( 9     BB99K1((1BB111((99911991( ((99919[zoSB111991  ( (9oK  KS(B[c[KBSB911(( (ScSB(1K1    9uo[SKB9BSSioc[[SK[u[(1((1Kiicozϳzuuo[ooo9(c(c1BcS1   (BKiuoiic9KiSBozBSc o9    BB99991 9KSB1 1B911B11(11(1BKKBKcozi[SKB911 ([B  9uzK19BS[K19BB9( Bc[BB 9B  1S[ccSKKBBBKSc[SS[[S[[B(( (9[uuoi˹uiuSK1[(9 ( 9    9ScoucicBSucBBScczɪS91 ˦i( ((((BB119B9111BS1( ((19KB1B99B9KKBSozzo[1 (  1B1  (  coSBKKKSSK9 (  (S[cS( 1( 1((BBK[i[BBB999B[[SSKKKSK((( (9[uozuªcoc[ou[ uz11(([[uu     BKiu[K99KScoSKBҪK9Sc9o1 1 BS9   99( BKKKB99( 119B( (911BB11BKBKSSBKK[iuzi9 (  1B   (czcB9KKBKB(   (BSSK9 (B(  (((11BSB9SccS999BBKSSKSKK[cS9(( (1(BizzzuoB9o1S݄ 1B1    9Si[KSK19SS[SKBKS[׿c((B(Bc( ݪ1(  19 9SBK911(( (9991( ( 1BKSB999KKBKSKKB19SiS1( (( 91  (iuiocKSKBBB    (BKKBK (1( ((9B11coK19KciSB9BKKKKK[c[SS91(1191 1S[oz°c1(uzSፉS((1( (  B1 ( 9co[SK1Kz[KSS9BSčzu991 [ (K1 (1(111K9 1c[KB1   B91  9KKB11(9BKBKBBB9 1SuzzoK11(( 11  1SocSouS91(111    (9BKKK1 ( 111 (K99ou[KB9BSSKB111BKS[[KBB919911  9KooǿiKKzc[zu ((   1( (B91BKSSSS[SB9uzcouSB91zz[9( [ oͳiK (111( 11( 1B1(BccB19( (   (1B91( 1119BBKKK991(1KiiccuuiS9( ((  BiuS(9K1      19KB91 (1( 1KB9KKBKK99BBB9( BSBSK1(9K[SK1  9izc‰1BozScoSz (9119BB(9999[icooSiziSSuuouzcBBB occc[[B9 oS9BٚS(((  91(1((  9KSB199   (  ((BKB( 199KSBBSSBBKB9K[SBK[uuc9  (1 1SK91(((     ( (9B99((B991 (119KKKB1( ( 1BB1(1((Bc[B(  1[uuKiǭcS[cB  19(B[u[91Sc[coucioi[SK[iiB9(11Si[SKB91B(1 (׹[1( ((9  9KK91(   (9BBciS (9BKSS[[BBKKKKKKBKB911Boc(  KB  1( (1( (  1BK9B(1B91  199[B1  (191(    1Kczoo·ouuuzu1B( 1B9o9 [uicccSSzoS[c[iu9BB99K[cKKKKK(9(1B9ocuS(1(    (9B9   (999B1 19Bcoic[SSK99BKBBBB1([uzi1((9K(  (  (    9[[SB1 1B9( ((9c[1      ([uoozͪuoKiz  ( Kii1cuuo[SKBBuiB9cccuuBSK11BiccSS[K (KSB19(     9B1((  91( 1B[B( (1KiiK9BBSK999B999B9( 1SozS1B1  ((      BSuziKB 91 ((BccK1( (1(   9( Soccͼ¿uSu( 1KiK(BzSBiuSB[zu[9KBSo[B19BBcB11S1(19uSSK (    BSSB11c[(((91 (9KSK( 9BBK9((11999B1(((1KizS1(BB  ((    9iioc[K1(1  9couzii[[ccS1     (K9 9iiczѿuzז[S19iu1[S (K 9czu9KcizoK(1 [u991199BKzu99i91(9cKic      1B[K((( 1SSB( (BS9(99KBB1(11 (11((B9(1Souzi1BK1  ((    1[iBBK99(B  1(9zociooi[[S9(     1(11ic [iSzͪ¹ocBu[1KSz (1 (1KcSKzciizS(( (czK(999BKKB[uccozB 9ci91     9SS91(11( 19    (1((11SK911((1(((1 (9KBB[iuuzocB      (1( 1KK19B9 19  1KiciK9ciSBBB(    99B9cB( KS[zzѷzэiKuK K 1(((19K9Suucoz1 1oo9(1(KSBSKKu[SKcK1 (BScK  1  9BK99(911( 1(  9cB  BB1 11(((91 (99KS[S[ioiooi9( ( (   (( (91(( (1 Kšui[SSKK[K91   (B911K1((c[zͿoSuoi[( 1[K(9B99((S[iiS[iiB(ic 1[o[cSB[[cSKK19Kc[  ( 9B1(  (11KSK9B1(((1(1   (1zB( BK1((991 (11111((11Si[[iiSS[cS9991( 11 ( ((  1(  11    (1 iĭccziKizSBSK(   1(91(1SS(Bc¢999SSBc[zi (11K[i[9  (BSSB( BSu[((119SioK1uKK9B99(BKc1  (BB91 (1BBB9SK9( (91 1  BBKBSBK9(B1((11111 (991(1ScKS[[SSSc[KKKB1(11991(( (1 (((((((1(    (zz[ii[K[iS[K  BKB1(9KiS([zžcc([oS(BooB9[(1i[19uoKKK9 cucB1(19Soc91B9999B KSS (KK9991 (9KK[iS9 ((  ((1 1SK[Scu1S9 1( 19B9( ((19( BS9BBKBBBBBKKK9(((199911(1( 11191 (9   9Sc[9(19coKK1  199B119Sc1i¿iBSuuzzc[9(([oc1(K[c9  (111ciKB9ii9[iK1 coB ( 9BBB9111 (BSSc[911( ((  ( 1KB[ocoo(9(191 19(B1 ((( ( (1B91BKB999BSK1 (1((111(((( (9BB1  ((   SKS9(99111   9919111[ϖ((K¿cuzzizǞKou1( 9uo9 1iuzi( 1K[[uuccBuuczS 1 (( 1B19911191(1K[S11119(    (Bcc[cB1K9 11(1(((1191 1( (9B9B9919BcSS1 BB19B1B9B9(((B1(   11BB(1(  Su[[SKS9   (191199BKo9(1[ķoiuucK9BSiuļicK(B[ic9Soo[( 1BiS 9Kiuziuuii[[iS1z ( BB991((BB9((B[B( (11  ((   1119B 1B( (911((91(191 11 ((1999B9BS[B99cc99B9SK[B1BB1  191BB1((  [z[[iS(  ((   1BKBKBBBKo[KKiuzS[[19119[uu1 (Kzz[[1(cc9 c˪c (19BBzoiziSKB1 K   (((B1(1( 1KB9(1Sc9 191  (   (1( 1( (9SK1 11911(( (( (999((BBBKSK[zzK1BS[99199(   1B19B1 (  ciBSc9 (1(  (19(9KKKKSKKS[zzciS[KBcS19cuiSc( 9ScoϖB 1BBB99ocKziSK9([   1( (911191(11( 9[K19((91 ( (( 1( (91(( 9K( (9(K9((( ( (B1( (9((Kiicuc99BB 99      ( (( 11( (  c[1B9 (BSB( [o[B91K[S[S[KBBSic°iKKSKB9Sio 1[  ( uz1(KKKK9SuuoBzuuzi[S9 B 1B11(9B9 191(  99( 91 (91 ((  1B (((9( ( 9B(BBBB91 (((11(91((11 (9SozuiB11BKSK9   (( ( (((  (iB((  1KoocB    iiKS[ccSSSBKKK[[iϭ[[K11Kiicu 9( B[1 [BocB9(Ko99So[SSKc[KKzoiKSK9 (B (111(( KSK (B1( BSB1((191 ((11     (B9 1BBK1((( 111( (19(1 1 119SouiSBKKc[B9(  (  (1(   1[9((1occiS( coiicc[icKBBBBKcoSѼoS99K[cSSiiuc( Ki1 uo( 11Ki[[[SSio9BczccKKB(9191(1BS(1BB (KiS91K[K191(  B(((      (1(1BBBB99(( (11191(  1( ((SciuocKio91     11( 999(  (uuK[iB9SK99KSSSi[BScic9BSioS( (9( u9KKBScSBou9Soo[[KK(9 9B1 (SouSBKB11ScKS9BB1191(1  1     (( (9 1KB1(((( (1(111991 (( Bzu[Sii1       K9Ku¿o (  (c[B[zuS99K[KKBKSSuiKScouoSS[cooSK[iK9(    S1(([S(Sio[Buu1SuoSSBB 9K  111(1cuoicK1(1S[999 (11 (1(  19  9911( ((11(( (1(  1911B9BB(  1uc9111(  (       S  iB ( [[B1B[KB99BKKBKcSSBB19[SciSc[iciccSB[9  9K19[ Kzo[SuS9uzi[KB(KB(( 91B9[K[KB11K[S9(111(  ( 1   ( (1 9KB9( 991  (((( 1(9B9   (ii9      1((  S( (Ku    (KB99BB999BB9B9Bcu˿B(1cu[1BizoBciuzocKKBKB   9K1(1zKiz[BSuK[uziKBB    19B9[BBB1 (BS99((( (( 1( 1 (( 1[[1 ((1 ((       Kzz[9(   1( ((  K9(9oB   (K91999((1BB999Buu[i[9BKScc[iicSSSKKK  (19[ o1(iBoiuoK91 (1  (((1919K9BK911(9((( 1((1(1 B9999 1191((99 (1((11B1( (     1SozK1   1K9  (((1  S[ (11oBS9  KocB1(1 (BB99KKuzuu°B BzzuiSKBKKBB91   9((i¦z9Bouco[[oiB(9[ (((99199999BBBB1(911 1((91  1(S[9SiS1991(  (119BB991111 9B((91    1(  1[icoK ((( ((  1S1 (11( 9[( 19Szz[9 iz[BBB1 91(BiiozoooicijcKoKuucKKSKB9B(  99cS(1B(BizuucS[K((  ( (BBKBB1(19KcSB1(11 1(1991(9K[191 11111911( (11S[uuiB1 (1  (1B9  (1 (11 ((B1Bcc[ii9191    91( 11( 9u[[c[Kiu[zB (9[ucS[S[K1((K[z[[[icouzu[cB(cSozzicK9BS9   ([[KBoǼKBuooS9B1  1119919B9119BcuS1(111B9(((1 (KKcz(((1BK19BK1((((([zu[ (1 991(  9(9B9(1((9(BS1(KS[[i[(    1( 111( KuuS9Kuzoi999BSS911[ozuoucoSKK i BSSuoSKB9   (KiS[iK9[(BijzooccS9((( ((1(1BKB91 (K[[BB((1BK9B(( (B9[(  11[i[99S[B9( (B[iu[czB9KK (19((9BB9(9919( 1S9BK19KKKS[1       1911( 1i[91Bzǀ[K1 91Kiiou9((1(99(11B9K[[SKiiSBS1( 1SozioiK9     B1SK zǼzic[KBKK(S1((( (BS9BK19ScSSK (119BS9B1191B  19B9[ucSBBB9SS99BSS[iiK[uo9(B1 (991 191(((BK (BSK1(9KBKKio9(   ((BBBBBB1 ((KBB((( SoKK9191(1 19BKSo˰c9SKS1 B 1SczoS9    9S99 9Ғic[[KBBci9 ( 11((1B9199(Koc( (( (91(9BBB9  (ooi³zS99B 9KKcuoK[ou[[zz1(11 ( ((  9[[19KK911KKKKKcu[B     (11( ( SK SB( (((SS[B    (BSSizu1SK((B 9[uzuS(    9oK99 ɿcS1BScuoB K9 ((91 19Sc ((  (999( 91SoSS((1(119Kic[ci[Sooc9 (91BB  ( ScoS((B[S( (9B9BSoic[KB1  cSKK9(   ( 1(1SS9K9((1  1SizB(   1BKKSͭS9z9K1    K[ccB1(    9oK KSScK1 [uoS1 B9 (199( 1KciB  (1   1K((11(((19SiKSK991 ( (((  9c[B19BS[9((19911B[SBB[c[K9( 9BKicSK991(  (( ((9K[BBB1( (9[ic1   ( 199K[idzoަ11z9    BSio[K  ([iuSiB[B9KKS9 S9( 1(191ScS        (1(    1((  (S9B99SS[B11(111(1ScS999BS[S19BBB9KSKSKBKK9999( ( ((1BKoo[K1999111 Koi[9(  (B( 19B9Kޞ (uK    1Sc[S(   ccS[9Sz1 zS     B99991(11KS((    1B1      9B91BSuiiKKi[919B119(((SSKBBKBBBB(99911BKKKB99B9BK99191  ((((SzoS99B91(1(KiSB( ((oz1((9BKKzzž˖1(cS   (11191 Ku1S1ou[o(  191KK9(9BBB9 ( (   (1((    (1( 1K[iSKSiz[1911(  11BKK9111 (B(B(((((91199BB9B9991Sc9((999KzĪzS1(1  ((  K19B11K[  1SSccBuB cu   (( 99KS1  9 1ci    199BK(9K1 (KSS9 ((11 (     ((     ((( (19KKB9K[K( ((1 (( 19911  ((B199111 ( (((1K9999BK99KKBzzcK1    S9SB  (9Bii19 1K SĚ  ( ( 99KKB(   (zuBSi    (199BKBK1K1(BS9( ( 11((     (( ((99(   (( (9B1(119919119K9((1BB1( 11119( ((BKBB9911191( ((1199BB9Bc[KSuii1   ( ( K[K  (Kcc(111B(SĄ(( 99B9BB(1    iKcu[[[i9  (19B9BBBBS9B11uSB  1  (    (1((1     9K(9KKB ((19(  (( ( ((1(  (9K99BBB9111(((((11991(1Sz[Kc[KKo    ( K1[cK  9Sczzc[99[B9(B‰1BB   (1(9BBB(1( B1(B191c[ 1199SS[KKSBB99Bo9111B   (  ( 1(    (( ( (B BKKB      (1  91 (9KSiS999K99BB999( 111119KS1 (       (1iKKo9(B[oiK1( 9ocK (¦11K1 (1 19((999((1 1K9K9( Boo9BBS[ic[S[cSBBK[z((1   (1   ( 99111   ( (   (   119BBB BKBB( 1    ( (1( (SBS[i[BB9BBB99K[KB991   (    Siz11cK(K11BBKS[S1  9K B(911BB9191 (19SB99   1KB91 (1[9(99SSSSSBS[SKS[io   1(  1( (BKB1B1 1(((1111  ((1(  (1B9BBB9( 9KBBB9B((( (((     ( (K[BSSc[SS911BKB9[c191(      (1Boc1 SuKKSS[[S(B199 9(19999BB9((19(1(((BS91(  (19999111[o((BcK1B1(9BSciooo(9( (9(  (KKB911    (11(11(1   1BKB991(1199199K99KB9(       (((KSKSSS[[S119BSK9BK         (9( SzS[[SSSK1(Sc9( B 199919BBBB9KK9B9 19K91  1((((1BB19B[S(BB(  (9Suoicc 1 (11   (KKK9   (((11(( 1(((19KSB9B1((BB19B9(119( ( (91 1 ((   ( BSKKKScc[9(91KS1((           (1B9 1ozziiuuo[[[[S1ic(9Su[ĭ[19cucKBBBBB9BB11((KK((111  BSSSouioz(91( (99BS[[[SK (( 9SK9  1( (11(((  999BBBB991(KK9111((( ( (19B1 (( ((( (  (((1((B[KB9KSccB((((1         11( KciSSizc[[[KS[SS Sİi9Bczoc[K9911((((SiS(191 1( BuzuzuB199BKSKB9Kc[[S (1(((     11    11   (9999BKK19119B911(11((((( 11( ((1(1(( 199(11((9S[[99Sc[( (        199B9( Kic1SciB9[[S[[cuB (B[zzSiSK[cSB((( 991 Suc((91((((1coizz 1BBKBKK9KcoocS1SS9       (111 9(1111B1119B1(9( 1((11   (((1991((9B999( 119ci[91SS1(1         (   1[[KSi[B9(  9BK9 11SKScc[SBBKB B1((izi[SB91 9(((  Kuc1 111(9B9i[[K 1BBBBBB[zzzcK(1(     (      (( 1( ((((B((1(   ((((1111((19BB9BB( (1KuoS9BK9(( ((     ( (9( 9ozui[SK9( (B[SSSB11B9B[c[S11cKBK oz B9( (9111( 1KSSB19S[ciSKzSi (99199Biuc ( (  BKB(  (   (( (1 (((    ((( (( (((BB9999111(iocS1191((11(     (11(((919BKiuuc[[B1BB(((1BKccc[SccKSSB9 1i99iu Ĺ(B91  19SBB1  1cSBKSSSc[1ozc19B9K9SuSSc 11 (BSKKSSKB1        ( ((( ( (( ( (19(1((((19991( 9ccK9 (((((11(    191991199KKS[ccc[9[cSSK9SiS11KuoS[oc999 99Bi9(S1  zK191(911BKSKB1 1iic911KSK[oi199BBciK( (((((((( (BB(  BS[ciooSBBB1 (       (  ((  1 1( (((((((((((9BB9 (( ScK1((( (1BB9(     1BBB9999BBBBBSS[iS9izccuS1SzocS[oS(1BBoo9 (Su1(99ccBBKKK1 9KiS1(1K9KiouͰK99K99  B1(( (191( ( 19KS[[iuuo[[K(9K9      (((  ( (1((1((1( 111 (  19191 ( (1   ((9ucB991( 99KK9(((((    (S[KBB1119B91Bc[BSB1czczKSBSc[cK19(1K[Sǹu[BBSSuoķ99BS¢[KBB1   ciicB999KzicouuĿSi[   ѼK[BK[(  KKB S[B11Kioz[SizuicB[[BKci[[uuciKciiiici[[uuuui[KSzzϹzuԪu[[cuiuoiciz1      ((((((((( ((1119B91991(1(((1( 1SKBB9BB91KKKKBK Ku[SoouiKBKSKK((ououiuĀ9BKS1(K[9(BK9( (BS9(9cziS[ooozBScKB[i[SzoiozcizziK[cccicS[Biuozc[SKǞķzzҼzouў  ( ((((1111( ( (((19BB((11((( ( ( (KcKB99919(9[BSK[(zS[uzo[1B[KBB9iuioɖB11(1111Kzc(1B9 KiKKuc[KuuuooiooB[[[KSi[Kiuoozzzǰu[icS9Sccc[c[[SKiizuuii[Kczuiciiu¼޷      ((1B11991(1(1((( ((1B911111(  1Bci[KKBBB9119oBKcB(i[cooSSozcc[oǖ[911((99B9Si[ (KK( 9SizccucB[uiciozzBBcS9KicKuzozc[[z[Sc[Scii[[S[SK[ozuc[cSBKcušzi[cccizҪK     (919KKKKKBB91((1(11(99((((11( 1S[c[SSKKSKK9BBcBBuzzc[ioͪS9K191 (9B9Koc((9K99Buo1Bo[[cuoicoB9[SKBSc9KouooKKSoizucicicccSSSS[uzcKKSKBS[czz˷zuoc[[czoccoҪͿ   11KKK[S[SKS[SBBBB191911(11(11 (9Kc[KSSK1BKKKBK9izcķoicSҷi199B9( (1BKKBcc9 1BK1Szi[KooKKSizzzo[o[9S[9B[SBKcioizoSSScB9[zoiui[KSBcuiB9SKKKS[zzzzɒuozɳooccuuѪB 1B9BKKKK[SS[cSKKSSBBBB911(((11 (Sc[S[KKSK9KBBBKB(¿uzoKBSc9B˿1(11BB1(( (9KB9So9  BiSKS[[ozu[SiuzS1KSK9K[KBSouuiouoSSioK (Kzzz[SSK[icK9KBBKS[czuzɭcSiտuoccĉ(    (B9B[[S[[SKBK[cc[SKBB991991(19BKci[[[KKKB(99KKSB(zzi[ScuzioiSBBK(1zozuou˹K1( 111( (91 Su[ KoKKSci[cz[Scizi9SSK9B[K9BiuooiuoKB[u[( 9ioooiSS9KcicKBKS1BBSSzzo¼iKoļzuiiiiiiu[iɦ[    919BSS[ccK99K[[SK[SBBKKBBKBS[[[iic[KBKKB9K9B9B1([cciocKBSzi[uocK9K1 uu[io[SǖS91(((((((1  1111K[KBuzucSoi[ic1ciiziSKB9ScSBBcziiiioSSSoi1 Bozicz[9BKcuuB9BKBBB9SczooǷ[BiɭҷuouocK[ouiiciuѿu  199BB99999B99BKKKKKBK[c[ic[icSSccSKSKKKB999B9B9[9K[[ou[SiociciBBKB(zuSiiSS[B1((1(11((91  9B91Kuuzuooui[K[zSBc[SoSS9K[S9B[uooioS[o1(SuouK9Siz[99BBBB91KuouuuzoiªucuzoS¼ic[oѭ[ 199111199B999199B99B9Sc[cicSccic[S919BKKB99BBBB9oBSScuiS[ui[ciiSS[SB[ouicSi911(11(91((9111 (( 1KB1[icS[zzcSccK[uiKcK[zKKozzcKBBSiuuziiuiS(([ooiuizocuoSBBKBBBB9KĹuuouuz[[[cocBǞicciɚ9 19111((19999B9999( (1S[S[[[[[cSSSK999BSKB99BBKK1zu9KSiuc[u[ScuoSSi[K[zioioB911( (1111199991  19BB1KooB91Sui[ii[[uzuouiK[c[Kuz99cuzuoooK(SuucoiizcB9BBB9SB19uzuouououzi˳[Sϼzci׿i1  111 19B9991((((((1SiSKBBKSS[[[[KBKKKKSKBBKBBK9oK[Sczuiz[[ooiS[K(Sz[iic(((1(((11((((1((11 (111BB1BoiK( BiSiuiiiciS[icK9coiuuuoioii[ Kicizucoc19BBBKKBKzuuiouuϚ˰cBK[i԰iizϦS(1Bo9(99(((11111(11((((9[oicSKKBKS[KSSSicSSSKB9BB[[KucKKizu[SSSii[91Bzo[iu1111 (( (19((( ((19KcK (SicSSo[Scouzci[icK9Siiuociouo[Kc 1coiuuioKKBBKBSuuouczuz͢ĭͦu119BKɖiiizǞK(KB1( 111(11( ((1KSiuo[BBBBK[SBSii[KSSKKKK[cKBSBSioioSKSKSicB 1zucu(1((((11 ((11((1(1(((1BKKB1(Su[ozSK[zuS[[S9Koc[cucocK(1oi1 9iocczccuioSBBBBoioiiuzѪc 1K[ccҪucozǼiKSS911911 1 ( ((([ccii[K9B9K[[Scii[SSSKBBSiiK[S9[cizzoSSKiuioc9(ziozu 11( (((1((1( (((11191999B (uz[iz[KBiz[S[K1Bcc[cciouiK9(KS((czuiziBSzzouiSKB[oiiiiozuzϦu˹uB1K[SBSiճoS[[oҖ[(B99991111 ( (BKiuc[[K9999Siiooicc[S[SSKSci1ciK[izuuuuzoc[Scoi[c[9(iccS( (( (( (1((19911(111(99BKB19iuciuucB1oz[ccK99K[S[cocKSzB1BK( KuuouoSSuuuuuouziKSuzuoiioouuozuټϪz99 (SS911[խ[KSSK[c׭B999999911((111Scooi[[K9911Kozoi[coiSSKKKK[i1zSKSuz[Scuzocc[ooicB (uiccc[9(1(  191(((1111199B11(199B1([ziKSiuiczoK[cK99SK[[cocK9Ki[9K9 9iuiuuSKiuciuo[S[izuzziiouuciuz˪°z[ 1BKS9((Kͪzoc[BBBSҹcBB99BB9B1((11Bciooi[K9911BSuzccKciiKSKSKSiuBBc[ciS[ucSS[[icBKKouoziBB9B91( (1((( (91 ((1999BBBK91 (czS9[izi19[SB9ScS[SucSSSocS[K9SccioSKcuzi[ocSKK[i˼oiuuo[izzªzzuzcSS9( c¼ٿoc[iտK99991BBB91BSK[ciiic[K9119Bczuoo[c[[9KB9K[[SSo9KKicccoozSS[oiccKiuo[BBBK1 ((((11( (((911B91999BBB(1[cK19uz1(S[91K[[ccciSoziSSSz9 KK[[uz[B[uozziiou[KSc[ɳzzzoicuuzijzuoouooouɖouz[9111Szǰ[cuzzzɪ 19911BBB9[ciciciicc[K9199Kizu[SSBBKKKKB91B[9BSo[czuuuuzuuu[[SB[uc[S9BBKK1 (11(((91(((1111B99B9911((1B(1SuiouK9KBBK[[[[[cK[cciu[[uzic[cizoc9[ouiuzcuo[icuuiuozz¢zuuooouuiccio͹ccK(9ozciiuz[19B[ciioz 1B9111BS[ioccc[cccicBB9BBK[uuzzoc[KBBBBB999BBK[Kizozc[ouuuS999BBiSKK19B9SSB(111(( 199BBBB19B9((119K991Kz[BSSB9BSKSS[i[Su[BSuoBBczzuc[SuuoizzSououioioci¦oiiiiccoocccciuo9iu[SSS[[SB 199BBBKuK9B11BKSciciocc[cc[cSBK9BBK[c[cicccSBBBKS999B[izozuz[[[couoK9BKKB9zoSBS9BBB9K[1 (991(1((((1(19B19B911(11B9SSKcz9BB91B[[[[[cKK[cBBiiK99[uiiouuzuuuuciuoooicou°uĭic[[cccccccSSiiiouoSKKKSKSK9i[19999999SoS9BBB99KciicSSii[KSSKBKBKKKBKS[KKKS[[BB9BBKBSKSooiooiccKBozc[[SB199(oSKzKKBB99KB1 1111( (1119911119B91999KScizS9999S[Scio[KSoiK9SiB1Bci[[cizuzociuoooiciuzo[c[[[[[[[[cciui[coozѷiKKKKKBBSBc9uzoc1(1919KB919BBBK[iocKBB[cSSKKSKB9KKBKS[cKBKKSK9BBBBBKBK[oSc[[K[czSSczoBKKK99B[1uuizBB9B919BK9 9B1( 1(9BBB991191(111S1 (BSKSiocBBSoiKKScK(9Ki[Sczuoou[iuouuc[iocc[SSK[[[[[[[[iciccouuouɍi[SKKKKSKB99c1zc(11B999BBBBKKS[cccK9BBK[KKKKKKKBBKKSS[iKBSSKB9999KS[SKuKBKSKKcizcoi[[BB99B99B1[zBBB9919BBBB( 9B11( ((191999B91(19911B9KKBKS[KK[ucBBScS11Kc[[iuuoo[ciizi[iocSSS[SSKSK[[[iocccciiiuzzz˹SS[SKBKB9B91zB1BBSSBBBBKKK[[[[SSB1119KKKSSKB[[BKSSciiciiK91999BSS[K9[9KSSKScuzo[BB9(19S91K9Bii91BKB99991BK9(199111((191111(((119((uSSS[cKSzziB1KcS11K[[S[zķzcic[oiouSiiui[[SSSSKKSS[S[iiSScuioioicuĖc[KBKSBKu((o1BK[cSKKKKScccSKSK9BB91BS[S[iicccKBSBSoiocKB9999BSS9(B[1KSS[iuuicc[B9999B[SKi[SuciK9BK1(199(9SS9(99919B991((( 11111i[KSKSuS9KcK1(BiiSSouuo[[ciizocco˷o[KKSKSSKKKKSciiic[ciiic[[izozˢi[[[KB9c1(oB9BS[SSKSS[[[[[SBB11111BScooiicccS99B[uooc99919BBSS9 BBKSS[cizzucSKKBSc[[ccSKc[Sii91199B9((11B[[9 1B91(1(11991(((1([iSKizS9Bic9(9[iSKccBSo[ouzu[[izzc[SKKKKSSSBS[oiciicc[cic[iocSSuҦcSSSB99K99[u[S[SBK[[c[[[[KB9111((9Sc[[c[S[cS99K[ic[B99919BKSB9KBSSS[BiuicciiouuicSSKKKK[c1( ((111(199KSS91KK9((((11(((((KSKzcBKic9(1K[SKczucoziiuzooziccoozicc[SSKKSKK9K[c[Sccii[Scioo[[[[iչoBKK([KKKSu[SSBBBB11( (BSSSSSSKScK199K[SB91((1BKSKBǚ[BKcoSKBoiuocciocccc[KK[BBK1zc[(1 (1199((199BSKB1 (1111 (1((1( 9zSKooB 1ScSS[zz[[KSzc[[[z9SB[iicKKKKKSK[cSKS[[[[Sc[cocS[S[oԿoBS9cİB[c[[zSKBB91(199KKKKSBBBKSccS99BBBB19B99BSK1cšiSK9[u[K[uoziKS[K9K[BBKSB(BK1ccu91(((11119(11199BS9 111 ( ((1(1uKiiBBSciSKczSBiKiuzo[S­c[K 9cic[[KBKK[cSKKSSSSKKS[czcciccS[ciϞKKBSuouocS[iuz[BBB9119KBKSKSKBB9KSSiiK99BBBBB9BBS[[(ɼSKKBSc[BizzcSKBKKBBB(BS9911K9ciBB1111((1111119B9KS9 (19(11((1ziiKBzoSSicKcSBSouuu­cS[SB99KccSSKK[cc[[[c[KKKK[iocKS[ci[[[ccS1KڦiouooououSSzB9199BBKSSSBKKBKBKSSci[KBBBKKB9K[i[iuɍi[S9Kc[[zcKB91BKB9BBBSSK91S[ioS91(((((1119B91911BB1(91(1 1z[BiiSiuzoi[S[K9KizzocuoSSSSS9 (KiiiSKccSScioo[SKKcicS[SS[[[[ScizušSKuiiiui[uuBBB9BB911B99KSKKBB[iioi[BBKKBBKizzi„oSSBccziicKKKKKB119919KcS9KoiiB19( 1((9999KK999((911( 1111 [[zi[czuzo[KK[S19[ozuiuǭuSSSS[[cK11Kc[[[c[[S[ooii[ScocSSc[SSScccioi[uɉ([׭occc[9991999999119BSSSSozioiKB99BBK[uuz¿zc[SKK[iKc[KSSB91BKKB[Scicouu9KK((((1B199B99191119BB9111 Kiiccuuu[K9[[99Souoco¹z[c[SKKK[[S19couui[c[[ouooiioiSBKSc[SSciouc[ccoSK̀cBBu[[c999B9919(11((KScccczi[icSSKBBK[ozuoǼoiiKBKozSKSKBSSBScioiiuoooi[[Kz9BB11(((9111119B919119B[S 1S[Siozui[BKScK9Souo[cɹc[[[KKKK[ccSBBizuoocSS[c[iz[SKBBKSSS[iuoSSc[SSiuSuzoS9Bu[(9BK99(1911(11((1SSS[iu[cccKKBKKciziiѷou[[SKKucK[cScoicoooc[iocSKBKBK1zo99((1((111191(111(1(119S[BKociuuiSK[cB1Kouoizdzi[[ccSBKKBS[[SSK[iuoi[[[[SSuziSKKKBKSSS[ii[S[iicSizcz(BB9(1uS 19BBB99(199(((19S[[ccizzK[cc[[BKSioiicu۪oSK[[oziozo[SSS[S[cK9BK9Ki[zuB1999B999(1911911((11(1BKSouzzo[ouooSKcuuicªo[[[[[SKSKBKKK[iK(Bizocc[[[iziS[cSSKBKKSiic[[ccicK(9zii((91c[1(1199B9911BB9999KSSScicooBS[[KSBK[cciccѢ¢cccScc[KBSSS[SKBBBBK[Kuz[19BKBB91(1((((((9911919uuuuioo[[ouiozuic[c[[[KKBSKSSiicB11SouoicuziKKSc[S[KKS[c[KSciioo([i1[S9911111B9B99BB9999KSS[[[KBB1BSc[SKS[[SSS[ǰoc[uocco[SSKKBBSKB[S[KKc[KS1Szɦi9KKB91( (111((11111(io[ozouiuuicozzuo[SSKS[SSSSBK[[ScSK19[uzioo[SSSS[SKKK[c[[[S[[[oi ([z SK9B9BB9999B999(199999KSKSSK91(1BKS[SSSSKKKKSu˳cK9[coS[KiocKB[B9K[BB[SKSio[BSc9uϷu919999( (((1(1(1191couui[iouicozooocccS[SKKKKKciSSS[[K91[uzz[SSSKKSS[S[cKKSS[iicoc 9Kiz(S1BBKKBBBB9BB99(((111BBKKSKB119BKSSi[SKKBK9Kuzu99ci[[SSoSK[KBSB99BBSK[SScc[[[Kz((1191((11(1( (9(KuiK[[ozucozoouooii[[SS[SSciSKSScccS99Szo[S[[[SKKKSi[KSKScccccziK[[ĞB1BSKKKSSKKKKK91(((9B9KS[SSB99KS[[coziKKKK[o˼ucu9BccK[c[cKKcK99191KKKB[[KKcuocuSzɍB9BB1((((((1119Bi9Siuoccucciiouuuoi[[SSio[[SSSScc[SS[cuuicSKSKS[[cicSSSSSSS[[uS1KuѪ9c(B[[[[c[SSSSKB999BBBK[c[SSKKScccciozcKKKSѷuoBScSKS[K[KSocKK[SB9KKBS[[S[i[Sc9oɞc9111((11(11 1oizoccuScoououuoociccziS[KSKScc[[zzKBiuui[[SKK[icc[[SS[SK[izoB(Kɭ[ǒ[[[[K[icci[SB9119BS[cc[[cc[couooooicSB9BiǦu9BS[Bizuuuccci[KKSKKKSKB9KKKS9o˰i9911((((11(oo[[ooSccooizzuicooooc[[SS[S[[[iz[KKcuoicSSiic[[c[KSKSKcu[izo9 cco³oc[[[[SKB911BBSc[SS[ccciuuiuzuicSB9Kzϭz[(BKcuzc[oi[BKBSBKooKBKiSKcKSѳo((91111( ciiɿ[ciciioouzooz[ic[SSc[[[coc[iK9[uuo[[c[Sccii[[SKKoo[Sczu9[zljKiji[SSKB911BS[ioi[S[[S[ooiciuii[KKKizϰzoBSScoiiic[[c[K9SoucScuuouc[ѹu9 ((9(1[ĭc[[cccouuozzicccciiccoScci[11[uooo[[[ccc[c[SSio[KSK[uucSozĉBBB9999B[cccc[SS[ccciiccciio[SSuzouzz¦ϰzouiuouococS9B[uzoiciccciͿB119 S³ic[[cooouuuzzuoii[[ioou[[[[c[KBozcc[c[[[ccScoSKBSK[izǢKBKKK[ǚB9999BB9Sozzoc[[[[c[ioououucBKizicuiizѳuiuouuucSB9Siuuc[oicK9ɚK111Ą[c[ciioozuuuuioiioozzuc[[ciicouuzicccicc[iziKBBKKS[izzS͍9KSB11119BBKK[ouui[ccccccciouzzoS[cSicciu˿ǰcou[ozo[[KSicooSciSKBBϦB(˷u[ioooouuuouooooouoc[SciziKiuoicciiciz[SKBBKS[[iǹcSuo(B9K[KKBBKSKScociii[SSiioiouuuui[dzzoKBiѼѼoozucSccicKK[ccc[[[[9B[c˭ļuciccoouzuzzuuuziuzi[[czuS[ozzuo[cic[[KBBBBSSiѷo1c9KiBKKKKScccci[S[i[[S[coccciiizǿucٹzzzzѹu[cSBBBc[Kc[ii[[cKSScšzc[cioououzzccozucc[uzzoc[ouzouicKKBKBBKSSoɹuSKԳ19oBKSS[[SSSSSSS[[SSBKKSSS[cc¦˦ocoouociu˿iK9KSiuioc[c[SSoϭĪcc[ioiizoizzz[cioziiouicouocSczuuoccSSKKBBBK[cizoccu(ccKS[ccc[KKBBBBK[[SSBB99K[ǭo[[[iii[Sccu·cKSKcoi[[[KBiͰ¿oicc[ouicciuuoouoicuuuccccio[Scucc[KKKBKBK[[KSzcioתBScKS[SKKBSSKKS[c[S[SKBBKoĉciic[[cSKKSKiuǼzcSio[KKKSuϷļcScioi[[Sccciuozouzuiiouuic[S[cc[KSooi[KKBBBKSKB[KSSBSoKKBB9BKKBK[c[cii[K9[ļoiocS[[[KS[[Sci¿zc[BoϹ˹uiic[[SS[ciiiiouzzoizzzooc[[S[cicKouoi[SKKKS[SKBSSB ǹcKiĪoB1119BKSSBS[cii[[KuĿ¢[cicc[c[KKKKKS[uuiiijzϿιoic[[[cccccuzoozuuuuzozuooocc[izzSSiuucccSKSSSKSKKS(BĞuoSScšK1119BBKSB[icc[SScĞǿ[[cicS[c[SKKSSKSSS[oչ¦˦i[[cc[c[[zociuuiuuoouuuuzuooc[czcc[couiicSS[SBBKBK( cuoKKK[ɪB 1BBK[ciuuuic[c¦ͦc[[[oiciic[SSS[KSSS[i׼ɪɷcii[SSKcccciiiiicczuuuuzzccucKSSccouoici[B999BccK[ooSBBSB919BBKouuuzziiɢu͉Ki[cicS[[[[cc[c[SSS[iǪͳͼoic[c[i[c[ccioiciuzzzzzuuoui[SSScicccuucS991Bu9KoziSBBSBBBB9Siuozzizɚiiioz˿uK[[cic[c[SSS[ccc[[[[cczճ͹İocuc[ci[[[cccioizzoozzou[[[KK[ii[K[uo[KBKBBB11iuSKciKKKKSKKcouzzociϭzuiSuɢcS[[[[SS[couuic[[[cS[ccio[uؿ˷oo[[[cc[[[[izuuioozuooouziS[[S[[cccK9Kcc[S[KB[(ioKz9KSS[cooouzzi[cѪco[ĿS[c[[[SS[cuuooi[[c[S[[S͹Ƿiccic[[[[[izoouiiiiccciic[[SKS[[cooK9BS[[[BcB [zSBKcciiuzzzzuizϞScǪoSciiiii[[zcizoic[cuѷijĿooo[c[ccccooc[cicc[c[[iiccc[SS[[S[oo[B19[icSɉuouoiiiozzooo͞c[S[ciioccoi[[[Ƿļuouic[couicciiccSKS[i[[ccc[S[[[iiccSB19[[uziicuzuuzuooz˪ǰ[ciciiuc[[coz¿uuoc[iooii[SS[c[S[ui[[cS[c[SKK[cS[[[cS99Suouzuoioi͞čS[iizĭuc[[cc[zdzuziiii[ccciSS[SSoi[cccSKSSSSccSSS[[ciS9S¼zզͰzzͿļu[SS[SoužǷzcouoicS[ii[KScozoS[c[KKSSKSio[KSKSScio[czǭ˭¹Ǽǹ¹ǷoocSKK[Siš¼zoicS[iic[SoziKS[c[SSSKSSo[[[[SSS[[[ouͷɍ¢͹İ˭uccS99BBKcu¹zzzzzzuooccccc[czz[K[[SSS[S[ii[KSSSKK[[[io޿Ǽ˼ϭo[[SBBBBBK9KǹĿzuzuuzuuzuiooic[S[zzcSSS[[[KSS[icSKKSS[SSK[Sɼɳcz˒[[[KSS99119zdz°­zzzoozzzzzzzzzzuoc[c[uoSS[[SSKKKS[cSKSKSS[SKSuoɚdzz׹iBSSBK[SB1[ijzuzuzzzzzuzuzzuuuuzzziic[zu[[[SSSSSKKc[KKKSKSSKSBioǞ˿i[͒KS[SBB[[9oǰǿuzuzozuuzzuoozzuzzuuuoi[ooiic[[c[SK[i[KKSKKKKSSciǿžc¢ɦ[9SB9KS[[ϳĿɼuooooouuzzzzzuuouuouuuzzzuooiciccc[S[cSKSSSS[cSKciǷɭuչiKKSBBSKc·¹Ĺªzzzuuoouuouzzuzzuuuuoozzzzzuziioic[cc[[cicSKSSSSSSBKoͿͰļǍ9SSKBKBoķǿɿǼzǷzuuuuuuuuuuuuuouzouzzzuuuuzzu[cicc[c[coi[[SSSS[SS9iuɼɹ˷SSiSKK[ǹzzǿzuzozuuuuouiuououuuuzuuuuuuuziiii[S[ic[[[SS[SSSBizuĿĪooBKzǿ¿zzɭzuuooouuuooouioiuozzuuzuuououuooocSiic[[[SKSKSS[u˿ǭ¹ižiiKBĪĿ¼zzͪzoooooooouuoiiouuuozooououzzuziuuoi[[ccS[SKSSouɿķu[BBzĪ¿ҭͰzuuuiouuiouooooouuuuuuuozuuuuoiui[ciiicSSK[i¼ͼķ·iKBİ˼zzǷϷzzuuuouuoiuuooououuouuouzzuzzzzucic[cooi[Kiz¿ǰϿķĿcSu˳˷ɰzͿҿzuzzzuooouuuuuuzuooouuzuuuuoicic[ici[zijĿ¼ªɪ¢B[¦ϼǼɢzzzzzzzuuuuuuzuzuouzzuuuuz[[iiiiuoz¹ɷɳo1zǷzɼѰzzzuuuuzuuuuuuzuzuzzu[iiicuz¼ǿҷSccK9Kzҹzzzuuzuouuuoouuuuzzzzzzzziccoiķϼķ¢zui9 Ko9oĹzĪzuuoooouuouuuzzuzzzziic¼Ͱҹ͹o1S°uBi͹zzzuzouuoooooozuzzzzzuui³Ϲɞ˦cǷB9cKuͷzzzzzoiozzuuuouiuuuuuϭo¿·Ƿҿ¿c (iĭªzKc¼Ҽzzuzzzzuuuuuooouuzzuuzu՞o¿ǹ׿zic1 BooĹտuzuzzoozzzzzzzuuuuuzzzҷooĹǼǦԹuzKļĪ1S³ǖzuozuzuuuuzuuouuzzzzzuz˳uoǿ³ˢչizѹ9 Kzzuuco³ǚouuzouuoouzzzzzzuzuuuuodzziǿ·׳Җzic˰³(1oz[czoic[ǰioij˚uooozuuuzuzuzuzuzuzzuz³oĿ³°̈́iĿǹuuĭԪK9uzucioB[cu¢cķѪzoouuouzuzzzzzzzo·ijѦѷz˹ѳuuooKBiǼ԰ucuzzzzzuuuzuz·i³³Թۿooǰ¼Թiczczi[¼ĿҷouzzzzuuuzuzoĹ¿ؼĄKϼͿo¼oiiczu¼ĖuzuuuuuuuzzzǚzoǼռϼɳoB[İi[iozzuioiɚuuuzzuuuuzzĭouǿĖ˿zzͿϳzocS[উucizziuzucScɞoozuuouoz³io˼ǿѦѹoļĦ[ioc[[ouz[[SzioiªoѦoiuoooozc¿ijɰ˷°Ĺ·o[ciouScòSiuzu[Buճiuoozc¹·ɪi1iǰzuo[[cio귍͉S[iz[oĭҿzouiļ¼dzi  zǰѿzuzziS[zcuͰآioicuiijɚuo¼ǿ°c( KĭzɹuzucSoBoԢೄucKco°ķͭooǷĿ (izzci·z[iuuz˪oKS෉iScuzz¼Թziɼɼc (Sǭi[cicc³iKScuuz˰c[ٹoSKc¼ªcijĖ9Bi[Scic[ǿǰocc[K[zoͷoiҭuSK[ļ¼¼ϳ[z¹°ǹcSĉoucKKcooo׳uKSci[[ooSoԿuѭuzzcc¼ҳcu¼·ozdziccoic[iuzئiSKK[iizu[ª[S׭zioz¿¼Թoo·ļKSuoiɿuocKSioccoآ[[SKSozuzi¦oKcߍz[[oz¼³ǿҼoiij¹İoBKScoǞ[Kouc[izzzɞo[[SczuioozzĦ[cҞcic[S[uˉǿciSK(1KB 91KcuzuiKSioocc[KKBBKK9BKKizcSKKSBB9B9(1KBBSzi[cKKB1(99Ki91(1(1B911( 11111BBuĢKBKK1111(       9zc[[K9Kuociuzzzooccoi[uozzuuuoozzooioS99B9B9B9999(9KBSczuc[ciuoiiiccc[[ccS[cSB91Sz[ciSKĭKu1K9199 oS9Siui[BKSSSiuoocK1(1BKKKBBSSzc[SSKB9119SSKBczSS[B9(19B99oc919111(((((119111(i˷˰cSSKKB91    ((((u[cSSBB[uuciiuzuiuzocS9KizuuzoouuiouuouiccSizzzu[99BBS99911919BSSKcoucBBccciocS[S[cc[c[cS11BKocSB1BzϞccKBB1 9B [c(coo[KBKKBK[c[K991(9KKKSK[ciiSKKBKB9KSB9Bccc[91(19B1BSzS911(911(1111K1BBKѼϹoKSKKSSB1 1( Bico[B9BciizoioiS[u[KB1Kuzuuoi[couuiiicSouccc (1BBBB9B911KKB19BKB1ScK1111191191B1991(1KSoS19BSўKuc9BB1(B[1KKou[B9BKBBKKB1( ((9ScSSS[[SocKB991(1KKKK[[c[B1BSKB9BKSzB1111(1(19KSSKKBiԦ԰iBK[ci[K19BccK1((1 zzKcocKKSiuzuiS[cSB9BSuzzoiiioococozoiu[[B(199B99KB9199( (1(((1 ( (1 9( (B11B1[B1KSK׳[ziS9BB1BiBSBKK1119B1(((  1SzzucKc[Souc99B99119KS[[uo[S9(BSBKc[[SSS(11119199BSSS[Sڳ͖K9KScKBB9Kcooi[9(  (((Bu[[[K99KizzcBioc[BBS[cuui[SozoozziucSSoK(BB9BKBBB1((((91 1   119BB11K19((B[BBKSociϖ[KKSB Bi9[i91(((((( 1zuc[[Bi[1111B9BSc[[iiSK9KSBK[cc[SBKK91(11BKS[cSco[uԚҹS9KKS[KKBB[i[icKBB(1(1B99ScoSSKBBBBcuzzzuico[KBBBBScozoiuzzc[[uzizuozoB19KccKB9999BB9119((1(((  1BBKKKBB9119BS(9BS[Sou˪u[cKBBBBB9zu9( ( ([zui[KuiBBBB9(19KKKioSK111BiciucS99uo9BBB9KSccc[cooϢzz1BBBBS[[SiiSBK911BKSK9SSScuuuc[K119B[uzuuiii[ooc[KB99BScoiozzcScuzzzccuiB919ScB99999B11(11191((    1BSSKSK9(11 1KSSS[ozzǞzicSSKB99[zB((   (9ici[KSuo[B99111119BSzoK911BcocicB111[BB9K9KK[S[[c[cѷB9KBKBBco[SS1((( (BKKKBS[[uzi[cK9(1B[ouuzcoo[uiiB 1KSiioiouzzzzuciouuuoozuiiuS 1K[KBB1((((( 1 (1   B91BSB11((19BB9KKBBSB  9SSS[coou׹oi[SKBKi[(1(   1cucSBBB[ziK9999((9B9SzuK((9[ooiiK111(BB[[KB999BKS[oͦBBKBBBKSozS9( 9S[[KKS[S[ooS[[B1(19[uiiucoc[o[B 1BKKSKiouzzuuooSSiiozuc[ouuiccK((((9KKKB1((((  (B1 9Kioizzi[SKB19KBBBSKK91SK 1KSK[iouuϿo[BS9Bu9111  (iucS99S[oziB11(119K99Suo9(1KcouiB((19BB[SSSKKKKKBBKS˚9SBBSSSoo[  (9Kci[[K9BSScouSKBB919KiuiSc[iSBK((K99BBS[iiicozo[KSc[iucSSuzzi[B( (119SS91  ( 9B1Kiozoizu[ciiioc[KB9BKB KB 9SSKcSiozzuǹi[BSB[c11(((1( (9Boɦ[[B1B[ccizcS1 11199BSS[BB9Siou[11BBKB u­o[SuiBB99BSKuϳiKKS[[[iK((11BSoouicBB1(9BScizi[KB19KSozuouucB 19B1 B[S[cciiiS1BK[iuuSSooucS1((((((BK1((((  (199( BSS[ioioucciiiou[KBBK[K (B99SSSKiouocioizc[KBScKBB9BBB9991((([o¿c[B19KiuiouS9999BK99BBSBKczziK19SKKB Ͱc[iui[SSSSK[Ŀ˭u[ccic[SB991Bco[1 ((9K[[iuic[K9BSKSoK(((19B1( BzuKS[SK[iS9BK[[ooScuziB (1 1 KKB(((  9K9(1BBKBS[[S[[ciiccicSBBKSS11iiKSKBKzzoouicuoKBBSo19BBKKKKB[BKKKǭoSS999BizoiuucǭzK9BB1(9KSKKioS9BS[[K91Ϣ[ciiiuoS[SSSSoҭ·uic[[SBK[[BKcccoi1 (1K[cScšKoi[B99BBSoiB (99991 (9oucooSKiiSKSSScc[iiK ((((( 1KS91(( 1B1((BK91(11BKS[cc[KBSiiSBB1(1([o[cSSoozooiizKBBS19SKKBBSioKczǹ[KS1BBSKSc[[co˼[99911K[[Siu[1(9KSK91BˉB[ScouuKBB9BKzԷicc[SSKB9BBKK9BK(  1K[[SoKccc[cS99[B9((19B1  Soo[ouiSKS[SSScK( ((9SSB1(((191( (119((((1(1991111BS[[B99111(BccKB[[i[[o[[ozuucK9999KBKB9B[iKc¦BBB1BScKS[B9Slj91919BK[[ciK19SSK9111щBSScioiB99BKioc[[KBKBB919BB1( 99BSSKKi[cciouc1(cu1((1111( (1BcozzocuoKBK[[ccS9 ( (11((919SSB11111 9KB11919B9(( 119KB(B991(((9[K[c[SciS[uzciS11K1SSKKKSKB9ciKKSKSSKSS99Bc˭B19K99KS[[KBKSB1BB91ϚKBBScoziKBBcuc[SK91K9(191111   9KKBSKBKoiS[[iuuo9([oS (991( (1B[iiuuooouu[SuoSK[S[[cB  91B911B9KBBSSK911(1 1SS999B911 (9( 1[[9((i[[cc[[c[cizuooBBBBScS[cB119izuuuo[KSK9KcS[S119SǷ9BBBB99BKKBK199BBSKoɹiSKK[couoSSSzoiS1KicK  1KB((  1BSc[B9119zc[[ciooc9(KS9 11199( 9BBScoouoiuuuu[SicK9Scic[  ((BS[SK991BBBKciiB( (([cK991((   (BB9( 1iucBBSicooooiz[BBBSi[SS(1(1iuuzooSB[K1BiS99((9[ѼĿ[9BK991SSKBB19B9BK[cu[SKSiuici[[ziK(1(1BKcuiiSSSS[cKK919BK[KKK[ioo[9((  1911999BBBKiuoooouuic[[c[BBSc[S9(1KccSSB119KKKBScuiK(11( SK9BB9   (1 (1BS99B(9oBBK[ozi[ciiooSB99KB1((((9[zuouiK[S(9[B((( 1u³ɿKBK999BKKKKBKBBKKS[ϖc[K[oooio[iocS9([ռuS[S[zuK(1BBBKKSSKSciocK1((((191(19BBKKBSoooiioooicc[[S9BiiK9(1[iS119BBKSSSSSScuiB11( 9SK911( (19(1( 1( 9K9KB1KiSK9Kuz[coo[cc99111 ( BioozScK9KS1(1((9z³ɷu1919KB9KKBBBBKKSKSoBSBSiioi[[oSB( 9z˷iBKB11(19BKKB[SK[cccc[9  119SSKB1111Sooicioiiicccc[B9ic11B[[B(((9KB[c[[c[SScio[9( 1K1((11( (191(11  1119S1SS119(Kcozccuuuc[iu9((((((1(9[uzzucuiKSB9KB999(11ɹĞ9999B99BKKBBBKKBBKScKKBK[icKz[1o9((  ( (KBS[KBKi[[c[S[[B 11((BBB9((((1SocSS[[[cc[S[ScK9S[1 9[S1(9BBSKBcc[SiSKSc[ciS9((((1((  ((  ((KK1(19K[91SBSzzzcooi[[K[cz9(1111(11cuoozoccSSSKKK199( 9ļĭ199BB99B99BBBKKKBKuKKBKKc[[oz[9 B[1  11K[BK[i[S[cc[icB((  9KKK9( (Kci[[[SKKKKK[[[[K991((1BK919BBBSiuiSKSKK[SKSicKB1(1( (  (  (( 1KKSKB1(9K( 9[ucizoiuicKBi9((9991Kiooozu[[[SSS919B9(( (c°Īc999B11BBKK999BBBKiSKK9KK[–i1 o[(  999BBSizi[i[c[SKS[B(( 9K9991((((9K[cSSSSS[[[SKKKSK1(( 9i[KKKSiiicBKSSSB99KKS9BB99( ( 9S[[KKB1 (11(1BSiuuuioc[icKBSozB999991Buzo[ccSSK1 9B9( zǿ–K1991999BBBBKBBKK[SKS9BScĖ9 KB( ((1KKS[c[z[S[[S[[[SB( (19BB911 (B[ioic[SKKKSSSKS[S9(SSB[[iz°zB9Kc[999BKK91(9B1  ( 1BSBB9BBB9B1119B9icuucS[[[[ciozzK991(K[[zoiuoiui[SB((1(11( 1³˿11999999KKB999K[[u919KĪcS( 9c99((1BB[uo[[[[SoiS[SS[[[ccB( ((9B9B99( ((1Kcciuc[[SSSKKBBS[[K (K9(SSuoK1 K[ozS9BB91( 9SK1  (1 (9KK991((91BB9BKB1S[zocicccuzzB911cucSuucccouiiB(99(( (1iɼ˳o9BB9111BSB11BKKBc91KK[ҚKK1 [zB11ScSiiz[i[c[iuiz[SKS[ccS9(1B9199B99(  Bciio[c[KKKSSSScS9 91BKSuoB 9cz[1B91( (9[o[BB9(  (BB9(1( (19BBBB1KBiozzouuzio˭oB1Kooc[Sio[cciocS1(BB11((K˿­Ҫ91919BBBSKB99B999͒BBBiҖS9  oi(9zziucKzuiiiiccS[ccc[B119SB11((1( ( (Scc[oziuzcKKKBKScB((1(9KczK( 1(9ozS(111(1B9KSKB19B1(( 199119( (9BB9119SuouoozcKizcc[SS[cS[S[i[K1(99(19(i°i91999119KKBBBB91ҳi[SuĚK( 1i9BSu[Scz[Soicziiiiiou91191((19191(((ciccccicccc[[S9B[S9 1Kcci9 1SiiuiS (BB91BK9BuSKSSBBB991 11991( (1( 119BB1 (99[ocuuziSozci[SSKSccS[SSiSK1 199BBKuѿ³zB99B91(19KB9999Kͼo[S–9 (SouiucBo[cooicizB(9(( 19B1((( (9oi[[cSScScic[B9B[S9(1[couzz[9( BzS1 1KK9(11((Kz[KKKKBSSSSBSc[SBB91 (1999B9BKBBBKizzouui’[ccii[KSKS[ui[KKK[SK1(BKSSic[·ҚiSB911119BK9911Bǹcciz1(1BSBooSooooocScS( 9(1199111(  Bcoc[[c[SKSSKKKciiB1(BSuoK( KBB[B9((( [iKKK[SKK[[[izzzu[B99SSKB9B1BS[BBSzzzooiozİiBiuiSSSScouoi[SS[SB(9[ccioSBĭĖo[K911199BBB91(Ǽu[ic((9[Ǽz€9ii(Bzoiuzz[1  (11999111  (B[u[SS[c[KKB1(1SiuS11ccoK1  Bii[ooccSBBc[9(((oiSBBKKKK[[couoioSK11(19SocBBBzzzozizoicuǞS[o[KS[[ouzui[S[oiB1KicSKBBK¢˰u[9199B9BBB9(³oKS 9ͼuiBioB1cuooz[ (1119991991( 1Kiu[SSSKB91( (BSiS9BoB(1ScSS[ioc99(9S[B1 (  zuc[KBKBKS[[[oS1((119BSB9SBui[uuiozozɚcSKSSciiouuocS[oS11B[cSKKBKoļϰzuiBK9B99BSB1 KBi1 1zS[cK99ucicozi1 (1KKBKBB91(((( Kci[SSSKBB9( (9BKKBKcz  1[i[SSSBK1 (91 (1zoSBKKSSScSKSiozo9((991BSBKocoicizuoɒ[B[uiKcoooc[c[BBB9K[KKKSio¼ǒuuuzu[KKKBBBS911zKii1iKS9((9S[[o[((1BKKKBB911((((((9KcooSSc[KSSB199B919K91  KiicKBB9(    9uzi[SBBK9K[SKccoiozii[KK999K[izooizz˭izoSB[ouzuouoKB9B[[KSScoio¿zSiuouzoiiSBB9BK9Ko[S( zu1((((cuiicoB(11BKBBB91(((( ((B[iu[Scc[[[S999911(1 (zoS(    (iuoooui[KBcS[[S99BKcouu[[ic[SKKBSi[uizuiuzҼziSKiuzzozzc99B[KKKcouoi¿zucccccciuiKBB9BBuK91zoi(Sozz[K(9SSBBB99991(11((1Bii[zcS[ccS[[9B9B(((((9((1[B   Buiioic[BBSioi[B19KKSS[iooiSSKBBSSuoizozouzˢoBSzziiicozc919c[S[cicS[zczucSKScccoic[KBSiKKuuiSzuicB[՚czz[1 1[cB1B9BSB91( 1BKio[SocScc[SKB(19BBB9119 ([K1(    [u[[SS[[SSccSB99BBS[[[c[BKKKSS[ccizzϢc[oicSSSii91Kcc[[[cK9B[zdzu[cozoico[c[iiKicoS uzzoo˪ooB11Sc[91BBB9(19 ((B[coocSccKS[SSK9((9Suo9  Buz  ( (czuicSKSSKBB9Kuo[c[B9999BKS[cSBBBBKSKouuzɚo[SSScuc99Bci[ci[9 Bzͷ[iouioz[Siiiz[i[cuSizozuiiScK9BKS[9 19BK9191119Soo[[iiSSccSB1( (Kuo1( BioK  (((  Bii[SScicKKS9Kcu[KS[[SB9(199K[[KKKKB9Souzoiɪzicc[SScuS99Kii[B1Kcz˪ocuuouccciuocuuuuoouK³uoooouuuoKKBKKBB9 999B9999BKKozzi[SccSKS[K911(199111 Ko[9 (((((( ([o[SKccSBB991Ko[KiiiKB9199BS[SKSBB9KKSzuc³Ǧuozc[iS9BKioS1SϷiizzooiccizz[zzzzuķuiozzK[[KKK1 19199BBKK[izuK91KiucKBKKKB1111B9KK1  Sc9  ((((  BcocK911(1SS99BoooozoocB1((BciKcSBB99SzzizuzuuǷuo[B9K[K1iǭuzuiiiccuziidzijzuizuKSB9((1BBBB9BBKScuzi1(19KiiK9BKB999B9BKK1 (9BSB ((  (9[c[K1(1(1KK91BSSoSzooocSS99cocc[SSKScczzoiu¹³iB1 ([zozǼzuuuuuociii‰oijc·ɼ·ouo[19 ((( BS[SSSS[iizuzz[B1(1(1[i[KKB919B91B9B9(9K(1    9191( (9S[[KB99999BBBBB9BuuSzz[iic[K9Kccc[SBKB[cuoozzuĦĹo (cuuzĹooo[[ici[ؼu°ĭ  11KS[[S[icuzuc1 11Sic[KBBKK999919B119   19BKB1(11BBKKBB99999B911((1BBBK[KSic[SBBBBBB91BBiSciiiozuuoco¼uozɼuzuiozǷocKKSizBSu˄Ŀļuuo 1919K[Scuzzu[K((11 991BciiSKS[[K9B919K9   999B999(((11KSSSS99B991191((( ((9BBKSSSSKBB99B9uzziSczuuzz[ccuuzɹzuou¢ҼiScSSKKzuz׹Ĺi ((199BKSzucooziB ( 991Bcuo[[ccc[999999 (11  9[ii[[c[91111(1B[c[[B99B9(11(((11 ((( 19KKKBKSSSS[[izzoziKKiiǿzuoioĭ„oucc[ozoĭ˿9(19BB9BBBKSoucouic(   9iuzccc[[[K91B(((11( ((BB11(cui[[zS111111BScc[K9BK9999((((1 (119((1(111B[[[[[ccz¼ĹuiiccBB[uuijİzouuuǢzoz[ou͢ɼSKBKKKBSKKSozizSSS9(   1B[oocSSS[ccK9999(1 (( 1BSu[SB9KK9BciB9BB911K[cc[SSK9911((111( (1(((1((( 1S[KS[cSuijǿo[SSS[[B[c˿zzuԹuucSoɪzэ9SS[[cS[SS[oocuu91   (( ((((BcucKKBBc[[K9911199( B[co[B11191Souzu[KB1B91BcuoocSKKKB991(11( 11((((( (9KKS[Scķiic[[oc9BoɷǞ[[uB1iǿĭ9ccKBcSBScoocSS1  (9KK99B11(KcocSSKKSSKB( (19 9BBB9((19KczuSSS99B911Kiuoc[[SKKK99999(11(((((( ( BSSSK[zKKioii­¹iSo z˪z¹zziKScSS[K9K[cSKB191  (KSSB9B9 1KizicSSBB9B9 (1((111191 ((9[uzSKKKKB1119[uiic[[KSKKKBKKSSBBB91( 1(1(9SKSKczciuouijouBoҦĹɪuz[9BB9919KK9111B1 1BK919B[B1(19Koui[BSB19B999((11111 ( (11Soz[BB9((119BKouuui[[[[SSS[[c[SSSS[SSKB999BB9BSSKz[u[ķzBoǪǼǼu[[cuicK9B1(( 11  (99(9BSS99ScS11(91BzocKKK11BBKK919991( ((9B919BicSBB11((9B9[izzzuoc[[cocSSccii[[ccccc[cc[S[S99KSKzouiuucϼͰu[BǿɳuuuoiuiK[cB11191(11( 19BKKSKBB919KB91Bzi[K[K9BBBB99BB9((11(1199Kcuzo((( (19BKciouucSK[SScii[cc[i[ciiicciiiiio[B9BKcooooiĹ͚ii9odz˷oiooioiSSK19KSSSB1(919BKSK9BB[B11(Bi[[S9BKBKB91(1 1111(1Sizuoc9   BBKKiuzoiSBBccKKiii[[Siocioi[S[S[cciucK9Su[zzcczuzzuoͿoBBS¼zzuiuuuc11K[[ci[SSKKKKKB19BB(  [ui[[KBSKB11(1991( (( (9[oucB 11B[iKKSSSKcooc[SSiccic[KKKBKKKoicSuoBSiuSBKciouoo[Su¹[ 9ǭzzuu9(S[SccSB1BBBB9(( 1oS[SBKSKB91BBK9(((( 1KccS1  ((((1Buui[[SS[ccouuo[SSSciSc[i[BBBKS[cczoKSooBSooSSKKBKSz¿u99ozzzuzzzuuzuuuuB1z[KK1119B911 ((c[ouc[BBKB911BKB9((((9[[[S(  99999KozuicKB[ooccuuicKBSSKcoiSKK9BSS[cui[BziKiS9999191KĿ¿˷S¼iuzzoiioiouzzuozzoKuB( 191BBB9((Ki[[9BuzicKBSSB119911(111SiK9( ((19BBScoucuzoocKB[ci[S[[ccK999KK99BKKKSK[oucoKBc[9( (((((S·ɿɿ͞cǼuoozǹuoiccc[c[c[SBKiiB[B1 (B99K91(  (SooSB19ciKBKSK99B91111 9[[1  (19B9KKKcciSKiuzu[BBKiiB99B[[BKKBB((19BS[Sczo[[SiSiKcK(((1( BiĹijˍ·uuuzǿzuuiccc[oiBKoiKB999( (91BB9111119SioozS99SSzzSS[[SBBKKBBB1(KS1   999BBBKSiooiSK[iouzuc[SBKK199KiiSSB9B(19BKS[coi[[S[[[oSKcK(9B11 KBiǹ˼˖ɼuzϰuooooooozu¼ioK99BBB9911BBBKB999K[[iuuozKBS[Kccc[SSSSSS[KK9(B9((  (19KKKKKSiziBKKS[iuo[cc[K9BBKcc[KB9KKBKBK[ciocSKcuSS[9BBB9KSB1((1SSKɿǹǖɹuѷuuucci[cou[iuiKB91199B9BB99BBBBKKK[iozSBB((cuic[S[KKSS9911(   999BBBKKKcu[SK9B[ooooSKKSKcc[[BK[[SSS[[[io[SBc¢zzBiu[[KKSK999(( SuB[ѹ˿˖ѳĪzuoiouzuocc[[[[cziS9111 ((1(1(99B9B9BKS[iouK(111ozo[SS[ci[S9( ((  (K[SKBKKKKSczuicK9KKSiSKB[u[KcSSccSS[c[iui[c[u[šzu9zzoiKK[K11( ((czKBz˷ǿ³ɿǦķoic[[[[cooc[B9[u[KB11(( ( ( (19BB9KKKKiiiozzuzui[91B9Bizoic[[cic[KB1((19B9BKiuSKSSSSK[izuucK[S[ucSKco[KKBK[[KSciouc[cc[uKo9zzocK9[B(1(191[iB9Kǹ¼ǹuu¼oocSBBKBK[[KB19cc9B9(  (( (1BB[cKS[c[KS[[[ccK991 [uzoc[cc[iicSB1119KSKKouc[ozuo[cozoo[[cci[coiS99SKSKKS[[[SKci[ci[K[[1iocK99SB(9KB119iKBBiɳzzuoiSB99999BK99BScK9BB91((( (   1BS[i[cicSSBBKSKB ( ( 1KuucSK[SKS[KSSSBB9B99iiuo[cuĭuuooo[K9991( 1KBKSKK[ic[coSScB99ĪS9uccKKBKS199911[iK9BKɹªzzuiiocBBBB9919BBBSS[KKSS[SSS[[BB1 9K[iouoiSBKB9111( (Bcozc[KBKBBK[KcSSB9911cziiuo[ccoϼzzzuc[[KB1(1111BSS[[o[SuzucK11(((uKoc[999K[991((1cS99B9cݹzzoiiioiSSSKB9919BS[ccicozooucSSB99BS[iicouoi[KK9  1BSiouzzoouc9BBBBBKKcScSB9 1izuiciuucKS[icĭzziziSSKB999BBKiuicoico[9(((( zĪoS[[K99B911( 19c[ 191K٭uuuuoicciccc[KB919B[cozzziiuuoiiiuzuoc[KK1( (( (BS[ioooi[izS19BBBBB9K[cSK1((1(11BBKKBKKSioǼzooiic[B1119K[occucSS91(19( zcK[9999B111( ([c(9119[ϭzǰoouoiiiciiii[KKKBSc[[zzccozuiuucSKBB( (1B[[ccc[[SBKuoS99BB9119B[cK911(( (1199BBBKSiɹucoooc[SB911KS[SiuuoS11(11( zo[BSB19B9 ((111KzzS91((9S˿uǞzzoicouiccooccciouzziSciczoSKK1( 9S[cicS[[SKSKcuo[[KKBB999KSccK((1(((((19BKSiuzzzzuizuiuoS[c[K9(19KSiciS11(91 uo[BB11BB1(19B9BcSS[KBBBK[°ɼڹzuuuͿiiiucBu[SzooiKB9( 1BSciic[cccKSSciccioiSKKBBSSc[S 99((((19KKco[KBSouu[[ui[cuocSB(911BoioS11(1( zuzoKBB99B919999KcooSKKKKKBS[˳¼·¿İzoz˷ziuzioiBKSicczoBBB1 (BKS[[SS[ccc[[[oucizzo[[cSSSS[SB1SSKB99BBK[ļi[SBBoui[SScoocizi[[SSS99BuciB9B99( zzziSB9((11BKKB91Su[S[SSKKKKBBǭ𦼷ǰc[ǷoKKuuooiSoccccuuoBB91(1SKSSKKSSS[SSScuuouzic[[[[[[[SKSKKB999BSiªzoKKKSouc[[SBSKSciuc[[SKSKBiu[cB(91 zzzB1K9(19KSB9919iKKKKSKBKKKoϰ¼°u˦zciuzǼcKKBBiuiicSSz[ciKciuSB1 (B[K[c[[ccSKSSccccooioiiouoicccSKSKBB999K[ɳozziicKKKiicSciS9KBBB[ccSKSSSS[occK 1( [ͷ91B9199[[BKKBKS999B[c[KBBuϼĿɹzoouĪioiccoiiBB1BicoiSiu[BicKocSzuSB91(Si[[[cSSSK9Scc[[cuzzoiiiciiiicKKK99999Kzoc[ucSSK9KoiK[oi[KK99B[i[cBSSS[zuSK[B (  zҿ91B99KKKKBKKK[S919(1BSKSuĀoɳzzzoouiSKScouuziiuKB1oi[[BBoSSi[SizoKKzoKB9((Kiiccc[KKKBSciccozzuoo[SSS[[[B1BK1119ci[[[cucKSSKSc[S[cci[B99BSSS[[c[[zuKS[cS(( ((999uѪz91K19KBKKKKKSco[19K99iioijĞSļijz[ui9Scoo[zoiczzz9BBooocB9ioizi[[i[B(1ccSSK11Sc[S[[SSSKKSSSScuzuuic[S[ccB(99999[zo[KSSSoiKK[[KBK[ciicK99119BScccozSKcc[S1( (B[izzSKϷzc 99KSKSSKKBSicuoKKSS[ǼĉSǦļzuzzcKiiKioiuuBo[couo19cuiioS9[ucuuKB91( ([o[SK99[[S[[[[SKBBKK[[oucSuzooiiccSBBB99BiucKKB19[iSS[SSBBKc[[[KKB99BK[SSczcBS[c[S1 199[ocKSSoĹ1 BB19BKSSSci9KuoSKK9zĄ[Ƿu˹ouioiSBK[S[KiSKic(Kuc[[[KSuioKS9B911 ( (9izi[BBK[[KKSicK[SKBB[ozu[[uzuuuuoiccKB99B[uo[B9919KcuiSKKKB9Bci[SKSKBKK[cccuzcKKKSSK1( 19K[izK99BBK¿ǚzc1KB19KKcK11zoK199[[zļļuuǷozuoc119S[SSuui[uBBuo[SSS[[[S99111((((111BcucSK9BBKKSciK9BKKKcuc[[uuoouuoc[[SKBKK[z[B9((1SicuziKSSSB9BSSSSSSBKBSiiuzi[c[BKB( ((11[BB999B9Kǰɼ[ozSc[   B(oK19KKKBz³uuɳuoccoiSKSSizcz[SzcSSSB1((1 (((1((91(1izi[SKB91S[S[[B9BKS[ocuzc[[coccc[cccSSBKKcoiK191(BzoizzcKSSSB9BKK[c[SS[[iziic9(( (((((1­͞BKSSBBKB99cǰuuouuS19 1(zK9BB[c9o˹zͷ[czcS[zoiiizzi[K91(1111((1 ((( 1coSKKBKB9coSc[B99KSozc[o[SKSSi[[SSSSBK9BSozu[9199Boiuzo[SKBSB1BKciiiccczzoS119999  (1ķ¦KKSSBc[SB1(uKzcuBiS919B (oB9BKz1BS¼zuͳuioSuBSui[ziKBB9(1111(1((( ((11 1SK99KKKSB[cSioS11S[iiK9KoiKKBBSKKSSSSKS99BS[oiS9111ooSooucSS[SSBBBK[ccciucK( (1(1( ((ɪBSS9Sc[B99uuicz9K9( Kc[91KS11BSS999zucizzuooϦuBļcuzBBBB9(11(( (1(1 (19Siiou[B9BK[cK[oiioSB9S[[B91Bi[BB9BKKBKKKKS[KKKKK[[zz9BB9[zo[BB[ozo[co[SK9BBBK[czi[K((11111( ļuǼ³K(KBBcc[Sczco[[i(99iuoou11BSSuz[999SKS¹[ciiozcciuǦuczͳzcSB99B91( (91((((19SouuuuiozuzuKBKS[K199Sc99991B99BKSSSSKKKB[iouc9919ooSB9BczocSSii[KScSSc[uicK( 11(991(((ǹ9BԼ˞91KK[[ioocuKci11BKiiuBK[ScB199SK(KĹi[S[coioiiiz˼oiİoioiK1Bii[S[cozuzzo11BKB111 i919919(1199KSKSccK[ic[S[SB[uiS9(1[cSS[ii[czui[czucc1   (1111191(11oBK9ѷKK[[cizicS[ ( 1KSuzSciiu11111BSKKcļzuiKBS[cooz˳zzz[z[SSiooo[ioiušuuSB9(1(9[[ĪuSB919 (19BBB9KKBScicici[[ciK911[u[SSizzzoiSSzuoo[B ((((1(11((1999SKKKB[ԷKS[izSBioBB(9BccBiB ((119KB9B[ļiKBBS[iSzu͹uuouoǹǰ[[[occzzuDŽi( 9KcuSSK99999919B1 BB[SciiiocS9(19iziuziio[KKzzSccK((((  (1111((199o9SSKKSªzBi[1BiuouK9S[czo(1 (119BB9BBKo¼[cSBBBSoˢociuuouǼɹzo[͹uo[SSK9919B (((BS[cioS11BSozoS[[KBBccK[SK9((11 (1191 ( ĿcB[S99Bu͢·u[iSB[ozcccoS[[ iz9( (99B999199KɼooSSBB[zcciuuuzzĿɰoijooocSB11(  (9KcziSBSizzzuooKKK9KBSoSS9B1 11BB11BB1 ¹[9ci[SKKɷǼziiKooBSiuoKĒSS[czoB9B(Boc9(119B99119K91[iS[[BBcǦouio³ͼ·zzɦuz[[B(  11B[ozcSioooc[ouiKKSB[ou[cB1 9S[(((9K1 ( ͼ[BcicSB i³uBBSK9Szzc˚S1(19K9(111Si[Sui9119B199((11BK9[iK(Ki[KBSĦozuiԿoԷuiuzzKB11  ((19Kio[[[[oc[uiSBBK[z[B1  (19( (9K(((( SBS[SBKccĹzBBKB9BKuuͦK1B919111119KB9BSSSSK[9(111(1199191 [SSSBKuǖuݹԿuouziicBBB991((9KSizucKcz[cu[BSizo[9(   1B9 (  ciB9K[cu[[iSK9KKKBͪ[9BKB9B99B99B91BBBBco[[B ((((( (((9K9(c9SSSSiǒzɭǭϿǹuouzzouc1((19BSSci[SioS[i[cuzz1     9( uiBiziui[[[Sc[oc[KKB9­i9BBSBBKKB9BB991BKBBK[SSS1((((( ((Kuu19z9KBSS[zĹɼKKKcccİuu9(19KSSic[S[i[BSczi9      (  ķcioz[[BKSBS[cizocBKͿi99BKKBKBKKB9BKB1B99BKSKcK (( SzoBSiKKKKKK[ϭiuǼ¹ļ˼uB1(119(c³ĪzK9BBSS[c[BBoziªc(((      ǞuBBKBKBKSSSB[ccui҄199999BKSBBBBBSKBKB99KBKcc (( (1(SzzKBKKKKSKKoǚo¼¿³ĭcBBKKB1Bķ˷¿S9BS[[cc[Sϭc      (ͳz[[S99919KBKKKSBcozzԦB9BKB99BBKBBBKSSKBB991KSSKco9 11(19u[9BKKS[KK[uǭouzuǿ¿¿cKK[c³Ĺž˼SB[[[[i[izǢz(        ˦ociiBKB9199BK[SBKBSc͹KKKSB9BBBB9BBBSSK99BB9KB999191 ((((1zoS9919[[KSiooҳ¼ĿSBS[ɿĦ¿¹uBKSiiuozҹK       ¦cBccoi[S[KB9B1BK[cKBK[zװzi[[SKBBB999KSKS[SK99KKKK99119B( 11( 9zK1(199KccS[iuzѰǹͼBSoҼѷ˹¿zz[[iicoˍB     19  zuz[[ou[S[SBKS11Bii[c[cѹcSiou[KSSK[SKSSKK[[SBKBSSB9111BKSB((1( Sz9(11((zK9czuuɷ­¿ͳǷ¼uzcuo[ѷ[1(( ((( ( 1S[SozuiK1( oozĹiiiicoiK((9[iiccKi(KS[oocSS[i[S[[[SS[KKSSKK9999BBBBB19B( izuB(91  uuB1Bczuz­ϹļǼǿ°¼Ĺuicc[ϖ1(1( ((((19999BBcz[BB( o¢[[uuuuuiK11KSBBSzĄBBKKKK[oo[[[S[S[cSK[SKK[SKB99BKKB1111B (Szc99 Bi[S[KKizzĞ­ҼouucS¼°iizz991( (((19BB999BB[zoKozuzizu[oiK9BB91SɒSBKSSSKKizuc[[KK[[SSSSK[[KKBBKBB919119K[B ([ccB 1[cS[cKBSiziuĚǼdzɰ[SSKK9iucˢB(1((1KKBKBBB99KS[ii9BizuɷĪuizu[ScS9(ϖ[[SSKSKB9KiiS[[[[SS[[SSKKKBBKK919B99Bui( Koc( 1io[SKK(BKSizuuذ˳dzĒiSSizzuǷzzuķz9919BKcSScc[KSS[[coiKScuo[uİzoo[KoԦSS[SSBB99BBKii[c[c[SKSKB9KSKBKB91(11BiBBu1Bioi[KBKSiSSScizͪͼϿɞoSBB[uoķɹzzuǼS((9K[c[Scc[SSS[oiKioozS[ozɿc˪S1SSSK9BBBK9BSizoc[[[[KKKKBKK9BBBK99(1ouzB1ioKKcicoc1B9BozcĿǹİ˖[S[K9B99Scoi9¹Ŀuoݼ((B9KSKSKBBBKK[ii[uoozzKKS[cicizªzټuBBKKKB9BBBB9BKScuzucSSSKKKKSSKKSKSKB99cizoK99Sizi99BB[[uͿļѷzczcKK9119B9119B S¿Ǽzoz9 11199B1((1BSiziozui[11999SzcSu˷DŽBBKB9KKKB119BKSKKKizoKBSKKSSSKKKKKKBKB[coS1KououzoK99SocĢzcS[cooi[[[KB9199Kco[SSSBoz[11((( 1BSoozc9(119KSzz[Ҽɼ͒c99KB9B9BB9K[SKBB99B[oiSSKKKKKKKKKB911SozKBuziK[zczǚiS[[c[c[SSSB9BS[SKuzS[cozcK[zcS[Kcicoi(( (1(1BSSouz1(((19KBKBSuoooc[911   (11KzK(1i[SSKKKSoo[BKK911SuoSSSScKKB911(  ((((( (((  19B9 11((Bzz[io1 (9SK[ouc[SBBK[ziBS[io[KcoS[[coi[czzi[S[BKKiziB99BS[KKSSS[iuccooi[SB9KuiBSKKSBBK9999B9(9BB91(1   (1111((((11119BB (BKBKSScuioi[[91(   (   1 SzBB9oii[KKcicui9(11(BiuiKKKS[c[[B91    11 (  ( 1(11(1[iSuu[( BKK[cc[[SSKSScɹiKKozuo[B[zcK[ciui[[cicSKB9Kczuoc9(9S[[[KKKKBK[ozzc[SKBSziKKSSSKSK991(1uuB9KK1((( 9( ((( ((919  1BK19B9BBKK[iicSSB(  ((( (1 KiB1 uǿuo[Sozuc1 (KoiuuKKcozcB(      (   (119(9izc[oS1(1KK[S[ciccKKBzzccuocui[BSooScc[coi[cic[K99K[cc[[S( 1KSKKSSSKBKSzocSKBBBooSS[[[SS9999( KzB9B1(1BB9111  (9S( (999999BBKK[KSou[KKSB(    ((Kouc(Bϳui[c[uS( ucz[BcS    (   111Soo[cc[[KSSuo[SccccoS[ozuzoioz[SSSS9KucBczo[[cocKBKS[K9BBB991KSBBBBBBS[ozi[ccSK999zzBKS[[SS9B9(( 1o(1( 1KS[SK9 ((BcK (1191BSK[ScuiSSKB( (((1   iucoS9ocSSzuzc1(([KzSBz    (( (((    (19Kziic[[[ScuuuooicSozo[o[cc9BcK9Buu[[cooS9S[SKBBSK91BBKSKKB9Kozccou[( 1BzKKSSSSB19199B11S( Bc[SS[[K9 ( (((9[[B ( ((S[S[iiSSSS9 119991((   Soi[(Buu[[Koi 1[u[KSuu1  ((((9999K11K[K9B[[[K999(  BoiozoocB9[uozSizuoiuoooz[99K99[iKKccSccKKSSSSBSK9KB9KKKBB9Kozocio1BKooSSSKSB11BKB99KzS (S[SK9B91(( (191(( 1K( ( 19B[SSKic9SSB( ((( 11(  Bzzuc9iucKuS[Kuz[c iczzc[cSS1  ( (1((ScSS[ciciuu[czuo[SBKK9   9c[[cizK9K[ccSouzi9iozuzoccccou[9K[99SKBSc[BKKB999BSS[[BKSBBBS[SSciiiicciS( 9BBSc[cK99B9BKB11[z (KKBBB91 (91(((1(( ((  ( S[[[i[991  (   Kzzo[9[[coҖicKcuiK1uuic[1  ([iKSSScucuuciuiB9(1KB11  KocSK[[[B11BS99couo9Bciiiuuuozu[KKKBBB9ScKBKBK[[SKBBBBB99KSS[S[[KBBKSuo[[ccc[999BKKSiu[SK1119BKKB9K[(119BK[[919911991   SKK[oS9((  1191((19[u[c[(Bco¦iSK[[zzS1Kzuz[K1  ( 11 B[SBKSS[icccS[cK(  (( (9cui[Sc[K191999cucB(SiiSS[[c[S[[KKKKBKB1K[B(11B[i[KBB99999BB[cSKSSKKBcc[KSuzcKB99K[cSozc[K9911BS[SKKio99 (999ScK119KK9  (  KSSSuS9       KccK99SScuuuuici[91iziBBBBSozcB1BcccĖ[1  (( (( Koi[[KKSSS[[[S91   BuS[[[B19999[uuB(czucKBKSKBBBKBBKBB99K[K(((9KSSBBKBKK9199BKK9KKKSS[zuco[K[ocB19K[c[[ScziSSB9B99KSS9S[ 1BB (9991((((BSB1   ((KKBSi1   1[[SBBciS[oi[ozu[[cK9(iS9K[SBB99K[zzB1SBK׿B( 11  Soioo[S[cc[SB(((  (1((SzucciiK91(1BB[o 9zzSKBKKBBKBB9BSKKBBS[[B(BKSS[B9BKBB919119911BczuiSKScSKKK9BBKSS[S[SocSK1BK99SKKcz1 (9(111ooK1B111 1BKB1 (1   SSS[9  (BK1 9[cSKBB[SKciSSuocSK1([[(1(S[9111BKSooK1919Ұo((19(    iuiiu[c[[S9 (((1((111(1Szuoi[K9(1BBBKS9 SiBBKSSKKSKBKSS[[K1[[[KBKKKSSK9KKSKB911199BB[z[BBS[K1 1BK[[[[[Soz[S[SKSK9Kc[ 1SuKS[9(1B9BSSB1 (  KK[B   1[zoKcui[111Kc[[i[K[ozioiK((9SB9SSBB9( 999KSK9((B((1B1   Ki[occK   (1((191991KzuooiiK((1BKK9((1ouKBK[c[KBKK[SS[i[91[SSKBB[[SSSK[[c[KKB1(1(9B[ouiK9SK9(((KKKK[c[[io[[SKK[SKi[ ( (1KKB11911(9B9(1KSK1 ((  Sci9  1K[izzcKcuu[9( 1[o[SS[cSoucicS11ouB9BSooiSB9BBKSS91BioS91 (1((1( (9zo[KB ((11((1BSzzzuoioiS[[SK9(11(ozSKS[[SB99S[BBc[1 9KSSBKS[c[cSScoicSSKB11(BBBKzKciSSB(1919KSciicczocSSS[ccSSK[1 ((919BB91BS1 9B9 (9S[[SKB9((((( c[B  (BcicczziSKccK( KzuSSSci[K[zz[[KB99c[19KccB9BB[[cKBBB999(( 1( ( 11B11 BcK  9B9(  ((1(199K[iuuzuuuzzouucB9B11oKBK[[[KBBKc[KSK 9KSS99SSccc[Sioc[c[SKBKB9BBSuzKco[S9991BBScioiuuc[SS[KBSiK 19((9B91(119B19BS[[[[[[KKKKBBB9((oS((1SicccouiS9111( ( 1ozuc[icBBuuSS[SBBKB19SzzoucSBKSiiocB9911( (((1191B9B9iuKcuzccB( ((((19BS[uuzcizuouo9111[S99KSKSKSK[ccSKB9KSSK99KKS[ccii[[[SSSS[[KBBKBK[iuzzK1[ciuzziicSSSKK[Sco9 1B191(((999((19((1Siccc[KSSSccc[[c[K(iB B[[icicc[KB( BuoooooS B[SciB11919czuii[BBS[[ou[B91  11(1((1(((99B[z[1(ScB1 ( 19KB1 (19BBKB[iuooui[iz[B19Kii1119K91K[SSSSSS9 BSSSSBBKK[c[KSSSS[[SK[[SSK91BSozu[SiuocKBSSKSSSKBczo9 9BB(911(119(1B9BBKKSSBK[KSS[cc[[c[cic[cB 9[c[cii[B11  ooSSScio[1(KzoSKKKK999(Kciioic[SSc[co[9B9  1( (((( ((9i91[9 (BKSKB9((( ( (1(19K[zzo[c[KSuzS9(1S[KSK119B91BSKBB9BK119S[[[c[SSS[i[S[[SS[SKK[[[[SSK[[z[ucS[K9KSSBBKBB9BB(1KSB9B9( 11(1BK9BBBBK91BKKKK[c[[[c[ccSS9(1[[KBB9(ScBBK[uu9 B[[[KB1BB119Kcoioc[[S[ui[[B99(   (Kiz9iKK((ic[K91((((1(((1( (Sicc[[SK1coS(9KB1BcK911BBKK99919K91Si[SS[[[[iui[SSSSSSSSKSSKS[cccu[ժu[BKKSSKKS[[SKKu (9KB1BB11( (91991BSBKS9(1KKKScic[S[S[[[K(99S[B  9iiK919SuK(BB919KBBKB99BScoocii[[[B(((((   ((KiouBB1 (cz[9( (9919( ([KSB91B[SiuuuK911(BSccB( (991BBKB9991Sic[[[[KSiui[[[[[[[[[[S[[SSS[[ouԹzBSSSSS[uuS[coK ((1119SK91(1BK9BBKK99B9119SS[SSS[[[SKSSK1BK9S9(11  ( (BBKKB111B[K1 (9KKB9KK1 (9KiuuiSSSSKB1((( (  ((9czzuii[B  (izc9  ( (11(  (SK[KB99[S9KSoKB9(19BBSK99( (1B9B9BK[B9ScccccS[cicSBKS[ccciui[[cc[[[zu¦Қzo[SKzB(19999(1BKB11(99KB9191911BB9 (9BSc[[[SKKBBKK9([B91 1((1  999B11(99KB9((1[[KBBKSK919KScoocSKKB9( (( (BK99KozoiS1 ((99BBKSuc(  1((   9cSK91111119S[B999919BKB991(KB9KKBSSKKBBScicic[S[SKBS[SKccizuoooic[[Si9ĒziSouK 1BK999B91(1( BSKK99( ( ( 199BSKBSB(99(( B(1 (119B((( ( 111KK[[BKS991BiucKBK[[B9KKSozuiSKB999(   9BSK9Koucc11KBBizo[So[ ((  ([SB9BB91(119KBBBB1((1KB9K[KSB99KK[c[coBKSooii[SSKS[SSS[cuocc[cc[[ccu[ئ9 9BB( Biuoc(1   9B1(  ( 1BK91( ( (B1  [BB11911(( (  ( (9ciK[BBB[oii[SBK[[K9K1Kooou[BKB1(   SSS[KKScc[B 1K9(1Ki[KcizB (99(     1cKB1999BBB99KBB9111 (B9(1S[K9199BBBSccBBScoi[B1BKS[SScc[iiSS[[[S[[[ziu՞iB9  9SK( (((    (1   (( (   uK1(( (( 1( (9ioKSSS[cooc[SKB9SK1[oiiccSBB9(   9[uBKSS[ioS1 (99B[iczu 199K9  ( 9cKK9KKB9SS(1BKK919  91(1SK1((( (11BSKBBKK[iiS9BK9BS[ccc[[KBKS[[c[o[zҍS191 ((  (     (  ((   (19KS9  19(((( [zocou[[cc[BKccKSiS1cuocS[K991 ( 1czKKS[[KB(9KK[cK(1BBB99111(  (K[KK9BBBKi[9(9KK9991 19(( 1(( (1999BKcSSS[SBBBBSKScii[SKKBBKS[[[oKzc(11((  (11(   1( 11( ((  (1191  (1(19BBS[SSzS(   (1BBBB[u[oocSKBKSBBci[S[1Buuc[K(  9ciui99KSK(    ((   1S[KSBBKBK[S9(1K[KBB9 1B1 9K1 ((9KSKB1BSS[BKK[B99BKKS[icS[SSKBBBS[[uu[ì[1( (1((BB9BBB( 1( (999911(  111199B91119BB999KKS[[KKuS  11BBSc[KKKSuzo[99KKKoicSBBozucSKB9( (BczuBBSB        (KSSKKKKKSci[B((BSKKS91B[K11BS[ScS[c[[99K[S[[KKKB(BS[SS[cSKSS[SSKSSKBc[zoҳ1 1B91 ( 9KBBSSB91191(9B1((((  ((( (((111999119B9999BKSSSK9((KB( K[[[Sci[B[oiuSio[icBKKSo[91Kozc[S91( 9cuzBiuSSKBSK    1(    (    BSSSSSKSSScc[S91BKB9911K[KB99Kcc[SSio[[KBSic[S[S11SKKKKSSSKSS[SS[[KBKccoB199B919BKKBB19BBB1(9919BB11   ((11199B999BKBB9BKKKB91 K1 SociiccS99KooiuoSzccuKSBK[B9Bi[BBK((( ccc[czi9( (1  (9KB  9KB   1SSS[[KKSSKScc[K9 (999B99BKB19[ooucKKco[SKK[i[ScuuKB[[[SSSSSK[iic[[SK9K[oߖK1 (BB91BS[cK1 9KBBB19( 1B1((      (((19BBBBKB1(9B1   1  9ioSSc[SB1B[i[uziuizoiu[[cBK[S99ScS9999(((9c1Ki[( ((BS1(   1BKSozo[[cSSSBK9(((  (KSKKSSS[[[S[ii[S9((BBB9999999iozzz[SccSS[[1BoSKiiS[icc[[ioic[[S[SSioii( 199911S[SKKKKSK9199(191       (( ( 19(    9((9KSSK[[SK119So[cuKcuziSu9(1B[B19B[B11( 19911   ( ((   ooccziocuiK1  9KSSSS[SSS[[iiii[B(9BKSKKB991coucciocBKciSSoi1Kouiouooiciiiicc[c[cooi19919BK[KKKSKSS99BB (     (     B11KSSSK[cK111BKizcccSciB[o[Soi91Kc9(1BB9BB11KB  (11( (((  (K[cSiuuB[cc[oK[K1 (  1BKKSKS[[[[[ciuoc[SBBS[SS[SK91iiSc[KBKB[[[ouK9[zoooiuzzziiciic[iiozc[ (199 (KKBSKBBK999999911(           [B9KKBSSci9 (K91[uoii[SccKSKiozK(1[c9BS9(1119K9 (((((( 1(1( (((9KciooiozcBc[KcSB119(   1B9KSSc[SS[SS[oooi[KKS[[S[ic[99zo[[SSSc[S[oiB1Bozozzuoooouocioiiiuzoi[((191 9KKBB91(((((1191         111[B1BKKKB91(1K[K9Kiuo[BuSKBKouo99cc(991((19BB (99119B99999B9Scc[cc[iiuuicizucS9SiSKoo1( (  1BBSSSSSS[cc[[ooiSBB9K[[KSco[ooSSSK[[9[oB1Bicczzouuuuoc[cooziB999( 9B9((((  ((  191((      1BB91cKBSSB9(1SSKB19izuiSBuz[9 [ouz[B[S ( ((1( ( 19KB91999BScccz[[iiccoocSci[B9K[[B9K9 ((   (9BK[cccoicciizcS991 9SS[ioz[uoѦiKKK9SiKKi[BKKc[Koocc[c[S[ccizii( 1( 99     1BBBBB9B1  (11KS[KB919KSSB1(9KSBB9(9oucSBiz[ uzoiucBSK(( 1B1(1(9BB919BBKKScizo[[[[KS[iSB1KK11(999(1((( 1BS[ciuuoozcouiK9999BKSSSScİzo[icSBBcKBKKS[cccSou[S[[[cioiuucz 1( (B991   119K[SSKKBBB11( (1919KKKSSKBBBu[B( 9cSSK11 Kzc[9SzBBuiuiSSB9KK11  11 191191119BKS[[[ooB(BSK9BBB9((   (   9K[couoiSiocczc99B1(9K[ccizzuzcBBi[BBBBSSic[c[cozooii (1111 1KKBKB1 (99119BKSBKBSSSSBK9(111BKBKBKKKKKKKBBB91((uKB11K[[K1  9uiS9Ki9Buuc[[K9BKBB11 (1(( (9BB911BBKK[S9K[(1K(((    (9Bcoooui[K[icuu[[uz[B91 1B[zoB1KiSB9B9Koii[ziuԹc111BBB( (19BS[SKKB1(1BB9BK9((BSBBB91BBBBKKKSKBKKKKBBSKKSBBB9B99( zcB9BKKSB( (KizioBKicKcziSSS91999 11  (((1BB99BBKSK9  ((9((9B1(1(   ( ((BiuuuiKK[ocooKSoouuz[9((9ScuzuiS99BKSB11Kii[uzoiicioou(999BBB1(999BKKKKKKB1(9SSKKKKB11KSB9999B9KSSKBKBKSSSK1 199111199(( SzoSSSBKB(( 1cuuzozoBKzSS[[KBK9991(   199BKS[[K  ((  (1(1SSB911(     SozcKBScciooSBco[[[izcKB9K11[zuooozcci[[K( 1KKB99c[oziiociuuհo(1B99991((1B11S[KSSK9((B[[KKKB1 (BK9BBBBK91KSKSSBKSSKB11999(( ( ci[SSSKB1SSozuiouuoBco919KKBB1( ( (1   1((BS[9 (11( ((1(  (((199   Kio[B9KccSKBB9KccSSSS[oiccSB19B11K1KBuc[[[cic9199B99cS[ooϿ1(1111 ((BB1 9BK[[[B((KKKBB99( 9991999BSB1BKB[SSSKSKBBBB199(   cucSSc91BcozciSBui99BB1(11 1( ((1991 ( 1KB( 1B9111( (  1991((    9ooS9KSS[SBKKSKScSKKS[ooci[SBB9((9(((KiccczucccSSSKBK[[Bc[zɹzB( ((  19((BKBSSSB(1SB1B9 1999KKB999((SSSSSK9BB9B911(  Koi((BSB9Kozouuciio[[9S[(9119 (( ( 1KBB(((((( (B  (191(((((111 (  (9KB99((  (  BuicSKccKS[SKKKBSuoSKScooccoiS91199( (((9[uu[[[Sci[9KSSKizҼuc[S[9(1B1 (  1B11119SSSB1B[B(19 (111BSBBB9(1KSBKBB99B((  9Kc91SKK[iicioiciS9999K999 (  1  9BSSKB1B( 99 11((1(((((  (  (11(19(   (czu[[[cSBSioicSS[io[SScooouiou[BB11( ( (9[iKB[ccS[SSc[[iͭzoSB[c[B (91((  (((1KK9 1BBBBB(  ( 9BBBBKB(9KKBB9(  BKiKKSKKiiSSiic[S1 BBB1 1( B91 19B[[[SB(19( 9999999B9191((  (1( (BKB91    (KuuSKScccSS[ii[SSS[[[SKKSiuoc[ooKB1((11( 1B9B[iiKccBS[[i҄zSc[Sc[K(((19(  ((( (191 (19((1 (( 1999BKK99KB      [czc[cSB[[KSiii[B1 (((1 (  ( (19B1( 191B9B99BKBB91KB9KKcicSSBBB1((B1((   1KSK9((   (( KuiKSSSS[KK[ic[SKSSSKKKKSccccc[[KKKS9(  (119BKK[cSco[[ccoњS9KSSSB( (1  (1((99(9(  9B1999999BB9BK(  Sczo[[SKiz[KSSS9(  ( ( (  ( 9SK1  (111ozK9  1 BKSc[SKKBKSSB[i[B11( (B9(( (( (111(9B1 SuoSKKS[c[SSKKKSS[[[SSKBKKSc[[SKBKS[K91( ( (BK[cooczzuiuުo119BB9 (( ( (  11 (( 11(   (9SK119B919BB(((   9SziS[c[cc11B9( ( (1 (1 ( ( (  9B91(1 ((  Sc9( 199BKKKKBKBBSiicB911(9(   ((9911BK( 1cu[KSKKS[[[SSSSSKKKS[SSSSSKBBKSSSSSSKB1(1((1911BK[oizz㪀u9 11919((   ((1  ((   (9BBK11BK1((99     1SzcKcoi[9 1 1BBB9((1 ((1  ( 119(1( (9B999B((( (111 (199B9BKS[[B99119B1   (( 1BB11Bci[KS[SSSSSSSBKS[[SSSKBBKSBBSKKSSKKKKKSKB9(((111((9ci[uzoܖ[9 ( 11(   991    19B9BSB99911(1     1czc[i[KB1(1(((111(((((1191  ( (( ((99(( (19B9191 (91(91 (B9KSSKBBKB1BB9991   (9B9BB( (B[[BK[SSKKSKKSSKSSSKSKKSSKKBBBBKS[SKKKKKKSSKB119( [uzzzozo ( ((1(   (((1BB9   ( ((9991KKB9B911     Kuu[[[B9( (( ((191 1 ((( (11(((((( ((99(191 (1B9991( (1199BBSB9BBB9BBBB1  (199SSBBBK919K[KBK[S[[[SKKKKKKSSSS9BKKS[SSKKKKBBBKSKKKK[cS9199(Bciouխ  (((991   9SSS1   (9B91(9(19K1(        cucKKB9( ((91( ( (1(19((99( (11  (99BS9( (919BB1( (9KKSB(9999KB99B9B9Sco[9BBBB99Kcc[[SSKKSSKSSS[SKKKKBKSSSc[KBKBSSKSKSBBBB9BKKSBBBS[zuou1  9BBKKK91  BKKKBB9    1( (1B9  ( (    o[KSS1( (( (  ((191  ( (1(1B9 ((91  1KSKB11(1BKBB91( (  9BK91BKBBB9SKSBS[iicB9BSKKBBKccSSKSSSSSKKS[[KBBBKKKKKS[SSSSBKKBK[c[[SSKB9B[SKKSiuioozu  (19KKBB9BSK1 9KSSSSB( (( (1((99( (( ((    cK[S((1( (11111  (11999( 1111( 9[SB911(19BBB91( ( ((1( 1999K[KKKSc[9(19KSBKKS[oc[KSKKKKSSSSSK99 9KKS[SSB99BBBBKS[cc[[S[cK99K[SBKziuoiω  ( 1KKSKKKKK1  9BBBKKBB9(   (1 111((  (( 111(19(   BK[9  11 11 111991(11( (1(1BB1( (199  (KBKK999111(1(191 ((11  1B1(  11BSK1 1KS[[Scuu[i[[SKKSKK9B9BBB1B[SSKSSKBKSK9BS[[[[S[[ci[919[cBSc[[Ֆ  ((99S[SKB9999(11 1KKS[SBBK991  19 1B9  (  (( (91(1( 111( 111( [c[B1( (99(19KB  91 ((9KB9 (1((11111(   ( (KSSK119((((((111(((11199119B(   (  BciSSSB[ziiuoocKBKBBBB9B9(([ccS[S[K99BB9Kcc[[SKKSccccK9[iBicSٞ9 1(119BKKSK999911(1BB9  (9BBSSSSSSBB  (K(((   11 (1((1(((((11911(([[[B (1BBB1(9B9((91( (1BS[S9( (19119BBB1 ((1KKBB99B1(11  1BB91111(1(1999(    BcicBKKBiiizoiocB1BB999B91Bc[[S[KKBKBB9BSKKSSBS[cc[[i[SczSiu[K (9BKSSK91 (9999B1  (1BSKKKKBKKK1  (1   111  ( (1(( 199((( (999c[S(1119B((9BBB9911 ((1K[SKB9119B99BK[SK91(((191 99199911((1991(1KSK9999((((BKB99119((KizoKBB99cuzzoiiioS99BBBB9(9KKSSKBKBBKB9S[[SKBBB[[KSScccSciozou((199BBBKB1 (( ( 1BKSKSKKSSK(11  (1  (( ((1( (191( 9B1 1((911ccK (1(1991((1BKB1(((BKKKKKSK9( 199KSSSKKSSK[iSKBK1 (99991(1111111KicSB999911(119991KSB199KioocBBSBBcuiocouoiooKB99111(BKKKSBKKKBK[[SSBB9BKSSKKBBKc[SSzzͦc   (19KKKK1   (9SKSSKKKSSK(     (( 11(B1  (1(191(( ((11((KBB9999991111991991 1BKBBKBSSKB1(B9BBKK[[[[SicSK[S911BBKK999(19BBBKicSKBBKK91  (9BBKKBBBSiiiiSKKB1Bcuoocci[c[ioSKB9B9(BKKBK9KB919SSS[SKBBBKKSSKKS[SKK[iժK (( (111999(   (19(9KBK[SKKB1(   1 ((11((11  ((99   1B1 ( (9B1919111999BB19KB1( ((199BBKS[[KS[[SSSBKS[SS[SKSS[9999BK9(991BKKBKKccSSSKKKKB11( 191BSKKcic[cKBSKBB[ooii[czoSio[BBSuc9S[K9119919KcSK[KBB99KSKSBBKKBKKKSožc191( (99991  (99((( ((1(1KKKSSBK1(    (((( (  (( (BB( ( (9B91 ((9KSSBKBBBKBB1( 1( 119BK[SS[ii[SSKKKS[[SBKBKSiccKB99 19KKKKSSocSKKBB91 ((BSS[ciiS[K99((9KcooiScziSccicS[ui1BKB99191 1K[[KBKKK91BKKSKBSKBB919B᳖oB911119B1(11(( 1999BKKKKB1(9KKSSSSK1        11911( (91 1coS1(( 9911 1B[ciSKB9BBB9999(( (9(1BBB9BSc[[S[KBBKSKKSKS[iiuiKKK9 ( 1BKKS[uzziBBBKB991(((1KS[[ciiKKSK999BK[ciic[ci[[Sczu[[[BBBB9(((119S[cK19B999BBSKBBSSKB999BޢzS91((19B99991( ((((9KS[c[[S9BSSSKKK1  ((  11 191  (9c[ 99(KK9 1KS[c[BBBBKB9199B11((1119B19BKS9KSSKKKSSSBBBS[cccSBKK( (1 (119919B((19 1B91999199KSSSiocSSSB19SSSiooi[[cSS[[czziS[BBBKB991(1BS[[K19B11999B9BKS[S999BSҼo[1( 9B91(1 (((1( 19K[ciii[BKKBBKSS1(   (( (1( (11 11  (1BKizc1(BK9K91(9KSSKSK919BKSSKB991119999199919B199B11(1991119KKB9111BB119  ((1((  (999119999B[ciiSBKK9Bc[[Kouoc[izcS[ci[coc[99K911(19SioiSK99BB9999919KBKK999BSϞz[1 1911((  (19S[[[cc[SSKKBKKB1(   ((  ((119S91 (9KKcuiK( SS19B1(199BBB111((199BB911 (9K9( (   ( 1B99(1(1KK191 (  (((BB91((1BKKS[SBBBBBc[B99oo[S[u[Bi[SicK(1B(((19K[ccoc[[SK91911BKKS[SK9(1BS˄o[9 11991( ((19((1KS[[[cc[SKKKSSK1(     (1((11 9[91K191 (1  (    ((  (((191  9[[S1( (    11119BB1BK(  1((   99BBB19BS[[SKKB9BBBK[K1 oz[[SKciizzSSi[(19( ((9[icS[cSKKSK99KKKKKSSSKBBKBSډc[1  1BB9((119K1 9KS[SSSSS[S[KSSB     (  B9   (( 1 (1( ((1(  (9ScB1((  (11KS9(KB( (  1( (11 (11B[u[ooc[[B99B9BSBBK1 (zzK[[BSuui[z[ (BB99B1B[c[KK[[KSiS9BBS[c[[KKKB9BKډ[K 9B1 19BK1 (9ScSS[SSKKSSKKB1(           ((((((11((111((  191SS99((  ((9K99SS1 (11(99( (11((9199coiSoiKKSKB1BBKK9911((BocBK[Szzic[c[(9KBBB119ci[SKKKKKSKK[cS[ic[[SSSScu( (1999( 1BKSKSS[SS[SSBBB1  (       1111111(   ( (9119111((    1BB9(9 (19191 (11(111KcoiSS[SKBKKSB99KKS9( 1(SicBBS[zSc[K[i119KS9999Kci[SKKSKKBBBB[KSc[[[KBBSޭB    19BB( 1BSKS[[SSSSSSKKB1 ( (9(((     (11((  (19991((  (    ((  (((111(((   9BKci[SKKKBSSScicK99[c9((1(9[cBScizzBKK9KB(1BKK1(19BccSSBBBBKKKBBBBKK[[SB9Sҭo(    ( 11 (K[cc[[SS[S[SK9BB1 (  (1911B1           (((((((((((  (     (  1BS[[KBK[SSKKS[cuui[iS( (( Boo[o[ziKK9BS1(1BBB1(199KKKBBKS[[[K9BBS[SSSK9K͚i1  ((   9((9Scccc[c[K[SKKSK9(  (991199B1                 (91(( (((((  (    ((  1BScS9BBKKc[[[[[uuuiiB((( (cooiiSSS[cKKB(9BK9((19BKKSKScS[[[SKS[SSKBBSߪuS1(   ((  ( (11BS[cc[[[[[[SKK9991((1((1BB1             ((91 (1(   (    ((  1KciS999KS[[S[icuiK( Bocciuo[SSSKScK 1KKB911BBKSSKBS[[KK[SKKBScSK[ԄB1   (1(1( ((1( ( (K[iicS[[S[SKKSKB9(( (((1991(           (1999( (1(        (9[oi[K9KSSScouoczc(  (1ciKSSS[SKSK9BK9 (9KKBB19KBK[c[KSSB9B[SKKKKiSB̀(    11((1((1((1( (1111(1BScc[cc[SKBKB9B91 (( 1B9111B91(         (BK99911199( (19(((1((     (  (1KSSSKSSSKB9B[zoczS (9SicKS[icB9BBBK99119KBBK99BKSKK[SK[KKB[S[SSKKKzz9   1911191 ((((11(((9(1K[cii[[SSSSSKBB( 1K911119KSK1     ((   BK[cSBB91BBKBKB1(  (B9((1      ((    (B[SSK9BiiKSiSKuiio1 (19B[icB9cucKB99BB9999KSBB91(1S[KS[SB[[KBSKcSc[So  (1( ((1B991 ((((11999BBS[ccic[[SKKBB999(( 11(1119B[S[SKK9        uo991((99BKSS99911 (9B9111((     (    9BSSKSB99[c[[Kc[ozoB(1B1BK[ocB9Sc[9(9SK9BB11B99S9((9ccSKBKK[cBBSc[KKuݷ[  (1999(9BBB1( ( (( ( 11999[cSKSSS[SSSKBBBB1(1(9B9( 9BS[S[[S9(       uiS(11((111KKSKB99B9 1B91119 (    (   1BBKBBBBB9BK[oKSiS1 1KB9BKcuiK1BccK1BSKKSB(119SK1( Kic[SKBSSKB9Kcc[K  19B99119999B91( (1((1B19999BKB9K[[SKBB91KSKBB91991((9BKKBBKKK9(        [KB1((19BKBB9911(1BK9(9( (11(( (   (911(     (S[SSK19BBB9BKS[zKS[K9KSK91B[ioiS1Bccc[[c[KK9 (Kc9(((K[SSBBKSSBB99KcS  (B99B9111919111((99BBKBK9B99B9B119KKK9(9( BSSB119B9   KSKBBB99((    ((1999BBBB91911(1B99((191((((    9KS19KB1((1   1KBBSK9BSSB((((BKBBBSKB9S[SKK[cozuS1B[iicoo[B9( KcB (SSSSBKSK99B91Sݍ  (11BBBSK99199911(19BBBSKBSBKBBKKK999BBKS199BKSS1 11  9SBB99B99((B1       1((11(1(((111((191119199B1 ((    1Kc[[99KBKBBB1   1K99BKB99B1999119999SSBB[[KB9SiouS9B[iiioocK11B9 9KBBK9KKK99B9Bܰu ((1BB19KKBB99B99919KKS[SKBBKKKKcc[9(9BBKS[KSB 9B1 (9KBBKBB911191( (    (  (( ( ((1999BBSKB1(   1B[c[[SK9BS[[SBB9  (1BS919BKB99199BBBSS9Bcc[9KKB91SiuuoS9KiiozzcS9(1(  9K99B99919BBKB  991BB99BKBBK919911BKSK[cSBKSS[SK[B(   11991 1BB  ((9KKB9BKKK99((  (( ((  (   ((1(19BB9911    1K[[c[[iSKSS[icKSB 1B[S9B[KSB119BK11999BKB9BBBBKiSSS1(9cioiiK9Suiiuu[K( 99  (KKB99((11999cS 1KS9BB919B99KB9B1 1KKKcioccc[c[B1  (( (( ( (9B1 (1119B9119B9   (         ((19BB991   (9[KSSc[[SKK[[uz[99(11KccS[ui[9(19KB1(1919B99KSB9KciSc9(9ic[SB1Bczicc[K1(BK1 1K19BB119999Kz (BKKB99(( 9BB1B9B9919SKSooiBBB911  (( ( (1 (99( 199(9B((9   1((     11(11  (11191191   9[cKKK[[[SSBS[iui91191cocKKui911(1  (111119KK[oicScuB11[i[S91S[icKKSK9SK1( BSB911(BKK9BzoK  1BB1(19119B9919119999BBKSK( (11911(11 (((91 (99119111  (( ((199(  1BKBB1((( ((11((  (((( ((    (Bioc[SSS[S[B9[ouc11( BzoSKci9 (1191199KB[u[BBciK99Kc[B(1S[ci[[KBK9   ([cKB199[[[Boz݉1(9191199BKSKB9191(1(1KKB9    (((19999991( ((9BB911(   (19BBBB119B9((  9KB9111BB999911( (1( (1(  19Kioc[KKS[[[K1KooK 1SzucKSSKS[1 ((99B9B119 1K99BS[KBBK[cK(9SSS[[[SK9(   Kc[B99BB[[iuzB( 1B9911999BKBBBBKBKB19991((((  1111111191991(1  1(11 (   1BKKKKB999(( 11  KKB9B9KKB9BKB1( ( (1((((1((( (99Kcic[SKKSoiK9SzK 9ouc[K[9(9KB(11(((BB9KKB[cSKBciSSKKcS(1KK[SS[SB( (( 1KKKBBBKcc[zzݹ[( KB(911B99BKKKKSKB9KBBB1(111 ((((  11111((( ((19(  ( (    (9BKKBB9BBBB11 ( ( (  111((199KKB91 ((1 (( 11111((( (19BK[c[c[S[[ic99KooB11Kz[9BSS(( 9S9  (119KBB[c11KioKBKcc99KKS[KS[K(   ((KKBBBBScczoc͚K11Bi9(991BKBBBKKSB1((1(  ((((111(((119B999( (((1(  (  (    (9999BB99BBB991( 1(  (  (((1(   ( (((9B9BK919BBBS[cSS[[c[[K19KozK11KS(Sc9  9B  ( (9999BSSBB1((19ccSKKSS(9S[[cSSSS   ( KSBKSKKScuoiu׷919S[99KB99KK9199((  (11(((111((11((((( (      1BB99911199(1991 (( (   (91  (((1BKKSB9BKKSoi[[[co[K9911Bu[(1co99ci1(  KB ( (11191(((1111919BBK[[KBSS[[[SS[S(((99BKB99ci[[SKBBuuzآz[9BK99KK9BBB1   1    ((191191     (9119B( (991( (((     (9B99((     (SoiS99KSK[uuuuzocK91(1BoK 1K9SiB  Kc9 ((191((((19[SK9((9K[S9BSSou[S[K 1B[cc[SBSooccSS9SzzמzS99S9B9B19B(      111(111((      991(191 ((  (1(  ((  ((991191    K[coiK99Sc[couoozc91111iS(c9BcS  9(9[c91(((1191111((BKccccK999KcSBcSoc[iS19BSSKKBSuic[SS޷zzzoB1BB919KSK1     1111(1(  (( ((   1KB1( ((     ((((  (11( (   KiuiocB9BScS[ioouu[[ziB9B99zSBi9KK(191(1[zc91(199911999B9BSSBK[[KB9S[[o[[zoSc[91S[S9BBiucciuuωuouc9(991B[cS         ( ((    (9BB11((1(      1B999(  (( (  (((9ouoc[BK[[[cii[SScKKzzS999Biu9[[91  199111KooSK9111199BKKBBBB9(1BKKKSKS[c[[io[ciSBo[BBB[uziio[Siɢצzzzu[( ((Bc[K(       (( ((1    BKB9(11(  ( (1B11BB1111B (  ( (  ((( (SozucSB[cSSciii[SSKKo[B9BKS[BiKB( (KB1(1KSS[ii[9(119BSKK9(1111((19BKK99BK[iciic[[czcKBKiooS[oiuڭzuuS1(9KBSc9                9911((9((  (9BBKKB9BB9BB91(1K ((((1  (((1(( [zioucKKc[SSiuo[SSKSSizcB99S[[izi91 (9ScK19Kc[KK[c[KBBBBKKB1((1(  1(19B9( (19ii[c[[cii[9Bcoc[SiuoܷooiSBBS[[[[9   (    (   1KB((( (  99(19BKB9B9999(199111B (  (1(1 (9B1 1[uccuocc[KKScuocSSKKSS[SB91K[[oozK1( 9BcB11BSSBKKK[cSKKKKKB9((   1((9( 9SSS[[SS[[coSSo[BKKiuuljiiiSS[[[[cB ((         ( (9K1 ((BSB1(1BB111(11 (BB1119 ( ((( (  ( (SuociuocKSKKBSiucBKKBKSSBB9(BSSS[c9(((1(9 999B99B9BScc[[SBSK9((  ((11 19BKK9KS[ccc[i[iuSBSScco͞zii[Sci[K11((    ((    ((((1B9B1 ((((BcS9( 11 (111(191(((B  (( ((  (( 1( 1uucuzuiKBBBBKco[KKKBKKB9B999[KK91  (119999119K[[[SSKcK91119B1((9BBBB9((B[[[cc[iucSSK[uئococSiocK(  (       (     (((1BSB( 111 9K(((911( (111((1BB9111B  ( 1K9  (SzicucB99K9S[i[SKBKKB99B9BBSB9  (19BBB91 (9BKSSKBBB9B9 (99KK9 99911199( (9B[[S[cccciݿuccuoiuocK       (       (((( (1B9 1111 (K((11( 1919BB91(1999 (  ( 1991(SiB 9Ki¢iizc[[911BSiocKKK91199BBBK1( (1BBBB91( ( 1(BKSSKKKBBKB(1Kc[Kc[1(BK9((19BB119BS[[[S9[z¢c[oiiioiS1       (     9B1((1( ((BB  ((1((11(( 1111cSKB11119BB9KSSuoccu͹ozi[icBKBBSoocKKB9919999BB 19B919B911(   KKcic[[KKKKiiicBBB1(((BSKBBBKBKKBB1(1KccKKzعuSScKKciiB(  (((( (               z9119( 9B1    (((9zcS[[KKBKKcozooozoKB99SuuiSKB9((1B9B91 BBBB91911  (B[ci[ciii[cccSK1911111KKKKSS[[[SSB1119[ccuiu¦zzoi[K9KSciB ((11 (((( ((              uu((91 ((K1 (   ( 111uoozzicccozioozoSBK9KiccSBB9919B1((( (9119BB9119((9KcicSS[ooci[SBB9B19BBBSKKSKSccc[[KBBB9BSziciҪzuo[S99KS[o[1 (191((9((( 19( (             BK1199((  ( (991ocouz¼zuucoioiB111B[[SK9BB99991(1119B991111191  19BSiocS[iuoic[[KSS[SSKKKBKKS[[icSS[S[KSSK[i[[cczܼoK9B9BKS[c1 99BB1191(1((111 11(   (((      c911B1  (   (  (((((111i[Siozɿ·uic[ioB( (1S[SB9BBKB( (99BBB999111(1 (9Siuoiccooiccccc[SSSSSSc[SScc[[KKScSSKB[izoBiϰuK1 B9KS[KK9 1BKB1(1((11(11( 11((    (( (1(       9ozc919K(  11((9991  ((1 (11(((((1uzouuļzuucioB (BccKBBKKB1 (9B99911111111(   1uzuicciiic[iicc[[[SKSKSBK[[[[SSS[[SSSSozSz­oo[B1(BKKK[SB11 1991( 1( (1(111 1111   ((19119(      1[o[SSB99( (11(BB1111((( 111(11( ((ͷzcSouB 19[cSSS[SB919SSBBB1((  (BKuo[cciicciic[[[BB999KKS[SKSSSS[S[[S[uoiۿzioB (19BBKK(((    ( 11 (111(    19BSKBB1( (     (KiucKKK91  11   19( ((( (((1(( ((1(Ѣ׷iSu[( 11co[KS[cSK9K[KBB9( 1Siooiicciocicic[[K9SB199S[[[SS[KKKBKSK[iuҦoouoK  1((((  (     1919(  ( (119KKKKBB911((( ((   (B[iiouocSSK1 (9   ((1( 11 ((( ((K1 ( (91 ( (BKcii[coui[S1  (91 11(( (1( (1(1B991(199111 (1(((91 11  (  (( ([uS91(( ((19K1 ( ( (     (Bi[B9B9111(( 9SS(1SBKic[(KSSouS   ou[[cS9ͿuKiczĭ[BBSS1((  (uS[iiK1KKozoĞS(((9(1B1  ((1  B[iii[[uuoc1 ((( ( (( ((( 9 99911  (111111191 ((1    (1( BcS911(((( ((9(((( ( (KcuiKBB111((( 9B9 B[ScuzS9(Bi[( 9ªcu¹Sz¹BuzcSBuc9((((BKKci[K[SS¢oBKKKSSS[91( (9B11 9SiouoiuuoiB(    (1    (BB91 (11991(((11111  (   (9Bo[9( 111((((  ( (((BciicB9999199((91(11S[1(11 99o[   ǞocҒ1Kuioc˿¹zScK(9  KKBcoc99SuoSzK19BSc[1  (11((( 1KScioi[ccoii91      991(  (( (1(19911(  (   9So91((1991(( (( ((KuiSS911(((1991111(  (SB1SB 9BSuطKڪ9 iKKicǒ9i191 (1(([oi99SucS99SzuzKBS[[S  (11(1( (KSiuicc[cciB(        (1   (( (11    KSK111B9111(( ( 99[c[91((1(((((( (1  9 9  (ٚ[[iτ11KB[ioK  (1Kio[[ioccK1BoS[oic   (1( (9SS[ii[cccc[S1   1        1[S9((((1 ( (     (( BBB91((( ((1   1c9 iҰuBcǪԢ[S[Bcijoccuz[zu҉1( (KBSccccS[icBSuicc1(    11((  1[[ioi[K[[KB1  ((       1KSS9111(   (9KicS9( (( 1    BS[czu9  c߳[K1BҖS۳oc[(žiKK9zo1 11KB99BK[KBKicouoͷic19919 (  (   Sc[io[S[[[[9     1  (    ([i[91(1(((  (9991(((1BKioz[B9991 (( S[KBBK[1 1ڳcK1ճzSؖBK1cǷS[iu[[BBԢ11919(B[c[BK[couz[iĚo(999 ( 9 (K[cocKS[B9 (    ( (     9oc9119((119    (1BccSB919K[iouuuc9999 1  ccK1   1oi[9(1zc9ĉKBiS1ɿzc[[cBBo1 (1119 1K[c[cuoiioioɼ 1(11 (( (((((Bc[S19( (  ( ( (     iS(1(11( (1( (Bco[K1119cuiicSS[B99B9 (1 (((zo(9(   ([cKSiKScKB19Kc[SKK1iSKio[9KļziK99BzS((1  Bcccooc[ciiiSczuz¦  ( 1(( KiS1    1(   919(1(     So[1 (( ((BKBKSioKK9999[i[[KS[SBBBKKB99111BKSzK((  [z[1BSKSSB1 ( 9BKK[i[KKB[zS99¿–ic[KBK9cc((1(  (BBSiuuocc[BBcizuiu   (( ((BK1    1(       (( 9uS1(  1  B[SBKciuzKS9(1BcicSKKSS9B19BKBBBBBKBKzzS1    (iiKBK[[B1(  9KSKK9BBKBK[SKK1cĹ˷[Kc[KKKSK9((  (  9[couzoKBSSSizo[ozz ( ([c191         (  ((1111191BK[uzucKB1  (  ([zzzzSBBKBK[cSBBKSS1((119BKK[SKB9Kii[K1  19 9[cKBB9K9( (BKB999911BBBBBBBBǼiSK[iSKK[zi( 1(11B(9SB[cKBS[c[[ozuKu   (Ku9         11( 1(((19(199BBzzS[[uocS[[iS1KioK9BicSii[B9BBB((9B999BKc[KK91[zi( 9KK9oB( ( (19199111(119199B[cɼziSBBB[iSKS[S(11((Kcc1 91([9K[SKczzzczSc   19B1          (9(9BSK91  111Kouo[Kuz[ozzϭcB9BccSci[K99991199119KS[c[S91Szc  BuoBScB1((119( ( ( (19B(19B1BSizžuc99BKSci[SSczB111BBBc[   uoK[S91Kioiu[KcKBu (1( 9B           (1((BB1B9(  9[uu[cc[SioocczɿۿczS19KS[[cocK911199991199[iiooSBS[9   Szz9BcuB9B(1B[S(   ( 9911BK99BccļzizucKBcc[c[zB999BB[[cK( (KKSci[999K[o[SicK[1(1191   1(1      1B9 1991991 (BS[iziiui[SK[cS[u͍[ocK9KB9BK[SK91911119911BK[ii[coSB1KiSKK[[K19KSciiK( (((  99B999B11B[ļoSKK[SSKcucouc[[iicS[BBKB( ( czoi[1KicSBBKSB11999((( (( 111 (((     (1 ( (1((11 1KSS[Kiz[S[ciouz[99KKKScccuoccKB9999K[[K1(( 9119999BBK[SKBcB  1zu9 SiK9BKBKSooS(  (111 ((9BBKSK911Bz¼z91B9S9BBSzzzSooioiiS((KzBioK911B1((1  1(19   (9119(     1((99111BSSK99S[SS999K[ScozK9S[SKBKSSS[cKuoc[icSB999BKScK9BB9B9BB919KKKB11(  9[zc11Sc1BKS[ooB  191( (1BKSc[B19991S9999BBK9(1[uoS9czzuuzzi99(1KKB[oSB99 1((  ((1(    (9B(1((   ( 1  ( (( (Su[91119B991999B9BBSociii[BKKSB9BBSuo[Sou[K(((1BBB[K9SB1B9BK1 1B(   Scu[B9(1ou99SSK[K((  ((1 9BBKoSK9111(K–99919BBB( iS9B[cuoSScziK1cuK[o[S ( ( 1( (  ( (( (1(  11    (((( (Kc[9((9KSB( 111(1BKSBBiĢoiuu[K[99919SuS[uuc9((((911919BK9911B 1S9(  (1 (Scoi[B9oo11(1B9( ((  9KSuciK9BBB[cB99B911 (z[9SS9SoK Biioo11cciSS 1(1991( ((  (9111(  991(( (     (  (SoiK999BB9( 1BB99999B91[uic[BKBK1(9cuKuS( (19SKK9((1( (1B9 KSB99SSK9[cS[iu9 9SK11((1 (    (((K[zK 99B[ciKBK[B1BSocKcK1119ciiozK (1Bu (B999BBB1911   (11  (( (9991(        9SiiSB19BK991191919BK991(1cuocKB1( 1Ki(1BKBKSBKKB9911(( 9S[[[[i[KKuoB zS[zK199B1 (   (((((( (( 1B9Kizu1 9B9K99ioBKSBBSziocBBK911SKB[KSS91   9cuu1KKBBKKSK1111 (  (( (99(1(  BccSSKB1991((11111999BB( 9Scoo[BB1((19[S 9S9BSc[[[[[[KB9911BS9BK[zzKBSzS((uSKzK(BSBBK91  ( 911199999911BS[S[[BoB19BBB99[šB9SBB[ͿzoSicSK1B[[z9    1cS[[KBKKKKSK9(  (1B91( (9911(( (   9Sou[1(1((1( 11  9B9B9  9BKKSo[91111(9Kzio[( ScS[[cSBS[[[KB9((9BBBKK[K1SoB 1uS1BiKKc[BSc1   (1((19KBKBK911BKSKK119uuB9KKB9B9Bi·u9SK9Biuזu[oic[izzc9  ( ([z[SKB99KB911   99(11119111( (  (  Kc[[SSK(19(((((191 (11((991999[B(BK911KiKK91( KBBKKi[KSKKK1(911( 1991BuK1KS((oS1K[KccSBS9   (1((  9BKSBBKKKKB1 99SKBBKSB9KB9BoSBSKKSoiiԪiKBoK(9919B9(  B[S1( KSB(((1KB9(   (((KB11((((BB91(  111   KoK119B( BB1(((((99   (11111((BcK1B1 9cu1(( (BK11BKK9BKK9919 (  (911991 [B(1BB[oK1      BKKK9Bc[[S99BB919KiiScK((9·KSBBBKSKizc9K1 ( [S(i(1 (BB9(    (999K9 (11199( (11 11(   (Sc9((1KK9BB199( 91 ((111991 BS911(1 9Sic((((1BKB(1B19( 9( (1(1(( (((9119oicS((( 1cK ( ( 19BKBBccBKBKSKSBBS[[SKoiK91KKKBBBKKoK( (u[Ko  S((91(      ((9B1(1991( (K[SK9( 9[zoB19B9B[B99(11((9  1B1(((( (1[S( (B9[c  11BKB19B1(( (19((((1 (  ( 1((9SBKi19(19B(  1 199(111KSKKKKSKKBKKBK99uiB(SBBBBBB[Ϲijo9 9cc9(Kou1 1iS( (         11  BcS9BK9((9Sz[BBB919B9B1((( ( (1(((( (9iB  9BK9i[ (1(1B1 19B1(1((((11K[B1 (((111 (1[zo[S1 ((  ((1( 1(1 9B919BB99BBBBBB9BBBBB1Si991ziBBBBK߿cK(ciK1(         (19(  9119( ( 11KzcKB9( (BBB9( (( 1((9999(( (19Ku9 (B[B9SuB ((1BBBB911( (1111((BSK9(( (91( ( (9BB91S[  (  (911 (1 9K9911119999B99(B19BKB[[ 9BKBKSu°S( 1zo(B1      ( ( (( 9[[K1 1BB(SuioK91 ((9B9( (11 (1111( 199BB1BoB((9KKBBzB(9B((1BB9KB9B1(((((( (BSB((91SucK((((999BK9  (99((((((9119B9B19111KBK[ SKo³uK[zzǚc[SS1  ( 1ui 1(       ( ( Kz1 K[cKi[[ozc199(99B9(9((119(( ((  (91 BB(Bu[11KKBSuS [iB((9BBKB9B91(((9  191(1BK[[c[B(1KKB  (    (99( (99  (911199B1BSBSSBB[[1(icc[zzžc1((  9iuK(c9 ((   1    (Koo 1BBczi9B9SucB9B99(11199(91( 9(11(111111( oS19KK[iB( cuK1( 111999199(( BKBB119199izoioS99( ((     (((99(B9  (((1B9B[SKKBBSc[1 9co˼­c9( (SK (1K11 1(191191(     9[S1 199icB991(9B1(9111(  9 1199( (( 11( S99B9o[K91((zB1(((( (919BKB1 (B91111B1 9SSSiS119119(    ((11  1B 1((1( (199B[[SSKKBKcB(1Su˚¦o9(KK(1KcS19SScc( (19B1 1(1      1( KuB9SK1((9K19  1(  9B991B1  19 ( B9K[zK(1991Koc99(( B( 119BSS1 (( (1BSB  (9K9   1B9( 11 (((9911 ( 1BBKKKKKKSSSSB[cB19¿zSSoªǿ³zc((oi[uuc(1[1(991(          S1 (ci91( (191(((( ( 1 (9KKB1B9  (( (9SS[zz[9(11KB(9[B(9 1BK9((( 19[B ((  (( ( (B(   (11911(11( (( (((((BBBBSSS[SKSS1( 9K[( oo9uuozzuccB11Sz¼ķzic91czKioB ( (    (     [B1 1cc(1(19B991  ((999(1KKBBB9 ((91 coczK1(91 11(KS91111991((( ((   ( (( (( 1  (( (9BSK9KB(     199BS[SSB (( ((1 99 S¹zizzKB1((KšSSuK(1         (   Ki9 K[K11((1191  ((191 ( BKB(19( 91 9B1(99couc119199((((11(((9BB9(((((  (1  ( 1(    1  So[[S9(( (    11(19119KK9(( ((((19KB( zio[SKKBSKKiuzKB[SB  (9(     11   99 19991( 119  1199( (KBB999( 991 1BB199(Bizc999199((( (  99111( (   (B1 ( (91  (SS9ozS91 (1  19911(19 1119BB9911999((9Sczo(1i·ozzo[BBKSSiuK99(1     9(   BuiS (11(  1B((9( (9991(1(1BB( 11((119BS[cKB9BBKK1( 1(11(1  (BB   19 (( (z˿cKccB (((9BB91((1 199KSB1991((19B[zz1(z[[SSccizžoS        (9  BzzS9BuS( (1 1BK9((  (1 1BBB1 19 1(( ((99BBBScoocB9B(((((1( (1 9 (  19( 1 11  (( ([ᰄucoԿi1199 1199( (( (111BB99B999BBB1(KoS1(K³ziouiiuoozcǰc( ((     ((    oS1SiuS(  (99(( (  (  9( 19  (9KSB9BS[oz[SKBBB911(  1(( ( 1K  1B99S 1S9   (9( (ˢc(B9SҢi1 1B9 (1 (  1((19BKBK911B[i9 9SSB91uzzioScc[[c[ciͳzBK9(       ( (1    ou[[KKSu[    191((  ((9 (   BBB9(9BBKizzoc[iziB9BScouooioi[SSBBKczzoK9BK[K K[9[uoiz[[ioB((( KK1BB91(   11KB1(1BBBKKB9iuB((9SouSKoSS[S9KKKS[[cc͹׿ĚSKiK9        ((((  1oc[cKK[( (K[S1  (B9(ScS 911( 99(1KB9( ((((1BBBB1(BcoocSKBSi[Scuzoouoczui¿ªB(1( BzzziS99B1(1( (1B99B99BBKSKBK[ScoB ([oS(uo((S[K[SBBS[[czɼҿdzS9B      (      KKBScSB99KKBSiocB1 199911S9 1BB911( ((1 9SKK1   ioio[9111K[cc[S[[Sic[uoic[ooc[uzuzuuo[1 ( 1KoS(uҍc9191 (coK1BKBKBK9199B[[Bcc9[zc1 11 iK(S[S[B(1BB[uiSoǭѿĿK9  ((  (    uKKB999 1KK1(1KuiKBBBczoK(  (9(  ( ((9ScK 11  cciKSKK[SKKKKB9Kiooi[[KBB1((9ioSKSKB[oc9 K9BB9KB9KK [ўc911 1Su[11SB(99KK919B[SKS[KSzucS1  11Bɳi119[c[BBizS1Bc°š9    ((    KB91 BKB1 KKSiK9BSczo9  19  SooS(  KB9uzoBSii9[ic[[SBKK19Sc[[KKi[9999SiuuuzozoSSǿi iǼB(((z[K9199Sc911BK(1KSB(1K[SKK9KBSKKSSc1 (1(ǿS19 BocScuoS(1[zzĒѳ   ((   KzBS9 1S[ 1Sc[K[B9B9BScS   (1B(  9ozc9 (((119[zBKzc9SiouucSciouiSB9(BSKScSScccSccciKuɳ἞׳c9KSzuǖ[KB9((1(91( (B9B91BKKKBBBBBBB9Sio 1KijoSKBBKSKBBKuuoouzu      (((   KBK[K19KS[K (1 1KSKS9BiK11(9  BzS1BBKucK999B(KiSKScuzcz[BKSSozi[SKizc9B919BBiiBKco[oz[ooiҒSSuuuzuBB9 (  ((1B999KKKKB9B9BB91Koui11o¹uKBSoizzui[K(u   (   ((1(    9B1[SSBBB9SB(( (9B911ci9 1B((1(((B[1K[Suc99BBz[[B9BiSzB[cKK91SocKB9ScB ( (9Kc[11Suo[z[u䚉޿z1[izoczҀS91 (9B199BKKSKBBB919B99BcuuB 1cɹѭc(Bzc[oo[11(      (1((   [ 9SSK(((1KK1(9B9199BB19((( 1czB1S[Kiu9BKciBKK19BcoKčSKoziKBBKS[SB9991191 (1BSB(1Szoooouu乼o9(uzcSi͞K19( 91   11BBB9KB9(((1((1BBS[cB ((ĭԳi KooBB11B9       o(1BciS(11(99(1K99119111 91(1199((9coiS1BSB9Si[KSizB1ٚSKKSKSKKSBK999BB(1S[1 (1BB919SoziizԳSKKKoiK[[cͿcK911B(9SB( 9BKBKBB91 ((111BKB9S1 19ͰɳϹ[ 1S[cK999KKozi[         1coco(1BK[ccSBB9911((1Kc1119SK1 1 (  (1[o99B1K[cK11 (( ĒSBS[BKSBS[KSKS99(1[oS1( ((19cucS[׿Ϧcz[ 9[cSS[czǒB1191(B[[KKB1SB1199B991 (99KSSKS (11oļĪi1 9KK[[SSucooci    1BS[9  B9( 9[uzoc9 (19Koo[BB((1B999B9(1((BB( ((9((1zzSBKKK(zi91BKcSKSBKiSKKi[B(9KSc9((19Sic[[ɿўooi99c[BSSB99Kii(( (1BB1[[c[9911(19 (K[91BKSoucS[BKzɿ[9 BSKS[KozcSci (     B[BBS19KouSKK( 1111((( 1K[cK11KS11ciKBKB(  91( 1(SzSBBKB iiSB1(1([iSKK99B11B91(Bc[SB91 1izoSiϼĦS9KSS9(B[KKKBcoo9( ((1[zoiSBB19Scii19K[zo(uɦuuoiu[9  (BKS[cS[oiou(      (B (  (KS9( ( (  (9Kc[K9SK( izooi9 9KSB 1ouS  1zuS9   c[S1(9o[KB991 (1999Bc[9SSB91SioiSǷo (9BB[iB1(BS[cSuB19KKScoc[K9cz[ozKK[czzi1 cķ[cicuiKK11(1 919Kiic[iz[u9(((   S(    (KSKBK(1ouuzuoS  9KcoK [oK Bu1(1K1   BKBK911(111111( ( 99B9ioK[o[[KBB[zzuizzѭc9[B9Ki’zoKSĒB((9S[ic[SKciuocuiS[[izizcB[izcoiocS9BK1(9[iicSo1((11(   9S((1((  (999(  (11[SKSB((( 1[i[oiS1( 9i1 K[( (ic1Ki9 ciKK999 BB( (1 199B1(BciS[uc[oucSziuoKuoǢo[u1iۿ[1Bc͢i999 1ozzzɦiic[[ciozzzķzzuzuSKK(19KBczi( 1 K1 9KBSS9(99( (B9BBBK9(1B99B9[zu[9 ([ccuS( ((i( B9  Bc[B B(  z[SSKB9BKSB1 1111(111B[icc[[cuzoBK[oBuSSii˪բB ((9ocB9io[Ǣ[o[ccSSczooɳzozooccK[͖K9KS[cio 1   99 9[K9[[BBKic[K9(1BSB11KuoKii9KK1SiS1 1Kc[S[  (SBSuK(  (B9BSS9  uiKKK99KBKcS( (1(199KuiKK9SoocKBKooc[ϭdzĉ׳[1B°[Scѷuc[cSKcoSK˦zcc[[SSSўzS[9((9BKSSc( ( (  1S 1ioBBKB19Si[cuuc[BSi[BS[[uc9BB11KBB 1B1SuucS(  [i[91  11BB1(K[B   uzcBKB9191BKK9((1BKKKBczoSB9[SBccSKouoiչDŽڄKBKKBoĪzooS[ucɹucocK9B91ǢijzoKKKKc[c[o[((99KBo(199((((9K( (ci Suc11K91B[cKSccioBuǍcBcucccS[K9BK191KK1SuiK1  9ouK(  11(9999B[[   zSBKKB9B19K9((11(9KBKB[z[B9Su[(9uzc9Bo˦cKҷڳo(B[KK[zu³oKi[B[z[¢ui[SKBSB(¹ٿzѦ91K[ouS(1SizS(91((9S(   (  (ziBuzc9119S[cioiKBSoi–uKizcu[BKB 99B9KizcB KKB (11B9B1 (91(     o[[iSKKB19K9(1[S ( 1BScoKBBS[1S[19izuzSSoѳiڞS[BcKBK9 uoiuiKBSi[׿uiSK1BB ǼiSicS1 (1cS 9911BKSz (zuc9111SoccoiK (Boz[(K[czoK 1( 1B911KcoS (Szi( BK11       cuioui[K1(99( (B9(91919919SKiiuc[BBSzcKKiɞz(K1Ҁ(1oucocB1BSSǰzizuouo[׭Sc[BBB1[cBoS1ci[K99c  BuoiBB9K[iiSicB( ([[K[B111(9SK[[B9(  [zi99zccB   ((      KKu[B9((199  (BB91BB(BS[u[iooSKSS19oٿ(S9z( (uzoK99K9[[ozzzѿǷuSK[1 o1icB( [cKKSSo zu[B11BSici[S[cK1 1KK199((( 19Sic9 cz[9[o9        (KKzc[K9999BB1 199KSBBSB19BKzo1 KuucSKSi9K‰c( (譭z1 9zɄizicScKB9 iuzz[cuuii˿zSizioi[zz(11(1Ku   o1BBBS[iS99KSS91B91cS11(   19[uc1(  BK( B          Kiuu[SB((99BBBB191(99BKKB9 (Kic11Si[KKKB9cSzcczBc ( 1BcǍczcSiSB(9ǷuicKK[cK İuSS[icB[uzԹ[ B 9i199Kcuuc9BSS9(B(1KiS(  19B[cB9(((1c[(1cS ((     BuiB9(91999((199K[91BSK99(B[[99K[SB9199B1Ki [ܿ[z91( 9o·ɭzzoS[K9(cǢc[KBKiSSSKK(dzoKBKKSS[[[oiS[cԷ9  S  [S9BKcooi[BS[cB (( ((9B1(  B[11KS9 (9coS(((9( (  SzzzzK11(((11( (1 1SSSKSSK91BKBSciiS99((1(((1ou1izouiK  11 1‰zocBKKKuoci[S9BSKKSKScǿcSBSSiuSBK[oiS1iǒ1ii  ǖKKKBczo[BBSSKB ((9B1( (9[c(  9ii9 KSB     (czo[9999((111(  (Suc19B9(BB[oui[KBB1  (1KщSoozo˦c999uc9 Sĭ˦zuccczcSz(9K[i[SϿBKKcc[[B9KKozucScooҼc[oK1zoB   oBSBSouiK9BSB9iS (9BB991  1BSSB  ( 1u[ScS9(( ((   9Sooi[SSS9((111(((S[9999(19KiocSBBB1(19ĒizooKzɢB9 uS͞Ǫzouu1[zic( 1BKKSSǢ11199KSKScioozzoizc[ذi( K[KK9KizSBBKK99c1 (19BSB11911((9ScK (911c[[[(  (BB9BB9(  (((((K[zo[KKS99B9(1 (( ( 9B(9B9((KSSK99991 (((99Kzii[BzuSKizҖzǒioooz[Soicc9(Bii[BBB(1K[KSKǪi9999K[cuuuozzzߚc    ioBKBBSziB1BB19BB (BK[S119( 119oz[9((99111iK  191(  (   9K9( 9[iuziKKK9911 (( (11(( ((9B9B11 9B[KB111119B1191Sooiuo9((11cKǍuc[ozSSouoz[SK 1BB1 (( ( ((1 (KSBB[lj9199Kioc[S91B9Buԍo9   zcSSBBSiKKKKB119 (1BSSKK91(9izzcBBBKB  (SS1     (  (9B[9(Sui[cizoSK9K11( (1((111( (999B9BB9SSB991999BBKSSiK9 9coԚo[Ϧu˪cSSu1    9[SKuύSB999KB191  1[oouSc1(19   9i[[SBB[oBBKKB9(11 (ScSBKB1 co1B9BSB( c[(      119KBKS 1iucKB[iK991((( (( (119B91  999[c[B1(11BBoocooiz9(BBĖu[zžzoϦoKiu9      ((KcSKčcSBB19S1(   B99KK((  (zc[SKBKS[99KSKK(( ( 1S[SK1911ucioiiSBou[[S9(1izS      1BKBBKSS11(KoccSB[[KBB1 ((119B999( ( (9[i[SK9999cic[K(1SѿK9S[њ[KcB     (( 9c[9BɷuoS[BKK1  (191BB    oKBB1BBK[[99BB1KKSB1 (9SKS1B99Su[9B999[uSB91 1KB  (      Kcc[SSS[KB119[c[zuB[oSKK ((1(1S91KBB1  (1BciS999BKcuuu[ScǪzc( 11Bc˚uK9ˢϭ[1(  9io[  (((1BB1B˪oi[c[KK1    (((KK1    9uoBB99B99Kc99SKK[[oB 9KSBK99BKBKB9( 9KB[ouSSB9 (     9SiuuozuS1( 9[ioKKzi[K( 1119B[K9B11((   1B[[[K99BSiicSziǪSKB(9(9uB(9o޿c( (11oiB (91(ɢiicS[cSB1    (199( Sz[11(9BBBSS1199S[K[K( 1KSBBKKBKKB999BK[K1SoK[z[    ooizioi[9( (K[KSS91999BKcooSSB1(( ( (11BSBBBK[[c[SBiouBiB9S[9(91 z˰ScljoK11( Suzocu[   (BBKϚ[[SBS[SKB(19KcB1 ( ((1BB1(9  SuK11111911(1BBBcB(99  19ScK1KSBSSK19KcccocKiiuB    1    ii[uoSKB991(([ɭouiS[cKKS[uocS9  1((( (1BKKB[cKK[SKKcouzKKķ1  ͼҖ99SK9 cc999B1 91(  9uˢiKBBB9(19(9zi (1 99B91S (Si1((11(9991(1(1S1B(11Bi[BKSB9SuS1KuuKoz[ BiS     (9zzii[9111(B99KҳzoiBScoo[uiiS9  (1111999BScuiiicScScicBB( BԪcK9 (S1ҭ‰91zB [B(((( 9iuz[Bi‰9991  (B[ǪoB[iB( (1BSK9S  Bc91911(1(11(1(19 (((911KB(9KB1Bi[19KoK9[uc 9KBSS9SuzS1  9uiKB9BK9 999oziiizzicSB[zcuoiiK  (( ((((9KB9 Siiiuu[co[cKS  (1Sz[uuczĚٳu˖i[So(9B  1ScBiz͚K111((19[oǚi[[S9BBKKBK   BcB(11(11919111((  ((111(1BKBB[[1(9B91Bzo9999io9  (B[[9uuizzuiB19(  o[i[999B1 9Bcuui[iuuu[[SBKoucoc[[111191( 1B( 1B99 11ScK[iizi  (SiKBSBiҦzuo[u9(  19Suo[c[9ɪ԰S(((19BK[uڷ[iui[ 9oS99((1( 1999(((((1( ((9B99BSoB9111(1SKBcK9Sooo  (1BSBBoc[czoB 1B  (oSScK9B1 ((Bzozo[[c[iiic[iB9BKKozcicBK[KBB((19B1((99( KuiSS[zoK1 ( ( B[B(1(Biziޢoi1(SǼ( ( 11SScociiu9Boz1( (999SǿoK KoK1(((199111 119991 (1(19199BoiB1 (91KK91(19BKK BB9BKiB199 (991 9BuuocS[K1(((((Kuioziizi9oiK[[9(9S[iiSSS9119KK1 1911199 (9K[iccu1  (9S1(1B( 1[[[(z[uiuzªu(111BK11o[cu[ uSמ9((19B9cǢ€[Kͪ K[BBB9(19(((((11 ((  B1(99((9Bu[1 91(1((1   1cS(11B  BSu[cccBBK1199 ([cciuzoczc(ɢcKB[K( 9KBKccB( 9B1199BKB199( ( (9S[coouz(9cK( (B9Ko[SucSKi[uS B9( 1uK(ccci9iس1 ((1BKiؿݼ[Sҳ BK99BB919(  (  19119SSzo91(99((( (  9S( B9  [9icouiB1B1 999[ouuu[uo9KSScc9199(1KKB9(1( 191B9BciB9B1  11BKSc[[9 (( (119izK KSoocǼS 19(((uc(9ozK(cK(((9SBcްoªͪ (9BKKB9111( ((  (11 (991( 1SBKoiK11S1(999( K( 19  9BioS[[9(9B(1KuzĪzBzKKoK191(9Kci9( (919[[S[K9B119( 9B199KooioiKBKBB1(cocS11KK1 Bzuiѳo׳˞[1(((BzoBBuK9B̀ (19B9iɿԦͿo(BB9999((1 (( ((1( (1 KiK99 1BBBK[B(1B911((  1   B1  BccouSS[9(11(SuzuzcKSi1BzoSB111BKKSB99 1(11coi[S911 199ScB919icSc[[c[11iiBKBBB9( SocK[u[ϳрS1((czcKo¢uz[9[uτB1(1 ( cڭɹuc  9B99991( (1 (9999  1(1[[B1 (9B9199( ((1BB1(((   KB  1uuiciSB1((119czuzS91KoS1KoiS(1B[icKK9B BBK[[c[KB1 191BBSiS9(9oi[[S[S1 KzB9B( 11BS[K99Bcu˪؉(9  (BS[ci‰cB(cͿ9( ([ļSioKc B91(111 ((1( ( (11( (( 1BSB(11191(9BB1 ((((1199  1S111 (1BicSK[zBB1(11((1KSziizi[S[KKcoBBoo9(SKciSB19(1c[S[S[SKB1 (999KKSSB( coo[SSSB19cuS1(( SiSK[oc9111[ci°מ91 1(SSii1 1[㢖˿19BuҪSSuoK[z[  1B19999( (((1((((  (( ( 9KB((1B919BKB11(11((99 (BB  (  1KSSc[[[i11(B[B199S1Bi[[cuoSSB99Kuc9SSB1SS[SS9(( 1SKBSKBBB1 1SK11BB1(19BS1B991BiS1(9B9[o[cu[S[SSSS(Bi՞K  1BiuS[(9BϰB9[zԉiioizSSui[B 1BB11119(911  ( (11( (  1KB91199BKB[B11( 9KB( 9(  (9K[[i[KBK911[S(1(9[B9111KBSKKKK999SoSKo911BiSKK(( 111991991 [iS119K11KBK(11((BS9 (9SoiSS[u[KB119[zSuz((cio[BBi[ii9Sϼc(9iziҀiouz[[S[BK1 (((199(1999991( ((11((1(1 (  (9SSBBKBKKKSSSB( (91( (9    (9KS[S911119B91((9KK1 1BSKKK991((izK9 1Biuci[ 911BB  1S[9((( (991u11919ScS1 ([zzcKKiuuiKBK111Bciu[  Bz[SicKSiooS[SKoٞKK[zǢK9Bocoii[i[cSBKKK 1BB(1BB11(1919B99((1 1((111   (((1BKKKBSoiSS[9 1cK9(    1999BBB1 (( ((19BK9 19( 1ScK99(1[oo[ SB(1Kc[SuK  (19B( ( ((1B(( (999K991 1S[9(9cuzziS9KzuuoB1((9Sozooo( 1oo SS91cuB SKKScĭo[[ucSicS[[uz[cB1K9 [SB19BK199BKB9K99BBB999((( (  (  (Bc[KKK9BK1 ([uB(1(  (( ((1BSK(  91(B19B9 (9911 B[ic91S1 1BBBoo (9BBBB11((99S9199SciKSucBB( (9KiB1K[[iicK9ouczo9((9KKS[SK1 (9SS([S1 KzB(zzu9Kicu˹icuooc[icKKio[(99B( (iB99KSS9BBKKKSSS[[SS991(9111  (1( (BKBBSSK9  K[91B9  KoSccK(11191(   9BBKccKB1(  9KSKB[K (BB19( Bi(11( 9KKSKBSKB1(Siciiz(Bcoc9( (1B[B19BSiSB9ouzooB9BSB( (1 ( (SoziSB99oK1coS[͹K[ziBS[uo[KBS[9 (11 S999K[SBKKKSS[[S[S[SKKB11(((( (( (( ((9(119BKKS11 9B1199( 1ozcco[B91((   (1KB[iS91111( 9ciB1[K (K9999SiocB11( KKB99(9BB((izzuu(Boi1( (11KK(19KS9Kiioozc[S1  (  (S[((( 1zoozS 9[SK[iǞBBc[11[ococSSSB1(1  99BBBSSBBKK[cc[[cSSKKSKBB991( (((111(1 ( ( (1BB9 ((991  ((czcc[iu9   (( ( SBuz[KcK(( 9B 9cK  9[K119BSzo1   9((((111 (KczziK[ccB(1( ( 19(19BBKoiuuuoz[9 B19BuBcS 9o[B[[o[B11SKSѷoK[SBKB[ic[[S9 (  (BBBBBKSBBBKccSSicSK[[SKS[KB1(1911 (( 1((( (19(1(( (91  ( BuS[[cc   ( i9(iuS99(  19iuB  (KK((119B (1  (( (19KiziccScuSB1 (( 11 (1111cuozzuzzuB BcS((1[o (ui(9c[oiS[K1 Kɳc[[SBSSKS[B 1919BKKSKKKSc[ScocSK[[KSii[SSKB99B((91((  11 (1((91BSB  ((19BB91BKci (   BK1(S[(   Ki 9B(9B(9K  11B9 (BKucK[cSS19( (1  199BKiouuuzzzo[SKKK9(19co1BK( 9[oK(  9ɭuS[SBBKBKK( (((   B9999KBKKS[ccSioS[[SKBBSSKSuo[BSB199((( ((  11 1B9B[1  191(119(  (( ( (9(9KS[99iK(119B9 1B   119KB((1BSzzKBoz[(19911111( ((911KSccoiuo[uuzzz[S9( (1(Bu(Kii11B 9uo–KKB19BB99BKK9191(9S[S9199BKSKBKK[cc[io[KSKKKB9KKcu[KS1SK99991( ((111 (1((BBK[(  (9BKK1   (B91Si9   (1cK(( 919991 (  1B9199BK1 (KiiBK[BK[[BBB(  ((9B99KBSuK[SSizzouiB ( (cucB9u[uuK(  SocSccKoĞ[KK99BKB9SicK1( 99BKS11BKSSSKKKS[[SSSKKKBBKKB9K[B BccK9( 1KK99(9B11(1(1 (S9Kc( 1 19BB91(      (919( ((BBB1( ((9BKB1  (119K[S11(11  19Ki[SzKSii[9 (( 111((9((1Buc9BB[zzzS(91(1So1 1SSio9  io(Bzo[B[99BS[cocS9 (199(9[(19BB[SKB9BKBBBB9111BB91(19((BS[KKSSBSSB9BBB91 11 ((999K (919B9999(    19  ( SK 1((9[BB911(1BKBKScB(91  (11SoBK( BK[uc9111( (11(1i[KBBczzzouS1KBBKi91SzzcKi1 (9[oBSz[KK„BKSiiuucK919K99cc[i11199KSKBBBK19KB (9B9(  (9B99919KS99KB9BKB1(((1( (((1(991(      ((1KB(1(19K91999(1B999[[B199 (1(1SS( 11(B[S11(9B1( ( 1cz[KSSiuiuzi[SK9Bcu[u[cuK((1SKoS(oooSKKi­[9[uoooz[BKKB9[uo1919BKSK99BB9BK9 (11(((1BKBSK(199B919991(1(  (11      (    ( ( ( (1 191(111B1 (1111 (1(1KB11919( ( (11(9K( (KBKSSB1( ((1uzuuo[coouzc[zzoicSBSic1(Kc19[9 (1KScc9(cuc[11KcĄ1Si[[cuSKB999[uio(((999SSSKBB991( 111((((9KB991 (1 1 BB( (9( 91(1 (111KB    (((( (9( 9KBB1((((11(1(99 (191((9 191(((((111 (KS1[cS1 (1((9czuc[[uzucScuzuuicuo[91 ([B1BB1BKBBSc[B( (11119 1[S119KBScĭ[B[cii[KB999BSiSSS(111BBKScS9BB99111((1 ((99(  11   (99191 19((( 9B9[K    (( (1 ((( (9Kic9 ((B91 1(    (B1BB1  1(( 9B SSK[S1 (1((BzSiuc[ccSSS[oucciS1 (9((9( B[K1 ((9( ( (( B[9(KiĦccucKKSSBB9K[[KSK(19BSc[ScuS999((1BB91 ( (  ((   1111B1 11( (9B9cS     91(1BKKK1 9B(((((991cK9  1(((1  (11( 1BB9[9((( ( ((B9 B[BSS1   KocoocSiziSKS[io[iui[99K     1oS(  ((99(1BB((BSzǿiK1BK91BKKS[K((9KSooc[[ui991119BK1 ((((  (1 (   (99( 11( (1BKc9      KcKKSS[SK9 (9B((((( (1KS9  ( ( ((99Kio9((9B19S((11119K czc91KB1 (19ciiicoc[[cSBScciicuoS1     91  19119(119BBS¢zcK11BB99BKKB Ǫžz[³ǹѳz9(Bc[zi[couocoǿѭociooiooc[uzɳcciщcuzuoc[KKBؖɭǢzo¹·oB9iucoic[iozݷuiu[KScoiiuѿB1i9Bczu[iiKKiؖϹ˦ouo[cK[io[K[u‰SSS19cooouzǞoc9(BS[uoui[o׍ɼϰo¹uz¼[B[uuSKcտcc[BKcuiuԍi[919BB[ouoo⍉¢ѼouĹucKcii[[’cccS[uijzccuiBB9119BSizލĪԼzu¹ziS[izi9zǼšcScSKzzzc[cԭKBK991((1KɉɦĦuǼuouoiS[ioSKu1(oļɼɞcSczzucSuo BKB91(((KooɰͰiuou[[ccB9Kiozu91SͿ԰BBuouucizo((9KSB(((1BiS9SzɹҹiziocK[icK1BK1Kuļɷi9BiuiziB(9KSKBB91SoS (Szzc[ǼԿuuoozu[[iiKc[19zѳϿװSScuozzK19KKKKKB1Kuc( ( (9[iiĦҹzzc[uuzuuc[cu9ccBoĹSS[oiB999BBKS9Kuu1 (1Bc˪ǪcB[uzuzciuB1KzzzzuzҳĞi9[iBBBB9KKKBBuuK(((( (1((i˷ɳi[zziuuS1Boo[iScͷɦ[Bi[KKK99BB99BzzK( ( (iķϹuz¿uucKizz[BBooziKcz˰SBKKKBBSS19iS ((((( K[Ǧz˦ɭzic[KK[coiS[c[uui[[zͿҿiBSS9BSK1[c((( ( 1S[1ϰzļɪu[iK[[[B9cuizKSiuiB[ɼͰi9BBBSK[i( ((111( KcB տ˳oczou[S[cS99cu91ioczϳϰo99BBBo9 (9B1(KiK1 ǿ¢cuzouooo[SSSS99zSKKizªu(1Boz1 9B99(1uS(( ³ļ˰B1oS(cc[zo[[ci[KKSoiB[Ҽz9c9 (9BBB11oo(((¹ǷҹKocǰzuS[ou[[S9B[iiSi99oĒu[ ( (111B(([u1 (ѿɷoĹɷz[BicB[[SB9Scio99ǰҳc((91((((( SoK(( 1 ¼ɪķļdzuiuKBSicBBSuo˦o[oɷɀBBBB(1((KoS9B991 ¿¿ļļĿijKi͹ciĪ[K[c[K[zͼoSKcذK9BK9119( 1oS9BKKB91Ŀ¿¼¼ĹSBoǼcoo99uijzziBKciSªuSSc˚ɉB9B9(11(Kic 9BKKKB9ǼѿǿKSˢuSKiucKSociKSoz³u[SSiݿԞK1BB11Kuc((99KSSBB¿ɿ¿˿ĿǷĭo[ccSizu[9[o[oczzz¿cKK͢ԦװoBB9Szu9 1111BSK[Ŀ·ɿĹuuB9Sc[ScuuSzczizcczǪz[ǰİˉB9uB 1119Bcu¿¿·ªǿcooziKBBSic[cuu[[uzK[zcS[ouɷzѭͷuSzщiuS( (199KBSĿɿݰzcizu[uz9Sc[B9[cciic[K[[[uSSoiKBou³ķĹiiciԪ[ 1((11999iǼ¿³İ°[coc[izo99Sc[K9KiuzuS9ScuuiuS1B[oc99i˷ݒ͢S1999111cļ¿ļǷɹuBSuzi[czzu[[cSBK[cK9[uouuB9KiuoicKB11KiiKK˳[Siเܖzټi( 11(KĦĿǹɼ·SBSiuc[iz9BSSKKK[cScuiozzzzK9B[uc9BSKB1Kii[zǼoic9B[–cSzzz(Bzɞc¿Ĺ¹˼Ƿ[BKouiu–S99K[K99[KK[uuouoKKoocB9BSSK9Bc˿[1BuuB1Kzռii˰̈́ z¦c9¿ļǿɹĹoKoi[99KSSBo[9(SouioiouoKSSK9KS[B1S­uoB1KouK B˪oou볞zտɰc9B¿ķ¼Ŀɿzcu119Sii19iz[ScBBKSSBKKS[ooSzz˿uuzzcKcuiBioiSc⪭ĹϳS9Ĺ­ͼzucB9 SzcozzoozcSSB9K[cKBS9KzicuĪzuoS9Suzozuǰ[iu¿ķªijzǭzo[Kiz[oSSiKoc99BSKKici[zcKcocuzccoKcocz[c[cѼǹuciļ¿¿Ĺǰҿz[uu¿ziSoSzouiiuuc[[BBSzİ[[[[oKcz[ 1[Siioc[zc9B[ϳǼzco¿¿¿ļdzķu[cšcizo[uzo[oo[1[ǼuuzuKSuzK SS1iicuzi(119K٭Ϳzzio¿¿¿¿Ĺ˿ļzuooĭiiuizzz­uouoicizoǭ[9czco((9i[[zc91(1(Bҿͼiuzuio¿¿¿Ǫɿocozuiozu[cz9c[uozciuucoϹu( 1Soi9SB(1(Bϰoz[[ioziSo¿¿Ŀɭ³·zo[couiucczu[SuozuiiBS1Bzzciuzdz‰( 9zK(( [ɳi[ucic[ozu[u¿¿¿¿ͳij˭zizc[[izzicziK[zzSczizi1io[z­zuĖ9   [˹ǹc BҼc[ioc[ioii¼¿¼³ѿ³ԦBBizi[u³zccuzicoiSzooɼoͼc[Ѣ1   1čİcҷiBi[[icuuuuo[¿¿¿¿Ŀ·İɼտc[ªc[icSiuzzǢuiz˪K  1i˰Ԛ͢ouzcS[iz[SizuSKu¿¿¿·¼ɼɷͰ¢zzͿi[K9[zoizi[uijiuzuuɳc   Biצi1ccS[oiSSS[oo[[z¿¿ĿļĿdzɉªuǹuo[[couzi[oz[1K·[iziccu(  9SBK˿o919cccocSSc[Scuzuou¿¼¿³ϳɳͿ[iɼķciuiccouuiKSciS[šcu9Si[oK(B  (SB((Kҹ91SKBc[uo[[[[c[[cooo¿¿¿¿¿Ŀķ˹ɭcciĀc˿uooiuic[ioSuiKB[ooicKoiiK(uc(   SK1911BzǒS9BSBKBciuc[[c[cccScuio¼¿¿¿¼¼ɷҼ’uui9iz¿ɭzuccuuo[i[cuocKKcozc[uui[( (K[1 ((((9zͭܚB9BBBBB9coc[c[c[SScccuuSc¿¿Ŀ¿ǿѿžzzoczzcSioSSozzocuucuzB1SiSSuĿzooc1 KS91(((((11u 1KKB99Kz[K[ioc[[[[coi[cuuS9u¿¿¿¿¹ǿѼǢzzz[ciuziSSoou[KSoo[cBii 9c[iz­[ouK[cc1 SS( ( (119([u91BSKSoKKScucS[[[ioo[ScoiKBc¿¿¿¿¿³ĪzzzucKciuzoSSoS[9Biuic[( SSKuiiz[uz[B[oBBc9 (1191SKKBKozSSSScic[[ooS[cSKcooiB1o¿¿Ŀ¿ijɪuouoSuzoozzuiooc9KocSzcBiziBi°oiSoizi[K9  ((9K[oocBcuu[[[[[ccS[oiSKccSSciuiBS¿¿¿¿¿˳ͳuoicoiizo¹zuzoSoKuzoSuz[o¹icuc[­K1911  ((KoSicuiziuuzS[cc[[[iocScSS[[SSSiucS¿Ŀ¿¿ǷͳɭuzzoBczccuoǪzoi9c¹iiiozzccuouo[cuzoi·i1991((( 1uS[iiozzooz[S[cicKSoo[K[c[SS[SKczciz¿¿¿¿ɹϷĢԍuzi9[uoĪzzuu[[[¹uiuuzSSciuzzcozu[BBi¼u991(( ( (ozKScioiiouicoSSK[[Sooc[SS[SSSKSizzozzcSo¿Ŀ¼¿¼ĿѿͰ͞זuzzooiz˼Ǽzooozu[ɹKBzi9BcuicocioiK1[¹99B9111 ScScczo[zu[zocKSSSKco[SS[SSS[cSSozcKcuuuoi¿¿¿¿¿Ǽ¢ͪ޳ccS[[oz­ɷzuuzɿiScB9Szui[Scoco¿919B9(19((S[KK[oio„[[oKKSKSiKSS[S[cS[S[uocSSS[ii[¿¿¼¿¼Ī͞cooiSB[ziSzɢzuoĹuozǦoizzKco[ci[KSiǿK 99911119[¼uKKc[oSKKScSBBSc[[c[cSz[BK[SSKczu[c¼¿¿¿·ǭҼSiuuo[cioiuBiĞiS[KSiǹoozzɼ¹o[uKSoiS9o·[91119((99[ǹSoSKBSi[BB9S[[SSSco[SSKBKSBKSiuo[i¿¹ɹɰؼzci[1[oS1BSǭ[KScKKScǷzozĿĿɼ­S[zoKScoiɪc91111111(BuKKSicKKKBBBKSKSio1BSSBBS[KB[ziSzĿ¿¼ɹǷѼcouK9B1Sz˪i9S[[SS[[cİzɭcK[zS[uiuɳu991991((((zBzKc[KBKKKB99BB[zoSBBBKKBBKSK[ozuizĿĹĹϿ¢iSccS9 9KiǷu1B[[[SSSciuǿuoĀioKKouozoǿ€1 1(91111(cķouciKBKKBKBBBBcuzSBSKB9KcSBKSccciuoco¼ǿª˰ǿͰiBii[cc[BuK9Kcc[S[ciooi­oScϰuuoSSozoKoɿĞK1((((((11Bijocicu[KSSSSKKKBBou[KBBS[K[KKSK[i[KK[iicSu¿Ŀ³ª˦ѹɞ[[ouS[[KKSS[[[oou­uKSϭzucKS9KuǚS99( (11(Kz¹³ɰzB[cuKiKSc[KKSKBSiuSBS99BKc[9S[[KKSSBSii[Su¿¿¿ĦϦɼozǦuuSiSSSKKS[czϿzuoioo˳c[ozoiS9SoS1(1 ((((1z¿³ǹS11[zuzcuSoSBSc[KScSKioc9BSKKB9Szi9K[SBKSSKK[iicSS¿¿ɭѰǚzuuiSocBSKSKSS[ǿzɹzɳoS[zcooc[ScK(1  ( (iš[199BSooocKiSSKKKSSSKczcBBBKBKK99Sc[[K9BBKKSKScioKo¿¿ͷѭ¿zozzu–Su99BBBKKSzzouuzɿ³Ϳo¢uuzcSSi[  (((oǿoK19BKKSoucScS[KBBKSSSicKBBKSKBSSB1KiiKB[[SBKSSSizuiiu¼¼Ĺ˷Ϫǰuouzoozѭc9BKKKKKzuou·°ococccSizc( ( (( ((oĦzzzªoBKBKKKSS[uz[9[[SBBKBSicBKKKBKBKKKSKK[[[SBKSSBKS[cSSoo[o¿¿¿¼¹˹ҰĦzuiiccouuiSzSKKKS[cǦoiuzz­uǭuzKK[oKScoc9( (1(((iɳuzo9BKKSKKKSS[zocSoSSKKKKSouS9BKS99KKKBSc[BKSc[KKSSBB[cKBcooiK[¼˹ѷuuioccouķĖcKKS[oǞoozuķoɰҷi[uzSi[9SzoS[zu9(91 ((((BϿuzzu(9KKKSSKSKKiuo[[SKBSioSBKSBKK99BKK[c[BB9BS[KBKSccSSBKSouiBK¿˿šuouozzuoozϷ׹o[iuzͼzĒ[Ǣzz91ci[BSuooz[1(1( 11BǍuzzzzzuBBSSSKSKKSSz[S[SSiuS919B99KSKBB[c[SKB99B[cB9[cKBSSKBSouiKc¼¿¦ͦѷuiuǞѷuuuɼĪBBͳc19[uiKBiiS[B(( ( (B¹ouzzzzzz[KKKKSBKzzc[S[[iuiKKBBBKBBKKBKcc[KKSSKBBSSSSKBBBKKSK[ozzu¿ɭͪҼšzuiuؿĦuozdzuc( BϷzo99cui9SuciiK( (1ziuzzzzzz[BKBBKioKSSScoSKKBKBBBBBB[c[BKSKKS[K9Bcu[99K99K[SB[zi˳ͪ˼ļǚzuocci˦ucuǿ˳oo1(¦uzi[ScuooozuS( SdzuuuuzzzS(1KuuSK[zuKKK99KBB9KBBi[SBKKBBBBKBB[ccKB9BBBKSScouzu¼ļ˷ѭѹĿuoocouccuķªϹ99zǖuouzoSczzoouS1 1Ŀɹzzzuzuzzc9uKSuzcBBKB99BK9BKccKBKBBKSKBBB[S9KSSB9KSSK[ocSczucu·¹ϿĦͿdziiiccuo[cuozzzɷǹͿķ[BĢiicoizzzicio91¿˿uzz[uu[KBBBKSKBBB9KcSBBKSSKSSSK[cS9BK[KB9BKKc[[SKSiuoĪĦļ°i[ciic[icoͳ¦ǿļoiziSiziizoK9z¿ªuzǿcocK9SKKBKK99BS[KBKBBSSKKSSciSKKKBBK[K9BcS99KSSSoouķɰɢc¼ͼu[iiuz[ccioͦݼ°uozu[czzuuuozķiiSB9KBKBKBKBS[S9BBKKB9KKBSc[KKKKKBKS[i[SBB9KSSSKooǰϭcKĿĿǼz[uoo[SK[uzɦɷ–uizzzucSizozǿi˹o9BKKBBBSK9KKcKKBKBKKK9BB[cSKSBBKSKBBSoiK9BB9BSSB9Ki˳ϹiB[¿¿cuioiic[uuɭǹѢo[oiSco[couijĹ91zzǿ¿ǼKB9BBKKBSKBBK[B99BB9BKKB9[SBKKKKBSSKBSicK99KKBKS( iĭԿSKS¿ciuuuoczuoz˪ĪԪzz[BKcioccoĭ¿¿Ģc1 cuuBBBBBBKKBBKSSSKBBBBB91BKS[KSKKKKKK9KSc[SKSBBKSKB 1ijĹi[[·coczuiizoiu˞˷Ƿzoicc9Kozoo¼[919KzzzK99B99BKKKS[SBBKB9BKK9B[[99BK[KKKSBKccK9B[SSBS9 uɳĭ¹iKi¿¼ioi[occozcoǞɹǭcSoucSco¼[1B9B9czzSB9BKBBBB[cKBBB9BBBBBBKSKBBBBSSKBKS[SSK99KK[SB (c˿ͷɢSiĿ°°occSzuciooiiɭɿ˹o[izoco°o999119BKuzKKBBBBB9B[[BBBK9BBKB9B[KBBKB9BSSBB[[K9BKBBKciKcİ˹ͪ°cuĿϹucicioioococuǪĿ¢ɞuoui1111119B99BzzoB9KSKBBK[SBBBKBBBBKKKSSBB9BKK99BKS[KSBBKKBKBKB K­Ͽ԰zcͼziuocooiuzocuioǭϹĭɹzuǹo1(1B9(199( KK1(KSBB[[KBBBB9BBB9S[[B9BBBBKB19K[SBKSKBKS[BK°Ħٿ[¼„uzuioooziuzouİϿ͹¼İiiu°u[[K11111 1[SccK((BK[SBBBB9KK99BBSKB999BBKBKBBBKBBBKKKS[S(9ͼ˰ǪijǼǖuouoiiiĢzozɳ˳ѹǰ˳uKcoϭz91K9191KS((cc[K19Sc[BBBB9BB99K[[B19KB9BKB99SKBBKKKK[SB( o³˳˦˳ijɢzzoou[[Īzcoɷ°˪ͪɭuuozǷucBKKSKBK1 9cz[[[BKKBKBB99B999B[[KBBBBKB999BBBB99BKKKSB KdzͼѭΚɳ˭zio˹ŞѼķzķzicKcccK1 ([zcc[SSK( BKB99999ScS1BKKBB9999SS999K919K9 9ijɼѿسzzǹi[ocɿǷϷɼ¦uiuo[czuSK9 (BuiKcҳ[[[[[cK 9SK999K[SB19BKBB9BB9KB9B9BBBBK 1idz³­­¼ϷļcccuoɿǼ˭ɰͼiҼiuu[[zc9((BczS19oDŽSS[[S[[K( 1KB19SK99B91BKB99BKB99B99BK999z³ɿɷǦǷɳzuu­iSoouoĢļɦɹİտucoiSoK19KiS99K[iǖScSS[[c[99SKSK991B99BBKKSKB919BB999 9zǷ˿ѿǪķϿocKB[uijo[[iouoɢҼĦ¹׳z[cio[KSS[oS((cǞo[[9BKc[SS91SS99B991BK91KSB199BB9BB1 9u˼˿¿¹ɰͰi[ļͳzuiSKKczSi¹oc[Szocɦϼͭ°S[oozicu1BScǞz[[SBBK[KSSK1 19KKBB9199B9SKB999B99B9S­Ϳ¼ɭ͹˰oui[SSiu9SuǰiiouoǦļ·˦ؼ[iiSzi(9cS9o˞SBBcSSKKKBBKS[S9 9BK9BB999KK99BKBBBB11u°¼ϹԷ˷zĿSS[[cuoSSu˭zozz¦ǿͳǞ¹[[[B1[zo[ϦocKScKSSKKK9B[cccB 1BB91B91BB919KB9BB  1z¿Ǽտijijz˼ͰcBBSizzc[dzciuͿҹɪ¼K19BozuѼiS[SKSSSKKKKBSc[S[SK(9[K9BBB99999BBB1 9zǰ˿¿ĭɳi׿·ɍKBScuoi¿ĿzicioĪտ˿cSccoooĖS[ii[S[[SSKKSicS[[[cK( 9KKKKB911BB999 (oĹ¹¿¿ͳҷooz[ѭiKSSczuǷĿuccc°˿ǢĪzz³uicu˞˖iuuSSSSKKS[iSScSS[SB1(1BSK999B9KKB1 cǹļ¿¼͹­ǰǰķSSSSouĭzzo[uui¹ϷǢijzSu˳ͰuzSSSKSKKSSKKKKS[[[S1 1KK9BBB9BB9SǷ¼¿³dzɪ¼c[c[uc[[Szi¹ҷĖѿzѳҿu[SSSSSS[[KKKBBKSioi[9((19B9BBB1 Sķɼ¿ǰݿ峉ļļoiciuiouu·ѳšǹzzǰ͹˷³KSSKK[c[KK[[BBSioc[K1 1KKBB9 Bž·¿ͳouķcuouzzzz¼ҿǞİzǿ–ĖɼoSKKK[SKKSSccKBKKSSS[SB( 1KK1 oª¹ǿ¿չcužz[i°ozo˼ozuuzo¼ǷǢİ[ijѼoSKKK[KBKKKSKKKK9BSSS[cK( BK  [°Ŀ¿׼▄ǭuouɿouzzzϹǰǹĞoɿ˹uKSSSKSKKSKKBKKB9BKSS[S[S91B Sǰ³ɼ˼ǦߪˢzǼ·uoɼϹǼɚɹѿ³Sc[KBBKS[SKKKKSKBBBBBK[[K11SǷ¹ǹѰ󳀉ɿzizz˿oiͿѹǼͰķĹS[SKKKKS[KBSSSKBKKBBBBKKS(SǹǼ˿ԼzoɿzucozozѳzuuzѼ˷ǪǿϰĢK[KKSSSSKSKSSKBBKKBB9BKKB K¼ǼͿĹiԄļǢɿzuuoozzuɼ¿˷ͰĪԼ­³ª·ԒKSSKKKKKBB99BSSSKBBBBBSou[KSSKKKKK9BB(9zzioiiɿѼK11B9KKBBKK91BBB1BuSKKS[couBBicKSK[SS[ɷ[(1((B919BSciz91KuS1(119uɢcķڰSBSSSSKBB9B919KKKBB99B9BSiucKKKKBKB19((i[Ϳצ[9[oz[B9( 19(1BK91KiSBBBKKSocBKioSSSSS[[İǹϭoB19BBSKKKKScuB 9[zB9BKBBoϚS[z˷ĹSzBBKBKSKBB9BKSSKKSBB999191Soui[KB9BB91(i·oi[˹S[o[KK9 (9K1 S[KBBBBBSzoczcSSSSSSSǰǹ͒[SBBSSK99BK[iuc(1K[uo(119SԚoK[˭³˿uSKBBB9BB911KS[i[K91911BKKBBSiziB9BBBB9i¿u[z˦uSSuuzuouuziB9BSBSiKB9BB9K[uoooo[[SSS[SSɦҿuҷSB9999B9BSS[iuoK(9ScuucooB 1K[ٿ1KijĦڿSK9B9119KK(1BKKSK9(1B99KKBBB9SiocBBB99[¿ocϞu[uucS[K[S[czoioiicSBKKBKSKS[[K[ccc[KKS[SSzĪļѹzͰu99999199BS[couc919B[oocSBBczļܭKS˼˰iB1KB99KB1(99KKKBB9(19BKBKBBK9B[oiKK9K¿cSKczcoͪi[[[SSSBBScozuc[[S[SK[ccS[[KKKSS[[S[[cScuij¼oiѭS11((19BB[c[ciS919KS[ioc9 9ozǭĦϳ˰zuK9BKKB99BBBBKKKKKK199B9B9KKBKKSiiSKĭioS[ou[ioiio[KKKBBSS[c[[couuiccc[S[SKKSS[Scc[[[[cu­ķɭiiѰo911119BKKS[S[S99KKKK[oo[11Kioo­ԿɳѼScoS11B9BBKSSKKBKBBB191BKSKKBKBBBK[BS¿uozuoioccuouu[SSKKKSSS[izuouiS[[[[ccc[[SSSS[cc[[c[cɭžuuϭico99911BScc[[[SB19BK[izuB1K[SKcπiǰoici[ouS99KSSKS[SBBBKBBBBBBS[KKKSKKK1BKS·uuoooiocooSKK[c[SKS[ioicc[[[[[[ccc[c[[[[S[[cccSc԰¹ɿ˷uzĦi9zoSBBBBKSS[[c[K99BBK[cuu[1(BB9cz[(ϹSSc[iSScuiB9KKBBKKKKSK919B[[ccSK999BB9o·ozuiic[uoc[BKSSSKKKK[oc[[[[c[[ccc[[S[cic[[[[ccc[Sšǭ³zoǼi[ocKKKKBKKKS[SBBKBKSSKB1 19Biɹljo9(((1˼[9BKKc[1Kuz[BKKBSSSBKKKKKBcc[[SBBBB9(oi¿ǿcc[KSc[i[9BKKBKKKSS[cc[[[[ioiiic[S[cioocS[[[[cccǞ˿oizѿzocSi[[[BKB9BKSBK9K191(( ((9iϿ[((1(Sѹi9B991BK91czSBSK[[[KSSSKSK[[[[KBK99(Bu9czĿo[KB[c[SicKKKKBKSSSSS[cc[[[Sizzzi[cioiiccccSSSc׼šoɚoic[iu9SKKKBBBBB9B1( (  ( 111Ǽ[((((1((1Bzi 9K1((1999B[ozzK9[[S[SKKBS[c[SKKKKBBBiucBSzii¹İzu[[iciSocS[SBSS[c[cc[[[ccccSiziiiicioc[cSSSKտచɷǪoicSSci[B9BB119991(111( ((1K[zɿ( 1( (1(((cc(11((1199BB19SzuiSKS[SBKKS[ccSBKSSBSi9ozcK9i[Bc°czoooic[cc[KccSKScccccic[cccccSuooiS[iuoccSSSBuĿڞǪĭ·zicKSK91B9991( 1111((111(1119BK[c[c˷dz ( ((1ScKSB 1BB91(19111SuK9[[KKSSSSKB1B[[S119[ic99SBKu³c9Kuozo[KKSSKKSKSSKBBScccic[ccccc[ioicSSicc[[SS[ScϰٿǷǦu[[ScS[[SK99991999((( (9KKSSciczu¹ ( 1[iK9SK919KK1(9B991BSzu919KBBKKKSKBBKBSS99(19ScK9BKB[Ŀu11BuuuzoouziSKBBKBBKSKKSKK[c[[c[Scicc[Soi[S[cccc[[SSSS[ͷ˼ϳɷi[[cioouz[[[SKKBBKKSBBBBS[iuzz¼(( (iuBB11[zS9BBB9199BKK9Bco[ 199KSKKKB99(uK1191 1SiK19SKoz­o19ѼuzzzScoziKSKBKKKSSKKKSScccicciiici[[iii[S[icSS[[SSSS[ǰǚczϳͳuouiSSioo[czuz(((1( (zSB911Kic[K9Soc91BBBB99KcS1 (9BBB9KB91Su11(991((1KKBKKS[[(ѹzouuoioczuSSSSBKKSSKKKKScc[[iiizuoii[Sco[ccS[[ic[SS[SKKK9dzͼǖҹ¹z[Siu 1 (KK[iKK9((KS[zSKzzS9SiSKS9(KuiB11BK9991(KKK9 1111111BSS99[u S’uzzouoKiSSBBBBKS[KKSS[ccciioouoic[[Kc­cKKSc[[ci[S[[[KKKKBuɳĭϰɹĹzzciu(1( 9zSzo[K1B9SB9cuo[[c[KS[SKKB9Kcci[9(9BKB(9žS 99(1((111(19BB9Bo[[͢ziccBuSSSBBBKKSKBSiiiicoouiiiiiz[[ucKc[S[K[[[SSSSSSBKKKSİϭ濉˿zidz(( (SzoiS[S1S[BBKK[i[99[[K9999BB9Bizi1 999 zu[119( ((1911119KK[[i׳ouS[cBzKBKBBKSSS[SucSccouiicczciuBic[[c[c[[SSSSKBBKBSKiǪԭ–zdz¦ ((Kc[c9czKBK9B9KS[oKK[KBB19BBB99Bou[1919z[Kco[11B9( ((1999Ki¦izܿizz[K[KuKKcSSSKKKcuc[[[ouiciccouuzo[iuc[cici[[KS[KBKBBBKK[ĪǒǷɷĞǷ KccSBKKBB11KKBB9Scii[BKB11111B19KcicS(BiBBSci[11111((11111 czBooczoiS[uc9Bcc[SKKSicc[ciiiii[S[coicuccoi[SKBBKBBBKKBBKKSi·ͼ³ǼɰĿ˿ĿzϼǷ(KSiSBKSBKoK1BK9119ScicBBB9111BKBB19Scu[SS9B99SoiB1(9(( 19B9([(uccѦzoiiuc99[cKKSS[[iuzccS[[[ciiSSSSSuzczcc[KKKKKBKKBB9BKBBS[[oķϿǼuz¼ɿzϦ˹[uB9KK9BKSSioSB9K91BKBKicBBBKK99BBBB11Bu[[S[[B119Ki[B 199(BB9BcBuz·uziiiB9S[KK[[[SScic[[[[[[icKBKK[uio[[KBKSBKKBB99B9BKKS[[SSu¹¿¼Ǣuzzzcoz˼zԭ999119B9B[ci[B19BKKK9BScK[KBKK991(9B(1Kio[1[c (1(BSSB(1KKBKSo[oªzccoKBKccii[SSSSccS[[[[ci[SSS[[u[cucKKBKSS9BBKKBKBBBKKc[[[[[oİǹˢu¿·ѿB199999B911BKBBK9BKSB9BBSSuiB9SB1199B911BiuSKi( ((9KcS99BKK¹iK9zšccccBBKizoc[[S[c[[cccicSSSSccii[KBB99KSKSKSBBBBBBKSSccSK[[c[ĭǼǪz¿zooS1B1((9B9BKB9KB(119999KK[[Kcic9BK9B91KB99BKiocczi9119BS[B19Sǰ91zͰoSuzcKBSozoicc[[ccciooui[S[[ccSSKB9KKK[KBBBBBKKKKSBBSc[SS[c[[[¼Ͽui¿uu[cuKBKB99BB11BKKBB[K19B9BSK[ocS[oS119BB1BB9KK9Siic[iu91(19B[[i[i͹cKBBǚcuuBKouuuuicccS[[cciouoccicccSB99BKK[ocKSKBBBBBBKKScic[[S[[[coϳoiz·Ĺ[So[KK99BKB19BBSS((BS91SiSBKSioSK[[[K11[[B19BBBKBBiu1SB19BKcϷ[Kuoiz[ozccioc[SSSS[i[[couoiicc[KBB9BBBK[cSKSKBKKBKBKSSSoo[[c[S[S[oǒiidzͼiKci99B111KK99KBSK1BKSSB9ciKB[c[SSBKoo9 Ki[B199BB1(iBSzS(9BKĪzzzcizc[[iic[c[Sccioicioooc[SKKKBKKBBBBBKBSSSKBBBKKSc[cocSSci[[ccoiܭuSSҹϷ[B[[SB99119BBBK9BBB[[KSSKK[cSKK9KSKKKc[91BBSB9KB99Bǭ[z[19cķɰouicccc[KKccSiuuuuiiuziSSKKKBBBKBBBBB9BBBKBBBB[uiSK[[SS[ii[[ccc[Ѧo[ǭǿ[K[oBSSBKKBBBBSK((9KSKBKKS[KKcc[KKKBKKK[[K1BSKBKSBBzķ[ocS¦ǰzczozcSS[[oo[couuoiooo[KKSKBBKKSK9BK9BSKKBBBBKioSS[SKSS[ScoozzzǍɷɷiSB9SuɷBBBSSK91BBozK119B9BB99KK1[K9KKS[KK[[KB9KSKBKu·zϼiuuocuucSccozoozuoici[[SKSSBBBBBBBKBKBSSBBB9BBBci[KKS[SSS[ciiuzĿճoѳBB9BBcuķ9B9S[SB99BK[[S919BBB9199BKczuSKSKKSKK[icB9KK1[¼ɹi(ciioizu[cccuoiuuozoSBKKB9BBBBB99BBKSSKBKBB[[[SSSSSSS[iicioziϹٰzu˿z[KKBBKKB[i1BK99[[BBKBBScK((19BBBB1BK9Bizc[[KKKBK[ci[BSoǼ¼i1SoziuziczoSScouuzuucKKKSBB9BBB9BBBBBKSKBSBSo[SK[SSS[SioccozoKǷѭĭu[[SKBKB9KKSz˼K1KBBKSKS9BKBBK99111199119BBSuo[KBB9BSKBooi¼¿ĹĿzo( zSoSiz[iziK[[cuuouuuKKSS[KSKKKKBKBBBKK[SSKSic[cSc[[SS[oiiozuoiļɭzoSKKSSKSciuķc(BK91ScSKKB11191((1B999(9BBKS[SB99BB[KSu°Ǧ˿¼o11c[[[ouzcc[[iuicSiic[SccSKBBBKKSSSSKBK[SKBcuccc[[[[SS[iozou¼¿ǿ¿׹zuuoiiioou¹u19SKKooSBB919B91 (11999KKBB1(BKBBKK[cK[ǿԹĹǼc1cSzijc[zoccoicic[SS[SKSSKS[KSSSKKSS[[S[ii[c[[[[[SSciuz¿¹Ϲ˹ǼĿĹͭcSSS[iu¿uKBKS[[zzSB99999B91(111B9(9B(1Sc[S[cSKzͪĹ¿coSSzuKcuS1BuoKKKKSSKSKBKBSKSSSSKKKKSiicci[[[KSS[iuuĿٿijɼĹĿ·İzuouoɹ³[1BKKiiBBB999SK1(1119KB1KB11[uiccKi¦˼[BSScicozSSic((couo9KKKKBKSKBKKKKKKKKSKScciii[cccc[couuu¼͖ϹǷĿɪooĹĞS9BKKccoc99B9B9911911B[BBBBKKcucKc·ͰǹuKBKKooBKo[SK[K( B[KKzuBBSS[SKKKBBKSKKKSSSSoczuic[ccciououzzu¿շuԼijǼ׹uϹɭu99BBSB1B9(1199111BKKBKBcB9izɹɭͷzoKSSciz[[[[[[K1(9BicBScc[KBKKKSSS[SS[izuooiciiuuzouzij˼ݳ¿¼¼ǦdzԿ˳99KKSicB11199BK9((19BB[KKBBK¦Ĺ˼ucSciuuo[[u[119KuK[oi[KKKBBKK[[[[cĭǢzoicS[iuiuǹҳͪ¿¿¿ǿ˞ozozɳǼͿ11BKKKKB999(19[K199919B99S[[ҿͼoSKSoijc[ziKBBKoK[oSKSSKSSKK[[SS꦳˰zcc[czǼҰͷĿļǒiouu°ĹB9B9(1KcB1111[iB11999KB9KcouuǢͳ·iKBB[o[uiBSˍciSBKio[[SKKK[cSKScc[uѦϪz[cuͿ’Ği͞uouuuzҼK9KK9KiK91(1BKBB91119BKiiļ͹ĪzcK9KKu[KKoi9zuB[SKSSzo[KKSKcic[S[co迉ؿĉiuɼ¹˞[ǿѰzzio˹cB999K[[K(19919K9119BSuSϪc¿oKBKK[iucc[Sco[KB˖[KKB9BKciKK[[[ii[[[S▀ĿķϭziijɿĿ¼ɪiouɿi11919K[B(199BSB1(1KcSɿҹc¼·KBKSKouc[icS[S[[ǖc[B919KBK[[cc[ozicii؄ǢuiSɹѹ·͹ǰooķɿ¿¿ҹ–zu[˼u91B91SiS9119BKSK9uuǼiļS9BS[cu[[io[SKcou[cSB999999Kzcii[oi[oݼuzzͦ[Kc׿¹ɹiuļ¹Ĺ¿Է¼ªoKBɷK991Sii[B19991Sz¿ɿĞķui[SKKucSSci[Sozzo[[BB91119BScoiiciuouucǖizuuij˼ĿϪzozz·¿ij˭uoKBSǼzK1KSSKS[SB911cǼ˹ɿ¹[KBKSzcKBK[c[uuž[cSB91(19[zo[zu[iozuouczicKBɹǿ¹Ğǰoo[cɼļǼǿc[ci˿B9KB19[cK91c·ĭͿzcS[B99[o[KK9BKSKiˍccB99199coiuocuuzzzicuoo[B1BcǼ˳iiicz˿Ŀ˹zķS (19BKc[c¿ļķ¹ͳzSooBKKB919BKK[SzuuҀoSKBKBBKzzicuiouuoziccicuiKB9SoĿ¿Ǽ³uoSc¹ɷ¹ǿĞc19KBBcǼ¼˭iKKKSSKSSBKSSciܒuBBBKKScuuiczoooiozicioiiS1119Bo˿¼Ħu[cɿĿǿ¹zͼĪzBBKK[¿Ͽ¹¹ѹ͍c1BoziKS[cozz[[[[i[cઉzcKKBSScciouozoozooiccKB9BKB99iɹ¼¿u9iͿ¼ǿ¹zcooǼ͢˹iBK˰ķ˿ɭϰocKiiucizizuo߿zo[SSioizS[ouzci[[SB999BSciiļ¿ǢzcB·Ͽ¿¼˹zzzzi¼ĿooİͷĹķ͹i c³İzcoԼzooooS[[iSKKSBB9KSizѹĿϪi9[ĭ˹ɷ³oĿǦic[[o°ͼ˰˼ļ¿ĭ9izB9ocoѢuiooooiououuuoouB9K[iuzzuuzzuz˷Ŀѹzc9·¼¿ɹĢoiuϼScciiİɿİǿčĭǷɳuSBzu[oKScuuuİu[BKizi[oi[[oucouuuuuzucu[Siuiic[ĹĒuScǼijǿzB[ļziuzzoccccooͳķKSǿǿ·cziKiSzcczi[[oS1 1SioziSiu[Kizuoi[cou[cozucɪiooccicuϿɞuuiS¹ķzuuB1uuĒuuu1icK[ocii͹˼1(ɿiuuK[z[iucuuS9(11KS9(1BcB 1[iouo[iucS[iiccc[ci[[ciouoѿcKczoic[ouҹĿķiuKoĿĿ͹ɳuzzzǷĖzuuKozǖuS[oiioϦտĞB iǷzSB[ic1u[uiK(    Bciiiccooc[cccicioouoiioķzciocic[[iccuϿļ¿z[SijĹuuĹϿiɢ¿˚ucozuļocuooҳ˷ɹc[·zcKB[S9icouK(     (9[cci[[[[iuzocioiucoic[cuiScǷҹϦzocK¢ͿļĿB(((Bco¿ɰ˚Ǣu9iozzϹ°ͪS 1uĢzS[cB[i[9[uooK(   1[cczzcSccczzuooi[ozoui[[cioz°ɪuɭi[S[ɼɷتK91((111Bi˭ĞǢuouuoi–ǦͿ 1uuiuɭoB9BccSB[i91uzzS   K[[czooccouzocSSuccooz[ciiiĹǪouoci˳ļ³ܚ9KK9(((((1[˳ڷ­iuiuǢɭ͹z19uzouǭo[[BKKKKB99BBozi9     1KS[uuccoocc[couiiSKicSoc[c[cļ˒zzizzozϷɼ¦cBcc[S99(11[ĭϿ­’cioĢͰ˚ ozzzͳoBS[SSBKKBK919Ko91    (K[S[[KBSSSSS[iiccS[SuĪuozciiu¼ѭzucoͿǹcoui[S1(9(Bcǚ¿¹ǿcozz[ѢzͼļKz[c[KKB99BBSzlj(    (So[cocKKS[[SSSciciuiiciz’uizS¹ɼɪܚKSSB9111(1Bњ¿չ³zizչzciĹǰz(BziKzSSKSBKS9(ع1    [ouKBSS[[[coc[izucozcKcǹi[K¼Ģu(11B[SB(((ҹz¼­ļioĚucuɹɰoKoccouSBKSSB99B1ҹ˒(    9iccBSS[[ciucc[iu[c[iuccSS̹ǹĚcSiİط[9S[cKB[K1҄˿Ǫzc[zĢucɷǍ 9zzuoB1BKB1BSKՒBiji(    9u[[[c[SS[Kcozo[K[uz[[cccicSSKc¼˿ǖzuucK[ĿĿѪ[BKK9BuoBі¿˭9i[Ħ[ɿˍizzK9199cǞc(   (BBK[cc[S[[[cioo[K[ooii[[[S[icScѿѿǼتuiooSK¼Ʉ1BB91zSǒ¿ª9c9uǭu˼¿ǭSiĞK99 9տK      (1B[cSKciicioi[iziK[iccc[cic[iozϢԿɼؼzzzuiocKǼҷK(B9BzSϷǿ·ˀS[oi[ͰͿ¢ļzzK1BBSٞɹc  ( (BKc[KB[ciicccizSScic[SS[cccc¼ϼ¿Ұzouzzozou¿ǹҢ1(91coѳĿϭoicocKSuͷļǦz¹ziouK9KKKS[ozǭo(  19  BooiiKK[[SSSSczBKSKKSS[ccSKiҼĿɿuozuiiǿĿĿщ(99[ϭշ˞SicKSoϳϰ͹ļɷoiccooK191KBK[[cBcu[z[   1oS    [o[[[[ccSKSizuSizcccScc[iĿ˼zuouzzuo¹ύB1BͰǢiiuu͹c9[ϪzİѷĿļiSBcoiS91((9B9991[KKK[(  BB   1BSzic[coc[[[oѿccoɼշuzzuuuo·uuzuzњSBzǪɖ[ciuҼcK9ͭǭzz˷o˼˼oic[SSBBB99999SѹK KSuc   uozcB(Kicozoc[c[cc[ciozǍ¹ĭ˹ԼzzoouuzĹo[zuzuzuioouzϞ[İտoooozzz׹9KѼǹzzzzzɹiuuz˷uocSSSKSS[[zǒ11K[1(ooiSS[c[SS[ico¦װz˿ͳioizɹoB9[uoooiiiouzǪҹխziciڰİռuzzzzzzļ[zioozĹ¼uc[c[c[uB9Bo(  11Kuzoi[SSKSc[SSScoɷɳտzz۹ĦzzcozuzɢcKK99[³zuuzoiioouͷ¿Җzz[cuշ°Ƿzzuozcozcuuou˹˳i[S[cuu91S¼i [uou[S[[KBSciSSSKi°ϹɷϹuiǦ¢ucouuuuĪzzzB9BBBiijoioiuzɹ¿іocԼ¿Ǫ˰zzzuuuoooǿϷi[[[oz¢zcu1Ki͹oucSccouoozzc[[cc[[iSBKoļɿͪuۦİuuuuzǿiuuuKBKBK[uzuɿǿϢo׹ļͰdzzzziiu˳ǿuizĚSciK[iji[SKBBBS[[ciuuiooiiS1z·zɢz޿ѪuoɦzuS9KK9Bi¿ļհu¹¹˰ĞļzozuozzĦo­KKS9199SSSKci[KK[iz˞zcS[z˼uĞo[ǒooc˷uKBS[[[uijĿճzԿ԰ĭ·oozuzz˳zuz¼ϚKuo[cKKc[KBKKKScccKBSKcozcu¼ɰuuĚzuizuuz[S[cioo¿ķ€Ҽǿzuuzzzͳzzii[cĹɼcSoicci[[c[SBBB9BSczozzɷšzzǪuzͪڦ[coocouuuoi[[oouuiuuco¼ļɉĖǼ˿·zzzͼzuooouSSS[zĿĦuc[SKKSKBKKuzzɳuuuuuuuԼuuzu۹uSciiiuzicciozo[SKcoiiioioķzoozɹ˪ɹĿžiiooucou[SSKSi׹ucouoiccouzĿoouzuzzuuzu[[[uzoKKSizu[BKBB[ic[[S[ozzoccSKS[ziuouz¼ѳ¹Ϲuuǰicciuu[[i[c[Bclj¹¦zzuuzuciz¦zuuooouuzuzzuooSSu˹ozuK9BScocSKBBBK[[[KK[c[[[io[KKBBKKSoiouoѪɰǹzz˪zzuciic[zuiciccoԉiuoiuzuooooouuozzzzijocuioѷouSB9BBK[S[SKKKKSBKKScic[iicB991BSSKzzoozzzѼ¦ǿz¦z͹uii[ciizuccuiعuizzcuѿzzuoouzuzoiozzϪzzĒiuuSBBSSKKSSc[KBKKKKB99S[[cc[SBB919BSSozɿuoɰuzzϼoicS[[ioucoѼzu­oouuozooiiz¿ĭzc9BKS[KKS[cSKKKKB9B99BSKKBK9999(1KSKcu’͹ļzz͹uzz͹iS[ciuciuĦzzz˷iouuzzzzzzzzɷuB9BKKSKKc[K9BKBBBBKB1(9B9KK111( 1KBB[uzui[[c[o­cz·uuoϼzzzǹi[ccciizziĢuiizzžzccuuoouzuuzzzĿc9KK[SSKccS9BKK999BB91(11119( (1(9B99SiKBBBKK[iiou¢uoco¿K[izĿiKiuoz¦zzzžuooiciozošoSizٷѼoiiiiuuouzicoǹoBBBBKSS[iKKBBK9(B991(11(1 (11((1199((Szu[KKSKKKKKKKScuzoooiooǷɿBBc¿K9K1iizɦuzzuzz¼ͼuoo[uzuuizѿuu¢ªoc[zzuuoc[coɰSBBKBSSS[K1KBB91 9B99(1119(991191999( Kuzoi[[[SKKSBBK[iiciuzuoouoiiooiuѼĹKB[SBS91¿zzĦiuzžɰoc[zocizɹĹ˪ccuuzoi[ciuzǢo9BBS[[SKB1(9BBB1 9B991999B9B99199B9911Soiuo[KKKBK[[cc[SK[ooicciiooicozĹ[B1Kz[c[9B¦˭[oɰou[Bz¿cScoioo¢ռɰuiczuuiiuuouzzzžoBKKS[SB911((1BKB( (199(1B91991119BB9BBKcuociiSKKK[coiSKKKKczuooccciic[uoK9(SziB1ªč[ͷzuɷS uǰzKKS[cczizڦ˳uiuzociiiuzɞiKSBB111111(( (111( (91 191(9911(1199BBKouo[K[[KS[cic[KKS[iuuociccouoi[izB1Ku[ocSo(uɷu[cѿĹi(BǒKS[SB[ccz٢Կzuzo[[ooǼzSB91( 111( 1((199( 1( 9KB91((( (19999KuzuiSBSc[[[[[SSSSizzuiiiiiouoi[cou¿KBuS1coS11ɼ1iĖo o˒c[oSKSSozzzuװϼuzuc[ozzzĭi199111911( ((((11( 11 (KKBB9(1( 11119Bouiuc[Scoc[[SKK[ioouzoccozzoiccSSioiuocSSKB[ǹĦSKԹz1 cҳcicKK[izzoͼɪuozoiiuzuiҦc119991111((( ((11( (9KBBK9 1((99KBBKKiuzoiiocooccc[[SK[iouoiuuuzzoc[[[cccoˀuz[SoiB1BKzBռu cǒzziiuSizciu˹ɼͳѷuocoizڿzK99((11911(((111((1111BB9 ((99BKKS[[[cS[ioio[[[[[SSS[cczozzi[SS[[cc[cϦτiBKocBScωoѪcBǒ9iuizizSiϹњɭuuo[iչziSKBKB11119( (911991((111 1((119BSS[[[[izzcSSKK[i[[SKK[zoi[[SScccc[[ĿuњoS9BzB9KK[Ͽҳu[˖KSoiuoo[iuijĹ˦zoԳuzuuzzuooicK9B9991 (111( 9K1(111((9[c[[[[ccioc[[S[cicSKBcuo[KSS[[[cc[[[ciѿiB iuSBB91([˦Ŀ¼¼uB[icouczuuz¼ijǷªϭ–ccouzuuoc[Scc9 1KB1 ((1BK[icc[[cioooicii[cicSSoziKKKK[c[SK[S[io[i¼ķzizSKoS19(z˭¿ͷ’iKKSouiuzuuii˷Ƿ˹ɼժSucciioiiouzušS(11(( 9BScioc[ccuouzi[[iiczzoiooicc[[iocKScoooccuĦcScoK9KcĿ˷uzzԷĪo[coicicuui[[ɿ˼ĹڼoSicciozuooiiiiouzҿcB((  1KSouociiuuocSczui[ciuzzzi[czuiioiciiiczuiiK99uɷuzչzzϷciiuuc[czziicϼĹĦрKzccuziiiooiouoooozϳS919B9K[cuouuozoSBSizzc[[Siziic[[ciou¿zuuļo99cǼziİu¦cSiooccuooķۭiuzzcoouooouzzuoou³zizuSSzii[[uzouo[SScuuc[iiioouziuoooǿ[c˼˿Ƿž[Kou[uco·щiicuzoooiioozuoizzuooioiuic[[[Siuooiic[ciuuuzczuccooǿǰuiiiS ((9co[KSSSKBBK[K11(    (1BcuzuozuioiciocccSKK1((1KSS[[[[[c[SSKKKuoݷz[[o[ ( (( (   (99B99B(11(1( 9B9(B((999BBKBB91(B99911(( (11BBSciioicc[B1(  (91    (( (((( ((((ijɷczooo1 (9K[ocKSBBSBKSoK1 (   (19BBKB[ouiozuzooc[[ciccSKB9( (9Sic[ciciiiSScuɚ[K99  (( ( (  19Ki[1111((( (BK1(K91B99B19BB9911991(11(11( (1[iccS[ccSKSS[[9(( (99     (  119ķͳ͍ooii1 (9K[icSSSK[SBSo[1 (((1119SoiS[SBBSS[[iuuooi[[[[[[[SKKK99Bci[[[ccciociڦz1( 11(   (  (1  ((  1KS9 9K91BBBK919BB91(99911((1((1B[oui[SS[cSKBBSB( (199(   ( ( (19BS·ļԹªuzuou(9SiiicSKK[[KSoc1 ((99BKizS[SKSB9KKSczzuii[KSS[iicScicSSS[ioo[[[KSSzɢK  (9B1    (1(  91 (K[B1(BKB99BBB1(9BB999B911(((1(1B[ioocKSSKB99B[S9 1(      (19BBKKcԿǿǰ漦uz9 1S[c[c[SBKSSKScS1((11119KScuKS[SK99B9Buizzuoi[[S[cicScoozu[iicc[K[[SBڼc  99B1  1((99(  (11 (BKBBSBK919B9B9119B99BKB9111(( (KiooiSBBKKB99BSiS(( 11     1BKBK[ci·ªSozK1((1ooocSKSBBB9S[c[91991119S[cicKK[KB999(Buozi[SS[coucSicozuo[ciSScKoעi   (1991 (1 (1(   9 (KKKSB91B1((11KB99BBB91(1199SouuucKKKBBBBKBB[[1 1111    9K[SB9KKBKS[S¼Ҽ[[ou9911BiuoSKS[KKKB[u[S9( ((((9SS[ccKS[1((11 Buoocc[[cocSS[uo[[oooc[ݳ[  (1(( (  1( (1(   19BB9 (1(9BBB9KBK99(1191iuzuocKSSBB9SSK9KB(911(       1oKSKKKSKKļϹ[o[( (9KS[oSSKBBBSizcS( ( ((KSSS[cSSK(((111KzzzuuooiccSKKKiu[ozcioucuԳ[ (991    (          1((9BKB9K9B9111919coicc[SSKS[[SK91( 91    Kļ[[[SKKSK¼¹ـizzS((99BKKocS[[SKSKS[B ((19BKBB[icS9  111Kuuzzzo[SKKSi[[i[[ou¢K  1991  (        11( 1BB9BB99((1(1(BiucSS[SKBS[cSK9(  1B1(   ( 1׼oSSSS[icѹ¹ĹԉouzoB9((BKKczcSSSSSSSciK (((1BKSS[oiB 1999SzzoozozocS[oi[ooKSczٳK(1( 99111(        1(((1KBB9991( (((9Suzi[[SKKSSKKKB9(1 (B9    11 տcKKScc[ɿļ·zuiuz[K99KKBKSKKKSKK[cccK (1199KSSciB(199B[zuuzuzzzzuziizi[Koo[Siu[KS׿B(11(  (91(       (  (((1(119B999B991((((SccSKBKBKSSK999199(( ( (    1ĭouocSS[[[[¿㿉coi11BKKKKKKKKKKSooiiB 1119KSSK[1 (((19BB9Kozocooouuzo[[SKBozcBKui[[ݷ[( (   (11         (19(( 1199B9999119(11BSKSKB9SKSSKB9111BB( (   cչiScoSSSSK[¿ɿĿےiu999KBBBKc[S[S[z[[1 BBBSSK999 ( 191(19B9Kuu[[iciiuSBB99SiicBB[iioเ91        111 (((1111(1999B911B91(( 1B[[cSSB[KK9B999((B9(    SdzzuoSSSKS[SSSɹ⦒K1BSSKSuzo[SSuciB19BKKKK9B9((((11(9K9B9Kozzzc[cS[cczzKBB19BKSKSS[iz[           (119919((9B91( (19B91(11( 1Sic[[KKK[KBBBBB9991  (9BB9KǞz[[cz[SBBBKBKSĿ޹99SSKBiu[zociS1111( (KB1(((( 1B111Kozi[9KKKcc[zzooB999B9BBK[So„B         (   (119BBB9(199(( (9999(((( Bii[cc[KSSB9BKKKBKK  (99[čocK[izucKK9BKK[Ŀɉ99[[KScouuozooc9  (91  (99  9[icKBSSKSSKizu[[iuB19999919Sci1        ( (     (11991((9111(1(199111 1SioouiSBSK9BSBB99S1   Kz¿icBBcico[SKKKSc¿ҿ9S[SBSSiziziS( ((((( (( (1 ([ocKBKBKS[ccccSBB[ocKKK91(((1KoK      (((1(    99991  9111111111999( 9SiiiiK19991BB99BBB  9KɪicS9[icii[ozci[[SScǹ°Sio[BSui[1 1(((1911 (119991 1SccSKK9BB[oo[SSS[[cSSSKBKKB919cˍ        (   (191(( (999 11(((199( 11BScc[S91 119KB1B9   ͚KKBB[ocKKczzcccSKKS¹Ͽiu[9Kuzzzui[B 99B99((((1( (999(191(1Bco[B9999BizcKKSS[c[[ccSSBKKKBoϷ9 ( (           1( (99((11((11(1((199B[[[S9((  1B991     BoB99B[iSK[ciccKKSKKKҼ³ǪzzccB[zSScccciS1 1B9BB9991999999B9999( 9[iSKKBB9KcocicKKKKSS[cicc[[SSS³[  1((((   (       ((( (((111111((9999KSSB9(  19(     (SKBBB[cKSi[BKiKBKKBKzzɿǷuzooi9So[KBc[ccK (1BBBB9BB9BKBBK91((11(((BcocS1199B[[K[SSuo[[ciicc[KS[iǰ1 ( 9B1 11((  ((  (    (1( ((( 19119BB99KKB9111( ((((1( K˄KBBKS[[KSiSB[iSBBKKSǹ˿iuuSicKBB[[cK1(999BB9BBB[SSSBKKB111((11Kiuzo[K99BKSSBBKuz[SS[cccc[[[ĢS 9( 19SKK1(( ((     ((     (((((1((99K999BB9(1911 11(   ͍SBKKKBBB[uiKicSKKKS[ǹİzzzSi[BK[icS( 1KKKKBBKBK[SSSK[[SK9911K[zoocKK[icSSKBBSc[BBKS[cc[SSczK BK11(1(        (1(     ( ( (19B9BB91(1999BB9B(((1( 11   ( cšcBKKBBBK[ocKS[[KK[[SͰɳѦuoouS[cSBKSicB9KS[SKBBBKKSS[[S[SSSSSSKKizcio[uzi[KSSKSKB11K[ccc[S[ziS    (1 (1( 1B1  ((    (( (111B9BBB19199991BBB9(11(     ( ٷSSKBBBKcoi[[SSSKS[SoҳİѹicSB1Kouuiiu[1BBB[SKKSKKSSScc[cc[SSSKSSoozocoocSKS[SB999Kiic[SSBc¦u[9  ( BB9111( (( ( (         (19BKSKSK999KB9KBBK91191    (1( ѳ[KSKBK[iocc[SS[SKBKocuɷɳ·¹͉uicSS[uzoK1KKSSSBBS[SScooo[K[[[[[ccSczuc[[K[SK[ziSBBBKcccic[KoS9(((    9KKBKB11((1((1(   ( (    (  19BBKKKKSSS[SSSBB9111199(  (( (ܼķi9BBBKiczoicSS[ucBSccuǼǿķ¼تzoioccouozzo91B9KS[SSKS[cioooc[ioi[[izzoz[KSS[SK[zo[KSBK[cciicioK((((   (((1KSSB(( ( ((  ((((11(       99BBKKSSKBBKKScS[SK9111 (((  (( 1( ((z1BBBK[[ccS[ouK[cc·Ǽ׹o[SiccoiiiiK(1SScc[SKK[iuoic[cicuuoiozzo[uo[KBSc[KBB9KSSK[iczz[1    (      (( ((( ( 191(99(((     Ki[91BKKBB99KKK[[[[Kcozc    ( (1 ((zҞKBBKSKiu[iiSczu[czuuǹɚu[oi[ouocK((B[S[[c[c[iiuoSS[iuiuiocizuzzzu[KB9BKBBKc[Scicz[( (BKBBBKK1   (  ((9911((  (19999111((   1Kc[991199BBB9999K[SS[oB       (9SҰcBKSSSozcSiiS[uo[[zzuzzİķuucozicK19S[S[[[cc[ccic[[cuiScuzuzcB9B[ocSuzi9 ( 9KK1(( (1 (1( ( (1(19BBBB911 111(1199111(  K[SB9KB911(99919BBKS[SS[oS11(     9KǦcBKKK[uui[cc[[iicKuuoozzzz¼ic[ooi[BBK[[SS[ciiccSK[cioKSciiioozzicSSuzoozªzc( (  (( ((( 1KSSBKSB99KB99119119911(   uuSc[99B9199(19BKKKS[SKKK9(    9BS԰[SSc[ciii[Scc[ccS(ǭzuzzzzzoouz¿oocui[B9[[ciic[ci[KS[iiicKcuuccccczzzo[[oozz[ciu‰zB (      (99(BcSBBK[B19KB9B9BB9KKSK99((111111[ѪzuSBBKK9((9KK[SKBBBBB9(    ( (99Bu۞oK[[ciioi[Sc[S[c91zzuuzuoooizo[11[ciuzic[[[KS[cciic[icScccooioouiSScouui[cizui9   1(    ((1111( B[[SKKSB1199BSKKKBBBKKKKBBBBKB1BizzoB99S[K19KKKKSKBKB991 (((  ( (((19K[S䪄[[iiioic[[cc[[c99uzzuuuzu³uooo[K[iouzuicSSc[[cciuucKK99KS[couzzzuuuocB9SciccizuB  (     (99B99SKKB91KSKKB91K[KKKSSSKBB9BKKSS[[[iuzo[KKK999KK19KSSSS[BKKB9(   (1119BKKSSǚcSciozoicSS[SSicSǹuuzuozzuuioziciuzuuocS[cciiciioo[B911BKKSozzzuuuuiS[iizu1    ((   ((((   19999S[KSK11ScKSB11[i[S[SKKBBBBBBKKS[[[[[K91(1BBBBBB99BBBSSc[SSB(  ((1199BKKBSSͳoS[[[S[SSSK[c[uiBѳuuzzzuzzuozozioiccucSKSSKBK[cc[S9999BSSSSououKK[z1 1  1B1   (91(( (11999BKcS[[K9SicSKB9BS[cccc[SSBB9BKKS[SSSKKB1((9SKKSBB99BKKS[SS[K(   (((119KKBBco„KSKBBBKKKS[iooK°uuuzzzzzzizooc[Scooc[KB1911BB99B99KBKSSS[iiczoSBB[9 (999(11( 19(19( ((199999BB[cS[cSSiS9(1KBB[iiccS[c[SSSSSSKBBKS[SKBB19BBBKS[uui[KKc[KK9    ((( 19KKSSczתSBKBKKBKKScuSɹzzzzzzzzuouozzuiiccS[cicS91199999((1119BKSSS[ioiuucc[[SBS(11(  (99B9((11 ((19199 ((9911BBBSuuc[c[[c9(1S[BKSciicccccc[SS[[[[SSS[SBK[K19919(9uSSo[9(  (((((19KKScc[[uİu9KSK[SKBKcz[ǞuuuuoouououuoouzĹozoooi[c[icK999B9991(19999BKKKKSiuuz[ozi[KKBK1cK (( 1999B991(199   (BB9B11(19BBKK[[zz[c[oK1K[c[KS[[cc[[[S[ccicS[[KK[KScSBSB991991Bc[cziK11 (  ( 1((9BKSio[izᰞzKKK[c[SSiz9Ϲzouuouuoouoozuiouoošouuioiiooi[KB99BBB991B9BBBK[SKK[ciio[ouuzoS99999SB ((( (199BB991(111(  (((  (9B 11(119Kcuzo[B[19[[BKKS[[[[SSSSS[[cc[[cccSKS[KBKBB9199B[c99zuB11  (   ((1BKK[izuu㭚€BBS[[SS[[z1uuzzzoouiiooozziioiuǰzzoioiizzucSKBBBBB99BBBS[[[KKSBBcooczzuoK99991KB1((119999B911((1((     119BKuuK991BB99BScccKSKSKSKS[S[i[c[cSSSSSSBB999BKKKB1 9uzci[9(   (((11BioicozҰ€BBKBSSKBKBuzzzuzoioiouuozuzozuuuziiiiouoo[BB999BBKKKS[[S[[SKKSSciiiuzziBBK9BBccK999BB9999991111((1( (   (((19Kizi9(((((9KSKS[S9KScc[KKSK[c[[S[[[KKSSKKBBBKBK((1BB9BBBB(   (1( 1ouuҷoSSKS[SBBuKzzzzoiiiozzuuuuouuczzoiuuuoocSB9B9BB9BKKS[KSc[SSSS[ciuzoiuzoSccSBKu–[B(11119B999911(1(((1( ((   19BSuuS9( (119KKB[[99Sco[S[KSSK[[SBKKB9KKKSBB9KKB1 9( 99S1(     SocuuoooĪzicuucciu[zuouzzzoooouuuuooououuzooo[999B99BK[SSSSS[cc[cc[ccoouiuizzu[iuiKiS(  (1999999911((((((( 11(((1(  Bzi9( (99KKSKScK9SouSS[KKBKSSS9BKB9BSKSK9BSSKB11K19( 9i( 1111B11  BuĦzuzizzi[ciuccǦuzzuoiuzzuoiooouzzuoouzzuooocK(9B91BBKSSK[ciciiiioiiozuoiuicuuuiiic[SK  1BBKBBBBBB9(((11( (( ( ǷuzK( ( 19KScSKiiKK[[Sc[KBBBKSSKBBKBBKSSKK[[KKK[ii9111(( (919((( (( (9ziBizuzzoooucccSi۷uozuoouzuooooiiuuuuzziozzuooocB119BBS[[[KKciooiiiuzzzuiiuocioc[zozoiK (1BBKKKKSK9( (111( BԼuoizc( (((9BBKSSKco[KScocKB99BSS[SBBKKKBSiciicK9Koc[1(1( ((199((1[uc[K1uocizioo[[iuizczuouoooooouzi[ouiiiK9911BKS[[SS[iuuoiiozzuoocS[iS[iǪz1(11119K[ScS1 ((191((   izouc[cccK( (999K[[SS[iozzSKBBBBKK[cKK[[KBcuoi[KcoK(   (((((((9oiKKK9BzicSozuicoucozuuSouuozzoozzuuuiizzzzcouicocKBKBB9BKSiiiouuiooouuzoiic[[KB[zš[ (111((9S[c1(11(   (((9B(o[[[[[KB( (1999KKBBBSiz[(99BKKScuuSKK[ooiciiuu[1    11KizuSB[[B9ucuo[ouiiiuui˦uuuo9SioiiiuzuuouuooooozzzozzzuouzoiioSB9BKKBKSSciiuzuouozuzuiic[SBB[o1  9B((( 19( (191   (KB11(1zziScocS9( (9919K[SSS[oii[91999BB[uzuKBiu[izuiiB(   1KcuucKKSSBBioc[uiiuzoouocouooS1KSciiiiuuooiuouzuuuoouuiciuuuzzocii[B99BBBBBS[cciuzuiuzuzocSBKcĭ˭uK11(1B9( ( 11((((  1991B1 (cuuuocSS[oiS1  19BSS[S[ScoiSKBB99BB[z[KSĦuozu[izozoSB(    ( 1K[iui[K[KSKBKoiooo[czzzuioii[Bc[iiiiccuouozuzzzzzoouzouuiioizuuuuocii[B999999KS[iiiouoiouzzocSK[İzح[1( (11( 1 (((((((1((BK91( 1  KcSBBKBBB[cB(( (1Kci[[Si[[oi[SS[cicczB9zĦzicB[zoic9      (9iuizzi[coKB99SuzozuuzuiccSKicicczzoooozuuiozzi[zzuuuozzzoiicccS999111BKSiuiiouicciuzuuucKKc͍S9 (( (((( 11KSB  (BouS((1999BSB((( ( (1BozcSSc[[ocKKS[ciui B[KB[zzcB(  9BSuzuzci[99B[uuzǦouzz[ioKB[[cc[uzccioooiiozu[iuizzuzzooiiiiS9((111K[[iuzoouuo[coouuzzzoKB[ҳK9(( 1(((   BKSB(((1 (9KoB(19911(111(1199KKKuiS[cii[S111BScu(ucKKciSB(   11BouuzuzcKBSizzSccc[9ScSSciizocccoouzioooozuiozzuiiccciB111(19Kiouzzouzoc[[cozzzzzzuzoSB[iϿuK1(11191   19[oiB991((((1SScSuzc199B1((111BooioKK[uz[9( 1BSczuKKuzuizoiiSK9B9   (KioiozzcSKK[uzzcBuzK[c[BKzi[[icioiiozocizouuzzuuuouoiccouuo91111BBB[icioouzuuocK[ouuouzozziic[K[Ұu[91999B9  B[izi(((  1(1BKouc[[K1 (9KKozzo[czzS (1BSouK1BuucSuiSKB9    (Scc[cozzK19SK[zuozKiouuzuozS[uS o[ioooioizuuzuzzzuoiiiouzcB99BBKKBS[SS[ozucciiScooozuuouzzzooi[KSϭzicB1B91(9K9(   (B[ouiK1  11Boiuzi[S9((BBizzzcSuuS( ( (9ocK[uu[SiS1  1Siouiciiuu[9BSKcuouioKK[ozicuoiuz9 zuzziouooziziozzuuuiuzzu[KBBS[[[[cccS[iouicii[ciiozzzuuoouoiccScѪzzc9  (( BSKK[izziS911119111( 9[ic[ozzo[KB91BKSioc[cuzcSSi1 1Bzu[KiuuzzS9K( (9K[cozucioouB9K[uzoiS[S[izzoooiii9 1zuzzu[zzucizuzuuuuiuc[[Scoccicii[[ioooccc[ouiiuzoiciuiccSiҢz1 [uKSiouuK991( 1B919999KSBKKBBKKKB9BB99BKK9BcoSKSouS  KuoiK9izuc[SB1(   (SozuuzocoocuoKB[ozuucSzuScuuB19BB91 19uuoz[uzzzooizzzuzooziBB[ziooiiiScioiuo[cccic[iuouzu[Kciozuˍz[ (  1 coKK[uocB91  19Si[SB991BBB11(911999KSKB((SocKKciS(  Boo[S99cuiK1( 1BS[uzzuooi[icB9Suzo[SccS[ouzc(  (99˷zioouuuoioozzzzuuSBii[iioiucooocicSciccc[cccouo[KSizѭzuS( [zucB1Si[BKB91(1KSSozi[[cocSKBB9119199KS[[919uzu[BS[9 1[oiizoSB19[cK(      (9coou[SSS[SBKic[cSKKSiiK(   1B9ɒcuoiiiuzouizzSouSoiooiii[ouocc[S[[[c[S[SSS[zĭu1    9[SKKKc[B1B91BKio[[icc[[i[K9B91999BBKSK19[ooucKS9  9c[[Szu[KB19SS1     1S[ozou[[[iS[Siuz[KSKSS[[B (1111  ((191(ijǹ¹ciziiouķcozuKozuuicoi[iuoiiiS[[[cSKKK[iǭoc   KcS9K[S9((99(B[i[KKKSSBKiSSSSKBSK9999999KcociiK9( 19[[[SKKiocSK9991    1ouuzzo[oziicuiuciu[[SKS[[[B9BKKBB1(BBBB1 ĭɼzuzǷiizzziKuzo[[iiiooiooi[cuucS[iڳuS(  [ci[9KK((11((119BBB1111 Bzzo[cuicc[SB9KKB9BSiiSScS9 (cu[iSKBcocK99911  (91(1((BKSKK[uicocuouzuczSKiuc[[S[[cS91K[SSS[[KB11 zzɼɼiizzzzu[oiicSccccciiouuuۢzzoiB1  1oSScBKB ((( ((( ( (111[zo[SS[ouiiicSB9BBBB9[iKBSB(9oiS[B9KccKK911( (1B9S[c[S[zuizzoioz[[[[ozzzozouz[KB9[ozzo[KSSS[iS9(BSBBKKS99((( ozγocuzoozzcioc[czuucKKSiic[iiuzzuzuc[9 1[iK[SKS1(1191(  9B9Kz[KK[cicci[SB9BKB99ScKBBB (KocKKB9KSB((1((( 9SS[oocKSouoizicSScozouooui9BSKS[iiSBKKKS[c[9(((1(1((  ( ozzoozoiouuzzcc[KKzuzozzo[SSii[[izzzuz޷zii[SB  [zoSc[cS (9BB1(((  1[KKKS[SBBK91(1KKB9BSKBB9(1SccKBKBBB( ( ((  (9K[SB91[zzozziiuoccc[cicuuoiozzc1oo[K[[[[KKKSKSSSB1(   ioozϳzccuuoiiooozziSBBzccuzzo[KSouzzozzzzҼSBBB9K91   1zui[[ccB BKB91((((111   [B991(1 ((999BK99BSKBB9BKSSKBBKB9( (   (  Biuoouuuc[uzi[[[izzooociuzuzuB [uuiS[[c[KB[oc[SSS9( ocozoc­zuuoiouoiciioioioioc[uucouoouoouziS9     (KoSK[KSSB(BS9999B119191(  SuiK9( (( (9B9BKB9SiKBBBBSKKKK9B1     (Sioiiiic[coccic[ozucccuzooc99KScc[cciiS[zouzuS(  ( SBcii˭zzuuiccc[cioozuiucSuzcuuuzu1   BS[i[1KKK199S[BB99BBKBB9B1991SSKBB1((1B9BKKKKBBK91ScBBBBBBBBBB111     BS[S[cicScozuciiozouuSiozuiiui(199ScccicSSouu1   (((iS[oozucͭzuuiciccciiuuuzccciKSzzz­9 (   1[cBBiu[iozcB9BKBB9BKSKKBBBBKBKSK1(1BcSKKS[cK9BBKB19KK9BBB9991(   1KSS[[[[SBKSiuciuuuiS[[uooiciuc9119BKS[i[BKouozz[   ((11(1oSSoiKciѳzouuouuoSouu͹zoiuuzĭªcK9((    9Sou[KKou99BB11BSKK[[SKSKKSSK99(9icKBBKKSB99B9911BK991(    9(  9SccSSSB((((91Kuz[[ooocizzK[zoi[cc[ 1B99K[[[K9Bczuoo[( (((BKBKKB1BK·cBczoi9B[KiԼuɼҪǹɪouuouuϼS9(  K[iuoiio¿Ǣi9911BKSSKS[S[ccciiciuziSB991B99999KB9BBB91((  ( 9K1   Soc[[K1( 19( Bouo[Soo[Kozczuiuzocic1BB(9[i[KBKiooioS  Kccioc[SSKKBĿBcoiS(9BB[cϿ¿°°zzozuz˭K    1BKSuɷoB1BSSS[SScououuiuS1(1119B999K9BB9BK119(  (1(( 9[[oucKB1  9SciSSou[[SKiiSSuo[oiozuui[1(9B19SiiK9[iS1  czooioc[K9(ϳuciS1119KSK[o¿ɹuzķzK   (SKBK[ɿɹz[BScS[[S[ioouziiS9B19B99BKKBBBB9((1     iuioi[9( (9cuiSczu[c[[[K[couicoiiuoc1(BB19K[iiKKzc9 ouoiiooo[B19(˷KcS9119KS[c[czuzĭɼҼu[ (( Ki[B9zǿǷiSSSKSccioiozuizzoouK99BS[SSKBBK999 ((   (1( Bcoccc9 ((BczcKKSiuic[SK9Sc[[iiiuuioK(19B9BSci[BKc[SB9cuiiiiiS1(1B9oScSB19BB[iocozzc[ooouuoķuuBuoB1 ((   (9cucKSǼ·ziKKSSiic[[iuoooo[iuzocKSSSS[SSKK11( ((  (1  9SioS9KcSS[SB (9K[i[[S( 1ouccSB9BKS[uziiocoui9911BKBKSKBBB9BB  9BSiooic[ccSB99((9zozcSSKKBBBScScuuuiii[K[c[[iɿ[11ii1( ((1(    9ciizu[ļ¿zcK[SS[[Scccccuzccc[ioi[c[[KKBB((11    Kuooouzi[SK911K[[KB1(  (Suzo[KKKSS[KSuoio[ouiK1911KSB9B99911SB BoSKcicc[KB919B1 (BKB[uiSBB[SBKKS[iouio[[cSKS[icĭҿzuzc(ScKS991(( 191( (BSc[KoiǼļz[SSBBKKBKBBc[Kcc[oicc[[[SKB(    9cocScuo[S99K[SB (ouiui[SKS[KBKKuiocioS919BBSS91BSKKKK[(1ioSK[[SKB1((1 1(( (KB[io[9cu[BS[iouuocSKS[[oװzٿzKB[[9uiKBB1 ( ( ((  1SKK[ScuijǿzK99BB999B9KzzcS[S[czoiic[SK999(    9Scic[SczuuocK19KK1 9coiucSS[[[SBKB[zzozu[K91119BKKKS[ccc[K1KccKKBKKK9( ((   SϷBBco[9Biocciiioi[[[Scouҿicizٰz[iҳu[[uzuooou9111  11  (BKKS[[[zķǿo199911119uuooiiSS[[zzoicc[KBB1 1111(Kioioo[SK[ciucB(19( 9[SuiS[icc[[SB911Ku[B9((B9BKKKS[c[ic[9 SocKB[c[9((( (K˿zBSoc91K[ciiciocS[[[uKiiuܰzoi¢oizuuuocK[cK111( ((   (9SKSSci[SĹ¿¹c1991999iccici[[[[o[cSKKB9((1111(91Soi[ScuicSKS[i[9111( 1[SB[[BBc[BKKK1((1[z[SB 1BBBBKS[[icoiB SoucK[uoB199(  Biu¼[ScS1(B[cciiii[S[cczozuװzuuicizo(1SSB91(11(((111((9[cocc[[SSc˼ķ˭c991BKKozSKS[iiiiczuuic[SBKB1(((( 9[Sio[[S[oi[cSKScS191( ([oS19B19ci[SKB99BBo[KB 9KSKKBKKK[ciuc11oiic[ScS(11( 1K[uouz°SScB99ScciiiiicKS[o¦zװuzzuoSBSozcz( B[SK9991 9KcSBScccooo[SKuiju[SciizҦc99BBKcuucS[[ioi[KiuooocSSBK1(  (11Siiiiii[[iooccSSKB991111( Kuu[KBB1(Kic[K9BS[[oiBB911KKBBKBBKKciicK  So[[cSBK(((  (ociɿ9SuK(Bciioiccc[K9SɖzuzuzzcK[oiKKo[99oc 9B9BBKK91BiiS[iccouoo[cuĿuBB191(99Kz–oB11K[izu[c[[c[SSiuic[SKKKKB(  199Siiciouo[[ii[[[[K191(1(((19ioccSB1(9oo[K99S[[oiKS919B999BBKKSciiK9 BccS[[K119i[S³B[uS1B[iooccciiSKuĖzzzuouo[SKS[Sizi9 9zu((99B9S[K9Kuziccciooioioļ[K9BB9B1111Bo·uS19SSozicc[[SKBiucc[BBBBB91(11 (((1BSSccS[coi[SiiSSSB((11((11(KioioiS9BKci[KBBKKBio[KB9999999KSK[ioiK(9ouS[[K1   Kzz[[o[9ǒSK[B(Bciouoicci[uҖuuzzuzzcSB9KBKSScc[cio[S(9( 1(9KKKcozui[[iooiiiĿuBKKKS[SS[cc[ciKK[ciiS[[[[K1coi[SKKBKK9(((B91199Kcooi[[[[c[ii[ccSK9(( ((9izc[icS99cucSB91111[i[SBB119BBKKKicS[c[B(1[ziKKB( ([[19iK9šSSSBBK[iuuiiciii͚zzoiouzoc[9(19911BKS[ooiczoBB((11BSScioio[cioicoǿɿSBBKKcocooiui[ǼiKB[uc[S[SKBcoiiSKSBKB1 1111BB[ouc[[[[cc[iui[[[B1  ((( Kzu[[[[[B9S[iiK1(1B91(9[o[K99BB9KSSiu[[ccB 9ci[S9 1 [i9(9oBKϿ[[[9BKczzocc[ic׹iuc9S[K9((( (1119KicK[S99BKz9 (9BBS[iic[[[couicļo[SKKBSoioouzccĞziiSKKS[KKioi[BBKKKB1 ( 19SiuzcBS[cciiccocSScK1  (Soi[[cccKBKSccB 9SB((SuzoS919BBSSS[icK[ooS1[cS9( (9BBBozicBBBouBBĚS[[B9SzzoiiiozzĿ[(9B9(91 111(9Sc[9SiS91((oKS[KBBScii[SSS[oz³KSKBScccic[ouizo[SijiSKSKBciiS9991191(99BSiuouuK1Biic[ioocic[S[9( (SccScuoiSBKKSS1(9KB1 1[iooc91BBBSSK[zuSSuK1[[ci9(9BcoK9B91coK9ɚ[c[99[iciiiz³B11 ((1B99919KKB9KzK(( SSzcScccccKBK[cuɦ¿oBKSKiuo[[[ou999K[ǼoSBS[SB119KK919BBK[iiocB(9[occiiuocic[SK(( 1( 1BS[[S[u[c[BKKKB991(((1ci[[[B19BBS[[oocozoKK[[9(Kozzi19BKɪuiK–iii9BoooouzҪS11919((19BK[c[KB9911(11S[[BB1iªoBS[ioc[SSSz€i¿SKKS[ouoizɼ111Suc[uijz[SKKBBBK1 (BS[[[ccS1 ([ziS[oooicc[S[B11( (991BiocSS[S[SKK9KKB9911(((9[[S[[S99BKK[iuuiizc99KB9ScozuuB91ci[K’cciBKuoo޷c9BKSS[c[cii[SS[SKK91(((1911K[cco˳uiic[SSccoİu99Bczzuu˚9(9BcuccioͼSKBB91B (19BBBBBB119SocKSiooicSS[S91((((((9izc[[SSKKKBKB91(  KoiSSKKK19KBS[ci[czziu91ciBKSuuiizuK1Sͼo[˼o[cS[oicuɷš[Scizoccic[[BBB9(((99(11BccziĿuuS[u˼SBBKcozčKBS[ouc[c[³zKKK911119BB99111991K[iSS[oiuc[SSSB1(((( (izuiccSSSKB991( ((( 1oi[[SKSB(1BKScoSKcioouu99cz[c[cociozuB9u[˭uBKS[[[o¢ٳiuoiooocizoS9919((9BB( (1B[­ǿǢcKSciouuoĞS9KSiuc[SSĪu99B119BBBBB99999B9[iiS[[oouc[SKB11 91((Kzzuuoi[[[cB919( 19BB1KuucSKBB[uS9K[oouuc[iuSBSKicSSouuoKczuKijzKSSSK[ަzu[iiiu[S[ccccouucSBK91 19B9( (19S­dzɰuBK[ozicĞKKKK[ocSScͼS9119BB9999B91BBSozu[K[ccic[K9B((((11B9Souzzzoi[[[c9(BB19BSSSK9[[SSBB9BBiuK1z[SzKBiccicicB[ioSBB1[٪ociccicKKKKiuii[KKKKK19199B1  (B[Ƿǿ˹9(9Soz[u¿žKKSScoc[[ͭuz919BBBKKK9991((iuuucK[icic[B(91(((19BBSSiuzzi[[[K( 9S9KBK9  [KKKB99999uKªzuBKcB9Sic[uzu[9Siozzci¿oiѢi[SSKSiicSSSou[[SKB9K[BBK[SBKB1( 1B[ij¼­K1(9[oo[i¼ԢK[c[cuu[iɞSc19BBSioiB19KizuuziSScccicB(91( (9ioSczocuoc[S9 1KB199( u[KKBBS[KBoiB1B1  9BSiu[S[[iu[[zoǼǖoo[BBB9999ScS99BKB99BK99Sicc[ou[S[[cķǼ¿ˢi991BSoucS¿¼ډScc[iiϿz1[z[BBBKS[K9(Bcoouoi[S[oic[1(11B91(1BcicioiiioicK1((9B91((( 1[u[SScccS[oo K[[(1B9BKKoiizK[ύuziiijݹzSKB99KB((119B91991 (19BBSioi[˹ziozuzɿǷ¼KBSKccoiKu¼¿ococcozooɦK9KKi[11BB911(1SoicoiSKScSSK99B99199BS[couccoic[[K 9B9 ( (19[c[ciic[cǭzSi19BKSBKzuuou⿀SB9919KB11B9991(119((11199BK[SiĞz˿˿ɹ·ļiSS[icicouocKSc[cͳuBKS11[[1BB1BB11SoucS[[SKKK[[SK9999919BScc[coiiiccSS1 9BB9111  1zucc[[[[[zzSuKKBBBSKoiizzzzˉiKKooB1[S919BKK1(1(91((11(1((1Bz¿ļĹ³¿Ŀc[ioc[o߹zi˷SKK1 1[iB9191(1Sccc[[SBB9BSSKBB999911B[ciiiiiccS[[S91B919B9B9B11Kuu[c[c[[SK[ioiKK[S9i͢z[BB9SoiKKKcSu٪ziozc1BKB9BSSB1(((((1BB1 (9oǹǿ¿Ŀo[S[uϹou­[9( 11Kci91((19[[KScc[K999KK1999999KSci[[cccicSSS[KB[[KKS[SKBBKSSizocSccSSBK[ziKBKBKK1 ѷ˿uB9cuiK9( zĚzozuzucS99BKSK11991( 1BB91((1[uzo¼¹ļ¿¿ziǹzo[ĿͼiB1(  99BBccBB919SSBK[[[[B919K9BBBB9BKcuuoicccii[S[[SciSKSK[[KKK[[[[ccSSou[B9Kzuc9((1K9 Sҹ[[S[K( zسouzoiooocK9BKKB9(119911K[SKBB[zzouzoicozuuzϿ¼¿¿ĿǦiS[uzĿɳSSB(( KoS19ScB9(1Soii[SScKBBKSKKKKKKKKooooicciouSK[SKSK119999((99Kccozu[[ozKBSc[i(1KB(1B[͹u[Si9(1(zuz͢zocccuzocccKKB91(111999Kcoic[[c[uuoiczcczԿĿǿǿǞiKKSizļǦoBB91(1 uǷucB11[zzoiccKBBSSBBKS[SKBioioiiiiiiSBKKB9(((((( 1iocczucii99ScK9cSK[ozijcciiKSi 191z͖ui[SSKSui[ciou[9( (((((1Sii[K[ocouuouzuioouķĿǹ¼¿Ϸc9SciuzĿ¿šcB1111 ([·i99czuoccocKBKSKBKKSSKBKooccciicci[K9B9( 1((9( (zzS[ozuiiS(Kicu[izccBKiocozozKBKKB[i9K19coz̈́cocSB99BSozociouuzc91( (( (9KSS[ouzzouuS[cccuzİǿĿǼ’KKcccoǿĖ[B1 (( Bİz9Sooi[[ucBBKKBBBKKBBK[iui[coic[[[B1K9(  (19KciBSiiouicoiozzuKcB1(9KK9So[BKccSKiiSSSKBKcuzطKSK9K91BBKK[uu[9( (((BSKKzuouccSKSiooiiu¿¼¼ϼoiccǼǞK91 (1(9˼zKKiic[o[KKSS99BKB99Siiooc[cc[SSK99B91119( 1ioiczicSSccicuouSioB9((1919[ouicKBczcKzoK9Kcoccui–oKBB91B119BK9BczooS1 (((9S[1˦uiiucKooKKScoii[uǦĹ¿ɿɿĿɦcB9( ((Bdzİoooii[SKKS9KKKKBSc[[[icS[[SBBBKKK9199B1ScKKBKcciic[[czz[u(1111(((9oiii[Suc[oiKBcuuioou[B91919KB19BB199ciiuSBBBKSiKǚui[uiK[uiK[cS[S[KiǪǿ¿˞[19 (1SdzĹ׷i[cc[SSK9BB99Soc[ScSK[SK9KKKB9((1999zoSSSKKKcuuS99K[ioSi1191( (KuicoiSSc[SiuciKSzzuݦK9999K[[[K999B99BKiuoi[Suzi[[[[czϳiiouzic[[KuoKKBKK°ĹϭK9B1( SҢҰϞSK[[KSK99919iccS[S[K[BBBKSB991(191[zicooi[KSS[KSB119KzS[uS9S9 (91 1[c[ccBSicSzSSBiui¼ǀBB9Kiuic[SBB9999BB9999999Biuc[SiհuiuocSKSziBKKKzuļ¿ϦB 1191Bcucz¿ٳo[[SKB119KiiSSSK99B99KSK9999999Buziiccouico[9Bc[9(9KzSuzuBzuB(1B9(1[cSS1(iuuBKouci9KS[c[ccccccS999B91  ( (1( 91 ( ((  ( (1  (1K[S   1ccSBKKBSSK9( 991 ( (11 (KS9  (991 19izKBB9999SiK(((( (((9[19oK( (SB( ( 1(9[i[[cSB911BScS[[c[[K1      ( (B( (9Ko’cSKB9KBKSBB  KcccioiicccuiKB9B11 (((( ( 9B  (    91 (9KS    9[cK1BBSKKK(((KS91  ((1iS( ((( 1119B[S9KK99Suz[S[S9111((B(91(B[o9 ( BBKKccKSS991((1(9KKKK9K9  ((  (K9  1BS˳K[S[oiK[KK  ii[coocc[ccou[cS991(191( (  (( ( ( (1(BK1 9BS1   1c[B((B[i[SB( (99BB9(  19cc   (((119(1[SKBB((B[[KcuoK99B911KK  1cc( 111Kc[KS[[B9KB1 (((    1cS  (( (1Bɳi9Sc[c[[[K99BSoiiic[KKK[S[S[uoS919BBKBB9991 (   (( 119BK1 KSK    [[B1(1K[K9(9BSSKB9( 1BB9      ( (B(1B1KK99BSKB9cooSKSiS91K[(( (cK( (1Kzzc[cSBB9B9       ((   BoK   S1  (((11BBKouuocK[z[SSSSKKSKKKBKKSoiSBS[SccKKKKB1(((((   ( ((119B9 1KKB(   [[SSKKSB[zcB( ((9BBBKSK911111 191(   (B1(9BBK1(9999Biz[KKiSB(S19 KzB1 (19[zi[co[[SK     BS1 Bc1    (  (B[Ƿcozoi[BKiiuuKSSSSSKSKBKKKBKioSKc[cicSSKB9BBBKK91  (111119999KB 1BB9(  [iK9BBBBBKccB111(9BBB9BBBBBKK9( 1B91   (B9(9BBK91B( ((KzcBBi[K 9K111oK1 11B[o[KBB1K9   ( (( (( (BB19(  9B (BB  99[ɰzuiK911 (SSSKKSKSSKKK999[oS[cS[[S999BBKS[c[K91((9B919(1B9K[B99(   (((SK9191B1BBKB19911KB9999BKBBK91( ((BS1    ((19SS9(1( 1Su[BBS[[[oc((9SS9( 11K[K1(   (91( (( ((1( ( ( 91Bi[B1(   9 (BK 1   9ĭ9111( ((SSSKBBBBBBKSKBBSccSKKKB1(9(199Biu[SB919BBB9999BBKK119B (11((111 1KBK1BSK[[B(((((1BBB999BBBKB9( (19     19KK19B1 ((Kcc[KKSK1So9(9[K(11BB1   (B1BBB11 11911 ((1(1(19KoS( 1KK1     1 9B  BžS BcSSKKKBKSB9KK99BSc[SSK9( 1B991((KiB119BBK[S19911((1 991  1KcoS99( iKKcK9KccS1 (1(BB9999199BSKB1 (((  (1(  9BKSB91 19BK[[SKSS1Ki1(c9 1(1B91(  ((BSS9BBKB99919111119(1( (9BS19cioSB1  (9((1 K[B( (B[( 9coSKS[SKKKB9BBBBBKSSSSB1((BSB( (1( (9KKK[iSKB9( 1(1(  1c[BBSc91  ¢zi[BSzK(1(11BB9BB9111BKB911(((1( (((  Si( (KcK (91(BSSS[[1(9cS( 1cB1(((99 ((1cucK9BKB9KKBB9BSK91KK111((((((1 (9coi[91 (BouoSK[B (9[1   (o9(KuuuSKKKKKKKBBBB999BKKKK91((9KB 11( 1B[oiocKK999  ((  9[oi[ 1KBuoS1111BKB9911(99BKB9111(1(((91(( Sc( 1[iB (1199BKK999 [[SB Ki[KB1(1B   (9cc1BB99KS[B919K[i[K1 1( ((((1( 1KKKB(((Kui[B9co[SKB991   (B B[[u[[[SSS99999BKKBBBK99BKKKKB1( 1  ((19S[S[SKB99( (    KўiiS[i[B[c9(11BB9999B1999BBBB99111((( (( (cS (( (KSKSKKK99(1KB 911i[ Koo[[[B19cc9(  ((911[ccBB1K[cSBKiuiKioK(((11( (1191 ((KiiSK9KiSKciio[( KBBc111oS[[[ccSBBBBB99BKKBBBSKS[[K191  (((((1( 199((9(   SԚKiB(BS91Sc[[KKKB11199(19B999B99(991 ( (coSKcB(19119199K[[KKB9B911991SKScK919[S[[Kcc9   9Suzuuuizuzouz9(11991(((1(((((SS1(((KK1So[[[SSB( (1[u9 1i1(iSccc[SKSKKKKB99KK9BKSS[[[KB91  (11( (   (1    BҦcKB9KB19KSouc[KB11BB1(1199BBBKB1991(1(1 (9[KSuuK9911((( 9KBBBKKBK9B9 (SB1ui991BSK9(  (9BKKSK(1ciuuiK9oz911(1911(1( ( 11 (9(9[iKSSio[KKKSBKSĚK9zKBcccSSS[[SKK999BKBBBSSS[[SSKKKB91191((((( (  19(    cҭo[9BBB999KSci[SK9(991(19999BKBBKB991191919c[KSS[9 9B9KB999KK1(1ccBBS1(SBSoK  (9( 1K911 (B1BB KS11 1( ((( ( (199So[BKSccKcoiS1[[i[K 9[ic[KBKSKBBKBB9SK19KS[KSS[SB9BK[SKB9119119119999(9B   (Sҳc[cB91 1K19BSSKBB11911(((9B9BKK[SKB999BK99KScS1(   1KSKBBK9 (K[1 19i91BK191     (1B9 (9(  (1B19cS( 1((((11(((1BScKB[ScK9[iK(BocSi[9BSzcK((o[[cBBKKBBBB9B9[B9BSKBBBKSKKKKK[[K999B999B1(9BBBBBB(  (( B9KzĄKBScS11SSKB91999199111(( (1999BKKSSSSSBKBK9BBBKK( ((  1B9B19B91[[91( 1[19( ( 9B(91(911   (BB  (Szi ((9((1((11((1K[S99K9B9BiiKBK9 (K19iccuS  K[SKBKBB9B9K99BS999SBSKKS[KKKKKSKK9999BBBB19999KKBB9 Bz9Bz[99[uoB9izS9B9( (191((((( (19BBKSKS[[S[[cSKKSKKSB(11((((  BB91 9(Bic[S1  ( 9 19KKSoiB191 1B( (((  ((1KB1(1[u1(111  (91119BBSK(191B[cSK9(1SouBooiK  1iSKBBKSSKBBB99KS119BBKKS[SKKKSSSSKBBBBBBB911(11BSSS9  Sz[9(oK1S[9(( 1B9( ( (((19BKKK[i[SKS[[SKS[S[[K9B( (  (1BSB( 1K(1[u[Sc9( ( (BSSoc1(( 1B (  (19199  ((1cuK (( (1((((1KKKB111BcoSB(  (Si[[SBcSKK9K  KSKKKKSSS[SB9B[K(1BBKSS[[KBKBKS[KBKKSKBB911111199BS1   B[uuS([u(  (( 1B( ( (11BBKK[ocSSSKS[S[c[[[KSKB11((  (1BS1 (9[BooS[[9 1( 9B[S( 9K (  ( ( ( (1  (9oi(    (1((19B[iiKBB( Bci[BB991(99BzS SSK[[c[ccS99BSB11BKSS[SSSSSSSSK99BK[SKB9( 9999SKB9  BSSczi[1oi9  111(BB(  (11BKKScicci[K[cS[ic[[SSKK1 (11(91 (KiSoSKSc[((1   ((  BS9((( (11(  ( (( BuK  (( ((((1111B91(( BicB1 (  S͍1 SKB[iuuucB9BK[199BB[[[S[SSSc[SSSBBKSKKKK911BBKSS9  B[[KBooiiB9(( 1199911K9(1 111((19SS[ooiuoi[[[[cc[[[[KB9( 9SS[K199 (1[c[KKSoi1    ( 11 (( ((((((((((( (1SzK ( (9( ((((( (( (91 [i1 11B(SĞSSKB9SouB919BS(11BBKKSKSS[cc[S[[KKBKKKKB9919(BK9(( (S[SB1(Si[cKui11((1111(1SB111(( (11BK[S[[[ciiccciiiic[[SKB199111Bozi[91BB119BccB(9KK(      (1    ((1 (( (( (((zB1( ((( (199((  ((((99 19 (BKSc[119ɒc¦KKBKozB(19BK9(119KKKSKSSSSS[SS[[SBKBB999SK1(BB9 ( ( (BScSB1((iKKS[[B11191(1B( (((1(119BS[[SSS[SSS[iicccoc[c[[SSSB9BKSuz[BBBBK1(11KuK    (K1(1((((( ( 19111((( ((([K (911( (1(((1B9BB( 1BB1(1( 1KK(9K9BKiKBBKioK(1(1BB1 (9KSKKSKSS[SSSSBBKKKKKBBB9KBKKKB(( 1(SSc91(cB9BBKB9  (1((1SB1 (( ((1Kcc[KKKS[S[[[[SS[iccoc[ic[K9B9KccK11BKK91((1[[(        9S9    (  19919991((Buc((( (11K[ciiSB(((( (( ((  9KBB19iSKBSSK11999SK1((B[[SKSKKKK[SKSKKBBKSSBBB9B9BB9 (1SK 9K[cK( Kiu[B9S[99( 119991[9( (1 ((11K[[[KKKK[[S[SKSKSccKSSK[[SK911BKK9(9S[K99((1[zB(     199   91( (99(  1Kuc119KScSK9     99191Ku[KKS1191119B919K[icSKKKKKKSKSSKKB9S[SSSK9991111191(S11BS[K 9[ucB1BK991 (1(1(19c91((( 11BBKS[cSBKKcic[[KKKK[cSBBBBB99B999191 1SS99B((Kii1         (( (( 19( 11 (Bcu[  (((((( (((   KK9B9BSocSS9 (((1BB(19[iccc[[SSKKKKKSS99BKSKKSSK9999BSK9((K9 BKK9  oocc[B1B[B91191911BS (1(((91BBKS[i[BKSS[[[[SSS[[cSB99BBBKK91( (11B[B( BSB         (  ([oB 9[[9 9K(iBBBK[K[B99((191(9K1 (Soi[ccSKS[[SKSSSSK99BSK9BBBBBBBBBB9 (Bcczo9  (ziiSSB99[SB((B911(1K[1111( 9BKKS[ccSBKKK[ic[SKKScccSB991BKBBB(1119K9( (1 (1  (11(          (KB    ( (19B9( 1Bc[BKK S99BBB99K1111111(1BK1(9S[SS[[[KKS[[KK[ccSK99B911BKKBK91(11 1cB [[iiKSSB9ccB 11((((9[S((((1(1BKBBK[[[[SKBKSicicSS[[[[[SK911BB91((9119K91 (Si919(191 ((         ((    (1(  ( ((1BBB11ScBS (9(199K1B9911((9B9((Si[KKSKKKSS[c[SSccSKSK99111119KB9( (1BKB9ui uB[[SScSBS[9 ( ( 1c9(11(((19BKKK[SKKSKKSccccS9K[Sc[c[S1 1(111(1(1K91Kuc1[9 91(           1(   (( ((((  9B1 19B(([((( (((BBB991(1BK9(9co[SS[[[[[S[c[SSci[S[S911( ((9KBB919BB( u 119o[Bc[ccSKSS 1(((1(Bi(1(1119K9BKKK[KKSSSSSSSS[SBS[S[[[[SK9 ( (((BSi[9BoiBKo1BK(         (B((     (111 ( (iS111iuS1(1(  BBB99111KS91KcuoiiiccScSSccKS[cc[[SKK9(  ((11S[K9KS(BS111KuoK[ciSKKK( 1911(11Sc111111199KKKKKKKKSS[c[KSS[KKSScooSKSBKB991( ([oui[icB(ic91            BB99(    (9B1 (9[zS (1Kc1 (BBBBB11111BK(Bcioozzzo[SKKSSKS[SSKKKKKBB1111(( 19( 1cB  KzoS91Si[S[icc[1  1119919[S (91199BBBBBBKKSS[S[[[S[coSKS[cKK[SS[KBB1B9cSKS[cB (1K9           9KBB(     (1 (9B9 11Kc 9zBB911111991Szzozc[S[SBKBKB9BKKSSSSK91(9((  BS1( (BS9BBccS[iiuo1 (191 9[K1999119BBBKKKKKKSKS[cc[ciuoKSSS[KBKBKS9K[KKBcB( 191 BB          (K((1((  (  (1cz·B911(1(9K[S[uzouziic[SKKBKKKKKBKKKSKKB1( ((S9 [c199Bc[[iozu9( (111(9S9 1999BKKBKKBBSSSKKS[[[[izzii[KSKSSKKKKKBKK9K[SB1( 1K[( ((1     (       19 ((      [BB191919KKS[iuzzoioicSKKKBKKKKKKSSK99B91(11( (11([c ([i919Biiooizi( 9S999999BKKKKSKKSSKKKS[c[czocooSK[[SKKKKSSSKKSB9991((((91 1191(          19(((       9zc1(K91(119K[KScizooozc[cccSSKBBBBKKKKSKBBKBB9999BBSKKKuz1Ko1(19[zuuuuS  1B119999KSSSKKSSSKKKKKcc[iiciu[KSSKSKKKKSSSK9((991K9              19(((((   1(   (i[ci999119911KSBScozzzuic[[[SSKBBKKKKKBBK9BBKKKSSS[SSu( KoK(9Bcuii[   ( 1B91999BKKKSS[[SKBBBKScociSKcuoc[oiSBBBKSSSB 191 (BS9 (1  ( (      ((    (9( 11(   (11(  Bcǹ(Sioz1((11(1S[SSizuoKK[[SKKKKKBBKB9KBBKBSSSccicu[ (SiB9SzooS(  (((BS91199BKKKKK[[SKKBBBK[ccu[coicooc[KBKKSK1B99((9KK9BK ((     (1(      [K[S    (BB(  1( (cucSBBSiiu(1111(9iSKiziSBBBKKSSKB199BBBSKSciizB1BSucSuuB(  (( 9[B9BB9BBKKKKS[SSK99BKS[[zSiuicozzucccSKKKS[B9((9(19B19     (99 (  Bo[(SzK     (    1B1(  ScB1BzoBKKSSo9B991(BucciuuBBKKKKK9991999BB9KKB[c91( 9BBKii9(( 9K1((cK9BKBKSKBBKKKKBKBBBKSc[oKcoiciuuccc[ccKBS[B91(1  1(  (1B(( 1    (So( 9[zS   (  1  9B911(Soii[ScSBB9B[B991199oiiouuioooozzuKBKKBB91(((1999B9((Kz[19 (9BBB9KϪzuu1 Bc[991[[KBB9BKBBKSSKBKKBB9BK[[[SSS[[iicS[c[[i[K[cK9991 (( (B9    (1BKBB((1 9919K[io[K11B9ii(      B9(1BKS9 ( 1oiKio9(9BB9((((19iicooooccSKBK[ioc[SizoKBB919999111999999KiBB(1KK9991oĒiooB Bio[BBBBc[BBBBBBBBKKKcoi[K9BBKKuoKKKBKB9BKKS[[SSSK[oSBBBB99191K1     (19SccSBB1KKK[c[iuiSB1(919BKcuc(      9KB91(Bc9  BĦzi[SuoB119( 11(1Bc[Sccic[S[[SKS[c[[KKK[iSBBB91(1119BB9BB9(SuB9 9B9999SiiS1 ( 1Bc[B99BS[i[K9B9BBK[[Sc[SKKBBKSSucB9BBBBBBKKKSKKKScuoKB11KKKSS9(     (19K[icSSKK[KBSSBK[K91(99(((1(Kou9  (      Bc1 1uzzuoc[o[9(( (1999BSS[[[[[SS[ccciicSKKKKBKSS99991199BSBB9BKB[B( ( 9BKKSoziocB( ((19BK911(S[SS[SSKK[[[[SKK[cKKKB9KSuoKKKBBBBBKScS9BKKccSB919B9BKSK91(   (  (19KS[ccSSKSSB9BKKBKSB( 1191 (1Si[B1(91K[c(   KS(KuSouiouucoc191199999BSc[[c[[ii[ccci[KKBBBBBScSKK9BBBKKSSK99SSc[B(( BKBK[uzc[[[9 (9999K1B1BSocKBKKcic[SKSSKKiiKBKKBBBooBBBBKKSKSiiS9BSSKSSK1(B(9ic99((  11( (1BKKScc[SSc[SKKKK9BKB1((19   (Koo[9(99Bic9      (u­oSKczicicS[91(1919BKcic[c[izoii[SSKKKBBKKKBcoc[KBK[SKSSKBK[[[zz91 1BBBBKii[coi1 11((KSKBKiu1199BS[[KKKKKS[iz[KKSB9BioKBBBKKKScuuiK9BBBS[K9 (1[u1   (1( ( (119BKK[c[SccBKKSKB9BB9((11  (((1KSB9 (1BKKK9(      KczccSScui[o[[zu919BB1999iiizooo[K[S[icSSKBBBKKcoc[[[[[[[[[[SSSSKoSB1( 99(Booioo9(B999SS[KB[[91(99KKSKKSKK[iouKBBSKSKiiBKKBKKS[ciccS9BKBKKB1119Boi   ((( 19B9KSKKc[cooSSK991(1K91(  (1111111( (BSB199199(    1Suzi[cucKSoz[[czii[iK91999BBSziiuc[[SSKS[iiSS[KKKKK[c[[[[cccc[[ccc[[SuzSSK1(11 BiicS( 11( (1( (( (99BKSSSSK[ozo919BBKSc[BSKBKKK[iiicS1BS9999BB9911z(   (1BBKS[[SS[cuziKB919B99K9  (11919119B119B9B(( 19BB9(11191(((9BczSBSiui[coz[S[oc[SiuzS[KKBB91SuciiSKKKK[[ii[KSKKBKK[ic[[S[[ccciiioc[SuS[[99co[9     191BKKSKK[uiK(9BBBK[SBBBKKKKSciSK99KKB19BB9999cK    1BS[ccccSKiuSSSBB9999K9  (9911919191B99BSB1 (9BB9BKBKSSciccizzSKSSccKcuucS[icKSccioi[iKKK9BB[zuuocSS[[ciocSKKBBKKK[o[Sc[ccic[[ioii[cc[c[1 1Kc[K   (((1BKSSSKKczoSBBB999BB99BBBKKSiuKB9(9BB9BBK9B9(9z1     9BSS[[iiS[uiS[[SKK911((11119919BBB9991((1B9(   19KS[[czozSBSS[SKcioiScoiS[[KcicSSBK919KiuzucSKSScuo[BB9999BBozc[[Scic[[[iooouoS[iS1 (1SiiS1  (((11111BBKKSSSooziB999B999B99BBKSKS[zoKBB1 1KKSKKKKBBBB    1SSSS[S[S[zic[[ccSK111( (19911BBKKBB9BB1  (  ((  1BKSScc[S[[[i9BSKBBS[SccSioiKBSKuo[1(((11Bccioic[[[[ScSKKBBBB9BKiocc[[[c[[SKSu[S[cS((1(1SzoB1111   1911(((91KSSKKKS[iuuS1(19BB99BBBKKKSS[[oziSB11S[cSKSB(KK    (BSS[SSBSizSSSc[ccK9B9((119BB99KKS[K919(  9BB  1( 1BBBKKKKKBBc[(BBBBKBKBBSK9S[SKS[icS(1991(Bcc[czocSKKS[zoSKKBB9BK[ui[[[SKS[[SBuuuuc[c[9( KuuK   (11991199B9BKKKSS[coc1 (BS[[SSKKSS[ScioiouuoSSK1BBSccKS[  (9KKKc[[ozc[[Si[cS9191( 1999KSKKS[[SK( 111(KS9(11((KS911119BKSSSB[c(BB1199B9(99(9K[c[[c[S(11((9[c[[ccozucKSSS[cccScSKBKKScc[[[cc[c[[So[iuui[ccB9(1[oo9  ((1991((((1BBBKKBBK[ii[KKBK[cS[[Scii[[[iuuoiioc[SKB1S[SK9K   (S[cuc[c[[[ocKBB9(  1BKBBBB9Scc[K91111  1[S((((((Kzc91(((1K[[SKci9BSKB91(1((99KScc[SS[S91119K[[[coouzzcKSSSSS[c[SB91BK[oi[[[[[[ciccSKcuoiic[S9((ciii1  (((19999111(11BBBKKKcuzocSBScccSSKKiuiSS[iuuicci[[[SB 1BB11  1ocKKS[S[[c[99SK(1KKBBKB[cccccB1((( 1[cB9 (((Bczi11(11BKKBBBc[9BozicB (1(9KS[KK[S[cc99B9B[cioiiicooSSc[SBSKB9B91BBKci[cicSKci[[S[i[S[[S[B11S[[[B  19B99B1111111KKKKSzczcB99SozoSBSciccccc[S[[B (1(    ((uzuccSSKKBKKSSccKBBSB  1K9Sc[coic[cc11SK9BozK  (KScoK9( 1BKKBBK[S99[ozziS[B( 1BKS(9K[S[11999K[[cooooozcSS[SBKKB919S[B9BSS[[[[SBSoKBK[cc[cccK19KSS9 (19B91199111((19BKcuz҉[119Kciic[Sciccc[[ccSSK91(       1Sz[Sizi[SSSKKBKB[i[cSSSB1 BBBcuocB9(KcS91BuuK (11119cc9119BBBB9K[SKSSSii[KB9(((( 9KS[9199BS[Scuoooooi[SSSBSSB9Kouo11BKS[[SScoSKSSSBBBKSSKK9BSK1 1199BBB9((1(( (9BScu㭄K91Scc[iuuoiouzuocc[KKSSK9     9icK[cuziKKS[SSKKKSci[[[K1( B9Bci[zi1  (191(1SBKS11(1BB91(Kc9(999B911[iSS[SKou[SKK[iKB9(1KK1BB((199K[Scuoouooo[KKScoi[KooK 1S[c[KKicBB9( (19( (1999   9SSSKKKB1(((11( (99[uzzuuzB99[cSScoozzoicicSSS[SB      So[KKKSciSS[[cSKKKKScc[B ( 9K1Sc99B1  19((11KiS11 11BBB1( 9K91991( (uz[S[SKBK[KBBK[i[KK9SoiK91( (1KiiouiiuooiSBiozi[zucB(1KSc[SccicBScB(   (19 (  (BBK[i[KSSB91(((((((((99SzuooooĚ[(1KcucS[zooiiucS[icSKScK((  1   9ciSSSKBKS[SSS[SSSSKS[[K9  (999B( (  ((99(19BKSB(  (((  K919B( BSBBBB91911(9SKBScSKKK999 (1(B[ioououuoiouziKc[S91B9BicS[SB119B( 11( (1( 19BKSK[ci[[oK11(( 1((111B9[zzzzozcKK1(9BS[Suociouo[BKSSSSSK(1(   (BccSSKSSKKSBKKKKKKK[[[[K1 1Scc9  (  1((19119KB( (  BKB91((1SKB9B9 9K91[ocSKKB91 (1[ioouuuuzou[[ii9(19BBSc[[B1(11( ( BB99( (119( BSSKKKKBB9B9 (1111( ((11KBKczuzuiic999(1KBBzz[SccSoc9119BKKB (    (9Kic[SSSSSKSKBKKKKKSccS[B ((1BKSKc((((((BB11B99919( 19(  191 9BKczBB99(  11Bcoiu[BK9( (1B[ioouuuziozzSciS (9919S[[S91919( (1199KcSK99B1(  B[K9( (9BBBB9191BBBBSczii[[cKBKB9KK99Scc[S[KcuziS99BBB9(  (  19Biui[SSKSSKKKKSKKKScocKB 1BS[B9B((1(11111BSS9999B1((  1(((  1BK( 9SSSK99(  (19B19K[S[o[999K (B[ioouoiuocuoou[BB(191(K[[cS9111( (1BSKKS[SKKBKB1( BK9   ([iicSB9111BSSKcozzo[[[KB11BK99S[cicKKBS[oocSKBBBBKB (( (  119[uo[ccSS[[SBBKS[SBKcicB (1( 1SS 11199BBBKKSS9B9(( ((((1(   19991(K[[BS1(1 B[ciiK11KKBBB919B[ 1K[[ciouoiccoo[[ooB (BBBK[[[oS1B9( (BSSKKSioK1( 1KB   1BK[ioSB19SKBBBKKKcuzucSKKB119BB1B[c[ioKKKBBSc[KSKB9BK[9    (91i[[i[SSS[[SS[SSBBK[cS((9B1 (1(19BSSS[cB991  ((9( (((( ((( (99BBKB[[SBiS1(1 KSccS1 1((1BS(1B[oiczo[[[SKio[S[ciS 1KKBBS[SSioKK1 (9[icc[K[[1 ((11((9KBKKBKSS[[K119Kc[BBKK[ciioui[KKSSK((1119K[SKciKBBBKSc[SKKK9((111111(   (11czSK[cc[[S[SSSSSSSSSSS9(1B(  1(1K[cSBScB1( 1991((    BKKBSccS919B[(((9191(    19BKK[zzScKBKBSc[[SSK BBBKKKS[cKKuoB (BiuuuiS9( (1( (((1BKKBKKKKKSS1 BSSBBBBKK[iicizi[9199B1(911BKKKBS[KBBBSic[[SSK1 (11(((   11coKBS[S[SSK[S[[[[KKKK[S9191  (19K[iiiSBSS9 (BKBBB9(  1KB19K[S9 191[o  (   (  BKKSzzoSBKKKSSKK19BKBBBKSSScK9[o11cziKKB( 9KK1 1KSSSK99BBK9 (BKB1(BKKS[ciouuuc[BKBB1919(1BSSSBKB999BSozocKBB91919((( ( (  99SuiKKKSBB[[[KSSSS[i[SSSSS9 ((11( (9BK[cioiKB991(19BB9KB(   9[9(BKBB1(B9(9o[    ((1B111 BBS[czucSKKBKKKB 9KB99BKS[c[S9(9z19SSK9(((  K[B11BBBBKB9BSSK111 (9Kcciiciuzu[BKK9(99B(1BB9B9BKB9BBSuiSKKSBBSB1((((  (BBooSBBSB1111BKKKSSS[SKKc[9(1((19BKSS[[[[S1( (9BBB91  ( 1[11BKB99B9999[zc(((  9B999BBBBB( 9B[ccozoccSBKSKKK1 9991(9BKB[KB1 9ucc[((91( BSB((B919BB99BB999( 9SSS[ouuuzocii[B91( 1999BB99119KSoiKBB[i19( ((   9KBuB9BB99999KSSKKSS[SSSiK  91((19K[[[[[S11 (19BK9(   (  9oS119B99KB99B9c[1( (BBKB9991KKB919[[[[[oziBSKSSKKS[11KK1  (9BKBBKK1 [c(1BB(  1B[9((9KB1((11999191(19BKSiouoccuuuoSKKB (11111999BKKSSKiiSSi    (((11KKKc99BBBKB999KSKKKSKKK[S((1(((( 99K[cSKKKK9(  9B9B91   (  Bz199991KSBBB99ii1 (1BKSKBB9991BK99BBS[cc[iuiKSSii[icS1 B( 1999B991KB(zzuB (9KBB1(( 9KKB1((1K99111191(9[ooouuuzouuuocK (19111911BKSS[[ccSBz   KB91919K[iB919BBKBSB9KBBS[[S[[K( (199911(((9Sc[[[[SSB 19BB99(  Ko11191c[SB9BiB19BBKSSKKSSKBKKBBBSBScc[ScucKScoz[cSB1  (9919BBKK1  cz1 (BKB( 99((1BK9 1BSK9  1BccccozozuziS91(191(1991B[c[BKKSBKc  BS91199KKczz9BBSKSc[SKKKBKK[[[[c1 19KKKB9111BKc[KKKSS9 (91911(     (io11111(uĹoSB99cc1KSSS[K9BS[S[[[KBBKSiocSccc[KBSii[KK1( 19KB99B9(((9oico1(9KB1 1B1 1B1(9BKK(1BScc[cozooS( 1B999BSSSuzo[KS[KK9 199( 1BB(1SK119BBBKci9K[ozziSSKBKKSSiiB BB[[SKB9B9KBco[SBK[B 1BBB91(  1( KzuS119B9BiɚS1BBKoiKK9BKB9KS[SSKBBBKScuiSS[SSSB9BizocKKB( 1BBKB111 9Siuii[[uoouKBB1   (1((199(   1B9coc[ouuouzzzo[1 191((BS[[coiKKKKSSS1 1BKKS[S((1(9K[[S9B[K1SozzcSBK[[[[[9 1BK[c[SKBBSKB[[KB1Bzz11991((((((  199( (iiSSBBB9Kii˰c1BK9Szi1 (11111(((1911BKKic[ccS[cSBKouziSB 9K9  1iiS11B[[[iS  (19191 9BBKB9ouzzzzuioiozzu[[K119119KSK9BK1(BKB9c (1BKK9 999[cS9(19iuBK[uuuuiioo[KS[co[B  11BSSc[KKK[iKBKKK91Bui(9B91(( (99((1BKB9 9SSBBBKB99SiSz[19B9Bic  19oc[KSiccii[couocB 1B1(191cuc9 (SoiSo1  9(11911  (199919B[uuuoiuc[cozzc[S99B9((BKB99B9((9KB9oz   (  1BKS91( 1SuoSiuo[S[[ciccccou[1 (9KS[[SBBBKoo[BK[SB9SoS9K9   (9B99  9KBBBKKKBB9BBKB(19BBSu[   ((uS[[io[[[[cio[1(1 (191(1KSuic9((Bouii((( 9B(19B1B119B9BSiocciccoooi[[ciuocSSBKSSB9BKB9(9KBBKBB9B[(   (1BSK  (1izoouzSS[[cci[[[iiB(19BKSKSK9KBKSSK9SczozSoK991   (1  9KB99BKK99B91Bcc 1BBKKKuz1  (cSSSii[[[SSiuuiSB1   999SoicK119[oziioz1( 9SKB991 (9B1(19BK[coiciuuooooicSKS[iccccKS[SBKKKB9199BBB9BB    19BK9 ( 9zoiouzuc[[[[[cc[[oc1 1BKS[S[KBSSK9BBBKcc 11(((((((1(   1B11B1BKKBB99(1[zuK19B99B91S[1 z[SKBS[[[K91Bioi[B (((( (11SciiB ([oio٦iB (9BKKBBB9 11(1( 19BK[uucuoiiS11BKS[[K[[BBKBK[[BB(((9KB((9     9ccc[S[cic[[cc[S[iS( (1BS[ccSBB[cKB9B9BcoK  (111   [99K[KSBB99BB91K[KB9BB9BB9(BcuuuB c[KKB19KKSK119Sci[1(9S[B9B( Boic( 9izo[u[KKB999BK919BB11  9Suuuzzzuooo[9911BSSBK[KB91BciSB911BKB 9 B[[SKBS[[[SBS[cccc1 9KciciK11191BB11BB(1((  ((  ([c1SKcScKKK99919S[BB9B1BBB1(9[uSi[11coSB199[cKBBKBB[SBScK9( czo( B[iuSB919KB9( 9B  (1 Kcouoooii[ccccSB99( BSB( BooKB919BK11(  [iKK99BBSKSKBBS[[SK 9KS[[[ciS91(1119K1((     KzKKS[c[[BBKBBB9KKS1((11KKK111KccKiK (co[991Bco[[[[KBS[KK[ou[ (BouoK  1uoiB911(1(  (1[uozicuzuoiiiic[SB1999B[K KuiSB((11( 99   (iiB991BKKKBKKKBSSS9 (9KSic[c[B1(((1BKBSc( (      (zKSSSS[cKS[[[B999SBB91(1BBB99KScKcuc99SoiK1(Biucoio[KSK9KS9 ( 9KoczuS uu[[uuzzK11(191   9czooocuuoc[ii[KB1199B[K1czS99(    Ko[B91(1BBBKSS[SB91 (BBKS[c[SK9119K99B1Sc(( (   KuKS[SSciKKci[B9(1BKB (9KKKB99KB9cuuzSBi[11Kciiocoo[[K11B9( 1Suz[o[99ouc[czǞicou[iucSSB(((   1Biuziuouuicci[9999B9BK( BcoKB((9       uiBBB9999BKBBBKKBBB1(BSSS[co[B9( 1B[BBS911 (91(( ((     1oc[c[ccccKB[KK9B999BB1 (19B1919B11KSSouuKoiB9Bciuzc[icS9 ( 1czoK1ociiuuuzoKcocco[SSK1  (9SzocoziozocSii999 19BB((S[cSS(1iS      coKBBB(99BKKKKBB91B99S[[[[c[K991BcoiS99( (1B91(991((   11( 9KSSS[c[i[SSB1BBKKKB9BB99BB9(19(((19KBKccKKSSizSczc[BS[c[[ouS9SS( ( 1czuSSo[ciicooizuouu[Sioic[B999((  1Bzzi[K[i[iuziKSocK1 1SK1(BBBuo 1oK    19 9[cB9BBB91B9KKKKBBBK9199BBK[S[K9KBSioc9(  (9KB1 ( 19(19911B[z[SSKK[cSKB1BKBBBKKB99KK9KKB91 1(((((9BSBKBKBBKSoiSBSS[BzuSB9 BKoS( 1BS[[[iizo[ioiuzocouui[c[B9B9(( 9[cuiSKKSKSii[K[oSK91BKK919B9BuK     1B[[iSBS[ci9KK[SB9KKKKKB1(19(((19999K[B9[iiioS9    91 ( (1(9KBBKBS[KizooiSK[[B91BScSBBB11119B1BB919991191(( 9999B991S[BB BߚB(B  BcKoozc9 (BBSS[SSSuzoi[czzouuiuoScoSBB9(  ( 1KDŽzoS[[SSccK9KSB9((BKK1(9(9zu (BKScoozuiuucc1BSc[S[SSKBSB9111( (9BBBB91(19S[cK( (1 (11119BSSKKKB [uiocK9BSK9 1SSKBB9999111((  19(11991(1B91(119KiB9zބ911(KioS[coz[1(BSSuKK[[9KuiiS9K[S[i[KS9( (( 1[zٞKic[SS[K1BSK((9BBB99K1BzBBSSK[iiozuucKKKS[[[SSSSSSSKB9((111BKSK9(  (1(   (1 ((KB1( SuBBB911BB9((1B99B99BB91(1(1(  ( (119B1991(19BKccBzSB( KiiicSK[[9 99B99BS[SBcĪ[( 9[[[oiSB11 (1( 1iozozoouzoSKK19SK19BKB99B[iK( 9ccicooozzuuo[SKBKcccS[SSKBKKBB (9BBK[9  ( 91  1  oi91(( (11B91B91191BKKBB((((19  ( (999991(1BKKoccɒoSB( (Soooi[SSK1(9KSK19BKcoBcooi1 1[[cui9991 999((9i[oozzzzzo[K9BKS9(BKBKBK[ii9 (  (19Kcoic[uuzcooiKKSB[iccSKKSKKBB11 11BSSB(   9B   1uS(919K (1B9B911111KB91KB119BB1B1( (1(11 (191(19Bucuo䰍[KK99B[oicc[[KS1(1BKKB[c[S1[11BB9BKoc(9SSK999999191 (1KcczuoiuozoK1BK9BK[S9K[SSS1 (9BB1999KB9SicioouuuzuiooSB9KB[ciicSBKB9(19(1(191  (       1oS(BBKiB(1BKKB1(11(191K[cB199BBKK1(((1(( (99((1B[cci[KB1 Kzic[[[SB( BKSS[SizozK(B9191[[1BBB9BKKB9  (BKS[oucciooczSB9Kccoi[[BKB  (9SSS[KKK99B9BBcu[ScozuouS999K[[ciicKKKB91991          i1999K9(( 1991999119BSc[KKKKKBBK11B91911((9((1BBiKicB(o1K9(9uS91191( (( BSK1Ki1K1 19KSSSBBBS[KB9  (1BS[ioic[ozoiKKB[oBuS9 (99BK9BSiii[9919KSouc[czzzoKBB9[[[iiiiSKB9B9BB1((         (i911( (( 111911119S[SSK99B9B[iiSK9 1119991119BoiiB9z9K1 Bizi9  ((BK9 cuuuucBB((1KKic[[[S[SKKB11 (9Kc[uoioocuui[BKKcS 1KKKB9( (1(9 9oiB11BBKSioui[ozzuzoouSB9B1u[[iccicKBBBBB9((   (       o( (91(91  (11(1111BKKccSBB9iuiu[K91((9B911119խcouo[B uK(19  ( (9911izSSiuuoc 1(19KKS[cci[SccKB1(((Ku[ouccciozuocKSKKo1 (1   (( (BiK B[c[SciuocuzuzzzuS191(1z[cciioiK19BK1  (((((((      (K(199((( (B(11 1(1BBBSciS91[ziKzzS911119BB(1((1uz[ڳ[B(19(BB( 191199(1zSB[uzS 119SScScioc[[91 Bcu[[i9SciuSBc9B9  (( 1((ci(SoiiiouoicuzuS( 11(cτiicc[cS99BB1  (((99111111911((    Kc(((1(( ( (9B((199111(9KSiiBBucB1c[B991(19B911(9uooziz؞c991[uB(9B99BKB99((SļcK[zoBzͭ(1 1ccBic[[K9KKB1( [zzSBSKciou[11B9i[  1(((K9((Bcz[S[ozuiiucB(1111uύ[i[[[S9(11((919KK99B9B9B9BBSB(    1((  BB11( (1BBB1( ((1B9(1BBBSB9[zSB9SS(11B99BKBB9 (uoc[oׄSB19S[1K[KSSKB99(ѦzcK[[KKK((([c99ci1 1K[[B9( Su(([oicuoB ( 9B  1( (B1 (9czu9KcizoiuuK11(1((1[Ǽz[cc[S9((  (19KKSSKBBBKKB99BBKB1(     ( 9K9111( 1BKB ((( 191 111B9KuoK911B1(199BKBKK9(uc([҉c[911(( (BBBKBBiS9uzKBKSS( (9B 1Sc(1KccB19(BiS11czSKci[c91Ki  (( 19( ( 1c[9iiuiouS( 1zu[c[SS9   (((19BKKSSSSKKK9911BBBKB9      (( KKKKKB99K9111911 1999  1BooccS1(oB(1199BB1BKK9uK1 c͞z[1(  11(((1(191[oc9(9c[B9Ki[B(Boc B[Kzi1((SSS9BKB91(9[uKS[9(B91Bizi((9S[KK9  1SozKBcizu[[B 9Bzi[SSB9 (99119BKKSSSSKKKBBBBKKBKSKB91(  (( 9[K9BBKBB9 (9BB1( 9991  1ucK[c[B1BiK911111(1KS1i[1Buѹo9(1 (911(((191z[91((1KuuzoK99KioK [o(9ozi9B99SSB9KBB1(1Boi911 1cc91KB   9Sco[K  KcuucB(9Soz[B1 (B1 u[[SB9((19BKBBBKSKKSKSKKBKB9BBKKBKK9911   11( 1ScSKKBBB9((9B911 ( (1(( (Si91B[S[11iiB999BB((1KK(iuBiݢ[S((( 119BB(1(BuB1BBK99[S1Bczc9 BiK1Bic B[BKKKSKKK9 9( (BzB ([uS91   BK[u91 1(9cc9 9BS[B(  (BBB((199BBKKBKSSS[[SK99BBBB91991((19111  111119BccSB11999999(  ( 1[iB9KBB9KKB[u9111(9111KK1Ǟ(S 1KSSSBBK999Kc1KKSBBK9199SK1 9[91SK1ciB9K[ci[[c9 (Kzo11((9S[B(  9[Suo99(( (Si[1([K9  1  ( [S11((  9S[SS[SSKBB9BSSSB91( (1((11((((1(  119B99BSii[KB991((191(1(  191(Ku[(K[B9BSSBSoB9B111919BKiBB BSioSBSSBiѹuKB1((BSSBKc[K1SoB99Ki[[K[BKScoicc[[9 ( (B[K(1SK1((  9[ii[( ( (c[zK911  1(119BBS[KҢi(1(  BKBBK[[[K91BKScS1(91 ((( (1((((( 199( (9K99BBS[iuoSKB991999119( (1( (11KozK1KS911KB9Sui11119B119K޼uKB9(KSSKS[Sǭ[iiKBSiS[iKzi(9[[cocBKSioi[ii[B1 1 991 (99    Bi[SzS   99BB(   (9BS[cui19(1(1KB9KSS[SB(9[[SK11(11(91(1(1( ((19BKK919KKKKSccciicKBB11199999BB1(  (KSB(((B9( (9K9BS9(91199BBBuooK1 ((99((1KKBBozcB1iuScuo[ocB[B(1  iiKK[iciooo[[S99( 1B9 ((   9[zuSBi[ (1(    1BBKBK 111(19B11BK[[B99KSK9( 1111(111119BBBKBKKKKB9BKKKKKSc[iuc[[9((1999BKB991(((((Sz9  ((9199oB1B991BS9KҖ[[c[ci[B 9ic 1 9ܿS iu[[S[B1SKBii[S99K9 9uu[[[BKS[uuuoic[99 9KB(  SKBii    9KK((  zKBB11111119BKKK99BK99 (((11(9B9BKKKSccoc[K99BSKK[SKSSioc[cSB99919KKK[K1 (( (119KSSS1 (( (1KoBBBB9119Kczɖ99uoco9iu9 (zɞK KicK91 (B[B([oK1111BK[BKSKS[ciiiouc[K1(1KB   c[BBB 1  (( (Sc[ouK icBB1( 191999KKB9BBB( (1191((1K9B9BKKKSS[cc[KK[KB9KBBKScicSSKBBB9BKSSKScB 9cK111 1izB (u1B911119BKSBBKS[KKK[KKKKKKKKKBBB9(oɷ³Ϳ˰uܰݷ˷¿ͦϼzuiouoiz°ѹɹϷļĢSSKKKKSSKSSScSBBBKSSBB( i¿dz׿ǒuǭܳuطļ¿ѳuiououuzͳɼҿɚKKKBKSS[S[S[cSBBKKKKB o˷¹ɼҼѷ͞İiuԳԦuǿ¼oooouoooļdz–ҪԳ[SBBKSSSK[SKS[SKBBKK1 KĹ·ҹ¹ݷ՚˷ɖucuooɳzoouuiuoou³ª׳¿ճ׹[KBKKSSSSSSKSKSKBKSBB¼¹տѹϭԭ·խǰiozɼļ׼uoioiiiz­෦¢Լ¹׷ĭSSSSKKKK[SSKKKSBB9( 9uz³ɷѳѿۭ°ޭͷɼĭɳziozoiiuiodzo[cSiɞͿϰɢ˼SSSKBKKS[SKBKKKBB(9u³ļǷuijɹ¹ĭ୹ͦªozziiuu˹uSi[ǖѷϰǦտ[[KKBKSKSKKKKKSK9 Bo¢zļǿٿ˹[׿׷ĿҰĹĿĿuiouzͷډKccĖĢ¢ĿzKSKKKS[SKKKKKKSK (iuzļķٿ˼¹˹׭Ƿ·z¢uuoozo˷ۉ[ioǚ԰ͼc1uKKSSSSSKKKBBSSS1  KzcozuoouzĹij·˿¼¿ѹϦǿ·İSiiu·ozͿڀciouɢɢİcķ[SKSiiBKKKBKSS9 1zuuϢǷǹǼǹ迭ǹ¿ǹij͢˿˹dz°oozSiccˢٷǷijªSSSci[KSKKKKK91i誄uĹļ¿ճĿئҿzĦǷɄuzKiiiɚѪ˪czouK[c[KKKKSSSSB9uްǿ­³ذǷªǿu¼ijzuzڄBii[ĚڼǖiK1iu SSSKKKKSSSSK( oҷz¹ԷĿ¹ǿǼ˭¹czļͼעɼizل[ii[ɚϖɼzz[[K˿c[SKKSSSSK9 SucؚoǹĹڷ׳ǷķĹǼǞϰ꿭iى[oo[ϞسĹc[SSKS[[[K  BziBuc·ǹ׷Ϳؒǿz¹ǿ·ɭii¦ްuحzioiўɍͼɿ[KBSSS[[S( BzɰzciĹǼİ˼ѿǿoɿǿdzzտ氰z٢iioo͚ҞϹoo缹࿷Ĺc[KS[SSS( BļcĿ¹Ħķuoz¿¿ĿĿ·ɢzՀcioiˢտٷͼi[ԭͿšSc[Sc[K1 9uª؍¹ķњǿuiuzĿĿª˼ǹz؍iioc͢ͷؼĢocKS¼˒[[cSSK Bo˭㰰·ǹѭعǪuozzzļɳɞĹ¢ڒooS͢ijϭšo9cɿѿ[KKSSB(o͹ۿɹɼطͷԼ˳³uouuuzɹzu˹Ŀɿۄoi[׭ԹҦѹzoĢ[cܿ[[SK9iѷzzozǿ˿¦zciicǪz¿¹ĭռϿļǹuciuذϷԭ˷ioǼɿϹK[[S( S¦uizǼ¼Ұ͍uz[zccuz¼ǷݼҼǷͳzioooխϹ԰z˹ioѹҰKKSB Kɦz˿ķͭĚo[iouu˿Ŀǰͳ¿ɹՉizѪϷѭͷzzii1B (o­˿Ĺǿٍc[¢ouu¿ļҿ˼ǪٍuzͭɿѰϢϷouzouoc͚uK(cķɷķҭcKɷ³oo·dzļ͹ϢՀuzͭ˿ǿհ͖ɳoouzoiuzuoᰚǭiiѼǹķɼ՞³ĹczĿķ͞˿[ԿĀuiuzѦİĹ׼˚uijuzuzuiiozizz’ªǹ·¹³Ԫ¿ǼǼzĪϰ˿˼عωzczzԦͼļռ͞zdzuooo[[[ouzoSzҚǿɿķǦԒ¿ķĦciϳɭ҄KzͿĦϢϢфoٳĹ¼Җ˳zooocioiccizzoz¹¿³ǹ¿K¹ɭĦzͿϿoi–zuɰѪωz¼Ǽɹ˄u˳zuiooiouzuooozoĖˢǹĹɼфiܢ¼¿‰ij˹zzSi˷„ѭĦuouϿǷѹĀiǷzuuiiizzoiouz’ǿɼͿǰ歒ҒĹ˭ҦzoBSϿ׿ˀѰ˹ouiciiio·Ŀ¿ǷҼ¼oǰuooouuzzocSiuԢ˿ǿ¿³³ҷ˿ĭɳܰoziuǿіzҷ¿K9KBB[ci[Sz¿ǹѿ‰oǰzuiiozuuzocSSoouĹ¿ǹɼ¼ђĪ್˖˹ķխ’ļzcccouzi[zĿҼĉz°uoizziouuooi[[iziĿɿ˿¿¿¿ު鰢ļɹѼɿǹĿ٦ؿĿijҷ‰³zouzziiiiiiouui[[uzo¹Ŀ˿˹Ǽ¿¹„oͪѪɚ­¿ǿ՞ԹĦҼ’°zzuu[ciiiioooi[SSi¿˿ij³ת°ǰͰiļԪ‰Ѱɢ­uoi[cciiiicicc[KSc¿¼Ĺǹ°˼㹰Ϸzɷ˿չioz˿٪€Լҿˢ­zzuoiiiioiiccccccSci¼ǿ¹ĭ¼¢ٹ°z˷¼˿׿ͰS¼۪ĖѿԼǢijooozoicciciccc[cccioļͿǹǪ⪉Գɳǹª·ϷǚdzĿ׹ԖĹԷɞķzuouzi[[[ciccc[[[coo¼͹ǷǪҞzĿ˼ļ¹u˼ɷ˼ύzǪɼѹհ˚¹zzzzoc[[cc[cc[S[ccļ³ԹѷٹĹ˼׳˿˹ǭz˿ɹ۹ٿ俞׼ɞ˿zuiccic[c[[[ccǿĹ¿˞ذĹͪ¿–˿Ͱѷzžɹ¹տᢉzǦͦ¹uuuuuiouucļɹѷ¹Ĺªķ˹¦zĚͰuѰϰuzuuuz㼉uͿϭ³zzu¹ɷϦǢ–ª¿¿˼ɹcuҿĭcޖiozzuuuzzuҹϭĭļɼ˷ɷҖҼͼͦ·ĭzǿ¿ªoٹܹcޞiuuuuoouߖSoϷѳ˿¢ķ˿ҭ¿zzٿ˚[­Ƿɭؼ¼ѰǷ˼հݹĢuuiuzuuuuuo[¼Ϸ¿·ܳ¿¿–˰Ğu­dzzǼͿ·㰀ϰͦdzҪo㹖zuuuzKij͹ĹǼ°¿­ͷ·ϳ͹¼ؿķ꿍ɳͳݷԦz¦uuuuѹ–žɿdzļ¿¹ķɢɭ翢ͷҿ˹ɼɷܭݷњz࿢uࢍչɦɷǿɹ³ǿݿ·Ҽ۹߷¹Ҽuij׷ѼԷɷܷ͖oiⰄⷖĢɷϦ¼ҪǼؿļϳڦ˿Էշ¹·ͷ¿ռǿذɿݷ߼Ѧziu㰉˦’­٪Ĺĭ¹عѢ·ժİļѳz¼ݰ׳o泀孒ɦϭ˪˦ɹѷ¼ݿdzɿ٭dz˳Կѹɿﰚijݳ٭z㹍乞ǦǞϳɹİz³ǹ䖿Ѽz·˷¹˼˹ۭ٭zz˭ǭϼɹļ¦ɷzoĿꪭ¦˹Կݿij٭ޢعuiozzzzǰǭͳ¿¼ɢǿzuozĭª¼uɿ¼ͳԿ¼ѹբĖocooouuuo弪Ǫɪ˿¿Ǣ˼ouuzzzuͳ³uɿѷĭѷѹמĞzuuzouuui¦ˢԼԿ¿¼Ǣļoouuѿzϰ°Ϸ¼¦ՖذcuzuuuzoǪѪͷĹ¹šĿ¦uziuͿٹz¼˹˷Ϫբҭzᦒzzuuuɷҿͼļļǚͷ³uio㼪ҳ¹¿³Ĺسתѳ༹uҼҼͼҚɰɪu·ouoٿ¢ͳ¿˳İͿܿ٢ڼԳᷖiԹ˰·Ԛ­ĹuĢ[˰Ҧijͷ˼dzϳ˿ϪڢٿzѿԼհǼ˖ɹĹuuͦzzѿѿİĦҼǼ°뷼ªݹѷ輖ҼռͼĚϿĭooԢɚԪĞ·Կɼ쪹ǿ¼Լϼɪ·ǖϼɚuuuݼɢiǪķ׹Ͽɿɷ濦ѷԭ¿ɼ͖ĹͿļǰǢuɿ­ټzϭɼͿ˼Լ䭍ҪԷ¿Ϛ¿ijҚѦzងع¿¼ѷ˷ͿǦռ尀ϢĚ˹њ¿˼ouުo³ķɷ˳ǿĿɭĢ׿ž˞ѦϿזͿu؀ɷ¦˹İϷ¼ɪĿ˳׼ɖ׹˼ͿٚϿuǖ幖¿ђ·Ǽ¿ǰɿžɹҹ׹ɼͷǚ˭ɿ¼ؚz˿Ϸɪۖ¹ɹĖǼҼͰѹ¿ڳع͢巒׼Թ·ٖɿijª۹Ǫ°՞ǿļͷǼͿǭհԪԹ߼㹉ҹ¹ªķۖɼϼǷٰɭzǪ¿ɳǹ¿ݹĿǹհϭۼ³ҿϹ۷俖ĿǷǼך˷ϷĚuu¿ǿǹ˹輿ɚͦؿϹǷĢ˷ط¹ͼԿǿɿǹԞǷɹªž­ķǷͼ檄˿Ģ͹װͰɼϹuǿɖ˹¢ɢuļķĢͷ·峹°Ǽހ[˷ɪԷسķļռuļªǿĹѿ˼uĹԷ߳ҹļdzǰczϢҰѳطԹ¹ҿļĪ·ǿɼѼĹɼޭԹɿɭķѹļ³€ѿǒѪͷ׹ҳ˼ɪĭzļķļuuzǿǼĹ۷ɹļ͢Ƿ˷ͼ˼ԼͰۿ߹ҹĿռͼozzz¼ɼuBi³cǼļĹͼdz񰞷ļɼɷɼĭɷϰݼ޹ļķžooĹǹѿ¹ª¼˞ɹꪳɢĭǼijķͳۭܿѹͳǼuzuǹ³ϼĹɹ¿Ƿǿͳ˼ǿѭͷžݷķװǼuz¿ǭĖzϷ˼˳ح˰¿ɼ˿ǒϼҼ߰Թټ¿¦z͹˚ئScļĹ¿¼Ǽխļҿ·¼Ǽ˿¿¿߭˪͞¹zzռؚϪ¼ɷ¹˿Ǽ۪KĿǹѼ¼Ŀ¼ļɦۢɿĞĪz˞˖ɭɳ°¹׉o˒ǿ­¼ɼ¹¿Ͽɹ٢Ƿz¿ķ˰iozuҿѰɿĦτѼ¹ѿɹ¿ҿĿɰ¿ªڢz¼u˪䭿¼ͭuSKSSiuzoo¿ļѷ­߼ϼѿɿǷ˿ǹװ¿׼Ǽݰzzعɦ˿Ϳu [oSuzizio­ٹdzܼϼמǿѼ¼عǷķĪ˚­˦ĪɢB1ziuzzc¹հĹ٢׼ڰɼ¿¦ǿ­ĭļĦҿݷ·ͿoS[zzuizijҹ԰ͳo¹۹ǼijϦ¼¿¿ǼϷzuբĚSc[ooziu˹˪ުɷ·ǚ¼˿Ѧǿ¹¼ٰcķͭzu°zĞKBucozuiSoui˹٭ɳɳ˰ɰķўĿ¼ͿɖĿ¹ަzڿɰdzǪzu(czi[iS91[zuczijϿ˰ҼԹ¹Ұ°Ϸխ¿ļצuϼ·°ĿϹzzioɷciucBK91Kcuz9⼰˷˪dzؿ¼צǭؿǼ緖ϷڼzuiBc˰cSSiiouScocoooiz˳ҿ¿ϭǷڼ¼շ˿Ĺѭu¹Ŀĭճi[uKKˍuoiuzi[ic[ii[SiĭĪļķij¼ع¼ϼ¿˷ҿĿzoiB˼uiz[iuiKuuiSSc㖭·¼Ǽ¹–ļ·¿ͼͳķKižѷooui[uozzuioKBcuz㼖¹չ˷ĹĒ¿³ĿǹSKǪčcz[SKozz[ioc[9Scu·ѹĿͦ¹¢Ƿzico[ϷˢzKui9iizuž9zoѷļͰ׷¹ϭҹ–ͷⷀ91iiczoiҷѭuioociozķ߿¿ѹ߹¼խzzɰĞ·׼񀀖(BcSizzuļعժoiiizz෪ͼ¹ĭǚɷ³׹uou¿Ě¹˿ѳڒK[Si¼ؿԳzɪoo[SuiSzuKczcoۀ˼­Ͽǰ҉ļĚzuuuuǚĿͼɦocc1uzͳҷϪozuc[ouSc๹ҷijҼͳ¼Ƿ˪zuuuouuuǚܹ׹ɳuϦ̀u99izuռіoļǰz[[izzuzdzɹ¼͹¿ĿѢzuoiioozǞǿšǷuS9uKiljuzuiz°­ouͳĿɹع¿Ԗzzuioioozz¼dzѿ˼۪¿€c1SzciuiuoϦu[izzɪuzzozuzuͼķԿϳۿ¹Ԧuoiiooz·­Ğ߿uמǿi((BKizii(KѳuS[ǰ9ioKKzu[Su°ǹǭĹհucciouļĹǦǹҪ¿ڪ1(9coooz1SѳzizͼzucoiSSĞzS˷­Ĺڿuiiiiu¼¢ɿǿ[SSBu·KK[ԿuzɳSiou˒o·Ĺ˰dzɷɚzoooouzĹѿijͿĿɹɼ¿˿ij¿ª­ϰizuciozϷ߳izouicioccoouocizSKcǼucSScooicSS[[[ciiooozo[ozǿ¦ǿͼ˹dzɼuo[KožSSccioiuzuouuzzi[uǭĦzi[coooiSBK[[[c[[[cizu·šɿĞijɹ˿zcS[ժ[9S[iiooouuzzuuzuizizuzzc[[BKS[[S[[[ciuzǿĖzzzɳ¿ĹǼ¿տϹԹĿҞcSciciiciuooiouoooiǰzcoz[KKSKS[c[[[[cizzuo͹ɷɦzuuuo­°ijuzijļ˹۹ٹuuiic[cozi[couzzzuoѹ[[ocKKSScccccccozzuooozz˼Ϧuzzz˼ĿǼuzuĹͰɢu[[[ccuzoccizzzzio¿SKcĦuc[[[[iiooiuzzzuioizocͼdzzzzzuooª¼Ŀouuķٹճ¢i[K[ozoiuucKu[Kczļooic[SouzuzuuzoziuzªĦzuziz°¼¿ǿuu­¿ǷٹicuzuuzzzoSSozccizuiiuioczzzzziuªǪzzzzuuuuzdzɷ¿¼˷ͼ‰zu[BBKS[SBKKcui[ioooicozzoouijzzuoouİͼ¿ǿǼ[ciԼǷzicB1Sic[[[[ioiuzzuiiououi˰zoo˹¼Ǽҿ¿ǼϿ¹[couižiKBioicozuoiooccoooķ·zu˿¹Ŀĭziz¿ļǼ˹ͼļocuuc9տzoiccoouo[[iiouoǼzuǿ³uSc°˿ɼǼ¹չ¼ǿ¿¿iSSK[ɹĿi[ciuioic[czo[Ƿɿ¼¼uuczϹǍzĿ°Կ¿¿ǿ¼İ˷ǹiiioiic[izoioĿ¦ǼĿzoouiuշoczuĿ˭ǹ·¿ɿoSScoiciuzzzuzuocKĹĪzǼ­[ciucĹɞc˳ͿɹiSK[ouocii[czzzuzococoz·ouϷ¹o[[˹ǒoĉ˼ԹǼɼuS[uzi[SK[uĿizuoiS[[uǿļz¼˿ɰo˄oz׭ɭ¼¿ɿuzoioozzzoi[ccuz¹uzzzcccKĪ[S[cuǼijķǼ˿˼o[u˳ɿ·ož¹ǭĪc[[SozzooiuuuoioouuzzuuicKSB(ĭzKcoiiozǿ¹¦¼ǼǿĹ͢[[˹ǹziǿɿ¿ĿҷdzzcSSKSuou[[izoc[iiuucuuouiS9˷zcciocciuĹϼļɿ·oĢzu³ɚzĦ¿ɿǿuic[SBcc[oczzicS[oucouo[iB9·’ouiuziiuizĦ·ĭϹǭתiuĿ˹ļϹ¿zuicSSKuSKozuouiSoc[ouSK[c1 iuĒuzziouiooɳǷĿ˷uijɼuc[[[ccSKScuˉuĢ·ǭzcSScccB[ozccuuoizccuiouzSuzSooiSڼiciooiuuooɭϿBizķzicSKSS[KKSKKKBBBK[o˭ϿĹ¹˿iSK[[czuo[[Scooc[czuuoouoiuoS9ozc ɢocoiiooiii˹ĪKKcoizcSSSSS[ic[KKBKSSSBBBKKBBBBKKS[cϷϿ¿¼ǿ°oS[ciicSiui[czzi[[cc[czic[zz9 ǚuiouicoio¢co˰BKcoɢoɭuiB999119KKKKKBBKSKKBKBBBK9BBKBBBBczu˳ɷѷ¼¹ǹo[zuoocS[Īuuzzi[cuoS[c[[ccoui[ucĖuBB9zuuiouiiuz¦[Sico͹ԹKBcioҿǒcSBBBB1(1KKSK991((99B9K9911BKKKBBBBScooͿɷͿɿͿ³ɼuooucSoͰzuoouzoSSoo[Sc[KKK[uucicc˚KK999ooouuiiuuu˳zi[SuҢcSiciҍ[KBBB99119SSSB911((((19991(9BKKKBKBBK[cozu·˿ϼ·­°oouoKo¹ziuzzoScu[KKSKB99[uuuo[KKcBB1 ([iuoouoo˭ucBBoԼoSuooҍ9KKKKB111BBSSK199111(11911(((99KS[[[ScoiiuuS[iuzɿϹ¼ɿuuļuziiizzuuzoK9BKB99Soucoc99K9( (1[cuoouuuoɖuuicKKuz–cuzii[[i91B99BK999KKKKB919119111B991119K[[iciccoc[cc[iSSoɹѰ¹³ouoioiioi[zouucSB9K99SuoocS9BczK( ((11cSiuoiѰcKuuc[Szuou·zuzuciuoz[SKB99B99BK919KKK91(11(1199BB9B[czuuiiS[KSSSS[o˿Ǫ¿ķǿǼzuuzzzozzĹB[izcioKSc[SS9BKizzc[[[o9  ((͢iScoczɢzc[iziouozioܿzc[cSKS1uKKB99BB99SS919BB9(99119199BBKuc[cKKKccoouǹфĹǰķɹĿzzouiiouzɿcozzi[cSKSii[iccuzoccui1 (( (1(Ѧu[iiǰociooouuzҳSSKSKKBBKBBB1BB919KK99BB1(991119BB9Boc[[ic[czzĉǹ˹¹dz·uzi[[[cooiu·zoiuzoc[SSKcoiozuoi[[[io[B1(((( (((Էziѭzc[zzozչ[Sc[KKSSoޚcKSKB91(1BSSBBB((999999BB1oɞiuociicuzuĹ¢ǿ­ѳouiKBKB[ciio¼uiiizuocSKSSS[ioiSKS[[SK9 (((  ԿԼzu·uzѹuc[[[SBBiύcccKKKB19B[cKB1B919B9BKSzϳuKuoiouzouzizĹdzɷ۷cKKSK[[[coz¼ocizooo[KS[BSic[KSSSKB( (((  zɭԷ԰ļc[[[cS1BicڒzzzuuuS91Kc[BBKB9BKBSz˹i[uuozzzu[[zoiz¹°ǭ˷ǿcKioSKKBK[Sczcuzzo[SS[SS[[K99BKKB( (   ((zzož¢iczҳɖo[BBKS9KizKzooS99S[K9BBBBSidzicizzuozzoz–ii¼ijĢؿѿi[KKSucSSKBKSuuuzzc[[SS[cSBBBKKKK9 (( (911oczĿϹSouͼSSKBBBKKizzz˰Ŀzuuzi[cSBKSSSKBSczuuiuiizuuɹҼɼϿuSKKSKoz[KKKcozuzzzuuzocS[[ii[KBKK9BSK1 (( ((111couiu­zĭ³z[z͹cBBBBBKScz׿ɉiiooSB[i[[S[ioozocoucizuuou¼׼˷SKSKKiicoouooouzzzccSouiSKKSSSKBKK(((((((9uiioi[װǢziuoz¢[KBBSBBS[uϼԖڷi[[zicic[SKoz[K[zuoKizzozi¿ѿ׿ɷo[SK[izuuzzuzucccouuoccc[oiSKKKKKSKSK1  ((( BiicccBբĪuizoiozĹzSBKSicKBciտļͿo[Succ[[SczcSS[uoo[iiSoozzcozuճǼҿϹļcBK[czzzouuzouzui[S[ccu[KKKKKKS[KB   (((((9ucicSuzKz͢zo[[oҿBBKSzzzɹˢziiiuocSSSuc[[[icKiuuuu[uԚoϿѿչ·iBSuozuzuuzocSSccco[S[SKSKKSS1  (1111[uzciuzzS˒uuiciuzѰz119Kiɪ[ziou[icciSSSoKKScuzoouou[zuzͭɿǹzտi[ozzzzicoouzzucSK[oi[[c[SS[SSSKB(  (9KBBzzuoڢzouc[o˷K999cioļicSiucSKcizBBK[oucoccuozuzociou¹ɿĿ˿׿zzuo[[iiooicSK[oiS[cS[[KS[K1   19BKzoiuijciiouͳ[1(9[uǢڰϳɢuǰuc[[czKKSizoi[[izcozuuu˼ǿĹķչǼuizzici[cci[S[SKSizcSSKKSSK[S9(( (((9KBS¹uou¿عciuuz¢S19B[čɪui[izKccuuzooioooiuuou[oozĹļĹ¹dzļzzzuiccic[KKKK[ouuou[SKKBS[cc[1((1( (19K[iodzu¹ԹoĿc[uuuͰSBKiۼ˳izuozBcoouzo[cuccuouiouǹouz·Ĺ·˿չc[ooic[icBBS[[cuuucS[SKKK[[[S9( 111 (1K[zϪzǦzijcͿocz˷zzĭzķzzoozSKoouzi[zoScoSoiou[uuuziǹ¹Ĺ˼oozzzzoiiic[BSoui[iocBBSKBKSc[KB1(11(( ((KcoϪzooǦzǼĪcoɹoiž[·ooozoBiuu[Siiui[coiizuKooioouizuuzѷ·ijǷzuzoicicouoccccKKczzicccK99KKKBKSSB9991(( (9SĖuuuziiϹz–˹[izͿo11KϷS[cocuiuc[izc[uuoiSocizoooouzշĪɿɷzu·uzuooiiicioiccccKKiuuoccSKBBSSKKKB9911((( 1BSuɰz[S[ozǭ˿խczzooļBKK(KɿKKczoozizooouzocou[ozzciuuucuռzz¿¿Ϳu۪ziioiiiiicciic[[zzuocSSKSKBS[cS199((1( (9KzuScѼu·ٷuzu’uzǪz91[[[Soǿ˼cSiccou[ucoozziiiicooizuioii[ciu˞ucccuzzzɿٞzzooooouooioic[iozo[[SKKBBSccS9(11 ( 1Kzuiǭzzǖ¢uķĢķ[91BuocuļĿٿ˷ǰuzozicuuzuozocozuiiuicS[ouuչoic[cc[S[Sciiiiozzωzuuzuoooo[[iuzouoci[KKKK[i[9 111(BϪϭǷİcSc³ͿϷ¿uiSBz¼uozzuooozic[uzzuuuzoĢuiiccc[SSS[c[[ciuooѰozzzcciocczzuozuiii[KKS[[SB ( ((((Sǿzu׷˳ٿǹiKcĿuuocB 99uczuiuzouuĚzououzzocɪoiic[[[[[[ciicciuoizuSouiuzzuzuuouozouuoiic[KKKcc[B1 ((1( (9Szzocczķۭ׹ɰ[czuoSB1BBB[K9Souuoocczozouiuzuczozuzzuѷuiic[ciciioooioouuuuo[[cc[couooizuoiiooccSKKKKcS1 ((( KzuuuuzcS[uzǰ͒¢ҪzciuiK9SK9BciccuiBzͭuiuiSSii[oĿcuuuzzcci˳uccciicouzzzuozzzoi[[[[S[[iouiozzuiizoc[BKKSKB1  9SzzoiooSKczǿ˪šĭټuicioc[BKzoiiuzuoiiiu[cϚzic[cuuoouzzzu[SKcii˰uiiiiiozuzuiɹiB[SSSS[ciiizuzzuuzuSSKKSS9 ( 9ououzzoocKKSoǿ˼ռzĿڹuouzzuiiiiuzzuzuuocS[oziz¦oiiccoozuziouzuoiooizuooioz·ziiiioouuocoњBKSSKSS[cc[zziuouz[SKKK9((11BzzoouoocKBKiz¼Ąͼɰo乭Ŀzccuuzi[[i[SKSiuco[uooKcKizuuizouzcioiuczoiiuzuic˄[cc[SKBS[izoiuzo[SKSK9119cɦzuuoiozzzzuzooi[S[izoijҭͿտɹҼSKuoozcSSSKSBK[c[o99c[cKScouic[zzuz¿ocouzoooiޭuiSKBKouiiiuouuuuzc[[KKB99K¢zzzioziizuuzoiic[[ozooioǷĿܳļoKSSizzc[cSBKKKK[cuuuoB(9izuizzzuuuͳuzSSoozuoo¿zSuzccļ˪oSBSzzuui[couziicccKB91[˰uizzzzioouuoiioccciccuuc[oǹɪɼozzKBBS[[SccSBKSSSiuuzzSBScoz[uioouiuozzczziiou–iKBo·ѰuS[zzoioc[[ciizzc[[SK9BɀSozzzzuuuouoiiioiciS[[icSio˿žؿļoz[KBBBKS[[Scciicic[cuouǷzi[uouiiiiouooouozҭoKSz¿˚ocou[SccozzuioooccooczS9KSB9͒iiuuzuuzuccooc[c[ii[SKSKScoo˿͹ĿϿτzoou[KBBSBKizc[[SSB9K[zǼzzuiuzoooc[[u[ziɢuo[zǹչocǿ͍zziii[BS[[iiizzuc[SSuuozzcBKKBSϒuocouuzzzuiiccccc[SKS[[ScioiziѿԳ˭ouuzuozuiSBKBcSB9BBBBB9Suiuzuuioozouc[ozzucozuuoii·uocczuķciuooooo[SKKS[[[SSioiui[ciozo[SSciSKSSzciccciuuuoiccccc[[[[[cc[SKScc[ioo¹ٿĭͿǢzziioiioziBSoi[B19BB9BKB9SǹocKSoiouS[uzouoozzuiouuǖouziǿzSS[c[ci[[KBSSSSSSSK[oocciicic[[SSKKS[[KBoSSccc[Siiiicc[[cKSSicccSBKK99B9BoocoѼɷdzoouoouo[cuo[uoK911B999BKBKɉSuo[ocuKKcuuzuzzcoui[uuuuzozziķiuz[[ǿ­z[[SS[iu[BKKKS[KBK[[Sizui[SSSSS[SSSBBS[B(1KSScc[c[[[KKSSSKS[c[B9119BB911coccoҹǼdzǼǰzouuoiuziiuozoK911KKK91S[Sԭ[[zoiuicĖiuiiouozuiuuzuuoiouo[iuzoicɼicc[ciou[B9BBS[BBBScuuiiSSKKBSSSS[SKKKB9(o9S[KS[SSBBKKKSSKBKBB9199999919Szo[ciiѳǦĿ­zzozcizzzo[iuSBSczzoccuuĉiioiiiui­zi[uiozzoiz¿[[[zuouzouodzuoiccoi[c[KBBBKSKSS[oz[B9BKKKS[[SKSKKBKScSc9ScKKSKKKS[cSKB91991199(19999SuuS[iiiѰҼĿļ³uccizzzooouczuoz˖oiooouozzooo[couozzcouiuuu[ioizoĹ˒iioooiooSSSKKBBK[[ou[SKKK99BKKBSSSS[[Siooi9KKBK[S[[[[[K99111(19BB99999Kuzccouuz˖zǼĹɼcKSzuzuiouo[SɹcciuuzozziooiSSczuuociocouocSzzzcuҳuiiozzoic[SKSKKS[[cc[K9B9BBBB99Sciiii[KcoouuzBBBBSiic[SB999BB991(9BBKBB[zz[oouzϼķĿ˷Ŀɼo[[zuciicc[SKiĞuuuoz¼z[SS[ziioiiccoiczzuuB[[ciuiicciuzo[[[[[[[[KSSSKBBBBBBKBK[oooi[KB11BKB9BSioK[[SSSSSKBBBBBBKB99BBKSSSKzͰɹǼ³ļzic[[KKS[zuzļzcKczuzuiozuuuuziuozzioǦi[SKSKK[cioo[[c[[ciicKKBBBBBBKK9BKoz[KB9( 1(119B[Sou[SKKKS[SKKKKBBSKKKSS[ioSK[uǪ˳·ĭǷc[KKBK[coɼo9cuzouuzzuoczzzzzoiccc[[SS[cc[[c[SSSKKBBKB9BcozuS11(1(1(9199BBKSSKBKKKSSSSKKKKBS[[cc[uiKKSK[iǿĹ˦ǿɰ[KKBB[iuzuzzzz¼Ŀu1[zϪzzuiouououuiSizzoSSKczzoi[SKSKSSKKSKKSSiuzziSB919999919991KBKS[co9BKKKKSKKKKKSiouiSuiS[[SSSSiz˼·ĭĿѹzuKB9SiczziooouĪK[oiצiiuuoiouzuuuzio[SoucKKBKKKBSizzu[KSKB99991111B999BKKKS[S99BBKBKBKKK[ii[[ziSS[[[[[SKcozz͹ĹĿ°˰ĹǼiiiBK[cczoiouuzǹcS[oiioiѢuciuuioczozzϼcozzzoSKBKB[zzoc[[K(9B9B9919111119BKSSSKKciz999BBBBBKK[[c[S[[[S[[[SKBB[cͪoǷɹϹļ¦zɰoozKKc[czoS[cuĹzKK[Sco¹iioouiozuo[ozzicoĿļiuuiizS9SczuS[[B91(9BBB1119111BBKSS[[KBBiiSS19BBBBKS[[SSccou[[KS[[[SKKKBo˿uozij³°zzozzKB[SSi[coĭiSSS[[ci¹uouozuooozuiozSİİicczooiSBKB (1BKB11199911K[[Si[SKKKi[KSuiKBBBBBK[ic[zSKc[c[[[SSSS[SKzuouuѳѿ¦Ğ¿uouzzziB[[[z˿oc[ccc[[iǼuiozo[iɖBioKǹ˪ǚzzoSSB1( ( 1BSK1( (9999Kcc[i[SBBScK[S[cc9BBBBSiuoziKS[[[c[[SK[cc[SuizuzidzϰҹϹǿoozzuzoS9Sİ˿ĭziuucSS[u˷ĹzzcizǦuϹĿ·Ě۰uzKK91((((9[S9(  1919BKS[[ccSBBKSBKSKcucBSSBScuo[S[ci[ucc[B[c[[SzzzuoiϳͪͼuuzuǷuuzuzcSKSioz°uuzuuuuuicz͖Թɳ˳ɉoK191111B[SB(11(1B91Bco[K[c[KBK91SSKSouS[[SScuc[Sccizicc[[SBK[[coǰzzo˖–ɳzu¢iczSKS[ci˿uoozuziiouoociiªˍɢٳS91BK999KSK11B99BB1ccK[[KKSB1KKKKczo[c[BiiKSKKSSSzc[SSKBBB[ozouuzװĞz׹uuzzziSS[[iuucSzcuzuooiioc[ooccuճžuiBoԳzu[11BSBBKKSS919BBBB1ɿccc[B[S1BSKBSuzozocuKSSSKS[SzuKKKSSKKozizuoiҢܷķzϳziozzii[SScuĿiiiSioouiu[[ozooˢɚ˦˪oSSSSio[cu·ϳύi[o919BBBKSSS999BKKBBĢiiS1S[9So[KKciSS[[SSK[SoS[[[[KBzɼooooݰɢǦcouocS[iz­ccuc[oozicouooouzǿݳǰ[SSuzocSiiccuܹu[[K999BBKKKSBBBKSSBcSSB1K[K[i[KKKKKS[[S[[[[cuucSSSSǷuoշǰǭzozǿ˷˷ķz[zzz[ScuSBK[ozicizoouzoozuoS¦ɀiKSui[oc[KBS[uzϿͿzuccz99BKKKBKKBBBBKK9ziKB1B[S[[SSS[[KSciccouiozoo[KS[iu¦չѰ¼ɷ͹ɳɰi[o[ouiocSBK[ozzuuoui[[uu[uzzzoǰuziuϳiz[ouuSKBKKBcczzooBBBKBBKSKSKBKKK9uK99SSK[[SKKSo[ciuzoozzucSSiiocĭĦչǿѼϿϞSKocci[[SSKK[iɳzuzocicuio[oǼɢzoScuoic[SSBio[SouciS99BKBBKBKKKSKKBSi[99S[SS[[SB9ķiuzouzzooĿĪتzɼİzBcouicKB[izz˷ϷuoziuioBSտziiS[ouucKcui[ooozooc[99B[KBKBBBBKBBSSz€(1[SSSSSS9Bzozɢ°ɳ¼ͦҷzɷحzoicK[uˢuѦooi[i˹ǚiozzzzzzocSiSB99SSBBKSBBBB9co[uĹi[uS91K[[Szuzķuuuѿ˹ѿͼժ˼ǭzczѹǰzozoi[ciooͿ[uɍoccuzzucSccšɍuĄuzziuzuuucucB[[KBB9BKKKSSKKK99uSSc[ª[SciozuuuzzzoccSSK[[[SBK[Ͱɪ͹ɿ¿эzizuuzķɼǒzzouocS[[ciͦiouİɼzĢziuoucSciS[iKizuz[KuBKKKKBKKKKKKKKB[iKKzoczռi[[ciiouzzzui[[[SSKS[[SB9B·˼dzϷ͞Ͽ˿zİɷԼzczzcSSS[SiԞzuuozɦ͹ɹuͷi(iԳzzucKcoc[cziuuiKͿ[BSKKKBBSS[[KKKKuoKBSuԿKBBS[[ioo„icc[[cc[[[ccKBBBKǞչĿ¼׿¼¢z·ijĹ˷zoc[c[SSSBSϚu·ѳiz¿coɭzzzzuSiuz[9zמ[9KB9BB1119SKKBScSBKcɰuiiBBKSS[[S˒[SS[[ccciicS99KKBϼ˒ɷǪ­İzzҿo[[[o[SKSS˭ĖoooĦ˖iͰ¿oK[o9[ݳB99BB991((99BB[uSKSuiuKBKKSSSSSSuKS[SS[ci[KBBBKKBǷɚļ˼ɳ˖zzij͹­iic[SciooڦҹǹҹĪi[[K9S̈́Ѧzչzzzco[cޚ9BSB9B9(19B1(KKSSo¹zzB9BK[ciKSBSuKKS[cc[KBBKKBKB׷˼ǰԼҪİ„˷iooizѪǷǢ˿ɭݼzzu[SSKKz[SԳuiۭuuzoouuiccKcĚuuSS9BB99B911BBKKuɰz(1KScuoBSKK[iSK[c[[S[S[SBKBuѹǼļѿǹ¼zİĹ˚uicuҢ[ˢԿuͳٿzoi[S[[cc[oiɦzu[Siտ[zi[i[[ҒSSKBB9B99i[B9Bz¢uiozԄ 1BScoiKSSSS[ooK[i[KSS[SSKSK˪ɹњuuɿĿɞzSSSoϖǰ³uzԭ[iiuuui[[z߭ocSKSBSccoɷǿoo[oɭziuuoSBՒSzocBKBBB9cuc[K9BKi[SSozuzتSBKKccSBKSKKSSozKKSKSS[KKKKKϰuͪĪoKSķzĚĢzi[uzۼu³ԹzuooizBKizzzuozҭuiii[KSS[Scoҷoc[uciS ڞcozi[u9SK99izKS[cS9BSic[KScuuzocԷuKSKci[KKKSK9BSooKKSKSSSKKKĚuuĦioijzͭ׹ziiĹ˿ɚzڪzi9Suªǹ׹Soui[KSSKBKcuuc[izoSc oئiizoSBcKB99icBScccSBB[cSBBKK[oĚiS[ci[KBS[i[K[oicKui[[SSļǦ¼ĢͼڳѪijzoS[ɭѭ͖u[couž͚KSoo[SKKBBBKKSS[ic[zuiiuouuucKBBڪiooiuc9[oc1(oiSB[icc[KBB[zucicio[[zoiuz[KKK[oiS[ccuciiSĿǰؼҳļ¼zٿİuiK[BͿo9[İɼڷoKK[cSKSKKKBKBBKcuuiiiz[iioo9cڪciizzSScocB[BSScc[[SKKK[zzuuozzocouocSio[[KS[SSSS[c[uSouocKĿļͰϪĚǿĿ¿uͦ­oiKz¼oͳɦٹĦzS[SS[[BKKKB9BBBSScoi[zc[ziizooKcצcocB9cрB9S[iic[SSKKSzoccicic[SSc[[oiiSBKSScicic[u9KzSKķذշĦǪͳĭ˞ĭcucɷzo¼Ϲ˷ۼoS[cSK[[BB9B99BBBKSSczS[uuiic[cuzK9Ϣ[iziKKoSScouzuc[SSKc[K[BKKSSKSS[cczozc[SB[iS9oi9S[K¹¼͹ϳĉͭǰzǢzǢuSo¼ԦĪuo˳׿ͿϹuzcK[c[SSSK99BBBKBBBBKKuKBK[iiooizzoBϞ[[ooizii¿ziiuzzu[BKSizB9SB9BSKKSSSSSiizuic[[KBBiiKzcSǼ޼ǼϚĭo((uͳcɞzz͹׭İKSuɳiSSozuuo[S[[[[[SKB99BBBBBKB9BoBBB[iouuzoiooScccc[zooªzljuzSKKSzB9K[[SicccSSKBK[zouoi[BB1uSSǼɹ¿ɭļ٦Ұzǹzķѹuooiic[ScccSBKSS[SSSSSBBB999BKKSK[uǖoSBizozoKcciz­K[[SczzziҖuozɀoSSKBu19Bouoioo[KKBBKSuoocccKBS͢cK[ªǷǪuĭ’zdzĦzoҦ٦zc[S[KSKBKKBKKB9BKBBKKKKKKBBB99BKKK[zɹcSucSBKSoc[BBSicczѪ[iuzouoz[[SSz[91ouoii[KBB99B[ouu[c[SBS–SK[z­ԹǹzĹzͷž¿Էͭ³ªªuziozzzcKBKKK99111999BB999BB9BBBBB9999BKSK[[zuuKBczuzSKK9KĹo[izozuuiKSSizSzzouiici[KB9iuiizoicSBB­KKĉS99KizSKSKKBB1119B9 ( ( 1[oc[šǼzoii[KB[ocKS[ѹzodz¿ͼB (19BSԖScǹ°ܹcSB91K[ozuii[SKSKK9(1BKBB999919SocS[c[iiiizz[[[iSSoScS[c199919BSoocSS11oziciuoczzouԚK911KozucBSSKB9(11999(11 9SKoɭ͢uocccSBocSSՍuiiizͿ¼ɦS 1( ( zǀ[u³ͼzK99Koo[[[SKKBKSB99S[K991(11( ozcS[cccozu[i[K9o[cB1111119K[ocS9((ououocSoۿzB11KSiioz[SSKB1(19B11(( 1KSڷoucoՍ[icouSSªoccczzijɦK(BBK91KuKiɿշϼSBczzSKB9SKKKB9ScSBB919( (B¼o[ccccouuzoSzu19uuB(( ( 1K[ccK19czouzi[czu͚cKKSczuKKooSSSB19BBK99(1( 9ɭzKKcKKݳiccccuzocccoouz¹ǹĹBKSSB[׹ǀS[dzؼ[i[K9B[SBBBSSB(19(191(cɿcciozuzcKouzS1(  1S[[[SKBBcuoozciuۼ[KB1coKBScSBKB9BBBKKK11(S߼cK9K[SSiճo[zzzi[[[uicozij¿ĿoccSoz͖uKϿĹzooSBBBKKBBS[9(11(((Kͳiuuouciozu[(   9[cS[[SKK[ozoccuoozĖz[BBBScBB9ioKSKKK99S9 1S¿dz[1(BSKKSSzհ[Siuuooi[[ccSS[iǹ¿ɼĿoiњici³˼˼i[SB9SiucKB9BKK9 ͭoo[[coozcc119(  S11Soui[[B9BKKScccizuuuɍuo919BB9BKKzcKKKKKK1[9ɳiB91K[KKS[c߼oic[[zucccccSScizouzĿĿ¹·ɹc[zҚ[ccİɭѪucuBBB191ScuǿϿico·u 1KzzSBicoucK9(1B99BSoouzuuuzuS(BKKB99BB[zSBKBBB1u˪ucuiSSSKKBKSK[iտzBBoocicii[Soouooz¿¿uSKװ[cui˼ϷSB1 1 ǿoiɹz[(KcoˍiiiK( (99B[cozi[uuuuoooB9SSKKSSKSSSoBB9BK9z㳚zo[SuiB[[cS99SSSSuİzcB[iͷiioiooc[icciozz¼ĹĿǼ͉[Bճciu[[oSɰɹ[(  ¹izi911[ժ[cc[919BBB[cciuuc[ozooucooiSK[[cccciioiSKuK9B91ljzSS9Buр9SScK1BS[[c¹uiiScScioooccciiicioz¹Ŀ¿ɍoK׹ocSKB9ķͿu((( °ooǦzK9Kc͹Ϳi[iiicicKK[c[SizuiScioocSuKccioiuooouzzcKB[iSK9KޒuKKKKcτBSSSKBSSKcķziz͒Scioccic[ccciciuuz¹¼۷zoczԳicSSSSϷ·–K11 Kٳz[zĦoSB[iɼϼzicouiuzzuzcSBizzoSBSoiKBSci[c[ciiioiocSBBKSScio[(oiKBKBKҪ[[KKKK[c[iiozɉBccc[Sic[[[c[[coouuļ¹׭ouoiԳc[cSS[u˭Լ¦c9B(iѹuuB³zc91[cĿuouuuiiuzc[Soo[S[[S((iiB9B19BSSKKBBBBBBBBBS[S[ىi[KBSSKu[[SScozS[oiKzo9[ccc[[[S[[S[cccioioעSuoc׳cicSSSؼǷɦiBB iɿzczoici[Ƿ[ucii[Souui[[ozioo[(  oK119(1919911BKBKBBBB91KcKKBKSSܒic[cooz[[c[1c9[c[KKS[[[[[cccciiciuɿۢouic٪cocSKcǀ³ǷĪzSB(ijuo[Ͱ[oicKKSSczoiiz[cc9  [9111199(19BBBBBBKB9BB(S[iBKS[Scccciiiiiic1ܦSKSccSSS[[[[[cciicccciozɷݚuciՉco[KKuۖԹɦu9cϿĖiozSiĒcuou9BKKcuzzuoicziB9 B(((11BB9919KKKKBBBB1[1cS9BK[[ozS[[ͷͷoizzoK҉[S[c[SSSS[[S[c[cic[c[coz¹iuicc[o׀ciK9Szϼɪiiuҹݹoo[cizcoo[iu9KBSciiccci[( 1  1((999BBB919BKKBB9BBBމKcuKBB[cizuݹiSiڿzcczuoiҼoS[cicciSS[[S[[[[i[[cciooouԼcci[Sc[[[[KB[ϳҿ˳SҼ˪ocouiiioo[cϰSBK[cciiSSczc1  (((9KSKSKBB91B9BBB99c쿢[iuKS9KScuooԢiڳzzccuuuziܚc[c[SS[c[[ci[[S[SSS[[ciiccouϿccoui[SKKcSBSo٪ϼĦoK˼Ͽ³uuo[S[zcScuucczo9S[cccicccS9(   ((1BKSSKBK9919BBKB9o牞9zBS19Kcuui‰ўzo[iحoc[[[SK[c[[ciiccii[[[ccccccioozɼziiiuoc[SooBKi[izئĿĭ[oǷucooSK[ii[Scu[uuicc[ioS9( (( ( ( 1BKKBB911119BKB1[z1z(B19Soo[o°߹ucioDŽi[SSSS[ci[[ciicccccScooi[[iiicizѿ㰄zoiouocS[ԿuKBcBccoխϿoiϷzuzzzc[uzuiooucB1  ((19B9((11919B9999911BB91uKi911BSouiiіoSuuo۳ucSSKS[iciS[[c[cccccS[cic[iooiciou͹¿ioiioocSiѿSBɖcSK[zѪϢoĪzªzozzu[B1(  (99B( 1999BB9B9B919BB9Sciuo[[9BB[iiiڹzuiSuܢi[[SKSoc[cS[[cc[c[cccc[iiiooiiioouuu˹ccui[iicczzzKSѹo[S[ϳ„³˼¦z˖iK1(  (((((19BBKSBBBBK991ociuo[ocBKKciciĹoiuBzךi[SS[[ic[cSSSc[[[[[cc[[cccioouioiiioo˼[uzuuuicuuzKSǹzoѼদuz׼uKB9( ( (1(9BBKS[SKBBKB9SԒBcciiciz[9KS[[izuuuS͒ocKScc[cc[[[[c[[[[[[[[[i[c[ccoioooiiuٚ[zzճɄ[S[ǿǼ³Ԛ¹Ϸzzz˦ϰzcB91(((((1 i(119199BKS[SK99B1(Ϫ[Sii[[[SccKSSSczuzcǀoiSS[[c[[c[[ccc[c[c[[[cc[[[ciiiiiiiĢzoѦђSSKĿϹ۹ɹĪzuuzuouu˼¦oK9 199Bc1119B919BBKSB19B(1҄Kccc[SSSciKKSSz³uuzݷ[zzzi[[SS[[[[[cc[[[[[[cciic[c[[cciioզ‰cķі[[[[˹ɍi[uuzzuooouĦoBKB  BuiBB9BB9199BKKK999 uտiK[[SKKSKSi[K[u¼uu[uuuoiicS[[[c[SS[[c[ciiic[[cccicciiziiڿuSiɳҍcccKuǼļԭiB9Souzuzuzioiu¼Ǫz[[B111(  u999B9B999BBKKSS9199ɍ[KSSKBKKSKc[[o·˹ߍSoouucccc[[[ccSS[[c[ciiiicccc[iicciooco۹ooocoǼҒccS9cĿ¿¼ؿ[ioccoİzucccu³ͼcKKBcK19KBB1 (ScS919999B9BSSSB9SozcSKSS[KBKKKiciu˭zc׭uioocSci[[[[[SScci[S[[ccioiiciicciuuciiuzš[SļҞKS[BSļǿˍ99ziiuĿuzoiuϿziB[coi[91KBKKBBSiKcS199BBB1KuǦoiSS[KSKKKSSiiouªՖ[Ǟzccoi[[[[cc[[[cccSSS[[ccioicciciiooicoiooui[oתiǿآKSSBSǿļķuKS[KKSozžzuuǹzi[SSiz[999KK[uzcuu19BBB[c[[SSKKKKSccozĹذioҼo[icSS[[[[SSccc[[SS[ciiciocccciicciiiiiouoc[czɼ¼צiicBuǿķšuccciiK9BB9Siǭzoiozuuzz¹iiuuiioB((19[uiz(19B[[[i[c[SSKKKBccizͼz͞cհoi[KB[[[[[[ccc[[[[[iiccccccciooiciiic[coiioآB¼׷icc[¹ķuSSKScSB999BSSz¿zoouuouĿzuzuiušK1 oc[u(19[zzzu[SzzccSKKKB99iiiɹzz׭͚o[BBS[[[[[cc[[[c[[ciic[cioioicciicc[cioiuuۍB¼ټSicoĿĿucScSBBB9199SSKoicuͳǹzouzzi[iB Kooz(1Kziuiuozu[[zـc[SBKKKBBcizɳˀuǭuuuKBB9K[[cii[Scc[[cicccuoi[cccccc[[[iuczc[uў¹ڹS[[ozɿĪcKSScSKK1 19BccSoǹĹzicozϷuzzuu·ijiSu[ci(9zouzzoicicKSiݞBcSKKKBBBczǪْ[SoicuzS9BSSSccS[[ii[[[[ccuzocciccicc[[[ouocSScio弭˿o[c[uռ˿[KKBKKKKS919BKccoušziciz˹zzzui[zoc[BizSi1iouoc[[KKKKzݷ9[SSSKBBKuǞ[SzuiiuKK[[[[SKS[[i[[cciuuic[ciiiooc[[iiouSKS[Kcǿu[iSouعɳcKBBBBKKK[[[BBSSi¿zczoouɳcuS i˚uuiSKBSooi[oziooiicSBKB9[ѼiKKKBB9B[uѷcBoccooiuoSS[[S[[[[SS[[ccioiSKS[[iicci[cuuizocSSBSuļicucKiozؿ˿iKKBBBBBBBK[cicc[oǿoSSiİzouz[‰uzc9( 1SioKciiozc[iSKKK9KɷoSKKKKBBc¼19‰zSK[[KKSKK[SK[[ccSBK[ccuo[KKSSScc[[cciuzi[KKKcoouɿѼc[SBizuռɦzSB99BBBBBBKSKcoiuuouozǹuzouzzu(uicS1( Boc(ciiioziccSKSScɦ[[KKKKSSi9uzoozz[B[[KBKBS[KB[[[cSKSK[ccS[SSSccccc[ccc[zz[SSSScc[iouҳ[c1BuuiijɰuSKBB99999BBKSKSouioouҷ¹zuuS[i[9(zc(9zi91(9cS o[ouzzzzSKco[SBBKS[cu͢Kocc[ci[S[SSKBSSKS[[[[KKSKcSKS[[c[cii[c[cS[iiciozuSKKBK[S[iuoSiѦ[zo(ScͿǷiicSKB9B9KKBKBKKcuzuzzociozķdzzǦo911(iS99[K(( 91 uozzouuuiKB9K[S[uzioS[SccSSSKK99S[[[[S[cKKS[[[SSS[ciicc[S[[[ooc[cciicS[[[cccic[zͿ˖B(iu[oҷ[[cS[[KBKKSKBBBKScuico­˭ĭu9S°ucB9cozS1 (( ozouo[Īc[[S[czSSS[i[Sozۭ[ܒoKK[[SBBSKBBB[cccSSSSBK[[S[S[[Sccc[[c[Scooc[[cic[iiiccoouic[¹’K(Bi[iɷzSKKKB[cSKK[[[cSBK[iuz°o[S [¦iB1SizKB(((uoiiK[iKKS[[cĦcc[cc[oiizԄiKSKKKKBKSKKKS[c[SKKSKSccSSSSS[cc[[[c[[oocccccoc[[ii[ciiuozS11Kc¿Ħ[(1uiccoSKBKSKKSSS[S[icSBKcoiciczuͳİuzBBiz[ĹiuK1Kc[S[91Bo[couccSKS[Sioiouucuč9BuuɀcKKBBBK9BKKKKKSc[SKKKKS[c[[[[[[[[[[[ccuu[cioiiocc[[[S[SKiouK((11Boɹˢc11czc[[oSKS[i[KBKSSSBBKKSSKS[BBScoooɷͭ·ļɦuuizo[SuiٚuSzc99Scu[S[(1iSSiicccSKKSScz[ooK[zoۼcc[BKK99BB9KSKBKS[SSSS[S[SSS[c[c[c[[izocciooo[S[KBKcoc[uoocS[B199BSɷͰo99[zoi[ioBBSicSS[[[SBKSS[[[[SB1Sc[iuuԳljoɍcccuoS9Bcфz[zcKB9BzKBB  oSic[icccSKSSScicKozciճzic[KKSBKBBBKKBBBKKSSS[SS[SSSS[SS[cicocoic[icSSS91BK[[ccSK9S[cK1BBcoͿ‰K99ziooiuuSBKciSKSccSB9ioc[SKB9KoocuzuuScuoczzĀcɍuSiou’[[BKozczoc[1(Bi[1999S[iucccoccc[KKBKcoi’KSuzooɞzicKKKKBBBKKBKKBB9BK[[SS[[S[S[cS[ioiczzcuui[[[[SB999S[S99111B[i[iou€KBBocccziSKSSS9BSicKBKizic[KBBK[uiuuiuiSKSB19cciioɭ͢[i[iKci[iciiizc1(1BB1(Boouiccccci[iic[KBKK[czuS[u[couǰoc[KBBBBBBKBKKKBBKKKSKKSS[[S[ci[uzuiiiioic[[[[[KKKSzo9(11((1[ķoci¿uKBBuoc[[ucKSKSS[ScicSKK[[c[SB99BS[uuuiSSK91BSccSS[cչ쳪o[ui[9zɞo[ccSSzz[11(BK( BSSBici[ccccioiocSSKKK[[o[SzozcKcioicKKBB9BBBBKSKB9BKSKBKKKSSSSS[iozuoouoioocccSSSKKK[[9KB9B[i͚o[ciouǼuKSKocSiiKKSBBKKSi[9B[[c[KBB91BKScoziic911(cooKBSBz޷㳼oSBiuB i͉ooi[BBooiKB1BK( ( cciicciiioooi[KSSKBS[ocǰ¹ccSKSBuǪo[ccKBKBBKSKBBKKBBKKKKBKBKSKK[[c[[cciuzuzuiiccc[[SBB[uziuzouzǭiS[[ioozɉ9[Socizi[S91[ocKB19BccK9BBB19KSSiooooc[SKB1(K[zuucKS[B˞ɼiuzc9BآSoucSB[ozi9BS( (( cccccioiciii[[[SSSKS[cozo[c[[[S˭uiciccKB9BSSKBKKKBB99BKKKKKKK[cccSBKScozouicic[[SSuzucoozocicSSiiozzzԭSKSuiu[BKu91BBSK11BB91K[cciiiuz[KKB91KuicizooKSKScϳzB(cKooouSKoB99(1BBK1occccccSKKKKS[c[SKKKK[i­zoioo[[Ԫzooocc[SKBK[K99KKKBKB9KKKBBBK[cc[[[SS[couuzi[c[[[[­u[KKKSSSScouiS[uiuziouuKSoioǢc999911BB1K[Scc[[czSBBB1Kuzi[czzzSSS[cu͢zK11cKSozioSKizocS9((BBKKBucc[cKKK9BB9BK[[[KSKS[iu¢icouo[ziicioioc[K9SSBBBKKB9BBKSKSKKK[c[[KSicc[iooozuc[S[KooccB9BKKSKKuoi[coiziii[uKcuuoBcټi99B91919K[c[SK9BSKKKKBizi[zc[[Sciڄ1K[(žoScoSB9BKooSK9 111 Bucc[K9999BKKSKS[[BBB[ii۹zc[oo[[ժoc[coocc[KKSSBBBKBBBBBKKKBKKKSiiSSSSc[i[oiiioicc[[SuSBoi[KKKKBcouzcK[cizziicccuKcuoiSˉBBBBBBBBScccSB99BBuzK99BiuuuoSzzSK[Scuoi9oz[ڪiccuzcBBBocKS9(99( [iccSBKKKKSKKSKKB[SSciic[ɰiSKSSKĄ[[SSii[SKBK[KB9BKKBBKKBBKSSSS[[SKS[cc[ouzi[ScuocicSS[i[K[z[SKBucoiKK[[czuoc[[SKoK9iui׷[KKSSizuc[iiSB9B[oSouB1BSuozzuc[S[S[ozoͳҿB(KKSicoizocK[cB1 (B[K((ic[[[SSSS[cc[[[coo[SSKSK[occS[[uži[[SS[[KBBBSSBKBKKBBKKSKKS[[KS[KKS[cicSczuooic[[[c[[SocKKK[uic[Scc[SKSSKcuoi[SKSccoSu׳ociuocK(91c99SouzuioiK[[[iuzzǿѷu[9„S[cccciSS[B(19Sc[SoccicBBKS[[ccc[ciSKB99BBKouzoiiuzzcSSSSSSKBBBKK9BKSKBKKKSSKKSKSKSBK[ccio[izo[ciii[[coSKKBBKBK[ccciu[[KBBSBBco[cc[BSoiKc˿cKSiii͚ҿ[1119Ė[cuzuzzo[zKScScuzɰتzڰouzooi[icc[K99KK9Suuoioii[KBB99KSKKK9199919BBiu[cuiuzccKKBKBB9BKKKSBKBBBBBBKK[SSSKKKKKSiicoo[uoouio[ScSiuu[S[SB111BSccoiKBBBBK9K[c[[c[SSo[KɒzcS[iic–ϞB(1BzzzɒizzzouzzccuuSSiuzԷߚ[تu[oucKSzKcS1(111(9S1iioiciocKKKKKBKBB999111999[ouiSBKoScziSSBBBBB9BKB99B9B9BBBKKKKKBK[SKKSS[ciiiiiuccooouocc[cuoi[SiiSKK99KSSuoKKSKBB1KiocccSB[i[iKui[cciu€9(1oczucoiuuicBKcccǼz (歰[czcSSu[cK(  ouc[coi[ScicSSSKK99119BKKS[SKBBBSS[zi[SKBBBKKBBK9(9KKB999BSSBKKBBKKKK[[ccocccu[[cioooiciiouiucSccccSBKKKSzuiSBKKKB1Koi[ccKBS[[uBKio[ccoѹ91(BoS[zuiocouo[KK[c¹11( cݖiiiuccicSK( (( Suiicouoiiuuoc[[SS99BBBKKBKKBB9BK9Sc[c[SK99BBKKKK999KSB9BKKKSK99KKBKKSS[[S[iccoo[[cciooi[iciiioccicc[SK99Kii[K91BBB9[ui[[cKK[Sczz[KSci[[iuzoocoͿ„1 (BozuiBziuu[iocKKKKKiҭc119͖zzzKSioc[ (((1SĹiozzzuiozzoc[SKB9BKKKKBS[KBBBB9B[[KB9BBBBBBB999BS[K99KKKBBBKSKBBBKS[ozicicczziii[[[ooc[ccSK[ccci[[[[SBKczccBBB[SKBcz[SScSSc[ioc[SSii[cozzic[[SS[izķB(9ciocBooo[i[KB19BKSzc (cԼii9SiciK   Bǚiuzuouzic[KB99BKB1KicSKKBBSKB[iİ[S[KKK9999BBKKKKKSSS999KKKKKKKKKBKBKS[uzocccozoi[KS[io[Sc[99KS[ccc[[[[[[izociSSSSB9Kou[[SiKBK[ocS[KSoiiuuoc[c[KSKcKBiczo1oouSSzi[ozS19919KSSu91SԪcoSSo[1(1(( i9ouzouuicKB999B91Ki[BBSSKSSKKBuiKB9BBBBBBBKBBBBBKSK99KBSKBBSSKKKKKKKK[ouui[[oiS[SK[iiSKSKKKS[coiccc[[ccczoiocic[K9[uc[[[[B9BicBKKSczzocSSSKKKi[cBoSBBiziz[cuiioB19999BK[ci[Koύzczuico9 1K91(z[9uuuuzzuzuooiKB9B99B9KiSKKKSBKSK1ozuoK9999BBBB9BS[SKBKSKB99BKSKBBSSKBBB9KKKciouiS[z[SBKKB[i[KKS[[SSScuooccSS[[oucccoc[KBcc[[SKBBBKcSSSSSouc[SSSK9BSiiccSKBKKzzzoiizziuiB(9BBKKK[iocz(Ǟ͒Si[zciociK ( ((9BKzoco9zzzzozuoooicBB9B9999K[KKKSSKSSSSzuSB999BKBBB99Si[KSSSKKKB1BK99BKKKBBBBBBKS[ouo[cuBBBBBK[[BBK[cSSScouiioc[SSczzucic[ccSSKSSSKB11B[SSKSKS[S[SB999K[iicziSKSKBBiiiiououiB919BKKS[ioociBԼScoSi[S[c[9 1(( 1KcccuuuzooozzuooicS99B91199BSKKKKKS[BczSKB9KBKSKSBBBBSKSSKBKBB99BBBKKB9BKBBKKSKBKcicSc[BBKS[[KS[[SB9B[coooioc[KKciociiic[SKBc[SB999S[KSKSKSoS[[K999SccccuiKBBKBKSzoSczouzK19B99BKK[c[iuϦKziu[cuzi[SKBKB((91( 1oǒuuuuicSKczzoc[K99999BB9KKB9BBKSKB[KBBBBBKKBK999BBBSKB999B9KBB99KKBKKKKBBSSKKS[SSSzcBB[c[SSc[KBBBBS[iiicS[iSSoc[Siui[SBSoK99BK[[[KKKKK[iK[K999Scc[KczcSKBKKKK[ozcci99BKB9BKS[ccciB99oKѢiSczuKKKBB((911(c[oooiccSScocSBB1199BBBSKKBBBKKBzuKBBBBBBKBBB9BB9BKKBS9BKK9BBB9BBKKKBBKKSSKKBKSS[[zzSBBKSKK[SSSKSSKKS[ccSSccS[uu[ciuzoKKKK[iBBKSSSS[SSKSSiiKKB9B[[[[SBiioziSSKB9SuoioucuuK999BKKS[[Souҷc(B([SǚoS[ioK9KK((9(19[iiooic[S[czo[KB91199BBKSSKKBBKKzuzSKBKBKKBBBBBBKKBKBBBBBBBKKKB99BBBKKBBKKKKKBKSSKScu[B9K[SK[SKKKSiic[SKScccccS[u[K[iuiSSSKKSB99S[KKS[SKS[ScuBKKSSS[[cK9i[cc[K[[SB[iiiiiuoouS9B9BBSS[c[[ii˿[9BK( 9ouoScSKKoiKS1 1SK9KcĒic[ozoc[[ccizziKB9919919BS[SKKKB[zuo[KKBSBKBB9BBBKKSSSSBBBBB9BB99KKKBBKSScSKBKKKKSKKKcuSK[[[S[cSSSS[cc[[SKKcic[[SiuSKSiiSKKKKSSBBBSKBK[[SS[SK[SSS[[S[[[[SiSKSSSccc[iuoooci[iozuKSKKKK[[ccc[cSͼĪK 9B199Bݪuzouc1KKKKciK1(BB9[oiSKSooiiScouo[c[S[iii[K911199999KSKBBB[zooBKBKKSBB9B9B99KKS[KKBKKBBB9919BBKKScuo[c[BKSKKB99Bizizz[[ii[SKSKKKK[cSKKScccccuu[cic[SKBK[[B9BSKSS[c[KKSKKcu[[SB9BScuziSKScccc[coicci[iiuc[[[[S[c[SS[coiշɦoKBSooioouɚuuo[SBעuSSKS[KBBSc[ci[K[c[cuziKS[izc[[KKizi[SB911199BB9BKSKBSuouKKK9BBKBB9BB999BSS[BKBKBKBB199BBKKK[ci[S[[KSSKB9111iuizuc[cc[SSSKKBBKSKK[S[c[iiooiui[SKKKK[[BKS[KKKS[SS[c[[iozi[cciiiuuSK[ci[[SSoziiioi[[icSKSSSccS[[[iooؿɹo9Kiuuzuoui[KBiؿcB919KSiiSB1B[iooicciuocSSKSiuicK9991(1BB9BBB99cuiuSBBBB9BKB119919BK[SKBKBBBB9B9BBKKKK[cSKKB99BKSSSS[BBii[iii[[KBKSKB9BBB9BBB9KcciiiouicSB9Scc[KKS[[KKSSSSS[[ciccuzucS[[[[cozoiozc[[[cKScc[[[SKSciicԼɞB9iuuiiouicuui[KKSĹ[991BBBSSB B[[uzooizzoi[SSSooSK91991119911B11iuziBBKBB9B9B99B99BSKBBKSSKBB9991KKKKS[ccSKKBBBBBBKKKSKSoicccS9BB9BKBB1B199B99KK[SK[cic[[SBK[[[SS[[[SKSSSKSS[[[[[cciooouuzz[cSK[iuzuiuSK[[zBKSS[[cc[[[c[SBѼ[Kii[[[[[S[uouo[BKcuzKSiSB91919KBBii[ozuioic[[SiiS91111((((9919KzSKKBBBKB99999BB[SKS[SB9919B99KKSci[S[KBSKKSKBKKBBKSc[[SKB91911(99B1111119BBBBBKuoSKKKBBSBKSSSSSKBKSSSSSSSS[[cc[[SKKcuuoiKBB[uiicozSSuScuBKSK[[cc[SSS[ScϼzSSK91ioSSSizoouu[KiuK1BS9B9BB[Kiziczo[[[[KKSB11999111(199[ioc[KB9B99B999BBK[SSSSK99111BBBKK[oiSKK99KB999BBB99SooBB9991 1(1999B11(((9K[[[[[o[B[cSB999KSSSB1(9KSSKSSSK[cc[SSSSSS[cioiiuzc9Bcoouzzucc[uiuciSKKS[[c[[KSKoϿiKB91uoBK[ozzuuzKic111SzS1BSS[ziKzzicuio[BKKKB9911111((9B9KzuzzocS[c[SBBKBBB99BKSSS[SSKB99199BBKKKBSSBBK9KB9999999BKiuS999BoucSKScicciocccioiciuKKi[KB999S[[9( 11K[[SKSKKS[[SKSSSc[ciiiccizuSKciciiciiouSB1Si[SKKKKu˿Ǣui[91[SB[cuzoozuizoo[1BSSuB1Kouozzu湍ouuuuiKoBKBB9B99111111119BKiѦuciicBBS[SKKSSK99BBBSSS[[S[SKB99BBBBKKBBKSKBB99991919(9KSicBBKKSucciiiiioiooi[[cccuc[B9119K[[K(19BKSccSK[S[[KKBBKK[zzoooouuuuoi[S[c[ioBzҞcBBK[c[[SKKiǹɹoiiSBcKBK[iozuiiuoziS(9S9iKSuuioooziiizc1iKKKB1B999991(91BKKu¿ooooSBSSKBBKBBB9BBBKSS[[S[SB999BBKKKB99BKB9BBB91(1(((1BS[KKBBSSc[SSKKKSKcic[[KBBSSSScucB119KS[S119SiooiSSSSSSBKSSSSuzuoooziozzzcSS[Kc’oooozucKScijiSiiiucBKccccccccocK99BSoi[iuuuzuoooo1iKK[K9BB911(11K9KKccz[K[SSSKBBBBKKBKKK[[[[SBBBBBKSKB99BB9B999B991111((KcK(BB9KBc[KKB9KS9K[cS[c[SBSSKK[ouuiSSKSSS[K (BcouuiScc[[SKS[SSuuiicoziioozui[Buz[iտzSK[couoiciS9[iKSK9B[[S[KKi[iuucuoKSS[KBB99999BKKK[K[KicK[SKSKKKKKKB9BBSc[[[KBBKKSKKB999BBBBBBBBB991191Bc[9111111K[9999BKBSSKK[[[SS[KKKKKSSBS[S[[SK999[iccioouo[[S[[SKouuoioocc[[iuzzoǼiciziϷoSKSS[ouuzo[[[S[K9Sic[[BB[ouiciuioiKS[S999BBKB[ouoBoSSc[SKKBKKKKKBBBSSSKK99BKKSKKSB9BBKKKKKKSSB999BBSSBBKB9991K[B9911BKB119B9BBK91BB91B99S[S[SK( 1Scii[Siouuccc[KKKoociic[[SS[cuǿ¼ɞcKBSiczǷͭoi[SSSS[[iuzzuoouiic[BSc[Siiozuccuzzc[cucozc9B9B9BB[u[KSS[z[KS[SKKBBKKKSSBBSSKBB99999BSSSKKKKKBBKKSKKB9B99S[KBBBBBBBBSi[SS9111119B99919( 1BB9BBS[[[[SB( KSS[[cioiuuiioc[Biuoucui[c[[[[iuzǿ׷z9cϷ°czoSSSS[SSouuiooooooiSS[S[ScouzoouuzzcB[uSBB99199KiSKKSSSS[uzSScSKBBKKBK[[SSSKBB999BKBBBBBBBBKKKKBKSKKKBB9K[SBBBBKBB9BK[[c[c[KBBK9BBBKB999BKSKKS[[[[SB( B[SS[c[ic[zozociziuioiiizuozڳiiozuuѼļ[Sic[[[[[[Siozu[S[ciiozziiciccioSKczzo[9B999999uzoo[BKKKSKSSS[zSKc[SKSKKBK[[SSKBBBBKBKKKKKSK99BBKSKS[[S[SBKS[K999BKKBKKKKSSKK[S[[SKBKKSKBBKKK[[SKKS[[SK1(Kcc[coiioiizoicczcoiiuuzuɿˢ[KSS[[S[zĢo[SKKSSSS[[ccciicSS[ccccoz[zuzoSS9991199Suo[KSSBKBKKKKSSS[[SS[ccKK9KKKKKKKBBBBKSBKB99BKKBBKKKSS[SS[SKKScSBBBBBBSSKKBBKBBBKK[S9BKKBKSKKKSKSSSSScc[KBBBioc[uiiuzoiuzoccuuioiozuc[cS[zҪoS[SSSSSKBKuɷcSKSSSKKSSc[K[[[ccc[[[uuizzc[Kco[K991((B[ozcSSSS[SBKBKKKKKSSSzKSS[i[BKBKSB9BBKKKBBBBKKB99BKSSSKK[[[ciicSBSccKKSSKBBKKBBBBKBBB9BKSKSSKBBBKKKSSSS[SS[[KBBBSooSScccozicicizuzuo[iuzozzi9 B[KSɼխiSKKSSSB (19izoooioooooc[[SSSS[ccSiuc¿o9Koo9(19iK(191B[oui[SBBKSS[SKBKKKSSKKKKKuuBK[io[KBB[cSBBBKBBB9BBSKBKKKS[S[[cic[cci[[SuucSKKKKKBKBBB99SSBBBKSSSKKKSKKKSSK[[SSKSSSKB9KSiiSK[c[ouoociouzzouuiiioozzzcSK 1BKSiiɳԷժKKK99BB1 19SuuSozuzzzzzzzoi[oc[[c[[[icͭzѢSKiucuSBK[ozocSKKBBBBKKSKKKKKKKKKKSS[cBSiiiooiicSKS11KSSKKB99BBKK[[cSSc[ic[icc[[izcSSSSKKKKKBB99BBBKBKKSSSKKBKSKKKKSS[SKK[SKKKScii[9Kouoozi[SouuuoouuoiuioiSKKK9K[SczuɭǞuўi[iKBuoioiouooioocio[SiuK·ĿϿKczuuocKBBBBKKKKKKKBKKKSSSSKKKSc[S[o[czi[iS99SBKKKBSSK99BBK[[[[[ccccSSc[[[cuocSSSSKSSS[SKBBBB9BBSKSS[BKBBBKBBBSSSS[cc[K9Kcoo[BKiuuuc1Buoiuuuicoi[[cc[[iuuɦͼϰuzoɰĿɹo[SSBBKKBBBKKKBBBBBKSSSKBKKKSouSS[cKSiSBSBB9BS[KB9BKB9BBK[cc[[iiicSKS[[[Scuoc[[[[S[SKSSS[[[cKKSSS[c[SSB9BSSSSSKKiu[[cKcoooSKcczziKSui[iccuzoScoociuuiciu˼ǭͼǹ¿ǷdzϦz¦iozuzzo[[ijSB9BSK9BBBBKKKBBBBBBBSSSKKKKBcziBKKBKSc[KSSSKBSKB99BBBBBKS[cccciicKSSS[SK[ii[c[[[[SS[SSS[iizuouuozoicSKSciicc[[uzoSSoi[iocSKSciouuoc[SKSc[ci[c[[ci[ccSciiɿozĭcc[[K[cuzzzǹѦSSuzoSScoo[KBSicouuuzBBKKBKBBBBBKKKBBBKBBKSSKKKKKSuz[BKBBS[[c[[[SKBBBBBKBBBBBK[[[[[S[S[S[cccciucSScSciicS[[[[cuzuocciccc[iuzziSKcu[[cSKBS[ooozuccS[oiozoiiic[S[i[[uԹ·ϖuouuoSSǍB9BKKBKKKSccSKBBBSuoio[ozuzo[cuK[oi[SK[cSKKcoi[Kuɍ[[ouoKKKBBKKB9BBKBKKBBKKKSSSSSSKBoiKBKKSSKS[[[[SSBBKSKKBKSKSS[[[SSKS[uo[SS[[ciuzucc[iiuuzuicozuooicSBcziS[KB9B[uzccoiS[K[icuio¿Ǧͷccii[c[BBccB9KSSKSSBKKB1SizoiiSK[cooiciczooizooo[ccSScS[cSSB[ciicצouzoBK99BKKK9BKK9BBBBKKKKSSKSSKScBSKKSSKScic[KBBKSSSSS[[SSS[cc[[[[ozuzzoiciiuuzzuuouozzoc[[[B9[KKBB9Kuucc[izuSKBBu9[oɳǷzozz[Bi[izzcio[SKSS[SKB9BS[ciiSSccccizzioou[ziSS[[cSS[[SSccS[iiocҚzKKBKKKKKKBBKKKKKKKBKKBKKKS[iK[KK[SSS[icSKKK[[KK[[S[[[iouo[ccc[ioic[[[[iiiioooozozuicc[SKS9ciSKSB9Boui[[couSB[i[[BciS91BSSSoo[cozic[[Kc[cuzoi[cSS[KKcc[couoouioS9iucSS[KSK[[SBB[iiic[S9ošKBBBKKKBKKBKBBSSSKSSKKKK9KuKBBKSSKKSicKS[[S[SKS[[[izzuc[[[[[c[[ciicc[[[c[[cozzi[SSSKB99Ku9K[c[izzoo[S[iuoSizic[[ccSKzicc[ui(Kccc[ozS[coiozo͹zo[cKSzKBKS[[SiiiiiccciSSSB[zzoSK[S[icS[SK[[[[[KBBiBBBBBBKKKKKKBKKKSKSSKSKKBuozK9BSSKKKScoc[[[SSSKSciuzoc[KSS[SSSS[ccc[[ccc[[ciuuuzĿiSSSSB991Bz99KSiizzoioic[uuzuooSKozu[S[[[SBBooiczoB9SiiccozScii[S[[iuĿS9[icc(1[cS[oouic[cc[SBBS[K[coiuzBKBBBBKBKBKKKKKKKBBKKK9BuzS[ziBKSBBKKKcocS[c[c[[[ozzuoi[SSKKKKBBSKSc[SSccc[couzzuoooiS[iļcS[[SB99BBui(BKSioouocccciizoiBKSScccouoooiuoc[ccSKcozuoii[SS[iuuocS[oi[SKBKScoĹuSB9B[SBKcccccc[KBKSS[cB9BKooɼdzSSSKKKBBBKSKKSKKKKKBS9Si9B[oK[SBKKKK[c[[ccccciuzoiic[SKKKKKKK[SKSKS[ccczzoiiooocBSSuoooc[[ccSBB9BczB9KSScoccccccciu˞SBc[9BScccciiiiuouzoiiKBczuSoioocccciioou[SKii[KKBK[SS[iuiiii[911BSSSSSBB[c[SccK9Kz·¼İSSSKKSKBKSSKKKKKKBKBKiKSucBKSKKKSKS[[[cc[S[uccc[SKKKKKKKKKSSSSBKcicooiuzuc[[KciuzozS[S[K[SSSBBBBcKKKKS[[ii[[[[cožcS[SB9K[iccicoiiuuuuoooccz[Sc[[iioocciuzzu[[ii[SKSSSSS[SSS[c¼zz[BKS[[KBKSoǪuzzouciouSSSSKKKBKKKKSSSSSBKSouoѭuKKSSKBBKBK[ccc[[[oz[cicSKKKKKS[[SSKKSKB[uoiioc[[[[coo[Soz[BSSKBKBBBBB[uK[[ccc[[S[[[cc˰iSiiSKSSiocioouuzuoiiiiuuuu[[S[cioooiuzzucS[[[S[[[SSSSSicS9coǷu[SK9K[[ǭc[ouzzic(9ooSSS[SKKKKSBKSSSSSK[oo͹zKBSKKKBKK99Scc[[coouzcicKBK[iS[[cc[SSSS[izzoc[uoSSS[ccc[KKciSS[BKSB9BB99BiBS[S[[[[[SSSioi·oKi[ioiiccicciiozzuiiiicccc[[cciouzuoiouoicc[S[[[[cccSKBKKuS(1Sc[KoɹiS[[c¢z9(BB[uoiB 9[o[[[SSKBS[SKSSSSSKcz[iuK9KSKKBBKK99BScccoucio[KKK[i[[[[c[ScciouiiiouSSS[ccKB99ciKBKciSKK9999Kic9SS[[SSSBB99uoSSiccioiooc[cciuzucciccciioi[[iuuouuoic[[SSzS[KBSSBKK1(B  (9KKKB[[(B[Sz­uͰoui( 9iiS9ScSB1 BcK((9Kci[SSSSKB[[[[[[SK[uuciizc[BKSSSBBBBB91BScioouoiziKBBKKS[SSSSKKSiuouoiiiiiocc[SK9BBBKiiSKSSiu[[K99Koz[KKSSSSKKKK(iSKoocc[S[icioiicizuiiiii[ccouuouzoioocc[[[oiSK911   (191 ( 9iozŒouS9 [i(9[B(B919[iii[[S[SBBKS[[[[ScciuoKKSKcc[SKB9991BSciiiouuouoSKKKKKKSSS[[SKczucccccouiocc[SKBBBKSScoKBS[ccoiSSB[z[KKS[[[SBS[BBzcB[oi[SKS[[cccciouiiouoi[[iuooi[[So[B(  (191991 (  11(cɪz[9 (1uS ((1( 1BSBKi[SS[SBK[SSSSSizziBBS[ScS99B99BBKciioiiiuuo[SSSKKKKBKSKSc[KizuoiiiouSKKSB999KKKSScc99KSSSc[Sczi[S[S[icKS[ccc[c[BKKcoicc[ccciiciiiiooouzzoioiccccioSuB9(  9BK9BBBK[[zoKBBBSB  199( (( 9z[Suİc (1Kuz[[1(9(1KSSzSSSSSKS[[KK[zccziBBK[[SKKK11(1BScuzuzooouicKK9KKKBBBKBKSSKSc[cccciiuiSKB99BBK[SKBcu[99SS[ccuucuicicS[[cicKBSzu[B(9Siiozzziuzzuzoc[S[[oz19B (1[ii[couzzi[cSB((BBKSKKBK1( 1[S(Buiu((99BuuBSuc[ciuz[SKSSKSSS9K[Sou[KK[icSKKKB1(1K[ioouuzuiiic[KB9KSKKKBBKSKKBSSSSS[couoiSBBKSSSSKKKBoiB99BK[ioooc[[[cc[[iiccS9oc1 (9czzoSKSSKuB  ( (BKScuzocc[KS[[[ouzuzuuiic[ii[cSB(119(BKKuc( 19B9BuoicicSKS[[[[KBScSiSS[ioo[BKKB91K[oooooiozzi[[SB99BScc[c[SKKKKKSS[S[cciic[991K[oSSSSS[oS999BB[coo–c[SS[[[[[oicciuK ( Bzuuzzuouzooz1(Kiioozuuo[[[[KBKKSS[ciuuzu[i[B11(( 19SKB(( 11Kizocoi[[SS[[[[SKici׹o[[[[oicSKKBBKSooociui[cuziSSK9999BozuzzocKSKSSKKKSc[KKK9BKK[ouKcc[Suz[[KKKSS[S[ɼK[[SS[[cBB1[uS 1  1[uoicouiScooiciozc (Kozioicoi[[[[[S[[[ccc[SS[[iuuuouzo[B91(((91(( (( (9[uuc[iuociiiiSScSzKKzziS9Kž[(1iiSSK9SzoK9SS( (SuuzSB1BSc[ciozzcSB111(   S[c  91  ( ((9z[9 ؿҀ11(((((1(9BKSSB991 999((1BBBBBBKBKKBK[ccc[B[K9B9BKBKcc[KBSKBKBSSSSKK[[19ic9199( (ic(  iKB9999(1BcSKKoouzz[ (SKcu[Bcu[SBB9 1SuoB9o[B9BKSSScuocSBBS  BcoKK[c( (9B1(   (uzBKB9KBB۷ժK(111 (1S[[S9 (9119BBB9BBBSSSKSSBKS[cocS91(19BKSoi[SBB99KKSSBBBBKcKKiiK911K1 9uS(( (1((111 [S1KSK911BSKB9B[ozoczzciK1 9BciiKBS9KK91(( 9SB99( Ku(91((9KKKS191BSc19SioiSBcuiB1uB (9B1   ( BKScٹz׿B(((((((9BKK1  (91(11199KKB9KSBKSSKSSKSi[1 1BBKBSzz[SKKBBKSSK9BKKK[[Kc[BBKKii9 ooB91999B91( ScKKKB1(KcS99BK9BSzoc[BBBKcoS1czo[K19ii91[S919SS9  (1 Bu B1( 19[S1   BͿzc99[z[919B1    ( 1SKSٰocɪc1(1(( (( 9B (99119991BK99KBKKKKKKBKBKcc9 (19BKSB[KBBBKS[cSKKBKKSSKKK99SKcc1([K199BSSB((ucKKSK9[[KKKB1 1K919111Kc[iczuzcB B[K (iuiicK( ( [KBB(1B9B[S  (91(( 9i[coϹuBBcooS911B9 (9B991  ( (͉c1ԦiB1(((11((1991(1KB999B99BKSSSKKK9B9KKSK[S[9 1BKSc[SSBzocKKKK[SKK[[S[[KBKBKBBK9KzB(Bz99BK[S  uiBBBB[uzoi[91((( 1Siuooo[911(9Biu[1  1BSuԉci[i[S[coiB(11(199( 9BczB9BScizoB[ziScKcK19KK9BoS99B9  ˭zuS1zSBBB991(1( 199BK99919BKBBBSKKBB99BKBBBKK1(1Kcci[[K[SzoKBBKSKS[S[cicKKKKKKKS11uuK1(S19BSS1 (cc9BKKcoK9iS99BBKKSK(((1BKKBBuzzu9 19KizzcB  9iuB[ܢoui9 (   9BBKSc[io99KSKKczuBcucoSKuo1BBKB(1B1 (B9( 9[uoi9iωKBBKKB991((119KBBBB19KBBSKKKKBB19BKKB9B9(9KSii[[[S[ioo[BBKBBK[S[iiuc[KBBBSu9(c[B9(oz991K[B( ((SiB9KK[cB1cBKBK[iiccB(1( 9111Bzzoc[1 11Kz[Szc9  ((SSKiԒuzc((B9 KKKKK[KKiSSKBK[uS9zzzuSKiiSoiB((991  ((19ociҚSSҭzK[cK9999999BB999119SKKSSKSSSSSSS[io[BBB[c[SK119SSci[B99BS[ccS[cocSKKKKKzi(9BBK(BS91KS91 1cKBKS[c[BK99(BBKBBS99[B1 99(9ozzu[9(((1Bcu[BiB (1(([Scc[ozBKoic[ 9S1  1B11KKKKBcoS9BK[uzB[uuoSKS19Kco9991(  19(SޖSђcϷфBcSB999111BB91( 9KKKKSSSKSKKKKS[zzcKKKBB911(9BKcooK9BKKS[[[c[KB9[[BBBcuB1Bii[SBKK9(1 (([9BKSSccKB1(1(111BK91111[oicB ( (9BSS9[zu[1 1B9iiKB1 ocoKcziccSB(Kc1  ((999KKBBKz[c[KSiociSS9911 9BKuc9S91(((1(cԷčzS[BB9999911( 9KSSS[[SKKBBKKKKKSB991(((199BSiuK1BKcoc[cc[B9B[[99(([ccSSBKB(11  KBBBSS[[K( (11( 19B919911cicS1  1S[B(KuuS1 1K9cuS999KSS[[icccK11BB( ((( 1KKKK91KziciiiiB(1  (9KKSuioBB9( ((iz­Ἅu¼iSSBB9B9((( 1BBBS[[[[[SKKB9B11911111199K[S[zzcocB99[iic[S[BB9KK99B(Buozozo[KBS[991( (Si[BBB[SK (((( ((( (1919˄i[9BK91  (9K((1BcK  9S[ooB9KBiK[cKKBKcS199BB1  (19KB911ozoiccczB(1( ((1Sc99ciuS(( KzɰҒKSKSK99(( 9BBKS[KKS[[KBB9( (((1119BSKK[ciucizzcSKBSiocSSKBBBouSziBiizKBKSKKBK[KB1((1KzuK9ScB9(   1(1(icB1BK9(BSK9BB (KB (B[[SK911(iicozz[1B[S11(BS(1S9(19BSBK[SSzu[izK ( (( ( (9(1i[ 9ڷu[ScSSBB9( 199BSS[SKKKKBB9  1((9B99KSKK[cccouiiciiS9B[oiSBBKSSoK99[KBKKK[[9(((1BuoKBcoKB ( (9SoK( ((Soc9911(19( (9[iS1 (9Sizzc(SK91(9( 9uc((BoSBKBKzz[ouB  (11(  1BSuoczuҼѰ˚SBKSSB( (19BKS[c[SKBKB1(((11119BSSKKKKBKSSS[zz[[[icKBBKioB1S[SS[ScBB9KK1B[KSc1 (9ioBKicSS     (( [zSczB 1S99K91(( (( 9[[9 (1Biucuzi9BSK19KK191BB1zoiuzio[   B9BKBBBBSSScKK[ioճ۹ҢzSK[1((19BKKK[cc[SKKK1((19999BSSKKKKKSKKKKBBczcS[[icB991S[1io[KB([ouuoS[KB[S(9[S[c1( 9B[c[coS[K   (19[[oB (  (ooiS1( ((( Kc9 1SS[ciBSo[icBSi[K9919coK(1K[¢uiB (9KK[[Sc[[[[ccKKKKKSKKzšѪҞiS9((199BKS[icSSK9 (1999BBBKSKKKKKKSBBKBBScKBSSioSB9(B9[zuK11BSB9BS[SK[K 9SSiuK 19BS[ci[BKB   1BczziSoc  1( 1(BcK[iK9 ( ([K 9K[SSKSKKo[KKB9KB1 9S[(  ciSiuù1 (Kcii[[[cSK[[[[S[SSKKKSѿǰ͹·ijo11(9KKBBBSSKBBSK( 1999BBB9KKKBKBSKKBKKBBBKKK[[cicSB9KBKouS1[[KBB919[i[B11BSKoc (1BKK[SKKKK  1Suciuo1  1( 11 1KciK ( BK( (11911(B[cccB(  (11B9 Bc 9KK[oߢ(1BS[c[K[i[BBSBBKK[[SKSSz–uu˭ω؍9ciB1(9BKBKBBKSSKKB1111BB99KB9BKKKBKKKBBBBBSKBSSS[[[cc[[KScc19[zc9BKKB9B11K[iK((Si[ic 1BKSSSSKBK(  (1 1czi[iiKKc[SB11((  1BKSK9( (1BK 9KBBKoK11 (91BSSB( (9B119BB1Buɿz1BccKS[SK[i[KS9(9BBS[[cSKioSKi˞uגi迄(1((19KSKSKBBSSK991991999BBBBKKKKBBKB9999BBB9KSS[[[[S[cS[[SBBSzi99[KKBB999Bc[ BK[[[S (199BBKS[SKK91((BK[ooic‰SKoiKB( 11991BcK(9KS9 Bci[[[cuSozocSS[SSS( (9KSzoB9(1999KucziSoicc[SSSSS[[B9KB19BKKK[ٰi[SB[cԳziuK9B9BKSBB99BB9((1199BBB9B9BBBBKSKKB91(111999KKKS[[SS[SB9Koi[ui9zoBBSKBK91BSS1(K[SSS9 (19BKSSKKK9Kcoiiz¼cB[Լz1 9[K9(((9KBBcB9[[[K999BKKzz[[SB[S 9BK[[KBScB111BK[o9(SiSS[cS[cic[KB9991199911̀KSBK9BzuԀK[c(KB9BSK91(((1((1111BBBBB9KBKKKBKBB9((( 1119BSSKS[[SKSSK91cuiui9KB1KB99191KcB 9BKSSB1 ((1BKKS[S9oicS[z͖cuz˷o1ucB911K[((B[[SB119BKB9KziScKBcS 1B[[[SKS[SB99Sc[B  ͼiS[[S[[c[K (1(( ((11 B׹ؚc[cc911119oޞBcz91BBSB111 (1999B991BBBKKKKBBKBBKB91 (199BK[SKKSSSKSSSK199[uzcB1(S B[K9 (19S9 19BSB1(1((99KSS[Ԗuzڼz[[ciKKKKKB c[199K[ioSKioc9BKo[BKB9((B91Bc[KScioS9K1iڍ(Bco[KB9( 1911(ˉ[zi1(119(BoݿuSucـ9999191119999BBB9BKBBKKBKKKKBBB9(11 ((9BBBBK[[KKKS[KBK[KB9(9SiS9BB[K 999((91B9 (99KSB(1(19ScKBҢ¼[K9Soz[[SSKB1 Ko[1BScioo[Suo[cK1KSScc[o[K( (KB9Socc9 cu(1iB(( (((( (111ύi[zuS9(1(19199cωKSٖB9119991BBKSKBB999KKSSKB9BKB99991((111Kcc[[cc99KSc[[[[SKB919[K9B11zS99BK(((9911( BSuB( 9BBS91uoioĭzuB1BzKKKKSSK9BS (cK19[ucSSBKzzc[uzo[[ozzo[  1( (9  (99[( 1  9((19 ìKuucB1S[1(1919KBצoo19999199BBKB9B9B9BKKBKKKKKB11((((9BB1K[ci[ciKBS[[[[SS[SKKKBB91(9KKoSB9B91(111( 9KzB(1BKc[B[[iٷcuzoB1Bc(1((9KK9Bc[(9iSKizB (1cuuuocKSiuioo1 ((  (( 1   (11(((҄99uK1cK((oi٦ђKKB1119999991999BBBKSSBKB911199999BB9KSoiS[oKB[ozoi[[[KBBSSB9B9KB9Bu 99((11BB((1Bc1(1KS[[SļoSiuicciǹ[[zB19czB((191119i[KczB9i[[KBKBBSioSKSB1   (11 1K  ( ((ˢcSiS9Sc99z載ͦSB1((1B99199BBBKKBBKKKKSKB1(119KBKBKSKSicKSi[ScooiicccS[99B99KSKBSSBzo(BB(9919SS9(9B   1BKK[[iocoui[[cozK1čB1BScuS1199111KK[i[1 ooc9((11iSBSiK(91  ( ((119SK  19(9BSිiBSczziSBcc[ҷɦ˭zS1 19999919KKKSSKK9BKKK9((19BSSKKBBK[iocKK[[Bciiizocc[S99KBBBKKSSKBKSB919B99cSK11B(  9B91BS[Siuciuuciouuoi1z’ 1B9K[19911(1KouiK((( (Kz[cBBBK (oKB[uK K[1(( 9c[[coz[K(111191(Soz„uB9Scioi[K[uiڼ˿װѦ[B9919B99119KS[SSKKKBBSSB1(19BKSKKBB99Sou[BKoiKccozuccc[KKBK9BBS[BBBB99 (9BBK1KB99([[B9BBSo[[cuziozciououo[KK(911[iB9B91 1uoKKB99 1i[K[[[i[KSizcKi9BKKSSSziuzzcKcoSK1(  (u˰zz[SS[io[BBzKKuٳ­ͼiBK99999999KSSSKKSKK91KK9(19BKKKKBBBSBBcu[9SziK[uuiS[c[SSK[KB9BB191K91 (B19(1B9(  (9[iK919KiKBSuozoococi[zzi٢B191Bic11B1((Sc19B((1Suu[S[SiuS[o[Bic(1ScuuSKc[io[zooS1([uҦzzo[[ccu[B9oSBB׳հǀKB199B999KKKKSBKSSKBBK9119KKKKKSBBSSK9SiK9SocziciSSicKKKS[KB99(19Bi(1BB11(11911( 1SoB99B9c9(Szzuzcioicciuķc99B1B[oc111(111uKB9191Kzcc9B[ciuuiK9K1BozuoiB9[SKizKSizuiS1BoczuzoSKSSo[99cɰzKSdzϒ[9(1999BBKBKKKKBKSKKS9 (9KKSSKKSBKKBS[c[K9BzziS[iSS[[SS[[[KB1119BSSu[(BBBKB19B1( 11Bc[99B9S11Scozouz[[i[K[cou9B9BSSSK11191(B9BKK9[icccB[ozzocS9KouoK9[iK[oS1[zcouuuioiziKBBu9ioKBBB99199cҰoKiҿհ̈́S9(1B99BBBBKKSKBKBKK9 9BBKKSKKBKBKBKccS9BBiicS[zcK[[[KKSSKK99B9B[SSKK1K[K99B9(  (((KoBBBi1 9[ccoooz[KccKK[[u9(1BKBKc[[[K1 9c9BB99coK[[[iBzoicKzuoK11SKBic99ccKKiicScSioB(So[oB[ 1111 1Kɞuu˷Ǟu[1(1B1BKKKSKKKB111( (199BKKBKKBB99KSc[B9BBSuzocSSczcKSci[BSKBB919BSc[K(i1[iK1991  9zcKKS1BK[ccco[cSBK[K9ciocSB1 (9B9Bcc1((cu9191BicKKB9iocSSczB1B9 ((19SK1Kc999B((i[KizK(B9cୄSK[SB99B(Bϰ¼ت[[B1BK9BBBKSSB9  9KKSKKBB9KBBKBSS[SBBBB[oiii[ScocS[cc[B9BBKK9K[icK9(K1Sc1111  BoSSB1BKciiioBKB99[S9Sc[ɹK   119KSoiS( i[1((Kzu[SK([zcuzi[ĉc9((  (119SK  oKB1Bco[11iؒ[1Kocciccucc[z‰1SBBBB9KKSSS1  (19KBKBBBKBKBKSKSS[SBBBKSioicSKcic[cic[[B99BBKS[cSB111cKi[9(  ( [oSS (19Soiio[9BBK[[BK[c͞o((19919BSocicB9SB11[ui[B(ouzzuKu1 ((  1( 1u9(1SicS(ҖzooiuoucB[cc٦K(119BBKKB9( (((1119BSKK999BKB1KKKScc[KKKS[cccS[Sicii[cSKKKKBBBKB1K911B(SoB( 1( (  1ouS[c(KKSiuuuoucBBSSSSKKKSuSBB99K[SB19KSiiu9B11SccoKBzouSBB (11(BK1  1icBoB19[zc1 1繭iozuǦi[ucBBiצS((1BSSK1(  1B999BBBBBBBKSSK9BBKScccKKBSS[S[[[Sicci[[SSSSSB99BBBB1119 iĦcuc1  1(  KoiKBci1KSKKcuzuoii[K9BSSS[[SKKcu[ii[S[K9KicSo(11Kc[[u[ͰoļS1( 1(1oo[9 1ucioc99[oBzҖcS[B˼zz[BBS[՚͢919K[S1(1((11(111BBBKBKSKKBKKKKSSS[S[[KBBSc[ii[[Sccooi[KBBKSKBBKBK911199KSSB (1(  SiK9K[c199K[iuuioioi[9BSSc[S[SB[z[SSciiK9[zBcuS(( Bu[uuռɷB ((BBcuK([o9zSic9199(1uK[ou[9ύKuK(KuoKoదٍ1BK[[S9B9119B119BB9BKBKSSKKKKKKKS[SScSKSSS[oic[[ciucc[SKBBKKSKKBB91((( (cKB91(1((  1K[B9BBS (9Sczuzuo (S[cc[SK[ioo[ScooiK1Scuo[K9( (czoiij°Ħ((19Sİ͞9[o9[ic[B((  ҄KKuzuoBzњSSKoi[cuѰi1KSSSB99BKBKK9(99919BSKKKKBKKS[SSSSKS[[Kcccic[SSccioc[[KBK9BS[SKKB1 ((1uK[[S991( (1Ki[BS1  9coouccKKi[S[iScǭzoSczz[[cScuiK99((KzSuuš¼K99Bϭ[K[i1KiKK( ozSSSooiSѼKK[uzicKuKS[cK9BKSKBKB9BKB9BBB999BKSSSSKS[[[SS[KcS[ccc[cccicS[[KBBB9SSSKKB111191 zK[[K11( 19((SiKK[( BB9(BicKc[Suz[c[Scic˳ocoiBKSSccSSiuB (9[iSz°oK9[ļ˼oui1oK11( 1ߦucSozzBScĢu[B9Si[K9S19K[oiB99KKSS99BKBB9119199BK[SSKSSSSSK[SSK[S[[ciicicc[S9BB91SoiKKB91( oǖKKKB9 119(1Sc[[S((9KB9[zcKS[KKzoSKSKBBcԼiSSKKKB( 1SB (9[[ozĹªc[ĿĪªiKco[(ooiuz[[[c9BB[[cB9BKB119uu 1KS[9(119BB19B9((((19BKKKK[SSSSSSSKB[[KKSSiiciiS[S[[SKKKBB[ic9K9   BBKKKK( (19119Kcc[B(((B9([ciKSBBS[[cB1( (iɚSScSSB919B19iuB1Bzciizɰ­¢zi[oKczu[B(oSSccK9SiSKi[SSK999(199cB(111(1B11B9((( (9BBBKKSS[cc[[[[SKB9KSSSSiuoioi[[[cc[KBBBKci[BB9  19(KB9(1(((((K[ccK( (ccS[ciKBSKKSBB9 (B԰oSK[zccK11BSK1BcS( KuuiuuzĞK[( 1SuucK 1KK( ((9’[SSKBiiSBou[BSK91((((BzK(119BB191  (119BK[c[[[ciiiSKK[SBB9BSKKSuzzuoc[[[c[cSBB9K[c[KK1 (199B911(((( 1S[[S9(99uicic[KK[K9 (91B˄SSK9iuK(Si[9BS1 iiozozu919919KK1 (((1((11   (19BѼSB9BSc[SccSzoiK[K1 11 Koߚ9(BBBBBB( 1KKBKK[ooc[[[cicSSS[[B91B[SS[ooouu[S[[[SSKBBBK[iS91 (19BScעBKB1 11( (KS[1 9919B[Sc[[K9KB9(( BBiǼ˭cS[[Kic9[ocBKB((1Buuc[zzuzio( (11(1( (K[S1  (9B9KčKKBSiuzcSi[[SB91(9B9(Sҭo9BKBKK1(9BKKKSKSc[ccciicSKKS[[B19Ki[K[cciz[SS[[SSKKKKKS[9 ((119[izcKB( 99(((BB1(1S1( 1(1icS11SK1(1S[iSK[ii[KSiSScSB1(((1Su[zoKzoټzB9191((((((11 1ciiSB9 99( BB9[׀ĉ[99iKSciSc[i[9  9cz᳢ܼS(19KS1(199KBBKBBB9[ccuzcKKKSSK919SuiBS[[iuS[[[[[SSKKKSSB  1KSuoSB9(9( ([K9BKB( SϦiiSBSiS(BSKBKuSBB[i[KSSiSK9( (1coSzKS͉1ScB19B9(1((119Sozuc[99c[( (((ϼSBz[Su[KS[ccS(9iiэ(1KB1 1111BB999(1B[[[iSSBBKBBBBSuiBKc[uoKSSS[ii[SKBKK9 ((BKiԄiK91 ( ([iBB( 1 (SSoicciS 19(19uiSSKKic[SK[zSKK(1(1(KzcSSSBSžz9[SB1( (1B9BczzSKKBKB( 9ԖciiuSSB9( o㢞˼c(BB1(( 1(9999BSSSSzzcSS99KKSSK[c[BBSSucKSSSS[cSBBKKKK9(1( 1KKKu[zioKB1( 9ziBB9 [B[[[c[K 11(1S[[SSS[[c[[SiS191 B99( Sui99SoǦɞucS9B1 (((1SiK (1( (111 㹀9BBB[iiuz[S  㹢ٿ9(91 (9B99BScSSS[[KKK99KK[SKS[SBKKKuzSKS[[[S[SKKKKSc[9 ( 9K91cuSSziS[SK9119BSc  ( dziSK9SicS11KK91B[[SS[[[[ScKSzi( ( 1 (KSK(SSSo¢zo[SiuS1(1 (111  1( (1˿э((91(BKBSuzuo99( Kⷳտccc[KcK11  (19BBBSci[KBKBKKKSB9BBSKKBSKSSKKuoSS[c[SKKKBKKS[ccB (9B99K[KKc[KS[[9(1KB91(   iSKSiic[KBB1(KK[[S[iSBKSBS(1(9BB1KKuB9SSc·zB99[uKKczziB99(9191( 1((K[ߚzziKB9B99SzzS ((Bժǭc9BKB99Kuu1(1119BKK9BciSB99KKBB999BKKSSKBS[cSKBiuc[[c[SSKB99SS[[[B(1((119S[S[uu[KB91 (1( ((  ozzoc[ci[[[1 1B9SuoBS[cciSBBKBS99K9( (BSBBBKS[cKS9Bo1 (B1(1BSK[icS[[c1( 119( oizcoiKBBBSzuļ[1(1o榞ҦKBKSK9191(BSizS9B1(919B9BKSB9919KKK99BBBKSSBB[oi[K1[zcS[c[SKKK99BS[[[K11 (99BSSKSiiK191 (( Kcczioc[KBB 1Bcoc[KS[[S[[KKSKK[zccc1(((9KKB11KS9BB1 Bz991(1 (9BKii1(91(9ouiciu[io[cuǹc9  9ط1BS[1((19BSiici(((199BKB9B9BB19BBKKBBBBKSc[B9[c[SKK[zoSSSSKKKKKKBK[[[B (9B999B1(B9((19( (  BzBKcicBB1 (1(Ko[[SSKS[[[cSBB9K[iS[11((BK99BKK99BB111BKio19991  (9Szz9 19iڼcciiuSuzoiB  [Ī([B1KSKBB91Kic[uoKoK(9991BB19KBBK((19BKBBBBSc[SKK[iKBBKKoo[c[SKBKKS[[SKSS1(119K1( (119BB9(  (  (SciKBizc[[KK((19Ϟ[cc[KK[SScS999KiziScB (999B9B99BKSB11(Bz9B111(  ((111(1[uoBKcϳiciioSizuouiK  1ٹKccK99B9KuKoi9cc(9B9((( 99B91 1B999999[cKKBKK[KBKSKiocSSSSKKKS[SSKK91 ((BK1 ((B911( 9(  SKSKK[zuc[cK ( 9i[c[S[c[[iK19[iuc9(19( (91(11( ((Kio[B1( (9919((1zɭzuٷuoc[SczzziK[ciuzicicB1(9SBK˷߉BioS911BiuB9S[1KuK1B11B[[S1 1KBBBB91S[BB1KScSKKKSic[SKKKKKKKS[[B1 1B19191( 9B   (   u[S[SKiocic1(((cڭzic[Scizz[B9oocuK (1 1B(  (1KSczz[B1( (1B91111Kİ٦i[[K9B[c[ooSKSKSizoiui1(9BSKoճ܍ccB1(Biu[K19SS9BziB91 1KKKB( 1KK99KBBKKKKBK[c[BKKKocc[SSKSKSKKKK(B91(991( 191 ((   1( uS[S9Siii9cSԭui[ciozoKcocB( (9B(  99((BouSS[uzzzo[9 ( (9BB9B9B峳oKcSBBBBKK[SSSSSSSiuizo91B91(ɞ(9 9ouiS1BSK1uBKK1BS9  (BKSBBBB999BSSS[ccB9KKiu[[SKKSKSSSSB 91 9111((191 191(  zii[cii[(((u–uzoooc[cui[[c[B91(99   (9cocK919BB[zzzu[( (1119999oioiziSBuiKc[S9BK[KKSSS[S[uzouoKB1(( ݼ[9ziciK(cSSK991( 19BSSSK1(9BBB9BBBKS[KBBScoKSSKSKKKSSSK19B(9K911(91( (BK9  czS[zzocB1u˷oczuzz[[c[SiicSB9BB( ((9( 1KS( 91 (((Ko[9 111111BScuɹčoiooi[SSKKSBSKK[iuoozoSS119Bݹu(uioS1[c9B1 (1(9BKKKSK( 99( (9KBSSK[B1Bcc[[[KKKKKSSSSK1 1BSB11 ( BKK9(   KozuSczuic9BڪoiuouzS11SSB9BBB9199  9BB[S( (1 1(1K991111119Kz[Sczz¼iz[ozoScii[[SKcizuzzSK99[iҹحcKKSiuzz[ Bz[BSB( 11(1919BBK911(  (99SKKcSBKoS[[[SKSKKSSSSB1 (99K9(  1  99K1 ((   1Bcoozzouc([ic[ouuuB((BKBKSS[[B1  (1119Scozc1((((( (˹S(11((919z[cSizѳSBiuScuuiziS[cScouu[S[c[ǭzBKK1(99Buc99B911111( 1BB91911(( (19BBK[K1Kii[[SKSSS[[[K9(1 (11  11B1( (  BBKSiuoiK([͒uK[ioiico[1(BB19[iSSSSB  1111BS[ozcB(991(9Ԫ[cK(((1BozԪc999co[o[SKSciuuSS[couuzzuucS[B9ǦzךuS[K1BoBSS(9KB911(( (19BB1(199((((11BBBKK1[c[cccc[[[[SK91((    19BBB(((( z[BBSoii[(9uu[SccoccKKocK (BKBBBS9(9[9 (11 (11BBK[KS[K1(( BɍB KǼ[9K[zSS[SSSco[coS9S[iozuuiSK99¦uzԪoK1Bzoc[i(BBS[B11  19BB991199( ( 19911999czu[S[c[[KKci[K9(     (19B1 ( BSKBKucKKc[i[ [ccKcoSic[S9cS9(11BK9(19B[S9(   ( 9 [[ iz19iii˳[BBKiBKSKKSiiKc[BKSSoouzcK9BS¢ozԦ°iuiKKoz((KKcc1(1 19999111B91(91(1((199Sc[K91BSSK1(BK91(    (19K11KSBoiii[zoiiciio[9c԰iuccoBBSKBBK9(KK9SK1BKKSK( (  1ͪĞz ziScdzuiSBK[zcBSKSSSSKSBKiKKzouuziKBKuǪuzz간oKBuz1((19K[9( 99BS[S119119BB1KB119K[[K9191(B91(1   ( (BB9BK9 (1Kioii[BoouuuiSB[zicBB[KB[[[iuiSc[Si[((  111B9cѳc(i¢o[c[SͿzz[19KSoBSSBBBKKBBS[9Kuzo[9K[Ǫzuu¢’[Bzz[BuK((99(1[cK[[KcoSBBBKSK99(9[icSB1(KB9KB9(    (((9KSSS[K( 9[[[K( oozzuzzccSuiuziS[ocB[uSKcK1B(   (  ((1B1uɢc1 Kzii[KioչuoucB11991uuKcc9BSK919KKB[zzzuo[[Sѷuiiuzo[K[uBKizSi9(  (9cSi[KɚoKBK[cS991KccS[S919B1(1(   1(1KKBBKK91( 1  ouoic[[zzK[oo[ 9c9KK9    9cB[ǭcSz˒czzzuuoc[ªic[B111( 1BoS99BSB1(9BBBSuzzz[1[ѦͭioooooiS[[SBBcuc911((KiuBBSKS³o[S[cSBK1K[SKB(11(((    (( 1B1(119B1(    oooocBcoiK[oooSzKB(B (( ((   ((1 SzҼͷ¼cciuݳo[S9111(11ozo(B9B9((99BKKizuo9ԢϪocioouozuSco[SKKS1(1[iz (1(((KzcS1 (KcϒizuiSKio[[B(KKK9((B9     (11(( (BB((((1((11   i[iizu[KKcu(19K (1B9BSSK9((1191[˪¹oi[[iz׷u[91111(1Sׄ[ooKBBBSS[[[cuozzuc9oǒɖzciicS[[cKScc[SK[S((9Szz1 11(9c((cі[c[[Sci[BB(B[B91199(      19911(9B1((19911B1  SSozzǰcKoocScKKK[c[K9B9(BB9991((19Bczzoic[c[ccizǰcK91111Buu[[c[[[cizuiciǭͦzociiSKSuբiSccic[[czcKKKzi1 (1911 BzzSKBKco[B919[K119991   (ii[KB9919B9(((1919BK9(S¿SSiiS19[[ccSS[9(9( 11999991 (919z璀oo[SScci’oS9B K׭uozzuSSSSSScozocBˢzĭzuzi[iui[o؉u[[KSSSouiKSi9( ((((19[K9 1[cK9BSccB1B9(  ((   (u[[[SSKBB11(((91999B(  1BS¹zKKo˒zozSBSS[ooB(1( ( (199BB((Sz҉ouooiiuz¢i[B9(B1ljiicouuu[S[[[ouzocSҭzooui[[couuiSSK[ucuzuuKSo[((1(  (9zz[9 ( B91B[coS9991111( (111191( ((zzS99BBB991111 (19999( (19BKiScu[ooocic[zi( ((11(Œioucooziio„iSK9B㪉uuciocczzzocooiuooc[[[coiK9KioczoKKSB(1 ((  (oou[B(9BK919[iiKKBB9(9111199BKB11999KizziB1(19999(  (9BB9( 9919Bz٭zz[B  (991[ǰSzKKiuucSڳoiK9(o漢uiuuzuuzcziic[SSSoѪS911KziuoKBiS  (1( Biuu[KB19SSSBBcuB1999919B9B9BBKKBBBB9([[KSS[BBB1999( ( 1BB9((1 (1BB((շiu[  (1 (19[¼uSouuuoz՞KKB9([·zuuuuoozuzozzicc[SSScouooSoK119SciizziiKSu[(  1( KuS[S91BBBKSSK1Kc9199911199KBKBBBBB911K[BBKBSS[[B99B( (111BB91 11( 1BK91 ҭozuSio[[ccS( (9BBSc[9(((Biuķoczɒui[لKB9(1Կķzzzzzzzioic[c[Sizzc1 9B119BB1Kuoozuuucizc((  (B[K9BB99BBBBBSB (K9(9KB99999B99(119111S[KBS[SSicS99999BB11B9B9B19(((1( 9uu[cijooccB111191(KSSS[io[1(((1Soi9ijou„o[S[oiB99zdzļ¢ouzuzuicci[[SS[oSK[K19KBB1KuzzoiSSz[(  ((KKKK9(9KKBKKBB99(1B((B91199991((((1(1BKKKKS[[[ocKKBBBBB19BKKKBKB1S[ (BuzcKccuԳĄK9(1( (([B9B999B9( 1ciB ѼǍz[[S[ooBSzķ׳˼·uiiciizuzc[KzzcS[[[[i¿uS[SKK1(9oiSK9KzB ( 9991Koizc[cucB91(1(9[[K(1119999191(19119B99KS[[cc[KKB9KSS[KKKSKKK[ozoiiB KSz[uuu¢لu((1  1 ((111 cdzuz˪uioicuicB9ͭ˭u[iouzouciczuuzu[S[c[KKKS[iooioB((11SicKB9 9uK(1( 99KB[zzuiBK91( 9ic91((999991999119BBBBB99KKK[[KBKBBBKKKKKK[c[SSouuoѪB( (  9911i°z糚˿iuuu[SB9չךuzo[cc[c[iiououzcSciSSKB99KcSoiouo[91SS9BK[KKB(uiB9((19[[BcuoSKB1 9[[B19BBBBKK9B999BBBBB9999KKK[KKBKB9BBBKKKK[[S[cozτڼKcz 91 ((((  ([ڼמͰiiioSԀ9B1ͷ꭭uzziccSS[ioozucciiizu[KKB919SKSizzcBuiuucuoouuooSB9B11iB9((99B1([iuuoB9B  (9cSBBKBB99BBKB99K99BB999BBKS[KKSKKKKBBKKKBKSScic[iрԹ˞K991(119((BB9 K1·Ԧ͢zi[iioܰKK(9SҳϼzocSSciiiouoiizzuoocKBB9BBBBB[uozcS[c[uoooS(1BK9uS9 (1BBBouic[uS999  (9[SBBSKBKKK99B1(19B[B9919BSSKKSSKKKKKSSKKKBBB[ccciuܼioѳѰ[119SK(9 1ocB((1BBҿٞǦi[cuՀ1B(Լ۰c[uzzuciuuozuouc[cSB999BKKKKio[BK[cooKBKc1KSKBKcc( (1SKKiS[cSuo[K191( (9[[BK[SKB9(((1( 1(9cSBBBBS[SKKKKBBKKSSSKKKB9BKSciooۍiͪճSKK9B9 (Szi[Boѿ迍¢oKBz܀(9cǢ˿Ģzzocouuuc[[[K919B9BBBSozzu[BKccui9( SzziSKci(119B9[SKBB[u[B9KSKB99SKB9111   (111Bc[SBBKS[[[SKSKBSKKS[SB9BBBBK[ciiiz㒉ѿĹoSciS111( 1Kz·ɷמzĹocBݭiǰխzzoi[[[[B91((9199Kiuuuoiccccoc1 1iui[[B1io1 19BBBoKK9SzS11K[[[S111B1 ((1i[KSKSSicS[SSSKSSKSKB99BKBBBS[[[cciciҿS9So[1 (9B91Bˍǰךļoǰϰɪzzoc[[SKB99B91199SozuzoicKKcS9 BocKB9[9(19199iSS(9[(1BKS[K1(((    (((9iSBSK[cicccSKKBKKSSKBBKKB99BBKKKS[[[cc˿[ScS9((BBB1[򳉿׼㹀٪˪͍۷uoijzucKKK9KSSSSB9BKS[cuzcK(9SKKSuuSB (i(((1(19KizS9( BK99K1 (  (91(19S[KS[cciiiSKKKKSSKBBBKSSSBBKBB999BS[iuĄɹzK999(99KKKBuǦϿҖu弄ՍzKSczo͹zucBB9B[cccKBBK[SczuuuSBBB1S[K (KoB1 (11Buoi[K91(1K[K1( (BB919991119Kc[Siiccc[SBKKKSKKKBBKSSSBBKKBBBB9KSo׭udz[Bi11991BKBBKS۷ҼǷͦ¿Җcoo( 9ԦэuҰuiKKSB9ciiiSKczucuzuzS919czccK( cc1(91(iiKoiSKBK[[    999BB9999KK[iciic[[SBBKKKKKKKBBSSSSKBBB9BKKSSS[uɰuBBB (9BBB[[KKBuؿ؞͞uo[iz[991ϭמo˿ĪoiccK uzucozzuuc[zizB1BSizuSSi[B i[(BB9SuK9zc99 91   ( BKK (B9BBBBKczoi[cSBKKKSKKKKKKKSSSKKKKKKKKKSSK[iuĖS(1[[1 KcSSS9BiڼzϦz҉c[ooB(11ܿĹziļĢuuiS9BicczocccziKozc[[B9BKSiczzK([c[1 ic1199oB(BziS1199   ( 1S9 1(19(B1KuoBSKSKSSSKSKKBSK[SS[KKKKKBKS[[KBcS9Ǧz((1KB1 K[1999u¿͢z¿ccc[1(1BѰuϳiic[KcoK9icSiuSczcSS9(BBBouB(S[K1 ci1119z[1 Koo[1Bc[1   (  (9BK1[[[(KBKKSSSSSKKBSKSK[[BBKBBBK[SKB9ii(°cz9911((11B99 9ط߹ђɼiKcuc(9(9ɳҷϦ[фzoocS11iiBc[[zo[B 1K9BziocB9( (1cK 91BuiB1(Bcoui(9Bcc1  ( (( 11((1B9B9BKB9KSSKSSKKBBBS[S[KBBB9KBKSSKKSozoǭi[S11 ( 1KB9B99ڼzouzz߿ɪu1ozi1 1˖ĒuiϚS( Buo[cuSKi[9((1BBKicSzu9( ( (  9[c[B( (Kc(11Kc9 ((  11( 19119B9BSBB[SKKKKBKKBKBBKSSSSKKBBBKBBSScc[icK o( (1((9KKKKKzuouѰzuozuճ°ǀo[Suuc((˳բuzҼoͪc(9uocic[SKK9 (11191[o[991(911KB11((cB99(K[  ( (111(919111999119B9iK99cc91KS[SKBBBKKK[[[SKBBKBBKBKcc[ciK9Bic19BB9KKBB[ooiccc䞪ۭziiizǪطzS[icKKc1BɪzzԪzoĦצS BuuciiKBBB9(19999 K1199ic((1 (1((ozuc9B9Kzi119B919BSKBB91991119BioSuuSKKBBBBKKKBKSKKBKSKSKKSKB[[ccB11cS9KKKKBKS[ucccccټuoiiouo՞װzc[coiB(19(խͰϷɿѪB1([ic[9BB1B9(111111ܭuccB ( 19i[  (KoK9BKuc(9KB1B[[KKKKB99B9999coiuc999BK9BBKKSSSSKKKKKKKKBK[[iccSSoz(B9KS[couzc[[SĪuic[oԹحiBcuzoK((( ҹˢ¹ҿلB9[zzucci[9K[K9((11((BzKci1( (B1B  (oz919S1 ( (19SicBBKKB9BBB9B[SBizSKBS[B19BKSSBSSSBSKSS[SKKB9BKSSSK[czu[i ((BSczuoocSuĦzoļ„KcuziB( Bϰټ°չߚcciuzoi[[[SS[c9 111 Bzu[Kic( 911KoK(1  (19BBKB9BBBKB11cuSKKSS1119[K9BBKSSKKSKKSSSSSKBKSSKKK9BB9Bu[ 1KKcucuzo[cuϰ¹¼iiiioc9(9 K·˳¿­Գתuuucozi[[[[[[[9 911ic[oc9 ((((((i[(B[zu9 ((91(( 1BSKBKB9KBB1ioKKB9KB111ccBBBKSSKKKKKS[K9BSKKKBBKBBBBKKo9BBBKKKzc[cozuci׍Ģuc[Scic[SBBSSB19cdzɰɼ[iuiccoiSSSSKB9  (iouK1K[B (91 (1 (K[99BBSzo1(9BBKB9K[ooziiSB9KcBKKKK9199iziccKKKKKKKSKSK11BKSKBBB9B99K[zBBKzocizoz[[cozuْiϷzzzoiiiKBKS[[S91 111( ߹ǭͿzuzωozi[[[[[SBB(111(((1BiSSo¢B9K91((11 (1 ([i1(9cBBu[(999BioBB9ScKB[[B19BKcooooiSKKBSKSSKB1BK[[9(99199KK9޿BKouiS[[zǹ׷zչoccio[S[[KSSKB1 ( (ĹճǼҰ͹zouBBSǷicoiSKS[S9(( 199199[K9zcuz[S( (( 19(9oS(9c1[S(9B( 1SoziKKKB99K9iu[K[[B(9KSciiciiSBKS[[K9KS[[K11(1(199Szc[ڒc՞[[[ozͪͦiScSSBBKccS9  ѷ换°˭ճS((1cucc[ioK9KSK111(19BBSoo1(ooziSooco( (19KBSz1 9991ouSBKSBB[iozB11 (99KcBKKB9K[[[[SBBiu[[[[BBKS[K((1(1999BBSuϞђzoc[coooɪҞKKS[S[c[B (  孞ҳԹķҢK1BSciicc[[cKKSKBB19BBScoiiScuoiiSSSB9 (( ((9B[i((KB1Si[KKBczocK91  S[B9B911zcK((1(19BK911((1Bczc[B(1KK91(1B99BBKSS[uoªɍzocioiozĦ˄ouiBScc[SK1  iz[ےɼĿ線KSiiiioo[SS[[[K((91oc[SB1 9[SuoKSKBcoK( 1B( ((1oc99BB9[cB99KczuB1KK9(111Kuԉ ((((((19919B919Kii1 (11(1999BBSS[icoc[[K1Ƿɷzzuouu˭uoSKSKB919(   Bⷍ׹᳖zB[ooccoo[ccKK[B((B[oB199((BuKB[K91((SoK9K1 K1 ( (KuzS((9((oc(1BS9  (99B[9 1BBB1 1Kci[[[[ocBB1 91199KBBSSKSSSo[Scuii¹Ŀi9[iĚzzozuzcSz˦ۚzԭϷ˚uuiiiuķzuu¿šٹۿ쿹u[ĿķKuicuč·ucouz[oz[zu9uªuiѳ߿ķ׼¦ϢziooiiuǿzoouĖ޷Ƿ·ļccziozɢucocoBozcic˹iǦؚzǿϿǼ¹խui[ciizĿzzuzšͪɹаuoSѹozzzzcoǍɍ¼ɒiԖiɼɿ˼¼Թucc[[izzķuz˿šĿͦĪ˿ͿԿɼuoSoռzuozucziٳͿ[zijǿ˿Ƿ׿zicicczɼļzzzͿϿ·Ƿɞ˼ǿϷǿ[iѢ[°i–o蒉Ǽĭҿ·ҳǚuoioouz¼Ŀ’ij㷄ɿǹǹicѢzǢczzªu[ǪuuǼ³¿¼㿦͢oioou¿·z˿š°Լњͼ¼İɼcڰͭoB[K[Kiuzɳճǿ˿ɹɿ濢ͪzoioozǿzz˿¿ǭ³¹ἷɼ߷ǭ¿ǪǍ˼[K9KoBzɄK[uoiuܚĿ˿˦·ļԦҭuooozzzzzĿuzͿ˳ķڷĭԷ¼ļɰzҳKB[ucKiiouizu⹪Ĺ˰uz˿¿צzuuuuzoz¹zɳķҹ·ɰ¼­zؿiizuo˹ljSzuioooiٚտ๹Ѽɹo˿¹Գzzozuɹzuuzz˿ǷijzѿҼ꿳¿ɹz͹њKSuz9·oioz[Ŀǭǹ­Ͽļzzzzz¿šuoou˿dzĭ㿷ǹĒͿ¹–Ǫšuoĭ¢ziizcccǷҿ¿ǢzzuuĿĿ¿uii˿˭°z୹Ĺ¿͖z˞͖[ϳSizu[˿ĹĿ׿˦zz¿Ǽ·˚uouĿ˭¹ķĹ­ɭļĚz¹[So³zc˿·ķ¹­co¿ϢzĿ¿њzĭļĹz¿¿ǪѢ˳oKoSuzѰicĿɹǭǿ¿ǚϭ¿ǼzĖu­İoѼ¦Ѫ¼ɳozozͷzѰ¼˚׷ѷĿ°˼zĦɿǷ–³dzoɿǢ˼䳪¼ɦͼ¿ԹǪĿ¿ļdz¢zu˹ɞci°oSc¿͞ɳ͹忒¼šĹ˼¹ϭĿ¿Ƿ¿¦zzzԿ¿Ϲ·zuoͪoizuɿdz˪ɼͰҳ¿Ĺ·zǿªzzطĢİǖoiժĦİijɿĦ¿Ģ¼Ǽzѿͪuǿ€¹Ŀ˹uziižռijǿɼտǷĪͼǼɿzzͿšķ˼޿i¦ijĒzc[ĿϿ¼·ɳǹ¹°z˿Ģǰ·ɞĹc­ǰuǰozǪѿǼǹ·Լ¼Ŀ³¹žǼڰ۷zɦ¿žϼϳļĹѷª¼ǹ’z¼ԼɪĦzozzϢzͭijzu׼ĖԿտѿĿɢǼǿļ³·Ěu˼ѿ輀¿Ŀɼ٭ii߳͞Ϳ͹ǹ͹ͼĿع¿Ŀɿ·ɭǿžoĿɷuݳczҰzz᭄ijѿzɼ⼹ҿ¼ؿ¼Ŀ¿³˼·˷ɿ¢­ǿǢ¹խuuzҞ[iizԒǿšĦ˰­梦¹ļڹͿ°ǹ˷ĹϷǦǼ°˷لcouccoo۹˞1KuiĞɷ͉˞ǼĿ³¦·¿¹ɳļҼǭҿ¹zuciuc[cio[zSٞɿϼ¢ܼˢ¹ˢ°·Ǽ¿°·ª¿­Ŀ׼ἰu[ioccuuiS1zĖzɭ¹ǷԪǞ¹ϰǿ·ĿǿͿĦ¼­Ŀ·dzzc[i[ z˹򒒚z׿˼ͷ¹ճĦǿªѹ˿ɰ¼¿ͳ񰪍ccuuK9Biu᷉͢uĿª¼׼¼ɼɰ¹ǹϹ͹¿·檭iz9SѿުķϿ˷ijɼ·ªǿĿɹͳͿķϼǹ㿖梞9[ljǰ۷zĿ˰ϿͿǷǰļ˿ķǰҰ³zɰ垢i(uǒcǼ˷z׷ɹĿǿ˪ͳǷ¿ǰĿİ԰ͿҿĢ覭z91oiiuǰ˼Ѧމ·Ī͢ͷ³¿˭˷ҭͿѿzͪ갰9([İuuɳɉĹĭɿ°ϰ¹ǿͳ¿ļĿͳļǷ¹ͦѼz·Ƿ¼볰[1BzǹoǪڳɹ͹ǹͷ°طĿĿǿǿĪİϦҿ˹밖i9So¹Ǽ­ٹ˹Ŀ߿ɳϿ·׷ĿǿɿǷ˼ijҰѼz[ BzĹdzɼ¼ϹҰ㢦Ϸ¿ռĹ­dz԰ijɹԿѿ(u¼šؼ¿ǹͷɹ¼ļؿϿΦķ‰iijɹѼ˿Ǧ­K1S·ooouz˷uļ¿˿ϳɿ˚ǹ³Ǧ¿ѷ˼Ĺc[idzɳǷ˿ݦ׼1ouzuuico­Ŀɷٞ˹ǿɿĹ͚¹ԭɼɹocuϹǷķ˹ԼKª¿zzc[ªzǿ͢˿ĿǼҢǼļϰuzɼڿ­ɷz׹˼z³Ƿzɳzzzzzz¿¹ڢļعǼĹϭuou˹³ҿǿѰͭ°Ǽɿļļuzͳzoiouo¿Ĺ¹¿泪ɼ¿عǿ¹ϪizuuɿĹɹ˳ɹuuԼǹ·˼峹¹ouϿuuiiicoǿ׼¿ªĭ˿³ĞĿǼѪuzuooijѿ¹ļuoz¿տ¼ɿ¿湦¹zzuĦziccuڼǿ¿ĪĹɪz˿ɷճuzzuuuǷĭzu¿Ģ¼ļ㢪ǼuuԹouoou˹¿ٿ˪Ŀ˭¿Ĺ­zҳouuuzɷɹ¼zɿ¿¦¼¿׿¿¼ޒԿĄoooozĿǼ¹ϳ°ҳǿ¿žzѳcuuzzǿ˹zu°ԿĹɼ԰˚[coiuzļ°³ԿĿǦҳozzǿ˹uuķzչ¼ozciouɳķ­ļǼ׹zzzzzzĿǷuzķžuz˿Ѽ¿zܷ¼ɹcScozoiu˹շϹǷĭɿ˭ؿ¹z°¢oo˿ѹ°zuuuz䷳ؿcKuiuѹ¹dzļɪĿɷɞؿĭ·zouɿѹ³zu귦ճzzuϷɿĭ˼dzdz¼˭Ͽčzտzɰuzouuǿҹzzuz볦iuuiozu˦˼˼˹zѹ˿¿Ң˿Ǣzǀz˞­uzzoooɼѼ¿ououۼ췪ǼS[icS[ii˳z·Ǧ¼ɼzԿzѦĦzzuii˿ҿªzuuǰ쳳oioooozizozļ¹­³zǷ͞Ƿz¹zoozҿ­ziuzz߿즭°iɹټ¹˼uzĖzªuuҿ³uzzuuzĒ뒖ǭoϿ꭪¿ļɹz¹Ҽuzzzzuiz¦zou͹ķuouzuuuuzzĖzɳļİozzϹzzuoiozɼzio˼ijuuooouuooz¿ļϿiiiiizuozoziĢĿĢzѷzzzouuǹooɿijɳoiououuuuz¢ԿzzozozoioĹĿǹuzzѹuuooozzuooo°zzooɿɹԼiiuzzzuzķ۳ҰǿǿˢǿɿªuԷzocccouoooouzo°·³zuoǿijĦuiozzzuuuz¿ǒuooĢzzdzǰ­­ҷzuuoiciuzoioouuou°ļzzĿɪϪzzuuuoouz¹٪i[ooiuzzzɿǿ°ªϷzoioiicuzuoiuiu­Ƿ¼Ězz¹c[[[S[iuzǷϿ¼zɿzzzuu‰zzi[iocc[iuiiouoi¼ļĿǷǷzuzzzzԷª¹ɿdzzzɿҳuuuzzzzz¿zuǿš·˿¹¹zz°¼ļ¿Ƿ¹c[uizĿ„uuzļ¿³ǿ¿¼ļ¿Ŀ¿¼cBKozo9SzĹoKS[[i[[KB19KKBK[cc[[ciiiiciccicciiozuooouoiiouuooooooouzzz¿¿ļ¿¿¼¿¿ļc[[iiBSz¼oKS[cociouooiiioiiiooioooiiicioouuoioccouuiiuuoooozzz¼¿Ǽ¼¼¹Ĺ¿ziziiǿķɦz·ͪoiuzuiݿ¿ɿzuzzzuuzzuuzzouuzuuɼϰzzuuuuzz¿uzzo¹Ŀ߳zzuooooouuoooouzzuzѼǞoouuoozɹɷzzzzzzzzzzuzoozuuuuuuzzzoĞzuuuuzzzzĭǪ¹­̀zzzuouzzzozocccciuS[[i[cccc[[[[[c[[ciɼĞuuzzuuǷĹ˷zuzzzzuzzuչzuuzzzzzuuzzɪ·Ŀļɼzzzuzuouzzzozioiic[ccc[c[iciiiiiiicoicciiǹšuozuuuϷ¹ɼ׷uzuuuzzzzuuuuuzķ¿zǼ˰ɀzuuuuouuouoiucccc[[cccic[cccciiiioooiiiooǼļѼzzuo¿Ǽ¿ɹzسuuuuuouuouuuzzuĿ³ǿͳuzuuooouooiizu[[ccS[ccciciccciioiiooiioiooǪѼoi¼ļǼuzuuuzٹzouuzzzz°°ļϷǀzuuouuuziiiiiiccciiiiccoioooououoouuǷѿuo¼¹ɿzuuuzzzzzzڿĿzǿϳѦozuuuzzuuuoouioiiioiiioooouzzǦĦǿ¹ļļijɢĿzzɿѷ٢zuzzuuoouuoioiiouiioooozzz˼ϼĿ¼Ŀķ¹­¿¿¼ǿuǷϹǢɷzz°˿¿¼¿¿¿¿ĿĿ˿Ŀ¿ǿķ³ĿĿѳ¿¿¿ļ¿¼¹¹ļɭͭ¹¿ǿɿ¿žzz࿖uuuzzzzuu㿒°uuzzzzzzzzuouzҳǼǹĹzz¼¿Ŀ¹¼·Ŀɞ¹¼ɼǿĿ¹˿ijĹ³¼Ŀ¿¼¼zzzzz˞zzĿdz³˷z¹Ұɭ­zzzzzzzzzzzuouoouuzuu՚uozuuz¿¼ĹzzuzuozzuoizĭzuuouuzuzzzzuuuuuzzĹϰמzozuuzzzuuuzouzzucioociuzuouzzzzzuuzuoouzzuщzououuzz¿ļ­zuzzuzouzzoouzuuoiozͪuzzzzzuzzzoouzuuouuoouzzzuuķѳouuuz㼄ziiouuuuouuzuzooouoiouoiiocccoooccioicuzzuuzzuuuzoiozzzԉzuuuuu¼ĹǿuuzzzzuzoouoiiouuzzzzzͦuozuuuuuuuzzouooooouoiiiooozzǷҳccouuooooouuuuuiicczzzzuuuuooocc[[[[[[[Sccccuzuouuzuuzzuuuouzuoooޚoouzzzu¼uuozzzzzuzzzouzzuuooouuzz˪zzzzuuzoooouuoiiiiooooicicioozǹҳoouuuuuiouuoioociooouuuiooiouiiicccc[[ScccciczzuuuzuuzuzzzzuuϖudzuzķҿzzzzzuoouzuouuuooouzuzzķҳzzᰄzooouzuouzzuzuioouuoooɖzĹ¼ļĿ¿Ŀij··¦׹¹ɪzzzz˷ѿ˼uooiiiuuoozzouz¿ǿĿ¼Ŀİ˿Ѣuzuzuuoozuuzozzuuڳļ¹¿¼¿ɹ¿¿uzuzuouzzzzozzѦ¿ļ·zuzuuzuzuzzzzouzzխ·iouooozzzzooouzuz޼ļ¼¿¿¼¿¿¿¿¿ɹļ¿¿¼¼¿¿ǿzzzuuz¿¹ļͿͿĿzɳ¿¼ļ¼˿ļ¿³¼ǿǹļzzǖչ¼Ǽ˼¼ҿ͹–zĿ¼z¼zzzټuuzzuzzzuuu¹ououzzzz­oiuzzziouoooz¿¿zzzzzzzzzzzzzzuzzzuzzzҿͦuouzύzzoooiioiiouuuuuzzzoc[uzuccuĿzzuzuzzzϞzuouuoiiiiiiiiii[[cuĿiciiiooui[o[[ciozuziuzuuuoc[ccǿzziiooouuuouzuoooouuuuoouzzuuuuouuu·˚uuiiouozioooiiicc[ciiouuiiici[Soic[Siuuuouozzzسooouuoioooccooiu¿uiioici[[o[S[[ccouoioioooiccccKcɿci[[ccccccccoiciciouzoiic[uooouozzoij͚oiicciozSouoc[c[[Sc[ciicc[iciccoz[ouc[[oiiouzzzuiouoiioiuo¿·iouzuco[SS[SS[S[[[ci[Scc[[c[[S[„SSSSSK[cccc[[ccc[cooooi[[[[iouuzzooİҞicc[[[ozSuzucS[[[S[S[S[[c[iooc[cc[uzccilj¿˼˰˷¿ijĿ¢³¹˪ɷբĒ[izuKKK99BBB911(199BB999BB1BB9999B91BBB[cKKi[z°ļǿii’cciuuoizc[i[K[SiĄiuoizuic[[ziouzu[[KK[o[BcSzϪǼǷiɢ˹Қ°ԒڷšzucKKBB9BBB911991BB9BBBB99BB9919B91999[[KKSi[coͼļǞuiouuoiuucB9BSSSSSouuziizuui[[uicuu[[K[K9B9ScҦļ׹ϹǷzz°¿ɭҭzڹѦĿz¼zoucSSKBB9BB91KBB99KKBKBB999BB1(999B991Bo[c[Ki[[ii[c˹oiouuooiiB(1BKKKSi[Kcozucciou[K[uuicozzc[[KBB9B99cuczǼ·ļ¼Ǫ¿ɿɪسc‰i[SKSB9B9BKSouSB9BK[[KB999BBBKBB919KB(u[[c[Szz[[ioiSKozcSocuoiiououoou[KBKSSSScĖSB[ouzzocS[S[cSK[zzuuiouooci[91B999BBSzˍ˼·dzoͿİɷɰķԳuǿzǍucK[icSc[cooi[[SKB999BBBSSBBo[BKKicSS[[oS[[ouccu[SKSuuoiiuuoiiSSKSSS[oiلK[ioiouzuii[SSBBBKK[zuuzzuocc[99BB9B9([؄ϳǹǷɳouĿªĖĭԹѭǷ͒icu[KKBB9BBBKSKBzcKuii[[[ucSK[io[SSScoiioiicc[i[ScccoSiociciiicc[SKKKBBKKcuouuuuuz[SB999K9¼ǼǭǪǹoz˼¿Ԓij˿dzuzzzucKBBKKBBBKBSמzuuooiSSK[ozzoSKKS[cziciioiBio[S[coi͍iiB[cic[ccSBBKBBKBKioiiocui[SBBKBB19ڷķcҿ˼uļɹݢo܍ǞoiozzzouuSBB9BK[KB¢o[SKK[uouuuziS9K[i[czoo[11[SBKScuoɭccoSBcic[SKKKKKBBBBBK[zuo[K[ccSSKBBKBBBi¹㷳iɞͼ˿ѳǰչ)ϰocoziuzuuzzuiuzzɦzc[zSKKKzziiouuiuzzcK9Soic[cB19BB11K[[uɉBBBBKccSSKBKBB9999B9Bizoouzo[KKSKK919BB99Sz··ئ­ĚͿij˳oͪĹչπļ¿z[Souuzzzz¦u[cuuicioiicoi[[ocSBB[i[[S[o91119B((BKKuϰK1BBBS[SKSKKKK9BB1(9(KiSK[iK9[o[99BBB9[ScĿĹĹ䳖·ķǰ–uozzĖɪĪ[izuzzuuzۢocouuiccoc[co[BBBSSSSSSoo99B91199999Biĉ9KSBBK[SSSBBKKBB1 1B1ouSBB[iKBcz[B999KczKKK–˷Қķķٿ³ˍczǷٹҼzuuzzocizխu[K[zoooiicS[iiKKBBSSSSKBKSzB999991199BBScuSSKKSSKKB999BKKB( 19KzcK[coSSScSB99[oSS[BǿǷع¹¢dzdzǪuoɭɿǒĿooozzuuooz[KSozzuzuiouoic[cicKB1BKBKB9BKKK111(11(19BKKSocSBKSKB9999999919119Bozzc1KiociiKS[K9¢ɳ¿­ҿ–ѹ[ɰķ԰uozuooizzzoc[Գu[KiԦzoozzuuuiccic[K11BBKBBKKBc[11(1((1((11BKS[KBKK1(((1991111(9BBSzzoɿcSioKSK91ѭ¹ڿϢް¹z׷¹ܿ׿[ўɞc[izzuuozu[cciouSoѦi[uoiouui[iic[K99BBBBKKBK(11(1((1( 99KScz[KKKB1((19911(1((9KKozušziccSiKBBK[ļdz·ϭѢ¹ɳuo˪ɷ⭖ɳĢoKcuuuuzzuoocizoi[cooicSijzzuozזzciozzccco[cSKBB999BKBBoo(((((111BS[SKB[[BB9KB1119B911119BKiicc[[B19BKSSoS[ioɳžɷɹ͢iiz¹°բ¹ķuiuuiuzzzzi[cuiKKcoo[K[zuozuiuzSci[[ccioiS[KSKKKKKSSSiuB1( 1KSooio[B11KoSB9BBB9999B9199KK[zzzoizSBSK99BKSSKuS[ooĦͿǿͼڳǿǼԹi³ɹπ׹·ͳ淪˰ooozicuozzcucczSB[oiiccozBBKBB[ioicKSSSS[[ciico9(1KciuzziSS9199K°[[SK9119B9BBBKKKSiozciuKKKKKBBKKSSoBBooǿɿܳҳϼѿ¿˼ͿĒ­Ēؿ¢ѿǒoizoiiuuuz[9co[cc[cizuuB9BBK[cc[SKSSKS[[cccc(9Szcc[BB9919BB9z–u[ozuSB119BKKKiicooczKBKKSB9BKS[izSci¿ϷĿϿ­׿ǪİĹo˹͹ϭԼ¢˷zuoouuicoczi[Ki[[SS[[uzSBKSci[KKKKKSKK[i[SS[ Bic9B9BSB999BBBzuSiziii[ccio[SSKccou9BBBK99KSS[[°uS[¿Ҽ¹Ǽdz˿ͪҹǿczz˭Ѫz–ɼɭoiuzzoiKccc[[oii[SSSiccoocKKKKKKKKS[cSBBBo1Bcc19BSSK9B9BBBoizšzoc[SBKSKKuooiBKBKKBBSSSKSǖKǹɹ˼ɿ°ͿԷͪͦziuiϷ׿Ϧ˭¹ķzuozzuo[cz[c[izzoc[[[uzzoiicccSSSKSKKKB9K[KB9KK9ic19KKKBKSBB9BSzĖuioizui[S[[KK[BB[[oSKSK[KBKSSSBޢķĭٷļ͹տĪzİذ˿ϼɞĪuuzzzocuucccuouzocc[czuzo[S[KS[S[[[[[B9BKcc[K9([SozS99B9BSSSK91KBoɍo[KK[[KK[c[SS[SK[iKBK[uBSSK[BSSSKS[弼Ͱɹɷ¿ǰzͳϖSɷiߢɳ¿ouuuzzuozzoii[Sczoiuzo[[ioocBBSKKSS[KBSSc[Koii[B99BBKKKKB91SBi׍KBK[ccBKii[KSc[Szc[SSuzBS[[[S[SBBcɷǼĿުϹԹ議׷ϖгɹ墍Ϲ˷uuouuuuzoiozoc[SK[zzcioouocic[SKK[[KKK1BooooSB19BB99BB99BcBiͿSK[[ciKSoi[SScioSSKKuc9SS[[SSKBKiǰļ˰˿ϼǿٿѹҦuݷҹѼϞzuuououiiiuziS[[SSuz[[iiozzzizi[SKKSSS9BKSzc[SBK[cou[ScoucB9999BBB9BBz9[uoSSccozcKcc[[ciziKKBKozuzc[SSSKKSu˦Ϸͳտ׿¹˼ĹͿ³ϰ͖˼Ƿǹѿ­ioǒioouooicioi[Scicooi[coicioccSSSBKBBcoK11119BSK9KcS19BKcoiSB99BBBBK9z1KSco[BKcioucK[cciiu[KKBSzoiicKcϚ㰿쿳˳ǹ¿ԿϹϰ׹ɢɚѹǦͼĒošuuooic[cc[[iuocziccizoizSSK99BSu[B191999BBK[KBSB1B11KioiSBBBBKKK9o1BciSKSci[SS[ciiiooKKSSiuĚz԰¹߼Ŀdzǹo˭ѿ˷˞ҹªڳz׿zuicS[[[couicuociuoSBKczziB(9KB9B999B9BBKSKB91BKK[oo[BBBKKK9oKSzoSKKci[SS[ciioouz[BKS[oicuozٚc[ѹڼح¿׿Īذǚz׳¢‰ڰuc[[iuuuizuioiSSKK˿cKKcSBBBKBBKBBBB99[u[B9BBKBK[ii[KSSKBSɢ[[oic[S[[SSSKizzo[ioSKSS[ocSc[[iz٢KSKѼǼ˹ɳ°ҿϷĭԷ޼˿Ͽ°ϼԳuzzoozou[S[[iĪBBS[[[KSB9BB9BBKBB[uiS[SKB99BKcoc[[KK̀Kizu[icSS[[cS[iouococKKKKSo[Scc[cu[ݳ[BB9ܹǼɿ¿Թ׿ͦĞ˼ĖѼǿѰ˼ǖϳzuĪzi[ii[cziiuciSSSS[KKB9S[SSSKSi[KicSKBBBBBcucSKicScuu[K[[SSS[c[[cc[cuSKK[c[zc[[cciouoǀSB91ҷѿɼҷ˰׼³ǪǷɭٳ˭ѭǰҿ·צu[Kiuuo[[iucK99KKSBKiiicSSSKBKKKSKSzS1ҹccozzcKK[[SSKK[[S[SKiiSciocoi[[[icccioϚiB999ĭɷǼ׼㳷İϼݿڼĦͳĢ˭ĭϿўѼouozoS[ioSBBBBBB9ouzuic[BBKKSBKccԒ[cou[KScii[SSioSSSSic[iiuuS[uu[KS[KzϚuSB19B­ǹǹڹİ׳Ĺ³¹ɖǼԹķdzoǹǹǢcczucciiuB9KKBB[ǰociuzzz۰ucK[o[KK[ozuiiczSBK[i[KizS[uoSK[[KKuҚiS9911BɼļѿĦҷzǚǿĖĹҢѪ˼·Ϛ°ɞuouuooioozc(9BBBu˭BBKSizoճ͹oSKKK[ouici[oicSSczoSBuoS[ccKS[KBBKucB99199޹Թ¼ͿѪ˭ooɹռ߳Ͽҿ٭Թɭ¿њɒժoiciooiii9191BعSBSS[uocS[ɀoc[KKKSc[[[S[[c[[iiSKzoSKKKKSSSBBKBB[oiK919B91˼鹰ĿͭݷooǷčǦdzϭҖۼҼĪĿ뼦Ѽצui[SScccccoc99BoɦoKBK[ioSc˪zzSSuzocSBKSKKS[[cccz°uicooiSBKBB[SBB9KBKSSKB1199(1ڰɿ˼ҷԷҭϢuuİͷ͢բئĪªªټķ͒icSSSSKKSSSzB9cci[KKSioS9i¢zo[SKBBKS[ccoiiiucSKKBS[K1BBSS[KB19(11999ļ¼ߪ¼ļĄܿuuϹ¿ǿǷѿͳ°˷ǚ€[[SSSSSBBKBoB(uS[[S[cuziBS’ozuuoc[[SScozui[BKKS[SBBKKKS[BB1(((191(ķԿ͚dzĹѭzطĦ¼ǞϢ˼Ѧɼ׿·ҷļԞ˳žհziiSScc[KBB9z99uB[S[izѹouuuzzuooiiiouzui[BBKSSSKKKKSSK911((1191(ɿ¿Ĺ۷Ĺ˷·˚zڹdz³zҿĪļ˭°ɞѹѳԿɪɍoi[S[cc[[S91i1iccKoѳziciiioicc[ciiuocSS[K[[[SBBKK99B991(19911ļǹͿռɼ۷׿dz¦ɿļͰ٪檰ͳǷզo߳cSSSK[S[icSK[oBcoiK۷ccccicSKKK[io[cio[KiuS[SKKKSS[KS[c[KK911((¿ҿijٿͿĹϭuǿط͹ĦɢɭךĭĹسԳɿͷɭu¹ՒKBKKKKKSc[S[cĦzzoɦiK[cSSSK[[ozcSc[[BBiiS[SKBKSczi[[iiicKBKK׿ļԹɹˢ¿չٿ¹׭ªطϷǹѼĞzɿѪiKKKKKB9BSSBoİԹuѪ[9KSK9BSSicSSuzSSKKSc[SKKKKSoz919KSiuouuuǷɷǖ¿Ŀڼ¦ǹĪɼŖzz˞iSSSK9BB99KK9˒מ[BBBBKKKSuccu[KKK[cc[KKKKSciS(1199K[iiuu¿ްǷͼҷ῍ɹǿ³԰ҳϷϹ·ϭϦoiuu[S[SKK91BB99B9Ki͞ozѦiB9KKBKKio[KKKcc[[BBKSS[cS9((99KKScii˿ҷ࿢ܷɳ۷ǼعSͦɪͿ˳˞حu„ciiKKSSKKKKBBB991BBizϹzizզiBBKBBScizzcSBKS[c[SK[[KKK[S9111B[cciou¼ؚڹժ°չԿĞĿǰ¿Ėz͖z͚ioo[zڰiKccKKBKKBKBBB9K[ڪٰ[1KSKSic[zc[BBS[K[SSS[[K9BKS9111K[iiiuu޷㹉տ–ĹǼͼҼ¹Ī׿ǞuouoSuۦoc[[SKBKSKSSBBBBBuܢזBScKB[cKuoiBK[SKSS[[BBK91B[S9BBK[[[ioi٢Ϸҭ¹ɿķǦѼou·ѹͰo­ܿ’ooooi[oܳui[SSKSS[c[KKKKK9K՞ˀiiKBBKKcKS[[[S[cS91K919[iB9B9KSioccݹϿҞĢѢzĹ˼ĭ˿Ϳˉcļɚҳķ˚iouccc[cڰzucSSSBS[ci[KKBKB9c˪ع՚[BBBKzKSKS[[[[SB91K[B1SzS9B99K[SK[˞ύĿǹĹտļªԹժϳošͭucoi[S[[[Īuiic[[[S[c[SSKKBBBBu˳ͭѭKKBi[KSSSSSBKB919BccBBz9999SK9BSѭ„ɼǹª˹ɹѼ[Էǰɰii[S[[[[SSoziciccozzc[c[SSKKKKSKԳҷǪcKcuiK[SSSKKBKScKKB[uoSKBKKcSBBSĢϹɹɰ­ϷĢoѰiij¿¿ѭiccSS[SSSKK[[[iiccuiSS[SSKBKKBcբҼKzcK[SS[SKKSocS[iuiz[S[[cKB9Bɿɹķ­dzǰoz˷·Էuccc[S[S[SSSS[c[ciiciuo[KKS[c[KKBKzϚ׿޷u[iB[[cc[KKSuiKBKioiz[K[ooiSSBdzĹķϼ˼˹¼„iccccS[S[[c[[c[SS[cc[[SKKBKccccS9cɢ°ۚz[KSS[[[S[[cuziSKScccicSSczoi[ռѪٿ˼ǿ¿Ĺɹ˿ǹijĭoiccii[[SS[cccc[SS[ciSBKK9BKScc[[SuѼԪ˿zoKKBKS[[[cci[cc[[[[[S[oo[K[iii[ҪԷɼǷǹ¿ļѳѳ[SS[[KSzuiuicccioic[[ccii[SS[ciiSBB99BKSc[[uտڷĿ׹oucKSBKKSS[iciii[[[KK[ScouiS99BK9˹ռ¿·˿Ĺ׷ɦiSSSSKKSioii[zuc[iuuuuoiicccicccicicciSB99[iiioz³ǢڪzocozSKSSKKKScc[iiccSKKKS[[[[SKBB11(Ϳۿǿļļ¿ڹǪz[SSSSKSS[iiu[[KSizouioooiccc[iuuouoioiKBSuzɖoǷגcc[cuBBKSSSS[cc[[[c[KBBKSSKB919BK99[ڼuϷ׹˼¿·׷˭ijSKSSKS[[iozo[[KScicoioioiiccciuzoo[KSzzic[Soz¿cڭicS[coKKKSSSKS[SKKSSSSKKSKBB99BB99c͒ĭouɿij·Կšͷu9BKS[[[[cuS[SS[c[[iiiiiuocuicozoiccuuico[cSiuzc˚c[[[ciuĭSKSSSSKSSS[KBS[[[K999999999zݷuz­zzuudz˿ǷijͭzKBS[SSKu[SS[cc[c[[iocioiizuiiiuzico[SSSc[oioooii¿ϼS[c[[[co[SSSSSS[S[[KBBKKSKB99BK99cǹuԦzzĢuuozouzzɷ¿¿ijǞuuuoSSo¢i[SScui[icScicc[[ouoiiiiouicz[BBKS[ciuoiizui[ķi[ioioi[[ciozoKKSS[[SSSKKKBBBBBcocSS[oϰuciҳiu͖zzioziuuu¿¿ɹҼc[¹­o[[SSiuoiioc[ccc[cciiciiouuicouS9BBBSiiuoccouuuuoccĞu[oz[[c[zcouKK[[[SS[KBBBKKSSKczoiKSc[Ĺuڹzzzuzuiiuuzİ˰¹¼˼ϼĒcS˰[c[[[iouoiuoicccic[cicioouuoccuoS9BBBSciu[ScicuziucKSª՞uĦi[c[[uz[K[SKSSKKBBKSKoico­oBB[[S¹չziuo¢ociiouuuzŒ³¿ĭ–cBuɖoiioi[cuuoccioc[cc[[[cciicouui[iui[BBBK[[KK[[ccozuzS[c¹㳀zuuScuoozoi[[KKKBBKBKSKBoScuK[cSKK⭒Ϲuuiiiiioozuuouij··Ϸɭɢc1uĖzouuiczzi[[ciccic[[[cciicouocS[coiK99K[K9B[[[[iui[c[¹ļɀuuSc[zo[ic[KKKKBKBBSKSz[KcocSKKSuǭzzociozuociiuuouͼϰ˳ϳuڿzzuzcSS[[Scoicc[SciiciicccSSci[99SSB9K[[S[cou[cS[ݿ˼҉zzzziczzcScc[SSS[SSSBBK[ooSizo[SS[ǖ᷼Ħzzuooozuouoiiouzzzu¹շѳɿzo[S[SKS[[c[SSciccioiccSSScocK999KSSc[cuiS[KiժڹגzooǷoSKS[SSS[cccSKBS[couic[ci[[[[zuciĭzucoouzooz¼ɹǢѹĿoooic[[[ccc[[[icccoiic[S[[iuiK9KKSS[cuzuiSBԦݚcu¦[99KKSSS[[[[[[[ciucS9BKSc[[uicc[ڼɼoz[cozzuuu͹ͦؿǭzuic[[[S[[[[cc[[cioic[[ccoziK9BS[KcooozoBcύҷުocciSSKKKK[ccic[uouzo[Sϼ³izicuuzuzz¼ϼǪϭ­c[[[[SKKKS[S[[cciii[[ioozuiKKK[[ScucioiBҒ˒עii[uzo[BKSiiiiiuªioĖi[ļͭϿշiiozzouzzu˿ǭǞzuzoii[SKKKScc[[ciiiiiiccuuzzu[KK[iuz[KS[SB˪˚࿄ciicBSoooiocco€ciou¹¿ķͭǰuiciouuzzoǷǰɦuuѰcS[uzui[KKcuoc[ouoiiiiozuuo[SKSuoK9BSSKKͭͰǭۢzuSiccc[[iͿuicuπciuzz¿ҹzuu߼ǿiccizĹocuϷɭ˭uuSK[S[ozuzuoc[izuiiuoicuoiooouuuSB9BKKS9oۿ԰Ěi[uoii[SKKoĹٰicuzuu„ozoiuϳǼzoiiozͭzzuuoϿͷ˰z¿KKSS[[[iiuuzzoiioiouocuoiiuzuoouzKK91BBBS1عݼuozcizuoSKKKKSiѢo[[uzuouĒooiooչİzzzzz˳zouѿԿ͹­SS[[cicooiiuzzuoiiiciuicciciuiccBK[[KKS[9ԹªzzzuSouKKBBSSKcz·‰[[SSuuuouzĹİzcouoհϿuozzzzɿҿɰĪªdzKKc[cSSiiicccizzzzuciuicciocizcKSuicc[iҿխuiSucKc[SSSKSo°Ͱ[[[S[uzuuu¿ǦocoozզϿoiouuzzuuz˼ɪɭҷ 9KccKBK[c[SKS[cozzuzuoiS[ououuoSBKuzuɳ˼޳izioSS[c[[cccoͷ˼ѿicocc[cooooo¹ĖicuسĭzoiuzocioɭѷĪճ( B[ccSKSSSKKKSSSScuziozucuoSK[ozuɦϼ[zzzziSSSSccciiuǰ°Ģo[ioooc[czzuuǼɳڷ˳zuuzzɞĿ˼¼İ͞[19K[[SBKSKKSSSKSSKSiuzuzzo[icS[uuooiհ͹oĦoiS[[S[c[[[iuǦĿocciouuiSS¹¹۳Ҽɞ¹°˹¿Ŀ˳շc(9KS[SKSSKKKKKS[SK[cc[[[ciuzucS[[[coǞicoio¢˪u͹oiS[[[coui[iiuͿϰuoo[Scuui[S¹¹ܰͰzzšǿİɷ¹¿ͳհK 19[cSccSSKKSBS[S[[cc[BKKS[[S[cc[c[[Sc¹zS[ciļ˞ouuͪuiSKKS[ozuzzuuzĖzouic[SSouic[¿۷šuociuoiiiczzzuz’ɹĹ¼Ϸ˒9 19SioBKSSSBKSS[[[c[SSSKBB9B[iic[[S[zz[KK[cĿҼĿucS[SK[ioiciuuioouoouiccuoc[طͪi[ccc[SS[uuuԿļİļǿ˳ĖK11B[uuSKSS[SKSSSSSSS[[KKSKKScoocc[SKKiiccSSSoɢϷ˼°ociuc[icSSSSccizuuoouziiiiuuoiճعuoocciccuooҼz·°³³ͳ͒((999[cS[[[SKSSKS[SS[SKS[[[c[coccSB[iocSSSհĢoicouciicS[[c[S[ioozzzouzװ׹zuoiiiozouҼտĹĹ·Ѱz(1((9Sc[S[SKKKKS[SS[SS[c[c[[Szo[[[[oziSKKSiչؼҿooi[iici[SS[[cci[cuocoo׳ϰuouuoiiuuozҷz·Ģɼ¼¼ѭo (119S[SKSKKKSSSSSSSS[c[[[[S[cS[[SSiuSBBKSoˢϭuci[coSSc[ScczziuoooǞǿ¼ٷ˭uԳo˦·¼¼Ĺɦټ[ (119SSK[SS[SSSBKSSSSSS[cSKSKKciSKc[[S[cuզϪzicocKK[[[cozoiozuzѼݼ˷uzͰļѭĹĿ¹׿Ֆ9((11BBS[c[SKKSKKSKSSSS[cSSSKKciSKcu[c[SizzؼzuѭuzoKBK[[cioziciܼǹzuuͰŖİĹĉԷz91((11K[ic[SSSKBKBSSS[SS[[[SSccS9[ucS[[Kczҭɚuicu˹iBKSSciciouzoouuuuz³ozzټɳuooioocc[iǭ԰¹ĿϪcϭ׹[((1119B[ioSSSKBB9KSKSKKS[c[icc[BK[KKKKKczzu԰Ұzoccizɞ[K[S[ouc[couou°zccci¼uouuҷzzooooicuĪuzĿϷĹ¼չoǪԞ1(111((9[o[[S[KB9BBKKKSS[[Sc[c[ciSKSBKK[zuuzuҹ˖uzi[[B99oɖSK[occciiouz[cSKBKSSSz[ccc¿zuuouѹzuuuuuɰuu͹ǿϢzcuҹi 11( (9KS[S[SKBKS[SSS[[KKKKS[coi[KBBBSizzoouzǰԿiSBKi’uo[Bozic[ioK((119BBBBcioioªzuzzu˳zzzzzɭzuϼǹiKBͦҦKB9(11( BS[cKSSS[cSBS[SKSSSSSS[ocBBKKS[izoouzԳzuzzzouɳuoou[zo[KKuoiozK91((((1B9BcuuuzuzoϹzzzzuzǦzu˷¹9K9SտɉBB111( (99ScKSc[S[SSSSKKS[[ccSSc[KKKSS[[ciiuuozzўoooioozǢuooozuSoiiii[S[ooKBcuoBB11(11((1BSc³Ϳ˰ɢuo¿°Ĺ’1K99ѦԷS19111((((B[c[cS[SSSSSSS[S[iiiic[KSSS[i[[[Sciuɖuoucczz[BS[[SuccioziB9[uuoBB9B919BSK99B[ļ¿­Ϧoz͹¿č9911BǦҖ(1111 ((B[[cc[SKSSSc[iiS[[ioci[SSSccSKKcicziz˭zuioѹK9ii[iuuouzcSScoS999KK9Kcozo[[zϼϢuѼļ911B9cԼS(99((1( 9Siccc[SS[iuzucKKS[coio[SSSK[uoozzuuzouϳuzzozݹo[zuioz͹uicSKSo[K9KBKSBS[ici˼Ϧϼ·(19BB1˦щ911((1 ( (9Kcoicc[Sizooz[KS[[[ioKSSoiuizzooozҷzzzoڢioiuouiuĹ[KK[uz[KKKSKK[SBK[ii[zѷ¦ͪɹļ9 1BB9BռҷK(1((9( ((11BScoz[Sc[[zzc[cic[zcS[oKuiiooiouԹuzzzɄozczzuoizBBciiKKBBKKK[KBSiucuѷͿĦzɿǿǼ¼[1111(͞o119B9( (((1119[zK[[Sooiicc[iu[ucKoicioooԹuzzuܚozuo[B[uzuSKKSKBKK99Kciou˳zziuǿ¹zo9 ( S׳՞(1BB(((((((11(9uͪiciooocc[[ScizizoSKcuiccooouljouozzuouz[B[uzcSSS[SBKKKBS[[uz[ݹɳu¦oizɿ¦z911(Ǣ[(911991(11((( 9Ǟiczi[SS[KSSiociocSBKSzzuiccuzoo͍ooiiooiϚcouuuzuuuzc1SuĄcc[SKSKKKBKKiciKݿ˹¼zzzu³uiS(cҰԖ1(9BB9((1(((((1BuKKSKKS[cc[[i[KBBcuicccizzooǍuociiuzͼuSiouozzzzciiccou9Kcu[[[[SKKSSB9Siicɹzǿ¹oSKKz[19ԿճK1B991(11(((((19KuĪ[BBKKSS[c[[io[B9Kco[ccicouucoǖoiou͢ccocoi[[iiizKBScci¦i[[[SSSKSKBSoucǹuzoicooiouzĢz³ɄKBB9Bzc(˦i9B99111111(((11BSuĢzSBKKKSS[[SSicB9Kioc[[[ciou[cuuuɍcou[oiiiouB9SciioĪicic[cSKKSSKSio[ɦuiozuooic[c[[ciu˭ĹDŽSBBB9BicSԷω11111191911((((9S[uɭSBKKKK[[SKSSKBKci[[[[icoocciĢzz˼[coozoiu99Sciizo[iiiicBKSKKBcouK[oiuouuic[[[[SS[[[[cczϳļ˭[KBKB9BiuĢ͢9((11 111191(((1Kcci¿oSSKK[c[SKKKKKSci[[cio[oiciooǦҷzccuucuo19SSciu[iiioo[KS[[ooziS[S[iicucSKKKSSSSSS[[[[[zϭ˰ªĿziS[SBSS991[ϭ͹c(((( ((11(((((9SioooSK[c[KSSSS[SSuocS[cc[oiccuo͹ؿuuzzuuuoic11KKScoKc[[cc[SiuzoKKcoS[zou[[[SKKSozϳciiSSSSSSK9BBSizuic[ccSK[ii[SSB9BBKKzuzzuoi[[cSKBBKK99BBKKS[ui[icScicS[[SKB[zѿo[[[KKKK9 oB( (1  (Kcooiooc[ii[SS[iocuzKBBBKKKB1 1BcuzcKKSKK[[KS[[ciiccc[[ccccciccSKS[cuzzuuoc[KKB1(((( 1[zzuo[SSSccciic[icK[ScSBSoSci[ccSBKKBBB99KSiuui[iicSKKSS[[[SKKS[couiciouucicSKBS[B19BB9BB[icccic[[cc[uz[[SK9( 9oB(( (((  (Kuoiiooc[[SS[ciooĞo[B( ((1SSBK[ccioi[K9BKKSS[SBSiuo[[c[[[c[c[cci[[SSKK[[[[[coiozuiicK99SuuiiuiSSS[[Scoi[[c[9[S[SizKBKcoS[[[K99BKB91B[ouuuoccoc[c[KK[c[SSSScozz[[[couuziSKBBSciBBKK9KBKc[[izoici¿iKKB9[o[1((1((((  (9iuuoic[[SSoɢ[ ((Kiziou[KKKKKKKSSKB9BcoocSScSS[cci[c[SKS[c[c[SSSKKSK[cuuuozzuuzoc[SuoSSS[[S[[S[[[KBoS[oiSKSc[SSc[B99KSSKKKizziiicoi[S[[S[ccc[[iiiuuo[S[ciooouzucKKB9KcoSKSSS[[cS[izoiϭuiiժSSK(1izc9( 1( (( (((BcuocS[[[z³9 (9[iuuucS[ii[BBKSSKKSKKBBScc[SSSKKSSS[[SS[SBKScc[[SK[[SSKK[[cc[Sciuuiiiicc[Souic[[SSSSSS[SKKBociz[KScSKKSBKBK[[S[iuiiccc[SSK[ioi[[[S[ciuocSS[cooooicci[K9(9Su[K[[S[i[SSciziuocz’cSKi[K( BzoS( (  ( (Boui[Kiu9 1BSouziScSSKSSBBBBBBBKKKBBKKK[[SSSKBBKKKSSKKBKKS[[SK[[KSSSKKScii[SSS[i[[[[ccc[KKzuoccScc[[[[SKSSKKBKBzoiizzSB[SB9BK9K[[[ccoozzic[SKS[ccii[KKSKSccicc[cciiicc[S[couiizzcS[[[ocSKS[SSccuSS[co[B 1SS[ (((11((1  ( (Biucii(1BciiiiiccSSSSSSB9BKBKBBBBBBKSKBKBKSSKBSSKBKSKKBS[[SSKSSKKSKS[[[[cc[cc[[[S[c[[[KBB[zocc[[[S[KK[SKBKKKKBK9˪uouoziKBBB1(9B9K[[iuuiciuioi[[[SS[iii[[SBKKKS[[iiiic[ccccc[c[S[uucciiic[[cSBK[zͰuScco(( 9uuK9  11 1(19  (  Biuo(([oocSSS[[c[SKKB99BKKKBSKKSKSKBBKB1Kc[KKSSSBBSK[cc[[SSSSKKSSK[[[[[[[cSS[S[S[ii[B(1Sii[cc[S[[S[KBBBBBBKSKK[KiiiocK911(19BKKS[[coi[[cccicSKS[[cccciccKBKKK[Scioiccccicc[[[KBB[ioocS[izuccii[[ocK[z˒ccccB1Kzc( ( 11 (91B1 (   (SuooiouBBcocSKKK[[[[cSB9919BBKKKKKKKSSKBSSBK[cSKKSKKKBKSci[S[[SSKBB9BS[KSSS[SSKS[[[[iicB19Scc[S[SSS[SKSKB919BBBKK[c[KSc[KK9991B9BBK[[S[c[SSS[cSS[SS[c[cc[ccSB9S[Sc[iiiccc[[[SS[cSKBKBKBBBBK[ooioiiciuoouio1Ku[B  ( (((119ci1    (Scciu99cicS[S[S[SSK[BB9B9B999BKKKzoSBBKKBS[SSS[SKKKSS[[ccSS[[BBBBKBBKKKS[SSKBKS[[[co[B9B[oc[SS[[[SKB99991BKBBBK[cicoBS[ccS99B1BBBKc[SSSSS[[S[SKSS[SS[[[[[[KBK[icciiciicc[SSS[[cc[SS[B99KKBKS[[oucocuzuuoB(czK ((((( ((1ozB (   1[ioz[([uSSKS[SSKKSKB9119999B99BKScKBKKB9S[S[c[SKS[cc[SSS[[KB19BKSSSKS[[[SBBBKSSccc[B1K[cic[S[[SSKB9B1(1(9BBKBBSSci[c9K[S[ocKSB19BKS[[[[[S[SSS[Sc[[[SKSSSS[SKKcuzoiiiiicc[SSSScoi[[[[[KBKKKKSSSS[iiz[[S[uzzc9BzS1   ((((( 9ouB    1[uBicBKSB999B9BB9119BB19999KS[[BKSSB9BSScciKB9K[[c[[[[S99(199B[c[S[[SSKKSSS[S[[[[9Bc[KS[[[S9BBBB111(119BBB919KK[199KKK[o[BBKBK[[[SS[SSSS[[Sccc[[KSKSSSS[K[coouoiiuuoccS[[[ozoii[SKKKKKSKKK[SKKouz[SSioiS 9cziB( (   ( ((((SiK1     ( BuSoi( ((1999911BBBBKBBBKScSBSS[SK[SK[[[9KB9KKS[[[K9(((199BSS[[c[KKS[Kcoi[[[[K9K[[S[[SB9999BK11919BBBKB9B99Ku9KSKBB[oKBKKSS[[[SSSKKKKSSSS[[[SKSSKKKK[ccooiccoiuuoiccioozzozoSKKS[KKBKKBKu[cioizu11z[((1(((( (1(( 9oo1 ((   9[iK (19BB9B9B9BBB[ziBKS[iic[KKSSS[ccKBBB99BSS[K911119BBBK[KS[[SSScoouoc[[[[S[[[[[[KB99999BB99BBBKBBSKBKKcK[c[cc[SBK[[SKSKS[SKBBBBSSKSSBBKKKS[SKScccoocccicuui[[ciociiiuo[[[KKKKBcu[Sccziz((KiS( ((( (( (99  iz(   9[zzz((9BBK[SK9SKKBBSiSSccccccSSKKSc[KBKKBBKKK91( 19BKKSSKS[Kcii[c[oucc[ccSSSSSSKBB99919BKKBBBBKBB[iicziuoic[99KcccSKKKKSKB9BKBKBBKSSSS[SSSSciiiiziS[cciouocccc[SSKS[[ozicc[cKcšo[[S[[czczzo9(K1 (1((((((( 1B1 B[o (   9ciBiocS1i[ 9SSKS[SSK[SKKSSSSSco[ccc[SSKBSc[KSKSKKB9((((((9BSSSS[[[Siuoc[cuzic[c[c[BBBBKB991199KSKBB9199Ki¹uoi[KSSScc[SKKSSKBKKBBKKSKKScccoociiiioc[iz[K[cciizoc[ci[KSKKBKSSuz[ciccoo[KKSSSoo[ooc1BB (1( ((((((( 11 ([iK   1ic1 1SBKBz1SSSSSKKK[SSKBKSSScoiS[SSKKBK9[[SKKBS91(( 1(((1BBKSS[ccS[cicSSciicicccco[999199B1((1BK[SBK991BioocSSci[ciSBK[c[KBKKKKScicS[cooiiioi[cooiioKBScciozu[[ci[KSKKS[KB[uuzzcScczoSBSioioiSi[1 (K 1 1 (( (( (19( (9S1Kc1 ( (  Bzuc(  999BcocKKSKKKKBKKB19KK[icKBSKKB[c[S[SKKSB9( 11999B99199BScicKS[[[[[iiccc[ciicKBB919999((9KS[S99BBK[³uuuiuuuiiicc[c[KK[i[KKKSSS[ooccc[[ccic[KK[iic[SKSciioiciS[icSK[KSSSKKSioco[BBz˦iSKSuzoicc91K9 ((( (((( ((1(((9Sc(((   cK(  (K99BSuĹzSBSSKKS[[KSSSS[[KBKSSKczuiSBKSSK1 (99KKBKBKKKKSKK[[[[[[cociicSS[[c[B9BBB9BB9919KKSSKB19BKcǼuc[Sccuzuc[SS[[co[[ccSKS[S[[ccccoiSB[ii[c[[cc[SKccS[ioiS[oiciSKK[SKKSKKS[zi[K[ciuzo[[czccc9 K1 (1 (( (( (9( (Koi9    cu1 (B[oiB[ooouuzuucBBci[SiuiSKK[[K1( (1BKSSKK[SKK[KKS[oo[[[oiicSSSSSKBBKBKKKKK99BS[[cSB9119Szǭzoiciiiooi[SSSS[[uoc[[[S[SKSccScioocS[ccccii[S[SzoSS[cSKSuoc[[SS[KBKBKS[ouc[i¢9ccooi[[occK 19 (( ( ( 1 1(19( 1KuuK(    u[( 1[[ii[ooSzSK[uuuozui[cozcoiciuiccioiK( (((19BSSSSSSKKKKSSSczcioic[[SS[K9119B9BKSSSK9BKScc[KK9BKzǦocccicccic[[SSSS[z[KSSS[SKSicK[cico[[S[[S[SK[iocS[[[S[cuu[[cc[[[SSKKBBK[Si[[o[couioz[SB (K 11( ( (9((9(1( Suc( (  Ko  9cocoBSouiBc[S[1((99999KScoK((((((9[cio[SSSS[[9B[iozucoucSSKKSK91(1BBBKSKKK919K[c[[[cco¹iK[iic[c[[[[[[[SKioKK[[SKBK[[KSciciSKKKSSSKSiuuiocSSS[SouzSKK[cSKKSSK9BB9BuoKcui[cozzuc[B B9(1( ( (11191( 9oz1 ( 1 icBKKzuiSiuS(KKBoi9 19BBKK[zo1(1911BSoucoiS[[[[SBK[ciiccic[SKK[[KBB9BSKS[KBBKB9BBS[S[uǹi[K[cc[[čc[SSKSKK[[KKKBBBBSSBBS[[[K99BK[[[S[icK[i[KSKSuoSBBKSKBKBBBBBB9ou[[Sioccouui[[ B9 11 (  ((99(( KzzK ( ( ((1(o(KB1[S[oc9 (BuuS11iª[99BBSKBKcuuoiiiici[(99BK[coiS[c[[[SS[[ccccicSSSSKSS[SBSKS[c[c[SKKSKBKKKS[iz¼ic[[[[[ScܼcSBB9BBKBc[KB999KSB9KKKSB999BK[[SKBKS9BcoSKBKS[[z[KKKBKKKBBKSB9ziScoiiicioii[[K1K (1( (( ((1( ( 1[uc(((( ( (9[ui KK99iz[9 1iiK1 1191(19BKiɍKBK[SKKBB[SKSSK91o999BK[icc[S[cc[[[cciiicc[[SKK[cSKSBSK[[[SSS[[cc[BKKKKczc[c[[[S[SS³9KB9BB999Kizuzi[B9(99BKKKK9119B99BBB99BBKuzcSKKBBKiu[KKB1BK919BB[c[[oui[[iooo[SS1 B1((( ((((((((( 9c[9 ((  (oB (9BB19K[9  (1 (91(19B91((cϚcS[SBBKB[[KKK99 cK999K[[[[SKK[[[[c[[ioi[SKSKS[[SKBKBB9KKSKSSS[cicSSSKSoui[Sc[[[SSSS1999BB9B9BBSizzzoocuKSK[SS991919999B9B9K[oic[SKKB9[i[SB91199[ozcB[ouziSSiuuiSSK(99 (((((( ((((  BK( ((( (1(cocziS911 9K((9K9(1BKKB9BBKzѦuiSKKSSSKB111((K999K[[[c[KKSSSS[ic[ic[SKKKS[SBBBKKKKB9BKKKBKKScoiSSS[icc[[c[[SKBSKcK199919KB9999BS[cicS[SK9119BSB999BKcio[[[S[S[KBS[SKB1SoiKScoziccouic[S(1K( (((( (((((( (B9(((1(  19(u1   1cuB199( 19BSSKKKBSKSĦ[KB9SK91(1 Bc11BS[[[iocSSSS[S[ciSS[KSSSS[S99KKKBKKKKKKKBB99BScc[KK[·Scc[[c[[[SKSSSB9911199999BB9999iշzoSSSB911KcccB9KS[zicc[cSSKKKcKB9ioi[[[[cuuccuuicc[1 (K1(((((( ( (((BKB1 ( ((( BzozuoK( 1B9S[1( ( (1BSSSKK1KcK1cc11( 119Ϸ[KK[oc[ciicSSS[cSS[cSSKKSKSSK99BSKK99KSKBBBBKB9BBBSSKKiSccccc[cc[[[SKBB99911199991119Sɿ[[SKBKB1K[iu[Kc[cci[c[SKSS[B9[uci[i[[cuiS[ioiicBBB 1((((  (((((((((99 ( (( (( ( 1zo1(9( ((  19((( ((9199KSSKKB(zzS199Ku[1 (BK¹z[Scoc[iiiic[SSSSS[S[[S[BB9B99BBSSBBBKSK9BKKSK9199BKKcuccic[ciuuic[[B1BBB911111((999Soɖi[[B9S[SK[uz[Scccu[S[cSKSci[9S[Sizzzuc[ccoozcSc[[c[9KB(((1 ( ((1(((11( (11 Bi1(  191 (1(1111B9BBB9KSBKB9(zcB19( Sz[S[czcci[Sozi[SK[[KKKBKKSK9BBBBKBKScSKBKKKBKKKKSK99B9BSzooocci[Buuuzocc9119999911111BBKucSĹKBBKioi[cii[[cccoo[9BSSS[iocSuK[ciuuuSczzzoocii[[[9([((11((((((  (((1(( 1(((( 1BS9( (9((1B9 (19BBB9( 1BKKK91BBSKc91111(( Bǭ[KKuuiuc[S[SBB9BKKKKKKS[[SKKKKKKBB9SSKSSScioiiiiiiSBcuo[S(119991(111BKB9iu[SiĪcKS[[KK9KS[cicccicuuSBSSKS[icS[SScouoiocizoiccicc[K 11(1 (( (  (((  ((( ( S[oc91((19SB111 (199991 (BSS(1Sc[SKB((( (( iǭoSSuuKioKBBBKKKKSSKKKSSSSKKKBBBKSSS[co[SoccouuuciicSS1(111991(1(1BBSuuiiBKB119KScc[i[ccuo[SK9BBSKcS[K[iciiioouicc[SKS[c[9(  ((((( ( (11(  ((( ( 99 [9( 1B111(( (111 1BB99BBB1 K[KBBSS((  Bz[iziccooucKooKKKKBKKSKKKKBB[S[SSKBBKSSSSS[[Kozzuc[oi[S91991(111((19[zzc99(1Kc[[cSSS[cuzKSKBB1KuzKSSKSSSiiciiiSSS[KSS[c9 (9(((( (((( ((1( (((((( 99 9[((1KK (( ( 11( 9SSK91BK[S9111999B19ioS1  9BSuoKB1cuicKKSKBSBKKSiuSKKBBBKKSSKKScSKB9BSKKKKB9Bc[SSKSSBzzo[K[[Su[c99911((111(9uzooizzuuuK19BSii[cSS[[SiSSSB(9c[SSBBK[cc[[[c[[[cSSKSK K1  (((1 ( 1 ((  ( (1(1(( (o  BcK [S    BK991( (9BKB1(((( S³z91iiKB[uiSSSSB9919ou[BBKS[SKcuuSKKKBS[ciozzzuuucSBKKKzcc191111991(B[cccizuzio9BK[cc[[S[ccSKooK9 SҒ[c[[SKScc[c[[[ccc[[SKK( KK( (  (( ( (1( ( 1 ((  ( BuK 1[K [zi( (1(191 (11(  ((((1(((1uǷ°ucoc9(BuzuiSKKK999Kuuicizuuz­uc[KKS[uci11111(19 BcSi[[coiiuiScoB[[S[[S[oocSBSzcoշc[Scc[cic[icSSci[K[SK( 1B( (( (   ((1 ((  11 Ki[BS9 9K1  SicK1( 1B91(( (((((1191((1[ϭzB99KizccKizuouic9KSuuc[999B19[iuziioozzzuSKK[oioB1911(((9c[ioc[[[SiuSKSccK[[SSccK9KS[عuSScc[ccS[ocS[[[[[[SB (9( (1  (((((1B91 9uc 9SK1(9[1(9(19K[K1(( (((( (19((B11((BoɖK ((9(( (B9KS[[9BBK[[[S911919B99KKouii[cu[ucS[icKKcuuuiuz[KKS[ouiu919111 Kui[iocKS[ioo[KKiScSSSKKK9((KS͚iuz[c[c[[[[coccc[[c[[KB9 (((( 1[zzc(1uzi1 (9KBS 91KozK(  11(11KSuo[BBKBBK[zu1  9BBB9((1(Biu[9K[ccK11BK9999KozBBBKzuu[SccSK[[coicioooiiiuooiSSSSScuzz111B11[ocKSuc[[SBcoci[K[c[B9BSBKcĹzzzuoic[[cccccc[SSc[K 9K( 1( ( (   1oo[[SB (u9( ((9B11zoSS[[[[SiuzuB 1BKSou9(11(  KiSSoziB1(1KKBKiS1KuoBSSiiz9[[SScio[occScuozcc[Sc[S[[K[u11199icii[[c[SS[uuiii[SuicSKiuczzziozzuic[[[[ccc[SS[K( (K9 (1((( (1(  BioK199 SKKuoB (cSucB9Buzo[SK[oz9 B[( 1KScoK (  (( ucKK[91BSKcz1[u19B9BKciKKccSKi[SSooicuzu[cSc[S[[Sczu1((9ouccoiiiuu[ooSi[c[[iuizoo[ccoc[[[[iiicc[ciccc[[[B B1 (((( (1( ( ( 1[oS((9[[1ooK1(( 1u˞S99((((9Suu[SB(1BBcz[[ucSucK9Kz( BcS  Koi 1Siuo1 ( ((zu[[B9B1(zcB9KKzK1ScK119K[[ic[[[[cK9K[oiciouuioicSSccc[[[ozi19[uzc[ccccic[coBBSKS[coui[iic[couc[KKB9SccccccccccccS1 BB 1(( (( (( B[i[B (9ciB(o[(11(  KϚ[(( 1( ( (1( ((BBSK1(( 1( 1oo9S[9   KK 1((1i[ 1( 19BKScǷi99cuS9Kc[K911Suzo[KKS[ccKS[coc[[[ci[SocSK[[[[[couc[uicoooicccc[SizB19KKS[ccucczicioic[[iiSSSKK[S[[c[[[[cccc[[B 9S1 (((( (( ((( 1iuS(((BSzc1oKB ( KҪK (  (1( ( (   BSic9(BK cic[z Ki(coKKKK9((cչzBBS[SK9BSSKKSizcSSSKcoSK[[ccccSS[[[cziSS[c[[ioocuzzuuuzzzocicciKSuuS119B[[[[ozSKKcuiuziSSK[z[KSS[S[c[ccKKSSSSKScS1 (KB (119 (11 (( (SiB(izS[uKo³o 9c9 91  (  ( (  (  (uz9 1Bcu[9cK9999  B  1S([uSKKB1((1Ko¦z[B9BBB9BKKii[SSKSccSS[cioiS[K[ciouz[S[ioioo[Siozuuooici[ccS[[B999B9KKcziSSSizcci[[KKBczoSKSS[SSc[c[BB[[SBBSc9KB (((19(((1 B[K cϭui[1Ko9[Soi[ĦB(9(((( (( ( (((1BK[[czu9 (io1(B[[coc([B1(( (11 B( 1K KcKBB1( 1919izK91991BioSKKKSiiSB[ooocSSKSciouuzc[iooou[SozzooiioiSKS[[[B9991BBu[c[[[ioSK[[SKK[o[KBSc[[[[[[SSSS[SBBSB Kc1 (((11(((((((( 1KBBKԍ[ ic9cǰi(((  (19KK[couocSc[[[oc(K[1 1B111BBB9(( 1111iB ( ( [ KiSKK99 (9919S[ooSB9(KuzuuzuSKKK[ci[Scooc[SKKKScoocuuccoouui[uuuzuoiiiocSKS[KB91999[SS[ccczSS[SSBKK[[SKc[ccSS[S[[[SKKKSK1i[11((11( (((((( BK99ic 1[SoɹuK  ( (9B (SuS9B9((9i (9( (1 (11 9KB119B999i9 ([19ccKKKK((191999(B[oucKKSoui[[ooKKSKS[[cc[cooi[BBB9Kii[cuuccuuccuuzuiiic[ii[KKB91111BccioK[iicoucSBSSKBB[ocSKKScS[[[[[SSSKBK9 cc919( ((((((( 99ci[S1uɚB 9KK[ɿoiK( (9Scuuzo( BKSSSc[K911((((91( (1 9B19SS9BKBB9Biu (((1KB1[[B99991BKKSBB9B99KiǖiiiiScoiBKSS99SSSuuoicB9S[KBiuiiuucooiiicc[S[ooSKB191(1SzzcS[[[z[K[i[ccKSKKKBBKcoSBB[[SK[S[S[[[KBBB K[9119(((11 ((( 1B9iz9oi1BoccSB(iͳS1(( 9zzziSB(11(   (BBBB9Ko1 ( 1 (( (9S(B[KBBKSB9BBi( (B9(SSB19KB9K[[c[S9BB9BKz۹cS[uoiBBSBBz¿°uioooi[S[S[SK[c[B9991(1uzcS[[SSci9B[[[[S[SBB9BKKSB9BSSSccS[[[SSKKS9 (c1 (9((11(1 ((( (11ucSi[B uiB1(u¼B 1zzKKK((B99BSSB9SB1[cSKKKSocS[u[(( (S9KcKBBSSB991[Ң1 (1((BK99SSKKSSS[KB[iٷKSͿļĹzoo[[SKBBSKSSBB9911ScKS[SSS[c[uS9KSc[[[[KBBBBKKBBKKSc[c[SSSS[SSS9 KB(11((((11 1( ((9uS Kic9 zzozoS19oK[11c[[9(11Soouoccouo[B911Koooz9 ( (KB(S99BKKK991(S 1(1 999(1(9KSB[o㷄Ϳziioooz˹uoSKKKS[[KKK91911i[BSSSBKSSS[iSKSicS[SB9BB9KSKKSSc[[[SKKKSSSKB1 BK 111(((11( ((((1((czocScuzB(( K[Biooo99BciSKooiozzzS 1((9K9BKScooK (99(9 (BBBK99991u( B1 (9KScizתo(KuԹiKBKSB99BS[uϭK9BBKKKBBB91(9uzSS[SSKS[[S[iozKKccSSK99991BKKK[i[c[SKKSSSSSB Sc( 11((((((( (1 (1 (1ozz9 (((cSBBciBBcǒSKK9o՚S 9K9BK[oouuS((9(((111991(9[o[  (BK9(((BKKK99911((91((11K˿uiiKKKi·BKSKKK9(Boc[KKBK[SB9Bc·B99(1919111(Ko[KSSKKS[[[S[[[i¦cB[[KBB99KBBBKKSc[S[[[[[[SKSB 9uS(1(((( ((( (( (1((1zo[K1( (91[[KBB9999SoocǦzB 1K[[S[KB9(( (999BB 1cu9 9S9((19BBBB919( oB 11((1SѢ[Ku[SciooožoB1(99K[izzocc[BKccKB9BScK[K((9(1119iu[SSSSKSK[cSKSKKSSuzK[SK9999BKK9BScc[SKSSSS[[SS1 (ci (11(1( ( ((( (((((1ucK9( ((1K[KB999911SԼu[KB1(BBS[K991 ((999B1119oc 1B(1(19KKKSB111 [c ( KўBBo[K199Sc[ozoi[SooSBBK[uiucK9[SiuiKSBB[SuKKB1191(1SoSSSSKKBSS[ccSSKKSS[c[SB99999BBBKcc[KKKSSS[S[[9 ci9 11111((( ((( (11((1[S  ((((SzKoSKBB19BB11So˼ciSBSKBBB91111(1B999(cu1 1 (1(1BKBSS9999SouK( 1Ϣ[Su9 (1((((((9K[[cic[KczBKSBK[[K[SoouiSK[KSciuB91( ( SzS[cSKBBBSSSS[KSSKKSSS[SB9BKKBBBK[c[SSKS[[[[[SBKoB (1((1((11 ((11(1( ((B9 (((((( (Kio1BKi91BB99BB999BB99[ouzz­cK9199KKKKB9999B91So9 9iK1(((1BKKS11BKKoo9( ͦzKiu[( 9111111( (1(19BBSB(9KSuocuu B19B[ciii[KBSKScii91(9KcǷi[cc[[SBBSc[KKSKSK9BKBBi[B9BBKKKKK[c[[[[[[[[[[[B( 1o[( 191(( 11(( 19((  1( (((( (9[9BSS1199BKB99BBK9B9B9B999B19BB[ǰc9(1BSKKK9999B99Kioozc1((((BKKSB9BKBSoocK11(oҚoicB((((11( (11((11(((((9 1cSKB91BKKB9BBK[[[[KKK[[[cico1Szļuc[[ccccSKS[i[SSSKKKBBBB99[uKSSKKKKBS[ccc[Sc[[[c[K( cc1(1991(((((((( 1(1( 9K1  (((19oˢoSSB1999BBB11BBB9KBKBKBBB111111Kuͳuz[11BBBBBB99B9BB[u9(((((BScc[KSKB1(111((ѷzoiK((111111((19 (1111(1(uS99111SoSK[ccKKSS[[SKK[c[SScciiS[c[[cc[SKKSSSS[KSSBKKKBKKKKuiSK9BSSSccccSS[ccc[[K( [c1 (((11((1(((( (1(( Kc999BScccoucB11BB99BB119B9B9B99999B9B991 1u[BczK91BBBB99K9BB9KSSB1(((((9coi[[[B11111( ўiic[B(11111111111((111(( c99B9B1KKK[Siuoc[KKSSSScc[SSciiuiuSBSc[K[[[[[BKKKKBKKBKBKKSSS[SSccB1BKKSSSci[[cccc[c9 BiB 11((1((11 (1B((B111K9ouizuiioi[BKziB9BBBBKSB19919911999999BB991(1ou9K[uuBKKKB9BB991111 (  9iuoSKB( 1(1( ۼic[S91119999(191  SKK[[1(9uu[u[Si[[KK[[SSciSccioz[[KBSSSK[SKSS[SS9BBKKKKKBB9KBKKK[[S[ioSBKSK[[ScccS[c[c[[( KB(111(1(( (( Kc(( ( (19S[BBSS9(1 1K991BKSS[B1((1199B9199999991919KKSKKcucBBKBBB1 11  (  (SuucK1 ( Bǀ[cc9(1(91(1((9(   KS9KKS(9SKo[KSKSSSKS[[S[[iuSKSKBKSSKK[[[cSKKBBKBBKKKBB999BBSSKBS[[S[c[c[cocc[[[SSS1 KK1(91((1( 1(11 ((1((1  9[͖1199BKBKSB11119999999999B9B119ScciSSBBi[1KSKB1 19(  1Sii[S1  1( 9SzuuiB19((((((( (KBB9(1[9SB91 BSziuiKBK[[SSKBSSSS[oSKKBBBBBKS[[[[SBKBKKB1BBKK99BKKKSKBKSSzoKciccccocc[c[[SK1S1 1B191911( 1  ( (1(( 9Soǹz199BSK91BB11((1(1111199991911izzzzzuiS[cSBKSSB11BB  1Kc[[SSB9((((B[ououuzi911(1(( iuuocciS Bc[KB( oz[SioicSSSSSKBSSS[So[KBKBB99BKKKKKKBBSKKBBBBKKBKKS[SSSKSSSccciicccccc[ic[K1 ([9 (1(1(119( [B  ((1   9[[[cz99B9B[[B919( (( 19111(1991119ˉioizc1(KziKKSKBB9(  (((((BSSSKK[[KBB9[zdzzKBB((19911(( [[BSBB1( [ziccB([zcS9ou[ooc[SSSccccc[KoKKKKKBBKKKKB9KBBBSKKBKKBBBBKK[[KSSKKBSSuiiccc[SScccccBSS((111(1 ((Bzz9    1K[SBBBS19B99S[K911199BKKcooozuS((9991co199SooK91[uiBBSBB1  ((((((B[KKcuzzԳ[9(191111(((( u(1 (oo[S9(1ScK9KK[c[c[Scoicoo[KoSKKKKBKSKSK99BKBBKKKSKKKBBKKSSKKSSKKBSKiuicc[[[c[[ScS KS1(9B11 ( 1S   1KSK9991c[KB99BBK[K9B[iizu9(191(Su9911[zzoK(9KooBBKK9991((1119Sio˪o91119119((1B[B(1(((  u[9((SBBcBS[[SKBKc[izoSSci[1[SKKKSSSSSK919KSBKSKSSSSKBKSKSKS[[[[[SSSiziiccic[[Sci9(c1 11911( (( Sc(   (19BKBB91(1[[BKBB19((Souz[B91( SuSKB1Kcic[B((9Kzu[c[SSKB99BBB[uɳ9(9919B 1KS9K1((11 (uo1 1zoBB1SoBczzcio[KKSS1c[SKKSSSKKSKBBKKKBKKKS[[KK[[SKSS[[SS[SS[coiiicS[izK [K (1111(( ( 9B(  ( ((19999B99K9(199(KuBBBBK119(9uucSBBBKKcuuoc9 1B9999B9991 9BBiu[SKS[KBKK[z[iİS99119B1KSB9B99ioB9zK ((uz991[i9zĿiSKBB91 1[SSKKSKKKKSKKKSSBBKKKS[KSccS[[[cc[S[[[[ciziccciuc SS ((111(( (11 B1((((B99111(19999119oS99999Bui K[9BBBBK99199K[iBz199B99111( 199Kz[S[[KBS[uzS9BBB[BSSB9BKcS9KKc9KuuBBz1 ( [BSBK91͹K[cKB1 c[SKKKBKKKKKKKKKBBBSSKS[[c[KK[ccccccccc[ciiuS[u[B[((1 ((((((ScK  11(1111B(1(119999999(uSB9991BicKcB111BBBBBBBB911SuS1B9BBB91(( 1999KoiK1(1ozoKcz[1(zuBSic[[cu[BSiiz1BK1Ku9(( ([9[K9(Suo·ScuioSS[SBBS[SSKKKKKKKKSSKS[cc[SKS[[ccciicc[[icozi[ozS (SB (( ( (SuS(( (1199B199B91999BKizBBBBB911Kcu[999B99999BBBB991(KizzS199119BB1(119B99SccuS9Sio11zzBKS9(S·ϢzSKcuuozĞo (([o( (((i1BK99uiozuiczϷS[[[[SSSSSKKKBBKKSccS[ccii[SSS[ccciicicciuzKSuoBKK((1 ((( (S[ Bi9 1991(19919B91199B[iBB99BB99z1SiK91KKBB9B9BBKB991119KK91911((991199999K[cS1SzoB[zK K[K[uo[[iuozϞuiccS((S[1( o1([B1iiSSuzoɢ[Sc[[SKKSSKKKKBB[ccc[ciccc[[SSS[ccuzzzu[ozS 9B( (1 ( (11    cuKBBB9((199199911919ouSBBB991BiBSoSK9BB9B99BBBKKKB11(19911111119KB99111BSSB c¹iBKi[9o[( 1(1iz[SiooouѦu[oc[Sz9(BS1( uS [[9occcKK޿c[c[SKSSKBKS[KKciic[[[c[[[SSB9K[czuiiuu 1K(((1( 19(   coKBB9919119BBB(1((9BicBKK999BS9BS[K999B999B9BSSB9((99(((1191119BB999BB  ucBBic ([K 1( 9uoK9[iiooccui[coiSBc(9Kc(( (u SiSiozioiSic[[SKSSS[Kcc[SciiciS[[c[SScSBKSouoiicczo1B9 ((1( ((9(  z[(911919111BBB9911KczzKKSBBB19u91KS999BBKBB99BB9B9191((99(1(((9KB9119 KiK99SoSB Sc1 ( K[uK1KScooiciiouuiB1i BSc ( (9oB[iccSuiiiucuc[[SicSSc[i[S[[ccc[[[[cc[ciciiui[[iciuiBB( ( 11(  i9(1199((111BBBK9BSiKKBK99iu[9BKB9999999BKBBKKB91 199191(9KKBB(Boc11B1 9[cc1iB (((  cuSiK[[cozoiccizz[BBo(9S[( (KizSii[[icioB[ccioiSScc[SScccccccicciiciuuǼzizo 1S9 ((([oK  SS(19BB91111BB9BBB[zoK9B9BBuciB9BKB999B19BBBBS[SB1(11999K[[SB1 BuS11999( (9zu1ic9 (( ( So[oڰzuucuuzzuocicBBKiSBSK( S[cS[KcuizBcciooicSS[[[ciiiciooiiiiiiioļ˼zS[S(( (9zc( (119[uK1(9[cS91119B9(1BSuzzooiouB1999B9SzzK19SSKK919BB99K[SSB91(91SS[[B(9S91991(1( (1BKS(zi9 ( (cczozuiuizuiouu[KKKccKB1(((cBzKScozBzzuuuic[S[SSciciooiouoioiiii˭uB((11[i(  9[[Sc[S[cSBB9SiucS91111( 1KouKB[SKBBSSii999BK9(9i[K[ii[BSSKBBS[iicSB1(99KK[B1i[9119BB11( ((111 [c9 1u[zzzciiizzuzoiSSBBccSB( (iz1uicz¹„Kuuoic[[cc[[[ccoooicccciiuzĿKcu[Boĭzu (9[iBBcSK9BSBBSBK[cSc[cS[K1(1( 1SuoziSKKSSKKKKKBic91K[B1(1SzcSB19KSBBozzB999Ki[([c1(19991B9B((91( (o˳oiu[( 1cǦuzciuoioouoKSB9i[B9(  ou1iu[cicccciic[ccoooiic[cuķͳ·oKBKB9BKz[( KK9 1[iS991199KSBSc[ccSB9KB (((KuizK9KKSSKKSS[KKouB(K[919(([zzociS(1BBSzSSSciBiS9(99B9(1(199(9([[BBK[oui1(KҿziiiKB9uKBB( (zi [‰u¿Sizuuicioic[[ioiiiiiǿ³[19[SKKSioBBK9[ 9KKKB99991B9BKBBBBKSSB91 1czz[BBBBKBBKS[[SSSouSSS1999119KSSzz[SBKuic[1Bz9 199((1(1(991 [ܼKBo ((BziK[щɿԼ[S[iǦ9BK1((c c¿۷uuѭS[ozzoicii[[[[[[[iz۳i19iiuziK9ci1 BKBKB99KB911(1((9911(19991(9[uuc[cuiKKKKBBBKSKKSSSizB99999( (19Sciooziuu[K( uK11991(   9SڷK c[ (1uuzՉ⭄ioš91[B(((KK¹ˉuouciS[izuooc[[ioi[[i³Ѣu[K(Suooc[1 9cS911(9BSBB1((1(1(11 ((( ((KoziSKBSScicS[[SBBBKKKKSKKK(119BB119911BiucoiKKcoKi[9B991   KǀB 9[B [zͪݰzuB[S((9 zSϼْ1Socio[uicizoiccuzz˹ܷz[KB9izoS9B9  9SSK1(1999BB9B1111(1((   B[oucK999BSKS[uzuuoc[SK9BSSKKSSKiS911119911191(cc1[oK9B[i(icKKB(( (KcuĹu9 ((9K9 9zˢĚocS[K((9(zҰҦc 9ciciicozoiiuuuzĿҷz[SB1KuoB([uK 19KK1119BB919919(1B1 (((1BioS99199KKKBS[[[[czuoi[BBS[SS[S[c[z[911((99119911SSKucBBSB[z[cK( Bɼ[B1 1991 cĿѿuuzuzuu[zzKoB(11KķфK( 19ozcuo[ooiccz¼ǷS99B99i[9iKB9(19119B991(99(((111((SoBBou[SK1111BKKKKBSccSBBcozo[SSco[KS[SBSouocB11(1991(199(ooiocKB91iSS991 K¦zzoS 1(11((1KB1BouϿzSBSSKBBB[ioiuoSiK11(Kڼ[9B1(19iicoiczuic[iǭ˷zS119K1 99BBSz((iuSKKB911191B911B19K9 (1 1SzSBzz[99BB9999BKBBSSKcocB9S[uucS[icS[[KBKBScoc9(11111 (19cu[KKKKS1oSB991Sǖ[1 (( (19111((1KcS9uSo漢ii؞S[[[BBSK9BKSouǒiozB11 BϹْ19SK(19B[oi[oc[uozžͳKB9BS[K11KKS[cSSoB(199199BBSS9(1BKBB1 1cc[[K9KKBBKB91BSc[KBSoucKBKSScu[K[c[[SBKB999[zzSB9B99KScu[( 119KK[B9B(9ئB((((1((11199 (B[oSScz񳒖cSzKKcSS[c9KS[[ziz1(1(SĉuBKKSKKBB9Sziiiu˳ɦ[9BKKKioiiiuuuz(9c[911111BS[S[cB9KKB9(( Kzuo[BBBc[BKKBB9[K9[oc[SKBKKK[oo[c[SKBBB191BozuuuuzzoS1((11B91SB991(Bo9B(11(((111B9((9Sc[1Sziڪ[cڰ9K[[SK[SKKccz1919K19BBKSSKSS9ScoɷĹcBKSiiizBBcS9(((((9S[SBKS99B91( 9zozocKB9SucBKKS[ciSii[SSSBBKKB[uSBSK9119B1B[uzuccS19B99KKuo1((([99B1(1((119191((9[cBi­ucuωBSSSKSc[BSo˹z1B9uK11(1BBSSSK[zצuzuou­ozucKS[S[o9[cK111 (19SK99911((( (B[[z[KB99KioSBKccuuiicSKScBBKKB[oc9KB99991199KS[SBKSKSSBBB9BS uK  cK (9K11(111111 19ciSBzĢuuui[1BKSBScSiijzo1[z[K(  BB91cuz͒zc[ciϭu[[SBS[[ciiooioB[[K9111 (19SK19( ((1 KoczoBB99BB[o[BKc[ucKKSSBKB91BB[oB91BBB9(119(11111KS[KKSSBS9oo Sɷu1 (1[K((111(11 (99[[SziɳuuzuuͰK19KK9BoS9u[Ǽ‰i[  (KB1SǍii[oizuzcScciiiuuzzuuicoocKKzS911(( (19SSB1((((11[zuuuziS9BBBSKKio[BS[z·[KBBBKB1(BBBS[zoS1(BB9B191((1191KScSSicSKSSBɹKB((11(([cB((19(1( 19BS([c[uuz˷zzuoociϦS9BSBK1(KǷz1(1(([ǖcoiiicuuo[coouuuzoiiccuziSoK1ozB9((1((999BSB (1(9[uccccSKB99KSKB[uuS[izšziSSSK11KSKKS[ozu[B(((BB111(119BB[ociucS BSǒSB (1((91((9cK1119B1(99Sci(cciizĖzzuiii[9iҪSBS[1(1Bozu1 (ǹz¢cuuouzzzcScoooouciccoccic[ii(izS91((9BKB99191 BSoz[SSKKKKS99BKKBSizcScuǷuSooSKB9B[SKSKScciu[1 (919919KBKcuoioc(Koђ(111((1(1(1SK9BBScS[c9iuo1iiooռuuzoc[B91iצ1(oB 911SiK 1׿cuziScoiiicic[[coiuu[[[o(Kz[9911(9KKB11 (1(1izS1[oSSKKBBKKBBKS[KK[ui[coo[SKczcK9BSSKKKKBBou[B1 19B9KSczziii(B[zu׿[19(11((((11111S9BSouozzSo[B1iccozϿzo[K9B91i۞1[11B9B9Sǹ9cזuouczcooccccic[[[iiuc[Sz((iS11199(11BB1 (1BcziB(KoziKKBBBBKSKSc[[KBK[[iuzzcScooK9BKSKKB1KouozzoS 199S[ui[(K91͢So[((((1(((1999[K9[uuouc[1 uc[[ouzҼuSKKBKB9ݪ[9BicK9[ǿ۪9͒z[czuc[ciioici[[ioozui[B(cc1((911111BB1 9K[oiS11  1Kc[9BBB9KSccioic[KKS[ozzu[cu[BBBKB99ciK9K[ciiSB(1BB[uuSS9(BϪBooB((111111991S[KczziK9 zoǢu[zuKKKBKSK1צ[9ic·ɼ۷Soui[ozziK[iociiS[c[ciio9(iuB19BB9119991(1[uoS1(11(91(9SS1B999[ccciiouiiiiouuziScoicB1SiK((KozuS(1K cc919Sտ1[oi9(1919999 (9ciuzSK9(11ܰz[BSiuiouiKBBBKKB9K„BļĞڪK1KzozucooocccS[i[KSui9[i919KKB99B91 (co[9((19SK91BSKKK9B[ouccouuucuSiuccc1Ko[1(  (Buo[SBBKKo[(19B[uK9ccS91111BB1 (1KuzoS(((((SܹiSKKS[KSii[SKKBBBB9Sؼo¿٪K991[uizɹzoiii[S[[ioiioScB99BSc[K1(1SciB( ((1KKBBSK[uSSicioiccizcBKiiizuzK1coS19911119[iS1119SSczى(BKS[B(11991911BoicB ((1zdzo[KSS[c[[ccoi[K9BSKBBo׭ύK1K999cuScϿzo[S[iiiizo[KBBK[cc[[[cu[1 ((( 1 (19S[SKciczuiouocBiKKiSSS KoSK1(1(1 (199Kczc1111KcK1[ԳB19B[[K999999919SzzS9((((KĀouǿˢocKSS[cicuciiuoSK[SSKBϳ¹uBBBKB991cKuҿ³iccuzuzuKKBK[BKui1( (( 1 1SiSSoziKijĪiSSii[99iS19 (((1((199SuiSuoS9911c[1(SSB[(9BKS[B9999919KSS1991(ScSooǿǦ[oKSKciuozciiuu[[ioi[cĹĿٿc(9BBB91119[oɒuuuzuoiozzuiSSKcSSS  (( (( (9BKSǷzĿc[K (ic9991199111(1BS9Kc1 ic9BB1BcS1B[9(o19B1(S[9999K9BccB1SB1 [iSSoɿSu[BK[ouozzoc[S[iouiٷɼǹչi99BBB1(1111Biuu‰oiiioiozuzoBoiSci[ii[ooK  ((919KB9iǦozuzzuK [z[BBK[K91(((19999K199(999S[SBKS9(ˉ(BBB19[S9BKSKcuui1BcB1(ozoBSoSo[KK[ooouzcKS[ciic˦ĿԢcB99B991(9111 9oSzҪo[cicoouucB[uKSK[uc[czuK  (((K[[zz[ozuzucBKz[KKScK11((1999KK((ou(19Biuc[SSKB(iijBBcicBBSKBKSczzuS(BS91(’cc(KiSSc[[SScc[[uzi[[ciiczǷĿ˄B9B9BB(91(111111Si[zǭzcuuuooc[oS9B9[ucS[zo9(9( (Kiĭ˼ccuzzzzzS[BBBB(191KKBSc[1((9uB9BSi[cK999KɀKiuiBK[SKKcuuooc[[K1(SoB[BǦɖ[[icc[KSSS[ouiiiioioǷɼz˿[BKBB91(91(1119199oiuzϹicǷiiuocui999B9B[SS[izzc99919K[զǹ˚uiuicBBB91KSS[Souc9KSciB9Kcio[S[B99BBĦSBiiBKcc[K[cuzz[9 zɳc[[cɍoccii[SSS[cii[S[ic˹ͷǪi[BB911191191(((99ǖz³ci˿oKizu[K91199cucS[[[[uu[99KSiɪϿѳǿzzĿĢ[oiKB9199BKKuc91K[ioK9B[KS9SBBK99BSc1BK9BBKS[iiSoic[KĖicK[߼o[S[iicc[ScicSK[o¼ɼĹɢcBB119191111111(KSKK[[ɼzuoouѦ‰icB1BK(  BϭϪؼչcKcocS[oicccB9BB1Bcc[cS91991BiSS9(( (K11B1(( ( 9i[1(111Ku( (9( 19SS9( 11[ɚ 1BKKBKK[ccK111So[BSucSK[cc[KSSS[[c[oicBKSoĞzzouuڹcKK1 9( [׹˷զϭ԰o9Biui[ci[KBKB99BS[[B1BB19B99Siiui1(9( 11((11BuB( 19cuc (9BKoui( (1(Ko1KSKBK[[[K (1199Kccuc[SSSS[S[SiocK[[ϪzzuϳiK9(((BKii99izoo׭ͼķߞ˿İS9Kci[SS[SB9B[ic[SK99((  [oozzS19SK1K9 91(11(Sz (BBSuB1 191KSci[B( 9KuiBSKKKSKB1  11(( 11(BcBB9BKKKKKBBSc[cScizҭўzzuu­i9119Bo–ljuͷǹϞǦSBB[ic[SSKBKB[zzcKB1(  (czcczo[B9BBSSKcS1 BB (1ScB(1BScuuB99 (B99B[izociĖzϢ[KBKK99  (1999((11( Ko 9BKKKKKKKKS[K[[SB„cc[uحuooz¿iji[SS[z뭢uiͳ¹ǼijuoK(K[ooc[SB9cicooS19(1(( KciiS[occc[ic[u[( 1SK11KB99BKSSioS 1c[1(((( (Kco՚zu[(111 ( 19B1999919S99((11B1B9KKKKSSBKBSuͰoKci˒uicuĿcKczzՉ[ǿ·Ͽzoi(1SciicSScizoKKSK99199KKKB9 9c[SKBBSKoziuS( ( [oK1KBBKSS[[ic(1ccS9((( BKKiz۰zKB[B   (11B19199B91(((11(19(99BKc[KKBcǷҹocScucSScۼic˷ǹzcB1Soi[c[[ooiS11BSB19BSii[SS99K[SK999Soo[uo[K1 1KzB9SBBKSS[oS 19BKB9(1( (9KiiªB11(   (1999919B9 (( (( 1191(19(919KccKB9iɹѪoic[iǷi[cizͪzSؼѭijzSBKcuuiS[cizz[KB99BKS99K[[[ciciuiK9((19uiSKScB9B11BczS9KS9BKKSic (B9191191( (1Sc[˖z1 1111 ((( 111B91((111119B91(((191BKciSBKuS[cϖiiS[˳oiiuǼϿiKi·ǪķzuB1Kcuuuu[[[iuo[SS[SS9KKSS[ioicioz[BBSB9K[oicK9999BK1B[K9BS[c[B (9B99KSccB(( ((1њoi[ (9S[B919BB999BB91((((9999KSKB91((119KSS[io’ccooS[io[czķoouzĹi[[°ؿ­iK99Kiiiii[SczoSKBKSK[S[cSBKBK119BKouzuS[ziizzcic11 19S[KKK[S1(11199BKBKizzoK1  ĀcKio1 1SSKBB9BK[c[BK9( ((((19B9KKS[KB999119BKKu¼Sciuuoi[cz·zzziizǪzouijuuɰijuc91BSciccc[cuu[911BKBKBBK9(11( cziuuzocuc1BK99SBBK[[9(99999BKKSccoi[B1[԰oSKS1( 1KKB99999Kc[BBBB111((11BKKKSSSSS[SB11((1K³iScc[cozcc෪˞uuuɿo[iuuzou¹ioc99Sccc[[ciuzcKKB19B919991(  (9c[ziuouz[(Bc11BKS[[9( (9(1999919KSi([ĭoc9 119cc9199999ScK9KSBBB9BBB9BB9BKKKKS[KBB9(11B¼uiiii[cio[B˹˷ocuǿocciuiozuoz[99Sioo[[[oucKBScK199199991  [zzuiS[oouc9 1KB 1KSKB1(((1(((119KcScz߳i[9 (99Si[91B99B9BcK9SSKKKBKKKB199BBBKKSS[[K91999ɿozuoic[[uzcϼzoiuɿoioooozzuoiuzuK1Sco[KSicSBBKccK119BB999((9iz[uzuoɭz[K[ocK119S[1BK[B (9991((99BB1Kzzަzi[SB((9BKSKBB9999BK[KBSKKKKKKBBB19B9BBKKKSSKKB9BSSϿouzouu[[izఒzzzoo˹zozzzuzuzzzuozuc11[ui[oz[KciSKB99K[cSBKB999BKcuzu[BBuzzuKiɭoS[iuou[(BKciSKSB(( (((B9B1(9KKciciܚocK1119BBBKBBKBBB9BKSSKSKKBBBKKB999BBBBKKBKSKBBBBS[ǿiiii[iuiiiz׳İziuuzuizzzooi(ui[[c[[oiSK991(1SicKS[KBKozuicB9KzicKBiK(Boz[o[9BS[z[[[1   (  99119BSKKKoؖoiS(19BBKKKB9999BBBKKKKSSKBBBKKBBBBKKBKKKKKKKB99BBB[u[iccccicciuz¼ǿzǹuiuzzuuuuzzzzucBoזc[SK[ooc[B9B911BS[B9KB9Kouoi[B1KzicKB199S[9(9iiKBB((SozBK1   (11 ( 9B999BKKKKSzicoSBBBKKKBBB999BBBBBKKS[SKKSKBBKKKKKBKBKKKKKBB9999[czoocioioiiciu¿Ěuķ­ziuzzooozuzoSz[KKKiocSSBKSB9919SS91(Buuc[K9(SoocK1((199111((K[SK1 BuoKB (  (119119B91999BBBSozcoSBKBSKKBBB9919BBSSSSKK[[[SSKKSSSKKSKKBBBBB9BBK9Kcccozocciuuoocciuҳooozzoouuzuouzc˄cSKKiiSKK999919BBBKSS1 9ucKB9oB( ( 19 (1BSB119oo(  (( ((1SB(9199BB91B1BKKi[iSSKBBKKB99991B9BBKSKSKSKS[SSSSKcc[SS[KKKB99B1999S[ciooc[ccooiiciioiu׿zo[Kzc[[[ouoiuzuicuuiSScoSSSK919((11KK[[c[[cBB9 19ccK1 (( (1(9KBB9(co11(999B[S9((99119KB9199Ku9SSKKBBB9 (9191BKBK[[KSKKBKKSc[cio[KKB99BB9B99119[[c[S[[ciiicc[[ciii׷zzicuzoiouzzciouzuiociocSScooii[KB1119919K[iiuzzu[91(iouiB(11B9(111((9BiB 9((KSSiozo[991(11BK9111B–Bcz[9BB1 199KBKSBKKSKSKKBKKS[coS11 (((119B919iS[SKKiiciccc[c[cciižoiuic[coiSiuK[zzuzo[c[SScoiciiK9B9BKB9(1KiuuuuuiiSBB9(u9(991(9BB( ( 1((( 1KKu[S119B9KK99BK͒BczcBBK9199BKBBKKKS[S[KBKKScii[[c1((((1(1191BKoSSBBKiiccc[[[[[[ciou¿Ͱi[cc[[[ccS[uzzuzuicS[[uucS[S91919BB9Kouo[icSBBBB枉uoiucK9((9KKB  ((9( (KcoocSicc[B19KBKKSu1BKciiiKKK99KKB9BKBKS[cSKSSciS1 Boc(911199BBBBSiSKBBKcc[[i[c[SS[ccu[u׭oc[[c[ccBcziuocicozuuuuzoiiziicoSKKSSKBBSuuzzo[i[BKK1((uǚSK[iooS91KKB1111BB199( ( 9[zKK[KKSoz[KBB1119Sz1911BcoBzcKBB199B9BBKSK[iiiB (o1(199BBBS[K9SzSBBBK[iccoiccS[ioiSKSoǿչzooooc[cc[ooozBKSS[io[KKKKizzuuiuuzuiozccSS[c[[K9B9uͳS((1BKK[SK9SoS (19ScK1BB 9BSiziKcoB99KcS91( (111o9(( (BKK[9999B199BK[[[ou[B  KK191BBBBB[i[K[KSKBBcoiiioc[[czKSSKڿٷzzuiioic[cii[ozu19KKBK[K9BKSoo[[[iİzBS[SK[KB99111[zS (((9B99Bci1B(1iS91BK (ScccciiSBBSSB1(1BK9(  191Si((1(((Sc11BBB91KScioouoc1 ((1Sz9991BKSSSKSS[cKSKBKcccccucSSizSSSKoݭuc[izcSiuizu(1SBBKKKKBB[uui[cS9ouѰzc[[SK9BB91(KuSi’SSB1(9BB99SouB19[uB((((9KKSKBBSK9(11 19199(  911uK9B9 ([c9(19BBKK[iiiouu[B((111[u9991BBSKKKS[ou[[[KSSSS[[oc[[co[[[Soѳuuozzz99cKBBBKKB[uoc[SSS9uizzc[[ccoSKBBBB1 (ucK[ڍS1 1(19SS[B(9BK( (11991(KS1((  99(ccB999Si991Ku[(1911BS[[[KSiocS11999[i9999K[SKSSScuzc[[KBKc[SScSSS[izzKS[[Ҽ¹zzuz[ SSBBBBB[cSSSSSoooozzc[ci[S[[c9B991((Su[KSoצ99(((1 9B((B1K9  ((1111( 1((((   SoKB9BizSBB(cK(9BBKS[[SSSS[uu[1 1B99ccKKBKS[SKccciuzu[SSKBBci[[c[c[[izzBSS[Ϣuzzuooz9S[99BBKiz[[S[KSuo[Sc[SK[c[[ciiKKScK119BBcuzcBB[iu[SS[[B9((11cB(  ( (( (   (oKKBK[iBKKc[191BKcoouuc[SccB (9BBBic9BS[SS[cc[cooi[cSKKKBBciccccc[coouBSK[¦z[uzzuuuzzoK[B1BSiooi[[[KKcucB99B999BBB[uuoocB9S9(Kciio[KSSBziicccccB(1991u9 KB(   ((([cKKBK[zKB[uuB1BKK[o[BB9(( (99BB[iKBKSSccc[SSSKKBK[SSKKBScciciciuuioBSczٹѰiczzzouuuuKSKBBcuuc[S[SBciSBB999999BB[uzc[zi19zuBcoouzz[KBSS9c[SKBSuooo9KScK9SB(1((( ( 1 (9iSSKKKK[u1ic1BK[Scu( (11BBKciB9Sci[[K9( (BSz[[[KKBSccccicozouuKSz˦ܼzoouooou[KSBKSioiSKSSBSu[BSKB9B919KocSzS1[i[[ouzucKBKKB1SBSKKSicuuB9Suc[S  9[B(( ((1 (9ocKBKBB(uioBBBB[ooB  (111BKczSS[SB91 1B[oicSKSScc[[cc[iuoizcS[¼ǞͭzocioouozzuKSSBScoicSSSK9iiB B[KB9991B[uiioiizcBǒ[KcoouiSBB99(9ioic[i[ScS99[oouK  (91 991 ( 1911Biuzz[KSKK[9[ɪuzSBK91SK1 (K((9999K[cuiB((((9KKS[oic[[[[c[[ccSioc[Kc˷ҼuouϷzuoc[izzuzKKK[iic[[SSKBSoSBBBKB99BBBSouuuuBKiouǢziooiSKBBB1 cuzo[[KBKK((B[io1 ((  (  (1( 1119KKc[[BBKB[ѳui99K91BSizu1 (1119BKS[cccǼu1(9BSSKSSzoic[[SKciic[SioSi[oݖuuijuzzoiiuuuSKSoo[Scc[K9KSKScSSB9999K[iiocu[B[uz[KBBBB(1zǒiioiS9B1BB911SS((  (  (   (1BKSSc[c[[KBiicK(99 (KcozS19 (191BSoocSScoz919BBBBB[iiooc[SKK[iic[[cicKc[ĀzuizuzļozzuiiuzuocKB[oo[KSiSBK[i[Ko[S[K99BScuoccS[uzuuozcS[BKKK9KSKcoiB((ci((S9 ( ((((((1(  Kou[[zuS1KzzcKB911(((1(( ((1(BB9[uoucKK[[BKoB99B999BK[[oǀuiSSSKS[cc[Sc[SKou㦒zzzzzzuiiz·zzuoc[cuuuzucBK[zi[[S[cScBScBi[KBBK[oiioc[S9BKiS[uuS[zozSKB(BiKBScS 9i9B( ( 19B1BBBK911 ([icuiSB1[zi19B(( (((((B[SioSBKK9 [SKKBBBB9BKKcizcKKSKKS[[[Sc[S[DŽzzoiizɿ­zi[SSiouuzSBoucc[coozB1KSK[KBSS[[Boi[[KBB[uzzi9Kiu[ciKzB(oz[cz[BSi[ 1[1(BB9 ((( 9SSBBKKB9KB191Su[[c[[S9BzucB99( ((((19couuS9B91( cSBSSKSBBKScouuc[KBBK[c[KK[[S[c[zzzuiij–zuSSScz[cuKKuzuocS[uozuBB1KS[uc[SSSSS[ocKKKKKuoS[iiKKuiSoioB Si[Sic[ci[991((19K9(9KB9BBB999K[iS9KKcuuc[ic[SKBSzu[[K199(((( ( ((9Szzic1((zuSSSSKK9BKcoooc[SKBBS[[icSKKKiKozuozǹzic[[c[ciKSicSK[SScooicSBSKS[KKioS[[[iz[KBBBKiuB91KccciS9cuzǒB1uc[SSouiSS[KcoK(9BSS1(B[SBBBB9(1K[c[KS[oozzuzuicSSBSoKB1 (1(119119B9Kcoo[9 1 (SBS[[ccKBSScic[KKKBBK[ucSKـioooui[ioooǹu[S[cu[cSB[9 1KSKBozcKK[cc[BSouiic[S[KB919ioK9B99SuoK99Scɪ9uuc[SSBcco[BB9[[1(BSSKB 119BB99BK1(9BBKBKiu[ciizuciS[iB19 1919KSSKSccuiuS(((  (SK[[iuucKB[SSu[SB9B99Kic‰uoiic[ci[Si͹uui[[czo[c[Su[K[KBSBB[ui[KK[iuc[[oooc[SK9BK[uK1999BB[[BKK[SuiiccKBSiziKK[B1(91BK9B (19991119( (1KSBiz[BBSicoocuzciiccB9B(BooS[uiKK[iizK (((19KzKcSoi[KSK[ccB9B1BcouϷխz[[Siii[SKSiz˷ķzi[[[ouuuo[S(KSBSoiSKK9K[ioiiSc[SKKcouuiB91KKK9KSBBBKKc԰҉uuiBKizo[ocB9((B9((111((  [i[cuSKSco[[oiScS[u[9BBB1 [oiui[cz[ 11(9[B[Sczuic[[[cc[BB99ocSiizɿԖucucuuzuo[[oɹuiicczoo9iSzK(911S[cuzcBB9BSiuiuKB1[iSBKBK991999܄uuuSczocS11( 19( (1( 1B( SoSuziocS[iuziuoSBKzcBB9((Buuiiu9 19B9iBSBKiuooc[[cc[K91Bo[[cio¿깿ouuuzzuoiouzuzoiiiuzziɷucczoccozoKBK9cuuc[KB[oK9BSu[BBB9B11((((o؀uzziuuocSiK(19B9  (1111BKK1Ki9cuooSBS[uiKc[19(B11[zuiio (9B9uBKK[iuuiccizicBB9Kzcc[[oѷתczzzoiiiiouzziiiuu˭zz[[iͷzi[KSzzK999BBK99[o1KK99991( (B[zo[ooocKS9(9BK9((1(111(91B(9[c[iuuoS[cuu[[zS9(11 1BKczuuccccK 199BS9BB[[coz[ooui[BB9Kzciiccۖzuiouzzzuoicc[cizzuioouzzo[cc[cϿzoczK9Scccoc[ozuB(KKKB99( ((9B[ۉzzcizuccc[K9B9B9B9 (9( ((uu[[[ccu[B91((11Soooc[oo(BK99Bo(KKKKKccizzo[KB1S[oocoҚiiiiouooi[ccicc[zoiiouizzoiicic[cuoizccuucoozici[czS91(1BKB1( (BS[SSzzo[[uzKK919SKKB (( 19KczoiS[c³[K119[cuzcSS1(9BK919KB[KKBBiuuuoi[SB Scooz޹occciioii[[[c[czzciouizuizc[[i[cSKB1BSKS[zuioicciB1K9KuuK11(19B91 (Kcoiciޖzicc9B19KB9B1(11991KoKoicuuzu[[ocBuiKiu[[ozzuzzocS9(B9111KK[KBBSuo[B9 i[ciԪzi[[[[[Sc[[S[c[[zozoiio鰀uoiioi[[SBB9KSK[ozo[1 9K91B1SoiS11119BKKKK[ic[c[zټuzzK991KB (11K[KuuKBii[ooizz[[uic[BKcuS(1Boo[c[B(1KScS9( 111iSKKKKSuzocB1 oBcz¹KBSSSSKSSSS[SSiiuoiiizzߦo[S[[S[icc[[iiSiu[B1BSKKKBSSB919BSSK[SSKS[SKKSuѷiciuoo[19KciB (  (19BcoKBS[icicoc[ouuoSBSc[B9B[B( ((1SucK9(((91  1 (1cc[SS[SSSuoS9K9ɭİɖ[K[[SSBBKSSSS[uoozzzzio„[K9BBBK[[S[cuouuSSuzuzocSB99BKBB99KcicSSSSBBKKKBiiҷiBS[c[K(KooS(9B( ( (1SzziB99BBSiiooc[cuzocSSB1BB9( 1911((9BBKB1 ((11BB1((9111uoSi[[[[SKKo٦uϷԒi[SSSKBBKKBBiiiiououziiou܉iuzuoSB919B1BSK9B9SziuuBKizuucK119BBK9Kzo[KKK99KS9[u[[u͒9BS[K1( [uS(99 11Ki[iKBKBBBKciioouciS9(1(((1KuK11((19K[K1((1119KKBBB9ciczz[KSSBBcucԼcc[KKKBB9BBcǢc[cooioc[iɭzz٢iiozo[c91191B91BBK9919[[i[Kcooi[iiSBBBKKKuouiSKK99BB1uuoiSSci[S11Bcu[1191 1([ocKBBKBKcuoozScooB[9 ((Bciu[1(((1 19KB9( 119999ooc[zSKS[SKoiu˷עcocKKSSBBKzzuc[zi[[[iǼzziiiSB9199919BB9KK9999K[cuiBK[K[B9Siuo[[K[zu[[ooKB9BKBKziiccoucK(9ozouK99( Sz9ouoKBSSKSozzc1S[[ouB19 11BK[cuo11(Kii[[KciuB 11((K[KSSucc[KKKBizcۼǷؼ׳i[S[cSBiuzzi[zicccuªעuicSKB11999B9BBBB99BKKKoi[ccSBBKSK9B[iuicio[B[ooSBK[[KciSSiuocczcB(izizSB  ѳScuSBSSS[ozz[1919KS9(1((11(111Kio(1uK1B9Kiui99ui[SKKBBSئ[zdzɍuzziccc[S[zccoui[iiiiiiioooo[KKBB999BBSi[S[SSKicKKci[KBS[KK[[czucioiKKSiicc[[icczuB9Kiu[SiizSKouo[iuBB(11˖KizS9KS[[uzzo9(( (( (11 (1 (9Kucoz99SozK9KzucSicKBBoiԉucǷڳ[[iccic[Kiu[[iuuoicccccuuoioo[9KK91BScui[SSS[[ouoSBSSSc[uoc[SKB9[ii[[ciizzSBBBSicouc[ui9119[[KK9Kii[iuou[9Sc[[iicS911(9BB( (((((( (((((1u9BScouou(SuSoKouSouc[[̀uSǰĢoc[iciccci[S[c[c[iocouuozɉozucBKK9Bcz¦ucouuuuuoiK[[iucSKK[BBKi[[cio[BBBBKiizzii[ BiiiiK1 1ouozzuo[K[[KKKB991BKKS[KB((((((( ((( Su9KKKcioBB1BBo[KccSiici¢uuzǰܭo[c[cicuzS[SS[S[[icciuԞuuzuuSK[iuiSzzouo[czo9K[cuiKBBBKooSS[[ccicB9BBBSc[zuuK9[[cB1B9 uiooi[KKSKB11(1KSSSSSKKB9(((199((1 Bii1B[SSiuzoSB9[Scu9[czooݷuiǹ͢Ϫz[SS[icco[c[[S[[ciiuzi՞ouzuuuziioc[Scuzc[[ccS[oc11BSSK99BBKSiiBBKKSKczSK9999BKBKuuzi[1( ((Bu[B9KKKKKKB1((9K[c[KBB991((((1991 [zK1BSSK[ii[KB19’DŽc[S[zuzu޷oiϳǰzi[S[c[[icic[[[SzouzzɚcozoiuzzzzziSKiiio[S[[[SS[cc[KKK9119KKSSKK19BBSzS9B99BBBBSozzc999 (1BoucK1119B9B9999KSS[[SKB1((11(((((((( Sc11KSioS[cSB9999¿Si[zczccɼiiiSSS[ccc[iSKS[KuuĢiczzuozǭzocuz[zu[BS[[KKSS[cioi[KBBSc[KKBBBBBBu99KBBBBK[uoou9cB9K9( 1BK9KB91B9BB9919K[[[[[SK99( ( ((((11(o9(9BS[zcScK9BSB9iĭzoSiSĪz[[[[[[KScucci[[S[[iԳziooioiozoSKBSSKKSSSS[[[icSS[[[SKKB99BKSuzBBSBBKK[izoizo(Szi((91((1KKBBKKKKKKKB19S[[c[[SS9( (  11(u91BSSScuucKKKK[[K(حz­ozBSݷҿϪic[SSSSSBSuzoiiicc[[uϷii[ioSSiuzSB9BKKSKKBKSc[KS[SKBBBBKiiSKSK[cic[S[cSSS[[uzoc[ocuz[91B9((1BS[[cc[S[SKSScccc[SSKB1((9B991(119S[[SS[SicSBKKSSKSK(➄ɰcSuǍiBiķͭi9[[[[SSSBSzcoiouic[uĪicooBczzzoKBS[[KKKBK[ciSBKB9S[SSScuzoiuzocoicSccKS[uocSKoiBSKKKBKKS[ciicccc[[ciccc[SKB9((KizzcS[ĦcSz[S[cz[K[SKB9BKBzzii1ҍBo˼ª˪oKKSKSSSSKSiuSc[ouiuioļ׹[Biu[[zuuocc[Sci[KBBK[[ciK9BKSiiSKKczuioiiuzooui[BScS[cuu[SK[SBS9 99B[iooic[c[ccciccc[SK9(((1BozzoKKzi[coS1KiK99BKcܚSzS1čiu˷¿ѼͿSK[[SSKKKBSzicccccizooͷoKBScK[izuc[SKS[S[[cSKKKSiiuu[KKcicKB9B[iSKS[oo[cSKSKK[ioioiSK[zoB991((9K[oicccc[c[c[[S[[SKBKKSuzooc[iiSSSziczSu[BSzzBizu19uSϿķҳ˷uS[[[SSSBBzuoiccS[ozzǷicSS[[S[couuiiu[SSSKSKSSKScozucK[c[KBB9[oc[cSizcSSBBKKScoi[cicSozoK91BBB9B1Bouic[[[[S[KKK[ouzzzoiccuc[czzzuuicc[zz[KzcuKiBoSBBi9oǹɼ˷Ϳu[[[KKSSSzzuiio[ScuĿu[KBBBS[cicS[izzzuzzcSS[KSS[iuuocucKc[KBSccui[couzuc[[KBSKSzzioc[KSizzouS9KSKB9BcucS[S[SSSKBKSczcBBKSi[KS[SS[iczoocoocKczSSɢSSzu9SBϖK(Kɿѷ¹Ĺ¼ɿucoSSKBBczzoiio[cuuɰ[BKKBBKKKoiK1BK[ouoooozzucSSS[oi[SKKu[KBB[zuoiSSuc[K[[[[SKczocSScuu[BKSB9B[ic9(9BKKSi[[[SciiS111BB19K999K[ouoizz[ocBKoǀSSozoz9BKzcKB9zͪizİccuKKB9[uzzocccSiuuªҿcB9BSSKKKSSoKB9KKS[couuuzu[[[[SSKKKccKKczuc[[Sc[K[[[ci[SSuzuic[cu[czicKKKS[[SB11( BSic[[[[[KS[S[oiS919B9B[SB9KcuuicoozzcK9KiKK[iuuњ[1z–S[iўB9SϪB9[z·ĭcS[zoKKBcuiouzoii[SSiuuoĹ³B999BSSK[ci[[9BKBBSSSicSSSSS[cKuouuziSSS[i[9Koi[c[Suuoic[ciSczuuSSSKSK99BK1(BBBKBKB999119BSccK9999KSSKB[zucSSuKKcucKS[KSS[oz„zccSS߷BKުSKK11Bǿ³cSKKo[BB[oiciiicicSScouicǿͿ91KK9KuoKKSSKKBK[uo[[[cc[K[Kci[SSS[izB9SccSSSSzuoio[[iKKizziicSKB99119B911999B91911911119K[B1999BBKKSiuo[coiBBBBoٖuu[[iKKKKSiSzSSS˚9ꢄSBKccK91SĹoKSKKS9Socicccc[c[[cioozdzҪuK(9S[Szļi[KK9BK[ozoo[[[cziBBSKzcSc[S[z[BBKSKKSSK[occico[BBcuSc[[K919911B9((11BKB99BB1BB1119BB999BB9BSS[cczoi[[[KBBz[SSK[oo9KSKKozcK9[SKSz9KiBBB[oocK(1[¼[[BiBczicc[[[[[[[[cizzٿ[c19KScz·cKBBKS[zzzoS[oKKKKSzuSc[[[cBKSKKKS[SBKooc[c[cc[KB9SoSB[SKB999119K1(11BKK91BBBBBBB99911KKBK9Bcc[zzouoScSSSio(1B9[BKKKK[zzKBBKSiu1cuS99KScz[KB9BuoK9Bizzoc[[[[[cSScccuİ„Sc9BKS[uɹ[[c[KKozzucu9SS[[uuKSS[SKBSSSKK[[[B9Kc[[ccoc[SSK[cSBiSKBB91(((B1 (91(9BK119SSB9KKB9B999B991c[9izuoic9KBBB9(9999B9iKKKcKKK[ozBBBBB9K[cziKBSKizSSu[9(iioc[ci[[KKcicuz–SSzi9KS[cļuic[[Sco[zoB[i[SioK19BKKBBKSKS[c[KB(Bouiuioi[cS[cc[S[[BBBK99( (9 1919(1BSB91[cKBBBBBBB9BKK99uK(SuoocSSKKB9( 1BKBuu9cSKKSzBBKiiK1B(9BBSSciSKB[o[cuccԼu[K[c[S[cSSiɰziS9K[S[¼uc[[[KK[u[ucKccSciB1119BKSSKKS[cc[KB[iuiciccK9KS[SSKSuzK999111(((91B9(  B[[B1KKKB9BKBBK9BBKKBucK1SuiizocSKKB11999uǦ[BcSSKK[c[B99cz1Bc19KSSKSSKB[iuS9KSSKBS[coϿɰo[KBK[S[zoccc[[[KB9Kic[[ioB[SS[K1191BBSKBBBK[[c[SouiS[[[[[B9S[SBKBuc119911919BSK99( KSKB99BBBBBBKKB1BKKKKoccBKizucKBBB((9([˦[ScSS[ioiiS91cuo(Ko9BBBSKKSBSzuuouooiuĢ˿zu[BBB9KKc[[oicSSS[[[KBBBKic[[K[z(KSS[99KKSSKSKSSSS[[[[iucSKi[SSS[SSKKBB[oB9999B99KSci[B  K[SSK9119B99SK19KKKKSS9KBKizuBBB1 (1KɳSiiSSiiB(iioB(BBBBBBKBB[ǭcoic[ciizԼɭzco[KKBBBB9KK[cizoc[SS[SKS[[KKBBKKczc[[[S[z9S[KBSoiKKczui[S[[S99Ki[KSSic9BKBKuuB9999BcS9S[SSKK9( Bc[S9(1BB119999SKBBKK119BScozzBBK1(1SSocKSuo11iSuSKK9BBBSKi˞uici[S[coozzzͪcB9BBBKKBSKK99KcccucSSKKSSKS[SKKBKKBKczc[[SSSKKzcoiKSuzuuuiKczo[SKK9(9S[KBKSicB[KKioS9BBB9BcK9BB91Biz K[KK99BSB9(19BSSB99ScͭB 1B[cczoiB99((1zioKouoozuc1[zuSzco1KKK[ɍ[[S[c[[uuuoK[iuoĭB11BBBBBBKSB9KS[S[oĪo[cSBS[c[cSKKB[i[c[[iuzu[SSSKSKBBuzoScuzi[cS[zz[czzooooiSBB[ocKK[[c[KSBcuSBSKKK19911199KSτKiiSSKKKSK((19BSB9BKSozK1(1Szuu[BKB1(Su[Suo[KcSBiicouعS[KSɀBci[[ozuouuuuiizzzz˼K1BBBB99BBB9BSKBSiiķcccSBSiui[SKKS[ouziS[SS[S[SSSKKSKKS[KizucS[SB[iiooScoSci[[S[i[KKBSo[BBKcS111111119BSiuu[SS[SKB (19BKBB[KSiiS[B( 9SSBK11(iSSozoSKKKKcioo[cٍɰziɄKizuouooooozzoSKSSoİ9KSKKBBSKKBBKSBBc[[z¼cS[cSS[ouiKSKKKKiuiSKKKBKKS[cc[[S[S[zicuui[S[[[[c[[cScuziciii[[SSKBSoo[SKKSB111111(1199(Si[ucSSKB1 199Bocc[izziKB11BSzSKB1B9zzKKBKK[[uioiSB9Boi9ɷu ϹԿizzoiiozoouuuicK(9K91S¼1S[[SK[[[SKKSS[[iScuo[[S[cK[[ccc[KB99SuiS[SSS[[iuuzuc[cicizzuicioc[[[[c[SKSSS[cKcozoc[[SKKSKBco[KKKKB91119(199(9ҢuoSKSK( 9B9Kzuzuu[KKBKBciz[B11Bioio[[S[czocoz[99[zSͳcKBcǚ9 čcS[[[iuioicK1B[cK11Bizuɰ1[c[SSSKSBKB[cioc[iouu[S[SS[[S[[[[c[[KKBou[S[Sccicizuuu[[iiiuz[ccBioSKKKSc[BK[KKSKS[coiKBBK9BBB[uiKKKB9(119S[B((1(19ϰcSuooc[SSK119BB[uz[ouocKBBiuS[K( 9occSĚoiuKKcǰ[(99BS[B9BշoS[coooccioSBKS[[1((Kuo1[cSKKB919BB[iooScicc[KK[ioc[[SS[[[cc[[[i[KBSK[cSS[SooiKS[ccou[ciBccK9BBBSB1KSSK9cziS[co[KKBKBBKcuiKBKB1911B[io[[B( cɄBB[zzzci[SSK99BSiSzKc[9(BiuK(((KKSu[ϰzo9BuuǼ((99B99B9Bcuuiczo[K99KScS9( Bi¹uzK[cSB9B91BKSioi[SSSSS[SScooc[SSSSSSSScoc[[B9KSccSS[SucKKBB[ccucccBSSKKSBKK9BKBSBBzcK[KScSB9K[[izoSKBB91119S[ccccSKBSiKKiuzicSSS[BBBizuzKSc1(1[u9 ((9iS[uͷSSouiiڹz9 1BBBBBBBBϼ߼ocicSKSK99KKKKKKK1BuSi[K9BKKKKSiui[[cKBSS[[[cicSSSSSK[iiciu[KKKK[cicc[[[i[SK9(SicSBKK1[couiS[[[[SBKBiiiSBSSBi[KK[zucSKKBBK99BBBBBKK[c[KoiSczzuu[KBS[[SKSz[119oS((KϒK[cɦuoiĿˀ9((9BBBBKKKBɦɖzuoz[KKKKSKB19B99SzB K˪ouS9BBBKSKizucooccccc[c[SSSKB1KSScuziuzSBccc[S[ccc[[[[iK 9[[9(KBBicS[cS[Sc[[KKKS[SBSciuz[KKKKB999BB99B9BKKSB1oiS[cS[KKKB[oc[S[u¢[(19[o9SՉK[iɉiooz՚K999KBBBBKB99ĖuuoSKBBKSK9KK999 [zB(11KzijoBKBBSiooucioociic[Sc[SSSK91Sc[SizioioiuuiSSS[[c[SSKSiK19BSBKcKBSicK[S[[[SSSKKKiiSKSziSKSSKBBBBBBB9991BBB91Bo[B9911(BKK[uocSSioii1(9K(19c9[uǒz[ccBKczcouii˒cKS99BB99KSKB9ܼݪzͰicKBBKKKB9K[B11(S(9BKBSoĢzui[SS[[SSSSS[cSKSSSS[[KKciSSBSuciBSS19SKKBKSc[BKBKS[[[cocuiS[SSKBK[SS[[ccK[oziSSSSBKKB999B919919(1((ouoS1( (9SS[ioSSiicuciuoB(9B9KS[z[1KcĞz19[SKKcS1KKKB9B[oiBKS[KKKKB99BKSKoڪ˹iuocKKKBBKKBKB1(Kc1199KKK[uİzii[SSKKKKKKS[SSS[[[KKKKS[[KBBK[SBKBS91BBBBSBcuBBBS[SS[ccSio[[[SBKK[SSS[SKSuzoocSS[[KB9B111119999 9zcSBBSSK[icicczcuocuzcK9BB19KBKBBiiSB9B[ݪ[9KicB1KB9BKSB( (19BSoucKB99BBKKzoբϳzoziiSB9BSSBB9BK1KcB19BKKBB[uo[ccKBSSBKKSSS[[[SBKSSSScSKSK9119KS91KSKKSSBoiKKSSKKSSSKS[iicSSSK[SSSSKSS[u[[oSKKKSBB99199((1111io[BB[cc[iiouoižcououuzzcSB1K[9191999BS[[9KSoS[iBKSSK91919BBB1((1B9 1BcuSBBKKB9BKuԪ׭zozui[B99BSBBB9Kc9199KBSSSKSuuK199BS[iccuSBc[KBKS[SSS[SKSSSSSccSKBB99BSSKS[SB[uc9S[SSSSSKKKKBBSicooici[ic[[KKcooB[iK[KBSB9999991 (11( Bu[KK[SSS[Kzuooiizzi[[K9KK9999999BSiS[ii i[BKKBBB999B9B911(1BB19[SK[B99BKBBBK˪zzoo[KKB999999BKSB1B9 1KKKB9(  11Suuzu[KSS[KBS[SSKSSSKScc[KKKBKKKSSK99[iK1BSKKKSSKKBBScozuoicc[coiciouzoSccKcSBK9B99B999(( (cuicKSSSSS[Szzoicoi[cc[ouK9999BBBSo(cSSSKBB99BBKKB991((119SuS1B9199KBB9BԢui[SS[S919(111BKBKB ( (1  1BB11((SuzizcSSSSKBBSSSS[SKKK[[[SKSKKKKSK((BKBBKKKKKKKKS[[cuzoicSKBKiuzo[cioucK[SBB9B9191(1( 9Bcҷzi[KS[[[ioiiozcoiiiozoB999BBBBK˰i1[c[SBKK999BKKBB999((19SzS11(191KSSBBo͖ziKSSSSK9191199BKBKSK1((( KSKSSSKB9(191u[KBS[[S91S[SS[SKKKSSSSSSSKSKKK9BKB9KSKKKKS[cooioicSKSKSBciSioS99BK[cocBKKBSK99991( (uˢzi[SSSSoozic[zuzoczuuuucuzcB999BKS[iKBoooo[S[SKKKKKS[[SB9199So[99((119KKKKžoٍuzocc[S[SSKK1(191BBBKSKKK9(KSKBK (9[KKSKSSKSB1(cK1BSSSSKBS[S[[[SBBKKKKKSSSKB9K[S919SSS[iuuuoi[SKKBKSB9Bo[199B1(19KBBK[[BBSSSS91911((SĹzuooiKKKozooioS[izuiicuouzuziiucBB99BKKcozuuuzB[uz[KBBBKBBS[ooSBB99K[icK( (99KKKuuװ[ccccicSSSSKK91B99BKSSB9KBBS[KK[KBBK1BB99BBS[BB9[zuzuu[SKK[[[KKccc[SB99BKBBBKSKKBBS[S99[iiouooii[BBK9KKKK91S[(9991119KBBB[S9KScSK9999(1ooizoi[BBczo[cioSS[ouiucuuoiooK11KSS[ccoic[ouoouozK1BBB99BKK[i[[ciSKSio[((1BKKBBuͰooĒ[cicicS[[KK[S9BSBKKBBKB19KSSKBKK99B991911BKSSBuBKcuucSK9BS1Ki[KBB99KSB99K[iiiiiioicooii[SS[SKBBKKBBB1(Ki1BB9B9199B[SBB[[9KSiiK1(9B9ozoiioSKBSi[KBS[icSKSciizoiczuoioci[KBKSScccc[Si[izoSKooSBB99999KBKciizK[io[9(BBBBBBBչ[Soccic[[SSSSSSKKSKB9BBBKB19BBSK91999999991KSKS¢B(1BS[c[9KS(KSB99BBKKSBK[uuuiociiioooi[SKKKKSSBBBBKKB9(cS1BSSB999BK[c[BB[iKBSzz[9(99Soozii[oii[KBKBB(19K[cSSBKBKcoiSuzcicSS[[[ocKSS[cc[SczoSioB9BSo[999919KBK[cizKSuoc[B9BBBBKBѰu[ScoSc[SS[SKSKS[SB9B9BK9KS919KBK919B11BBBSSccožc( (( 9[ouucKB9BSS[[[[ciuuzi[[[KSKSS[[SKKKKKB9BBBB19KBiz[ 1B99B999Scic[KB[i[cuuS1([K[oo[[uzooic[B991((9BSSSKSKSKKioccK[KSKBBKoi[ucSSSSKKcoiSKoouzK19BouB(9B99S[SB9B[uiBKcizoK9BBBBKKњioo[9[cKcSKKSKSc[SSB9BB9KKBKB99BBBSK19199BBiuu­zK (( (Biouo[couuuoouooocSKBKKKKKKKK[[SKBBBB99BKKcuo[iB1119((999BSS[[SBBocczB cS[uu[S[uzii[S[K11(19KiziKKS[cSSozoccSSKSKoziSBooK[B(9[zccKKiu[S99Kic9BSB9K[SB19SS[SBBKc[BBB99BKKɒSKuuzK1S[S[KB[cci[BBKBBBBBKKKKB91BBScB9BBBScuB1(((  1KScouzuoiicc[KKSKKKKKKKKKKKKSSK9BB9BizcKSB 1((( 119KSKSSK99ooKoK(uzc[iu[Kco[BB99((19[ozSKScc[KcoicSSSSi[[S1[occS9BScKcK9[i[KK[SSKSBBBSSK[c[KKSK9BKBBBKBKBKK°uioou99[SKSS[ii[[SBKKBBBBBKK9BB19KKc[KB[co¢[(( ((  ( (((1K[SKSSSSSKSSKBKSKKSKKSSKKBBK[ozcB111(((((( (9BBKKSSK991SuiKKSKS[cS9cic[iccoS99(((19Szoui[ScicSc[KKS[1KB9S[ioi[B 9KSBBciSS[czuS9999BS[zcBK9BSB1KKBKK9S[ĀziziBKi[Si[[[KKc[SSKBKSSBB99KBBKKSSS[o­c1(99( (   (( ( 19KKKKKSKKKKKKSKKBSBKKKBizoS1((19(1((((1([oSSKKS[cSB99BSciB11KK[K[iziKSciucKB9B91Biz[izucioi[coiBBB[cK[BBBKSBBBKB11KKKKKKui9BKccozoK1999KSSKco[B1BSSSccoiҳo[[czuiBSu[c[S[[SccSKS[[SSKKKKKSSKBKcouS199BKB( 11 (19( (19KSSKB9KKSKSKKBSBKizzi[KK11(11S919(91(B SuzzcK11B[icKBKK[cuocBKSSco[SKSSK9Kizuzo[czucci[SccoouzSBKiKB91BK99 (BScSS[SKSzBKBBBKcuoK919BBzoBSou[BK[SSizzS9K[BczB[cS[iooocciSK[SS[[S[[KB[i9(99KKK1(11  ( ( (BSKBBKKBBSSKBSSuoKK9B99999BSo(11 11(9KzoSBoui[[z[SKKSSKBBKSB9[ouzouu[czici[Scc19[iB1([SBB(9S[[[[S[[Sǒiz[9B[[[iiSK9BBc[BSic[[[SSozuuzzzuzzuzzzzzzčcS[[[iz¼ɿizuS[[[SSSSuico[SS[[[[[c[Si‰SS[[SSc[[[ccccc[[ioi[[[SS[[izĿķcziijўoc[S[[uuczi[cc[[SS[KS[[[ioui[cc[[oozuzzzzuzzzzzzzzuzҢiiizǹ¼ĦiS[SSSSSoo[ccSS[SS[[c[SoĀ[S[[[[[[cS[ccc[[cii[[[[[[ccczzš[ooc³˚ocSKKczcuc[cc[[KS[[[[[[[cooiuicizzuououuozuuzzzzzuz¢dzɳ¹zocKBS[[oc[czKKSSSKSS[Soz[S[S[SS[cSc[c[c[[[[[[c[[c[iiuouu͢iccSu­͖cc[SKcuzSozo[[[S[zSS[c[S[[[cozozoiooiiziuzoiuzzzzuzzտ­cS[[[[S[SScSSSSKSS[SSc„[[[S[S[[cc[[[[[[ccSc[cS[[S[iouuz͞ic[KiĭϚc[[[S[ooi[[[[[Sz[S[c[SSciccuuzuic[ciiouiozzzuzzzǦɹɿzucKKSS[iz[SSS[[[c[SSĒSSKS[[c[ciic[[[[c[Scc[[cSS[cczu˖ccccoĭϦu[[c[[ic譍9KSSSSzS[[[[[S[icizzoioucSS[uzuzuzzzuzzǹԼ˰i[Sc[iz[[Scc[[[S[[ɉSKK[SS[[[ic[[[[ccc[[c[[c[[c[[uiz’ccouzĭҪccc[[iS[迍c9KSSSKKSc[[[ciiiciuĀooc[oi[icuuzzzzozɳijڷϞĿuizo[[[S[[SS[iuS[[[S[S[S[[SSS[icc[[cc[[ccicciuҹccouİ԰cc[S[cBiϒSBSSSKKKS[ccccciioܞcicciuuuuoiououzĪ·ԭհ¼ˍi[SSSSSSScǼoSSS[ScccS[SSK[S[[[SS[c[ccc[ccuizz׹cciiİտcc[[[[KԍBKSKSS[S[[ciiioz̈́iccouozouuoozzzuzouuzɳ¹ĭ³˭ǼͪocSS[[SSc¹uu[[[[[cc[S[[[S[S[SSS[S[S[S[[iooz۹[ioiijѦoccc[[ciKSSS[[[[[ccioz߰u[ioozoooouzoouzzɷ˷ǹݰǹ¼o[SSS[iǼSS[SS[[[S[[[cc[c[cc[S[S[SSSiiočcouiij‰ic[[KoS[S[ci[c[[[ioҚ·iuzz˼˼ѭҼͿļĿc[[[oļ[[[S[[[[[SSciic[[ccc[[S[SS[[ciͿcuuzİռi[[cBS[[cc[[iciizɞİoɿ¹ϖdz¹zooĿuuiic[ccc[S[[cccc[SSc[c[[c[[SSz[cİ[uu°ϢiKScSoc[c[ccico͢¿[u¹ǼͿdzɹѿªǿ¹Ĺz[oc[ccc[ci[ci[[ccc[[[[ccSSzi[ѳKouѿljoc[S[SS비ccciciuĦՀS[Ĺ¹³ͼǹ׷uiļɿҿcic[iicciiccci˚oc[[[[[S[[oiczշSiuzҿռ[[cc[[u鹄iiiuzԿķٳSoĿzuԼ˼԰ϼԖ͖ǷijijǰǪocciiiiiciczuSc[[SSS[czocuҹ[cuz¦Թ[[SciiuiiuĦɹҼĿͿڹij؞ϷǪɹzouoiioi[u՚cSSc[cc[[ocz߼ҿccuu¦ҹz[[S[coui˰͹ķǰziu¼Ĺͭ˞ĹްicicS԰cBccccSSSzucҹK[ozտҳzScSKKiuٳͰɚžuSiĿϿݦѿҭͿ嚀uoتccc[[SS[SuziuѭBcii׿ѭzSiSKKccǼͷϹҀio·忷ǰɿҼ݄¹¼’c[cc[[S[[[SuciѪKS[[¦ѰcoS[[[i­ؿϳǰ˷ķڄuuĿoo˭ĿϿɰķɼ͹ɭ׹zzKcc[[SS[cc[Szzoi׳[S[[Ǫѹiouuu˼Җzzǿϼ뉀zz¢zi˷³˪ļؼijǹž͖uu[cicSKKS[S[Suuouڼc[ci˳–io·czoɿ·󀀄¢ucǹͪԼҪɿϳɿ¿Թ·Ǧiiu漉zic[S[[SS[Soccuعiiio˳ɪozɿϚuoczz¿񉄄¦zcu¼ҷǰϭ밒žĪ¿˼ǿzooļ˹uic[icS[cioSuؿiiizĭɷٷoKiz[zuzzİizۿؿɼܚzǹªɹšϞĿuuc[S[i[͚iiiu­¼ͳےouzzǼuuĿѪdz׳˷ϳǹعiuz¿¹ocoٳou°ɹªͷͳuuzĦzuѭϷչĹ湀ooĿ¹ĭĹĿ˷ĞԳ߷zǰzؼϷ¼ѿ˼¼˦uu¿¼ļ¼zoɷljoѿzɹzѹ¼ѹɹĹɿǪԷijociǹ¼¦uoiuc[ؿ³Էc񄍍ĚzϳļϹͷϹļ°dzɿuzz¼輷ͷccSSc[c˷ɰiu쉍zͪzu¼ª¼ǷoozͿ湳¼ɭuii[[[[[۹zҭuǿ³iš·ҹİoiocu巷³Ǫoooiic[[zªǿzzԳªɿɼžooļҿĹǿzccco伿Ŀɭuoooicc[ٰ¿ꉀzuzzҼǷ¹˼u¿uǖiciĿϭouuiiiocתͷꚒoizĭz[ļķ·zټɼ˼ĦҪiououioԪԳ갦zͷu[u°¹Ĺ˷⭹ܷǿijuoժoouou[[ɖļ꿷ѷzBKo·Ǫzžܷ͹·Ϫɹ[Kozoسuououccu¿İ˷ooͷ͹ϿժiSK[uܿuouiiui[c꿿İǿoo°ͿϷĿ¿ޢĦcKSczziɄoicioiKiu輿·zɼoijzļɭ忿ټuSKKcuuiҖic[coc[фo榳uǭcoɹ٦ѿݷoSK99zzu[՚cicciccɭ斞¼oidz[[°Ϧɿĭi[Buuuzcۢio[[coi㖢zzuo¹ciz¿ҹ³Ͱ༰ͷooozzuoڢuuiciocۖļzzz¿ocٰĿ˿⹳˰Ϧooozzuoٞuoiiooc͍Ǽu¦zc˹ļ¿ɼҖiiozzoՖuiiiiii„ļuĪcuѼ·ǿijǷϒi[ozziՖuoicciiך€z¼Ŀ°izijķͿdz˷ǿ޹oiuzoՖoiiccSuuuz̀zѰϷǷczļɷɹĿϿϼߦoouzuњoic[cBuuo˿uzzuzzϷͿǿiu˹Ǽɼعؼռْ¼couzzzύoociiizouuo˿oooooouɹѼǦoi¿¦ɿͿ¹ǢĹɍ¼ciouzzooccioS氀uzzɪozzuoioɼ˹ǰziϼ﷞ǿ¹ڢⳒ¼z[cizuҀ[iicouuᰚzĖoizzuo˹Ǽ˳iǹĿɼ¹·ٖ°[[izoٍ[oiiz㼦iz’zSouuuɢϼi¼⼿ǹͼķϷᦰˉǼcziٖizuoĞužKSouuzuuuzĢѿ[iǹͳijļ°עṒ·ɍoٞz繄˰SSizzzzzi[ccciiouzǹǢoiտ³ǹİح¿Ěuզzzuou㰖uScizuuocSS[cciiiiz˰ɭo˳ѷɹ˷ɳ߿Ԫļuzuتiiiiu෪coiuuuocSS[cioicciĭ˰c˳ɉ˹ǷϹoǢϚ¹i[Sİzڞcui[cic߳SzuuoiSSSSiouuiccizzcuİ˰ozͿdzϦ˿¿³zҳĉ˹c[oݦccccccKoczozzii[[[[[oooiic[[oiSSiͳǼuǪǿļǿ翹˳Ǽziioucccc[Kczzouuoii[[[[iiooiic[cc[[[[[Ұ¦zu¼ͼ˹ᦳϭ¹oicҞi[[cSuuzzuzicii[[iooiociiii[S[c[cS[ɳǭiǹzzɹحԪļ¹iiiټo[cc[䳀zzҦz܄oc[ccccioc[c[ciicSS[[[c[KS˼ѳ˰io¹ϼu[ϼ͚ĿķicoؿcKcc[[ou¹͹uz߹oiS[[[iuoc[[[[cic[[[[S[[KK[Ѱǹoǿ˳czu¦Ĺҿɢ¿ijzocozǒc[c[[Kuoijoczzuoi[S[ioocic[c[Scii[SSS[S[SKSoij˿˷ѹ¼¼ǪĿ°zicuǷۢicccSi[ۖoϳ˪uioщuuuc[cciciicicSBSccKSSSSSSSSSBSĹɼǼϰͪzǼɦĿļccoךoiic[[[Ϟ°ްzzzoouzuic[[[c[Sic[KS[[SSSBK[KSBKKKiҹǪ‰žɼǞĹ¼[cu¹zu՚ooiccciҰu׳zuҞiiiiouoccoiccS[cSS[cc[[[BBSKBBKKcci˼ɳzͳ¼ɳǼ˼ɢɼ¿ciziբiocicii˚ozչouiǭzii[[ouuuccic[SS[[[ccc[SSBBKKB9BK[S[oݳ˹ϼĹγ¼Ŀ͞ļ¿cucئoiiiiic‰cu׳ͪou˦o[[[[iuzcioi[[SS[ccccSKKBBB99KKS[iiu޼Ͽ³·ķϚĿu˚ziٷuoociɄKuĿĖucۼɚSSS[[czocoocc[[c[[[KB9BKBBBBKSSS[ciĿ°ϿĹǦǿϚ¹¿ҚϪouުoizuўzĞS[SS[[oiiicc[[c[[SSKBBB99BBSSSS[iiiΦ¹¿͞ĹǼ¢uuޞzoozzҰ¼ɦic[[[[iz[[ciicc[SSSSKBB99BBKKScciuuz˿ǪĿķҼҷɦ·­zcz¿˳uc[oݒzu˚uozªuc[[S[[ocS[ciic[KKKSKBBBBBB[[[[[cuouǿ˳ɿĿіĞ˞ļijoiuѳiS[coߞuzުzizii[[SiicS[[[cozc[ccoiKB9BSKBBSSBKSKK[cioiooԷ˹ϰİϹ˿ϰɞɿªccooԞuc[[ccciԖo[zzoiucSKczzzucic[SSS[Scz[S[ccBBKKBKBBBBBKKKScicccioiǷ˼ɭǷĭĿǦǦɿĪccuz[Җii[[[[SɄǍǹuooc[cuz[KKK[iic[ciuozcc[[SSKKSSz[KSKBBBKKBKB99BBBKKSc[[ciicSͿɿɼꭞǹĹҭĪǼ˪icoucϒci[[[iiijզ¼zuo[S[icKKSSKSSKSSS[coc[[[SKBKKScuKKK999BBBB9B9BBBKKSSSS[c[S[cǭؼ¿¼ļɖɦɚicoziђiiicciǷij­uooi[SSSSSS[[SSSSSSS[[SSS[[SKKKKSKiiSSB11BKBBBB9BBB9KKKSS[[SSSSͿ˷ͭͳ¿ǿĿѹɳİۦijўǖiciiԖ[ciiѦ˹zci[c[KKKKSKS[c[[SSS[S[S[[[SKKBKKS[Su[BKB9KSK9BB999BBKKK[[[SSSSSɰѿڭɹ۹ĹռўĿǹiiuci՞c[uuiܿ˒ɷzuicc[[SKKSKSSS[[SSS[SSS[SS[SSKB99BBKK[BKKB99BBB99999BBKKci[KSScco¿˰ǰҷĒļĪҼzˢҿǭccooozoٰzzoް–zi[[[[SS[SSSKKKKSSSSSSSSKKKcSSSKBB9BBKKKo[KSK99K919BB9BSBKS[[[KKKccc׼Ѽ˭ݪҿ͹u͞ϷicouzzuϳĞoiz[[SSSSSSSSSSKS[[SSSSSSSKSS[SKKKKBBBKBKKocSSKB1KKB9BBKBKBKSSKKBKKSci˿ͰĹ¼­İњԹo[iziɪocSSSS[[KKKSSKS[[[[[[[KS[[SSBBKKBBKKBSKSocSSSBBKKBBBBKBBKSSSBKBBK[ccǼϹͿϹɷǷͼտ˒ǿ˰czo³ijuzzccSS[[[c[[[ciooi[ccoooucSİzcc[KBB99BKSK[[SSSKKKBBSSKBBKSSKBKSKBKS[[ǹͼ¢޿տĚҼϰǹoݳ᷿ĭiiozoS[SiouzzziuoižiBKBBBBBKKKS[[SSSKKKS[SS[[SKBBKSKKKS[co¢ɷĦİҼѿz¦Ѽͳi袀߼ioooozuicizzzizuuzǼo[9BBBBBKKK[[c[[SSKSSS[[[cS9BBBBBKKKSSKSɢ[İ˿·­Ѽɷ¦ziܹͼϹĒ˹Ѽ࿰ǼuiSuzzzzzzzzuuuu[[iuɭiB9BKKB9BB9Scc[[cSKSSKK[[cKKKBBKKSK[[cKoč¹˼ĿϹuo͹Ϳѷ蒖Ĺ߷ɷo[ouzcizɚ[BBBBB19BBKSSSci[S[[KKSSKKKKS[c[[[[ii[ͼѼ°ɿͼĪҷšuԼɳij񍄹˦ޭiizzoozoi˼cKKB99BBBBKK[uu[SSKSSKSciooo[[S[iioǼ¿­ļĿǞϹzdzoѷĭ˿ij漒ߢˀczziS[iuiiz˰zSKKBKKSSSSS[uuS9BK[cooouuuoc[S[iicuǹ˿·˼Ŀ¼˿ǼҿҷժǷuҪ˹ͼꀭǞ㰒ߞĄuuzouiizzi[uzzooozooǚcKKKSKK[[[SB[c[KKS[iuuiiioooocc[[cc[Kͼ¼¿ɭǿuuļĹ¿ռ[շϢҼ¹섦ǪĦ঍ Գuciouiczo[cuuucioozozzuu͹SB9KS[[[K1(9KK[uzzzoouuouoi[SS[iiK[ǖͭ¹u[oļɰԹi͢zԭڼǹѿͿ߹ݖݞljoozoizz[SouuzuzouziozzzziͭuSBKSK9((1SiciuzziiSSSS[iciic9װiiuz­dzuciiuouozĹ·˷ռz­ݹϿչǷ׷–o߭ߖڪњcuuiooooooozziSiuzzSuĒ[SKB91(9[oiciozo[SKKKKSS[SSKSiiuҳo[[[ciu¹°zciicc[ioozǹټ͢ǰĪת̰갞좹–c€ߞܢi˷oiuuizuiouiouzoiooioozS[˹u[9((KSiooicozzcKBKKKKKKKSSSSKSicuu[ccooiccio¹i[iccc[ioooiͷܷ˿Ŀļؼ¹ĿķԿ卢ꦪ³τߪލioǖiouuuioouuoouSSuǞc9BciiuooizcK9B1999BBBKKSSSSSccczBcoooozzzuooǷiicccccioioic˷˪Ĺ¿ҭ¿zުϰްѭ°ռ閞ɼDŽܪޞzu[czuzziiuzKK[couuooozSBBBBBB99BBBBKBKSSSSSic͒Sczuuuzzzzzociu°ccccooiooɿѹ¼ͪ¼zѿܿɹ¢ɳzܞޢzzciuuiozzuozKKSoϿzzzzcKBK9B99B9BKBBBKBBKKKSSouϚzzzuoouĿѦc[ciouioz˪İ¿ĪɿͿɦu˼ܼ˿ɞ󹍪uߦޞz˹ziouizzoioouzuzuoouBKKSzͳİu[KB99BB99BBBBBB9KKKKSSSS[uɰzzzuuouɰuoooooozzڪdz˳˹Ǽͦzu˿ǪǢz೚ߞҹuzzouuououzooicooBKKKSͪԞcKKK9B9BB9999BB9KKKKKKSKSKSo¼iuuuuͳzoiooizc’͹Ϸɷz³Թ¼氞ේⷚѹzcSzzoouzuuoouuuoouzzBB9BKiϿɢiSKSK9999BBBBBBBBBBKSKKSSSKKiɼĀcuzuѷzoou[ڞͿǰǼ°ٿcْݷ­Ěo[uouuuuuuzzuuoouuuuzoiuuBBK[[[uɦzouc[[SB9BBBB9B9BBKKBKKKKKKKSKcoĹĚ[zzozžuuۭ³͚dzǦ˭Կڿcicڪἰuuoiuzzoiiuoozzuoo[[oo9Biuo[SɼzcuSSSKBBBBBB99BBBBBBKBBKKBBKSiļzouiuuzĦuǰ°dzĿϹ³˭ǹžɳڼꖚɢcS[۞ު͞zuioozuzuoz[izziKi˳uuoKS[SKBBBBBBBBBSKKBB9BB99KB[o˖zoioiizɪɿɿͼѰɹķ׿卢Ԫuuuiڦުɳ€zuzzouuiuuuc[˞[ci[S[SBBBKKKBKKBKBBBKKKBBBBBScѰzioooiɰϹĿϳǿͿԹzϪzu伳ڭݿuuzczocozuuzc[i„S[[Sc[BBBBK99BBBKKBBB99BKKBBK[zǒ¹uiuoouĿɷҳ°Ŀ¿Ұ¿ѳSǚuܦݿzzuouuuozuioo[KcͷoKSccSK99BKB999BBBBBBBBBBKKKKKiѪķoouooļǼѿ˰շɹ¿ԼǿҳuĞٷږ߼zocoK9SuiS[ucKKcɚKSc[[S99BB999BKBBBB99BBKSKKB9cǒǷzzuociǼdz˭Īɼ­¿ѷɪ泹–ݿڢۦuczzozzKKKSzzuzzzi[ciBSuĀKS[[KBBBB99B999BB9BBKS[SKKKBSѷ³uouoio˹ɷĭdzٿ¿ɼ̼­ՖĚuzcuzzzouiS(KououuzuucKcϷiKccKBBBB9BBBBBBB99BKS[SSSSBKiͪǪuioc[zǼɳ°ೢ˷ǿĢǹ¿ﳪĿῢԿҖocououuKcKB1(BcozziKciϦc[iBBKBBBBBBB9BBBKSSKKKKKKKSožɰzocc[i–Ƿǰ༪˿ϭ·ɹѳɀcz[oziooS9 9BB1SzcSiǒzž[BB199BBBBBBBKSSKKSSSKBKK[ioͼšiioc[SzϞ˹dzǢϰ˿Ƿ¹عoczziioi[KKc[BKuz˳SSuϹ[BB9KBB99BBBKSSBKBBSSKKSSS[iiҿٿcc[Scuĭչķ¼ۼϿ­ԷĿѭuizuc[ozii[uo[iuizziKKKSKSKSKKKS[[[Szҷշ°zzuzĹ1(99SKKS[BBKB[Թz11( ( (((((((( (KcuiSz[co[KKS[[[[S[zzc[c[[oziiuuzĿĿ[oiuco[BBSKKco°iS[SSc[Sczoii[K[[SizzcSSSSSKKSKSSSSSKSz³ǹǭzuzzuz·9199BKKKS[[S[BB[Թ͉1(((1(1(1(((( ( 9S[icBiouu[SKS[SS[SoiSccSuzuiͿĚziSKS[cS[oziĚci[[cicc[1S[BBBSu͉[[SSKKKS[KKSSKS[[i·ɰozzzuo¿c1999BBBKScc[SBB9BͿ˞(11(1(1(1(1(( ( (19[[cSSci[BKSSKSKcz[[[cSuzuͷԼ[SS[cccozuo[ociouzuBB[[BKc­iKSSKKSS[SKSKSKS[coļ͹zzzzuzuķiSKB919BBBKS[i[B99(i˦˰9(((( ((((((( ( 9BB[B(BuucBKKKKSKKu[[ci[ouiiͷz[oɒcBK[[ScuuǪSioooozuiccSSc[S[uuu[KBKSSSSS[SSSS[S[cizϼzzzuĹSc[SK919999BS[KB91(SͭɹB(((( (( (( ( 1(19((19ccS9KKKKKzciio[ucccozzϚuzզicocciĭzci[[oocSS[ccSKScKiKSK1999o[KKSSSS[SSS[SSScuļϿĹSSK[[SB99999BB19911(Kϰc (((( ( (1((((( ((( (((( 9uzo[SKKKKziociizocoozzĦuz˰¹ccciiiic[ScoccKB[S(1KB99BKBKoccSKKKKSSS[SSSSS[zѼ¹Ŀ[S[KKKKBB1((199199199Bѹˉ9 ((1(( (( ((( ((( (((19S[KSKKoicSiiioozͷuucSu¹[ccSiiKKS[ccc[KKSKBKSSBBSSKiic[SSSKKBSS[[ciijͿͦiKKKBBKKB91((111119999¢ѭcB(((11 (( ( ( ((( ( (111Si[[[K[i[Sczuiouuz˹uuicSizui[oK11K[SS[[SBBBKKKKKKBSuzuiiiSKKSSSiª˦c9BKBBBBBB91111199991͢ҿzS ((((((( ( ( ( (991(KcS[[SiciozzѿouoooiiuuSoiKcB91K[c[ccS999KKKKK9Bucuou[[SKz¿¼ijɢc9BK[KB9991119999B9 [ˢѿoz[( (((( (1(((11( (1(119SzoS[[[oucuuzzļͦuuociiizo[K[[BKoK9BKB9B[uocc[KBBBSBKK99z[zzcoѿĿijªĚ[KS[[KBB91999BB99B9Sɭc9uc1 (((((1 11( 1(( (1111KzScccicucuuuz˷Ģziczoizoii[[SiiKKB(9B911BSKK[i[KKKKBBKKKSK[uooz˹¿˷³˰i[cc[K9919BBB99B9Kѷi9ui9(((((((((( (1(((11(((1[uc[[[izuc͹iioczu[KSKKc[KBuoSKKBB9[S99KKS[KKKKBB99KKK[ѰǰճļǿǷļ¿¼ɭzcc[KK9199(19999Sҷi(Buo9 (( ( (1((( (((( 19B[uS[ccozzտB99KBKciuiKSiSB9BK1([[B19BBS[SSKB9B9BK1Ϧզ[¼ؼuKKSK99919BB1919ѼҞ( 19izK(((( (((11 ((((((( (19Biocicciڷͷc(1K[[[cicS[ooiuuzuizzK9BBBBKBSKBB99KBSuuioϼu˳¼¼շiuiSSB9KB1 9K(ѼτK1 [S 1(((( ( ( (((((((19KKcozicccczizҒiǚiBBS[[SScozK9BBB99SKBBBBKBzc99BS9BѼɦͿ¼ѼϦoiSBSKKuٿѿc S[(((( ((((( (( ((((( ((1919ciccciэ[ljSKKS[[SczzzB1BBB9KKB991KuKBBKKB9BѭĚǰuoiu¼ɹĞicKSĉB 1uoB ( (11 1( (( 1KScoiuozzuoS[[SSScu[SKc[K99BBKoz11B99KK9(1[uK199BBBKB޼Ͽͦͪzuzu¼Ŀͼ[9Bz͖S Buz9 (( (((((((11((((( (((9czoizo[o–c9SSKSco[KKSK[[cc[KKB(11[zB999BB99iB999BBBKBB˹ɿɦzuuuuuuzzzzccu¿ķɷBi˿͢K(BuuK((( (((( 1( ((((11(111(((Sozozo[cѼ1S[[KciK9SSK[[[ccc[KK19BKKc[1((9KzSBBB[o[KKSSѹɦuocozuoiuoooiuzǿªϹɼuİҖ ([zB(((((( ( ( ( (((1((111111Kuo[ouѪuz[9SSSiSKKSSSKSc[cic[B1(99BBBcz[Sicoչ¿ҪzuczzuS[uzz[iouuɿɦ¹čiKBBBcɳɦi((([zS( (((1( ( ( ((((111(11((9zzzucizoۿuKBKBoz[KSSSSKKKc[SccK9((99BSB1[Ϳciuuo¹Ѱ¹zoB99BSuuѰdzo9BKKSiǼ¿oBҷS(11[[( ( ( ((1BB1111(((SuiiuҖoS[ozuS[SS[SKSKK[c[cS9111BKSSBBKBǞoic[ccciooozzz׹˷Թ°޹ouoiuzzooiiɦzҷ·ĭiS[[K˹˪iSˀ(111Szi( ( ((( (9B99111((11[zcuͰuSKSS[[SSKBS[[[cSBBKKSSSKKKSBuuii[K[ccic[cc[[[ǿϳĖzu¢zuuuu³ĹčԿɭ˹Kuˢ(111(KuiB ( ((( ((((1((1199((9( S͹͹dzzSKKSSSSSSKKS[S[SBBBBK[iSKKKBouzouiioccii[K[ccc͢ijuoĚzuoooiu¼˿ǿˉ˿ٿǀ(ǹB(11((9ioB((((( 1(((((1(999(( 9cҼǿocciz[SSSKKSKKKBKccS[B9999BSKKBBuu[izooozzoouocciiccɹzzciuɞzzzuuuoiͿĹߪտ¿uǒii1111(1[zB ((( (((((1119S[SS͢iKuѷK9SSu[SS[SSKBBKSc[S[SB9911K[[ooK[cuoizzuzuiiioc[Թ·ɼݿ誒zϞuz˼¿€ͼǿ[ K˭ѿc 9111911[zB ( ((9911KԞc9SoiՒoKKc¼cS[[SSSKSKK[[BBKc[SiuiSSSKczouzzuiccicc˰ްݰݍԞzzuz³ҳҼzļªB1(BѿS(911991((Kc((1(((BBKu·׿1Souo˳KScļic[KSKKBSiouooooSKKSBSzucozzzzoiciuzۿϰɖͷϷzoiouoouzɰϞĭz·ž9 ((1uS(111(1111(Bzi1(1 (KiͿ9ccuBc¿ķucoooiuozoiSKKBBSKKioccozuouoozu߹ɪҰԦѳzizϰˢuķǢ9(( cђ (1(19911(BooKBSǰu9(Szc[KiĿĿǿiuiii[ic[[ucSKSBKSBBKBKcc[ioouoozuoooǿ׷ļ͍Ǽic[zҼͭ³uĹ˪9(((( [ϒS( (9B9111(1ҿi9Szzo[19Koܭucc[[ǿziicSScuc[KKKS[SS[SSSBBBBK[c[[[[iciuouo[˳ذɦԳiķ˰ĭѪuķҷS(1(((((SˍB111((19SҒ9(19S[BiiB[iu[i[[ĭ¼o[[KBi[BSKBS[[[SKKKKSKSKKizzzo[SSSiioiSɦˉؖizͼ͹ǹǪ͢³c((( (((9խuSBK[ۼo (11BS[[SioucS[S°ĿĢoBKBSBBSSBSSSSKKSKSKBKBBioSK[uoc[Sǭž󳍉uҼɷԷɹ˭¼˹ϒS ( ((1׼ĖK 1S[91BcoooociiSo°¼ǿɼc999BKKB9K[[SKKSKSKBBKBczuico[[cǷoo9cu¢žҰϰdzϼo9 ( ( (KǼѪc99S[cii[ozu[ذ·B19KSKKKS[SKKS[ccKBKSKKcuuuuuozzooiɹڿozͼɹĿϿ׼zu¿¿ĢK 11 ((11K[iiۭcccB1SS[ܳ¿[Sio[KSSSK[SK[c[BKBKKBS[Scouuzuoooo³¢˞zuɼ·˳ϳύu¿˿ўK(((111(1BԪuc19SسԹ¼[BKKSSKSSSSKKBKKKBSK[ccoioiiuzͼ˰ccoz¿ǿ¿·¼ٷ¿¼ǚB((119oԼz1Sܭˉ9SǼǹoKKSK9BKKK[c[SSSKBKScS[cciciz˳oѼ˷˷̀ϿzĹĿ׹³·ͿļĉB1SzٰoK(oɳڿɉ9S[o¼ijiSKB99KBKcc[[[c[KKS[SSSSS[iuu°ijԹ媀¹ɼǰ¹‰ǹҿǹ¼šբciiK[zϿ˿ɳў[KiiKSĿ³S9919BBKKKBKSSSBBKKSKKSSSc[iϿǹĚ¼ѼɄdz˚¼Թ¹¿Ŀɰϭ9KScϢ޿z[ci[K9Bɿ¿c991BBBB991991BKBKKKKBBS[c[c˳ijdzѼѳoiɰмҿǿͿҳo[ͼ׿ĖoiiSKK99uĹ¿c9BKKBB9999991BKKKBKBBBS[[[cԳoͼͷǚ˳uuǿĿ¼˿˿˹ɳ¿׹ĭo[KKKBBBiǿ¿u[BBBBBB99BBB19KSKBBBKKKKSciiİԢĿ[ĭ­·ļɷuҚĞǿĹ˿ҭɀoǰտo1BBKBBBKo¿uSK9991999(9BBB9KSSK99KSSScoooɷǭߢiKcu·Ͱ׼ǼɿzϿͪ¿¼ļ˚zټB9Bcİ[9BKBBBK[¿uKB9B19199919KB999BK99BS[ccozuu¹İizSKڼdz¼ĭշϰ·ļǹҼo[ϖSKB9BKuҹK9BSK99zuSBBKSBKKK99BBBB9991199Kciiozzz˳᳒ozzzҿĿͦ¹ĭݼͰij˼ijѰc(Bް[BBSB9ScѦiBBKKKǭˢuKBSciiiii[K919KKB999KK[iouǼĞ༞¦¹տɷͳĦĭͰ·ļ·Ϸ1 iݦBBSKBBSizo[izɳoKKz¼ijoKSiuuzzzuo[B9BKKKBBBK[iuĿ·¢׼ɿҿcBiĿĪĞzzԷɼĿǼĭz[ڰK9KKKBKczzS[ccuuzǭ·o[ozzzucKKKKKSSBScoϪoi׼Ŀ¼Ī9 9BzǷzu·ozzؼĚļ·ļķuѢcBBKKKKSocccccSouzɭǼzzucKKKSKKKS[u¼ҷ͉Ͽ˦¹dz(ڭ9cɿǿͼzĢuz٪ĭ¿¹ɿ˿³ozխ[KSBBKKK[oiccccKiɪicɦļzuSKSSKSSSi˼ϞѢǖ˦c1uǿǿuu͞uuɭ¹¿¼˷ǼǹuǹoSSSSBBS[[iioc[[[cԿoSo˪˹oooKKKKS[czͿ迭ҭҷͦo9o˰ĿzioljoǢǹ¹˰ɹ·zu[SSKBBS[czi[ii[[[[–¹Ѱճǹzzz[KKSS[[uǼݭϷɭuKuccǿ[KSouiiiozo˷ѿ˪ǹ˿·ķzɼ¹u[KSKBKSSSzo[ccc[S[ǭҭ¹iKKcc[SiĦuͭĹڼɷɳzoiu–cczcouc[cooouĹѿͰͼ°Ŀª·zķu[[SKBKKKSii[cccccSͳԷiiS[ii[Kc³i[ɭšK[oozuܷoiiuuu[[ciouzzozĭѰİĿšzɹu[SSKBBBK[cS[ccccSoɿ޿Ėɹzzuzuioi[[[ci[[[­׹ououiiccooouoi׿ǹɹ͢ĹziϿuSSSSBSBBSii[c[c[cڰ­ͳ࿿Ǫuuuuzzoc[[SSzocK[ѹzǭѼzuoooiiczc[ciiiuuii˷ͿͿǢ¿ɭo[Ͽi[[SSSKKKKiuoSSSoݹѿԹǭzzziSKBBKiuizئĞoiuuouoiuioicccu³zļ¹ž˼ѦiĪo[SS[KKKKKS[[[uu[coSu˒˼㹉͹¼zuzu[KB9BK[oziѷzǪuooooioui[iiuԷļ˿⹒ҳˍ¹o[KSKSKBBSK[zi[iiouK[շϹuzuɹzzouzcBB9BKKB[uzc˞zccuϼɞoicozzozoiuzuoK[ciԷĹٚ˷٭ѷo[[KKBK9BBKKoocioiioizǷϼذzizc͞o1KuuzuuoSBB999BBKiuoiuooo·uoucSziiiuoooooczc[[cuuǷѰװܢϭ¿iSSSSSKK9BBSooioiocicª׼ҳiK·Ϲc[¼o[KKBB99BBKSioozuBўoczɿ³zuuzuuuzziiuzoio[SciuzռĪٚoĪĿKK[SSKBBKKu[oooi[cѹذoö́zz[BBB9BBBKSKKcuo[ǀzϚocoɭļzozu[ouuuzuzzzo[S[iozعѦĿ·բ˹¼ϼoKSKBBBBKiǢ[iooo[[ɳԼĭհz[(z͍[1KĭzcSKBB99BKKKKS[uzoiuzuϿĪzucuzzi([[ozɳǪ¿ɼͳ¹˦iBB9BBB[Ϸioii[uͪu[czS1(iiSSSKKKBSSKKS[Suzu߷˰˿ɢzuiiizzozzz9[iiz԰Ŀͭɼǒ[SKKBSɹo[[o·᳀ɿSozi€[11zu[SSSSS[K[SSS[[[z㢍zɒ׭zzuicccoo[SiozcSuSioo¿ɿɹ˿ͼo[SSϿɭi[’ɿScuBzՄii KiiSKSSSS[K[SS[[ciuoͼճucɼzԼuzzuuouzi[[[Kcoc[oS[ucczuicoͿĪ¢ٿճuuSu͹°zǢ⿷iBooSozB9Bo[cSKSSKSS[[[[Sccuoizzݭzoci곒u᷒oouzuc[ciioc[[S[iziiKScu³ǹѹ¦zզu­¿iSoǹɉzԳB(KcԳ1(9Sc[SKK[ooSSS[[SScouuuz٢zicccѼѢ–ziiiiozzi[coooiciuouocioi[KKco˹Ĺˢijo˞uuzǹĿBKK[ķ伖[צSK19o͚S1SiocSSSioSSS[cciiuuzޖzzucc[c[[oњuuoKzzuuccouziSSioouzoiuzuuuuuooiSScBBi¹˹ҭķzz–zzļ˹KBSKBSzĹǖ˪9 K㷀([iuc[S[czo[SS[iuouiuuucSKK[uuzocSiioiuzu[couzi[[iouuoiuzuuoiuzoiSii[Ki˹ѿԹԭמzǼ[BSKBKK[zĹ¹·[zշئi( iͰߦc9coo[[Sc[ciu[S[uiozozSSSK[oļoSSS[czozcSizuzKSizzuccioouuciuz[SzoK[uic˼·尦ɳѷڪi¹uKKSKBS[ou˼Si99͢BKiuc[[[ioi[cocS[uiuouu[[[S[[iuijoKK[[ozzziii[ozucScozzui[ccuzccuoou[S[cǞҳ͞ۿѢoɳzoocSSozuSSѪScڿ[KcocS[coo[S[cuoiiuuuoo[[S[[ioic[S[izzzzzc[uoSczzzzc[ccu˭uuuziuoKBzĚuž·ټĚuǖzɳicu¿czɖoS[io[S[ii[K[iuuii[izzooic[coucSSScizzuoucccKizo[ScҞuuuoozo[[iļǷԞܼ˚zdzǼǷɼo[zSKozuijuS[ioiccii[KS[ozoSS[o·SS[ciiicioouoSK[ScĚzzuzozu[cK[ozzoSSҷǚuouzzzou³Ƿ¼ڭמz㿢zǰϰuzziiuzzzKouB[oBKz[S[ii[cic[SS[iuiSBS[[izucuSKKS[S[[cic[zucSKK[icuɭzzzuoizoKczo[ouuooĉozzzzzzװ·ْuҦzɹoz͢uuuuzzz[KczuziSccuSSSioc[c[[SSScuoSK[[[[[cioc[iuSSKKSSSSKSSSuo[SSSKScc[u߼uuuzzoczuS[ccizzzzzu[Szšzzzuu[[„ͼǼܦu³湞ڰzؿKc[[oKc҄Sui[[SKcii[SS[SKSS[i[KS[[S[ciouo[[cSKKKKSKSSSSSioSKSSScoizzǚzzzo[iuuuzi[uouzuuzzoc[ĭzuoouo[u³ѪziĪ˷ѿҷz[o[[oSuiS9S[SSoiccKK[SKKS[[SKS[KKS[couoc[[[[[[iooozuzuuooozzuuozzzuiSSi[uucuzuooouuzcozouooooǞ³ۦщu俹¿عzzSuoio[Ϳ[BSi[[uoc[[SSSSSScc[KBS[KKS[ciiicSBuuizzzzuzoiiooiucizzo[cuooouuuzzzuuz߼­İɼķ઀˪⪞­uuzSoooo[uĹiS[c[oz[[[cccccozziSS[[KScccc[[SKKzzc[cozi[[Kiuouucocuoiuuouuiouzzzzzuu¼׍㼚¹Կ࿢䷄zԚޖzԷouicuoiizioϷSc[[SSoiSiuuiuuuuzuoi[K[oiic[[KKKuoouzzcK[czzu[SozoKcuzzoizouziž׿ު¹ټ߷uۦzɳɢK[uciiuoozװҚS(9[iSSzucoiccouzicouoouzzzocc[[[SKzzzzociiiuzuzzzoS[oucouoozoziuuت賍ͳɹɢϢ߼ĦuSSzoozuiuuzɢz91BccSSzzi[SSccc[[ciciucSS[SSzuizu[SciiiccuzuuoSouoizzouۖǭ췉ⰳҰ۰ɰɢɰİ[Szoiuzizڞ[1B[SBBS[zc[[[[[[SSSS[Sizozui[[[[oozuzzuocuocSizzzuucizzu[czzozzuzc9SتcҞ˖ͼɼˉɞǭdz¿c[Էz[ozicˀuK1[cBB9BBouS[[[[[SSSSK[[zu[cooc[So[izozuzzzoicozzoouiouiuzziuociuuuuuuuu[9KϰɢljԷ­ɪܢzĦzҪɍ˦ϷiK̀SciizئSKS[SKBBScc[[SScc[[SSScci[[iozzi[[iooiczzuzzuuz[czuiii[Sziciizuic[uuuzuuuuoK9cɪў㭄ĪڼͳҿĹ[㹄SSiٷ[Ki[BBBBK[iiic[Scoi[SS[[oc[Su[[iio[oooc[uizzcoiz·uiooicc[uc[iuoiooio[izuooucKz׷uª㪚¿Ѧҹ氍Ğ͞ԷĿ[Siz(KcKKB99K[Suu[[cozuic[[[cSociciiSS[izzuzzucciiiozzuĦuzuoicouzcc[uziciouooiBcoiozciҹ緞dz˦ϭ迍Ǟͳۦziuiizzouu9(K[SKKK[[[Su[S[czc[S[ciiziii[SS[coozuuooiouuz˳[SozzozuzzoKKozzoccccSciS[uuiuuc¼zˢ۷ܼԷҀɦɷ˦ɼĹo[ BS[KK[oi[cii[[Sooc[SKizoc[SSScuiSKzoļzuzii[cuiucoz[iuzoicicSSc[Sozuc[׭ɪuіܼdzª幼ǭޖošɼ˷ۿɼzzB‰cB9ci[BB[o[iuc[Siiuoi[SSSczuKKBzoiuzooo[ioizuoicouu[o[9[oK԰˭Ѱɷ˭z¹˼ط³[[BzljKK[c[SKBBuSczouuccouuu[[[czcBKKzozouuuuzziiuuuzicoicoouiSBiczѹc˳ͳĭ¼ڳ˞dzͼɿĦiScuiBKĒSSc[KSKBSuuSczc[uoooiczoiuuiBBBKzuououuzozzzuzui[[K[zoc[cciu[SczizտɰĦϰǷϳѿϭĹ¹·ǼİKKucSKɹci[SKSKSiuu[Kiz[Bczuzz9SciuiKSSKKzzzuuzzuuuzuiiuociiuoziB[ccouioc’ۼͿɳԿļİǞѿɷ³˿Ŀϼo91uuzciiSSSS[[cii[cziSSoo[[[[uuiSKSKKKzzzuzzzuzzzzzzucooozuicoi[ooziuciϢϿĿdz˭¿˼¿ɷª࿰ϼǼǷշz[ zziKco[KKK[ic[ciiouiczzc[coocouo[KKKKKKBKzzzuiuuuuuoioS[SKuuouzuoucuocҰ˹ɿ¼ѷİ¿˿ɹզҼ㷦¦ijԉz[ciKcuicuoSKBBco[SS[iczzo[SKzuzzcS[SKSSKKK[ouzzzzzzuzucozocozzioc۹ɳijǰҹĿ¼ǹ¿uĪݪѿѳѿS99Si[KcKocooiKK9B[ui[[[SSoicSzi[SSSKKS[S[iouzzozuuizzii޷׳˼ǿ˭dz¼ķԦɢ­Էoo1BKSB(Soc[Sii[KKBK[uoi[[S[uiozuii[zzoccc[[SKS[[[SuouozzuocĄޢǿɷic·Ǽdzعۢķطz’BKB(Soou[cS[icKKK[[iuzoiii[cooic[i°ucccc[[[SKS[[[SSzuoiozzzzz[ͳప¼­uBB9o¿·ܿעǷǹoKKcScuSS[[S[ii[SSc[cczuziccioc[czz[S[S[[[S[[cccK[c[zzzzuoozzuuuziiϼٿ[BScѿǹǰɚڿǷ˼Ĺz[BKiˉBBSSKSS[c[cc[[Sizuziccicc[u[Sc[ccS[cuucS[cSuzuozzzzzzouoccѹѦĿ91c˷ؿ³ɿҪ޿˰ͿǼžooSoSKSB9[SK[[i[SS[[ouii[S[iϰiiicoiSSioSKKKKzuuzzzuucozii˰চĿ¢9Bǹªij¹ҹͭճĹ¿ĹzoBBS[cBB[SK[c[KSScoo[[c[z׹ouic[SSSiui[K91Suiiuzzzzzzzoiٹɿ·­iKѼ¿Ĺѷܼ¿ǭzczS[[KBKBK[i[KScozzuuui[cc[Գuzuccuo[[[ooo[B[zozzuzzzzziizuzziiѹĹKɼķ۹İ¢˼ѷucSK[[cSBBKSiicioiS[cc[[[ccccccˢozcSczizzzuuzzzzuuzzzoiiiiĢɼǿiҪļ¼ķª˼Ϣo[izS[ic[cSBBS[cuziKKKKKKS[S[ccciu˚izz[SiczuuzzzuuzzzuzzzuuoiioԢؿɿªļͰ¹­¼ѭ­ˢocuKS[[Sci[KKS[ouSSSKB19S[cSB[zѢoouzzzc[ozoKzzuuzzuzuuuiiouzzuoicico¹Ңۿ–ļǼ˼ҷͰɒˢozSSK[[S[[KKS[iiKKKKB1KSS[B9[iҪzoozzuzzuouziSBzzuuouzuuzuizzucuzoiciuz¹ۼ߹¹³ɿզԳ׭׳iiKKSBKSS[[SS[Soo[SKSSBK[KKSBKizSĞzcSciuoSuoiziS9cuB(( 19KoucicSooKBKSzǹ¢oɼoİucu[91191(1B[uo9BKSBKKci1K9BKKS1BB99B[̈́99(9B99KKoi[[B9999(uuoSuצui[KScccic[[[SSBoǹ¿ĿɞcKKBz1 11911(1111KĪĒ[uoiKB1ii9c[ouicciiioi[o[SiizİĚoi[c[[[iS11BKBKKiuK919KK9B9Bi 9BSc[B(119BKcͷ199S[B9KBS[ioBB1119ouzzĒoi[KKSciiicc[KBBշĹªč99BB9[[((191(111([ɷz[cuuicozSBB9BiooiKSicc[iccuoKuͳ³o˷zKKBKc[iS99BBBBSoc9B( 9SB11(cz9(SicS9199BKKSoi(KiuS99BBSo[BB111Kzo͒iicKKBSc[iiic[KKϼ­zɀ199999([[ 191(119cS[zuzuuc[SSoo91(1BKBK91czoci[cc[ozzoz׼¢ϼͭiS[Siii[B991(1B[[(91((BKB111BB SioSB9KBKKKBSҖ9K[uc9999BuS99111SoiݭiicKBBKBScuoic[c·ɹzzi(B999111cK 11119iz[uuoiouoc[cc[[cB ((11BKK9Kuiuii[K[[[z˿„SicSKBB9(191(Kui9 ((111BS91(1[B[uBBBKKSB9B[ɭBBBciSB1KKuoB11199ziociu[[KKBB9Kcocccuž¿ذS1991(191B ( 1uz[icSciouucicciS((9911KKKcozzuuzucSK1BK9[oiĪɼ°coiK(((  1KKBi ((1BSB((uBczKK[KKBB99Ki91Bcui[9cozz99919Kooiz­ɿޭc[SB9BBBSiciuĭת[(11(191oB9zo[iuS[[BKciiuz[[iuzS(B911BKKSuuoouiic91B(([ioǹϼoB[cB(1KSKSiz[c[B( (9BB1(9zoKuzo[SccBKS9(1Kc(SiiBc 19B9u[o¹¼Ւ[S[SKKK[ciuǞڢ( (19BczcuouzzzizK[c[K[ouuooiSucKc[BKccccuuiicSB((SSS¹o[oǭuuzSBSouoozuK(1991 Kuc[SiiKKSB11( 9ozSii 1199zzoǹܿziu[SSS[izɪ؄ 9Siuİi9[ozcouoiciuzzocuiuiucciioizi[SS[SSzžuzϿ·uϪuizzzoiiu[(1B11uic[[cSBB9991cB1[uuzS(991Kiئio[[[[iǿՒBSScҼļcicoozoc[[cuzcczoouoiciuuuiKKKoˢoѿzǞžoSBKSS99B919BSS[c9B9cooi[[[B19111Kc9BozS9111oĦoSc[[oĪڦcBBѼžziuzzuoicSiiSu[cioiuzii[B9Kz԰uoSi[–oocuiicϞocSSKBBBKK9199999Bci19zzzuioi[c[99919Bo119KuoB99(Boҿ͢u[cu؞izĹiuzzzoiczcuuoScuuzuouuiii[B9cĭKuuc[KBBK1KS[zziuoo[SKBB99BB1(BKBBBB9Biuuuo[[[K911(9z 1(1i[99B9[oc­ϪuĭzzzعҪcczzzuziiiicScoouzuui[KBKozizuooo¿oSKBKBKS[Souuozoc[[S[SSBBB9999( 9BBBBKKKSSzo[S[B(1((Ϟ1119czioS199BzuouɼǢϭzozzzǭϰiizzi[SizKKSKcicciziKBKcui[cKS[SBBBoϼo[KK919Sc[S[io[SSKBBKKKBSSSKKB9911B9BBBBSSScoiKKSB91 K199KS[iK191Kziǹ۳Ҽˢociuzzzzzz˹99KSci[K[ozĦcBKKciK9KcozzcBBB9BKSSSSS[S11BBS[ScuzzucKB9911K[SKKSBBSSBKSBBKKSKKBKSSKKKKBBSBBKKBSKciBBB1( oiSSKB9[cB99(SzuzĹ׼ɳ–oK[iioozuzzuzzڪ9BB99BuKizͼ[SK[oc9KSS[SKKSB9BKSSKKK[c1(KKSci[uzKKozo[[zuzcc[ciiSB99KS[B9KBB99BKKSKBKKKKKK9BKKBKKKSSSBK[[SSSoiSK91(cՀuu[K1i[B191Szo·ǹšzcBKciiooouzuouzͰɪܷ9BBK[SԹuiǰSKKucKKBSccoiSKSKKSKK[iiK9K[iucKKSK9KKKKKSSSSS1Bccic[KKSSSSB9BKBKB9BKKSSKKKKKKSKKKKKSS[[[SSSc[cccoui[1(z؄ui[[Bz[B9B9coǷҍϞ[KKS[iiioooooouuzͳԹ˭Ǧc[BBK[۞iǷzSSKoz[BK[oooocSSSSiouuuoiiioooc[c[SSSSBBKB9BS[BKcicSBKSSKKBBBKKKBBBBSKSKKKKKKKSKKSSSKKS[[[[ciS[ci[iSiocczuoKSڞuS[cKu[9BBKǷǹݳuҦiKS[cccccciiiuuuzuԹҿ¿z԰cuKKB„zcSKBScu[ciiccuoioozzuiicouooooiiiccic[[S[B9BSS[cci[KSSKKKSSKKKKKSSBBSKSKKSSSKKSS[[SSSSSSSS[ii[c[iSo[(KS[cuczuuzo9[[[u[111iķ˷Ĺ˿zoļǢu[S[[cc[ccc[[iuuzuǦ¢Ŀ幭ciu[KĚoSBK[cozi[ciiouuzoc[[SSccKKooi[[[c[c[cccS[[SS[oicSSSKSKKS[KSSSSc[KKS[[SKSSSSKKS[SSKS[SKSSci[[ccii91B[cciiuu[[ooozKociu[91 zĪoªǒ͖uS[cc[S[icc[coooo˪³­ڼuĭoKSc[ouzzic[[iozocii[ccS9KooocSSSSSKc[[S[[S[c[[[[[SSSKKK[SSS[[[[[[S[[[[[[KKKKKKSSSSSKKK[iicc[[izzKKB[iic[cccz[[o۳zocoK991iҹiucccc[Sciiicioii͞ª˰oiѼccoiuocc[zu[SSiououuuouzzzo[SSSKK[c[SKKS[oKBKccSKKKKB[SKSS[[cccc[[SSc[KSSKS[icc[KKKKSui[[[oiccKScSKSSSScuzu[ѷuS[91BSzǷšBɦ[[ocic[iooicc[[ؿoSɹܦciizǷzuuzzzi[SSocSSuizzzzzicSKS[[cc[[KBKczc9B[cKSSB11SSS[[[[S[[[SK[iicSSSS[ci[SSSSSSScS[SzciiSS[KBSS[[c[ScooϼoS119oiϭͭzoS[[occcciooiiSS׭Bi˹Ŀؼ˦c[zoizļucozoKSBKiS[oiĹuui[KB[iicic[SKB[zoKB[[S[S9(9KKK[cc[KSKSczoSKSc[[SKSS[SS[zSSBciii[[[SKKSS[S[c[cc[[u˚čo91B9zc˪ǖuK[oͪSS[Succiiicc[SעS 1K[ҿǼĪط㼄iKSioiİ[Sui[o[[K[uoo[ioĿzicBSSiciiic[SB9[ui[K[[SK9999BKK[iccSKKuz[S[c[[[[S[SSSio[SScoicc[[SS[[[[cccic[Suzɚ׹[(19Bĭ°¿¹oS[Sz9KSS[uiiiic[S͍B9KB(K°Էɖ¿ךucKKKiuozz[czuiSuiKKuzuzzzzcSBS[cSioicSSBBi[SKKSSKKKKB99[KiocSS[zuic[cz[S[SS[[[ccSSiicSou[ciiicccS[cc[[cccciiuuoz[Ϳ1 (iǿҹ¹dzcS[coB1BSSKSoccc[cԳ[(9KSBK׳͉Ͱ۷չucBB[zuuuocccB1uuzzzuooziSK[[SSooicKSS[iKKKKSKKKBB919[Kc[[c[u[ccc[S[uui[[[[S[icSSic[Sciiooicooccc[[[cc[ioou[KS[SzϿ[9BǼѪɷc[c[SϢ999KKSScoc[iҰS1KSSKcܭ˞izٷ¼zooK9Szuzuuzzocic[cz[1cziiuiozuuouzuuo[SSKKSioc[KSio[KKKKSB991B11KSB[SSccu[[[iooS[Sozzozicc[[[ScccSczcuuiiiccouuoccSKScuuoiooSBBB[iuϼoҼ’cioiKcuB99BKKSKiooɢB([ii9BѷoҼۿu[uoS[uoouoiozoooic[[ouiz1[ooiozo[ououzzzuzzoicSSS[ci[SKci[BKKKKK99BKB99K99KS[cci[KBKiui[S[uuuzi[cS[[[uic[oozziccciiouoi[B(KiuuiccSKK99[ii[coo԰ciiic[Ϫ99999SKSS[uˉK(BS[[KܷҼݦooizuccoicic[ii[[czuuicouio[9zzooz[czuuuuo[S[[c[KSS[[KKKKKKKBBBK999999B[c[[[SBBKScuii[ScK[iic[SSK[uicoioooccciiicc[[K9(Bcooicc[KB9BSKB9BczioiBSiķoKSicSSiu(9BBBSSSKScǀ19SK9SiĿշ˳³ٳKKcuuoicouK[[[[SSuuiioiizczziuzc[ziiuuuzuiioc[KBKS9SKKSSSKKKBKK999BBBBKBBBKSK[cSScci[SS[ccc[[SKScc[Siccioiicccic[[SSKKKcocccSKKKB919B[cB(B[SK[Koz[uĚKKS[c[K9Կ119KKBKS[K[ioْ1KcBKṳļͪټzzKBiooui[uKcc[SS[zciiiiuziozoSizozzzuiuuozu[SKKSBBBKSBKKKSBB9B9BKBKKB9B9KSS[ic[[ScKS[iocSS[[cic[K[iiccoooic[[ccccc[[SKoicicc[SSK9BBK[cB1B[ccoucS1ScBS[SSSBBߦ 9BB99BKS[iiSSBS9S­’˰Ǫo99iouooSicc[iuiuoi[zuuzo[ioozuoiiuoozi[S[i[BBBKBKKSSKB9BBBBKKBBKKBSKS9[c[SS[B[S[[[BBBSuui[[zciiiiiic[[c[c[[c[[S[uuoiioii[Sc[KSBBcc91[c[cziS[¢iKKKKKKS9܄1BBB9KKBSc[[SB[11BϳǭǹԿizooS1KozoS[ciuzzoooiiѪuouiooiiozoiiiozuiuoicizcBBKKKKKSSKB99BBKKKBKKKBKBK9KSSKKKS[SKKK919Kozo[ooioiocii[c[icccc[[[iocKKciouo[K[cSB9BSK1BccccoooccuS[SKSKKKKKٳKBBBBBKKKS[SSSK1oߍBؼɭĢͦĖKcuzz[KizzSSiozuouuǿzzoizooocSccciiouuiouzoiccuuSBKSKKBBSSKB99BKBBKKKSSBBBBKBKSKBK[SSSKKB9K[uuiioiiiioii[[i[ciiiccccoicKKS[coi[SccB1191(BSKSc[iiSScou[iSKSSSSKz˼[9B9BBBKSKKKSSSB91uعطͷǼܼcioucucozzzuouzϿzzoo[[ioc[coi[[oiiioccic[[io[KKBKKBBKKSKBBBKKKSKBBKBBBBKKBBKK9BBB[SKKBBKSouu[iiciic[ccic[ciicciiiii[[SSScSKS[S11B919[KBS[cicK[[SSciiic[[S[[S͒9B99BKKKSSKK[[KBKKK㼭˪zѷ㷉ozuzzuzzziuzizϷuoozuBSoocS[oicccc[Sc[KcicizcBKKKKKBKBKSB9BKKBKKKBBKKSKKSSBKKBBB99KSKKKKBSoi[iiiiccciiociciiccciicSS[[[cK99K991999Kc[SS[[c[[SSc[SS[[ciiccc[zoKKS[SBB9BSSSccSS[[K9њͰ࿦u[cz[zoouzouiǰoiouu[B[uoc[[icccc[S9SiKSccoz[BKKKKBKKBSS99BKKBBBBBBBKSKKKKBKKKBKB99BKBBSKcouzuS[cciiccoooicicc[c[[cocKSS[[cKB99119999ScSScSS[SSSSc[SSSSS[[iocKcSK[iS919S[SSS[[SSSKKzۿհ͖uKKioKizzozzuuzoizzªoozoiSSiocci[[[[ccSSSK[SSKcuoSB911BKBBK[S9BKKBBBBBBBBKBKKB9999B9KB999K9BS[iic[[ciiiiciocciicc[Sccccio[SSSSSKB999999BKc[SccKS[SK[[[[[[SSSKScici[B9B9BKKBKS[KBKSKSSKSouĦǒzo1ozuz[cuzzuuoiozoizzoioKSuu[ciccicccSScS[[SKzoKBSB911BKSSSK99BKB9KKBBBKKBBBB99999999999BB9SccczuScciciiicc[[cc[[[[ccc[cooc[[SSB19BKB1BK[cSKS[[S[[KSc[[[cSSSS[[[cz9 1 1S[[KK[BBBSKKSK[cc[uۼɖuzٿoK[zizoBiooioicouiz¼zcc[B[zciiioooc[Scccc[uziKKSKB9BBKKKBBBBBBBBBB991199999BB99BK[[Soi[cccccc[[c[c[cccciccccoozzoi[K1BKKB99BKSSKKSS[SS[[[[[[[c[cc[[[KSK( 19KS[[KKB9KBKKBKKSKSSSoټuouհzziziSz[Koccioocozziozļooc[ccozii[SiuuocS[[[ioKBBKBKKKBKBBBBBKBKBBBB11BB199BB91BKKSK[ccii[[S[[[[cccciciicozooooS9BKKSB9BBSKBBKKKSKK[c[S[[cccc[[S[Koɰ1 BBSSKKKSSKSK9BBBKKBKKKBKњozi޹oouzzzKSzcKc[ciooiuococuzzˢzuuo[oocoucSKcuoooc[[ScǷz[BKKKBBBKKK99BBBBB9BB99B19999999BKKBco[iiccccS[[[SKcicioi[cSB[[K9B9BSKBBKSKBBKKKKKScc[S[c[[cc[[SSKDŽ 19[SSSSBBS[SSK99BBBBBKKBBKSɀzҷuoiiSKcucoSSiioouzuzccouiiozzziKcSBSocc[iuccoooc[­icS[ccuzizuKBKBBBKKB9B9BKBBB9B99((999BBBKBKSBzc[cc[cii[icc[KB[iouo[[zzB9BKKKB((K919SSKKS[[KKS[ci[[cc[[ccSSKKc9199oSS[K9KS[KKKBBBBBBKBKBKSK[ɀ[zoĹicouK uiciuuoouuouiciiiiuuzzuiSKB9Bc[[iozuzicciciouuizzicS9KKBKKBB99BKBBBBBB9((199BBBKKBKScSS[[[[c[ciiii[BSiuuu[Soo99BKKK911B((BKBBBK[[SS[cii[S[[[[[cKKKKc1 9oS[[KKKSSKBBBBBBBKKBKBSS[SuݪzzɷuoucioSouuiioozuczociiiuziizzzzzoic[KKS[[[izuoioocoioocKKSKKBB99BBBB999BB119B99BBKKBKuz[SKK[c[[cciccicSK[ouoicio99BKKB99991BSKBBBK[SS[[[ii[[ccccc[KKBc B1Ki[SS[SKBBBB9BBB9BKKKKSS[[SS˒z˳ooouo[S9 oucc[ciouo[czucccuzoouzzuocccSS[SK[ioouuzoucuK SoKKBKBK9KBBBB9999919BBBBKKKKB[iS[SSS[[ccc[[cc[B19[occoiozoKKSKB999919KSBB9BSSSS[c[cccciccic[SKSuS[Sco[BS[SB9999999B19KKKKSS[[[[[ɉuɷɼiS(B[oBBK[iiciccizz[izzuouzozoc[i[S[[[[c[[ciuuuoo1 1[uiuK19BB9B9BB9BK9999BB99BKKSSKc[S[SS[S[[[[[c[iS (S[[[iiioiKSSSB99B1(9KKKB1BSS[cccS[cc[[KS[[[c[cB9cSK[cSKSSK99B999BKSSKSKKSS[[iic[i೚¿i˳iii1cπoBBSSiocciouoouzzuuuoiouzioocK[[cicScciuoiuK(1Kuu9Suu[(1K9BB9BBBB9919BBBBKSKSScziccccS[Sccccccccc11KKSccioi[BKSSB11999BKKBB9KKS[c[SS[[ccSKKSSciS1cSBBKKSKKKBBBB99K[ozuc[cicS[[[cccci༢ɿoziǀzcBKSKcoiciuzzuuzooooouzzuoiS[cicuzzzuB9KiuB9BicBB1999BKB999(11BKKS[SS[zuzuuuuouuzuui[1BKKSiciccSBBB9919BKKKKKBBBKSSc[KSS[S[[SKSSKcccK9cBBBKSSKKKBB9BSSiuzuocizcS[[[[S[[So˿zzzii°zouҀci[9KSScoi[czuiiuuoiScuzuSSSuiKSBKcziS9B999911K911BKS[ccioooiioiioiuuouoBuz[[ccc[[[K9999BBBBKSBBBBBBS[[[SSS[SS[[S[KK[K1SSBBBBKSSSKB9Bcuuooc[S[zooc[cSSSS[[[oԹzuzzic[˭S9ooS[cBKK[cccczouuioioĿ·uoiSBicc[SK[zzcB( (BBBBKKS[cuSicc[[[[[c[cc[[cz[Succ[SKSiKB9BB9119KS9B9BBKS[[SKKS[[K[[[[BKKSSKiK99KKKS[SB9B[ozocc[[[iuiio[KKKSKSS[[Suמo[cǹu BzcSccKKKK[ccuzuiiicĹ·Ѽio[oouic[[KSiuSKB19KKS[uciocccciiccccccSB[iBKzc[[[[[[9B999919KSKBB99KKS[SSKKSSSKS[S[SKBS9SiK19KKKccSBBScic[[[cioooiiiSKKKKK[[[S[uڦuiiiԪocii[S[[S[czzoiiczտzii[Kcz͞zcciciic[[[BBKiozuKBS[izouiiiicciiiiicc[c[Siu[S[[cc[[cc[SKK91999BSSKKKBBKS[cSSSSSSS[SSS[[S[[ BS[KBKBK[i[SK[[iic[iiuuiiicccSSSSSS[[KKoozozչ[ioc[[cii[ziiicoɀoouzui[ccczuzĿzuzuKBSic[SSccSKKBScoiKSS[uSKcS[ccciiiicicic[[[ccoc[SKKc[[SKKSSB99BBBSSKKKBBKS[[[SS[[[[[[SSS[[[S(KK[[SSKSScSKKccoiiozuoi[[[S[KBBS[K[[KK[uҪzuo­iooic[[ouczzii[cɞozc[uzuoui(1Sccc[K[[B99K[ciocc[KBK[czoouScccciiccic[cccciiu[[SS[icccSS[B19BK9K[SKKBBKKS[[[[[ccc[SSSSS[Ko99SS[[[KKSS[SKK[[oiiuuic[[[SKKBBBKKS[SS[iicioz͖uzzoo°u9Sciioic[ii[ii[[cǪuzoczuzoiouz[1Bcouc[KKB999Sccii[SKBBSc[KcĦiS[cc[ciciic[[[[[[Siz[SKccii[ccc[B19B9BS[SSSSKSS[S[S[[[[SSSSKKSSS[BBBSS[SB9BSS[[SSS[[cicSS[[SKKKKSKKSSKK[iccciioԼouc(( 1ououozzzuuϦzzzzuouoz¦icizozKKB[ii[[K99BBBSioi[B9BSciuoicc˼ǹc[SSKK[cicccc[S9( BocBSccioc[[c[KB19BSSS[SSSSSS[SSK[SSSKKSSKKSKoB9SKBSccK91BSB[iSKKScc[SSSSKKBBKS[c[[KBKcicciccu͹oK(99uݞ˄iuuuouzoccuuizuBBKSSSSSB(9BBBKc[KBBKciiiuuuiBuu[c[SSSSSSSSS[[SB( BioSS[izu[[[SSB9BKSKScSSKS[SKKSSSS[SSKSKKS[c 1KKK[iuKBKBB9ciSBKS[[[SSSKBBBKS[cc[[KSciiiiiccuǰuu[1cz誖ozuuozoooiļui[ouoizKSSSSKKSB1BB99BKBB9KScc[[c[B9Bi͹u[[[SSKKKKSS[[KKSKKSS[zo[cizcuo[[SKBK[SKS[SKKSKS[[SSS[SKKSSS[cz1KSSKBSiKS[BBBo[SKSSc[[KBB9KK[[ciic[[cooioicccciouǷoc9Kocii[[uuuoocioooɰocouioi[[SKK[SBBK99BKB99KBBS[S911 iiiBSSSSKSSS[SKKSS[SccS[ouoiouzooSSKB9Bc[SKKSSKBKSS[SS[[SSS[[cciziBSc[[[KS[KScBKKcKSKSS[SKBBB9Kcc[ouii[iuociuccc[[u[uɪoiϰKB[KBoBS[[[[ouzoiciuouu„iiuzouc[ic[KSKcBBK[KKS[SK9911199 (1czKSSSKKSSS[[KKS[SS[cKSiioiiiciozo9KB19KSSSKKSSKKKK[[SS[S[[c[cccu1KSSKS[[[SKKK[SKKSS[KKB9BKSSciccuuiiiuiiiuiciccuSzǞɄ9KK1[SS[cicouuicizoo­oĞoicczSScoiicScK[[cS[KKK9(((1  iocoouSS[[[SSKKSKKSSSSSSBK[[[[[cccio[BKB9KSSKKKKKKBBKK[c[[[[i[[cccuK9SB9SccSSSS[KBKSKKBB99BSiiiicioiciuzc[ciiociuuKK¿˹KSKoiiiiizuciuzuɳiuuuiuoS[ciizooo[SKB9(1(((  1S[Szoc[[ccSKKKKSSS[S[SBKKKBKS[[S[ii[B9BSSSSKKKKKBBBKS[[[iioc[ccoɼc 1[SSSSKSSS[SS9BKB9991B[io[iuooccozuic[[iccicii9KiْuKKS[ǀuuuzuiuouozuzzoSSc[c[[[oc[[BBSK991( (( 1SoiSKczu[cccS[SKKSS[[[[K9BKBBK[[SKK[icB9BBBS[KBBKSKKKK[[S[iiioc[c׹o[(B[KK1 KSSSKKBBB99BBScioo[iooicuuoiiciuocc[K9111Si[uբic[؉zuuuzizzzoouziicSKSi[[cS99BKB9BBKcic[S9 ((1BBKKSS[[occc[c[KKS[SSSS99KSBKK[S[S[cccKBK9B[SB9BKBBBK[[[[cccS[cSS׼[((9KK( K[SKKBKKB9KSczooocioooczziouuoouuii[K11K( BcSczĞocגzouuoioz[cuuozzuic99BSSooSKSB991((1(1S[SBK[K( 9Kczozi[SS[SKioic[[cKKS[SKSSBBSSKBKKS[Sc[[[[BBKS[KB9BB9BBBS[[ciic[Sc[SԿS19S[KBS[KBBBBKBBSiuzic[[iuoioiiiiooi[oi[iS9KuϿԷoٖѭouiozoS[iSSioozuSKKKKSoiiK111191((1911B11 (BK11SuiiiooKSKcSBSicc[[SKSSKKSKKKSSKKKKKS[cS[S[SBBSSSKBBBBKKBScccii[S[icSͰcKKBKKSK9BBBKBBKcooi[SB9Koc[oo[iiic[SSc[[i[o˳ۦoխzcoziuzcoo[KSccc¼uiiicc[SKB991999((1B9991 ( (9S[Sc99SouSSKS[Kco[cc[[SSBBKKBSKSSSBKKK[cc[[[[S99S[S999KBKKB[i[[c[SS[cSKĢoB1 1KBB9BBKBBK[c[[[[SKSi[[c[S[i[[oc[[[ccˢc˦o[czzuzzi[ScuozϪziiiiic[SB99BK91999999KKB91( (9KciSBB9KzcKSKS[[Suc[[c[[[KBKKKBSSSSKKS[Scccccc[[KB[cSB9999B9B[i[ic[SS[c[uɼɳS(9KBB9999BBSciiooooooi[icSSScSiu[[ooo͹uǚooizui[cuSKKSKSSB9999BKB9119BBBBBKKB1(9c[B9BKB[–czKSKS[SKcScS[ccc[SSSSK[KSSSSS[Sii[cccccSKKSKB999BB9BS[[[[SSS[cu·ϭK9S[KKBB99KiuuiouocSozocccSSS[czici[uˍoˉzuuooozzc[cuBBK9B9919BKKK991(199BKSKKBBoi99BBB9uucK[KKSB9Kc[Si[iiccS[SSS[SSK[[K[coiSccii[KK9S9B9BB999B[[KBKSS[[[zϷoc[iiSBK[u[BKSK1(Sozu[KBKK[iuc[KuuuzĄuozzzuici[Sc(1B999919BBBB111(199BSSSKScKKKKB99Ҫi[KSSSKB9BSS[uc[c[K[SSSBKKKcc[[[i[Scoi[[KBKS9BBBKB9BBSKSKSS[[[[zҳziiuzK9B19cuiScuc91SS[SSiiKS俦碞uuzzuzoziuu[[[iuocii19BB999BBKK9(( (99KBBSo9B[KBBBo͒uuKBBSSK9BKSSS[ciu[[[S[cc[S[SScc[SKcc[iicS[KKcK9BBKSKBBKSSSSc[ccc[uطo[[uSB1(KSoiB1K[SK[i[cس㼦zuԿiuzzuuozoiuzo[cizoioz[[S99BBKKB991 (99191KzzczuKKSBBK[cBK[[SB9BK[[SKSS[zc[SS[ccii[cicc[S[ccc[[[cSSi[BKKKKBBBKSSSScccccioĪoicu[B9oɼzuoouS1B99³آzɿz[iuiioozz[[uuouuSSKBBB9B999BB1(SuccuoK999BK[zuoz[KSSKKK9BSSSS[c[SozSKKScoicSii[cc[ccc[SK[iSKSSKKSSKBB9KSSSSS[[[Soz˞oK9S[תouuoicBSzzэz[S[S[[iiSczoouzuui[SSKBBBKBKK1KzuoczoB9BBBKSc[oo[S[KKSSBBK[[S[c[coooSBScic[ScSBS[[cSK[SK[cSKKBKKSKSKKK[[KSS[[SSSҰ–o9K͚ooBKBSՀz[Sci[czKKczzzzuuzKSii[cii[SKBSSBKSuzuuciKK9(B[[[[ioKBS[[S[[SS[SKS[[[iciS9Sccc[S[9 (KSKBKKSS[[cKKKSKKKSBBK[[SSc[[S[czѰzBB[cK119o[[ozzzi[[cSBB[ioozzzzuoBBKS[c[ccc[[SK[ooouuocuiKB19ii[ScSoBK[[[S[S[[[[S[SSS[[KcoBB[SSKS[9(BKB9SKKS[ciKBScSBBKBBBS[[[cccccuĹ͚c9ooBKK19B1Siz[[oz[S[B99BSooouuoizozS9BKKKBK[cccccuoouuuccoiB91[icSK[SuBKKKSSSS[[icii[[[SSKKoiBBKBBBKK99BKBBKKB[cccK9[cKBBBBBKcc[[[SSciǦǰzuzS(1B9[[ѿҹSozzĖSKouKKSBBKcciioououzooozzBBKKKKKBBS[ciuuuuoc[oc99KioS99S[SKKKKKKK[cocii[SSKKB[cSBBBBBKSSKBBKSKBScc[B1B[[BKKBBBKicSSSSS[i˚рuuSKSSuɞؼK[ci[c¹SKzi99BBKSiiiuzozuooiicccziKKKKSKBKKSScuouzzoi[uc99cocB1Kc[i[BKKSKKKSSc[S[[SSKBBKSioKBBSKKKSKKKKSS[ici[( 1KKBKBBBBKic[cSSc[[͢z[oi[SzŰK[cSKSiiͷziK9BBKKKczuzoiciiccuSKSBBKKKSKcuooccooii[uiK9[cSBScocSczKKSSSKSSKSSS[[KK9BSKKKicBBSKKKS[[[SccooicS1((BKBBBBBBKccic[[cSo˪z¹߷ĦuSciSB[oڹziSB91BBKcuzooiozuiz9KKKSSKKBi[occoziicoiS9[cB9[oo[BB[SSSKBBKKS[SSSKBBBSK99KuSBS[[[couuoooiic[SK1BSBBBBB19Sc[ic[c[SԿĄϭucSSSSSS[cSB[ou͞u[SB1919BSozuccoucBBBKB9KKuououzuccioiBKc[9BcoSB9KSSSSKKBKS[[SSSBKKBKBBBKouKS[coouzuoooicc[cSBSK9BKB919Soccc[[ScϷǒᦪ߰iKBBBKKKKK9Kuuu˿u[BB9191K[[iozziizuu[9BK9(1[zuzzzzuiccoiKS[KK[c[S99KoiSSSSKSK[[[[S[SKSKK9Kccccc[ciiicioiiiciic[SSSKB9B919[oicc[[Bo˿ݼϿ׭ozԍؒBBBB9KBBSSzu³ucKB99999Sccciouucizuooc[z1KKB91iuouzzooiooiouicKBK[[SSB9BSzuKSS[SSKKSSSKSSKSSKBKSSSoic[[[c[ccicoic[icSSSSKKK9 9iiccii[(ǿչҭcǞ左מziSB9KScooKBB99999Kci[KSciozouucoucioocu(KBBKKcououooiooizoi[SBBSccB99KuSc[S[SKSSKKKKSKSSSSKKKB[[[[S[KKSScScic[zcKSSKKKKB1[zoioccK9˹ĿĚKSҹܿ׳㼖uiSB[uuzouzo[KBB91999SccK9BSzuuu[oiicSS[9BSK[Sououzziccczu[[ccSBSccB99SzS[SSS[SS[SKKKKKKSKSKKBBiSSS[[KKKSSKS[[czcKKKBKBKBBuuuiouc˷ͼҹi9c˿ѪϹْo[io[uo[[iS[zucSKSKK991B9Scc[[[ozzo[o[KB9B9uu[[cu[[cccoicciccS9S[ii[[cK999SKKSSKKKB[[SKKBKKKS[KSK9ooBK[cc[SSS[SKSSciSKKSBB9B1Boouzizuצ˹ˢB9ɷĢԷ˹ǢucSSio[KBcc[[[izcKSSSBB9BBKSocczzuuziooui[BBB99Sccii[KKK[[K[i[K11Scoi[[S119BSKKSSKKKBS[[SSKSKS[[S[SB[[KK[[[[[[[cSBK[[99K[KBBB99Sc[ooooٹ¢o(1uǭڼǭoSKBSiKKKci[S[S[zo[S[[KBBKSciic[uuzzzicoic[[SB99BBKBz¦cSSicSKBBBBSccKBBKKSSSS[9(19S[K[[SKKKS[[SSSSKKScc[SKicSKS[[cc[cSSBK[S11BKKB999BcciucѭĹڪKB Bz¹İǿdz°ĄuK9BSiBK[[cSS[[[ooiicccSSKBKcoui[cucioozzuoiioSSKK99111S[[Kdzcc[SSocSBBBS[ccc[SKBK[B9KB11BScKSSSKSSSS[SSSSS[S[[SS9[BKS[[[SSc[[KKSKB99SKK999K[ozuiļĦS91SuϿ­ĦuzɒˍiKBSozBKS[iKSS[ouzociic[[SKBB[ouoccuzzocooozuoiicKSKB9919B[[[uɰi[c[SSuu[KK[cc[cic[c[c[99BBBBKKuoBS[SSSSSKS[[S[i[SS[[[Bo99BKKKBK[S[SKSKSB9KKK99Biuѷ·ҭuSBS޼ĭozǖⷀiSK[ouKK[iiS[[[izuuiiuoc[[KKBBKccoioioioiuzuoc[[[KKB9999K[Sc[SSK[uoS[cc[[ioc[iocB9BKKS[SSouKic[S[SSSSSSKK[[KKiuzS199119KKKKKKKScSBSKB99SoϦҹǼԭiio˷ɹi[ժωzSSciiKBScc[cccizuuiSii[SSKSBKS[ccizccoioiuooic[SKB99(99S[[oiSiKSSSiziic[[[ooiciiB(9K9BK[[[iu[i[[SS[SSSKS[SSSBBzuzB(1 1KBKSSSSci[SKBB99czzu¼޼i[oտǷϭui᳖޿S[ioiKKK[c[[[iooozuc[ooc[SKKBKS[ccozuiciiiiioui[B991(BK[Kciocicco[SKKKouicc[S[iiioocSBKB99BSSBici[[[[[[[SKSccc[Kc[Bio[[B99KKS[[ccc[K1BBB11ioǹ¼iSiǹɼĹuɒoo͚ǿ[[coi[SSSScuuiiiciiiciuuuocSSBBKSScioouiciiiiiciiKB1999SouiSSoiciccuKKSSuucccc[SooioiiiocSBKSSKKc[S[[c[[[cc[cicc[[zu9BKcoicicKKKSccci[S99KK99Kizϼѷu1ǿo[SڹiKܞɪcSiii[9iciiiuooiooouzucSKKSSS[S[ciouuicoiiciicSBBKSSSuucBKziouicoSSSoiiioc[cccicciii[[oi[S[SzSKKKSSKS[[S[icSSoo[B9KKKcuiKKScc[ic[S[[K99[u­ǪS1(ǦǪ˿ķĦicSSccS[oˢou[ǖ–[Sc[SB1cccizzzuuoouucBBBKS[cczzooiiioiic[c[BK[ciiozo[K9iiouuzuoouoK[uciiici[iiic[iiiiiu[SKSScSKKKBBK[S[[cicizocKBBKKcKciicii[S[SKKBSizz¼zSB9K9㷢ǿݹļozz[cioouɚoiooɷϷcSKBB1S[ccozo[Kcc[[oziK9BSScuz[[oui[[cccc[S[cciccc[B9Sz[oooococuccccciiiiuocuuc[SK1BKSzi[KSSSS[[[[Scczo[occuuiSSBcSiouooi[KKBKSKKcooo[Կǭuo[Bcciɪ³ҰĒzآzzuozޭicciѹ˹c[[999 (B9KK[c[icK99Siiozzo[9SuuzcKSiucK[cioc[KK[[SSKBB1Bcociizzoic[oziSSScozoiuocicKBB11Sicu[[SSccicicciizoc[Kzo[KBcouuiSi[couoiuiSSKKSKB[i[Su¹عcK㪀9zo­԰šĄoicouciiط͹oc[cK19S9B[ii[Ko[ziuoiKSuzoSS[SScSS[[[[KBBBB911119Szzuuzoc[cSizuuc[SKSuoiccSKKBBB9Kou[cSS[S[iiiccoiuzccSSuSK9BB[oo[cozocoi[SS[K9KcSSS9˹oSSS[čKoi߷Ϲ¹uiu[coSio°ѳuo[Bc[9oSzzzozۼcoccKK[iziS1ccK[[[c[KBB11BB9BKBSiuǰc[ccccuzo[SSizuc[[SBBKKKKK[iocSoiSSSc[[c[[izo[[SSSii[KBBBSi[iozuiioc[S[B9[iS B˷iKBKiuoѳiKc۳Լ㚀zuoSKSoٿčucSBizouuuoioɖco[[SS[iocSK[BSiozo[SK[iiiiiuzoؿi[ooicuc[[ouiSSSKKSKKKK[iiiSKcSS[[ic[S[[oo[SS[SKKuoSSSSKB[cc[ioozoio[[SSKKiizS1SɪiSKcocԭuצ¿zKKzڳǍiSBBozoic[[S[icu[SouSKKSi[[[[KSczzi˞ocuoouio[iozui[SSKBKSBB[c[cccK9c[[c[cccS[iuc[[[[SSKB[oc[[KKB9uc[iociiii[SKKKScco(BB[SBB[׿ɪcuݹͳĭؼ׼cS9B[˷uoc[[S9BcoicooSiiB9[oSciiuuzziczz˦uouuoo[uuoooocc[[[KBBKBBKSSKBK1(oo[cccci[[ozc[[[[[i[K[oi[[SKBBiicouiiiii[[SKBKKu¦9(KSicBcoc[ǼٍiiͰǭĿ؞ڿͦucKK91SzҷooKczc9Kzzuu[zS[ozziSKB1KS[[iuu˰cczuuo[Kši[[S[[[SSKKKBBBBBB111 1zoS[ccccccuzc[[[[co[SS[ii[cKKBSucoiiiiiio[[BBSKz11BS[BiizzݰBKϿݭۿ˞KBB91Kiiouzu[Sozoc[B99999991iozͳuc[zuuiS[ɪcSSSSKKSKKBKB999B91111BucS[ci[ccizo[[[cc[SSSSKcuic[S99[[c[c[cc[iBS99iɒ1191BS ϢiSѭ䷦͞iBBBBcɿSuoozocciiocS999BBBK1SߞuzǞoioocc[co[SS[SSSKBBKB99BB9119K[zi[S[[S[[izo[[[cc[SS[SKKouccK9KKuoS[S[[[SSBB(BK(KKK[Scčۭ˭Ǣ[BBBSɼĹczczc­u[[[ooS1B99BBKBuрczĚicuc[c[cS¦cSKKKSSKBKKB99B9999B[ci[S[[[c[[o[B[[ii[[S[[[Kii[SK[ScS[ci[SKSKB9SǢ S[oԢĿzԿzoS9BuǰoİĖczi°[SKzi1BBBBBKKK1uڪo[iu͞oiouiSS[[ccuz[SKKKSB9BB91999BBBKS[oS[[ioiccoSB[[[c[[[[[[cozc[ccSSc[[cicK[[[KB[z9[[oĿԭϷ­Ԧݷz[KoiBѢuzuucKBc[9ocKc[couuzziioc[[[[[SKScccc((99BKB91199(  BoB(1BS[SKBBBBKczcSBS9(KBB9999BBiu1(( (1 Boociiiiiio[ˢǹic[KKBBB991Kiiuziuz[[uzicc[KiioziS9(BK111SuKBSBKKKKK99SS[icoSBBcS9S[[c[K91τ11KiiK1ouooozu[BzoiucSiozuuzzuuccicKKK[uoS[SS1(((11KSK1(1BB11( ( iuSK1(BKKB1Bi[1((BKBB919919B9coB(1(11KBBSK9BBSSBKcĿĪuo[KKBB919Siiuco[ioiSSSBiK[i[9 uKKK[io[[[KBBKK1(9BKK[(KKB1[K9B9K[izډSciciS[uziizoK[uİiouzzuocc[coz 11991B[SB((19111(  1icu[B9BSc[izcKB9119coB(1K91(11BiiB911KK1KSSKKKSSKKKozتĞcuo[KBBKKSS[izzoi[oi[K[[K[K[iB 9uBSKSc[SS[SB99BB((BKSKBuKSK9KKKK99KiѳҭĖSKS[[ouzSiuozzzzzzoSioi11 ((1BKKB119(  ((((1(( 1[S11SooziB[uucS99K[S911[oK(9[BK9119[iK99KcBKSci[KKSKSSKSciocc[uouSKcoSKSS[[[ScooScuic[icK[SSK1iͿS[[SSKSKKSKBKBBB9(9KKK(iǦS[SK[c[SSiĿuiBKS[[zuccĪzccuuzzzzuuoiuzzcKK[K1( (11(19B1((( (9B991 1ii1 (1SzzKB[K91(19S[1((1S[99KKiS1B9( 9BScKoouoSSSK[[KK[cuzSi[uoSScicK[cc[[[[coKciiiiicSBzo[c9zǿi[iiSK[SKBKB9BSSBB99BBB1([Ǽi[iccioož¹iocS[KB9BSSczuizuoiuzzoccouuuzziBBBcuccSK(  1991 ((BSKK91izB ( 1[cK9(  9K1(( KB((9[K1B19iui[c[[[io[co[19SccS[SKuzocccczzBioccci[B[i[KiҀ9K[icK9KKKKBBKSc[[[SB9B91BS˄ooicoͦҰĖS(B[cSKBKKSSizuiioizoccc[iouuS99KSuuii[cS1 1(1( (((19BB[[( ((9B[[1  coB BuS  (([zcSKSSSSco[izoS19BiouzcicuziizzzBBcicS[[S1uiB Ϫ[BSS[[B1[uuooouuzzuuoSB1(19˚oocoږ޷o91K[[cc[SSScccBoizĢuoioiSccici[K19SczoSSSicB1  ((1((9919((9u9( 1 9iSKuK( ( (( 9o19ļɿi[zocizzzc91(1199BBB[S[zK9BBSzooioioui[KKBKKKKB1cK ooicSKB[uzoooioiccioouucB1(ĭu[ϭ޼9BoS[cicS[o[cBiuuziSuuiuzzzocBBKSc[SSS[SB1(  ((19B91(9zu9( (1[Sco19B9919BB[ooKϪzz³ܼuBBBB991 (9BB1(9KKKoz9KSBcԪ[uuo[Ki[[cziiccocK19Ąiiic[B[uc[SSKBB91BKKB[ozzB[iǰzǿķ[ ScKccuo[ccKSSiu[iizuK[ǭSB[[io[SKS[S[SKB1999911  (999((iu((1(( (Su[uK1B919BKK9(([SSKSiټSKKB99KcccSKKKBBKKKKo[1KKK[ڿoouuoS[[uu9uSK9uiSKSSozi[KKKKB9((1BB91(9[Sэuuii[[K SSic[ouSSKBBuzuc19Sizcuzczɷc9B9B[K[[K[cSB91((99991111   ((1ozK9B999 19Kuu1( (9KSB911KuicS[[BSu[[[[izuSBKS[SS[ciSBK[SK輒ǞiSKuccS[iKzuuucicBS[S BBKKSKBB 19991(11[zѳuS( 1ozSSccSSSB9zKBi[9BScooouuuiSKKK99S9BKK[SK1( ((11(11((1(9(1coS9BB9KB(iBKoS(11BKKK9(1Boucio[[[SK[ḯ[Sizc[SKScc[[cc[KԞzuuoiSK[[Bo[cc[uz9SczS 1KKKBKBB9( (19991((1Bi[SKBBcuoKK[ccSSKB9c1(Ki[9BBSzzuzziiui (19SocS[KKSSKBKB11(111(((1(1191(9(([u[K9B9 99BiSS9199SKKB91KKoi[zzcSSKcic’uiiiSczu[KB[[Scic[cizudziizoii[KcuoScccizuuoocuii[( 9KKBBKK911  999(((19Kio[KS9(Kc[[KSKKK[B19SiB19BozuuKBou  (9oiSSKKK91BBB9991(111((99919SBBB1(B1B[S(9(Bi[SK1199BB9999KSuu[ooS[[[չ[[c[Kcz[ioic[[S[iuuz9oziioSuĪS[ocouoooiB  (119KBK991( 1199((9BBBcoBzš9BouuSB[[[[[SSKKSz[9K[uoKBB[ouio((zcB((( 9iS9B11111(((19KS91(9119111BBK91(1[cB( [oSc9(1119(((11BouociuuS[S[o’zzuuzo[SS[iiucuuoBcu[i͹ioccuzzz[SKB1(  91B91B9BB9B91911 (1BBB1oi9iĚKK[zc[iiizzi[SS[c[SKzozi[zziK19[i[i[ c ( 11((19(((1111(((19S[B1(91((9BBBKu9B[9 1B9((oo9 9B91 (czcozicSSiSKKccڹ˳zuucc[cciu[iui[ioɪucziozzoS9991(1( ((19B91 (99KKKci[S99 ( 9KK1BzK19ˀBBzu[ii[[uoi[SK[[[uuzouizzci[11Kouiz[[uB (( ((11 111( ((199BBBBB1((9999iB(BKBK9 1iic9(99KiiS9(ScSciouKB[[cuzz[㪦ͦozuzzocc[cciouzcuziScǷuSK[coiccciic[KSK1(1111191((19991 1(119[iic[[1((9BKB9zucKu׍c[i919B9BSoucSKSKcuuozzuu[Sc[9B[cioc9(((1( ( ( (((1199BBBBBB991S1(( Bc[K1Ku[[919BucBu[SSìB[c[couucSBҹͼuKciiccicccouz[ScĖzzz[SK[c[[ccSSBBBBKKS[1(99191((( 1991 (9BBccKB1B9BSiϞccc ( 19Bu[[ucSKco[iuuuuoKKcu[BBcc[9( ((  (111   (11( (111BKBB19o[(( (BSK S[i[1BB[uiiKSccSBzoSccScci9cݿϭuǞ9ccoc[ioc[ozzĦiioɼu1BSSKS[ccc[[[SKBBKBKBBKcK11111((1( (1((11(  9S[[KSiii9K9(((11 SKBKSBBBBiB9S[uoBScuzcoic9 ((( ((((((111(  11( 1919BBB9ic (  11 1io[BKS[[K1( BS[SKͰic[[S[[uڳٷ˪zci[cciuiozɰoz1S[[ccc[KBBKBSSKKSKKKKB[[1(11((1(( 11 11  (  (11cziuҭ 1 11111((BKB111BBc19BzK[i[[iuouocS99(1((1( (((9911(  (( (((991BKBB[ (9(o[oS9KSSSB1[i[c[iic[[[[c좖ǭiucKcocizK[cocSSKBBBBBKBBKKB999KS[B((1(((((  1 11   cɚ؄(1(111(19999SB999Kic9B9[ouSiouzzuiuuoSKK[[B1( (1(111(11(191 (BSK1B91BB1oSBB( (1 ԪciiB9BBBBB(9uoiocSiiicccicczouzǷo[KSioSc͉ɭz[cicKKB9BKBBBKKBKKB9919K[K1199(   ((  ( ؿ˭zS(9B919199B9K[BBBBccB991S[oiiu[czu[zozzi[911KSBB11((19111((191((( (1[S99B9B9Su19BB(  (((KэuKB1199((oioc[czKii[Sciciuuou¿o[uz[[dz¹„zoo[c[SBBBKKKKB9BKKBKBB991SS999BB99(  11 ( (1(1ҭɭzz(KK9B9BB9BK[999i[KSKB9[KKSucK9[ucii[icKSzoSS991111199B99SK1(1((91 (1Bcc9(1 B[S9KB 11(  (1KͭuzBB9111 K·ccSSSuSK[SS[ii[S[[ooizoĞiu˿zB9BS[[[KKKKBKB 1BKBBBK9B199B9SSB19BK[o[1 191BB ( uͭuoizͳɀK99BKB9((1KS9KB1SSBB9iK19[o[B9KiucKKzc9S¢cKKB1( (((1BBcoiK((((1 (Kcioc[1  BKKo1((( ( (c[oc9KKB1c°zo[K[uSSSSScc[SK9[iuouzzBBiɖicB19BuKSKKSKKSK11SSKBKB919BK9[KB919KcocS1(1K[K( 19Kϼoouªžzzz1 9KSBB9oiK99KccKBBcioooԖSKB1(((((191K[iS11 (1(9Souzc[oiK9 1oi91((  ( iuSiiKBKKK1KcSocSocSKSSScc[[ouioizziɉScщcuٿKBKSciSBBKKBBSSK9(9SSBKKBBB9BB9[KB9119KS[cB9(9K9  zo[uuoɳc9119K[BBBiziK91Ko[9(1oҚK999(((((((((999999( 9Kozu[[ic[SB( 1[zuiKB(((( (( iio[KBBBK1i[S[[iuzSS[[S[c[izuco͖cuciioĦǒuBB[[[SBBKKB99BBBSSKSKBSSKBB999B[B11111KKK[KS99B9 i·zuzi[ioi[ljiooozoK11111K[KBScouoS91cz[B[uמK99 (( ((( ((19KB1(9[zzouiiS[[[cc((9BB9 (9(1119iicSBBBBBB([S[c[uccS[[[S[coc[ucz°[izc[cc¹ԭuuzcK1Kc[[K9KBBB9B9(1B999BBK[SKB1(Ku[9B111(BKBKSSSSBB9BĿu[[uu[czoiuS1KKKKKKB911919SSS9B[c[cuzziczziiբ[1((((((((( ((9KSKK[uoczuciz9 19 1K[uziB9999B1B11cSS[iS[zuKK[cKSioSKuiKz[ocB[ouKSic[B(19SKBBBBSKKK9K9((1(1(9(1BKBB19S991(1(19BB[[ccKuɳ[[oz[KczuciuoɿzK[cKKS[[SBBB9BBBccSKS[c[SzcoccצB1((1111(( 1119BBiKKzc919( [ziuzcS9(19991199ucSSK[[9Su[[iu[S[BBBScSuiBucizzS[uuoizo1KKBBBBBBBBBB9BKKBB9BSK999111((99199[9B9111 19B9[cciİucuziScuoKBSc˦i[cSB[iccSS[[SKKSBKciiuiSuuziˀK1999B111(9BBKKicou9(19B1BziKBB919BB9111iK[[ScK9SuSSS[Sii[[S9Kcoci[[o[icoc9KKBS[SBBBKKKBBSKB91BcocB9991((1119Kiz1191(1919BB((1SɦiuoocoiKBBozǒSoKSiiicicSSBB99SiiizoS[ۿSSKBBB99BS[izzi1 111(9i[KBB99999KB91([SK[S[[KKSioKKSSSccKKKKSoozSKuiizioi[K9K[SKBKKBKKB9KB9999Bcuc9(1((999(BuzK 91((((9BB119o͞zizuou[c[coSKS[uocKi–[[cciucBBKB9BS[[cioc[ozoĭoSBKSBBcozc((1BSBBKzcB111B99999B9BBBu[SSSSSKSS[iBKKKSiɞcSKKS[iuc͞zzocSuc[uiBBSSSBBBBB999119B999KSoc1 (11ozS((991( BBSuĖizz[cucocK[KSSKKKKK9B((ziziicSK[K9KS[[Sccuioĭհiouoz9 9BKKSuc1B9119999191BSSiz[icKSSSKSS[cKKSSKzo[S[KK[[uɹiiuͪcKBBBBKBB91(199BB911S[9( 1 9K ((9KB (Bu·oio[[oiSSKK[SSB999 (9uiKB11ouzuic[[SB[[[SSz[uzoɦ˿ɭo[SB91([cBB99B9111991119KS[zBB[SKBS[KKS[cSSKKSiKKSSBSzizɰ޿c919KBB11(19BBB91(19(((Kco1 (1KSouu[ic[ccSSBKSSB( (( KS((( Bouzzoc[[SSSicKBSi1Sķ԰uiSSKBzѷuBKSKBK1KoSB9BB999119991999BSio9KB9BB[cBK[[zi[[KS[icBK[S[[ouuccϚ[9BBB91119BBBBB1(((1[ziuozzii[ic[SKSBBSB9(  ((BuiB (19Sizu[[SKSS[S[[ozu (ԹSBKS91KK9B91SK19cu[[oc[KBB91191((19KBSiKKKKBBK[[BSciuzoKSKS[[oo[[S[S[[ui՚K 9K11BBBBB9BB9 Szuuzzozooozcc[SBBB911(( 1K[o[BBB19i[S˭oouoKB[[S[ScuKuˢ–B1B1K[9[[[oui[ccuzcSKSKBB91((1BS[[BSSKKKSSKBB[uuicoiK[[KSSSzzcKS[[cciocuS[SB9(1199[izuco[iuiiuz[cc[SB9911 1KooBK[uijiSccBB[c[cSc˪oi9BB[šK[uBBKK[[[zcSKS[SSBB99czSB[[SS[SB99ScccS[icSccSSKBoעcuo[SKKoocؿǞoiiui91((K³iiuzzu[iiScicczSS[S9111((  1Kcuuzi[zĹKK[BSci[cSSSSc·Ϲ[K[ķuuc99BBS[[iz[K9Kc[SSKSuzizKccSSKB91BKK[[SS[c[ii[KBc߳uio[[zuڳiu[1(KİǷocciuzzcocSczuu[KB9(( (1999Booi[BB[užBSSuB[cizo[cS[[cKciuoczK1BSK9B9BKKSoiKBBKc[[[izicKSc[[SB119BBS[[SS[ccciSBS[Ączuzz޳oouİiouiicozuziizcczuiucK91( (((BSSccuicSK9K[ooBcK[uciioo[[Scoz[ciĦu–[BSSSKKBBBKKSSKSBSc[[Bo[SSSioKSSB19B9BK[SS[[ccciSBSKDŽccuǭošoiioccizzuzouuocc[S[K11 (9BSiciouzuc[[S[uuizcS[[KuuS[iicSScizo dzϪĉKBKSc[SKKBBKBBSKScSSKocSS[o[ɍBBB99BB119SKSc[[[ccS1[z[ɉo˿izoouoiiziouoic[SK91( (BScouiiouuuoucKKK[oicS[[[iuB[oocccc[ccKĉBBS[cSBBKBK9BBBBSKSSu[SSKScioc99999911BK9B[SS[c[K9i˖շĹĦiooiuiizozoicuiSB999119Siiiuuuoouuzzo[BBB[cBcuio[[iiSiui[[[[[ccSuɍcS[iuiSSBKKK99KSKKKiu[[S9SK[[B1BB99911(9BKKS[c[KS³z⿳c[[uziizizuS[icK91999K[ozuuuuozzoo[B11B[uzoiK1Bzuu[Kiicuoioo[cooiҦ[BKK9BKSK99izcSB9KS[So1BBBBB999B9BKSSccS[Ǣi[¢z[[[oiuzi[io[KSSSKB(119BSozzouuucSKB199KcicSB991ic[Sui[uccouccoo[ɳSBKKKKB911iKKKBScSSco9BSSKBBKB9KKKSci[[Ħ[czi޿cioozzzzu[KKKKKKKKKK1B9119coooooicKB11111Kci[KB9(11ScScou[ic[[ozi[KɭcKSK91BBuucScK9K[SSBScS[[SB99919BK[[c[[Ħuѷzz[cciuozcozuuuiiocSBKKBBBSK99SooiccBK99 1(1(9KcoiSB11(19Bu[cS€iiz[[zu[S⿪ii[[oo[KKcKBBBKKSSi[[B911119BBKS[c[uɹܹouiScioz[uociouuuu[K9BK[KB[[K99( ( 1Kiuuo[K911(BKKSSK͒co[K[uiSBˢoSBKKSK91BBBSco[B1(111BBBBBK[c[SԳ՞oouiSKScuiuzoSS[ozS919KSSSizzz[SSB99BKSczucS9(1(1S[Sz[KS[[ocSKSKSSKت˪SSKKBKB11BBKSSBKuB99BBKKBBKBB[Scu˼ªǍio[SBBBczuzziSco9999BKSccozuuiSSSS[cozocK1( Kc[Sc[SKoK[SSSSBBKSշcSSKBBB9911K[K99K˚KBKSSKKKKKBBKBSټ˼͹ڳcKB99Buzuo[ic9119119KiouzuiBSKScozzicK9919cc[[uoc[BuBS[[SSSK99z[[KKSSKKB11KS99K[ucKSSKBKKBBBBBSoij³ҭzz[BB19Suzoozc[zK111(111BizzzocBKB[iouzui[B119B[ii[uiSKKKSK[SKK[K99uiiSKKKSS9BBKK9K[KSiic[KBKKBBKKSz¼Ŀ˹ǰzcS9919SioiciucScuuuziKB911111BczzcoiS9BSiouiuzuiS91 (1Kciiii[KBBB[SSKKKScSBoiu[SBBSSBBBBKKSB9cucoiSKBBKBBBKSu¿حɼ͹uuSK911B[iouicoo[ScuicKKBB9((9K[ozuci[B1BSciiciicK9111BSccccci[BBKKzS[KKK[ScSSuBo[BKKKKBBBBBKKBKizoSciSKB9BBBBKKSuؿڪ[[ciSKKKS[ciuocooo[[c[SBBBB1 (BSczoccK9BKScccc[KB99119KSS[zicc[KBKSKucBKSSccS[KuoSKSSKKBBB99BSKSozSSccSKBKSSBKKKc⼄cic[KSiciuoouuocozzuuocSSKB111( 1BK[iuiiSBBS[cc[c[K91111(9SSSouccioS9BSKBizB[iioi[[9͚cSBKSKKKKB9BKSSSiuu[K[[ScSSSSSSScSiǿˍuzocK[iSizzoiiciiioicSKBB91 1BK[iuziiSBKSci[SKB9911(19K[[[[Kzi99SK9[cccccSK[KٷiSKBBBBB9BBKKKS[ccuu[KS[i[[[[cciu[KzտٚuuooiSSSKiouzouo[cccocSSKB991 (1BS[iui[BKcccKB1111111BKS[[Sz[KSSKcuc19K99KBԞ[KB9B99BBBBKSSic[zuBK[[[ciii[io[Kc¦iiccKKKSSccozzziccuziccSB111( (9K[cizocSBKSSB991((199BSSSc[Sccci[cĖic((KBB99՚uz[BKKBBKSBBBBKSiocuuK[cc[ziSSSSSSSoډzcoccKBKSS[uz[cuuiB999((9K[[iuuii[KKSB91991((KSSSc[SiocSSou[9Soz˷u[BKSBBBKךuuioS[[KBBKBK9BKKczuoicS[c[cuzcKSKKSS[cSuiu[BS[[ziuuKozu[119B1K[oo[oziiiSKSK11(1BBBKcc[ccc[ccSSS[i[[Kzii[KS[Si[ioziicSBKKKB99KBiiS[SScSScziSSSKSSSzتizzc9SicccKooi9999BKiiouuziSc[KB((((9KKSc[[c[ccSS[SS[[c[[BzoSSci[ؿݭzcooououioSicSB9BBBizui[SSS[SSzz[[cccB[ļSBSizicS[[Kczo[K1191BSccoiBSS91((1BKBScccc[[c[SS[[[SSS[KKozozuuzozcciiǦϚccucooucicKKBBBBScoi[KS[S[iuc[cicBܳuoBK[czzoc[[c[KS[SB91(((BK[iizoSK9((((BSKKSic[[[S[[[S[[S[coic[ioSiuoozSiKB[iϳou¹ܰii[cizcSKKKB9KBSzzocSKSSKSSuuuoic[zԦoScoSS[c[iuoiccoocSBB919((1KKSccouiuzcB91((1BSKKKSicS[[KBS[[ciiozzo[ioKcoi[[uiiB9S[̈́K[icSSSSiܿzicSKi[KSB9BKKcoi[KKKSBBSczoi[ɒ[SS[S[cc[coucScoi[KB91(((1BKSScizzocccK111(9SicSKKScc[cc[KK[[Scuuoci[Kcociziic9[Sѿ1BK[[BB9BBK[uԚuĄiz[B[ui[SB1BKKci[cSKKBSKKSczoiuɀ[cc[SBS[couo[[ocSKB9( (99BSKKcizuoc[KB1119[[c[[SS[[[Koi[SKScScococccScccucuiK[SҷKKKK[KBK[c[K9KKBS[couSSzi[SK1BK[c[[icSBBKSSSiuozԹ׷uoocouK99SouuiScocKB911( 9BK[[KSciouoiSSKB9BK[[KBK[[[c[SKii[SKS[cio[ouiioSS[[ii[[K͉SSKK[[SKicSSBBSSizzzic[oi[ozKK[[KKB9KKcooic[SS[KSSSouiiͰuuo[B19SiuuuciiSB1119BBSS[i[Scouccic[[SB9Kou[KBBS[S[[S[cc[SSS[oozczz[ccSKSucoocSSzBKKK[cS[uzzzzo[[ooS[[zoBKiKKKK9BScucS[[ooSSSSciico޼žizzuioiSK9BS[iuucc[B911K[coioicSSuuSciccKBBScoBSSBBSS[c[ScicKKSciozzoS[cczBSuuzuzzcccזKKKKccSizuzoiiozuSBBoiiSSSB1BKSuzcciiuocSSSScoii꿒zozocS[cii[SSSS[cuzcSSK91BizuuoocS[ozuc[oucc9(KiuoSKSKKKSSSSSSci[KS[[[czo[SSS[ciuuzzzouiѿۦKKKK[SBzĪωuicii[Sc[BBoucuui[cSB9S[[ioiiiouoo[SSSuzuccoݳoc[[SSci[KBKKKS[ucKSK99Biui[[izi[ccziKBB[co[BKSSKKS[KKBS[[SSKSKSSzžzouuooiuuuuuoo¹ωB9BBSBKdzzcii[KBSSSK[z[BBScccS99S[coiii[iuocc[SiiKiϹ¹occ[cc[icKBBBKKKSiziKKKKKK[uui[SSiuoS[iozS9K[[[c[BKKSBKSSKKKS[[KBBSSSSĒziciooouoiǚcBBSc[ScҪ皿iicKKBKKKKK[BBK[ii[S9BSScoooo[cciizcioziBuԿ蚼uicuoooc[SSKKKKKKKizoSBBKKS[ic[[SK[cc[czocKBBS[KKSKKS[[[[[c[[[[c[[SSS[9[uuoiS[oiccccciuu‰iSSiuuɢ˰ic[SB9KKBKBBBBKKii[SBBSSuooi[iicuu[[coco¢݄ooiioiic[SKSSSSSSS[ziKB9K[cccccc[[i[ccoocicB19KBKSBBS[cicciicc[[SSK9S[9KSKB9BSSKuccic[cioz˼zcSScuխcSSK99BKK99B99KK[SSSKKS[zo[[ooSciSScҳiocciocSKSc[BS[[SccciocSBBBKSKK[ci[[cc[cozcc[K( (99BKK99BK[cc[SSKBBSSKcS9BSKBBKii[uiKccciiciz׼u[SSK[icԢĿԦzKKK99BBBBKKK9BKKSKBKKKK[ziS[uo[izccϢԖu[S[[ccKBKSSKccSK[c[cSBKKKKKBKSS[[S[[S[ozo[[B1(1919BKK9119S[SKKSSouoB9KSKKK[ci[ooBKSicicS[Ė[[[SS[iɉuz簼zcSB9KKBKSSB99BBS[KKBKK[oucciooicoɦ޷u[SK[SKBKBBBK[[KBKKBB99BS[[KSSKSKK[[[ciuuucKB9BBBSKBKSSB11KSS[ozzB9BKSi[[i[[[uSBKooi[[cdz‰ouuuuKSSKS¦ziuouªic[KSKSS[K9B919BSSSK[iciiciooiS[z೒ͪ˪zi[[[SBBBB9119BBKBBB99BK[SSS[SKSK[iiuzuooi[KBK[[S[[Sciiiouuuzuuoizc(9KiouioiciuuKBiociicͼuz¿³ĭuKSSS׷i[iuoz[[SKSSS[SKB9199KS[KiuozucciuoS[[iԦĖcuzoic[KKiucBBBBBBBBBBS[ccKS[SScouuzuuzo[SKBKS[[[oziuiS[uKBouzccouiuz9K[ouuo[ioucSc[SBiuziSS[ͷzcciuuiiiSK[SSSKSSB9KB99S[SK[ciz[Scui[[iխĹѳҷS[zuo[oz[B9BB91Kozzzciozuoioiuz[K9BKKSSuioooo[cSSiuuiozuuo[[ci[[ou[cizzoSuo[K9BccSSicB(9BSzo[ccczo[oooi[o·o[[[[[iooziS[S[[[S[SKSK9B[[SSS[[u[SSiuoc[cĹئ·i[[uuzoozoiuozzoiooccciS1 9cocizoccSKBS[SKScioicozoSҹzKK[[KK[[K[i[coo[[iuiSKSSKB9Sic[[icKBS[[oo1Kcciizzo[[ciǪo[[[ciouiiuoocSSS[[cSui[KKSSSSSSSScoi[Scii[99ۼzi[[[ooKBS[iiKc[ioi[KBB919Suoo[Scoui[[oi[KcciocizzuB(1BB9KccKK91Kcc[SKKSB(KKKB9Sc[[[[[SKcuioozK9[c[c[uuKSc׿[cicizSzoiozioiBKKSSSoizio[SSKSSSSBSKSc[[c[SS(1ĞzǼۼzSSSoz[SKS[SS[cizu[So[BKS[c[K919Kcoi[zuKKScuuccoc[[oouiuzuuSB91KB9K[[SKKBKK9BSBKoBB999[[SSSSKB9ozooicuo[uoc[[[z[So9S[KKiĢ9[iiioci[KSKSS[iooiucSSSSS[SB[KKSS[SKBSKcբczϢzSizui[KSccioicSS[oozuoSBBcSK[SBBBBK[iccSouSSSSSccccSScuoioozS9BK[SK[c[SSK[cKSKcuKB9BBKSSBBB99Buoiiiiozuc[[SoBKKB9SK[ccc[[iiKKSSSciuuocicSS[c[[[SiSKKKSSBK[zoz٪uu¿˹ݞzzuoui[ccicouoiKSiozzoouoSS[ozSK[S[ccS[K[oKcocKK[[[SS[iiczz[io[KBKci[S[[cioz¹BB9BBKSKBBB19Kci[[ioiouc[[SuuKKSK1Sz[[[cc[cocKSSKK[ciziSc[K[uoS[[B[[BBBSKKKcuizԼڢϦحˢuzooc[ciocS[iiiccccKKSS[cciouiuzuzocciic[SBci9cc[SK[[ciS[c[[zzi[cz[KKSSK[[[iu­iccKB99BBSSKSSB9BKci[[ci[ɭccSS[cܪiKKSSBǼzoicc[[co[ScSSSS[ioc[[SB[uKSKB[cKBB9BKK[zĚܰԢzɭҭzuoic[KScicSK[ii[[c[SB9KSciiooc[coiiuzzicSSSBBi9S9BKS[[cuiic[cui[[uiSSKKB[iǿcKBSc[oSKBKSSKKBBK[[[ioic[[cuu[ԚcBKKBcѰzicSSS[i[[c[KSS[cSSc[BKKooSBSKScSBBKKKSiozz˼۹ɉ¼˿ziic[[[ccccSKS[[[[ci[SS[coouzu[BKKSSS[oc9911Bc9KBSSSSScooiozzo[Scuu[SSKS[˹o[BBSK[[[[[ioS[i[[[BczoozoiiuziĿzK991uɞzooiic[ocKSSS[SSSKK[cK[[ccS9SKK[K9K[SS[ciiKճԹ­zc[ccooocc[[[i[KBSizoiccciouzzzozoSS[SKSSBSzc[[ioKBK[c[S[[ciiuiSSKSSBSS[iǹ[9K[[SSS[[S[SKBzocooiuoǷ[BB9 BzuzuzzcBBKS[SKKBBS[ciioi[SK9KB9BBBScSKc[[o߰Ѱui[[czuuiozziouzzooocciccKBBcouicoi[ioic[SSccSSSKKSSSK[zuSKSiocS[[[[[ccSKKK91KSS[zdzK9BSS[[[SSSSS[B1zSiiouio՚KBKB1ziuz[czo[SBBKKSSKBKSciccooooK9KB999BScKKizz[zݿݰzioioiB[[[[Scoicuzzzuoouuoc[[SKKKKco[KiSouiuoSBKBK[[SS[c[SSiuuzz[SS[[c[KKKKKSSSKKKB9KSSKcϿoSSKBBBBK[SS[[SSBBiScoˍoiuiuoio۰zKSSB[zoozSKS[K[[KKSKKKKS[S[[[ScioiKB[S919BSccuuKoչؿϚSouic[BSoic[Scoouc[oi[[[SKBKSKBSK1[u[iiucBBSc[SSSS[SKcii[SSKBScKBKSSKKKKKSKSSSSKBKSc[[iͷcS[c[KBBBKSSSKBBSo[SuSKu˼zuouoouz[SSBKzoiuu[KKSSSc[[cSSKKSci[[[SS[[[KBB[[K1B[c[iuzzK׹[uѢoiuccciucKSozzcKSciiccKSSK 1KBSuucciouoccci[KKBKSSS[iSKKKKBBK99BKKBKSSSSKK[[SKKicS[iϹSBSSS[SKKSSSKBScK[zSKSoĦoiuzߪi[KK1uziouu[SKSSSKSSSic[[[S[c[[c[cSSSB9BK[[KK[c[[iizuBհocc[uْ[zoizuSci[zoiozzS[zuu[zoiK[KK[iiuoioociuzzKBiocB9SSK[cSKKKS[KBSKBBBKKS[[S[SS[[SKiz[9SҼKKSSKK[SBBKS[ozBK[SBKKc°uiɉi[[KB[cozu[KKKS[SBKKK[cSS[i[KBSSS[SKKB999K[[SS[S[ciiS۹z[KSicSz׳Kuo¢zuKBiKKuozzzo1uo[oioo[cicicucoziK99[ScccSKKKKSK[[SBBK[K[iSS[ccSBKSiiB1uϚzKBSKKKBBB9Bi919SS9KuɰzuzocѢu[[cKcuiuzo[BBBBK[[KBBKS[SBScc[KB9BBKSBB9B9BS[c[S[c[iucωSS[SSc[[[i͞°uB[cS[iicozicui9iziuiioS9B911BoKBi9(1BKcc[[cSKKBBKBKS[ccBczicoz[(Bi[K9BҭzSKSKB999Kcu9BK[cScuzuzii[[uoioǚzKSc[ui[[KKBBBKKKBBSS[SKS[cccSB9BKSKBKK9BBS[SScoSzذc[icSK[cccBKĞװoSi[c[BB[[ii[BBBccSci[iiB19  1KB1Soc9KcSSSKK[iS[K99BBKccSKK[ou[io[K[KKSSuϷoiKKcicouz׼oKSz[Siiuzzzi[Scc[czociuϳiB[zzKKSc[SBKBKBBKBKSKKKSccK[[SKKKKBSSSKKBK[SBiSɰcciSBK[c[cSiozѪԢzooicKBS[SKSKBKSKKKB919B 191BKKSKKK199((B1([ui[ooociiKBSiocBSuuiuSBBBS[S(BKuͿB[SoǼiSS91zǖziioi[[KiczϿio[9KSiiSKKKKKKSKKKK[[KiiBKSSKBB9BSKSSKBS[91uzKzɚuicSB9BKccicouiҿ°uScic[[cui9B(((((BSiouzuiSBK9(9SiKuzo[S[[K9ciK9c¿KBBSB9BiuɒSBĪocK9[oiK9ܚzzzzzucKۿϼc1K[c[[SSKKSKBKKKSSSSooKBBBKK9BBKBK[KS[iS[cKiճzi[KBKKK[cciozzˢoKKB9BiozScio¼zouK KiB 1KS9KcB9[uİoKSĚi9c·ѭoS9KKK[oo[B9ˀiouzzzzucuǢժSK[cS[[SKK[KB9BS[[ScuuSBBBS[999BBKScocuzcoK[ɼ³uic[S[[[[SSSoouڷiB9991((9Ku¿¹zoS[cucciScciz¼ɹ¦zcizǖ[KSSSBBKKSKSKBBuiouuuuuuzu[oSKKS[ccS[[9B9Bcc[[cuu[BKK[[SKBBBBSicSoziuS[ijoi[[SKScicS[Suɖzzc1  9K[ouǿĿļ¿ķĹ[1BScS[SKBBKKKSKBocooouuuoiuzoKĿɞS[S[S[[[K1SSSi[SS[cioSSKS[SSKBKSSS[[ooii9zĢzuuoccSKKKKS[[[[oۿuc[SBuS Su¿ijĿǿzcc[SScccKS[SKBBBKSBBooouoocioiouiS˹ܭSuz[KKBKSKKKiic[[[SKKSiSSK[c[SBBScSKuooccSB¦ui[c[[[SKKKSSSSoiѷcS[9uuɪĿ[B99BBBK[oic¿ɿҿǿļļuS[iiiccc[cSSSSSKKBBBBBooioiiiiciiiiizɼܢS[i99BSKBSccc[SS[K9BK[SKK[[SKBBK[[co[ccSBz޼uooooicccS[[KKS[S[z[uu1( iɼzuBK[[Soo[KB[¼¼¿ϼĦcKBSKS[ccccc[c[SKSKKSKKKSSo[iiooi[iii[o˦zܞKSc[BSSKBKS[SKSSKBBS[c[KS[[SKKBKcio[Soz[S͢zc[cioicci[cc[SKS[[zoԿK1cz¼iizScɢ°uii[[SSSKK[[SScicc[SKK9BBBSSS[¹uiiii[[oi[oѿ۞[[cci[SSSKSKKBK[SK[cS[[SSSSKKKBBcoi[co٦io[coii[[cuiiioocSiuɰ[(1[oǿziijɹzouozuĹ·ļĹ[[oocKSc[SSSSSKKS[ic[[SKB99BBKKSdzuiccccccoǰĉiouo[SSSKKB9KSSKS[B9SccSSSKKBK[ic[iuòiooozziciooooiiczz11oªzouc[³ziciiooǹuiS9Boouo[SScc[[[SKKKBBK[i[SSBB99BB99Kļuc[[[cǒzizccccSSSKS[SKKS11[cc[SSKKS[cccizBĦђciouicii[[oioK(iĹcBS[[K[Kczzzuczzi[11Bczic[[[cc[[[[SSKKBBBS[[S[KB99BKBBB˖ucccڿռѰi[[uiooccci[[c[SS99[cS[[[[[[cicoSzתociuoSocK9KccucKcdzǭcoiSKS[Kcozz[S19K[ooc[ccScccc[SSKB999BKKK[KBBBBBKKKܭ[cϢocSBB9B9BBBBKBSKKBBBKSSK[KSS[iiuķzicudzķ·ǹ°·ķǿԳ·Ėzooozouziiuzuouoouzzuͷ¹uKoɄKSSBBKBB9BBK[[SSKBBKS[KSS[[c[ioª°Ѽ¼ͳ˰˹ĿļdzͷziuiizcBcuuuouuociĹSSuͷu[SBBBBBKKK[c[KKKBBKS[SS[[c[[ciͿĦİϭϳ˼͹Ϲ¹ǹiuc[ScuB9zuzuoioudziBcĢcKKKBKKS[ic[SSKSKKK[ii[cicc[[[iz¼°ؼϰz­·³ѼѷķªuozucKScu[BizuuuzzuooǭzɿoKuSSS9KKS[iSSKKKKKSScuuiuocc[[c[ouuĹǭ׹ϭiz˪¼ªžİɼǼѿzziizzoiK1Szozo[[uzo°¿[o˹ucu[SKSSSKKKKBSK[SiiuzzoccSK[[io[iĿͰ׷ɞ԰dzijԼ׷Ŀ׼¿ǿĦzzoouuSi[K[uzuc[cuzzuoo˼¿ͦiuzui[KBBBBKScciizic[SK[cccc[oĿͿռѰĞɰĹǼɰ·ռ¼¼uzzzo9KouciK[BBiuuuzziouҼɰ˚ii[SSSKK[[[[cuzzoc[[ScccSS[co¹Լس­ǷǼҿĦļ¿ijzKK[[(co919Bozzzz¼ǖzouocc[S[ii[[ioicSS[cic[KKS[ciuǿϰ˰dz³Ƿ¼߭[iiҿԿzouiKKSoiS[izuzu¿˪zͭoizuooozzuc[S[[cc[[[[cicSS[SS[ciiuǿԷdzೢļ˦ǰ¹¼ٖKiuuɼɼǷcozS991iuzuzcuz°uԿǒSccic[iuui[[[SSKSS[uzi[KSKSSS[cioouɼѹčɷɹ¹Ƿ¿ϷמiooiǼԹ[zoccu1K[z[uĹͿɿzBSSKSuu[[cSS[[[ozo[KK[S[S[SSSS[[[u˿Ϸļչ¿ѼĦԢcc[[zķͪuozuKBcoSS[Biuɿ͹uKSS[uuuccc[c[ciui[[S[SKSKKSSKS[[Scz¹ϼɼͷذİ¿¼ªǹǢɖ[ciizķǞizuuoc[KKSuzciKѭcSciuuuoiooiSK[iooo[SS[SSKKSKBKKKBS[SSco¿¼ؿ׹ͷٖ巚ļ˪˰ĒciiiuijǚzucSoiiuzoiiuzuoϚBǦoic[cci[KSiuiSKKS[[SSKKKBKKKBKKKSK[ci¼Ұ­dz٪߹Ϳ˼Ƿɖcii[oĭ°ǿ͢uzzzoiuuiozziu³³ռzo[SS[ScicizucKBKKSSS[SKKBBBB9BKKSSSK[cǪϷš³ͿǼɼհ˚icc[oǪ¼˞·iBuzziouzoozz[ɼĿϭɞ[K[[c[uzu[SKBKKS[KKKKKBBBKB9KKKBKSKSoͿ˷ͦϳɿĿļĢǼ͖oiiciǷˢҳ–ucozzzzzzzzozǿ³˖uo[ScccizzcSK9BKKSSKKSKBB999B9BSKKSKKKcu˿ɭɷۼ޳ͿĭԼǰǭzˍi[[[cͿİĪעļzzuzzzzi[˼ļĿɿѼoi[cccozzuSKB1KSBKSKKBBB99BBK9BKBKKKSScoļǢϼķעdzѭ¿ǒcciccͪĿ°͍uouuoouoo޿ĿdzijѼi[Scouuo[SKKKKKBBSSBBKB99BBBBBKBKKBKSciozͿɷϿͷ˹ްܪխɿĿĦĿǖcc[Siɢ¿Ŀɹไoouuzzzuoؼɼªĭϼz[[cuuu[KBKKKBKSKKSKBBB9BKBBBBBBKSKS[ic[cͿڪ˿ڼҿǹªݭ׹Ǽ¦ϷɒSS[Siͷ՚zzzouuuzuzzz˷ĹĿĹͰoiozoiBKKBKBBKKKKSKK99BBBKBBKB9BKKKK[c[[iļǹݹ㳚ͿªĖzͷ¿˪ɉ[[[SiǷ„uzzzuuuzuozѷϦ˹ϼѿzuuuiSBBBBBKBKKKKKBKBBBKBKBB99BBBKKSSSS[coϰԼ˼dzͦѿuɳ¹ɒicicuͳϿԪܦzuuSizuzzcSzɹzϦϷuziSBBKKKBBBB99BBBS[BBBBB9BBBBKBKBKBSSccoؿϼѷ˭¿’oǞ·˖BSciuļҭͿտ͒zzzScuzucuo脀ĿͳɦzziK9BBBB9KSB9BBB9KSBBKBB9B99BBBKKKS[S[[ouͼɭɷ忖ǰ–ѹі9cc[u˹˳ǰݦuuuzzuzzǭ˷uļĞɿo[KBBKKKBKKBBBKBBBKB9BB99BBBBBBBBBKSKccouԿѦijϹ˹Ė˖¹՚S[[[uij¼°zzuzzuϷɷǼͳɷzSSBBKKBKKBBKBB9BBBBKKK9BBBB999BBKBKioczdzؿĢĖoš¿؞S[[SudzĦ˼ĦczuzuzzziiɼǹϹ³zͪSSKKSKKKKBKK9KBBKB9KKBBBBBKK999BBKSu˼dz׳ĪɼĢz¼zzzמK[[Suǹ˼cuuzzzuuziSKĿϿİϿ¹oɍKKSSBBKSKSSKKBKBKKSKBBBBBBBBKBBBS[uĢouɰɳ¢ķǭzzouךBcc[uļɳzuzuzzozzuo[9i͹‰ǰĿɷuSS[KKSKKKSSKKKKSKBKBBKKBBKBB9BKKKSǭĿdzc[cuzoiɷͼǹǿcoͿouoՒK[cczļ°ɹǿzuouozuo[[ociuǿ݄ļijuz¿ĭ[SKKKKSKSSKKKKKSSKSSKBBBB9BBKSKBKSɷͼzŦuScccciouuɿٳuico–zzuuښS[c[zǿĚĿzouuozuozzuiB9uzciĿ³ބzzǼ·ci¿[SK9zzSKSSKKKBKKKSSKKBBBKKKKKBKKcoϿuocoozͰo[cic[[[couuĭ[c[cĚzuoouޢSccKuڭǼzuzzuuzuuuzuzocSiuҹ¼㍀zǼ¹ļ°[K[ۦSKKKSKKBKKSSSKKBBKKSKKKKKKK[oc[z[ocSScuɿoi[c[c[SSciiuizɰ¼c[cc[[zĢzuoiuuzi[[Szڹªozziouuuzuzoiɷǿ덄ǿzdzzҒBSSSKKKKKKSKSSSKKSBKKBKBKSKS[SSɉiiSS[[SS[uzKS[[c[i[[[[[[izoiuǷ[[[[[SKiɭoccoz߷˼ǿ¼ozuoozzzucoocĿzzļ˹z[[c[KKBBKKKBKSKKKSKKBBKKSKSc[SKɒc[KS[[[KKKSc[KS[[[[ccSS[ccciiooiuϳoi[c[[SBc͹ui[uǹ˰uzuuoozuiSS[İ떄¼·ǰzouzocSKKKKKKBBBBKBKKKSc[Scɖ[cSKKKKKKKKSSKKKKKScic[[ccc[[cuzo¹ɰɪocc[c[SScdzoouǚzuooouci[dz랒¼zͿozzcKBBBBKKBKBBSSSK[ɉScSSKKBKKBKKKSSKKSBSiiiciuuicci[׼·ͷ˿o[S[[SSi԰zouzҼ³zoouuļuucؼꞚĹi˹zu[ouuccSBKKKK[cSBKBˍ[[SSSKSSKKSKSSKKKKKS[cioioooioucѼɿļo[Scc[cɢzooռª˳uzzuzķuǷ³랉Ŧccuic[couuĿ­icSKS[SKK[Kǖc[SS[[[c[SKKSSSSSKSSS[iuuuzooɿǿzuozc[c[cĿɪzuzǞٷzzuozuziԿҞuǷļ·zǼucɿzcKKBKcKǚui[SKS[cc[[[[SSSSSS[[[iuui˼ɿzS[[oǷɹzuzĭѳzzuouzoϹǿljiɭ³uoiciz¼¿cKKKBĿ‰zu[SS[[[S[[S[S[S[[S[cc[iuzuiz­Ϳͼ[occu­Īzz¦ɷǪuouuczļǦϿu[ɿizzoi[S[[[cuĹĿ³iKBɿoi[[[[S[[[S[SSS[SSS[[[[ooi¼¿İucczzz·ɦzԿǦzouziuoi¹˷Ĺ[ozoouuuzozǿodzǰKoz[c[[S[SSS[SSKSSKSS[ccoo¹ͼķϪz[[io¿͹عzooouu¿ǿ쳄uuzzuo˿˼˷¼ǼϚ˹[BɄS[c[S[SSKSSKK[[SK[[cozɿ¹Ϟo[[[[zªzͰ˰zouiiu¼Ŀijǰķij·˒cuocc[SKKKKSSKSSSKK[iz¼¼¼ɒcSSKiǭҷɪooooozoz¿¿¼ǿoɰoozzĹ¼ǰzuocSSSSSKKKSKSKSS[uļɹ˳uocǿɭͪozuuozzici˷¼ɪ¼ǼzoǞzɳɿɷzi[S[SKKKK[KSKS[uǼ˳ѿ¿ĢǢziu˰zռɳouzuuoooؿļɹǼϹɹzozͼ¼ɭ¢¹°ļoicicSKSBKS[cozͿզ˦ͭ·ozzz͚u¢uizzuuio׹¿ɹǹ˿ocuͷ¼ǭİ˪i·uocSSKKScuzzuzzz㹖ռͦccuհuҷuczzzuiǼǖ[izǰcco¦ǭķԿoccc[cozoĭ˷ͪչĢoiİ۷ɼͦzozcϹ˭¼SuǞuzzzϿĭļҹciuicioooozªĭ¹ǿͪɢzɍšzzuzuzҿҳ˼¼i¼ªzz˭zoǢɳѭKioiiioiiɼɚ͖iuɰİϖ͹oiuuҿўļޚͿɿzuu¢ǒoouzĢͭ԰iic[oouzooɼɿ̈́izuouou˭԰oiuuciǷɰ·מİoɿzuuǹҷuռװԭoiicoozzzǭĹ˭uuzouoicouɷڷouuuzzziiķļמudzzuuzĄɢխԢѢoiiouoiuzǰѹϰԷuouooiiiuɿzټzzozzzziSz³¼ٞu¹°ɒoԿѦ蹢ϒioizuooooiϷzϳբܷzzzuooooou¦zɦzocoociuuuooi[o³ɼٖKB19uǪ¼ǍuѳɦǷꢒɄiuiuzǭzz߿zտuuoouuuĪĪiccc[c[oooz˼Ǽؒ1iǪijuuͭĢɷ԰¿iczzˢzuzɭϰͷzooouuuzɳzuo˹ǿǷ؉ BɳǹĹuĚčǹɰļļǷc¼Լi׼–uozɪͷĿzϹuzuuuou’iociɿdzىi  SͪĦdzҰ¼˰ɭzǼzԒ ޿zɦļz˿zzzzzzuuz׷uScǿ·ԉS Kճͳª͚z˿ǼͳǭĿijǷ˚zǦdzijuzzzz¦zu¹ٍ [ռĪ˚չ͹ij˹͹ؿǰzҷѳdzzuzzzuҿķ㒄z[9Ѱ˪ĞͭǷɷѹͰԿɷĹͼǭzzzz˼ɞĹ疄zǼϿĚǪѿoԼѳ·dzĹ·ijzzzǪ¿¹蒀ĿɪϹǷ͹¹ǹccz˦Ŀ۷¿ɷ·ǹzz˿ļ[ઉǿĢټ¦ĿĹɰѿɿժ׳˭Լ͹³¹zzǪuu˷o9ڷѿļ͹͹ɿ³Ģ˒uͿռѹ°ϷǼzɿzzzzuzͼ¹BSͿ˰ĹĹѹ’ɰ˚˭ĒͰ¹uzz¼uuķ˼ǹSB[zǼ¹Ƿ·ɼҿɷǿҼͿϞҿuzzuzzzuĭzzu˿·z9KKBcoѢͿĪǷ¿¹˦zɷϳճ˳zuzzuuuuuuİɼ¹c9Kciou[˹Ǫ¼¼ɼ׿˳˹ͷϳzuzuuouuuozǷǹic’cɼҷĿǚuĿͿϹѹzuuuuouuuuz¹·İĖuϪɷzzzǼ¿Ƿ³zzuuuuzuzzĿ˿͹ɿļɿѰǞoѿǿ¼ļzzzǷǼѿǷzҢϳ˹׼ǷǞzǷǹzzzuuzz°İ׿°–ziooԍǦǢuͿͰҹ͹uuuzuuzzuuzzķķϷϼ’uoͼǪɷzzɼҦǼĭuzuuoooouzzuzzzķļ˼·zz˦Ǧuɢ㿉ѼϷzuuuzuuuiououzɼuͿɹ׹zz˼Ğo¦z͉uسĭǦzuzuuuoouooooozzɼzzzz˹׳ucu˰ɦԹozѢǪ°׹uzuuuuuuoouooouzijzzuuɦ˿㼒uzɰ͉ҦuۢԢªϭ׹uzuzuuoooouuooouuzzzz˳zzzzĭǿǒž­ѳz˚ڼ濖ɿ°ɰڼzzuuuuuooouuiiouzzzz˭zzzzǹͰ͞ўĒع㿖zuzzuuzuuuuuuuoioouzzzɰzzzzzz¹¦€ҳɚתܰԚzuzzuzzzzuuoooooouuzzz¼˼zzļ¹ϰzˢѪǚĪ᳭zuzzzzzuzuououuouuuo¦¹ĭ˞u¦缳ǖ޼ɰiuuuzzzzooououzuouzĦǼ·­€ĢǪ߿³׹uuouuzzzzzuoououuuzzzǪ¿ǹuzϳͦѷ۹ij῭zuozuzuuuuuuuuuuzzzuz˭zz¿ͼžuɼzzz˪ĚǼϷѿoouooouuuuzuuoouzuizϹĿĪˢǿ³zuuzzzіѰ混Ŀiooooiouuuuuuuuuzzzuocioѿ¼ª͞³zzzzuzzҳªطɳǢĞщuiiiiououuzuzzzzouooiiuϰ¿Ҽ빿ɦ˳uozzzzzϞҿѼĿչĪༀuoiooooioozzzzouzzzcoioiocuѹ¹˰ԼԹuzzzzzuzҿ¼ϦϹѰǰĢuiioioooozzɼzuuuozzoooooiicioǷ·˹ռuzzuѷǼطɭ濉ͪuiooiiiooouĹzuuzuuuzciiciioiiɹĿļۿǢˢzzzzzѢ¼Ϸڼ㹉iooooooououzzuzuzccccccic˹תɿ¿ϰzzz–uɞѹĹϪԭܿoooooouzuzzzzzuz[ciccccɳ¿Ǣ¼׹ļ˷ǖ༞ǿٿ˷zciooiǷzzzzzoiiuicccc[uϿİϭ˼İ˿zͿ๞ϿѿխǿdzoooϿuuuuoic[cuzo[[[o³ǰļ˼ĿϿɪuzĢuҳҿɷҿۿͳdzĦ̈́u˳uozoii[cc[cuuii°¼­ϷoĿǖzzzѹu˳ǹϿҭ¼ĿϰĦzoiiuicccciic[izķǼɳǞļϷuzzzzϳu˷տ­ͼϳªuuoiiiccccciiccuɹ¼³⹿ijİĹ˿Ǧzzzɞo׷ǼѰ͹ǪĭuuuooooiiiicccicǷǼ˳ǹķѹҼzzҿzݭ˞­Ǫǰɳzzzoiiiiiiooiiczijͪϼ­ɷĹϼzzzz˦i˼ܿҦϹ°ͼͳzoiiooioouocz°˿ҿuǼšzzעͼzuǭ­ؼzozzzuoiuoioiuo˼³˷SK¹’uҼ‰Ϣ[zϰĦռuuzuiiuoouzzuu˼­Ѽi9cİԷoѼѹɍ9Ǫͼѹzuuuuuuuzzzɼķ[zz1KļǿĚoozϷͪѼzK׹İ¿ǪozzzzǷͼSSo[(SϳϷҷcu¢զɰҳ[[oɦǹ°zuzzѿijϿuB11uٿɦҰuiѼѷѢBzB׷ϹǷ¹SBo˭ժҪuoɭҍKSշͦɹ¿uuϷĒͪuu¢ڍKui­zҦϿ˪uuooccouuuuuziz¹ɹɿɹĪļĿouķ·Ѧz٢ϢocciuBKB9BBKSSSS[cziKBBKKKSSKKBKK[i[SϷizczu˹ɖcouuuicoouzouǹzS[zco˼Ħ˭ǿɪɿ9Bİ׷ѭتͰ˪oiiccziKKBB99KSS[[[ucKBBKKK9BKBK[SK[SBԹuuozļɢcouoooiozzuozu[iiu[uǼķؼͿͳɿհB91K˭ɍͰªuuoccuoiS[SKBBK[Sc[cu[SSBKKB9BSS[c[KKK9ѹouǷoSzѷuoiiozzzSSc[[uoSuooļɰҿɼɭϰuKKBKع٭ҭİui[ii[Sc[ic[KSS[S[[o[iSSKB9BBK[S[c[[K(š¼ouɀiiuzuz[KSBui[ٳ˭Ҫǿ׹ĹͳcSS¼ijܼžسզ˞uzuo[KKS[Kc[SS[c[Scuzc[cSSSKScKccKSSK[[1ijšiǷ³uozzuuuzoccuouzicɰͷ¿ɿԦǿ–uc˼ª㰢ܪĒoKK[[SK[SScciicuziS[SKKKK[cczziioK¿ϳuĚozoouuii¹ѷǷ妄ǿǿ˦ɿĞ漍ۼĭijcBSc[SS[[[iiiouucS[SBBBKScozɰzuuǦɿouzzzii͹Ğټ³ᚍɿͿҭɚǒz߹ɢ˿cK[S[S[[ciiizzuocSS[KKKB9ozzҭzªooB[zuzuciu³Ǫٷɼ㳖ɿɼϹԳǪiǷ˹¿¿z[KKKSK[ciiiouuocSS[KKB(1zǹªč­Կzoccou[izzo[SͿ˿ǞɼԳ뿚ɿ¿¼ѿijտ¹ͪշocSSSSSK[oicuiicKSSK9S1Kzzzͼ˳ҿǦ͒zS[cizzzozuzuoouĹͪϰ͹zǭ孢¼ɼļǰ˼˳¦޼SS[SS[c[cooz[cc[cSKKK(1cu’ٷšiiuiuzicc[[zĿͷ͹zcǰদ͹ĿǼķͿ³¼ǷݼiBcc[[ccciozѼzc[cci[[cS9cϖĦ[io[[iѷǿ͹[ocɭښ˹ɿĹĿ˷ɳհS[icKK[[[iuušoiiooiS99[zǚ˿z¢фzSi¹Ǫ˿ݷoҿڞļ¿¼ҿĪڰͭi[iccKS[ccuuicuzzicciooK 9izɹǢǒɳɉzɹǹϼiiѦՖİļǿļdzհǼϷˢoiic[c[[[couSSiooicSiccciiiKBKSͼĿ­zzǷoĪɿѹª€uɹњ¦¿¹ͳҷĪͼB˿[ii[[icc[iuiSSii[B9BS[[cccKSzўĦzzzzzozͦǼ°͹҉cǿdz˼ϼ·¿ϼ˷Ҟɼuz۰iSS[cciiccuuiccoiSB19[cci[91[ɳz³čzzuzzzizϷdzϳܢoϷϹǼĿͼ˹ѭͿښoi[Kc[[[icczuci[ii[B99iuc[19cžcS¹ѰϞKzuoouzzԿԿͷzɭ߭uǷϳļ¿dzzİݿǿiSi[SiccS[cozccziccSKKKu[B1Soɚuzuu­cKK[izzzzѷĹKiɿzⷀz¹³ϭİɼϷǹɼ³ߖSc[[[ioiiiizo[ou[[S[ccu[19cczļɪc9Kcuͷɿ˦щciͼuuޢoİ·ϭĿҿijϼ·[ci[[[[ccccozouiii[ciizoB9S[cɢuİҚKuͳҼ˦o[iɢiz۞oozĿ°ǿļϷǪ¼uiɀSic[Sc[cS[cuooiiiiicic[[B(S[SϼϦzİ9Ĺ׹ɼiSzzc๖zozϿɼ·ǭǼozzuoz[[[[[[i[cSciio[coo[[[[[cSKB[uu˳ķĭɖK9͹ɢiǭļijԀuizͦoioɿ¢Ƿɼǭ˼ĪɳzzzuuiSccc[[SS[ciuciiuocii[[ccozzozĭzSۦ[[ҷč(ɷҷԭ߳–[z­u[iiz·dz­ijͰѳzzuziS[[[[SSS[ciozz[iu[io[ioiɭǰBiɒuuo°c9ǿآici˞zicic[¼ɿ¼ԿuzcicSSS[SSccouzoc[uS[cciicǼ˼ϞoSzzzǖcKooǢǖSžͭzzoщiioicoǼª··ɿijѰzccic[KSc[[[iuoioi[zz[SS[SK·–KczB¿KKzɰijoKԹɹѼuuسzciu[[ɞ¼°ž¼˹zo[SciiiSS[[ScuucciioziiiS[i[S­91iSu·uiɪzcu¿ˀߪuciiKSudzĿ¹տǞuc[[cccc[[[[iuz[K[iiou[icSiuci˰¹’[9zؖzo9K[oˢǹSĿݞไuocc[Szuzzzij¿ͳ⿖uiccc[[c[[[czzcK[ouic[[ccio[[ǦɳuSoݷzz[Kzڼ[BϿu᷀uc[S[İuoziϹĭ߿ذioic[KKc[S[uo[[cooiicccou[(K¹˹iiooϿϷ€So͹͖žz‰i[[[zo³i[ԳǞu[c[SSKKci[[iccicc[cicizi91[oSiɼSuĪioǰDŽҳzuzuiuuoz¹z·¿Ϲi[[SK[c[cii[zi[[c[KScoiic( SԹiuK¦9zɞ˳ϖ¢عzuoiizoĹķĹǼļϼoS9SKB[i[cii[oS[[KK[cc[c9Ku˞ϰzoɹuSϭ¿¢ɹؼ˪ucouİɿ[u͹ѭzcKBSSKS[SciccuS[SS[[[[S91ѿҿɰiҹعoɼҒ‰uuzoozɿªɹuu[Bҿᷦo[[KK[[KK[[c[cuo[SKS[ci[9cļɳϳǷuK׿ĄBS[Sװĭiuozuozuoķ¹[[S[Ħ߿oicc[[[SSKS[cio[S[c[SK[icB((co·š¹Sѭi³SSoտշlj[uzzuuiS[izĪĦ¹ķڹS9zc1o˰˰occ[SSSS[ciiic[K9SczcS[cK1 9[iuͼ˷iuĦzcԦzǚ[[ļϚou€o[uz[ozc[czzijiĿͦK9iS9KѳcicciSSSKKS[cSicSKS[SzSS[9( ³dzzĄܼ[Suzɪz’iScuizz·ͪciu99BS༿z[[[ciSK[SSSKKSc[[KSSSucSB i˹zoioouzɖuooͿ׿[KoԼԳz[oݒoucķǿҹK1(1Ko·o[[S[ccS[[SK9K[[[[KSSS[uiS1 S˷[[czzBzՖuuccc³׿z[i߿ҿ˿oi㖀uuzǰͪS ( [˳uo[[[[[SKSSBBKS[S[[[[[SS[iBBǰzzؼKͳωuuoz㿳ļͦɷĢuߪooij·ϼ¼[ 1z߄¹ci[[S[SSSSK91BB9S[cc[[ic[[cKB٦ͿĿͿطͰĦİϖϚɳzzڿǞɰoɖSz­˳ijҿ1B(ؿici[[[[S[[SKBSK9BSS[cc[iicciciԦuў˪iucѷ˹o঒ĭ׼ٹǭzǚzzoijĹuiuϪcܚzicooi[[[[SSS[c[BB[SSScccc[[ccuĖuļǿ˳o۷uBScuڷiҦɭͿ͖­izķǷzuicS[iسǚziiiioi[[c[SKKSSKKKKKKSS[c[S[KKudzzɚע[K¿ǚɰ٭Ѫ˭z­չǷzooucciuzzͷĒњziiiioc[[[[[[K9BBKK99BSSBK[[[K1Szuuͳ׼⿰zciǦ׷ܿ¢oSScijѦ³oiuzou˳輢ocociccc[KBBKKKBB9BKBBKKS[91uiooouzİzuѢuozS11S·ϼɳڢz¦ocuioі³Sozzɹu[[S[iSSSKKKSSSBBBBKK9SKSSB([zuzzSSS[zSBcҼǹϳuucu9KScoٰ׹ͪщz·uS·۹³o[zzuzouzǢĪԒoĉcu[BKSK99S[S[[SKKKBB[S9czcļuuoSSccSSKS[BBScuuSǭiSS9SuͰļت°ئǼuzSͪ¢zzzcoļɰԍ[ɳSBSSKB9S[[ii[SSKBSKKiuoi[[ٷiSci[SBB999BKS[iiuˍzͰuuSBS[z¢¹Ϳ⹚³ѪSiϪĹzcz۰coǭĪݭBɭ԰u[KBKSKSiiicc[[SSK[S9BKKžu[S[B((9BKSB1Kc[c[SoǭzucKS[[coԿɷªҦճ¼גzuĞcSǭİocKS[icici[c[9BccSK9u߳zS19BKKKKSSczocooccS[iuzcuio9[oiooͿɿ˷ϭǼijo۹ijoҿ׹zϞoǪҹcSKccc[c[ccBuooSBBiSco[KB(999BuzuSS[izu[SBBcKioؿɷĿ¼ɳu۹uuԪoԹڢļǭɳž԰iicKS[[uoozzoiKK9ccKSS[K9991[S9cĹuiciuzoK9Kci˖ɿϿͿϚo9zoѳǞ·Ѽ͹ɪzѼcSScouǞcB(1((SSSKuuiiĖcS9Kzˢ[[Ւļ³ߦKע¹ح³ϞԿўɰKiǷ–ziooķS9[cooizɪ9BĹ˰zzٳϳļĭ¿㿢KzčzzټuתڰoB˼zzҿoɖu°¹­İc°Ƿ˿ͷǼϼɳİ׭zcצzuɭuǿװ[oǚѷͿĦ¼˿ɳ¹zzټo¹ij˞೷˼ɹؚš˳u¹꿼­˷˹Ěiɷciu­ɖɖϼzɍǞz[ĪԿǿİ˰dzĪuǰ˒ªҿ٪ډǼiS[ozzª¹Ϧzͭz·oɢǞѭ͢Ŀu义ɼǍ­Ԟķ˿߷Ұ˭uSiu˦Ŀ¹ǚoĦžz˿Ͱuطٰɭuz˳ɰ¿˿˼oͿ޷İؿՖ­Ҟ¼ǿǢ·SSzioozuɰǹocoĚ¹ciǷǖǼɷͿ·Ī˦ǿªɖԦc–oٰф¼ĦޞuªզĿѹɳSSSϞuc[oǦͿiĹoiuzzҷ˼u߷հļͭ’ؼķͳɒi˭zԪɷɢĭ׼ǼٹǼܹ¼ǪǪ–K1[iԳz[Szǿziiĭ·˰զ·zǼ¹Ŀ˿ɭzuˢآzܹͭzc³İ򳳦Ǽ޼ɭªu9BzĹuzu͞ҿzcɿ˳ݿ°ѳ˖ijભժǚ¦٪ɿǭɹĿ³ĞļSKi°ĹzouzoizioĿ˭ɦѹi[cˢѼ͹ɿ՚Ѫzؿɿٷİ¢zzɳķռ٢¢[[iz¢ͦzooo˹iciioo[cļؿѰĚo[S9iܭؼٿ¦Ͱ٦uijϿĭ٪Ėou碍ܹމo[ǿooi[ouϳ¼Ѱ°˰c[uBBczžǹķªἰ㰍˿Ģ湞šz·–谀³³iªz¹ѳzzzz·ǪѰϢzϰiSucKcխǷĚܦҚuͼԿժϿǹ˞Ϫǰķou˳zªzuuu­ķǷĿҷ˪SuѪ9 oĪ߿ĿɖհǞz˰ϷڷϢĿ­ǿ٭Ⳗ¿ͳ[coªiučuijǿ·odzªioٳuB1u¢˼˼ͷ濢㿦Ԣļ¦ճѿۢĖعļ¹Ĺ˿Ϫ­šuB˭zzuuĪɹķž³cͷu9ªļԭšᰭ؀ɪķҰ͹ͦҿ¿zzɭתɭ1oˢBioϳuo˿ɹ˼˹iѷzKİҰɪڹͰϿžϰڷϼij߳¿ۿϹ·zcǹuiizzǷiuzScoɿ˰iҚ͢oiٿǷɷĦ㼢׹˳ϼɹǷϪ­ϰc˰ico¦uzSzzzǿzoѳϷzuouǦooĦ᷼׳˭ҭϳļҳⰄԦ·׹zoԼž¦¿Ƿozouzu[oԭozzu³ˢziziicououoicc³Ҧ¹Ī¹ǹҦ湰ļĚuͭٹz͖ooļ³cBiͭ˦oi[ĚuuɿͿii[KzS߹uiicS۳ɳϦհ͹dzš۳ļuؿ¢Ğcڭ[9ozc˭Ģo[њ·zuɰɹɖz¼ѭ[[cݢzozۭ˿ɹҦļݳͷijz޿㹖ϷҿozzKzouǷ͹zɉczzķռǼԿz[͖ך˹³ҿĿܪz³ǷԳ߭·uuBSĦɼͿ€iScǿͷ˰z㼒۪ɹzzѿǼټǦ¼ڳ˿ɹuzļͰͰB Kzzo͹uªucu¼ĿǷ¦ۢžɹɪѼ͹ǿϪžļݳզɳiu˿Ǎoc99ouɢu[[uuuɿi–cϹǿ˿Ƿz·װzɼzϚžҳ˿ǒݪ˷ĪˢĿiǖi[iz[[iiɢizͪzooѦo[oɿocSiijª͒Ѱu˭uĿҹ¹תķڢԷ¼ĿԳ­o˼o͢zu͹¹iioɰuozuoizooɼziiic[iz˿˳೉o˹oozuܿĿޢz³ݰ°͒ǖzuĿǭ㳦ͷzzci­¼šiɷzccKSǖooozoocucoui[ciodz°ئuϹioou°ǪĹ˭ɞĪⰉzcǿԷצ·zc[ϰ¹žzɳBoiuuuǦzzozSSĭzouuiuuuu°ķϚĢouzzճϰšԭ⿢ǿܳzķ­ijϳiǦªuuuzoǦooc[uuoizz[iĹoizzuiii˹¼ҍ¢طѼ­ۢɿ೚ĿϿѹžϹz[ϪouzǢ˷Ĺuo[[[Kii[ozzzuiiuϼ¿԰uoԒĢɚԹɰؼ¦ἚļĹĭuuªѢz[czͿϪuu˭uiiiiž°ScozzuzuooooiͿտҞuuզǭĪ˼զڼ¿ɳռ׳uɹĭɳcoɿizuKcɭͿ–¹o[izuɳijciuuuoɿzuuzuccͳѼĦݭǪݹuo˼ɷι°ݢǪϚļSoicuooooɦ¦oSozuu԰zozicuzz¼zzzuuzzɳɳɭԿuoizǿ¿ķ˹Ħڪݦ¹ڪuKuu³Ħuiĉļic˖zɼuzİuzuucoɳǹzķɼ˼uiooz¹ǿ¼¼ɼҪɄҒoo˼ǼScǰ׷oiļuiczzɉͿuuzozɿѳ¹·³ķzoiuzɪ԰ĚiͷĹ弖ؒͼ°ĭljozǭɷuKzzKBz[ɳiiuzcoizzzؼͿ³ǢǼѭzuiozҷǪϷĭɦѦݦdzɹɿiϰ׳Kˢzczuķcc9Sciªuo³ziioicu·˰ɰͪɼչuzzš͚ĭͦͰɰտͷļdz[ϷĭǞo’zz[zi–iju¢uuouzzzɷzɭ͹o׿dz˹ɭس԰Ǫ޷ɪ¢ѰǼ̹zҼo1KuuϿzozϷozİo҉ɹzzɷǍٰɭªu¦’˖Ī˹¼ܿ³ڦ¹ɭǼzoiu³o(Sczǭo[u’iozzͿǼ’uuzɰu˼zسͷ͞ǰoܹͦ԰ǦɹԹܿ¹˹ϿziİK(((9[cooz[Su¼zuzɼzzijoKoɼǒzuuu¢㼒ij۞ɷɚٿĭ׼°ķǭ‰z¿u9(991Bciciuzoo[¹¿zuuzz¹uǰucKcoϳĹuzooǭժˉ԰޿ҹķ·ɹɰదԳɒiǹi1(91(9[c[coziS9uziǼĢzuicioǹioĹ·o³ǰǹoziouĭת˞۷ǭɭѿ˳ɪĚҼحװiSǷշuB(((BKiiuzuuuѼļϿĿ­ķuo[z¦iczɿ˼·zѳɢzuz[zzǰ˭˦ɰ⼦˷צݳ¹۳ؿi͹Ǟoccuؿټ¼zҢo­uuĹǼijɚcczzuz·Ѽعͳ׷Ϲ³Գ˰ϼɳ׹oўͿɿɼԷǭǹ­Ģļ[zdzuɦ°oiǢzucSS[coo[izuoĿǼժϹͼļij۹˳uzĢǿĿͭ˹°ɼķǹ˳zucɹozǪi¦zzªcĭĢ[ziSuoiizzǹɼzٷ°­z˰ĪǦͦǹǿzcǭ·ǦzԳu911Bz¹³zuİݪcسcB[cǦuiii[uzǦuuǪuĹ˼ɪǿ°ĭڼķz۰ѿ԰S1(cͷoB1 (1(1zš[[9Ki°ǿǪi[SKuczioϼoѿicc[zؿzšܷ¦zǪϿϰϪɳ鿄ªĦz99ioK1119(19u³o(9(BciѷuozĞļBKiizcB[¦uuzzoSzɭziɼĹKuiožz˰ޭǷѪԿͰǿǹ·༪ļ³uK91KcSScK119B9(1ocuzc((B19cǞooKzϭccoiuizҿ¦cciǰǹiSĚɳݹǰǪĒҷǼͼĿҿooK1(1BBBKBiiouK( 9SouS((BB19uccSBiuiSSocuoĹҿuc[Ğzo[Ħz͹۹ǰռҹڷϼɿڿǰo¹cc[KSKKS[Kɪٷi1BScoB(9B911cz[[czKzS[uuSzzuͳ¼ļui[cǍziiu[ozķBSuzzouo9Bzu9B999BKK[ozϼ͚zuzc[[SSciiuucSSSSBKBB91199BBKK[[S[[oo[S[uiScccc[S[SSSozoiiccSS[c[ciiSc[[KBo­iBB[K[ϿĿ¿ǒĿ¹԰۹K9K9Koђɹz˼uzzSBSzuzoSKoK9999BKKĄuz¦izicccScc[cciKBSSKKBBB99999BBK[Kui[[ccB9izuooc[[ciiciiS[cS[[[[oScc[[c[SKK˚[SKcccڿĹcozչ㿀SB19Kiļ؀€z[ĿzѳҼɹKciKBBBBBSɞτ¹iuoci[[[c[KiouKBKKKK9BBKBB99BKSSBiucccSK[zzuiiouzo[[[SKKSSS[iii[S[[[SKcuKKKuozݹĚ[c[cuռڼzSB9Kuϳu¼ؿicҼͦKczcB9BBBKKizSى˳iiioc[cci[KizooiSSKBBBBKKBKBBBKSKBooc[[Bizooozuozzooicic[ccSB9SccSBSuSS[[ccBSKKcBuǦoK9oϹz[˪πKKuܿ׍·Ϧ[KK[ozB11(19BBB[SB9ى˷zcoocciicc[czu[o[SKBKBBKB9BBBBKSKKoocio[uSSS[S[[[[[c[SSS[[[SSKKccSKBuS[SSc[KBSKczĹKocoooKKͷzcšijǭɳԉSzҼ¼KiKK[zuB(11199BBB99Bzzo[ozooc[ii[iuc[z[SBBB9BK919KK9BKBouzczoc[[[SS[SKK[SBBS[SSKccKK[ccuzzc[[[[cS[cK[KiĉSiizzzuz˷iϼ͢Ҧ˒z˦­ooɀ1KizoB119119BBB91BuĢu[iiciiii[[oicoz[KKB19BB9BKBBBB9uoiiuu[SSKSSKB91(9BKS[SccSSS[uz[S[SS[ci[zS[SSuzԉ9oziuB[ǿoҖuټ¼šǚͪİ˹ҹɿi9[oucB11199BB991Bzuiǿuoioc[i[Scio[KKB9KSSK919BB9Kucuucu[B9KSK1 1199BKKSSciKKziSSSSKSiicK[SiczzS Bi߿[ijuu[iiɰɿĹǰɷiɷɼiB[co[K911199B91SzuǞzoooiouo[couuzz[KBKKBBBBBKSSKSuiziozzz[B9BKB1( (191BSSSS[[Kco[SSSSBSoSui[[So¿oKuzzuu[( [˚u¼ouzKKSz¼҄ҿϷ[ɼdzo9[[o[BB9999999SuuͭuzuouooizoKKKKKSS[KSS[[ozicoziiS1((9111 11919KSBKSKiuSKSS[Sci9cS9Bozž[ [uzzoozzS9([檹ij˹oϚuҖoiiKcǹ㼦ҿzi[ziu[¢oK[iz[BB11SoiKizuҼzuooiiiuuS[[SSS[[[S[[[zcciuoooK(((1((1 ((1(9B1KSKzSKSKKS[SBo[B1SuѰziozuzuzzzcSB9S깼˹K¿zzzۼoKccScǰԦz[cªϚcɞɭ[[[i[S[SKuuu͢uouuzzc[iuoi[[[KKioio[K[[ocoiioiizc911((9999911( 1BKSSzKSSKKK[Kzz[cKcuuɞuz[[zzzzSB1[Қϳoɰui˪o[icBBطҚuBǿɭɰͰK[c[zoizo͚ɍBiuoo[cSiuucKScciiiiciiozcKK9(9B[iui[[S9KSSKSc[uKSKB[S[iS[cciociǦ[u³iuizoڳiB9 z˭u¿ϼ³۳[iiK91ϼuϷǰɍҿKS[SzzzzްˍS˷uoic[­oiiKS[iioi[[cooc[SB9BScozucoui[[i[Bu[BKSc[[SiccKKiiSczuļcoz͖ziSKBBuĭ㰢ɷu³S˿SKK[˿Ǎ[ɳz9[[cuzzzzoozිiͦzu¿ωiu[[ocK[Sou[ioucSScic[[[[[cioooooiuoici͉KuiSKSS[[o[ccK9cuuzªiouuzozo[99S[SSzԍzzzǹoiϞSBc˹ɿǢoϷռzc(cciccoiu[KScԚociҼͿіiui[[c9S[[[ooi[KKS[c[S[ooiiiciii[ciuՍSioS9BK[oč[[S[KSuzĞzuS[iczS11BSSS[ͭz–zu[Kucz˰¿ˉzĚKBiuiKSi[ciiuzuzooi[͉Ϲ¼ǹɪ͹‰[zzcKcucSciic[KBK[[Sciooc[[[ccSSi[uB1BB[[cc[SK[z˭occSuuuiK91199BScz˦˞zouuuuzuܞ˹ouzķocioc[BScozuoz9uSiuzouoĦǞoiKzĒuou[cciuui[S[[[ouoi[[[ccSK[ǖcSii[uo199K([KB9Sczĭuoiui(BuuKBSK9( 19KK9[՞հĦziuczɿ氞ɰ˦i˷[icKS[[[ouuzuiucǀ¹°˞޳oScoiczi[[cuicic[[[KKKSoo9KS[[oi91(iSK[11BBSo͹Ͽiui1ic[99111119111 KͪzuǷo[ijzouҦǢ’˿ǚoɳπ[SSSSioiz³ѭžۚ͢uuuicccziiuoS[c[K[[S[SSSKB[KBKKKKiz[BBBBcK9ScKKczǭɭiuooc91 11BKiS999[cuzzoͼu[Ko˰oiouiϰ䦷ҭ’ѷڷSScS[SiĉzǭϿǷªҹziic[zocoucozuzo[SSKS[KKSKKKKouKKKKKBciSB1i[ScKSocB1KuĦɼcB91(199SuǞoi[zzǞ[oSSªucucScϿ˭čzіi׷uBicSKKz„cuuuuuuɹ׷ǹ˳oci[cooiiczoouucKSK[cc[[SK9K[KS[cSKSo[B9B[K9coKKScǦǹo19BKKSSK[zzzuǪ¦ico[žuuucz[[[׿ҪĿuouzz˹uԳ˞SSoi[S[­uĞcziciuĉ¿¿ۖui[u–zuoiɢczuuuocSKK[ciiccS9uuBB[[[[KSuiKBKS99[KBcĞ˰ǰ[ BKKS[o[Souuou³ou[cuǭuuicoo[cǼٿͪic[Ĺ˪„[couzi[czzoҪ˼ucouoԢiuuuuuuii[KSKco[c[KiKKSSKSKKicoz9B99BK9c˿ĞK(B[K9B[ocizɖzozoɿ[ucci¹iic[[cҷ갦[S³¹ԹK[uc[ucB[cizouѹ·u˼uuoԢSzo­uzzzzzzuzciuoSKKcoci[uc[[SSSS[Si[KB11KKK[չǪi9 Kc[K19Kcoo˼˳o[uzѿǖcc[oouizociicSф¹Ϧǚi[SǼo˰ªz[KicB[oozozǿoĪoɿzzuuѷuɼuuiioKK[ozuziii[SSccc[[ziBB9[[[cɰ˼K19[cKB99KuԿĦuzĿS[uoǿzzccic[iحտܢ°c[uuķzzKcuu–oɼczzzzªzǪzuuouzB[iuoziccizoioooKKBSiS[uͰǿ¿iji1BKKBB99BSǰzouz˿B[o¼oiiciuiizǭdz[ɦǭzouњKKzĪ[uz³zozz[Bci[czzuuzzozcKKKBS[[iĞS99( 191B[ɿuiz¿[oouǭǢzcioooĪҢ˪ĒiͰczizѭ[BzuozzuǦuuuouuķzijzzzuuuzo[c[ic[izuoK[zzKBKSSicBcɉo11((( 9oɰ[Si˼zǹSozij[[oi[czҦzѼɢcozcuicĹǦ[SuzzizzuĞuuuzǭuiozzuzzccoS[zc[ic[[KozcB(1KKic9[zǰz[9   ( ([ucĦoozu[KoɞǷiKiiuoooSioc[[iܭo˰ĢciѪzoo[K[ozu˿uuoעuɚɳ³ǰdzuucǚz[o[SKSSScuo[K19KBSKczǹªK(  (((1911BizuĹɭzɹBizuccuc[cciciuuϷɼScږ[uͦui[ouzzzzɷ⦄Ħ¢ɦo„SǪuBSK[SSo[cB9KBSBKuϼª¢oB1  Bc[B9BB9S¿Ǣ¦ϼǢKBco¿ooziuo[[icci[SİİuĚS1[uѿoǷѪѹzcǭͼѦؿǷ͞ɼ瀀ˉBKļoKK[SK[cSB 1BBKBKiǼҿioB9((KioiSKSiļɭ¿z(K¦zcouc[S[[cc[c·z˞S9Bi˖i·u³ǹἀu¹uzu­ؖɰoļ˰c㢉[9[uoiS[i[KocK((991BKSiozɢ[oB1(Sz¢ĞS9Kz¼ioui[[S[SScciu͖oͿKBouzu˷uoѳܰzuɭozĞϹ¿z°uǹڹɼi[[u[[ic[Sou[ccKBBKS11K[iocz˰o[9B[zuɰǹͼĿBoouĦͭz[[[SKSiiiuoͿĒK1’z·uuo°uɷ¦ڢcܿzԼ݉zoi[cociooiSco[SBBK[cB9K[[iiҪoziu9SzzocciiiuzzϷǰɭccoզzi[[[cioouiɹ˖BBzτͿϞuzɪSczͪϼԼذ׿zǚݢzuoic[iuuuuiciioui[BKS9BBBBSizziKBcKKKSS[[SSK[odzo­³zouucіzc[[ciuϷ[1z׼Ǽ͹¼oouɚعԷɭɍu٢uc[[cuzuocizziz9Ki[[ciiSB119c[oioz9cucB99KBKSSKKKB[oiKo˼ɪo¹zio‰czKzzi[Siuzz‰KSɍۼĞiĹɪɹzĄ¹Ͽž￉cSS[uzoioicii19KBKS919[ouzu[oSciKB99BKBSSSBBB9Scu[iҷҿ¹Buzooɳuoiuozc[oiuzucc͖[ScoՄĿˢSoɚҦzķzz췭Ϣizْu[[[oiiozoizS9BKS[o999Scoiu[oi 9K99B9B919199[zҪ¼˪Ī[9BiĿϰzciocii[ozoSčoǭiicoڹuĿuuķcKcu칞͚uzڳšzզucSccouoicK9KS[iiSKBBK[[zucoocKoSKcB9991(1999BSuzS[[co¼zzoi[zoouoc[zczĉ˳zioĭҿԹuzz¿˹K11cݼǿzϷɹoozuiiioS9BKScS1BSSzu9iiuziii[SooB([cBBK91199999K[iuuo¼uoucoziKozSucoSSžĞcouz˳ͭͳicķzɳuc(Bu߹ijzϭ·Ϫoc[o[B9BS[[[Kccuc[i[[[KSSSB99999B9B919KcouͷoiªizuBS[ozoiKczĭoBcozzošĦccuozcͼ¦Ǟ1ѭzzĢɖo[SzB9KS[[S[iouSo¢iicK9BBB999999919B9K[zoǷ’oz[ScicuoooǿBczuBoiuziǷzž[ziǹKؿ·oĀzҪiciS[cK[i[K[oKK˿³uuiocB999911191(119BKKoϒɭĦϷzuĢocu¹u[cuɖKKiouz[K[uiS¹İɷ˿ĭSzcǪSѳªzS۷iuۍњcKc[KKc[SczSiĞoiiocKBB991((9K1(9BBBK[Ѧɼ͢[oozuɉoocioǢ[iccicKSicci¼ĿĿҢcuozɿou๼cSԄzzzzoSBicSKSK[[uzɷuuKBKK999999KKBKSSBSciou’dzljKizzoi[uĿo1o[uicoiooiu¿ļ³iuzuªo(SciئļǪzooziozװ[[ci[SiBSi[[uzĹc9S[KS[coi[iic[KS9[zѰuu͹uKiuu„iuuizoSczczϖioc·zo˼K9KKoǭ¦ǼoަK[zԉcSSSSii9[i91Su°zSSiccuzzizcK9B9[zĿiioĞͪc[zuzͿoiuzozziou[ouijհožoooiɰu˳uBBB9iԹԼcouĭɒ[1BScS99S1999ou³ooucoiSciuiiuooo[B99BBouҹu͞iizzuoziBozzoiǹǞ[ooz[͞SBKBBS輳zݰ[u°ҷS1KccBBBKo([ucSciĹz[[[iSciiziK9BB9[uɭɞiSouuɦzzSiozu[·ziSiԿoǹϼz°[zuoɀBBB9Ku۹㰪ɹzziԍSiuҭucBBS[SKKSK1ooicǪz[KSioouoizuKBB9[˦°S9zzzuziSiSBBioѿ[KSiiϷijܪuͭuozz·Ϳ[BBKBcɹɢ¹İzoicªiiuSSco[1Bi1Koͷu9Kciii[czKBB[cǰǹĿѰ[9SհzicBo[zc9Suocc[iuzzϪc[KKico˰ۢѿoozͼ˿B9BKK⭪Ƿճ෼Ϳɿu[ϒ׭o[iicB Bz[(c°Ƿciicz[[ozz[ͷɹ˦B9i͢uSuuziS[zc[ciSzB[iK[o[[Sizˍz؞͹czijzKKBKi͢¿ݼzoSzͷ؍cS[K19BioK[ǿ¼cǹoouu[[cڰoǖKKzdzzzzKiu’z˭zuz‰SuzcSooSi[oioĢɰ˼ĢiuzcccSKϰԼzuo°͹iiucSB999oiKSo¿oSi³BuccuϞ͖ǿz[KĚoǭoiuSiuuªiKiozuKSouuĹljǷiicͳͦ°zu˿ڦuuKBcc[[cS 9uzcccoui9cozɢ°u³[Scωz–uczi[Scii[cco¿iK[coziioǞҿǪіczǹu°uզŰǦɀo[9BoiSczuK9So[iİuS[zo[SK[ucooiĪĞ1S˳cͳu[iucBSBKo[uooi[zui[zuoouuǼiǢ˼Ͽu[i˚uocccSKKczcBBii[zooKcizSiKKϹio[zSSzɷϿz(oͷizo˹uuoui[9B[ScSoİuuiz˷¼z¼cϿ¦ɼǦzčuɦoǭocuuoocSBScuoS9Ko[iiKS9iucicljiozSSi[zķɭcSuiizcccizuuu[KizzuS[zuzcuijڿi¹uzzķcǰ¦Īɚ˳zuĿ·šiizcSSKBScozzcK9izozB[ic9Szouu[oiSKz[SuĦSozzouuz[SS[ccciicǢoK[z[KzizzoooתuuɹխɷžϿѼĪucĿzѿǼž[zo[SKKKKSzuc[KSoouo[[B9iǷzzzocou[S[zuB[˷ɿSuozzǷzcSSKK[S[[KSĞo[SKoiu˷[z[o˦խɰizªoϿװɪªĭǭzuzz͹ɪoiz[[SSKKKuc[[[izuui¹iSKS˿cuccoouco޿ijzKuoѼucKKKKKSKKKKSªzoiz[ouiļuuϷi·Ģ˷ļǼ·¿ļzooiS[[[KBcS[cczuucSKSzcuuuoͷǭoKiuzϢSS[KKBKSKSBKSuucuuoiiioiocBSzԞiuǚѿɼǖozzuuɼ³ucSKKKBBi[ico¼SSSK[oS[ĭi[uzzuɪ[BբoSKBK[[[KKS[[KS[ǿ³S[cizuuzoiuzzSoǭic[c°ĹǷǼ–˚z¹uͿļzcSBSKBKuSic[uzİ¢[KSKSozz[KKSoKKcuzzzoiozǚKSϖuuucccSK[SS[KS[[cSiķ[o[[[ciDŽuɰocSKSoԼɼɚɼ°zzucSKSKKScoiBKoiuudzKKSKSuzoK991B[iiBB[uzzioioiozziuuϿBuĚiiucKKKSSSSSKSiSo¹zouo19[ѿuǦzuSB99Bu·ɖ˞zz˳ɳzzªzioicKSBSozSuKK[zuu¢[BKB9KzS919KKKKi[9BK[zzoiiii[KScczzozzɷzKuc[iuoiSKSKBSKKK[KoϼzcSooScoǷ[coziB9BB9Si°zuzzǷĞǼĪzĭzuͼz³ijucټKii[B9KuziS[Siiiu­o99B19Ko[9(KSSKKS9111[occuoooccuuoic[Si˷cBzuoKKScooSSSSSKKKK[SԷoozK[İK[uoc11SoiuĖc°ϿԿɹѷ͹˷oĦɼzտ[Bc[SKSucBSKKizuǚK99911KuiK9[[[KBB119KKouiocKziS[uoɞK[ucSSSccKKSSccc[ccS·iɼԼoiioKBKǍˢui޿ªɿ‰׿չ˹ѳiz¿zz[[[[cci[SKKcciuuĄ(11199[ooSKcc[BB991B[izuiSļlj[KSKcɿKcĪSuzoSK[ic[cccocciSS¼ǼǷuzSBuϳѭcu˦¹ճĚǿϹ¼ĪǷĢu˼zzuSB[oioucc[cocªS(9(( (czzuoS99119[zKKBBu¿zKuuzoz·u[SozoicciiiiBSɰ­z͹׿c91BѼ¢uԷ˰ɼɿĞǼšijzuiKK[oiScizzciioz991( 1czϼiB919K[ɼ­coS199B¼[SouzizoSuuoouo[ciϭĦzuտ۷ɢS9BzɭizϪԞ­ɷİķϼijتĿĭiǷoKKKK[[[[[o[[[oԼzB991(99BcļzS99SiijiB9B9BɿBcozziiSѭ˿oǢۼϚi9oķ[׹uͭԳouѿ˼ϹǿϹ˼˿zǼuiSKccB1Kcc[czc[[zܳ˿[(11((Suii˪ĭuc[oչĭǹcB91S¼u1iuuiS9ϰĦzݿԳ͖ziiioͼǹoطª˿˰ǹϿ͖³°ɼzucc[B9KcS9BK[ccciccuϖcu1 ((( i¦ɿϪϳo[z¿i[iuzzuziͳzzэcoѿԷĿuuSoǪiҳi˳zͦ˭˹·Ѧ¹z˿ѼuucSSKScS9Kc[BKBK[[S[uczuSou[zS( (  ijͳͰ˼ԢϰɼzzSizzuuz͢Ұoǹلuѭ¿ǚuҪco˦[iԹoϹdzɹ˿¢čѷzzĿic[[[[BB99iiKS[cSB19[cc[oi[zoBccooK91( iͦĪ·ϿϢ’ǿiczzzuzz°ϿѢz¿̈́uɹ͉ҭuĿ[oҼڿĭ˼·ͷͿS9ScccKBSKKiS9KKKS9([iccczzccoBzcB91((Bڹǭ·ɳ³z³uuuiouzu׷ѭšzѳzܹշo°iiռiĭ¼ɳĪԭɭĭzzccBK[i[SKK[[c[99BBKKSSiocczzcciioķS91(((SĚǞ˰uժͿɷ·zzuҳoϷžѷ԰¹˳uªco׿ĚտҼǷdzͳɼԿoSK(KKSBBBKS[oc11KBKSiucc[occoio³[91(( (˷ĭҼɳžͪǹĦuio¹cĹz˼ļͿڦǍɭ’ͳooͷu˿ҭɰ°Ī¦zǭijz91 BSS99(BSKS[1BKBKcci[ccooiKziK1( (i°ͪϼѷ˹ɳ³ooĹҿڼcİϰɰdziҰ’zѹiɪzi[SooouĦճҷļϼ¦˖cSS19B1111SSKSS[[K9SiSSczziuo[oiSB11(11ɳѷ¿ª¿iҹªuĚ­ij[i¹ǒouu͚uͭuuϦouuuoouzuiz¦ĭϳļϦ˷zooocK1 (9KSKSiuzuiSB[c[z[KS[cciiKK1((1S¦տ­˪Ĺɪ–­ioz[i’iiocԷziĿҹǹǰoĪuuզͰzuzu˹İǢѼi[zoB(1Sciuo[cuiKBK19oiKBB(( 1z·ªɚɷšԷzϷScؿSKK19ScټĿĢzzļļļ孪ǭiiuװǦuϰijͰ¼ĪScouzcBcouؼzSucc[KB9ucSB911( (S·԰¹ͷϼ͹ĿcScļuccS919Ku¿cuͷ¦ɦﭭļͿK[zͦzuԪѭ¼ķ[S[[[ziciizĢoocc[BBcBB11(((19ļǪª¹ڳ·Ĺ­ªuucoo[Ŀic[BBKcoiuiuѿšo[iuoSoªͼzcuzɢĚuzizzuui˪Ąɹ°zKSKKcĹciz˷zucicKi[B911(((9i¹ij¼͚iǢ˷uuzcuoKuɰoo[c[[zuiuعɖucSB[zicɼĖªªǦ͍[zu[ijdz˳°ķi[[KBzĹ·ooc[SSzuiKS9119Bcͪ­˪z°ɪuzzzoS[ǰ͞iuczijѿճɢuouzҹѼiuzizϳ¿Ғ˿׼z[[iSB¦c[SKBiĦzouoiocSSiuҳ˼ѹͰĹͼz[zczo[u˪ɍ[ii͹ͿǪɞzѿuךuuu’uzizɖcuuzҼҪɳɹi[S[K[Ǽdzoo˭oSSSuuooiciicuٿѳɷ˷o˼ǿ˚Koucouuziuİuciݭ¢Ͽ’Ѽϰ˿ͭͷǰcizzzuozط¦³o¿occ[[[z³S˚i[Kzuuo[SKKKKcooi˿¢šij³[ouooucuɷucϪ˷°ͿѼu˹˹˦ɢ[iuzzzzzչ˿­uSooc[Bi˰uicBzoSKKSKBBSoi[ҳϹ˭ɞǼ¿uizc[iuzBuoo῭cԼعǹѭ͹·uuuiozĞɿɹˢcK[zicKǢuĭoiSziiuuiccoziciucSzϿ°ͼijzĚǿuuiu[BoouzѢuͭĖļͪ͹zz¢İciouzizѿϹ˷տiKBSSouoc[zɷǪz[icuiicc[[ooiiic[[cczǼɹĪzѳǼuuuSSoǰɭciiǹ͞zˢzͳoooziѷǿչiͰo(K[cK9B11ScoiSu¹¢zi[cooiSKK[c[SS[B((BSǼϦǦɼɷzziKKoļo[SSoܭϿѭښzzoz¢uzªzzzuu¼¹ĭ·zK9KBB9KS[c[i[Sĭzljcuiiic[coo[B1(19119SSɰѿǰǹĪozooiKSiǼ–ocSSKĿijzuoou¿Ѧziǿuczuo¿Ǽo1BB1(9BBKcoizuo–oozu[ciccioSB((1((1119ɼ¿˷˭Ǽɹ¼i[io[i[Kciou˹ui[SKo¼ĪĪuziccuͪϷco°zcuuͷļǰ³uooi[B(( ( 1S[SuijoiiKScooci[ouzzc9BB(((1Kij¿ĭžǭzuzzozS[ucKiuuiļzic[[ciԿϞĪɿύoo[K9czݭĀouuiSoǭĞSB9BB99B(( (11Buķ[zuKKcizSozooSScSBB9uԿĹͪ¿­ocB[c9izɼͿucicSSSzĉǿ¼͉uu[B9Bzռϭoo[ooĪĿcBBK9B99S[cucBSBSiicB 1oǼ[ciooozzzzuoiuǷc[uicS[oui[uͭoĪͿĹķczoouKKcoɳoiiicS[dzĉ׹˭ѳi[SBB[zުĒuuzo[³­cSKBBSKB9BocBǭccciuzuzizoziB[c[uzicɳѼͼžɭzzuo[1B[[izٰzoiiKo­ɹiBuiBSKc¹߄uoui­zziSKB9KBKcziju˿uS[uuzuuuoozi[[iiSiuuoѿ˷ǰ˳·[uz[BSSc[c[չɳuicKͭɿϢu[[iKKKi­ccizǼ˼zc[KSSio¿SzͷiKioiocSSizzoicioioccozuѰĭ˼Կ·ɹizzi 1KKK[ccuǼĹzo[S[ͼ¹¼Լzui[BScҼozɭ[°dzo9K[KSzcͰzuu[KcicBBKSS[iuuouuicc[SSiiiѪzɰĢѼ¼Ͱ³oioz9 9KKK[o¿oiS[cտķ˞oiii[Ki߼ijuzzѼ¦z[K1cc1B³oi¢coiiiSiziuBSK99BK[c[[[[[[KBK[ciͪuzİɢǪši[BB9BK[cz¹°zicSK[ĦѳѼS[ooioĿ׷Ϳ˿ic˚Ǽ’ziiuicoSBz°Ŀzcuuo¼iuzSSKB99919KB9KKKSSB9Kcuu˼Ǧͷ˦ķouzz[[K99[iizɹ­u[[[uoɹuuiS[cccSz¼Ĺ˳izcuɚķɦoicScucczĦzzcc[cicoioS9KB999B99KB9B99BKSSSiuiͿ͹Ǣ˳ļuioSKKiuuϷo[[ͳĦouzic[KKioiK9KǿͼɞuczϿĿzҷļc[[[oĹ[ǿ¿ucBBB9SiouzzK9KBBB9BBKKKBB9999KSSiuuļǰ˼ռѦǹiuc[cS[SooϢiϦˢzcuzooiciocKKKcz­ĿiĿͼdzzzoͿi[BKuo[uzodzozo[9999czuuzS9KKBKBKKKBB9BBBB919Bcio¿Ħͭ˦zĪɞziKS[BKSozĖͼǪҭiK[ciizzoc99czйoɷĿǭucSBouzicǿzocS[SSBKucSSKKKBBBKKSBB9111(1Kcicǹzdzͷǭ³zϰzciSBSSKS[cҳܿؿǹucKK[cizi[[czu–o˼u[°z[SKuԭou³ļĖioSKczc[SczuSSKKBBKB1BS[S91K9BK911BSu¼Ϳ¢ؼ¼iiuziB[[SKKScϼoļoSKKSSci[uocǹcǰ¼׭c[¼۹Ğiωc[Sciooicic[[SKKK[icKSK[[[SccioKzz޹[coi[9KiK19KSSz[ccSļǷ[[ozooİ༖oooo[B1Bci[zoicS[ccciic[K9119BBKKKKKKBBBKKBխѷԿ­ªuiؿoiouoc[[[S[SKKSii[KKS[[SBBSzzBuuzciSSSi[9B[[K1iϦBKĹSuz³ݿzizzoɿocS9(BuuBz[BKSciiii[BBKBBKKKKKKKKBBKKB1հҹĹ³[iѪu[SSS[[cKBKBKSS[[[K9BioSžoܪccccoiBBc[19ǿϿzciKKcuzϢuҞcz¹Ĺo[[9((BzoB[BKccc[cc[KBKKKKKBKSSKBKKKB91῍ͿǪouo[iiԼzic[S[[c[999S[S[cSBBuzSi[ܷo[cccB 1B( (SϳuoKou19KuzzoizۼziziSͷɼzo˼cKKB1(1Kiǚoicc[SKKK919BSK[KBKBBB91۹ўizɹ–uuz–Siioc[Ǣuiic[S[cSKS[SKKSKBiuuzĀiS9( ((9iҦzz[SiuiSSuzSuuSKcuɿ·u˪Ǽi[cSB1(1(9[iuԦ¹uzoiouuoiciocSBBBB9B91³KoociK[izc[ɢuzuoocouiSzϼĹzuioi[S[cc[c[SKKB9[zzooҹ[K9[uĿ׷zizioociSK[SKci[idziݪļǼuc[SSK1((1(Koou[ܹzɳcKB999KSKڪ˹Ĺuizuo9uucϦoioĚcuocco˷ɚoooioSc[[SKKS[K9iiio[uڭScc­oijzozcSBiz[czSBScĭz(9cɿ¼zccSBK9911(1BB[cozo།i°Ƿ[SB9Kcoئ˿cSi߳cuSS[Sժoi[uucc[iɳϿ׹˦¿ozSi[[KKKKSK9ooBci[oz9i¼˳˪ziiuiouuzic[oǰĿ[1BKudzi[[couuc[S9(((( K[S[SoܷKǞzouo[SSS[׹ɼcB[­Ҧ[KziKBԳuS[KBuoccoٍizzicSSKSKKKic€K[[izˍiҼϪ۳ooiuco¹zc[uɿ¼oBBBKSzi[SBBKKSKB991( (( 9icco޹K9˼cSSKcؖijiĒiočB1oiSS9ªzSKSSKBĹަѪuzzucKS[K[[oo’iczϹѿĿĹչ߭cu[oļ¹uKBBBc[uz[SK91191111(  (( 9c91ϷzKBS梦¦iSzɍiKB91iuKKKBͷSBKKS[SSĹצSBSccKizzɚͼ¹ɼ͹­cu¿ozzuu[SBS[uociicKBKKKB1911(( 9‰iS խo[zozSKc쪦¦oKu–icKu99iz[S[SoĒ[KBKBS[[K[ǰ˷ؼўS1KocB[[uǹioϼĦuzSK((Sozcizuoo[S[KB1KuoSi[SKBKSSSK991((1  Bɉoc ɼuK[[91Kui[Sڪ˦zc9Biicioiz׷[9BKKKS[[S[¼ҭzui[KBS[BSSoϹ˿˿°i۷׿uuuzo[B(1(9[ozzzcSSK99KSSKB1(((SoiSKccBKKKSSKKBB91(1(K[BczĖiu°i[KKSiizocc·ǿucKouoiiiioiz۳[K99BKSSSSSBcҷ٭z[[[SSKKB9oɼ˿dziɷϿoSBK1 (9Sciouc[SB9((11(99(( SicSBBo[9K[SSSKBBBB91 ¦uڰuoozҹ¿oo˹uoª°ouo[ououiouiiuɰiB(1BB9911ɳђiK[[SKKBuɼļͼdzɷzععzS19( 1KSSco[K911( (( (9KcuiSKBczziB9BKKKSSBBBB9 uҷ°uiòuצϿ˦zzǞouϼSio·c[cuouiioiziǿ˼i919BB1Kѭĉ[SK[[cScͿĹ¹uu˹ɿšcKKB9( (1KKK9BScK9111( (11Kczuc[SSuoS91191999KKKB([Ǣ¦oэK٭zuѦiuĀo¦zcoɭucKci[uiz쿀z˞S9KBSc˖SسzzS[SK[icɷǷ˿Ϲijzo׳չzu[SK91((9KS[K119KS99B9((B[cSi[BioB119111111BBB9Bªİiu ݹτSҢԷuz[эuSzBcioۀ[[cczԪoSScoĚiuئziSSKKKi͹·uzļzͼozݿҳuoBSB11KS[c[[[[KKKSB99B91BuzSBzzK11111(((111191KdzռcK1޹ĖoĪذKKzSiScSi[K[ozܦo[uĪzoѿշz[SKS9Sɳuɪzoiɪoioҭɪ˿iuKBBBKSic[[SKScoSKBB9BB1izzzzcB911(1B9((1BBBK[iᚍ¼չSB氰oͿiBi[iciiKco༖˹iiS[ϿҦiSSS[SĪǷu͹uucuͭzccݹ’ԳozK[Scii[SSKB99[zKKBBKBSiuccSci99911B[cccoijoعǷcSזuĖSozzizziizuԷ­cBB9c¿ѦٿzzSSK[cɹ·˚[Kz͞ijiizϪͰԿzoic[SSKSB111(KuzKKKBB[iiiSioS[ioi³ͳɹԉo˹˭zozo[izϹ͢oK9Bzu°oSKS[cǰǦoĦѷiiܷɷocSSKKB91((1(9izziBBSķzuiuoz˹˼zϞzۦSBĹрSSi[iuܷسzKKSiioKi[[cSo°zi˿°Գozoo­ҼǰicSKSB911(991Bo[ozɹuoucčͿɿuϰ[cĹĿocS[izҳɷiKB[S[cSccɰoB­u°˪ucխdz˰c[oiK99BB91((BB9SzϿ͹uͼѪɞҰՄ[ǹǢic[ioڿݿس[91c׷€[cB[¼coo͹˳cɳKc޿ɦu9KcK119911((1KSSodz¼Ҽ¹Ēo„ouĄ˞z؞˭iu¿czĀu[Kocۦ9K͍ǷozSKBcķocS[[oijoKozzljzBϪڼiSK9BBB9((11BSS[zzļzϭϒczɍuǍ͚u؍ɰǭĢuiu¢[[iczziɍozciKcuzuoSSouooɢc׷˚³c[[SKBB911KciozĢǢϹij[¢zuϭ՞تɰǿǼļuSiuSzĉ[[izczuuuii˷ѿu·ǒ׹i[SS[c[K9Koozڿҭou˿Ϳc˷KijczǿҪتͷɳǪɦiKzKĹۢBozo·ɦz[cuc˿Ąz˼Ѧ˼[SKSSS[K[oooĖɳ˼zKҳĄĢǚͿ¦ԚϰĿϦuuioi[Ͱ˚1SozǷzɼicuo99Kuzo­ĪɿڷĢ˿SS9919Siɳuҹuǭiz԰ɪķͳ˖תϿcuzuzz[o׿طKoz¢z˳ĪozzciļǢϹĚuĹͭؿčKKKKKcɹɪѢi’ɳ¿ɞѭڰǹɉcuc[˷°щooo̳oļɢǖoԿԿ·SSouĹzuɢzǒuɉ’ͭĢϿ¦uSi[ǹ˿SooļĦuĪzճªɳi㿿ĪuĿǰ԰ijzuioĖcɚɢت˦ύou[iozuzǭuǷiǍuSBSuĪuSiͿѭocoǿ͞ǼooͪSzѹ˰oѰ׿ļĪciڼ߭ռ˭oǷu[šiKcuzzi[iuuo[co[KcKBSu߳˭z[1(iѿͿͳzķǰѿo€zǪzoz[iɒ޹Ħ˷zĪzo[¹iiui19KB9K[ccSKB1911Biļ˳S( zϿiۿǚc¹Ҫ¢u¿׷oɼiBcҀcz[iz˿Լ˿Ϟiu˦Ǣoѹ[·u9BB919BBBB99((1BBBoչǿu11iչɳİϼ[¹Ħ–c԰ɷͿociuzoz˞ͿۼijĄc°uzšzžizɚu˪zi1B1(9911((1((1cuS99uļu9ioϦɰϭͿѼuuoԦiǰѼɹuuuǀzzټխļϿ˼˳uoǦͰ¦uzǚciK99(1KB(((9919ioci׼oiuϳžϷšz˹ҳzzѰiǹ¹ͦĒzozcc­˷zuuc¼ǭ߰Ǣԭ‰iǢoc¢[ocicB91BK919BK[czɷuuzԼɍɪļϿzĢc¿€oܷio[[ɳz˿ɞĦuouݰSu㼹ķͪԼzķouoɿii͞ozz[ioKB99BSKKczؼzɭ€ĭ¢ɼͿz­Ϳ°uĿ¿uiѰܞ۹ϼᄉzҍiozؿѼܳԿzuuK[uİuɿzzSczɒuBiiB911Kioo͹oϹͰ͹ǹ¹¿KcѰϖђڹɳļzzzuuccuѪϹ۹عҷԚzi1Kzczķzz[[ĦocKi[9919oļ³z¼€šuǭǹɼ·ĿzĢĿˢ͍˒c˞[ѰĹzcc[z[ͳšڹļϦĹooSKii[ԿuozǭzS9SSScB91 uɰɷͼɍϦͼļͿķǰؿĿϿ㿹·[Ǽ[˹͹zSKcuؿϭo¦ڦ۹ǹªB 1o˳oiǿ[KB9(SiB( 9سɷǹĹ·ǭˢ¦ˢǰǷĹ¢İ͢˦щiuҿ˳[ǿoc[o׿¿ijͿ߰˰ĚzzտK9( iǹ[Sz˿z[B99((ic11(ٿijǹռªϳ˼¦oϿǿ°ɷ˒ɷ¼Ēĉc[˼icǷĹuuњ¹ѳ¢խǞǹĢoK[ҷzuBczSzͰucS91911KB1KKԼԿ˿Ϲž¼ǷªzĹǞɰتҷuտɖ[ռҞSǼɼ͹ǷScu¿͢۷շļ˭ԳoBcɞoĄ9KiɳouK[K9911Ko9S[zǷǭɰ˹¿uحͷ˭տĿļdzԒѿѢiu˼ؼczĹչɰ„рcou˼ǿɞ߷˼עͪKuѹoտoKSBS¹z[[[BBB99cu[S[i˿ɼǹķѰҷɼĪǿɷKoķuĹɀҷՉz˿ߦzϪϢķžo·淀uu¹ת޼İ˼žҭiɪuiĖc[uzzcSB9111[uiKSc¿¹ѿĭͷ԰¦ɹɰocİ˹ͷҭѼzǿްɹϷ˷–ooݦozչټئǷzzͼiozucKB11(1ic[oǹ³˹¿zšˢɢɿɼɰiS¼ɼļuɦǼ͍zտoĹǞհcou跒ioi[[ɰˉucuǦǷuuc[9ciKBK911cioiǼͿ¼zzĦ¼˿Ħi[Īǖ‰u¼zˢͼcu·׹෷תu¦czcހi[i[[[oǚoͿڹўocKzzĚoccذĖiKKKKS9BSB9[ccoǰɳϿ¼ĿzuϿɿǞͿǚ[9oĿij–¹ɉͿϦSu¹Ѱ˼͍˼cocĄSci[iuoioi[uǹؿ¹ճoioošuijoScצu[iS[cSBBB9KBBuzc[coͿͳij¿İuϦ¦ĞɖB[ɹ޿ǰɭĹi٦­ݭİĢ­Scoczzu[[[[iiK1 Bci¼ɿĹcižziuҰo9[uiSKBBBB9199K[[[zǰǼdz¿¼ͿǰĹ˞KKҢz˼˰˦uǹSzسշԍu[ou[[iǿ[[KK[K199SuzͪɢzϷϢuiK9K[[K9BB991(11Buzi[SռͼĢǼ¦ļǢǖizѭiSѹzѿǿˢoĞҖoɷתKij¹ռzzoiBcoǪB[SBBKBKKuǪĉɭzzoѿcSKKBK9199999BBB111B[c[SuǹǞĪǷļļz˳·ɄĿ°Ēz¿°žϿu҄i҄cԳҰͰuu[Szoo9iSBBKczuɿǿҦܭcɰǰzͳS9KBB11111(99BBB911Kcic[iɢǹĿǼzz¿³o˹ٰz¿э³˰˭ܼoټحKɼɷĪuͷzizuSSzcuKc[KBKzͳǷװͰͦǞuǦ[9999((991111991(1Kiuuc[ԹɹɿǿzİķǞǿϪ⦼ª¢žҿэҿz[ˢǢzc[izo[Su[oKS[SBo޳i³ϢzϿu’o[SK99919(1119111(SiiuiSu¼Ƿǿɼͪ¦ǼɷϼǪҒټzѪ­ͰoSzuo[KucizSS[So¿ٳzcuɢo[[¹ķuooiS9BSKKBB911((1BououiK­·z׷ǭĢ˷zՉѼͼٹ¼ϭ[oui[Kuc[oKcuۼz[coooozS³ҭi((1oķɰKzzui[[[[c[SBBB9BKcuuiiɼļ˿z˹¦zԢ[҉׷ݼܰzĿ·[o[SSoKuu[Ĺzouuic[oªciҭԦB(9KKcɼuuK[[ii[KKSK[iiuzzǼɷķϿͿuuՉoz¦ij҄iҼǍǖٳ͖[˳ɦczui[Sc[9ˉϼiǢuozzoi[oǰǦ[iѰҪiiuSBSļc[[S[S[ccioooiz[ǿ·ѭ¼˷˪o˭zuzͰª٭[uϹ˼ioǼzzo[[u[[͒iiuoicu­z[ѰoǪuuoBKo¹zozocSciiiuuuocuɳ˭ѷϞzozɹzɿu[ՍS˳ҼzͿio¹ɖzoKɼǪϢcc[[co[تoհªcKcǷzuuuicioiiiioտحͰؒzzucu­ͼɰխ͹ǹzܼzoѷuɖoz͹ĹɦզǞoSS[ouoiզѦuѿi[iozzc[ccccu³¿ķϳͷњzzoizoϹ͍oҳļ׼Ǽ͹‰·ɳ„¹­ĉzĖocozؼɞϷuK[uϼuzzuc[cc[zڿĿǭѷǞzzozԳɿ¢ļϷļɷѹz¼ɹuzɷzz°ui¢Ħiɷcccci˳zzcSiiczĦ³ĭ˳zo¢ªǰĹuSĹ·dzi­dzoĹɚķǪuSozSiczɷĚzozͦiizzcϷouoozocuҼݼҹ˚ĭoczuͦž­i˰Ğ[oɹijuoئķİ[ci[Kiװu[Ǽ[iuuͰzz[¹ݿijԭۿuzzoϿ¼¹ɿ˭zcuijuz˿uķĞijɳz[SB9[ϭտ[Ŀucuuzzҹcuuzļ°ڷİ·׼ĪҹǰĭBKzKuǭĹ³c¼ɢzǰؿ°˳zcB9KuĖ­ҹi[Ƿuouuzɖc[c[S[¼ҿݿɹ¦ڰļѰcSi˷oKi͚iji˿ĿϷcɼǼǿ‰ؒSSSu˳˳ϷɪSuouuoziico[K91Bͷ˼ǰǪҹ¼³῞¢i[¦K[ϰ[[ҳzİ­uiߦϳњS˿ĭĹcSzKc¢Ĺ·˭oo˼o[iuozuSBBB9K[oɒK99Kcoiuտצڿ³Ǽİ˳iuzĹzɰ9cĞciɚͰzǷǿ䷍ԖuĭˉKKKSzĹz׷žoiѷiiiciiS9B99991B[[ciB1(SzoozzuoioչˢǞɳ³ĿdzԼizĞٿ[Bo·Bc˷z͹iѿɰ˭ҪzحijԷzzuͷccת°zuoķշioc919111991BK99SK9B1iĦzoo˷ٳ³uܳɳǭڦzļԹBSտc[iĢiSͪ–BoܿҿռoķɷͿzϦSoɪļzoiK1199KKK999BB99B9BBzϼɿɷz¼ɪİuzҰ˿ǭĦͿ¼ļǪzѳuBiѹuoԿBcˢzBϳ¼ɼѦߚciҹܪKzǿĢĉ[zڳuzuc91BS[co[KKBB99199Koļɼĭĭi˳ͼټǿ׹ҳdzɿ׳uѼ’uzĚiͦSͦc׹cKϿҭϳǦݹuciݿװocSzcSԦzoouK (KciiocKSB9999BK[zdzzĿǍĿĭĪǿټռǹǼԭɪԚ͹zi·icĒo[’͖Ki˞ǭuǦ͹ĹɿuocBzϚuoooiuu¢Biǚoiķzcu[uzccc[ccicoKB9BKSSiɖuzzzǿªǿouϳ˼ѪİǭǼǼ­İ¿c[ԷBcڹSSiװuϼoSͿªĪ˰ǿicSKSўzccziuuzz‰9ٷ11zz[izozۿcc[icocc[[iccz³ǿǿoo¹ǹ³ؿɼ¼Ͽz°¹[cͳKuշKSšiuҢ³Ƿļ׼uiSS[ciǿicoz„iͪS 9cizǭzzi[[SSSiui[cooǼuɰoS͹Ŀİ˹ǷǼ·Ϲzɼ·¢oiuɷcoɰ[i˦oܼɷzԹ˿ҹҪi[[[[[[cѳoo¢zعcSi[1Bcccuzi[SKKB[oc[czozzoϞ¦˼ѹķɷͷͿ[uҿSǢciչǪɪҳϼ޼iBKScuzzϿuճuoͭuu³K1 1czo[[B999coc[iuzuzuužͷz׼ҼĭĹϹļciͭu9č[Sˢ巚ҢǷ׿uK[uǦͰuuzo¹oKªz°o9(1Bҷzouo[[9119ozi[ozooϳͿucoѷzuɼǿ׷°Ҽ³ožcKѷ9[۰ĭɪ˼ͷطuiܭǒ۹zuzzĭɢoİcc۷oSK[oicѦKcS[c[S919Szi[zoķĭzɦužuciҿ˰ѹ˿ɹ¢Ѽ¼zѼBoϰ([τͷ˿ɿ¼¿Լ׿zz׭ٳozoĪɼ͒zoB԰ļziSz[Kco[SuKc[[[B99Kouiicǹɹ¦uz·ɼuĚªǷ¢͹uu˷SBǭcKuԳu¼ļǹ˼ռoϰuԹĒ٭o1ǭzɞoKS¿uc9(Bio[Bczi[SB119[zocozuѷuozuzǹuտؿϹ׹ɼļϷouټBSªcScͷ˿˳ɼ·[oѼϞ˦ѹ׭uoݼzͷucuz[czo[B1K[[KK11(Bii[oouuzzzĭuzocɞuz[–ݹļǷ¦uu԰9o˰[[i¼ɼž¢͹oǰͿciؼǚܷuzذcuSucB91BB91B911Kuz[iouzuzǿo[ocѹBK˷˹׳ϳڿoҼcɦzSݖ¼¦·ļͿˉ[oҿҼߞoooѭɞ°¦zڒSiiBzϦͭzzczɳͼuoK9B9B1((1119iuzu[zziozzɳzz³ccuocĹcSBcٿҳԭdzɼؼĪǿ˼i[˦Է³ɿɼϪc[cĚحiuoϷɿњ¿uu[[K9¦˪zoǿooSKSSKBB1 (9KouooiuuzoiouuĞzoi³z[[K[ɢzi[oϷϷͿɼdzĭ׷ĢzzļɳɢzļuczzzĪļĿooiªϪzzzɼ͹ǢږiS[KK޷ϼuczzicBKKSS[SB19Soo[cciuĭuuiiz¼uS[ocSuzɼcdzǹ͹ǰijǭiiѰ³zocu[uuo˰Ǧzzo˪°šϪi[Siiڦڭ[SªooiccBBKKSSSB9Suzicoocuuzzzu[[u·uoiozc¼榰ļɭ¼’uݼ¿dz˪ɪuuuo³ǍoKKK[՚ͪo[ĹiuiuK[cK9BB99999SzczzoĹiizucSz¿u[oij³ئļͰɳϭ¢[ɰͷѿuououoҿժت1111z͢Ϫi˹uoS19[SK9999999BououzuzioϹ°iiuozzi[iiͰ[SzǦK19KoǼշɿij˞ɢzoiczo[iڹoǷĞԉKKK9oªǪoɹSSS9KS1((((9B9B[zczozzouzǭɷz[coiiK1B911KϷ˰Ǽ¹Ԫi[couiKǚڼі­oc[BcuٹoiɼuKK[BB99991(11 (oouǰϳuioucuǞuzuiui9[cB111SªİǿǼҹļǹ³DŽzcciui[cݳˉɢͰoi[Bշzzuiǹo[SSB19BB91199(Kzz¦ļɳoo[cuzǭc[uuScc9BKBB[ouǿۭμ˼ĿǼͭҷѳcSuiui[izĭ°ˢi[oҳzǞuzozoK9BB19911(199KzziuĿuz˦oicooziuziiuBKSBBuucScouuǰǪ˿ļ¿ļͿ˷Īչo[uɭڳčǍuiSǍԳcǦuc°i9BBBB91((19BBco[¿uiz°oĹļooozoz919K[ziiiucS¹㹦¼ɷ˼¼¿¿ͿˢњͰ۳ҦĪǚҦiic9ͼͦu9izҼ[(11(111((9BK[uuico°ziĹzoļɳiozziK(KKiiuS[[Koۼ¹ɰzo¿¹Է¿ٰҿؚǿĢسuǰz[[cKžšu1(9Siİzc1(19(  19B[ozzuoiĚou¢zuuİuoiuu919Scioǚu11[SBBz׹ɰ[[KKi¼–ļҼڰǞĄc[BKi–շǖ[B9 KuB  1( (9BSoiiooi[iz˷uzzuuuzi’uiioB(9(zǚu[BcuuK9iǹ˷9K9999[zĿǿĹɄii޹ĪdzĢܿcc[B[zͪ٭ccccB9 BoB( (1(( (9K[zzuiiuozuozļzozzzziiɞzuuS91 1K˳ozu[S[Ͽǹzc[99SzĹ¿ĿĚiiѢɷͷɰ[ic[uѳ՞zuioBScB(((1(((9Soiiuzoɦouĭuuzuocijzo9(11KuͪͳzuiSSioǷٰouoouioݦozҿɹԳuc[cccuoͳɢKocB9(111(((Boc[ouuzuzoozooo( (9[ozѭu°uoouSzĹǰڷcozzuuoozuu¦İǹɿBzoٳoiS[[S[B9ɷ˹c[B((((((9B[ucuo°uuzzǿouzuK1 119BKoͦzɳoiu³ǰzͿϷҳiǦoozzz¿ǒcǹ¼uzBS[SKSBS˼Ѫou9( (11(Siii¼zªouiuizĢuzuizccB(9[iciǿɪļzz[¹ij·˳cϳǿ¦Ě׹ϰicoўҹzzoiK[[SSooiѼҞi[uc(((11Soizuuzzzϳzocziizѷuczuui[oS9SSĭ°czdzzѦĪչ׼ͪڳǿ·ccǦǰ՚iuzicu[S[[zKɞcouiK ( 19Kcozouoz˳zozuzǷzuciu[cS 9cc­izu€izĹ˰Ͱ͢ѭͪآǿi­İҳ¼ɖiϿc¦zucͪzdzɭocoļɼĢ’˿ؒuϿziiio[uѼͿͼccڼɳϼ·ҳɞuۼͷuicccc[[İuudzɷuiz³ɹǹ­Ѫ˳cϳҼuc[cccS[cժuiuuª¦oui¿ѼĿ¿ϰĢiտzocc[SSKScĭউuuɰĞzczz¿¼ϼĹļ¿ɦϿ[o˿iccSSSS[[SuǼުz·ͼİooc9[ķͳɰļѹѰc­o[[[SSS[ccuҿǷԦǰİiou[KKKzԷĿ·Ğcz·zcSSKKS[izͼ¹˷Ĺzic[KKSi᰷¿¿¼ª˹i·uio·İ˹oiSKKKS[ļǹϼͳziǿļѹ˼zzSSSS[[coԿԼɳĚiozǼ¿¿³ѼucKK[[[Kc˹˿¿ɼϷcozzz¿¼·¹˿ϭucS[c[[[Si¼Ϳ¿Ǫuczķ¢zzi[Sci[볼·ɪҿoo·Լo[iuϿ¿˰¹˿iuzļ³uucuz·ҿǿѿ[zuzɷziiuzķ¹ͭo[zzuu·zouzuoɳ˿Ė[ozzz¹Ϲǰ򖰚zuzuİɿ¹ǹѹcozzz˹ǭɿ˼ļ˹ɪou°ļǿɦoozzzɷϳijļɷiuĹɼؼªļķϿiuzzzѹ¼ķǿuuİٚĿݼǿϼouͷzuzͼķ¹Թiou޹ocoɹǿ¹ͦii‰uz˷ĦϼĿc˷ɭziiuuzķļ‰iuzzɪ··ļϖͼͰiuչɞoi[Ko·¿Ǣc[ͭijǼ¹آǪoouzؿ˹[zɿǼ·ĿϿ[zͷǿĪ·͞ѿiicڹ˚¿ĿĹǼ¿ǼͿ˳iͷĭǼ͹ijՉ[iozϹռļĹ¹¿¿¹Ǽ˰ocϹγǹɰcKSo¼Լ³Ŀ˿ɷĚĒizzzɹͭǷǰo[[cǹǿϳ¿ɿ˿˹ˢɳu[zzzѼzϹ¼ijDŽ[Sc·¿dzǹɳǚ[iijzǪzͿݷšBK[ҿ°˹ҿKoĹzzɷzuķǼͳĪǿKKScԿ¹ļǿԹuS˳z­³’˦oSSi·Ǽ¿¼¼ɦuoz˹uɰ¼¹Ҫu[ScɼİǿǼ¿ĦžouzuǭͿǼٷް[[iļ˳¹Ǽ¿ǞͿcuѼuĦǷצ⿪[ouɹҿ·ɿ¼ɹǦiuz¼ijİ˳׳ɞcuuijij͹¹ǰԿczzuzͳͭϼѿɼѹ˒Ģczz˷ǷĿ­ɪucuoϹoɼ¹ɹѹͷzɷǷϼĭǚiuҿ¹oĦɰdzͿտͷozҳ·¼ϼĿǭͷoǭi°Ǧ׼Īu­uzzɹķ¿¿͹Ŀ˭zu˷z¼ͼҪۼǹuc–oiϹǪ·¿ͷž˞uzǭǼĭ׿¹coc԰ª¿Ǫo͹ɹѦ޿հؚ¢zzš··¼ԿϰϿɰ߹ୢǷꖍSc¿ɰ­¼Ŀ˷uzĭª˳ύͿzcBiҭĦǿĿɳocԳͼϹמ°쀀oo[KzϹϹĿ¿¿Īǹ­ͷآĭ199Ko[ž·¿͹ǪdzªἍļ91SuiǿǼǼǷǪǭϪѿBKi͹[[zǿĿ¹ɼǼuoɳoԦ˹oۿi[Sؼi[oǿ˹Ŀǿ°[[ozڢɷ’ѹS(BؿͿu[uļɿǿ¼¼˷uioݪ˹˷KBǞoczɼ°ǿ¹˹[iĢϭzziͿǿ¿¿ɿ¿ļ˷c[zuѷǭލ׿Ԫcc¼˰¼¼ļ¢u[uzzz˹­׷zic¼ϷĿ¿ļĿ˼ǪczzzzzuzڿͼǰzԪii׼°ͼĿĦ˳cuuuzuzzzѼ¢zǚԭzzKoѹ¿°ļ¼չϳ[zuuuzzuuϳ˼͚Ǣ٪͒Sΰ˼ҷϹczzzzuuz·Ԫǭ٭(zĿz˰¿İ¼ѼͪϷiuzzzzzuzzϼ³؍ɰˢі[ϰ˹ķǹĿǿɳĚԳizzuuuouuzzzɿǼԉǼocuɰǞuϿĿ˷ijĿɿѷɢzouuuuzzzzzzzzzuɢɷڦٹؖz’ϳz¿Ƿ˷dzϳ͞ziuuuuzzzzzuuuuuucioiİ߿Īڷˉۦoizɢǚoǹǿɼɹͼ‰zԼuuuuzzuzzouuuzuuǞǿͿطܪzuuͳz¿ɳɼ·˷ѹҢczzzzzzzzzuuuuuuoϒzת㳄ooǒoļªɿǼǪͦĀozzzuzzzzuzuuuuzzzzuǰѼķ˰ͷzuɼuɳ­ĹªĚiҳzzozzuuozzzzzuzuouuzĿ˰ljuɼɼ¿ǰuoǹϷu˖uzzzzzuzzuuzuuuuzzuuzɿ¹dzɦɭǒ[zǿdzİĹi iĿϪiտuzzuzzuuuzzuuuuuuoouz¼ijͦǷհɿͿ⢄i[ɿļ¼z1cˉcϚozuzzuuuzzzzouuuuuoouzĿѿļ˿¢ԼǭSǿĖKͼ¹ԳozzouzzzuzzzouzuzozouooozzoѹԳĢͼǰoɹ˰cuĿ°͚cѢizuuuuuzzzzouioiuuzzzuɿ˿Ģ˷˼ݿ҄¿uĿdzҹzzѼzuzzuzzuuzzuoououzzzzuzɿ°¿ɳ׿°ذ۷[oǿ˼ԭiҳzzuuzzuzzzuzzuiiioouziiuou˼·³˿ͷ͚zczSɿ°ϒiϚuzuzzzuuzzzzzzoiuuozzoiozzuiɹ¿¹ǰɹoKuγco¼ķԹzčuouuzzzzuuuzzzuiiouuuoooiozzc¹¹˿couz˿c¿˞zҦzuuzzuouuuzuzzzzouzuooouzzuoĿĹ¼¼ijozoǼɹSoļ·Ҽzĉuuuuzzzuouuzzuzuiouzzoou¿˼ǿѷ·˼ɼcSǼ¿͢uխuuuuzzzuuoucozzzzu¿˷·ǹ˳9oĿ¿Ϲ͖oiiiiiz¹ǿĹ¼³ɹɿdzc[¹˭zҰiiooioiuz¿Ǽz³³ijǼĪiu˿Ģ˚uouiioizzzļĿ¿ǰټĿĹocļ˹Կuooououzuz¼³Կᷰɼǿķ¼Ŀ[ͿǭϞĿzoiououuiu˼ɹ߼Կ°ļϿciķǞԿǿuoouzooouzzzĹķǼ¹ѹļšiĹϼϦɼzzuzzuuouzuou·¹ķԼϿļķzcǼ˪ǒ·zzuzzǿɼɭͳɷͳĿKuϼĞѳķzzzzz¿ĖɪĭĹɪѿɿ¿Kcķ˹˿˞¼zzzzz¿¿ļɰɿ㹰ǿ¿SѿϷռšzuzuļˢĢ׿¼ǿ¿¼ziuǼɹϦšzzzz­ϿϦ·ļ·Sz¼Ǽ˹Ŀ˹uu¼žzu˹ǖܳ¼ǿioɹǞ³ĿǹǼժͳɿڪ˿uĿ¿˭cҿzҹǷ˼Ұ˪Ҫoc¼İczտ¹Ϲɼ˹׭­ճ¼oii¼¿Ͱu[ͿĿzͰ¿͹Ŀٚ¢°˼uzco¿¿շzK[͹zҿ¿¼ǭ¼Ěɹǰuuic¿¿¼˪cBuuؿ͞¿¿ļՒijϼiizĿ¼տ³o9SzcǼϷzuϿǿĿعuzɿܰ͹ooĿ¼¿¿խKBzzizªzѦ¹ҭozǞదϳ[i¼¿ļ¹ժ[ooS˷zuzzԿǿ¿۳uǭٹSio¿¿Ŀ­ioc[ǿ¿Ƿzzzz˪¿Ŀ譀zɼcocĿĿ¿ǿ¿ǢziªϹuuouuzzǢɹ¿ɒz˦oouzz¿¿ǹķİuuuuzuzuuuzĪ͹Ŀ¼Ңš˹zͷzz¿¿¿¿³zǷzuuz¼Ǫ¹¼Ŀ¿ѢݳuǪ‰oi¼ɼzǼuuzzzzķ·ͼ·¿¹ϞǪ͢uiio[¿¹ķzzzuuɷͰ¿עϞѭ˹ǭciuuoz¼¿o˼zzuzzzz¿ijĞĿ٦۪ܪĪ[ouiiǿĹİzzzzz¼Ϸѹ¼ļԷܰɖu˭ooiioi[uĿ¹˿zzzzuzuzzz¹¿ɳͦ¿ɳ¿Ҫ߰ࢄudz[i[ǿ¿³zzzzuuzzzĹ¼¹­ѿ˿dz¿Ǣܢ䳒zǼ꒞·ͿĞɰҳijǰͿĹǹټĪׄĿu[ioiS1[ٷϖi9cSK1 1(9KK99Sz¹SozcozuzԼ¹zo[KcczuBSzĚĦĦoɼٿͰ˰Ϸտ¼㦉ɹzªiouS9­iu9oc91((( 1SK1([Ǽϼccouϼuzicoz[iouS[ɍˍzɷuĢu·ҳͿ㿳Գǹռİuɒziuuzoڭzzzo9cuK((KozK9911Kķ¼˷o[z˳uĿɹuĿuzǷѦĦz۹¿oɞ˿·ijɞ㼷ϼijǹ¼dzǪzzczǚiz(9K1 (cS111KªķžuuǍϪǦ٭ͦɖijԢǹǢѳݹ῰ɿު³uѢiK ( zۄ9(1Bǹ˹zoǿĹ˼¹׿¦ڿ³զİzuϒǼɿͿ㹹ǰ๚˷°ucK 9uհS99oǼѷz[ĿǰzuoBuĪzioozzϭͳɭۭǢuuԞ˼Ēڿ¼ɿ°рizǹzǹժB[ˀoͦB1KcɭĿzKzoҿSuu[ScSKB[ccuczzzzzucҰªݳɦշ¼ܷɦҷķ­ڰdzzczuzǷi119iiocuzzozɪiioKBS[S[SKBSc[[9BcǹǦzɼɳٿԭǚɳ͢ɳĹ˼ؼզ˭ԳͰϳ޷˼c[cciuoɉB91KuB((Sozu¦zٷǭo[[SK99KSKBSSKSSBBSSKiu͹¿ܷªԖڦuϹĦĪڿǹɭ¹ڼ¦Ὺ˚͞¦oSiԢzٿi9(1((((9S[[c[izĹĢo[KBB1 (9999BBBKKKKKSK1(  (BuoiɪɳɞǞ࿀ǰϿԪǪѭ˼¹ɿѹͦdzcz˷iiؖɉi111(999( 1BS[ccuuco­cicB((( 1911 (9(1KB(11 (((   1BSo[ioķĢϪѼɳzѢžzˢɿ׳ͭѳͼͦɹπ˼c9˳zuoSBciǞzzB11B9991919Sc[icS[cciczzziKSi[cz[1 (919919((1(19(  11  ((  (B[[KSuoSSɹ˭˼Ҫ簍Ģu۷İ˿ķͷļ¿·ϰۉucouuļo( 1oɼozհuSB9999B9(9B9KS[c[cuzc[ii[ioSccS[K(1BB9119919999(  (1     SoSKozcS˰ɿװװ͉İɭĿǼǼ۰͹۪[­ou izǰzzzĀS111991((1 (KBKSccS[iczioii9czS1(1119999991(11( (   (  9K((Sooiªļ­ڳĖzͰĹɿǰҹ˭˿عԀķzzuozi(BcizzɖǍz[ioB91(9111 1S[iKKKSuciicSKoc919991BBB9B91191  ((( ((((  Si[¦¼ڿไǚ˳ĹǼɼطĦ߹ǼzuSKcczu[תzzϖמcB9B91119B9K9[iiiSS9[[[B((111991999911(1( (( 1( ((991((1991999B9  19(˳ѰչտĪǰɰ·­·ǹijɪijo 9iouziuKͳzz„c991BB9( czic9KBBS991(9119B9999111((9(BBKKouuiiK[SB[[i[cS9(( (( ѪԳԹٹ᳦˿ԚݿǪǢɿdz[c Szoךcˉuzzzi99K[KBB99[i[K1(B9((119B9199KKBBB11199[oo[[couS911((  ߳ڹ¹ҷǪĦ˿ˢѷݭɢϷ[cBuuuzĹǖіcoo ziB91B1991 ((199 999BB991(BSoui[zouzcB(1( ɦ·Ĺ­ў¦Ƿ๢ɦේuzĦoc1 1ozouKoķ墖iuiͷͦKioz[K91991(((( 99B9B9B9BocKBBS1 9[ozu[SSK1 ((1(ķ˿ɪuĒĦİ·ǭ¿ǼǀעS°c[ɳ9 cuo9cĹozؼzicu[KB91(199919BB99Scoo[BS[[[uɳu(KKB99[ziB1911˭Ͽѭuͦئ˿z٭ݿ˦՚ѰucK˼S9B[cB 1cu( ooczܦzcciizouo[SSKKKcii[ozi[coz[SzzuuSSSc¼iSB1ܦ˼ϦԳͼ༒ѷǼɚɼoSuoǿzB  BuzK 1iiSoiĖ[u[SKScuo[icoS˄o[cScoњɿɦ˹˿͹SĭĹɭǿĿ¢zu( Sz1  ioicuްSKSzcoªԹizoBBSSiucco؞[[B91SڿɼҼҰϚ­ɞļϿ۹ǭzzzozii1 (SuK 9izuǷĖuS1uҪĿBSoooozzzu˹ͪzuo[B9Bo­ǚݰ˭ͿѷҷĪͭݹͼouzzuzi[ (izzzijziBK–ҳz9c[c[zoicii¿¢cKKoooطɪɦߢҿ⼰ĦݦĹİĭǹĢĪuzK(  9u9 KѷϿiBBKiѳ°zSBuuzzizļu·o[iouoݹɪզɢ¢ϳİ޿ɦѭzzzo1 c  KKcѳǿcKoǰozͼoBzzo[ǹuzozǞ޼ͦԢԼzĞǹǷ¿ϼzͼzzuz 9i9 uzǭziҰĿuiKui[uooĦǿ¿͢շϭճ幚ϼҷ˼չijuoɭļouz K9 (o¿ɿ¢cijDŽuSouBiķuKuu˷³˼Գͪ¹ǰ°ڿްļ¹˳˿ժ³zzcizzzc  1cǷzªҭzKuucļϭķķ٦Ͽͷټ°ɳ޳ǷҹĹucKzzuz 1iouǹzİiš˳uKuuuzucozϿzԷͪ˷깖˼ϼžͳij¼Ŀݷ·zzuui [zϳK1z˷Ēo¦ժc9uzzoouɞİ˒ǹǪᰉɢϭϷķĿǼǷ͖ijzzi  Bzzzu S͖dzoіͦiuzz[[uuoKKSzzKzɞ˹ϭ˪ҼĚԹҼɚṚϷݿǰܷϼui 99 9iu[Kҹi9czĒoמ¿zu(ccic[zu(o¼Ϸ¿ѹijz׿ͿɢݰuϿҢح°oz(KoB oo  cĭS(9ccɰiªļ°¼o1oic9uzͷ–׹ĭ³ĦҷɳǢୀzz11o1 o( ·ͳ( SzozϹĒu˪͢i[[[S[˪ziͭzoɹϰ׭շǼ۪ɒoouB  cB Kci[(uɹǞB9Siuzؿ͹ǚ€9io[c[ozuϦ·°ժǭiɰ׳ܿķuiu9 [u[   KɳͿB KuizѼǒiĪĪɿz1Ki[iSSuzz͖ɷ͹ͳ·¼˭޳۷ǼɷzuǢzuǼۼǼuĞzzKuuzK(  հ˚BBi˰ͦİu€oͳuBB[Szuu˦Կ°տϦķĪἳ˼ɼzuǦϿǹ[չB1z z׭B 1SiuĿǒuѢ[ˢzuKoizczuϿdz˚Ѣ˼ϭ͹ɼļ淪ܳ·uSuɷļoKiuzoǿi  9Kiɼ°zɪiBoĿ¼·ĭĿҚԚ¿zհԿķiݭzɦuzצ۰ǿc­ou[1( (SS1 9KcoϢĪSҰuuuziBoz·İĿԳǦϪԿɹizۦɦĪ[˼uiǰociխ ui Ku˰–ouzziuK9coKĹİdzoܼ­Թǿ˿u³ǹuciǹSo¦uoczzu߀ cǍ1 o³žucz[ouKc³o[ij³ǖ٭ɼٞɷչѿoҪu˿iuiSijiozuzi[Ģizz 9ǢͼS(1uѼ˭ciziİciuzuz¼ĒizɷzբɰǿͿ·iɞu˼z[9oĞ[iioozcuĹ¢ui˪ui1 oİǿouoozzcScccic׹ͿoK³շշ¼ǿݿ¹͹ižuiiĢz’czozzooicİ9(ij–  BouBKzuuĢoK[¦zuiuiii˪˿oĿѷɦǿ°ͼͿ߿zuuzǼǒiuiozuuiİ¢K[³Ͱ[·c (oiͼĿzuKKzziu[oķɰĹ¿Ğҷ͢Ҧzc[ɉSuuzzzziɼzK S1 zǿi Su˹¦cuz[u·Ko˼uiĭ˹zǷǹ˼cҢ¼ԒڦzoczѪ[o¼zoci°uoB(czS czc( (uBoɢžS[ozijoB˪dz˭ڼ·¼šⰰͼĭݦzzccciǦ°ic¼iK1c[ KzS 1cS Kzªɿ[Suuz°uc[KͰĿzԦ԰¼¿Ǽ¼Ǣ˰Ҽͭizi[iidzɷoKϪzzzcuž·K[99i 1[‰uuu¦u[[ozzi[zoĹuĀ9oגԷǷĿǿ˭෷չzuuu͹ɼɰiSɦzzuzͰ՚9 [ (Ki((Siz͹z³ucuzoiziɼoSճݪļǦo迷ˢԖzuͼuKɿozͷoozzB 9¼K   z¼¦zcc[SuuczuziczϿiļ氉³չؼ¼ѷu¿չͪު[ͷiij„zzz9Bu¼ϭ9 Kϭªǭ[KSiouooui[uoiiԹuzuͼĪ䳦ij¼ĚzѹԹǞҭiɳμĖ˷š9(ɰS KoͰuoĹuKKozzi[[KBizicuoz˼Ğ˰բ˿¼¦Ěɹ˷ɞ˿ĹĢҰuoϪu  Koٿ°[Koziu¼ĢccoK[ouzuuǦoo¿zu˼ɦ¼ǹļ˿˚ĭϼĿ°ļ͞uouɿB  9z҉°ĉ1Suiٹɳi[uoouB[Ħii˿uoٿciɍdz׿ɼͿ߼͹uɢǪͳǿ³˦oio(9  [B ScњɉziKucBdzcoԼͷ„[uzž¹Ǫ·޳ǿoԼޭϹɭ°¿¿uoSi9 1ci Sdzi cǹͪuzu9(cuzǷɿ·iĪ˿˪³ɼi[ɚ˚׳ѿ¼¿o KzK9K 9uɖ¿uouzciuzKĪi¼Ŀoͼ˳ϭucoĿ˭ҼϰĹɰij¿ϹB ii  [9 9ooɭz¿oouuo°žǼi[ǿĪi¹¿˿ئ¦o˹ɿےcuѭdzǞǰϦǰ·¼ǞK1z1Bi[ioi³Ği[iiSuªɷcɀcͰĞuiuѪǪĹϭ¼سܳi[շzҦѿѭķdzĹ¿ͿzzҿcS KzK 9uo·zB[ǿzoii¿ijiɢoǹǷڼɷİϹzǰۼiB͖uϷչܿ°ĹͭǿuzzڼS  1iuiiǦuio[ɰzĢiSiɭĿ°˼ҹ¹˿³¢SˢžªװԹѼ˄zuizoSآB czcB[πz¹zBidz¼ɰKcϿͿǭ¢ԿǹdzdzǿѭzuϢiǹ¢ϭ¦Ұķǰo³uļuouǰS uu  1cou¢uSͼiB˼ɹǢᷰzuɼ׿˖iuҳuo³ϳѰͼuǚطcoķiϚo1   9i°uiBϿzǭĭ³ɚ׳zҷoiĭտԹķǿϢzİz¼˦(  c[   zudzzK1Kz¼ķ¹˷zzɳͪ˚ϰ„SǭĦϳɢԦѹ¹ϼuz¿ˢ˞( 9KS[  1ou  B¹¼uioK1[ĪĚu¢Ϳzɼ׭˞ɪϖiǼĹǹϳԼǍļ˿ؿϰɿĹɭĪK ou1Sii1 izɒi[uĹ1(K[’u°z99ĿǿͿķz۹ǭ׳­ܿǷҷҰžǰĪѿzϷ¼·ϷšB(i1(( uuBczɼzušS(B9[S[1(ع­ĭz¦՚u˳˰˼˦¦հdzķ¼ɹϼɷz¹ǿi Kc9uzKui[iKSĉ¿¦i99Buc91KBBɹªİǢϚɀcǦͦϹ¹¹·İ͹dzͳ˭ǼĹĹĪzuBBzB1zSoo91ozcB[KSoBozcSKczcBiuSBiuKK¢izİĹٹطcKɿĞzļѼ­ϖķɚ˰ijo¼zcuɷo KcuoSuScoc[iK919 1S[czz[[漖[uĪԹoc՚޼ǰi9ķĪuošɳ˹ǀѹҍoͰužcĿooͷ1izBzϳoiiouS( B9(9czzzԦuiĚoĖҳ٢u9zĹ˿ͭzoǷϼɼĭѿo°uuuuɼijuozѳ[ 9ɼoͳiSi˷iu[B(BBSc91ii㪰uuzoiɚ԰༒˹uٷz˷ܰ˰ɹžǿǹ[cҷocoΰuɰuSϳz͚z9i(zĢz[1 1Koo[9Kc[SܰzzzzzuzzzczϿĉĪĖoɹѹuuǼѪzzмKɖѿuzǷļĿͷߞc  iتͰҹu9[9šouuzuB1 9iSKucSzuzuzzzzoSiǪɳ˞զzBͼuϹzzic˹¦zͼ˚uѦiǚzɿǰ¹˪߷KB (1Scu˭ϳuSBuozzuucSc[izS1 9oiooB9ooKuo³ooiouuzzu[iļšzǦ¹³ۿ[uǿoĞo[SĖzi˰ɿ¿՞ǒi¦uĹİɼͭĢ(1BBKi׷հozcS(o[K Bz[B ((1B99BKS[ooioozzzzcuªǹzϚļݹccĦϭuS[[i­Ēcɳͦuݹuǹ·ķĚzzzuǼoB(Ԟ9K1iioi[izczcKS[[¹uiiSooBuoKB111119(9[9 Kzcoiiouzzzzسǹڹ³ļܷ[iĿǦuSS[ǹ˿zuuϷuz˭zuiɚzuĒz¿u’9  KSKKS[[KouS(Ki[ioKBK 9uiKK[c911(9K9[zo9(iz[zcoiouzzoo؞ĹԼķͷĉKSɿ곳װ˼ocoİiɼϿzuoiϞĿǹu(  BSSKcKBcٖSKzKScuu[[[SB[SKoziz(KuzS9K919BSz[9Boucuioouuuozɼ٢˳Գ·¼¿[ĢҢϰǦuĿiuizªѿǼzuziռzuo¹o 9BB9SBBBciozz(ozǰiBS19iozSB1SiczS9icBiB 19BSc[SKBcouuzzzu¼۰ϹϰzذijϿ¿ɳۦ°ϭϦz˷ucĖuoiuϷozǷǹo(9KSBB999K[Si9B[BcSuɼ9ccizoi991KKczKBK9199(9B9KKSzzzzɷϰɚɭoڭ³ļ˳˼dzϪҷiciĖuzuz͹˪¦İ[ (99BBSSBB[uz9( 9czzĢcu[ocKiKcoici1ooSK[o[11K[K1ScoѢzzzĹ湢dzĚ[u߭ª˿ĿķͭzuucϢoui9ķooziz˿͢ª·i˿ϳu9(KBBBK99uuKBcijǰoozooiiuicSiBuizS(9ccKBuǚioɼªܭѭɼSɭǰͰǼɷϹĚuiuozuzѼĹiɪzcciu˿z׳˰oհc((BBBB99B·ucKSizͰ¿9oScuicS9czizz9[zzzccc1 KKKSiooϿİѷļٳ³oѼԷlj¿zѿ˰ĞooiiiͼѼoiciɿѼuoiҷcļ­cc1 BKKB(1BuuuuicuicioѹϿͦiziKzioi1KBKBozzzzzi(1(Buuo9(cijͦչ³ɼԹԼ¦zݼўϦuiiǰɍļ˹ouu˹zǰoc·K 1BKKBBB[uuozziͭͰ·ǷuKocco[[K 9uzici (BB1BzoBKiİٳɳdzɪi¦ķɿ˿uѿuչǹϹͿˢz˒¼u˿oB 9BBBB11zz¼­˿žzicczoiSSic9BB9oi19S[11[uocc[dz˞š˼­ϰķuĿ޼zzzz˚ѰǷ³ҹii͹z͚ǹSB9 ((BB99K9c˦ͼɳ­uzSciS[ozcSBBBK[oo91BiuB(9SKKSBג୹ٰ°ɰ٪uoǼiҍuučuzļdz[uĞizuuuiͪ„KB9BBB9B9BK[i¼z͢ɷǼɼĿcuSBc[oizzSic99Sic119K9BKB¹ͪĹɭĪz͒oižc˭ԪzzϚučzzuɭcuѼžSBKB99BKSzzoϦ˼ĹzijoiKouuozB99K[1(9KSK[KKṭǼǿϪǭܚSSu¢㳍uo˖׼ui[zcuz·o˿ķǦǹoKB9Kiz׹׿ˢcKBBdz[io9iuKSiuuuS[K1 (K1(K[SKK 9ǢĦĹijɪz㹷Ħoc[ǭǼ߀τ[ڳҰ˿[KzoouuzušcǼªzozzǼļǒc9BuuǿSi[ ([Siz[SSB( 9SK9B9(1(1׭dzɪ伭ɢuҍKcdzǿٚ˚تؼǷžiiocioooͷ·ĿɿĖu¿u[SKK[ĿªcooBK[KoocKKSciK((19111911(( ڷǹķĿ᳒¼ٷi·¿ݦĖϭuizdzѢzǹǰѼ¢˪ɼuo 1KScǒziccSBB[SSSKKKSB (1 BK1BSBB㼦ĿݳɿܪĚ҉dzͳ漢ϪռǼϷ¦ucuǷİzozzͿiĹuo[9B1 B[zɭSKccK9(Kc[B(((( 11 (SzoBzKu˼ɿתĞ¢ij¼¿ɢـcSc乞Ėzdz¼’uĹooiz–Ŀžz[9SBSi[zɳzzKoc99[zi9 (( 1[i[iBKS¹ѰɭҰĞǿѿݷǿ[9(9oԪˍi˼žɭcɰzcuͼ˞ͿzoBBS[ičziBz[izK(1991coK[Sdzطǭ㹰ѿ¿ԉ[[iҰĿ͖i˳Ħu³uiuİccķ¿zҳc999Ko[iϷiiKSzSSBBB(1( BBKSiiKuĹ˼ٿɭްɿijĹѰتzѢšϪuooªuS༦ɷ͹ǹSBB9Ku[iuiuuSBS[uĭuKKz[BB1Buz[9 9ui9SKɪϷ¿ɷdzɢǹdzɼզucܼҳ˦İuouo[iizҷoԿѭuSټij19999BS[oizB9zuu[[BKiziKuoc[19KiuziBcS9oc9³ѿɹǭɚļɰѹ忪Ģccշտzoioz¼ªzĭoio[Sccozozi[ɳuĹǹKKͰuKBc[B9SzciSKKBuo[KBcS99ozK 1uuuccuzic[KĹ¹S³žz˳˳uo۪ɞoiuu[o­uS99SB119ouziђczϹ¹SSK[z[[KoBKSB[[c[[KKKBBioK199([B1o[uzic࿷Ҫɦڹҿҍc͢­˷ǭ￉Ҧo[io¼ļB( 111[uuož³˳oz¿˹u11Kz[11B[iSiz[uo[1BK[BKS[[B 99B91BczzicSoiuBo¿ؚܿ¹İזuϦϿ³Ģz[ccczuz㹚׷zzzzǼ·9(19(19K[u¹¼ijoϷͼķ99coKScccu[cu9KBBBSSS[SSi[(KSS1(91Bo9[SKB[9ǹؚǼɷi¿Ϳϭĭo[SKSozzoouѢطzzҼcSK 9K999( 11B[–Ģo¿˼B[o[z[coucc[cS[iSKB9BB1 K[[[B 1ScBBSui[u¿z KKK9ioKSuͳԼ˹ڰڹĦǪB1BKBB9KKi۳ռĭzSB1 199199111 ((1SiuتͿzziuzuzziou[[SSBBSSBB991 919( (1KuoK[žBKizKS[KKuzc[Bczoui˿oĿi[Si˖ǀɰҦzcoc9[iizoSSKBBKKS1BiicKizzuiSBBKuijҿ˰¦ɹociouzzBSi[SSS[cտĖizž˰­cKKKBczociªzi¹Ƿuoozɿz¢oiܞԿǷciuϭouz[Bcuu[KS[oicicuzouuͪijɪǦĞͪǼo[SuKioccocSKK[iuԖozuǭɭĢuSBScuǰucc[[Ki͹iciĚiooo[oɳzz˦ǖoѼռ[oɪǿu[ouoǢu[KiĪcouozuoozzɹԼҿѿͷѰ˦Ͱ˼zcuouzou9KBKoĿϒuzo[°Ĺ[K[cozzi[KS[Kķocc¹zooozouz˹ɹiBǪɄ9uĿǪu[[ĭoiK[ozͼcic[ououzzuuzҿǼ¿Ͽdzϼɦ¦iicuzo1KKcɿ·zoĹ·z[[SĪzSBKKS˦zucoɼu[[coĞİ˿ocSoiKKBiiczͼi[iozuiiSiǢ³·ɦǦɳoii1[cz[BKcuzϹǦz¹­SSu¼Ԟ[9[9uijͳͳzĪzc[B(u·zz’iBBczzuSSBcu[zzoǷ¼ɷoiziSKuϼ°͹˿Ͽi[[o9uoScSSS[oioɪuu˷Ǽǿѭ1[[z¼°­ϦҼziz[iͼɿoSB[·zS9(iizou¿ͼzoBKiҹ˦Ͽ·ϼic[cĭ[ooi[9BSoziɹªuzcž͞԰ѷz9SoѰzzĪҰzS[i[˿ɷªoooĿSz9([oozi¿uo³KKBKoͿoouii[iĿ˿¿Ǫuo[Scc[uzoi[KKSuoo¹ɳzoiĦշ׿zSKcϳooϿĞic[c˹ϭؼzz[BKuoKKKSi[Ēcocc(1BS³iiB9Sz[Ϲ¿ǪĭĹuzuicciiocK[cicSKB9SuiǷzuzozuͼ³˞˦շKc°ijİzBzϳ͚oiSuښɪiѹɰSiuScioooBKB9uo99Koķ­u991c[·Ĺzuoiiii[SK9KS[[SKKKiiouuķϦϪѰİSչǷͿѼͷziiiii„Ğ’͚uiSͭuzĹi[ScciSKKKcǼ’­c 19SĚo¹zooic[9((((9S[[[[S[uɹˉuؿdzԹ­ɼɿoz¦Ҽ[cu˪zuzѿKi[[ˢͪҿocoªzui[Sͳzo[Ėio·[ccuuicS[cucĿĞoBS˰ijzcccB (((1KSSScc[­͒uzuz¿ҷİu[cScozcǭKS[coҞiSSScҚĞ¿iSSzĹzo[SBz·c[i[zcucoiciuzocuozij¹ɿzǭ[[BBSc[[c[[[[[[ѿĒzuuzoǚzǼĹĚiKBBBKKSoڳتcS[[S[u͚i[[[S٭ɭoSSicoozzzuioooou[zuoi–zu[SuoiccS[ǷĢScܳiKSc[c[SKSSS[ccѢzuoiioiɷɿѳ[BKKKKBBizcKzKBB[iccuĦzcK9Siݿշ¹uooS[[[oiuc¼oouuoiciuiǼɿuԼ³cS[KK9BS[SS[S[ǿתuiiuu˹iǭўͼSBBKKK[[czuSSuļ1( Ki[[SSo[izdzi[K( oǹǢɰ¦İiSciuzzuuuݹ³Կz[[SB9BSSS[[[[uٳiǼ˪ްװɪSBK[[[S[czuiiiķ͉ 9KSK9KScS11BcǚiBKKKiϳϿذǼҷ¢zSccuĚzǿ¼oBѿԹc[B9BK[SSS[Sc๳ɚĿչzSSKKS[SSBBuiǦ (9BB19ciS19KcoSB9ɚŀoķ·u¼zzoK[iuɭ¹o[1Sϰİo[KBKSS[SS[[cឪoǷ˰uɦziSBBBBKSSS[ozozͷč (99B SicB 1K[SScSKSǢz¿ǹݿ׹Ku¢ѰzBBK[u¹zSKKBSķխoiSKSS[[[SSSczڦɷi۞oSBSSSSSSSco˰ѿ( ((oziB 19S[[cBĢuzĞ’[Su¹ϼ[Bczu[9Kҷɰoi[[SSS[[SS[czѼͷˢǚcϳѼiccioooiioѦiɦ1( (( 991919i¢ۼˢi[zzi¹ǿͭzSBKSiĹĹ׼ci[SSKS[[S[[So˹ݼķ’cijɒzzuuǒiͷ9B9BBB1Si1S[iiٷɿѰuSizzuڭͷo¢ͼѿicuSKc˰­ҹS[[[[SK[[[S[[i٦Ƿҷi͞zzuuzzͰǿ԰o[ccK1zo1 1Suϖcizziİ뷪ªǢ‰cͷ¹ͳ̈́iuͭiuzoSռĹ¹uKSSSSSSSSSBBKSuҦ¹Ϣzzǒc[oocĦiuui[Bu[[io͹zK[izocui[[ozܹ㚪zǼɿɪoٿķ[Ͱuҿ˿cԿǹͪѰuc[[SKSKKKKKKKBcѿعɿɍԦ޷u³uo[[c˿uuzݞucBK[c[K1Koo–zɼѿǿ˰z׿ٷoɳɉoҳ˞ͼ׿uc[SSSS[ccSSKBK[Ħ˭[ķ€žҦ˒cKzǹ˿zu¿ǿĿڼĿ͹cSB ciSBz뼀zѼĪzcoļͳuϷǿɢڿ˹ϼշ¹Қii[SS[SS[[SSS[zܿcķϳuķͭǼ׭zB٭ҹouu¼ǼuKBBcozҭͳɦ˄9۳uϰuϞSϭu¼³ķɷz׷’طijcc[SSSSS[SKSSuĀĹ˞uռ˷ϳɍc[عozzuzziuzio[K[SKBS¼zoͳѹǷ·uɍKܭ1B91ѳoϳ[հKҼ·ҼɞuuհѪzسªiccSKKSKSSSK[zǿϼǒzǢ¹cSzɳuzi[SKBSBKczϰzҭ˿ijiS˹z̀zzzҼocͪͼSuѪǷocڹɉݳc[SKBKSKKSSKSoѿݿĒѹ‰ѪؿɪҚBSڼªzzz[cK[˷ҷɞɭǹo[BiuǞɦlji͹ĚǭǪSiͿعuؿ˼zɹc[KBBBBBKS[[coļϳҿzͿ؞Kzzzªuɹϰ¿­¹c[ɰϳҼzKK[c˼ɪzljzѿĭɦužuS¿ɒϞѼİS(( (1BB9KSS[i˹˦İ€u·٦SBuouoԢϞ·Ԫ˚¢ϿcBi¢˳Ƿz[u‰ͪǭ׿ϭ¢˼cuѷխ׼ѪzB ((KKBKc[[iĪǚ˰‰ͭɿİѭB [ouz˿oسͰuҦ³Ϧ෰o[i˿ǰǦɿccǿϳ’·ٹѪdzo[uϿdzԿ¦[SKBSS[[KScK9cعҪĿѼoĒļ°ĒB czzuɼǰķoͦɀ­czļǷķǿKzͼ˷ǹˢ˭ǹcoĭuz˷ϼɹui[S[[SSK[c[BKuzռ³ϦհڷѳҦ͢oBSK9iuocoiɞ˳³uͿѹķǰzļǷǦɿ˪cǚuuɷǢķuĒu°[ɼԳiSKSSKSKKSc[KKi͹ѷذu˷Ϛoi[cccioicizuĖ­ļĿzuǷ˪coҹ³zǼǼoKKĭͼǷ’zѹ°uiͪǿiSKKSSKKS[S[c[iu·ԼѳzuǷSiScciio¢cSco˭ǰuz¼ٿo˷¦zǢccSKKKzijэ¢ҷocɼɳuuɼϼdzzcSKSSSKKSSK[[ouzĭ˿¿ǹɷɹuuKSuoczɖK[izɭĚzϷzĭ°׼ǹz­բiĿ˳cBKKKB[Ƿdz€·ѢzcuɹªzuͿۿ[KKKKKBKKKSKSiuļİ͹ɼڼuoišuuzžĭҿǷɢɷѭijcڷ[[ǹ‰KKK91BuɪطĢĦɖii˼Ǧzc˿ɪͦz[SSS[SBBKKKB[uҿ·ǹɪoccĦ͞¦zzuuzɳļ¹­Ŀѷ׭˹zBiĖz9KzǿĿĦ[Kc[ciĖɚz¦ĭzĞ[o·Ěuiˢİi[[KKSKBK[i[KcǿѼ¹i˿Ԧu[[˳ɰuz[žĭ­ͷўͷzĢBz’c¹­zɦķǦccѿč[z·Ǽu°³zz[[[KKSKBS[cc[i˿’z˭uuԒoSuͭiioǼzzгoɚļ³zĦؿĭǰoĿ˼Ŀϭ͢˰uϪզcoªuu˼·u[cSKK[SSS[cccuz˿ǹĦuѳؿS[zժzuݰcicoҰռѿķz¿ͳ¦ǹ˹ǰ³ǼǼ˦ѦɉciϷ¦zzǭ˳uKcSKS[SS[[[[cļҷܪǹˢošѹɭzKcɿגczǪuizu­¹ɢzļǹɭͷuɹz³Ąɷ¹¿˞uo­i¹Ė˭[c[KKKKS[cc[coͼǿǞuͳͼ˹cS[oѿҍo¢˚zuuɿ¹Ѱ°³oo˭¿SͿ˖ˀɉ[ozouªcİɖooǷɹͿͪcccKSSSS[[[Sizc˹İĿɰɿdzdzSͳžϹ¦i¼ǭɭɖɼϳİo[c͢ɳ„iع’׭cɷocǼπu·¼ǞoccKSSS[[[[Kooǿ¼˿ɼҢҚu͹ĭoSѹǹijϿzѹiSiĭzocļɿĚzzѼߢļǼɦѳўouSiɹoļdzzccS[SSSSSS[zzuuͿĹoļ¼İɞzĢu޿Ŀi[ļǷĪĞoS˼ǭcҹ梚ռ˳dzzz˼oͷoѼҼ°c[[[S[SS[[cuuio¼ķϹͪϿ¹ɼ˹ך[iu­ĢѪǷzĿz˿ǹz[SuۢzuoİzٷǢϷzi·ҷ˹͢ټ˿Ϫc[S[SSSS[[cuooϹǹϹͼǷɼouķ³˳ѰǷocuՀuzĹĹ߹ͦzǷ¿Ǫ–z˞˰uתocSKSKS[[[ouuĭu¹³dzuzķiuǦͳzǹͿ’zͳ͖zouzuczBS·ے°ǹϼɼĪǞɭiϹķԒocSS[SSSSSzo͖¼oǿ˹ɖĪ[ǭi³o˷ճϭziKuzcoicSuķ݄ҹ˳˷Ұuozҹͷucc[K[[S[c[uϰۿuɹzuǷ˚Ԅo˼o[z¢z[BǷ‰[ѼɷoSB[SococzziϹ漣Ěo¿¼ķύiuǿټc[[KKS[[[[[zz߷ĞǭoǼٳ€uĭuɭuK1˪iu˼ɿ[9([zzcuc[z­uoSoo­uĢzzz[zɷɖ[ĹϭǪ˳[[cKKSc[[[izz͞[°˰zooSSҳucz˹ɪ­[1K[oĢ[cziz¢i[iɷzѰϪuĉu’zzzz°Ѫ[c³³˷[ciSBSicSSoziت­u­խ˰¹iuzi[S[ϪuϷɚ[Kzɖcozccou[uɪǼ°zozozzuoiռi[ozԿ¹Ǧci[KK[i[[Si¼Ĺoz¿ªiziizzuzuoucKBciϰͦu[ozcuzzzcK˷zciuu˳ϰϪzoiSzuozuĢoizoz˳˭ѭci[KS[c[ccozٷҿļ˞cɿ·Ϫzi˳uu[cuuozBSocѹ¦¼oKSǷĚ[uuuoii¼šcǰɳҰѪz[iuzzuu[zcu˷ǍccKKS[ciicozϳϖ͹ˍo˪Ͽzuuuui’zzuuuzɭĦucoz¼ouuSªuiɼϹ¿ĪiozuzzzzScuǷѷuc[SSS[cc[[oͷټѿiتԿocuzuozzķɳicz¿uiuϼuiǭdzǿ˹ͷuiczuzzzz[uɼɼiSKKS[c[[SuuԿ¿¿ĢiĪٹziuuoooizͪu¹ĭǪiz˹zouozozioǿɰɿzuoouzuzcuϼɰĖo[KK[[[[cSzzɞǦuzǪzzɦɿɍooicozoiuͪɰњz·uz[oSczzzuuci°ҷ¦ɹzzuioiouzuzozǷіi[SBSccci[oo˪ѷzuĀ˷oiiuuizǿҹ°z9Soɹuzouu[iuu[ouiu·uiz–ĭļǿ¿oouiSSi[[cuuoͼuĿѼҷiiSBK[c[ccišؿocooo·zzi[ѢڹzcizzcKoɹSSuĿ[zozuoizzizK[oozoͿuo˭ǼS[o[KB[c[cozzuocozoi¹Ͱ[c[KKS[ii[[ݹ–ɖ[[uzu[oĪzoiozč٭ucBBK9[zǹcSuķizozcouuoziiu٦İSSci[SKSSKcuuzuoװcɪziSc[SScc[c[[ozڷĖdzɒiiiuzzcuuooc[[cooooĢѹi[KKB1SdzioSo˼Ŀuoiz[i˚zoܚcoijcB[SBB[ccSBS[[[uzouzĭ¿ڿҹocicc[cciciioɹآϹǰzz[uc[[[[[cuuuooiuzɚzuccBKSoSKcϼocoϹǿuoiiuzzzǦ˹’oπSiªucc[K11BKSSSB9KSͿz[[հĞɒoiiiccccciooɼ͞ǿ¿ziciozc[[[[[cozz¿ǿuziKBSczuioİc[ԿͿuɰzcczoozzuoļͭocuuuciiSBBBBBB1919B9Ěoĉ¼iioiccicouzzչϪĿij[ciioc[[[[Sciz¼uzo[iuzizoioҼizzzuczžͼ·ؼziiuic[KBKBBS[K111B99czšu°ɰ˿ļzcoic[cciuzuͿϖ¹zؿicoiic[[[[[cuķooczi[o[SouzuijǹĪĭzozocoozǞͦԦi[ii[SB9999BiiKKS9(1B9K̀[zҭicccSS[izzi˿ɷªzǿѦcoic[KSiooɰzcS9Bo[B[ucuccoSozo˹˹·zuiiSKouc[ouuҚziooļzɢuoi„uooKKB9B9BSS[[99[B(9SBKcocio°dzڪci[[S[[zzozǷԳ³izĿ¿¹ciuzͪiKS[S11iiSuz[uciiKicciiuĦzc[coķzccczcoouͪocoouzչui͖zzzuc9KBKB9BK11B91[B1199BS[coz¿˳۷תcc[ccciuǹĪiİz¹¿¿[S[[S9BiScSBuBKciiK[[BSoiuuuzi9KczS˰uozuuoizϼ[װooizicBSBB19(B 9KSKoS999KBScoϼǰ¼ҿcc[S[uuԼɳժzzܼժ·Īi[S[[[[[BKc[ScKizKioocBBiuciziouzz[[oiuoɚoіuicui[S[[9(9B1K9S[iiucBKKSKiuɢ¹¦¹uoc[[uzѹǹҹzuǭޞoڳɹuK[SKSBB[[B[ucic1[ozSB1SuzzuccuzǞooz­zϚzzcczzccSBK1 9[KBi[[cSio[9K[cdzķijĹɼѪzii[KBo˷氖zĿ˰z[S[SSK9BSKK[u[iccz[BBSS[uKz[[ziž¦ouozou[ɷѢuzui[czoiocSB11KK9Koiic[ocKKczͷϼĪɿĚuoS[Kozzݿǹo°Biҳ¦uǿ¼oKc[[SS9KSBSiKoo9KSiizi[K[zozĢczĪicǿozi[cuuoouiK9(B9SKcoocSoSSzz˿ǖǿͼ˒zio[cozzɷoozz[¿oc[[ciSBB1S[SuciS1(SooziS[S[ozɷzizucuİoɷĢSzcSozoooK9(B[cKKoouic[izzɼͰɹi[uc[zozǿuuzoiѳĪzK[SBSScBKKKSSi¼o[B(czuuiuicuu[Scɼczozoɳ„[[SozzS9KcuiB9[ouoco¼uuǦͰļšo[icKcicczuǿİczªooͿĞ[BSK9BKB99Kciicu˭ocuizzo[ozSKz¹zuoozizuz[¹iizocciz[Bcuuui[[cc[o˭¼ϼİщicc[S[[ciKz–ǿij[9B1119B99SozzouiiozcizuK[c[ou[Sui1izuocuucǹcizcc[uuiuoiuo[S[iouzuc[[cɪ˪ɿܼɳҿܪuc[[c[[uҰķĿšSS99999KSuoouoBii[SuziuoocSczuSB1S[izz°ocooczzccSK[zcoicouzzc[[ciciiuicļѰ­Ϸ³ɳǰѪļɷzoi[[ioѹķšžĹ¹99[c[Siicz„u9Sc[ooczicSizSKzuozo[o[(BKoiuzoz[ouuĹcic[cKcǦ˹u[[[oiiiiiic[cuiĹ˰Ģ͹zzɼǚ˞ˢucooocǹĚǿB9ciiuuBKiouicuizS9Kcu[KciuciuSozziczzoiİuui[BcoĢzS[cozooociu[S˿ǿĹǼ³Ϸǰɷzcciiǹ¦ǭǼĪo( Szuuociiiciozzc[oc((99K[Kiu[izozoucSoªzouiKczKiuԿiScuzcuouuuu[Ħİo·ĦѼĹcc[iz¿zķǰļǷ99izuiS[o¿³iio[i[1KS99Scuo[ui1zioiS[˭oozuizoicķiicuiSoouzoiiɼͼĭԿ¹oɹ¿˷ucB[Ǽoi­ĿɰzcB9iǦoKoc[czco[[[KBKB[icizi9SuiiSS­zzzuu˷uczǰoiiozSSciuuoiiuͭªĹĿ¿װucKS˪oiǷ¿ɷo[iS[u˷oSoi[SBBzzc[iicB(1S[BSciiiK1KzuuoKc¹¢ocSKuzcciiSciuuuzzcĿ·ˢѿɷzdz¹ǢiicuuļɿǼzKcoSuz¼İ[cucKBcoooic[[K9K1Kc1 BKBK1(SozuuiK[czuiSuzuc[ui[ouuiͳiiuciccouϼ¹ͭšװoĭšzĿѿoiizi[oǿ˿c[i[Sz­uzoucKKci[uz[K99KB1BSB11K[B1(KiuoiK1K[zuuuouiiKS[cz[[z[ǦuiocioǼѹžǞuij¹ٹ˰˼·[iu[So[ijǿɞoii[S[Ϳuuoc[SKSicBcz11ui1Si[[9ui99cuoS((Bozz[[uiBKioo[Kcizooi[[iuzzǪ¼İ˹˳ǷuĿªijϿcioczzSĿɪĿǦocci[KBzzoiS19KKci[ooK1uzKSzzooBKcoK(91uuucuBS[9B[cooiozcio[i[iSuǿ[c[[uoiSo˿͹˪Թ׼¹zo˷Ǽui[[¼¹ui[[ii((izoozɪSBB9[ccio[KouBcBKuiSzicouc[111KcK9B9 oioiSuSBzuS99co[iiˢu[[[coiiSĿ¿ɭԼļǼuziǼªzo[oͿǹB[KSoc SzoouB99BSc[K9BKScKK((ccKSS[B9(91((9B911oiozi[uټ–z[cSczouzSc[[cc[SK­ķɿɼzzuo¦zu°zļ[¿ɷɞc[cSS[BcļzoK1(9BBB( 9KKcoKBBK99KKS9KB9KS[KBB1Bu[uz͞·ouc[uzuĹcSic[[S9Sz¼ɦ˚Ŀݰz˖zz˳Ĺz͹icĹϿļccccc[9dzǪzK19191119BBK[z[[[911SK[KB9(SuoSBB11ouziziS[i[zoɷc[c[[SBSİɢ˳dzzѹĖzzɹԿɼžo[uɷļɼĿcicSccS9(BϹĪzzuuz11(1(1(BKS99ScziiSSBSK9BK(9[ziSB9 [zuiKzoBczcoͳucĿzc[SSK BͿϼķǪ˼ѼݳzͿ˿Ͽɷ¿S¹ªcS[[SSKK[տªiizoou91 ((1(9BS19BSzc[cBBSKKK99KuSB (ocozuocuucz˞oĹoKSSS1(ziɪĪٿѹ¼ѹۦڹͳͿ¦ҿccǼžļɳKSK[cKKiz˹ooo1B9BSK19B9 (1SocBScBBS[KB91BcB19SzuSoczzzizzɼϚuoKKB1Kzuǹ˚ĞϹ˼iļ·׿i˼ѷѿ¿SKɰuuššcB19SK9ozͼzKooKuu99BKB111K9 9KS[[KB9911BKozoiououuo[uĖԳzǢuKBB iѿ˪Ͱ˼–uĿ¼ɖz˰°ǰiKzǼ¹ǪoKB9K[9[ǹocizu˿iKouB9B[B11999999co[19B9191Szuuz[iuuiuiԹz’uϰiSS([oɿǷ¼Ŀذɷٷǿ¹KoǿuuuĹǼK9KK[Sc˼ooizuɳ[cc(1KSKKK919BBB[KB1BB(1( 1iuzzc[cuS[iczljSzѰc’c9Suǚzzǰϖ°٢ؿ˰cSu¿izoǞcSKSSS[ͿϼuuǼcoS(99(1B9991[SB1 ((9B19 1KzzouiocciSzzzocķzuzuuɖcu(BiǞu¦Ħ˭čɳdzԼ¢ccSuuodz¿ǿSSB91Ku¹ϷczuzҹuuKBBBK991991SSB11(1B[11((9Bcuozǭc[oicKizuiz‰Buz¦Ǣzu˞ǷϷĪcuiɹɿɪi99( 1iɦoiuu˪uz9ozK((191991( (uu 11119cռuczooccoǼɞouoҹuzuo¼ɪiɀijҳdz°izǰ·ļ͹[K1(([zɦzu1K((1111( ( 1ic1BB9BKԪ[[cSczco¹ǿɢĦioļɷĦǭ³ɿڪɦu˿¿ǒcS1 1Szizѿ˞ǼzoczK1ͰiKB1BBBB(9S1BBB9KǢo[[[uioocozu¼ɰ˿uci[ij޼­Ԧzǚz¿ǰucK Sc˦u˷ǪzSKi[uɢouoB(199( (1c˒9BuiS[Su˼zzuziuS1Kuɷ¿ǿzĀiiiucѰz¿S[ͦѭݭcōc[B uzzխuzĦĭBKziuiB999((Bi1[z1BzuͿ³uS 9i¿ǍSozo˿ii–˞˼˿Ē˹z[¼ǰ͍˳Ėz˷ĿǚcSK11ϼĿuBizzSzBu[S1(KzBKcK1Kuc˷c[ozziScĭzziϪc[zzuuiǹѳɷͭcijǼɒcɢ­zdzɹ͞iSBB(KĪɰuSSou[zuouuK[Si[czK 9i԰zSBuuSoiuuizuuǪzzuuĹǷҼͭǹuu¿ǒoiǹϪzu·Ŀ¹Ǽ¿ɷcKSKK1Sļ˳İiuoKS[KozzcS[B9[uui[oozS[BS1B՞Ұզ9iiBB¢zzuuoђĹoͿٹϷɰuo¹¿Ѽɪzz¿¿ѢzzҰĿǹĀ[cc[K(1oļǿͳcKS[[ɿooouocK[z9cѹoziuS( ((1BcizuuoĢzzoozuou¹uiuԹzicouo[B9(9ioo˭c[ciuuļɼozcziicɹǰ˷˼צҷͪҷɹuuǒuĦuouuuo[BcuBBҭzuzuc9  (1B[ciuuiczzoǪozzu°ouoѿcuicSBKKBcuuuϷuuu[Sz˭io[ǹԷªѿطɭɹϷuz³ڦuzǷzouzuoooi[oucѦcouķzzc9((  1BKc[uoouciİiu˼·uoouzzzĿuoɷuci[BSK1Szzdzoizzziioz°o¿czž¹ɹ³ѰǞdzuozѰǦuuoɖKiĿ¢Ǧzzio­Ğzz9( (B[[cooicc[Ѽo[zǦi[uzzz˭uc[cK[S(Sozijci[zzuɳzͪuczԭҹɰҿѪĹzɢuozzɼuuǼ˭oϷɰzo1(( (1BK[[ci[coi’ͿozɰcziSoijoS9[919BoҷuiiSiz­zzz¹o˼uS[ĿǍܷ˹˿˹³ѳuǪԹuzļǭozoĭɦii((( (9K[czu[SoijuǼzoczi³i19BKK1zu’ooc[uuoǿzzzo¿ǢuԳ۰ɭٹǭziѹѭռzٿϞĹɢuciϼiozS 11( (1Kcui[Scco­­uzİzzz[zzBB9BucBuɪiizcSzͿǷccci[u˷ɷɞizĭ­ͳɿϢװ޿oo˭ٹǪؿϰǹǒiuoSiǰzzuiz³zS191(( 1BSczccKBuuzɿzz­uu¿zi[o[BBB1Bi[izĹuzccoozĭoiuoiioczǭozխɪǰҷԷzoİĒԪɼĒiozozicҹuzǼiB(191111K[uzic1KzuĢzziuzu³u[999111Kzzɳo1oϹou[zĉi–Թǿɰ­ҭԳdzcoѼɿ„׹ΰͳoioKciɰuou¹c91((( 19SczcBBcziuĹoicuɿouziBcK9911[ĿB9o˭zuǪzuciiSĿ˦ѢĦ°ݷĭ͹zcɰĦ¼c¼ǦҰzoouS[io˼coS¼z[KB1( (B[ozuucKS[zuzKcz¹zzoK[[KKSKBouķz1Suijz¿cou[oɢԷҖٖ޹ˢzu[ܷԼouz͹Ǟzccc˹³cizi[SB1( (KuiciSSoiϼzouuzɷioKKKKKKSSizzoͼzB[u˹oi³¿Թ³zoiiͭԿ˖ͳآտ[zݼԿzuzzzժzԿoͳzzɼziSB91( 1cic[cS[u˼uio9B9BBBBBBoicuo¦uBi³uizѿªzѳ¢uzoͰϪԷ˦۷ǢoSɳ˹zzo˷uɞ³Ѧioz[KB9111BKuuic[[ciz˹˭ucczuzzK 91111999KcKKzuooiuzziozļšɿɍu˿ؿdzϿ¼ҳu[˼ĄļoҷzͷšcuoK919BKSKiS[[[Suo˷ǷoSKciczzocK((1((111BB91Suo¼uBizuzԹoϼ·ܿ˪³˹ѷuc[ϼ¿ˀzķzў[o³ĪuK119B1(1[SSSc[ķcBKozzzuioouS(11(((1((11(SĢoz(zoouuB9[oտzzķĚuԍǪ۹ٳzcBuĿˉǼշĀoѰķzoB911(( 1[SBS[c¹uzҼzzzzuuzzouS1B999( 1((Koczzǹuz[zuuou¦9BSBSci˖z¢¼z׼oij׼˰iK[Ŗu·ɰ[iسzciu[S9(((111io[SSuciijzzouoooS(1911KB919uɢBiocz’oucizzǷzijuBuoBSScԭuѼz޿湍ϷǰiSɹϹǷǍz³z[Ҽzo[zcS111(999iu[Kcoi¹uouuz[(91(((9BBSɷǭuzzzzijo[ouٳiĭɳɼĭڹĪciϳѦ¢Ě˳Ϳ˼zu[cҷzuzĿui[9((19BKcuSSuͼiS¹·ĦzuuzouS1991(11(1[·zɪzi[u[ϹuԿiodzķĹĭ˚oizzu׭ɚouijªzouzco׼oo˄uSKS9(919K[coiudzuS¦ɦuozzzzuS1(((91( 1uu͚zzi[zͿǪ[u͉ωzoz˹·ۿ˰ϼ˖zǹž¼u׳Ϳzz[cuiĭzoǿu[zĢuoBBB1(( 1BKSouuoicĪiioioozuozcB1 ( ((K˚uuoiiǒozizdz¹Ku͹zo҄uoǪ¦ªϞuuɳu[iouĒǦzcSucKB111( (919SzuKuoziɼ9(SuoiuuocS9191((( ([ǢϹuiooϼzi[Kouu˭zɿoǼiuozuuǚ¢ɚݹɞiozzǼĹ³¹zii׼˿uizo[ooc[[91 (((9[ozi[[zzc[˷9BciiiuB11111((( KuĢϷu[1[i[u¹ɿ˒cžuɷĭz޼ǷĿiozzͳdzϿzzzii׹ǹzuɹiKouo[K1(  1BKBSKuKS¿ķuiuociK111((((1( 9u˪ͷz[couoϰǞuٷɪĞǭuuzխږհioc[·Ǽ˪Ko¼zcKiB91   BSK19izooKǼ˹zzuuuS111(((((1 SoĞ¿uooǼoizحizuzɼἍļĹĪuucҰļɦϰǦziu[9ϼSuͳzS1 ( (  (Sc[S[c[BKuzo–­Ϲuzzuzi[91(1(( BͷozoucoѳcSKoš³zϦzǿϦoidz¦oocSczĦKoªzoK9  199SiozzucicĿ·uoooiuu[zK11119(11 B¼Ǟi[iuiiciuzziİc[uoizuɰuuuz¿Ŀɿuu׼ɰڿui[c[iˢ˰Ƿ¢uSoucS1  (1BB1Kiiuuooc[ɿcuoooozoB[c 1(1( (19((Kz°zucciĭicc[KSccuuiĚ¢zozuoiͳcɰͼzzuc˦ͪdzucc[So¦˷ǹcKzzi99   (9c[Siziooc[[iooiǼKczoooi[9cu((1 (11(1z[iozİzizzccoSKS[SSizczšˉzuzuҿziz˿ǖͷɼouoKѼdzijoiKSciͷķ˰BiiocK(  ((1B[izuoiSc[[z[oouo[K[z((1( Bu[[cuziɷzzuSoSc[KKSKKuuc[ĭѿu˖zuǭoĪdzǹ¿ɿɭci[c˰ǹǼoccoKS˷dzi[zu[(  (9cScoSiucoiuiKcK((( ioSicuBi³zioտcuuǦKKicKSSizi[cĞ˚oz¹oz˪uǭǿ¿ɰ¼˿ĹuoSoİԼسzocicKS˳zuiiuiK  (1SucoĿĦo[uǿ˰ozoiocSz[( (  9[czSuuozizč[o·c[[ic[[zuiS¦ǚuuɹҞ˞oķɭ¿°u[ͦļuuooc[[ǰɳzBKK1( 9cuuiͦļocoziSco((  (ciczoucuuuuiScĪz[[uucizcc­ǹўĖiˢ¿·zco°׳udzou[K[ǹϿSoSB    [oozcu[iҳķSScoiSKoB (Bzoc[ziiizoouuuiciǼozziiuui[ozѭ͢ǹ–zu¦ijİ·ioijzoci[Sz͹ɹ(KK1  9uuzzuSoĭ˭­o1K[[[KSc1 1zziiciuiizoo[zĿzoicSSiҼzo˳ĭuSĪijҿɳĭouiioz˿·[ĉ[9B9 (1 (cu¢iuǢB 1BKcKuK1   (uzccc[o[zɼuoozuoKoҷĪi[SKcҳǚiozճɖ[Ğǿؿѳ­cطuuzzoi¦¿ĄKc[K9(((Kzoٳɳoi[SK[cK91(  czoizooouocĭuuzuuzuizzzĖoǰzoo[Ki„zǪuɷɭǰĹķ–i[ļidzzzzuo[KiɰSuļzKKBK9( (Biiiiϼoodzc[u( (BucoczoĿɼzuϰuހuzۢԚiɭаzcc­uozzccK9[dzSѪz(((1K9  9[uSz˹uuzzK   [u[iizu˼uiiu׷z緍uz˿[˒uĦĢɳªͭļ³zuzuǿzuicc[B[­ĭϞ[ 1B1 ((  (izioz[˿oucoiz111   1oc[zii[cuǷSK[uĭucu䳚oͷoǪ°˼ͷѹؿҰdzĚuoĹuuicciKuijuijuoz1 BK1   Ki9uu˼z[iKKBKcS19(  KzciooiccoSzzuozziSioϷzciiuĿɖzuczoz˞ͷϿ˷ݷɼѳ͚izo­[S[S[·uzu9[oB (((( 1BooSuoķi[z[c[K1(B[9( ( iuiicc[BciiczzuuzuSoz԰ooc9czžiSzouzu˦̰ҹտɖǼɹizɼKBB1cǹuzKoz9   (11BuozĞzucK(KB91 9ic ( (1izzuuc[S[[uijzi[coouuzz[izoiɖuzc9SuҷuBo–ǰĢɭ¢ĿķiɿuKK9BǪizoS[z9 ( ( ( 1Soiioo[( 1( (Bz9  9iuiizuoo[KSoĦoooizzicziҳu[S[cϼKuzɿuciĞ˖Қ¼ǰ˭–zǼoSKBcͼ·ciiS9c(1KKSSB( (Suzzuo[[u[1( (9Si  (  9uzcucicSczǹzzucicc[izǞcK[uuɒuizzɼozuǷǞɢϳ¦¼ϳ¿¼ѹuSciuiuiK9Bo¦izǦzcoSS9iu1Kc[[SB91(9couco[Sic9  (BKcK   ( KuuiicSzuziu¿¦ucSSKcѼcBioǷzzoS¹uzҳzuչɞzdz°ɭؿҿKSz¿KK9iԞicĭu[[9[u[KB91 999 o[zǷiuiSi[9((1B[   ( izuo[cooͿKK[oİuuBuuͿuo[B[¦icKǼ·uҹczɷϷķϳɪz1iicBKBoĒ˰o[͢occS[K(  11(SuɷǢoiScK91 (9Bc[ ( BuooS[zĹKcuoo[1iɭiBcuٳoi[[Ī˪¢SKzuĪɷѷļԼ¹Ŀžc [u˿SBB9K͚[iKS[[ii (  czzĢuoiB1(1KK9oz1 [izuiouKi˼zuu[K[oɿzczɞzzuici­zͷoui³ɿķҹ¿š9 (KoڼBB91KҰiuķKuB[SSS1  (( 9uuzuzSccB9KS[K(zu  (S[u·uoouBo׼oic[iҹzczoz˿zɰ͚ioiu׼’99(((BcطǢKccS¹cuǭo[cSB11(   [zzcKSB(9KKSB1[( (  9zSczcǷioooz[iշ[uKS[­z[zoҹuuϹouoϳzǰ¹¿ɷҿѿ9(BSS³zoS[oĦzcziB9K(   (izzɢzczoBB9( 1KKB9[zK111 zoSiz[S­˼zuuzu[ͰcSB[iѳBcoϳuuzoooǭzբzz˿ĭϹ˪c9K cBK˷ooɰ[uϹ[1cS   (uuuuuSS9( (9B99u1  ( ([ocSBSijozooKuzɭiK[zĞiuuͼzizϼϖݳ¹ɹͳɭziK[oªBKѰoo˹BѰcScK   BuǞǍicK9( 1B1Kui(  ioiu[ciuiz°ioiKSicziBiѷouzɭSͦuɒͳuc[oɦļɳ¦ǦzuKuijS[ѷooSu1Kc( ([iljɢuzicK( 91ozS   9iuczzuzϞooKKu·uS1[oϭBiؿzuͳoz˭zuccoSKSižɼǼ°Ŀ·ժiizͼuzzuc(cS( (BSKiz·¦iiiB(( BBz9 ( (( uuioBouzu۳uu[i͹o[9cuǖu9uצoϼzzoǖiu[9KuzzԿ·˭[[uͷz³oui9B 1( (BcccooĞzªci( (99Kczc((( ( 9 (zc[co[zzoz[ooicoǞuccci˳zzBKoo[o͢ziozǹu[ii„izǿ¹Ϳ[B9[­uɹo[Kzc(( (BK[cioouc[ouu·oc1 (KKBz1((((91ouozuoouSKuiišoizcciɚ9uǦuzo(9coɹBcĖciͰͦcoĀzuɳcuB1c[ǹiiĹɞuĹo[SSi1 ([iiizzc[KiѢzuS9 KSBz(SucuuiS[S[zooĞuuicoo‰c ɚuz[1cuzžuB׼uo[iǦzͿ[cϭ­KBB(czzͰ·zzzuļzS99ci1(((SucKKoi[ccuǖouc991BSKci zuzozzicicijz[iizͪ[(ou‰zz9Kiuušo[Կo[[·¼oiϢcc¼zĭĞK9911ϹĢz[zi¹i91S9( Kzo[BKS[oiiou¿zuicBS91(1z1  BucSczozoªuiS[ozɼou[iu„oc1ScǹzuB[[iǢoco˿uozǰ¹ɪͦuSizzļǿĦB191BĿԼooշĀ111 iz[9BKKK[iouzuuzc[KB11zu  1uicSoiiK1Suu·zocuiji9[cǰozSScɿzKuu˼ĞouSoǰ˿Ŀ˿dz˦B191BcǼǼuuϭ[ o9 (izSBBB911ouªuoouzi[9(BzK(  1ziiSiocS1cuuzzoĒu[BKS–uucKϳSzuouɼǦiiɞzz·Ǽ[(119Sϳ[[1(1z( (1[ooK1111(1oϦu͞ozcuuS1( (oz9 (oiuuzz9SooBcoo˞zcKiioɳoBBǰcuijuoiͰuzSɳzioǪɼuɀcļS 1 BSc˿oci¿B((9BB Bcuuu[9(( ((BuzuϢu¿izSzc9((( Ku(cc[ozooBSzzioBKiu·zoĀBKdzi[[ԳcɍicϹuKѿzu[iѳ¦oSzB1 S[i·u[zzcKK9 (iK9ozzo[9((( (cocoi°Ϸzzz[SuzcS9(((11uuz (( 9iozuciS9[užcz[Soo˒zzzҞioԼi[ouzճcĀioĞiiѷiuͭBiķuKK„[19(cK˼oicc[KK(1[u9(cozuciK( ( ( 1[cizozozKKicSS9(11BBz[ (((izioBBoozuzzouzzuuzo„Գi[zoocˀuioucDŽouĞѦScѳoKĖouBc[ҷzizo[uB1cS99[uB[ooi[S(  (9[cozioҰouzSSioSKK9(9KBSi((99 Szuoi(B[zoozuzzuuoͭ˭zcicuuzozzo˹oͼzɭzS‰˰zuiS˪iiͳouzzc1BouS[ouucS[S9( 1K[SioczoϷcoKS[iSKKKKSS9cou B9([[[[i(iuoouuužzzĹS(Kuzzzoo[ҳiuϹzǖuϢc˿[o¿oĹizK9KuuiSi[B9   BocSiozzcKzucSBKB9KS9i[ B([cSSc¼SBuz[ɿzocǚ˼zz[([zzziKcǢcK׭zǰdziɖ˒°Ǽcouĭui[oo[( 1uSiѰzooScuSBBB( 9KBizB(1BuzcoǿB(Bi[iԹϭuzBѷuSK1 9zzciSzԿcuҖuoҿͭԖdzljzѹooozϼz³oɖoS9 [ccɷ͹oooSooSK1( 9Bcoc (9ou¿c(1[c1 ϹͼSͿuiuS((B[zocuizuiڪuo„iizžouϞϰϼ·zuu˹zǼi°zi[1  (BouuuǪzziKocKK11(1BBzzK( (oouiuziB9(c[iiK˳u¼zuui9( 9[oz[uiuٰuo͹cuǹioѢuª¹ǼĹͼ­ĿuiiĹuzi[B (11BSz[’zuizzoSco[K9(999KSc  [zccSiz[cB1 ciS[B1c[ɚiuioiK1((1[oi¦zǿzo¦czѪcѼ˦ĞͿzooļozdzɪzSKB( 1BB9KczcĢuoKc[B(9BBBSio  (ouzo[KKK( KicccouļzcouzozcB1((1(9icٹzccĭzzժcϞouuϰĢҦ­ouĹzzi[B1( (KK9BScu[cļ˷ɷuuSc[91991iozK (1ciuS1(91 11Sz[KcuuzziozzzziK1(( ( 1SSoҪuz[SĞzǪoİzѼouzoķiªzzz[SB  BSKKSuuBzcɪu¢zSci[[S9 (((i (1izzB99(((11KucBB[ooouozzS( ((1( 19S[z˿ɳozoSu˞z¢uzoicɹzzͼuoǼɿĿuĪ[oozǿocccSB( 9[SSKSuuii9BScSKB(( ((Bi(KĦcoozioB1(  11 99K99BuocKKSK1(  (BSczķozc͖zĚzicǪzouͷu¹uİɰª[Ǽ¼iuuiͿiSoѢiS1 (9SSKKBKuzczǭ¹uijiKSSSKB9((((9oB9o[[Kc³Kc9 ( ((119199oi[coS1( ((119 19KcKĹѢķªuizˢiuͪ³cϿϰķuouͷizicz³iS9(BK[SB9BooozozҰizKS[[[S9( (9Sz(KzzzicuuK( ((1(((11 ((9Szuc11 1(( ((9B9S[SK[oɹijۭѼooѭiǚuu˰ziuɳucǰzKii91  9KS[[SBKiizz³o[iocc[K1(( 11Si(cio¢zS19(( ( (91 ( (1B[oocS(  ( (119BKBiɳ¹۷ɪuͦoužz[ǖҳɼ°zuzoɹ[ouoBo·uK1( 9ScS[cKBco˹ͳzBouc[SSB9((91[zB(uSK9 (9(((((((11(( ((1KSKK9((( 11B[BB1Kҹͼ¹Ϧuz’oҭocšiǞĭɼĹɼĿouiҿ˦uScSoozzu9zžoS1(9S[cS[[KczzϿSSKuuiSS[KB91119zz(([ĹiK( 9991(11 ( 9SS[SKB(1[coi[iuzѰļuĖu[ͭccϭiɼiɷ³·ĭɰǹoiuĭSzzcKo9(  9B[SS[cciіu˹zuS[cuuc[[9(1((Bc z³˰c((1( 91(1(   BS[S[SKBB[izui˹odziiɢ[oǚuiǪBɹ¿¼¢uco°uoĦǷo[izB(  B9BBKS[z·o[cSK9( [B(oS (1(( 11((( ( (9[iiioouzz߿ǹ͢u˰zͭzz˼iSuͰuzš[zozĭcK[oK(91 1B19BBBKɳzz[uoSK11 ( co9ijK 11(1(((99111(  1cuzzzziSo¼zuǰԉİz¢ĿuĹioǦzzi˼zzϹz˹zoKoK((1( (1BBBKSKBɷoioc9 ((((z[cտz111191199111191((1SzuouoKKK9[ѹɰijSϷoĿzzɷzzļu[˳o[oϭ¹ouijSKzuu( (19999BSSSSBouizzc9((( 1Ko׼B((((1( (1(19199991SuuoK9[u[KBS[zҼ„(KͰuDŽiռozoԿljuio˚˪udzɉǰicuzͰzKoz°oic11999KSS[SKz­uɞzuic[cuoS9 (1((1ouѰu( (( 111(19K[Sozzz[K(iϷdzɳªu–ooͳziz–ĭ¼ͪuzǞͭϰoĢoBSͼ[z[iļuuzB  (99BBK[[SuĚļocKou[SB 9 (9oɿ[u ((( (991(9B[iuuz[Sع[oɼ¿ܚzc¢ziϿĀuiuzϭzSSϼo u¹zoB ((  9KKKS[SKKiiicBK9((1 1Kucio[ ( ((  (((9KScizuuɦ¢izBc³zфzĹҹioϼoշozzuo·zuuoɳu9iB1(191(9BK[cccSKBiioiK11911911[cozuzoKB1 ( (  1BK[S[zu԰³ozu͹ĭuǰoo¢’iǞ[ɳzoi͹u9³o[o[9( ((1BciocSKKKKKuĹ­SSSB( 199KKSziBccSSSK999SoS91  11(((1 BSKS9ui[Ϳªǚ(c˳¼³K[zz°zzzzǹuɄiǪɼu˿zo˭BKuBSS9   9oucKBS[SBKocͷ˭ͷo[B19B99K11BK[K(S1 (((cc 9 (BKK9BcKK9KSB9ioBc­ǹ[czoouݼiɿiiuuoҹSiسuǭ¹uĚ·ԭu͍z¦([zu[SS9( Buc[[SKKKK[uc°uKBSB9B9111BBKou((1((11(1 Bo( (KKKSuziSSBoz[BSذzK1BKѼĹٿzzooo˰zuѢuzǰuijªչu˼ zzoicK(  ScS[iSKSScizɒѹzSK[SBB 9KK9i1 1 919BSS9 1S[SuBzuB1KoijccϳѼcuɳzc[ϰuĒļuǼdzǖziuɳu iudz[[SB  Koo[[[[S[iѦcKKBB9(9K91ui ((1911BSz9 ((   19Kouz͹iBcǿžcҿ˹uzzciĿzoz[Ěicɪ·ڼzz­i1ocoo[B9(  KiziczĢoBKBBK9(9KK9SzK 19919911[B  (1K1Si͚Ko·˳oǰԦzuuo³¹zzziͳciѳuϦdzĹ¹ĦĹK̈́zouS11(  ([izSzciǰizzǞzo[SKSSKBBSBKo9 BKB9911S  ((9[ooz˳Bع­ucK[ɷ˹°uĖoocuɿuzuiǿuoǖij˷ǿķ°dzSoǭc 1oouz°uzcuu[KKKKKSSS[BcB199BB1( c[  (((9So͹ǼzSҷ˄c[oc[ļբKu°uuuuİuiĹļz·İɷɰͼBi(  1([İc[uu–coתuoiiǹĒocKSKSSSSSS9uo( 999999 oB Bzo9SiڼɿɼSBozѷļzžozĿªuuz˿Āļ¹˿ϳ˰uS9   BKSo[[uĞњ[ccožuiKKBK[[S[K[9 (191( (oB 91BKoocudzķɼتcoz­˼ĪǼzķ·zuĿoɼĿĭij°Ǟҿ9(( 1BcczzzicKSouªuoKSBKSSSSKS1((((( (KBc[҄BzԷijzļĢͪoižzտѦ‰zzuzϭzoĹѼļij³zoo9(1(Kioi¢uzozoiǰoBBBKS[[KKoB11 ( 1[icoҖSou[cԷɹ˭dzo·iiϦzouocǷĿĹz˳zcS9((  (9KK1[zcuuǪǢSizzSuiKKKKSS[Bou9( (1119[iuSzᳳcu[SiS[zҿɿɉzҰuiB°zo[ozucuǖ˿¹¹uo¦uĦKB9(((1K[[[BK[o‰SͰ³ioɪ[uczcKS[SSS[[SBB1 ((( KoSչѼz[uuoK[zozuҳ͢[ioѿĦoķczi¹ouiouu[i­dzǰu˿9BB9BBBicK91iicǚ׼oi˦ɞcz[o[KS[SKKS[ziBcc1(999Szzoǰc[[¢i[Kuzz[uSzǰiǰoSioķǼiiɭǷĭĹԼļzǹBSS999BcB( KuSK˳zǢuozu˼Ԗšzz[cS9BSSKKSScz9([[S9Bczϭzǹ„iooS9zczoωSiҿooozdzioi԰izǒ˭˪ķ¹ɼҭ[[[K9991((9ciSK˿SuijdzzoSK((K[SKK[9[K1KԪĭɰziouc9[uoiooozico˹zǹͭžİoɿϰ[[[SB1( 9KKKBKSĢccczz[ozuuic9(9K[SKSoB BKBKoؿķ·iuɦKKB(uoizcz–˰u¿ijĄɳ¼oռ[SSK1 1[S9Kcu˭ozͪczozzouoɚci[1zĹi[1BS[SSK[o((19K[oioǼ³ªooĞ[BBB1uoc[ccouuњǼĹĪzɼɭizuĖ˼³ķuĿ׿ϳ¿·³zzzuzzzzķ¿˪¹ͭ·¿¹˷ޢĒɼύizɿǼzzzzzĿĿļ׳ǼǞ¿¦’߰Īіcܦi¼¼ǼzzzɿҦ˿ɞķ·ῢķĄѳܢii€c¿¿Ϳǹɷɖu¼¹׷ǼϖךҹuioǍo³¼¼¿ĿǼ¹zǰļ¼Ěu¿¼ɼ¼Ħ¹Ŀ͢ϒϦouzժu[¿°ǼǷǼǷzķª¿Ħǰɳҳ¿¿¿Ͱ͹uԼzouuuc[ǰ³zĹ¼Ϧ˳˿ͭĢ¿¿ɿ°¿Թzuuuuuzdzzuz[zuKªªzzijɷѹͷ¿˪ͳļͷ³Ŀ¿ĭɿzozz[ѳuuizuzuzɼ˷zzzķdz˭ĖǿǰǢǹ˼˳·¼¿°Ҽciczo¹zzļǿ¦zuzzzzzɼǦɞǰٷѿĿɼdz¼¿ciicķ¿ϳzzzzzzzzzİǼͰļɪijͪ˰ǹɿu¿Ǽooz͢zz[˳ǿ¼˳Ĺzzz­³·ɪ³˪¿Կ˳ѿļ[¿ǰ˼cuzǍzzzSĭzzĿ°˞zǭĿ¿ǦĹϢz·ĿϷѼ³ҿ¼¹¢ccooociuzuouoҿiuͳoizocϪzz¿Ϳ͹°ĹĿԷͭ¿¹ϼɪϰİǷĹzzuzzKڢiioǦucizzBKSzuu¼ϿǦzļǪ¹ͳͦĚuǢͷ˼ɷo¢檍oi[ԭuzoc’iicczc[ozĿǿ˿zz˿¼ij˖׹uͳǪͭ䞍uc[S·ǼշĀoѰķzoB911(( 1[SBS[c¹uzҼzzzzuuzzouS1B999( 1((Koczzǹuz[zuuou¦9BSBSci˖z¢¼z׼oij׼˰iK[Ŗu·ɰ[iسzciu[S9(((111io[SSuciijzzouoooS(1911KB919uɢBiocz’oucizzǷzijuBuoBSScԭuѼz޿湍ϷǰiSɹϹǷǍz³z[Ҽzo[zcS111(999iu[Kcoi¹uouuz[(91(((9BBSɷǭuzzzzijo[ouٳiĭɳɼĭڹĪciϳѦ¢Ě˳Ϳ˼zu[cҷzuzĿui[9((19BKcuSSuͼiS¹·ĦzuuzouS1991(11(1[·zɪzi[u[ϹuԿiodzķĹĭ˚oizzu׭ɚouijªzouzco׼oo˄uSKS9(919K[coiudzuS¦ɦuozzzzuS1(((91( 1uu͚zzi[zͿǪ[u͉ωzoz˹·ۿ˰ϼ˖zǹž¼u׳Ϳzz[cuiĭzoǿu[zĢuoBBB1(( 1BKSouuoicĪiioioozuozcB1 ( ((K˚uuoiiǒozizdz¹Ku͹zo҄uoǪ¦ªϞuuɳu[iouĒǦzcSucKB111( (919SzuKuoziɼ9(SuoiuuocS9191((( ([ǢϹuiooϼzi[Kouu˭zɿoǼiuozuuǚ¢ɚݹɞiozzǼĹ³¹zii׼˿uizo[ooc[[91 (((9[ozi[[zzc[˷9BciiiuB11111((( KuĢϷu[1[i[u¹ɿ˒cžuɷĭz޼ǷĿiozzͳdzϿzzzii׹ǹzuɹiKouo[K1(  1BKBSKuKS¿ķuiuociK111((((1( 9u˪ͷz[couoϰǞuٷɪĞǭuuzխږհioc[·Ǽ˪Ko¼zcKiB91   BSK19izooKǼ˹zzuuuS111(((((1 SoĞ¿uooǼoizحizuzɼἍļĹĪuucҰļɦϰǦziu[9ϼSuͳzS1 ( (  (Sc[S[c[BKuzo–­Ϲuzzuzi[91(1(( BͷozoucoѳcSKoš³zϦzǿϦoidz¦oocSczĦKoªzoK9  199SiozzucicĿ·uoooiuu[zK11119(11 B¼Ǟi[iuiiciuzziİc[uoizuɰuuuz¿Ŀɿuu׼ɰڿui[c[iˢ˰Ƿ¢uSoucS1  (1BB1Kiiuuooc[ɿcuoooozoB[c 1(1( (19((Kz°zucciĭicc[KSccuuiĚ¢zozuoiͳcɰͼzzuc˦ͪdzucc[So¦˷ǹcKzzi99   (9c[Siziooc[[iooiǼKczoooi[9cu((1 (11(1z[iozİzizzccoSKS[SSizczšˉzuzuҿziz˿ǖͷɼouoKѼdzijoiKSciͷķ˰BiiocK(  ((1B[izuoiSc[[z[oouo[K[z((1( Bu[[cuziɷzzuSoSc[KKSKKuuc[ĭѿu˖zuǭoĪdzǹ¿ɿɭci[c˰ǹǼoccoKS˷dzi[zu[(  (9cScoSiucoiuiKcK((( ioSicuBi³zioտcuuǦKKicKSSizi[cĞ˚oz¹oz˪uǭǿ¿ɰ¼˿ĹuoSoİԼسzocicKS˳zuiiuiK  (1SucoĿĦo[uǿ˰ozoiocSz[( (  9[czSuuozizč[o·c[[ic[[zuiS¦ǚuuɹҞ˞oķɭ¿°u[ͦļuuooc[[ǰɳzBKK1( 9cuuiͦļocoziSco((  (ciczoucuuuuiScĪz[[uucizcc­ǹўĖiˢ¿·zco°׳udzou[K[ǹϿSoSB    [oozcu[iҳķSScoiSKoB (Bzoc[ziiizoouuuiciǼozziiuui[ozѭ͢ǹ–zu¦ijİ·ioijzoci[Sz͹ɹ(KK1  9uuzzuSoĭ˭­o1K[[[KSc1 1zziiciuiizoo[zĿzoicSSiҼzo˳ĭuSĪijҿɳĭouiioz˿·[ĉ[9B9 (1 (cu¢iuǢB 1BKcKuK1   (uzccc[o[zɼuoozuoKoҷĪi[SKcҳǚiozճɖ[Ğǿؿѳ­cطuuzzoi¦¿ĄKc[K9(((Kzoٳɳoi[SK[cK91(  czoizooouocĭuuzuuzuizzzĖoǰzoo[Ki„zǪuɷɭǰĹķ–i[ļidzzzzuo[KiɰSuļzKKBK9( (Biiiiϼoodzc[u( (BucoczoĿɼzuϰuހuzۢԚiɭаzcc­uozzccK9[dzSѪz(((1K9  9[uSz˹uuzzK   [u[iizu˼uiiu׷z緍uz˿[˒uĦĢɳªͭļ³zuzuǿzuicc[B[­ĭϞ[ 1B1 ((  (izioz[˿oucoiz111   1oc[zii[cuǷSK[uĭucu䳚oͷoǪ°˼ͷѹؿҰdzĚuoĹuuicciKuijuijuoz1 BK1   Ki9uu˼z[iKKBKcS19(  KzciooiccoSzzuozziSioϷzciiuĿɖzuczoz˞ͷϿ˷ݷɼѳ͚izo­[S[S[·uzu9[oB (((( 1BooSuoķi[z[c[K1(B[9( ( iuiicc[BciiczzuuzuSoz԰ooc9czžiSzouzu˦̰ҹտɖǼɹizɼKBB1cǹuzKoz9   (11BuozĞzucK(KB91 9ic ( (1izzuuc[S[[uijzi[coouuzz[izoiɖuzc9SuҷuBo–ǰĢɭ¢ĿķiɿuKK9BǪizoS[z9 ( ( ( 1Soiioo[( 1( (Bz9  9iuiizuoo[KSoĦoooizzicziҳu[S[cϼKuzɿuciĞ˖Қ¼ǰ˭–zǼoSKBcͼ·ciiS9c(1KKSSB( (Suzzuo[[u[1( (9Si  (  9uzcucicSczǹzzucicc[izǞcK[uuɒuizzɼozuǷǞɢϳ¦¼ϳ¿¼ѹuSciuiuiK9Bo¦izǦzcoSS9iu1Kc[[SB91(9couco[Sic9  (BKcK   ( KuuiicSzuziu¿¦ucSSKcѼcBioǷzzoS¹uzҳzuչɞzdz°ɭؿҿKSz¿KK9iԞicĭu[[9[u[KB91 999 o[zǷiuiSi[9((1B[   ( izuo[cooͿKK[oİuuBuuͿuo[B[¦icKǼ·uҹczɷϷķϳɪz1iicBKBoĒ˰o[͢occS[K(  11(SuɷǢoiScK91 (9Bc[ ( BuooS[zĹKcuoo[1iɭiBcuٳoi[[Ī˪¢SKzuĪɷѷļԼ¹Ŀžc [u˿SBB9K͚[iKS[[ii (  czzĢuoiB1(1KK9oz1 [izuiouKi˼zuu[K[oɿzczɞzzuici­zͷoui³ɿķҹ¿š9 (KoڼBB91KҰiuķKuB[SSS1  (( 9uuzuzSccB9KS[K(zu  (S[u·uoouBo׼oic[iҹzczoz˿zɰ͚ioiu׼’99(((BcطǢKccS¹cuǭo[cSB11(   [zzcKSB(9KKSB1[( (  9zSczcǷioooz[iշ[uKS[­z[zoҹuuϹouoϳzǰ¹¿ɷҿѿ9(BSS³zoS[oĦzcziB9K(   (izzɢzczoBB9( 1KKB9[zK111 zoSiz[S­˼zuuzu[ͰcSB[iѳBcoϳuuzoooǭzբzz˿ĭϹ˪c9K cBK˷ooɰ[uϹ[1cS   (uuuuuSS9( (9B99u1  ( ([ocSBSijozooKuzɭiK[zĞiuuͼzizϼϖݳ¹ɹͳɭziK[oªBKѰoo˹BѰcScK   BuǞǍicK9( 1B1Kui(  ioiu[ciuiz°ioiKSicziBiѷouzɭSͦuɒͳuc[oɦļɳ¦ǦzuKuijS[ѷooSu1Kc( ([iljɢuzicK( 91ozS   9iuczzuzϞooKKu·uS1[oϭBiؿzuͳoz˭zuccoSKSižɼǼ°Ŀ·ժiizͼuzzuc(cS( (BSKiz·¦iiiB(( BBz9 ( (( uuioBouzu۳uu[i͹o[9cuǖu9uצoϼzzoǖiu[9KuzzԿ·˭[[uͷz³oui9B 1( (BcccooĞzªci( (99Kczc((( ( 9 (zc[co[zzoz[ooicoǞuccci˳zzBKoo[o͢ziozǹu[ii„izǿ¹Ϳ[B9[­uɹo[Kzc(( (BK[cioouc[ouu·oc1 (KKBz1((((91ouozuoouSKuiišoizcciɚ9uǦuzo(9coɹBcĖciͰͦcoĀzuɳcuB1c[ǹiiĹɞuĹo[SSi1 ([iiizzc[KiѢzuS9 KSBz(SucuuiS[S[zooĞuuicoo‰c ɚuz[1cuzžuB׼uo[iǦzͿ[cϭ­KBB(czzͰ·zzzuļzS99ci1(((SucKKoi[ccuǖouc991BSKci zuzozzicicijz[iizͪ[(ou‰zz9Kiuušo[Կo[[·¼oiϢcc¼zĭĞK9911ϹĢz[zi¹i91S9( Kzo[BKS[oiiou¿zuicBS91(1z1  BucSczozoªuiS[ozɼou[iu„oc1ScǹzuB[[iǢoco˿uozǰ¹ɪͦuSizzļǿĦB191BĿԼooշĀ111 iz[9BKKK[iouzuuzc[KB11zu  1uicSoiiK1Suu·zocuiji9[cǰozSScɿzKuu˼ĞouSoǰ˿Ŀ˿dz˦B191BcǼǼuuϭ[ o9 (izSBBB911ouªuoouzi[9(BzK(  1ziiSiocS1cuuzzoĒu[BKS–uucKϳSzuouɼǦiiɞzz·Ǽ[(119Sϳ[[1(1z( (1[ooK1111(1oϦu͞ozcuuS1( (oz9 (oiuuzz9SooBcoo˞zcKiioɳoBBǰcuijuoiͰuzSɳzioǪɼuɀcļS 1 BSc˿oci¿B((9BB Bcuuu[9(( ((BuzuϢu¿izSzc9((( Ku(cc[ozooBSzzioBKiu·zoĀBKdzi[[ԳcɍicϹuKѿzu[iѳ¦oSzB1 S[i·u[zzcKK9 (iK9ozzo[9((( (cocoi°Ϸzzz[SuzcS9(((11uuz (( 9iozuciS9[užcz[Soo˒zzzҞioԼi[ouzճcĀioĞiiѷiuͭBiķuKK„[19(cK˼oicc[KK(1[u9(cozuciK( ( ( 1[cizozozKKicSS9(11BBz[ (((izioBBoozuzzouzzuuzo„Գi[zoocˀuioucDŽouĞѦScѳoKĖouBc[ҷzizo[uB1cS99[uB[ooi[S(  (9[cozioҰouzSSioSKK9(9KBSi((99 Szuoi(B[zoozuzzuuoͭ˭zcicuuzozzo˹oͼzɭzS‰˰zuiS˪iiͳouzzc1BouS[ouucS[S9( 1K[SioczoϷcoKS[iSKKKKSS9cou B9([[[[i(iuoouuužzzĹS(Kuzzzoo[ҳiuϹzǖuϢc˿[o¿oĹizK9KuuiSi[B9   BocSiozzcKzucSBKB9KS9i[ B([cSSc¼SBuz[ɿzocǚ˼zz[([zzziKcǢcK׭zǰdziɖ˒°Ǽcouĭui[oo[( 1uSiѰzooScuSBBB( 9KBizB(1BuzcoǿB(Bi[iԹϭuzBѷuSK1 9zzciSzԿcuҖuoҿͭԖdzljzѹooozϼz³oɖoS9 [ccɷ͹oooSooSK1( 9Bcoc (9ou¿c(1[c1 ϹͼSͿuiuS((B[zocuizuiڪuo„iizžouϞϰϼ·zuu˹zǼi°zi[1  (BouuuǪzziKocKK11(1BBzzK( (oouiuziB9(c[iiK˳u¼zuui9( 9[oz[uiuٰuo͹cuǹioѢuª¹ǼĹͼ­ĿuiiĹuzi[B (11BSz[’zuizzoSco[K9(999KSc  [zccSiz[cB1 ciS[B1c[ɚiuioiK1((1[oi¦zǿzo¦czѪcѼ˦ĞͿzooļozdzɪzSKB( 1BB9KczcĢuoKc[B(9BBBSio  (ouzo[KKK( KicccouļzcouzozcB1((1(9icٹzccĭzzժcϞouuϰĢҦ­ouĹzzi[B1( (KK9BScu[cļ˷ɷuuSc[91991iozK (1ciuS1(91 11Sz[KcuuzziozzzziK1(( ( 1SSoҪuz[SĞzǪoİzѼouzoķiªzzz[SB  BSKKSuuBzcɪu¢zSci[[S9 (((i (1izzB99(((11KucBB[ooouozzS( ((1( 19S[z˿ɳozoSu˞z¢uzoicɹzzͼuoǼɿĿuĪ[oozǿocccSB( 9[SSKSuuii9BScSKB(( ((Bi(KĦcoozioB1(  11 99K99BuocKKSK1(  (BSczķozc͖zĚzicǪzouͷu¹uİɰª[Ǽ¼iuuiͿiSoѢiS1 (9SSKKBKuzczǭ¹uijiKSSSKB9((((9oB9o[[Kc³Kc9 ( ((119199oi[coS1( ((119 19KcKĹѢķªuizˢiuͪ³cϿϰķuouͷizicz³iS9(BK[SB9BooozozҰizKS[[[S9( (9Sz(KzzzicuuK( ((1(((11 ((9Szuc11 1(( ((9B9S[SK[oɹijۭѼooѭiǚuu˰ziuɳucǰzKii91  9KS[[SBKiizz³o[iocc[K1(( 11Si(cio¢zS19(( ( (91 ( (1B[oocS(  ( (119BKBiɳ¹۷ɪuͦoužz[ǖҳɼ°zuzoɹ[ouoBo·uK1( 9ScS[cKBco˹ͳzBouc[SSB9((91[zB(uSK9 (9(((((((11(( ((1KSKK9((( 11B[BB1Kҹͼ¹Ϧuz’oҭocšiǞĭɼĹɼĿouiҿ˦uScSoozzu9zžoS1(9S[cS[[KczzϿSSKuuiSS[KB91119zz(([ĹiK( 9991(11 ( 9SS[SKB(1[coi[iuzѰļuĖu[ͭccϭiɼiɷ³·ĭɰǹoiuĭSzzcKo9(  9B[SS[cciіu˹zuS[cuuc[[9(1((Bc z³˰c((1( 91(1(   BS[S[SKBB[izui˹odziiɢ[oǚuiǪBɹ¿¼¢uco°uoĦǷo[izB(  B9BBKS[z·o[cSK9( [B(oS (1(( 11((( ( (9[iiioouzz߿ǹ͢u˰zͭzz˼iSuͰuzš[zozĭcK[oK(91 1B19BBBKɳzz[uoSK11 ( co9ijK 11(1(((99111(  1cuzzzziSo¼zuǰԉİz¢ĿuĹioǦzzi˼zzϹz˹zoKoK((1( (1BBBKSKBɷoioc9 ((((z[cտz111191199111191((1SzuouoKKK9[ѹɰijSϷoĿzzɷzzļu[˳o[oϭ¹ouijSKzuu( (19999BSSSSBouizzc9((( 1Ko׼B((((1( (1(19199991SuuoK9[u[KBS[zҼ„(KͰuDŽiռozoԿljuio˚˪udzɉǰicuzͰzKoz°oic11999KSS[SKz­uɞzuic[cuoS9 (1((1ouѰu( (( 111(19K[Sozzz[K(iϷdzɳªu–ooͳziz–ĭ¼ͪuzǞͭϰoĢoBSͼ[z[iļuuzB  (99BBK[[SuĚļocKou[SB 9 (9oɿ[u ((( (991(9B[iuuz[Sع[oɼ¿ܚzc¢ziϿĀuiuzϭzSSϼo u¹zoB ((  9KKKS[SKKiiicBK9((1 1Kucio[ ( ((  (((9KScizuuɦ¢izBc³zфzĹҹioϼoշozzuo·zuuoɳu9iB1(191(9BK[cccSKBiioiK11911911[cozuzoKB1 ( (  1BK[S[zu԰³ozu͹ĭuǰoo¢’iǞ[ɳzoi͹u9³o[o[9( ((1BciocSKKKKKuĹ­SSSB( 199KKSziBccSSSK999SoS91  11(((1 BSKS9ui[Ϳªǚ(c˳¼³K[zz°zzzzǹuɄiǪɼu˿zo˭BKuBSS9   9oucKBS[SBKocͷ˭ͷo[B19B99K11BK[K(S1 (((cc 9 (BKK9BcKK9KSB9ioBc­ǹ[czoouݼiɿiiuuoҹSiسuǭ¹uĚ·ԭu͍z¦([zu[SS9( Buc[[SKKKK[uc°uKBSB9B9111BBKou((1((11(1 Bo( (KKKSuziSSBoz[BSذzK1BKѼĹٿzzooo˰zuѢuzǰuijªչu˼ zzoicK(  ScS[iSKSScizɒѹzSK[SBB 9KK9i1 1 919BSS9 1S[SuBzuB1KoijccϳѼcuɳzc[ϰuĒļuǼdzǖziuɳu iudz[[SB  Koo[[[[S[iѦcKKBB9(9K91ui ((1911BSz9 ((   19Kouz͹iBcǿžcҿ˹uzzciĿzoz[Ěicɪ·ڼzz­i1ocoo[B9(  KiziczĢoBKBBK9(9KK9SzK 19919911[B  (1K1Si͚Ko·˳oǰԦzuuo³¹zzziͳciѳuϦdzĹ¹ĦĹK̈́zouS11(  ([izSzciǰizzǞzo[SKSSKBBSBKo9 BKB9911S  ((9[ooz˳Bع­ucK[ɷ˹°uĖoocuɿuzuiǿuoǖij˷ǿķ°dzSoǭc 1oouz°uzcuu[KKKKKSSS[BcB199BB1( c[  (((9So͹ǼzSҷ˄c[oc[ļբKu°uuuuİuiĹļz·İɷɰͼBi(  1([İc[uu–coתuoiiǹĒocKSKSSSSSS9uo( 999999 oB Bzo9SiڼɿɼSBozѷļzžozĿªuuz˿Āļ¹˿ϳ˰uS9   BKSo[[uĞњ[ccožuiKKBK[[S[K[9 (191( (oB 91BKoocudzķɼتcoz­˼ĪǼzķ·zuĿoɼĿĭij°Ǟҿ9(( 1BcczzzicKSouªuoKSBKSSSSKS1((((( (KBc[҄BzԷijzļĢͪoižzտѦ‰zzuzϭzoĹѼļij³zoo9(1(Kioi¢uzozoiǰoBBBKS[[KKoB11 ( 1[icoҖSou[cԷɹ˭dzo·iiϦzouocǷĿĹz˳zcS9((  (9KK1[zcuuǪǢSizzSuiKKKKSS[Bou9( (1119[iuSzᳳcu[SiS[zҿɿɉzҰuiB°zo[ozucuǖ˿¹¹uo¦uĦKB9(((1K[[[BK[o‰SͰ³ioɪ[uczcKS[SSS[[SBB1 ((( KoSչѼz[uuoK[zozuҳ͢[ioѿĦoķczi¹ouiouu[i­dzǰu˿9BB9BBBicK91iicǚ׼oi˦ɞcz[o[KS[SKKS[ziBcc1(999Szzoǰc[[¢i[Kuzz[uSzǰiǰoSioķǼiiɭǷĭĹԼļzǹBSS999BcB( KuSK˳zǢuozu˼Ԗšzz[cS9BSSKKSScz9([[S9Bczϭzǹ„iooS9zczoωSiҿooozdzioi԰izǒ˭˪ķ¹ɼҭ[[[K9991((9ciSK˿SuijdzzoSK((K[SKK[9[K1KԪĭɰziouc9[uoiooozico˹zǹͭžİoɿϰ[[[SB1( 9KKKBKSĢccczz[ozuuic9(9K[SKSoB BKBKoؿķ·iuɦKKB(uoizcz–˰u¿ijĄɳ¼oռ[SSK1 1[S9Kcu˭ozͪczozzouoɚci[1zĹi[1BS[SSK[o((19K[oioǼ³ªooĞ[BBB1uoc[ccouuњǼĹĪzɼɭizuĖ˼³ķuĿ׿˼ǰɰǹ˿ªĢzBoĞڷϼͷ޼ϷiɼcKB1 1B(1(1BS1911( (ci³Ĺ¼[9cSioKKKBKBBSS1 (1((( ((BuzuBcuuz[1Sɿ¼Ǽ߰ͼ¦ǦռoǿժڳϿcĿK9BB9KKc9B11K[SSB91(1zuu˹ǭuKBcKc[SSKB91BB( ( ((1( ((((9Kuouooozoi[ϼ·˳ķĭϼͼĚcB1¢šuzK(1BBKoSiS[SBBS[S91KiiiĭzocoSKcuzzoBziKBB99999 (((KKK9 ((B[cucoou[SiuziSiĦݦռĿİ˿ɭSij„K9᭷տiušuK1BKBBKuicu[BKS[9(19KcĢ€ouB1KczS9BBSuiuSKK9119(((((Bzi(1( ScBoiuuuzzzzKizizzozičఖ͖oɼҿǭoתBͳcɭͳz91K[KKSizzo[K9BKB1(Sou11BKuc11B1BuiuiSSB( 191((([SiuK 9[SKS[SuuoSuczzzuiu࿉跚͍ϖ·Ѫc˳zo͒މz9ڼǿǦS 9c[K[SiuciuozcccB(BK9BSzoK11SoṪiBK9B[SKucccSKcB(1(99 11uzSBBzK1KS1B[oiouzzuiouǒ忞ǿϼװzozɼiϪ׹Ԗ1(ɹo([ic[[Biiii[ioiuucBB[SKSciSSicĞuiS[[[iiccu[ciS9BB((9(1 1 [ciuzzǿccuB1BKB119cuczu[ioKo۪z伀oouĿɿ¦ɪzšo–oռǹu(ϰ¼S(9KS[co[czoc[SzzzKKi[SSuuu°oozucoioSSiic[K1 (KzSuSB[Ϲ‰B999B((1cozuiciB9czccoczύSǿ¿ѿɉBoͿļɳϹoicKBKScSSuzcSKioScuuuKKoS99ozzİuozcuzzzKScSScS( (9BoiccKu¦uScS9( 1BuiiuB[uKKcuĚui[i¿¿zճčuiļڿo޷۹¢cB19KSSoiSB9BSSScoKKcK19KoǪuiuoBK[919( 1KK[iiuzuiu°i[[B919Ku[Sz[SSzzK[zoS¹ɹѼ˷Kzצiذ¹㢳˷zc9SSSio[B911BizcSSKB19SuzɹczSo[oziKKS[( (((11SuK[cuiuzcϞu[9KcziouuoS KiKzo°zۼªͿ[uš[ĭɒBǹɷĭuuzoiuoK9S[KSiiSBBKKKKco¿[S[iSKSccizcKK9[i 191((BSKuzKccooSz[uzKBuc[coK9[S(9[ooizuǹϪzۿɍoļzoس–¹i[[ozzo[SczoSooc[BBKB9BKicuuziSS[[B11Bic[uoSScB(9SB[cS1 Biczoz[[ciiocuScKczc[i9( K[1KB9cuo[K߳uoѹ˖uuչɦzݍB9o˹z[SBKuuiuo[uzuoiocccKB9((1Kc[B9KK[[KB1BiuScuiKcuB9SSBci[[zcouiccSziBuSo[iBicSSBBSKK[9SucSSc[9(uuuioucoi[o࿚տǷ[iiioԼ¹蒖ɢz1(BSϢĹi[S9SoucouzciuoizuiiuoSB99199[iKBcoi[ScSSizcSoc9Su9coc[ocozzcoc[coi[cKo[(Kiiu[[oc1S[K991111((߰i[[[ɰĪz͖Kiiz¹ɢǼճͭoιiS[[zzzSKc[ioSScocKcoB1K[K91[°oBBS[ciouSSuoK[SBSiB[uzicz[i[ucSoSBKScuuSi[SKSKSoiuz[ BS91( 1((19ǼշĀoѰķzoB911(( 1[SBS[c¹uzҼzzzzuuzzouS1B999( 1((Koczzǹuz[zuuou¦9BSBSci˖z¢¼z׼oij׼˰iK[Ŗu·ɰ[iسzciu[S9(((111io[SSuciijzzouoooS(1911KB919uɢBiocz’oucizzǷzijuBuoBSScԭuѼz޿湍ϷǰiSɹϹǷǍz³z[Ҽzo[zcS111(999iu[Kcoi¹uouuz[(91(((9BBSɷǭuzzzzijo[ouٳiĭɳɼĭڹĪciϳѦ¢Ě˳Ϳ˼zu[cҷzuzĿui[9((19BKcuSSuͼiS¹·ĦzuuzouS1991(11(1[·zɪzi[u[ϹuԿiodzķĹĭ˚oizzu׭ɚouijªzouzco׼oo˄uSKS9(919K[coiudzuS¦ɦuozzzzuS1(((91( 1uu͚zzi[zͿǪ[u͉ωzoz˹·ۿ˰ϼ˖zǹž¼u׳Ϳzz[cuiĭzoǿu[zĢuoBBB1(( 1BKSouuoicĪiioioozuozcB1 ( ((K˚uuoiiǒozizdz¹Ku͹zo҄uoǪ¦ªϞuuɳu[iouĒǦzcSucKB111( (919SzuKuoziɼ9(SuoiuuocS9191((( ([ǢϹuiooϼzi[Kouu˭zɿoǼiuozuuǚ¢ɚݹɞiozzǼĹ³¹zii׼˿uizo[ooc[[91 (((9[ozi[[zzc[˷9BciiiuB11111((( KuĢϷu[1[i[u¹ɿ˒cžuɷĭz޼ǷĿiozzͳdzϿzzzii׹ǹzuɹiKouo[K1(  1BKBSKuKS¿ķuiuociK111((((1( 9u˪ͷz[couoϰǞuٷɪĞǭuuzխږհioc[·Ǽ˪Ko¼zcKiB91   BSK19izooKǼ˹zzuuuS111(((((1 SoĞ¿uooǼoizحizuzɼἍļĹĪuucҰļɦϰǦziu[9ϼSuͳzS1 ( (  (Sc[S[c[BKuzo–­Ϲuzzuzi[91(1(( BͷozoucoѳcSKoš³zϦzǿϦoidz¦oocSczĦKoªzoK9  199SiozzucicĿ·uoooiuu[zK11119(11 B¼Ǟi[iuiiciuzziİc[uoizuɰuuuz¿Ŀɿuu׼ɰڿui[c[iˢ˰Ƿ¢uSoucS1  (1BB1Kiiuuooc[ɿcuoooozoB[c 1(1( (19((Kz°zucciĭicc[KSccuuiĚ¢zozuoiͳcɰͼzzuc˦ͪdzucc[So¦˷ǹcKzzi99   (9c[Siziooc[[iooiǼKczoooi[9cu((1 (11(1z[iozİzizzccoSKS[SSizczšˉzuzuҿziz˿ǖͷɼouoKѼdzijoiKSciͷķ˰BiiocK(  ((1B[izuoiSc[[z[oouo[K[z((1( Bu[[cuziɷzzuSoSc[KKSKKuuc[ĭѿu˖zuǭoĪdzǹ¿ɿɭci[c˰ǹǼoccoKS˷dzi[zu[(  (9cScoSiucoiuiKcK((( ioSicuBi³zioտcuuǦKKicKSSizi[cĞ˚oz¹oz˪uǭǿ¿ɰ¼˿ĹuoSoİԼسzocicKS˳zuiiuiK  (1SucoĿĦo[uǿ˰ozoiocSz[( (  9[czSuuozizč[o·c[[ic[[zuiS¦ǚuuɹҞ˞oķɭ¿°u[ͦļuuooc[[ǰɳzBKK1( 9cuuiͦļocoziSco((  (ciczoucuuuuiScĪz[[uucizcc­ǹўĖiˢ¿·zco°׳udzou[K[ǹϿSoSB    [oozcu[iҳķSScoiSKoB (Bzoc[ziiizoouuuiciǼozziiuui[ozѭ͢ǹ–zu¦ijİ·ioijzoci[Sz͹ɹ(KK1  9uuzzuSoĭ˭­o1K[[[KSc1 1zziiciuiizoo[zĿzoicSSiҼzo˳ĭuSĪijҿɳĭouiioz˿·[ĉ[9B9 (1 (cu¢iuǢB 1BKcKuK1   (uzccc[o[zɼuoozuoKoҷĪi[SKcҳǚiozճɖ[Ğǿؿѳ­cطuuzzoi¦¿ĄKc[K9(((Kzoٳɳoi[SK[cK91(  czoizooouocĭuuzuuzuizzzĖoǰzoo[Ki„zǪuɷɭǰĹķ–i[ļidzzzzuo[KiɰSuļzKKBK9( (Biiiiϼoodzc[u( (BucoczoĿɼzuϰuހuzۢԚiɭаzcc­uozzccK9[dzSѪz(((1K9  9[uSz˹uuzzK   [u[iizu˼uiiu׷z緍uz˿[˒uĦĢɳªͭļ³zuzuǿzuicc[B[­ĭϞ[ 1B1 ((  (izioz[˿oucoiz111   1oc[zii[cuǷSK[uĭucu䳚oͷoǪ°˼ͷѹؿҰdzĚuoĹuuicciKuijuijuoz1 BK1   Ki9uu˼z[iKKBKcS19(  KzciooiccoSzzuozziSioϷzciiuĿɖzuczoz˞ͷϿ˷ݷɼѳ͚izo­[S[S[·uzu9[oB (((( 1BooSuoķi[z[c[K1(B[9( ( iuiicc[BciiczzuuzuSoz԰ooc9czžiSzouzu˦̰ҹտɖǼɹizɼKBB1cǹuzKoz9   (11BuozĞzucK(KB91 9ic ( (1izzuuc[S[[uijzi[coouuzz[izoiɖuzc9SuҷuBo–ǰĢɭ¢ĿķiɿuKK9BǪizoS[z9 ( ( ( 1Soiioo[( 1( (Bz9  9iuiizuoo[KSoĦoooizzicziҳu[S[cϼKuzɿuciĞ˖Қ¼ǰ˭–zǼoSKBcͼ·ciiS9c(1KKSSB( (Suzzuo[[u[1( (9Si  (  9uzcucicSczǹzzucicc[izǞcK[uuɒuizzɼozuǷǞɢϳ¦¼ϳ¿¼ѹuSciuiuiK9Bo¦izǦzcoSS9iu1Kc[[SB91(9couco[Sic9  (BKcK   ( KuuiicSzuziu¿¦ucSSKcѼcBioǷzzoS¹uzҳzuչɞzdz°ɭؿҿKSz¿KK9iԞicĭu[[9[u[KB91 999 o[zǷiuiSi[9((1B[   ( izuo[cooͿKK[oİuuBuuͿuo[B[¦icKǼ·uҹczɷϷķϳɪz1iicBKBoĒ˰o[͢occS[K(  11(SuɷǢoiScK91 (9Bc[ ( BuooS[zĹKcuoo[1iɭiBcuٳoi[[Ī˪¢SKzuĪɷѷļԼ¹Ŀžc [u˿SBB9K͚[iKS[[ii (  czzĢuoiB1(1KK9oz1 [izuiouKi˼zuu[K[oɿzczɞzzuici­zͷoui³ɿķҹ¿š9 (KoڼBB91KҰiuķKuB[SSS1  (( 9uuzuzSccB9KS[K(zu  (S[u·uoouBo׼oic[iҹzczoz˿zɰ͚ioiu׼’99(((BcطǢKccS¹cuǭo[cSB11(   [zzcKSB(9KKSB1[( (  9zSczcǷioooz[iշ[uKS[­z[zoҹuuϹouoϳzǰ¹¿ɷҿѿ9(BSS³zoS[oĦzcziB9K(   (izzɢzczoBB9( 1KKB9[zK111 zoSiz[S­˼zuuzu[ͰcSB[iѳBcoϳuuzoooǭzբzz˿ĭϹ˪c9K cBK˷ooɰ[uϹ[1cS   (uuuuuSS9( (9B99u1  ( ([ocSBSijozooKuzɭiK[zĞiuuͼzizϼϖݳ¹ɹͳɭziK[oªBKѰoo˹BѰcScK   BuǞǍicK9( 1B1Kui(  ioiu[ciuiz°ioiKSicziBiѷouzɭSͦuɒͳuc[oɦļɳ¦ǦzuKuijS[ѷooSu1Kc( ([iljɢuzicK( 91ozS   9iuczzuzϞooKKu·uS1[oϭBiؿzuͳoz˭zuccoSKSižɼǼ°Ŀ·ժiizͼuzzuc(cS( (BSKiz·¦iiiB(( BBz9 ( (( uuioBouzu۳uu[i͹o[9cuǖu9uצoϼzzoǖiu[9KuzzԿ·˭[[uͷz³oui9B 1( (BcccooĞzªci( (99Kczc((( ( 9 (zc[co[zzoz[ooicoǞuccci˳zzBKoo[o͢ziozǹu[ii„izǿ¹Ϳ[B9[­uɹo[Kzc(( (BK[cioouc[ouu·oc1 (KKBz1((((91ouozuoouSKuiišoizcciɚ9uǦuzo(9coɹBcĖciͰͦcoĀzuɳcuB1c[ǹiiĹɞuĹo[SSi1 ([iiizzc[KiѢzuS9 KSBz(SucuuiS[S[zooĞuuicoo‰c ɚuz[1cuzžuB׼uo[iǦzͿ[cϭ­KBB(czzͰ·zzzuļzS99ci1(((SucKKoi[ccuǖouc991BSKci zuzozzicicijz[iizͪ[(ou‰zz9Kiuušo[Կo[[·¼oiϢcc¼zĭĞK9911ϹĢz[zi¹i91S9( Kzo[BKS[oiiou¿zuicBS91(1z1  BucSczozoªuiS[ozɼou[iu„oc1ScǹzuB[[iǢoco˿uozǰ¹ɪͦuSizzļǿĦB191BĿԼooշĀ111 iz[9BKKK[iouzuuzc[KB11zu  1uicSoiiK1Suu·zocuiji9[cǰozSScɿzKuu˼ĞouSoǰ˿Ŀ˿dz˦B191BcǼǼuuϭ[ o9 (izSBBB911ouªuoouzi[9(BzK(  1ziiSiocS1cuuzzoĒu[BKS–uucKϳSzuouɼǦiiɞzz·Ǽ[(119Sϳ[[1(1z( (1[ooK1111(1oϦu͞ozcuuS1( (oz9 (oiuuzz9SooBcoo˞zcKiioɳoBBǰcuijuoiͰuzSɳzioǪɼuɀcļS 1 BSc˿oci¿B((9BB Bcuuu[9(( ((BuzuϢu¿izSzc9((( Ku(cc[ozooBSzzioBKiu·zoĀBKdzi[[ԳcɍicϹuKѿzu[iѳ¦oSzB1 S[i·u[zzcKK9 (iK9ozzo[9((( (cocoi°Ϸzzz[SuzcS9(((11uuz (( 9iozuciS9[užcz[Soo˒zzzҞioԼi[ouzճcĀioĞiiѷiuͭBiķuKK„[19(cK˼oicc[KK(1[u9(cozuciK( ( ( 1[cizozozKKicSS9(11BBz[ (((izioBBoozuzzouzzuuzo„Գi[zoocˀuioucDŽouĞѦScѳoKĖouBc[ҷzizo[uB1cS99[uB[ooi[S(  (9[cozioҰouzSSioSKK9(9KBSi((99 Szuoi(B[zoozuzzuuoͭ˭zcicuuzozzo˹oͼzɭzS‰˰zuiS˪iiͳouzzc1BouS[ouucS[S9( 1K[SioczoϷcoKS[iSKKKKSS9cou B9([[[[i(iuoouuužzzĹS(Kuzzzoo[ҳiuϹzǖuϢc˿[o¿oĹizK9KuuiSi[B9   BocSiozzcKzucSBKB9KS9i[ B([cSSc¼SBuz[ɿzocǚ˼zz[([zzziKcǢcK׭zǰdziɖ˒°Ǽcouĭui[oo[( 1uSiѰzooScuSBBB( 9KBizB(1BuzcoǿB(Bi[iԹϭuzBѷuSK1 9zzciSzԿcuҖuoҿͭԖdzljzѹooozϼz³oɖoS9 [ccɷ͹oooSooSK1( 9Bcoc (9ou¿c(1[c1 ϹͼSͿuiuS((B[zocuizuiڪuo„iizžouϞϰϼ·zuu˹zǼi°zi[1  (BouuuǪzziKocKK11(1BBzzK( (oouiuziB9(c[iiK˳u¼zuui9( 9[oz[uiuٰuo͹cuǹioѢuª¹ǼĹͼ­ĿuiiĹuzi[B (11BSz[’zuizzoSco[K9(999KSc  [zccSiz[cB1 ciS[B1c[ɚiuioiK1((1[oi¦zǿzo¦czѪcѼ˦ĞͿzooļozdzɪzSKB( 1BB9KczcĢuoKc[B(9BBBSio  (ouzo[KKK( KicccouļzcouzozcB1((1(9icٹzccĭzzժcϞouuϰĢҦ­ouĹzzi[B1( (KK9BScu[cļ˷ɷuuSc[91991iozK (1ciuS1(91 11Sz[KcuuzziozzzziK1(( ( 1SSoҪuz[SĞzǪoİzѼouzoķiªzzz[SB  BSKKSuuBzcɪu¢zSci[[S9 (((i (1izzB99(((11KucBB[ooouozzS( ((1( 19S[z˿ɳozoSu˞z¢uzoicɹzzͼuoǼɿĿuĪ[oozǿocccSB( 9[SSKSuuii9BScSKB(( ((Bi(KĦcoozioB1(  11 99K99BuocKKSK1(  (BSczķozc͖zĚzicǪzouͷu¹uİɰª[Ǽ¼iuuiͿiSoѢiS1 (9SSKKBKuzczǭ¹uijiKSSSKB9((((9oB9o[[Kc³Kc9 ( ((119199oi[coS1( ((119 19KcKĹѢķªuizˢiuͪ³cϿϰķuouͷizicz³iS9(BK[SB9BooozozҰizKS[[[S9( (9Sz(KzzzicuuK( ((1(((11 ((9Szuc11 1(( ((9B9S[SK[oɹijۭѼooѭiǚuu˰ziuɳucǰzKii91  9KS[[SBKiizz³o[iocc[K1(( 11Si(cio¢zS19(( ( (91 ( (1B[oocS(  ( (119BKBiɳ¹۷ɪuͦoužz[ǖҳɼ°zuzoɹ[ouoBo·uK1( 9ScS[cKBco˹ͳzBouc[SSB9((91[zB(uSK9 (9(((((((11(( ((1KSKK9((( 11B[BB1Kҹͼ¹Ϧuz’oҭocšiǞĭɼĹɼĿouiҿ˦uScSoozzu9zžoS1(9S[cS[[KczzϿSSKuuiSS[KB91119zz(([ĹiK( 9991(11 ( 9SS[SKB(1[coi[iuzѰļuĖu[ͭccϭiɼiɷ³·ĭɰǹoiuĭSzzcKo9(  9B[SS[cciіu˹zuS[cuuc[[9(1((Bc z³˰c((1( 91(1(   BS[S[SKBB[izui˹odziiɢ[oǚuiǪBɹ¿¼¢uco°uoĦǷo[izB(  B9BBKS[z·o[cSK9( [B(oS (1(( 11((( ( (9[iiioouzz߿ǹ͢u˰zͭzz˼iSuͰuzš[zozĭcK[oK(91 1B19BBBKɳzz[uoSK11 ( co9ijK 11(1(((99111(  1cuzzzziSo¼zuǰԉİz¢ĿuĹioǦzzi˼zzϹz˹zoKoK((1( (1BBBKSKBɷoioc9 ((((z[cտz111191199111191((1SzuouoKKK9[ѹɰijSϷoĿzzɷzzļu[˳o[oϭ¹ouijSKzuu( (19999BSSSSBouizzc9((( 1Ko׼B((((1( (1(19199991SuuoK9[u[KBS[zҼ„(KͰuDŽiռozoԿljuio˚˪udzɉǰicuzͰzKoz°oic11999KSS[SKz­uɞzuic[cuoS9 (1((1ouѰu( (( 111(19K[Sozzz[K(iϷdzɳªu–ooͳziz–ĭ¼ͪuzǞͭϰoĢoBSͼ[z[iļuuzB  (99BBK[[SuĚļocKou[SB 9 (9oɿ[u ((( (991(9B[iuuz[Sع[oɼ¿ܚzc¢ziϿĀuiuzϭzSSϼo u¹zoB ((  9KKKS[SKKiiicBK9((1 1Kucio[ ( ((  (((9KScizuuɦ¢izBc³zфzĹҹioϼoշozzuo·zuuoɳu9iB1(191(9BK[cccSKBiioiK11911911[cozuzoKB1 ( (  1BK[S[zu԰³ozu͹ĭuǰoo¢’iǞ[ɳzoi͹u9³o[o[9( ((1BciocSKKKKKuĹ­SSSB( 199KKSziBccSSSK999SoS91  11(((1 BSKS9ui[Ϳªǚ(c˳¼³K[zz°zzzzǹuɄiǪɼu˿zo˭BKuBSS9   9oucKBS[SBKocͷ˭ͷo[B19B99K11BK[K(S1 (((cc 9 (BKK9BcKK9KSB9ioBc­ǹ[czoouݼiɿiiuuoҹSiسuǭ¹uĚ·ԭu͍z¦([zu[SS9( Buc[[SKKKK[uc°uKBSB9B9111BBKou((1((11(1 Bo( (KKKSuziSSBoz[BSذzK1BKѼĹٿzzooo˰zuѢuzǰuijªչu˼ zzoicK(  ScS[iSKSScizɒѹzSK[SBB 9KK9i1 1 919BSS9 1S[SuBzuB1KoijccϳѼcuɳzc[ϰuĒļuǼdzǖziuɳu iudz[[SB  Koo[[[[S[iѦcKKBB9(9K91ui ((1911BSz9 ((   19Kouz͹iBcǿžcҿ˹uzzciĿzoz[Ěicɪ·ڼzz­i1ocoo[B9(  KiziczĢoBKBBK9(9KK9SzK 19919911[B  (1K1Si͚Ko·˳oǰԦzuuo³¹zzziͳciѳuϦdzĹ¹ĦĹK̈́zouS11(  ([izSzciǰizzǞzo[SKSSKBBSBKo9 BKB9911S  ((9[ooz˳Bع­ucK[ɷ˹°uĖoocuɿuzuiǿuoǖij˷ǿķ°dzSoǭc 1oouz°uzcuu[KKKKKSSS[BcB199BB1( c[  (((9So͹ǼzSҷ˄c[oc[ļբKu°uuuuİuiĹļz·İɷɰͼBi(  1([İc[uu–coתuoiiǹĒocKSKSSSSSS9uo( 999999 oB Bzo9SiڼɿɼSBozѷļzžozĿªuuz˿Āļ¹˿ϳ˰uS9   BKSo[[uĞњ[ccožuiKKBK[[S[K[9 (191( (oB 91BKoocudzķɼتcoz­˼ĪǼzķ·zuĿoɼĿĭij°Ǟҿ9(( 1BcczzzicKSouªuoKSBKSSSSKS1((((( (KBc[҄BzԷijzļĢͪoižzտѦ‰zzuzϭzoĹѼļij³zoo9(1(Kioi¢uzozoiǰoBBBKS[[KKoB11 ( 1[icoҖSou[cԷɹ˭dzo·iiϦzouocǷĿĹz˳zcS9((  (9KK1[zcuuǪǢSizzSuiKKKKSS[Bou9( (1119[iuSzᳳcu[SiS[zҿɿɉzҰuiB°zo[ozucuǖ˿¹¹uo¦uĦKB9(((1K[[[BK[o‰SͰ³ioɪ[uczcKS[SSS[[SBB1 ((( KoSչѼz[uuoK[zozuҳ͢[ioѿĦoķczi¹ouiouu[i­dzǰu˿9BB9BBBicK91iicǚ׼oi˦ɞcz[o[KS[SKKS[ziBcc1(999Szzoǰc[[¢i[Kuzz[uSzǰiǰoSioķǼiiɭǷĭĹԼļzǹBSS999BcB( KuSK˳zǢuozu˼Ԗšzz[cS9BSSKKSScz9([[S9Bczϭzǹ„iooS9zczoωSiҿooozdzioi԰izǒ˭˪ķ¹ɼҭ[[[K9991((9ciSK˿SuijdzzoSK((K[SKK[9[K1KԪĭɰziouc9[uoiooozico˹zǹͭžİoɿϰ[[[SB1( 9KKKBKSĢccczz[ozuuic9(9K[SKSoB BKBKoؿķ·iuɦKKB(uoizcz–˰u¿ijĄɳ¼oռ[SSK1 1[S9Kcu˭ozͪczozzouoɚci[1zĹi[1BS[SSK[o((19K[oioǼ³ªooĞ[BBB1uoc[ccouuњǼĹĪzɼɭizuĖ˼³ķuĿ׿Scui[K(KKKKSc[z9Szou9SooBcucBBɿuuɳǹooĭϦѹz¹حu˭ɞzzբ˷מKic[c[Kcɞ˭ĭccSKB[[oSc1SzKo[K[[[9uB99uږi­BiBBuuzzijzzɿioĢǖҷ˦Ҫz԰ԹĞĹǚicSKci[c¼uoͷ˰ozoSSKB9ic[KS1BzuoSuuSBiucci[uo[ou[KuuicuĹziozļz99ci³ͦ͢Ǣ³ɪˉͿѭҹѰ˿ͼѹSK[ucKSuͳSzĿz¦ucocSKKB9BScK1BuSzuoS[i[zBoԀcozSooizzoiozǷzcuuuu°cBBoǪļ¢zuٰǢ˪Ѫ[iiSBKĹĦoSBKKB9Bo[Ko99[zzoBSizSouzzKKu͢cczizuzuoǼiozoououziBKcz°zĢijɭzuzͭĪ˹¦oKoc[[SS[c˼°zķuSKKSKB9B[uoSBu[BuzcSzKSzzicczuiS[˼zccizcuocɭzKBzzuziKcͼɿĪ˳ozuoz­Ϲ¼ǿɪzSBB[u[[KSScu˹ɹoSKKS[KB99[SS1BizSoizSKuzuuSKucSB9cz[Sizuo[ɭcK[o‰͹iKBcĭ[šͿǦǰuoiz˰ǿ¼ɚciKS[[[ic9iuoɷªS9BKKSKK19Kc[9SKu[zK9o[o1BKKBBBSoiouzS­ɪzS[uĦuoɦzušļϰuzɰͿϹ[[[S[cKS[oǹo1׿zѿɪuSKKB99(1((ocKK9oouoizi[99BBK[zoz͹ziczļuuuuijɿɼ¼¿¼z[[c[Kc[9Sicǒ°ɭǪªiSSKKK1(( Suz[[z9[c[ccc[99BSco¼ziuzuzozzc[zɷԹɼzozzz°Ŀ¿·i[SBKiccucSoѷϿͰzK9K[SSK1 ( SSz’SSzuz9 9KKzzizzz[Bci[i°Ǽzzǭoo[[ҳuzzzγɼuSKciizu[SccڳǚzҼ[9BKB999111 9K9KoSzoucB99B11KKzzzozoc[oz³ǹɦuoĹczi[oiҿ°oɦ¿ĿijcS9iuuo[SKK[ͭҹzzǹ[KB9( (  19 (S[ic[uuK1SuuzcBi°SB[ǿ³ĭzz˰zii¦uu’ݹuz¿Ŀɿij¿ĿoK[ouo[BS[[KizoiտouϪzSB1  (191 (9SKziizoiuuui[Scǿcoziuuuzu­ݼuҼ¦u¿¿¿¿zouz[[[[[B9izu[[[[zo’[iz[B19( 99Kc999c[SuucKSªzioiii¦İ¿uu͖u1cĹϿĿİ·¹ĹǰĹu[[[B11BSiSBiĦķS9999  ( (9SuB99KKBBzzzziKcSizcoozҳoǭ·˦uu˦o[BuzuķĿҿz׷cKSKB1BiǹuiS[ozdzoS99(( (( ((9KciozǼշĀoѰķzoB911(( 1[SBS[c¹uzҼzzzzuuzzouS1B999( 1((Koczzǹuz[zuuou¦9BSBSci˖z¢¼z׼oij׼˰iK[Ŗu·ɰ[iسzciu[S9(((111io[SSuciijzzouoooS(1911KB919uɢBiocz’oucizzǷzijuBuoBSScԭuѼz޿湍ϷǰiSɹϹǷǍz³z[Ҽzo[zcS111(999iu[Kcoi¹uouuz[(91(((9BBSɷǭuzzzzijo[ouٳiĭɳɼĭڹĪciϳѦ¢Ě˳Ϳ˼zu[cҷzuzĿui[9((19BKcuSSuͼiS¹·ĦzuuzouS1991(11(1[·zɪzi[u[ϹuԿiodzķĹĭ˚oizzu׭ɚouijªzouzco׼oo˄uSKS9(919K[coiudzuS¦ɦuozzzzuS1(((91( 1uu͚zzi[zͿǪ[u͉ωzoz˹·ۿ˰ϼ˖zǹž¼u׳Ϳzz[cuiĭzoǿu[zĢuoBBB1(( 1BKSouuoicĪiioioozuozcB1 ( ((K˚uuoiiǒozizdz¹Ku͹zo҄uoǪ¦ªϞuuɳu[iouĒǦzcSucKB111( (919SzuKuoziɼ9(SuoiuuocS9191((( ([ǢϹuiooϼzi[Kouu˭zɿoǼiuozuuǚ¢ɚݹɞiozzǼĹ³¹zii׼˿uizo[ooc[[91 (((9[ozi[[zzc[˷9BciiiuB11111((( KuĢϷu[1[i[u¹ɿ˒cžuɷĭz޼ǷĿiozzͳdzϿzzzii׹ǹzuɹiKouo[K1(  1BKBSKuKS¿ķuiuociK111((((1( 9u˪ͷz[couoϰǞuٷɪĞǭuuzխږհioc[·Ǽ˪Ko¼zcKiB91   BSK19izooKǼ˹zzuuuS111(((((1 SoĞ¿uooǼoizحizuzɼἍļĹĪuucҰļɦϰǦziu[9ϼSuͳzS1 ( (  (Sc[S[c[BKuzo–­Ϲuzzuzi[91(1(( BͷozoucoѳcSKoš³zϦzǿϦoidz¦oocSczĦKoªzoK9  199SiozzucicĿ·uoooiuu[zK11119(11 B¼Ǟi[iuiiciuzziİc[uoizuɰuuuz¿Ŀɿuu׼ɰڿui[c[iˢ˰Ƿ¢uSoucS1  (1BB1Kiiuuooc[ɿcuoooozoB[c 1(1( (19((Kz°zucciĭicc[KSccuuiĚ¢zozuoiͳcɰͼzzuc˦ͪdzucc[So¦˷ǹcKzzi99   (9c[Siziooc[[iooiǼKczoooi[9cu((1 (11(1z[iozİzizzccoSKS[SSizczšˉzuzuҿziz˿ǖͷɼouoKѼdzijoiKSciͷķ˰BiiocK(  ((1B[izuoiSc[[z[oouo[K[z((1( Bu[[cuziɷzzuSoSc[KKSKKuuc[ĭѿu˖zuǭoĪdzǹ¿ɿɭci[c˰ǹǼoccoKS˷dzi[zu[(  (9cScoSiucoiuiKcK((( ioSicuBi³zioտcuuǦKKicKSSizi[cĞ˚oz¹oz˪uǭǿ¿ɰ¼˿ĹuoSoİԼسzocicKS˳zuiiuiK  (1SucoĿĦo[uǿ˰ozoiocSz[( (  9[czSuuozizč[o·c[[ic[[zuiS¦ǚuuɹҞ˞oķɭ¿°u[ͦļuuooc[[ǰɳzBKK1( 9cuuiͦļocoziSco((  (ciczoucuuuuiScĪz[[uucizcc­ǹўĖiˢ¿·zco°׳udzou[K[ǹϿSoSB    [oozcu[iҳķSScoiSKoB (Bzoc[ziiizoouuuiciǼozziiuui[ozѭ͢ǹ–zu¦ijİ·ioijzoci[Sz͹ɹ(KK1  9uuzzuSoĭ˭­o1K[[[KSc1 1zziiciuiizoo[zĿzoicSSiҼzo˳ĭuSĪijҿɳĭouiioz˿·[ĉ[9B9 (1 (cu¢iuǢB 1BKcKuK1   (uzccc[o[zɼuoozuoKoҷĪi[SKcҳǚiozճɖ[Ğǿؿѳ­cطuuzzoi¦¿ĄKc[K9(((Kzoٳɳoi[SK[cK91(  czoizooouocĭuuzuuzuizzzĖoǰzoo[Ki„zǪuɷɭǰĹķ–i[ļidzzzzuo[KiɰSuļzKKBK9( (Biiiiϼoodzc[u( (BucoczoĿɼzuϰuހuzۢԚiɭаzcc­uozzccK9[dzSѪz(((1K9  9[uSz˹uuzzK   [u[iizu˼uiiu׷z緍uz˿[˒uĦĢɳªͭļ³zuzuǿzuicc[B[­ĭϞ[ 1B1 ((  (izioz[˿oucoiz111   1oc[zii[cuǷSK[uĭucu䳚oͷoǪ°˼ͷѹؿҰdzĚuoĹuuicciKuijuijuoz1 BK1   Ki9uu˼z[iKKBKcS19(  KzciooiccoSzzuozziSioϷzciiuĿɖzuczoz˞ͷϿ˷ݷɼѳ͚izo­[S[S[·uzu9[oB (((( 1BooSuoķi[z[c[K1(B[9( ( iuiicc[BciiczzuuzuSoz԰ooc9czžiSzouzu˦̰ҹտɖǼɹizɼKBB1cǹuzKoz9   (11BuozĞzucK(KB91 9ic ( (1izzuuc[S[[uijzi[coouuzz[izoiɖuzc9SuҷuBo–ǰĢɭ¢ĿķiɿuKK9BǪizoS[z9 ( ( ( 1Soiioo[( 1( (Bz9  9iuiizuoo[KSoĦoooizzicziҳu[S[cϼKuzɿuciĞ˖Қ¼ǰ˭–zǼoSKBcͼ·ciiS9c(1KKSSB( (Suzzuo[[u[1( (9Si  (  9uzcucicSczǹzzucicc[izǞcK[uuɒuizzɼozuǷǞɢϳ¦¼ϳ¿¼ѹuSciuiuiK9Bo¦izǦzcoSS9iu1Kc[[SB91(9couco[Sic9  (BKcK   ( KuuiicSzuziu¿¦ucSSKcѼcBioǷzzoS¹uzҳzuչɞzdz°ɭؿҿKSz¿KK9iԞicĭu[[9[u[KB91 999 o[zǷiuiSi[9((1B[   ( izuo[cooͿKK[oİuuBuuͿuo[B[¦icKǼ·uҹczɷϷķϳɪz1iicBKBoĒ˰o[͢occS[K(  11(SuɷǢoiScK91 (9Bc[ ( BuooS[zĹKcuoo[1iɭiBcuٳoi[[Ī˪¢SKzuĪɷѷļԼ¹Ŀžc [u˿SBB9K͚[iKS[[ii (  czzĢuoiB1(1KK9oz1 [izuiouKi˼zuu[K[oɿzczɞzzuici­zͷoui³ɿķҹ¿š9 (KoڼBB91KҰiuķKuB[SSS1  (( 9uuzuzSccB9KS[K(zu  (S[u·uoouBo׼oic[iҹzczoz˿zɰ͚ioiu׼’99(((BcطǢKccS¹cuǭo[cSB11(   [zzcKSB(9KKSB1[( (  9zSczcǷioooz[iշ[uKS[­z[zoҹuuϹouoϳzǰ¹¿ɷҿѿ9(BSS³zoS[oĦzcziB9K(   (izzɢzczoBB9( 1KKB9[zK111 zoSiz[S­˼zuuzu[ͰcSB[iѳBcoϳuuzoooǭzբzz˿ĭϹ˪c9K cBK˷ooɰ[uϹ[1cS   (uuuuuSS9( (9B99u1  ( ([ocSBSijozooKuzɭiK[zĞiuuͼzizϼϖݳ¹ɹͳɭziK[oªBKѰoo˹BѰcScK   BuǞǍicK9( 1B1Kui(  ioiu[ciuiz°ioiKSicziBiѷouzɭSͦuɒͳuc[oɦļɳ¦ǦzuKuijS[ѷooSu1Kc( ([iljɢuzicK( 91ozS   9iuczzuzϞooKKu·uS1[oϭBiؿzuͳoz˭zuccoSKSižɼǼ°Ŀ·ժiizͼuzzuc(cS( (BSKiz·¦iiiB(( BBz9 ( (( uuioBouzu۳uu[i͹o[9cuǖu9uצoϼzzoǖiu[9KuzzԿ·˭[[uͷz³oui9B 1( (BcccooĞzªci( (99Kczc((( ( 9 (zc[co[zzoz[ooicoǞuccci˳zzBKoo[o͢ziozǹu[ii„izǿ¹Ϳ[B9[­uɹo[Kzc(( (BK[cioouc[ouu·oc1 (KKBz1((((91ouozuoouSKuiišoizcciɚ9uǦuzo(9coɹBcĖciͰͦcoĀzuɳcuB1c[ǹiiĹɞuĹo[SSi1 ([iiizzc[KiѢzuS9 KSBz(SucuuiS[S[zooĞuuicoo‰c ɚuz[1cuzžuB׼uo[iǦzͿ[cϭ­KBB(czzͰ·zzzuļzS99ci1(((SucKKoi[ccuǖouc991BSKci zuzozzicicijz[iizͪ[(ou‰zz9Kiuušo[Կo[[·¼oiϢcc¼zĭĞK9911ϹĢz[zi¹i91S9( Kzo[BKS[oiiou¿zuicBS91(1z1  BucSczozoªuiS[ozɼou[iu„oc1ScǹzuB[[iǢoco˿uozǰ¹ɪͦuSizzļǿĦB191BĿԼooշĀ111 iz[9BKKK[iouzuuzc[KB11zu  1uicSoiiK1Suu·zocuiji9[cǰozSScɿzKuu˼ĞouSoǰ˿Ŀ˿dz˦B191BcǼǼuuϭ[ o9 (izSBBB911ouªuoouzi[9(BzK(  1ziiSiocS1cuuzzoĒu[BKS–uucKϳSzuouɼǦiiɞzz·Ǽ[(119Sϳ[[1(1z( (1[ooK1111(1oϦu͞ozcuuS1( (oz9 (oiuuzz9SooBcoo˞zcKiioɳoBBǰcuijuoiͰuzSɳzioǪɼuɀcļS 1 BSc˿oci¿B((9BB Bcuuu[9(( ((BuzuϢu¿izSzc9((( Ku(cc[ozooBSzzioBKiu·zoĀBKdzi[[ԳcɍicϹuKѿzu[iѳ¦oSzB1 S[i·u[zzcKK9 (iK9ozzo[9((( (cocoi°Ϸzzz[SuzcS9(((11uuz (( 9iozuciS9[užcz[Soo˒zzzҞioԼi[ouzճcĀioĞiiѷiuͭBiķuKK„[19(cK˼oicc[KK(1[u9(cozuciK( ( ( 1[cizozozKKicSS9(11BBz[ (((izioBBoozuzzouzzuuzo„Գi[zoocˀuioucDŽouĞѦScѳoKĖouBc[ҷzizo[uB1cS99[uB[ooi[S(  (9[cozioҰouzSSioSKK9(9KBSi((99 Szuoi(B[zoozuzzuuoͭ˭zcicuuzozzo˹oͼzɭzS‰˰zuiS˪iiͳouzzc1BouS[ouucS[S9( 1K[SioczoϷcoKS[iSKKKKSS9cou B9([[[[i(iuoouuužzzĹS(Kuzzzoo[ҳiuϹzǖuϢc˿[o¿oĹizK9KuuiSi[B9   BocSiozzcKzucSBKB9KS9i[ B([cSSc¼SBuz[ɿzocǚ˼zz[([zzziKcǢcK׭zǰdziɖ˒°Ǽcouĭui[oo[( 1uSiѰzooScuSBBB( 9KBizB(1BuzcoǿB(Bi[iԹϭuzBѷuSK1 9zzciSzԿcuҖuoҿͭԖdzljzѹooozϼz³oɖoS9 [ccɷ͹oooSooSK1( 9Bcoc (9ou¿c(1[c1 ϹͼSͿuiuS((B[zocuizuiڪuo„iizžouϞϰϼ·zuu˹zǼi°zi[1  (BouuuǪzziKocKK11(1BBzzK( (oouiuziB9(c[iiK˳u¼zuui9( 9[oz[uiuٰuo͹cuǹioѢuª¹ǼĹͼ­ĿuiiĹuzi[B (11BSz[’zuizzoSco[K9(999KSc  [zccSiz[cB1 ciS[B1c[ɚiuioiK1((1[oi¦zǿzo¦czѪcѼ˦ĞͿzooļozdzɪzSKB( 1BB9KczcĢuoKc[B(9BBBSio  (ouzo[KKK( KicccouļzcouzozcB1((1(9icٹzccĭzzժcϞouuϰĢҦ­ouĹzzi[B1( (KK9BScu[cļ˷ɷuuSc[91991iozK (1ciuS1(91 11Sz[KcuuzziozzzziK1(( ( 1SSoҪuz[SĞzǪoİzѼouzoķiªzzz[SB  BSKKSuuBzcɪu¢zSci[[S9 (((i (1izzB99(((11KucBB[ooouozzS( ((1( 19S[z˿ɳozoSu˞z¢uzoicɹzzͼuoǼɿĿuĪ[oozǿocccSB( 9[SSKSuuii9BScSKB(( ((Bi(KĦcoozioB1(  11 99K99BuocKKSK1(  (BSczķozc͖zĚzicǪzouͷu¹uİɰª[Ǽ¼iuuiͿiSoѢiS1 (9SSKKBKuzczǭ¹uijiKSSSKB9((((9oB9o[[Kc³Kc9 ( ((119199oi[coS1( ((119 19KcKĹѢķªuizˢiuͪ³cϿϰķuouͷizicz³iS9(BK[SB9BooozozҰizKS[[[S9( (9Sz(KzzzicuuK( ((1(((11 ((9Szuc11 1(( ((9B9S[SK[oɹijۭѼooѭiǚuu˰ziuɳucǰzKii91  9KS[[SBKiizz³o[iocc[K1(( 11Si(cio¢zS19(( ( (91 ( (1B[oocS(  ( (119BKBiɳ¹۷ɪuͦoužz[ǖҳɼ°zuzoɹ[ouoBo·uK1( 9ScS[cKBco˹ͳzBouc[SSB9((91[zB(uSK9 (9(((((((11(( ((1KSKK9((( 11B[BB1Kҹͼ¹Ϧuz’oҭocšiǞĭɼĹɼĿouiҿ˦uScSoozzu9zžoS1(9S[cS[[KczzϿSSKuuiSS[KB91119zz(([ĹiK( 9991(11 ( 9SS[SKB(1[coi[iuzѰļuĖu[ͭccϭiɼiɷ³·ĭɰǹoiuĭSzzcKo9(  9B[SS[cciіu˹zuS[cuuc[[9(1((Bc z³˰c((1( 91(1(   BS[S[SKBB[izui˹odziiɢ[oǚuiǪBɹ¿¼¢uco°uoĦǷo[izB(  B9BBKS[z·o[cSK9( [B(oS (1(( 11((( ( (9[iiioouzz߿ǹ͢u˰zͭzz˼iSuͰuzš[zozĭcK[oK(91 1B19BBBKɳzz[uoSK11 ( co9ijK 11(1(((99111(  1cuzzzziSo¼zuǰԉİz¢ĿuĹioǦzzi˼zzϹz˹zoKoK((1( (1BBBKSKBɷoioc9 ((((z[cտz111191199111191((1SzuouoKKK9[ѹɰijSϷoĿzzɷzzļu[˳o[oϭ¹ouijSKzuu( (19999BSSSSBouizzc9((( 1Ko׼B((((1( (1(19199991SuuoK9[u[KBS[zҼ„(KͰuDŽiռozoԿljuio˚˪udzɉǰicuzͰzKoz°oic11999KSS[SKz­uɞzuic[cuoS9 (1((1ouѰu( (( 111(19K[Sozzz[K(iϷdzɳªu–ooͳziz–ĭ¼ͪuzǞͭϰoĢoBSͼ[z[iļuuzB  (99BBK[[SuĚļocKou[SB 9 (9oɿ[u ((( (991(9B[iuuz[Sع[oɼ¿ܚzc¢ziϿĀuiuzϭzSSϼo u¹zoB ((  9KKKS[SKKiiicBK9((1 1Kucio[ ( ((  (((9KScizuuɦ¢izBc³zфzĹҹioϼoշozzuo·zuuoɳu9iB1(191(9BK[cccSKBiioiK11911911[cozuzoKB1 ( (  1BK[S[zu԰³ozu͹ĭuǰoo¢’iǞ[ɳzoi͹u9³o[o[9( ((1BciocSKKKKKuĹ­SSSB( 199KKSziBccSSSK999SoS91  11(((1 BSKS9ui[Ϳªǚ(c˳¼³K[zz°zzzzǹuɄiǪɼu˿zo˭BKuBSS9   9oucKBS[SBKocͷ˭ͷo[B19B99K11BK[K(S1 (((cc 9 (BKK9BcKK9KSB9ioBc­ǹ[czoouݼiɿiiuuoҹSiسuǭ¹uĚ·ԭu͍z¦([zu[SS9( Buc[[SKKKK[uc°uKBSB9B9111BBKou((1((11(1 Bo( (KKKSuziSSBoz[BSذzK1BKѼĹٿzzooo˰zuѢuzǰuijªչu˼ zzoicK(  ScS[iSKSScizɒѹzSK[SBB 9KK9i1 1 919BSS9 1S[SuBzuB1KoijccϳѼcuɳzc[ϰuĒļuǼdzǖziuɳu iudz[[SB  Koo[[[[S[iѦcKKBB9(9K91ui ((1911BSz9 ((   19Kouz͹iBcǿžcҿ˹uzzciĿzoz[Ěicɪ·ڼzz­i1ocoo[B9(  KiziczĢoBKBBK9(9KK9SzK 19919911[B  (1K1Si͚Ko·˳oǰԦzuuo³¹zzziͳciѳuϦdzĹ¹ĦĹK̈́zouS11(  ([izSzciǰizzǞzo[SKSSKBBSBKo9 BKB9911S  ((9[ooz˳Bع­ucK[ɷ˹°uĖoocuɿuzuiǿuoǖij˷ǿķ°dzSoǭc 1oouz°uzcuu[KKKKKSSS[BcB199BB1( c[  (((9So͹ǼzSҷ˄c[oc[ļբKu°uuuuİuiĹļz·İɷɰͼBi(  1([İc[uu–coתuoiiǹĒocKSKSSSSSS9uo( 999999 oB Bzo9SiڼɿɼSBozѷļzžozĿªuuz˿Āļ¹˿ϳ˰uS9   BKSo[[uĞњ[ccožuiKKBK[[S[K[9 (191( (oB 91BKoocudzķɼتcoz­˼ĪǼzķ·zuĿoɼĿĭij°Ǟҿ9(( 1BcczzzicKSouªuoKSBKSSSSKS1((((( (KBc[҄BzԷijzļĢͪoižzտѦ‰zzuzϭzoĹѼļij³zoo9(1(Kioi¢uzozoiǰoBBBKS[[KKoB11 ( 1[icoҖSou[cԷɹ˭dzo·iiϦzouocǷĿĹz˳zcS9((  (9KK1[zcuuǪǢSizzSuiKKKKSS[Bou9( (1119[iuSzᳳcu[SiS[zҿɿɉzҰuiB°zo[ozucuǖ˿¹¹uo¦uĦKB9(((1K[[[BK[o‰SͰ³ioɪ[uczcKS[SSS[[SBB1 ((( KoSչѼz[uuoK[zozuҳ͢[ioѿĦoķczi¹ouiouu[i­dzǰu˿9BB9BBBicK91iicǚ׼oi˦ɞcz[o[KS[SKKS[ziBcc1(999Szzoǰc[[¢i[Kuzz[uSzǰiǰoSioķǼiiɭǷĭĹԼļzǹBSS999BcB( KuSK˳zǢuozu˼Ԗšzz[cS9BSSKKSScz9([[S9Bczϭzǹ„iooS9zczoωSiҿooozdzioi԰izǒ˭˪ķ¹ɼҭ[[[K9991((9ciSK˿SuijdzzoSK((K[SKK[9[K1KԪĭɰziouc9[uoiooozico˹zǹͭžİoɿϰ[[[SB1( 9KKKBKSĢccczz[ozuuic9(9K[SKSoB BKBKoؿķ·iuɦKKB(uoizcz–˰u¿ijĄɳ¼oռ[SSK1 1[S9Kcu˭ozͪczozzouoɚci[1zĹi[1BS[SSK[o((19K[oioǼ³ªooĞ[BBB1uoc[ccouuњǼĹĪzɼɭizuĖ˼³ķuĿ׿SKSB 1(9K99[uͪͪczzucS˹BoKKicSSKSz9199Bccuuz˭ҷɿuzzS9(19 o׼oz9BBKKcoiǦ–ɷĭǍi¼cSuͦԼzzѿi¹SSS9 ((1B1(9[uɞ˪zuzuKcɚzωKu1KiicKBczzc K[Sozozoz·uzzc( ((((ϼzB9[c[BSKcԿzɿšouz[SKKKczčzѼ·uɷzSSB( 1(11SczuzzzzoSu˷oiz[Koi9B[c9[B(9Suozuz¹­zu­B ((1(9iSSKc[[SKBz͹Ͱǭoz¦o9KSSSKcoiizǷzɿ°BSK(  (Bizķooǰoiou[i[9occoocczuS[iiSKiB( Su[cuͿoi((( (1SoBo¿SB[uKKBiož˰ͳͷzSKSKBS[[ooǪͼizijB[K9( (1SizİozĢzuucĹSSuic[[SS[cSS9ioczS91(iҳS[˿izu1 (1((1iKSBcݒBBz˭ɳĦ˷zɿ޼¹ciz[[oc[iouzɿ¿ķuozzzBSSB ( (Kizo˦uҭzicoicSKSKB99B9SuKK(9oԦuczcdzɳuzK (11(BziBzǼ[iiϳټiǰͭzcucc[ouozˢ¿uuuuz˷zuioB9B(1(1uzioljozicciccSK9999BKcicz¿1 91c˭¼¢uozcoK (B1[z[i³Kѿc˳oouicuuu˚ļuĚoǷuo919 BiSKzzo­oɷuuuiico[KK[[KBBKKKSoc[S1[KɿɭiuzzK( 9KK( (BBcziuѳɼuǰ³ĦuҼuuzuzcczocozzѰǖzuoz9B19SzɰouoɭSoicozuSSK[K11BBKKSccĦ[B[uciҖz9S[S9 ( ( (9Suocoͪҷ¹Գz[Soz9Bouz[uoS9SuǞuz¦zKBBKߢ[uz˰[iizuSK[SK19KKBSS[Kcİuc[uKў¼( 1    (9ocoioϼǿϢucSuBBK[cziuuo[[uɷu99շucǹziiiɰuozoSK[SB9SSKKSSKcҿzǰĹB(1( ((  9zzĹz·ĿĀz[BBuicuoiz[zɳz1ϭ[zuoĹzu[Sziuoz[KSBBKSSKKKBSĭͪ¢[11((((( BB(   SǼzS¹uɳĿuu[(uicioS[uzzz˳ªS¼zuĦuuĹizizuuiKSBBSKSKKKBozzuz9 (91( ((K9(  Sz˿԰uzozS9iuic[oSoioouzuuzoɳz˼ɼzzzuzzĪziu[[oociSKK9B[SSKBKiu[Bco[[u((11111191KB9((111 BķγSuϢuSzS(Szci[cSSzzǿɹɭɿoҹѼuiuzozuĦiKScSBKKB9KSKKB9ozziSSS[[SozSK1BB9999BSc[K[K9B[u[( 1i˷iz¿Ǽؼc[¼zBzz(BczziizBiocczzĿԷzķuziuɿcccKSczo€coSccKBSSKKSKKK B[[S[occS[ooozzu[1B9B[K99BKiui9Boi[iS(([İz·ϹԿoBz9 (B[[Sio[ooiuozĹuҭouzljǼշĀoѰķzoB911(( 1[SBS[c¹uzҼzzzzuuzzouS1B999( 1((Koczzǹuz[zuuou¦9BSBSci˖z¢¼z׼oij׼˰iK[Ŗu·ɰ[iسzciu[S9(((111io[SSuciijzzouoooS(1911KB919uɢBiocz’oucizzǷzijuBuoBSScԭuѼz޿湍ϷǰiSɹϹǷǍz³z[Ҽzo[zcS111(999iu[Kcoi¹uouuz[(91(((9BBSɷǭuzzzzijo[ouٳiĭɳɼĭڹĪciϳѦ¢Ě˳Ϳ˼zu[cҷzuzĿui[9((19BKcuSSuͼiS¹·ĦzuuzouS1991(11(1[·zɪzi[u[ϹuԿiodzķĹĭ˚oizzu׭ɚouijªzouzco׼oo˄uSKS9(919K[coiudzuS¦ɦuozzzzuS1(((91( 1uu͚zzi[zͿǪ[u͉ωzoz˹·ۿ˰ϼ˖zǹž¼u׳Ϳzz[cuiĭzoǿu[zĢuoBBB1(( 1BKSouuoicĪiioioozuozcB1 ( ((K˚uuoiiǒozizdz¹Ku͹zo҄uoǪ¦ªϞuuɳu[iouĒǦzcSucKB111( (919SzuKuoziɼ9(SuoiuuocS9191((( ([ǢϹuiooϼzi[Kouu˭zɿoǼiuozuuǚ¢ɚݹɞiozzǼĹ³¹zii׼˿uizo[ooc[[91 (((9[ozi[[zzc[˷9BciiiuB11111((( KuĢϷu[1[i[u¹ɿ˒cžuɷĭz޼ǷĿiozzͳdzϿzzzii׹ǹzuɹiKouo[K1(  1BKBSKuKS¿ķuiuociK111((((1( 9u˪ͷz[couoϰǞuٷɪĞǭuuzխږհioc[·Ǽ˪Ko¼zcKiB91   BSK19izooKǼ˹zzuuuS111(((((1 SoĞ¿uooǼoizحizuzɼἍļĹĪuucҰļɦϰǦziu[9ϼSuͳzS1 ( (  (Sc[S[c[BKuzo–­Ϲuzzuzi[91(1(( BͷozoucoѳcSKoš³zϦzǿϦoidz¦oocSczĦKoªzoK9  199SiozzucicĿ·uoooiuu[zK11119(11 B¼Ǟi[iuiiciuzziİc[uoizuɰuuuz¿Ŀɿuu׼ɰڿui[c[iˢ˰Ƿ¢uSoucS1  (1BB1Kiiuuooc[ɿcuoooozoB[c 1(1( (19((Kz°zucciĭicc[KSccuuiĚ¢zozuoiͳcɰͼzzuc˦ͪdzucc[So¦˷ǹcKzzi99   (9c[Siziooc[[iooiǼKczoooi[9cu((1 (11(1z[iozİzizzccoSKS[SSizczšˉzuzuҿziz˿ǖͷɼouoKѼdzijoiKSciͷķ˰BiiocK(  ((1B[izuoiSc[[z[oouo[K[z((1( Bu[[cuziɷzzuSoSc[KKSKKuuc[ĭѿu˖zuǭoĪdzǹ¿ɿɭci[c˰ǹǼoccoKS˷dzi[zu[(  (9cScoSiucoiuiKcK((( ioSicuBi³zioտcuuǦKKicKSSizi[cĞ˚oz¹oz˪uǭǿ¿ɰ¼˿ĹuoSoİԼسzocicKS˳zuiiuiK  (1SucoĿĦo[uǿ˰ozoiocSz[( (  9[czSuuozizč[o·c[[ic[[zuiS¦ǚuuɹҞ˞oķɭ¿°u[ͦļuuooc[[ǰɳzBKK1( 9cuuiͦļocoziSco((  (ciczoucuuuuiScĪz[[uucizcc­ǹўĖiˢ¿·zco°׳udzou[K[ǹϿSoSB    [oozcu[iҳķSScoiSKoB (Bzoc[ziiizoouuuiciǼozziiuui[ozѭ͢ǹ–zu¦ijİ·ioijzoci[Sz͹ɹ(KK1  9uuzzuSoĭ˭­o1K[[[KSc1 1zziiciuiizoo[zĿzoicSSiҼzo˳ĭuSĪijҿɳĭouiioz˿·[ĉ[9B9 (1 (cu¢iuǢB 1BKcKuK1   (uzccc[o[zɼuoozuoKoҷĪi[SKcҳǚiozճɖ[Ğǿؿѳ­cطuuzzoi¦¿ĄKc[K9(((Kzoٳɳoi[SK[cK91(  czoizooouocĭuuzuuzuizzzĖoǰzoo[Ki„zǪuɷɭǰĹķ–i[ļidzzzzuo[KiɰSuļzKKBK9( (Biiiiϼoodzc[u( (BucoczoĿɼzuϰuހuzۢԚiɭаzcc­uozzccK9[dzSѪz(((1K9  9[uSz˹uuzzK   [u[iizu˼uiiu׷z緍uz˿[˒uĦĢɳªͭļ³zuzuǿzuicc[B[­ĭϞ[ 1B1 ((  (izioz[˿oucoiz111   1oc[zii[cuǷSK[uĭucu䳚oͷoǪ°˼ͷѹؿҰdzĚuoĹuuicciKuijuijuoz1 BK1   Ki9uu˼z[iKKBKcS19(  KzciooiccoSzzuozziSioϷzciiuĿɖzuczoz˞ͷϿ˷ݷɼѳ͚izo­[S[S[·uzu9[oB (((( 1BooSuoķi[z[c[K1(B[9( ( iuiicc[BciiczzuuzuSoz԰ooc9czžiSzouzu˦̰ҹտɖǼɹizɼKBB1cǹuzKoz9   (11BuozĞzucK(KB91 9ic ( (1izzuuc[S[[uijzi[coouuzz[izoiɖuzc9SuҷuBo–ǰĢɭ¢ĿķiɿuKK9BǪizoS[z9 ( ( ( 1Soiioo[( 1( (Bz9  9iuiizuoo[KSoĦoooizzicziҳu[S[cϼKuzɿuciĞ˖Қ¼ǰ˭–zǼoSKBcͼ·ciiS9c(1KKSSB( (Suzzuo[[u[1( (9Si  (  9uzcucicSczǹzzucicc[izǞcK[uuɒuizzɼozuǷǞɢϳ¦¼ϳ¿¼ѹuSciuiuiK9Bo¦izǦzcoSS9iu1Kc[[SB91(9couco[Sic9  (BKcK   ( KuuiicSzuziu¿¦ucSSKcѼcBioǷzzoS¹uzҳzuչɞzdz°ɭؿҿKSz¿KK9iԞicĭu[[9[u[KB91 999 o[zǷiuiSi[9((1B[   ( izuo[cooͿKK[oİuuBuuͿuo[B[¦icKǼ·uҹczɷϷķϳɪz1iicBKBoĒ˰o[͢occS[K(  11(SuɷǢoiScK91 (9Bc[ ( BuooS[zĹKcuoo[1iɭiBcuٳoi[[Ī˪¢SKzuĪɷѷļԼ¹Ŀžc [u˿SBB9K͚[iKS[[ii (  czzĢuoiB1(1KK9oz1 [izuiouKi˼zuu[K[oɿzczɞzzuici­zͷoui³ɿķҹ¿š9 (KoڼBB91KҰiuķKuB[SSS1  (( 9uuzuzSccB9KS[K(zu  (S[u·uoouBo׼oic[iҹzczoz˿zɰ͚ioiu׼’99(((BcطǢKccS¹cuǭo[cSB11(   [zzcKSB(9KKSB1[( (  9zSczcǷioooz[iշ[uKS[­z[zoҹuuϹouoϳzǰ¹¿ɷҿѿ9(BSS³zoS[oĦzcziB9K(   (izzɢzczoBB9( 1KKB9[zK111 zoSiz[S­˼zuuzu[ͰcSB[iѳBcoϳuuzoooǭzբzz˿ĭϹ˪c9K cBK˷ooɰ[uϹ[1cS   (uuuuuSS9( (9B99u1  ( ([ocSBSijozooKuzɭiK[zĞiuuͼzizϼϖݳ¹ɹͳɭziK[oªBKѰoo˹BѰcScK   BuǞǍicK9( 1B1Kui(  ioiu[ciuiz°ioiKSicziBiѷouzɭSͦuɒͳuc[oɦļɳ¦ǦzuKuijS[ѷooSu1Kc( ([iljɢuzicK( 91ozS   9iuczzuzϞooKKu·uS1[oϭBiؿzuͳoz˭zuccoSKSižɼǼ°Ŀ·ժiizͼuzzuc(cS( (BSKiz·¦iiiB(( BBz9 ( (( uuioBouzu۳uu[i͹o[9cuǖu9uצoϼzzoǖiu[9KuzzԿ·˭[[uͷz³oui9B 1( (BcccooĞzªci( (99Kczc((( ( 9 (zc[co[zzoz[ooicoǞuccci˳zzBKoo[o͢ziozǹu[ii„izǿ¹Ϳ[B9[­uɹo[Kzc(( (BK[cioouc[ouu·oc1 (KKBz1((((91ouozuoouSKuiišoizcciɚ9uǦuzo(9coɹBcĖciͰͦcoĀzuɳcuB1c[ǹiiĹɞuĹo[SSi1 ([iiizzc[KiѢzuS9 KSBz(SucuuiS[S[zooĞuuicoo‰c ɚuz[1cuzžuB׼uo[iǦzͿ[cϭ­KBB(czzͰ·zzzuļzS99ci1(((SucKKoi[ccuǖouc991BSKci zuzozzicicijz[iizͪ[(ou‰zz9Kiuušo[Կo[[·¼oiϢcc¼zĭĞK9911ϹĢz[zi¹i91S9( Kzo[BKS[oiiou¿zuicBS91(1z1  BucSczozoªuiS[ozɼou[iu„oc1ScǹzuB[[iǢoco˿uozǰ¹ɪͦuSizzļǿĦB191BĿԼooշĀ111 iz[9BKKK[iouzuuzc[KB11zu  1uicSoiiK1Suu·zocuiji9[cǰozSScɿzKuu˼ĞouSoǰ˿Ŀ˿dz˦B191BcǼǼuuϭ[ o9 (izSBBB911ouªuoouzi[9(BzK(  1ziiSiocS1cuuzzoĒu[BKS–uucKϳSzuouɼǦiiɞzz·Ǽ[(119Sϳ[[1(1z( (1[ooK1111(1oϦu͞ozcuuS1( (oz9 (oiuuzz9SooBcoo˞zcKiioɳoBBǰcuijuoiͰuzSɳzioǪɼuɀcļS 1 BSc˿oci¿B((9BB Bcuuu[9(( ((BuzuϢu¿izSzc9((( Ku(cc[ozooBSzzioBKiu·zoĀBKdzi[[ԳcɍicϹuKѿzu[iѳ¦oSzB1 S[i·u[zzcKK9 (iK9ozzo[9((( (cocoi°Ϸzzz[SuzcS9(((11uuz (( 9iozuciS9[užcz[Soo˒zzzҞioԼi[ouzճcĀioĞiiѷiuͭBiķuKK„[19(cK˼oicc[KK(1[u9(cozuciK( ( ( 1[cizozozKKicSS9(11BBz[ (((izioBBoozuzzouzzuuzo„Գi[zoocˀuioucDŽouĞѦScѳoKĖouBc[ҷzizo[uB1cS99[uB[ooi[S(  (9[cozioҰouzSSioSKK9(9KBSi((99 Szuoi(B[zoozuzzuuoͭ˭zcicuuzozzo˹oͼzɭzS‰˰zuiS˪iiͳouzzc1BouS[ouucS[S9( 1K[SioczoϷcoKS[iSKKKKSS9cou B9([[[[i(iuoouuužzzĹS(Kuzzzoo[ҳiuϹzǖuϢc˿[o¿oĹizK9KuuiSi[B9   BocSiozzcKzucSBKB9KS9i[ B([cSSc¼SBuz[ɿzocǚ˼zz[([zzziKcǢcK׭zǰdziɖ˒°Ǽcouĭui[oo[( 1uSiѰzooScuSBBB( 9KBizB(1BuzcoǿB(Bi[iԹϭuzBѷuSK1 9zzciSzԿcuҖuoҿͭԖdzljzѹooozϼz³oɖoS9 [ccɷ͹oooSooSK1( 9Bcoc (9ou¿c(1[c1 ϹͼSͿuiuS((B[zocuizuiڪuo„iizžouϞϰϼ·zuu˹zǼi°zi[1  (BouuuǪzziKocKK11(1BBzzK( (oouiuziB9(c[iiK˳u¼zuui9( 9[oz[uiuٰuo͹cuǹioѢuª¹ǼĹͼ­ĿuiiĹuzi[B (11BSz[’zuizzoSco[K9(999KSc  [zccSiz[cB1 ciS[B1c[ɚiuioiK1((1[oi¦zǿzo¦czѪcѼ˦ĞͿzooļozdzɪzSKB( 1BB9KczcĢuoKc[B(9BBBSio  (ouzo[KKK( KicccouļzcouzozcB1((1(9icٹzccĭzzժcϞouuϰĢҦ­ouĹzzi[B1( (KK9BScu[cļ˷ɷuuSc[91991iozK (1ciuS1(91 11Sz[KcuuzziozzzziK1(( ( 1SSoҪuz[SĞzǪoİzѼouzoķiªzzz[SB  BSKKSuuBzcɪu¢zSci[[S9 (((i (1izzB99(((11KucBB[ooouozzS( ((1( 19S[z˿ɳozoSu˞z¢uzoicɹzzͼuoǼɿĿuĪ[oozǿocccSB( 9[SSKSuuii9BScSKB(( ((Bi(KĦcoozioB1(  11 99K99BuocKKSK1(  (BSczķozc͖zĚzicǪzouͷu¹uİɰª[Ǽ¼iuuiͿiSoѢiS1 (9SSKKBKuzczǭ¹uijiKSSSKB9((((9oB9o[[Kc³Kc9 ( ((119199oi[coS1( ((119 19KcKĹѢķªuizˢiuͪ³cϿϰķuouͷizicz³iS9(BK[SB9BooozozҰizKS[[[S9( (9Sz(KzzzicuuK( ((1(((11 ((9Szuc11 1(( ((9B9S[SK[oɹijۭѼooѭiǚuu˰ziuɳucǰzKii91  9KS[[SBKiizz³o[iocc[K1(( 11Si(cio¢zS19(( ( (91 ( (1B[oocS(  ( (119BKBiɳ¹۷ɪuͦoužz[ǖҳɼ°zuzoɹ[ouoBo·uK1( 9ScS[cKBco˹ͳzBouc[SSB9((91[zB(uSK9 (9(((((((11(( ((1KSKK9((( 11B[BB1Kҹͼ¹Ϧuz’oҭocšiǞĭɼĹɼĿouiҿ˦uScSoozzu9zžoS1(9S[cS[[KczzϿSSKuuiSS[KB91119zz(([ĹiK( 9991(11 ( 9SS[SKB(1[coi[iuzѰļuĖu[ͭccϭiɼiɷ³·ĭɰǹoiuĭSzzcKo9(  9B[SS[cciіu˹zuS[cuuc[[9(1((Bc z³˰c((1( 91(1(   BS[S[SKBB[izui˹odziiɢ[oǚuiǪBɹ¿¼¢uco°uoĦǷo[izB(  B9BBKS[z·o[cSK9( [B(oS (1(( 11((( ( (9[iiioouzz߿ǹ͢u˰zͭzz˼iSuͰuzš[zozĭcK[oK(91 1B19BBBKɳzz[uoSK11 ( co9ijK 11(1(((99111(  1cuzzzziSo¼zuǰԉİz¢ĿuĹioǦzzi˼zzϹz˹zoKoK((1( (1BBBKSKBɷoioc9 ((((z[cտz111191199111191((1SzuouoKKK9[ѹɰijSϷoĿzzɷzzļu[˳o[oϭ¹ouijSKzuu( (19999BSSSSBouizzc9((( 1Ko׼B((((1( (1(19199991SuuoK9[u[KBS[zҼ„(KͰuDŽiռozoԿljuio˚˪udzɉǰicuzͰzKoz°oic11999KSS[SKz­uɞzuic[cuoS9 (1((1ouѰu( (( 111(19K[Sozzz[K(iϷdzɳªu–ooͳziz–ĭ¼ͪuzǞͭϰoĢoBSͼ[z[iļuuzB  (99BBK[[SuĚļocKou[SB 9 (9oɿ[u ((( (991(9B[iuuz[Sع[oɼ¿ܚzc¢ziϿĀuiuzϭzSSϼo u¹zoB ((  9KKKS[SKKiiicBK9((1 1Kucio[ ( ((  (((9KScizuuɦ¢izBc³zфzĹҹioϼoշozzuo·zuuoɳu9iB1(191(9BK[cccSKBiioiK11911911[cozuzoKB1 ( (  1BK[S[zu԰³ozu͹ĭuǰoo¢’iǞ[ɳzoi͹u9³o[o[9( ((1BciocSKKKKKuĹ­SSSB( 199KKSziBccSSSK999SoS91  11(((1 BSKS9ui[Ϳªǚ(c˳¼³K[zz°zzzzǹuɄiǪɼu˿zo˭BKuBSS9   9oucKBS[SBKocͷ˭ͷo[B19B99K11BK[K(S1 (((cc 9 (BKK9BcKK9KSB9ioBc­ǹ[czoouݼiɿiiuuoҹSiسuǭ¹uĚ·ԭu͍z¦([zu[SS9( Buc[[SKKKK[uc°uKBSB9B9111BBKou((1((11(1 Bo( (KKKSuziSSBoz[BSذzK1BKѼĹٿzzooo˰zuѢuzǰuijªչu˼ zzoicK(  ScS[iSKSScizɒѹzSK[SBB 9KK9i1 1 919BSS9 1S[SuBzuB1KoijccϳѼcuɳzc[ϰuĒļuǼdzǖziuɳu iudz[[SB  Koo[[[[S[iѦcKKBB9(9K91ui ((1911BSz9 ((   19Kouz͹iBcǿžcҿ˹uzzciĿzoz[Ěicɪ·ڼzz­i1ocoo[B9(  KiziczĢoBKBBK9(9KK9SzK 19919911[B  (1K1Si͚Ko·˳oǰԦzuuo³¹zzziͳciѳuϦdzĹ¹ĦĹK̈́zouS11(  ([izSzciǰizzǞzo[SKSSKBBSBKo9 BKB9911S  ((9[ooz˳Bع­ucK[ɷ˹°uĖoocuɿuzuiǿuoǖij˷ǿķ°dzSoǭc 1oouz°uzcuu[KKKKKSSS[BcB199BB1( c[  (((9So͹ǼzSҷ˄c[oc[ļբKu°uuuuİuiĹļz·İɷɰͼBi(  1([İc[uu–coתuoiiǹĒocKSKSSSSSS9uo( 999999 oB Bzo9SiڼɿɼSBozѷļzžozĿªuuz˿Āļ¹˿ϳ˰uS9   BKSo[[uĞњ[ccožuiKKBK[[S[K[9 (191( (oB 91BKoocudzķɼتcoz­˼ĪǼzķ·zuĿoɼĿĭij°Ǟҿ9(( 1BcczzzicKSouªuoKSBKSSSSKS1((((( (KBc[҄BzԷijzļĢͪoižzտѦ‰zzuzϭzoĹѼļij³zoo9(1(Kioi¢uzozoiǰoBBBKS[[KKoB11 ( 1[icoҖSou[cԷɹ˭dzo·iiϦzouocǷĿĹz˳zcS9((  (9KK1[zcuuǪǢSizzSuiKKKKSS[Bou9( (1119[iuSzᳳcu[SiS[zҿɿɉzҰuiB°zo[ozucuǖ˿¹¹uo¦uĦKB9(((1K[[[BK[o‰SͰ³ioɪ[uczcKS[SSS[[SBB1 ((( KoSչѼz[uuoK[zozuҳ͢[ioѿĦoķczi¹ouiouu[i­dzǰu˿9BB9BBBicK91iicǚ׼oi˦ɞcz[o[KS[SKKS[ziBcc1(999Szzoǰc[[¢i[Kuzz[uSzǰiǰoSioķǼiiɭǷĭĹԼļzǹBSS999BcB( KuSK˳zǢuozu˼Ԗšzz[cS9BSSKKSScz9([[S9Bczϭzǹ„iooS9zczoωSiҿooozdzioi԰izǒ˭˪ķ¹ɼҭ[[[K9991((9ciSK˿SuijdzzoSK((K[SKK[9[K1KԪĭɰziouc9[uoiooozico˹zǹͭžİoɿϰ[[[SB1( 9KKKBKSĢccczz[ozuuic9(9K[SKSoB BKBKoؿķ·iuɦKKB(uoizcz–˰u¿ijĄɳ¼oռ[SSK1 1[S9Kcu˭ozͪczozzouoɚci[1zĹi[1BS[SSK[o((19K[oioǼ³ªooĞ[BBB1uoc[ccouuњǼĹĪzɼɭizuĖ˼³ķuĿ׿ BCpD(E(2pP0`@ pP0     `  @    pP0ppppppppppppppppppppppppppppppppppppppppgdl-0.9.9/testsuite/tiff/8bit_gray_tiled.txt000066400000000000000000000011011340051421000210510ustar00rootroot00000000000000Magic: 0x4949 Version: 0x2a Directory 0: offset 1146888 (0x118008) next 0 (0) ImageWidth (256) SHORT (3) 1<1024> ImageLength (257) SHORT (3) 1<1024> BitsPerSample (258) SHORT (3) 1<8> Compression (259) SHORT (3) 1<1> Photometric (262) SHORT (3) 1<1> SamplesPerPixel (277) SHORT (3) 1<1> PlanarConfig (284) SHORT (3) 1<1> TileWidth (322) SHORT (3) 1<256> TileLength (323) SHORT (3) 1<112> TileOffsets (324) LONG (4) 40<...> TileByteCounts (325) LONG (4) 40<...> gdl-0.9.9/testsuite/try000077500000000000000000000020641340051421000150640ustar00rootroot00000000000000#!/bin/bash # expected arguments (passed by make to this script): # - argument $1 should point to $(top_srcdir) # - argument $2 should be the name of the .pro file to be executed (with leading /) # both conditions are ensured in Makefile.am # expected contents/behaviour of the GDL file: # - the script to be tried shoud exit with a non-zero status if failed # (if the scripts exits with status 77, automake will ignore the failure) # - the file should contain a procedure named in accordance with the # file name, e.g. test_wavelet in test_wavelet.pro # - the procedure should not need any arguments/keywords # a quick & dirty way of making the "checks" script work #test "x$2" = "x./checks" && exit test "x$3" = "x./checks" && exit echo "exit,status=1" | \ # IDL_PATH="" IDL_STARTUP="" GDL_STARTUP="" GDL_PATH=+$1/src/pro:$1/testsuite \ # $1/src/gdl -quiet -e `echo $2 | cut -d/ -f2 | cut -d. -f1` &> /dev/null IDL_PATH="" IDL_STARTUP="" GDL_STARTUP="" GDL_PATH=+$2/src/pro:$1/testsuite \ $2/src/gdl -quiet -e `echo $2 | cut -d/ -f2 | cut -d. -f1` &> /dev/null

.ջDZ'_[t&_zF9Կ%L"L=c$Z;0|. U܍K:쿾T?taK`}v6 a41R`_Q"Ȧƥc[rNTGܴX&u>._SӼ{*҅us#$i|rNEi=zJJ%ָt|Ox>/7}\D1/ˬ|K(wg>*x*I#BZtsO`5$E*D#Yra]}n$KQ l-S ׭i>=Kָt|W9'fMT`EV"խJ? %R.lvnq9QEqӢ{o[P@Eh$K.q騬zQKU`jkiOOKָt,\RK$nZpa/%YEIb1rӴ,Mo_QCWxk~xӴHr$Xpa5-d)J %YFTwUDiTDEVy*#dɅmQq+l%Y*05mNawҰv;͗XץwwwerNdIܴ>VQR(QO$KؑKVJl$K,Ma5'O`G.a[+iO <Vqml!\z+>_[.t7F:'CR2D==!l 4Idi;r {Z?Q.efF4 [6)eTCl\ݹpaw`w$إ~!=/ h\/$KI&rWznJkhwO-|0w\R/t,M`\M_,ޢ[ ;r*;>. V -C͗Udn}jǗQŦwD="E]|9A.V[Ee ;r <ʗ/p[E4ͧvR3b\y^E)CR's;p`d)I["7-j=X='أe|dM%<ݕ JRN4dI[ԍxax)qr'IԓɗUdn~t_Ɨ^Q-ue԰c`s;r;5. \r`5`0_xJĦS=M4OJ~ ;r ǕIrNdIܴv`/UJ*$y,@Oڢ$iQ!ƗUȓ _#píd)IEpKl_(IAɗRI _F:6kZWuEY" $K \AI9I%qӢہMzJfCB}*|9}\.vPeg=w>#8y;D$QiQ>v`%Yao`$K.%>d)I$]Xǥ J*Mc$K. lи5!7-j#ăU)KI"OOYa.מ[rNRGܴ6:eU',#]r|\{/=XU%J%)>_'Y]t^q+ }x>4N'Iԓv/:J _F:'C;YQ,ɒ`_Y"O~Ɨ-%piQ|'K#nZq;I.6˻,d/.","MuɁ"*Z! v4}xK>͇pKK U*l ;xQpWRV9'#nZԾQ= BH\ءKp=K%YR5ڼ l, _@(K>_fmpܲ>5jfYYU[R5ܣ, ׵i^Fpr)0P?N4RT'|;t8gI9YEqӢX(_6,*$Y/Y86Q&ޤv:=@ d ݳzueKA$ V%, fwOI\\䢀(KU*ʒdSQUe \U&?c}>>XeC=}LO%jr㏻@ݓUj!nq]}#haEY2j.]͓xa 嶢,Uz}Z$4ʓxiagykRNDYlj4|QXKQR?UI(K!̤蛑ݙ#U霪$dSAetQuvxWi>#[7hŰ*Pe\NMzQo"PW& 4NէS)Kݻ:2Ud*5t?U*R|teI_U$Ox͊+S5-R:*#h3OX=n%yj}&nnTEgdO6մHR?U%[NMkid ʒdSQC*Ompc@ǫmx$Dm/_nnK Фvi2-ze ܵ&R={XQew(K_BcS&NG ;Ue)Ӕi3k~)*uM霦$dS#E`LluYvjҸ*ץJ0fr4NV꧉f,EYj,5Q$Y`{.@o,(Km,M`g&&RE$hj|IX DjK3(t3nvrv>:H ;g, י|ml,5QL=,E=M)4Q-4v)I l,I65d[5(KmFY7Ȗ)Ӕlj4ve`EYj eag&&ReED3R(KM=j3_/BcS@9^9^ {?%k*T&5/?[ƻRjw|ۦwM&R|`/EYjVvXY1t}JُwwDlj4`5-"Kf% ;s[̑&RȞ}؞jOO⥁qɮ2IM%ɦFww.`/j:֙t+>xCwM"ONY aI^4ȖMڦ5i {;j"519e[G?;(Tu}SP`gm;d{Cz޿M1^ޤ=ݥ4dS.{ `XI`x:b}ZݮtMs,d]1:즧 Mkr<ܵM1ºu` %Njx/^Oƒ +X_??]Tϗ[>&ʺ%<nW6Rʹ-V7ͫ:DM Fada ֙tM;}&R(ۚ4|\_i=x:Γ0cI& ,(\`Xr<%ym\ aI[sXǕ% )K!3 kЃl99{|\"hȞ6ǕEEꑰ%a [7(ka'R\lEy݁FRCS2EEljȞj|IXM/CXolJ䶢,"٣aEY?R?.q֏/IV]],I65)E[JJGٝt%y$:)KVC%yvwҟƗm-..Nr<}17/CXgtE(%DYUnW]pR-4ܴ/m>~h|CӢCvifES%3)V?GVݿ [2;oW}]SfR kљ{,#Ί-)@R[\qmHeT_Z\.f _,򚗿/yVEpkU_ ˄/BEg{Kku8 jkIjg+[ zz6: 3Lי껠fOC._@Nc{:WsN?Ug_9Hǟ zGx}@]+nվ޶!.?}} }CUGZomC^([)pakxa^rqZ7+З  B7ꆾ+]`(1NBlg(xrB+۶-R۝^n۽)X팻B]S+@< PЮ<>{Dz{θcQ6ϭ@3Q`}g3 ́^o#\fz>t&@Q+0n0; !gθ?Oņ<5|!tmkS>q/p#logr3} %M /wtO< nj<θkZɇ[jOBᖎ®0p q=~tKEmzpn> e۽\gcsˣ&s'}c6r[n:3VlnkU"u AQ}(`{X`#vo8]bO{g zmbBT*a'p-K&8gbό'G+N4(<{ ( vb7ylq7ƽ99@7{m u>0L)pB'sC{2w﩯itAg %} (P`- b2==;I5.@P|-EnY0)Ͷ{Ǎ;$Bl!? 3U[ło[ l܂!{[V[bOV=Xശ-gB+ܲ:\c?lé܊;Fn@b) <@Q+0wR 3ʃ=3InķH(|c7,)4pqnWާΤ!(-Jźsl܆[ha$\gnyա{a) .bCmX;ivqĆ[6xےbbҕ^~ G]%b(r-o&d+FhQ`[;t V;F;r[>9/­ԛ %'*mncH(sswc b!dzjnt+ێŲcy#\b#:XnaO~?;< A:+y@{p{21ݯ*V[|#;rVpnؓ0~p˩Prݍ-ܾ9KJʹg ~B];ZandwApۺ Mˬz>Rnv:kQBhRɮ*ڽ\g]!*Ѝ; RA;q^aOrkӫF%YM鸗FؿwpWnBPTm(`0 ONCmC|\E{p P5CD`?l9 x:,& E@xVF1bW7`wC)gؓ;p5ƍ GB]D5wېܐ@",(0PBj?Bb;mCpCmCrN2ؓS`aX&-ې(F1)0pHnaO⎥--"2uV lM6dtv8`1DWq3 `'ANƘ o{Ys7w"JY\})/(O^ZCeZ,X,wד.ӯks YW7c,j5wGl:'IZE "2uVst,V{2뾗 ܲ ( pKWa,VnY\qW֩]ԗO"("Q&b lp 6ܲ+ h}}`Mc+pˊ%oQ`tvŒBnt\#܊x[WUǀ |ʃc ϮDBs`^mn팻Lo׵V %*ΎFG6n^Xu !3*k۶RXRh bX>,Fnm !h$|?{?npˆ2uV-WʛlnHm 6*Clg uf?E>k]hxb l*HmHIwQdpxޅϝD;rW;F•>L^2]?;{nVJlv6wm팻hZ=W+1wC*0z s7dqP"v]Q>c|$N@@ېbsl6d7$6$6G qWT0x 4 4VX3p^ht!#^›ܽc wQA4:+lM@hh.ĞОu(BP Bb ㈽rƀbOJ(6,$KABw6-_ eOǽƀbO,O"ߚ@K%htV YZBr.9]Q|jg"r Bᖯ-Wn [r4ۗI#{pִ?3Cn!{.mtK*/Ms7wۣ*phԛG̅qL3oJ%آ%ht 4ht!/9yS ht 4].9 4XFbOJk' hTjw; u>`@K^1n}sM''c,@KiP|ѭ1IؤbOǥqbO* mK2a-s59`%0 g=yrەNmtA?+prݍ6m)9 wph7ym.]?%$(f_;øJ9.Fؓ\۽)].]ckI!:ڽ| '^`&R(T'9EK ~!%3%'G%de 4ht+ n [r4{RoubL%htV lMht ]r4{V֤T%dѭpAK`JՂV\DŊDܭH(396ns7htĞq]B.!Q@KF`Un,eW̛|w0wXB*0%V*LHFG!_k>9V n ].!;RY nht![wm~r*nFGl7bKmθSVhtsC~ܲ ].c/CGU^ʨ/(ώvS[\B-p,G ] RJF@KB'%F.t8хθ+pP+ RB.!Q@KFƒ@Kb !ߥpۺUX!F@Kn%dm ht!_r-5X̡ p%K r%gmv]Y2F7 t4_q`@N?m!pCHq 9&MPX߷7N0fq{ΘwA*VͶm[`+AͶ{MX{xK@q;`#.w<9 n[N6[Ia? e$ʤQockb' {Bʾ%F_xP*0ӇʛdHe s=agmE ].Fn:>| ĵѱו(03e褀QnqpAˠe貣хθkxlʠeP2ht4ht+lp C1p4{f5*(Aˠedn6htYZ.;]=sS@+ɠw]@v0; ʂ!;ht4:\bYHUNkA [:/8b-bp6uXJQԽ˪rؙxoBbS4b*❧E~޻ tA0wC* lݐHe+b;%{/JC>:FQ2Wݐ̞F 43hɹ k~nz'Gę7A˞F7nl%m ' vzWn9:Y qK2mht!d.T]T(ҝ vrIuh܆%6Ez\P0-]fmp96ht4Xi'UUU@ ]m2cѭ13j' UJ@Y ].#SVؘ! @ˠeG ](4 ].#;n ]F0#ˎFbOeE`f2n4 ]v46Fny+.Ğp (UțFq]it܆.p[E܃W5w+8*nSͶ)na-K])q芣ѭXV,H$$s팻"Uc> AhPb`z@-Gn['*ޅ[?.mcfOǽƀbS [Fyr W Xlk\wP&0HAF7Z`cuqa'pb zc'`~@u+`IQV` ~ G q7򮺅LFW@s XZR($ htBѸ={(FW@+dѭpA+H$犣хθq;pP@+$ ht8b#>Vit!h]I_Q AhͶq+l-)d mN qיZ]J(~O`ANiG 9/­^tA ˬ g/A+$ sBlgej]t.n첂՞\ackht!3vA*bXm={[A V22Ѹw'f>WȻq -H$$s팻lF SW(+G[ack18]ƾ3U@+Vht4]pQކnczoT9*l,(_i={+ ht4RǡD;},. ht4ht+l-d hɹht!']]\X$(d e4ht+ 8]={ǸT%"2uV n`]it1]ܽS@+ htVԞ,(X.ƕU[Pv]_qĆ[$d| n#\p#H=?fq^A[|eq+ؠYlvw8хθ5."htV l@+芣хؓ۽Ǟ{e ht4]8 4ZAr8]_w9 2u]q46FFV.pzx"p46&  sg%DrBn.nht`?O m?mp+4_tfJV.68ϞbW*ht \u4wq uA? B7X= ,7G C3丹[Ypf*htT ]: ;8bWZ!T|AJqk!|4:z@hx&qf:cuD؞C/gjn>U*2uFG[aFWHլiTu4yHV=YAUd=FEdEht!ϻ#X Y [ړ`w」:|rؓBUбm[c?n F[u5Cg^]J("~/ϓuVhpKE 9/­ԛ }l@PJ l\b9živIa ]խFg uؠYl8Xl"IAʚ4*N xK 8"VA4{2H> VUFWq]Ev: K V*m՝FbOإ00DwA? C6_ 6,ht!d{gX$F7: qK*m|YUc3B\܅9+wA.s Y`Y$Nnks~FQ _Q{혻!;X}6nV$*sgاSwHIأs7 4۳:"0V{}:2uVc+oRa۽<#wēP*ht4 ]EvؠUd+ht4ht!wF+SA vO[cw㈍Q9 n6_RϷ)3O`(q`GwF`:]=){U4]c(<{@k6$htBl7Ny?<5ht 4`s4nCF@kFbH;<1FאkH5蚣ѭ#Cn=)U)kѵ݅=M/-)}^naOf<豁Fp]it 4ht+l-)4l`50ˍp۪mwUbY'R:ᗧ|6l5W6Wrv9p,G 'Gsy>kt.n 2)` 6Sl,֊r4{R(9."htVI[]CF.v]{ǞԱF6 dѭ+\E%B&i<ͺFpb\it 4ht+4n/v_kF%F7:d%Nk`50Zr# rgM\5#=P!S\BP""lGQH>a( 53PGϱQX! ؐ@kH5WX3ۛE ZIeC]s46n dk~pKhtV_`+o@k`50ښх~}yt˙P= vrufq!Yc1.g!/= c[֊wpb zy >`IQ̒BlpGn( d͐9LF0-Ak5htBu %@k5htV6$sBlO@z ."eR(#\ y]팻"l*A4:#-%9ht-.vl?g{n*4ht`?Oa5 9=6mŶ-Tщ;R]B[PZbΓk5ZG!'](n5$htؠYl8XlBl3m/jˀFPU`6n(PpKWX3v{0u_NQCɹP= vrp}va2Z(v7uA?+p}t_q@{sбmk-Ak`50.j*bz;jE˜XRuε{%wҽGht;ht;htq7g%;vmܯbyGB!>)]O|{-IBZmW2ť$-a;4*ϋ~W... |.ey kfXx^fעw*7%wzF+U|8aK_^pĄ[s/ؕ{?xwǓL.*֔˭fll\} ˣ{ÓCz]+vsD? `;&6(_:3%hySɉ!ӽ&G\?Nv:]>a._cQ6_W>މs] (vEϑۥy~޸˻8 Dz~f{s;g]us'Dnjw}fkNu]ħuMߺ0^?o}';yLi j_}ծ7Ix󐔳}`?OHY_g@P<7 xccI@0?n=Dq/m](՘cTi_v6EzG]dž%JņQh]?S!")r Riw{B+ us}r-žNL?iN_엂Kft7~:ճg<2hIǸ B5y+l\axp$^1ؓŠv[N~..WnWܬ2ž,+p Y 2 mqU^FG ŲH:kQAq+P*iYClo?هθ+Y%c\ b 'qt8;:Ğ^Ht.2u/$ʤQ̦G"섡[&x;:Ğ$`b:jwm[$ lR !\9PK̈́"q vrLŶEؓD];.g%njݍv[-p@zz] yIRiw0@Q$1Dؓ-*Fy=J%[K Ƿ{ǹ7TFN F:y0EK ~!BrN2ؓmawZnz%2u/$ʤQn #6ܲ+pCɆ|ק`/p˂LU[y/$^n*؎Tsm濮A ";ru5V tKp{=6EzU/rUvGŘ$贡bVs$us[Ep:B vR!SBL l Ǫ7ĞL"JЩ@Â2uVst YWl8W>ĞRÍQ nܲ9\`#" jplc 'ߛWuZ-]]_qĆ[=vpUP Y ָ5vwK|Am 1o{Tݱ(هEqRiwAQ1ǷqCl_:e }CP[$= ,pw,)t8х3uQtx ˸ K ny+\=w w; (LU`t6|Ŷ;ƀb;㮿>Gsp`{`z`I@=ƀƒ/^G!3!pߧ!t˙PrݍF FbsC\`<$A? 9j{X`gGC 7ĞUD^q%A6-m[a+:};aϊ4\qؗ}; ƍ>4wې@^tq[;zU ^pKd6$ʤQQ`e ]@*0VʛlnmmFb;ERhthththtѭw<976趗:zeۏP=?W݋N8UNtBjmγؚ Cns'\ؓ2wu+AޭZ!4P ㈍G޸}:JGEdγÎFb;mת 〩Сm[c?n˶{1o{Tp߂m`IXW` ݖ1ȈwFbO* 4mIV4 ,BɓHQgHЩht2uF[y Y 4BqH݆ht+l\d,pKG '> [knhw GjFճ՛|m{I|; LBbbck1wwFb{>k*."htV?c+Ff۽\'LFU|+nnF Y --!dnrWR56P666G[acc`mFbZ8 -Bv-Ahh.Ğ{im[N-s5vrIuѶ5pw,)9/­ԛfYdPbGPS$ٱLc1dZRymwEˬn(wR 3 EW ])П.s XXRunCm;naO|-A@ېbv9FEpCmCrns4{7/2 6P666G[a#ob`mFbOfVQA4:;-u ht Fv@Vsݪ pK\\ճ靖s> lEB[s7a'۾2WؓtIf6F@K%蒣ѭ \Aǹ[=٥#0>C C[7v] r([F3 [.EK&ԡL/хؓ3\jO΅-]_'b F[r5Cɶ{ɭI]JhcG6uq(7xK}{I'\o Tv쾽4: GXFb;㮙ݽ@> (]fpV:8:@KBV՛]8E bv;i8%sv]lԄc$]de 4ht ņ[+lgU0[p˔!4Chmk[K YF[ 2Wؓ2|@ [:/Ut|MgA|nބR#]im 2k96ht 4ZBr.9]=+>8E]ٻ%_&W{r#d4{RtQA(FѳWؚ%dh)-s4HT.4`W!nN^`*LH%$$s=awD0= ,#6ܲ+.Ğ~|*4LU4,`.F.Ğc].F@KFF.dBht!8KI(-]_qĆ[$d'pUUԛT.du 5!ӾBbslԞt؏jOؓ2ٌ,5}@P)`[`c\BʴcBIA{mEҎht 4"ɝpF.F@KFbOmt.!S(K%G[`FgBIR*z]GEd-ڊ<2.ĞԠO1e.g%ny8\c'!;Xg 6?mp+&++8d!ޖ.68Ϟbg2ht \v4{RU>OSh @[vq.0@ΤŞwiXj:F+V-bkQL3іh릣 oFɹMΰ 'u_ '5!DwA? (~]_ 6ht!]~VBv&؏[Fh` d5w[Wuz2Vi\}/ A2@?{ӒBuεƀbbsht v1V8.c+IŎ` ]F v5t͹n0p ^jOؓqsA:dbpKs$r[Ye=>aAˠe2Ve2mB] Cwݍ#6,|Mmn7)c}_R]?8-7 5= ̱qF`-g7w'Ùq.F 8^`kH r4{^r7Q{2FAfW{r]0zFɌҏٟFaOXc!Xj ."e/=بC {y,hs%vm8WX3Ğ,PRXD~VB1)8 r:`ANVM. v :.F@HeG 'e+R]ٻe褀QQ```eG '{s$v4 ]F*]`cIYZ.;]=+F̷JDPitht+l\d3Xg-ǀbOv)k}IL]FL N#\  2WؓT։ΠͅmkqK2m|Yކ.Gfw[dͽ=2]ЩvU`R:.:Q2|ev4{sjωړ vYFjOpAHe$粣хؓ2wN>a5e/=`7xN '(> ]@*0Đ d'[U4FAˠedѭ7.uhˎFbO6oP--n F[>|=p!\HI> O`(s$((P4Mr# 7`ɤX) 2uT8 [4,`A|˱хVsf]ǸB3s~ Y]8]=)c}_R4[FWn8`/zpC C.T4Q5 [K 4 +FbOhtuA?+pKW{ɡfAɂҏ6Ezsx+ C;JiIA_9ž2KMwAgV@3ng7GC8r=-[\@+rtpFW@+FbO`]FW@+FFE薎aO #EE Q&b lp-6,ht!u4СmqKFWh+`AN ۺp,w[ޤJ={e%&^IP*(>?"V2kRbO<Q :FWb l\ hɹht!2viXFWPd8 C `(>9EؓJ] ).g%th[؏[FWh+`G '^*=9ړמ\c?O4Y8]=)vX Y [ړkn-h+܂;F1)g՛,5}A2 5= ,7`wC)gRbO*iUV,ѕvS`0n s RX4{w!q␶ bcIbZArN2ؓ$A+$ htV n [q4{j'5:4]*r ]Vh+FbOB*-s5@+`0JՂVJssGBؠ@4d.g]!(]Vbv?F"VFbOJϒ(F]Чw. Q&b6bWGit!$#xU*htVw[ F[MtqbOrh.g!4-薿`?O4 Y&p6EzD}]|SR1l*htĞlVMFWHU誣-Ap r4{{d Bnm[a+\U誣хؓSϡ.TAU*htVU*mBɞ!P ]_qpl%d}wvA? c~4+8pq曻 rgM~R+k'P*i;Avl^63tnN@YCǀFWAUG @U$*htV ] ˸'LUm_`+oR8`htqtKE褀Q!" XAn9?64Pp4:  2{m|;?@u8M ?lvتAY FW@UGOe1wCv: s7Ӭ`U0ڪ+ [ړ`w :lr&th8 r@`Ճn9qr&[[FWA`U0tA|0]fm7Ub9eJD5tB(Ew]߼8àwk?+Dz~v{\`Ng8˭\n\sx{ing]S/,_>'N5i5=\SOuI|c;7tk8 SK5py[uG{{/M֧k>i?{[xٯ9 iHV?hޣ~ w #n)?vgsH~#w ֭; LSv$iZ氩?{:i=%a+?3Ӥ*U_& "تTSrCׅ-aIw"Ի; <$Pw8Ǜ2nߏ~}c4){G{I`6ȖFC"lWOA3|nyR*Svr66uHIi>Tc^F6G.F>^/ItaKؿHyw+I`W56$^z1^ͤuѹ}-{U MӚ4:4eI/8@99S:zOmr 7˿;֣xۦx6xsحD"$x2vȟcM=RQ`ۚHs&:_ͫmrۤ%p7Mcחi=xsws>I-% +F]*^v|SIPJc a^ 9P/i *@k1^#-OO6nIs]_8W[yMQ9^,0s%Y㏻e @+g葽(LF\&x#SP/ݲqaI"En[4-*CvviQgdӼ{lI)]xG~pVi=U]|ny1^CA? WmU`-sXǫ|uh>2֙4-_o@ 4zdOaMH+ѤY ww6y薽մj6/ttlG)[i&Ei4iWSciӳPOix X˦a.xc*nm2xۮ vxsX/ +w/wMxB箘ӢP)!|vMv_vMvE} XMuqZて/r]=Ɨv{7q6ͧߎsHyt֓<_MsXK孶Cw/t|.͇o"Pw8[>&Vw4/a Lv&mӚOwo|zj{}]Dzc%IHwxVJإW @heOa:C l` &C/n!Ozu\I3A&=Qktl k2ͻ^c)9E0w)IE^-`|\o,9<䎥R%p@9kt.6oylcƓsSVPna:DOI [:fw)I l!M&eJJu5U`w>RݩtNRGНlX9<4Uߥf La{.@_i>=5/CYh l$yz+6=k' 8 a'&ݫE/tYnw g')0ͧ2R;y._)o[yI^<(^vدT.Ye!dT,Kyw9IIɦFvfX9^/n>&LFs9l aOOM㿘t@ї7IU\x9*^V [񪋗-_Z)5Ywaa K95W`%VxY5-WNudُ.NxY5Ĩm簚VC*ש.^FULp.-)5/)۹4`߿nyTs2d+bɿK9MR`kY5Hhzx4lU')#aKI']$f;MZqoVk[5=6BIV.]>R~mӚ}OqL)>w_r-GJM2*ZirV`agm;dӔglxNDvr&#XMJ;\g?!dCv<`ANs?c) /&N5v,RV:'ds[𧰢, ++ɎNvBk-]ʻ;JH65#$+S';R;ٯ fcyrʮX%5is}Sn ~;a*S`eIzJ}ؚEʢ,嗋[[6ӼiQԄ9RAP<[,ze6s>-KS<% [N=WEYJd%y$=M&VY(K!섅Uq5RY,RVvL)(K}SNv6 J\r&ʒdSGVRyxI(K!Yj".v)?Sr4:1 r'Al/jmӚ}Oq_,Q6b/C&r8(YDe4`w8R;WW7E"&VR:Nԋ]ʻ;[QbmEK~e;)NQ/ Ht)l6%lWa}ZL20IKsrO|I65ݤa>Y L\ʁ|I3(+񖰏I(חeUn}weԤMXIR"NG#{%a5-rGY a'+$ԥD1a{R_w|zj!hҽ^s'Jѥ&iZT5-R ݲ)o 7n aIg^Isww*ljȞjm (ɓe)u&]Cz}.p0Jrʖ+ddlk3ͧeLEYʢ,eQ$=簊,e(KxkZ[^y뷏P)!פ^KN8Kyk{kZ$:4zda5-e) EYʎ:cQEY,"ɦF9>UDV';RL;Wr[QLFs9!SV|\`]E-99Y%ɦFVYT,ROv֙tmHy66b-@ tYu$=簚V'R`Iw%"FEYʇj٣-`5Wap[wr駻Tu5T{.Ҫ\Q;_EQ9l k6ͫC,IY&U es9lS& McLzOrv!6Yv{$*S):20EڞUDY*,%(Q$4r֙tL϶E t%OW8ƒxqz}Zt)?Srs%c` *۷eg[t߽P)_nV3Ǥy'<ʩD@jȞ&X=n%y,Z w)"Ei&MaH_i>=>7ppq{e(SzKQ=(SoL7>X"RE$hpVcD)r@ e {;*b1,$l۰_T uk)qrէSn*HYtj٥5 l9 ;UF\z>qtM}cs9Ɨc$e;35~LФv) +S v2,7Ok]ۤVEY*UZ$P,-`[^T2tUjZtNQG ;VWd0VN޲559(KE &v%}o`߿&Ӽ{QBɐQ˱J\5TjSDꁄdbs 3e1 ;/[햑"&{&gUD)"H 5Ve),1q Re3ʎ"X *J](K!Mwg^'C$Ⱦ2NY*J%y$l ;`UNtNQG lNY23"wR;_ޛvz(^+ddOƗDŕ a' *LQְS8YT"R$<񲳃-_h*5{,F'&Vu5xɶadssvaWTz$](KVCMեNa|rV`vۧE}ZL)GY a'4"t)I l,I65VROU:R;!äg,Us.Vؼ;de;)!)U*N9V]H+Yks,UwH=ƺqgVK䩮D];-w;])[M ) +S8/CYɥ+HU*ReI#{x)RէSe)ƺU315c`x"Cr@c ?+WmT)R~+j:cH-{ t6ԾiQg(KM=SSQfU\4kJ4Q$=UOvI*+Fbn7TuR<$]9Ǜ2I/9 !줤]:7iMZގDM "HXN ޵Q!K 2ir|~J,5Q}H=P:2^g>TjR\*][swH=FqgV%~5~=*wGb튭68NYljȞ*^*oDi 7vR2y.vRݩtNSG#{ǗV'R`';絉4h֤%x jK-gh*59aZTe6z3?eI__yw,#6k0$6z$=簊,5~8ūK9;Dyb$Ԩ˞3XQZ|;9>8kDYjJ0Q,-`{R_i=(K!7 OeRNتTuSXƒ㉲$aKؙI&RS:)#h2I,?֛9DٔM&Rei(KM=jLSaqS@9+QJ5k*ך-_Z):Z>;TஉD1;*^Tp1^g|U=e;&RS:$VRyӉ!jLsbM"O![N5 A@یtWAA)K_AG5"-&,H=lkvqMye;$܏K]iR"͹ƒ)ɳu!$\Lrvah|C"ёvOxjZvv$ˤ99eiw.]t+?EgϿyQ/Ĵ ^_] z$_IJy><<ܞ >9iG x0\:~~|8/y/`|}nU.>w|TD>KJ'| nKϒ{hF7\\μ׷6}]n}t=6ӥ?=U]B֞>y}kvBb+.lm7*eύ*.A&l{aNrzm?w3{mܡT}Z!+'Wqpnخ}̀tB[ q~>r\!{mߋJL8}%{m2'}]UPo4KG^ڭuP**`ݶ{{m_.4N۲vøglGx{k$xwjw/#6pŧCqz-jwٶY*Fv8q"^gދAFP} n-'L;g/2{qn+qNo++pc#9WKm W٨ح 8b0}k̫6c /`l8,^g^DBP0(` z%  nYfisUn鶺k{QA oa+ܲ+\{my/*r&tl/s؏[Vmnw rBf3ժ슠X[$JCK <{L ^d^D'}GBXnXRh=rL{6μZ)AmPX`c۰tgk̫3`mņٞQ8Tv8G!ghtKņutV n-ǀb3wnJ%15p^c6F1-_[{yzͅS(W{ B,6n}ck!8j Z;FFg[C.h5pCu]W@P66(`CYh/$^pCq:"$ `-x?M6^gދn9:9-uk;n2k^tA?sjkBt߉ 'Ylp79/­ԛW P!FBbS?^a}z#j 3I_[{_MgϾ⦳a KK >Otk~mEz-u$Bᖮ [K Rk~ap^/EUF1;!޹R!8^l3c{a~rC0ߒm?*[y6xH( o۽&kk/2Vpw#T,TbxrmHm Fؓ{j%6d6$ʤQCl,62+k0.^g^T݅&^g7ِܐ@2#{my/2!(90 Xl\d1Ag*ƙBB:~;c@nF"CP *a^~)C P0Ď10ꅇk̫AQUF^a+,ö{M{my2FA ^I, nQcCmCrN2k̫UmHIX0p(%=E[EdW% Y;nsً{Qo[r %s[Ve#܊x"JuWם8DBXFU %*n^d^[EPcWbƒBc!lZFFWl>l8W<^g^l5L\e6fnHmHI{my/bn BûcuWX3o4*ȼ:ƻF&[ya7G;Fm;)՛Wkg9J%!vێHlrk̫KXm|w\6nn;N ƙWk 2)` 0ؠYl%Xlхk̫݆LU`yd766G '*+i 666.Fnlm,8^t˙P1xͰqN*W~pwC$W|=0w3U֯ȼZ粕oˎ7 GU'skk/U@+$ htV 9M5wA6 Cl u(,8Z' ht4ړ՞\`FW,/ nht!8^SpdIaݍ#v%^g B8%v0 mּ!v@|pK&3l`9@ ]uε֯ȼZ htPG[a#FW@+HG ƙW 4[FWn``G ƙW 4 2uV[lFW,`0ڊ;.Ğ ߣ"m0.AhP4xZR( mŝFb3htspKGGl%Xl%p!&kk/2Vg⽅V.PXbkVP{8]6μZ ]*ltpu V2B=z2J].^'saȎZArN2k̫V#Q&bq.o;.^gދqht:@+lM 4]q4{my/@+ htV htݶ}5[ܻ,(_Yʃb;Fʂ4]^g^- 2u]q46,ht!8jFW@+Y&Cl 4]q4{my*A4]q46.4薓DŞ ߃4[FWf4K 3<ѭ9{y/SC{a~ܲ!` \n±ܙoz1WA2 6htԹr4{myv %@+nB,6.ht4]q4{6|^- n4]Blp 6֊b+3W 4]A*0bpKs$ htBqx G[acVy`]N2k{\(~n [1X,o#\ׯ3 ^zUPw (6 =vg#T%(s6VQ` B_0bkVHU+bUA(~Y f7EO4`O6_[{_M!tCniwl0^1IT߹{|x-gBv4|a?n ]Vg4:6μ/T(5xͰ']묂V_.?9/­[y^JT*eֆ A4pq\,ǴWk̫]ʼnq2cѭ3YRؓ{jFWA9{[E"V7F~mEUdXFE"Vr2\s"^FWAuU誣ѭ5µpKتхk{]FgXVޤFWq]it5*5 J-To2^-0j: f >?UjcMn^d^-*ht4 ]u4* \u4{mynDYEjO15pKԞFb3V[NqqKӬCY  '(p˙P5v=~\  F[u5Cqx&:awΰqĮ0rp x:$~mELS("ej 3I_[{y@U 6ht4Z:]= ]K .F=#V%8jFWHU誣ѭ1%6mN ƙ!΄qqK*mht!8^F7 t4_']묂VVfՙxgA2kÄb#FW@;kB["j혻!SW((~Y]6nñmڋ̫óq]E*0Eؘ! X@;ҝFb3FWbaZEr:]=htDYht6ht F~En.th/s؏[hgF9=| WǼZ<rVIͩ{G`(]:]6μZ5ht4hts]C!֐kFbφ~NB3j C;8bWZ!gB["Z 4]C*0xEZRh6htBq|/ht 4]94]묁.^g  ^6ԛFP` -F?mpp$~map+1Z(_@uk`5l| {q>`(kFk̫gF. L6ht Թ:mc9]6μZAk( B,6.ht \s4{my@k(xPoFn]aw &J=Ght 5Fgl % ѵD*ȼMF4Y%7 ns_[EսZwO-Jźs0%d7Vܭ!Sא(Fw vP`bkf=Ght-'P(0*PL!@8jF@k5dѭpAk`50ښхk{3pKW{nhke ,ƙ-gB8%ht F[+>n±ܙoz@jxv'2@4wFcdW 4]:!Fؠ5ht 4ht!8jFאkH5蚣ѭ1w3p p4{my*4LU`[y,`CF.Ğ WJDP!;f44]kt b3htS5G1`c ܆ ܙoz1#?7)` lvZG!8jF@kY֞mAk6$htB=z@k(~vݐl3]i6Ԟl(\a{myvT(՞Glrk{-gB8_0Al2^s"^p˙nya?O4Y>JVMfѫՙxgA2kd7g ],ǴWk̫5tsjً֓sNk{EZ'{/#Gi~n<~pQS\nVȸ?_= ys.ھx^ϧ5<8n ts@U<(rāmNa.7Vֹ՞quq8O{nG84nм\.#r!7B5+ ҁ}jrnĻ.0pKx.gؿ[b܁=pV lhWwےa;t:F~:R@~B6< 'N 9b?9/­P޿@-JźsiHiqyvNiC)lq|?NϓJ%s$N3~:5f+BlgYmpu.Sn\ b 'Wqp qG}AQѠQQ`8`opˍ^n={rgE{lp AqCp%̷lOm>jxwEu>ɛ$@ ]9vETlia{wg;G]= =>u\BMt,7q)y3F? ĻA&=A؛3pHna{ip˄a-EnSq.Fθshx;+ [`'AN[omqiY9yp˙ t#~~3oQ;͂!P"RϾ|#t󻍠k ((0nR 7r]AQqsCmF0/߶;w1 X`(Qu10= ,p݆[+b{9*g<5e ܲ (t'VleW=p!73'Q-jwնػܲ`[mwFأq5IgaG p:/ϓwnYnmA|nهv;NG gp+^%w;BloqFW:M `V+nŰC6FnpFn팻_^n5ݨ=ܭa֒m?gvMqg~_tîܲa0alpKW{bYeÐb{gg316ޅws#Vl7 qEv}O%T`ǻbk7~:nwPb9i\CT|Nz`H(|X`cc(W3%Blo5Y}9 `(sw}}AXW`ŲÔwcf!3|Μ_} (;N\$@sClo\yAqW@P<`pwɁ`~T~: qǷ|0q-n Gp,)pnθku9t -_wP+1? rOO n#\p#HY\x O5 D 9.F޸k㍂K'Bw=7Mms7v]/=R,P⥢W =`9KWol8wsXŮ~2aGvjO1I$ħpq9ƿ+% C8`ݍ#62%3\뙣d:qkyq>`Q5ñ\P=?6A2b.P*ckIA?`{=wιsU%cF:x0t +OPiqCqf/Ἵ F5u#\ ,2pClo\>- "2uV-Wʛ|!*p2wDw4 ܲ (Yd_p Yh/$^|퍻0\R]Чw l[+lp]ᖕ^nEo# D F_5uؘl Ǫ-v];հ) ( #\vk,;n޸k;5i?joūjO,ː|5e[!3DޑED0= ,15ph.F޸k'c9np˩С=~ܲ v7rBloq;[F [`'AΎ1Cݕv9/­ssmfw|Ļ(՞Xa#6c+lo\\t}s'x^AqoPXW`%MGc9]팻>7c@zóK FsK 9hn ޸\ny (XR@vht+l\d_Ӂxwa;E"?>.eR((`-xF7"."t˙С=n`Ѷ}-]@Vsݪn m`{럛>z?xw  l7P6$6L+loEׁ[]Ǹ B snxr GG؁n팻v"ߟ0v4wېې(FG」W{BlgܵY,m/kP &hNS7Y)?] .F!;#WʛlnmmFbf{`'ht+4 ,pnC)nsG8$ ގպ.`|P}4XW``b!7u{|W)n*0z [ 4 4Bl_ѥaQe?W !(F!;9 Y--lq{4c;it.2ueR((2ņ[Ŷ9]D{-tGJrnn*r% 4-;q~gøP4~ON--bOp"J=?}Uw aEtzv!;^`#Fe %2Blgܵ+N>}6Gv궁]&b ㈍nFs4w&[Fn*["FF9]팻v Ɓhthththtѭpܐ@ې.vݻt5JٻmHmmF`- Blogc\y҆Z~VB`q˂ mm.jGU6W=Tgo] L"(]gt߳m?ht!3>۫ ݆ {X`#FU:Blgܳi`^lmmHmmFPHm^G޸ܷgfnn(ht+l r@hh.}WY Y [6kɁFuѶ9]팻FU/ Y [6knh@;Fl^uoCGin :gGPS (cc;bwC){4.ikWAt󻍠vSƒs;n !7.QQ=gnm:\acIa [#{f==DnCL "lM 6,Blo[mhththtVslM@ې@@.v]{n]9_Ӯ4 4 V%mnOp"J=?c7Ѳ`Y 9nP*ck&/AN8w q״nJ%de 4ht+MGh3Bq7*;l;4.&ԡL/8 qƸ%ըړ 4]BjOp 'J?&G g,I$P= v7@wmԼYI%㖠%0mns_ R=?h&^.s cF@KH ht!ĸ}CP,!;Ŭ!6.ht \r4wM[owWJↀU<{8b-b̸%c$T !("Sgn9NZRH&0m}k>,I»qB3-w9 Fd.q~{9+]T(~n [J>&6up#fsQG :Tvl,n 'х޸~{S}@P*<{tpu.!2Bqw #eBɤB aȎZBrN2θ+]]ٻ%$ʤQQ`]g1 2W޸{%F@KYFV [y,`B-F.]lVJ%ht ht+l\ht 4T|EJ{a]U7ԛx6T|+n`AAbV1L.F'Klg] \]B.!Q@KFP`*❣х޸6{NRdQA: l u(S[:]팻j]۫l*4]BM((0.! @K%G q=Ƹb.@K%G[acI`-Q{29]!5T[b?nb;܆x[W7Rϵ Ϛ8JGʄi"TQ`cI']W{2}^{'2'ԞL%ˌ 4: 5.хθ{95n#(F'b lp 6֊bKFb{t]L%dn6ht Ytltхأq S?xF1A4:)`Xa#" @K%G qE(|A [:/8b-bK4em7T}_Lt&זAu`IQQ`A Y2\a{>CěkӫB3n=7V:8F@ˠeG qW9"|2htYu%vZ`vœr`[0Blo'?hxW[΄0tݍ6mrθ+i:qk-A`e0ڲхθMLk3jO΅-]_'],і_.?9/­sM]im2k s rL{팻2$2ht'eˌF0nR 3-͠AhRG2s -]f$Q ]Fvuf$r[a;Ң9!FAuˠe貣ѭ7؈O`eG qqn7KﻠСm[c?n ]-і ۺpnfh-L5w8)0;kq[.F8w qf݇h/"ht4 ].; [s,`F-#9.זχhE.ӻ"Q&b+lp 6'х89dE."2uV-WlwpClgܕuzX1,e r %[lk\,I|A?+_qx,64@ CCP=?WDKCwAg.Pأ4: Gp,G qhɱLgFA 8^`+AHe貣х޸Y4FAˠedѭpHe$粣хθ{ÒT\He貣ѭ1%6m+\qs,Ii4eÒ2uFr%d3m6\a{r_m4P<92Xg|mvHd̠e2WfWr ].dFht!3&!ޛ#A-]Q2ړ+lp 6'х޸Ou;<edγؘ! @;;.v]%#cFb l*He$;.}VxA}.AF#\ -;]>,Ir*th-.іhˇ ۺp,w[+-0/(s74 7 %"q'  ht4]q4  \q4WqU@sL]AL źs`hp#qzUChи[y]FW.v]4n$FFW@+G[a+ jO~,FbOz( [ړ`w DI|nOp: z>5.76hV6x5uب=C)՞ g݁kTl htNи[s]FW.} ht4]8 4]8]=3,P DPDFWn8``.F3㞑"HpK 2uFr-]AFW@+FbOc|ͅ-4Ynns_[7O=3c4QFW@o+`YCݜ lFWp]A 9Wit!34v-Y :{b[P1γl%Xlžw'|YFW@+Y[.7)$ htBloLO) htht l htF[q4w }1-s5v7pKJ!C7{]tA 2 5YBl 6;Xl}۫ 6%ʎ2uVslFW,HN qUޮmA] ;X\6ː,=YP8]팻[3g;DYAjO15p^ht!7rg -gB`% +b;<"MFWuVhpmp+||zoCOط}l@P0\a#FW@Cr8]팻t+UP*htR((0ŮYl9B:]팻o4 ]E*<{%,`V.}3Ksq BV5t9]qWĺ[*htDY:ņ[+lo\pôF7:؏[FWh`՗ d5{[p,w[k-Qӷ|e}Chm? øö{a;EYQ{V.=Y]6ht4ZEr:]=_܌bwAu`Iح ;8bZ g !7$'w:8Xa+oRHU;.v])KA4 ]";Xn}i\:n9pClgU4,|Cɹ1`-b܄;F1P=?߿2 P"@QQ`F` 2W޸hI4 ]E*<{ ]E"V3BlgU!Zy}K ^g/XVU誣хθk5垚| ]խFWAF®0؈O`UG qWaIbz:qk8 3KۑL=9ړ՞yr(YQ{c->3߂Vy'++CֲGBXW`dC9v]Y%0խFg uw h,ht!3-Q̡FWAYFV [,`F+loܵp$U*ht4ht+l\d+o8:]=w\l}["("Q&b+lp ]m18&|ʻWB`qKFWh`Us ݆x| ss\}<6܆-0c]a7FHU誣хθ+-QFWAUd-AU$*sBlogޤCjeE ]u46n F[u5Clgܕ|W|.g%th[؏[FWh`UG q{cu[΄-]_ z,`\팻2GϖF.p˙ny8\c?l0bx: z~!.PXW`%J9.F3cgFWs lzO\"o.f/j-.\eW^禌̢} <]L>z)^AtN?J\u碻&*#E׳k}C0h._mAgEEiˋ̥χOE/,}r 'rWϼ/z^mr\<^ܖd.v%xsѵ Siq亖Jj[݋r%{/KI?Hhc^dq[wzw#5uoWsLTݘ5wO|H 9q>9ۚO Gt%7^\|^ή՟1l5{֯-ļ~/| =$l OL҄K9Wn:i&lI-NXVt d.EOJ`b+[ui>=U&î"mVRN <$Pwx=دkE8|o=]Q,cͲ.K6w CpV)g4 l^ 5e$n6)^#g_%l>w\DK__y`1 %E)IIWŲ `Xr﵎5.R:\M/9ޫJ`@9kx$^zua}^2m{Sx9a&ضulj&e}cI(u㏻e @+~ke?@ 4eVþvIlx9ڋ Hb&. c`PӼ%u YmR`KI_2/) lwOu ,R@괎VÞIi/[L%.2IZIX6aw$,xd!kEx2iOwm9Ssn/[:y=&mV`-bلm|:d/[L5\ ꏔO> <(MCOI]:|ۋihZT/ 1m >=-Ml.be9^)3ejQ4(4Z=u1\JrVu.rv<xY4Nr*+x99a[x*ǫ8{DX9^^R-z^ɾ" U9Um^ 5eVr+\Mrl6ǛƗC_N~8rֶ@ 4 eX˦iQPisbE(H9S)^66HX6aLu<p78[׎g`w9mOOdpcr]mWx/GX]]v/wMxK6G舳Ew:^XMvMv]Ep珔;5ܵkⶄ"Y/8o͋, lJ0Qrv뎧,чS*^NIK r@9ޱr<{?CcCw4?7Pxrcx1cR+}w4G KؙI/ew)?c34)wdWOA/-~IJQj!IR% ;*lY43tHFSOzufL:V#ݝM{lj4`䁰̤s@=Ȗ㽊 L`߿V|zj64^z-S:'$ϗdS#+;HxLdM x&ImKrSns$^Zfr͓:DNU/ *d]I3 OҦL34)iJI 3vf9>J礞lj4`H_I$-ag&AO霤$dSAve`5PV>[\يI=laOOMƗvfҹqy}t<=ӓ^+i4Y~ovP xhe @+fr}4!FC4z Y'y ;3s|]ϻjgn3OXEd%y l;3>Ȗ6%zKL2vfҹ/|9'y$ XKR9^K ;3d xJ$%y$ &++ze/ ĤtrVuϗ`߿&Ӽ{xY5ny*5OJj. l ;մ* jOL⥅tR3WiQ+S'n*^VM>US'L㶲&6xY5Ĩ3MKҤ$`g&TA>Mi|Iٓu5a~RPM⥅tE&ӛ<] &h4`5Wk'79^\NLg A6/(kǛ>& v훗ewUj!J1z;HƗc$L⥅|8ٷ)4M `5-R(i>=5[ؙIl}IEJ0AA=4-R*)䑰%̤ ['nQH ;؃3"eL:* Фv<ݕ JbeL:ɨl8^,Pw/}R'gQ}f`MqwY4JM:3w)?fFVv`B l`g&z]ٝ^ 5dLu0_e碓eOI(;4Ê$R?%ǛQ,̤7Ȗ)EYlj4`{K$OQ,̤I7Ȗ)lj4`LOI<,YؙI'n S`Ȟ9^{z"eQ˭O-}E RI|xxVMne f!l k1ͻCɴL:yx"6 +3,EMO:EY3ʒOYٝJH65d{XQ /(KvfdDYJ03 `<-yԌdag&LAo"Pf>OIcQ}H=t2pX//}LDYl(Kp $^Z&Y;-PM FVve}I3N}(KYQvhR}Sxiag&}V>E|K<8O6-EV~<tr.i>=5_ZؙI'n Njb)i,O/keg[ƻrKԬCNռM6z*^JeNL.N6z$YƗ(K_ norִH &#{Ee~rMH]$s(KMl%V'(K_6nnNs-fOOr7Lj2CL 6=(S)1eW06"RQ:(#=Kd\S"XgԆ\DY*/yjnoSn:06D.g*Pr}R'M}X/?[ƻRuߥ5}C7sXKQR?EI)K3 jSrK9H`,\XOx*W-_Z):<{&/ɾ;D*R|t9(K*WU&:RL>|SEljȞfX 5U:RL}VeEddrӔ}Sc aIkG*SEYljȞŠ$دӉ!:r@9^q}LONY aGȤWqr@4&ao]U*Q5,]wk|9'qJ^dRDeŠ$i(K!3 <;g^霪zMsXMJT%y:û^lMT.dSGVy䁰3 <;7Ȇi@,"#9VcQDƱGL?߲Un"PJԭa$RէSe)u&Iwxd&xD1 r.Vؼ{jǗ!3l}ioeSE1֍;]U*S]֙dҾCK9SMIɦF9!O=x:VڗvVQ(KU,"vr,U1DQBXgJ.g*P~J,UQ}H=p񲳃-_e!و]?O>M'ݲ_M&-aIf#6Q9MIɦF9lI-H8 aIf+v)*UiZ=M)i>=5/CXgJwH!Lr7=x/8/CXgJ]LKrM"luKX:VoR~mӚOw5DP:t7J42n"K'R-ag&Ao"Pf>&V'ROK.^&KޢϼJ@R9n}ZDi"H65d{XQ l5%yZ;13dmEYj"`{R_i='L:Gl}i:eI ;-zJ'+Ӕi)KؙIsxt%y$ ]& V$O(KؙIe"쁲My@YL:G$,I65d,5(Kxwf~ϼUj!s\yWԊE#AAvifj" י|-Ĥ-RS:)#ʎ`'ҵ:[ؙI [R=lOS k3ͧ&L:)l99M%ɦFVRy&PeI3t-RE$hj>NX9JԵ6vfҙd&m34)Ow5kM\l_vbg 3GEM,"ɦFVv%aB*P'L:?UOIM &#NL `{.@4ztQ'L:SYه/3p ;NYj"5Q1YؙI禷Ao"Pw/}LOfNY2p 'KԬC΍U&RRAv`?G$^ZؙIS#Ky77 ! (;iJMy=vbg ;ɤ,YLmۧE}c5IhͱIvf9<dL`u1Ibo/a ;3ܮoexގv1v1$^ZؙI'b-ǛfOI]T]5wxKԬCN̠yU(c4P@+ؙI'˾Dwvzu$VV>AܶwvzF}>.4&K ;3餝 xJ,I65d[JJ$^ZؙI'l-hH Êd`x"i/-̤v6ȖMfhR {;E ړb3_/2/{/;ԾDmH_->󋰆?0*xޅϝau|rYeîAze H)+ٶ~1o±\)P^b5EB cpClgVqk`+OÔG(tq(b;( % JleWB!3+pK:]hmko{qe4.vƁ:*,,-C pKW;ƶA p:/؏qnYs G"C7T8 Ux\mPأ#J9c q؜(xv'}GB[̀o?7l6`;M)PضH({X`#6F #iW);v!?:* A!6_Wnm !3Q%b(r?߶;n !3G< pAqGᖻs6ᖻ;nmp+fjz`H(1w1w|w8>Bq(mwbَ<{.@{tqbόC1G} ("Sg8fa=k>Ot+bό]ǁo?/wd ny-ݹ!83[N-[Nq޾喟Ğ]\kGͰo}v *qۺ MUo?8L_PO vET7{LŞ3b@7#J"O@ErL{=3PtvBbK#\ |+^kgơuWn*Z 4vh\%a!kOǽ7ž>*|!(R80YB'!O!޹!8(Y458 R GwCo#\\ެp@xVFA¸J9kgC*xC nh[c[=3> $ %ڏPdؠ@ۆ,چd.g᜕ 2)`3#62+dk'%[&Ed 7ِa۽&bό;I @E vrd f5ws9/­ԛϹ5i{WIpk;v2ax'C =3lw:FPc<{qĦ#$Zq8o+.Yf`R87~:LŞp˂P(6(a#" e[I2 -ې(F1@[xE\=3d -+*F[FK qՏp+nm]U8V\ެLh<"( 6nV3 {fYIkTCP(6(a#V+U'bό;XRh bXQg`7p 6ܲ+$Zq'Uw 3?d 7ِܐ@m23pfuW8 ;@wYeÐ 9\bόQ|]mޅws᮰1%eWz^bT38m7S.n ,]t Q?3?c0"9 mZn2Lj`Ɗ$38Fa8*Qշ1\h;7:72ODK`2æĀMjbϜ;4Fs7ԍ"æUCǶtd(1bϜ;QPdtdtd2&]*`Z\02:{\@2@@@2`dt+l7`SX-=sF&abS݄dtmm\s,D)> <9 #6&ڌ=&܈mV֣y3f Sx ^aϜh!:{iuHÔv%x& |R.IFIFIF70Jx$$$$FFbOIFIFIFIFn 8Ş9gBtn!B$,]B16%آѹ3l19n3Rv`KXbIF%*/JB8j̛GGRŐ4yl2Æ....=s֣#"""袑ѭ)ᒌ. ,#s'εmn_m!m$]읜#l*Q1Y1bϜH2yv'enMHv8O "a'iCH6YaϜ),qlqI &J6ip'fBtI"@: 9Q$Izt$]$]$u1u'H9Ӗ$I{H2i)6ag|R hs\bϜH2HHH2hdt+@16%آѹ3}$$ I$]Z$]42:{-&aIIdtVؔpIFIu Mؑf neެF % JH0eMsBs7Eсs=s֣#"U""袕-i6`s [LnZxEw(1),iKX9,~!uT KEEa6%\JaY),~1(, 984 [ Gcq:prNc!]$]NJ  %mTQ{eޛh%PR$u1`?6s hQ`2:vRg1$$T$\FlJ$˗i7{"U""/`'ƦZ9* ~!u..Rn0MU#)")ڢ/o;j,bNН>)U#")~ܱB RX298@Xm# W~tnc+Q] '- av$;x ^;w:. F֑=bH:ulKǭƹcEPɹFH+9ѓÐ=Q-m7ƹcnFaID200`3ވQ ͝Uj7F h`nh3DD2:\aq‰%&_F7*uN<;aۄKWSCۼ7s>tھ20`07`-dtdt)7ڹ 1zDDD2&ؙclJbKa=8w(IFR7DUD2D24m$K$K$K$KnM dtdtɗi7 K%%%_F7NcS~"E[ets~fbrNc$]J-gnӹJGR{e޺72OH2cFlIRc/o;4 ]"  )ᒌ...2:ƹKR"["]"]etl;9JC _F8wiL$KT pWs$KTLT@K$KNcq(L TLnMLCv%сsƹcOn1rJJacSX8% m 'm޺Q CRTC:0`nĦ@(|~ܱ@ 6LT X'nTLT@K$KvcMsZ1Fe*4w`etlf hsnaqX*PX҆L$Kǖ5(l KR%ƹc @a9%Us%))ڒ/o;(,MXjlyr4$Y"E[6Vo3_ 2o?Bt@Dчud$K$y sTN$KtF["u/`Wc̳Ojݑщdtdt*uƀs6ݨ HF|~գU/IF 8|~I/`w$[et{\br"]"]"h:,Gl.itNKM;݆hKB8-{?TN26la?cX'@L2Le:-.2 6>ef*e*es9G ٻH+rt=+9;9:Oj݁Bt@2Lр7a$T̴e(,}~"ބOn qxrBFL29i&G `sH•_?N wֽQ=Z![&uH|dt;)de*ee_F8GL2L2L2L&ؔpIF8}~գ32U22/4)ڲ9~4 i$0W IіIіit.ڹ3n-O.SQX-GpcQ/[-D$oˤ.}XGM2L2LLŹ4-DG-,{rM#!Q`2:9G i@!RVsLUL(,SY;IAh!:ۉt'R &,읞 ٩8it.u.tO7dt*u edtّͱi;`xTlّ9 XIFIF7`b.!$$$&\ھrFn_g>Pd 0=Ǧ+3m_IFIFJxֹ4>eeee+[`cY*`Z\2:8w&@RPIFn]9Ʀ$[2:EU6Ò"UFLX.w KJ$˕$\"yԯ}HFIFIFIFnM dt̴c62:8Gfm}Rh=[cl K{2Wp76=u3ChHI]il\`nĦn22:8GfmE62FLd/iF2L2L2ldt.qTJ... .22粑ѹ9R5k*%%E*ee#[aIŖ΅]v E6VT7 B2L2:\ahmm唔`'GeReR4R í33+ )mKʆu؂1` 6 U ``X7`9Nh"=ps7\&Lil-1w+fyԱ-`ڹH;xk8,6"v'AN!Y8, 6ΝGl3R'`wl KR#ss6rJڣsk$+h+h+Ij61˜g>PdJᑲ݀9v'`?A'\8G;x;sHGʆuP4:ghsGtn@J]B^͹cSX #ssvpXRRJhvdN9,uusA $+$+$+T,FF¦K2BBŹbdt.qPXԭ ;s]B<6B|%_T꟝Hw"Q⭰wrIFW9:E@2B2B#[aCFW XVQ\lܱob %HFWHFW:Xޓ+lJT,dѹ9>E@a9%4{O,,s\߀La9#ѹ5vKڴ5]l ܌2~ vr$+:+h+(?6p+L'>J.}Ы9WؔpIF qqq $u+$ի9$)HVΕi=itN Б¦O t]Z!]1ѹ9:E@aI:Pu >)P꬐\lܹ˘k@'z.H+ Nos6%؊ѹ9:E@a9%Uѹ5vKRRj.mb*95ϴ]HW*%ERY`?dVN.qqQޓܭ܍=¦U  i=ZޥJ]B  Xaml4:8GǸh(,IFWR7rI*`iؖ#\87-&#[`Pm3XX9'rbdto9Ʀʰ As6J$+fJMd/i(1`Sb'[12:[;Ǹhٕdt+u:ؕdt hdt\lܴ]IFWIFWIFW:Xn[ XIFWIFW61.e}T"DZQ+J1Nģm+**FLXαIFWIFWIVIV6, K:itdtVPi3JJo+c[L 5ϴ]iJJJWV} Q4꟝x(1.|R$u.a lэV\ѹƹi=ZN()n4@G J2JJ2jdt.q.mq%] oV؅\8ƹi1҉qN$FF9&]zVbjLk+覤=:aIURURhFj61˜ggZī}eJ1`vDǶJأs$ m~YiJA24`MkVV*U*U{ܑQU~dtU4),IF+sGB@aI2J2рQX5'36rJJafa9'GFaڈ:7`Ϝ;)e[#lR}sx3环bʀrFۮs$hhM$V3I͛O94ڇDCIe\l@9Ӗ${11v=϶%eỒcocw|l!c[ط[(K8^tcۋo/:VE(~)~9&~Y#~y ~2G5's'|2'퓁id}>ymd'YI{|d'ο2am+D^c;׻qix>^9|ީ=dN#Ds=OOowimN``X7`#v"G]lW+`Ӫz 6htXNߝƿYb;-s@aIv3~nX`7zrm0gHa))b0v¦Up6e4+\lwC?G G":9N,sKm8 Dnέ{X&z8{ +nJTJ$=p3s CIkc, %sݖ1 {So8DsL9jN_Z`Sź&a1kAJI1S41;Q),3Eݾ6%I쑜 LI1w0;#,3%\ƶtIu ?tFP  ؍ ezb箯)^<" 匴PXk܀MaYÃ[(N I0y'l(JqHĀ96plz=lUͧܭPR,4 0C?Bɼ>ƶt=/{ Pi(QiViV)N+lUU Ja9;bOn/u,p[iX]iT[), l7`xRW=tsל^+%J Bq0$vEXV}lKǙ=s1GF isF јxلho3_ 29'^ zݷ쑲abn)o:{3tޥDe2f'6 %lJ=n6읒NՉsl;#ql3۷س'wZzwNIq;e$6%ܝ&;NaaϜNaSR)f6}R),w =K"NF"l$AYµ؂"qlG=ʯmb*+ӊz# i@&쑲;Sdrmp8^Dc!:kDڈsv6nuN<;a۹=2 B]l~t'GMdϱ}Ʒ A0 {27Ł4ذū4iFaOfzH3?!:::O =BGaQXnY=(MrFJaix-v A Xfnc3ogXAv8H)BvH?-;s [e$pk(gնl]l6naqf(aOFjHYp.{Ɠa(Ɓ΄£FŹaOkL5#eHw:/i3`S~:{3>6"Um׹ vH%ޥJF20 X`wSuus`_tLgJ;}RJhN+l@Umoc[:Np]lܱw )nr-OC@F1lno3_ 2U@;My& ,p炑ѹƹb1sDZ4&ؕclF~vsmzkECH ] ] ] ]02v'W(Rq.w8OW T T(a+읜#Ha9*tusOwِgBt@2@rI*` ] ]02:8w-??c\$PX... .B)mEN\6rT`s(, _?C$=u3s bHH]n;sMDedt.qZsH7E6FLd/1w $ m8p]l\\߮p5 Bt:GIdt0`06`M dtdtdt\lܕUp*#[aw؂ѹƹ{=OaQdtdt*u|6b\ǶtN.q),ل[ IuHF-lA C$$T@TFFbO7w Bt.I"``8p39\ĴZh(Dqв2@G }|q擂= L#b7"42vKUHH6p.'CFޥJ]B  ?ظ؉cl KR {/ۤOmdtsR>Ͱ{X.--FpIfnS)NxMkK1I%ERo6"I""m_Ş|W$o.Tf6%\E*E*E#s'x ;<"DgҰ e6fv%2QT'EP#.l a@UFLXα;󋰏;.x/$#"""UѭQ7TT@TFFbO ZH2HRH2H2hdt+l4 [6m|IyU Z+ BCBsL/#{]h(1`Sb'q'KT5$..Rn4@G 2HUHX(=Y\t@Bt:GIdtdظŦKUHPF2=YvK]E*q閇M2’Tl\ɂ@^tIFIFIF7`rMHFk۽㌌Ş,LטKF{rNJai|-OFϴdGnӹ@|1ʼ:tMxl+# iO FE3WؓE:J ѻ$u.5{Oi6`hP\?^qMIdtz(F98...=>""""袑-IF w ˝\d%_`ѻTT(aŦMaI*hdt.Dla0 "椪=8NCvRER4F61˜7Q'L^>h%Rb'%%*+Y=g.PN&"ş X`#&%*%*%+s׆*6z'%2~dt؅c݉D=쉴7_![!zHU{tn-aM"E[8, Ş9D)=ޓo#]"Y"E[22:{"Ugɻ=Wf7c7r9FF[cl KRjn;FC I23<&'>܃)>!neLf6Flޓ\q0x4"dte&('%*Fedt.䠖{Ç${2itNKTLf6ݨ 8it䈝{ٻ@20&̱3cS-8Wسb..n0VT7!]"E["E[yس{_K܅J.`ظŦĀ́@edt.D/o>;"n4@GP=ľf7KDQ^n[ XHuVHVŞ)kJH 9 s;U=QlPR7`dts  U ) )ڈs=ƫ:B29)ѭ#]!Y!E[L•_?mel:MN|g+ m_Y+FӨv22:{"g,wIVH]Vhb\`nĦ@XFFbODi!: H l I Jk=Q}V -itdX7`]8 *s=K!]u_ԭ {'m%rTY<.)Dnέ{XDpIfnS)̙oy-PiBJ+V,+ %HFWHFG+5O`dt hs\ٶCWMwRWPú H16%؊ѹؓ=}Rx_B2B2B2 lM ) )ڊѹؓUh9)%_lyr4d'K#=-_c sAJ_܀MaI{Olnoc8 5o߽v7+}eɔi[BW}F[e=ٞmPF$+$+$+$+FFbO6ּ/ 芑ѭ)RKɮrPP F6% WŞ5DN()Rn4@ {dN2R9,d'Jn覤$+FF?9:꬐x$V - =&X+9VBt@Z2~ wMHFWV8WŞl@^m.DGԭ u$)HVŞl_dt6,h6h3BBb6t'O/䜔=[ rHuVHVŞЮ( D){ 8Gؤh+,'guX:OC R[c$]!E[!E[m%MLm|s͛9#;)NIeƀIs-c=9bgq^$ :bO0گJ##ы3Q`}~M6.X϶-9k׬}}^XWs}v-[tCjAC'D!7:h}KhybM>y_rr}B'h׀}a] Wem}~Yaߕ^wX墳߻.z;aJޯzuyRY]$[!mskë}. } __˫}X^9tMWTnw{kڹ{u~\ޜ^,]VۺzYq~>/sG\,:9۷757罇_7]g珯 <]KZŪ/UP譽HhWZh_;<jeafyнY108jBSܧ]-a\-g(. ]f#zyw07tP⽢gxS@WN t9hgSC]"-1'+GtI&栻x#уhv]yao_hIxt=@ kyH뇉WO_=bY{*]zk&Śq0WUCGɒ)hqwDq17^{xډxs ^Nsv xNĜ,GDPՉ{"mݯM47Ho*ƛ+Y{Nr KRAK4|qwJ.AӃpIεQ!umIm&栻<]z( "MCJVrV6 RWt$҂9h0fcYu:J51qm\y݃ u#BtlMgV0X :z3ֵL ҈Bר޷?ͻN՝ߊnՃ;;"u(tMA% q)%+E=̩D|3%#m z?nBDc:[2*5Al;;!ujOA%&DODOɛ"r k:F&̌'+kὟ S,lgsPdsE9(o<̉?ݻGRI-#2Y^Y"-H0"ciY"-g퍃i\H~*s|КڌHH]YaH&MfA|o\;pS|<ٻH#<̩7MI=R|$!_=/̙uĭg>8.+Qh( OԛsIYxuO.>v횎toJ+t8`x1ot=K6 ROaE$H78ɠB'OBBIEoqc]:D7 nFd/’uxN膖;AHM1Dn]t: }t$V:L&dEZى#B1td8y@t"U (DœLE*A Uf2Y@% WDU%FĊNCF ՏD)1[3~t@fDID+u5,DDJTnxih 7{Fɷ =H8oQ[*7dl*zôޜuq ǫ;I`G 5<M2:dLדדN)ȭo5_ts&!pwvʚ?{fLd$nӖR;NDlt}|pf"0'e{c#H+RW! ^뇁wU]L-^ZږL8oj:yW]J:q"DKɺ{ я*]/jsPĘ*eC]zU[]Մ9f# n.Yykx}I45:t͙,Mlߢ`FH:b}wG4=L |w% ޯ:FLOAe jPl%Vzgv9vQW?V"l,gfLDP@4\ӵ% M H0KK8Aoi'Чĸ? p!PEFcaZuAi Dڮ#m ڽD/4|OWO}=\7J9Vvmx׫p<_ttYӱ5yśSJ.^s+p tБay'ôgC&VDc~Y T46J$)$q17Y5׋&~D$IEٚ< a"Ҥ4 [w|]fڿE:zF}ܼ- j c:Ҭ{CA)$%tڧ0|!!3Fƛ{k9_'AcP+IR@b3AxCȶ"uIZcboS&Acr&H뇁wii>&a 7H]b3A%""-Ji9,0N"-H[vo&Z0'h{|猎[ʛh4dtZ^kl[EТ%%=s̖#X!a 򜔐D2>`Pͻ#4܊U46 $ZKm[J:&%z+Zcbڍe =Տ+K:L2XH:HYFH Vƛr) r&} 37.*ƛzt"%7ʗ5yZ` J--1I^y!((\:l"mڽ&D/l^at8^O(ECלRY ǫ# ;IE:f^11Jxs}u$K(Lt}|qwJ.ER4*S"Sܐ5y*ST*"Բ!nv{d-~D$IEٚ<LPظ E9$-&/h+7{ѡiлYK'hl46I46B PI$ZhlR߸y[;5g-}= retF3dMgUKMs]}@,ʇ=L5y*lDJs{NRhlTntHCeiGtb=/9$!fk:T!A $Z56.dՇK'hl#KI57T&ˌH- Vƛ19< Mڑdw4&֑28 ,?$v2 KsLG/[ kNgYd'_Y(#9hͫ#ظƛ{s!1خ,CvE"lMgy6=T_TCxsطSb& CE"lMg 0QUR@Zcbjoڽ|7146,"6hͻ4\θaA&c?I`K&ϪBBmiUƛOq@83:MG{L^rxhxI]Т'֠F9#?NhQs(&Pظƛ+Y؉QZ tS`~XٻH]LͽB  MF$ʗ57ɳq@FU%GDƛwo(sAc"}b3Ae4Ѣdq17ڼ-gsF- 4ܔ!z"zZcbo}خlB'f+[g# J-J:vA^J9#z˽_>'RWsPI #NZ+L޹3a8CѢ_) u0m Iv<.܌:LADR,*9#t:07rz*/oP+ɢb3A%QUR@%^q =L5y*CDI%kiE ^Qh:M&u-@7w`dӡZ2G9ar>;iCGRT0SZhl@´S~-m!CcQ+ɢbFS,#BOXFkl\#(G?"uIEٚq*0sYx*Ҕ"ҠR!b]/P뇑wii?˜{QNÇ&tif%lZxB곌i?qtC}M83:Tu:\vosctXx=[ךӆm'dѢ[әQ1ki>_s~vdhlhQFћL!eɨ&56.^|Kp uy/Bt9CcQUR@xs6-Ӧ46,!fk:Tα0KD96.y<'p̘,K冉u:\d UKKە|(EX𘡱I? p!PɢEɻN]Т׷~e}hk]0}p<NhQfS"`~TUPظv1ǃ$.. ]{]47YXxôˆEptU 7s>;7{eCdI׍4Jhl_9WAUHhiWKΝƦVR"l,F03@ӮV [8^09hlaEFcaN4604*hlhlsPIlVdװ2،ƛ}v}yp}JK(Llts>뇙wi9S^ϑ> RhlsPITUPظV}AO @cSP+)R@b3OAEc3`"众56.DO8y\83:n)oVwUKMظ )U= 46:4Yg.*E( Z֯qͱ\uޛlC9? d'E(l9{n *`~'\$VŴk:LaP+)R@b3A͘xR@)z5n"u;P@cS 0;M2gU"0vef})ixϋFٚ<a46Ri(NnwI'9}Ҋݮlz{Ø4Ѣq1'7v=/sFǭћ%i@RDRN"hQ׋e+ϜɆ: Nj!ue$V1m2YE5h*hiYV)Ѣ_FcrÈӁ s-,NhQ/sTFHJەƛ{u5q0#uI冉MAw4XTUʎH;{ƛ--hlhlsPIThQ9ô\1*fY1-wWD: ߪӡg$[^Bxx~U S,ck?v o0%Vh9\D  M t8`~yuQ5xUuoMApDD+=U` ̈́[ʛiBRERN"hoLIk*);Մ%Z&67skەUNhQsPITTUPظƛ},m>#G?b0*!fk:47Yd%}9) 46-&p$0EUƦj9UͲiSƦBcSEc#lMgo|!!EcSŜl*fًBcS"}b?2:dLERNp=2X5gRY?kqtrT5cw6aBcS bE=Lk<)]Ʀ:yghl7.*bN?kB[ RhlxQ PTTq1fWӼZI5y`BcS+J.l30e.hl*46U/Dl46 P,CcSAXeظ֛w/NەM$veK`ǵ ªVNU&/̙[cdNg*ZT!46;ՆXÜ{hsdx#d'U(Bt9LaE٤ D+LqN66K/L ^뇅T:t1' ߩ6TJhl)CT*rKxsM}6|nHu-Aoo&R0'&L踥Yޑ*T-UD/ϱnxX&q1qgt0ҡwqxAN5 20_H4)4]i)2$"l0OAxC4)40'"[GE6hl46M/Ll"m *`~ywظ5'p21&R@ s2YaIƦAcD).Ki#9q_Twp<'t"_|@cӰsYMڮӡt6\-=s&ߧYfq*Le #f9 PܛUKe-1'EXڠQ+Q@M3tE=ȓ=1M,{fqO⬖v~c'SqmRorsOMb7ܠF6ðx=[й[86kM:.k]1A˽o U6s~J^ʿDp'iyٽw񳋆}f{9gND_ƻ&>[i|׋e?n-콍ï;إU]?;V,˖>gb$\g _bɮWk6J9ennVutSPw.ݺwJ ~Zt]^q˻\zv7xͅŰ̻y_ NeM\궣yOR#n^&?_=2W5l9c>,gJ{TQ~\7^/ yK@sGJ{$jd7qf7ڪrCһ!=VzkY_CAs(B?O͜sBy%&Ä8Lf|*k=/Z6߃=4dhQ/OŮGD+^VȚʼnEƸ3=pvS=Xv$ 9Hf4{=</8&Ym[8̈C|4hnO3HW ~p8, z x9KO.X rl*= %ꒆvbiT#Izk-AsS+R~~UmO=I<Ц9ʮKFu9r|# xwOYlpPRګPFu2Y0U+>*-]`[;'qڔ*f̮$uhK|Odh9W"|Zi(šʧ._v籵.hnmhC]V L>mg{Ky@s MZ1Q~yLI!1x;❜mhǍ>/5OyFSMm;Eދ{XOљ=9)B2Fu2)6Mm(zmzfx7o}4G42f2+0HЋ\`u=kŃ湠ʯ%rCܶB;cf/Uu~nsJ) _! hH"#4ȖsA +c"Mh}:hN QKFurA+`'daC&Мݺn(:y_#0|$O=`D^Nf^s:5y>ǡ{lS~]D+e%lWB>? r'+l=ټQ~\AMMDztͪ7v_G֞\<;\4%E)$,}cxM=ih\ [>r0j|,.20%H[Lv6<]C@sSړ͟Gv d>t>'k`:q~eJ{4~O6P%m܃V ѭT (B `T_ 'u>_{2E椧np,@-=lvc~J3섰@.Â8,f|Z0RjeK\v;|J{%[J6JȧYv'~4f7-w!Zcf|0>U v =cqyVK T2Y$ dN?yL~auW031ϢZhTԟx^N,*}0j) xWONNqH>C }辂}nt_`H] #+V*@_CrN($'#6>ۚDi}=uخa~=^he&l(Fz9ï>z\8})v/YYt_t_u_.̯{26c\I}E{HHWԺ/'""Pht_+pC$hׇR'`(RhNBEDZ$W+jݗ 5.Csw'{rUBst+"P>5.t1>)+"A\ןJq8ʯ%rJ}Eb㕏֟^o˟VF}M)͍k,ϋ+}E>U}VMև|dEz[!#+Rm*0Zu/4gRڃKe.r_ dt_Dŀ( Fo@|jkjSq8:xΓ*FhH(QEF>Z$T+ݗMW{ ʭP5sb"XzD 9UiIa2}K HD&d%!Lfr*a+u>'.$МڈE jSiHzpx0Rm AmD)Cbf7Ӯ>6 xb>R'}BC䖌k,D{*&M%o 1*$=. 7B &c(Q7 Y#0%m(RPxJ at_ GΞmT~-eDDWٺ_HHJ}%Z!#Rm-+AkǼP"WXB*Ak,F`C(}f06++A58\ |?++Avmx׮DN)Z>kdy^&ڇ0a'M>M2jed{2ƻ%0$+A} ȧJ u_.d<} [)A%Q~X+'+`ft_t_ rCR&W+iݗ ~v JFBƸ`8*]~yڕ=+6 [&S1+A.d~}C?/}JqX #~yzrYy8Q"%aOiE>U0ܯg@WɳDQB9u/#hݗ <9<$t_|(ŮZ cOZ/=OӿyDD9gi|JDWҺ/xr=8SP dt_ dF`C(uODDnpզt_ɜOө\t_t_ ["#+y_ }}h:ϰn=yc\< dtcs0ځH$Cͳ\y|=95+S ,FBN X@=ks1y(z^(+( 7GVRWT[˴'a~1O]`׵~Vdڇ0+Ca6.T[˴'afY\`u=;v%pqF8ِ,_L5žyM(k6n$ae_񾿡_s'a_ӊ1D*|&X R_}ezvr_y//J{}FBF>%WTF+kݗ lNj~~CoI}eZ!WP^er_,+9Q:+y_%}eeae>6~G_t~+e%Rk4t,LLZ -_e &*4kJ845P^hiD>U0ܯkK4 .B QPFu92t_#0Yfr_*Rg IOi] Yꪙ^jS9!6~]{2+4_( (yXjSE/[iМJCb}0/wETP^e}ޗ l=X*IIQcvZ!K}"Sm-+C6~ +GRId}e}e2t_Vȧʤ}l)1iC[T0/GN&cgiOqcasdciL W.j\k5xJL%"T+ 6WY\`5ɼ{gʤ( :WRWT[ˤ}er_$xZ8)AFBF>Z&W*Ư2Ue32ɳ2t_lt_+d`A؇0kݗ lB\PM!÷@"j{`$"If*`DQ]LZLglHҺ/u-"ɉV =2#:t_t_u_.뚅ݓ@32ɳ2t_lt_+dO`H Uֺ/u,W+=/J{( z= yGRT+kݗ l&|&ag'W)w>JndT_ cXt_/[kڕUƳr}M)FFʫ}㻕~5>u 3rFjyK!yVy< `T"F`<"E([MrniuМ((7n*2*T[+T*} l{BB Ge_&+SU"@V\`pF_ʃee& ~0F+. LmTrl*=IUHU *Z[O6ڝCh Jfpܟ i DXei10/]"_ \bHO3򩺇~O=lYӃV5 / (#kDlBR(`)N?G.JT*}olUݓWIU輯 JnVȧtWTAK/x҅t_J`EW12Ƨ L"V}֯F9گrC}a}Ưk=8B)%yTZYZ/=/ZfR^U!4DQ&ȧ*T*"ISuvI'4GR U b117DR,HlՔBs< %,M8}zr)IU*(Q#\hKWѺ/udat_J`EW12t_#0  u/˟Tt_SʡZ"8 t_WǸ`ƪ;"Ic6{7XOq%Hv ~q t_E\`W9U? **t_bt_s WZTEѫjݗ <람 T*U*t_V ~1p! Ht>?^t_t_%Yjkt_u_?$Xt_ W52t_t_R"u_.̯\␶>|BUkg1DO/BXSǰ_ 1//(( e5r_ Q5<>x)IU!'q!CUIUiOIZOꃽ=_j]dS}UMU}|`ަևV辪} bF>"؃y3yQ㼯]G\!Cz7FC=ykF W55r^tW%TF=>|{_sIc)4>6BA͸%ɉ1ϪT(B `H!' `zP^U H0QiOJ ~jxM˟fBsEi5N]dS}UJU}3q8D}`Hi}pN_9 rC}UaUj6*}D$s\&Odr IOlEn{y]IUIU\492t_t_t_u_.уBst+*P>5!\d̳`ÂHк/xRɉFBsSC l`7q@DZTjݗ yCJ{}Uܪ}OIUIU+šΧ$*[I55Ӝ 'nOiFiѵSiӽPmϮf{]; f9犧nViN}O"Ft[zy_}ZW~~&X4oY]?C<%S?mg>EGݾ9/lˊ?,~K2L>+'񛳢r_|򿎎Ko܋Wd¸±[J`BiNE0Z/EN:iOX58+]o ; TwNw' ~ְӒ v w36^!mN#> v3QfP&n~vZCvrk~/CZ C3]!7S$=/ᠤO3F%fOr`ÌH{t_^"/>~\Xf(3 #ey>yPġ^C~ eACYC)K4$ȧTXr7BB!V_0>iU6{t_4* ƧゾV닀_?-=Ҹ>g6ގ:}?Cޣ vv|bؑwOWȧ;'vqא_;tG= VȘ;"A!eio{eaGx~8_ϧO{HB{EhNLRKFd m~ee_&{t~,lJl "7HɞM~mxoJl e~I}Ǐ=}o>pM!QrY+U(7V/ %iF8P`HO|0V?ᠤ PF i8(d?KYֶmW׷l ~EgmT[ۨ6pկHqiX2C' rPěU~{}F94?Kt۫moΧpB84{ya%Y$}}~uK4.HRlK?"#&ʡ 7W?WgS;Χ#2Ƨ >r|;jx^8lJ6_Y>~vﱼ_0S˘ڡ䶙=VȧT[ۨ6e>~QR lCJ> 0#!$?;u C[zӂG,̧?/<$KyVyVCKYγ~_4>-4,+2{"+ | ւH*J`P>ޯLqX z_RVJ{( ?}/>~vR(fO5զ66GSR lCJ> rЎj>Xp( |1ߧڶ-= q8D80 |{%,W;el~ }}M}_gg}0*b`~ $|jvAٸ_;@QFqj(s YjkjSE/6? T (B `~e|Dk/UyQC5+d}}}f򩜅X5D> W%Pڳ-7? ,?NC> JW!J y0ʭ(ze T (B辂}wE0R$|s> (1{8+Pm-+@8$W+@k|J)E$7e0ߟR6'ô$}}c7OY!QKPFX5!7DqLQq W WHuhK|zNfqt_>uӯOIH Z_ T (B辂}1>iUк_ J`^Bjk!ס-=/%0Df2I+ "W=/~)dz[!#+Pm*yɳt_>_IZ~Qg6D̳6*a^HH (Z!cB@ZVк_pF8?}ae(gCs>A@"V&B_#"I(-%_j~iߜO H \qAC>m4H]~AoO!\W20զNӝt_%0f" T[ T }e(I (Z!#+Pm*8$yV+@k)h ΧO{c3rosE D `MB#AW4_H>EyVZ|ԡ-=WW# &f HƍwQR , bC"t8>Q~//mvc߯B~M( t,ϫPD3ʧێ~1w t1P RQ% "զ"^]~u[I!D}_ǁҞ;D>Ǿ9+FJ{q%jkR",."!"P>_ ~10!W.(gCs>AЖ3*}D$oΧDQ~++Rm*&D}_$ɊEEȨB>%WTD+j/yVXD*bh!\!W 7Eqiq>6uor{{ ((EZ!K}"Rm-Rm*1<+BFBtW1|} {(B'~и`6:vA${*Ǥ( ?}EEMłu_ H(Q|JH{Flv(|!"P>/F`C(}_} ?}E}Zv1e(gqXO+ |iˆA"b1w h-"b#7% bgȘg 4Vmh/yQڃk`qt_t_t_u_t t_W42t_jkq8Z~T(B `~a|:SBy8QB}b6"DXT#I\_qzR(J/ DZDHJZ~ W"J+">Ki"WTB+iG~ݓLD[&l>JFB.wq>k5#1FI$Jš=wE(a2"W"T+i/Eq8D}7ɧO{c~ tJE `~ZX|$~_JDQsdH۽&}~UZJ6*W8D+}/CJ{(B `~6"E7S}%}%辘VRHJ$Jay_߯L~M(ZOSiDX)|eEP/4>RzXJ6}$g%:++A_~+HR:NFBcB}_ǤJ( ?}%%ړ0%ġ}_J؇0}WȧT[K'aߜO32#OaxeCNrh~+($JaD)UYaՍ?O5Y /DQݙ}%z%MHҺ/'*4. W+FF})զ^=W&Q ,JFB|8*}_P&1ߧZ"V^}8?}%J%8Q"k,~10!W|ZO{h\M{֯ ͳH J0} }4>I~կFqLQq W"WTj$eh\@}%PrKf2YT[KTJ(z%_RR%Qi LUrHHbvZ!>AD"VҺ_pF8"JJJaӽ_{_]Bゝ^n)٨,:#,?[ @he Jn%Qo}|L qМ(3(7?Kꪙjkt_u_W%Q6PVyf222t_Y>\ijLL W++Y#0!!̣k3~Q(~|n{Жi~sPsxXJ6}gڇP{_A~Qڃ] ?}e}e}e$}e農}3bB>o󢴇^~¯8DMoHqؾׯHqH ݗF LL WߜOI5DƟC5SBy{K//e'PF}/;"`MD_t_/fO?}e}eMHJߜO;S%B:D'geS1V*C%|SJJOסIÐ|_pB96? /ՎCX C8D柈C22i2DX9| eEP/4. IV(j'iF>\n~_BiC9ޯLϾ ΧnShNz0ݍ 2tWT |+t_[.nNO6Q˧!ɳ2t_\8)!˧W8Qj{|Z1>UHDR qyJ`~mJa8xxt_ܼ/E%t_Y!w`<@y>ɧ;[{Kq_(A%Q 0?{DtG}@UHU6U*ͧt_t_[y|BBZVy|o>[+QVPy>-8k$ߛO ʆ~A l`8d_VHU 7E)%p8V@U6O/2_ȧ%l//((WMEnF "i3~aUHU *l8DR+P@5OEj!WT f-ϧ߯L~Q㼯_ϫPQU?~5C } t_E;"`aHO_pB96? /CX4*}D$E?~8(d?藊~q t_.)*}J8PmPmU?.~%̳ P>_~10!W.(IU"**$*a!R"xCUHUh’#_pB]K8y_#0!!,ӌ|a,)cX2:l1Xa?؇PG"i|Jݗb/ t_|s>%W!W@Uk|JBW)ߜOIUVP*}g c|:SR~! ;!=I;5J8~kF W8 E}J uߏypOb?B: Jd:ɧ.2[PmU?>~J#oΧ+;=>it[) t_zE_EI~__.V袰_.Ewɋ=}?ǯw/?}x|(W{G<-}\j/??tͣ]c~~j?v约;?>~[}~"ҠqM8?޼pysn7.onۅyOej?p9ߞ:۳l?GWo Եt+imθia/ ?+h_GkXXZoկejRߍXJm[/^-EFt)}(jW#Ǒ5i/JȢjc@j]#,+DȡE6#EȊI)vX ]B,# -Bk]$vZs]qػrC4\/~QM=:kRB bZY5`WOuy7*)Igwg&UCnbHV::"GF{{Mh[wXuZ#*&݄M%8:8r؍B)^E!Bu6 (QBkgt"GQ .:Z["dZ#sC#~֨ջF;8RK^gEhIrv!thwy"{ Z*ݹƑk/:6iV$ Ck#ť,:ݿzo̪].zM).>x=;ru VNZi{!+ HMu㊏]vMFqGQqCpɬ!޴'"tLdV_?Ժf3Y~'i| p$ Y2 MOf#% aY"owjI#(L/mS&b x۝hI4;ݴAB#ZʑZrO ZwBݍw$8왲܎~B1d0; D)Z^ ('cA$ YG9h#C;\xGÛS/nBBKHdg(% UMB,Rktdؿo gZkm82jXm)G$ıE`J#Vy"UF6[:̶k :ūq8"r1--tKAnoT`aB8z@^)k22LJG%fqa?tZԄL^DbrgN5"ڻ#R@%dl;cK*ݹvi.#;m%ň( %Sd!1#@Jw.YFC@Ym}JheINRaZZ >vjQEPTZESg*E]b*ZE"ru V8>+Hr*ِN;GtWdQ\$8Jw.qXʌHr*98QyEjV ~uwM];r6#j2yW^z(xQQ ²D9r8hbX%qK!JhUyUgOquE%ٺjycpmThYqIL6IN"ip{LNw̑-gh#lՐE ʌC*-Jp4 'lǗ=E+3)FD)P-2: QBK `Y!9i%DE~hy2$yHFF4qAL%ķ7 ?""y8s*ZG&OBE{(6#hr@\FS&= S<_dYȲ&#SFZ1#]Fę#)&d͐(E ɬ [k|5\|ioGD.iQ!h@y)ۅl*.1! J"K"ky8sزCCEVC]"Ej]!."ɲWU$.vjVh7tZ -)F-CHѢHv$bVDRQ@!dK; FqY\u!#xn0XGA|QwJwEw1JCo/.*"`eL2C@\yF\;,")R("Z2ťA|HEq!#[DRQ@!dOˈU_U\yF|CEvZ(A|,PW8B=-2;>ȖRŕh7{d5!+M#@ВJ.r#_~rt>yoznBEˆ2Γ+шoԳSDK˘C_?Ժƕh7Л?+X!E!BK(N!EE ŕhĵ#z]5M J~MR$DWEEq!#,2bDВ)>-#+J-<7<0cyH)2mv(3HѢ<,+Dw'+%m-i2$yH}E-=$#iG&h v%DKQY!ޡ%TQlTQl{hA:sB(DDR*ؕtT2g}uD-k!FGVwh=U4UOnpy7JCbz`:]I%9b{`KjPE4j!3%S:;A|Dҝg&&{U5ٿJhɔv Vq *1ƑٌS<'dY!^{(6(6Ƒ{NV.H8jx?4W4R4-qGGZ.ָT4vOwWOu9 C["= IBF0#]8g I#E }2+Ej]Ȁ8s+(d!B&dV_8ZRhNVę#4KJhI1IBhE VqZRh !ę#JJhI1ys:K+X!M!BK(Z(AjRhRhOw#yHbDВ)A,!B|&-W$!M"L;Q&RhhhOw7i=9I1ŮIhY*Y4W4RqL=EIhIh J-E:UIwteVt72lVD-В)#(;B(Z]d,_NHo"i`Z?&DgZw4?Od'&ň&-hDqHIѢIL'$$@!dH!B(Zg@7i=44n0mqw -֢h;BݥOޤɾsL$mCGCidt'[`Z(>y'et'q]fh$&Dqa#M4MD!²D9rm_ÿ?+hu2gS':~2'(|>OO3'}>>'迾pc~jv^Wޭtp]k{CZ9[muҞ~5##7GQz537{OQSpQ|&."B{[ z #&ָt(iqQN;)v Di vKl ăe~Dx=!Tѥ%xLܼ{jW}ؗ`ޮ3lxea\?,O j ɸ{[!.5nJ+i"#7N+Ko."8 {Ɨm0Dg)t҃b<"kǴhGbeVfOf|ՆφҦ7ua/";o ayGi cEx(DKTk,9\`{][x<)={.:;sF(MVSȰc WEE@+3 GtHad;%a :C,7W%. U&,gw ![$s. 1Pqܛ$ j'v?=k?5 3t)0[|\`j0 65taFpG ٝHl[!oSp y& gmۖk]J4G&sKpl*V=p=L~-bBGoގ~t[(sX!7-4Jm sK ERŘ6<%~Bџ=X[:θPEIi+Ӣ\`ׅFdBDɆgS#7GR [~BDE] `KҰFdBDE$6وlQ^"_n"/Ke k㴜;- Nװ`)$"u zͻF9洸tC^/٢νkaBG®WǗ'F&$6wVa2?ݹ)= ^O+a|d#apEŸ6#_nP ( kW}gǩrt' LEfdy6%Ee<ךxf" Be͍Hl(0 V!ܔGzv%jƚW02(x;g^V- [  _L[_2tQ3X!Hl%[Bs/`/ Eћ%-inL [A,b X/%a[*Ɨ̭v+if)! k\RˍTUP $,j[~*JBD; ^VL,m1,]|v`% O ^mi;x-pSzʌ/Ɨ-ݾ{F:v. ܽCE-YB2Nq{5 cN`g. "(BiVF#]؉K|ΤpcZS@G٢ۃdiEA6dɃD 7 ZVR0%vm* `$K%ڴU)|B> <V\(M 2ʆzcרI隿(g0MM.lKxG z|\(gNqۃiQd)B!YZ\=[^Rd)jRd)BdɅdSD'Bdi"6<|-Yrag.ABg9  37]MuVF:N ܽC (ZEd)QQZ\r&MvrEH-RlKK%K.%g Rd)4pOփ|uO)|Y?WgRd)BQ͊ZED*B ZN\jgGQnhva1dXdC [\r>C4#K>lF:ľ;A-!=X)S&vK.iɒ ;sɾK%zKzlS*)z~lw>,gw66Vx燭 `QI=|ngiCme@@V V35A6DHG5+i Vj [%~*JBdߨ !7D:$KIKV.v0| R_6-I؉.a;f{+׼]tǃp#lγ)S4PJ,%HR^KK,%H$K %K+XKԭ$K %K.hRHl%K+X5"  vR$K  V Q(iɒ %7'a!Rޢn +OI [%lɗI}z!cw Q[7["_B^ %K.hrv'$KlK&dCIK\صKP/!YJ, |960$K %K.H YJ,%H$KIK,%ԭJ? %K. RʈHd)i 6%EA6 Ҍph\R=2,%H 2c|9"!t7F~C [ RB',#Y`.ڥ.}Ya1-B*PQJz=K<Ād)aO}$KHx3,wsa߸D{'HKo^[1V{ Qһo\:"uk YJ$(+YҰk2Q+oBӰ" Jˊ|9B@r2_O^U'hD=B ɒ+YҰo\1$Ka>Q^4b>jje5i#Rd)A4x"_nPI(%Wa߸D=%H L ERr%K>,$K,J4%N4A YJ, aQ d) YJdIþqߨ,%H$K լJ&ȗ,%pRM1-[vn}iQ5xk>ڧ \_fN~,Exsd)Qɐ,eW4Mp` +`X/'DCrrWVn\`LQح.?v2_OF.ٷd)CE][-`!Yʨ[eV ^v%KvRYfgy x24Deð}Q3$K3¡rIf~ Q]:p7-z!><Q^uBSR!dIî] >ΐ,eH2$K+Y"_BQɨ(eWa߸D3$Kڢ Rd) lKl(% %~BqRFi^S2V Q֧,o\7j p)03.+U'CA)K. ҌJ" ˈ|9B@r2_O^M;!ez-rXHXelQ]ɒ}M;ɍQ Vʔ:ONWa߸C׼sΦ"2lG؂q2J?%![®]z'Qa@"pE.%!%K4̐,eH2 LJ&R Ȩ[eH2$Kٕ,i7. Rd)C] Rd)g/pKط|?>y?}weh`Ͱ.c Rd)kkcH2 LE Rv%KXJ44˄d)CQ`a;J2n!Yʐ,eWa-&xHl,eH,-`/Qʐ,Jk\"d)C[!Yʐ,e#YZb>ΰ3آ.ɒ8ƋzB84G=^ơGj%4R}}k!rmCbGq2d)CqQn#Y`m['xC!Y8 u,%$K R6%lKK5(G2E R֒,Ɨ / e-YraFi]P`ʾCF'CdɅu7#!Y;"}Gdiڎq2$K%![š-oTHf<-YZÊKld/w|Fo! [o8k>ǻ(GChjBsOa;+HVƥ˫7G2-*[~ $KESC´;\ Lp=xJ=UP`K7jyP56Vxo` *=|}j'/0}vpl.-a{AT *P-YraQ7jgy x 5lJ, Ueܢ"QCH-|@3XnSK1psk\1 $K!z;-YZF4wĠOdCRdG2-*[~J@iɒ ]JYfg9]Bbdn,%V)TtaK7*$K%"E$IH,`e|9"  ָD;in$K[ VjS NY*X!tK}EQCcJArsiQd$ 5-raKyd@T Y*,-YZgUA駠TdɅ5.>b[E"OxEoQaxآhɒ k\QoB84G=^nu%#{.qiF<νO)cO]\XRy&Ν9'N5DÀ|/[HV5t| : !d:vKxG *_ƥRdIq.a!Y*,~ $KEK\X|R)K,T,`/qRA駠T)K.qi>˄dTP),-YZb|IP(>eɅ."_cspi Qhɒ k\47oBӒ5lJ,H} D|Y :dEE@+LǵC ,WaEdSʗ.qi>lTPns/`1-bX inwʨY)ؿ[:clp7X [!=Dz܈X}ؙK|Cs˴TQnHq; ylM`'.URMx3.P^EB̥cহx,UH*Y5"_BT!PvFMx>!/7 Q0,ag.9oԌ Ǧ Qf/R}k8/x Cԣqa:˱)/'s1]dB4x=XH*$K R-~ag.9cH* LE R%KkXLW/'/Q = <VjuOd?_O^y <$6H*YLσEdBT+/'/gH&,: <İ#I-HOF&!FŴUb$lb|ɰȐ /'# 1 Y,Un?l=XH*V Rm~̟\3˄db{0-B56?l]XL^uq׽ ĥQoBk~M`%Ef37j +Q)GE7 w?%H*> |KRݢ"Qq^^{B A3X`/!Yt4-؎&d;?Rd ?I_ᓄ>eOQ3'}>>'ɟ迢닦~Gt?U>w4ካ='kWה9o# ].8"s}M\p`{?|Oo?7Oo/?_oo?9O7{8?ҿb(G80|?_˔5w)|w~mwo:O[Tu{]?{{\OǏÿ/3ǿ/m_W?ǟ=u?~?xُxowWُ{]Oq???ُ?!ÿǿwi#Y)SNaf5qŦ/\TAـ`$1gkvABp;Γ*KBs~ӭӒСБZBrHJrG}yxَ#yhQ_4.da_K Bg\d`j>kU7tSW`F?U |;$(aU.죮壇x0{xb13^]|7/_Ū Rw{ɹ8!UYo=LR%Qx!)wQR3Z$[?^U6/fh_5MAs41{٬Vetn\^FҺ$fj UEw&6FFf*`qVQK(`rXCUI ;5*wFBlLlAyӅ-`rO,4힀M7x&tAH[ڿ$qvI=9)+rV!$|?=Aս$rߗV؂Dy$}jM^rzDnfdrwm9LaǶ;; [i ,oh _4gonG'_p?\o?IX#_gSXs W$>eYkwE\H|⿐ f  }o:r F 1v_)5_\7_z/B\K/|gY=Lr!ˋ%kYS^G¿D ?h:g@ \7[??\+%t<`6nc{%? zn.&a盭㿢//*HmQfGfO}I:l?]?@MD{i2}⿏OL*AXP|c=Lq80hX鳀Ьك8X:#9CNߧg EuJGϿv-QB? RK/o6[gQkk0-2o?˅}ԵF[˃BQΟ] LHǪ |c=LKRx'Qa._Ƕv`o+ ?r?߬wW1`m@ھ v+.7k?IX ?yQfG?e ]5U\7}$^BO>w#s-l'ۿctx)qФ mGNLDgvmEdQpL=ƵKF;DKgwl-׳;w_q?߬?q'l/bpa_>7$E /CZxk? gGm ȷnYsߝ }uva^hMҨ MT3J-Aj}7kvEFhվ^͸R.׾)r+y};=[*O2O\7[c#5fzZTA 'LES=!2z@4?yjKl~ `,0@ͪw) Q#_E ˅hl vO!&j=L6'\h\ )FX"+!7dEBHiBVdt1ªhVj8(FK+)&ѓC@NLNGNB}o ,g*\\:Kk΁RR͐f((XXڸ$"Kf-|<,ʇ=bN0F;9cZAl7ύU_NI/FX/?^ cC_U?8ba1チVMSI+glBcC?]!/@9jd/ 4?]Bt&Ju|:X 9{ߍfUa?.U_F?D]/ńU&{$EITth`>g8.:&3ń_E|gX!/fu}Pp&} k96YR`/?'{߹Ex fAloU|k=LWHXUh: CQo2OYp;.G[v`Y ]Ym͇W+|\4kJ 4\׺"} Nè4p^=uU.sSOW J֮.;AUA'in̲Gz?e)k0Oɓ%|?r_Y 뿨 ?'}w{[lȽ=wGYv}uL~.:E_Aai_ͨ(o)-gINȤ[ R迨@_.&OH\G]GK;䕍a`uU\7n?+٦# т-Sdx6ja+i:@㿋݊'>xjDl=Lqz4X|:oV{Z8&)"?~_ Gl41"`HȐl ɠ[NE\Dx Y^*L_'*TA3 /{I٠$#r!Ú@G~3H\o?IZ, wz<ݵ/f_S&'] ?$ {X ?kkGr^e ON?y\7?Ep/E0 |g_ ˁG.˿\?;NWu=wgο7Obo A|o?I_Dx 7;e|Jw/k0/Ud8'Kq߂U(!Jo΢X%]]\7޳E?D]!˃-keXb=L'{!Dhqص=[n9]:EZ_$U &Rٹ 뿦"?@Mf"R=G./a._T!3@FLD12ymo/ шU qY=LB_Y\0>UZYo&:3eMT;f^./K?bM!@?1Jt_.̆D"V/ /_۷_Ra> 9 ?:WUg'0;盭??d,\X5n/lirq=A?A|3{$J8A>sMd4Rk3٩Ǵ_U4hs?d-/G_?. F ҍ_[ %TvЅW<4hlw2+ _..r/b$*bּs.|3{vOk?.7J{Ʌul_? vg~y奔=+dﻌ5ߠic4|k=LE ;7fhG]FH _m4M>E<"ˑջ\r^9JSƦoq$:ۿ!DžtP.)L?~}Gd^ˎ<S L@h9|l!4xh搜d8g~3z}&f <>?9AEPɹ<~rr w7?9?/׊=2[G/';;^uw-~>~Q=Yay'YاAr7=u࢛_#|8WoN2O"s|y|KKRsHJ=|~~|8#{8GG?(7߼bq-nS?[^~?wQ}o?_?H矿7_޿y^?<=/_>wۿtsjyuKM8<ߟ IO"Kp{}W}Vu~~e9hf~x_)i >/']?/hpw_c%7뿣m^~>y~oim^~?˟|_揶__ 8՛|W9o8}?OxOA'߼{#?><:Sn͏Aixx叏~_'>Q>yPh; &cDlo(ǯޟ>/z{?}#ϔ_HHi$u3w4Ac?2~?>}3/޾?yR ]"iK Z,8j&Lˣ,~eD~v~(x}IB|xU_{a9#~įo_<|!Vb>t7׿=}zbDQGw߼S4|?_e^>~ 1Tꑫҵ|M?UĻ_>|}?9+ ??Q;L|=?}gP//^? zեE;Fww77iK ~}Q9`jkh49_yy˯^oZRcAu/a#)'X,n#uK>_~R-/DVtf ?z@uSgjt⓻)*zJIwn)TsLy!3l0DON<& `">E݄$4acHMtˇn5 /u.u9`whb]EE/i1]h.{l{$ӳFj#M#FYaf# 3͑1nn- KOqNus+(ٚJGڒ 5Xv7{U{a$7Bq{C q3E\-9wۺmJ@ K@Ԕ'F0@Ka. Nk ;)$1=e(po):7qUR]+U:庺I4T=Izʻ%/YZN ,}Xg""dP2EZ5C^N ܌9˯n9jZ0X>,M+nvhIƪ/kUJ>;>i+Rsۉ{5l~bGp ob d-{<]@ +dx<]@ /. 4p  Kpޓ+dctɿ'O«h2]iVOO'i G!fqY6SJ+%\4Hce,f$vJ CpbӠ[Dv6J 7"6 j8=(}-:C`p'bC-\SSjX)#, lūƅWūƅW;eqU6 ū /jâF), syUszUޒk@*b oe.))2RPFZ)346 rxUN "6J "vJE=NxQjxSJJ+A "8-)UN "v~=1 C {rfLf8ES,8EQ$Fva*)%4vE(NiSrhҵ}ְ|:3 ϨBXNF* 3̈6=π6$|0P#a,2TʮnKV?xxhZj YY4MTsmJ̬¾; 340%flzNLOX}S}SǪ:̦ 4Im캔ww.:B|z}š2MѤ= )ԽiL7M {DG0 Va{^>@2p72ӡyួeٓuI#hphCA=w%;,2 ``dL]_~s%LUY!BùZl>"Mtnm6vK`gv@seXD9\\3h9`box$a] E-'ixNnUиfoRΩ[Xp>u0:YqsNt@J֝Sl2BTi幔ʆ)`i9R,Z4;q @ӌ1jA³/Ix} )rCҮŴF%;G{,6-O6{*dhՏW6,=F@K)+AОoECn6H8y.8nѴ3a0YuʛeM[e=N7)m&CV^2%I0)MB.4]St>[K<LCm%BZ8e J)A)eWQɩ%%X(%즔1Bttq2ϭxloyIgԠ82eikPr](n)bTkPj])ew)^(9#8=j8(%$6:ȸPgZM^*}Pjѝ*CM n#\-(jOӜp+ G|+2k)+/4I#i8|Oi8UYV!uH["B+ڂ5|al h tJۚ7FíA>WBI G%-[C:%e-mlZen,C{lRdg^-oOˊ-%e "ON%,K-\ń!i.4Zj8 0"Mwڴ.3>A&x4 -4hʸ#wwZ}QeSXG?=-5Fs#5exgWe, '-b/;[pN2@؉0n+:|E3B6 3욱A1fW7 K0 ~K6X7g4`wg@ 0f%-yA0)cT̈́bXe@A4-Z@/쿖DB'VSdJlMc amrtg.8+p/ݝ)=Wwԛ_WEu <[R'I]܂g{7'b5fq"-iOD:0|maUMmu-5;[:t2:QF;ˮ .H [tdnp:{F>.jZ۷Фos|.9ڭM>Rػ0<<(U̼͋u%:;T2oP8%cҷPP9V[c*KQ,KQ6 :u:ѝ_*%؍'n5e,5e,=Xj.R7/2V u5]4՞7ѕ=WqwycY]>dofo1zk^LQ7lޙKr1Q^ߢ. ]?R'!ЁOV_JԿ௲3qb4/e7^bWՄ^XbO ^Yb8X _x-邧Klx,5*>)6kl\X~~%Z+6O+~7xL"2b |ÂLx.x69@`I 9 ye_l,$wz[!ywzE$[V;2l!-f0T+ k\US0ސ0+pWB/h˟ڜVn@R-L{M]vSh"v?/jF,W bM:B/ Ysq?9&f#NؗKAn:p08U0KՍq _򒠟Y𠤛gEOB$0s^#'Jɍf&)L}gC Mr CYVNt Y #'/u`dZT]uA\dN w+f-,x 4me3*Mٲy f˶mf;{1b&WzuDtmЍ&T'A㢶T"ixYp |]L;pAh*14c񤈫#@ *O>R~B99Fw{3.zى7Dz ٷfPjrq5nm1L mc"pĜo)#pamƸ{="gN+,;pm~X} qZ˻L :A7}԰I4Гw{vl]hTЧ}Yu hx'(q cyP&H n:;N  qyg^}Faxoǭ AG͍7ΣM:cosQ=z_(w!X6T5 o:*] i"ƖCR8''=nߌWL oކc"G8 |=\ ب8륿NfP6t6x:^ng顧SOǷv|qF\xhW#:º}Y.b<nm4O -{ I/4W9(/jO?U(Z/ ?5_=jϡۮ{ Sږ yHΓRfȌDo+&^ƛznt n[!./AX65H*%P“h:^`#`.uEHB 8pґ+PX$2@+՛#Vp2[x Vdzr8l"%,6XEMK´t=͢z!d`!5j; Gn = :0 }#,YЁ)\k1*&554NI+|bMù߇F̒LUI! 1W )1ܻu_K%Ïbx%D:ޔ2w/~`6N{IOR-λYuXe ԾRZ{YUE3!"oj2r5 Zwа`.'6\I0H)K|N܉=C4F Ć6Qeq)$83oo+a M퓰m!+nZ' Wʖ()'̀-]槠ӟtAi(oe+JAw!L!JФ p928|b?C quAIJ+箻AN ω&cfc* Ik8 E47SeK80B5cgz˞F{rj'͘1d p@y2aHZ@4a2tϘçf"c#ړC?q@gȠd@^d04hO!2 !E4׳XknݬhlHI8F[Y&d 5xfM̡\g4O#c:E۲,jc(0 r z%V2vpJ:Ce0fCn[4,ܱ*̘Ho۰a5̆5HeOvu[UbݙHR1Fbz[Gw5oWzj`C)bK^ᘼN94\gE"'GŊ FcWv;; )6#Oy%#E1hEJsJ''}ni2Dȷҙrm>:8I<64-g| i`EJ)-^Pw8AWRs'dzwהQt-U=ff y="o!ux ʸ-z 5GXm9z"FK{ĨN)._€%ƗO%AGdmsg"Q+p8Vc%p>>ȱg!=ނ2nx%@.4>1zZ1jE E< Mf\Fw0bm |<]_?v|Z49=Eߝ?_P߯RǏ[iR'{x}//z}˿CE'o=1i>~?q][)gsJ?9oxo>?Po]$?>ߓ[}G?WLۿ3_?)?5/׿;)]O/~s׿N?_=|77?=w}6,ۍ۾'~Qfo_?<_xwᝇѩzxsn͏z7/, o^/է>^3 ՋG99|~)@_9}wx%b3t>ˣz~V/z{?}#ϔ_HHi$u3w4A7$xx}#I5wf,_@ș%Xq~ LӗGaGY* ۃQh 7(QzEp Iw_bxދk'~}K6!_#:"<{Vh?~aFKC*]$S\qA;󷒀ćw/=~f><{ :٫ׯϟ[]Z?kqH|o^<~xG{?k p/c>VO՛ߜ5 &%5Ͽ9Wo26 O~ߺ%YŽ/^z F "+~:[sz#COrTټZ1n&GJ'⟞Tο^,POLuV#dℊN"bӮ8E4`ظ3>E݄$4acHMo?1`hN<::;CE4}eq it)9Lf4@Fhf9?i$4G i(w, =Ωnn%[YI'(j8l]vynk;l-0č7B7C qs{ =]@+>p@vZx\$m(N=(u_ㄳ%m bc}Wϑ/e h z7-yhȗ祼df2Wd뢿>OJIYÏn"~vty}N̔ly#74̈N9,'MseD\+ CU)ofGTDcZTMMcL]M?-\.3Of4\-s|ޖ Lg4>dnkuzbGPe61F6)JջL\ "f3m,7y =hClWhn6Q=5RWS;y{'y.^1XzhvTFà ,-eZWc@\ ѴՀxP4+kfuU2Jsm^ *ěЫ=PLs5dЬGdЖ92R_ޚtnm-.M{Fnga^cpasΰiYHº#4؝ǹDR ;o\tdT6x=d" ڻ<~ Zk@cN%N)n]Xe4\JeäwX3}rDXBxBr=R{7)ҭAFڍtܫe[el)`vyݺH@z Y+B6< -Ίox|G mLt>Ҽ2Ѡ CN6Qzj 0Zv gAMuۛ'G¦nBI21doHLOVZYYxoIلgEBaTQvhCYQhHa,e5TЫ\ E;B{ˆV祒b,}s7Ou@Nf]hm /'L"ko:.P1]ʤ1uJw!;_ V{2;Plea)Y1١05xGb6--pfEw ><N' \c4;^*-`'M+4i84HxE7}Vn˦3vmPf.6fѐ쀍&;NWihwv Fv΢$TޜdMR[^NN7 Wn :GhRy)L G@wvtj M%%υ"Fiv(imIРV!NA)/*RB f3K'n`PR[卒Z_((PnJ)as`,>8ixn e}K:xCȔQ^VJAu;luԺRvSPrXnup/;ZrJb6ʹ]U/cԢ;U(Tá5GU[V5Q~3՞95%V2SVdRV~+d _hՓNGp7px"̽55BíB \ʷ*EZW-k>>n[蔶5fo<4퍆[s=|.6M[AK8ZZ vuuJ>Zش=Y֡ ;+ٕR[eܒMBE\'e}E!ԎP\ń!i<,(ChX/36UCF$ SJdPXHKeH` TݔW^;bcա!V?0eRx^,_ByRXyV\QgešY" ibTAʙĚXyykC9o࡛X(mw^U 6/X*+2\!=+wr=9W+,OLgfk^PUUP[A0l*A2u f3:Q $ J {갲fT+L"2L3@1,QSePCύMSO:y^f7  rB(3`q~?iO!<\ea苇v3J&_Py ohhޟ85 (n&CA/}/Ѐ2z"ܝ W<e[Xo0LuS;PozѲsBً P Dyͪ>23-%Ba>A=s39ѝ$euB ~v̑4j{0 m+@!7g=  xAPplQ3!̭V6"!z0"!0 ի6*+ϽDp.y{ʅV- R6Pž{;=쿏(}4>9x`s̼͋K{3F%KѺ-|nnk{Cut%ӆ<}{Bvp{^Yn>S8XTB(xaQ5p(>-xeQp`&X/wV< 2/_c(>)6kl\Xv~~%p+6O+wƣ!rx˭+6 :6kl<2i$yd'g/ 6kL  W."- $wz[!yîӳSu m+6΂;:+8_K8 mg<&{:Wx@$-/vvOuAoދ]XGfr8,|`1K‹k9R"\ϵIY|U"2#yAXٲ6 ,U<|0$bTg갲/K i*S2m%?ˁž]mINblO6\\q r5E ||J=U*tU1~Ӵp 4ȱڝf͢!ClΨK Î\S|B)&SS,3>wwg`N)&0 [k{T/zTPEpg.;hmhʕdç›]Shӱի;eyq "oBAh<4MR^a$$mLߗ(rqMycrm6An._(!csl}:nHOȒ r-IGIw&}ZғK@Za6M860~`MÇ'n|f^Z{!U_<*OS~m9ʢ-ʓnp鲠Oj'%[b.h%ʒBv'}ʽ}<%is8Us7+A?}v(`Qj|YkMسBيlylZ5ƶAGQ"Iwn IՇhKv\3'2W+>iBg`~6@eʜXʹJwC"ߺ 4^wA0Cgsl3(B2_|R`zzj8t|;.Iz~H> ) db79)x75yqb"Lm_1ޤ23EZH˘.ri&p{$`v ~K8x{5Qd19; fp6Lc[:fa`PBX hGOHzzw^c"=O$bM%(a-EAsLI:2ynrMvL{ ؃CI@1؜!YӞц͌ #7ѷG|x;5T>nazR~ =vlPcݴW8ub{wkt нtޜ;B`jnTŊJեKcᙋFcA (m fqO۸3[ĝɤOc)NN߃qvSeʈȗ%.RJL^ϑp{x,V^dM{MƲ-xI7\!]%>޹ԱH-Kq+Rf^CXuĊb8K)澲3\ -{T b3t}P]c깹;S 榧%7=,fyf%L/Sf}vY;"f<,Oha.jX, N^pIq3-t䌋GV IVpeE%3eDf< {dݬozʍǃt QVO -xE )ژ|E fEkkS=ctûXC $,t!Oa.Lo':Z/tǐw=jV<¦q"ω)gDF^aCOwxCgs=εK.gH[-)/Z.:-g|fQ)l^ޯh_d@Vё{\W0γ(,.j6,#uű..g%gaJ#r&o]{5<2bx7K<+AHo#nE՞];>w8}$޿{/K4'1''bC@\.jQ/XdMʍ8zqu϶ȷs% fk%p|~01|hDg3l˛N̥.gx(sg&11+jE~H.p}D%"s̈=|a=wqh]OL#4EF'4mѣs}w(爽-Ss7\Ƿg_W( q~^Vz<L7> c2Ebx7Iޖ6!x>=}uS8Iw&i3>ȧU*v""naqWMǒV }(3Hi̸aI`Oj[iA-a cEiS:w]h}JIaGMQ$ٗʌ RRM.Iu I%G]1zE fຮov5O oR#e)R-v{lK`>KO\bFŗ.esܩ@NӅ.64CKQ\1ڶcpTP fїpjSkʈKkXLE5(UWlX \eэ ڣY=ݿ =}>"}.oš:}hJqߍs+ڌ ٱa y@{)`g < k3\ܝk!lJƮjm"Nt\[# (A@"f@yz̟7H Ŷ,>#nm׭h3tnu IC Bo5vd)'ʾî Y|k^K=o-V@rGVxr Äasm hp1dСҝ(dHދђ735,'7~2L0V<2Y{\ Z+u *9CS0؆V6a#F[Ju>n,p`Ak'(6@8c95OɮFθA-8FθA>15Ol,|3k5k*L| XOvuMÖ낽nލBK h06dRJ[!hd%a[ ] ]K((-dwL5r/w@|{BxGH>V,;5.Gbx 9V.\j)bWj*q3O(X!`H6(N"=UcR+<.*i[SWR` 5) I̅쨹?qpefә.3Gs~ո,q/b?"wI!I=$q{ m׾ri,]E;k(bݚaN7+Aٯq ÂkLq`ӂϓ%xۗz-~im-ا.هw8ZEh퟾]еSZ2wzXFc!m _[wBzK9-Ժ/-#rRBx%x}aBc0gNKchBҝQfLIWp Қu]H@Iӥ) W;1F^bKz>B_ccCWhm1"cF/~] |{BJ_ׅ}‚?螭nd"]r1>>]GLshĥXue$g*Dž"9;ap9bU՞҂}r9b_P29)^g\gk6$^b^z G]N਻ }Xް9H .f.YK1"SJJ~PT5NEt 7nq+non,E%TyrJx) 8ػ dzy~,p[_J؟f=i5؝Aߟ+t 3;=I7t`#I<;K/=`  }ZN|[av%7Gx=ͻ˝l 0S SffD*R%kT5"0΢q惂\ tJ)yy/\`G4\Ü+GTRB}l25T''K wi{WC?W"nѢpO BgѪOQ9+THS΋}=< 'zԹH!u{ uˬnqgq,ҥ]reh#wc$]fҥcV+ / *<~5h]Az+.ϸ-R}UN7޳b!nw~A Ss|[pӾ=4uqUY/2,-1S1cf'lC;76;wlvgMﻧ|}} k[u_&ul!ul!5?Y. r،L4^۾Vf౲wj1#_ح4sN9bG8N#p^;'4B-1#5FNGnKim5xG|mʑZB8yj.i{BT[xO7s<+AfrnPbWYK|Nw.1\I(YnP0fna4blAna4lu*&čS͘CG)B!Mm΀ؖ\RK㩔v".WغpJ1g!t^$SdTHF)?qa<4<86a)%}Ia* !0bZM*nDVR(l˛ŨޒO+' `Slt*mN%~c,7[e{1ZBP p<1_d!z:Yu+ Su"&ǻ-9k1hZwuk:īkݑj~w4%\ 6%I?#2ٗ<ʂ8%iqg]G Ka.)̧Rx[C>Y2󢉄WNz G?6a"w>_yj-}-Y7rT:6AB7aFlxI98֧ܖ0,dƻ͇˝(T<7B֝Sx]ZW2(yLh| uRӴhZI*kM|3>lBlNf̉a=EČ럱 G3F[Gm$^Ӷ[m5-pF }Sh}Ic\ۍ\ 6[M A'8 ):}J<8u(ñm %p-Ë9[TQ3%@.L}c"%`i |l(RVwgø@hNICqq' 7 X=1Z hьb)%岤w`RKuI]l^۩ ?w_w_=O7/y˷~J^i=|7h V]5sԞz&/_q}C#y?18>j9朧w^|w>wA}Ic|gJo?8/uߙGܿϿx<?=׿>TRd~G~G>~PGuoǐC=r|O_'|sŻWo*It/};b?Uo:|ϼ >4{}hY;97u|>~?w/7?O)Wo^z_=|s'YvN}?OdYգ o߾~x<ͻo8B;ǣSy>Xo^Xր߼×_޿y|:}O?}gɫr do?ݿ?R?l͐|/[ 8gx׏opϯ>So^|!")Hgo߽U_|>",gį->;J̇ۘNBOuT!Za_ߟ j!_,B zt/_OAOJ{B߽`o?{}>{ %:g^>nuir߮?!yE~`5bR_߿x~"ڟZ>>zWo^s(ěwԘ> B_}vtHs n[ϊ6^[!_Wo(AdOgk.PoFpSTG?|6VL'>QId~>=@ Էyn4L%?δi ?6n}ưlaIZmrdD|h*DD Qje::;CE4I"4͘.e4=6=L#HM#,03͑HD77tV%|VQ5d+~K&P pغ6ϣ!5)^`l-0č7B7C qs{uK-As95I"% G (89߸MԼ{IӲdr|6nxqݤ=`s~'J\W;fgU;I]eZYwKݹ]r[>rݛ1bE2End j"ǽJč 7c`NzuE{򓃕IWӂPǢafhrE pkK(fգNEjl:C[EH1\!ѣBp p.ۊsWdr{%]=!𶤫2\!Zxt1Z`Bhǖ -\2\! H~Mp@ ?wO§ tŧH~au.OBkpbͳAc{}Wϑ/e h %p@ o^1oy)/` ,uy_[W?)'e ?MDa\yZ3>B"3%ہdH9 up*3ݦNɋx]pj'A17@2p72ӡyEo` FI(Y01%;,2 ``dL]_~s%˪\.Ȭ"ZV jA;odgywf[V]ގu&J_Ơ &´ڝA+{# 뒏hhrbwyۖZ(4Ysu|[0EpacwMyNo{g}zP2llTb)5ZJ3/ϥT6Lz5,-GZ%T'$1!νwR,dzr1^͞;-vK,l - `. t}\æ*1mxVZVutnS}y dJAgmԜAa,΀4v7ObMݢ:?UgecȘߐ: j$4nYkX5n6kџi"O*(Ds8ڈ2GFCmwc)oPG^g-IohBF:/cr2 {Av⯏k: }SC|B`6]ʤ1M' w[iI*\oc]!P-{ؐ!;Plea)Y1١05xGx¡R]Ѻ3orhz wʽOƶS!e/.{̀Փfc#bdip&ˤ Ͼ&Icrc3 Iӎe4bL)>X#kX.X#D#psRV6,i2s=6dl4ّph=OC%,ΰ[4m L 63u%aDĠ%h³+G =N7)m&CV^2%I0)MB.4]St>[K<LC k%BZ8e J)A)e4PlS JjKQR JM)%c< m#e%-v;*[GBb!p^Zm82eikPr](n^CG,lZWJnJtpK((vM1AI-9%eAfZM^*}Pjѝ*CM n#\-(jOӜp+BoEp-eBp[ \= t$ |s= *9+»[Q#4*µ|BZDuE[в3ÚV5mNi[SavCh57JhT5iD𱄣pkhWW]䳬Mk, ezh"8C/6g %`u-!#ԄYD %XR2(P,2$0nʫObcա!V?0RtZG&`% ? CupX*%K-F1MIare]y3<*oV {)w9Wd\¢0 U܃9%9̞ٜkSQY3k5/Ϫ*UR }:lͿj.覚ΠlFa0 P$#+TR쩪ʚ!TBfS!2 0hoҜf04Sk|MhcW tJC=^W &.&VO>eDžFV-gdWQĿuN%`s}c@'&AfmQRVwNOP)s`ȖHD^Z[^W|vQf z@ȝ-AM8Wll DVb7udƕLT!zvX٠v3wDk%   JdxF3~XZFO3 auT|lIeA\xlӆ3}:DB;^`xѲހFً P )ips<یf<ǫцN;K#cIPHc'5Zb0( I/xٰTԈV=1Gm^| ,2XNv 0[}ms$2M^! C}e }YpvHTԶAvPplQ3!̭V6"!z0"!0 իH%BOrHN)fߪ `ȉܥbӽҨJj:*D;aKh5q`tIf?(x4mPCol =J;r <y>f023Ȅq4yd qLi: n[d%-{)*lTBV*!Kw:#:[9f{ m5CDDr|rZ,IMڍ\y>dA1Z b8lFY}/N3lĦyvwJ+4K Xߋ֧צ偮z8h[RwrD蚽\#{^-똘.b_ŴO',u:tݑbG{kxܥugC#`&x25I-(uy"fZ=-2ے?\Y{vY3,B\`EB^kuI,8VZUj=ۼh ڢa[4m[`V?ne`(xP*yI :deĸ[=Z`]6@_IX-ە^®=[>eYo|:O1 x.f+y90-ŀ6/>V_|e{zZD*h<a]ks9z [V@6Zts3ހtɓW+~;d,ohF2,GraQ Sx2Xe3 /5\g8,vv^49;" JΊTI@8;d$ửGA=5<̺.-xID[6 6C&~oh9w-I؆ r1.\7x ow ,85x*^ |JiV}3x _+%ټp@LwU qUGF&g=:)3s]4FֽhO<js]:0/)2ڥ>bF\+mu ,b[:g!C iY?p \ӭug7kZ3MClyTx]rm:6urs/,oX^ @M9vf6iY=p^1}%}~ͱMOv!=#K2ȵs$YR&ݙiIOi;KqC~6ՙ[="BkhЫ~|Ro^sDhƕ%B'Iq"LQ:EK3d/N@-N0MM’])3&vBM'Y!n zCFJkmm(Bs`i>})іNP5 4hlz2d ׉ I"bS(|?Mݲk|t_\"C0k)gI';走 49Anz  ynw`cAZ;|'rpgZ0/i3xtJ=#]s;~EaxOOV-nOl}ބ$W?0ѦM7>H3߽n/iL)M?ݶeQ jWA^r˂>\vnX-(K ڝ,*9dj6<%T|vaR{lHjA&=fŷ8|f+j~{b1(_Ķ>b-!"WmѮb虮~8n`4~3A؁,Ys ԢMrk?%lD3pIts8t^)]k%EӺhMA[hlNXur&L%x6!Ze#C'4:&ĥ>QN7ZEZ-nۢu~JkZMDV] L#=\΂86N ө#D'p aiV;c"hwɢyE7}=C9xvh\2Q5/tq{q_xF"o=b}J~*('m"ϖh~|H}";#gfQ I\fQĎ9S=%vZn!%SkPZӆ; g.bqO2'&n>0|3d'] PG".6) ʆ[ ?9N=N =ezkqާjp8Ÿq1XIg MMl!S۵aL>.R2 -Li-R2K\)3%Іnc)cޝHDX #d*w =tX Em $ԍCraHx׹N-*I紩Y$3ЖB=Bz$:揳DJTG4Cg!}h,Ozw v!Ӯ7h'z ST\[-7 B9 V(r*<{-tg: 䰆d*p2^'ΐ=[6BfY;95\&|'XDCOO&1 nm)wi\ܝK.n mdKz^dmjǬfwT'4Uo:Zswk!dSLL `4Kxnu?Y5_ӛ&BrBޔ}Al4ݛ;ԇP8{^x9zb -rhQCZdbMzZUPc#RY;g1Ϧi^ue>EAsLI:2ynrMvL{ ؃CI@1؜!YӞц͌ #7ѷG|x;5T>nazR~ =vl$o~ݴW8ubwkt нtޜ;B`jnTŊJեKcᙋFcA (m fqOWBG~-dҧf~e )Gf{xfd% ^pOx,V^dM{MƲ-xI7\!]%>޹ԱH-Kq+Rf^CXuĊb8K)澲3\ -{T b3t}P]깹;S 榧%7=,fyf%L/Sf}vY;"f<,Oha.jX, N^pIq3-t䌋GV IVpeE%3eD< {dݬozʍǃt QVO 8YY <mmLM>"FZ"G)ZBf1x!:䐧DT\&7[-J[Jaݝ6ƢQ]4*FyZH&{k9ʉ<)Boz=b뗥I1SN! .bb5r稗o `,r`2^FW"[L:z`HENY[Qasw|e>?kGk4DflM~^_pr݀|xhh<]qwΘ5QH$ u~>id_c9f>oYĻUG4'ۢQ~Biѹ;~@x;sޖԎ9h.3 opgX8nE/OPY_}yI1i"1q'syǢQW| g5!$3r3{JS֎[[^1,XҪe)Bw:9Iq_b]-b1-%Lp"4}}25Ͳxcj<x\6 O)@l)$R[^J}ZCI%n!䈝#w+F\(XL\ͮMj{,%ZZ}"n/z,է¹Čߋ/]%NsScၜl' ]jmNi>"'.bm+଩k/զ<ƕw>'0Y*kJjPرa(v>,GX{Z\N{R|E\$^gQ'u5uДx !U[ Н[,{!DKtH]-. 3݉waؔX7 -kv (%ú`p3q-inq;-`Kzɣm~CePmLWHAsf}F Y{*0@؈!Vdj=:i݊AJJfz#ҳ1:7pKDPwIHC3dL75 !ݳ[t'y3Ѱ}ArN d PXt7䚩/ꗄC+ݜO7܂a3!NsT$hp Om :{F2#92EF;3zbF}3n<[Af \ Knu K;VQwMXL\ qHd,P2vTk3q^h1lA 2m6cyD`,fh_q?n@?PĄw. uvopH2f|[$K9QvM[3`D^"v//xozZ;Z+Ͻl&mnnk@+%!{35Π@!C^Lf^*8 -ngqg2pZe8y/&gZcPxpd6^ձbHc. ?nm-d% kXxSK3nifFelbK=g \bdNS'6x5u ԅ O'[yu&au^{azaww o! ݥqK:W2v-x42o- îJ֮R{hsKʻe&)OpT#}؞#3O=n_Q?Ă:![F[m ibƭ>fǦpaNmѺ-Z/ht-)ֺXgj{[;Po=xRN}>akz ;l,96|q njc -xfy0b9gtgp)S$f]9-lRti$o'dABaUD }3ZpHwib^Ru.liDGl+p&[X1re{;c?G/q/+xOgZ vgЗJ'lC xLOO=6p҄%@O!nX.%?d,#@Bf-Vq(~] q3'^Or'[;̔”:xYg4Q:T 1-UH8Aohct!!=:\yb̠L 'O"զyi+0CHIE <r1yl:a>Ov Y* Vz)]#^G\#2js=9xb{!yzλ4ݫNX<_bYET\g[#7R^%x*plmG5 w=fg>2͠ }t|ñOo/>vmNˤ-;'%A.y7w/ổxl"Z{1v+͜Sδ =rIb[wg>ɥ[o\ev6m /c;Fk7Rpa 擓Ug3.&Si# \P owc7op΋":Mt^yyJNNl^i`h"-:/jгP؃H$~)QdQF"7' TRaiRDTsIl]9[}w+̮ T3sHނ/&{Sɽo لy2Nn{a797k {:tN2a\唻OjDafty.9M͈6b@ӮeOPWxruxC]\oL8fwi yZe3 Qw LoZW&Dͧ\6)ϸ/3-֤`S$L2IbNFFtαe7Xܨ|h"RK xЪcrj%@Qض`ENB~-x*(ܙ WqÂ14Qz]@)taB_4v'ä8}踓,npkt| -hF˒rYR 0a)%庤ܮR6\/Tû^߿;Я~tzo4zw;fԞz&華_q}C#y?:|9=Eߝ?_P߯RY_Kwfѯ3o/|{/_>Oϟǿ/ߟ}Ǥ2~?+柜SG2x}^}чw_%iѧy+{_^_QY}/_LJ}hY;Tu?ݯ>˟|_揶__ 8՛|WyLm?Yl}(3ȿ۷/_T^=9G=f?7//է>^3 ՋGR27zsg)ޟ?6Kf|>G?~_~GW)7/`Ig^i*/?>o#I~Gȓj?[(YV%gz,3Kh,0/Ž UnWoP9$W^:Y|13Ngb%mL'~}C|s!ۧ:*FuDx|Gа5Ì/\!J=rU֗I xwˇ'o%燽?j^0={>ʽ}yt\W_?H9woz߼xx"F?0f1 )_;e:l?wgJdwQ_[/`jy ⧳57#ogJ>W+MdPUSm8뾜ꋽ<7w&]'z eشCM >wcgh/$v{C69Ch[>[="ozl2Kwk؝"XWq{QnwpfL2lHihCHLs$l F:yeOqNus+(ٚJA%(j8l]QNvfj0dF!nq{!nkк%C̹d d h`sqqB:Ri= uLfiY2}={ Lсt8ىnR9CugTLZDLݳڪ$l \w%.9ݛn9MYʅ""dP2EZ5y^10'yqG椫ipc04-Z5^%}M\g"(6ۭk`"'/Zl[fB ; Wh/i(2]󒮞[ax[Wq}t-xns_0\!vpp.;Y$qG8W» hd ${mOO'i G!nv[݃R5N8 Q vJAcz(c)s;%\)<ĦA !8%)==, lnDlp$b{PZz(sՠ;;%4hR'(=G~RâNaQ``,^5.j,^5.J.;vJ[5W #1UWW^aQ`1iRRB``.^5/j.^5W[r ^E>mŢ9W;ԶRF H+eA"89)UF)UNɑ`Ӡ( "6J "vJA)y4UW;%)UNٯG"" B( RB9qbYpbHTSJh-46QB`)yF4 SjhyF("U4v RC`=(i͏4FvJ RL¢hF S«Խ](UFëFPX)%UXzvSNie)UFIݻӅ^E*bHn`(Sju ^El)=4vJxSRq R*^U*^%<բ24tʶZTS^^%C]litU26 xUxU*)5, 2éS3\j5'>WNs&b€݌~'E%p@ .FXn_}sKZvd|3›Wz|[x^Kf. k8K]}Ef,.OJIYÏn"~W'УLv 7qsNC0r3ʵh匧µA5^SW4eIc*h*wi W O[+ڝi9Lji\uI tE̕<2̬鋡-kTh&]Rk*1IW^:dL"]x`{)'m-WT-&ʷ'JW\ rjGIғ6Ed +}c}@Ooh/3[[6`-`H3X3Ȳ(m/̭p&,ѨN7Wʕ̪,[eU.V1nn.[!VMvw'/n&йμYKѥȍ^Rm2Tk `".L{07<.&'vq9gBΛ5W5Kz Sk6xw'a0l}B=:u FI`N%N)n]Xe4\JeäX3}rDXBxBr5R{7)ҭAF('7 K鼓1bm:yb 6pϮN5l*//0rچgUeUYqM(1UQܧYw`@4tVaIߦ9JODFn! 4Hia{$H4-Z(#Xu^F : ɠIJe^f p7&RЁB4ӡ(nxd4$v02unUL.aqݢNΎF]!=aDRI1>|: 'bwa+ vy`Td>W"fEL!ާaxHp oeȥ;eز' rޘ,mņhZVpJ Sw7#-*[:~57A;dl;Ş,R X=iv<"[Nw>n[蔶5fo<4퍆[s=|.6M[AK8ZZ vuuJ>Zش=Y֡ ;s.3toC7GʮlrK6 rE"JP;Be[,rasѰ ^Vg DM_02" @MEPR%%BZ^-CMꦼ .6Vj^[+kAydB]0T\QgešY" ibTAʙĚXy>*Wӥ7S^ˣjbr3|E-, _QU.yĚ\͹Zfyu?0_R% A_fn +o0 e@¹:H%Ş:B%d6"fRmJ8Wڄ:v@OǮ1d]8ya`S|\hn"qAvaE Pi]6g7V $|0Lh[h%eqG<,)X/2:lt?L$Э1qܪexgWe,Π7k |2ԄpuƖNoE.vSGh\D+!xI8g׌ a73qgMdXҀPРDg_j9쇥eD;hPG7˶(Ref<88u^CA4-J-{yef$hu@7gsh/xlƳ{i42t d@} Y%v|ѐ:_KJho慫 kZ/K"Z()I7,dY1h,5S=GpkByj 3G"d0dwUvه@f1Ξ}kDJmKNpd|o! 7ƹYѹ;zk|nc+gz-B #P;QRˊ)M-'``d"lfxx]j+6.o>+*X!M8f3:iZ[N3 \yV&\M@w;؛kָ)iy8?A9^(Mg7X7}ĺZ~48LKl<\f xJefȑZeg<2*L托i)uиmٖQ$4Xnm }eE ﲺq}*wBŁ ^Js*fYX\cgVƛi ҝ*5)IC1SkD6{w8%kˋO} W\pW?krVϓ<QvADl#zuK )K<3<ymؕQuwɧyyUϬ%0jxƥN*gꓨΣgrM托i:hܶlKZ桺 o9rXmM&\y{8`c:Qgm-.uoj,%>c^G>S9꛵Їz)#Ř6̼u]:7a&,ly%-5Rx2یT2Z/HikR6P>'Yj'FOϰ^V!n^d%-X :jb͸LAѺ33cQ;z0`e%G׸=eڮ=\fͩ~Goƴ`5@ZmAښ {Kz>RY3+vB K=ʢp㆏\p\9 BCi+B) 4 89]yOV|Rl:Fkl:\>]lҹ-1yf3xH+H^@/[+,O x@>8_ &ua&:E5^fjOK(vJ(&B Ysq?9&f#N[!p[˶D#q 2BO=uGuc\7eE+N 4=(חXaCfS'vfb9uat=-|a_cAt鍟zr*ax͢OF-B42Rkh$=߼;;w+=T-xҴK|3ؔ-:e m]oqa#Oň\KկIk/qOw=t9t䱚*?C;h\ԶJ= ײIayo^_ 2`Zmꕠ{Ģj~bŬЎ8Hfwq2q߼X)NnDuPPS6 xq2y Hk/z#97H]k}#m%E# ݕ7Z.^o^] zu)l} W\p:BxyOR=L' ߼Һ}aEG5-ހu790_ <;m6q^V2}nb`%DDӍ* 493調.ʁ1;`@ ~9@{n] %:hhf,8Z3αRw`B:TxƠ8mn.L `еԱ7͑n!mԮuD3!tfjxr<f]T`m3 +uBCAť ):L8EeC=lb9ƒ=\r BoF+AGVcQwex>NcUl F_ƃF1jEmS<c DpHAǡlJZ*1wYudY1tdz3GV4]Z`H<.EEP6ljJ6ϱe/iRiΧ'͛-oZ逯fԑ@apLrHR/Ί3 /`m9eVb7Jr3=k颧yq;IoD2E\d[, ;p`Eo>CK^1Ɓ'vݬLK-seKy/ft$C 4!5 KV)L/X<S^۔6\Ea͡=AcT'B Y7hP-QZd]퉏'ł\` 3e P&SKlmCDf+yP ֻ֗]%ʶ6JrP#ۡK#}Ā XnPVLúS=YLPu]l5,k %htHQ/!iA+Y((`oi}B]L̈́i%s .IN%(zIXtXաL[ ӗaM¸.$B*Rsdw(LGE6mgGJ-ZO>ůe)kc3iH/S>ЁA#W/ )NثtW E<1ȃ"'_9%DJIQM9q|T~mޣDohb΋kPON{ǝ+83u̓mZF Mxm0ŲB+` +`15|J3RofȉLcnቼH|׃:<3x}ݠ8GN1˘2&+n3H+BRcY M<@J]Eݖ>OReڄ͗%aC>f|6L~Ԓ6?EBt MƟPX:˘ (Eל&DzLkzE 7L8pa(6]bp Ég|D *B 3leAfl2]8ˤV&f`O\*T`*lܺ(["> |Pxq"ce S!F~ <1$U9*S"j9* LƛiiFi0@"Me4`iɴiU=bWSHI1̻y]K)6rbz%z$<)kS9_O:Az^nR_O-nVY {PjnQߊGu7 GֽhJcM-s'r9n,8(G-aV4~ qnL>z❴JiJNJIK0 "&o퓰@-hL75 #ePXՄ-S||isWӲHHgHTՔ%djxG#k, P}-4ۮKdgs]I*Cl42`0gFb. Yv`ahMU,bC:W,޴fAjOr$P1IA4@X0t[/?Q~C?Zq Z/~N O P~2@0TE,XgSxŊLwӦֶJF:TwDP%L W)VEH 'ひ[%VC ՄB^7"8U,ӍyV;XeӓT'aO+J- ˰WJΤCiyof˲*^j# FuHH ߜ(i `\Dհ|HdbK&G`5R5+\XnQsnΓ&ߤR4$K5BT?Aj <5U|= I+1EDulFF^J`xl3$,P _AZJk@"7Mh=cof.?/?7/}}gO߾x#㇯?~ D+SG-A?:ǧowU~Y/k_/sZ>9ZӞڳo{o3+O>_VG_>z?_=tg~sdB߇_{C>o_> |7U2ײ}_{/ ?GIx;g飏~/^oz|ÙC9w?"ȟÛ{W{/?}|xk?T^<>ݿL_?ëWߝN|O?<>}5DI/^>w' ^><}ܒr:}joǯߝ<ߜw_~~xnO߿?y}epQI{ٛ/X ׏wOK~;/j?:ojL)/~,P-J͈鿾Y#+ DovFٮh~={$Jy?޽T'_&~{:"ݹgx|{/9}/G* B.uU_8qUW?>Oߑ{oI=}}ޕ{+Ig/SKv/^|yRR(??^/[)8˷O$,(GzI;aaߞ_}x֢ow" '矤F;SuL4D_Yb/SoH8 JOg.oFp{G?|Vf,N|27!{J'⟟Tο]rf랲N lK`E6>Wvgdj>5aZ؜CE0<`eH&ص&eȨcb:n:CE6&7 sSq;[{:6cwtĠCu5lZ:ߑ`e0w};ViKDդ,ĽXKn@0BJ}n 5ڏN)t6-vu4[jZ.a87ol@W5͔|r*)5mos魼`BHI:C9ʅwb"PiM3Q-aS6MPs.%|"3tR5\L@绚Pn9d鸚ZvO (|5M./ (rɧ%PW5j0~Ep}u:ΘǝERflFnQ`Tw#AuGlyzwJmZk$(PU.%S VJ^`T(Q[X5Fq*:(-j0WWUU3x=NwsMYjfvt>q通ެ 19ED.Ww}"^|ͨG?)'% ]"G>zv;"%ێ(nDŭy "veθqNY_p;aTwsɶ\J *9z[hq$mRND.HI ݵ@F|pU3>(?#EBl{IeBd3DB:D3ȣ@rө@kKb曉ɽ%g <1\P'C20ZimR6 `ӪćHzZfRqt;m\AaWEP_ng9a 3IHBJ#g͟gpB6Ct1aΰ2jr6hA7:8m ތayeu,08X " V<)EH-i%<Kt{^uJӶ0>3EdJ̾ɘIeFifUOs5dЬ`a@4("J1ӿ,H5VcTNfkWۊythAx}Šlfw(a uPB~4Ս l 0 g4> 0XdޡY gEi2xN 3@Q&rd} K6, oeNgM05}+iUu*}nZU:E[w wުCu5-иy[6p/5i|5j m*ȶOi `H~"@aҲgZL%ZJXHvF^Sm+-!6.Bu2g|Tp D 1.mxd6 X duCpSEXaj}13#[]G%X|#̢1$,[H/'=2 <4:Ϻr~_{Ba8oڥ8r7ni q13荲O,,VWK+€fC6n+6^HH ;.jӢPLSn6mS8;01b&MG)8ʗrXM4i Ph?4zЍ/۲'O q%j' e8J=}^% k*hA`WvX{ .BSVvXħRbxm d;lb]plrv+W`1x@agΠ3;U'( #$7-iE6MrTFk*(:F"8tՈ?4]R8-*Jiz(()PTUSS:P'(8_ Ȧr2N.%,z9@q1uԁ!o u'ga([rpM(v硐R,Sr ֝z3(H)8P[h:85QdNI-%ɠʶoW*KY+UPNjp:4tU\W._qD h3._ ̯ NW@:{ő8q:Yޜ!}.M^Wx-1} K_nٜ1pH[ uAʖ+aLuHf` ҇uC򙾥{>}1wOl]n=e/27- 0 !J+|J* ?Ӻ#W ^/O}z6|/1ȶX.ȂE3Je؛@sӔ@a#Ⱥ1/ݓw⏍GJnlZYZV1ҹT53eI|K6jgF֔1t]pmhMu# +L  ô˒Nu(=3w29WmL`3gfs]ПYUQ!`ظlſl.ƚ)l&0" 87SdOVV J5f +<߱weNS k3.Csvq{瓫y a=Ku(L- Pہf sn엤C5lAIhw"{B^,~qo'upbm3YC3#UWar]u|yrGY1 AK_4y:eVnڍyUW28 u5ΰNLͤFHN-$WWncdN:C/V} V$pW7׻ͤ4)/uM(pNa@{Fݙ&ek=Ddk0@ ~f |!z7ʲո”PB;"oF9\fOmXWNpjQɍWZth k/v~)N/im/{~ \ͬ2E#tP:G2<+ʟZ?iq~ښtl2ꏼA2֤##K:xgq(wx35CY+l_aݑ"9fL>:.k -S q&P ׳4ד\a$t#RBM f{_+_ cJ+͐Ũ9x}c uO$31Qӛ\8RfgN/GkjW9R%84gI0r7Y62[Ȑ# &&7bk_Qw$3@1p0CO13vhQb e,0^s@SW_CJ UCʔ%,K>İE>\x^p d9Pjܮہ S4OĆSxoRځAqE[$5~c$:P|=a b%MhCHE#V/q|5aK<_y,_Cc+(m(մ,~<0)U|5e4^0:?c/bZK33nK56`Ӫ٫yv%P$>lo ٰ5 h,XgSx* 2jŐ5 7Y\a3>+ƳTL`Rh8 ?ia"P1, *fV+aTЏV?zQI g~\*"P, ɳ)bt^ik%aq;L&M+ȋ"@Y+!jBi!SPDYJ ң xV;XeӓT'aO+J- ˰WJΤCiyof˲*^jC&0j9QGӲNnU{$i0v ʮYrps59&$!YbwZR!X hdLZ(m jn##/%0<6WHꆯm OU-5]GhzOKN۞7|3ZOR!o"6xAxg2O&=/u.t&*2 E<(r8ЪuF Fr[Kcykj-v'7YBpq݀J-JZR}jjB 26@Zr ^Vi[^\-ƢQ:wC&Y:)X$8"+Ur23;ԼuqRl L]aO>?_ D9L 3:?]kCF_dOlVc@|j5[L͂M ,a掊zɶB;XOQ1ڰlZa-7K6f^1b-|&x1嫎 c #XrZiZmJA2x !-Ys*Ԙ7 `9laWBlnWF+΂qv=τQ*fƇytW{\KmKym0Zˬ_t=-GO czZ::_h#g <.EW-=t8W@zR9O[]pLߝ 1GO czZ:ZW MZ R0s94j 3Vۆ`\+kjMIނ$ >}>{g׿:O_yyw_=׏#O>{?}~ǣi?|㷏WZ..#ڕLߤR/?ڏ'+_{|vW凐jūZ.>SmᬵN;={v>}?_Q_d.GOj+藕wWϿ~yOU7ob~[?ğ6ߜS_W/COw?GƟSP}Z~tn:/||od?߇/pOuK{go~g~{v>G_ 3-ns#E?7/雯_yxx}nc맏>2~ˇW_?;>ϟ~s~Gy~%|#>?'@/_>}vO|x%t>_;yxC _9~wݞ~+4'7o_@.?> 7<͋w^')7 _tXk(P/^~+X)gi`Y[ }7GVó] є#zMi aw JIۗ/b1_{縉Or)#~sM/b)uN#~sE|s?;/jw/^igO_ޟr^Tw/?~j\^ҹ|#q^<Ļw|ߟ#绽?nBO>߽{|'+Ww^> _xP<˽Ƿ_ˇRqo/I 'YT_QgvTzcg==%*-E=DwO?I?w5뀙i7^^֧?㳗/ހq@:\ߌ':$ ~*^Xdn*CON??%]QȻyaE=ea HKߖ׊l| ΰɪ|k*\Y99`xbʐ4dk-Q7*t.ta7l|M,nvxLӌefe`w1=i7iiALCٴ{aj]f :yGH e-qާtf-[Z _ Z[fuj^=栤& /nxqӋ^BqZӾ뭥CZ1)OM LI s1rB4m8`ǴlNZZ%ʓ zāx8:WKa3j~GJ;ZW;ʦӪڪ Vs'Aj%dojqMZMǚ&:Se T)J J C,Nͭ: R^MެLCIgӂaWGf!咾֋s#6~ $}UjL'B[h 7| 6,-t攤3_x&5V`K:CMV=ht@K5=IS[I:CIbrn#2F:C=g3j:ntޓjrٟ?M.gHjjz7L.%t@_jɊ~6wMw:cwJIUCQpJ.#X5-Jo QklwFqw 6JeERݍI)=i]R`C V `N%X)={}RݢFnQ``,^5^Eע*X5fy9ݢJ]tB6Jq UjjZѫLFql>X4*NY9W 6JmN-RFrH\` W <ٽJQܫ+W 6JE-{`T*F))%GJs U^%X4*Fql*F3Հ~e: S-KU(lS\)B(RhwnM R\`lRl%F]5c[*(56 J.eFQUXlz%ECPŽJQؓ ^%X)ӽJQ)%9H\9gDǔQZŽJR:{RiW 6{`mB6pN ^%X)4]Q Qkl*FID`UU%xU9x-7)ejlUU9xU>x-jWWєZ56Jt*H Q[(5rZѧԊGBKz7ћnftw/E&(通M.?gDCޣtw=ޔE.of7@Iɑͺ@CoC{Qd@JzugW(5ϗJz~R`5(qq@{'Mk!RFTZKP)"h7)Ł :ǵ3F[9˥tט !+/)׌QYkKq*IY^KԊN]Od ]P9ib[$;JXYK!Ķg*k6(DFOt/tCQT9ؘN%< !7$6aH_j_KȨ]O^rʣh#uR %CZ6~Έ XxU TR;RطvRkg>)îWǏ1tr?&'PGNכ?Ѕl^GH=cÀWae1lЂ nt0fl Xaȇ qfELy6S .[hJ'yX'4NW5㕦ma_%}fkɔ}12Ы^,jɠYw#h&C PDb٧!P%7Y0<Ցj2 &:0פ6|'<т|>A)L٨PU60h DI`@&Wo y}XaKɸC7) l# 'd#gM8>l Y6Ps3 )aj;WҪRU# tFrSfe3U-{~ykZ6q`wm:nk(cPg} FJ %EcH&X^6KOzneƣxhtu,>(:W;҅!! p:+p*<&ݎdfgX7_V؅͆lV( 0%m6:ԑBw]ԦEӡRhӹmtDqvqabt9LRp/s尚i&n]#La1 b8 pi x_eO@+ NpFoٕ{dۿ?VK6-/2T['į2e] ;2찈O+ņ|4Dvddx>NVb S AgvNPFI :oN[Ҋ&N7wmcީ# D6R5CW#tIx6P  C+n@I[SkPW!OYN)@ۡRJ46Pp|8BRR끂ƔQƇ5"JrJ v;Yql!pn9"$BJDJN5PZwJn([_棔Z#L@nrwE͓w;%d$(rʶRE^˪/eR TB9zpМUqs]|*:̯A:bNNG p6͸|m2s+362/8]IHGtVWgEz7;{s:zk@:!._7z]5,}}gsvlNX!m >6xp:N+[ 1!ӛ H>B:FZNׁ6j g66nLߡ?v#g/j*/T+|z*𙪀 dO낏\E hz<|a8g"b02B <+IƢAcoB^MS Ƽtމ?6Vr\\v+ʗkA{d6nJZH> 8R̔'%/7#CX%YS ,ƀ:µ7Up׍, \2M6, Ӓ.KJ:%`\]3]ϼkyuAfUE%< akʛÈfL(J=YuX+N(d3LB2T3@2 })סmPy*.}ϸ:OŅUO.^.>]v00@.1M_7̲%+ݠ\^[o%{-4Q u!w-]UVˁ)t`-S]]Y^s{ SQ}n<%{^ev1S'u?R>@ٚ _ K^י-xEC]H" w\ x y-l[buPZd{}Wql\.W8OieJ B߃Y7a6Kmkwd̟e-J +>h䐝\ne^M$&U&Sǁ^_vMMvz>iK=@maVX)cFlH6-%Ҷ$V.6FQ՝LuQ'wwFys(3YAx|Lxr}<X""Ǒ&s5%s!"`| 80DY x9x:bʓ cʟ{P~EkO'qgPx5`HlWB^N O^06Jha4{5UyX[,,<=sv{C $rֳD7 +N_f=M*5W5Ljn`ϧWI:^ zӼc9+>4;b~&$/*2QQ*cza `j,zjtYc5̓#,X^KY 5 8lܪԎ%PUG9(;< BSOÛ%Rvmjd%d=yC\هquu£w*#vR4^VqwlB0*mHj>"6vk=iekJ67FT <y%e)倯.!'" җUL}y˞p xa+L9eAAWWGo.Iie6 wM~&esJAđ7uL୽X.!}{;tW.ΐθ`y<[7i4U,gen WF_;;𵳪7uH: Ye“SK]QЗ/Y4@_vMMW &gϙƋ0,}h4(l+c$m^Ca' ٠/`+^ k!(.y-i9 7 ">Ua~'8tpY7L/&EYa y\C;H>!kw x9yD+!xA+5K[|PߢrϦQ/W:@֢3Ц_Yïu9zhe0}Ă}~}ё0r|5L[X9Q7mUG7afʃUO>EoyyfR eV%n03KX -h z̝̬6j|3fV2#뱲*P˔ >$3@1<"aZ#@`}v'y: 4ށG@ۏm>))CyS=i4:0>bsa,_Y-k0ݑ/m28|ÉN_}XOŭ:&'6['8Eis:չ{gdM>f)7{F|=7061*4)`_=s@<TxJs"(Vj:wqVaI;,)b,+9g/zqՋ˺>9 utW &Ő.; h㺧YOuUҳӝUK&+yLoPooNSlt 7%xi,,^6;`3w#D v*_bMHv!ՅHQȼmC`mrOiQ\@v,vͅjC6VuM(ψÄВW-xKv: IK~,Kdܬ1M vW݅afuMDR]5beL"`IƦ/vJܝҬ0K㣡v!Rlr|p)aA ɇ{ԭ>8pj|Ӓf?P9#OpHV,hqxeҜRoQ_o"[wefﰌ"۬ ?|\(iXp gfjX𰐎>s p[W>9%NY| HFӱk<%8xeB@*6q$/[Qd<`fv;RȫROޙ=Q5\i=8? W'& @ISKKj-O?P&נ{i݊QF2_@а3S|.N}2╛eE ER㄄)%GRB~,3hн4J R%р1NuG̃6+M2jUɫ* xOУQƁ^ǁK3\Ve.<9W'$ uԇ\P+g$I?izv՞hpQYPR%PR %HJͮ_^@douBfvy. gE]ȊogӾ<#JKkDL*+X^b0iԗ)cn?zy v5§H-?DsJ=hn3TPZ"eKf:4毈GM.ɑdZJ6ʊU(5qUJ yjx̥'Rgv93潷._ 45᫠n$p R3f AZ[[y~m̲T:SaO|]\,:0SG2m<~аw)Sh}WoU_>\3Xkm)X'j! 4Osŋv$H@lf8@- 5 қUK| -7~Kҫa2$% aR(Cz18 8j=$̵`yg3d(HC^EMUHv!Ņ=FJ,o!Dk†^/16d˂ 7K$cXLuj`8iM;Y0Ͳ 9`pxja AjQ,>?tvNjL7lfAfD~S۞zHXT#@IOO> Vi"@ws9Bfɻǯۓ ^E[T̉|4ٗ78D{ xd3c<[k!ycz薫kQ7*-8=Go K{v͕f8(ak+Qj4(Gqv4bGI0CV<=p$<ݸL&} wAR&tWJzjԕC 6$yj`۷:pGכUc"9%<#(oyf,{D=/m cr6{J,aOVZt-Pb jq@(RJWJyP9PV.(~}Eq|''PW 5kWDFxKn-RǭRh~q&nH JSS0DY(r9U,1$Ew/@bNU>(ѷFqGB(1G Ux/u<)RF r32|e,ǑdQa %Va򔐧qckbVf(-PzM邢]WQH(BWaZի+x"m#&wu^sDMXЉydڃ2,ܢN*M#&i3H'?xyj=(82h-5|Ej5m F,L8" :98z~D1GpYyޕY.i`B7 yq6͑Db?gs)bيfo-sg$]ㆪ5EW:kкkmoNe9,;˝^뵛DS`-:ESSRx>JrTP.7ңI3^Vl^`!(-L'ƒ[]Z^.-SpCzmp_F/K=4:PSpti.](<$oU5{Q&Dz-o!/*\Wxlce'"kxD^ѭ[\gJ?sпx]/sv}Pqur$yj`-*An$pў^Uy!*emJsʰrp1AB OMZ[e٭7t;LڝDTMzE򠉑JfmV-c3P7-UJ2U [n$XKRu LJHe̋hn$PTuT]c:娪I%2C(ssOEV慼кekSeS{9g8~%* nhSpsDq(Čp^\󷨐3j%*g4FhF!ӅxWqݐ{'EYNr3G3[-'IgR\GQBCɶy80MN75׷+]יqxH(sC} ve!E'm㲙oYn fBjra#WQ琎򓡪őaM˒ [8[tMa 6][^F2 .2X-J[Jvex$gC ~f-Nd2gV(ݻ%Ӱ Qjf :iI5"^e }tIj!5l{JЭUCR^$]xE,xΗTb>D6R93$ޯPJ ޒ63yhn_-Cjp  9◫8_u{"ea'U|Pi+ F|ڃSf dY3PPD/ ~ =P 2Y)yEAN PCiGq<S. Eh# F+-i<-i<ūreEcS*.ҤڸY5NNzar=êNi rR4&+J2E+y8yRKvUY]a~*P߃=tsj=^jE 5߬˓0A灐+xpYΟ#qiLN{n2% a3NgxL3+R=9pClp8w[}qnέZa\÷!",ʘh MD]&e 6~%ZGkq)`%g^űM|"YN,uY%ϰfk*ZwJ6oa?dk CC3h >Vc`#ەqۃ鲠\7Kg,x^[ [qD2X,T'6x+ cA14@QU#EVp:*xqGC3no%C8z22TZc1RZUÁK}BF>)%Ra#E_VP!,`!j+qprf: y[2y3$.l%̂UZ%MjI34XJbIl3R|pi.Au$_I2`rRסlUW5|RqJ|"k0/P(#mAcrni~xǍHи֢9*i)c;JQ-)T@iJV9PdI>@yBtBprRݱ'=Tb+RǭRh~1bl#5!yARz4G2)0d t0h`U(QQ>@(c+J X)J;)TfL/7G4JK=6c2|84z'EL#PFSBiPZsS;J4 D3x.=[F͖1@JO3: G@9Gc7is8D" Kw]i$'ú4 4-J|-Mҋ9*\=Hk%PVmy/$WmגkIV ufs/ ttz;~zNݿ~_~'>}O}/^??wVr}Ǐ>~_48Zm9vma?:ǧowU~Y/A_/?:}u~G}|vIՏ?HV/+/^ٟϯ׿կ>Бo>)2>/{=~ǟeoxsNoC ;?ǟ#O~ϔ?߇_{Cms7/?~_%O{-C}~T<?}O~?o_8}/~/O|5:Ӻ6NG_7w_P§/=m(Q~{קO~.O#w߼[w7o(7_>/`o}E\d2 =~?>?Ӓ=yq ?#E3ӷ}˯}K ,-,+y~D3btJћxk?{5r;_Ϟ)->.A)R^xO,w/=Wn9%~co_=|^,|io/w.g{E>}+8w_NˑǯBKkU:o/Nkǁxw7w$~|m7^gwo{Dw<}Juˇwt/_ԾJ9bO~z>{xV;N% 3j+J~y쑞s߽};oX}|~W_D#^%۝~q'i ipL4D_Yb/SoH8 JOg.oFpxG?|Vf,N|27!{J'⟟.Tοk]"xcˉ*%T)T)azIk[H-|0HMz5E{RΦîfCBP%}!ąY_jV-)Th'R;6_RB{$mr!Pi[3tZW, ѵi:ȥg4=|* t7 6=T~c %}lf7@M]IPiu3lz:L.WPӻerL.'isG HJ3qgY5%)2Z/((56`V `S܁{}2ݢJFU$۴.X)IQܡ]Jq>FnQ` (j0WWUUtQZ`X5fy9ݢJl+x:x ^W%46{`*NY9W 6JmN-RFrH\` W <ٽJQܫ+W 6JE-{`;d޽JQJvJɑ\`ՠW <ͽJQܫŽJQLD5_)S-K쉙 ]06 Jj+(T`(kjFFɮQcX)J6Ju Q+jlF ܕb}hP Qklm lz4 ŽJQؓ ^%X)ӽJQpJRSJ5ѫyF*~LHɮQܫ+'u{{`W V =ޕl6 ]s-ŽJRh`t(Ui*iQJ(M EtR56J|*F٢)xU:xMU`JJh`T(Qk,NO-w=jU?-wޤD0w3##G3YыMP5\@MwψӧwNCo"P7ӛjz.ТЛ^^Yjm ŀ,b`̳4UCۮnM+anXzFWҴ9>q?}fRL7S.,>@|Kt^uf  ='@Q &g@4dXVGɰpb6\Lѧz:Ђ|>A)L٨PU60h DI`@ sa{}@}n2n ~,tx%d#g zpanndcϢYtLDSW޹Vu%*}nZU:J[w eP/oM4nM-G¾ m*rVҰ5aQGI}$[)[MHтrM_SWt& ^~BSAOg.:)K@L.;,Pɼ`Ikx4f*MYk)*D7‹ =R42Rz]d_0qIhn1q =ʈcdĦ]Kڬn֭teT *C*gnp}1K/P)0ԤoKf df!b 8qcf" Vͦfs%9>!CF|`R$qoJg^!<[ ,n 2HF3M%̰etX]-  ٸP`Jl3Yd!5MC2MѺ9s۴&Qr4be尚PLa10L3eSH41[f'B-~"yK52;'į2=CYB!) ;, )rɹfh3l,۬bv+W`1x@agΠ3;U'( #$7-iE{INP`ȝW8Fly0jŇ˯FlnQ( Ǩ1-RR-ȩ5z))e(8@DCTN&}*,1ۍ)ŭyk%~`urllC!KY"%W(;`7^g-XOVJRٍqdNnup;Z2Jڙ-lz"eUmHWH=8]th8ҹeu*:̯A:bNNG p6@Kی&C:2k#s:-ΞtqҗVWgEz7;{s:zk@:!._7z]5,}}gsvlNX!m >6xp:N+[ 1!ӛ H>B:FZNׁ6j gFMqz!{)g^Z/UMTH_!WT2}_ A z Cl ^VcEm\O!f͕$cQˠ7d!n/)FucFXyj |UI٭|-h,Pt$}ph*)#OK^ZnF0P;K6Xu;W+]7Up׍, \2M6, Ӓ.KJ:%`\]3ԈϼkyuAfUE%< akʛÈfL(J=YuX+N(d3LB2T3@2, {/-hsWLx*pS{9qLdil{00=~:@)"w`qwB%ނdj7CLI,=ܝˁ֊&&O0"m!Vc O~J]PՍ-GB0qP!9i6Vu !'<`.;F,ƐLv8DͼVc`uұ ; :X>y>,&8h5m$XL&?7Z;x+8ߢL8L V[CVlxxSDwXScG|)3tKyh5LLY< ,@mdoxmm⺻jˢ<`+bq!&57XÔ{fvzѱVV |MZUE~1 O$W6몖xWHg\tw9=yݨ6}[w/ MhiZkҮYi[Dw^Q:P6PoUokN4{@N<->!͡de ݊~t*NZ}6o#U5u#{C6l޷Kl^>c'`A^gvY>i\ފ=POjۃC?PyWg32zᆕ4y1tԦ4Y(IuRNO˥e ?ag`<3†(α#|^`t<Y"o e K>B[=CYxYs 9T= RB;Bci鐖 m|A@֚u굘lyѢ)Pf0B@iѼ#>_ 6e uX%` `3`)BT)*[L5bc.8 ޱG,vD"q)_q8ރyNX/dvO+*GxϏ\XKu|<_acO'0DKXy<uÀ j O /Y ~|+M ^^u鵖;y!p U)B8Z)ȯϛ~D \CzʏUV(>Vs G,/lbؾS5Ť԰B>/IItZJZJ*^xȾI7>xk!=坳uM$)z`4(/62&i*=7b7[HMɂ!a}r6hh;\|/_%/Q,1!>GLp# F| C #>^s#/<=bƐϵ쉏;ScKd ΃47w[΃D^r,08+rqYJ'L1WlXKs0YBv'%VrK,Q ֮mV=n麩G:x3LS-ˢ^O i^vd?`G\_2qdhvgdRj1x:-ʵ4&8`ύR zGa_0L<, 2刱f.Τa"#JAZ6&iZZm%s#`]_G{$/Nz2ӒO6ODϭ< |.^K59 $_ʦӞ(Nirn\_ N.g#atprDeUKfW@'yuP҂a(lrM^a-[ ɋpʜD]` ^3{jB~P;xVY[h? /IwY^#bzmٖh# xt︙T_**fXړK_eh>]REУ"^+%SK5徳shdc cq^W!H}%^*7oMEO⼞AyFzaA".lڌ@P&\ꃚFzVij3B-}4rII,;MK=6k;ϖ- #=˔bi?``/9aԳ8O I^fEA5[5ȡ5ԠߪZ[FXr _؂/hԎrubk^ ^jbu,Z!aS'|fyv` # ǥٻ艼q <Px]L,5vg#gt 4V5X `!®, rڨ`lm) Eך9(㇤l8[7[G| Ź,LN-9ז=%%9-yq~Ce% F-Ц 鰏hׁA='m9e9ofzzri:zV pXެ%6KTYEw'q΃^emNE4ry{ˊvXKAZ8¥Y9}HWq£qhhyd!9b?+ 2ěy3 a a ku Jw8]Ⱥ!D+2l]\ "{N|6 Mvظ$gUBԨ(6Rbx ۆ8v ^l0/+w'r] vl1`qxҍŞ^lK1c첤C}^]kAA#ѮZn;,h)#PƁ9U1HLZZ2JTWʘ27-RjCZcb<ї!uf3CiTZ-;%t.:0HD^t@)+*EF@A|PgfWgf|Ftܡ]Hu!UC4w%DkŽ5hPNvxՅ g#QCzOaޭ 5X֛g4JZUic'xOlÎ&BXf$̾Î0#ԑJVܝa!Qѽj3'0oub\ZkPTDR a0[dS͆8Nq_2JMSžK}_ eyp| *W/LzѰG/Q򙇺0r!A% 9-#:2CU0`@ ](-5%OU_(EHL &ou$D(B z !/ߧbOjFez.mCIYZK7?ާ`?dl,`aٍfEEoyb5( Z޽5phq&cc_^HMg1 Llʯ 8b#QGI`'Ά:ra#K)CY5ËD돊^.zylע^vUua|lj{,@=pu5wTMq2y(! mn\'sT&Fk-d JX3-s$O o,`H&7o & #8 f8(-x߼)Gyɇ5u^30"jmdINLWo0d'XWZMY98rB7%G:jhd( _`uxU5fyHn{+*qHΌ25 k0UtTY] c' ZA:tK''6z K#.{'GOqH:czW"񞼌j9;P$ݖd_o至jl"[n(Ptή$ؒN& d-+5t>#[AbM:(PL1\Ig/E8P }n{v]U/SMQY_EpaCdk kD!YXMoe6C.Lle-`` Vʸ9 [2 i5&01I.a8 ΀pH YWHC!3xk kakEm]*M[{(q JE6čyYƐ֓ K"d2,{2PZll0*ܔ(-f ^gpxk͈?7^Lp'Hx("G N%JmJ}]sP" W~-HhehUJJ5cJ6.kZ"Ql^[zmI )l Hw(k+DS#kSe _- ]["ԼPb);k/OrK~!GkKl4s|smI6 Ze2J(퐧z>%3Bi3R4C+  _ŀ"AWP^ObEsLH5$W#EUezrG$c<8;LZ4P^"-kzI w=;Jt4y&ynHsc<&7@JgJsDW*/A8^r^&87/#ymgZK{{ѓh=Ș^/OpPm볰).h+M@ (1hI-PB oS%o)pI4{01GO[@eLQ_-PWAJ 1 uvL񆐗oUmZ`$oAr K,$'\$ Ɋ_GF7Gۧ/^޿gOs:W}{Ͽۧ޼ɻ~'=>J~+ڮn{Q*{^~eɊU!d?W%O>xۧkN{hG]e/#Io`rN>:՛/z_?߿ß"Oo^?_Ooi=WO_Շ̟??Sv?=ɿ?Ek:/||od|F*G[C}>'?䏷~>_~xg8f[g:ʥ͹SowA޼|x<ۧoS[K}>>޿~ch/^t?gtF9J铟K?-)7J8?g|痏t/g_Q8D̟yr}yOx(ߏϾygo^ܿ?H_FA~w_H9K Jߢь뫽->@fgZ^x׳hJKKPJW/߾|݋}O|[NkW_|K9s+ߝ}~1{Q{ǷO_{ N?{/r{P+RZ!Zonxw7w$~|m7^gwo{Dw<}Juˇwt/_ԾJ9bO~z>{xV;N% 3j+J~y쑞s߽};oX}|~W_D#^%۝~q'iOL4D_Yb/SoH8 JOg.oFp]G?|Vf,N|27!{J'⟟TοKv䥺^=eaW0HKɄg-\ʗΰ9-'+Jz v[jɊ~6w΅N3qgY5%)2U<Z/J6Jq #(*NY9W 6JmN-RFrH\` W <ٽJQܫ+W 6JE-{`T*F))%GJs U^%X4*Fql*F3Հ~e:'S-K-ԧELQN0V _-`R R\`lRl%F4c[*(56Fa2Qkl%MXlz%E4MFqlnhW VtlS)mDJIN))R6`FGѫ1eV"%FqΞq(U^%X)xW Q[(Fq((56{`b+**hg-JSClѢ4T **QA ^^ESj(Rt*+(- l eSS]jEZՄOiEo7) H3L-f"zt@M&P݁F3ir{ӣЛ(|*5YhcM_sh/ \@I,5 _+5_ɭOI~GנϳY&Z mG7Z:Rw5s)\hSs-C\ H'*B38ǙNQY` UUj)('3ZDk "g4-at JXYK!Ķg*:(D'IЁRmbc:(Іt ڒ؄&rQ7%<<1\P'~30Zimr1V ݯ#J5b2%fdLKw 4ܨ.yu, <f2ED)&}U|cY&j bÉ sMj3SFtjhAx}Šlfw(a uPؒZƂaz6QRpɅz^}@}n2n ~,tx+d#gM.8a7X1g. 57 ":Ys%*&U3ݥ°ɠDC%J%!UИV4\JaҲgZL.ZJXHrjh! Űq'eŴ[Ŧ]d5 M IGWiVU:,KچUVdN}24b/fi*٠3mԌԑl,X q6~Ltl$Gՙ2`ȈoPL D4lo̫2g|Tp ǥp ҷf 4c1Qա O-W`1N|_ǠNlu$c{8J0 A|0ғF/R{j<3`Mx'USl| UnΏǑwtćw|l \]-  ٸP`Jl"xu#!5[Ҥ6@:T*a:Mn(Nqc9L.IQ n`VgCM37]48E'eՃn$ O@,H{巢B-~IZA oy Z&oE@  g+e] ;2찈O+ņ|4Dvdd;NVb S AgvNPFI :oN[Ҋ&\NqppuccFW ax]|hj.)J^Bah4= (i rjs *))e(8@f84q<(zӷqϧw8f=Ͱ˅tTP<}7US!}\!S}(!3t~Z|*ZD%f ճ+xqXE:pazfaI?U(Kf^nj +oR #"s3uK(Idae:T!* 0 iPɰ40.1]1㹫M2 ' 3+3傳uI* aoa:pGܤ[@ !"ne JWƉq{Z){{_ٮ5WOTJDh=Ժ (zc7@nf,8Sl22@7ϩ'S2<gL?+$nj@ru,dHQрP0xUzº_c_aN1@0g:\|lAy g0[$ܙ& 7rp*ek*ײZӀ`P%n74-0-M/fu]6V{iQO0ْ-eUH:(?r' Xjes m(x(ԼW{pmnj~tOɞ72sxB熷Վ0{r=gS:tԾeQ-xeX<u@9|Z^_/ؾ#hl#mFOCʆwn1iu5>wh_A5KG\C9][V:ԝÙCI,llbm3f6%M#/A!هXuZwZ{ Zn-QkV:Y>rKJChMv:|uMu$$ *aCߠ8 :8s*Yoxƞl~xELQprTp\ѵ&N&Ȑ[c$kfY_{69_01C7^H>^\T_Mu\x毣Tr8$7B]8KvP'5SY%tYbK`$$/qH:o+9:Sy=z~iRtJj]N&>Ŗ}fmjyarS ]}n(gҝ[$զ^r]=Yn N7\"A_ń/yfxS5m7v~SGPG'8Gfb"$mixɍ7*3.:,r%LN9.nE3eQL,-W|Z#!=4!!e|@0^(9l)NQ|3މxStu  HA2$>*{y$//A^D>+JγX0S U-ڎMR1~5 KNKU-R"y-=\F hkI{aMB:8F“:ѣ`mT1$uF&cs!0)g(9Mp's0MޝDHw!2wq=2Xl;U' P7&x cSwrV +/Abx,DpZ3M`@-8[_VX&#~uWZgS?Audc;tiM t b!_ cz?{okm\ g00i`;V  AJgZ}WfgZsΕ-$kXHEnpU%7Gp$EtweFux"0dŊ/aeWçW8J㧸0kn>xSSKnCr MF叻5<1gÓ\-Jڰ OF5Rf~?`koHdTffo3#Cц4]UX1h:ܼ:eaS?QhXuә jY5}*7QY}e/loեD)JKk8NLM ,Pj/,4UO-Άi5z;wg(O^ij)HԶEH)Eg KzἩnCQ^[XdeQ122b.)4(>RnK)d%K3mɼu^-S?D؈nfc O.?th z 8E:vNe2C %ezf4@,!1eAr(#N/&;N#^0\ùҨFSطߗ>F" +ˋhJH:&2f ÞK&NӘ[pj%g\:཭QU5 rg;쪅eʙJKôQB<"ǂJ/KC E5tg8Sch+v7bq:h+jʰy)|%m'b9n䬧F3ܔ8=Qaɴh<[\wL7&H~X:dn^E8!".9e_)3fuHi^oHɿF8yYΫ$4Q;LLU2erOV(GW^K1fKQ)"E^OHHi5=JÑb w\Le7g}q|e\K@ͫIb )c LOY)u}qZKk[(=fQ_KB^fL[J^){ J]맵"hQlYZ(Ѹ4~HЂ4Ƿ.6Y}7+GM_l\sUH)./WXʕ1GPEѫ=.h:=8(m̕Ð崐{R֫{&^=<=-A1b1j J,q0is|HlYGbeO.01K$Ky┾RЁV [Y"I)~(p"K$ mw,P{V~dN7ݕ SAϬf/BIlq ?fUm7 CBN3,5t[vD_H9G{#)2/E&]bDGDJ72K %jQ[ 1zvr)x,30z-K8]hcD7ŀ'flciDaш*㥽nrczFbvs KxAnʐvY1ʶmE~ۓyqTk0QN_a+.9ZZX zbBith}pm}PMbr1503:Z]Py|5U49eH.)uWm<_BxF/C@QEi8}~ r*vTX Q9-8{wxʊ)v{H_;(,hc.S^ q9ɤ_[Ϗe D XA*\3KHt%?1̺v r)(it]np^w%'6Μ9:)"ηdsy (;O71-1LUXL(tyB%Lx~?Y=Tٻ:۰6JrIC]rK=Ԧ14\SZT/ 7׌}i࢟ňsѝx;l1#fʳ~iulG6=EjY^l_+*,VUgx~mmޗ/ڗ4v]R/Z ac|%#LÎbJJ| H4ɵ,h׃cRHԞSۖ)Pj&jU^+ |ޫzH f_+{ C>>;E;ї**x@400Hbl R<;E;*0|{t!{(s].Wp=ָ0#'K:}ZoS5 }}o^uɇ?ˇHǟ>oJ^i=|㷏?4^+=<&7+R/?ٲ?>wc__=V1h<翅h}o1_FGi=<.uˇʗ^~gCC}g{q[K?ƟU?wK_~O>4{/ߔc}q=y/'o(_|<~#C#}r\}/~sW~+/~՛/۟zZğlzO_{#?><>*ޜG[?=7/WoߟNgϿ?\>yQ\)_ @ ޜ>G ~x5t>櫣~~V/~{?}#~ŗ xa?2DzQ?;}ij_<}u>?3I1w-,_`YkhѬ SPɄ~uTveޯ=#fׯް*G9$$$IW߽~u&W^Мq7/>HVb>t77|.GÈI=*?{{/tK*%SR_xwo'$CCG^hg?{>½}݋%W_r߭?/~;MŻK~WI+ ~}Qs߽{8ٯ!!9_yy_oQ[bȄݳ_CG)t:R~#OׯޒQe ?`y;O0~*lV F|r3.gGJ'4N|v*_'tA<|n m'$ @z)2d~BevJqKwk؝2XnI᪚1=<9MϦiaPH4+Tsdl "UAޱLrS\K5j&&KP'Mj2%^2dɍHnDr{$Gr3\kbZ*xВUZUM,i MR8!+N."eh&NV$Wg3oQ(5 8',lPMVv'ѬPujv'TyP]ʢwK QkN{p#֙y^ R(R(eY*m7cВ'@$%!E"y7DG%<{=U(dգNEK]sn+aI"w4PZ -\0k8˱_ pSNie䐀)aUaI? %JSªE>F!v;ET V(2\1 SzH@씰*NI% 6JY\XUY\X RV)۪QNNY*_XU^*_X uŪ҅Uɐ$ vbUªbUªdob(SrH@F5WaRsY= s5LJ3&j$0}=yW+Zx| -< h3|j=}|j;=L#3e͗7L\ -yhLR_2jx cʃE=ߺI ;)pmQ$ӲArTќ\)$FܜӐmzq|mZ.+KQ:J.~̀VIhz3.πNL#[*{Pw:0݈FJ ~L}ϪcqdIܒ|;~mRpθSuOOV/z `i;%^$TPZt|x2dm$[Fpw 7V,0D%k+ Y%šT(7ggVZop0h3(&uAe'S#fD^f vjcX D{dlE4]ݖ:b7c@$jՀt_5wJ{*T])3tuSM]%둱2'Pɴ9jxb{nxW@͋ XAUR;qq)6;J!Z}šLѤ=.W{&G3ِq8÷h* T QHL (7X2ӡY8Wk+* F pE4ʁKKvof`Ќ%c+YQ٢U6yЊ*.V[r7OPV-,~5o6s Es~hf햆 gƀڝ IGI>BI?{IIJhy[*.wشȋo(M) ƒ| }Ouܲd֭P85@PRvLp3bKb9йnԾ;Ky.O3=;-v:ouJ+'&F0 dw:GeZTkEmË hE>+tna Aeji% h$}f(=5gq4Zv g Dgͳ#clh!$G댯@~27 &&I/nV6zέ]x^'`θ8;eo 8јuRY`PTUtg-0ibgBʻ{ƌV祐,Ӻ+2?cw."~wnm0lٳ 5<;N' g*|Ac9;߇fW{veP'ًG3$k<'v2S "Fdc\:婝@ k~ _611Y޵8`NEmڠ\lϷ͢1kW8y4n*,ΰ[4tL0ldg,BRİ%+h_'") %J s#o9fPҢv|4)P5ȒQ^VJAuSE;2lZWJ]o %vJ^{h2NJj)I;R͞t>j2Mऊ&pʁp&8QVoEE8~SáO:@UYgHߪe[%#vp3 Òp7C8f 3oE ц5!T[]AZ9<|~e#6`IۺӃwgpn>Ŕا!}d𱄳EuKYa۲}7p1>:ؒj3pW_C1xٱ%ӠP)CSɲk]U,1f-KSjD.x XD 11 !2V"Z)ʒaeo EC/pː`dƊ!!߸Z]5_ #+TȰK T̕mpX*%"6H+ԳFmjbXqC6P.w|^ 6/X&+j%3 0{asVYAfggF 3( 3DU P. Vg8ibTff#;*S(U"2L2BQtWficʁƮ 7c/y_bq0 |`Ѻ5r*(b@qhNz9þi`'&dp <"2,2OS-hr(sp'%e"\yR[Y7|ܣ̀d~B VF3Dy8eӞM٢q!N[AhA, =dZ٠(v3wF&C[eM JxE3yXU` 1f754aR戩 nF!AB0>hϳ3UC„49߸G4}n9 :1_O'$bѷKTт׀~>BaSDcHbod 50%#$h! 3&e߸31hSP<@ni8¢`țaoz8j2(U}}΢(\ nz'p@xa 9O ^Y[D[,{WtS%6kl]b8qS_aj]2҈͸=%.!\/z[Pz[)kZ)c J](R |"~wދNzF+R2ؓ ^=0bEV1x=0'Zܹ9k:)O/-iJtRN pޖ·(W6e4} GRŐSyr\܃7H3aȓF+/2kXmϨma$mIy 5 幩AϝOlӿ~ juR]ZC>~W{w} U;vr]4}%n6kgjȋ3nқo嶋Pg|85S=Ҧ+ź1FtUfM72sA} V}GTZC}>(Ӭzw䜖Sle}由pi9.UuAЛЖ\uA*d=xsZ|tmq˒fIyTĥj0}\jgM\N%3I|="KOƱKU)s2| n?k_xQsC%3PH3I+jAjܾG'ʣ2g\N۹n)aH<>#~^l)yS*E2{\f߭v-a^)+,|nuW#%R&G"dr].R\in. rK> 4'ouժ{L7t)E)4*g-Q-WO0`` JM2!;< ^t8+{~CHord4hxk&L^ɭ֙YnЌW%Vg՛^]a%f%E2b,R93sl*qî[0eP'JYd1ŢN&(ka sOpwE=Xf$+LV3ZY 8`/+"mqd7 F w섽8>lYKImq_6 \,x] aa2Z[{[%KD%mݺ.=mR?G{0{+ܱЮ-mhqI[ Gi)t oSw{2Xi:|Fq ~}&r&Ѣ-=x]jy'f_j%>"4O=*DecOkQQE)D}ccfn3nga1 e1#c_[Y 7; +m`W~3uoZ+N-x6i4͡eݭ[]r*sn*K,y'0i[|Oeo.fE5˸Eyבݝd{P4~}$b5ruobv-Odfa%`}R'VQЋ=/h7I!4Av[R*uy4dO|. X8*[oȿ ѽӆSՕlɄXWκ.} ‡G >HBQ1_pږG[=p9Xsg5:Q`M5Ƶfxc:"&uz BE[iRV߬֐]9o5N^FDFʶR8Mm|߮5/{%Ŷ:NZZ Z>gm"W΁I%HcNEz :}Hk^俛]f}k%Ӷlް^#\1xc BCMNVA=ʆFjn#5(IY"|(Oze^(CT]x݆,6܏ .h)5ʹBn4rExߗy8%p:OSL oNW/2Gfk23<> K+pT}*|^/X tgtG Z_x>5`o)<*ʆ$e3JJDҏ+<6DKFu+$RM|iPxDfq'Ow'̈́k%*ӔbNzFC'= 9s4B6r=~-{.#bo+AS|LOsPKO p\‰SCaZ[o8T+;ּޏlt$:2LLSbޖR4A͑RK)*[h~'`iޠ0y4pU2#Ĩq՗X[ ӡb_jhen [ӿ81`u2!q:œnx2Ne9@<%q3{e>[qJπ c~Q.%XjN#"\䝖e=/ڰ.Z}##:sV-xhX^164ʁ3{;=UynzE{{`ћRe y!ŝ].eF>B6il]袇PYNk灵6}Db-b7HRZoPxTq\.p"$s͇tnZ~_ zT.BJv.)oWޛ;]޷Xw+97R90ܒ2Ϸj_ Kq^x%u>yGyn0M;E&iZ$7(m%+DYZ[oIO&鸒!q=P'𖥾zWIp(  B_ C#_k=nBq-u"d)NIUgTom!f2M3ކR P2So.ze?C8"> nFp|`j8Mlo.8X;ݣ8@uj~n} #|_‡#߱;jQ;|䝅qb7 lKQn\=/3d]cQ߮iWݲeĨ!(y?7 +ZOAhs R۟>PDž`jV7 +g5.b{'ߨ/¤:5-J_ sAЫ@ZXj4%g'R[󱔟HmsZz\٘&ŷ}Ii''#"֦Կ%pӋCƳ⛅EYbAF-[۲HKz/X{]<72".\v^Xƥ!1MXSIJwU})Apf'Lj<[Z$=M5_o/e4KB-raDMO.ž`sw|3Ĕ'qYGEܓJix^n% -x8 | 5*zu .)|,2+ %â-OOs:j!N`CBvpqoz'pElSJ;V5W+eq\'LvO[뗫j>(Zh3bmQ}by%v[=o[ z^gu:}֔8S\#^#ny5GI-Г6fU.rpٽš+Z4\}AJFnEn}4B;/O؀h}aŷi OCZúe oה8dدjg`NmZCTg\NJׄ[K/;EK=``4E&`j披h!W ija)<1]^p槲bʐŷ1,̬{hT^aZu*O_ ceJ㏗_r^2ۄxz]W]Nu lLJn΀{^֣4=jWϏ w!p+)f,ԕ:3#KJ zJ ̈v ^|y ij_¡”!UI g\7*KܚɕIY42oK pǃ2n˔Rvue9ڬۂ`ܦc#xՓJ QWeC|$J>{#HKc=b1"?CTE3e x؆KK56#Xq[b_۳ }i)68_딺RQF7EoY_CCߑ^˛Ls)_gNznmɭ/uksC==Oe;}֗YRN o}w!<ӯblҨkx>;8kG}ekoj9-r`{v|=l{( 86iG͐XOv14#'!|GT֑"g_df'ttl sĨE[1;at)5=8+lѳӖTtK\-ͪ3-崏tn]}\'^PlQmq2H0 Ej 2tQJ_(%?h5:zRReɇfٽpI\tmmLŅv&Ĵ*;O}Ӊ?Y牍`g=9\NVzxc M38ӻYOsg>1*({QF= ݻIg]!7n[$uP2./Aٮ3~6xgc|i/^A3(f&Ak>E>Enq4H }rwm'z-vs[tOW[oP$8G#rYv稱cQ$"Ǿ-i;5*9aWR?yvtFv)9[9oږL s<C}3M*NrVs|cw.i]ҴH=cT9H5a''?Om#%U a%?w_wOqgt_~~>?x?Ͽ/߽hWG_?~Cl׊C+?zv4~rf}C#W_{嘫tОڋ.ӇhҮi'MZ[ ׅw/z{|H^zx? ?߿?W?|?=8?ƟU?{?|O>{}c}q=/[;jۿG|Go^j?kH{&ua/~sW~+/~՛/۟mbğIzO_{#?><*ޜG? 7/WoߟNgϿ?\>yQ< /^9}wx%ck|>WG?~_~wGs/%Ade,Y<+dg#ͣav~g)xx}$fȓb?Z[M)Y6%篿~%5ТY `_Y#z{0GD_aUnsVIHH^=޿{gM$9#~on_>||on\O?:"<{U ?_hA/R1R=JU:7J :+W?>OI?jD߽߽|?3}>{K K ^>amiIߝ[#w_w_#wWţ|4𿝿{p4_CCs>zW_f%7 gH;S]~b?Y]G*/5q z|[2J᧳ul7#ogIO%ͪՈOnehP&)ɠNP'6 i)BrFd4\9BN?.°l}}X;JƐ,.Rd}u^=|],o22;Ce4ɱܒ/U5cz*ycs#M5U5U5 hV#1S͑D6W 2Cc 2'8jlM%Ғ%(D8u]QX*^2dɍHnDr{$Gr3\kbZ(В~ZUM,i 8!+N#eh&NV$‹мFԀp[KT9Cu&NYEmN267W-%⃔P=愻71b/P-R(RZxЪb p3-I.ho^r_KҡZ2X>L--]wmT E^z4٩ABzwmW|E TEN}k8 -Zp@ <pspBWXx^e+ oK:7ϗ‹Kdp@ NhrA-\li8=5{ʏ 'Zx| -|zش*?n\hx]6Kha's(6SmqX%m^ N#(y0&e,p_)N)!St;%GIP|[)=C=4Jlf$aH=NAk9)vJbI)8aTs)54J%6 bUªbUª3S*Xj\X*_Xj}ª=4JlP SJH@lŪUŪjUyK.bU)vJAnvWiEӤZUN2RPFZ)3$ 6 rXbwV)aURª;%GyMB'JQjXbWJ MVⴰ*N R씰*NٯG"&roC=B93ݤ+v!Sr)Fb)Lb)[H@lF;N!S8F4 SjH@li2&SFH@;%AIky 0 SzH@uJ%(vJXbw %JQ*Ni#(mRJB}*|r,X )RrH@씰*F鰤ӅV)aU"w;eFRK@씰*FQCbU)vJ*.QbUªbUªd甲jTNVp$ vbUªbUªdm -V.J&SJVJV%};FCb0 E՞f\IfR1wW#!ɛžZ5»Kha@c3VWa:})k5\fNh͛@[-Ff͗PkK]mEV,.NJIYÏn"~(W|УJv Y7&^a\Wzq|&1 ;wGéz 1"Rt OP8S>P;!ŒUVuJKˢt -4_hz3.όRe51FTAI,OeEıIYu,,18$[RO9n"vƝ}Z~|IݥD_coe1N:PxŒw/ixVf-C˘b9!˗:X^n,@ Y%ḡˌVZq(bp0h3(&Q $F4h3̈6̄nmĨ@dG&YDs!b-uZ4<ovǀjՀT5J\PMvLv]oڧ@]XtQ+zLfQg,ƾ 鶉iG XAUR;qq)6;DOJ!Z5h=,G4iy{ށ1eL6d {DS! `Fbix`@}ߴ>7 ŻZRAe0^O#((uwˤ{Kve`Ќ%c+YQ=U6yЊ*O4x[|V-Yڄ΍ n96vK7 gƀSO _cH| ,|FGsȳ$ /Iڭwެ:-g((68|3OmS k4fO,f LSq`[B%BfVK1ғw,-GZeTg$5#@޻R,:d]܅ú1B uJ+'&.F$q.NW'5t*OچЊ}V|v{@Fd CL*}UK/X(DH%4C9Ѳk8 >LlodE !>]g|eÐ!m07Izil5n3?Q."$ PFY!|aUXah¤ )3ZB[}bQ|sD]hG^G;dE?cìYDS$cw%.0wn0{UL ށrDawTV u{+I`iƳS]RripTvnˬK4:0Cr,L" /Rً=fٌTa]T5놬BpjL6ɚ=A!܊Ie1jv&ۏ !mY{X[[槐ů u#KC8X8`Q6(+mhUv*;2N'B8n 0`I%bƛ>]VmLrߦB4^e%IĤr?gWM׻FhpmWIWIK>(mmȄ)ʽRJH xU$%AS*A!A)}S R>(GlrUJ1/wSBRV J JZ%RzH. AQ۹-[Uy[%H{HUBשJH xSZk{Q\k{!6V lu`[J]tBm[$Hs-ܹҷm{3EOxVJAs@pHo!㢤UBV ]QJGH*Ao!Ao=AJzPuþ붯nPjvkmJPgHP*A!AԲJ nNV }^85tCW sG[$Ni䥤i ҾJzH*A!A))Ț阫 JE;p?j,jysuӧI@ZV[Q _SáO:{Vg!ܪJfx|,><_3$OLV2zf 5 _kb;exYefx[}򵮀Σi ­ax|bx|KcZ'pn󵎖i]3Çk9çmDzp~1o p0{Qbg !_1<{dx|ۣ}o>O>ËkwGV0<5rإ`>%< v^wF0GT >%_n6c|mkCIsp|2<7_..t> w#܆ / ==Çksp>0<{6`x|mpjMj{6 B8gNËףM<_1|x6c|mOY|m$S$tK='q=,E; k 7_qZy*qpAη[n<ʐ+3TFÎ7-<T,1f-#2`gK BFóL fAUB:|o ECRXƩJ2զ@ G~U6||h7i2$gH=6) ͅ <:k _kP ,rBq*SSVN5e@A8].dRi+qF d|XtFn>- YF4k ъ-ZaݜVW`w\$֧gaKQXNió̑Z3*łP #ikh{b Ȣq`P eb䵤PG NVf}ͺ@l!#Z~j4q>\=ZB} 5Iz&M3fߟ0Jb52skRdSWt86'tNjOgvni -_j/lʌuLbfV'~Y6څ47 %zI"3,ZhNmTȃ}+%ɖC6iMP@|AVM0wgE[C7%M622 Ew}ny_ٸ@'4SvugW`>21 X!#BEb'&3$RqR \u`]%"VMan {vS|pTiK|QxQEn Ͼ-舺Q&Ty%tKl `K6λ`{m[>1phU4B< ^$&gy䔚a`h *Xy*@I`(Nq}^'[mV':=u5ylD euUxldKV'm_i ۭ"萊'.leci8?mѴ˵ZcKꜬ15T1KĒ P#fS4zABz.^r7P.>=M{|]Bi8H-QAc/ƔsƑ혵*Wڰ]TK`4\)(yq#+dq5iq͋;8Sb#[UיۼlD[Cn;NњZ?VĬa7/i%/0e e+VVִqa e]c^ee%a=)aϸZ^=z[z D,FZr$tC$'ѡWK]<RLeb=M9b*陘z&̸!ӤnGc*Oo-%ּj|K-i%/}^Z-mרgo)j;^bKST-սE_Q6RG5J!`C첗Z&f䈛4{}R6k9Q8:K)o_0ۂ?[vkc OGS%΢,5-JR `9O ^Yy8X I9 E pyxed$-Jt[-Po/y4|6klWOO*lpEy6+WXqvʃ>A 5ƂO<=]bS %6kl8` |56̀U ?Tao*{O> *om^~w>&\ &5#`i`ݭ&J*[Ǚ5*׋g6 1p8"pW^̋wtWM4y ;['ყ6%NWB\2K-7lVNi8u9~.bn8 $''\a?z?0]g;ªq0MLYhqUUȦq _ #p{1Q_5̵ V:p ?Ss'W2{ׄddy=ұOcsúQr%ñ"n*xBJƅmUr!7)gG+ .[[1 6.Z-x-yAe߄-1^P6ley(b #67^ɭqBjseCf֦)(!>) V?_<MLxr-gU{臸] ؊`-.WM kńnx;1q9i6]ĐMNL׺/-3zS@P@UW, T@^^+;Zvۇ 6l^L/p_zP8754{y8N?Wf.2c^_F/P,=w-FW\প`9~冯 2֒Ix^ |A7\*?i?cݍǝzk<1Ҷf {0@ӌ0&Ƌ xA$}LD8#Abh`.Ǣk1 1뒚!Dux=\uYq_Q]V5#,OXR:@ybɀcG Gw]ov ?f*q,33yq Ԋ 3ZɉTB 3 ɴWexXa8%c,n%pͨq%`d巋8֫:n>bo7WK8}n2&jp}4G~He4fd [̝jPFVʃQUߦ3Dkq[4[m#(I#@U<} 24"B3^ʬZyLyG~! +[N%ո^i00>s| U7kpG jl=64"43dbuG9<6oc{ȶ48liQ62ʦe5tʩʾ۱vQ cS ا;;P[5ƀw;|mo^Qu&)CP6u(ٴ\Q u!`t\yL_ͩ^Xumc\q/Pv0 1UQ4p~R bJD 5c L-zoF+Anއs*pr|=\ بXnjMIRԿ'Fx8"r2 |;.nrIkvϤ::6mMM!5.`ǤwcbXlx\ |3,qnϕa24],Pfp:EVOͦMY%͙CA1=ZI*7y%-ZLa4MV0k8zPٔ{ - (J |;\8×n QƾRǺ!ton.tIW-ꂀꐍXCnၽᒶf=po<)EmF$͠% Hlʛ,RGM`9|o+AwФZĶBq|pl 3 JVJ?RB4Ƿz!F%}AY;;uC |3_ 60W4OT}-V}N!i^C~>Dl㢃4 Q٦}OegwON O sBM0 3`PDOsĪo\H %Ϋ$8nfz悆P&j2=<0³'y '\5Z/X,2c0PDN,UeÈ4px A)DUдQ'lu4 >,5vNƞN('Wn "\Od*RBy~G 4mI LfBDT(ƨ,4EA,R)GwEh7l.@@qJ[S{n}Xa͚" 1W 5Z(<ϣ0{/Y>FF4w~!`6 ӓ^v 4o)o V loh+h8k[(킲đY18oo+@*-<}RdkbnI%NaJlYr~`8(( c%`gdԓN_dHO[3~Qb0gt;~i u3&n&g'FCڙ1ZD3x' "Ԃ S X|{ 6g(, z<1d,P0f}aJ v.j^ʇ3zC:e X&z-Y8jF3x`fUXF8d@ٹ."sO٬<u$ qs2(O[~rRkڰ'yC I?#  (B>G^SqA ͼ G)gv. Z8vI R#nh@{$?؎_ Nzk^RMD'aMŲnՌ'RMFl؆[즉3%)xr9E~Ug)_ֲPi l{Fn[ kTtǷ+d Xuc!1\Y5O|}M8S_lc\zf/Y קS_fa)[vm!؀KE$=,l÷]a^$'. =0z]!VWѡykjKfSKeI,%Z.$ͨo%ʜ/NR%}RҶGa@"XoVڥXux^%U:;8OV5M3x[\68n29d W|Jtᝀ? q'p{킽rd4!dXf2nΐ"Zt,6?  >g:BgzaM1fi06x0\gnΐ"Z; ,6+ChGFn}lس221`8*|k &GoE20}ܽeoٗʨLzjjo3|5 8>(z/>8qxmq$Pʵ{sU0ǡ1磚IǤݳ™&FlG pPxaߠໍwYhc.JB/3QQ~+{́z oȤ_X8!@İ~mRj sR*H^ᛯJchOcʯOȎC@1|k0w6{A L mtwKej/0 "xn`O? tFh^LV,N Yyg dp>n̓lx̤S}^p[K0m[%o[,{\`M<[\$^W.,{gCDNNV)ff іTYpXCc}V%NCyѲ 1":Ϩ]r.t%@6jN}D'glh 8T- 1ZMWgZʂwJfq)nrʀUl; 7%ʫim33m5RR-f4%6Mht}Zm=6\݆Y2}'33scmF 47 +e6j4{7߽L1xHW>eZ`>ԐN戧Mlݿei 8{~ Z/([PL# ZKA{RlN"2`MuXj.LHk!-Kܤ4ft;=i?6,Lw7doFkR U3b6 \-)!Ǥ> [v \"<2 ,?6]j6 7{[|!& J/ Ǜ$8cy6u|eV: eÔǥA7 +AM3؋PB uȂiPҜu0աXY5*y(um%',zjѼ'HZl-I0ջV!@[}*7i(3]XAږ~yW1 |鈢c#//eG:H4]d>B}]/vg}RpX쐣8`ggl<|ӏq9.ʣkS|F/IW"Q_$[H$)hhgxC Iyєߡ㛯Jl8Ps_JWJᛥr}NYcOʙdSG!q=}o^uɿ翯_~Ͽz|<Ͽ/߽hG_?~Ckſ['>S/?GsŎ?>wc__=VKMZtОڋ.Ӈ}iҮyGi=<".uˇ_^~gCC}o?{zs|J {?А]?(Zj{_?w~|[?R#__ xuy/?߇ޯ~knc?Oӧ/^>/G>WN?_>|7_÷?;mTWğlzO_{#?><*ޜG?]7/WoߟNgϿ?\>yQn_ @ ޜ>G ~x5t>櫣~~V/~{?}#~ŗ xa?2DzQ?;}ij_<}u>?3I1w-,;_`YkhѬ SPɄ~uTveޯ=#fׯް*G9$$$IW߽~u&W^Мq7/>HVb>t77|.GÈI=*?{{/tK*%SRqA;7wšڡ#w/4w={~>Rutׯ_X[ZR9wHy&F$(9 o= אϯ޼ׯY7-i1rAdBy/'sigA:R~#OׯޒQe ?`y;O T٬Xf]ώNh⟝Tο^,/]!M5+s7< / tF%p13[^I>xXyX26dD|H逻ސdF¥̥5PMrkr{O^jTFG6=j5jjAU#ѬGb# S͑1lTezeOqNus-ըٚLKx!Y=ASVҽ䵻+AL#ɍHnHnFr3KrMRmVUZUM,i sq1BV8Eb'@L4H&/Cy Bu8y,R{ N4hnw Uw/jfw1]h,tZץ㉙N:-R(RZx#_p3-I.ho^.Cd8ıh}ZZ"/}uT_ E^z4I^΄[λsn+a?2곤ppB ?z1 pxa8۲Kh%p97ϗ‹KI {j\o^Z\ p@w/* 'Zx| -|zش*xmϗNj'i CQk݃R5Nb͋)y%&$wn*)%$ vJb(6 JbS€;GyFRÌ5 I=(}:Cb0'N Rl0)'JQz;F2B&Xj\XXj\Xh!SVoQb`_j}ª=4JlR SJH@lŪUŪjUpl_bU)vJAV 6KPќª;ԶRF H+e&ARlqrXbU)6J R!6 bSڪV(5JSJJ+&A RlqZXbU)vJXb#@~_2\ݣ,SķQ"=;EȫN)!Soԋ?k;q ?$ v8 DN;Ud5K 휡*?2^݋YKН>Sq7()lp6wU+BC*)Ncurc{f;7fxGˑp0h3(&Q $Fj͑ 3M/3aqG3ת@dG&YDs!]ݖ:bӟfw hv{џ(C )I;eo 8јuRY`:;lo) ]vvNP,K!EY=%NYtm /'ovHGC68ɃťNdE?c-ݱNKw,w'΍w@}eϚ2i(® 6FC]11B>ն'_Rripć (_r'.s۬6䚪l8Ş,i pz6c3|DT=n2jNYpjl5O1G=#tzPf=*v7Wc䝀e{]SZ ^8`q1f'pڴAY{fјMUvd<^U잮 EC' Fv&"$A oN[jgeW`41UoGz"N4|tkDWgFBehmRBIےOm!AV8e J)AAYQK>9%GPX@)3`n4Ǣ4 JZv4<Bb#pϨAq8)|)%ׅ"^sʶh'ZWJ]o %vG>vr_vv'(I;Rd3-|!egUh'U4QS7"}+*©r}2\Չp­:CVe G-* Y0p5$i7cexw=y#- 6 _іpkg_%m >Ly ­a>SbKCxs{N#ΞѮ.gK3gr>#8+ؒ[iPv!Wfɩd_o|B|.*%p 5q΀D .̂d-eIͰ7!eH` liNlOy^^}S U2Eeajc"se%VJmfA@5R DaqYޡC6P.w|^ 6/X&+j%3 0{asVYeggF 3( 3DU aC R،ÿPed3@Z41*F3ő@R ѩeP ƒ*r&(V:Ɖֻ5{`ʁƮ 7c1 yf5rN.[H ¸" 洡.36 f|bb\A ̣-B.ݡ>,9)I񏆏'8ԓŒ2@hA"exO!= XA'T` m=AdS6Ia[Yđ-2b*гK b7S`GUGafM Jx ^%s,L zR;3F4he[ǣC I#j*T( # ke{"j,\H3T۠[ZR( ;iMѷKrL2dDKOԴS 1k$FP ChRmK1+O-d-ޤ?)ɡMA{f֯܀6 FD$C ڕk=  5{Z=1F/7 @PAv+P^plB~:p8Yomڋl e  &:Cf|0JݺP L8pLrB)lVl\`s>f ,ΐ8T<Vg8iZ_N wg`ƹ8<>zU?ȸ&8X1 lT%<\2{RQ֨Wq~r/$c ~M؅x&%9s/x0KZcs嘥ٽM4nt۫y>ch@lu[)x[{Xо/mK|s-*E!שQjxeI.O`$'rr8X( w[=x-邧Klx4G2l<1\plZ_\r֊-'+ 6!F 6klSbtSǼGVL)56~Yj]>]l[_cIr\AS XYdb0VO'.e7BX&uM:WxE3s\ !K DëD/zHnBzlJg8"Z83OlvZ3gՂVy$Q(p##e8OaLʏEבЍGmKe /#Y|i\o^2E9I߃2|K18+.\0udIS{T)4pyr <PvM@LU> HLSfsHS=b |-K#g}̅;7/$_gzA?-փj/ދu6{ǻvHؗp›“g~yK˙gx[uP5*7y>/+A.CLo@x'\'+٩n(dK y  d4r@b P3M JiXcMfR `c0L8*E8F ác.S7ƕDX/註jx>#nG_SO1jFo1BN51@^Tʶ&n |3B[ 2BK-NGVYG[5|*/#+XTIVx#M-F8'E\Ua< 2V' 9FwRfʻ Z\?k\b\Ev Ss:ǘ=b]o~#pG /jm1{;RL#"tFk[ ȦKSUt&sD(}It̔S\pRᾧ}Uc hxs'Xdž irϼlb:ec\qZxX Rg 3*V٣!:.N+~Y5\Wur爽mΥ" ߎrƲ!ahF== X.(9e E hCJ~T%XT.ag{q.^8v4l i艮2f8.!JJ!DgG%fwkro=eG&=2 Jn \kd qxcc^R.)o[+K.p$}AUI=R*&irqX)˴j̴Z˫iP۩B"+Sm3ˆs!{2I8C"ndΌb1w]"9¬]5 a֋U8۠I`sW>**N:xnČѶȭCm .[M%S88MDxKRf4=ѐ<Y V2GK %=0|(O\; 2 6aȿAJc-W)XpPm1j#îޝ%@MK)qq2ù(W9,Zz8dq[@yȑ7嘃^c3TW9rzK㗲dὅzĶ%l>SV)zף5GvUkWU,g)􆻜P܅J0LGh1Ck~kЖC4URrM+ܓK[h[67KS J-3Mqr1SKwD0~ 9@(0a]KxcW,`Cj53>0׈=7\ϖuU k8sxNSr):}b ek8*kQWmzlhJXl%9p9:g:њĴE7es:hes4܀cWIk<8 WELRPlaYEM:IZvFuNRzS`֣x  ɘ ɘ='cީ”#69H~U%+I&ǷP e]'oRAgd8Y'P7gDMJ4楏@}ݍ=ރ͞&*ge}lac{R9oxZ'a1 &g^^jPFxƗnd3Sx1v_)B_~Ͽz|<Ͽ/߽hG_?~C*׊c (R/?db;D1]Z.1MWy:h o?icmnj;6io-_OϿ|}yׯvo׿>4w_ֶ|~"V~~^!|{wO>4{?}o~rzG|Go^?kH{F7ac?}_o"~%ӟo^z_>|sC:g9qPW߾}x"<ʫ7>d_>|ǟ~o?/?O^x?$P~sū7cdl 9ǯߟ>˯ߞw_y~xr~9x}D ,%_߾{ |y_?/y,o_ݿ? yR ]+)"ˮD¦&rZ4q~T2a_u+tDoFh7Q~xΪ0 Iիw_|d>24go-ˇ??1 ?}v0GRGw߼} ^<}'^#-?zR*@GJG{FģTǗ{%ޝ;GP~fχpo?~:{ :c/--?wkyz߼xxNk~Ҁ_#bJ_߿xw`bk}}zWo^{׬ěwԖ9 2<s?>/0,#8 =x-Y^vٺ y W4Sgj`5ⓛv?;T:vJvLS9z=@s{#d&=" iw WMoQ>wcgh[b>, 26d!:a?)t*5^jTFG6=j5jjAU#ѬGb# S͑1lTezλeNqNus-ըٚLKrȸ%KP'p6/c^] Hk܈F$Gr{$7#%&KFr%-\E5 P Tր܂23+- G3qҴ"z8y B89l=`sv'n]MZ۝DB݋ڪٝdl nL8@ڥ,Y_(B/I ,}X1B)JJjE&rJq\$y-Ijpc0tEލoP vy&Yh.SrSD^ܧ~A l Xj/ᒭRRBb(vJb(8% HSz){h(5HIPÐ{ރ:3$ 6J sR0(&A Rq¨(Sjh)#4JlŪƅUŪƅUg7UXո}bUUUVQbRRBb`.V5/j.V5W[r ;%JS JY2V)2RPFZ)3$ 6 rXbê;%JQJXb(IPZhU)6J R씒RJi!IPê[V)aUV)H$_Y Pp!tPA"/)Q2By{J% vJ Fj4 SZH@;EǶ8F4 SjH@y1(F&c;eN!Sj<)=$ vJ:%vJ vlw ;%JS`IݻхV({XbmRJ JI+e ժɱ8c*|J!SªÒNJXbU)6|ލB%v";%JQdbb)aU"UbŪʅUŪʅU Ux(۪QNNY*_XU^*_Xe[%HU !I@Ū҅UŪ҅URRCN!Rf\mjIբ,4ÜjM2Ҍ - -< i_)hjE2pB /~FXA0tj92S| -|sj5›7Z-4Ue+}~Wf:4+י! *z@AMt9J%;l2L݀{0hM1uyuΕ3yQeGҸY(w;oM%br%KT @ΛuWxTY#xM+;HmJa0tfߌ#a2ƣ2(æ赏JIKl S UYy.j#M_Qk)Q-֌{JtD{N nA1:%W~X< >G5t*{kJچЊ}V|v{@Fd CL*}UK/X(DH%4C9Ѳk8q">LlodE !>]g|eÐ!m07Izizj5n3?Q:`B&}N7xh̺,0XJ|OuZtg- ٻ.3ZB萾GYuG9Fٖyx7O{]< oﲼPƉ^2`wѲ,j31:NK?;x;]k?g0+Os3 ve`W#LɪM3NSu 8\YpNkq=Y8Sً=fٌTa]T5pjlxYs&CgE:=(Q3~d',a%vg*fV)d'p|vpWmcs)NU;ir?6Ƭ]el#?`tg-:&vV 63q!D bxsڒ4BDF((M&&,9h5F5٨QP_/)imɧjb2RPD|2C/0h( %J s#o'4 ϵP5w㓑AwG,Rr J -+uFuPrhUoH :ZIIy>_@ {/$"LÊK09$p`bBn{3a[9]U՗իV_)۞B9ZJ-RZRE"z ]@:5G*t j*s2]܉tҵ^P!ʘZV2.͂hILt=צtVkcez7?hF:{ҵC0} FaGz6ҵc#cB:0}l@:p=[4! ڃ L>B:GZ@j -mlǼC=Or:, n[r/3/T+ TEW:AuGXz$<~Cl ^Vc̆) SFAE3J.gaeoP_^SmAuq +~d͋e]v]q!#<_ # 0W'>јv, }TY %L?N֢mߡ+wF!CzM _.zaBXiXp놋^bp7@ ]-_'뎪: 7r̴KZM>Ӯ0&YՐpP%nȐM+Ԓiiw"/W AF.P J{ H @leP뒐E> >{^ 2Tφ0+,E%-uW4lg~\ϟvqB}]'8s~|J(h5>Q4ss r(= # gZ6:f ˓$ UG^ Pn0lAY_trzÕp&&O22B(Vc .UkE7xnÝp%﷪Xr֤}Zivb i֞wNu,i ,87SkއV$5К+؛i 偉8PY >Mms4^ WE& ׁWn޵B Sty3LޤZ-kR(Ok,ô<7)K0t4;"Vr)|C$e$k}rW!`7*:6Y7,K*wkY:m+ er`k-<3҇Ioޝ'őUI0"O=OsԀYG+fʲ|#6:08n$@ȃ X}# V; 5r|G_.x~+O^ |Vk\bekE"VOhNXos8>]_cY199ʏltnXMiAḂ»Thuk,IPú0@} ^_'3e/Uw;zCak@L#7?î)yZMD{hC:ʼo6WY<.tl,t2aTDcY25xsCmH_oJmVs QZEiEFpv^npeh'`I$q#aXs +tʰ/Wܱ+lPw`P彙*.檋~ukeq]33Qkh>I`=$Xkq\vZ$hX|$Nf tZʍ.H[v׾XަN2,@25(lƀQ؉0; F6E\4sNlX2ޡrfLfFtp+g01a坛U`3Cdrϲhu uc^p <NjwL[gzG4|;o N9H-JlK˿tP1U.*N9ķ@\UܫtQ媫EI96}rҼ=]u$fc8'rS) Ί3儗~0ʶ;e&eOΗr3=Kw=.z =Lp#lV`cjm^nC2ÂׄdP`A#7/_Mx 3GShЅ]H))C)gh:oʑצ=ZIHZ89C[rw |tǬ` $2Ya&<6-xX0WZ(} ز@kaLM8O)cF fv4usAx&*"YG56񴒣-r6 ¤xR2}/I$h[Q{>#ehл;)z$AE"X7>mau$D\8 ۆtA[PfvZ_/\`!=Aq|3T5׽hk/c^dL+n#g$!iCY;) En.xD]')Lp?RuMUbz-MZ&"W L:JVf% UWzb9*Z"0^n>#2p ;!P"u) '\%j#"kY00Qf50#nD% ^ψcLJ%BҘ{]?76PYNViv) "Z o>Nt8U2k4;(LĔnhXn$/L&`bʦҰotʥan-ȉ4NI>MeT`ɴiU=7SHI ֺ%鶗a[D9}) 7ڔ2ՔIgP0k J')o:#(GuW ". o&jҵ]t]~W뉅g<$R`fPJ(Y6OvA)Z'bCK۱GW)2"0Bof zUo'lXt,Z#`)[=Bz1 [7ӲH{NgHT͔%djҰF0~Lfk,ܪ ȍĖ56Ugcp%P$ۚ}oIٸEX4f, ͳ) tAjaZ z5 b 1X& nO*Eaxax<ɩZq Zᄆ},' 5q|3)TK[*m ؍- NF/ժzG80ٮO<xa^9 bsb>Vޝ ū)3aCp<]}Ky XGNGp eh3yOVs/VbtKq|v@Dc&)5GJݟ8~rAL`fPQ?| p֢Io)Xҙrm6;EImh[|3gr8SlK(C48=hD̯VeNsR[/}o^/q?/>Wo_߿oۿF+9>zo2VZw;ʏn-(m}?:l}C +W/ uDھC6L>~@~o]!IMڸG~?>᫷C_~~߯?߻_~x?<<'_?>|͟Џ~G{?SK=>~?<O?e{*ߟC(޾^}~LZM_g/~}W7~N?_?|7_÷?9w\p^K^qE?/ԟxzxsnu߼q˟?|ǟ~o^>yq>>\`%JگxOݿ?J?-)7_ۇ+__?;=<߾re 4WQ￲̟} B|$y~__|o_ݿwg{__r߼ze9 to/N<:ܑxwoO߭.>{!ɟ{_J/߽x~%@c//)]D"w$ +<g؇|~篾~JIxGo_D w?w5o>~C'Woɸ(?u`y;dl角ڪʐCg+y>;Ҟ뺞wYGrꑲ'OZr1̆_MVܧ2=k9 sh' IC n%^5}㮩RLMvc̆cY2]\3v2YQ\f1kV69P+\p<9;8lM%lwO*pAt6vvs{?ƞ^ 7\tq.nwq{~ ^kDžRlGdc`[_u Hρj"0궎eoư{l&,0ƂyV8EL/X5l3^ uWPu?Iú1uxU4k'JI[X_L워)8\N`U/9w5dԬ{€@4D(Eb> *imB1pb>\s} T8N[ՉkVG1# {fw(a u(lg~4  l t ɕz^V> a}n2nxl#:8O]z@EM8- K6Ym lNև+\IM]G#pl^BU}@m~yk*и1XᮺM-G.5ydhW0`2>L\&/^#4%@>)oVH#7>mL]njmj*Znpa E뾸 4 ٨3ђPzjưԑl2&x&Q8yge0,RDwQ6 Y`:YpSE ,05 wwZVK%poOZsH^l!lnC(~$u;'wKS|c6Da<<O3 z'dƉva`1SjNu$pitT)Z7tnV!g-9]N1S V+flΖkaq B<%p7װp5ݖUg>ywwBdݓ~zޒ y˻ k*p-V p< ,=CYBSVXM+\i6m.;`'&!\f @agΠ3;U'(I'bΛӖc׍iLrKFT(mu^*Eqv>4]SF %Jizt))Pʩ5ҫN)2 @)h4-'|aRR y畒ZV)7P{G0?(rI{ڝߎg?-rx)v/򬐥R,Sr ֝ze %:J5R4Jv{gjm)%$tHvl{ |hW*KYDjJttU8a+䫩Hwa:tq'YH @: ʘZV2.͂hILt=צtVkcez7?hF:{ҵC0} FaGz6ҵc#cB:0}l@:p=[4! ڃ L>B:GZ@j -mlǼC<Mu!ŖL 0B>9,SB<.UT^>`_j 8va2B,y6Wr9k +{<(l B7NX15$D# .r57ׯȰnݖr8?x5 `Lt٥/[2gp'ٌ͹juM+>c=3,̘g**b$ ،ſpuf 1@^D#Ef/'Ta; H@,rr|)אmG1whg^YpuOWi%g=owwoa:lN÷8l07,*s!ps,[Pr}e ne!u>CkbJDg ͜ +5/-:< a(b *upωEd2P~Mf 6ê`-h%$:}‡]\R fch $PŪ 0*T~(Ԓ0TƋmì LI2%,ԗf͕\ok3.P{ƍ+dPgwlHxG2U|HGMdYx Bo? {c<,rb@>:8iZ6( 䓁 h̶0uueE [p⠅F ld5@V]Cep'ja5v !$p +A5A$f#. f5.cbeW$OE.rIS]MҊR1 OAЙyy1efXFxVyV',<ԁy[BYMik7.ddJqγV)aulRWIſddB߮<'&U)X?=<.iٛɃ>/R/ ml3kk:Gu{$(e21k<%{dP?u?rM:,=kױ+FvֽXYή$yņYYLJ[]K([>)| hg=_zyZQݟ,K-TQݎQ.F)&kgKR&};3g-bŷR{y[BY:BVb/Oǜ.koϊk_&VF3z =vRsu+ qvgi`ExmxĬQV79:ψ=gl6/Yx&۰o^+{úP}F,RЏ٢@~ GatqddO.Oag&O/7>YY j8tSKXyj,'`ʟ%.V0byfz+X Xy;"Vǧ L Vk<+Z r* S1x? wdy1}fc1܊c kVJ]W>fF>SLoO 7fY3&=[a[dj<_͚~e[E?R"}=).oB&`Zc(Ō4wܶ+?Q~R;qgЇؒ%M}PL/nr]SV0)z I-+}89쫣XX[#y[\.'8VewtcSaV0+{eX&BEy%[r#t+b#AIuA9]ZC +V,߳UFKvJ98@' +ʍf@Xdže<Ͷ+ Mw硻P<[nIŜ!ɿSgp d 4Λ7y v%kFob֪oN+;pR gsZؑ-]ֿY2Iܒ=C9Px2#oeOݪmjL\Pon<2}Ϊ7:}70G[?*!kt|-RׅRӶ Z]M&gzf*&ڦ> T ;fg`Fu ^2} m!W}CUW' b vctZˠⲭ&\EM*-Z.a\bHKϰrы==ik~WFz5fLŨ75Mɶaw:1:nb![qXaEIui iA+y|x%iC;i݉Eo^Z*챌K@fs,pDxZ53e*l!V}3oVkӰAj"Nd@%36"ji8JN1ĝ}%Ϲ~UQBUPVt U; ٲ֞奎BrݒvmhQ7סUpNo:iJjmA]K+;;y]9C,Mҳ̢y l *_55/xQ3!3q!#tk'LzNf,P+1j9XI, n|:f!/;wtI=Uㅤj>ව0U)/Y_mk`5LGgHlYl5`&/|T/(S$m-<%w֬o)HG?e=JQB` ` 'Ao^#,N'Hz}fͤTa!FbSړK_eh>]UJ*-WT^+v!*rY94w1XC$E|>3Žym2/{!o 2s-C(X3>s DND*xγe HL,x1ܺMѲ7 M.3"ZЃ!w,m9---A(gSk:`Xj"~Ŧs-Z޹u!XB8F!2٠]\dW8 e+nf# &ب'{ECS/G5߄"f gH!/#, tQe # Bq^}`x\N-9ז=撒q$h(SLqX'D78n?\&m-VpǂmOW`{ЮkkGDkA)̿Â2e\P64#9 7F3 ŎВQ:@)cFܜ2H!b-,2K˙A%-ꖝ:pPnWQga}(cwʞ F@ǷA|̮6ڌA*xpF>7X O ,r.'4"-SZ]r*Da=v>E#|< *dv,Oo$B$§d/z!U i k(NvPVF gEBtz^A2T\1}%9wVJ%6nLGIbtm3#l-DɁp;"t/nDؑn:Qݩ 2ف37:ZqZkPTFRa0[dS'+"]pJk!bF)RtJ~w^biClXp*e8DUbYثzK:5Q\>j<{^ #gP%h5r5Fu#evw(a$<2Hzk%E״>g:HeVP=s"AީDЪcQt?lO牔Z.(bZPԯQ=S'Fƅk hB[ˁ#exo)#(ں˜Rm2(yLZߝ2Ƿ@|ZhSϋYFh` /~+5:RjGȥˋӦ]{Œy)񯘧I4,YñܒJ $CM4=Av1$~p%_]PBLF.# D"A.!#7L0*Š$Mh+N鑂-RF8K{ _p|j*qMAo9̆o9;8pY9֛y#/yAS/.[/O>uA+T$)кekSyx)|1n" nhodƻeFlX!IEq3-aJ)d \r[*D(L/^ O"}*kPmK]]f])56fqhT?ߧ?d 0"x4 iVhћūB;xf6 L@?!m0ڈw)v7QZw|axѢw/zWEۢ^YS%[QeSeJxbq#s W)j4x 歲XgYlAyu-x"k=G5jxbBp\x9CzkFTt\t()6vj`0“`#|Rn[L~8y ɇ5uޝgaD4UkBɮ라噮^axL]AmbxZj&26_yzէL=Fv֖4ݸFEϡo-ÜƲSXmV ?f$e" >(W5#C2.[JyA̓1ѲM#V Ynl3${(.oTS6)>sL^rZJR{Jb_S_R4%Iqq)+7AM de#`/Xb~CmmJRyxW<|8mۓ إvDSrִK h,E)(o aX-#"z|ˑsX7s./ l1Rc/)SAcߧu7ŋkjDiIC}uC @K.Ҡ"ǰyTNJV%=UF36 כAc*`1ʈFJyίC岜|~  `vEGC:(]RR(kxj 7Qy2U8 \Ɇb/>9d}9Ԝ< hpȱ%Q]:qGУ=jЃ7SڎHAZz]R& rH)%*ZW@d,+-,] R5"g-pW=ҥJP-Rtw\tX6pUY<:{'{ʅ\)T\/S:λYžNGuu^1|b LAHOq3[=.u`M]I ~\dPxV I:ezAz˴'/sZ1&r=e.AVMXVNeVvuía-yɊ`eeQ$g\Cbp%P_4K(>} ^QY/"!jZ"z,xemg!Rv]%Ӱ 0Jw1¹T=oqԺDtRZ&t1 wa8 pJ YҮCY83xk +*IBں j*-e61ɀP* 'f]d)kLZd,l.±7Q]FC1j0ZnV6ѡ[̘5#;ܰN"x(RWV%6Jr>9iPRA ߮ ]=""w%F ffs1J6J״4Ul- v)][DD-%y,b8DM M5|$tmy"uIYCy" ʼ>'rl-QJkKXA"Ze2J("Ou>%3)uZcևSob@FP'1ш\Rl EH-ժǍ2gzrG$c<[_o$Q ֵH]}XcipA)y&ynHBws<&OA+YY^b^b[`%zyx{ o.#ymgZK{{ѓh=1=G-vL <@zvMoCFgD.X+M` (1I- RQ~y^e.fsOr=s9j+|(vwV `qH)6!fİΎW!Ma_<ݦh-\B%,$'-k(]^ӻ^߿;ЧϿs:/N?ˇ|?}?yGH=|㷏{z] GbԞzѶBGo?>w}/W/cb[GۺuOA{!i~?_Vc|/W?t^w~m#˯_W?G?t?WZ}~xi~߯kO//=W??2~?Z2 >p_Ӧ~O?e;9O%>_|XK?O߿9ҷ֮HgvO?~՛/۟/~^95 o_?<_?wᝥTy>?ϟ?޿y뛗ǛWoߟNgϿ?_yyJՋu+Q~}ū7QcdnI9ǯߟ>] _=~ݑŗ+:xeW(#ͣO%xx ?3I5V[thͼ>SRCה -Q^zY@`~U?^=o-ˇ??Į9 oE>n!^ًޯ"#/UU87B'VqA;7'VB߽߽|?gP/%^~x_1|ڗp.fw_w"oŻS~sjzI?{ptU_AcCs>zW_f%$V"gJ;Sx`?I7^?{!d\r@:\ߌOB%6Sgm҈OLeѡ ]Su6WqMXp[;]nl=Rv]a°VYZ/&yS5ۜS9=ޫ`eHm-,ܖRLMvc̶JQ,^x.Id`bzV׬(YP\5+Z~SEkafAUPgwt-XzSKk&@ @׵嵛+A ↋.n.njzunX!I ,(5&(\KR0cXvbM^iTIqڼta&[Cv./SVWkw+UڪU2Xs]KeY^&ɾ,X1cep/.VRpSWS7uZXZ2h>- ܥuި.v}.}UjLgh-/wܦ+aֲ5H: L'.Y5}toN(宓4=r_[(k%Pfjzr n3 t@=x3jZ*v&rt@)wL+P鄚^MBMV.V.ڴ ?G+Pӽ챝f;MxcSo2UlRMJ!6Jq MGQV 7xleGR V 7$wXuw Ҽ9 67(A&%xbT(Q{X5UV5Bjj5UV57X5U͋V5CjN(R9T(F)jV_==%@QU 6JNnz^JQjsJm2SF5 V *'{loURU 6Jv{UܣĖ[`ToURSJ[`ӼU 6*FV%(z&:S@%P]OK1rc`7\,bR R\blRV5*(5 6Jv o#>NcYoR.o7BI]L'f]5=Z)Pҫ7 .ݕʭo'%N?EQ5۪_TdԮ1r[y@,Թjg =VZi;:\/!%O3 GHzjXTF{7NNQ-l@[UyE5Mhp# Қl2V֫ 0m& Oi 0L4mL]G^mj*|Znpa E뾸 4 ٨3ђPzjưԑl2&x&Q7~Un3E" < ԝ/p7 %n 9hS7>UTb Sp<_H}luTr9 wlN(,^vwG=bW`';m=JaLJnSpMԾ`V]WOup`Bi`;yeAnߊj' ekvO=>;%w2T['į2DzáKY!) ,Ҧ|46ˎeCMb Sa@gЙ1aiKjh6G=fX2/9z0 FlU9(M_隂x6jT(yVJӃHIPNmA^B:GZ@j -mlǼC<\.!ŖL 0B>9QB<.UT^1TƯa5l;t0LY! <+j \B}{M xۚ(ccԐݏ 84^:>@с sc_bƖΕ}pQ+#&%j>UϒmyScG: ySQUXr8?x5 `LrTeK d09W׼"dgg~ UE%@d anLa5˛c0L%P\2 b'3i<蒥Y.C5#\]޻vj+'z ܔ!c~w W>0ٺv$Q*aվ9mf snOf-(2NZwBJ٧XAT{ItLyc4sx'Z:Ֆa_{a1~B VzC}ԌaMF ; t}yDcJ&QmL1lIg~5jqjʝQȐE:C3hu3\F_a@a'X0Qc,[P4|C&S6p,o^ZTfVU.W!J*܌aX{v,}ٯ:z.p{d SȀVlk XZ7\ì^VT!U'ZHNjߪN`YI6Xڊ k1]&Z{fVc:iױN1LyZ\LLBk6`oYX:05id-Xk]Y|f:;yy N o]:ɫRӚLޝgM̓`) < vJV{wZիZz wY: 6n'.!)z;V#Bs 5e:ʡEQ{w2zWCv(SXJqJth]669q-Se#XY.6Pfe #FV>e;PJ߁vdFёbB2зt&ZI^,&cso<MˢAp:Ж! ={=_Q0g<͟Ã*@m} gX,ZΤv oOz^zw\+!jVew2s(K4-k2k/bZӒ[1oj cӬ yh }}060fLK5cX|Z)joAs}ks]s"or!GMvh"_,FAS_Lq 9>nyN=HjARqqȾŊ5>5x"=]ۓ#k|G76Ef:eX%'EQaT f敘֮lҭ\+KT5Rb9s{nN#8Vlކ5aRq,N\] Vͭ̑& !mW`wCw3/yܒ9C>i' rɜܝ/ϔ#:oDBt mZ+Ե[:3``/e`(%KU[|XK^&k\='PgO麩W7hG3ޠ}&+o~HF*4veڰzjeRG,fPLAƲtvgɮJ4VnK|su$<$uZn.aD? ժ1]@z (SaaYiHcr(- #7br[Z}v'kF~ou:`ϰ*{s u[=ԑ3)\>c+Ҏonhl^强jǴ“y3*~vg#`QSernQ|sq$^q-V-%8־:Q Y[kg. Zqe{@n093@W5)lƀ4aR؉0; F6?]d{iK١:$]_tk+b:M&*. gU $믢u bƕJ+Ա zK*PM'ӳ6Hw.jTg\MTZxSԮlklBt wc7uC Kq (7,+MDIui iA+yPx%iC;i݉Eo^Z*챌K@fs,pDxZ5Ne*l!V}3oVk{Aݗ$"Nd@%3Mji8JN1ĝ}u!Ϲ~QBUPVt U;G ٲ奎BrݒvmhQ7סUpNo:iJjmA]K+;;y]9}B,Mҳ̢y l *_55/xQp!3qO#tk')zNfíĨ`A$@^o,'S @u?%]7^ ki%3+ |퓼xyCZ0EMܰK:_޲Հz!NRsLi% Ж/ۭWX[ y(F -ԟ_%؟kyxfkg;aY|棛.T_ݝ*֊Q3d:4o'X}RەT][b)ihWKU徳shdc 4^7!HA/"| fˋ{d^_k+gT; C 2$fh y[ k}hhFk}$Pv$zlV)[w-[FzdJe40eƣj8,Γ5e_D z n9X5XП@-#=6[bm^{e z껽10$#lx zwnga?QL646{=w;Ncmي"Bɰ769x0ԋ*G)h>#7aH@pYCi2~H:?ˆuE!.L;ķA@@(Uܫ̒tQqi6ڲ\R%g\T8.1]M0r Z :N8v]41:Nx'}J@H= ߆څUC&ٛsk6UּXü5b({ՆgvB35ls,Nk?7\z"JcKˡJ)qRKA耺Ɏ:Z/y,xjT%I <ƩX6lhmHNJBW'@ޭZB_v*,3Хq`q'(:%H}ض/e':Ӌ ZK_GKzr ^c,̡r PD%5=(=px ӧm]FɩJ' ?5VoBR ŊB%5 q3qcΣ~w-dnq]$%7̧k"t䂦:CS.bňN2R؊AɘcҲ`4%.)"]+n(m‡ :)v`1JTGp<:bnn8lmQJgCpB/LyE9i/>vcS;yU * `Rf_ϯ;P(B-6殤큲 skvx \F Wadz*rVJ)U;E:IKhv둧GfՊ87tу_+(| 9ړST{8@{p.hBi%RVw/NzH{9F)rk0/(#Pƅn5W)[\{Р_Pjj7H\fOAXJJWYC<)<#y.*WfLrl/8b)2w-Kэ/M^f˴9 COn:E:G݃){q:s} `q)ZB)A12OBpc4FlB <3t/J}ԧE zLU0:,;P'N+FT{BhHÒ Uؓ9ͺfb4;5`ǐ0҅ c܊fy dke^IA`L?bY#=G pЯ[WSOK39H\~tK86JVe֊+HӜpVak՘[A&m]dZ-t6]xxܝH<-y^ 2`ZGB:S?;>-l>3h͍p{c/Q(ldd hJD#dpQH)֤ MK=(Z|¶30M`+g'qogU Xeʈ4Y#zKkf{Z1.‰pRI% IڎK:a햶Axj"XgAז$ iRPhJ~z Ya#njcB?|E:w`y|`9NKr@6mfYrz*&:u"뎴r5ꉀy¼yd{ 6[-u?VtP=sӟK@@G_p=Sӄ\@ 7ܜkkL+iLJ{Mϑ`Skzr+Sv*yr^evj,)Z2FYfO•|ӟXY- 1ikG+Xb'>ί_f؉ Mkӕ;ļJ(JqA]ZSY}#rb'҅gf!`KjAgĦ&>es35G 9j} :wH -m,(I6 #)+l唝izi͉DmRLj R%w=<] u敺kow]m]J[]F19p X '.km]!RӖwNK./6uU|N̛uG9mb݈ ܤ+dmA)KpP.A,Gʁ-rF A_(2+>9G#Ԯ*Uff\mS+Y8<4bP4wgɳN0]Ȼ*p`R2m)z u %졄=P.سݪǴDžb׺b >3;*ި5i}մ3C +ԵhAZF6e|q Ml2>];ٯҟ1t~(byA.Tk.B 'ĩss RTEEbEICŹ1UqH>qSʹ`b\<y6?Vng E4n %{{-* ڴNA Ѩx1dzBV@uayкw|Fy5ʇyG+8D=d@T2\IAj RRY4?e5]!s t`qP(<*;ӮjЮ|igFsrΰNFeXw8\i^5ыA>|j$:|1߬og)#'){'t5HuP=sгZ>% :DJ*WyJ$kJܲWm3 So㷁ﲟc;FiÍh‡'Chz%@}R%Abq(=R|Eݚk:m[cBlv֙ȉ>5oQ6 WX4l侳Pr %P2yXrJnW%+vӻ^߿;ЧϿs:/N?/>Wo_߿ۿF+9>zo2VwRQ*ǓgԞzѶҤg~ݡQc㫯Kjx[*DŽt:?Dx$)?߇߯1>Ү,~t^w~m#˯_W?G??WZ}~xi~߯[}~?ڿ?_?գ?~x~~?O~W?{m_,p7/_G;絎yPǯWӿx|#?>>*ޜGG?57/b}k~xO?7?/?_ z=\`%JگxOݿ?J?-)7_ۇ+__?;=<߾re 4WQ￲̟} B|$y~__|o_ݿwg{__r߼ze9 to/N{!ɟ{_J/߽x~%@c//)]D"w$ +<g؇|~篾~JIxGo_D w?w<"o>~C'Woɸ(?u`y;yl角ڪʐCg >;Jw!.#eOd;+\v=pv }*ܳfN՘sh1]f[C 95 oXtΥ5;PmXY2]\3v2YQ\f1kV69P+\pRt،Z[W:JTMLmU*Xu2e B<{>f܍ee0ԊB: "n jf3%%áfCݲ]n<<:C_K_լZ6S٩k9)@(Fl#a: k1Jz[g0P]5=r{A[($Pfjzr h*Z.zf~#WʅdRV.c=: 5ޭ\BM߭\B)wiI'~,+Pӽ챝`;NxcSo2ܝ2B%!b׀(t`ՠxy7 FnQ{X)՛f;6ĖQzӺJiޜ`ՠylyQ VJnQ{(=JЪEUVx6JЪECЪEU͋V5{X)8R(F)jV_==%@QU 6JN 9ylڜR[䔑"ew UJު[`oUbՠ4(V%X)[`씒#ĪAV%X4oUJQU 6ʼ민T0e #1>-ʺN)F9L0 RJ!6*Հ(5 6+eUR\bd׀(?,Ble˫`.eFQֽJIў5((5 6J:%6JrO7MFV%(hI݆@V%X)[`{F䔒"es flUxh[SFi%Rk@loUђ=N[`xxW Q{(FV%X)kbt׀(ުe]-+VU.ZU \*\=F٢GtR5 6JhUUЪEZS]lQZUhUkJ%tѪRhUURRݣFɮPvoT{lS7=Z{lO7=&%jz77j7L-flEMP 5[ h3zr{l;ݛN-g)K%}K:7-9׊ H^VpAנVnx;)p5(s%+y:rTѾ3Rhō}) $zqЮG#u1 ]x7u0j"j:rZPn| *imB1ЎQTNgk65GMKy lb (uD_az϶z%L_Un ӏ`aMT8D6z|k>7h p*l]NVX1Ϣ]Rn R&d}Ε=#p{ƽp7 oUeu`.g(7MhhHáѴgF *Lfۇ Ók:< "M$S%6PPIőP>%dg!k9IaAibغUP*M[y.Rt`iٳRZu0hܳڧt:"C將2ADfcv<FVo(z}u偘S0ST|gc]npa E뾸 4 ٨3ђPzjưԑl2&x&Q'5~Un3E" <2 T9'B<.UT^>`_j p# a"Qh\U3M kJ-D+~d1Rd:C6t쳄Cf^1/yW;P0zl˛"m>:W^zzTyP.'&Y.,Ilɔ f36-Q̰0c[؟Q f,4SXl&) ,87Sg} %?: L@diPccʉ7eȘ.u@W>0ٺv$Q*aվ9mf snOf-(2NZwBJ٧X5TkQ\4kID 7F3'wSmQGcX'T`7 Ѡ! ) vVZ1UƔL: b wc4 c7ujʝQȐE:C3hu3VXГi ,٨m-( ey1Uu@N.# -[}Vj@u8@ 7c&w'UWBע+TɐF><䶴vlW3"Ev|kv} i6ܗ%Yxܺd{Ш/ags%?7~DB+(!7۟:R}87 Z̀OjdM\}E|Hn5Md2ݨP[0H& s&E,,NڬVm2ld Z--"L`5jpϴzYQ_tV!8h!9Q~:e!'<`Mj+:/w>f ,Ɛv8ph퉚ywX]B; s3u}hPpM2qP3 وKfM>~ZM'() h;5i]i}evDIiMuwz.@K 3Rpw$*$X耼-l&QѴެ` .kY3` ^w uMa5{TKלQ=fiX}䮸DZ<Xn^L5P[7Byn:pr\dgn{ nYֻ_NYy^?D5k+ueԭ׳.ܟ.֖/M٭)٭xt`\E~c^ zZM(Vv }Xlfmkq"z'e(SŻPgNRtC;^JZ`_`X@9^1ƈZ㖝Mר̓`) E\b3V(+5VuEtS~+ϊ(>. 5V~LVǧ mM,Vk,<{SxZP8Z?,I S;1͛~Yuȗu|{1nMgtV|'w} c3/nL#;=ë*ϵ `z*},,=?n.;%ڝ,stlt25_ig^ C:vXs?=k~gjQ7ow`uҧ~|d|Fcw\\^qiγʕ:ML9Z4q;ŸȭG|ś)yO]*NquK3Ez7G xkŭweطHrO7;m{O"UO$ĵCG+ʵzY rZϴZ/4lGKkf4uTY> b jͽL "N챉*o몤.Y_eaN[#cF__eiO۰g5[B|x&><3AY":4Zȶ|WT ƀ$F! 5Vΐٖv37ŠKI됂l:*4ͤIIu ƀM1cPi6pHaSVt.-k bLDjwBaj}ɫ lfC]IxZ 3%/\^7D6ƚsZqc$W^)KѧP:ΣiAilP(_,wHQuՐvL?^7}dj SVd[lpYx U'! ):),-Ch撓AuW▩lɺ7ed Cm3EYp !bd@5;w[)p8BjdW4 (n4Vx lH v*X5|@5yEX04kӸ).8UrK+; _:rw癪ɉ/ά U#g\6{! "$/^09œC7_H??:_hj*ՆqnJUyI .͈m^TI;<OJHI/W8SJ=؜ި΀o^#/6MJ8I4)՛zSk6]V۰e]}nPgҝ`$զn_ 9ZѮr`ϔq{晫C$뿸R`k*Xԥ7ԭ:p0MdiZ=h'Ǣ; H/Gp&ژi)Ek9mqJE1>^O7ZuvZ-hRA-蝃ޡ0R$`Tܮ X349ts`(3.66LQPOYGG<>`T".V=}z gvTor=+3x%?֓|f a>aO:39|gJץ1If +L.TB۰\ ȹF^]-I߈tQk):rptv{!^\4/)' ( EZ#!=V!YAx7|0BsBvl`N,Di6.\Azy=$i*@I)ɋ=b3 yv{wj¡ʠEvlo|*3L/];ZEr+=\29Vg l1U4V1; #zk6*L1$[.]Ǥm6Fa0Rm} E;-I! ٟ(D -(Zd w7pj t@dypQ<k[P^Ųaw审Y dwֻ?κ[5ڳ)fT.;<@aܘ.VnU43=+t匪un+=nޭ\QݘC[1Kٕ*}~$>} :D{J<+ ڐHn)6н7*f2pX-cPI.oH4(YklOOaWq/"-UU lwT': VJNla:3)ݎ}ؽcL%C.6ܙn\eu-Q8R`reuh4cԮZaa5 JRJzYX&Պ4 \!2ʌI5ȯfvE#řR(e4MzeL5q3%pj^V@ȧxwe.(_PzK".>'RzPS/c{VGxP)ts|xf$KJ+9I)C +EV@2iE`p5{(CJV:SѼSnNūTU.vc)93:j]LlTz2g7+~iyv'܎+8^`!uLm!cwC{.ŽC|eKV fe83/oL|p& Xk=%r'鉌 4N=fdlM2 1`'I.9t#a#݌2#|JٴH[ώ< iURp^x au8`ǤRl)e#jἢAxxl.s aZԠEZE}B ړ]豌f?M,$pg0f_J&>>#%doo7 E^5&QFPDJ.(=Pr `vml7A~i6BB"7[o#eVX?JoA6 \5hN ]z@`w{f2rdޜk>Ņ5ml5p дە?´YzpPZ쑒!B::NWs3J{,L@_d{`Ԑ (X/vA y0)RRq  EubDf8-td' {~1J `2R@M$]S81  >O26|w;y%6Gn$WoOLѼN,oCз8i?ϢO ;5<0ok֭X<K.Jf7pJCQx x5R)$[qJW :/Ѣ3jS[r5Ipg=;ΧjݵpzU›#[B:fZǛ\<165 oSU.d\,qeܴUoѧx9cX%.FY$lSB*̋Ӣ7B^^1q^֙[^B:%^AaoC7z+Sf;@ZT /4 GU>XAiB?Qt6/zwmmO6΋g<G *溂jsUDM!EKh[(aBp\a:-|waEqYauiSu%Pk^Ntnr܏D꒒T]B-=9CD_o JAN^Xh)/l"l:hU| opGX!N|y5{}Q'#iNaqensIxmxqGTjrb/3q EcҴ lg{mv*bc(+;+ vjk%4AiUi7 ;A&<'7UZҤrk߮&[Ԍ/"k$=ESLj 1:mCn ̴_jhj(=ro6( MlӪj$Y Yy=QDoYeeOh-⃫?PT#jVt 諾0Ybg^"P 7s-V(6νs'!RK%u0ɥ߸~F*K^iMOKWH3*ᅦ>^KWCj+)+ ͷ}6H >}\KV.I\F1ĵkU|g05 kSRt]]/̅{m(9ito,3"H;EMErdX{ʼn`BOOA@%L~ɥYNrtJ2Iz(j($f`zTݺkƵl<'qQa뮊WbWITԍ9fbd3 41ɁJmW1{ir'9E++<\JjEqJ3ejT$b[:p&[ouZ޴JUWQ )SU|vfUI%Hκ*r.>5QKj~ZiAM`t2+N,kѼɉT2I-HjAM^N0J |@t|SjX&Ja8X ڕd,Vxo:\'xIuhZ=+U}LsY=Q]%9hnNJ@X!ěV~]6qv YХi Peִ3x&d1bxn2r6p!@eVP\Q0t~k@ZCtͭ~ve۫W>0HyCƊRw☲nmH$5+yC[ k褋 yj}brïnPo V)+]MƗr[Қ} M z!jBzeKFQQvdO"N蓎ԓ慯t()쪡Cj@<>.4]}$(2VE| LƴށMkQ`uJW=›}!]>Cd9ߔ~8h/Bj(!r(zwZd9]pإشC8\FE"ۆc6bnG%eL$6I9HbnB>녆VuXz] H.iWjڃvٯJW:i - [@$`W4CZ Qu6(ShՑBDj%H$ I(^ug=TkycM>Bu%""bJ#Jxԕ5+Ej%H$ ];az_!VNN,q vP9O^F>;?(st]~3 B )=.,|S-FEԱ'b݃غM5G4'[@U̠v͉#rԲVv=YD]swo(+>!foYyU;mRua}=B:6帇Տ)hM;{ |` h_~Q~Qxwo~I0"$w )R+#°7Skl6J{Ai9t)ī!=! :5%ʳ>ZnG]Zef({Q{Z#O^R {,ɜ |D[5F3se&o(x<ǝ!Guf[fų縳9W9lۥ q3-μ]|-aI9 r[oS%o;Cޫk-YWo_߿ۿF+9>zo2VwRѺmIh[g~ݡQW_rj9^>HCOO}1+'{x7Mmk^~'/>G~2O;<~~x?<Ͽ<ٚ _~~*~z}~xi~{[ۿ??T׏/^?便PcS=ߏӧ^>Go> ~~Wooryks'~A߾~xϞs~ɫVWoN ^?<ܒr:}Q_?}x/~{?}#]s/W/J!yu+wP /G›Gw7=J~{fʓj[)y}_Y?/ g%ϯ)A4[L.>?ʽ}݋W 4_~}BRrz_xxND-xJ¯`nQ _߿x\9Iwj+}}zWo^{׬ěw1zA>Ws 3'b? #o8d}_~[^Y 3ilφ~*Xɚ ?9:T:vJpS9*$ '#D{y[n°<+" XpS5ۜSMH\E4%eH Z!KY-}@Υ5;PmXY2]\3v2YQ\f1kV69P+\p<;8lM%T&)e6nnnFR_/↋.nv=kRW bK+5b+O&^¤֎WjQNZeSuҮ&5 k^Ѝ& Rf ݺBU:Z]ݭljTfjV`u~"/ @ ,kQ½ZQZ^WsMĒ^MެvUõd8l}[TKߍ Q \w \fղNemX{ιMWet@9۟NkjZ,递KJN(宣4=rE[(;K$Pfjzr n6 mVt@a3jZ+通J:;K(XtBM?w+Pw+P]mZ ;Kz ~ۇKNN Epi*Θ`l5O$(!6t+z3ToH-ONN+ysloPUMJF%؎nQ{(=JЪEUVq7JЪE±bB!V fhUUЪE=Ju,b׀X5C/ZZ[Uޒi (ު7=j/NكGsV%(9H)#E[`͓U 6*J)ު%=ĪAiQbJR*F))%GJs UJiު[`xly=Q _ymT0e #1w+(:F6aQV QWF)Q6׀X)Bl%F9VjJ!6Ju {V RVQ 2\bT׀(i:%E{bt׀((=J, iBloUm oU2U 6JNi#RJrJI3*sAcuHcǗ9k[(L3]5T\}dzB@8g!"JGg?@1][57#l:̸6Շab k+uDl|yGu(2TmcfmWPd¤ QL5k}c~2nkeAоaF'vlN@F| 31`\VT܀H#u25~eϕ(Tu\5VuQYny u^7;]7QcZ/bUMvNi'nK򚇶 wJz0sFIfóPhrs0f(\*u^u::,8lܥH9M tu΀6clw10T24U1Vs) L0DgOm  @>H =u!9I ⠑1Qʈ03t.ٸnusjRaM7*V4SG`߭umXbѱ6B2Xv(5F0ؑd$DXf :3;v+C983f91doo0)Ĝ4Fi rf2gE? ZeA w# £$caXΪdg+ dv!$d[‚a˪r5rH^sC$7p$˩>9iq1W^Nf8Bn8{L P̌d3F3m/A/(~w@@h*d'r*iUljSf;5ۑHG/B]TER9mu،}զ;`٩;P͊Qu#i8sPpbT4a Rh"&X2mM#PwuuX8;;Ne['O|A S1Z&E??AX52N p"}Z8X9&c&"d B+00@'ЕǛӚ/thWpFdFNgWM׷Fhy6ZTbr1;>2fWKmI!&mw6t)})cJ 14 r2t0&!MGƤ6c\n).bRoAn1)L:!fc͡zf9Fqd1(1&oWk,f ҁ5dٶSp.ru騽`w=&b :YǬdtV 7n*^J"hH'W6N3uEZUS:W0dlk mV62/݂I p=]쭠jrp~~Bh"~u#hYxwȗpαG:0l@8p-1 됆 oB8GZ@j<.mX,>kqqӠ;srQMJB Lb"Al]xU43=K6O[p3ĤhF@XF;K!MɌ|~\'d;<ڃmH(W< `V%|%3 d0[es޴]̆gF 3 g*,b$eʿyg 7#;+Jfwcg C`RFJ5YyP$\rF8;Ǝw:9ڕ =]J1 | ɪ~INVQFb.w#8V,Xx"Ι% L[ƃ{A{h!CSp)C(e6udFh@FMNnۡuiTz#McrA! ) lnš+c2 +{)AƙV8GWWB|!Z4(^b_m5+ܴX0dƾYjNj^^!!.2WLP } Wni TɲȳlMCBTaXUzfwl݋2w>\7,]b~Q <}^LQPEsd,R+&$%<}&Y PT&W %9dXgMOv^GnAvppzJ{sj4gjNhR>Jk= #&sm tZEls#CՄAP>0r3nt^.9u@8i^}nQdșL6Jf7#3WV! o( -$']ene!<.]. 6m=a3wu,DfXpލ7m^ ޒ,mD$`ߍ].?ѿq 1;NWlv6t u`aVJxKtMBCgۆ<;}9N3ttX{ser*:^jC_]%+e+ c%;XbZ[n'.TRSyX?BcBk"(МӦj'(m ӊ%~Ѐ7IO<)[ޓțߤ\%J}RR054.@,C2}[S̖cL]?&Xcտ:d[{,ݥ [iZb~wǴ9CYWo 1\i툋8s㵀:ɡVb;rw ㅂ{׺&\zrB|#>|<7`dmmA=myPۂ|,Wj9 ^B)vo{5cBӼ7ԡyOg̡,FެHWZ`Y&#ym58>Nymz2,"N8,kC>6Ga0Œk#F#0Ga0a9seQGai9G/h}!΋Uz=K|C ˦A6=9l is3( 4)ʦ { 8h l7@Mq$\E({Iۀ$E"p$)nްY&gXiv`J@~Qi=T2biΏbB5VkÎHJxh'XiɭS\J}Jxhֱ\ X鯱]2P\AZOdO(@0()ak꼘^WI*bh)o[TBqBn*)|<=eOB›S"US8=q>6z5.4g>xb9%z(ifݛe/y&iKJsۙX*: %m|'h"bZy o(Kq *ۈ݀N8<9O,c<0c6Q7UܝZxxQUO{ FC%Lm꙾\6ƚVpa/ P{F8S:#PDJڢ'O}0_]n- {uש몃Ld8b"isq*.BvrÕ^u7"pu|,~cؗtv .OFmyдrois35u]5CN;p:Q{m!͐oN.GL FǓGr^pay5NzXcv8PIy5k++Ł~mZ^$?4M;ߓ&Q\jO*<3ڣR{4WH+{m)Oќv,dꟶ;1քeQ\-9~/vYt8t ^D}i" ˸9 N#Hh_II/QzffFًH^|jJ/?29e"zse/JzQK=qv"4ofTҋS;Nn2^d4*D֛d ~0 Wԭ#~6xп[Í\rѤ8 i\{oi`ۺDxoV1bXU,aOZl~:亜GǒNUeHyfL 'GKQ  o yt%QfR2a!uR^k eڡ,$ZN\nf)|*~gl &'pf;(!`xeE4O i_544eMhxy">Gp\Nު\YGPpK!CX$$y.ҝ;oEׅ?3?L.ՐVa0Aq ?9c rb/!E(=K2b4ۊGFt~[WKb;<^BPoU-|s0#T+¡LD1\-fcxf$.{an"a!p=#^ښ7v$ɩ4\xjibQ~<Ė8iP^`1ħ.2l+h64awYL%%(4# ;- (UƱc5.α3Ilv[{QVnuEP4o^K"4bb\ %U[kJ-St8VELV|sH ^6 ƶ{}4cb1idenv7pT@'*I289܉r'l}G-G~W)(,SXͷ#暵 Mj~/C1u7}2vb 2Ftf1xlN4|e|p\wUJD`JS!Ʀ43w"3,)80=h+h٩9l$S!cx[@C^ob8+ ?^=Tŏ_Ĉ\2$=G'>"=PjB^UԶZ 8WImҤ*`"Ɛ6a1FeŢ=E7\ާWTo7!BH֭AwmIBOݡKxWռ nv A&^{{t COP`a[7MΛ~hbJ\zy Kbk(Y)EJaIRG/ iaJgIZ2 (B";0JrUw{VD Nڃr*p鶫bXMm*q˚oW/϶ZZi6k6{V+vٹg_{|x]Nzeh"M9^vJvPB9Hbk^vZ@}kg:+wicW(\_qݾ'yWq/ h66*C{ xE sh˵\֜-ť4 k:pnI4ឤ{ i.X.B>!W:^aVCF*̋VW֢nP =0:nq9* +L \-[ry < C33i+GcU@ЙLn P;OG/$NMvHm'4wGׇ;1u7;< 'uꎗZ m脗eNkΚC\UDR$Ϯ ˥jƲ+*~i 8~p>a7xs,‡ѣίd=j>4ܣ*\`<;LW *_BZzZ`4Q#yÑw-N$3po&K@#&5SFE(+gU>O&H=h x5AB]7?2#YomJs LVoȻ`9 Sހa6RsOTY38{@:-09ˬ#x42m9%%W[Rڢ8аWVЇ9pN[L7LIKx JV/^/VZJ8m}T^\b{qip/m: WEV\b[uqU+-yKsRȩɉd(9sݗz~n?o+?ZKK٣FϮʧ{1o|㭵k9n{&VCו'߾7lWoWoW0u4O#{}p[˧i;xg~y/.?_~>}Mͤ/2~?ni|?-z5 g?~??{K4O}׿%_I~wˁ{/}?ӷ~_S%нxW?>mT9AgAOi}`~C4W}_.!?_7_EaD}(u -?߇_~[k}>ڿ?{g?DZ'i=?'%ne?,gC|?p"ھ~^~?ڍ}$~~x>?,g  G?Z+iݝ{g}ߧO߇Tn_(ؔw?~i44i>8in˧{/_ f?;Gg_\iWO:\;o}iO߃8|_i{Qo?^~?_*?=_翟O8]i>~/?˯՛O 4??7?n&=ߧO7h_oI{=j_|oZ>~~?ߣޯsK[k+o˿On_{}nzk} Ǧ_~˿o~yo>{[ ۯ/;A޽^PoWo~ݲ'?gysn7?_~#P~_~o}Yˏ|/ZBlwoF_s|qwg/_4o~/G/J!xuw7|% Dq 4䯏|4~< 6V&jGҟ~II0"-$+i~A~u6+7'!dW_~ͦ\/߽y736 /߽/b6fd_47_lGʷ)-77_KyY }}u~?g_G/|/2Ԋ)YRF"Gm|Wo[QtG)3g~.?w߾߯dRϿzݛt:Ͽ/[ \~o.go}}J*rw#7N$]~CP/_~ś^~؈7RZ_~zty?}D@o2_$μ?_} g9᧋nZ^/˾})X:bT>?ԁOrQ;ץKN pBWڧ|,|%|Y 5||%!=Y>^BC!^-PB>m|5<[>,BoOtϧ~U 9OXGoX <[n2#N4ܑC9sGmRx=4U3r\UessDYjf,"pAJpx>:٩R(.79cfrbCN`u9̀ZG2keȸ7@k Vе A>(BS PpNNޜC僂QH5 ʙBݷKJ Gz^@=~q;C$|@V@ks=|7c3c=|-7@ Kok /] G[Gpyt?&K a7C`d'V]FLdR("Ŷy@]쀣iw71ꍜW -[XflÆP6 Ǧ kow&$(qѠhQf=V-[C w#(왂hKڍzf@ FB7O6jXksh-i͊;g̙]u^ a4euaz>< %,B5Zkk>ڍPgkϴZJxlzXz;m3+$fS2)]m1&'Y'B&+2 i\'n+-vVuVK)YD$iBͱNJ^mqNJ,\ vdƢAd:I`u2Yt(.79sLXRII b뤴:)mNXoIg 8mu(2;NJ.:I`uÓʙ$]$q$=KWH@q}dˣWG8ȖF=laȖE=tQ45-z\ق-z\ bP+![u_q8]ʋ"P&gѱv[ "[jv]Ґ R5gYMW=D#+tsN޲b]s!-vnAiA𪋘fLx YԮKtSw]bhQCnK Cbr!t]3xn).jT&\ V4ȥm3j¹% >.lSs屄 ~,syJ:@>,HAY]"t(m(.A?dHX9Xq\26Uk5 p̝q\U\)0}S8J?*Xqr\Q`p|6{ɳBP6.OVXz./sR,zD#"I\K\Xނeñ(p0|]\K\RuVA!0E>'-R1>E4]̑QvzlI}H!@.pEesj &hΪS|WbvVsc,2}lpDpA>;N*OAhpSW+9JLtȓ.G˟2XںQYsva}p\x7(SK mMi]ʝ()#գe>DStN9cPYkAy4.?G=%ii(GSR+J"‰+ (1l6I0.WuVbn .1vK8Fg:ZqƔU,ؓ'5Go󮈵tV&J ._ ]%T` rܲtXO'FX%bƕBnk,D{rFp(w|2eנM>cbÚ: gZ^G%?˪(vc Խ)~j+<+Ij(%=7a %ḙ5mPFLvg33׀0찙 E [7y?.=clcۚ@Wr?c=\f#k92cՎf'#'HvO&42EpGS8Y5&5"nmiv9b=2mş9Rj~CGGLsْ3n.e֚nU1I ێp/wJq'`$[}DzvDltqi6ggOŒ"- ?#3RC۔'8WorPB9x?x4xG>-=ϧ8WXYA mPMndZC,Y1lb8' =\`NS`!aF/Y;ҰFLKgK^V1 nćisF}K1!I"o<y9:.2+4S[=zDZrykt=٠G}PX*^@sInOPhR*w\FiC Y(ObIuHN儠q͝u4BI8GONNo3&L.\l-p^z-/RzZ*iz7t-@ae3ޭ=τfOvm ,* xS%=fiY<(:ϯK.Fe bWKBjQ/"P |Z9%[".f8bDC.R[mFj,dIŤj#FUsSV[\ !A+b]B%hp Es=Bj0Qf6N0FZey6b<Ț"s;RAPCG$REPGmک3D JCZ-J-NPu%3tm|>yMFN2 nN)r6QѥJ(Ww϶\u}yпqjZ(ԅ4Q#*{܊ /4}b1dX_}J Kn^)=h"ET~z{Wuzb0A 5~D9gx_-\:~ dptm!{?ҷϾ ep&|x!m~~*־j@aX2tL'`qij0Y>ZV'8){UEa#m2#g/NT0 ]CI]ҩ&D< 7h Xjy$;P! e ˬ:C!ֻbRHw&2mkC#sQ"с*NԥNPa͗i\_> {ciN'{->\k&=WU{^ϏqFgΗI߮8OO 9|Lx>]\nrr7J8o\Q`=5FNg۵PWEJJ\نh1l6CA?Ã18Y:>jq99zh{8չHY)ԓ0b&̤q%YVyU>;7%(b5ah O3&!kh.QӄZJJM nq] c*4xJ#wU89$y.ʪԕJcTԼQJbL9T;9MbcNK]Ӡ"%si" Rz@}%E?GF"+UxNM1rƯO\ `Tr*S#`9jkndg|I.9j.#` Txܨ:bJTa sS1<×r1y KQo^}E>jvH7XM 6IrH\l*rfJ[p4Q|WXڦgƲ;-@ƱՉxE jGP?F2鎡Vv8 qgc>hK*8b/-h\ g<&{C,g]~A} G'.گSf%n'u01`i'i)%KY~oa2ITZFj m-gY7/vE3z]oeJ#~KpSAy+ӊ%J\Tǹk̲&`,`Q|^XfG|݆*Ns$SB֚f^W3`18*<,|B$h#G_!3R̍ )7ILrvy%1福%yn{ykf*6I=ִ͊Qnm[+.fP$dZkJprL B-esl$p>q쮸i<} r4^.u'[z VBEG dĂZ]ĢՕ:u9`>!XN249hb+6jE)ޭqtvy+[ .oɑvC>+vM[qzRk-qfj;Tzѩ'.;=~ԀUOjWLK-6ä]C;=q p,eQ#oc>vBYkxF+޻9Ӯ[Tz^=yuyqH\NSAϫSOpnUBZn=i%4=,3ϊWߒ\o&2^L#Sb"ă+=~c ocn\0fKqBΗ4ͮ}ynv(Θ1=^O1G툹U"11ZLr{[=zZe6 rұ:b1ջIëvQ7m׀{2n/RGZy ?k01SSUf90vKn(M(*y*GrAwQ6 Ǽ6+ȩ:dȲ@CF嵠 ecxuwQK0XI>mݽmS G5K :hBYgg]Ǖ|Rh$t(&cP%ROJxYtGCIBَk>TtF#ݮHi2^q4K2C퉧.q}ɸutj4IVn)lQ&H<Ⱬ$;\ZcxLR{ Ԫ]DI9^f b'.`*֠U6*:ywْ7Π9rgPɟ*YەdTQ-lG*+ %ReNFfpc^ o e+*7s<$Rygҝ,IJ^^秫lS= /S|zcu+oFC=,Wꃯ aXĀe72ܷ OW3Yzvi{ c9sӘsx*0Wov<28K'~T([j,;U!jlI(=< )ҏt]1.hx6fOgՠ鰫C+L1Ut{JG *r cr(Glqm6|KWrvXJ6D\,nm~tno%^S{j su&̮ HÜc =y=w+8=|zpwM>>{r{!NVnT1<%X s2 t1.LHDwt疸N`NH@w|H23M!)/Qi8KԖoMQiQBnjKp0f8KE=Ɂ/ MH(Z(({=FPlIمTdI-}C ӓ$6ˌ9un3M촙Ѫ;[1T*y (8',^V[j8sD@:G\]U0~t"lZlZ7j\sF9@>,;gn:W6;FBB no+Rz9L{p$JBY$y//B%k@Ңq%'#\?Vr8n=uzg U}vQtq'Pu:G4(tGMTmT͌q{|@VgW;2jӌXӫu tAGZv". @MR .x9U؋aC׆ڗw#XI;H+rX_pջf$T0Ur, Daá-Zŀ1ٵ`M*2EKrh;{P95"Tf0‰otL@Egq%'P9Lau͙m}WNm-$VbE=XFI )xfC䵦P`]%!֚p2m5䀇% XLnyiaћ^O≼iiPDqC/%9*G-MCUWud0:% ݝhg Ѯ"C lx =+0'(k,@ |E+W\l)u)ĐVNI; }LΫؓncAbL ݇8m!_]N/WIǺry~G](g0܅x24Ep74PNJ[WeNz ]\K\XAb<8 <:.%J.@Ltu yvՇ"w<ИLl8#uS,Nכ:[JxJWXZˢSeg璪ς|X؉ QstA>Enou .1dm{w2I.D8?qJOʉ) 7e/F'@lQY e?Tk&Yㄎ$Heӥv|;\zqI;V#xT"ϸ 00/ wx67KH9WH+Ţ~gimc#Z1Dw?s8Zee߸\瓙 =`8COvszJz))r(K%*PsU ,Ծ'ȡ!Ds]$F?|q!X{d+cF VC e-yp $^ϻ@ _qUNNnfIܴКc IN .pSU&nUC?L^]8ܫTD! ¦7ƾ&E$-؄YX)pS c^E/f#Ǟ#2Aeڋ8Obh"JX_WIL>-Q-% !.e՜drpwXVRNa-B=3"x'X]gw,$Pc"MM wEW&XacAbdJ=0\u'Iu%n{`5V&LXhWX7H!P EE٤=ue$JN| s9z|B7 oI6\UægߡbWsqv "ީdk |-8;+vƂynbVƒ D -=H>Ѕq]Ie큇WI(סxu,n&]c 45.oǥajqGO]4'i߬gݜ &uE^q}钷#SSqQ|z1@,&SLAb1j1Gi1SKӧlmm'1[m?cT18#9Vs)yc襍19B6Ј09já?~srEr[{Z5\ /c}OF^Ak &ݫRFW9PqMB:5 ՐL[B`UN9@ҁCGr$Ւ; 3egW&+[E8>|!и`{  $+tX:' Pqcơ\w\@\d uFR"Y5 C,-LVaC,5A_ JGP {t/YY;#  ]1r6+9T{AWiy{!P;q/fd0dL1ri-Qa]+8KYYjNKu_q}\i!\VUs1.*72"`\VnBCZ{zhz~Ը.s#65UCLݳy |ITlW91,eRĘ1rE 2jA-3 y\Ǻz~բKr:Ix $beM*J>3Hr1Â$`2U^yXTY-e4P\r5пK(Gx6@`oEr5LV\vW s_nW_ӕw?ru.8j\g>r}Q7>jx!uq}(aZ0ױb*/:}~e-26 JM}{04 ?^neRYƏ1솞f&Sa2^W0F9SQsup&17vx1Qa(ݶdGlm2O\8=s(G@ɰϛ/q7Yֆ9aگe力Y_b(Ru6*SGޓytP^a/P&$GaԴg)ee DY.Z פR<]I 'X"(]}˄_UǪP9:s)JCoǯt.pQx2f`SXY8<<-x~4KDW0S#L=uWUxWN|$ber((E$^vfq{@x&ih?Cre>Uimw,̲ ޵Mq)fNuۖE%X&TWiDiKSqLF~o5] .N#"X$ϭyY[&r+&qlSTScL`d)pbpJ&q'c*y1D&LW'ɛ i^U\7ucʣ§;6PS +ʘmu͘=&ۅӦ4=ʓ8ƴskV.Y*cJ>w|.1thPbԴsD7r4_1uu6meܨr߀T̎Ź-qgHv+Ggph*V2—GiyT\cG⎹3%pJW\T)M¡8,V7)8=Yi&wLJ[Aɒca>OC()fq0ܴ)C`zw) u)i䃵;>eo1'˰ZNުT[|i⏭г8UIk>;85āƝsNM1ϐd7e; g {JGiكe=hZ K+B{ri٩ȚQxwjZ2)5Cyaڕ[Yp濒hdl4*zQMKGﶇåf,CoFƔ1ѱ-n7vuIBqn91=rM[,HGb1۔:+#5I9-ʠ!7}ŘKyQMu,(e'֔bm4Q d4r!BSu %ihšs:ttyjİ,n]܋~co6c]'_,ol[^Nr}wً\Rl62Ce#aE6LӿܤcNH)..+yOt%W,g.Ǹ2qM\ /s.Y1fUKG{x"0V\S&{rǯrC^]r<7OCӐwWm"ɦvx9enGhd2c MC v2^S©vjGZtvyw?ix3CKߴ#mW79j7ܞ|MS}m<0b4y[<k3͖"v 9ێ~f0,7Vl/AU&S=;͖~KJЍ䢤/s @R%SZǍ..ӧ+ҐIe ߠ{=$Gˍ869:ƺ_dt%/n7r1[7|;~]+p{ć0H3z(ԍ;s\]J =\|xWz5a(j?=S֠)fq}+TrQJǧr"R6>p;Pqv@%` 51w||@:p$ c O^XuHچҚbXbx?4 McxơzOa]bU4sf6GچG,Cٚ=j\k ଋOuqi(+rbA4 }(k l>BB78@1t]B5VR)p݄\uV>qEGQczC\G#+ uEem:>p /8v}r+BWb4 [(BZ Oe߷lcIJܑb\6Y]09&.0CC 1J}r;i()5>R֌kY8I %.x}J^Ei jW~h·q#9H+tEB?F{Y&kev'FҐ fwuvzR:Sy>[GWGm.O #>IcES_g.NV/ܹH! H6v 0vpH4Vm|9PӷxPhwfΡA]:w}QЬ@ijB }vNYK:BOÕ3dcS"V]16_;1Jp{,nftOm\_. N.&9o&5Fj# =NK@IcE]8 PϦ'xp@SВ"͏4#9Spv@v[oWhȰ_ Ɲ)ELy ~xƗ,,c^΅yDZJKh<4]Z@ƊI8ĺXv3EPv]'#h,P^|{uszx(mگj"4{T"t 9ЈF"h[P|MXJ-H$ߴ:mC >x4j_yHs|@[T!:o%prHRqE8\7nFƔnQiG jø166IZ6\XܭfTE'YD؄vCS<1۳adnrjK]V$3Eg`'X67 Ξm<2\4ڈޙ3MIy]NU[#qCJӮuE7IT,I4 y4*f\gsw;3]Rgm$pl'~/s9ۡ;h8I,o-KCA2g`/q9sJ5|toy 7ǜխKI-g=ۜ!^_M/sT9ښjz;:?َ $ggk4^t5jjLxw-8F&&\4KR6\3tn}:m=t2,AR֊kzܻՇ#Ց%2@}ueD:KP=H+:}}УIt r.IiPA^W=xqoO>$Wk9YgOÍ:uj%ÝA:Echp@2u9_-9!vYз4-+RW.\`1quOxVKlV0\`%aPVKh5G}穭 ^髵5n§ tf.Qs w"8gpC_+aW>ϝ>q~\5%bהԂxiЂux,Q:tKq]t+\bw .CX]rL%›4[y i+I:\|!u$(J>&A(q#tPX$CJǂ]D4I E71P$v&(p#K Fy _$ \t:\BP43/0>~^PՋOtkrt=_<\b(Spjx?2Yz']'KZGJ4L|X!s$|8@m8dX$ItlMOl=/kRjS^|Kr [ g>.koJ␰[j두7v?Ԓz;?|hRp SgzIgzڰs O J֨ia!a:ܜ υ 2G 8!5V-E$,&ty̾3`8H4@k(.R÷yڠ%2\f|0LG*LF0}E+aJj`2VmV[[7d˓MB ]!6̌͆"+ζɳ PaPjd:<nVaDW+p5Xn$ ;H>!%dw nYG&{#x~fhL8p@9O8P 1=|@u3;Vp˝rI9EK&j4 (l&^UTO>:#zjcXפ%xy86ꈳ`ŝo]-֕wcs (=C_@WC g{!ZB=E{pT㝩XEvmE %k|$Z4uJ9LWˁ!xq1NN&q(k&\D2J9ŝ0[( h..w] 6La!7v]<8PٗP :gef]h}tk:BoA1 *;aM} Eܜ!Fh; fn@E6)Ej.d'Yw 7X.f + 3==W_I 4|@Q}{>5ӜY1ڑtgޏO7vq@#^u1ɽi,_Ӕ[vkcLq:.hЀdաԊi4SX (v2S %>t53aa.' \) >AErb4)/b^$_!xW6a˖D ާ"<m!&{N?@b%H:U=vx!TkMڝf=5}">+\A5Io;#x'>zzXFJԏ |&z'8i>ᝪ"WqU$ENlxo> BSI'ŲmlF k L;1~o"٫ ; D,ܙoGDvTCjhw~2Lx :̖lst͈喯U m*%YZxK.B2z./IBfq=8FLY]&ar݅r?ĐPcֹJM΃pCD20@_j݁KHړk8_]N/Iw!u2I#j {n&.ܒ< XB&8֕1}UR,`݉6Zd Z ݈q}ju.M\$hw!/G>Z(r§WIksGHGw.RpH]n&psNfEށ/).Gp/٦"|zNZDoT7xؤyS,sD @$Z.٫ wP"8՞MMrs&dPG;gr'%))(>GI{henψ_C؆8\[u7L=Cyi͸Mqk[.7Ƽ!11]z܅rY7bz,}73ڐ2{C=l[in5\y3eya#ryCOD1Liyn?# mLi pCm6P8y?]ɞr2v̲fp&=C5d7*22˞IYƏ1\ʗ=~luq>]ɳz12W31Lr{{ʃYn9 `r^G[KJBnee /Ф],C#a$W{0I2K7TpILuZ>]ӝf9:f15x}cu fGm맫@Zp2ok#{04WȩW.8VZŒ /sX3@{ \*tʗ.TmBh5Q՛k\]\OIVjgqiS\ĦAP:8SZ)`uEjIK2U,ʩj:9GXW*qTNİ'U}kPYsǹTlJLb1HQ=_bꯩ!cxSaq2` TEƑhI8MtP ^3%`p7=x,BgKPޓi %mbP.QPA;$ qmPK 15}P_oP;];Tx=Aߡ ,W)@yw=Zcko t8l"3yW"j kVB`z/Kڼl-YSP/.lkhMaq9tefi(XCn9:Mje&|,r#/jBOqv8gjcsoá{'|Zi%=7Wv =[ oL8}}Bzx/m?{}剝b}}^)\(BJRTtd:lΑ"0@EXc/F5*UbCÇk*4|֋xPظ΅sDl$8J&Xj )oIM"I}mM6=nbFC#JySf#>1fvU0MFA\s%ֽhK쪣`h\%QhլXcnEz3wr|#aIMjPqfe dUL*!3gxЛcބ*ƁM 5eof58{0*q>/E.S(4*ѯ6C8q>Y[&QСFT6I~JڛfLRuζR}|&l#\ѕl/H$>.נ{$Lohe9{3Mpi73ݜLW'!"+ln)ze .x`%=j9'9<~ 22˧; Äv_ktUM /s8b|5{ ::8fGm맫YN/7^t穜QNP1t+VKSɆ9T'4:,"Ӥ;%ҚK | Aq<Ry|V筕sphX7|6|vyʉҥce`ɉXV(٥7n̅ƋrhvSǂSs$Q1ɕ'pv7.4E"]Z9iE^d%.y=ړ6;"]޼fY}՛oO~滿o|ٟ_o~ٯw?~|g_~w}en=)?KVs?\}Qջ/查}|IeʏsKw/=n|G_7Z{%]}|{os"_7}yW??5io~e}>ڿ?o?_ugʼnwֿ\~g=C^._Ez/_gw_?.w}헿3&?U=3˺ߧOwo?,_}5ģߟ_|Տ+kiۧ}?{w??miO鋷?{WG_7/oyzk};ձO7_}w~/пg~kU|eQQ׿ݛqWz?O?͛w?_xwCܧ`J˯ͷo;K|s~SKȹ7:[ݯ|p\?7_\zw˗?͛~ˑtEe7~_\r|N_^>wNs7_3ΐlicoWhq9>_KJ!i YI3 -M$o7'!dW_~ͦ\/߽y736_o.1B՗|՗?1_~{3/]rm/g#۔ȯ˥O߼axϬ: ?\#ng>R~jU^~##Z6E\~y|(~:o?^~ݻooWr2g~)w__~-\.?7?37>o%_|GE9՛$]~CP/_~ś^~؈7RZ_~zty?&\1"Hm8z\7$< ʇ.:\iy/vBtj`ċuS҂OKR.Q.R 2 | i_pBf^jqX8_ҮB_Ƅ'^jx(oh8o՗PÛ՗P‡z ' 8 /n%K(5Y} %a[HKoV_B V_B v=-BU;I2T,XYfxqN>>C|qxpwM;sm:xRD= NFs߾VCecvCsnzX,[213=\[]a2@h ,Nfq9,09zӪb5Zeشyڥ3T|sYjNB0T>Cv;/ F{ ;Jj#HpUxTy݇OIh+q^`%|J1R"_b/1b7oIz1c{1Dz_e3泵vNçLxfFMP{"p7+[fx`2Z_.Wu.pDԣ gg&\lŒ lF %>u9EQk1H6 5 g@K+ˀY8j:ה^7m[j )[Jx@(BY[ /Lz:g̙MyTm&%lCժTG!,VqUx۴*(pa[on$cKWA~C ;C(d"z7馉RΚRΖT_!>v${Y_cxBY}Utɑ>^Cx6K 1FwH9{ b 0;4BbQի".rDgYݚ\56o+mVz{% އf9 0_L-=,N[KɫCwTI'jC0;\Zyv|NEx-+Wn^o͡ǫүyd܊58%+T!ރ%dOp mw3f~#m?r-B|xJ6o{f541H1KWϿ_#"o1ܣk!olu)= 8iŵHE:߅<:;{"G)VR7B牡IMS@un!xqS)nl>MVM 'Q4W 7ůbNyDbh:Y{yJo`sFvHžҒ"9zs?$ǭtor pܪoUsZ%j- ?4\n&+LՓNTd o8] |9C+ Hm 3588!G6rG)\`=k!NI|&é03C, &y6y$ =++z@?ű6m6 \o]`؂\f#FȌU>`1 wlXdN#Z GO1yx}(șX!r2,m1X˩~ )^y);G EIS[ȿ\+o[Y`3bC,(T$*A-EICQ\ߎC`uE] "VvG>z2 ψ>4 kYԇj $XyzbCz[&Eϋ1qer,_tJ>Z/AEj9eKPS;;k0I :OyG5U9dŁouubq[5*Gi(cv(buǷbvG ?k:W:X]ŮԪd}\-9v` >Ab.%_Si[JM tvn.8;FAl>|pr^B~c_T=YZ'aӈѿb\ZJkC.zͰNa{ݝ8/im|c)h"ys8j*U.iɫ@u"wXIp8Cg<S fPy''.eRWMONj%̼CfKq7 yܤi'>2K5$qsy%\fFr-Xι7Gׯ]o= cg.2~7ϒ\ /sge\0r6|62OΜA.16[>JgN&VȚ1䍕&w%\ /S**Fe]e[DN`4 c?]{^y22Wӥ r}/,Gx$W,o>v%ׇ%b/?qY>]յf^kI~ DX M{qz [e X)}d q5Rb,mPUM7Uc1L^i#XF=߮:Q<]mUe ߱V{d0Frih&"*wSɆ9||q~%OctUB&'ǯSM*q,*3Vef:6@z!=T,zUcׯ#[8|s!pp %Mxaݛzzs,v([/fέ[4qqO@1ESU,_QJTp4iPI-eSq\}7C3I̓g, jƒҘԵҸ:/Q#ZGQō+]ꬥޔ$7ў_h5L?LҳT$$!)Pee>I-|"vJl%.ʣ×<\旪({ɱNI>lZ3&L)vU[JG~fi(+I_&]+)f?q}7b]Y̶zLLPNB9[iP6CWZ6r=O졜]$&OPN&,f*rTʩxxN dDTZ.$]X ^o`̓ٿր`V!#l#Y2"y*V6W/R"dtZOr͂4X/+Mq3^1"IXgeYTʽ\ o\RCk:J*K. 1ܜ&qvmM{ݥ :Fm5m'K7{ɳ{?2!kIꮗ}Tײ.j^kx׋6֦jmCOZF$ ;Ż^, oAk~TZ[R_)w>U>V糙178Ut& U+Y=nC^W[ ]j]b]J2|@\F p8f{Z9lrDB͹x/ `\u(Ҝu\'(X:h XҺ_`}С b $|Ng=C)K*)aR_ĺ) }BGVU+΁9T`'bf+?;nNp4̿Wk'/Y{i{\ëwPH%f۾98^覸5.4?l: F4TeZ^d1OY*ybyS=EBsEqɓ_xwz]T\x¼n z%?`M#MUj[ 4mԷ+'G}AoS |S?TSJnS艷@SCT՛ouaaLn1TD8S;9Us9ݨƏ6- @{%eTt ]S9DCcVUV :U,@`Aphi FU+?JsZ?S?Ϻu E L-cp“6iN:~Li!c^r(V9\W?r꼭"sz~xV 5]ZGj]|r@(G2IJl18ѵ yܤ(CY^qS\fpN$q^f,GQx \&N.PxW|{V!-+/>- c|?,&^ 8>Fy? mg:~ |۪m;J;y)dW;-G> (^[{^I֭F)nrr3N-Jyh ӕO7R6c?. D)G ⍆Fv|&81-@_.9 *!P{̅a;|@|DQ+!в( q̝v d#N<&=wU;807vjE  :U<H~8#8L-rr\0'D|ÀD]Bѫ.@r!'mfJ#d$>&ܱ"ӑ,ԭ7]v+Mt FuLp:8(`rrBНd gպ 1aWXgLfw>(8\ K#T!ñ}ci=&MC%11?"{G kP@==?3p 1A@B=bG`2,o% l#0d13IA P8D*oMhEW s \1FPZ޴JM@r`+2EE@y2;cPfwf+o&2 ̇%˻eM΀LkTפ3l^"3+͊^qVf&Gq4\UO |*E!Ֆ:a6(I !wlYyr4kic=<$lZTBvX688ۜ3=!l+-XdE(,B &<"]E"MBuE"t#s9"aPMC]B0!=#F↾"1c:`[3s''3בұ2|T#3{21^~85~"}X*ړ(5vUFhFs6dF('MW uBm|a[|a!#,4MbZ4ZzC5_7X Xl>G+vLM0 X5!:R@ `Dkp}aմDMar ?}y l@#{3;el*6?څ1J^aG-YfhF3QgĢDFZn!c DGKA3uj)io#jZ[QR7d:LɂEa-;]| XÖUc$籄"X ԏ+sy[l}dDG,.X Ϭޅ'ŇA?Bͫ:du.zhq ̿^Rk{](]KF Cq%{pVd "UND*E12'Œȶ=!#R$aγeT>yn}8.]\K\ct+.䙼 B3ۘ9)''`8vv"Ƨ(Ql~-;K = Av8]?m >Mek;"o!ϠƎ q\Z2|X 7ob#|]LOL1ebep2pq{jCiP uLSkhw5O!dkh";7.0x~X̊CލS9=E'(1q:бu[QeJGc mt>J>캬]6$d.I`! > qsLnTOz1;.VݧPsA#k1PpcucٹxY(;i,;9jkgp >V\^Q4U!y%} P@4q=q"2plÅ? J?PjO#z^̖<~9閰gkVEץЗ9 Y`4Rd6ʖ`HEo z|ww~S1tE;T˘Л4T0PA*2ǝ^pX±LОIXp@mH6 'mRM V"*UF VCKQ$ҍ7Dsh+P &PMt6OkU3$-d2욊LnJ ]x,2X"BrBQR HpVXM҂M!7% P?.6{ X͡XE6 {gcq-:0/nS\!6r}JbTpD룂e4.pI4$ՎF O * VAEJE_ػ)4ٍbY]t'zh"X*׎ t VKϘd}E^r#.[bYIj#XW\nzxy=WgClKk5$J{ T搷ViI{8Cٔ`2^\zI\qY2 n-v܍y"߸{E{('q EИJbxǡZMZ$4|&̴<.*?k?;2s"y؄:nT.#聅WL聫k9ڵܝO˛޿ 5)_׸ŧoo1k\,e824" W'S~mU _oX[ma8`x?"?b1C^ޏ n~X+Qj'6͋t `[ɰafȹc*pshwu^:`&#Ȍ)` gn K xr b ͩ3np]ysA| + ƺБڤre20UsВƥ) &d2|# uo4mH@9Ҩ[(X`hNŶP $&HLX Bc5Нٍ@dȝ+ 9c(2tcg_fiYw_w<+&dV m5XM.7LDUPڴƻvUm]*Џ0s}iNG.5r)|`y=?xe%p̵jT>{3gNkzK>z~椸5]ZO6>^x(ݸ >Ao5?6A/7z狞c<C\dIJĠVo$s^iճda\Kk9a\͏k&=tRdy=wLV}2K5qM5Yw^c.Gxv%R xJ0sIP'?\ >M? VJ| *t8r)CŎN'2S^A~0Fjӵ3˯lx>TYʏF%)Drz`/֎ךM7%G)O?.OvZ-+\9]+~]\OOĝlx~3z_O4W"=;V7g q/O) 1Tϛ$;Kq;1|ӥ)s.KdaS[&>¸bu_Vn%;z[)Jd C*'~=M xRN`9-P1%Cs蒺`HcaGgVٵߕ |J >śPi<ˢy0IZɿ4&a:xWŤWd 1ژ@ےWi Q)Z&5 k>R ?Wl)b؟]fW1j঒M /j炪G^J+Qz-lclz;*X*8ZQb5ꖩO:rW vטּfǴ[TVP~`(*UNKL,~y='׃C O  ;E] B,ұ^a=D}|( u;O,PRø9i瑽,(h=x5)AQ8;[O`Llײ;Tn m*ihSܔdw SEInr0*7zш=aU+'T5$5p'Fo_OlĆm<"군**S,&= ;hx W W3rx 4-se y0i:nBX:?0$ujcD&-ΧƑNcR#1S:G[-lFO[%PQNi6sr#J%&9B9:1=E Fb8b2fOS9ib9pi'1'1Wӈ;e#Mwd% 3T=FO0T阞+U$Vp~y,^K p.= "\T#4=yV!-Q/fP\ct(%ZLl#Ύwv SݤcWov%mhX85wm Eoҏ6"ZA y:"F(nZ\EBZ2rAZrUe((qsNFvBCBNf}^fXteړC 4jVtdO+`֐13Q.aCo-{oYwb?þj6i ҬxBe\m$׋ݮ¼E<7ƦM gP7=pǣl~T=́g@|#O֕`9߳bV2b f+"8ogbSjm񀗭J#Wi3EYzbv\0zjA3 G\.8{8 .cXM:XZ{Ϯi`޻m#OIc,'N%i{diHJRq>: d9V#2`0CnVc4`; NS&,tp7_<4Mn )ok<Zz] 5}!JH߫'N#1KBKnisF\=mv1HQzL-trtz:t뺺nQOc5CZ/Y=zR%kS'2l e+$-"&;!{"i&%n)fΫpk y/[2(?ϔ0H $M}̹5ܖŵ-,?mh6,B)O'iaY֦Sݖі|R([Utʞto Dnv3{-ΫM;Sj\j&9.YfèKku 8ѬuR'/vUI^10cA;>:Gj\\823M0[ niY^(S`ll+6]nex*5IMY,.Od%Yfy8mj{cx;YY7ZIOas+ vT\;4v-.^=TYa&^[jZSwgZ:&a߾5o ,槝?ڽ[@UWSSɄ=Ҙ-P9GqZx%ak~;"?GR(fmuJE0KȆ>WfzӐ`WH|-I}'Ù] vg3e=~JZ֢E0[sw;wBPSYV>U|f{l7"2z0e<3||'C!J,jNͤy86 [xҼ%k 0gӹe+kNEF.uAt,άZi6wݶB;IN`+NF{r0iI\w xӍl|8c:[Wb{;6]u65i&)ֆ>ug:vN [Tʓq6U/)yN*wL%P[y% )zsG&QBvڒyLzz:9P ٕ́!N5} GU`NY&|%hӯ.+1Ty-\ ۙ:"euD n4uLƂbuDA1/jȿS1Kdy2uD #ȾnYQE MiF ֣]{nF~r% x$4tHT4$% IɫlHo\ePr}SPͬ5ݎn i\maR:ɕq3FV&-Lr]vd&ه/&odmMNhǎmہXim="$M8IWx5WeǷ]%HJt 5jt]e9skrEHCK:)A α)$Sv6sK7x>%hIObJ\NQArzf^CL3|%]o$jx2P+A&Gե9l:tTxPYbY+^tiiCDkr64(*]KůOpfy"nnʡ*@zdjh;!Ë!"X~bT{!Wcr8 UK&wK!T/vm#rTX q*YBP99px8j5qRMWL&o%˯)u?`- rgpcyMB dMMR$MzERYQdQF<8jnq+]9].˵C-ŷ.9eNo;6{xim|f|,wL|,wݬ|,wMݬ|,w?q)CtFz7]g+AG' Gԋ0 6{#?NZFʥ*Pns ,'`RaNVJX켍@:ަepIі%7e[T-+tJ :D1T$8dؚIB`]Imѽ:]_3]N65QÕ*Vo²N# fڶj,f:%*\u3+&0:G.ݾ(f7/մ\bnլjYd,b Ђw4zy;ARcv)"$OVx:Cwuɀ-KSPIA#  ÒCRb ږ!5ۂS5)s` IM#IW1 |U!E; 6\)l vt :0hY! H(GYkr jH v_ilu#PҰ4ޑDŽGK5cn7r[n[yd9ȩeCZ<.-:J¯BsĜ j+!]>CUC,r3k(Q0Ê2;DÂ|<bлk-=ı%癭Rk+S+l_iVaUԥ C qj\ƏJVP[㜵LIȶ]y#q-iR@)_;Hb,,Zkץ+Vne[Fj~M,meYٶQjFٶF@:bj-rvv:+1v3]l7+Ui$.CuDb'iK_^EX(w8 fYP'ڙ\joTQiUe3`TMB j8 ׎۱<WdN vC,۶<P"A)|'UR/&h!WC2.aRwHr0śjIn95<RpxGItM (en(% 9v6WWcrK+.( C-.e׆U: nChH(1KJtpFH҈Բ(pStw>[Qv[YAuV%,sjS]6ڡh [䑜 lR[Æl~ˊr'W咲:mKo\B;p[e!+>*c֥K]6&̌A Ց@ĩLiɌI2dV+,m蛬[i[[`ȭe3@DM pXA 6ݎeL >sr錘,܊(|LYP9ˊWuVU n$wLҫt>0iAˌEg$avAΠsI |ilwao> pKR_uMYQ̔]2J)m\tdӡA zpco]{82(mĢޅC pl,)a"] \)m%&j3Oޅޞ=t>tЊЋzLe nwMyHă'צw22R;W;|uN9P卥\H(PTd+GJ Zsk ig~РeƢW]nuMjY I$]Aˌmu%&kNHN:7#8Ӳ'"ҎI/z2ئ\`L,d^>7(cV)릒&d'(ѻ<hcE :mU@YՖ^ L,괇3A>ҵE 9t{YN&]/TX,p'Wamt,ȍ%ZTK+9t7i(XiM7B\] (J]XrsZƑ@KCJȦsk}[F!CW$9|^6debz@u mKܱ^qAJtKsurE s=^*6&K؛ݐd/ :nGWJߠ%M3$r6Յ s5\LQ؛o4U,Nһ6^c Ik㥂4z}ui"ڠt,A[' Rd]3Xנe&&I: K HR;IUH.`#d[G|J:T |ݺN`gٸu]=3ТGP]/\N@llFo")A~k0ߚdLӑ7lETѮRPa7ҍ80ؕx`+= vumX[iQ`Gwյڱ)CNC&XA]R/`Hv vU|W0($HB,ld@eqdԁAm-E%ˠp K]e(u6wf˸ Avy0Tu5V3%P^ݠy Z~7hA^Рyk& 4h[YFVCm;DJІD 4>Qw$ںX#祐 !gL+-]yLIY񆌄I3 u7˦@u'!ɲuuaƏsMi;cI$FWWhey$߰gWD1Ȗ`+ Zdl3F`]'#Kl cGlۖ؜- YlS#)Q8RP"8M[ t5f2VlQbM mĤ/ cɛ/d_¾4KcvK#c걍z\=Q5v[q8z'W5(EŨJ E.lڕ(ߴSБ.?z vwyi*I>0]ţ:^Sb_nFN]de5.H츯;[NX$Ar ΞZC9aq4v\x[rr$]0xz>U7;g]9K•Ui450ttyUj}-YQL%d]G])mjϩLVYp~c@:-I֭$*1^Z0 ) ~N@5Ѩ*kS1̂nI*ꒆ۫63|VG3$/Jq@!U2;WI9K.Rd,\6 ʘ!Kq@mF2+jB!1~WzI%PPK+ڡSZkvWj{1+յ=<j5KD/TЕF0.PBֱͬ꒠%zZuml<eT=AE җ91Z݈:Q,#5HW#mJH=:YXAġKlD H.ֵ0*haH1IMu5PU]َ֎U vMͶ@[FKro@`]'Zj3:m5p 6UtuYб3!ٸbv?f%P$<*NN@f|ULSŷD~B9(Pi7/M#Yx_rؼPn汍z\=vȓ6fǨZ\1qŨz\=嬕\i^,m 2_fL_Q6g+ж3!w@Φ=W"ﰴR(X5$N``kYXUdyI FGɒDZdRuRT+L9j]ǀY:VH P8Fb"LzaupÀ#,Ykԥঁ'-F;r%u"QJYw˗|hgg`}GLr 6#5G`z*HI{ݖ]$Y[xb!-# ʥʑl!ȑKA2#4x^L=;-7ε!|<ҁn 0Z>u l#v F =Ss[xJVsT;6Œ sTy:Zj'xW`0;?RPF#D."0V6xq W米 y"g=ٛ7 4'wj&it|͕]Ξp:Yw Y$TIXQ6)I#r)HQTND׺RJ: iɼɫ)ITCtL:K~1tΓiؑ+Pb'k*ّ3P"/JCT}Q0ñ[CEf+ @*Ҷ44Zơ$U.xB 2X@ ?orZ!MbPuv!ZdQ * *ޖZwT @uф>pp15*Zvdiiq:ۏ`Ոu}!XEYoV@tF9IV`]" WSza5"(Te4c&I#ڂq?"u53cۂ`3m5(MЖ,:bh l2d`#qYzVX=nL,K;{&AwÑ?tRZ tY\Xhg,!;.WU$m nC7ìd2tl,Z _h6旖1+ʾ(n汍zbԣ.PuaY'Wcqz\=Q5QzQmv{AwGTWgμTN&/q \bj2W`)؈o4 ؝#>nHlpۀyؚel-"W٭vE^Óa)1( /ZU<*J-* v㢞63(ӣv'P;'PJ>hfRYRjFŠZ08JOvli0eID]Gǻ*X2C.d{MGj1Iw2#`v,1hujL֪r3[P.Ub" Ğme oda2̼q M&}?m&K١¾ VPrITYq_ߑk6b, T3T u6W,cɢg뺺0TzoSa V6HhjI5C.`3 xMARh+},|EMo,)@PWO:zVgPw$ d͖Fn[ u%~ aGa'LzJEwbJ7htiZYf'+`qI鄀 ÖjRG%Q]ES*eI&,?Y7M4t+~dp=KԠCLI1yB-bSחw\f֥겏qP#/hlΨ(K-}eJ|.׋x6 8UBn/sg`jXƭq!ښ*n=_n= 7YjrqrF(tXf87vvu3dit4=3!?*ב/n9介AF(/jT&+e1KkDKTMΝl؛`K 4]1 jV;|I k1LKd779dt> -/k&7m]k|9Q筵ڡ"LrTÎ!y̅-R2a7;>-Va.ZZ(e1ݑr[)Îb4(i娚;sa셆+GɅ05rT/O0 Am%/7$c/WWrS-ń`F 򽐃(?F'.t^(n*Q&t>3)oo :JG6QY֢rm_\pC"c*wqb\.F\_a_4g'h'G/0-hWFW_ry6$ /,|wLCS0(rݳn+ {|W`z(v{K$N\>ޖtGlW_ꢖ#4fW=fdUa7U>XR`1sr2gF>`}ۖ~2BBo,ҋ)'_VՋ`M`۱%2b,[!R c*beXZWG ص|azL-nM#v FtҮk`kT,uPSJ2`-S"h!;r#Clfс{K9iN&0R pd@6Vҩov6R ,C}4N'Wl.6u3zShM~1̩E.mSHG|d*b4Q3EjENlg*b<`z~X^=g ~L{>>{}?Njj$ׁnѠ1veܿA|n~fga^ l#i6nh }oчtSph|/v{0ј_J椚qeߋ h4?Iqyu܁N%_p YFQUk/_8Ozŭ> I75b bхm[#BW _~=߉$8mg\=Cnq|ܯR4'"8"wj]]v;|n[nSnr{1,כOWOAZN KCwu.*B;bX5aaZezq4 1a܋ϼs_l߶Oߏf'pyX; xo;FyPwk"݋Ӡ7a~K~'ڮi)~򽘾v-&EDQ?I+&<"GAzQ?ď5F?Fm '3Mb?j/8.8FgT(L$Q؋{A?_O4B>6}/μħǨw Zݩ5EI9 ǽ AOΠ+@u~K/@S"blzITK߮1aSwhv 䂻OQTD|"h싴2.tx{vNjQ|Dҋd="l3eSw(N+AN;O>W6IΓyqx]wYhr<s^/ѯ~,VwHDsmA@Wu0:DZ''G0:8}$b OH/|VDdCƀDx^S0?AO>DUEv8'?M9&|"g'V00~(,QX $&M`%Y"Et/%F Hl)I8 Yt؇^H4 մ> Փ'o_VhJ6l[iCt1Cw'1_%sKx6r^rv^Y>ՠZi/yNj܇1;ġ `"h@@o;KV!gHaUV]aq4م,tr`8Y^Oz5$IkYaw}x|#?Üǿf0co44{7۽K$\*84€[aboGc ,bܳJ~.gx0_X} EC)EC|mN^RS>Xe.G>4˚W5{`#,?zy"%[sÏ^ ^ (~"m)!Y}XaWciBA2 D$W3Xskb 88L#lC0kzXo%d k5W4E),5 @Y`< 1oH0}oRG5 p,dθmbnh[[E?_e;lI/ 'Fj@uWA۴g[jն$mCCd4YT>Qpu@@8?n'id+z{8 ČrYU"}KJAp3G߳Q\IxY!0 TD,q஗zq}zb!y'/1(|Y+6O/w~9>9?x~f}MW_}9PT0t_y8JDn\TU}q5ܭT{yIl~`?)NEE-JqAxjefYeoDYk2TjK*e5a!̧0J<8 yb~v&: |(oYiԲv}V踏*(0zջk,pj1 StTBBtr =]q⡈`@ǗA 'o1X(%6iǓ(b>K6ҮrXR 3hzb I1 I j '}ExrjnjM) 2\.BNBR?ٵSLq#/ogQP Lvp/6GS _.FA޳Z\@g^V>C_rD "7[o0|we_{X,$cTջj䐐 $֫u8 qn\cc 3PNF=D¶!E]۪2d3r0ڀIt0d&&2- i0tS⧯jco|3}}w=E)&_+P8RbM ,`@"X/rɼQqzH~3x*2e! Sg*‰0'/_lIq1ЃQy2V%z^K Jљr"5 T,8uU/*ݵQ !s\KB bSpvJs |D`<"wסBHhG>gηTg3JH2x S$M 0a&nkΗ|}/h 0(a]קoiԓl%I:΢>0:‚eL*k'XB &)7ĭƒ1/q\d >zu09ۂ\2ՈC"dt,&$^%JN?e|~Z,Hܼi~y'sQ P5BQRa%'&dThJ3 ٪x4^~x|KRC< P8]CoҌN}o9O` _{°iIvxJ 2*T՟ #Hbv #LJIroA}xX5cm ^ZGz?r, pltN~ɥBμCJ4F=d^I%? 7a7U|{ E 9ZJoe1 5^q> $-~uzNl Y/'>F**Aa$br;=g0`.7=eOK<髬֛h$xTzM XdE&L%L`M^.Y?rteI}b۳vIp \4_A%|?&-`y('WPȧjq>3T4sM:WzڏZZ7<φ%+ ECI|cC7$`;qœፅ`|>R R/d҇+9/Q9Қ 6A8ƀObX&O ^vBrCf~)Ui[RkW$wj! ʭI0Le@@&Fp7ר͔˖B\o@`ZQGtX`M*pZk:[&-z2W Ä9zH'邕rZ\P.Ty#^r7QFȓ_ȇhO{:C<hoGEiI- |8C:3H xI)qfNE ymToBCDf E xEb,!cv] l{!.9a7)i3#5iA3RH?ChėExL3*y F^'^(#$Fa3 /?ߟ% ȯ?-HK>F96a3.%sd? "dzIIg R^E R_b\أ `D֛'ϞU{:DXD`O_/ݟ[(~:\zwYz7^# Cha^NSG|1pKX@XX=+%rkaQAzŇx3`>_"*ɇatnǺK#6g;,T ]Pqtgo7>?&jE9DO~ @֧gZx"sMsg%)E2!7 ;Sꂅ9( tʒ#kS#2i2㑖8Fռ8>׫#m -w!x1la1J*m&lo×sRGiv ,x|(^xx8GfS lQrޗz>,G@N,5L/\(#ftl+Caƅ|Cq<=~GY drZ*;s8o,$M:)]mgxS?IIKʦvv_:QzHя?%EtI Wad0T_ ޏPD cHU"@O8뫱|ܦ+(BOcݘ=yi"*àCi(ړ 7@BjiFXk@WMxB6b[y3@V00;i[Ρh52Aa?Z^Ov_E(;H{p YR5s"},X)O :|ON_XS=(O{^~vP'u5EʒPQuՆMlˏm}mEV]斾,Sx\ׅ8aYY`G?`p>*^ãW >-55TZ1˂66A& }1JƆ$EX.|T2CSNŶi7|3S~Uj2]VX?Ծk]=}(S`; SʰGIۤSc*>˚.u=5]jC /DS~`:,ֵWRczkR^9˒'_7NCͭPAuELR6_i,sJ.R|\^s:~7Ӧ\,&? {%RO}q+%xȏ*QA5h4P+K/ 64}e֏zƄ_L8RZ *{ád$SR#q A 47 m⒵atyFvf붳oFQ%_Qѫm``J)7Dj?HzC1<~[yxSQ 0MH~pIjg7sVG.F6 ؜71t4;L`6֠Lbs3Y^T-OmU 0U0Yަժ9Mi&i87LO tH)>Nqцg`r4| WQ_U $xZچ6twAM7$2%f`^.y9+}|Og$3+ݜ*vd?|0J~:LnWQ@O`|n@4f|GBV=s8AܑЂK():xEl A| {FpAp&:mĜͯ"u\Tă+P 1ڸ,iOӃTD>Ru"ۍPu&Z26 {hQ(O¼z5[wtUŰrfg}Y`1 O6 z_b٠ O6_^}Y0 d{ya@?g" Hh,c]=Pd`퓞|ϡ>޲=~1Nq ^wA_? 6Gn@`V?kmPK<BA$ó鶄 >p^Z Hbjߓ@a/MHtNZMoE1?}j7RҢبbgs6$g.BF@F= dPT_7^(2u;Xl/HG(o>?yuol Ry?(_ &t4 ?QiIEMzo Wiۘf S- 4&A[HAQY<2@ C6~"AkBx,pAh+9%v՞>M# #}qVJhmQ漠( #0஠bA _qBo gB0nHI栿dJ3H 7)uk毜XYƍkINLf.yܟeG, ɳ]3EU&ƬāM>U@ `òTP$ō>1IU&0Fa;'!>/ƔNZGӦvvYcx$C̑(mVggCj%La}Wqog_{;#4GAfatSkadb8@v;aqD9h8Te*ݰ+Ƒc̰ LCLj6ʼYܹMX՛Y"n}oɕ85ue֭jܒ]rAiQZGIуj$.| 'z^ /`R|iazE52fqOTi '͍FA}k*vŵJ$OLWU Җ' V.ՠ ihV^DA3:wxzɫÓ'heXo/IJBG%{U_XĮ8Rl m~]y kB n|KDžߒ\c4iR FSmL'||} t7y40R~!zIR8C9ioH9w0ӄy,t&DG|+$9ӒF A<3 l˷<}!hyzn9OdP7 lY[u1)J1{^UAՀOCڷLWF⏞TAajqiWJoŰLfpWA _E=HSZh`pswH/9 _$SL@<ٕ¤_Ho߽y^m;IzMHJDTw/oWY!Bew`wY.>Si!Nѹ'.~B)9&GLDnN 9y*]Cz OEvGXavQq~X*9 cwp;v)"8:vm[ͻ[oѷ?Me}Sm`͜O M,!ɱ,iUzR5F+fYmDGg }˲Th8DNI43K|IrٌbeW&"_XHLH*HXEhveUBzEswg}yyYOkYsz|"sPZ,W />z1.'fmk@:}-"s8=NYzQ|\ݡ<4JJG'mmd(p< ؜Ӕ/$=+5P=j<$pP^ ~!1gW<4Qw/go/@@fE:^+ ).@И?z\0O/>o:>t[Pwu]z.UgO6*hA]|Dllkϓ{V%BRgE9DfM7@Z s-yFm0 k7n%6蕼PJZY?19GOnqߨWJ6ߋawo !UG?b ߜԉj~ 6N F7[lL# |^⿞g|ݖz|7փizMa wJw(ŰugJ-t̩ TTz+tA Ħ4ͮ[Pn^PE@{hҙ RW6EfNc2Yf?hOAq~~T ޹2֦M$doD {WSE4Q-{テ|}o<9Gp\hNwY*>E|B~Oޤ_yUΪ1<@,8'z)++~Ԫ+G/d+*Yn2IŃ;q  ƕǛ)HUʟ70=hX}kk F , Cʀ q@($1]UmqDer#xp(fvWr7veA9) C"1 *]s[M< 񉞶]=߿Tȷ.Y7T**3$΅YSXnH,5(0xk|YyDŌ$WG[b"?D l%lυkW\V8S̚krRkIoRKᨘ/ւfTc 5GxV OjoB~/&wc31yÅK a= lZM̄ &䯸G5u۟_A:Ybϐ\SN_2P!ȹ pn>c?мLp(4MMh)yţA4G/4[r}}x`kSJ^T[rb)u5yl֬_e*Yv6ynH7969PGp\mdEm7%KϓL:ӁI_!J.v:jy3ehMb[:2Y6 QnΥtM֧i4ζR6䂲|O@5'sxL[ϰۜq' H ؔ2 ;rmץdL,Ǣht>|sgl( ]6]\ĭnb N›Ѭ%;Qbܞ턒Fr]#65G12O7UD/MиA)M{6heA[pWKwao{o{o< o;ձ_Ʌ5?xg o-ş7f\WO͙lVU"!lGo8! Cs<$Wcy`G)WLBdR"SIkz9pj>E_`yz f+$g<ڍ}i}k?/Rfá3_tf;_Cקgz=d/%~{1,o7K+ 2vV 71?#/[w_>\+ sso.͒g<^ Km;EVmQ`f؟3Ym_7xGHL\#52J^Fb%cѐ*"'"`.T T֭ɉO=F/6F&4<۪]W*n'~q2vN8XMd΅Tu}Tv&gT~f#I7, EkԳrfO=|e.QFhfV˫ɋד;=9f0߃ϗڎ[$zw?vi{Ey0;ڛOn Q?%_I(z<^ KVPw?;וwp,VJF~8(%_4ߋawEj9%aˤ~<@] _?0 R@_BǬ k7HC #Vcco|?PfPk◊82BʯڢhMFI X*c9z@q*zyb]qϩ #ҮDDWm/98xMO94q uS|a8D(F dzC/aQȥ|-}5}Ⱦp|hN /d "\(iuz D$b&N?LԤR=/A4a#3EF8-0_ ƃ 7b 6?FA撜\xh -RRa"Є+LNe/`8uv<28G`qʁPRP ʌ)b+>]N%x{.%݊I:i%g 89zbAc]?Ol܄D,agƤRaI (~BhCh=Drvct`b:R$eHsXJNbL?Ɨ`{@DjltBt;ktc n5̂ QϾP?C{=(`'7Ywis'+50 "!6O)NH3'|@dt\S6g&oj(c +by|RK\J Ǿ蔙'dyOīcqKȔ?#V?/wn?ٰK+ zbXv?OQ[I(;ق. [[JPy?>JB;,R% ^{1eJPKC/lQ(z^ KSwfR%gY".x~/ŇuZ!i%qd6Ћ H ~1mK[mBi=O zק㧛*W[S}ciŒD֩Hg^5u=Oi2Q&﯃'\T! A)>g8E !4#E J'.b߬o[^sDy+K9siӻq,],`]> ,ƀ0Śٙ7< _(D-0[R(ASSȁղó(h{r6 Xo؛FOR,7"Eέ髟vw"Dfߕ"T{HCPIlI b܍x;H8U O=ԿD%/_DJR_Pso)"?+ %_P1ߋ]XM(z?H?7J_+ %_4ߋa)og]I([[M\nVJ!7i2l5sWiKٴR$d?}6 #,!l47F(Q7!c3+;4<Ȉgب̌j{({H?V _w?VJޡe)]XIѷsx:=t."$)Y%,?J]$C|/ٜsJ,|<`p/ׁwJB;=bXw%agoGrOd1x|u8t0s$?s$gN~x~BTɫW}0he.$C|/euS$pg\؋s؟Y":1%Mh5R:/{fbX]a.o!?*oa9}담+ %_0|2}VO'19ծK٬ʮV7Ȕ!K4x 5:=\4B on(|+rJwŰt?n?VJ 7s? Q;/ .%_4ߋa,W+ئ?|vOГ };/$ga輧cp#hViI>B\w[ۥՄw{Ű[z_IL7P`coTNO|e l}< ~ uHS&%d yOC !9R,̓q˽sŨ&"n󣝗-Z@&U(%v脔 *V>a}cK\PF8P蓷wo7.;|{~gN@nbhu?=iAbsr8q]ߋ_v^{0 $53M6~ŭV 6}X9 ,OX-90Kf\?9;g =z/Lc`.wQۭcQo=7@:@"@wb '}mw_`m0qei4 `O*Ӯ \?:h^"oxG>{O\@NftU+ AaD8\k+K *Л㫊E}XyX@Jqp6'|OcUhhtdX@ĠŜAH@ZUw%ak OgZJ\kn#$`*$C|/_n+ K F7E`Ex<RIb z#ƫ4`wsQ>Qy(^Pt#Κ=?؛ZϢ/Ʊ 6Us*pAʐM3Ϗ_@kϓdpwEi _g!TUGHaG 3vs%;_>ߋaLՄ("N$*@^ _ Xk|!6% _>?9:i)|QX8~(zYtZJ\*KS&Oh<\CÍN2s[fPOzcV^^IX΋ս_Nv^Nf?zq/Vwgw7wŰ7gKqoߒhVaѬD{8nvڥ 7/ |>o[wŰ9j roݒ$Cn|/9ci?V8@%Fg"g G/OH).Q^I(zYV}ky@u?pJ/<%hVOne_ۥwŰ;ErVWr/tk7/< w[畄w{Űv}^$yxaR1rf:Vj֌ׇ{GO_O-UK&)0,Pá1֐L~L5B+G 7V 2DNe5vqPN%d51ے^L0L4Qb~"]0Y'3?p3-^@-IKJw2{J72GM´74֎FP5n c0Z h#H/`Nu=!aHBfolR[gv'n)":/Pfppwh+K7'~uW~(VJ!7i2ovNf`d҃h3=Nz c^G1:Ck٣VaXQf?.*B;bX.W?1Q% ҡ_DnWG{GB Oӊ0;D_ÑӯIm VnqKww㟒 C|/ec 6%_E(?wqu_qJB;bXw3.*=<χ=baRrs̟qI%qÓint|%a/s_\Q(z"^ wJB_p3J/ Nii%a.o/E]̐3ߋaw[3z]?}{G@}YH~/~_Ln2(s^^wMė㫭|L^/>Q NPHѵs z H~Zp#mWճx%_M(z^ K͢RU3i!,S(5W,Ws?|/SZM(;,P3a2fK+ ?xԞ^x 'lxQD( x0to ыB6zF)Z@s -jS9о D<^+͊]ȸ ^Í>NU\M(;=b?)?$7~/V%_4ߋa.i5rPy!;o *?R3r [ہAx>K?,,*~O(z>{1mޜrJ O?8}0}h&}}?èH78z~ˏ1 1{B;/L0fJs/ E|ᔈޅ WtqX  aJ+"aMUS]<ÈmJX8 XZ`WOV(oO~Z4L E!Jfzm_kdřߋo] 6Sd ȣG˳'hJ qT /h/:shD2U ]g& ?8, ?N }XBuAQ엑E$WIꏒ v1^@B1>tEIjZL}" ygI4tXD-Qb_A؋}'N[3Yu#\X&[D, .g$F"ϩ&֏謂nð.YЅbl{ s4eNЋ~yzoxs{aSqzٗlՃlʐ S:2C)~9QTuJR#e`u؜3@8Ѧ.kʦja1M+=GiݾeHkP\(ڭ Z "ȨKCut=1W N(O=¹_N<1#ng>>+}NPQ я uX7G>;Z/O,x[~}?ۢl^͆'L6ʨInmt/pIb?_rW8s@. 9Lg|}c jx٫wv߫&ɮ 5RVf}aScz놢X?|!7D 5FIT*ͅQ+#\ޘ9zc d8nQ\gR#Qe2x8&=H(4C!ţDJ>J>4G'{ÃӭٷpAwU=$륻#+^!-Cޖx &!P(!-/61E~* S*1j:@"`Mֳ <)jAęD o{-Z~P /z0:RJEd)dbv ` D\Z" '_  E`F2e&\2!+UxFyI~6F[$+ٌecZ@P ώvw~x9'I]fzv\c06@hC`D i\+bƉ~瓽㭛rr?e˚dc,"c$rvmqpFʗ؛rg{'OާM0y| 3sTXyw\Ֆ m+Z"6mJ [#8Z%=d #?RAGH_x%EPc~XYl$@DOˆO{kgO .q%.H5T=Qsz2xo١0>&PPG@es gƇ=V2%հj@N05,ct=]^Y?v[JBy!s?n9c[M e<85"O5Fͼ̺RC;Dc 2/lQ nݩjt[k2]ڷL׹e-m:Mx[R۷}[b۷}[r۷S''ݿQY]ϗN|P~cX"yl9וze;Fie5>{1܁%_I(zo}8 / %_3ߋ^WJaj7->_c2oOnim%8Z'Gt{t&ӣP>~ G 2b?"kV%_P1ߋFim5wXQ#ۥw(Űt_꺥וY:'sMȠUȆWK*wϕw((Wz?Ds_&܁J %_0aSXM(ze|CȻ͒"C|/FWJaG_ t%>{1܅JPK˭ޅ7+ %_0a^_I(ze?ߩVJޡc-$2?:.+ %_P1ߋUWJf?^;Py?٘9o+ ;yizOgY!׿ ׿JSFzVPO>l%_I(?_PE_M(zz/_[N%_3ߋn6KP7 ?]$Cn|/5nV' a\wu`w/K1 e(CP2O.ŕ ?gdl-0.9.9/quick_start_GDL.sh000066400000000000000000000052261340051421000156450ustar00rootroot00000000000000#!/bin/bash # # must be run as a BASH Shell # # AC: improved shell to avoid "big" when sourcing (or ".") this file ... # echo "(ba)sh or source ? "$BASH_SOURCE # # AC 01/10/2010: we can keep the current $GDL_PATH using -g [--gdl_path] # Absolute_PATH="`dirname \"$0\"`" Absolute_PATH="`( cd \"$Absolute_PATH\" && pwd )`" # if [ $BASH_SOURCE != $0 ] ; then echo "Please run this script throw one in the 2 next commands:" echo "1/ ./quick_run_GDL.sh" echo "2/ bash ./quick_run_GDL.sh" return fi # # AC 2011/08/19 to avoid conflict with other IDL/GDL environmments # which have been setup before # REF_IDL_PATH=${IDL_PATH} REF_GDL_PATH=${GDL_PATH} REF_IDL_STARTUP=${IDL_STARTUP} REF_GDL_STARTUP=${GDL_STARTUP} # IDL_PATH="" GDL_PATH="" IDL_STARTUP="" GDL_STARTUP="" # if [ -z $flag_help ] ; then flag_help=0 ; fi if [ -z $flag_quiet ] ; then flag_quiet=0 ; fi if [ -z $flag_valgrind ] ; then flag_valgrind=0 ; fi if [ -z $flag_gdl_path ] ; then flag_gdl_path=0 ; fi # while getopts ":ghqv-:" opt ; do case $opt in - ) case $OPTARG in quiet* ) echo "Quiet keyword swith ON" flag_quiet=1 ;; gdl_path) echo "Keeping GDL_PATH swith ON" flag_gdl_path=1 ;; help* ) echo "Help keyword swith ON" flag_help=1 ;; valgrind* ) echo "Valgrind keyword swith ON" flag_valgrind=1 ;; ? ) echo "option illegal -$OPTARG exit ;; * ) echo "option illegal -$OPTARG exit esac ;; q ) echo "Quiet keyword swith ON" flag_quiet=1 ;; g ) echo "Keeping GDL_PATH swith ON" flag_gdl_path=1 ;; h ) echo "Help keyword swith ON" flag_help=1 ;; v* ) echo "Valgrind keyword swith ON" flag_valgrind=1 ;; ? ) echo "option illegal -$OPTARG" exit ;; esac done # if [ "$flag_help" -eq 1 ] ; then echo "Usage: gdl -g [--gdl_path] -h [--help] -q [--quiet] -v [--valgrind]" exit fi # if [ "$flag_quiet" -eq 0 ] ; then echo "Running current GDL with ./src/pro and ./testsuite in GDL_PATH" fi # if [ "$flag_gdl_path" -eq 0 ] ; then export GDL_PATH='+'${Absolute_PATH}'/src/pro/:+'${Absolute_PATH}'/testsuite/' else export GDL_PATH='+'${Absolute_PATH}'/src/pro/:+'${Absolute_PATH}'/testsuite/:'${REF_GDL_PATH} fi # if [ "$flag_quiet" -eq 0 ] ; then echo $GDL_PATH fi # if [ "$flag_valgrind" -eq 1 ] ; then valgrind ${Absolute_PATH}/src/gdl else ${Absolute_PATH}/src/gdl fi # # restoring initial envionment # export IDL_PATH=${REF_IDL_PATH} export GDL_PATH=${REF_GDL_PATH} export IDL_STARTUP=${REF_IDL_STARTUP} export GDL_STARTUP=${REF_GDL_STARTUP} gdl-0.9.9/scripts/000077500000000000000000000000001340051421000137545ustar00rootroot00000000000000gdl-0.9.9/scripts/README000066400000000000000000000026571340051421000146460ustar00rootroot00000000000000Alain C. and Ilia N., July 2015 Nov. 2017 : CVS discontinued at SourceForge, force move to SVN. Please post improvments on the Discussion http://sourceforge.net/p/gnudatalanguage/discussion/338691/ or here http://sourceforge.net/p/gnudatalanguage/patches/ Just collecting few useful scripts : * The SVN side : ** init_gdl_SVN.sh : How to do the first checkout of the SVN of GDL ** update_gdl_SVN.sh : How to uptade the SVN ** same for GDLDE, an IDE for GDL: gdlde_init_SVN.sh and gdlde_update_SVN.sh * The packages side Which packages you need for a given distro, the mandatory ones and some optional ones. This is convenient on a new machine before running the first "cmake" to avoid install in N times the various packages we need. These scripts are not perfect (e.g. it is not that easy to manage non LSB systems, it is not so easy to manage the virtual packages like xserver-xorg-dev vs libx11-dev : both are OK) and we really welcome your feedback. ** which_packages_to_add.sh : if you don't really know if you are using a APT or a RPM based system ** aptget4gdl.sh : for APT based systems (working well on recent Debian and Ubuntu) ** rpm4gdl.sh : for RPM based systems (not that bad on CentOS) ** a minimal script which can work on a very large number of OS : most Linux, OSX and MSwin. On Linux, it is better to run before "which_packages_to_add.sh". Details here : http://aramis.obspm.fr/~coulais/IDL_et_GDL/minimum_script4gdl.html gdl-0.9.9/scripts/aptget4gdl.sh000077500000000000000000000037261340051421000163620ustar00rootroot00000000000000# # Alain C. and Ilia N. : June 2015 # A simple script to help end users who can be sudo to add # as much as possible dependances needed for GDL compilation # BEFORE runing "cmake" # # On Debian or Ubuntu systems, we need the "dpkg-query" # command to check wether the packages are installed. # # Alain C. June 2016 # We switch from "dpkg-query" to "apt-cache" # which is more realiable (would have to use "dpkg-query --print-avail") # if ( ! which apt-cache > /dev/null ); then echo -e " not found! Install? (y/n) \c" read if "$REPLY" = "y"; then sudo apt-get install apt fi fi # echo 'Please wait ! need some time.' echo ' ' # mandatory_dep_list=(g++ cmake libgsl0-dev libplplot-dev libncurses-dev zlib1g-dev libpng-dev xorg-dev libreadline-gplv2-dev libreadline-dev) # dep_to_aptget="" # for dep in ${mandatory_dep_list[*]}; do # echo $dep test_installed=( `LANG=C apt-cache policy $dep | grep "Installed:" ` ) if [ "${test_installed[1]}" == "(none)" ] ; then #echo $test_installed $dep $can_instal dep_to_aptget=$dep_to_aptget" "$dep fi done # #echo ${mandatory_dep_list[*]} if [[ ${#dep_to_aptget} -gt 0 ]] ; then echo "Missing Mandatory packages you need to install :" echo "sudo apt-get install"${dep_to_aptget} else echo "NO Missing Mandatory packages" fi # dep_to_aptget="" extra_dep_list=(libgrib-api-dev libnetcdf-dev libfftw3-dev libeigen3-dev libhdf4-alt-dev libhdf5-dev pslib-dev libgraphicsmagick++-dev libudunits2-dev libwxgtk2.8-dev plplot12-driver-xwin plplot13-driver-xwin libproj-dev) # for dep in ${extra_dep_list[*]}; do test_installed=( `LANG=C apt-cache policy $dep | grep "Installed:" ` ) if [ "${test_installed[1]}" == "(none)" ] ; then dep_to_aptget=$dep_to_aptget" "$dep fi done # echo "" if [[ ${#dep_to_aptget} -gt 0 ]] ; then echo "Missing packages you may would like to install :" echo "sudo apt-get install"${dep_to_aptget} else echo "NO missing extra packages" fi gdl-0.9.9/scripts/build_MinGW_8.1.0_Makefiles.txt000066400000000000000000000026471340051421000213720ustar00rootroot00000000000000Version 0.1 02-08-2018 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 @echo Software Foundation; either version 2 of the License, 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 REM PURPOSE. See the GNU General Public License for more details. (It should be included in this package in the file COPYING ) Script made by SI LOUNIS AMAR (https://github.com/SIAMAR) with the help of SFLINOIS (https://github.com/SFLINOIS) This script is not an official build of GDL on Windows Its purpose is only to help you with the GDL build Any feedback about the script is greatly appreciated ! :) For this build to work, you need : -7zip (We use 7zip to unpack the libraries we download, you can always modify the script to use another software to unpack) -LIBS.zip (wich contain some libraries that we were not able to compile in the script) -wget.zip (wich we use do download all the libraries we need in order to compile GDL) -gdl.bat (The script used to launch GDL once compiled) The gdl executable is located in .\build\gdl\bin (Please use gdl.bat to launch gdl with correct paths) You can find the script here : http://aramis.obspm.fr/~coulais/GDL/GDL4MSwin/gdl-minimalscript-win/gdl-0.9.9/scripts/gdlde_init_CVS.sh000077500000000000000000000011721340051421000171310ustar00rootroot00000000000000# # AC 01/08/2015 # create a copy of the current status of the CVS from nothing # echo '------------------------------------------------------------' echo 'CVS disconnected on SourceForge since end of November 2017 ' echo '' echo 'You must use the SVN version !' echo '------------------------------------------------------------' exit echo 'This is for the GDLDE part : IDE for GDL' echo '' # echo 'just press enter for the passwd !' echo '' # CVS_PATH=/cvsroot/gnudatalanguage CVS_SITE=anonymous@gnudatalanguage.cvs.sourceforge.net # cvs -d:pserver:$CVS_SITE:$CVS_PATH login cvs -z3 -d:pserver:$CVS_SITE:$CVS_PATH checkout gdlde # gdl-0.9.9/scripts/gdlde_init_SVN.sh000077500000000000000000000003031340051421000171370ustar00rootroot00000000000000# # AC 07/12/2017 # create a copy of the current status of the SVN from nothing # only the trunk ! in a gdlde/ directory # svn checkout https://svn.code.sf.net/p/gnudatalanguage/svn/trunk/gdlde gdl-0.9.9/scripts/gdlde_update_CVS.sh000077500000000000000000000012601340051421000174460ustar00rootroot00000000000000# # AC 01/08/2015 # update an already existing CVS with sub-directories # should be run at top of the root of the CVS (e.g. gdlde/) # echo '------------------------------------------------------------' echo 'CVS disconnected on SourceForge since end of November 2017 ' echo '' echo 'You must use the SVN version !' echo '------------------------------------------------------------' exit echo 'This is for the GDLDE part : IDE for GDL' echo '' # echo 'just press enter for the passwd !' echo '' # CVS_PATH=/cvsroot/gnudatalanguage CVS_SITE=anonymous@gnudatalanguage.cvs.sourceforge.net # cvs -d:pserver:$CVS_SITE:$CVS_PATH login cvs -z3 -d:pserver:$CVS_SITE:$CVS_PATH update -d gdlde # gdl-0.9.9/scripts/gdlde_update_SVN.sh000077500000000000000000000002271340051421000174630ustar00rootroot00000000000000# # AC 07/12/2017 # # update an already existing SVN with sub-directories # should be run at top of the root of the CVS (e.g. gdlde/) # svn update # gdl-0.9.9/scripts/init_gdl_CVS.sh000077500000000000000000000010761340051421000166230ustar00rootroot00000000000000# # AC 21/01/2008 # create a copy of the current status of the CVS from nothing # echo '------------------------------------------------------------' echo 'CVS disconnected on SourceForge since end of November 2017 ' echo '' echo 'You must use the SVN version !' echo '------------------------------------------------------------' exit echo 'just press enter for the passwd !' echo '' # CVS_PATH=/cvsroot/gnudatalanguage CVS_SITE=anonymous@gnudatalanguage.cvs.sourceforge.net # cvs -d:pserver:$CVS_SITE:$CVS_PATH login cvs -z3 -d:pserver:$CVS_SITE:$CVS_PATH checkout gdl # gdl-0.9.9/scripts/init_gdl_SVN.sh000077500000000000000000000002761340051421000166370ustar00rootroot00000000000000# # AC 07/12/2017 # create a copy of the current status of the SVN from nothing # only the trunk ! in a gdl/ directory # svn checkout https://svn.code.sf.net/p/gnudatalanguage/svn/trunk/gdl gdl-0.9.9/scripts/minimum_script4gdl.sh000077500000000000000000000261611340051421000201330ustar00rootroot00000000000000#!/bin/bash # # Alain Coulais, 3 Mars 2015, script under GNU GPL v3 # # option "5" --> Vanilla; option "6" --> Git Master # # Changes: # 2015-11-06 : cmake is now in httpS, allow to jump to a given step via $1 # 2016-01-04 : move to 0.9.6 # 2017-01-21 : move to 0.9.7 # 2017-01-31 : fixing various improvments, # properly skipping Readline/GSL/Cmake if available # 2017-02-01 : plplot 5.9.11 had critical problem with CMake 3+ # --> if CMake 3.2 around (OSX), use plplot 5.11.1 # (different policy on Linux) # 2018-01-19 : move from CVS (deprecated at SF) to SVN # 2018-08-01 : move from SVN to GIThub # change plplot to 5.13.0 (OSX) or 5.12 (other) # flag for OpenMP (OSX) # 2018-08-07 : force cmake 3+, force plplot 5.12 or 5.13 # # The purpose of this shell script is to automaticaly compile a minimum GDL # as a basic user even if mandatory packages are not available # # Since FFTw and Eigen3 are not used here, it does not reflect # the best performances you can have with GDL. # # To do that, the TGZ of useful dependancies are downloaded then compiled # (with "curl" because Curl is by default on OSX) # When a dependancy is downloaded but something goes bad, # you can fix the script and run it again, downloading is not done again, # and succesfull compilations not done again # # We prefer to strongly limit the use of options and flags ... # Please remove manually local directories if needed (if troubles) # # Since 2015 Nov. 6, we can jump over steps already done # no step : all is done # step 1 : readline # step 2 : GSL # step 3 : CMake # step 4 : Plplot # step 5 : GDL 0.9.8 vanilla # step 6 : GDL 0.9.8 Git # # $1 == $use_curl, $2 = $URL, $3 = $filename run_wget_or_curl(){ if [ $1 -eq 1 ] ; then curl $2 -O else wget $2 fi } run_wget_or_curl_no_check(){ if [ $1 -eq 1 ] ; then curl -L --insecure $2 -o $3 else wget --no-check-certificate $2 -O $3 fi } run_wget_or_curl_v2(){ if [ $1 -eq 1 ] ; then curl -L $2 -o $3 else wget $2 -O $3 fi } # # $1 = $filename, $2 = $expected_md5sum check_md5sum(){ OS="`uname`" if [ $OS = 'Darwin' ] ; then md5value=`md5 -r $1 | cut -c -32` else md5value=`md5sum $1 | cut -c -32` fi if [ $md5value != $2 ] ; then echo 'Bad MD5sum check for : '$1 exit fi } # URL we use (revised on 2018 Aug. 7) # READLINE_URL="ftp://ftp.gnu.org/gnu/readline/readline-6.3.tar.gz" GSL_URL="ftp://ftp.gnu.org/gnu/gsl/gsl-1.16.tar.gz" # PLPLOT_URL512="https://sourceforge.net/projects/plplot/files/plplot/5.12.0%20Source/plplot-5.12.0.tar.gz/download?use_mirror=autoselect" PLPLOT_URL513="https://sourceforge.net/projects/plplot/files/plplot/5.13.0%20Source/plplot-5.13.0.tar.gz/download?use_mirror=autoselect" # GDL_VANILLA_URL="http://downloads.sourceforge.net/project/gnudatalanguage/gdl/0.9.8/gdl-0.9.8.tgz" GDL_CVS_URL="http://gnudatalanguage.cvs.sourceforge.net/viewvc/gnudatalanguage/gdl/?view=tar" GDL_SVN_URL="https://svn.code.sf.net/p/gnudatalanguage/svn/trunk/gdl" GDL_GIT_URL="https://codeload.github.com/gnudatalanguage/gdl/zip/master" # step=$1 if [ -z "$1" ] ; then echo "No STEP (numerical) argument supplied" step=1 fi # export RACINE=$PWD # # AC 2018-08-01 : obsolete : no more SVN # # switch it to 1 to have the SVN snapshot #gdl_svn=0 #if [[ $step == 6 ]] ; then # command -v svn >/dev/null 2>&1 || { echo >&2 "SVN (Subversion) not found." #; exit;} # gdl_svn=1 #fi gdl_git=0 if [[ $step == 6 ]] ; then # we don't need "git" program, just "unzip" gdl_git=1 fi # switch it to 1 to have the final checks for GDL gdl_check=0 # CPU Core number, switch it to 1 if you don't want to overload cpus=`getconf _NPROCESSORS_ONLN` # curl or wget # (curl seems to be always present on OSX, wget on GNU/Linux) use_curl=1 use_wget=1 command -v curl >/dev/null 2>&1 || { echo >&2 "Curl not found." ; use_curl=0;} command -v wget >/dev/null 2>&1 || { echo >&2 "Wget not found." ; use_wget=0;} echo "Curl ? : " $use_curl echo "Wget ? : " $use_wget # # take care of "dash" on Debian/Ubuntu # https://wiki.ubuntu.com/DashAsBinSh if [ "${use_curl}" = "0" ] && [ "${use_wget}" = "0" ] ; then echo "both Curl and Wget are missing ... you must provide at least one of them !" exit fi # ----------------------------------- READLINE ----------------------- # starting READLINE : if READLINE not found in default places or # already compile locally, we compile it echo "** preparing READLINE" cd $RACINE # READLINE_PATH="" # # "official" READLINE on OSX is a mess # os_type=`uname -s` if [ $os_type != Darwin ] ; then if [ -d "/usr/include/readline" ] ; then READLINE_PATH=/usr elif [ -d "/usr/local/include/readline" ] ; then READLINE_PATH=/usr/local fi fi # Do we have already locally compile Readline ? if [ -n $READLINE_PATH ] ; then if [ -d $RACINE/readline-6.3/Compilation/ ] ; then READLINE_PATH=$RACINE/readline-6.3/Compilation/ fi fi if [ -n $READLINE_PATH ] ; then echo "READLINE PATH : "$READLINE_PATH echo "READLINE (re)compilation SKIPPED !" fi # if [[ $step -le 1 && -z $READLINE_PATH ]] ; then if [ ! -e readline-6.3.tar.gz ] ; then run_wget_or_curl $use_curl $READLINE_URL fi tar -zxf readline-6.3.tar.gz cd readline-6.3 mkdir Compilation ./configure --prefix=$RACINE/readline-6.3/Compilation/ make -s make install READLINE_PATH=$RACINE/readline-6.3/Compilation/ echo "readline Compilation done" fi # ----------------------------------- GSL ----------------------- # starting GSL : if GSL not found in default places or # already locally compiled, we compile it locally. # echo "** preparing GSL" cd $RACINE GSL_CONFIG=`which -a gsl-config` if [ -z $GSL_CONFIG ] ; then if [ -x $RACINE/gsl-1.16/Compilation/bin/gsl-config ] ; then GSL_PATH=`$RACINE/gsl-1.16/Compilation/bin/gsl-config --prefix` else GSL_PATH="" fi else GSL_PATH=`gsl-config --prefix` fi if [ -n $GSL_PATH ] ; then echo "GSL PATH : "$GSL_PATH echo "GSL found, version : "`$GSL_PATH/bin/gsl-config --version` echo "GSL (re)compilation SKIPPED !" fi # if [[ $step -le 2 && -z $GSL_PATH ]] ; then if [ ! -e gsl-1.16.tar.gz ] ; then run_wget_or_curl $use_curl $GSL_URL fi tar -zxf gsl-1.16.tar.gz cd gsl-1.16 mkdir Compilation ./configure --prefix=$RACINE/gsl-1.16/Compilation/ make -s make install GSL_PATH=$RACINE/gsl-1.16 echo "GSL compilation done, version : 1.16" fi # ----------------------------------- CMAKE ----------------------- # starting CMAKE : since mid-2018, we force Cmake to be > 3.0.2 echo "** preparing CMAKE" cd $RACINE # do_cmake_compil=1 CmakeEXE=`which -a cmake` #echo "CMake exe : " $CmakeEXE if [ -x $CmakeEXE ] ; then cmake_version=`cmake --version | head -1 | awk -F " " '{print $3}'` if [[ ${cmake_version:0:1} < "3" ]] ; then echo "old CMake version ("$cmake_version") found, a new one must be used" else do_cmake_compil=0 fi fi # if [[ $do_cmake_compil -eq 1 ]] ; then CMAKE_URL="https://cmake.org/files/v3.2/cmake-3.2.3.tar.gz" CMAKE_MD5="d51c92bf66b1e9d4fe2b7aaedd51377c" CMAKE_NAME=cmake-3.2.3.tar.gz CMAKE_DIR=cmake-3.2.3 fi # if [[ $do_cmake_compil -eq 1 && -x $RACINE/$CMAKE_DIR/bin/cmake ]] ; then CmakeEXE=$RACINE/$CMAKE_DIR/bin/cmake cmake_version=`$CmakeEXE --version | head -1 | awk -F " " '{print $3}'` do_cmake_compil=0 fi if [ -n $CmakeEXE ] ; then echo "CMake EXE : "$CmakeEXE echo "CMake found, version : "$cmake_version echo "CMake (re)compilation SKIPPED !" fi # if [[ $step -le 3 && $do_cmake_compil -eq 1 ]] ; then if [ ! -e $CMAKE_NAME ] ; then ## since Nov. 6, we do have a problem with KitWare certificate ... run_wget_or_curl_no_check $use_curl $CMAKE_URL $CMAKE_NAME fi check_md5sum $CMAKE_NAME $CMAKE_MD5 # tar -zxf $CMAKE_NAME cd $CMAKE_DIR ./bootstrap make -s echo "CMake compilation done, version $CMAKE_DIR" CmakeEXE=$PWD/bin/cmake cmake_version=`$CmakeEXE --version | head -1 | awk -F " " '{print $3}'` fi # ----------------------------------- PLPLOT ----------------------- # starting PLPLOT : we don't want to use packaged PLplot version # because of various issues. The options used here ensure stable results. echo "** preparing PLPLOT" cd $RACINE # # AC 2018-08-07 : succesfully tested on OSX 10.11, 10.12 & 10.13 # with cmake 3.11.3 from Brew if [ $os_type == Darwin ] ; then PLPLOT_URL=$PLPLOT_URL513 PLPLOT_MD5="bfefeae7fb9a23377c6dc37b44a7da8a" PLPLOT_NAME=plplot-5.13.0.tar.gz PLPLOT_DIR=plplot-5.13.0 else PLPLOT_URL=$PLPLOT_URL512 PLPLOT_MD5="998a05be218e5de8f2faf988b8dbdc51" PLPLOT_NAME=plplot-5.12.0.tar.gz PLPLOT_DIR=plplot-5.12.0 fi # if [[ $step -le 4 ]] ; then if [ ! -e $PLPLOT_NAME ] ; then run_wget_or_curl_no_check $use_curl $PLPLOT_URL $PLPLOT_NAME fi check_md5sum $PLPLOT_NAME $PLPLOT_MD5 # tar -zxf $PLPLOT_NAME cd $PLPLOT_DIR mkdir Compilation cd Compilation $CmakeEXE .. -DCMAKE_INSTALL_PREFIX=. -DENABLE_ADA=off \ -DENABLE_f95=off -DENABLE_fortran=off \ -DENABLE_python=OFF -DENABLE_java=off -DENABLE_qt=off \ -DENABLE_tk=off -DENABLE_tcl=off -DPLD_aqt=off \ -DPLD_psttf=off -DPLD_wxwidgets=OFF -DDEFAULT_NO_CAIRO_DEVICES=ON make -s -j $cpus make install echo "Plplot done" else echo "Plplot SKIPPED !" fi # ----------------------------------- GDL ----------------------- # starting GDL : 2 cases : with the SVN or the 0.9.7 vanilla version # we don't need to manage the step here ... (always 5 or 6) echo "** preparing GDL" cd $RACINE # # SVN Obsolete #if [ "$gdl_svn" -eq 1 ] ; then # echo "preparing to compiled GDL 0.9.7 SVN version" # gdl_path='gdl-0.9.7svn'`date +%y%m%d` # svn checkout $GDL_SVN_URL $gdl_path if [ "$gdl_git" -eq 1 ] ; then echo "preparing to compiled GDL 0.9.8 Git version" gdl_path='gdl-0.9.8git'`date +%y%m%d` gdl_name=${gdl_path}'.tgz' if [ ! -e $gdl_name ] ; then run_wget_or_curl_v2 $use_curl $GDL_GIT_URL $gdl_name fi unzip $gdl_name mv gdl-master $gdl_path else echo "preparing to compiled GDL 0.9.8 VANILLA version" gdl_path='gdl-0.9.8' gdl_name=${gdl_path}'.tgz' if [ ! -e $gdl_name ] ; then run_wget_or_curl_v2 $use_curl $GDL_VANILLA_URL $gdl_name fi tar -zxf $gdl_name fi # # 2018-08-01 The default OSX CLang version does not support OpenMP if [ $os_type == Darwin ] ; then flag_openmp=OFF else flag_openmp=ON fi # cd $gdl_path if [ -d "build" ]; then \rm build/ else mkdir build fi cd build $CmakeEXE .. \ -DREADLINEDIR=$READLINE_PATH -DGEOTIFF=off \ -DGSLDIR=$GSL_PATH -DOPENMP=$flag_openmp \ -DPLPLOTDIR=$RACINE/$PLPLOT_DIR/Compilation/ \ -DWXWIDGETS=off -DMAGICK=OFF -DNETCDF=OFF -DHDF=OFF \ -DHDF5=off -DFFTW=OFF -DEIGEN3=OFF -DPSLIB=OFF -DPYTHON=OFF make -s -j $cpus # if [ "$gdl_check" -eq 1 ] ; then make check fi # cd $RACINE # if [ -x $gdl_path/src/gdl ] ; then echo -e "\nCompilation of GDL is finished" echo "Please remember it does not reflect the full capabilities of GDL" echo -e "\nYou can run GDL calling : \n" echo -e "\tsh "$gdl_path"/quick_start_GDL.sh\n" else echo -e "\nIt seems a problem occured during the compilation of GDL" echo "Please check carrefully the outputs" fi gdl-0.9.9/scripts/rpm4gdl.sh000077500000000000000000000032741340051421000156720ustar00rootroot00000000000000# # Alain C. and Ilia N. : June 2015 # A simple script to help end users who can be sudo to add # as much as possible dependances needed for GDL compilation # BEFORE runing "cmake" # # On Debian or Ubuntu systems, we need the "dpkg-query" # command to check wether the packages are installed. # # On RPM-based systems (CentOs, Fedora, RH, Suse, Mageia ...) # we try to use just "rpm -qa" # # know problem : CentOS 5: libX11-devel, Suse 11 : xorg-x11-devel # echo 'Please wait ! need some time.' echo ' ' # mandatory_dep_list=("readline-devel" "zlib-devel" "libpng-devel" "gsl-devel" "plplot-devel" "libX11-devel" "xorg-x11-devel") # dep_to_aptget="" # for dep in ${mandatory_dep_list[*]}; do # echo $dep status=$(rpm -qa $dep 2>/dev/null | grep -c "$dep") #| grep -c "$dep") #echo $status $dep if [[ ${status} -eq 0 ]] ; then dep_to_aptget=$dep_to_aptget" "$dep fi done # #echo ${mandatory_dep_list[*]} if [[ ${#dep_to_aptget} -gt 0 ]] ; then echo "Missing Mandatory packages you need to install :" echo "sudo rpm -i"${dep_to_aptget} else echo "NO Missing Mandatory packages" fi # dep_to_aptget="" extra_dep_list=(GraphicsMagick-c++-devel ImageMagick-c++-devel wxGTK-devel netcdf-devel hdf5-devel fftw-devel python-devel udunits2-devel eigen3-devel pslib-devel grib_api-devel) # for dep in ${extra_dep_list[*]}; do status=$(rpm -qa $dep 2>/dev/null | grep -c "$dep") #echo $status $dep if [[ ${status} -eq 0 ]] ; then dep_to_aptget=$dep_to_aptget" "$dep fi done # echo "" if [[ ${#dep_to_aptget} -gt 0 ]] ; then echo "Missing packages you may would like to install :" echo "sudo rpm -i"${dep_to_aptget} else echo "NO missing extra packages" fi gdl-0.9.9/scripts/update_gdl_CVS.sh000077500000000000000000000011621340051421000171360ustar00rootroot00000000000000# # AC 21/01/2008 # update an already existing CVS with sub-directories # should be run at top of the root of the CVS (e.g. gdl/) # echo '------------------------------------------------------------' echo 'CVS disconnected on SourceForge since end of November 2017 ' echo '' echo 'You must use the SVN version !' echo '------------------------------------------------------------' exit echo 'just press enter for the passwd !' echo '' # CVS_PATH=/cvsroot/gnudatalanguage CVS_SITE=anonymous@gnudatalanguage.cvs.sourceforge.net # cvs -d:pserver:$CVS_SITE:$CVS_PATH login cvs -z3 -d:pserver:$CVS_SITE:$CVS_PATH update -d gdl # gdl-0.9.9/scripts/update_gdl_SVN.sh000077500000000000000000000002421340051421000171470ustar00rootroot00000000000000# # AC 07/12/2017 # # update an already existing SVN with sub-directories # should be run at top of the root of the CVS (e.g. gdl/) # cd gdl svn update cd .. # gdl-0.9.9/scripts/which_packages_to_add.sh000077500000000000000000000012051340051421000205630ustar00rootroot00000000000000 if [[ -z /etc/issue ]] ; then line=`sed "/^[ \t]*$/d" /etc/issue | cut -d' ' -f1 | head -1` fi #lower case line=${line,,} # list_RPM_GNULinux=(suse mageia centos redhat) list_APT_GNULinux=(debian ubuntu mint) # rpm=0 for os in ${list_RPM_GNULinux[*]}; do echo $line $os if [[ "$line" =~ "${$os}" ]]; then rpm=1 fi done apt=0 for os in ${list_APT_GNULinux[*]}; do echo $line $os if [[ "$line" =~ "${$os}" ]]; then apt=1 fi done if [[ $apt -eq 0 ]] && [[ $rpm -eq 0 ]] ; then echo "unknown system, please report !" fi if [[ $apt -eq 1 ]] ; then aptget4gdl.sh fi if [[ $rpm -eq 1 ]] ; then rpm4gdl.sh fi gdl-0.9.9/src/000077500000000000000000000000001340051421000130545ustar00rootroot00000000000000gdl-0.9.9/src/CFMTLexer.cpp000066400000000000000000000711401340051421000153140ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "cformat.g" -> "CFMTLexer.cpp"$ */ #include "includefirst.hpp" #include #include "CFMTLexer.hpp" #include #include #include #include #include #include #include CFMTLexer::CFMTLexer(std::istream& in) : antlr::CharScanner(new antlr::CharBuffer(in),true) { initLiterals(); } CFMTLexer::CFMTLexer(antlr::InputBuffer& ib) : antlr::CharScanner(ib,true) { initLiterals(); } CFMTLexer::CFMTLexer(const antlr::LexerSharedInputState& state) : antlr::CharScanner(state,true) { initLiterals(); } void CFMTLexer::initLiterals() { } antlr::RefToken CFMTLexer::nextToken() { antlr::RefToken theRetToken; for (;;) { antlr::RefToken theRetToken; int _ttype = antlr::Token::INVALID_TYPE; resetText(); try { // for lexical and char stream error handling if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff))) { mCSTYLE(true); theRetToken=_returnToken; } else { if (LA(1)==EOF_CHAR) { uponEOF(); _returnToken = makeToken(antlr::Token::EOF_TYPE); } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } if ( !_returnToken ) goto tryAgain; // found SKIP token _ttype = _returnToken->getType(); _ttype = testLiteralsTable(_ttype); _returnToken->setType(_ttype); return _returnToken; } catch (antlr::RecognitionException& e) { throw antlr::TokenStreamRecognitionException(e); } catch (antlr::CharStreamIOException& csie) { throw antlr::TokenStreamIOException(csie.io); } catch (antlr::CharStreamException& cse) { throw antlr::TokenStreamException(cse.getMessage()); } tryAgain:; } } void CFMTLexer::mCSTYLE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSTYLE; std::string::size_type _saveIndex; if (((_tokenSet_0.member(LA(1))) && (true))&&( format)) { { switch ( LA(1)) { case 0x42 /* 'B' */ : case 0x44 /* 'D' */ : case 0x45 /* 'E' */ : case 0x46 /* 'F' */ : case 0x47 /* 'G' */ : case 0x49 /* 'I' */ : case 0x4f /* 'O' */ : case 0x53 /* 'S' */ : case 0x58 /* 'X' */ : case 0x5a /* 'Z' */ : case 0x62 /* 'b' */ : case 0x64 /* 'd' */ : case 0x65 /* 'e' */ : case 0x66 /* 'f' */ : case 0x67 /* 'g' */ : case 0x69 /* 'i' */ : case 0x6f /* 'o' */ : case 0x73 /* 's' */ : case 0x78 /* 'x' */ : case 0x7a /* 'z' */ : { { { switch ( LA(1)) { case 0x44 /* 'D' */ : case 0x64 /* 'd' */ : { mCD(false); _ttype = CD; break; } case 0x65 /* 'e' */ : { mCSE(false); _ttype = CSE; break; } case 0x45 /* 'E' */ : { mCE(false); _ttype = CE; break; } case 0x49 /* 'I' */ : case 0x69 /* 'i' */ : { mCI(false); _ttype = CI; break; } case 0x46 /* 'F' */ : case 0x66 /* 'f' */ : { mCF(false); _ttype = CF; break; } case 0x67 /* 'g' */ : { mCSG(false); _ttype = CSG; break; } case 0x47 /* 'G' */ : { mCG(false); _ttype = CG; break; } case 0x4f /* 'O' */ : case 0x6f /* 'o' */ : { mCO(false); _ttype = CO; break; } case 0x42 /* 'B' */ : case 0x62 /* 'b' */ : { mCB(false); _ttype = CB; break; } case 0x53 /* 'S' */ : case 0x73 /* 's' */ : { mCS(false); _ttype = CS; break; } case 0x58 /* 'X' */ : case 0x78 /* 'x' */ : { mCX(false); _ttype = CX; break; } case 0x5a /* 'Z' */ : case 0x7a /* 'z' */ : { mCZ(false); _ttype = CZ; break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } format = false; } break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { mCNUMBER(false); _ttype = CNUMBER; break; } case 0x2e /* '.' */ : { mCDOT(false); _ttype = CDOT; break; } case 0x9 /* '\t' */ : case 0x20 /* ' ' */ : { mCWS(false); _ttype=antlr::Token::SKIP; break; } default: if ((LA(1) == 0x2b /* '+' */ ) && (LA(2) == 0x2d /* '-' */ )) { mPM(false); _ttype = PM; } else if ((LA(1) == 0x2d /* '-' */ ) && (LA(2) == 0x2b /* '+' */ )) { mMP(false); _ttype = MP; } else if ((LA(1) == 0x2d /* '-' */ ) && (true)) { mMOINS(false); _ttype = MOINS; } else if ((LA(1) == 0x2b /* '+' */ ) && (true)) { mPLUS(false); _ttype = PLUS; } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } else if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff)) && (true)) { mCSTR(false); _ttype = CSTR; } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCD(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CD; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x64 /* 'd' */ : { match('d' /* charlit */ ); break; } case 0x44 /* 'D' */ : { match('D' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCSE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSE; std::string::size_type _saveIndex; { match('e' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CE; std::string::size_type _saveIndex; { match('E' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CI; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x69 /* 'i' */ : { match('i' /* charlit */ ); break; } case 0x49 /* 'I' */ : { match('I' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCF(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CF; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x66 /* 'f' */ : { match('f' /* charlit */ ); break; } case 0x46 /* 'F' */ : { match('F' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCSG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSG; std::string::size_type _saveIndex; { match('g' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CG; std::string::size_type _saveIndex; { match('G' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCO(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CO; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x6f /* 'o' */ : { match('o' /* charlit */ ); break; } case 0x4f /* 'O' */ : { match('O' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCB(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CB; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x62 /* 'b' */ : { match('b' /* charlit */ ); break; } case 0x42 /* 'B' */ : { match('B' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CS; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x73 /* 's' */ : { match('s' /* charlit */ ); break; } case 0x53 /* 'S' */ : { match('S' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCX(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CX; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x78 /* 'x' */ : { match('x' /* charlit */ ); break; } case 0x58 /* 'X' */ : { match('X' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCZ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CZ; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x7a /* 'z' */ : { match('z' /* charlit */ ); break; } case 0x5a /* 'Z' */ : { match('Z' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mPM(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PM; std::string::size_type _saveIndex; { match('+' /* charlit */ ); match('-' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mMP(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MP; std::string::size_type _saveIndex; { match('-' /* charlit */ ); match('+' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mMOINS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MOINS; std::string::size_type _saveIndex; match('-' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mPLUS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PLUS; std::string::size_type _saveIndex; match('+' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCNUMBER(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CNUMBER; std::string::size_type _saveIndex; mDIGITS(false); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCDOT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CDOT; std::string::size_type _saveIndex; match('.' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCWS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CWS; std::string::size_type _saveIndex; { // ( ... )+ int _cnt75=0; for (;;) { switch ( LA(1)) { case 0x20 /* ' ' */ : { match(' ' /* charlit */ ); break; } case 0x9 /* '\t' */ : { match('\t' /* charlit */ ); break; } default: { if ( _cnt75>=1 ) { goto _loop75; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } } _cnt75++; } _loop75:; } // ( ... )+ if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCSTR(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSTR; std::string::size_type _saveIndex; if ((((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff)) && (true))&&( doubleQuotes)) { { mCSTR1(false); { switch ( LA(1)) { case 0x22 /* '\"' */ : { _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); selector->pop(); break; } case 0x25 /* '%' */ : { _saveIndex = text.length(); match('%' /* charlit */ ); text.erase(_saveIndex); format = true; break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } } else if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff)) && (true)) { { mCSTR2(false); { switch ( LA(1)) { case 0x27 /* '\'' */ : { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); selector->pop(); break; } case 0x25 /* '%' */ : { _saveIndex = text.length(); match('%' /* charlit */ ); text.erase(_saveIndex); format = true; break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCSTR1(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSTR1; std::string::size_type _saveIndex; { // ( ... )* for (;;) { if ((LA(1) == 0x25 /* '%' */ ) && (LA(2) == 0x25 /* '%' */ )) { _saveIndex = text.length(); match('%' /* charlit */ ); text.erase(_saveIndex); match('%' /* charlit */ ); } else if ((LA(1) == 0x5c /* '\\' */ )) { mESC(false); } else if ((_tokenSet_1.member(LA(1)))) { { match(_tokenSet_1); } } else { goto _loop13; } } _loop13:; } // ( ... )* if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mCSTR2(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSTR2; std::string::size_type _saveIndex; { // ( ... )* for (;;) { if ((LA(1) == 0x25 /* '%' */ ) && (LA(2) == 0x25 /* '%' */ )) { _saveIndex = text.length(); match('%' /* charlit */ ); text.erase(_saveIndex); match('%' /* charlit */ ); } else if ((LA(1) == 0x5c /* '\\' */ )) { mESC(false); } else if ((_tokenSet_2.member(LA(1)))) { { match(_tokenSet_2); } } else { goto _loop17; } } _loop17:; } // ( ... )* if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mESC(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = ESC; std::string::size_type _saveIndex; _saveIndex = text.length(); match('\\' /* charlit */ ); text.erase(_saveIndex); { switch ( LA(1)) { case 0x41 /* 'A' */ : case 0x61 /* 'a' */ : { { switch ( LA(1)) { case 0x61 /* 'a' */ : { match('a' /* charlit */ ); break; } case 0x41 /* 'A' */ : { match('A' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\7"; }; break; } case 0x42 /* 'B' */ : case 0x62 /* 'b' */ : { { switch ( LA(1)) { case 0x62 /* 'b' */ : { match('b' /* charlit */ ); break; } case 0x42 /* 'B' */ : { match('B' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\b"; }; break; } case 0x46 /* 'F' */ : case 0x66 /* 'f' */ : { { switch ( LA(1)) { case 0x66 /* 'f' */ : { match('f' /* charlit */ ); break; } case 0x46 /* 'F' */ : { match('F' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\f"; }; break; } case 0x4e /* 'N' */ : case 0x6e /* 'n' */ : { { switch ( LA(1)) { case 0x6e /* 'n' */ : { match('n' /* charlit */ ); break; } case 0x4e /* 'N' */ : { match('N' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\n"; }; break; } case 0x52 /* 'R' */ : case 0x72 /* 'r' */ : { { switch ( LA(1)) { case 0x72 /* 'r' */ : { match('r' /* charlit */ ); break; } case 0x52 /* 'R' */ : { match('R' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\r"; }; break; } case 0x54 /* 'T' */ : case 0x74 /* 't' */ : { { switch ( LA(1)) { case 0x74 /* 't' */ : { match('t' /* charlit */ ); break; } case 0x54 /* 'T' */ : { match('T' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\t"; }; break; } case 0x56 /* 'V' */ : case 0x76 /* 'v' */ : { { switch ( LA(1)) { case 0x76 /* 'v' */ : { match('v' /* charlit */ ); break; } case 0x56 /* 'V' */ : { match('V' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { text.erase(_begin); text += "\13"; }; break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : { mOCTESC(false); break; } case 0x58 /* 'X' */ : case 0x78 /* 'x' */ : { { switch ( LA(1)) { case 0x78 /* 'x' */ : { match('x' /* charlit */ ); break; } case 0x58 /* 'X' */ : { match('X' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } mHEXESC(false); break; } default: if ((_tokenSet_3.member(LA(1)))) { { match(_tokenSet_3); } } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mOCTESC(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = OCTESC; std::string::size_type _saveIndex; mODIGIT(false); { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x37 /* '7' */ )) && ((LA(2) >= 0x3 /* '\3' */ && LA(2) <= 0xff))) { mODIGIT(false); { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x37 /* '7' */ )) && ((LA(2) >= 0x3 /* '\3' */ && LA(2) <= 0xff))) { mODIGIT(false); } else if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff)) && (true)) { } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } else if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff)) && (true)) { } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } std::string s = text.substr(_begin,text.length()-_begin); char c = static_cast(strtoul(s.c_str(),NULL,8)); { text.erase(_begin); text += c; }; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mHEXESC(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = HEXESC; std::string::size_type _saveIndex; mHDIGIT(false); { if ((_tokenSet_4.member(LA(1))) && ((LA(2) >= 0x3 /* '\3' */ && LA(2) <= 0xff))) { mHDIGIT(false); } else if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff)) && (true)) { } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } std::string s = text.substr(_begin,text.length()-_begin); char c = static_cast(strtoul(s.c_str(),NULL,16)); { text.erase(_begin); text += c; }; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mODIGIT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = ODIGIT; std::string::size_type _saveIndex; { matchRange('0','7'); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mHDIGIT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = HDIGIT; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { matchRange('0','9'); break; } case 0x61 /* 'a' */ : case 0x62 /* 'b' */ : case 0x63 /* 'c' */ : case 0x64 /* 'd' */ : case 0x65 /* 'e' */ : case 0x66 /* 'f' */ : { matchRange('a','f'); break; } case 0x41 /* 'A' */ : case 0x42 /* 'B' */ : case 0x43 /* 'C' */ : case 0x44 /* 'D' */ : case 0x45 /* 'E' */ : case 0x46 /* 'F' */ : { matchRange('A','F'); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void CFMTLexer::mDIGITS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DIGITS; std::string::size_type _saveIndex; { // ( ... )+ int _cnt71=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { matchRange('0','9'); } else { if ( _cnt71>=1 ) { goto _loop71; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt71++; } _loop71:; } // ( ... )+ if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } const unsigned long CFMTLexer::_tokenSet_0_data_[] = { 512UL, 67069953UL, 84443892UL, 84443892UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x9 const antlr::BitSet CFMTLexer::_tokenSet_0(_tokenSet_0_data_,10); const unsigned long CFMTLexer::_tokenSet_1_data_[] = { 4294967288UL, 4294967259UL, 4026531839UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 // 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f const antlr::BitSet CFMTLexer::_tokenSet_1(_tokenSet_1_data_,16); const unsigned long CFMTLexer::_tokenSet_2_data_[] = { 4294967288UL, 4294967135UL, 4026531839UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 // 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f const antlr::BitSet CFMTLexer::_tokenSet_2(_tokenSet_2_data_,16); const unsigned long CFMTLexer::_tokenSet_3_data_[] = { 4294967288UL, 4278255615UL, 4272668601UL, 4272668601UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 // 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f const antlr::BitSet CFMTLexer::_tokenSet_3(_tokenSet_3_data_,16); const unsigned long CFMTLexer::_tokenSet_4_data_[] = { 0UL, 67043328UL, 126UL, 126UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; const antlr::BitSet CFMTLexer::_tokenSet_4(_tokenSet_4_data_,10); gdl-0.9.9/src/CFMTLexer.hpp000066400000000000000000000053251340051421000153230ustar00rootroot00000000000000#ifndef INC_CFMTLexer_hpp_ #define INC_CFMTLexer_hpp_ #include /* $ANTLR 2.7.7 (2006-11-01): "cformat.g" -> "CFMTLexer.hpp"$ */ #include #include #include #include "CFMTTokenTypes.hpp" #include #include // using namespace antlr; class CUSTOM_API CFMTLexer : public antlr::CharScanner, public CFMTTokenTypes { private: antlr::TokenStreamSelector* selector; bool doubleQuotes; bool format; public: void SetSelector( antlr::TokenStreamSelector& s) { selector = &s; } void DoubleQuotes( bool dQ) { doubleQuotes = dQ; format=false; } private: void initLiterals(); public: bool getCaseSensitiveLiterals() const { return false; } public: CFMTLexer(std::istream& in); CFMTLexer(antlr::InputBuffer& ib); CFMTLexer(const antlr::LexerSharedInputState& state); antlr::RefToken nextToken(); public: void mCSTYLE(bool _createToken); protected: void mCD(bool _createToken); protected: void mCSE(bool _createToken); protected: void mCE(bool _createToken); protected: void mCI(bool _createToken); protected: void mCF(bool _createToken); protected: void mCSG(bool _createToken); protected: void mCG(bool _createToken); protected: void mCO(bool _createToken); protected: void mCB(bool _createToken); protected: void mCS(bool _createToken); protected: void mCX(bool _createToken); protected: void mCZ(bool _createToken); protected: void mPM(bool _createToken); protected: void mMP(bool _createToken); protected: void mMOINS(bool _createToken); protected: void mPLUS(bool _createToken); protected: void mCNUMBER(bool _createToken); protected: void mCDOT(bool _createToken); protected: void mCWS(bool _createToken); protected: void mCSTR(bool _createToken); protected: void mCSTR1(bool _createToken); protected: void mCSTR2(bool _createToken); protected: void mESC(bool _createToken); protected: void mOCTESC(bool _createToken); protected: void mHEXESC(bool _createToken); protected: void mODIGIT(bool _createToken); protected: void mHDIGIT(bool _createToken); protected: void mDIGITS(bool _createToken); private: static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; static const unsigned long _tokenSet_2_data_[]; static const antlr::BitSet _tokenSet_2; static const unsigned long _tokenSet_3_data_[]; static const antlr::BitSet _tokenSet_3; static const unsigned long _tokenSet_4_data_[]; static const antlr::BitSet _tokenSet_4; }; #endif /*INC_CFMTLexer_hpp_*/ gdl-0.9.9/src/CFMTTokenTypes.hpp000066400000000000000000000013171340051421000163460ustar00rootroot00000000000000#ifndef INC_CFMTTokenTypes_hpp_ #define INC_CFMTTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "cformat.g" -> "CFMTTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API CFMTTokenTypes { #endif enum { EOF_ = 1, CSTYLE = 4, CSTR = 5, CSTR1 = 6, CSTR2 = 7, ESC = 8, OCTESC = 9, ODIGIT = 10, HEXESC = 11, HDIGIT = 12, CD = 13, CSE = 14, CE = 15, CI = 16, CF = 17, CSG = 18, CG = 19, CO = 20, CB = 21, CS = 22, CX = 23, CZ = 24, CDOT = 25, PM = 26, MP = 27, PLUS = 28, MOINS = 29, DIGITS = 30, CNUMBER = 31, CWS = 32, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_CFMTTokenTypes_hpp_*/ gdl-0.9.9/src/CFMTTokenTypes.txt000066400000000000000000000004721340051421000163770ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): cformat.g -> CFMTTokenTypes.txt$ CFMT // output token vocab name CSTYLE=4 CSTR=5 CSTR1=6 CSTR2=7 ESC=8 OCTESC=9 ODIGIT=10 HEXESC=11 HDIGIT=12 CD=13 CSE=14 CE=15 CI=16 CF=17 CSG=18 CG=19 CO=20 CB=21 CS=22 CX=23 CZ=24 CDOT=25 PM=26 MP=27 PLUS=28 MOINS=29 DIGITS=30 CNUMBER=31 CWS=32 gdl-0.9.9/src/CMakeLists.txt000066400000000000000000000134071340051421000156210ustar00rootroot00000000000000set(SOURCES CFMTLexer.cpp CFMTLexer.hpp CFMTTokenTypes.hpp FMTIn.cpp FMTIn.hpp FMTInTokenTypes.hpp FMTLexer.cpp FMTLexer.hpp FMTOut.cpp FMTOut.hpp FMTOutTokenTypes.hpp FMTParser.cpp FMTParser.hpp FMTTokenTypes.hpp GDLInterpreter.cpp GDLInterpreter.hpp GDLInterpreterTokenTypes.hpp GDLLexer.cpp GDLLexer.hpp GDLParser.cpp GDLParser.hpp GDLTokenTypes.hpp GDLTreeParser.cpp GDLTreeParser.hpp GDLTreeParserTokenTypes.hpp datatypes.cpp datatypes.hpp datatypesref.cpp datatypes_minmax.cpp accessdesc.hpp allix.hpp allix.cpp arrayindex.cpp arrayindex.hpp arrayindexlistt.hpp arrayindexlistnoassoct.hpp assocdata.cpp assocdata.hpp basegdl.cpp basegdl.hpp basic_fun.cpp basic_fun.hpp basic_fun_cl.cpp basic_fun_cl.hpp basic_fun_jmg.cpp basic_fun_jmg.hpp basic_op.cpp calendar.hpp calendar.cpp cformat.g color.cpp color.hpp convert2.cpp convol.cpp datalistt.hpp dcommon.cpp dcommon.hpp dcompiler.cpp dcompiler.hpp default_io.cpp deviceps.hpp devicesvg.hpp devicez.hpp dimension.hpp dialog.cpp dialog.hpp dinterpreter.cpp dinterpreter.hpp dnode.cpp dnode.hpp dnodefactory.hpp dpro.cpp dpro.hpp dstructdesc.cpp dstructdesc.hpp dstructfactory.cxx dstructfactory.hxx dstructgdl.cpp dstructgdl.hpp dvar.cpp dvar.hpp envt.cpp envt.hpp extrat.cpp extrat.hpp exists_fun.cpp exists_fun.hpp fftw.cpp fftw.hpp file.cpp file.hpp fmtnode.cpp fmtnode.hpp format.g format.in.g format.out.g gdlc.g gdlc.i.g gdlc.tree.g gdleventhandler.cpp gdleventhandler.hpp gdlexception.cpp gdlexception.hpp gdlgstream.cpp gdlgstream.hpp dSFMT/dSFMT.c ) if(WIN32) set(SOURCES ${SOURCES} gdlwinstream.cpp gdlwinstream.hpp gtdhelper.cpp gtdhelper.hpp devicewin.hpp devicewin.cpp ) else(WIN32) set(SOURCES ${SOURCES} devicex.hpp gdlxstream.cpp gdlxstream.hpp ) endif(WIN32) set(SOURCES ${SOURCES} gdljournal.cpp gdljournal.hpp gdlhelp.cpp gdlpsstream.cpp gdlpsstream.hpp gdlpython.cpp gdlpython.hpp gdlsvgstream.cpp gdlsvgstream.hpp gdlwidget.cpp gdlwidgeteventhandler.cpp gdlwidget.hpp gdlwxstream.cpp gdlwxstream.hpp gdlzstream.cpp gdlzstream.hpp getfmtast.cpp getfmtast.hpp graphicsdevice.cpp graphicsdevice.hpp basic_pro.cpp basic_pro.hpp basic_pro_jmg.cpp basic_pro_jmg.hpp brent.cpp grib.cpp grib.hpp gshhs.cpp gshhs.hpp gsl_fun.cpp gsl_fun.hpp gsl_matrix.cpp gsl_matrix.hpp gzstream.hpp hash.cpp hash.hpp hdf5_fun.cpp hdf5_fun.hpp hdf_fun.cpp hdf_fun.hpp hdf_pro.cpp hdf_pro.hpp ifmt.cpp image.cpp image.hpp initct.cpp initsysvar.cpp initsysvar.hpp io.cpp io.hpp lapack.cpp least_squares.cpp least_squares.hpp libinit.cpp libinit_ac.cpp libinit_cl.cpp libinit_gm.cpp libinit_jmg.cpp libinit_mes.cpp libinit_ng.cpp libinit_jp.cpp libinit_exists.cpp linearprogramming.cpp list.cpp list.hpp magick_cl.cpp magick_cl.hpp math_fun.cpp math_fun.hpp math_fun_ac.cpp math_fun_ac.hpp math_fun_gm.cpp math_fun_gm.hpp math_fun_jmg.cpp math_fun_jmg.hpp math_fun_ng.cpp math_fun_ng.hpp math_utl.cpp math_utl.hpp matrix_cholesky.cpp matrix_cholesky.hpp matrix_invert.cpp matrix_invert.hpp mpi.cpp mpi.hpp ncdf_att_cl.cpp ncdf_cl.cpp ncdf_cl.hpp ncdf_dim_cl.cpp ncdf_var_cl.cpp ncdf4_group.cpp new.cpp new.hpp newprognode.cpp nullgdl.cpp nullgdl.hpp objects.cpp objects.hpp ofmt.cpp ofmt.hpp overload.cpp overload.hpp plotting_axis.cpp plotting_contour.cpp plotting_convert_coord.cpp plotting_cursor.cpp plotting_device.cpp plotting_erase.cpp plotting_image.cpp plotting_map_proj.cpp plotting_misc.cpp plotting_oplot.cpp plotting_plot.cpp plotting_plots.cpp plotting_polyfill.cpp plotting_shade_surf.cpp plotting_surface.cpp plotting_windows.cpp plotting_xyouts.cpp plotting.cpp plotting.hpp print.cpp print_tree.cpp print_tree.hpp prognode.cpp prognode_lexpr.cpp prognodeexpr.cpp randomgenerators.cpp read.cpp real2int.hpp saverestore.cpp semshm.cpp semshm.hpp sigfpehandler.cpp sigfpehandler.hpp smooth.cpp smooth.hpp specializations.hpp str.cpp str.hpp terminfo.cpp terminfo.hpp tiff.cxx tiff.hxx topython.cpp triangulation.cpp typedefs.hpp typetraits.cpp typetraits.hpp where.cpp widget.cpp widget.hpp ) add_subdirectory(antlr) include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/antlr ${CMAKE_BINARY_DIR}) link_directories(${LINK_DIRECTORIES}) if(PYTHON_MODULE) #GDL.so set(SOURCES ${SOURCES} pythongdl.cpp) add_library(gdl SHARED ${SOURCES}) SET_TARGET_PROPERTIES(gdl PROPERTIES PREFIX "") SET_TARGET_PROPERTIES(gdl PROPERTIES OUTPUT_NAME GDL) SET_TARGET_PROPERTIES(gdl PROPERTIES NO_SONAME TRUE) SET_TARGET_PROPERTIES(gdl PROPERTIES SUFFIX ".so") # e.g. Mac defaults to .dylib which is not looked for by Python else(PYTHON_MODULE) #GDL.so set(SOURCES ${SOURCES} gdl.cpp) add_executable(gdl ${SOURCES}) endif(PYTHON_MODULE) add_dependencies(gdl antlr) # be sure that antlr is built before gdl target_link_libraries(gdl antlr) # link antlr against gdl if (MINGW) target_link_libraries(gdl ws2_32) endif (MINGW) target_link_libraries(gdl ${LIBRARIES}) add_definitions(-DHAVE_CONFIG_H) if(PYTHON_MODULE) find_package( PythonInterp REQUIRED ) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import site, sys; sys.stdout.write(site.PREFIXES[-1])" OUTPUT_VARIABLE PYTHON_PREFIX) file( TO_CMAKE_PATH "${PYTHON_PREFIX}" PYTHON_PREFIX) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import site, sys; sys.stdout.write(site.getsitepackages()[-1])" OUTPUT_VARIABLE PYTHON_SITE_DIR) file( TO_CMAKE_PATH "${PYTHON_SITE_DIR}" PYTHON_SITE_DIR ) string( REGEX REPLACE "^${PYTHON_PREFIX}/" "" PYTHON_SITE_DIR "${PYTHON_SITE_DIR}") install(TARGETS gdl DESTINATION ${PYTHON_SITE_DIR}) else(PYTHON_MODULE) install(TARGETS gdl DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) set_target_properties(gdl PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) endif(PYTHON_MODULE) install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/pro/ DESTINATION ${CMAKE_INSTALL_PREFIX}/${GDL_DATA_DIR}/lib PATTERN CVS EXCLUDE PATTERN checks EXCLUDE PATTERN Makefile* EXCLUDE PATTERN UrgentNeed.txt EXCLUDE) gdl-0.9.9/src/FMTIn.cpp000066400000000000000000000462051340051421000145040ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "format.in.g" -> "FMTIn.cpp"$ */ #include "includefirst.hpp" #include "FMTIn.hpp" #include #include #include #include #include #include // gets inserted after the antlr generated includes in the cpp file FMTIn::FMTIn() : antlr::TreeParser() { } void FMTIn::format(RefFMTNode _t) { RefFMTNode format_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode fmt = RefFMTNode(antlr::nullAST); RefFMTNode __t2 = _t; fmt = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; match(antlr::RefAST(_t),FORMAT); _t = _t->getFirstChild(); goto realCode; q(_t); _t = _retTree; { // ( ... )+ int _cnt4=0; for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { f(_t); _t = _retTree; q(_t); _t = _retTree; } else { if ( _cnt4>=1 ) { goto _loop4; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt4++; } _loop4:; } // ( ... )+ realCode: reversionAnker = fmt; RefFMTNode blk = _t; // q (f q)+ // as later format_recursive is used, this loop only // loops once (ie. could be eliminated - left here in // case of later changes) for( int r = fmt->getRep(); r > 0; r--) { GetLine(); q( blk); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL && termFlag) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition if( actPar == NULL && termFlag) break; } _t = __t2; _t = _t->getNextSibling(); _retTree = _t; } void FMTIn::q(RefFMTNode _t) { RefFMTNode q_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode s = RefFMTNode(antlr::nullAST); { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case SLASH: { s = _t; match(antlr::RefAST(_t),SLASH); _t = _t->getNextSibling(); for( int r=s->getRep(); r > 0; r--) GetLine(); break; } case 3: case FORMAT: case STRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } _retTree = _t; } void FMTIn::f(RefFMTNode _t) { RefFMTNode f_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode t = RefFMTNode(antlr::nullAST); RefFMTNode a = RefFMTNode(antlr::nullAST); RefFMTNode ff = RefFMTNode(antlr::nullAST); RefFMTNode ee = RefFMTNode(antlr::nullAST); RefFMTNode se = RefFMTNode(antlr::nullAST); RefFMTNode g = RefFMTNode(antlr::nullAST); RefFMTNode sg = RefFMTNode(antlr::nullAST); RefFMTNode i = RefFMTNode(antlr::nullAST); RefFMTNode o = RefFMTNode(antlr::nullAST); RefFMTNode b = RefFMTNode(antlr::nullAST); RefFMTNode z = RefFMTNode(antlr::nullAST); RefFMTNode zz = RefFMTNode(antlr::nullAST); RefFMTNode c = RefFMTNode(antlr::nullAST); RefFMTNode actNode; if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case TERM: { RefFMTNode tmp1_AST_in = _t; match(antlr::RefAST(_t),TERM); _t = _t->getNextSibling(); termFlag = true; break; } case NONL: { RefFMTNode tmp2_AST_in = _t; match(antlr::RefAST(_t),NONL); _t = _t->getNextSibling(); break; } case Q: { RefFMTNode tmp3_AST_in = _t; match(antlr::RefAST(_t),Q); _t = _t->getNextSibling(); SizeT nLeft = ioss.rdbuf()->in_avail(); std::istringstream iossTmp( i2s( nLeft)); int r = 1; do { SizeT tCount = actPar->IFmtA( &iossTmp, valIx, r, 0); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case T: { t = _t; match(antlr::RefAST(_t),T); _t = _t->getNextSibling(); int tVal = t->getW(); assert( tVal >= 1); ioss.seekg( tVal-1, std::ios_base::beg); break; } case STRING: case TL: case TR: { f_csubcode(_t); _t = _retTree; break; } case X: { x(_t); _t = _retTree; break; } case FORMAT: { format_recursive(_t); _t = _retTree; break; } case A: { a = _t; match(antlr::RefAST(_t),A); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = a->getRep(); int w = a->getW(); do { SizeT tCount = actPar->IFmtA( &ioss, valIx, r, w); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case F: case E: case SE: case G: case SG: { { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case F: { ff = _t; match(antlr::RefAST(_t),F); _t = _t->getNextSibling(); actNode = ff; break; } case E: { ee = _t; match(antlr::RefAST(_t),E); _t = _t->getNextSibling(); actNode = ee; break; } case SE: { se = _t; match(antlr::RefAST(_t),SE); _t = _t->getNextSibling(); actNode = se; break; } case G: { g = _t; match(antlr::RefAST(_t),G); _t = _t->getNextSibling(); actNode = g; break; } case SG: { sg = _t; match(antlr::RefAST(_t),SG); _t = _t->getNextSibling(); actNode = sg; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } if( actPar == NULL) break; int r = actNode->getRep(); int w = actNode->getW(); // if( w <= 0) // if( actPar->Type() == FLOAT) // w = 15; // set default // else // w = 25; do { SizeT tCount = actPar->IFmtF( &ioss, valIx, r, w); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case I: { i = _t; match(antlr::RefAST(_t),I); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = i->getRep(); int w = i->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::DEC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case O: { o = _t; match(antlr::RefAST(_t),O); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = o->getRep(); int w = o->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::OCT); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case B: { b = _t; match(antlr::RefAST(_t),B); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = b->getRep(); int w = b->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::BIN); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case Z: case ZZ: { { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case Z: { z = _t; match(antlr::RefAST(_t),Z); _t = _t->getNextSibling(); actNode = z; break; } case ZZ: { zz = _t; match(antlr::RefAST(_t),ZZ); _t = _t->getNextSibling(); actNode = zz; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } if( actPar == NULL) break; int r = actNode->getRep(); int w = actNode->getW(); do { SizeT tCount = actPar->IFmtI( &ioss, valIx, r, w, BaseGDL::HEX); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case C: { { RefFMTNode __t19 = _t; c = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; match(antlr::RefAST(_t),C); _t = _t->getFirstChild(); int r = c->getRep(); if (r<1) r=1; if( actPar == NULL) break; { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case STRING: case TL: case TR: case X: case CMOA: case CMoA: case CmoA: case CHI: case ChI: case CDWA: case CDwA: case CdwA: case CAPA: case CApA: case CapA: case CMOI: case CDI: case CYI: case CMI: case CSI: case CSF: { { // ( ... )+ int _cnt22=0; for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_1.member(_t->getType()))) { calendar_code(_t,r); _t = _retTree; } else { if ( _cnt22>=1 ) { goto _loop22; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt22++; } _loop22:; } // ( ... )+ break; } case 3: { if( actPar == NULL) break; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, 24, BaseGDL::DEFAULT); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, 0, BaseGDL::COMPUTE); NextVal(tCount); if( actPar == NULL) break; _t = __t19; _t = _t->getNextSibling(); } break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void FMTIn::format_recursive(RefFMTNode _t) { RefFMTNode format_recursive_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode fmt = RefFMTNode(antlr::nullAST); RefFMTNode __t6 = _t; fmt = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; match(antlr::RefAST(_t),FORMAT); _t = _t->getFirstChild(); goto realCode; q(_t); _t = _retTree; { // ( ... )+ int _cnt8=0; for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { f(_t); _t = _retTree; q(_t); _t = _retTree; } else { if ( _cnt8>=1 ) { goto _loop8; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt8++; } _loop8:; } // ( ... )+ realCode: reversionAnker = fmt; RefFMTNode blk = _t; // q (f q)+ for( int r = fmt->getRep(); r > 0; r--) { // GetLine(); // the difference to format q( blk); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL && termFlag) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition if( actPar == NULL && termFlag) break; } _t = __t6; _t = _t->getNextSibling(); _retTree = _t; } void FMTIn::format_reversion(RefFMTNode _t) { RefFMTNode format_reversion_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; format(_t); _t = _retTree; goto realCode; q(_t); _t = _retTree; { // ( ... )* for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { f(_t); _t = _retTree; q(_t); _t = _retTree; } else { goto _loop11; } } _loop11:; } // ( ... )* realCode: q( _t); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: _retTree = _t; } void FMTIn::f_csubcode(RefFMTNode _t) { RefFMTNode f_csubcode_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode s = RefFMTNode(antlr::nullAST); RefFMTNode tl = RefFMTNode(antlr::nullAST); RefFMTNode tr = RefFMTNode(antlr::nullAST); if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case STRING: { s = _t; match(antlr::RefAST(_t),STRING); _t = _t->getNextSibling(); SizeT actP = ioss.tellg(); int strlen = s->getText().length(); ioss.seekg( actP + strlen); break; } case TL: { tl = _t; match(antlr::RefAST(_t),TL); _t = _t->getNextSibling(); SizeT actP = ioss.tellg(); int tlVal = tl->getW(); if( tlVal > actP) ioss.seekg( 0); else ioss.seekg( actP - tlVal); break; } case TR: { tr = _t; match(antlr::RefAST(_t),TR); _t = _t->getNextSibling(); int tlVal = tl->getW(); ioss.seekg( tlVal, std::ios_base::cur); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void FMTIn::x(RefFMTNode _t) { RefFMTNode x_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode tl = RefFMTNode(antlr::nullAST); tl = _t; match(antlr::RefAST(_t),X); _t = _t->getNextSibling(); if( _t != static_cast(antlr::nullAST)) { int tlVal = tl->getW();if (tlVal<1) tlVal=1; ioss.seekg( tlVal, std::ios_base::cur); } _retTree = _t; } void FMTIn::calendar_code(RefFMTNode _t, SizeT r ) { RefFMTNode calendar_code_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode c1 = RefFMTNode(antlr::nullAST); RefFMTNode c2 = RefFMTNode(antlr::nullAST); RefFMTNode c3 = RefFMTNode(antlr::nullAST); RefFMTNode c4 = RefFMTNode(antlr::nullAST); RefFMTNode c5 = RefFMTNode(antlr::nullAST); RefFMTNode c6 = RefFMTNode(antlr::nullAST); RefFMTNode c7 = RefFMTNode(antlr::nullAST); RefFMTNode c8 = RefFMTNode(antlr::nullAST); RefFMTNode c9 = RefFMTNode(antlr::nullAST); RefFMTNode c10 = RefFMTNode(antlr::nullAST); RefFMTNode c11 = RefFMTNode(antlr::nullAST); RefFMTNode c12 = RefFMTNode(antlr::nullAST); RefFMTNode c13 = RefFMTNode(antlr::nullAST); RefFMTNode c14 = RefFMTNode(antlr::nullAST); RefFMTNode c15 = RefFMTNode(antlr::nullAST); RefFMTNode c16 = RefFMTNode(antlr::nullAST); RefFMTNode c17 = RefFMTNode(antlr::nullAST); if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case CMOA: { c1 = _t; match(antlr::RefAST(_t),CMOA); _t = _t->getNextSibling(); int w = c1->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMOA); break; } case CMoA: { c2 = _t; match(antlr::RefAST(_t),CMoA); _t = _t->getNextSibling(); int w = c2->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMoA); break; } case CmoA: { c3 = _t; match(antlr::RefAST(_t),CmoA); _t = _t->getNextSibling(); int w = c3->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CmoA); break; } case CHI: { c4 = _t; match(antlr::RefAST(_t),CHI); _t = _t->getNextSibling(); int w = c4->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CHI); break; } case ChI: { c5 = _t; match(antlr::RefAST(_t),ChI); _t = _t->getNextSibling(); int w = c5->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::ChI); break; } case CDWA: { c6 = _t; match(antlr::RefAST(_t),CDWA); _t = _t->getNextSibling(); int w = c6->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CDWA); break; } case CDwA: { c7 = _t; match(antlr::RefAST(_t),CDwA); _t = _t->getNextSibling(); int w = c7->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CDwA); break; } case CdwA: { c8 = _t; match(antlr::RefAST(_t),CdwA); _t = _t->getNextSibling(); int w = c8->getW(); if(w<1) w=3; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CdwA); break; } case CAPA: { c9 = _t; match(antlr::RefAST(_t),CAPA); _t = _t->getNextSibling(); int w = c9->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CAPA); break; } case CApA: { c10 = _t; match(antlr::RefAST(_t),CApA); _t = _t->getNextSibling(); int w = c10->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CApA); break; } case CapA: { c11 = _t; match(antlr::RefAST(_t),CapA); _t = _t->getNextSibling(); int w = c11->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CapA); break; } case CMOI: { c12 = _t; match(antlr::RefAST(_t),CMOI); _t = _t->getNextSibling(); int w = c12->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMOI); break; } case CDI: { c13 = _t; match(antlr::RefAST(_t),CDI); _t = _t->getNextSibling(); int w = c13->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CDI); break; } case CYI: { c14 = _t; match(antlr::RefAST(_t),CYI); _t = _t->getNextSibling(); int w = c14->getW(); if(w<1) w=4; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CYI); break; } case CMI: { c15 = _t; match(antlr::RefAST(_t),CMI); _t = _t->getNextSibling(); int w = c15->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CMI); break; } case CSI: { c16 = _t; match(antlr::RefAST(_t),CSI); _t = _t->getNextSibling(); int w = c16->getW(); if(w<1) w=2; SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CSI); break; } case CSF: { c17 = _t; match(antlr::RefAST(_t),CSF); _t = _t->getNextSibling(); int w = c17->getW(); SizeT tCount = actPar->IFmtCal( &ioss, valIx, r, w, BaseGDL::CSF); break; } case X: { x(_t); _t = _retTree; break; } case STRING: case TL: case TR: { f_csubcode(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void FMTIn::initializeASTFactory( antlr::ASTFactory& ) { } const char* FMTIn::tokenNames[] = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "CSTYLE", "CSTR", "CSTR1", "CSTR2", "ESC", "OCTESC", "ODIGIT", "HEXESC", "HDIGIT", "CD", "CSE", "CE", "CI", "CF", "CSG", "CG", "CO", "CB", "CS", "CX", "CZ", "CDOT", "PM", "MP", "PLUS", "MOINS", "DIGITS", "CNUMBER", "CWS", "FORMAT", "LBRACE", "COMMA", "RBRACE", "SLASH", "STRING", "\"tl\"", "\"tr\"", "TERM", "NONL", "Q", "T", "X", "A", "F", "D", "E", "SE", "G", "SG", "I", "O", "B", "Z", "ZZ", "C", "CMOA", "CMoA", "CmoA", "CHI", "ChI", "CDWA", "CDwA", "CdwA", "CAPA", "CApA", "CapA", "CMOI", "CDI", "CYI", "CMI", "CSI", "CSF", "NUMBER", "DOT", "CSTRING", "H", "L", "R", "PERCENT", "W", "WHITESPACE", "CHAR", 0 }; const unsigned long FMTIn::_tokenSet_0_data_[] = { 0UL, 134152130UL, 0UL, 0UL }; // FORMAT STRING "tl" "tr" TERM NONL Q T X A F E SE G SG I O B Z ZZ C const antlr::BitSet FMTIn::_tokenSet_0(_tokenSet_0_data_,4); const unsigned long FMTIn::_tokenSet_1_data_[] = { 0UL, 4160758208UL, 4095UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // STRING "tl" "tr" X CMOA CMoA CmoA CHI ChI CDWA CDwA CdwA CAPA CApA CapA // CMOI CDI CYI CMI CSI CSF const antlr::BitSet FMTIn::_tokenSet_1(_tokenSet_1_data_,8); gdl-0.9.9/src/FMTIn.hpp000066400000000000000000000145741340051421000145150ustar00rootroot00000000000000#ifndef INC_FMTIn_hpp_ #define INC_FMTIn_hpp_ #include #include "FMTInTokenTypes.hpp" /* $ANTLR 2.7.7 (2006-11-01): "format.in.g" -> "FMTIn.hpp"$ */ #include #include #include #include "envt.hpp" #include "io.hpp" // StreamInfo() #include "fmtnode.hpp" //#include "getfmtast.hpp" // for FMTNodeFactory; class CUSTOM_API FMTIn : public antlr::TreeParser, public FMTInTokenTypes { public: FMTIn( RefFMTNode fmt, std::istream* is_, EnvT* e_, int parOffset, BaseGDL* prompt_) : antlr::TreeParser(), noPrompt( true), ioss(), is(is_), prompt( prompt_), e( e_), nextParIx( parOffset), valIx(0), termFlag(false), nElements(0) { nParam = e->NParam(); NextPar(); format( fmt); SizeT nextParIxComp = nextParIx; SizeT valIxComp = valIx; // format reversion while( actPar != NULL) { format_reversion( reversionAnker); if( (nextParIx == nextParIxComp) && (valIx == valIxComp)) throw GDLException("Infinite format loop detected."); } } private: void NextPar() { valIx = 0; restart: if( nextParIx < nParam) { BaseGDL** par = &e->GetPar( nextParIx); if( (*par) != NULL) { if( e->GlobalPar( nextParIx)) { // defined global actPar = *par; nElements = actPar->ToTransfer(); } else { // defined local if( prompt != NULL) { // prompt keyword there -> error throw GDLException( e->CallingNode(), "Expression must be named variable " "in this context: "+e->GetParString( nextParIx)); } else { // prompt not there -> put out or ignore if( is == &std::cin) { (*par)->ToStream( std::cout); std::cout << std::flush; noPrompt = false; } nextParIx++; goto restart; } } } else { // undefined if( e->LocalPar( nextParIx)) throw GDLException( e->CallingNode(), "Internal error: Input: UNDEF is local."); nElements = 1; (*par) = new DFloatGDL( 0.0); actPar = *par; } } else { actPar = NULL; nElements = 0; } nextParIx++; } void NextVal( SizeT n=1) { // std::cout << "NextVal("<= nElements) NextPar(); // std::cout << "valIx: " << valIx << std::endl; // std::cout << "nElements: " << nElements << std::endl; } void GetLine() { if( is == &std::cin && noPrompt) { if( prompt != NULL) { prompt->ToStream( std::cout); std::cout << std::flush; } else { std::cout << ": " << std::flush; } } else { if( is->eof()) throw GDLIOException( e->CallingNode(), "End of file encountered. "+ StreamInfo( is)); } // std::string retStr; // getline( *is, retStr); // ioss.str( retStr); std::string initStr(""); ioss.str( initStr); // ioss.seekg( 0); // ioss.seekp( 0); ioss.rdbuf()->pubseekpos(0,std::ios_base::in | std::ios_base::out); ioss.clear(); is->get( *ioss.rdbuf()); if ( (is->rdstate() & std::ifstream::failbit ) != 0 ) { if ( (is->rdstate() & std::ifstream::eofbit ) != 0 ) throw GDLException( e->CallingNode(), "End of file encountered. "+ StreamInfo( is)); if ( (is->rdstate() & std::ifstream::badbit ) != 0 ) throw GDLException( e->CallingNode(), "Error reading line. "+ StreamInfo( is)); is->clear(); is->get(); // remove delimiter return; // assuming rdbuf == "" } if( !is->good()) { if( !is->eof()) throw GDLException( e->CallingNode(), "Error 1 reading data. "+ StreamInfo( is)); } if( !is->eof()) is->get(); // remove delimiter //*** // std::cout << "FMTIn::GetLine: " << ioss.str() << "." << std::endl; // std::cout << "tellg: " << ioss.tellg() << std::endl; } bool noPrompt; std::stringstream ioss; std::istream* is; BaseGDL* prompt; EnvT* e; SizeT nextParIx; SizeT valIx; bool termFlag; SizeT nParam; BaseGDL* actPar; SizeT nElements; RefFMTNode reversionAnker; public: FMTIn(); static void initializeASTFactory( antlr::ASTFactory& factory ); int getNumTokens() const { return FMTIn::NUM_TOKENS; } const char* getTokenName( int type ) const { if( type > getNumTokens() ) return 0; return FMTIn::tokenNames[type]; } const char* const* getTokenNames() const { return FMTIn::tokenNames; } public: void format(RefFMTNode _t); public: void q(RefFMTNode _t); public: void f(RefFMTNode _t); public: void format_recursive(RefFMTNode _t); public: void format_reversion(RefFMTNode _t); public: void f_csubcode(RefFMTNode _t); public: void x(RefFMTNode _t); public: void calendar_code(RefFMTNode _t, SizeT r ); public: antlr::RefAST getAST() { return antlr::RefAST(returnAST); } protected: RefFMTNode returnAST; RefFMTNode _retTree; private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS static const int NUM_TOKENS = 86; #else enum { NUM_TOKENS = 86 }; #endif static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; }; #endif /*INC_FMTIn_hpp_*/ gdl-0.9.9/src/FMTInTokenTypes.hpp000066400000000000000000000025321340051421000165320ustar00rootroot00000000000000#ifndef INC_FMTInTokenTypes_hpp_ #define INC_FMTInTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "format.in.g" -> "FMTInTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API FMTInTokenTypes { #endif enum { EOF_ = 1, CSTYLE = 4, CSTR = 5, CSTR1 = 6, CSTR2 = 7, ESC = 8, OCTESC = 9, ODIGIT = 10, HEXESC = 11, HDIGIT = 12, CD = 13, CSE = 14, CE = 15, CI = 16, CF = 17, CSG = 18, CG = 19, CO = 20, CB = 21, CS = 22, CX = 23, CZ = 24, CDOT = 25, PM = 26, MP = 27, PLUS = 28, MOINS = 29, DIGITS = 30, CNUMBER = 31, CWS = 32, FORMAT = 33, LBRACE = 34, COMMA = 35, RBRACE = 36, SLASH = 37, STRING = 38, TL = 39, TR = 40, TERM = 41, NONL = 42, Q = 43, T = 44, X = 45, A = 46, F = 47, D = 48, E = 49, SE = 50, G = 51, SG = 52, I = 53, O = 54, B = 55, Z = 56, ZZ = 57, C = 58, CMOA = 59, CMoA = 60, CmoA = 61, CHI = 62, ChI = 63, CDWA = 64, CDwA = 65, CdwA = 66, CAPA = 67, CApA = 68, CapA = 69, CMOI = 70, CDI = 71, CYI = 72, CMI = 73, CSI = 74, CSF = 75, NUMBER = 76, DOT = 77, CSTRING = 78, H = 79, L = 80, R = 81, PERCENT = 82, W = 83, WHITESPACE = 84, CHAR = 85, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_FMTInTokenTypes_hpp_*/ gdl-0.9.9/src/FMTInTokenTypes.txt000066400000000000000000000013031340051421000165550ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): format.in.g -> FMTInTokenTypes.txt$ FMTIn // output token vocab name CSTYLE=4 CSTR=5 CSTR1=6 CSTR2=7 ESC=8 OCTESC=9 ODIGIT=10 HEXESC=11 HDIGIT=12 CD=13 CSE=14 CE=15 CI=16 CF=17 CSG=18 CG=19 CO=20 CB=21 CS=22 CX=23 CZ=24 CDOT=25 PM=26 MP=27 PLUS=28 MOINS=29 DIGITS=30 CNUMBER=31 CWS=32 FORMAT=33 LBRACE=34 COMMA=35 RBRACE=36 SLASH=37 STRING=38 TL="tl"=39 TR="tr"=40 TERM=41 NONL=42 Q=43 T=44 X=45 A=46 F=47 D=48 E=49 SE=50 G=51 SG=52 I=53 O=54 B=55 Z=56 ZZ=57 C=58 CMOA=59 CMoA=60 CmoA=61 CHI=62 ChI=63 CDWA=64 CDwA=65 CdwA=66 CAPA=67 CApA=68 CapA=69 CMOI=70 CDI=71 CYI=72 CMI=73 CSI=74 CSF=75 NUMBER=76 DOT=77 CSTRING=78 H=79 L=80 R=81 PERCENT=82 W=83 WHITESPACE=84 CHAR=85 gdl-0.9.9/src/FMTLexer.cpp000066400000000000000000001200001340051421000151770ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "format.g" -> "FMTLexer.cpp"$ */ #include "includefirst.hpp" #include "FMTLexer.hpp" #include #include #include #include #include #include #include FMTLexer::FMTLexer(std::istream& in) : antlr::CharScanner(new antlr::CharBuffer(in),true) { initLiterals(); } FMTLexer::FMTLexer(antlr::InputBuffer& ib) : antlr::CharScanner(ib,true) { initLiterals(); } FMTLexer::FMTLexer(const antlr::LexerSharedInputState& state) : antlr::CharScanner(state,true) { initLiterals(); } void FMTLexer::initLiterals() { literals["tl"] = 39; literals["tr"] = 40; } antlr::RefToken FMTLexer::nextToken() { antlr::RefToken theRetToken; for (;;) { antlr::RefToken theRetToken; int _ttype = antlr::Token::INVALID_TYPE; resetText(); try { // for lexical and char stream error handling switch ( LA(1)) { case 0x22 /* '\"' */ : case 0x27 /* '\'' */ : { mSTRING(true); theRetToken=_returnToken; break; } case 0x28 /* '(' */ : { mLBRACE(true); theRetToken=_returnToken; break; } case 0x29 /* ')' */ : { mRBRACE(true); theRetToken=_returnToken; break; } case 0x2f /* '/' */ : { mSLASH(true); theRetToken=_returnToken; break; } case 0x2c /* ',' */ : { mCOMMA(true); theRetToken=_returnToken; break; } case 0x41 /* 'A' */ : case 0x61 /* 'a' */ : { mA(true); theRetToken=_returnToken; break; } case 0x3a /* ':' */ : { mTERM(true); theRetToken=_returnToken; break; } case 0x24 /* '$' */ : { mNONL(true); theRetToken=_returnToken; break; } case 0x46 /* 'F' */ : case 0x66 /* 'f' */ : { mF(true); theRetToken=_returnToken; break; } case 0x44 /* 'D' */ : case 0x64 /* 'd' */ : { mD(true); theRetToken=_returnToken; break; } case 0x45 /* 'E' */ : { mE(true); theRetToken=_returnToken; break; } case 0x65 /* 'e' */ : { mSE(true); theRetToken=_returnToken; break; } case 0x47 /* 'G' */ : { mG(true); theRetToken=_returnToken; break; } case 0x67 /* 'g' */ : { mSG(true); theRetToken=_returnToken; break; } case 0x49 /* 'I' */ : case 0x69 /* 'i' */ : { mI(true); theRetToken=_returnToken; break; } case 0x4f /* 'O' */ : case 0x6f /* 'o' */ : { mO(true); theRetToken=_returnToken; break; } case 0x42 /* 'B' */ : case 0x62 /* 'b' */ : { mB(true); theRetToken=_returnToken; break; } case 0x5a /* 'Z' */ : { mZ(true); theRetToken=_returnToken; break; } case 0x7a /* 'z' */ : { mZZ(true); theRetToken=_returnToken; break; } case 0x51 /* 'Q' */ : case 0x71 /* 'q' */ : { mQ(true); theRetToken=_returnToken; break; } case 0x48 /* 'H' */ : case 0x68 /* 'h' */ : { mH(true); theRetToken=_returnToken; break; } case 0x54 /* 'T' */ : case 0x74 /* 't' */ : { mT(true); theRetToken=_returnToken; break; } case 0x4c /* 'L' */ : case 0x6c /* 'l' */ : { mL(true); theRetToken=_returnToken; break; } case 0x52 /* 'R' */ : case 0x72 /* 'r' */ : { mR(true); theRetToken=_returnToken; break; } case 0x58 /* 'X' */ : case 0x78 /* 'x' */ : { mX(true); theRetToken=_returnToken; break; } case 0x2e /* '.' */ : { mDOT(true); theRetToken=_returnToken; break; } case 0x9 /* '\t' */ : case 0x20 /* ' ' */ : { mWHITESPACE(true); theRetToken=_returnToken; break; } default: if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x4f /* 'O' */ ) && (LA(4) == 0x41 /* 'A' */ )) { mCMOA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x4f /* 'O' */ ) && (LA(4) == 0x49 /* 'I' */ )) { mCMOI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x6f /* 'o' */ )) { mCMoA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x44 /* 'D' */ ) && (LA(3) == 0x49 /* 'I' */ )) { mCDI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x49 /* 'I' */ )) { mCMI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x53 /* 'S' */ ) && (LA(3) == 0x49 /* 'I' */ )) { mCSI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x53 /* 'S' */ ) && (LA(3) == 0x46 /* 'F' */ )) { mCSF(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x44 /* 'D' */ ) && (LA(3) == 0x57 /* 'W' */ )) { mCDWA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x44 /* 'D' */ ) && (LA(3) == 0x77 /* 'w' */ )) { mCDwA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x41 /* 'A' */ ) && (LA(3) == 0x50 /* 'P' */ )) { mCAPA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x41 /* 'A' */ ) && (LA(3) == 0x70 /* 'p' */ )) { mCApA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x25 /* '%' */ ) && (LA(2) == 0x22 /* '\"' */ || LA(2) == 0x27 /* '\'' */ )) { mCSTRING(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x6d /* 'm' */ )) { mCmoA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x59 /* 'Y' */ )) { mCYI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x48 /* 'H' */ )) { mCHI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x68 /* 'h' */ )) { mChI(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x64 /* 'd' */ )) { mCdwA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x61 /* 'a' */ )) { mCapA(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2b /* '+' */ ) && (LA(2) == 0x2d /* '-' */ )) { mPM(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2d /* '-' */ ) && (LA(2) == 0x2b /* '+' */ )) { mMP(true); theRetToken=_returnToken; } else if ((LA(1) == 0x43 /* 'C' */ || LA(1) == 0x63 /* 'c' */ ) && (true)) { mC(true); theRetToken=_returnToken; } else if ((LA(1) == 0x25 /* '%' */ ) && (true)) { mPERCENT(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2b /* '+' */ ) && (true)) { mPLUS(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2d /* '-' */ ) && (true)) { mMOINS(true); theRetToken=_returnToken; } else { mNUMBER(true); theRetToken=_returnToken; } } if ( !_returnToken ) goto tryAgain; // found SKIP token _ttype = _returnToken->getType(); _ttype = testLiteralsTable(_ttype); _returnToken->setType(_ttype); return _returnToken; } catch (antlr::RecognitionException& e) { throw antlr::TokenStreamRecognitionException(e); } catch (antlr::CharStreamIOException& csie) { throw antlr::TokenStreamIOException(csie.io); } catch (antlr::CharStreamException& cse) { throw antlr::TokenStreamException(cse.getMessage()); } tryAgain:; } } void FMTLexer::mSTRING(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = STRING; std::string::size_type _saveIndex; switch ( LA(1)) { case 0x22 /* '\"' */ : { _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); { // ( ... )* for (;;) { if ((LA(1) == 0x22 /* '\"' */ ) && (LA(2) == 0x22 /* '\"' */ )) { match('\"' /* charlit */ ); _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); } else if ((_tokenSet_0.member(LA(1)))) { { match(_tokenSet_0); } } else { goto _loop59; } } _loop59:; } // ( ... )* _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); break; } case 0x27 /* '\'' */ : { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); { // ( ... )* for (;;) { if ((LA(1) == 0x27 /* '\'' */ ) && (LA(2) == 0x27 /* '\'' */ )) { match('\'' /* charlit */ ); _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); } else if ((_tokenSet_1.member(LA(1)))) { { match(_tokenSet_1); } } else { goto _loop62; } } _loop62:; } // ( ... )* _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCSTRING(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSTRING; std::string::size_type _saveIndex; if ((LA(1) == 0x25 /* '%' */ ) && (LA(2) == 0x22 /* '\"' */ )) { _saveIndex = text.length(); match('%' /* charlit */ ); text.erase(_saveIndex); _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); cLexer->DoubleQuotes( true); selector->push( cLexer); selector->retry(); } else if ((LA(1) == 0x25 /* '%' */ ) && (LA(2) == 0x27 /* '\'' */ )) { _saveIndex = text.length(); match('%' /* charlit */ ); text.erase(_saveIndex); _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); cLexer->DoubleQuotes( false); selector->push( cLexer); selector->retry(); } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mLBRACE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LBRACE; std::string::size_type _saveIndex; match('(' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mRBRACE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = RBRACE; std::string::size_type _saveIndex; match(')' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mSLASH(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SLASH; std::string::size_type _saveIndex; match('/' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCOMMA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = COMMA; std::string::size_type _saveIndex; match(',' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = A; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x41 /* 'A' */ : { match('A' /* charlit */ ); break; } case 0x61 /* 'a' */ : { match('a' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mTERM(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = TERM; std::string::size_type _saveIndex; match(':' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mNONL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = NONL; std::string::size_type _saveIndex; match('$' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mF(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = F; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x66 /* 'f' */ : { match('f' /* charlit */ ); break; } case 0x46 /* 'F' */ : { match('F' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mD(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = D; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x64 /* 'd' */ : { match('d' /* charlit */ ); break; } case 0x44 /* 'D' */ : { match('D' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = E; std::string::size_type _saveIndex; { match('E' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mSE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SE; std::string::size_type _saveIndex; { match('e' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = G; std::string::size_type _saveIndex; { match('G' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mSG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SG; std::string::size_type _saveIndex; { match('g' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = I; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x69 /* 'i' */ : { match('i' /* charlit */ ); break; } case 0x49 /* 'I' */ : { match('I' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mO(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = O; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x6f /* 'o' */ : { match('o' /* charlit */ ); break; } case 0x4f /* 'O' */ : { match('O' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mB(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = B; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x62 /* 'b' */ : { match('b' /* charlit */ ); break; } case 0x42 /* 'B' */ : { match('B' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mZ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = Z; std::string::size_type _saveIndex; { match('Z' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mZZ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = ZZ; std::string::size_type _saveIndex; { match('z' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = Q; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x71 /* 'q' */ : { match('q' /* charlit */ ); break; } case 0x51 /* 'Q' */ : { match('Q' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mH(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = H; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x68 /* 'h' */ : { match('h' /* charlit */ ); break; } case 0x48 /* 'H' */ : { match('H' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = T; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x74 /* 't' */ : { match('t' /* charlit */ ); break; } case 0x54 /* 'T' */ : { match('T' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = L; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x6c /* 'l' */ : { match('l' /* charlit */ ); break; } case 0x4c /* 'L' */ : { match('L' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mR(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = R; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x72 /* 'r' */ : { match('r' /* charlit */ ); break; } case 0x52 /* 'R' */ : { match('R' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mX(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = X; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x78 /* 'x' */ : { match('x' /* charlit */ ); break; } case 0x58 /* 'X' */ : { match('X' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mC(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = C; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x63 /* 'c' */ : { match('c' /* charlit */ ); break; } case 0x43 /* 'C' */ : { match('C' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCMOA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CMOA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('M' /* charlit */ ); match('O' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCMoA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CMoA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('M' /* charlit */ ); match('o' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCmoA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CmoA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('m' /* charlit */ ); match('o' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCMOI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CMOI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('M' /* charlit */ ); match('O' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCDI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CDI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('D' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCMI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CMI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('M' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCYI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CYI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('Y' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCSI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('S' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCSF(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CSF; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('S' /* charlit */ ); match('F' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCHI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CHI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('H' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mChI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = ChI; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('h' /* charlit */ ); match('I' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCDWA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CDWA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('D' /* charlit */ ); match('W' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCDwA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CDwA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('D' /* charlit */ ); match('w' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCdwA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CdwA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('d' /* charlit */ ); match('w' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCAPA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CAPA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('A' /* charlit */ ); match('P' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCApA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CApA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('A' /* charlit */ ); match('p' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCapA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CapA; std::string::size_type _saveIndex; { match('C' /* charlit */ ); match('a' /* charlit */ ); match('p' /* charlit */ ); match('A' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mPERCENT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PERCENT; std::string::size_type _saveIndex; match('%' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mDOT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DOT; std::string::size_type _saveIndex; match('.' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mPM(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PM; std::string::size_type _saveIndex; { match('+' /* charlit */ ); match('-' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mMP(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MP; std::string::size_type _saveIndex; { match('-' /* charlit */ ); match('+' /* charlit */ ); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mPLUS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PLUS; std::string::size_type _saveIndex; match('+' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mMOINS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MOINS; std::string::size_type _saveIndex; match('-' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mW(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = W; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x20 /* ' ' */ : { match(' ' /* charlit */ ); break; } case 0x9 /* '\t' */ : { match('\t' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mWHITESPACE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = WHITESPACE; std::string::size_type _saveIndex; { // ( ... )+ int _cnt154=0; for (;;) { if ((LA(1) == 0x9 /* '\t' */ || LA(1) == 0x20 /* ' ' */ )) { mW(false); } else { if ( _cnt154>=1 ) { goto _loop154; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt154++; } _loop154:; } // ( ... )+ _ttype=antlr::Token::SKIP; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mDIGITS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DIGITS; std::string::size_type _saveIndex; { // ( ... )+ int _cnt157=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { matchRange('0','9'); } else { if ( _cnt157>=1 ) { goto _loop157; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt157++; } _loop157:; } // ( ... )+ if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mCHAR(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CHAR; std::string::size_type _saveIndex; { matchRange('\3',static_cast('\377')); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void FMTLexer::mNUMBER(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = NUMBER; std::string::size_type _saveIndex; antlr::RefToken num; SizeT n = -1; SizeT i = 0; { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mDIGITS(true); num=_returnToken; { if ((LA(1) == 0x48 /* 'H' */ || LA(1) == 0x68 /* 'h' */ )) { _ttype = STRING; std::istringstream s(num->getText()); s >> n; { text.erase(_begin); text += ""; }; // clear string (remove number) _saveIndex = text.length(); mH(false); text.erase(_saveIndex); { // ( ... )+ int _cnt164=0; for (;;) { // init action gets executed even in guessing mode if( i == n ) break; i++; // count chars here so that guessing mode works if (((LA(1) >= 0x3 /* '\3' */ && LA(1) <= 0xff))) { mCHAR(false); } else { if ( _cnt164>=1 ) { goto _loop164; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt164++; } _loop164:; } // ( ... )+ } else { } } } else { } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } const unsigned long FMTLexer::_tokenSet_0_data_[] = { 4294967288UL, 4294967291UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 // 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f ! # $ // % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F // G H I J K L M N O P Q R S T U const antlr::BitSet FMTLexer::_tokenSet_0(_tokenSet_0_data_,16); const unsigned long FMTLexer::_tokenSet_1_data_[] = { 4294967288UL, 4294967167UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 0x11 0x12 0x13 // 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f ! \" # // $ % & ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F // G H I J K L M N O P Q R S T U const antlr::BitSet FMTLexer::_tokenSet_1(_tokenSet_1_data_,16); gdl-0.9.9/src/FMTLexer.hpp000066400000000000000000000065621340051421000152240ustar00rootroot00000000000000#ifndef INC_FMTLexer_hpp_ #define INC_FMTLexer_hpp_ #include /* $ANTLR 2.7.7 (2006-11-01): "format.g" -> "FMTLexer.hpp"$ */ #include #include #include #include "FMTTokenTypes.hpp" #include #include #include #include "fmtnode.hpp" #include "CFMTLexer.hpp" #include //using namespace antlr; class CUSTOM_API FMTLexer : public antlr::CharScanner, public FMTTokenTypes { private: antlr::TokenStreamSelector* selector; CFMTLexer* cLexer; public: void SetSelector( antlr::TokenStreamSelector& s) { selector = &s; } void SetCLexer( CFMTLexer& l) { cLexer = &l; } private: void initLiterals(); public: bool getCaseSensitiveLiterals() const { return false; } public: FMTLexer(std::istream& in); FMTLexer(antlr::InputBuffer& ib); FMTLexer(const antlr::LexerSharedInputState& state); antlr::RefToken nextToken(); public: void mSTRING(bool _createToken); public: void mCSTRING(bool _createToken); public: void mLBRACE(bool _createToken); public: void mRBRACE(bool _createToken); public: void mSLASH(bool _createToken); public: void mCOMMA(bool _createToken); public: void mA(bool _createToken); public: void mTERM(bool _createToken); public: void mNONL(bool _createToken); public: void mF(bool _createToken); public: void mD(bool _createToken); public: void mE(bool _createToken); public: void mSE(bool _createToken); public: void mG(bool _createToken); public: void mSG(bool _createToken); public: void mI(bool _createToken); public: void mO(bool _createToken); public: void mB(bool _createToken); public: void mZ(bool _createToken); public: void mZZ(bool _createToken); public: void mQ(bool _createToken); public: void mH(bool _createToken); public: void mT(bool _createToken); public: void mL(bool _createToken); public: void mR(bool _createToken); public: void mX(bool _createToken); public: void mC(bool _createToken); public: void mCMOA(bool _createToken); public: void mCMoA(bool _createToken); public: void mCmoA(bool _createToken); public: void mCMOI(bool _createToken); public: void mCDI(bool _createToken); public: void mCMI(bool _createToken); public: void mCYI(bool _createToken); public: void mCSI(bool _createToken); public: void mCSF(bool _createToken); public: void mCHI(bool _createToken); public: void mChI(bool _createToken); public: void mCDWA(bool _createToken); public: void mCDwA(bool _createToken); public: void mCdwA(bool _createToken); public: void mCAPA(bool _createToken); public: void mCApA(bool _createToken); public: void mCapA(bool _createToken); public: void mPERCENT(bool _createToken); public: void mDOT(bool _createToken); public: void mPM(bool _createToken); public: void mMP(bool _createToken); public: void mPLUS(bool _createToken); public: void mMOINS(bool _createToken); protected: void mW(bool _createToken); public: void mWHITESPACE(bool _createToken); protected: void mDIGITS(bool _createToken); protected: void mCHAR(bool _createToken); public: void mNUMBER(bool _createToken); private: static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; }; #endif /*INC_FMTLexer_hpp_*/ gdl-0.9.9/src/FMTOut.cpp000066400000000000000000000513241340051421000147030ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "format.out.g" -> "FMTOut.cpp"$ */ #include "includefirst.hpp" #include "FMTOut.hpp" #include #include #include #include #include #include // gets inserted after the antlr generated includes in the cpp file FMTOut::FMTOut() : antlr::TreeParser() { } void FMTOut::format(RefFMTNode _t) { RefFMTNode format_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode fmt = RefFMTNode(antlr::nullAST); RefFMTNode __t2 = _t; fmt = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; match(antlr::RefAST(_t),FORMAT); _t = _t->getFirstChild(); goto realCode; q(_t); _t = _retTree; { // ( ... )+ int _cnt4=0; for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { f(_t); _t = _retTree; q(_t); _t = _retTree; } else { if ( _cnt4>=1 ) { goto _loop4; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt4++; } _loop4:; } // ( ... )+ realCode: reversionAnker = fmt; RefFMTNode blk = _t; // q (f q)+ for( int r = fmt->getRep(); r > 0; r--) { q( blk); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { if( actPar == NULL && termFlag) goto endFMT; // no break } case STRING: case CSTRING: { f(_t); // if( actPar == NULL && termFlag) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition if( actPar == NULL && termFlag) break; } _t = __t2; _t = _t->getNextSibling(); _retTree = _t; } void FMTOut::q(RefFMTNode _t) { RefFMTNode q_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode s = RefFMTNode(antlr::nullAST); { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case SLASH: { s = _t; match(antlr::RefAST(_t),SLASH); _t = _t->getNextSibling(); // only one newline to journal file GDLStream* j = lib::get_journal(); if( j != NULL && j->OStream().rdbuf() == os->rdbuf()) (*os) << '\n' << lib::JOURNALCOMMENT; else for( int r=s->getRep(); r > 0; r--) (*os) << '\n'; break; } case 3: case FORMAT: case STRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } _retTree = _t; } void FMTOut::f(RefFMTNode _t) { RefFMTNode f_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode t = RefFMTNode(antlr::nullAST); RefFMTNode a = RefFMTNode(antlr::nullAST); RefFMTNode ff = RefFMTNode(antlr::nullAST); RefFMTNode se = RefFMTNode(antlr::nullAST); RefFMTNode ee = RefFMTNode(antlr::nullAST); RefFMTNode sg = RefFMTNode(antlr::nullAST); RefFMTNode g = RefFMTNode(antlr::nullAST); RefFMTNode i = RefFMTNode(antlr::nullAST); RefFMTNode o = RefFMTNode(antlr::nullAST); RefFMTNode b = RefFMTNode(antlr::nullAST); RefFMTNode z = RefFMTNode(antlr::nullAST); RefFMTNode zz = RefFMTNode(antlr::nullAST); RefFMTNode c = RefFMTNode(antlr::nullAST); if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case TERM: { RefFMTNode tmp1_AST_in = _t; match(antlr::RefAST(_t),TERM); _t = _t->getNextSibling(); termFlag = true; break; } case NONL: { RefFMTNode tmp2_AST_in = _t; match(antlr::RefAST(_t),NONL); _t = _t->getNextSibling(); nonlFlag = true; break; } case Q: { RefFMTNode tmp3_AST_in = _t; match(antlr::RefAST(_t),Q); _t = _t->getNextSibling(); break; } case T: { t = _t; match(antlr::RefAST(_t),T); _t = _t->getNextSibling(); int tVal = t->getW(); assert( tVal >= 1); os->seekp( tVal-1, std::ios_base::beg); break; } case STRING: case TL: case TR: { f_csubcode(_t); _t = _retTree; break; } case X: { x(_t); _t = _retTree; break; } case FORMAT: { format(_t); _t = _retTree; break; } case A: { a = _t; match(antlr::RefAST(_t),A); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = a->getRep(); int w = a->getW(); int c = a->getCode(); do { SizeT tCount = actPar->OFmtA( os, valIx, r, w, c); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case F: { ff = _t; match(antlr::RefAST(_t),F); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = ff->getRep(); int w = ff->getW(); int d = ff->getD(); int c = ff->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::FIXED); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case SE: { se = _t; match(antlr::RefAST(_t),SE); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = se->getRep(); int w = se->getW(); int d = se->getD(); int c = se->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::SCIENTIFIC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case E: { ee = _t; match(antlr::RefAST(_t),E); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = ee->getRep(); int w = ee->getW(); int d = ee->getD(); ee->setUpper(); //'E' in uppercase int c = ee->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::SCIENTIFIC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case SG: { sg = _t; match(antlr::RefAST(_t),SG); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = sg->getRep(); int w = sg->getW(); int d = sg->getD(); int c = sg->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::AUTO); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case G: { g = _t; match(antlr::RefAST(_t),G); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = g->getRep(); int w = g->getW(); int d = g->getD(); g->setUpper(); //'E' in uppercase int c = g->getCode(); do { SizeT tCount = actPar->OFmtF( os, valIx, r, w, d, c, BaseGDL::AUTO); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case I: { i = _t; match(antlr::RefAST(_t),I); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = i->getRep(); int w = i->getW(); int d = i->getD(); int c = i->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::DEC); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case O: { o = _t; match(antlr::RefAST(_t),O); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = o->getRep(); int w = o->getW(); int d = o->getD(); int c = o->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::OCT); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case B: { b = _t; match(antlr::RefAST(_t),B); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = b->getRep(); int w = b->getW(); int d = b->getD(); int c = b->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::BIN); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case Z: { z = _t; match(antlr::RefAST(_t),Z); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = z->getRep(); int w = z->getW(); int d = z->getD(); int c = z->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::HEX); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case ZZ: { zz = _t; match(antlr::RefAST(_t),ZZ); _t = _t->getNextSibling(); if( actPar == NULL) break; int r = zz->getRep(); int w = zz->getW(); int d = zz->getD(); int c = zz->getCode(); do { SizeT tCount = actPar->OFmtI( os, valIx, r, w, d, c, BaseGDL::HEXL); r -= tCount; NextVal( tCount); if( actPar == NULL) break; } while( r>0); break; } case C: { { RefFMTNode __t13 = _t; c = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; match(antlr::RefAST(_t),C); _t = _t->getFirstChild(); int r = c->getRep(); if (r<1) r=1; if( actPar == NULL) break; SizeT nTrans = actPar->ToTransfer(); if (r > nTrans) r=nTrans; actPar->OFmtCal( os, valIx, r, 0, 0, NULL, 0, BaseGDL::COMPUTE); //convert to hour, min, etc { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case STRING: case X: case CMOA: case CMoA: case CmoA: case CHI: case ChI: case CDWA: case CDwA: case CdwA: case CAPA: case CApA: case CapA: case CMOI: case CDI: case CYI: case CMI: case CSI: case CSF: { { // ( ... )+ int _cnt16=0; for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_1.member(_t->getType()))) { calendar_code(_t,r); _t = _retTree; } else { if ( _cnt16>=1 ) { goto _loop16; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt16++; } _loop16:; } // ( ... )+ break; } case 3: { if( actPar == NULL) break; actPar->OFmtCal( os, valIx, r, 0, 0, NULL, 0, BaseGDL::DEFAULT); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } if( actPar == NULL) break; SizeT tCount = actPar->OFmtCal( os, valIx, r, 0, 0, NULL, 0, BaseGDL::WRITE); //Write the complete formatted string to os. NextVal( tCount); if( actPar == NULL) break; _t = __t13; _t = _t->getNextSibling(); } break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void FMTOut::format_reversion(RefFMTNode _t) { RefFMTNode format_reversion_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; format(_t); _t = _retTree; goto realCode; q(_t); _t = _retTree; { // ( ... )* for (;;) { if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { f(_t); _t = _retTree; q(_t); _t = _retTree; } else { goto _loop7; } } _loop7:; } // ( ... )* realCode: q( _t); _t = _retTree; for (;;) { if( _t == static_cast(antlr::nullAST)) _t = ASTNULL; switch ( _t->getType()) { case FORMAT: case STRING: case CSTRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { f(_t); if( actPar == NULL) goto endFMT; _t = _retTree; q(_t); _t = _retTree; break; // out of switch } default: goto endFMT; } } endFMT: // end of one repetition _retTree = _t; } void FMTOut::f_csubcode(RefFMTNode _t) { RefFMTNode f_csubcode_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode s = RefFMTNode(antlr::nullAST); RefFMTNode tl = RefFMTNode(antlr::nullAST); RefFMTNode tr = RefFMTNode(antlr::nullAST); if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case STRING: { s = _t; match(antlr::RefAST(_t),STRING); _t = _t->getNextSibling(); (*os) << s->getText(); break; } case TL: { tl = _t; match(antlr::RefAST(_t),TL); _t = _t->getNextSibling(); SizeT actP = os->tellp(); int tlVal = tl->getW(); if( tlVal > actP) os->seekp( 0); else os->seekp( actP - tlVal); break; } case TR: { tr = _t; match(antlr::RefAST(_t),TR); _t = _t->getNextSibling(); int tlVal = tl->getW(); for( int i=tlVal; i>0; --i) (*os) << " "; // os->seekp( tlVal, std::ios_base::cur); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void FMTOut::x(RefFMTNode _t) { RefFMTNode x_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode tl = RefFMTNode(antlr::nullAST); tl = _t; match(antlr::RefAST(_t),X); _t = _t->getNextSibling(); // if( _t != static_cast(antlr::nullAST)) // { // int tlVal = #tl->getW(); // (*os) << " "; //for format "X" (no width) // for( int i=tlVal; i>1; --i) // (*os) << " "; //for format "nX" //// os->seekp( tlVal, std::ios_base::cur); // } for( int r=tl->getW(); r > 0; r--) (*os) << ' '; _retTree = _t; } void FMTOut::calendar_code(RefFMTNode _t, SizeT r ) { RefFMTNode calendar_code_AST_in = (_t == RefFMTNode(ASTNULL)) ? RefFMTNode(antlr::nullAST) : _t; RefFMTNode c1 = RefFMTNode(antlr::nullAST); RefFMTNode c2 = RefFMTNode(antlr::nullAST); RefFMTNode c3 = RefFMTNode(antlr::nullAST); RefFMTNode c4 = RefFMTNode(antlr::nullAST); RefFMTNode c5 = RefFMTNode(antlr::nullAST); RefFMTNode c6 = RefFMTNode(antlr::nullAST); RefFMTNode c7 = RefFMTNode(antlr::nullAST); RefFMTNode c8 = RefFMTNode(antlr::nullAST); RefFMTNode c9 = RefFMTNode(antlr::nullAST); RefFMTNode c10 = RefFMTNode(antlr::nullAST); RefFMTNode c11 = RefFMTNode(antlr::nullAST); RefFMTNode c12 = RefFMTNode(antlr::nullAST); RefFMTNode c13 = RefFMTNode(antlr::nullAST); RefFMTNode c14 = RefFMTNode(antlr::nullAST); RefFMTNode c15 = RefFMTNode(antlr::nullAST); RefFMTNode c16 = RefFMTNode(antlr::nullAST); RefFMTNode c17 = RefFMTNode(antlr::nullAST); RefFMTNode c18 = RefFMTNode(antlr::nullAST); RefFMTNode c19 = RefFMTNode(antlr::nullAST); if (_t == RefFMTNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case CMOA: { c1 = _t; match(antlr::RefAST(_t),CMOA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c1->getW(); int d = c1->getD(); int c = c1->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMOA); break; } case CMoA: { c2 = _t; match(antlr::RefAST(_t),CMoA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c2->getW(); int d = c2->getD(); int c = c2->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMoA); break; } case CmoA: { c3 = _t; match(antlr::RefAST(_t),CmoA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c3->getW(); int d = c3->getD(); int c = c3->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CmoA); break; } case CHI: { c4 = _t; match(antlr::RefAST(_t),CHI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c4->getW(); int d = c4->getD(); int c = c4->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CHI); break; } case ChI: { c5 = _t; match(antlr::RefAST(_t),ChI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c5->getW(); int d = c5->getD(); int c = c5->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::ChI); break; } case CDWA: { c6 = _t; match(antlr::RefAST(_t),CDWA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c6->getW(); int d = c6->getD(); int c = c6->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CDWA); break; } case CDwA: { c7 = _t; match(antlr::RefAST(_t),CDwA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c7->getW(); int d = c7->getD(); int c = c7->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CDwA); break; } case CdwA: { c8 = _t; match(antlr::RefAST(_t),CdwA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c8->getW(); int d = c8->getD(); int c = c8->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CdwA); break; } case CAPA: { c9 = _t; match(antlr::RefAST(_t),CAPA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c9->getW(); int d = c9->getD(); int c = c9->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CAPA); break; } case CApA: { c10 = _t; match(antlr::RefAST(_t),CApA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c10->getW(); int d = c10->getD(); int c = c10->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CApA); break; } case CapA: { c11 = _t; match(antlr::RefAST(_t),CapA); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c11->getW(); int d = c11->getD(); int c = c11->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CapA); break; } case CMOI: { c12 = _t; match(antlr::RefAST(_t),CMOI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c12->getW(); int d = c12->getD(); int c = c12->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMOI); break; } case CDI: { c13 = _t; match(antlr::RefAST(_t),CDI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c13->getW(); int d = c13->getD(); int c = c13->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CDI); break; } case CYI: { c14 = _t; match(antlr::RefAST(_t),CYI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c14->getW(); int d = c14->getD(); int c = c14->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CYI); break; } case CMI: { c15 = _t; match(antlr::RefAST(_t),CMI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c15->getW(); int d = c15->getD(); int c = c15->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CMI); break; } case CSI: { c16 = _t; match(antlr::RefAST(_t),CSI); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c16->getW(); int d = c16->getD(); int c = c16->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CSI); break; } case CSF: { c17 = _t; match(antlr::RefAST(_t),CSF); _t = _t->getNextSibling(); if( actPar == NULL) break; int w = c17->getW(); int d = c17->getD(); int c = c17->getCode(); SizeT tCount = actPar->OFmtCal( os, valIx, r, w, d, NULL, c, BaseGDL::CSF); break; } case X: { c18 = _t; match(antlr::RefAST(_t),X); _t = _t->getNextSibling(); if( actPar == NULL) break; int tlVal = c18->getW(); if (tlVal < 1) tlVal=1; std::string *s=new std::string(tlVal,' '); SizeT tCount = actPar->OFmtCal( os, valIx, r, 0, 0, (char*)s->c_str(), BaseGDL::STRING); delete s; break; } case STRING: { c19 = _t; match(antlr::RefAST(_t),STRING); _t = _t->getNextSibling(); if( actPar == NULL) break; SizeT tCount = actPar->OFmtCal( os, valIx, r, 0, 0, (char*)c19->getText().c_str(), 0, BaseGDL::STRING); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void FMTOut::initializeASTFactory( antlr::ASTFactory& ) { } const char* FMTOut::tokenNames[] = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "CSTYLE", "CSTR", "CSTR1", "CSTR2", "ESC", "OCTESC", "ODIGIT", "HEXESC", "HDIGIT", "CD", "CSE", "CE", "CI", "CF", "CSG", "CG", "CO", "CB", "CS", "CX", "CZ", "CDOT", "PM", "MP", "PLUS", "MOINS", "DIGITS", "CNUMBER", "CWS", "FORMAT", "LBRACE", "COMMA", "RBRACE", "SLASH", "STRING", "\"tl\"", "\"tr\"", "TERM", "NONL", "Q", "T", "X", "A", "F", "D", "E", "SE", "G", "SG", "I", "O", "B", "Z", "ZZ", "C", "CMOA", "CMoA", "CmoA", "CHI", "ChI", "CDWA", "CDwA", "CdwA", "CAPA", "CApA", "CapA", "CMOI", "CDI", "CYI", "CMI", "CSI", "CSF", "NUMBER", "DOT", "CSTRING", "H", "L", "R", "PERCENT", "W", "WHITESPACE", "CHAR", 0 }; const unsigned long FMTOut::_tokenSet_0_data_[] = { 0UL, 134152130UL, 0UL, 0UL }; // FORMAT STRING "tl" "tr" TERM NONL Q T X A F E SE G SG I O B Z ZZ C const antlr::BitSet FMTOut::_tokenSet_0(_tokenSet_0_data_,4); const unsigned long FMTOut::_tokenSet_1_data_[] = { 0UL, 4160757824UL, 4095UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // STRING X CMOA CMoA CmoA CHI ChI CDWA CDwA CdwA CAPA CApA CapA CMOI CDI // CYI CMI CSI CSF const antlr::BitSet FMTOut::_tokenSet_1(_tokenSet_1_data_,8); gdl-0.9.9/src/FMTOut.hpp000066400000000000000000000101231340051421000147000ustar00rootroot00000000000000#ifndef INC_FMTOut_hpp_ #define INC_FMTOut_hpp_ #include #include "FMTOutTokenTypes.hpp" /* $ANTLR 2.7.7 (2006-11-01): "format.out.g" -> "FMTOut.hpp"$ */ #include #include #include //***test #include "print_tree.hpp" #include "envt.hpp" #include "fmtnode.hpp" //#include "getfmtast.hpp" // for FMTNodeFactory; #include "gdljournal.hpp" class CUSTOM_API FMTOut : public antlr::TreeParser, public FMTOutTokenTypes { public: FMTOut( RefFMTNode fmt, std::ostream* os_, EnvT* e_, int parOffset) : antlr::TreeParser(), os(os_), e( e_), nextParIx( parOffset), valIx(0), termFlag(false), nonlFlag(false), nElements(0) { std::ostringstream* osLocal; std::unique_ptr osLocalGuard; //if( *os_ == std::cout) // SA: this did not work with win32 if( os_->rdbuf() == std::cout.rdbuf()) { // e.g. print, 1, f='(A)' osLocal = new std::ostringstream(); osLocalGuard.reset( osLocal); os = osLocal; } else { // e.g. print, string(1, f='(A)') os = os_; } nParam = e->NParam(); NextPar(); GDLStream* j = lib::get_journal(); if( j != NULL && j->OStream().rdbuf() == os->rdbuf()) (*os) << lib::JOURNALCOMMENT; format( fmt); SizeT nextParIxComp = nextParIx; SizeT valIxComp = valIx; // format reversion while( actPar != NULL) { (*os) << '\n'; if( j != NULL && j->OStream().rdbuf() == os->rdbuf()) (*os) << lib::JOURNALCOMMENT; format_reversion( reversionAnker); if( (nextParIx == nextParIxComp) && (valIx == valIxComp)) throw GDLException("Infinite format loop detected."); } os->seekp( 0, std::ios_base::end); if( !nonlFlag) { (*os) << '\n'; } (*os) << std::flush; if( os_->rdbuf() == std::cout.rdbuf()) // SA: see note above { os = os_; (*os) << osLocal->str(); (*os) << std::flush; } } private: void NextPar() { valIx = 0; if( nextParIx < nParam) { actPar = e->GetPar( nextParIx); if( actPar != NULL) nElements = actPar->ToTransfer(); else nElements = 0; } else { actPar = NULL; nElements = 0; } nextParIx++; } void NextVal( SizeT n=1) { valIx += n; if( valIx >= nElements) NextPar(); } std::ostream* os; EnvT* e; SizeT nextParIx; SizeT valIx; bool termFlag; bool nonlFlag; SizeT nParam; BaseGDL* actPar; SizeT nElements; RefFMTNode reversionAnker; public: FMTOut(); static void initializeASTFactory( antlr::ASTFactory& factory ); int getNumTokens() const { return FMTOut::NUM_TOKENS; } const char* getTokenName( int type ) const { if( type > getNumTokens() ) return 0; return FMTOut::tokenNames[type]; } const char* const* getTokenNames() const { return FMTOut::tokenNames; } public: void format(RefFMTNode _t); public: void q(RefFMTNode _t); public: void f(RefFMTNode _t); public: void format_reversion(RefFMTNode _t); public: void f_csubcode(RefFMTNode _t); public: void x(RefFMTNode _t); public: void calendar_code(RefFMTNode _t, SizeT r ); public: antlr::RefAST getAST() { return antlr::RefAST(returnAST); } protected: RefFMTNode returnAST; RefFMTNode _retTree; private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS static const int NUM_TOKENS = 86; #else enum { NUM_TOKENS = 86 }; #endif static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; }; #endif /*INC_FMTOut_hpp_*/ gdl-0.9.9/src/FMTOutTokenTypes.hpp000066400000000000000000000025401340051421000167320ustar00rootroot00000000000000#ifndef INC_FMTOutTokenTypes_hpp_ #define INC_FMTOutTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "format.out.g" -> "FMTOutTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API FMTOutTokenTypes { #endif enum { EOF_ = 1, CSTYLE = 4, CSTR = 5, CSTR1 = 6, CSTR2 = 7, ESC = 8, OCTESC = 9, ODIGIT = 10, HEXESC = 11, HDIGIT = 12, CD = 13, CSE = 14, CE = 15, CI = 16, CF = 17, CSG = 18, CG = 19, CO = 20, CB = 21, CS = 22, CX = 23, CZ = 24, CDOT = 25, PM = 26, MP = 27, PLUS = 28, MOINS = 29, DIGITS = 30, CNUMBER = 31, CWS = 32, FORMAT = 33, LBRACE = 34, COMMA = 35, RBRACE = 36, SLASH = 37, STRING = 38, TL = 39, TR = 40, TERM = 41, NONL = 42, Q = 43, T = 44, X = 45, A = 46, F = 47, D = 48, E = 49, SE = 50, G = 51, SG = 52, I = 53, O = 54, B = 55, Z = 56, ZZ = 57, C = 58, CMOA = 59, CMoA = 60, CmoA = 61, CHI = 62, ChI = 63, CDWA = 64, CDwA = 65, CdwA = 66, CAPA = 67, CApA = 68, CapA = 69, CMOI = 70, CDI = 71, CYI = 72, CMI = 73, CSI = 74, CSF = 75, NUMBER = 76, DOT = 77, CSTRING = 78, H = 79, L = 80, R = 81, PERCENT = 82, W = 83, WHITESPACE = 84, CHAR = 85, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_FMTOutTokenTypes_hpp_*/ gdl-0.9.9/src/FMTOutTokenTypes.txt000066400000000000000000000013061340051421000167610ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): format.out.g -> FMTOutTokenTypes.txt$ FMTOut // output token vocab name CSTYLE=4 CSTR=5 CSTR1=6 CSTR2=7 ESC=8 OCTESC=9 ODIGIT=10 HEXESC=11 HDIGIT=12 CD=13 CSE=14 CE=15 CI=16 CF=17 CSG=18 CG=19 CO=20 CB=21 CS=22 CX=23 CZ=24 CDOT=25 PM=26 MP=27 PLUS=28 MOINS=29 DIGITS=30 CNUMBER=31 CWS=32 FORMAT=33 LBRACE=34 COMMA=35 RBRACE=36 SLASH=37 STRING=38 TL="tl"=39 TR="tr"=40 TERM=41 NONL=42 Q=43 T=44 X=45 A=46 F=47 D=48 E=49 SE=50 G=51 SG=52 I=53 O=54 B=55 Z=56 ZZ=57 C=58 CMOA=59 CMoA=60 CmoA=61 CHI=62 ChI=63 CDWA=64 CDwA=65 CdwA=66 CAPA=67 CApA=68 CapA=69 CMOI=70 CDI=71 CYI=72 CMI=73 CSI=74 CSF=75 NUMBER=76 DOT=77 CSTRING=78 H=79 L=80 R=81 PERCENT=82 W=83 WHITESPACE=84 CHAR=85 gdl-0.9.9/src/FMTParser.cpp000066400000000000000000001147711340051421000153760ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "format.g" -> "FMTParser.cpp"$ */ #include "includefirst.hpp" #include "FMTParser.hpp" #include #include #include FMTParser::FMTParser(antlr::TokenBuffer& tokenBuf, int k) : antlr::LLkParser(tokenBuf,k) { } FMTParser::FMTParser(antlr::TokenBuffer& tokenBuf) : antlr::LLkParser(tokenBuf,1) { } FMTParser::FMTParser(antlr::TokenStream& lexer, int k) : antlr::LLkParser(lexer,k) { } FMTParser::FMTParser(antlr::TokenStream& lexer) : antlr::LLkParser(lexer,1) { } FMTParser::FMTParser(const antlr::ParserSharedInputState& state) : antlr::LLkParser(state,1) { } void FMTParser::format( int repeat ) { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode format_AST = RefFMTNode(antlr::nullAST); match(LBRACE); qfq(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); qfq(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { goto _loop3; } } _loop3:; } // ( ... )* match(RBRACE); format_AST = RefFMTNode(currentAST.root); format_AST = RefFMTNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(FORMAT,"FORMAT")))->add(antlr::RefAST(format_AST)))); format_AST->setRep( repeat); currentAST.root = format_AST; if ( format_AST!=RefFMTNode(antlr::nullAST) && format_AST->getFirstChild() != RefFMTNode(antlr::nullAST) ) currentAST.child = format_AST->getFirstChild(); else currentAST.child = format_AST; currentAST.advanceChildToEnd(); format_AST = RefFMTNode(currentAST.root); returnAST = format_AST; } void FMTParser::qfq() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode qfq_AST = RefFMTNode(antlr::nullAST); q(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { switch ( LA(1)) { case CSTR: case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case PM: case MP: case PLUS: case MOINS: case CNUMBER: case LBRACE: case STRING: case TL: case TR: case TERM: case NONL: case Q: case T: case X: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: case NUMBER: { f(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); q(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } qfq_AST = RefFMTNode(currentAST.root); returnAST = qfq_AST; } void FMTParser::q() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode q_AST = RefFMTNode(antlr::nullAST); int n1 = 0; { // ( ... )* for (;;) { if ((LA(1) == SLASH)) { RefFMTNode tmp4_AST = RefFMTNode(antlr::nullAST); tmp4_AST = astFactory->create(LT(1)); match(SLASH); n1++; } else { goto _loop8; } } _loop8:; } // ( ... )* q_AST = RefFMTNode(currentAST.root); if( n1 > 0) { q_AST = RefFMTNode(astFactory->make((new antlr::ASTArray(1))->add(antlr::RefAST(astFactory->create(SLASH,"/"))))); q_AST->setRep( n1); } currentAST.root = q_AST; if ( q_AST!=RefFMTNode(antlr::nullAST) && q_AST->getFirstChild() != RefFMTNode(antlr::nullAST) ) currentAST.child = q_AST->getFirstChild(); else currentAST.child = q_AST; currentAST.advanceChildToEnd(); returnAST = q_AST; } void FMTParser::f() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode f_AST = RefFMTNode(antlr::nullAST); antlr::RefToken t = antlr::nullToken; RefFMTNode t_AST = RefFMTNode(antlr::nullAST); antlr::RefToken x = antlr::nullToken; RefFMTNode x_AST = RefFMTNode(antlr::nullAST); antlr::RefToken xx = antlr::nullToken; RefFMTNode xx_AST = RefFMTNode(antlr::nullAST); int n1; switch ( LA(1)) { case TERM: { RefFMTNode tmp5_AST = RefFMTNode(antlr::nullAST); tmp5_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp5_AST)); match(TERM); f_AST = RefFMTNode(currentAST.root); break; } case NONL: { RefFMTNode tmp6_AST = RefFMTNode(antlr::nullAST); tmp6_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp6_AST)); match(NONL); f_AST = RefFMTNode(currentAST.root); break; } case Q: { RefFMTNode tmp7_AST = RefFMTNode(antlr::nullAST); tmp7_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp7_AST)); match(Q); f_AST = RefFMTNode(currentAST.root); break; } case T: { t = LT(1); t_AST = astFactory->create(t); astFactory->addASTChild(currentAST, antlr::RefAST(t_AST)); match(T); n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); t_AST->setW( n1); f_AST = RefFMTNode(currentAST.root); break; } case CSTR: case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case PM: case MP: case PLUS: case MOINS: case CNUMBER: case STRING: case TL: case TR: { f_csubcode(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); f_AST = RefFMTNode(currentAST.root); break; } case LBRACE: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { rep_fmt( 1); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); f_AST = RefFMTNode(currentAST.root); break; } case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { switch ( LA(1)) { case LBRACE: case A: case F: case D: case E: case SE: case G: case SG: case I: case O: case B: case Z: case ZZ: case C: { rep_fmt( n1); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case X: { x = LT(1); x_AST = astFactory->create(x); astFactory->addASTChild(currentAST, antlr::RefAST(x_AST)); match(X); x_AST->setW( n1); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } f_AST = RefFMTNode(currentAST.root); break; } case X: { xx = LT(1); xx_AST = astFactory->create(xx); astFactory->addASTChild(currentAST, antlr::RefAST(xx_AST)); match(X); xx_AST->setW( 1); f_AST = RefFMTNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = f_AST; } void FMTParser::f_csubcode() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode f_csubcode_AST = RefFMTNode(antlr::nullAST); antlr::RefToken tl = antlr::nullToken; RefFMTNode tl_AST = RefFMTNode(antlr::nullAST); antlr::RefToken tr = antlr::nullToken; RefFMTNode tr_AST = RefFMTNode(antlr::nullAST); int n1; switch ( LA(1)) { case STRING: { RefFMTNode tmp8_AST = RefFMTNode(antlr::nullAST); tmp8_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp8_AST)); match(STRING); f_csubcode_AST = RefFMTNode(currentAST.root); break; } case CSTR: case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case PM: case MP: case PLUS: case MOINS: case CNUMBER: { cstring(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); f_csubcode_AST = RefFMTNode(currentAST.root); break; } case TL: { tl = LT(1); tl_AST = astFactory->create(tl); astFactory->addASTChild(currentAST, antlr::RefAST(tl_AST)); match(TL); n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tl_AST->setW( n1); f_csubcode_AST = RefFMTNode(currentAST.root); break; } case TR: { tr = LT(1); tr_AST = astFactory->create(tr); astFactory->addASTChild(currentAST, antlr::RefAST(tr_AST)); match(TR); n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tr_AST->setW( n1); f_csubcode_AST = RefFMTNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = f_csubcode_AST; } void FMTParser::cstring() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode cstring_AST = RefFMTNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefFMTNode s_AST = RefFMTNode(antlr::nullAST); { // ( ... )+ int _cnt12=0; for (;;) { switch ( LA(1)) { case CSTR: { s = LT(1); s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); match(CSTR); s_AST->setType( STRING); break; } case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case PM: case MP: case PLUS: case MOINS: case CNUMBER: { cformat(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } default: { if ( _cnt12>=1 ) { goto _loop12; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } } _cnt12++; } _loop12:; } // ( ... )+ cstring_AST = RefFMTNode(currentAST.root); returnAST = cstring_AST; } int FMTParser::nn() { int n; returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode nn_AST = RefFMTNode(antlr::nullAST); antlr::RefToken num = antlr::nullToken; RefFMTNode num_AST = RefFMTNode(antlr::nullAST); int sgn=1; num = LT(1); num_AST = astFactory->create(num); match(NUMBER); std::istringstream s(num_AST->getText()); s >> n; returnAST = nn_AST; return n; } void FMTParser::cformat() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode cformat_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c = antlr::nullToken; RefFMTNode c_AST = RefFMTNode(antlr::nullAST); antlr::RefToken se = antlr::nullToken; RefFMTNode se_AST = RefFMTNode(antlr::nullAST); antlr::RefToken e = antlr::nullToken; RefFMTNode e_AST = RefFMTNode(antlr::nullAST); antlr::RefToken i = antlr::nullToken; RefFMTNode i_AST = RefFMTNode(antlr::nullAST); antlr::RefToken ff = antlr::nullToken; RefFMTNode ff_AST = RefFMTNode(antlr::nullAST); antlr::RefToken sg = antlr::nullToken; RefFMTNode sg_AST = RefFMTNode(antlr::nullAST); antlr::RefToken g = antlr::nullToken; RefFMTNode g_AST = RefFMTNode(antlr::nullAST); antlr::RefToken o = antlr::nullToken; RefFMTNode o_AST = RefFMTNode(antlr::nullAST); antlr::RefToken b = antlr::nullToken; RefFMTNode b_AST = RefFMTNode(antlr::nullAST); antlr::RefToken x = antlr::nullToken; RefFMTNode x_AST = RefFMTNode(antlr::nullAST); antlr::RefToken z = antlr::nullToken; RefFMTNode z_AST = RefFMTNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefFMTNode s_AST = RefFMTNode(antlr::nullAST); int w = 0; int infos[4]={0,0,0,0}; int d = -1; { switch ( LA(1)) { case PM: case MP: { { switch ( LA(1)) { case PM: { match(PM); break; } case MP: { match(MP); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } infos[1]=1;infos[2]=1; break; } case PLUS: { { match(PLUS); infos[1]=1; } break; } case MOINS: { { match(MOINS); infos[2]=1; } break; } case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case CNUMBER: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { switch ( LA(1)) { case CNUMBER: { cnnf(infos); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); w=infos[0]; { switch ( LA(1)) { case CDOT: { match(CDOT); d=cnn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } break; } case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { switch ( LA(1)) { case CD: { c = LT(1); c_AST = astFactory->create(c); astFactory->addASTChild(currentAST, antlr::RefAST(c_AST)); match(CD); if (infos[1])c_AST->setShowSign(); if (infos[2])c_AST->setALignLeft(); if (infos[3])c_AST->setPadding(); c_AST->setW( w); c_AST->setD( d); c_AST->setType( I); break; } case CSE: { se = LT(1); se_AST = astFactory->create(se); astFactory->addASTChild(currentAST, antlr::RefAST(se_AST)); match(CSE); if (infos[1])se_AST->setShowSign(); if (infos[2])se_AST->setALignLeft(); if (infos[3])se_AST->setPadding(); se_AST->setW( w); se_AST->setD( d); se_AST->setType( SE); break; } case CE: { e = LT(1); e_AST = astFactory->create(e); astFactory->addASTChild(currentAST, antlr::RefAST(e_AST)); match(CE); if (infos[1])e_AST->setShowSign(); if (infos[2])e_AST->setALignLeft(); if (infos[3])e_AST->setPadding(); e_AST->setW( w); e_AST->setD( d); e_AST->setType( E); break; } case CI: { i = LT(1); i_AST = astFactory->create(i); astFactory->addASTChild(currentAST, antlr::RefAST(i_AST)); match(CI); if (infos[1])i_AST->setShowSign(); if (infos[2])i_AST->setALignLeft(); if (infos[3])i_AST->setPadding(); i_AST->setW( w); i_AST->setD( d); i_AST->setType( I); break; } case CF: { ff = LT(1); ff_AST = astFactory->create(ff); astFactory->addASTChild(currentAST, antlr::RefAST(ff_AST)); match(CF); if (infos[1])ff_AST->setShowSign(); if (infos[2])ff_AST->setALignLeft(); if (infos[3])ff_AST->setPadding(); ff_AST->setW( w); ff_AST->setD( d); ff_AST->setType( F); break; } case CSG: { sg = LT(1); sg_AST = astFactory->create(sg); astFactory->addASTChild(currentAST, antlr::RefAST(sg_AST)); match(CSG); if (infos[1])sg_AST->setShowSign(); if (infos[2])sg_AST->setALignLeft(); if (infos[3])sg_AST->setPadding(); sg_AST->setW( w); sg_AST->setD( d); sg_AST->setType( SG); break; } case CG: { g = LT(1); g_AST = astFactory->create(g); astFactory->addASTChild(currentAST, antlr::RefAST(g_AST)); match(CG); if (infos[1])g_AST->setShowSign(); if (infos[2])g_AST->setALignLeft(); if (infos[3])g_AST->setPadding(); g_AST->setW( w); g_AST->setD( d); g_AST->setType( G); break; } case CO: { o = LT(1); o_AST = astFactory->create(o); astFactory->addASTChild(currentAST, antlr::RefAST(o_AST)); match(CO); if (infos[1])o_AST->setShowSign(); if (infos[2])o_AST->setALignLeft(); if (infos[3])o_AST->setPadding(); o_AST->setW( w); o_AST->setD( d); o_AST->setType( O); break; } case CB: { b = LT(1); b_AST = astFactory->create(b); astFactory->addASTChild(currentAST, antlr::RefAST(b_AST)); match(CB); if (infos[1])b_AST->setShowSign(); if (infos[2])b_AST->setALignLeft(); if (infos[3])b_AST->setPadding(); b_AST->setW( w); b_AST->setD( d); b_AST->setType( B); break; } case CX: { x = LT(1); x_AST = astFactory->create(x); astFactory->addASTChild(currentAST, antlr::RefAST(x_AST)); match(CX); if (infos[1])x_AST->setShowSign(); if (infos[2])x_AST->setALignLeft(); if (infos[3])x_AST->setPadding(); x_AST->setW( w); x_AST->setD( d); x_AST->setType( Z); break; } case CZ: { z = LT(1); z_AST = astFactory->create(z); astFactory->addASTChild(currentAST, antlr::RefAST(z_AST)); match(CZ); if (infos[1])z_AST->setShowSign(); if (infos[2])z_AST->setALignLeft(); if (infos[3])z_AST->setPadding(); z_AST->setW( w); z_AST->setD( d); z_AST->setType( Z); break; } case CS: { s = LT(1); s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); match(CS); if (infos[1])s_AST->setShowSign(); if (infos[2])s_AST->setALignLeft(); if (infos[3])s_AST->setPadding(); s_AST->setW( w); s_AST->setType( A); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } cformat_AST = RefFMTNode(currentAST.root); returnAST = cformat_AST; } void FMTParser::cnnf( int *infos ) { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode cnnf_AST = RefFMTNode(antlr::nullAST); antlr::RefToken num = antlr::nullToken; RefFMTNode num_AST = RefFMTNode(antlr::nullAST); num = LT(1); num_AST = astFactory->create(num); match(CNUMBER); char c; std::istringstream s(num_AST->getText()); c=s.get(); s.putback(c); s >> infos[0]; if (c == '0') infos[3]=-1;; returnAST = cnnf_AST; } int FMTParser::cnn() { int n; returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode cnn_AST = RefFMTNode(antlr::nullAST); antlr::RefToken num = antlr::nullToken; RefFMTNode num_AST = RefFMTNode(antlr::nullAST); num = LT(1); num_AST = astFactory->create(num); match(CNUMBER); std::istringstream s(num_AST->getText()); s >> n; returnAST = cnn_AST; return n; } void FMTParser::rep_fmt( int repeat ) { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode rep_fmt_AST = RefFMTNode(antlr::nullAST); antlr::RefToken a = antlr::nullToken; RefFMTNode a_AST = RefFMTNode(antlr::nullAST); antlr::RefToken ff = antlr::nullToken; RefFMTNode ff_AST = RefFMTNode(antlr::nullAST); antlr::RefToken d = antlr::nullToken; RefFMTNode d_AST = RefFMTNode(antlr::nullAST); antlr::RefToken e = antlr::nullToken; RefFMTNode e_AST = RefFMTNode(antlr::nullAST); antlr::RefToken se = antlr::nullToken; RefFMTNode se_AST = RefFMTNode(antlr::nullAST); antlr::RefToken g = antlr::nullToken; RefFMTNode g_AST = RefFMTNode(antlr::nullAST); antlr::RefToken sg = antlr::nullToken; RefFMTNode sg_AST = RefFMTNode(antlr::nullAST); antlr::RefToken i = antlr::nullToken; RefFMTNode i_AST = RefFMTNode(antlr::nullAST); antlr::RefToken o = antlr::nullToken; RefFMTNode o_AST = RefFMTNode(antlr::nullAST); antlr::RefToken b = antlr::nullToken; RefFMTNode b_AST = RefFMTNode(antlr::nullAST); antlr::RefToken z = antlr::nullToken; RefFMTNode z_AST = RefFMTNode(antlr::nullAST); antlr::RefToken zz = antlr::nullToken; RefFMTNode zz_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c = antlr::nullToken; RefFMTNode c_AST = RefFMTNode(antlr::nullAST); int n1; switch ( LA(1)) { case LBRACE: { format( repeat); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case A: { a = LT(1); a_AST = astFactory->create(a); astFactory->addASTChild(currentAST, antlr::RefAST(a_AST)); match(A); { if ((_tokenSet_0.member(LA(1)))) { n1=nnf(a_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); a_AST->setW( n1); } else if (((LA(1) >= COMMA && LA(1) <= SLASH))) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } a_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case F: { ff = LT(1); ff_AST = astFactory->create(ff); astFactory->addASTChild(currentAST, antlr::RefAST(ff_AST)); match(F); w_d( ff_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); ff_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case D: { d = LT(1); d_AST = astFactory->create(d); astFactory->addASTChild(currentAST, antlr::RefAST(d_AST)); match(D); w_d( d_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); d_AST->setRep( repeat); d_AST->setText("f"); d_AST->setType(F); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case E: { e = LT(1); e_AST = astFactory->create(e); astFactory->addASTChild(currentAST, antlr::RefAST(e_AST)); match(E); w_d_e( e_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); e_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case SE: { se = LT(1); se_AST = astFactory->create(se); astFactory->addASTChild(currentAST, antlr::RefAST(se_AST)); match(SE); w_d_e( se_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); se_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case G: { g = LT(1); g_AST = astFactory->create(g); astFactory->addASTChild(currentAST, antlr::RefAST(g_AST)); match(G); w_d_e( g_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); g_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case SG: { sg = LT(1); sg_AST = astFactory->create(sg); astFactory->addASTChild(currentAST, antlr::RefAST(sg_AST)); match(SG); w_d_e( sg_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); sg_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case I: { i = LT(1); i_AST = astFactory->create(i); astFactory->addASTChild(currentAST, antlr::RefAST(i_AST)); match(I); w_d( i_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); i_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case O: { o = LT(1); o_AST = astFactory->create(o); astFactory->addASTChild(currentAST, antlr::RefAST(o_AST)); match(O); w_d( o_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); o_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case B: { b = LT(1); b_AST = astFactory->create(b); astFactory->addASTChild(currentAST, antlr::RefAST(b_AST)); match(B); w_d( b_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); b_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case Z: { z = LT(1); z_AST = astFactory->create(z); astFactory->addASTChild(currentAST, antlr::RefAST(z_AST)); match(Z); w_d( z_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); z_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case ZZ: { zz = LT(1); zz_AST = astFactory->create(zz); astFactory->addASTChild(currentAST, antlr::RefAST(zz_AST)); match(ZZ); w_d( zz_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); zz_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } case C: { c = LT(1); c_AST = astFactory->create(c); astFactory->makeASTRoot(currentAST, antlr::RefAST(c_AST)); match(C); match(LBRACE); calendar_string(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); match(RBRACE); c_AST->setRep( repeat); rep_fmt_AST = RefFMTNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = rep_fmt_AST; } int FMTParser::nnf( RefFMTNode fNode ) { int n=-1; returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode nnf_AST = RefFMTNode(antlr::nullAST); antlr::RefToken num = antlr::nullToken; RefFMTNode num_AST = RefFMTNode(antlr::nullAST); { switch ( LA(1)) { case PM: case MP: case PLUS: case MOINS: { { switch ( LA(1)) { case PM: case MP: { { switch ( LA(1)) { case PM: { RefFMTNode tmp16_AST = RefFMTNode(antlr::nullAST); tmp16_AST = astFactory->create(LT(1)); match(PM); break; } case MP: { RefFMTNode tmp17_AST = RefFMTNode(antlr::nullAST); tmp17_AST = astFactory->create(LT(1)); match(MP); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } fNode->setShowSign(); fNode->setALignLeft(); break; } case PLUS: { RefFMTNode tmp18_AST = RefFMTNode(antlr::nullAST); tmp18_AST = astFactory->create(LT(1)); match(PLUS); fNode->setShowSign(); break; } case MOINS: { RefFMTNode tmp19_AST = RefFMTNode(antlr::nullAST); tmp19_AST = astFactory->create(LT(1)); match(MOINS); fNode->setALignLeft(); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } break; } case COMMA: case RBRACE: case SLASH: case E: case SE: case NUMBER: case DOT: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { switch ( LA(1)) { case NUMBER: { num = LT(1); num_AST = astFactory->create(num); match(NUMBER); std::istringstream s(num_AST->getText()); char c = s.get(); char next = s.peek(); s.putback(c); s >> n; if (c == '0') fNode->setPadding(); break; } case COMMA: case RBRACE: case SLASH: case E: case SE: case DOT: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } returnAST = nnf_AST; return n; } void FMTParser::w_d( RefFMTNode fNode ) { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode w_d_AST = RefFMTNode(antlr::nullAST); int n1=-1, n2=-1; fNode->setW( -1); fNode->setD( -1); { if ((_tokenSet_1.member(LA(1)))) { n1=nnf( fNode); fNode->setW( n1); { switch ( LA(1)) { case DOT: { RefFMTNode tmp20_AST = RefFMTNode(antlr::nullAST); tmp20_AST = astFactory->create(LT(1)); match(DOT); n2=nn(); fNode->setD( n2); break; } case COMMA: case RBRACE: case SLASH: case E: case SE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } else if ((_tokenSet_2.member(LA(1)))) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = w_d_AST; } void FMTParser::w_d_e( RefFMTNode fNode ) { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode w_d_e_AST = RefFMTNode(antlr::nullAST); antlr::RefToken ignored = antlr::nullToken; RefFMTNode ignored_AST = RefFMTNode(antlr::nullAST); { if ((_tokenSet_1.member(LA(1)))) { w_d( fNode); { switch ( LA(1)) { case E: case SE: { { switch ( LA(1)) { case E: { RefFMTNode tmp21_AST = RefFMTNode(antlr::nullAST); tmp21_AST = astFactory->create(LT(1)); match(E); break; } case SE: { RefFMTNode tmp22_AST = RefFMTNode(antlr::nullAST); tmp22_AST = astFactory->create(LT(1)); match(SE); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } ignored = LT(1); ignored_AST = astFactory->create(ignored); match(NUMBER); int n=0; std::istringstream s(ignored_AST->getText()); s >> n; //does not work (loops probably at format_reversion) if (n < 0 || n > 255) throw GDLException("Value is out of allowed range (0 - 255)."); break; } case COMMA: case RBRACE: case SLASH: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } else if (((LA(1) >= COMMA && LA(1) <= SLASH))) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = w_d_e_AST; } void FMTParser::calendar_string() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode calendar_string_AST = RefFMTNode(antlr::nullAST); { switch ( LA(1)) { case CSTR: case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case PM: case MP: case PLUS: case MOINS: case CNUMBER: case STRING: case TL: case TR: case X: case CMOA: case CMoA: case CmoA: case CHI: case ChI: case CDWA: case CDwA: case CdwA: case CAPA: case CApA: case CapA: case CMOI: case CDI: case CYI: case CMI: case CSI: case CSF: case NUMBER: { { calendar_code(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); calendar_code(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { goto _loop31; } } _loop31:; } // ( ... )* } break; } case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_string_AST = RefFMTNode(currentAST.root); returnAST = calendar_string_AST; } void FMTParser::calendar_code() { returnAST = RefFMTNode(antlr::nullAST); antlr::ASTPair currentAST; RefFMTNode calendar_code_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c1 = antlr::nullToken; RefFMTNode c1_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c2 = antlr::nullToken; RefFMTNode c2_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c3 = antlr::nullToken; RefFMTNode c3_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c4 = antlr::nullToken; RefFMTNode c4_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c5 = antlr::nullToken; RefFMTNode c5_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c6 = antlr::nullToken; RefFMTNode c6_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c7 = antlr::nullToken; RefFMTNode c7_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c8 = antlr::nullToken; RefFMTNode c8_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c9 = antlr::nullToken; RefFMTNode c9_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c10 = antlr::nullToken; RefFMTNode c10_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c11 = antlr::nullToken; RefFMTNode c11_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c12 = antlr::nullToken; RefFMTNode c12_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c13 = antlr::nullToken; RefFMTNode c13_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c14 = antlr::nullToken; RefFMTNode c14_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c15 = antlr::nullToken; RefFMTNode c15_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c16 = antlr::nullToken; RefFMTNode c16_AST = RefFMTNode(antlr::nullAST); antlr::RefToken c17 = antlr::nullToken; RefFMTNode c17_AST = RefFMTNode(antlr::nullAST); antlr::RefToken x = antlr::nullToken; RefFMTNode x_AST = RefFMTNode(antlr::nullAST); int n1; switch ( LA(1)) { case CMOA: { c1 = LT(1); c1_AST = astFactory->create(c1); astFactory->addASTChild(currentAST, antlr::RefAST(c1_AST)); match(CMOA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c1_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CMoA: { c2 = LT(1); c2_AST = astFactory->create(c2); astFactory->addASTChild(currentAST, antlr::RefAST(c2_AST)); match(CMoA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c2_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CmoA: { c3 = LT(1); c3_AST = astFactory->create(c3); astFactory->addASTChild(currentAST, antlr::RefAST(c3_AST)); match(CmoA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c3_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CHI: { c4 = LT(1); c4_AST = astFactory->create(c4); astFactory->addASTChild(currentAST, antlr::RefAST(c4_AST)); match(CHI); w_d( c4_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case ChI: { c5 = LT(1); c5_AST = astFactory->create(c5); astFactory->addASTChild(currentAST, antlr::RefAST(c5_AST)); match(ChI); w_d( c5_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CDWA: { c6 = LT(1); c6_AST = astFactory->create(c6); astFactory->addASTChild(currentAST, antlr::RefAST(c6_AST)); match(CDWA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c6_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CDwA: { c7 = LT(1); c7_AST = astFactory->create(c7); astFactory->addASTChild(currentAST, antlr::RefAST(c7_AST)); match(CDwA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c7_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CdwA: { c8 = LT(1); c8_AST = astFactory->create(c8); astFactory->addASTChild(currentAST, antlr::RefAST(c8_AST)); match(CdwA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c8_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CAPA: { c9 = LT(1); c9_AST = astFactory->create(c9); astFactory->addASTChild(currentAST, antlr::RefAST(c9_AST)); match(CAPA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c9_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CApA: { c10 = LT(1); c10_AST = astFactory->create(c10); astFactory->addASTChild(currentAST, antlr::RefAST(c10_AST)); match(CApA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c10_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CapA: { c11 = LT(1); c11_AST = astFactory->create(c11); astFactory->addASTChild(currentAST, antlr::RefAST(c11_AST)); match(CapA); { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); c11_AST->setW( n1); break; } case COMMA: case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } calendar_code_AST = RefFMTNode(currentAST.root); break; } case CMOI: { c12 = LT(1); c12_AST = astFactory->create(c12); astFactory->addASTChild(currentAST, antlr::RefAST(c12_AST)); match(CMOI); w_d( c12_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CDI: { c13 = LT(1); c13_AST = astFactory->create(c13); astFactory->addASTChild(currentAST, antlr::RefAST(c13_AST)); match(CDI); w_d( c13_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CYI: { c14 = LT(1); c14_AST = astFactory->create(c14); astFactory->addASTChild(currentAST, antlr::RefAST(c14_AST)); match(CYI); w_d( c14_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CMI: { c15 = LT(1); c15_AST = astFactory->create(c15); astFactory->addASTChild(currentAST, antlr::RefAST(c15_AST)); match(CMI); w_d( c15_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CSI: { c16 = LT(1); c16_AST = astFactory->create(c16); astFactory->addASTChild(currentAST, antlr::RefAST(c16_AST)); match(CSI); w_d( c16_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CSF: { c17 = LT(1); c17_AST = astFactory->create(c17); astFactory->addASTChild(currentAST, antlr::RefAST(c17_AST)); match(CSF); w_d( c17_AST); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } case X: case NUMBER: { { switch ( LA(1)) { case NUMBER: { n1=nn(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case X: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } x = LT(1); x_AST = astFactory->create(x); astFactory->addASTChild(currentAST, antlr::RefAST(x_AST)); match(X); x_AST->setW( n1); calendar_code_AST = RefFMTNode(currentAST.root); break; } case CSTR: case CD: case CSE: case CE: case CI: case CF: case CSG: case CG: case CO: case CB: case CS: case CX: case CZ: case PM: case MP: case PLUS: case MOINS: case CNUMBER: case STRING: case TL: case TR: { f_csubcode(); astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); calendar_code_AST = RefFMTNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = calendar_code_AST; } void FMTParser::initializeASTFactory( antlr::ASTFactory& factory ) { factory.setMaxNodeType(85); } const char* FMTParser::tokenNames[] = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "CSTYLE", "CSTR", "CSTR1", "CSTR2", "ESC", "OCTESC", "ODIGIT", "HEXESC", "HDIGIT", "CD", "CSE", "CE", "CI", "CF", "CSG", "CG", "CO", "CB", "CS", "CX", "CZ", "CDOT", "PM", "MP", "PLUS", "MOINS", "DIGITS", "CNUMBER", "CWS", "FORMAT", "LBRACE", "COMMA", "RBRACE", "SLASH", "STRING", "\"tl\"", "\"tr\"", "TERM", "NONL", "Q", "T", "X", "A", "F", "D", "E", "SE", "G", "SG", "I", "O", "B", "Z", "ZZ", "C", "CMOA", "CMoA", "CmoA", "CHI", "ChI", "CDWA", "CDwA", "CdwA", "CAPA", "CApA", "CapA", "CMOI", "CDI", "CYI", "CMI", "CSI", "CSF", "NUMBER", "DOT", "CSTRING", "H", "L", "R", "PERCENT", "W", "WHITESPACE", "CHAR", 0 }; const unsigned long FMTParser::_tokenSet_0_data_[] = { 1006632960UL, 56UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // PM MP PLUS MOINS COMMA RBRACE SLASH NUMBER const antlr::BitSet FMTParser::_tokenSet_0(_tokenSet_0_data_,8); const unsigned long FMTParser::_tokenSet_1_data_[] = { 1006632960UL, 393272UL, 12288UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // PM MP PLUS MOINS COMMA RBRACE SLASH E SE NUMBER DOT const antlr::BitSet FMTParser::_tokenSet_1(_tokenSet_1_data_,8); const unsigned long FMTParser::_tokenSet_2_data_[] = { 0UL, 393272UL, 0UL, 0UL }; // COMMA RBRACE SLASH E SE const antlr::BitSet FMTParser::_tokenSet_2(_tokenSet_2_data_,4); gdl-0.9.9/src/FMTParser.hpp000066400000000000000000000042211340051421000153670ustar00rootroot00000000000000#ifndef INC_FMTParser_hpp_ #define INC_FMTParser_hpp_ #include /* $ANTLR 2.7.7 (2006-11-01): "format.g" -> "FMTParser.hpp"$ */ #include #include #include "FMTTokenTypes.hpp" #include #include #include #include "fmtnode.hpp" #include "CFMTLexer.hpp" #include //using namespace antlr; class CUSTOM_API FMTParser : public antlr::LLkParser, public FMTTokenTypes { // class extensions public: void initializeASTFactory( antlr::ASTFactory& factory ); protected: FMTParser(antlr::TokenBuffer& tokenBuf, int k); public: FMTParser(antlr::TokenBuffer& tokenBuf); protected: FMTParser(antlr::TokenStream& lexer, int k); public: FMTParser(antlr::TokenStream& lexer); FMTParser(const antlr::ParserSharedInputState& state); int getNumTokens() const { return FMTParser::NUM_TOKENS; } const char* getTokenName( int type ) const { if( type > getNumTokens() ) return 0; return FMTParser::tokenNames[type]; } const char* const* getTokenNames() const { return FMTParser::tokenNames; } public: void format( int repeat ); public: void qfq(); public: void q(); public: void f(); public: void f_csubcode(); public: void cstring(); public: int nn(); public: void cformat(); public: void cnnf( int *infos ); public: int cnn(); public: void rep_fmt( int repeat ); public: int nnf( RefFMTNode fNode ); public: void w_d( RefFMTNode fNode ); public: void w_d_e( RefFMTNode fNode ); public: void calendar_string(); public: void calendar_code(); public: antlr::RefAST getAST() { return antlr::RefAST(returnAST); } protected: RefFMTNode returnAST; private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS static const int NUM_TOKENS = 86; #else enum { NUM_TOKENS = 86 }; #endif static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; static const unsigned long _tokenSet_2_data_[]; static const antlr::BitSet _tokenSet_2; }; #endif /*INC_FMTParser_hpp_*/ gdl-0.9.9/src/FMTTokenTypes.hpp000066400000000000000000000025151340051421000162440ustar00rootroot00000000000000#ifndef INC_FMTTokenTypes_hpp_ #define INC_FMTTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "format.g" -> "FMTTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API FMTTokenTypes { #endif enum { EOF_ = 1, CSTYLE = 4, CSTR = 5, CSTR1 = 6, CSTR2 = 7, ESC = 8, OCTESC = 9, ODIGIT = 10, HEXESC = 11, HDIGIT = 12, CD = 13, CSE = 14, CE = 15, CI = 16, CF = 17, CSG = 18, CG = 19, CO = 20, CB = 21, CS = 22, CX = 23, CZ = 24, CDOT = 25, PM = 26, MP = 27, PLUS = 28, MOINS = 29, DIGITS = 30, CNUMBER = 31, CWS = 32, FORMAT = 33, LBRACE = 34, COMMA = 35, RBRACE = 36, SLASH = 37, STRING = 38, TL = 39, TR = 40, TERM = 41, NONL = 42, Q = 43, T = 44, X = 45, A = 46, F = 47, D = 48, E = 49, SE = 50, G = 51, SG = 52, I = 53, O = 54, B = 55, Z = 56, ZZ = 57, C = 58, CMOA = 59, CMoA = 60, CmoA = 61, CHI = 62, ChI = 63, CDWA = 64, CDwA = 65, CdwA = 66, CAPA = 67, CApA = 68, CapA = 69, CMOI = 70, CDI = 71, CYI = 72, CMI = 73, CSI = 74, CSF = 75, NUMBER = 76, DOT = 77, CSTRING = 78, H = 79, L = 80, R = 81, PERCENT = 82, W = 83, WHITESPACE = 84, CHAR = 85, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_FMTTokenTypes_hpp_*/ gdl-0.9.9/src/FMTTokenTypes.txt000066400000000000000000000012741340051421000162750ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): format.g -> FMTTokenTypes.txt$ FMT // output token vocab name CSTYLE=4 CSTR=5 CSTR1=6 CSTR2=7 ESC=8 OCTESC=9 ODIGIT=10 HEXESC=11 HDIGIT=12 CD=13 CSE=14 CE=15 CI=16 CF=17 CSG=18 CG=19 CO=20 CB=21 CS=22 CX=23 CZ=24 CDOT=25 PM=26 MP=27 PLUS=28 MOINS=29 DIGITS=30 CNUMBER=31 CWS=32 FORMAT=33 LBRACE=34 COMMA=35 RBRACE=36 SLASH=37 STRING=38 TL="tl"=39 TR="tr"=40 TERM=41 NONL=42 Q=43 T=44 X=45 A=46 F=47 D=48 E=49 SE=50 G=51 SG=52 I=53 O=54 B=55 Z=56 ZZ=57 C=58 CMOA=59 CMoA=60 CmoA=61 CHI=62 ChI=63 CDWA=64 CDwA=65 CdwA=66 CAPA=67 CApA=68 CapA=69 CMOI=70 CDI=71 CYI=72 CMI=73 CSI=74 CSF=75 NUMBER=76 DOT=77 CSTRING=78 H=79 L=80 R=81 PERCENT=82 W=83 WHITESPACE=84 CHAR=85 gdl-0.9.9/src/GDLInterpreter.cpp000066400000000000000000002223541340051421000164220ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "gdlc.i.g" -> "GDLInterpreter.cpp"$ */ // gets inserted before the antlr generated includes in the cpp file #include "includefirst.hpp" #include "GDLInterpreter.hpp" #include #include #include #include #include #include // gets inserted after the antlr generated includes in the cpp file #include "dinterpreter.hpp" #include "prognodeexpr.hpp" #include // tweaking ANTLR #define ASTNULL NULLProgNodeP #define ProgNodeP( xxx ) NULL /* ProgNodeP(antlr::nullAST) */ #define RefAST( xxx) ConvertAST( xxx) /* antlr::RefAST( Ref type) */ #define match( a, b) /* remove from source */ using namespace std; GDLInterpreter::GDLInterpreter() : antlr::TreeParser() { } RetCode GDLInterpreter::interactive(ProgNodeP _t) { RetCode retCode; ProgNodeP interactive_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; for (; _t != NULL;) { //_t->setLine(0); retCode=statement(_t); _t = _retTree; if( retCode != RC_OK) break; // break out if non-regular } _retTree = _t; return retCode; { // ( ... )+ int _cnt3=0; for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { retCode=statement(_t); _t = _retTree; if( retCode != RC_OK) break; // break out if non-regular } else { if ( _cnt3>=1 ) { goto _loop3; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt3++; } _loop3:; } // ( ... )+ _retTree = _t; return retCode; } RetCode GDLInterpreter::statement(ProgNodeP _t, bool throwImmediately) { RetCode retCode; ProgNodeP statement_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; // ProgNodeP& actPos = statement_AST_in; assert( _t != NULL); ProgNodeP last; _retTree = _t; // if( callStack.back()->GetLineNumber() == 0) // if( _t->getLine() != 0) // callStack.back()->SetLineNumber( _t->getLine()); try { // for error handling do { // if( _t->getLine() != 0) // callStack.back()->SetLineNumber( _t->getLine()); last = _retTree; // track actual line number callStack.back()->SetLineNumber( last->getLine()); retCode = last->Run(throwImmediately); // Run() sets _retTree } while( _retTree != NULL && retCode == RC_OK && !(sigControlC && interruptEnable) && (debugMode == DEBUG_CLEAR)); // commented out, because we are only at the last statement // if( _retTree != NULL) // last = _retTree; goto afterStatement; { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: { ProgNodeP tmp1_AST_in = _t; match(antlr::RefAST(_t),ASSIGN); _t = _t->getNextSibling(); break; } case ASSIGN_ARRAYEXPR_MFCALL: { ProgNodeP tmp2_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_ARRAYEXPR_MFCALL); _t = _t->getNextSibling(); break; } case ASSIGN_REPLACE: { ProgNodeP tmp3_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_REPLACE); _t = _t->getNextSibling(); break; } case PCALL_LIB: { ProgNodeP tmp4_AST_in = _t; match(antlr::RefAST(_t),PCALL_LIB); _t = _t->getNextSibling(); break; } case MPCALL: { ProgNodeP tmp5_AST_in = _t; match(antlr::RefAST(_t),MPCALL); _t = _t->getNextSibling(); break; } case MPCALL_PARENT: { ProgNodeP tmp6_AST_in = _t; match(antlr::RefAST(_t),MPCALL_PARENT); _t = _t->getNextSibling(); break; } case PCALL: { ProgNodeP tmp7_AST_in = _t; match(antlr::RefAST(_t),PCALL); _t = _t->getNextSibling(); break; } case DEC: { ProgNodeP tmp8_AST_in = _t; match(antlr::RefAST(_t),DEC); _t = _t->getNextSibling(); break; } case INC: { ProgNodeP tmp9_AST_in = _t; match(antlr::RefAST(_t),INC); _t = _t->getNextSibling(); break; } case FOR: { ProgNodeP tmp10_AST_in = _t; match(antlr::RefAST(_t),FOR); _t = _t->getNextSibling(); break; } case FOR_LOOP: { ProgNodeP tmp11_AST_in = _t; match(antlr::RefAST(_t),FOR_LOOP); _t = _t->getNextSibling(); break; } case FOREACH: { ProgNodeP tmp12_AST_in = _t; match(antlr::RefAST(_t),FOREACH); _t = _t->getNextSibling(); break; } case FOREACH_LOOP: { ProgNodeP tmp13_AST_in = _t; match(antlr::RefAST(_t),FOREACH_LOOP); _t = _t->getNextSibling(); break; } case FOREACH_INDEX: { ProgNodeP tmp14_AST_in = _t; match(antlr::RefAST(_t),FOREACH_INDEX); _t = _t->getNextSibling(); break; } case FOREACH_INDEX_LOOP: { ProgNodeP tmp15_AST_in = _t; match(antlr::RefAST(_t),FOREACH_INDEX_LOOP); _t = _t->getNextSibling(); break; } case FOR_STEP: { ProgNodeP tmp16_AST_in = _t; match(antlr::RefAST(_t),FOR_STEP); _t = _t->getNextSibling(); break; } case FOR_STEP_LOOP: { ProgNodeP tmp17_AST_in = _t; match(antlr::RefAST(_t),FOR_STEP_LOOP); _t = _t->getNextSibling(); break; } case REPEAT: { ProgNodeP tmp18_AST_in = _t; match(antlr::RefAST(_t),REPEAT); _t = _t->getNextSibling(); break; } case REPEAT_LOOP: { ProgNodeP tmp19_AST_in = _t; match(antlr::RefAST(_t),REPEAT_LOOP); _t = _t->getNextSibling(); break; } case WHILE: { ProgNodeP tmp20_AST_in = _t; match(antlr::RefAST(_t),WHILE); _t = _t->getNextSibling(); break; } case IF: { ProgNodeP tmp21_AST_in = _t; match(antlr::RefAST(_t),IF); _t = _t->getNextSibling(); break; } case IF_ELSE: { ProgNodeP tmp22_AST_in = _t; match(antlr::RefAST(_t),IF_ELSE); _t = _t->getNextSibling(); break; } case CASE: { ProgNodeP tmp23_AST_in = _t; match(antlr::RefAST(_t),CASE); _t = _t->getNextSibling(); break; } case SWITCH: { ProgNodeP tmp24_AST_in = _t; match(antlr::RefAST(_t),SWITCH); _t = _t->getNextSibling(); break; } case BLOCK: { ProgNodeP tmp25_AST_in = _t; match(antlr::RefAST(_t),BLOCK); _t = _t->getNextSibling(); break; } case LABEL: { ProgNodeP tmp26_AST_in = _t; match(antlr::RefAST(_t),LABEL); _t = _t->getNextSibling(); break; } case ON_IOERROR_NULL: { ProgNodeP tmp27_AST_in = _t; match(antlr::RefAST(_t),ON_IOERROR_NULL); _t = _t->getNextSibling(); break; } case ON_IOERROR: { ProgNodeP tmp28_AST_in = _t; match(antlr::RefAST(_t),ON_IOERROR); _t = _t->getNextSibling(); break; } case BREAK: { ProgNodeP tmp29_AST_in = _t; match(antlr::RefAST(_t),BREAK); _t = _t->getNextSibling(); break; } case CONTINUE: { ProgNodeP tmp30_AST_in = _t; match(antlr::RefAST(_t),CONTINUE); _t = _t->getNextSibling(); break; } case GOTO: { ProgNodeP tmp31_AST_in = _t; match(antlr::RefAST(_t),GOTO); _t = _t->getNextSibling(); break; } case RETF: { ProgNodeP tmp32_AST_in = _t; match(antlr::RefAST(_t),RETF); _t = _t->getNextSibling(); break; } case RETP: { ProgNodeP tmp33_AST_in = _t; match(antlr::RefAST(_t),RETP); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } afterStatement:; // possible optimization: make sigControlC a debugMode if( interruptEnable && sigControlC) { DebugMsg( last, "Interrupted at: "); sigControlC = false; retCode = NewInterpreterInstance( last->getLine());//-1); } else if( debugMode != DEBUG_CLEAR) { if( debugMode == DEBUG_STOP) { DebugMsg( last, "Stop encountered: "); if( !interruptEnable) debugMode = DEBUG_PROCESS_STOP; } if( debugMode == DEBUG_STEP) { if( stepCount == 1) { stepCount = 0; DebugMsg( last, "Stepped to: "); debugMode = DEBUG_CLEAR; retCode = NewInterpreterInstance( last->getLine());//-1); } else { --stepCount; #ifdef GDL_DEBUG std::cout << "stepCount-- = " << stepCount << std::endl; #endif } } // else if( debugMode == DEBUG_SKIP) // { // if( last != NULL) // { // last = last->getNextSibling(); // DebugMsg( last, "Skipped to: "); // } // else // DebugMsg( last, "Cannot SKIP fro here"); // debugMode = DEBUG_CLEAR; // retCode = RC_OK; // } else if( interruptEnable) { if( debugMode == DEBUG_PROCESS_STOP) { DebugMsg( last, "Stepped to: "); } debugMode = DEBUG_CLEAR; retCode = NewInterpreterInstance( last->getLine());//-1); } else { retCode = RC_ABORT; } } return retCode; } catch ( GDLException& e) { // reset _retTree to last statement // (might otherwise be inside an expression in which case // .CONTINUE does not work) _retTree = last; if( last->IsWrappedNode()) throw e; // WRAPPED_... nodes should not stop inside // set !ERROR_STATE sys var DStructDesc* errorStateDesc = SysVar::Error_State()->Desc(); //MUST NOT BE STATIC, due to .reset static unsigned nameTag = errorStateDesc->TagIndex( "NAME"); static unsigned codeTag = errorStateDesc->TagIndex( "CODE"); static unsigned msgTag = errorStateDesc->TagIndex( "MSG"); if( e.IsIOException()) { assert( dynamic_cast< GDLIOException*>( &e) != NULL); // set the jump target - also logs the jump ProgNodeP onIOErr = static_cast(callStack.back())->GetIOError(); if( onIOErr != NULL) { DStructGDL* errorState = SysVar::Error_State(); (*static_cast( errorState->GetTag( nameTag)))[0] = "IDL_M_FAILURE"; (*static_cast( errorState->GetTag( codeTag)))[0] = e.ErrorCode(); SysVar::SetErrError( e.ErrorCode()); (*static_cast( errorState->GetTag( msgTag)))[0] = e.getMessage(); SysVar::SetErr_String( e.getMessage()); _retTree = onIOErr; return RC_OK; } } // handle CATCH ProgNodeP catchNode = callStack.back()->GetCatchNode(); if( catchNode != NULL) { DStructGDL* errorState = SysVar::Error_State(); (*static_cast( errorState->GetTag( nameTag)))[0] = "IDL_M_FAILURE"; (*static_cast( errorState->GetTag( codeTag)))[0] = e.ErrorCode(); SysVar::SetErrError( e.ErrorCode()); (*static_cast( errorState->GetTag( msgTag)))[0] = e.getMessage(); SysVar::SetErr_String( e.getMessage()); BaseGDL** catchVar = callStack.back()->GetCatchVar(); GDLDelete(*catchVar); *catchVar = new DLongGDL( e.ErrorCode()); _retTree = catchNode; return RC_OK; } EnvUDT* targetEnv = e.GetTargetEnv(); if( targetEnv == NULL) { // initial exception, set target env // set !ERROR_STATE here DStructGDL* errorState = SysVar::Error_State(); (*static_cast( errorState->GetTag( nameTag)))[0] = "IDL_M_FAILURE"; (*static_cast( errorState->GetTag( codeTag)))[0] = e.ErrorCode(); SysVar::SetErrError( e.ErrorCode()); (*static_cast( errorState->GetTag( msgTag)))[0] = e.getMessage(); SysVar::SetErr_String( e.getMessage()); // look if ON_ERROR is set somewhere // for( EnvStackT::reverse_iterator i = callStack.rbegin(); // i != callStack.rend(); ++i) for( long ix = callStack.size() - 1; ix>=0; --ix) { EnvUDT** i = &callStack[ ix]; DLong oE = -1; EnvUDT* envUD = dynamic_cast(*i); if( envUD != NULL) oE = envUD->GetOnError(); if( oE != -1) { // oE was set // 0 -> stop here if( oE == 0) targetEnv = static_cast(callStack.back()); // 1 -> $MAIN$ else if( oE == 1) { EnvUDT* cS_begin = static_cast(callStack[0]); // static_cast(*callStack.begin()); targetEnv = cS_begin; } // 2 -> caller of routine which called ON_ERROR else if( oE == 2) { // set to caller, handle nested while( ix > 0 && static_cast(callStack[--ix])->GetOnError() == 2) ; // just set ix EnvUDT* iUDT = static_cast(callStack[ix]); targetEnv = iUDT; // while( static_cast(*(++i))->GetOnError() == 2 // && i != callStack.rend()); // if( i == callStack.rend()) // { // EnvUDT* cS_begin = // static_cast(*callStack.begin()); // targetEnv = cS_begin; // } // else // { // EnvUDT* iUDT = static_cast(*i); // targetEnv = iUDT; // } } // 3 -> routine which called ON_ERROR else if( oE == 3) { EnvUDT* iUDT = static_cast(callStack[ix]); // EnvUDT* iUDT = static_cast(*i); targetEnv = iUDT; } // State where error occured // if( e.getLine() == 0 && _t != NULL) // e.SetLine( _t->getLine()); // if( e.getLine() == 0 && _retTree != NULL) // e.SetLine( _retTree->getLine()); if( e.getLine() == 0 && last != NULL) e.SetLine( last->getLine()); if( interruptEnable) ReportError(e, "Error occurred at:"); // remeber where to stop e.SetTargetEnv( targetEnv); if( targetEnv->GetLineNumber() != 0) e.SetLine( targetEnv->GetLineNumber()); // ProgNodeP errorNodeP = targetEnv->CallingNode(); // e.SetErrorNodeP( errorNodeP); // break on first occurence of set oE break; } } } if( targetEnv != NULL && targetEnv != callStack.back()) { throw e; // rethrow } lib::write_journal( GetClearActualLine()); // many low level routines don't have errorNode info // set line number here in this case // if( e.getLine() == 0 && _t != NULL) // e.SetLine( _t->getLine()); // if( e.getLine() == 0 && _retTree != NULL) // e.SetLine( _retTree->getLine()); // if( e.getLine() == 0 && actPos != NULL) // e.SetLine( actPos->getLine()); if( interruptEnable) { if( e.getLine() == 0 && last != NULL) e.SetLine( last->getLine()); // tell where we are ReportError(e, "Execution halted at:", targetEnv == NULL); retCode = NewInterpreterInstance(e.getLine());//-1); } else { DString msgPrefix = SysVar::MsgPrefix(); if( e.Prefix()) { std::cerr << msgPrefix << e.toString() << std::endl; lib::write_journal_comment(msgPrefix+e.toString()); } else { std::cerr << e.toString() << std::endl; lib::write_journal_comment(e.toString()); } retCode = RC_ABORT; } return retCode; } _retTree = _t; return retCode; } RetCode GDLInterpreter::execute(ProgNodeP _t, bool throwImmediately) { RetCode retCode; ProgNodeP execute_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; // RetCode retCode; ValueGuard guard( interruptEnable); interruptEnable = false; // return statement_list(_t,throwImmediately); retCode=statement_list(_t,throwImmediately); _t = _retTree; _retTree = _t; return retCode; } RetCode GDLInterpreter::statement_list(ProgNodeP _t, bool throwImmediately) { RetCode retCode; ProgNodeP statement_list_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; for (; _t != NULL;) { retCode=statement(_t,throwImmediately); _t = _retTree; if( retCode != RC_OK) break; // break out if non-regular } _retTree = _t; return retCode; { // ( ... )+ int _cnt16=0; for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { retCode=statement(_t,throwImmediately); _t = _retTree; } else { if ( _cnt16>=1 ) { goto _loop16; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt16++; } _loop16:; } // ( ... )+ _retTree = _t; return retCode; } BaseGDL* GDLInterpreter::call_fun(ProgNodeP _t) { BaseGDL* res; ProgNodeP call_fun_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = NULL; assert(returnValue == NULL); RetCode retCode; for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; // if( retCode == RC_RETURN) if( retCode >= RC_RETURN) { res=returnValue; returnValue=NULL; // already done in RETFNode::Run() : // if( returnValueL != NULL) // { // callStack.back()->SetPtrToReturnValue( returnValueL); // returnValueL = NULL; // } break; } } // default return value if none was set if( res == NULL) res = new DIntGDL( 0); _retTree = _t; return res; { // ( ... )* for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { retCode=statement(_t); _t = _retTree; } else { goto _loop7; } } _loop7:; } // ( ... )* _retTree = _t; return res; } BaseGDL** GDLInterpreter::call_lfun(ProgNodeP _t) { BaseGDL** res; ProgNodeP call_lfun_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = NULL; assert(returnValueL == NULL); RetCode retCode; ProgNodeP in = _t; for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; if( retCode >= RC_RETURN) { res=returnValueL; returnValueL=NULL; break; } } // res must be defined here if( res == NULL) throw GDLException( in, "Function "+callStack.back()->GetProName()+ " must return a global left-value in this context.", false,false); _retTree = _t; return res; { // ( ... )* for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { retCode=statement(_t); _t = _retTree; } else { goto _loop10; } } _loop10:; } // ( ... )* _retTree = _t; return res; } void GDLInterpreter::call_pro(ProgNodeP _t) { ProgNodeP call_pro_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; RetCode retCode; for (; _t != NULL;) { retCode=statement(_t); _t = _retTree; // added RC_ABORT here if( retCode >= RC_RETURN) break; } _retTree = _t; return; { // ( ... )* for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { retCode=statement(_t); _t = _retTree; } else { goto _loop13; } } _loop13:; } // ( ... )* _retTree = _t; } BaseGDL** GDLInterpreter::l_deref(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_deref_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP retTree = _t->getNextSibling(); BaseGDL* e1; ProgNodeP evalExpr = _t->getFirstChild(); if( NonCopyNode( evalExpr->getType())) { e1 = evalExpr->EvalNC(); } else { BaseGDL** ref = evalExpr->EvalRefCheck(e1); if( ref == NULL) { // use new env if set (during parameter parsing) EnvBaseT* actEnv = DInterpreter::CallStackBack()->GetNewEnv(); if( actEnv == NULL) actEnv = DInterpreter::CallStackBack(); assert( actEnv != NULL); // this is crucial, a guard does not work here as a temporary // ptr will be cleaned up at return from this function actEnv->DeleteAtExit( e1); } else e1 = *ref; } if( e1 == NULL || e1->Type() != GDL_PTR) throw GDLException( evalExpr, "Pointer type required in this context: "+Name(e1),true,false); DPtrGDL* ptr=static_cast(e1); DPtr sc; if( !ptr->Scalar(sc)) throw GDLException( _t, "Expression must be a scalar in this context: "+Name(e1),true,false); if( sc == 0) throw GDLException( _t, "Unable to dereference NULL pointer: "+Name(e1),true,false); try { res = &GetHeap(sc); } catch( HeapException) { throw GDLException( _t, "Invalid pointer: "+Name(e1),true,false); } _retTree = retTree; return res; ProgNodeP tmp34_AST_in = _t; match(antlr::RefAST(_t),DEREF); _t = _t->getNextSibling(); _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_decinc_indexable_expr(ProgNodeP _t, BaseGDL*& res ) { BaseGDL** e; ProgNodeP l_decinc_indexable_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; e = _t->LEval(); res = *e; if( res == NULL) throw GDLException( _t, "Variable is undefined: "+Name(e),true,false); return e; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: { e=l_function_call_internal(_t); _t = _retTree; break; } case DEREF: { e=l_deref(_t); _t = _retTree; break; } case VAR: case VARPTR: { e=l_defined_simple_var(_t); _t = _retTree; break; } case SYSVAR: { e=l_sys_var(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return e; } BaseGDL** GDLInterpreter::l_function_call_internal(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_function_call_internal_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->LEval(); _retTree = _t->getNextSibling(); return res; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case FCALL_LIB: { ProgNodeP tmp35_AST_in = _t; match(antlr::RefAST(_t),FCALL_LIB); _t = _t->getNextSibling(); break; } case MFCALL: { ProgNodeP tmp36_AST_in = _t; match(antlr::RefAST(_t),MFCALL); _t = _t->getNextSibling(); break; } case MFCALL_PARENT: { ProgNodeP tmp37_AST_in = _t; match(antlr::RefAST(_t),MFCALL_PARENT); _t = _t->getNextSibling(); break; } case FCALL: { ProgNodeP tmp38_AST_in = _t; match(antlr::RefAST(_t),FCALL); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_defined_simple_var(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_defined_simple_var_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; assert( _t != NULL); res = _t->LEval(); _retTree = _t->getNextSibling(); if( *res == NULL) { if( _t->getType() == VAR) throw GDLException( _t, "Variable is undefined: "+ callStack.back()->GetString(_t->varIx),true,false); else throw GDLException( _t, "Common block variable is undefined: "+ callStack.back()->GetString( *res),true,false); } return res; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case VAR: { ProgNodeP tmp39_AST_in = _t; match(antlr::RefAST(_t),VAR); _t = _t->getNextSibling(); break; } case VARPTR: { ProgNodeP tmp40_AST_in = _t; match(antlr::RefAST(_t),VARPTR); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_sys_var(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_sys_var_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP sysVar = _t; //match(antlr::RefAST(_t),SYSVAR); res=sysVar->LEval(); _retTree = sysVar->getNextSibling(); return res; ProgNodeP tmp41_AST_in = _t; match(antlr::RefAST(_t),SYSVAR); _t = _t->getNextSibling(); _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_decinc_array_expr(ProgNodeP _t, int dec_inc, BaseGDL*& res ) { BaseGDL** e; ProgNodeP l_decinc_array_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ArrayIndexListT* aL; ArrayIndexListGuard guard; if( _t->getType() == ARRAYEXPR) { ProgNodeP arrExNP = _t; // match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); BaseGDL** tmp =_t->LEval();// l_decinc_indexable_expr(_t, res); res = *tmp; if( res == NULL) throw GDLException( _t, "Variable is undefined: " + Name(tmp), true,false); _t = _t->getNextSibling(); aL=arrayindex_list(_t,!res->IsAssoc()); _retTree = arrExNP->getNextSibling(); guard.reset( aL); aL->SetVariable( res); if( dec_inc == DECSTATEMENT) { res->DecAt( aL); return NULL; } if( dec_inc == INCSTATEMENT) { res->IncAt( aL); return NULL; } if( dec_inc == DEC || dec_inc == DEC_REF_CHECK) res->DecAt( aL); else if( dec_inc == INC || dec_inc == INC_REF_CHECK) res->IncAt( aL); BaseGDL* resBefore = res; res = resBefore->Index( aL); if( dec_inc == POSTDEC) resBefore->DecAt( aL); else if( dec_inc == POSTINC) resBefore->IncAt( aL); return NULL; } else { e =_t->LEval();// l_decinc_indexable_expr(_t, res); res = *e; if( res == NULL) throw GDLException( _t, "Variable is undefined: " + Name(e), true,false); _retTree = _t->getNextSibling(); // e=l_decinc_indexable_expr(_t, res); // _t = _retTree; if( dec_inc == DECSTATEMENT || dec_inc == DEC_REF_CHECK) { res->Dec(); return e; } if( dec_inc == INCSTATEMENT || dec_inc == INC_REF_CHECK) { res->Inc(); return e; } if( dec_inc == DEC) res->Dec(); else if( dec_inc == INC) res->Inc(); BaseGDL* resBefore = res; res = resBefore->Dup(); if( dec_inc == POSTDEC) resBefore->Dec(); else if( dec_inc == POSTINC) resBefore->Inc(); return e; } assert(false); return e; // not used _______________________________________ // ------------------------------------------------ if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { ProgNodeP tmp42_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getNextSibling(); break; } case DEREF: case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: case SYSVAR: case VAR: case VARPTR: { e=l_decinc_indexable_expr(_t, res); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return e; } BaseGDL* GDLInterpreter::l_decinc_dot_expr(ProgNodeP _t, int dec_inc ) { BaseGDL* res; ProgNodeP l_decinc_dot_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP dot = _t; //match(antlr::RefAST(_t),DOT); _t = _t->getFirstChild(); SizeT nDot=dot->nDot; Guard aD( new DotAccessDescT(nDot+1)); l_dot_array_expr(_t, aD.Get()); _t = _retTree; while( _t != NULL) { tag_array_expr(_t, aD.Get()); _t = _retTree; } _retTree = dot->getNextSibling(); if( dec_inc == DECSTATEMENT) { aD.Get()->Dec(); return NULL; } if( dec_inc == INCSTATEMENT) { aD.Get()->Inc(); return NULL; } if( dec_inc == DEC || dec_inc == DEC_REF_CHECK) aD.Get()->Dec(); //*** aD->Assign( dec_inc); else if( dec_inc == INC || dec_inc == INC_REF_CHECK) aD.Get()->Inc(); res=aD.Get()->ADResolve(); if( dec_inc == POSTDEC) aD.Get()->Dec(); else if( dec_inc == POSTINC) aD.Get()->Inc(); return res; ProgNodeP tmp43_AST_in = _t; match(antlr::RefAST(_t),DOT); _t = _t->getNextSibling(); _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_decinc_expr(ProgNodeP _t, int dec_inc, BaseGDL*& res ) { BaseGDL** refRet; ProgNodeP l_decinc_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP mp2 = ProgNodeP(antlr::nullAST); refRet = NULL; BaseGDL* e1; ProgNodeP startNode = _t; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case QUESTION: { ProgNodeP __t24 = _t; ProgNodeP tmp44_AST_in = _t; match(antlr::RefAST(_t),QUESTION); _t = _t->getFirstChild(); e1=expr(_t); _t = _retTree; Guard e1_guard(e1); if( e1->True()) { refRet=l_decinc_expr(_t, dec_inc, res); } else { _t=_t->GetNextSibling(); // jump over 1st expression refRet=l_decinc_expr(_t, dec_inc, res); } _t = __t24; _t = _t->getNextSibling(); break; } case ASSIGN: { ProgNodeP __t25 = _t; ProgNodeP tmp45_AST_in = _t; match(antlr::RefAST(_t),ASSIGN); _t = _t->getFirstChild(); Guard r_guard; { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case CONSTANT: case DEREF: case SYSVAR: case VAR: case VARPTR: { e1=indexable_expr(_t); _t = _retTree; break; } case ASSIGN: case ASSIGN_REPLACE: case ASSIGN_ARRAYEXPR_MFCALL: case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_MFCALL: case EXPR: case FCALL: case FCALL_LIB_RETNEW: case MFCALL: case MFCALL_PARENT: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case DEC: case INC: case DOT: case QUESTION: { e1=indexable_tmp_expr(_t); _t = _retTree; r_guard.Init( e1); break; } case FCALL_LIB: { e1=lib_function_call_internal(_t); _t = _retTree; // if( !callStack.back()->Contains( e1)) if( callStack.back()->GetPtrToReturnValueNull() == NULL) r_guard.Init( e1); // guard if no global data break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } ProgNodeP l = _t; BaseGDL** tmp; tmp=l_expr_internal(_t, e1); _t = _retTree; _t = l; refRet=l_decinc_expr(_t,dec_inc, res); _t = _retTree; _t = __t25; _t = _t->getNextSibling(); break; } case ASSIGN_ARRAYEXPR_MFCALL: { ProgNodeP __t27 = _t; ProgNodeP tmp46_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_ARRAYEXPR_MFCALL); _t = _t->getFirstChild(); Guard r_guard; { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case CONSTANT: case DEREF: case SYSVAR: case VAR: case VARPTR: { e1=indexable_expr(_t); _t = _retTree; break; } case ASSIGN: case ASSIGN_REPLACE: case ASSIGN_ARRAYEXPR_MFCALL: case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_MFCALL: case EXPR: case FCALL: case FCALL_LIB_RETNEW: case MFCALL: case MFCALL_PARENT: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case DEC: case INC: case DOT: case QUESTION: { e1=indexable_tmp_expr(_t); _t = _retTree; r_guard.Init( e1); break; } case FCALL_LIB: { e1=lib_function_call_internal(_t); _t = _retTree; // if( !callStack.back()->Contains( e1)) if( callStack.back()->GetPtrToReturnValueNull() == NULL) r_guard.Init( e1); // guard if no global data break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } ProgNodeP l = _t; BaseGDL** tmp; // try MFCALL try { tmp=l_arrayexpr_mfcall_as_mfcall(l); if( e1 != (*tmp)) { delete *tmp; if( r_guard.Get() == e1) *tmp = r_guard.release(); else *tmp = e1->Dup(); } refRet=l_decinc_expr( l, dec_inc, res); } catch( GDLException& ex) { // try ARRAYEXPR try { tmp=l_arrayexpr_mfcall_as_arrayexpr(l, e1); } catch( GDLException& ex2) { throw GDLException(ex.toString() + " or "+ex2.toString()); } refRet=l_decinc_expr( l, dec_inc, res); } _t = __t27; _t = _t->getNextSibling(); break; } case ASSIGN_REPLACE: { ProgNodeP __t29 = _t; ProgNodeP tmp47_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_REPLACE); _t = _t->getFirstChild(); Guard r_guard; { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case ASSIGN_REPLACE: case ASSIGN_ARRAYEXPR_MFCALL: case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case FCALL_LIB_RETNEW: case MFCALL: case MFCALL_PARENT: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case VAR: case VARPTR: case DEC: case INC: case DOT: case QUESTION: { e1=tmp_expr(_t); _t = _retTree; r_guard.Init( e1); break; } case FCALL_LIB: { e1=lib_function_call_internal(_t); _t = _retTree; // if( !callStack.back()->Contains( e1)) if( callStack.back()->GetPtrToReturnValueNull() == NULL) r_guard.Init( e1); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } ProgNodeP l = _t; BaseGDL** tmp; { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: { tmp=l_function_call_internal(_t); _t = _retTree; break; } case DEREF: { tmp=l_deref(_t); _t = _retTree; break; } case VAR: case VARPTR: { tmp=l_simple_var(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } if( e1 != (*tmp)) { delete *tmp; if( r_guard.Get() == e1) *tmp = r_guard.release(); else *tmp = e1->Dup(); } _t = l; refRet=l_decinc_expr(_t,dec_inc, res); _t = _retTree; _t = __t29; _t = _t->getNextSibling(); break; } case ARRAYEXPR: case DEREF: case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: case SYSVAR: case VAR: case VARPTR: { refRet=l_decinc_array_expr(_t,dec_inc, res); _t = _retTree; break; } case ARRAYEXPR_MFCALL: { ProgNodeP __t32 = _t; ProgNodeP tmp48_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR_MFCALL); _t = _t->getFirstChild(); ProgNodeP mark = _t; _t = _t->getNextSibling(); // step over DOT BaseGDL* self; self=expr(_t); _t = _retTree; mp2 = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); Guard self_guard(self); EnvUDT* newEnv; DObjGDL* selfObj = NULL; if( self->Type() == GDL_OBJ) selfObj = static_cast( self); try { newEnv=new EnvUDT( selfObj, mp2, "", EnvUDT::LFUNCTION); self_guard.release(); } catch( GDLException& ex) { _t = mark; res=l_decinc_dot_expr(_t, dec_inc); _retTree = startNode->getNextSibling(); return refRet; } parameter_def(_t, newEnv); _t = _retTree; // push environment onto call stack callStack.push_back(newEnv); // make the call BaseGDL** ee=call_lfun(static_cast( newEnv->GetPro())->GetTree()); BaseGDL* e = *ee; if( e == NULL) throw GDLException( _t, "Variable is undefined: "+Name(ee),true,false); if( dec_inc == DECSTATEMENT || dec_inc == DEC_REF_CHECK) { e->Dec(); _retTree = startNode->getNextSibling(); return ee; } if( dec_inc == INCSTATEMENT || dec_inc == INC_REF_CHECK) { e->Inc(); _retTree = startNode->getNextSibling(); return ee; } if( dec_inc == DEC) e->Dec(); else if( dec_inc == INC) e->Inc(); // res = e->Dup(); if( dec_inc == POSTDEC) e->Dec(); else if( dec_inc == POSTINC) e->Inc(); _retTree = startNode->getNextSibling(); return ee; _t = __t32; _t = _t->getNextSibling(); break; } case DOT: { res=l_decinc_dot_expr(_t,dec_inc); _t = _retTree; break; } case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case EXPR: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case DEC: case INC: { e1=r_expr(_t); _t = _retTree; delete e1; throw GDLException( _t, "Expression not allowed with decrement/increment operator.",true,false); break; } case CONSTANT: { ProgNodeP tmp49_AST_in = _t; match(antlr::RefAST(_t),CONSTANT); _t = _t->getNextSibling(); throw GDLException( _t, "Constant not allowed with decrement/increment operator.",true,false); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return refRet; } BaseGDL* GDLInterpreter::expr(ProgNodeP _t) { BaseGDL* res; ProgNodeP expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; assert( _t != NULL); res = _t->Eval(); _retTree = _t->getNextSibling(); return res; //tmp_expr(_t); if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case ASSIGN_REPLACE: case ASSIGN_ARRAYEXPR_MFCALL: case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case FCALL_LIB_RETNEW: case MFCALL: case MFCALL_PARENT: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case VAR: case VARPTR: case DEC: case INC: case DOT: case QUESTION: { res=tmp_expr(_t); _t = _retTree; break; } case FCALL_LIB: { res=lib_function_call_internal(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::indexable_expr(ProgNodeP _t) { BaseGDL* res; ProgNodeP indexable_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->EvalNC(); _retTree = _t->getNextSibling(); return res; BaseGDL** e2; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case VAR: case VARPTR: { e2=l_defined_simple_var(_t); _t = _retTree; break; } case SYSVAR: { ProgNodeP tmp50_AST_in = _t; match(antlr::RefAST(_t),SYSVAR); _t = _t->getNextSibling(); break; } case CONSTANT: { ProgNodeP tmp51_AST_in = _t; match(antlr::RefAST(_t),CONSTANT); _t = _t->getNextSibling(); break; } case DEREF: { e2=l_deref(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::indexable_tmp_expr(ProgNodeP _t) { BaseGDL* res; ProgNodeP indexable_tmp_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->Eval(); //lib_function_call_retnew_internal(_t); _retTree = _t->getNextSibling(); return res; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case QUESTION: { { ProgNodeP tmp52_AST_in = _t; match(antlr::RefAST(_t),QUESTION); _t = _t->getNextSibling(); } break; } case ARRAYEXPR: { { ProgNodeP tmp53_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getNextSibling(); } break; } case DOT: { ProgNodeP tmp54_AST_in = _t; match(antlr::RefAST(_t),DOT); _t = _t->getNextSibling(); break; } case ASSIGN: case ASSIGN_REPLACE: case ASSIGN_ARRAYEXPR_MFCALL: { res=assign_expr(_t); _t = _retTree; break; } case ARRAYEXPR_MFCALL: case FCALL: case MFCALL: case MFCALL_PARENT: { res=unused_function_call(_t); _t = _retTree; break; } case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case EXPR: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case DEC: case INC: { res=r_expr(_t); _t = _retTree; break; } case FCALL_LIB_RETNEW: { res=lib_function_call_retnew_internal(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::lib_function_call_internal(ProgNodeP _t) { BaseGDL* res; ProgNodeP lib_function_call_internal_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; assert( _t->getType() == FCALL_LIB); BaseGDL** retValPtr; res = static_cast(_t)->EvalFCALL_LIB(retValPtr); _retTree = _t->getNextSibling(); callStack.back()->SetPtrToReturnValue( retValPtr); return res; ProgNodeP tmp55_AST_in = _t; match(antlr::RefAST(_t),FCALL_LIB); _t = _t->getNextSibling(); _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_expr_internal(ProgNodeP _t, BaseGDL* right ) { BaseGDL** res; ProgNodeP l_expr_internal_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->LExpr( right); _retTree = _t->getNextSibling(); return res; BaseGDL* e1; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case QUESTION: { ProgNodeP tmp56_AST_in = _t; match(antlr::RefAST(_t),QUESTION); _t = _t->getNextSibling(); break; } case ARRAYEXPR: { res=unused_l_array_expr(_t, right); _t = _retTree; break; } case SYSVAR: { res=l_sys_var(_t); _t = _retTree; break; } case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: { res=l_function_call_internal(_t); _t = _retTree; break; } case DEREF: { res=l_deref(_t); _t = _retTree; break; } case VAR: case VARPTR: { res=l_simple_var(_t); _t = _retTree; break; } case ARRAYEXPR_MFCALL: { res=l_arrayexpr_mfcall(_t, right); _t = _retTree; break; } case DOT: { ProgNodeP tmp57_AST_in = _t; match(antlr::RefAST(_t),DOT); _t = _t->getNextSibling(); break; } case ASSIGN: { ProgNodeP tmp58_AST_in = _t; match(antlr::RefAST(_t),ASSIGN); _t = _t->getNextSibling(); break; } case ASSIGN_ARRAYEXPR_MFCALL: { ProgNodeP tmp59_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_ARRAYEXPR_MFCALL); _t = _t->getNextSibling(); break; } case ASSIGN_REPLACE: { ProgNodeP tmp60_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_REPLACE); _t = _t->getNextSibling(); break; } case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case EXPR: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case DEC: case INC: { e1=r_expr(_t); _t = _retTree; break; } case CONSTANT: { ProgNodeP tmp61_AST_in = _t; match(antlr::RefAST(_t),CONSTANT); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::tmp_expr(ProgNodeP _t) { BaseGDL* res; ProgNodeP tmp_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->Eval(); _retTree = _t->getNextSibling(); return res; BaseGDL** e2; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case DEREF: { e2=l_deref(_t); _t = _retTree; break; } case QUESTION: { { ProgNodeP tmp62_AST_in = _t; match(antlr::RefAST(_t),QUESTION); _t = _t->getNextSibling(); } break; } case ARRAYEXPR: { { ProgNodeP tmp63_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getNextSibling(); } break; } case DOT: { ProgNodeP tmp64_AST_in = _t; match(antlr::RefAST(_t),DOT); _t = _t->getNextSibling(); break; } case ASSIGN: case ASSIGN_REPLACE: case ASSIGN_ARRAYEXPR_MFCALL: { res=assign_expr(_t); _t = _retTree; break; } case ARRAYEXPR_MFCALL: case FCALL: case MFCALL: case MFCALL_PARENT: { res=unused_function_call(_t); _t = _retTree; break; } case ARRAYDEF: case ARRAYDEF_GENERALIZED_INDGEN: case EXPR: case NSTRUC: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case DEC: case INC: { res=r_expr(_t); _t = _retTree; break; } case CONSTANT: { ProgNodeP tmp65_AST_in = _t; match(antlr::RefAST(_t),CONSTANT); _t = _t->getNextSibling(); break; } case VAR: case VARPTR: { res=simple_var(_t); _t = _retTree; break; } case SYSVAR: { res=sys_var(_t); _t = _retTree; break; } case FCALL_LIB_RETNEW: { res=lib_function_call_retnew_internal(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_simple_var(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_simple_var_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; assert( _t != NULL); res = _t->LEval(); _retTree = _t->getNextSibling(); return res; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case VAR: { ProgNodeP tmp66_AST_in = _t; match(antlr::RefAST(_t),VAR); _t = _t->getNextSibling(); break; } case VARPTR: { ProgNodeP tmp67_AST_in = _t; match(antlr::RefAST(_t),VARPTR); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } void GDLInterpreter::parameter_def(ProgNodeP _t, EnvBaseT* actEnv ) { ProgNodeP parameter_def_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; // as actEnv is not on the stack guard it here Guard guard(actEnv); EnvBaseT* callerEnv = callStack.back(); EnvBaseT* oldNewEnv = callerEnv->GetNewEnv(); callerEnv->SetNewEnv( actEnv); try{ _retTree = _t; if( _retTree != NULL) { int nPar = _retTree->GetNParam(); int nSub = actEnv->GetPro()->NPar(); // // variable number of parameters // if( nSub == -1) // { // // _retTree != NULL, save one check // static_cast(_retTree)->Parameter( actEnv); // while(_retTree != NULL) // static_cast(_retTree)->Parameter( actEnv); // } // // fixed number of parameters if( nSub != -1 && nPar > nSub) // check here { throw GDLException( _t, actEnv->GetProName() + ": Incorrect number of arguments.", false, false); } else { // _retTree != NULL, save one check static_cast(_retTree)->Parameter( actEnv); // Parameter does no checking while(_retTree != NULL) static_cast(_retTree)->Parameter( actEnv); } actEnv->ResolveExtra(); // expand _EXTRA } } catch( GDLException& e) { callerEnv->SetNewEnv( oldNewEnv); // update line number, currently set to caller->CallingNode() // because actEnv is not on the stack yet, // report caller->Pro()'s name is ok, because we are not inside // the call yet e.SetErrorNodeP( actEnv->CallingNode()); throw e; } callerEnv->SetNewEnv( oldNewEnv); guard.release(); return; ProgNodeP tmp68_AST_in = _t; match(antlr::RefAST(_t),KEYDEF_REF); _t = _t->getNextSibling(); ProgNodeP tmp69_AST_in = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); _retTree = _t; } BaseGDL* GDLInterpreter::r_expr(ProgNodeP _t) { BaseGDL* res; ProgNodeP r_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res=_t->Eval(); _retTree = _t->getNextSibling(); return res; BaseGDL** refRet; // not used if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case EXPR: { ProgNodeP tmp70_AST_in = _t; match(antlr::RefAST(_t),EXPR); _t = _t->getNextSibling(); break; } case ARRAYDEF: { ProgNodeP tmp71_AST_in = _t; match(antlr::RefAST(_t),ARRAYDEF); _t = _t->getNextSibling(); break; } case ARRAYDEF_GENERALIZED_INDGEN: { ProgNodeP tmp72_AST_in = _t; match(antlr::RefAST(_t),ARRAYDEF_GENERALIZED_INDGEN); _t = _t->getNextSibling(); break; } case STRUC: { ProgNodeP tmp73_AST_in = _t; match(antlr::RefAST(_t),STRUC); _t = _t->getNextSibling(); break; } case NSTRUC: { ProgNodeP tmp74_AST_in = _t; match(antlr::RefAST(_t),NSTRUC); _t = _t->getNextSibling(); break; } case NSTRUC_REF: { ProgNodeP tmp75_AST_in = _t; match(antlr::RefAST(_t),NSTRUC_REF); _t = _t->getNextSibling(); break; } case DEC: { ProgNodeP __t43 = _t; ProgNodeP tmp76_AST_in = _t; match(antlr::RefAST(_t),DEC); _t = _t->getFirstChild(); refRet=l_decinc_expr(_t, DEC, res); _t = _retTree; _t = __t43; _t = _t->getNextSibling(); break; } case INC: { ProgNodeP __t44 = _t; ProgNodeP tmp77_AST_in = _t; match(antlr::RefAST(_t),INC); _t = _t->getFirstChild(); refRet=l_decinc_expr(_t, INC, res); _t = _retTree; _t = __t44; _t = _t->getNextSibling(); break; } case POSTDEC: { ProgNodeP __t45 = _t; ProgNodeP tmp78_AST_in = _t; match(antlr::RefAST(_t),POSTDEC); _t = _t->getFirstChild(); refRet=l_decinc_expr(_t, POSTDEC, res); _t = _retTree; _t = __t45; _t = _t->getNextSibling(); break; } case POSTINC: { ProgNodeP __t46 = _t; ProgNodeP tmp79_AST_in = _t; match(antlr::RefAST(_t),POSTINC); _t = _t->getFirstChild(); refRet=l_decinc_expr(_t, POSTINC, res); _t = _retTree; _t = __t46; _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_indexable_expr(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_indexable_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->LEval(); if( *res == NULL) { // check not needed for SYSVAR assert( _t->getType() != SYSVAR); if( _t->getType() == VARPTR) throw GDLException( _t, "Common block variable is undefined: "+ callStack.back()->GetString( *res),true,false); if( _t->getType() == VAR) throw GDLException( _t, "Variable is undefined: "+ callStack.back()->GetString(_t->varIx),true,false); throw GDLException( _t, "Heap variable is undefined: "+Name(res),true,false); } _retTree = _t->getNextSibling(); return res; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case EXPR: { ProgNodeP tmp80_AST_in = _t; match(antlr::RefAST(_t),EXPR); _t = _t->getNextSibling(); break; } case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: { res=l_function_call_internal(_t); _t = _retTree; break; } case ARRAYEXPR_MFCALL: { res=l_arrayexpr_mfcall_as_mfcall(_t); _t = _retTree; break; } case DEREF: { res=l_deref(_t); _t = _retTree; break; } case VAR: case VARPTR: { res=l_defined_simple_var(_t); _t = _retTree; break; } case SYSVAR: { res=l_sys_var(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_arrayexpr_mfcall_as_mfcall(ProgNodeP _t) { BaseGDL** res; ProgNodeP l_arrayexpr_mfcall_as_mfcall_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP mp2 = ProgNodeP(antlr::nullAST); // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack StackGuard guard(callStack); BaseGDL *self; EnvUDT* newEnv; ProgNodeP __t79 = _t; ProgNodeP tmp81_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR_MFCALL); _t = _t->getFirstChild(); _t = _t->getNextSibling(); // skip DOT self=expr(_t); _t = _retTree; mp2 = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); Guard self_guard(self); newEnv=new EnvUDT( self, mp2, "", EnvUDT::LFUNCTION); self_guard.release(); parameter_def(_t, newEnv); _t = _retTree; _t = __t79; _t = _t->getNextSibling(); // push environment onto call stack callStack.push_back(newEnv); // make the call res=call_lfun(static_cast( newEnv->GetPro())->GetTree()); _retTree = _t; return res; } BaseGDL** GDLInterpreter::unused_l_array_expr(ProgNodeP _t, BaseGDL* right ) { BaseGDL** res; ProgNodeP unused_l_array_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ArrayIndexListT* aL; ProgNodeP __t35 = _t; ProgNodeP tmp82_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); res=l_indexable_expr(_t); _t = _retTree; aL=arrayindex_list(_t, false); _t = _retTree; _t = __t35; _t = _t->getNextSibling(); _retTree = _t; return res; } ArrayIndexListT* GDLInterpreter::arrayindex_list(ProgNodeP _t, bool noAssoc ) { ArrayIndexListT* aL; ProgNodeP arrayindex_list_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; // IxExprListT cleanupList; // for cleanup IxExprListT ixExprList; SizeT nExpr; BaseGDL* s; // ProgNodeP retTree = _t->getNextSibling(); ProgNodeP ax = _t; // match(antlr::RefAST(_t),ARRAYIX); _t = _t->getFirstChild(); if( noAssoc) aL = ax->arrIxListNoAssoc; else aL = ax->arrIxList; assert( aL != NULL); nExpr = aL->NParam(); if( nExpr == 0) { aL->Init(); _retTree = ax->getNextSibling();//retTree; return aL; } IxExprListT* cleanupList = aL->GetCleanupIx(); // for cleanup while( true) { assert( _t != NULL); if( NonCopyNode( _t->getType())) { s = _t->EvalNC(); } else { BaseGDL** ref =_t->EvalRefCheck( s); if( ref == NULL) cleanupList->push_back( s); else s = *ref; } assert( s != NULL); ixExprList.push_back( s); if( ixExprList.size() == nExpr) break; // allows some manual tuning _t = _t->getNextSibling(); } aL->Init( ixExprList);//, &cleanupList); _retTree = ax->getNextSibling();//retTree; return aL; ProgNodeP tmp83_AST_in = _t; match(antlr::RefAST(_t),ARRAYIX); _t = _t->getNextSibling(); _retTree = _t; return aL; } void GDLInterpreter::l_dot_array_expr(ProgNodeP _t, DotAccessDescT* aD ) { ProgNodeP l_dot_array_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ArrayIndexListT* aL; BaseGDL** rP; if( _t->getType() == ARRAYEXPR) { rP=l_indexable_expr(_t->getFirstChild()); aL=arrayindex_list(_retTree,!(*rP)->IsAssoc()); _retTree = _t->getNextSibling(); SetRootL( _t, aD, *rP, aL); } else // case ARRAYEXPR_MFCALL: // case DEREF: // case EXPR: // case FCALL: // case FCALL_LIB: // case MFCALL: // case MFCALL_PARENT: // case SYSVAR: // case VAR: // case VARPTR: { rP=l_indexable_expr(_t); SetRootL( _t, aD, *rP, NULL); } return; // _retTree = _t; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { ProgNodeP __t37 = _t; ProgNodeP tmp84_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); rP=l_indexable_expr(_t); _t = _retTree; aL=arrayindex_list(_t, false); _t = _retTree; _t = __t37; _t = _t->getNextSibling(); break; } case ARRAYEXPR_MFCALL: case DEREF: case EXPR: case FCALL: case FCALL_LIB: case MFCALL: case MFCALL_PARENT: case SYSVAR: case VAR: case VARPTR: { rP=l_indexable_expr(_t); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } BaseGDL** GDLInterpreter::l_arrayexpr_mfcall(ProgNodeP _t, BaseGDL* right ) { BaseGDL** res; ProgNodeP l_arrayexpr_mfcall_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP mp2 = ProgNodeP(antlr::nullAST); ProgNodeP dot = ProgNodeP(antlr::nullAST); // better than Guard: Guard wouldn't remove newEnv from the stack StackGuard guard(callStack); BaseGDL *self; EnvUDT* newEnv; ProgNodeP startNode = _t; ProgNodeP __t69 = _t; ProgNodeP tmp85_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR_MFCALL); _t = _t->getFirstChild(); ProgNodeP mark = _t; _t = _t->getNextSibling(); // skip DOT self=expr(_t); _t = _retTree; mp2 = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); Guard self_guard(self); try { newEnv=new EnvUDT( self, mp2, "", EnvUDT::LFUNCTION); self_guard.release(); } catch( GDLException& ex) { goto tryARRAYEXPR; } parameter_def(_t, newEnv); _t = _retTree; _t = __t69; _t = _t->getNextSibling(); // push environment onto call stack callStack.push_back(newEnv); // make the call res=call_lfun(static_cast( newEnv->GetPro())->GetTree()); _retTree = startNode->getNextSibling(); return res; tryARRAYEXPR:; _t = mark; ProgNodeP __t70 = _t; dot = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; match(antlr::RefAST(_t),DOT); _t = _t->getFirstChild(); SizeT nDot=dot->nDot; Guard aD( new DotAccessDescT(nDot+1)); l_dot_array_expr(_t, aD.Get()); _t = _retTree; { // ( ... )+ int _cnt72=0; for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == ARRAYEXPR || _t->getType() == EXPR || _t->getType() == IDENTIFIER)) { tag_array_expr(_t, aD.Get()); _t = _retTree; } else { if ( _cnt72>=1 ) { goto _loop72; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt72++; } _loop72:; } // ( ... )+ _t = __t70; _t = _t->getNextSibling(); if( right == NULL) throw GDLException( _t, "Struct expression not allowed in this context.", true,false); aD.Get()->ADAssign( right); res=NULL; _retTree = startNode->getNextSibling(); return res; _retTree = _t; return res; } void GDLInterpreter::tag_expr(ProgNodeP _t, DotAccessDescT* aD ) { ProgNodeP tag_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; BaseGDL* e; if( _t->getType() == EXPR) { ProgNodeP tIn = _t; _t = _t->getFirstChild(); e=expr(_t); Guard e_guard(e); SizeT tagIx; int ret=e->Scalar2Index(tagIx); if( ret < 1) // this is a return code, not the index throw GDLException( tIn, "Expression must be a scalar" " >= 0 in this context: "+Name(e),true,false); aD->ADAdd( tagIx); _retTree = tIn->getNextSibling(); } else // case IDENTIFIER: { assert( _t->getType() == IDENTIFIER); std::string tagName=_t->getText(); aD->ADAdd( tagName); _retTree = _t->getNextSibling(); } return; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case EXPR: { ProgNodeP tmp86_AST_in = _t; match(antlr::RefAST(_t),EXPR); _t = _t->getNextSibling(); break; } case IDENTIFIER: { ProgNodeP tmp87_AST_in = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } void GDLInterpreter::tag_array_expr(ProgNodeP _t, DotAccessDescT* aD ) { ProgNodeP tag_array_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ArrayIndexListT* aL; if( _t->getType() == ARRAYEXPR) { ProgNodeP tIn = _t; _t = _t->getFirstChild(); tag_expr(_t, aD); _t = _retTree; // noAssoc==true, as assoc vars cannot be struct members aL=arrayindex_list(_t,true); //_t = _retTree; aD->ADAddIx(aL); _retTree = tIn->getNextSibling(); } else // case EXPR: // case IDENTIFIER: { tag_expr(_t, aD); //_t = _retTree; aD->ADAddIx(NULL); } //_retTree = _t; return; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { ProgNodeP __t49 = _t; ProgNodeP tmp88_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); tag_expr(_t, aD); _t = _retTree; aL=arrayindex_list(_t, true); _t = _retTree; _t = __t49; _t = _t->getNextSibling(); break; } case EXPR: case IDENTIFIER: { tag_expr(_t, aD); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } BaseGDL* GDLInterpreter::r_dot_indexable_expr(ProgNodeP _t, DotAccessDescT* aD ) { BaseGDL* res; ProgNodeP r_dot_indexable_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res=NULL; switch ( _t->getType()) { case EXPR: { ProgNodeP tIn = _t; _t = _t->getFirstChild(); //res=expr(_t); res = _t->Eval(); aD->SetOwner( true); _retTree = tIn->getNextSibling(); break; } case VAR: case VARPTR: { BaseGDL** v=l_defined_simple_var(_t); //_t = _retTree; res = *v; break; } case SYSVAR: { res = _t->EvalNC(); _retTree = _t->getNextSibling(); //res=sys_var_nocopy(_t); //_t = _retTree; break; } } //_retTree = _t; return res; BaseGDL** e; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case EXPR: { ProgNodeP __t51 = _t; ProgNodeP tmp89_AST_in = _t; match(antlr::RefAST(_t),EXPR); _t = _t->getFirstChild(); res=expr(_t); _t = _retTree; aD->SetOwner( true); _t = __t51; _t = _t->getNextSibling(); break; } case VAR: case VARPTR: { e=l_defined_simple_var(_t); _t = _retTree; break; } case SYSVAR: { ProgNodeP tmp90_AST_in = _t; match(antlr::RefAST(_t),SYSVAR); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } void GDLInterpreter::r_dot_array_expr(ProgNodeP _t, DotAccessDescT* aD ) { ProgNodeP r_dot_array_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; BaseGDL* r; ArrayIndexListT* aL; if( _t->getType() == ARRAYEXPR) { //match(antlr::RefAST(_t),ARRAYEXPR); r=r_dot_indexable_expr(_t->getFirstChild(), aD); aL=arrayindex_list(_retTree,!r->IsAssoc()); _retTree = _t->getNextSibling(); // check here for object and get struct SetRootR( _t, aD, r, aL); } else { r=r_dot_indexable_expr(_t, aD); //_t = _retTree; // check here for object and get struct SetRootR( _t, aD, r, NULL); } return; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { ProgNodeP __t53 = _t; ProgNodeP tmp91_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); r=r_dot_indexable_expr(_t, aD); _t = _retTree; aL=arrayindex_list(_t, false); _t = _retTree; _t = __t53; _t = _t->getNextSibling(); break; } case EXPR: case SYSVAR: case VAR: case VARPTR: { r=r_dot_indexable_expr(_t, aD); _t = _retTree; break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; } BaseGDL* GDLInterpreter::assign_expr(ProgNodeP _t) { BaseGDL* res; ProgNodeP assign_expr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->Eval(); _retTree = _t->getNextSibling(); return res; BaseGDL** l; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: { ProgNodeP tmp92_AST_in = _t; match(antlr::RefAST(_t),ASSIGN); _t = _t->getNextSibling(); break; } case ASSIGN_ARRAYEXPR_MFCALL: { ProgNodeP tmp93_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_ARRAYEXPR_MFCALL); _t = _t->getNextSibling(); break; } case ASSIGN_REPLACE: { ProgNodeP tmp94_AST_in = _t; match(antlr::RefAST(_t),ASSIGN_REPLACE); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::unused_function_call(ProgNodeP _t) { BaseGDL* res; ProgNodeP unused_function_call_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res=NULL; if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case MFCALL: { ProgNodeP tmp95_AST_in = _t; match(antlr::RefAST(_t),MFCALL); _t = _t->getNextSibling(); break; } case MFCALL_PARENT: { ProgNodeP tmp96_AST_in = _t; match(antlr::RefAST(_t),MFCALL_PARENT); _t = _t->getNextSibling(); break; } case FCALL: { ProgNodeP tmp97_AST_in = _t; match(antlr::RefAST(_t),FCALL); _t = _t->getNextSibling(); break; } case ARRAYEXPR_MFCALL: { ProgNodeP tmp98_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR_MFCALL); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::lib_function_call_retnew_internal(ProgNodeP _t) { BaseGDL* res; ProgNodeP lib_function_call_retnew_internal_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->Eval(); _retTree = _t->getNextSibling(); return res; //_t->cData->Dup(); ProgNodeP tmp99_AST_in = _t; match(antlr::RefAST(_t),FCALL_LIB_RETNEW); _t = _t->getNextSibling(); _retTree = _t; return res; } BaseGDL* GDLInterpreter::simple_var(ProgNodeP _t) { BaseGDL* res; ProgNodeP simple_var_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; assert( _t != NULL); BaseGDL* vData = _t->EvalNC(); if( vData == NULL) { if( _t->getType() == VAR) throw GDLException( _t, "Variable is undefined: "+_t->getText(),true,false); else // VARPTR throw GDLException( _t, "Common block variable is undefined.",true,false); } _retTree = _t->getNextSibling(); return vData->Dup(); if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case VAR: { ProgNodeP tmp100_AST_in = _t; match(antlr::RefAST(_t),VAR); _t = _t->getNextSibling(); break; } case VARPTR: { ProgNodeP tmp101_AST_in = _t; match(antlr::RefAST(_t),VARPTR); _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } _retTree = _t; return res; } BaseGDL* GDLInterpreter::sys_var(ProgNodeP _t) { BaseGDL* res; ProgNodeP sys_var_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; res = _t->Eval(); _retTree = _t->getNextSibling(); return res; // no ->Dup() ProgNodeP tmp102_AST_in = _t; match(antlr::RefAST(_t),SYSVAR); _t = _t->getNextSibling(); _retTree = _t; return res; } BaseGDL** GDLInterpreter::l_arrayexpr_mfcall_as_arrayexpr(ProgNodeP _t, BaseGDL* right ) { BaseGDL** res; ProgNodeP l_arrayexpr_mfcall_as_arrayexpr_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ProgNodeP dot = ProgNodeP(antlr::nullAST); ProgNodeP __t74 = _t; ProgNodeP tmp103_AST_in = _t; match(antlr::RefAST(_t),ARRAYEXPR_MFCALL); _t = _t->getFirstChild(); ProgNodeP __t75 = _t; dot = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; match(antlr::RefAST(_t),DOT); _t = _t->getFirstChild(); SizeT nDot=dot->nDot; Guard aD( new DotAccessDescT(nDot+1)); l_dot_array_expr(_t, aD.Get()); _t = _retTree; { // ( ... )+ int _cnt77=0; for (;;) { if (_t == ProgNodeP(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == ARRAYEXPR || _t->getType() == EXPR || _t->getType() == IDENTIFIER)) { tag_array_expr(_t, aD.Get()); _t = _retTree; } else { if ( _cnt77>=1 ) { goto _loop77; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt77++; } _loop77:; } // ( ... )+ _t = __t75; _t = _t->getNextSibling(); _t = __t74; _t = _t->getNextSibling(); if( right == NULL) throw GDLException( _t, "Struct expression not allowed in this context.", true,false); aD.Get()->ADAssign( right); res=NULL; _retTree = _t; return res; } void GDLInterpreter::parameter_def_n_elements(ProgNodeP _t, EnvBaseT* actEnv ) { ProgNodeP parameter_def_n_elements_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; Guard guard(actEnv); _retTree = _t; // bool interruptEnableIn = interruptEnable; if( _retTree != NULL) { int nPar = _retTree->GetNParam(); //int nSub = actEnv->GetPro()->NPar(); assert( actEnv->GetPro()->NPar() == 1); // N_ELEMENTS // fixed number of parameters if( nPar > 1)//nSub) // check here { throw GDLException( _t, actEnv->GetProName() + ": Incorrect number of arguments.", false, false); } if( _retTree->getType() == REF || _retTree->getType() == REF_EXPR || _retTree->getType() == REF_CHECK || _retTree->getType() == PARAEXPR) { try { // interruptEnable = false; static_cast(_retTree)->Parameter( actEnv); // interruptEnable = interruptEnableIn; } catch( GDLException& e) { // an error occured -> parameter is undefined // interruptEnable = interruptEnableIn; if( actEnv->NParam() == 0) // not set yet { BaseGDL* nullP = NULL; actEnv->SetNextPar( nullP); } } } else // used for error handling: keywords are checked only here in Parameter() { try { // as N_ELEMENTS has no keywords this should throw always static_cast(_retTree)->Parameter( actEnv); assert( 0); } catch( GDLException& e) { // update line number, currently set to caller->CallingNode() // because actEnv is not on the stack yet, // report caller->Pro()'s name is ok, because we are not inside // the call yet e.SetErrorNodeP( actEnv->CallingNode()); throw e; } } // actEnv->Extra(); // expand _EXTRA } // if( _retTree != NULL) guard.release(); return; ProgNodeP tmp104_AST_in = _t; match(antlr::RefAST(_t),KEYDEF_REF_EXPR); _t = _t->getNextSibling(); ProgNodeP tmp105_AST_in = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); _retTree = _t; } void GDLInterpreter::parameter_def_nocheck(ProgNodeP _t, EnvBaseT* actEnv ) { ProgNodeP parameter_def_nocheck_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; Guard guard(actEnv); EnvBaseT* callerEnv = callStack.back(); EnvBaseT* oldNewEnv = callerEnv->GetNewEnv(); callerEnv->SetNewEnv( actEnv); try{ if( _t != NULL) { _retTree = _t; // _retTree != NULL, save one check // 'if' is needed already for Extra() static_cast(_retTree)->Parameter( actEnv); // Parameter does no checking while(_retTree != NULL) static_cast(_retTree)->Parameter( actEnv); actEnv->ResolveExtra(); // expand _EXTRA } } catch( GDLException& e) { callerEnv->SetNewEnv( oldNewEnv); // update line number, currently set to caller->CallingNode() // because actEnv is not on the stack yet, // report caller->Pro()'s name is ok, because we are not inside // the call yet e.SetErrorNodeP( actEnv->CallingNode()); throw e; } callerEnv->SetNewEnv( oldNewEnv); guard.release(); return; ProgNodeP tmp106_AST_in = _t; match(antlr::RefAST(_t),KEYDEF_REF); _t = _t->getNextSibling(); ProgNodeP tmp107_AST_in = _t; match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); _retTree = _t; } void GDLInterpreter::arrayindex_list_overload(ProgNodeP _t, IxExprListT& indexList ) { ProgNodeP arrayindex_list_overload_AST_in = (_t == ProgNodeP(ASTNULL)) ? ProgNodeP(antlr::nullAST) : _t; ArrayIndexListT* aL; // IxExprListT cleanupList; // for cleanup IxExprListT ixExprList; SizeT nExpr; BaseGDL* s; // ProgNodeP retTree = _t->getNextSibling(); ProgNodeP ax = _t; // match(antlr::RefAST(_t),ARRAYIX); _t = _t->getFirstChild(); aL = ax->arrIxListNoAssoc; assert( aL != NULL); nExpr = aL->NParam(); if( nExpr == 0) { aL->InitAsOverloadIndex( ixExprList, /* NULL,*/ indexList); _retTree = ax->getNextSibling();//retTree; return; } IxExprListT* cleanupList = aL->GetCleanupIx(); while( true) { assert( _t != NULL); if( NonCopyNode( _t->getType())) { s= _t->EvalNCNull(); // in this case (overload) NULL is ok //_t = _retTree; } else { BaseGDL** ref=_t->EvalRefCheck( s); //indexable_tmp_expr(_t); //_t = _retTree; if( ref == NULL) cleanupList->push_back( s); else s = *ref; } ixExprList.push_back( s); if( ixExprList.size() == nExpr) break; // allows some manual tuning _t = _t->getNextSibling(); } aL->InitAsOverloadIndex( ixExprList, /*&cleanupList,*/ indexList); _retTree = ax->getNextSibling();//retTree; return; ProgNodeP tmp108_AST_in = _t; match(antlr::RefAST(_t),ARRAYIX); _t = _t->getNextSibling(); _retTree = _t; } void GDLInterpreter::initializeASTFactory( antlr::ASTFactory& ) { } const char* GDLInterpreter::tokenNames[] = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "ALL", "ASSIGN", "ASSIGN_INPLACE", "ASSIGN_REPLACE", "ASSIGN_ARRAYEXPR_MFCALL", "ARRAYDEF", "ARRAYDEF_CONST", "ARRAYDEF_GENERALIZED_INDGEN", "ARRAYIX", "ARRAYIX_ALL", "ARRAYIX_ORANGE", "ARRAYIX_RANGE", "ARRAYIX_ORANGE_S", "ARRAYIX_RANGE_S", "ARRAYEXPR", "ARRAYEXPR_FCALL", "ARRAYEXPR_MFCALL", "BLOCK", "BREAK", "CSBLOCK", "CONTINUE", "COMMONDECL", "COMMONDEF", "CONSTANT", "DEREF", "ELSEBLK", "EXPR", "\"for\"", "FOR_STEP", "\"foreach\"", "FOREACH_INDEX", "FOR_LOOP", "FOR_STEP_LOOP", "FOREACH_LOOP", "FOREACH_INDEX_LOOP", "FCALL", "FCALL_LIB", "FCALL_LIB_DIRECT", "FCALL_LIB_N_ELEMENTS", "FCALL_LIB_RETNEW", "GDLNULL", "IF_ELSE", "KEYDECL", "KEYDEF", "KEYDEF_REF", "KEYDEF_REF_CHECK", "KEYDEF_REF_EXPR", "LABEL", "MPCALL", "MPCALL_PARENT", "MFCALL", "MFCALL_LIB", "MFCALL_LIB_RETNEW", "MFCALL_PARENT", "MFCALL_PARENT_LIB", "MFCALL_PARENT_LIB_RETNEW", "NOP", "NSTRUC", "NSTRUC_REF", "ON_IOERROR_NULL", "PCALL", "PCALL_LIB", "PARADECL", "PARAEXPR", "PARAEXPR_VN", "DEC_REF_CHECK", "INC_REF_CHECK", "POSTDEC", "POSTINC", "DECSTATEMENT", "INCSTATEMENT", "REF", "REF_VN", "REF_CHECK", "REF_CHECK_VN", "REF_EXPR", "REF_EXPR_VN", "\"repeat\"", "REPEAT_LOOP", "RETURN", "RETF", "RETP", "STRUC", "SYSVAR", "UMINUS", "VAR", "VARPTR", "\"while\"", "IDENTIFIER", "\"and\"", "\"begin\"", "\"case\"", "\"common\"", "\"compile_opt\"", "\"do\"", "\"else\"", "\"end\"", "\"endcase\"", "\"endelse\"", "\"endfor\"", "\"endforeach\"", "\"endif\"", "\"endrep\"", "\"endswitch\"", "\"endwhile\"", "\"eq\"", "\"forward_function\"", "\"function\"", "\"ge\"", "\"goto\"", "\"gt\"", "\"if\"", "\"inherits\"", "\"le\"", "\"lt\"", "\"mod\"", "\"ne\"", "\"not\"", "\"of\"", "\"on_ioerror\"", "\"or\"", "\"pro\"", "\"switch\"", "\"then\"", "\"until\"", "\"xor\"", "METHOD", "COMMA", "COLON", "END_U", "EQUAL", "DEC", "INC", "AND_OP_EQ", "ASTERIX_EQ", "EQ_OP_EQ", "GE_OP_EQ", "GTMARK_EQ", "GT_OP_EQ", "LE_OP_EQ", "LTMARK_EQ", "LT_OP_EQ", "MATRIX_OP1_EQ", "MATRIX_OP2_EQ", "MINUS_EQ", "MOD_OP_EQ", "NE_OP_EQ", "OR_OP_EQ", "PLUS_EQ", "POW_EQ", "SLASH_EQ", "XOR_OP_EQ", "MEMBER", "LBRACE", "RBRACE", "SLASH", "LSQUARE", "RSQUARE", "SYSVARNAME", "EXCLAMATION", "LCURLY", "RCURLY", "CONSTANT_HEX_BYTE", "CONSTANT_HEX_LONG", "CONSTANT_HEX_LONG64", "CONSTANT_HEX_INT", "CONSTANT_HEX_I", "CONSTANT_HEX_ULONG", "CONSTANT_HEX_ULONG64", "CONSTANT_HEX_UI", "CONSTANT_HEX_UINT", "CONSTANT_BYTE", "CONSTANT_LONG", "CONSTANT_LONG64", "CONSTANT_INT", "CONSTANT_I", "CONSTANT_ULONG", "CONSTANT_ULONG64", "CONSTANT_UI", "CONSTANT_UINT", "CONSTANT_OCT_BYTE", "CONSTANT_OCT_LONG", "CONSTANT_OCT_LONG64", "CONSTANT_OCT_INT", "CONSTANT_OCT_I", "CONSTANT_OCT_ULONG", "CONSTANT_OCT_ULONG64", "CONSTANT_OCT_UI", "CONSTANT_OCT_UINT", "CONSTANT_FLOAT", "CONSTANT_DOUBLE", "CONSTANT_BIN_BYTE", "CONSTANT_BIN_LONG", "CONSTANT_BIN_LONG64", "CONSTANT_BIN_INT", "CONSTANT_BIN_I", "CONSTANT_BIN_ULONG", "CONSTANT_BIN_ULONG64", "CONSTANT_BIN_UI", "CONSTANT_BIN_UINT", "ASTERIX", "DOT", "STRING_LITERAL", "POW", "MATRIX_OP1", "MATRIX_OP2", "PLUS", "MINUS", "LTMARK", "GTMARK", "LOG_NEG", "LOG_AND", "LOG_OR", "QUESTION", "STRING", "INCLUDE", "EOL", "W", "D", "L", "H", "O", "B", "EXP", "DBL_E", "DBL", "CONSTANT_OR_STRING_LITERAL", "COMMENT", "END_MARKER", "WHITESPACE", "SKIP_LINES", "CONT_STATEMENT", "END_OF_LINE", "MAX_TOKEN_NUMBER", 0 }; const unsigned long GDLInterpreter::_tokenSet_0_data_[] = { 2170552736UL, 2151161983UL, 2285240323UL, 1208614912UL, 384UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // ASSIGN ASSIGN_REPLACE ASSIGN_ARRAYEXPR_MFCALL BLOCK BREAK CONTINUE "for" // FOR_STEP "foreach" FOREACH_INDEX FOR_LOOP FOR_STEP_LOOP FOREACH_LOOP // FOREACH_INDEX_LOOP IF_ELSE LABEL MPCALL MPCALL_PARENT ON_IOERROR_NULL // PCALL PCALL_LIB "repeat" REPEAT_LOOP RETF RETP "while" "case" "goto" // "if" "on_ioerror" "switch" DEC INC const antlr::BitSet GDLInterpreter::_tokenSet_0(_tokenSet_0_data_,12); gdl-0.9.9/src/GDLInterpreter.hpp000066400000000000000000000720261340051421000164260ustar00rootroot00000000000000#ifndef INC_GDLInterpreter_hpp_ #define INC_GDLInterpreter_hpp_ #include #include "GDLInterpreterTokenTypes.hpp" /* $ANTLR 2.7.7 (2006-11-01): "gdlc.i.g" -> "GDLInterpreter.hpp"$ */ #include // antlr header // make sure it gets included before the 'tweak' #include "GDLParser.hpp" #include "GDLTreeParser.hpp" #include #include //#include #include "datatypes.hpp" #include "objects.hpp" #include "dpro.hpp" #include "accessdesc.hpp" #include "initsysvar.hpp" #include "gdljournal.hpp" //class ProgNode; //typedef ProgNode* ProgNodeP; // tweaking ANTLR #define RefAST( xxx) ConvertAST( xxx) /* antlr::RefAST( Ref type) */ // print out AST tree //#define GDL_DEBUG //#undef GDL_DEBUG //#define GDL_DEBUG_HEAP bool IsEnabledGC(); // defined in GDLInterpreter.hpp with EnableGC(bool); void EnableGC(bool); class CUSTOM_API GDLInterpreter : public antlr::TreeParser, public GDLInterpreterTokenTypes { private: // ASTNULL replacement static ProgNode NULLProgNode; static ProgNodeP NULLProgNodeP; friend class BaseGDL; friend class ProgNode; friend class ARRAYDEFNode; friend class ARRAYDEF_GENERALIZED_INDGENNode; friend class STRUCNode; friend class NSTRUCNode; friend class NSTRUC_REFNode; friend class ASSIGNNode; friend class ASSIGN_ARRAYEXPR_MFCALLNode; friend class ASSIGN_REPLACENode; friend class PCALL_LIBNode;//: public CommandNode friend class MPCALLNode;//: public CommandNode friend class MPCALL_PARENTNode;//: public CommandNode friend class PCALLNode;//: public CommandNode friend class RETFNode; friend class RETPNode; friend class FORNode; friend class FOR_LOOPNode; friend class FOREACHNode; friend class FOREACH_LOOPNode; friend class FOREACH_INDEXNode; friend class FOREACH_INDEX_LOOPNode; friend class FOR_STEPNode; friend class FOR_STEP_LOOPNode; friend class KEYDEFNode; friend class KEYDEF_REFNode; friend class KEYDEF_REF_CHECKNode; friend class KEYDEF_REF_EXPRNode; friend class REFNode; friend class REF_CHECKNode; friend class REF_EXPRNode; friend class ParameterNode; friend class REFVNNode; friend class REF_CHECKVNNode; friend class REF_EXPRVNNode; friend class ParameterVNNode; friend class WRAPPED_FUNNode; friend class WRAPPED_PRONode; public: // RetCode returnCode; ProgNodeP GetNULLProgNodeP() const { return NULLProgNodeP;} void SetRetTree( ProgNodeP rT) { this->_retTree = rT; } ProgNodeP GetRetTree() const { return this->_retTree; } // void SetReturnCode( RetCode rC) // { // this->returnCode = rC; // } // enum RetCode { // RC_OK=0, // RC_BREAK, // RC_CONTINUE, // RC_RETURN, // RC_ABORT, // checked as retCode >= RC_RETURN // }; // code in: dinterpreter.cpp // procedure (searchForPro == true) or function (searchForPro == false) static bool SearchCompilePro(const std::string& pro, bool searchForPro); static int GetFunIx( ProgNodeP); static int GetFunIx( const std::string& subName); static int GetProIx( ProgNodeP, bool throwImmediately=false);//const std::string& subName); static int GetProIx( const std::string& subName); DStructGDL* ObjectStruct( DObjGDL* self, ProgNodeP mp); void SetRootR( ProgNodeP tt, DotAccessDescT* aD, BaseGDL* r, ArrayIndexListT* aL); void SetRootL( ProgNodeP tt, DotAccessDescT* aD, BaseGDL* r, ArrayIndexListT* aL); // DStructGDL* ObjectStructCheckAccess( DObjGDL* self, ProgNodeP mp); // DStructDesc* GDLObjectDesc( DObjGDL* self, ProgNodeP mp); // code in: dinterpreter.cpp static void SetFunIx( ProgNodeP f); // triggers read/compile private: static void SetProIx( ProgNodeP f, bool throwImmediately=false); // triggers read/compile static void AdjustTypes( BaseGDL*&, BaseGDL*&); protected: std::istringstream executeLine; // actual interactive executed line // std::vector tmpList; // void ClearTmpList() // { // std::vector::iterator i; // for(i = tmpList.begin(); i != tmpList.end(); ++i) // { delete *i;} // tmpList.clear(); // } class RetAllException { public: enum ExCode { NONE=0 // normal RETALL ,RUN // RETALL from .RUN command ,RESET // RETALL from .RESET command ,FULL_RESET // RETALL from .FULL_RESET command }; private: ExCode code; public: RetAllException( ExCode code_=NONE): code( code_) {} ExCode Code() { return code;} }; // code in: dinterpreter.cpp // static bool CompleteFileName(std::string& fn); -> str.cpp BaseGDL* returnValue; // holding the return value for functions BaseGDL** returnValueL; // holding the return value for l_functions bool interruptEnable; public: bool InterruptEnable() const { return interruptEnable;} // procedure (searchForPro == true) or function (searchForPro == false) static bool CompileFile(const std::string& f, const std::string& untilPro="", bool searchForPro=true); typedef RefHeap RefBaseGDL; typedef RefHeap RefDStructGDL; typedef std::map HeapT; typedef std::map ObjHeapT; protected: // typedef std::map HeapT; // typedef std::map ObjHeapT; // the following must be all static because several interpreter might be active // the heap for all dynamic variables // ease the handling, no memory leaks, gc possible static HeapT heap; static ObjHeapT objHeap; // index for newly allocated heap variables static SizeT objHeapIx; static SizeT heapIx; static EnvStackT callStack; static DLong stepCount; // smuggle optimizations in //#include "GDLInterpreterOptimized.inc" public: // triggers read/compile/interpret DStructDesc* GetStruct(const std::string& name, const ProgNodeP cN); // bool Called( std::string proName) // { // for( EnvStackT::reverse_iterator env = callStack.rbegin(); // env != callStack.rend(); // ++env) // { // //std::cout << (*env)->GetPro()->ObjectFileName() << std::endl; // if( proName == (*env)->GetPro()->ObjectFileName()) return true; // } // return false; // } // static bool IsEnabledGC() { return enable_GC;} static bool IsEnabledGC() { return true;} // the New... functions 'own' their BaseGDL* SizeT NewObjHeap( SizeT n=1, DStructGDL* var=NULL) { SizeT tmpIx=objHeapIx; for( SizeT i=0; i( objHeapIx++, (DStructGDL*)var)); return tmpIx; } SizeT NewHeap( SizeT n=1, BaseGDL* var=NULL) { SizeT tmpIx=heapIx; for( SizeT i=0; i( heapIx++, var)); return tmpIx; } static void FreeObjHeapDirect( DObj id, ObjHeapT::iterator it) { BaseGDL* del = (*it).second.get(); objHeap.erase( id); delete del; // delete (*it).second.get(); // objHeap.erase( id); } static void FreeObjHeap( DObj id) { if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if ( it != objHeap.end()) { FreeObjHeapDirect( id, it); // delete (*it).second.get(); // objHeap.erase( id); } } } static void FreeHeapDirect( DPtr id, HeapT::iterator it) { BaseGDL* del = (*it).second.get(); heap.erase( id); delete del; // delete (*it).second.get(); // // useless because of next: (*it).second.get() = NULL; // heap.erase( id); } static void FreeHeap( DPtr id) { if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end()) { FreeHeapDirect( id, it); // delete (*it).second.get(); // heap.erase( id); } } } static void HeapErase( DPtr id) // for LIST { if( id != 0) { heap.erase( id); } } static void FreeHeap( DPtrGDL* p) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; FreeHeap( id); } } static DByteGDL* IsEnabledGC( DPtrGDL* p) { SizeT nEl=p->N_Elements(); if( nEl == 0) return new DByteGDL( 0); DByteGDL* ret = new DByteGDL( p->Dim()); Guard guard(ret); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end() and (*it).second.IsEnabledGC()) (*ret)[ix] = 1; } } return guard.release(); } static DByteGDL* IsEnabledGCObj( DObjGDL* p) { SizeT nEl=p->N_Elements(); if( nEl == 0) return new DByteGDL( 0); DByteGDL* ret = new DByteGDL( p->Dim()); Guard guard(ret); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end() and (*it).second.IsEnabledGC()) (*ret)[ix] = 1; } } return guard.release(); } static void EnableGC( DPtr id, bool set=true) { if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end()) (*it).second.EnableGC(set); } } static void EnableGC( DPtrGDL* p, bool set=true) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; EnableGC( id, set); } } static void EnableAllGC() { SizeT nEl = heap.size(); for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) it->second.EnableGC(true); nEl = objHeap.size(); for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) it->second.EnableGC(true); } static void EnableGCObj( DObj id, bool set=true) { if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) (*it).second.EnableGC(set); } } static void EnableGCObj( DObjGDL* p, bool set=true) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; EnableGCObj( id, set); } } static void DecRef( DPtr id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "-- " << std::endl; #endif HeapT::iterator it=heap.find( id); if( it != heap.end()) { if( (*it).second.Dec() and (*it).second.IsEnabledGC() ) { #ifdef GDL_DEBUG_HEAP std::cout << "Out of scope (garbage collected): " << " at: " << callStack.back()->GetProName() << " line: " << callStack.back()->GetLineNumber() << std::endl; #endif FreeHeapDirect( id, it); } #ifdef GDL_DEBUG_HEAP else std::cout << " = " << (*it).second.Count() << std::endl; #endif } } } static void DecRef( DPtrGDL* p) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; DecRef( id); } } static void DecRefObj( DObj id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "-- " << std::endl; #endif ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) { if( (*it).second.Dec() and (*it).second.IsEnabledGC() ) { #ifdef GDL_DEBUG_HEAP std::cout << "Out of scope (garbage collected): " << " at: " << callStack.back()->GetProName() << " line: " << callStack.back()->GetLineNumber() << std::endl; #endif callStack.back()->ObjCleanup( id); // FreeObjHeapDirect( id, it); } #ifdef GDL_DEBUG_HEAP else std::cout << " = " << (*it).second.Count() << std::endl; #endif } } } static void DecRefObj( DObjGDL* p) { SizeT nEl=p->Size();//N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; DecRefObj( id); } } static void IncRef( DPtr id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "++ " << std::endl; #endif HeapT::iterator it=heap.find( id); if( it != heap.end()) { (*it).second.Inc(); #ifdef GDL_DEBUG_HEAP std::cout << " = " << (*it).second.Count() << std::endl; #endif } } } static void AddRef( DPtr id, SizeT add) { if( id != 0) { #ifdef GDL_DEBUG_HEAP std::cout << add << " + " << std::endl; #endif HeapT::iterator it=heap.find( id); if( it != heap.end()) { (*it).second.Add(add); } } } static SizeT RefCountHeap( DPtr id) { SizeT result = 0; if( id != 0) { HeapT::iterator it=heap.find( id); if( it != heap.end()) result = (*it).second.Count(); } return result; } static SizeT RefCountHeapObj( DObj id) { SizeT result = 0; if( id != 0) { ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) result = (*it).second.Count(); } return result; } static void IncRef( DPtrGDL* p) { SizeT nEl=p->N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DPtr id= (*p)[ix]; IncRef( id); } } static void IncRefObj( DObj id) { if( id != 0 and IsEnabledGC()) { #ifdef GDL_DEBUG_HEAP std::cout << "++ " << std::endl; #endif ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) { (*it).second.Inc(); } } } static void AddRefObj( DObj id, SizeT add) { if( id != 0) { #ifdef GDL_DEBUG_HEAP std::cout << add << " + " << std::endl; #endif ObjHeapT::iterator it=objHeap.find( id); if( it != objHeap.end()) { (*it).second.Add(add); } } } static void IncRefObj( DObjGDL* p) { SizeT nEl=p->Size();//N_Elements(); for( SizeT ix=0; ix < nEl; ix++) { DObj id= (*p)[ix]; IncRefObj( id); } } class HeapException {}; static BaseGDL*& GetHeap( DPtr ID) { HeapT::iterator it=heap.find( ID); if( it == heap.end()) throw HeapException(); return it->second.get(); } static BaseGDL* GetHeapNoThrow( DPtr ID) { HeapT::iterator it=heap.find( ID); if( it == heap.end()) return NULL; return it->second.get(); } static DStructGDL*& GetObjHeap( DObj ID) { ObjHeapT::iterator it=objHeap.find( ID); if( it == objHeap.end()) throw HeapException(); return it->second.get(); } // for overload functions static DSubUD* GetObjHeapOperator( DObj ID, int opIx) { if( ID == 0) return NULL; ObjHeapT::iterator it=objHeap.find( ID); if( it == objHeap.end()) return NULL; return it->second.get()->Desc()->GetOperator( opIx); } static DStructGDL* GetObjHeapNoThrow( DObj ID) { ObjHeapT::iterator it=objHeap.find( ID); if( it == objHeap.end()) return NULL; return it->second.get(); } // static DStructGDL*& GetObjHeap( DObj ID, ObjHeapT::iterator& it) // { // // ObjHeapT::iterator it=objHeap.find( ID); // it=objHeap.find( ID); // if( it == objHeap.end()) throw HeapException(); // return it->second.get(); // } static bool PtrValid( DPtr ID) { HeapT::iterator it=heap.find( ID); return (it != heap.end()); } static SizeT HeapSize() { return heap.size(); } static DPtr FindInHeap( BaseGDL** p) { for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { if( &it->second.get() == p) return it->first; } return 0; } // static BaseGDL** GetPtrToHeap( BaseGDL* p) // { // for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) // { // if( it->second.get() == p) // return &it->second.get(); // } // return NULL; // } static DPtrGDL* GetAllHeap() { SizeT nEl = heap.size(); if( nEl == 0) return new DPtrGDL( 0); DPtrGDL* ret = new DPtrGDL( dimension( &nEl, 1), BaseGDL::NOZERO); SizeT i=0; for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { IncRef( it->first); (*ret)[ i++] = it->first; } return ret; } // no ref counting here static std::vector* GetAllHeapSTL() { SizeT nEl = heap.size(); if( nEl == 0) return new std::vector(); std::vector* ret = new std::vector( nEl); SizeT i=0; for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { (*ret)[ i++] = it->first; } return ret; } static bool ObjValid( DObj ID) { ObjHeapT::iterator it=objHeap.find( ID); return (it != objHeap.end()); } static SizeT ObjHeapSize() { return objHeap.size(); } // static DObj FindInObjHeap( BaseGDL** p) // { // for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) // { // if( &it->second == reinterpret_cast(p)) // return it->first; // } // return 0; // } static DObjGDL* GetAllObjHeap() { SizeT nEl = objHeap.size(); if( nEl == 0) return new DObjGDL( 0); DObjGDL* ret = new DObjGDL( dimension( &nEl, 1), BaseGDL::NOZERO); SizeT i=0; for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) { IncRefObj( it->first); (*ret)[ i++] = it->first; } return ret; } // no ref counting here static std::vector* GetAllObjHeapSTL() { SizeT nEl = objHeap.size(); if( nEl == 0) return new std::vector(); std::vector* ret = new std::vector( nEl); SizeT i=0; for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) { (*ret)[ i++] = it->first; } return ret; } static void ResetHeap() // purges both heaps { for( HeapT::iterator it=heap.begin(); it != heap.end(); ++it) { delete (*it).second.get(); heap.erase( it->first); } for( ObjHeapT::iterator it=objHeap.begin(); it != objHeap.end(); ++it) { delete (*it).second.get(); objHeap.erase( it->first); } // The counters are reset for easier human readability. heapIx = 1; objHeapIx = 1; } // name of data static const std::string Name( BaseGDL* p) // const { return callStack.back()->GetString( p); } static const std::string Name( BaseGDL** p) // const { assert( *p == NULL); DPtr h = FindInHeap( p); if( h != 0) return std::string(""; // DObj o = FindInObjHeap( p); // if( o != 0) return std::string(""; return "<(ptr to undefined expression not found on the heap)>"; } // compiler (lexer, parser, treeparser) def in dinterpreter.cpp static void ReportCompileError( GDLException& e, const std::string& file = ""); // interpreter static void ReportError( GDLException& e, const std::string &emsg, bool dumpStack=true) { DString msgPrefix = SysVar::MsgPrefix(); std::cout << std::flush; if( dumpStack) { if( e.Prefix()) { std::cerr << msgPrefix << e.toString() << std::endl; lib::write_journal_comment(msgPrefix+e.toString()); } else { std::cerr << e.toString() << std::endl; lib::write_journal_comment(e.toString()); } } std::cerr << msgPrefix << emsg << " " << std::left << std::setw(16) << callStack.back()->GetProName(); std::string file=callStack.back()->GetFilename(); if( file != "") { SizeT line = e.getLine(); if( line != 0) { std::cerr << std::right << std::setw(6) << line; } else { std::cerr << std::right << std::setw(6) << ""; } std::cerr << std::left << " " << file; } std::cerr << std::endl; if( dumpStack) DumpStack( emsg.size() + 1); } static void DumpStack( SizeT w) { DString msgPrefix = SysVar::MsgPrefix(); // EnvStackT::reverse_iterator upEnv = callStack.rbegin(); // //EnvStackT::reverse_iterator env = upEnv++; // upEnv++; // for(; // upEnv != callStack.rend(); // ++upEnv /*,++env*/) long actIx = callStack.size() - 2; for( ; actIx >= 0; --actIx) { EnvStackT::pointer_type upEnv = callStack[ actIx]; std::cerr << msgPrefix << std::right << std::setw( w) << ""; std::cerr << std::left << std::setw(16) << upEnv->GetProName(); std::string file = upEnv->GetFilename(); if( file != "") { // ProgNodeP cNode= (*env)->CallingNode(); // if( cNode != NULL) // { // std::cerr << std::right << std::setw(6) << cNode->getLine(); // } // else // { // std::cerr << std::right << std::setw(6) << ""; // } // ProgNodeP cNode= (*env)->CallingNode(); // if( cNode != NULL && cNode->getLine() != 0) // { // (*upEnv)->SetLineNumber( cNode->getLine()); // } int lineNumber = upEnv->GetLineNumber(); if( lineNumber != 0) { std::cerr << std::right << std::setw(6) << lineNumber; } else { std::cerr << std::right << std::setw(6) << ""; } std::cerr << std::left << " " << file; } std::cerr << std::endl; } } static void DebugMsg( ProgNodeP _t, const std::string& msg) { DString msgPrefix = SysVar::MsgPrefix(); std::cout << std::flush; std::cerr << msgPrefix << msg << std::left << std::setw(16) << callStack.back()->GetProName(); std::string file=callStack.back()->GetFilename(); if( file != "") { ProgNodeP eNode = _t; if( eNode != NULL) { std::cerr << std::right << std::setw(6) << eNode->getLine(); } else { std::cerr << std::right << std::setw(6) << ""; } std::cerr << std::left << " " << file; } std::cerr << std::endl; } static void RetAll( RetAllException::ExCode c=RetAllException::NONE) { throw RetAllException( c); } static EnvStackT& CallStack() { return callStack;} // the callstack // static EnvBaseT* CallStackBack() { return callStack.back();} static EnvUDT* CallStackBack() { return callStack.back();} std::string GetClearActualLine() { std::string ret = executeLine.str(); executeLine.str(""); return ret; } RetCode NewInterpreterInstance(SizeT lineOffset); // code in dinterpreter.cpp ~GDLInterpreter() { } public: GDLInterpreter(); static void initializeASTFactory( antlr::ASTFactory& factory ); int getNumTokens() const { return GDLInterpreter::NUM_TOKENS; } const char* getTokenName( int type ) const { if( type > getNumTokens() ) return 0; return GDLInterpreter::tokenNames[type]; } const char* const* getTokenNames() const { return GDLInterpreter::tokenNames; } public: RetCode interactive(ProgNodeP _t); public: RetCode statement(ProgNodeP _t, bool throwImmediately=false); public: RetCode execute(ProgNodeP _t, bool throwImmediately=false); public: RetCode statement_list(ProgNodeP _t, bool throwImmediately=false); public: BaseGDL* call_fun(ProgNodeP _t); public: BaseGDL** call_lfun(ProgNodeP _t); public: void call_pro(ProgNodeP _t); public: BaseGDL** l_deref(ProgNodeP _t); public: BaseGDL** l_decinc_indexable_expr(ProgNodeP _t, BaseGDL*& res ); public: BaseGDL** l_function_call_internal(ProgNodeP _t); public: BaseGDL** l_defined_simple_var(ProgNodeP _t); public: BaseGDL** l_sys_var(ProgNodeP _t); public: BaseGDL** l_decinc_array_expr(ProgNodeP _t, int dec_inc, BaseGDL*& res ); public: BaseGDL* l_decinc_dot_expr(ProgNodeP _t, int dec_inc ); public: BaseGDL** l_decinc_expr(ProgNodeP _t, int dec_inc, BaseGDL*& res ); public: BaseGDL* expr(ProgNodeP _t); public: BaseGDL* indexable_expr(ProgNodeP _t); public: BaseGDL* indexable_tmp_expr(ProgNodeP _t); public: BaseGDL* lib_function_call_internal(ProgNodeP _t); public: BaseGDL** l_expr_internal(ProgNodeP _t, BaseGDL* right ); public: BaseGDL* tmp_expr(ProgNodeP _t); public: BaseGDL** l_simple_var(ProgNodeP _t); public: void parameter_def(ProgNodeP _t, EnvBaseT* actEnv ); public: BaseGDL* r_expr(ProgNodeP _t); public: BaseGDL** l_indexable_expr(ProgNodeP _t); public: BaseGDL** l_arrayexpr_mfcall_as_mfcall(ProgNodeP _t); public: BaseGDL** unused_l_array_expr(ProgNodeP _t, BaseGDL* right ); public: ArrayIndexListT* arrayindex_list(ProgNodeP _t, bool noAssoc ); public: void l_dot_array_expr(ProgNodeP _t, DotAccessDescT* aD ); public: BaseGDL** l_arrayexpr_mfcall(ProgNodeP _t, BaseGDL* right ); public: void tag_expr(ProgNodeP _t, DotAccessDescT* aD ); public: void tag_array_expr(ProgNodeP _t, DotAccessDescT* aD ); public: BaseGDL* r_dot_indexable_expr(ProgNodeP _t, DotAccessDescT* aD ); public: void r_dot_array_expr(ProgNodeP _t, DotAccessDescT* aD ); public: BaseGDL* assign_expr(ProgNodeP _t); public: BaseGDL* unused_function_call(ProgNodeP _t); public: BaseGDL* lib_function_call_retnew_internal(ProgNodeP _t); public: BaseGDL* simple_var(ProgNodeP _t); public: BaseGDL* sys_var(ProgNodeP _t); public: BaseGDL** l_arrayexpr_mfcall_as_arrayexpr(ProgNodeP _t, BaseGDL* right ); public: void parameter_def_n_elements(ProgNodeP _t, EnvBaseT* actEnv ); public: void parameter_def_nocheck(ProgNodeP _t, EnvBaseT* actEnv ); public: void arrayindex_list_overload(ProgNodeP _t, IxExprListT& indexList ); public: antlr::RefAST getAST() { return antlr::RefAST(returnAST); } protected: ProgNodeP returnAST; ProgNodeP _retTree; private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS static const int NUM_TOKENS = 238; #else enum { NUM_TOKENS = 238 }; #endif static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; }; #endif /*INC_GDLInterpreter_hpp_*/ gdl-0.9.9/src/GDLInterpreterTokenTypes.hpp000066400000000000000000000113521340051421000204470ustar00rootroot00000000000000#ifndef INC_GDLInterpreterTokenTypes_hpp_ #define INC_GDLInterpreterTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "gdlc.i.g" -> "GDLInterpreterTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API GDLInterpreterTokenTypes { #endif enum { EOF_ = 1, ALL = 4, ASSIGN = 5, ASSIGN_INPLACE = 6, ASSIGN_REPLACE = 7, ASSIGN_ARRAYEXPR_MFCALL = 8, ARRAYDEF = 9, ARRAYDEF_CONST = 10, ARRAYDEF_GENERALIZED_INDGEN = 11, ARRAYIX = 12, ARRAYIX_ALL = 13, ARRAYIX_ORANGE = 14, ARRAYIX_RANGE = 15, ARRAYIX_ORANGE_S = 16, ARRAYIX_RANGE_S = 17, ARRAYEXPR = 18, ARRAYEXPR_FCALL = 19, ARRAYEXPR_MFCALL = 20, BLOCK = 21, BREAK = 22, CSBLOCK = 23, CONTINUE = 24, COMMONDECL = 25, COMMONDEF = 26, CONSTANT = 27, DEREF = 28, ELSEBLK = 29, EXPR = 30, FOR = 31, FOR_STEP = 32, FOREACH = 33, FOREACH_INDEX = 34, FOR_LOOP = 35, FOR_STEP_LOOP = 36, FOREACH_LOOP = 37, FOREACH_INDEX_LOOP = 38, FCALL = 39, FCALL_LIB = 40, FCALL_LIB_DIRECT = 41, FCALL_LIB_N_ELEMENTS = 42, FCALL_LIB_RETNEW = 43, GDLNULL = 44, IF_ELSE = 45, KEYDECL = 46, KEYDEF = 47, KEYDEF_REF = 48, KEYDEF_REF_CHECK = 49, KEYDEF_REF_EXPR = 50, LABEL = 51, MPCALL = 52, MPCALL_PARENT = 53, MFCALL = 54, MFCALL_LIB = 55, MFCALL_LIB_RETNEW = 56, MFCALL_PARENT = 57, MFCALL_PARENT_LIB = 58, MFCALL_PARENT_LIB_RETNEW = 59, NOP = 60, NSTRUC = 61, NSTRUC_REF = 62, ON_IOERROR_NULL = 63, PCALL = 64, PCALL_LIB = 65, PARADECL = 66, PARAEXPR = 67, PARAEXPR_VN = 68, DEC_REF_CHECK = 69, INC_REF_CHECK = 70, POSTDEC = 71, POSTINC = 72, DECSTATEMENT = 73, INCSTATEMENT = 74, REF = 75, REF_VN = 76, REF_CHECK = 77, REF_CHECK_VN = 78, REF_EXPR = 79, REF_EXPR_VN = 80, REPEAT = 81, REPEAT_LOOP = 82, RETURN = 83, RETF = 84, RETP = 85, STRUC = 86, SYSVAR = 87, UMINUS = 88, VAR = 89, VARPTR = 90, WHILE = 91, IDENTIFIER = 92, AND_OP = 93, BEGIN = 94, CASE = 95, COMMON = 96, COMPILE_OPT = 97, DO = 98, ELSE = 99, END = 100, ENDCASE = 101, ENDELSE = 102, ENDFOR = 103, ENDFOREACH = 104, ENDIF = 105, ENDREP = 106, ENDSWITCH = 107, ENDWHILE = 108, EQ_OP = 109, FORWARD = 110, FUNCTION = 111, GE_OP = 112, GOTO = 113, GT_OP = 114, IF = 115, INHERITS = 116, LE_OP = 117, LT_OP = 118, MOD_OP = 119, NE_OP = 120, NOT_OP = 121, OF = 122, ON_IOERROR = 123, OR_OP = 124, PRO = 125, SWITCH = 126, THEN = 127, UNTIL = 128, XOR_OP = 129, METHOD = 130, COMMA = 131, COLON = 132, END_U = 133, EQUAL = 134, DEC = 135, INC = 136, AND_OP_EQ = 137, ASTERIX_EQ = 138, EQ_OP_EQ = 139, GE_OP_EQ = 140, GTMARK_EQ = 141, GT_OP_EQ = 142, LE_OP_EQ = 143, LTMARK_EQ = 144, LT_OP_EQ = 145, MATRIX_OP1_EQ = 146, MATRIX_OP2_EQ = 147, MINUS_EQ = 148, MOD_OP_EQ = 149, NE_OP_EQ = 150, OR_OP_EQ = 151, PLUS_EQ = 152, POW_EQ = 153, SLASH_EQ = 154, XOR_OP_EQ = 155, MEMBER = 156, LBRACE = 157, RBRACE = 158, SLASH = 159, LSQUARE = 160, RSQUARE = 161, SYSVARNAME = 162, EXCLAMATION = 163, LCURLY = 164, RCURLY = 165, CONSTANT_HEX_BYTE = 166, CONSTANT_HEX_LONG = 167, CONSTANT_HEX_LONG64 = 168, CONSTANT_HEX_INT = 169, CONSTANT_HEX_I = 170, CONSTANT_HEX_ULONG = 171, CONSTANT_HEX_ULONG64 = 172, CONSTANT_HEX_UI = 173, CONSTANT_HEX_UINT = 174, CONSTANT_BYTE = 175, CONSTANT_LONG = 176, CONSTANT_LONG64 = 177, CONSTANT_INT = 178, CONSTANT_I = 179, CONSTANT_ULONG = 180, CONSTANT_ULONG64 = 181, CONSTANT_UI = 182, CONSTANT_UINT = 183, CONSTANT_OCT_BYTE = 184, CONSTANT_OCT_LONG = 185, CONSTANT_OCT_LONG64 = 186, CONSTANT_OCT_INT = 187, CONSTANT_OCT_I = 188, CONSTANT_OCT_ULONG = 189, CONSTANT_OCT_ULONG64 = 190, CONSTANT_OCT_UI = 191, CONSTANT_OCT_UINT = 192, CONSTANT_FLOAT = 193, CONSTANT_DOUBLE = 194, CONSTANT_BIN_BYTE = 195, CONSTANT_BIN_LONG = 196, CONSTANT_BIN_LONG64 = 197, CONSTANT_BIN_INT = 198, CONSTANT_BIN_I = 199, CONSTANT_BIN_ULONG = 200, CONSTANT_BIN_ULONG64 = 201, CONSTANT_BIN_UI = 202, CONSTANT_BIN_UINT = 203, ASTERIX = 204, DOT = 205, STRING_LITERAL = 206, POW = 207, MATRIX_OP1 = 208, MATRIX_OP2 = 209, PLUS = 210, MINUS = 211, LTMARK = 212, GTMARK = 213, LOG_NEG = 214, LOG_AND = 215, LOG_OR = 216, QUESTION = 217, STRING = 218, INCLUDE = 219, EOL = 220, W = 221, D = 222, L = 223, H = 224, O = 225, B = 226, EXP = 227, DBL_E = 228, DBL = 229, CONSTANT_OR_STRING_LITERAL = 230, COMMENT = 231, END_MARKER = 232, WHITESPACE = 233, SKIP_LINES = 234, CONT_STATEMENT = 235, END_OF_LINE = 236, MAX_TOKEN_NUMBER = 237, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_GDLInterpreterTokenTypes_hpp_*/ gdl-0.9.9/src/GDLInterpreterTokenTypes.txt000066400000000000000000000072011340051421000204750ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): gdlc.i.g -> GDLInterpreterTokenTypes.txt$ GDLInterpreter // output token vocab name ALL=4 ASSIGN=5 ASSIGN_INPLACE=6 ASSIGN_REPLACE=7 ASSIGN_ARRAYEXPR_MFCALL=8 ARRAYDEF=9 ARRAYDEF_CONST=10 ARRAYDEF_GENERALIZED_INDGEN=11 ARRAYIX=12 ARRAYIX_ALL=13 ARRAYIX_ORANGE=14 ARRAYIX_RANGE=15 ARRAYIX_ORANGE_S=16 ARRAYIX_RANGE_S=17 ARRAYEXPR=18 ARRAYEXPR_FCALL=19 ARRAYEXPR_MFCALL=20 BLOCK=21 BREAK=22 CSBLOCK=23 CONTINUE=24 COMMONDECL=25 COMMONDEF=26 CONSTANT=27 DEREF=28 ELSEBLK=29 EXPR=30 FOR="for"=31 FOR_STEP=32 FOREACH="foreach"=33 FOREACH_INDEX=34 FOR_LOOP=35 FOR_STEP_LOOP=36 FOREACH_LOOP=37 FOREACH_INDEX_LOOP=38 FCALL=39 FCALL_LIB=40 FCALL_LIB_DIRECT=41 FCALL_LIB_N_ELEMENTS=42 FCALL_LIB_RETNEW=43 GDLNULL=44 IF_ELSE=45 KEYDECL=46 KEYDEF=47 KEYDEF_REF=48 KEYDEF_REF_CHECK=49 KEYDEF_REF_EXPR=50 LABEL=51 MPCALL=52 MPCALL_PARENT=53 MFCALL=54 MFCALL_LIB=55 MFCALL_LIB_RETNEW=56 MFCALL_PARENT=57 MFCALL_PARENT_LIB=58 MFCALL_PARENT_LIB_RETNEW=59 NOP=60 NSTRUC=61 NSTRUC_REF=62 ON_IOERROR_NULL=63 PCALL=64 PCALL_LIB=65 PARADECL=66 PARAEXPR=67 PARAEXPR_VN=68 DEC_REF_CHECK=69 INC_REF_CHECK=70 POSTDEC=71 POSTINC=72 DECSTATEMENT=73 INCSTATEMENT=74 REF=75 REF_VN=76 REF_CHECK=77 REF_CHECK_VN=78 REF_EXPR=79 REF_EXPR_VN=80 REPEAT="repeat"=81 REPEAT_LOOP=82 RETURN=83 RETF=84 RETP=85 STRUC=86 SYSVAR=87 UMINUS=88 VAR=89 VARPTR=90 WHILE="while"=91 IDENTIFIER=92 AND_OP="and"=93 BEGIN="begin"=94 CASE="case"=95 COMMON="common"=96 COMPILE_OPT="compile_opt"=97 DO="do"=98 ELSE="else"=99 END="end"=100 ENDCASE="endcase"=101 ENDELSE="endelse"=102 ENDFOR="endfor"=103 ENDFOREACH="endforeach"=104 ENDIF="endif"=105 ENDREP="endrep"=106 ENDSWITCH="endswitch"=107 ENDWHILE="endwhile"=108 EQ_OP="eq"=109 FORWARD="forward_function"=110 FUNCTION="function"=111 GE_OP="ge"=112 GOTO="goto"=113 GT_OP="gt"=114 IF="if"=115 INHERITS="inherits"=116 LE_OP="le"=117 LT_OP="lt"=118 MOD_OP="mod"=119 NE_OP="ne"=120 NOT_OP="not"=121 OF="of"=122 ON_IOERROR="on_ioerror"=123 OR_OP="or"=124 PRO="pro"=125 SWITCH="switch"=126 THEN="then"=127 UNTIL="until"=128 XOR_OP="xor"=129 METHOD=130 COMMA=131 COLON=132 END_U=133 EQUAL=134 DEC=135 INC=136 AND_OP_EQ=137 ASTERIX_EQ=138 EQ_OP_EQ=139 GE_OP_EQ=140 GTMARK_EQ=141 GT_OP_EQ=142 LE_OP_EQ=143 LTMARK_EQ=144 LT_OP_EQ=145 MATRIX_OP1_EQ=146 MATRIX_OP2_EQ=147 MINUS_EQ=148 MOD_OP_EQ=149 NE_OP_EQ=150 OR_OP_EQ=151 PLUS_EQ=152 POW_EQ=153 SLASH_EQ=154 XOR_OP_EQ=155 MEMBER=156 LBRACE=157 RBRACE=158 SLASH=159 LSQUARE=160 RSQUARE=161 SYSVARNAME=162 EXCLAMATION=163 LCURLY=164 RCURLY=165 CONSTANT_HEX_BYTE=166 CONSTANT_HEX_LONG=167 CONSTANT_HEX_LONG64=168 CONSTANT_HEX_INT=169 CONSTANT_HEX_I=170 CONSTANT_HEX_ULONG=171 CONSTANT_HEX_ULONG64=172 CONSTANT_HEX_UI=173 CONSTANT_HEX_UINT=174 CONSTANT_BYTE=175 CONSTANT_LONG=176 CONSTANT_LONG64=177 CONSTANT_INT=178 CONSTANT_I=179 CONSTANT_ULONG=180 CONSTANT_ULONG64=181 CONSTANT_UI=182 CONSTANT_UINT=183 CONSTANT_OCT_BYTE=184 CONSTANT_OCT_LONG=185 CONSTANT_OCT_LONG64=186 CONSTANT_OCT_INT=187 CONSTANT_OCT_I=188 CONSTANT_OCT_ULONG=189 CONSTANT_OCT_ULONG64=190 CONSTANT_OCT_UI=191 CONSTANT_OCT_UINT=192 CONSTANT_FLOAT=193 CONSTANT_DOUBLE=194 CONSTANT_BIN_BYTE=195 CONSTANT_BIN_LONG=196 CONSTANT_BIN_LONG64=197 CONSTANT_BIN_INT=198 CONSTANT_BIN_I=199 CONSTANT_BIN_ULONG=200 CONSTANT_BIN_ULONG64=201 CONSTANT_BIN_UI=202 CONSTANT_BIN_UINT=203 ASTERIX=204 DOT=205 STRING_LITERAL=206 POW=207 MATRIX_OP1=208 MATRIX_OP2=209 PLUS=210 MINUS=211 LTMARK=212 GTMARK=213 LOG_NEG=214 LOG_AND=215 LOG_OR=216 QUESTION=217 STRING=218 INCLUDE=219 EOL=220 W=221 D=222 L=223 H=224 O=225 B=226 EXP=227 DBL_E=228 DBL=229 CONSTANT_OR_STRING_LITERAL=230 COMMENT=231 END_MARKER=232 WHITESPACE=233 SKIP_LINES=234 CONT_STATEMENT=235 END_OF_LINE=236 MAX_TOKEN_NUMBER=237 gdl-0.9.9/src/GDLLexer.cpp000066400000000000000000003071221340051421000151730ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "gdlc.g" -> "GDLLexer.cpp"$ */ #include "includefirst.hpp" #include "GDLLexer.hpp" #include #include #include #include #include #include #include #include #include GDLLexer::GDLLexer(std::istream& in) : antlr::CharScanner(new antlr::CharBuffer(in),false) { initLiterals(); } GDLLexer::GDLLexer(antlr::InputBuffer& ib) : antlr::CharScanner(ib,false) { initLiterals(); } GDLLexer::GDLLexer(const antlr::LexerSharedInputState& state) : antlr::CharScanner(state,false) { initLiterals(); } void GDLLexer::initLiterals() { literals["endcase"] = 101; literals["case"] = 95; literals["while"] = 91; literals["repeat"] = 81; literals["ne"] = 120; literals["endif"] = 105; literals["end"] = 100; literals["le"] = 117; literals["then"] = 127; literals["endswitch"] = 107; literals["until"] = 128; literals["and"] = 93; literals["endrep"] = 106; literals["not"] = 121; literals["foreach"] = 33; literals["mod"] = 119; literals["forward_function"] = 110; literals["do"] = 98; literals["function"] = 111; literals["endfor"] = 103; literals["gt"] = 114; literals["compile_opt"] = 97; literals["inherits"] = 116; literals["of"] = 122; literals["or"] = 124; literals["if"] = 115; literals["pro"] = 125; literals["xor"] = 129; literals["ge"] = 112; literals["goto"] = 113; literals["for"] = 31; literals["eq"] = 109; literals["on_ioerror"] = 123; literals["endelse"] = 102; literals["begin"] = 94; literals["else"] = 99; literals["lt"] = 118; literals["endwhile"] = 108; literals["switch"] = 126; literals["common"] = 96; literals["endforeach"] = 104; } antlr::RefToken GDLLexer::nextToken() { antlr::RefToken theRetToken; for (;;) { antlr::RefToken theRetToken; int _ttype = antlr::Token::INVALID_TYPE; resetText(); try { // for lexical and char stream error handling switch ( LA(1)) { case 0x40 /* '@' */ : { mINCLUDE(true); theRetToken=_returnToken; break; } case 0x2c /* ',' */ : { mCOMMA(true); theRetToken=_returnToken; break; } case 0x3d /* '=' */ : { mEQUAL(true); theRetToken=_returnToken; break; } case 0x7b /* '{' */ : { mLCURLY(true); theRetToken=_returnToken; break; } case 0x7d /* '}' */ : { mRCURLY(true); theRetToken=_returnToken; break; } case 0x5b /* '[' */ : { mLSQUARE(true); theRetToken=_returnToken; break; } case 0x5d /* ']' */ : { mRSQUARE(true); theRetToken=_returnToken; break; } case 0x28 /* '(' */ : { mLBRACE(true); theRetToken=_returnToken; break; } case 0x29 /* ')' */ : { mRBRACE(true); theRetToken=_returnToken; break; } case 0x3f /* '?' */ : { mQUESTION(true); theRetToken=_returnToken; break; } case 0x7c /* '|' */ : { mLOG_OR(true); theRetToken=_returnToken; break; } case 0x7e /* '~' */ : { mLOG_NEG(true); theRetToken=_returnToken; break; } case 0x22 /* '\"' */ : case 0x27 /* '\'' */ : case 0x2e /* '.' */ : case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { mCONSTANT_OR_STRING_LITERAL(true); theRetToken=_returnToken; break; } case 0x3b /* ';' */ : { mCOMMENT(true); theRetToken=_returnToken; break; } case 0x9 /* '\t' */ : case 0xc /* '\14' */ : case 0x20 /* ' ' */ : { mWHITESPACE(true); theRetToken=_returnToken; break; } case 0x24 /* '$' */ : { mCONT_STATEMENT(true); theRetToken=_returnToken; break; } case 0xa /* '\n' */ : case 0xd /* '\r' */ : { mEND_OF_LINE(true); theRetToken=_returnToken; break; } default: if (((LA(1) == 0x61 /* 'a' */ ) && (LA(2) == 0x6e /* 'n' */ ) && (LA(3) == 0x64 /* 'd' */ ))&&( LA(4) == '=')) { mAND_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x65 /* 'e' */ ) && (LA(2) == 0x71 /* 'q' */ ) && (LA(3) == 0x3d /* '=' */ )) { mEQ_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x67 /* 'g' */ ) && (LA(2) == 0x65 /* 'e' */ ) && (LA(3) == 0x3d /* '=' */ )) { mGE_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x67 /* 'g' */ ) && (LA(2) == 0x74 /* 't' */ ) && (LA(3) == 0x3d /* '=' */ )) { mGT_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x65 /* 'e' */ ) && (LA(3) == 0x3d /* '=' */ )) { mLE_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x74 /* 't' */ ) && (LA(3) == 0x3d /* '=' */ )) { mLT_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x23 /* '#' */ ) && (LA(2) == 0x23 /* '#' */ ) && (LA(3) == 0x3d /* '=' */ )) { mMATRIX_OP2_EQ(true); theRetToken=_returnToken; } else if (((LA(1) == 0x6d /* 'm' */ ) && (LA(2) == 0x6f /* 'o' */ ) && (LA(3) == 0x64 /* 'd' */ ))&&( LA(4) == '=')) { mMOD_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x6e /* 'n' */ ) && (LA(2) == 0x65 /* 'e' */ ) && (LA(3) == 0x3d /* '=' */ )) { mNE_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x6f /* 'o' */ ) && (LA(2) == 0x72 /* 'r' */ ) && (LA(3) == 0x3d /* '=' */ )) { mOR_OP_EQ(true); theRetToken=_returnToken; } else if (((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x6f /* 'o' */ ) && (LA(3) == 0x72 /* 'r' */ ))&&( LA(4) == '=')) { mXOR_OP_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2a /* '*' */ ) && (LA(2) == 0x3d /* '=' */ )) { mASTERIX_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x3e /* '>' */ ) && (LA(2) == 0x3d /* '=' */ )) { mGTMARK_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x3c /* '<' */ ) && (LA(2) == 0x3d /* '=' */ )) { mLTMARK_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x23 /* '#' */ ) && (LA(2) == 0x3d /* '=' */ )) { mMATRIX_OP1_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2d /* '-' */ ) && (LA(2) == 0x3d /* '=' */ )) { mMINUS_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2b /* '+' */ ) && (LA(2) == 0x3d /* '=' */ )) { mPLUS_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x5e /* '^' */ ) && (LA(2) == 0x3d /* '=' */ )) { mPOW_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2f /* '/' */ ) && (LA(2) == 0x3d /* '=' */ )) { mSLASH_EQ(true); theRetToken=_returnToken; } else if ((LA(1) == 0x23 /* '#' */ ) && (LA(2) == 0x23 /* '#' */ ) && (true)) { mMATRIX_OP2(true); theRetToken=_returnToken; } else if ((LA(1) == 0x3a /* ':' */ ) && (LA(2) == 0x3a /* ':' */ )) { mMETHOD(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2d /* '-' */ ) && (LA(2) == 0x3e /* '>' */ )) { mMEMBER(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2b /* '+' */ ) && (LA(2) == 0x2b /* '+' */ )) { mINC(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2d /* '-' */ ) && (LA(2) == 0x2d /* '-' */ )) { mDEC(true); theRetToken=_returnToken; } else if ((LA(1) == 0x26 /* '&' */ ) && (LA(2) == 0x26 /* '&' */ )) { mLOG_AND(true); theRetToken=_returnToken; } else if ((LA(1) == 0x21 /* '!' */ ) && (_tokenSet_0.member(LA(2)))) { mSYSVARNAME(true); theRetToken=_returnToken; } else if ((LA(1) == 0x23 /* '#' */ ) && (true)) { mMATRIX_OP1(true); theRetToken=_returnToken; } else if ((LA(1) == 0x3a /* ':' */ ) && (true)) { mCOLON(true); theRetToken=_returnToken; } else if ((LA(1) == 0x21 /* '!' */ ) && (true)) { mEXCLAMATION(true); theRetToken=_returnToken; } else if ((LA(1) == 0x5e /* '^' */ ) && (true)) { mPOW(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2a /* '*' */ ) && (true)) { mASTERIX(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2f /* '/' */ ) && (true)) { mSLASH(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2d /* '-' */ ) && (true)) { mMINUS(true); theRetToken=_returnToken; } else if ((LA(1) == 0x2b /* '+' */ ) && (true)) { mPLUS(true); theRetToken=_returnToken; } else if ((LA(1) == 0x3e /* '>' */ ) && (true)) { mGTMARK(true); theRetToken=_returnToken; } else if ((LA(1) == 0x3c /* '<' */ ) && (true)) { mLTMARK(true); theRetToken=_returnToken; } else if ((_tokenSet_1.member(LA(1))) && (true) && (true)) { mIDENTIFIER(true); theRetToken=_returnToken; } else if ((LA(1) == 0x26 /* '&' */ ) && (true)) { mEND_MARKER(true); theRetToken=_returnToken; } else { if (LA(1)==EOF_CHAR) { uponEOF(); _returnToken = makeToken(antlr::Token::EOF_TYPE); } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } } if ( !_returnToken ) goto tryAgain; // found SKIP token _ttype = _returnToken->getType(); _returnToken->setType(_ttype); return _returnToken; } catch (antlr::RecognitionException& e) { throw antlr::TokenStreamRecognitionException(e); } catch (antlr::CharStreamIOException& csie) { throw antlr::TokenStreamIOException(csie.io); } catch (antlr::CharStreamException& cse) { throw antlr::TokenStreamException(cse.getMessage()); } tryAgain:; } } void GDLLexer::mSTRING(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = STRING; std::string::size_type _saveIndex; { // ( ... )* for (;;) { if ((_tokenSet_2.member(LA(1)))) { { match(_tokenSet_2); } } else { goto _loop261; } } _loop261:; } // ( ... )* if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mINCLUDE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = INCLUDE; std::string::size_type _saveIndex; antlr::RefToken f; _saveIndex = text.length(); match('@' /* charlit */ ); text.erase(_saveIndex); _saveIndex = text.length(); mSTRING(true); text.erase(_saveIndex); f=_returnToken; if ( inputState->guessing==0 ) { ANTLR_USING_NAMESPACE(std) // create lexer to handle include std::string name = f->getText(); // find comments on the same line size_t pos = name.find_first_of(';', 0); if( pos != std::string::npos) // remove them name = name.substr(0, pos); StrTrim(name); std::string appName=name; AppendIfNeeded(appName,".pro"); errno = 0; // zero it to detect errors bool found = CompleteFileName( appName); if( found) name = appName; else found = CompleteFileName( name); if( !found) { if( errno == EMFILE) throw GDLException( "Too many open files " "(recursive use of '@'?): " + name); else throw GDLException( "File not found: " + name); } std::ifstream* input = new std::ifstream(name.c_str()); if (!*input) { delete input; throw GDLException( "Error opening file. File: " + name); cerr << SysVar::MsgPrefix() << "Error opening file. File: " << name << endl; } if( *input) { new GDLLexer(*input,name,this); selector->retry(); // throws TokenStreamRetryException } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mAND_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = AND_OP_EQ; std::string::size_type _saveIndex; if (!( LA(4) == '=')) throw antlr::SemanticException(" LA(4) == \'=\'"); match("and="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mASTERIX_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = ASTERIX_EQ; std::string::size_type _saveIndex; match("*="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEQ_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = EQ_OP_EQ; std::string::size_type _saveIndex; match("eq="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mGE_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = GE_OP_EQ; std::string::size_type _saveIndex; match("ge="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mGTMARK_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = GTMARK_EQ; std::string::size_type _saveIndex; match(">="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mGT_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = GT_OP_EQ; std::string::size_type _saveIndex; match("gt="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLE_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LE_OP_EQ; std::string::size_type _saveIndex; match("le="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLTMARK_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LTMARK_EQ; std::string::size_type _saveIndex; match("<="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLT_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LT_OP_EQ; std::string::size_type _saveIndex; match("lt="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMATRIX_OP1_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MATRIX_OP1_EQ; std::string::size_type _saveIndex; match("#="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMATRIX_OP2_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MATRIX_OP2_EQ; std::string::size_type _saveIndex; match("##="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMINUS_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MINUS_EQ; std::string::size_type _saveIndex; match("-="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMOD_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MOD_OP_EQ; std::string::size_type _saveIndex; if (!( LA(4) == '=')) throw antlr::SemanticException(" LA(4) == \'=\'"); match("mod="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mNE_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = NE_OP_EQ; std::string::size_type _saveIndex; match("ne="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mOR_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = OR_OP_EQ; std::string::size_type _saveIndex; match("or="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mPLUS_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PLUS_EQ; std::string::size_type _saveIndex; match("+="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mPOW_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = POW_EQ; std::string::size_type _saveIndex; match("^="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mSLASH_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SLASH_EQ; std::string::size_type _saveIndex; match("/="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mXOR_OP_EQ(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = XOR_OP_EQ; std::string::size_type _saveIndex; if (!( LA(4) == '=')) throw antlr::SemanticException(" LA(4) == \'=\'"); match("xor="); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMATRIX_OP1(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MATRIX_OP1; std::string::size_type _saveIndex; match('#' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMATRIX_OP2(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MATRIX_OP2; std::string::size_type _saveIndex; match("##"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMETHOD(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = METHOD; std::string::size_type _saveIndex; match("::"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMEMBER(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MEMBER; std::string::size_type _saveIndex; match("->"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCOMMA(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = COMMA; std::string::size_type _saveIndex; match(',' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCOLON(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = COLON; std::string::size_type _saveIndex; match(':' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEQUAL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = EQUAL; std::string::size_type _saveIndex; match('=' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLCURLY(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LCURLY; std::string::size_type _saveIndex; match('{' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mRCURLY(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = RCURLY; std::string::size_type _saveIndex; match('}' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLSQUARE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LSQUARE; std::string::size_type _saveIndex; match('[' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mRSQUARE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = RSQUARE; std::string::size_type _saveIndex; match(']' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLBRACE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LBRACE; std::string::size_type _saveIndex; match('(' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mRBRACE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = RBRACE; std::string::size_type _saveIndex; match(')' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mQUESTION(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = QUESTION; std::string::size_type _saveIndex; match('?' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEXCLAMATION(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = EXCLAMATION; std::string::size_type _saveIndex; match('!' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mPOW(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = POW; std::string::size_type _saveIndex; match('^' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mASTERIX(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = ASTERIX; std::string::size_type _saveIndex; match('*' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mSLASH(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SLASH; std::string::size_type _saveIndex; match('/' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMINUS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MINUS; std::string::size_type _saveIndex; match('-' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mPLUS(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = PLUS; std::string::size_type _saveIndex; match('+' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mINC(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = INC; std::string::size_type _saveIndex; match("++"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mDEC(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DEC; std::string::size_type _saveIndex; match("--"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mGTMARK(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = GTMARK; std::string::size_type _saveIndex; match('>' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLTMARK(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LTMARK; std::string::size_type _saveIndex; match('<' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLOG_AND(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LOG_AND; std::string::size_type _saveIndex; match("&&"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLOG_OR(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LOG_OR; std::string::size_type _saveIndex; match("||"); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mLOG_NEG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = LOG_NEG; std::string::size_type _saveIndex; match('~' /* charlit */ ); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEND_U(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = END_U; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEOL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = EOL; std::string::size_type _saveIndex; { bool synPredMatched313 = false; if (((LA(1) == 0xd /* '\r' */ ) && (LA(2) == 0xa /* '\n' */ ) && (true))) { int _m313 = mark(); synPredMatched313 = true; inputState->guessing++; try { { match("\r\n"); } } catch (antlr::RecognitionException& pe) { synPredMatched313 = false; } rewind(_m313); inputState->guessing--; } if ( synPredMatched313 ) { match("\r\n"); } else if ((LA(1) == 0xa /* '\n' */ )) { match('\n' /* charlit */ ); } else if ((LA(1) == 0xd /* '\r' */ ) && (true) && (true)) { match('\r' /* charlit */ ); } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } if ( inputState->guessing==0 ) { newline(); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mW(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = W; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x20 /* ' ' */ : { match(' ' /* charlit */ ); break; } case 0x9 /* '\t' */ : { match('\t' /* charlit */ ); break; } case 0xc /* '\14' */ : { match('\14' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mD(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = D; std::string::size_type _saveIndex; { matchRange('0','9'); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = L; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x61 /* 'a' */ : case 0x62 /* 'b' */ : case 0x63 /* 'c' */ : case 0x64 /* 'd' */ : case 0x65 /* 'e' */ : case 0x66 /* 'f' */ : case 0x67 /* 'g' */ : case 0x68 /* 'h' */ : case 0x69 /* 'i' */ : case 0x6a /* 'j' */ : case 0x6b /* 'k' */ : case 0x6c /* 'l' */ : case 0x6d /* 'm' */ : case 0x6e /* 'n' */ : case 0x6f /* 'o' */ : case 0x70 /* 'p' */ : case 0x71 /* 'q' */ : case 0x72 /* 'r' */ : case 0x73 /* 's' */ : case 0x74 /* 't' */ : case 0x75 /* 'u' */ : case 0x76 /* 'v' */ : case 0x77 /* 'w' */ : case 0x78 /* 'x' */ : case 0x79 /* 'y' */ : case 0x7a /* 'z' */ : { matchRange('a','z'); break; } case 0x5f /* '_' */ : { match('_' /* charlit */ ); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mH(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = H; std::string::size_type _saveIndex; { switch ( LA(1)) { case 0x61 /* 'a' */ : case 0x62 /* 'b' */ : case 0x63 /* 'c' */ : case 0x64 /* 'd' */ : case 0x65 /* 'e' */ : case 0x66 /* 'f' */ : { matchRange('a','f'); break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { matchRange('0','9'); break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mO(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = O; std::string::size_type _saveIndex; { matchRange('0','7'); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mB(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = B; std::string::size_type _saveIndex; { matchRange('0','1'); } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEXP(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = EXP; std::string::size_type _saveIndex; { match('e' /* charlit */ ); { if ((_tokenSet_3.member(LA(1)))) { { switch ( LA(1)) { case 0x2b /* '+' */ : { match('+' /* charlit */ ); break; } case 0x2d /* '-' */ : { match('-' /* charlit */ ); break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { // ( ... )+ int _cnt331=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt331>=1 ) { goto _loop331; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt331++; } _loop331:; } // ( ... )+ } else { } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mDBL_E(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DBL_E; std::string::size_type _saveIndex; match('d' /* charlit */ ); if ( inputState->guessing==0 ) { { text.erase(_begin); text += "E"; }; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mDBL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DBL; std::string::size_type _saveIndex; { mDBL_E(false); { if ((_tokenSet_3.member(LA(1)))) { { switch ( LA(1)) { case 0x2b /* '+' */ : { match('+' /* charlit */ ); break; } case 0x2d /* '-' */ : { match('-' /* charlit */ ); break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } { // ( ... )+ int _cnt338=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt338>=1 ) { goto _loop338; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt338++; } _loop338:; } // ( ... )+ } else { } } } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_BYTE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_BYTE; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_LONG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_LONG; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_LONG64(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_LONG64; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_I(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_I; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_INT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_INT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_ULONG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_ULONG; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_ULONG64(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_ULONG64; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_UI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_UI; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_HEX_UINT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_HEX_UINT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_BYTE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_BYTE; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_LONG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_LONG; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_LONG64(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_LONG64; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_I(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_I; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_INT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_INT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_ULONG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_ULONG; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_ULONG64(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_ULONG64; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_UI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_UI; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_UINT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_UINT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_BYTE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_BYTE; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_LONG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_LONG; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_LONG64(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_LONG64; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_I(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_I; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_INT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_INT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_ULONG(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_ULONG; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_ULONG64(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_ULONG64; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_UI(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_UI; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OCT_UINT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OCT_UINT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_FLOAT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_FLOAT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_DOUBLE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_DOUBLE; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mSTRING_LITERAL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = STRING_LITERAL; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mDOT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = DOT; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONSTANT_OR_STRING_LITERAL(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONSTANT_OR_STRING_LITERAL; std::string::size_type _saveIndex; bool synPredMatched384 = false; if (((LA(1) == 0x27 /* '\'' */ ) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3))))) { int _m384 = mark(); synPredMatched384 = true; inputState->guessing++; try { { match('\'' /* charlit */ ); { // ( ... )+ int _cnt382=0; for (;;) { if ((_tokenSet_4.member(LA(1)))) { mH(false); } else { if ( _cnt382>=1 ) { goto _loop382; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt382++; } _loop382:; } // ( ... )+ match('\'' /* charlit */ ); { if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (LA(3) == 0x73 /* 's' */ )) { match("xus"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (LA(3) == 0x62 /* 'b' */ )) { match("xub"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (LA(3) == 0x6c /* 'l' */ )) { match("xul"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x73 /* 's' */ )) { match("xs"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x62 /* 'b' */ )) { match("xb"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x6c /* 'l' */ )) { match("xl"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (true)) { match("xu"); } else if ((LA(1) == 0x78 /* 'x' */ ) && (true)) { match('x' /* charlit */ ); } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } catch (antlr::RecognitionException& pe) { synPredMatched384 = false; } rewind(_m384); inputState->guessing--; } if ( synPredMatched384 ) { { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); { // ( ... )+ int _cnt387=0; for (;;) { if ((_tokenSet_4.member(LA(1)))) { mH(false); } else { if ( _cnt387>=1 ) { goto _loop387; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt387++; } _loop387:; } // ( ... )+ _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); _saveIndex = text.length(); match('x' /* charlit */ ); text.erase(_saveIndex); { switch ( LA(1)) { case 0x73 /* 's' */ : { _saveIndex = text.length(); match('s' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_INT; } break; } case 0x62 /* 'b' */ : { _saveIndex = text.length(); match('b' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_BYTE; } break; } default: if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (LA(3) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ull"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_ULONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x73 /* 's' */ )) { _saveIndex = text.length(); match("us"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_UINT; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x62 /* 'b' */ )) { _saveIndex = text.length(); match("ub"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_BYTE; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ll"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_LONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match("ul"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_ULONG; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (true)) { _saveIndex = text.length(); match('u' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_UI; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match('l' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_LONG; } } else { if ( inputState->guessing==0 ) { _ttype=CONSTANT_HEX_I; } } } } } } else { bool synPredMatched393 = false; if (((LA(1) == 0x27 /* '\'' */ ) && ((LA(2) >= 0x30 /* '0' */ && LA(2) <= 0x37 /* '7' */ )) && (_tokenSet_6.member(LA(3))))) { int _m393 = mark(); synPredMatched393 = true; inputState->guessing++; try { { match('\'' /* charlit */ ); { // ( ... )+ int _cnt391=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x37 /* '7' */ ))) { mO(false); } else { if ( _cnt391>=1 ) { goto _loop391; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt391++; } _loop391:; } // ( ... )+ match('\'' /* charlit */ ); { if ((LA(1) == 0x6f /* 'o' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (LA(3) == 0x6c /* 'l' */ )) { match("oul"); } else if ((LA(1) == 0x6f /* 'o' */ ) && (LA(2) == 0x73 /* 's' */ )) { match("os"); } else if ((LA(1) == 0x6f /* 'o' */ ) && (LA(2) == 0x6c /* 'l' */ )) { match("ol"); } else if ((LA(1) == 0x6f /* 'o' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (true)) { match("ou"); } else if ((LA(1) == 0x6f /* 'o' */ ) && (true)) { match('o' /* charlit */ ); } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } catch (antlr::RecognitionException& pe) { synPredMatched393 = false; } rewind(_m393); inputState->guessing--; } if ( synPredMatched393 ) { { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); { // ( ... )+ int _cnt396=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x37 /* '7' */ ))) { mO(false); } else { if ( _cnt396>=1 ) { goto _loop396; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt396++; } _loop396:; } // ( ... )+ _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); _saveIndex = text.length(); match('o' /* charlit */ ); text.erase(_saveIndex); { switch ( LA(1)) { case 0x73 /* 's' */ : { _saveIndex = text.length(); match('s' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_INT; } break; } case 0x62 /* 'b' */ : { _saveIndex = text.length(); match('b' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_BYTE; } break; } default: if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (LA(3) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ull"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_ULONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x73 /* 's' */ )) { _saveIndex = text.length(); match("us"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_UINT; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x62 /* 'b' */ )) { _saveIndex = text.length(); match("ub"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_BYTE; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ll"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_LONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match("ul"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_ULONG; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (true)) { _saveIndex = text.length(); match('u' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_UI; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match('l' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_LONG; } } else { if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_I; } } } } } } else { bool synPredMatched402 = false; if (((LA(1) == 0x27 /* '\'' */ ) && (LA(2) == 0x30 /* '0' */ || LA(2) == 0x31 /* '1' */ ) && (LA(3) == 0x27 /* '\'' */ || LA(3) == 0x30 /* '0' */ || LA(3) == 0x31 /* '1' */ ))) { int _m402 = mark(); synPredMatched402 = true; inputState->guessing++; try { { match('\'' /* charlit */ ); { // ( ... )+ int _cnt400=0; for (;;) { if ((LA(1) == 0x30 /* '0' */ || LA(1) == 0x31 /* '1' */ )) { mB(false); } else { if ( _cnt400>=1 ) { goto _loop400; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt400++; } _loop400:; } // ( ... )+ match('\'' /* charlit */ ); { if ((LA(1) == 0x62 /* 'b' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (LA(3) == 0x6c /* 'l' */ )) { match("bul"); } else if ((LA(1) == 0x62 /* 'b' */ ) && (LA(2) == 0x73 /* 's' */ )) { match("bs"); } else if ((LA(1) == 0x62 /* 'b' */ ) && (LA(2) == 0x6c /* 'l' */ )) { match("bl"); } else if ((LA(1) == 0x62 /* 'b' */ ) && (LA(2) == 0x75 /* 'u' */ ) && (true)) { match("bu"); } else if ((LA(1) == 0x62 /* 'b' */ ) && (true)) { match('b' /* charlit */ ); } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } catch (antlr::RecognitionException& pe) { synPredMatched402 = false; } rewind(_m402); inputState->guessing--; } if ( synPredMatched402 ) { { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); { // ( ... )+ int _cnt405=0; for (;;) { if ((LA(1) == 0x30 /* '0' */ || LA(1) == 0x31 /* '1' */ )) { mB(false); } else { if ( _cnt405>=1 ) { goto _loop405; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt405++; } _loop405:; } // ( ... )+ _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); _saveIndex = text.length(); match('b' /* charlit */ ); text.erase(_saveIndex); { switch ( LA(1)) { case 0x73 /* 's' */ : { _saveIndex = text.length(); match('s' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_INT; } break; } case 0x62 /* 'b' */ : { _saveIndex = text.length(); match('b' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_BYTE; } break; } default: if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (LA(3) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ull"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_ULONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x73 /* 's' */ )) { _saveIndex = text.length(); match("us"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_UINT; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x62 /* 'b' */ )) { _saveIndex = text.length(); match("ub"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_BYTE; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ll"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_LONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match("ul"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_ULONG; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (true)) { _saveIndex = text.length(); match('u' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_UI; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match('l' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_LONG; } } else { if ( inputState->guessing==0 ) { _ttype=CONSTANT_BIN_I; } } } } } } else { bool synPredMatched375 = false; if (((LA(1) == 0x22 /* '\"' */ ) && ((LA(2) >= 0x30 /* '0' */ && LA(2) <= 0x37 /* '7' */ )) && (true))) { int _m375 = mark(); synPredMatched375 = true; inputState->guessing++; try { { match('\"' /* charlit */ ); { // ( ... )+ int _cnt373=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x37 /* '7' */ ))) { mO(false); } else { if ( _cnt373>=1 ) { goto _loop373; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt373++; } _loop373:; } // ( ... )+ { switch ( LA(1)) { case 0x62 /* 'b' */ : { match('b' /* charlit */ ); break; } case 0x73 /* 's' */ : { match('s' /* charlit */ ); break; } case 0x6c /* 'l' */ : { match('l' /* charlit */ ); break; } default: if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x73 /* 's' */ )) { match("us"); } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x62 /* 'b' */ )) { match("ub"); } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ )) { match("ul"); } else if ((LA(1) == 0x75 /* 'u' */ ) && (true)) { match('u' /* charlit */ ); } else { } } } } } catch (antlr::RecognitionException& pe) { synPredMatched375 = false; } rewind(_m375); inputState->guessing--; } if ( synPredMatched375 ) { { _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); { // ( ... )+ int _cnt378=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x37 /* '7' */ ))) { mO(false); } else { if ( _cnt378>=1 ) { goto _loop378; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt378++; } _loop378:; } // ( ... )+ if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_I; } { switch ( LA(1)) { case 0x73 /* 's' */ : { _saveIndex = text.length(); match('s' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_INT; } break; } case 0x62 /* 'b' */ : { _saveIndex = text.length(); match('b' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_BYTE; } break; } default: if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (LA(3) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ull"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_ULONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x73 /* 's' */ )) { _saveIndex = text.length(); match("us"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_UINT; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x62 /* 'b' */ )) { _saveIndex = text.length(); match("ub"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_BYTE; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ll"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_LONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match("ul"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_ULONG; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (true)) { _saveIndex = text.length(); match('u' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_UI; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match('l' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_OCT_LONG; } } else { } } } } } else { bool synPredMatched426 = false; if (((_tokenSet_7.member(LA(1))) && (_tokenSet_8.member(LA(2))) && (true))) { int _m426 = mark(); synPredMatched426 = true; inputState->guessing++; try { { switch ( LA(1)) { case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { { { // ( ... )+ int _cnt418=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt418>=1 ) { goto _loop418; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt418++; } _loop418:; } // ( ... )+ { switch ( LA(1)) { case 0x64 /* 'd' */ : { mDBL(false); break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )* for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { goto _loop421; } } _loop421:; } // ( ... )* { mDBL(false); } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )+ int _cnt424=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt424>=1 ) { goto _loop424; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt424++; } _loop424:; } // ( ... )+ { mDBL(false); } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } catch (antlr::RecognitionException& pe) { synPredMatched426 = false; } rewind(_m426); inputState->guessing--; } if ( synPredMatched426 ) { { switch ( LA(1)) { case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { { { // ( ... )+ int _cnt430=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt430>=1 ) { goto _loop430; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt430++; } _loop430:; } // ( ... )+ { switch ( LA(1)) { case 0x64 /* 'd' */ : { mDBL(false); break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )* for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { goto _loop433; } } _loop433:; } // ( ... )* { mDBL(false); } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )+ int _cnt436=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt436>=1 ) { goto _loop436; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt436++; } _loop436:; } // ( ... )+ { mDBL(false); } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( inputState->guessing==0 ) { _ttype=CONSTANT_DOUBLE; } } else { bool synPredMatched449 = false; if (((_tokenSet_7.member(LA(1))) && (_tokenSet_9.member(LA(2))) && (true))) { int _m449 = mark(); synPredMatched449 = true; inputState->guessing++; try { { switch ( LA(1)) { case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { { { // ( ... )+ int _cnt441=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt441>=1 ) { goto _loop441; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt441++; } _loop441:; } // ( ... )+ { switch ( LA(1)) { case 0x65 /* 'e' */ : { mEXP(false); break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )* for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { goto _loop444; } } _loop444:; } // ( ... )* { if ((LA(1) == 0x65 /* 'e' */ )) { mEXP(false); } else { } } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )+ int _cnt447=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt447>=1 ) { goto _loop447; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt447++; } _loop447:; } // ( ... )+ { if ((LA(1) == 0x65 /* 'e' */ )) { mEXP(false); } else { } } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } catch (antlr::RecognitionException& pe) { synPredMatched449 = false; } rewind(_m449); inputState->guessing--; } if ( synPredMatched449 ) { { switch ( LA(1)) { case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { { { // ( ... )+ int _cnt453=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt453>=1 ) { goto _loop453; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt453++; } _loop453:; } // ( ... )+ { switch ( LA(1)) { case 0x65 /* 'e' */ : { mEXP(false); break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )* for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { goto _loop456; } } _loop456:; } // ( ... )* { if ((LA(1) == 0x65 /* 'e' */ )) { mEXP(false); } else { } } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } } break; } case 0x2e /* '.' */ : { match('.' /* charlit */ ); { // ( ... )+ int _cnt459=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt459>=1 ) { goto _loop459; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt459++; } _loop459:; } // ( ... )+ { if ((LA(1) == 0x65 /* 'e' */ )) { mEXP(false); } else { } } break; } default: { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } } } if ( inputState->guessing==0 ) { _ttype=CONSTANT_FLOAT; } } else if ((LA(1) == 0x22 /* '\"' */ ) && (true) && (true)) { _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); { // ( ... )* for (;;) { if ((LA(1) == 0x22 /* '\"' */ ) && (LA(2) == 0x22 /* '\"' */ )) { match('\"' /* charlit */ ); _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); } else if ((_tokenSet_10.member(LA(1)))) { { match(_tokenSet_10); } } else { goto _loop409; } } _loop409:; } // ( ... )* { if ((LA(1) == 0x22 /* '\"' */ )) { _saveIndex = text.length(); match('\"' /* charlit */ ); text.erase(_saveIndex); } else { } } if ( inputState->guessing==0 ) { _ttype=STRING_LITERAL; } } else if ((LA(1) == 0x27 /* '\'' */ ) && (true) && (true)) { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); { // ( ... )* for (;;) { if ((LA(1) == 0x27 /* '\'' */ ) && (LA(2) == 0x27 /* '\'' */ )) { match('\'' /* charlit */ ); _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); } else if ((_tokenSet_11.member(LA(1)))) { { match(_tokenSet_11); } } else { goto _loop413; } } _loop413:; } // ( ... )* { if ((LA(1) == 0x27 /* '\'' */ )) { _saveIndex = text.length(); match('\'' /* charlit */ ); text.erase(_saveIndex); } else { } } if ( inputState->guessing==0 ) { _ttype=STRING_LITERAL; } } else if ((LA(1) == 0x2e /* '.' */ ) && (true)) { match('.' /* charlit */ ); if ( inputState->guessing==0 ) { _ttype=DOT; } } else if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ )) && (true) && (true)) { { // ( ... )+ int _cnt462=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { mD(false); } else { if ( _cnt462>=1 ) { goto _loop462; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt462++; } _loop462:; } // ( ... )+ if ( inputState->guessing==0 ) { _ttype=CONSTANT_I; } { switch ( LA(1)) { case 0x73 /* 's' */ : { _saveIndex = text.length(); match('s' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_INT; } break; } case 0x62 /* 'b' */ : { _saveIndex = text.length(); match('b' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BYTE; } break; } default: if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (LA(3) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ull"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_ULONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x62 /* 'b' */ )) { _saveIndex = text.length(); match("ub"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_BYTE; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (LA(2) == 0x6c /* 'l' */ )) { _saveIndex = text.length(); match("ll"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_LONG64; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (LA(2) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match("ul"); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_ULONG; } } else if ((LA(1) == 0x75 /* 'u' */ ) && (true)) { _saveIndex = text.length(); match('u' /* charlit */ ); text.erase(_saveIndex); { if ((LA(1) == 0x73 /* 's' */ )) { _saveIndex = text.length(); match('s' /* charlit */ ); text.erase(_saveIndex); } else { } } if ( inputState->guessing==0 ) { _ttype=CONSTANT_UINT; } } else if ((LA(1) == 0x6c /* 'l' */ ) && (true)) { _saveIndex = text.length(); match('l' /* charlit */ ); text.erase(_saveIndex); if ( inputState->guessing==0 ) { _ttype=CONSTANT_LONG; } } else { } } } } else { throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); } }}}}} if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCOMMENT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = COMMENT; std::string::size_type _saveIndex; match(';' /* charlit */ ); { // ( ... )* for (;;) { if ((_tokenSet_2.member(LA(1))) && (true) && (true)) { { match(_tokenSet_2); } } else { goto _loop468; } } _loop468:; } // ( ... )* if ( inputState->guessing==0 ) { _ttype=antlr::Token::SKIP; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mIDENTIFIER(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = IDENTIFIER; std::string::size_type _saveIndex; { mL(false); } { // ( ... )* for (;;) { switch ( LA(1)) { case 0x5f /* '_' */ : case 0x61 /* 'a' */ : case 0x62 /* 'b' */ : case 0x63 /* 'c' */ : case 0x64 /* 'd' */ : case 0x65 /* 'e' */ : case 0x66 /* 'f' */ : case 0x67 /* 'g' */ : case 0x68 /* 'h' */ : case 0x69 /* 'i' */ : case 0x6a /* 'j' */ : case 0x6b /* 'k' */ : case 0x6c /* 'l' */ : case 0x6d /* 'm' */ : case 0x6e /* 'n' */ : case 0x6f /* 'o' */ : case 0x70 /* 'p' */ : case 0x71 /* 'q' */ : case 0x72 /* 'r' */ : case 0x73 /* 's' */ : case 0x74 /* 't' */ : case 0x75 /* 'u' */ : case 0x76 /* 'v' */ : case 0x77 /* 'w' */ : case 0x78 /* 'x' */ : case 0x79 /* 'y' */ : case 0x7a /* 'z' */ : { mL(false); break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { mD(false); break; } case 0x24 /* '$' */ : { match('$' /* charlit */ ); break; } default: { goto _loop472; } } } _loop472:; } // ( ... )* if ( inputState->guessing==0 ) { std::string s=StrUpCase( text.substr(_begin,text.length()-_begin)); { text.erase(_begin); text += s; }; } _ttype = testLiteralsTable(_ttype); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mSYSVARNAME(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SYSVARNAME; std::string::size_type _saveIndex; { match('!' /* charlit */ ); } { // ( ... )+ int _cnt476=0; for (;;) { switch ( LA(1)) { case 0x5f /* '_' */ : case 0x61 /* 'a' */ : case 0x62 /* 'b' */ : case 0x63 /* 'c' */ : case 0x64 /* 'd' */ : case 0x65 /* 'e' */ : case 0x66 /* 'f' */ : case 0x67 /* 'g' */ : case 0x68 /* 'h' */ : case 0x69 /* 'i' */ : case 0x6a /* 'j' */ : case 0x6b /* 'k' */ : case 0x6c /* 'l' */ : case 0x6d /* 'm' */ : case 0x6e /* 'n' */ : case 0x6f /* 'o' */ : case 0x70 /* 'p' */ : case 0x71 /* 'q' */ : case 0x72 /* 'r' */ : case 0x73 /* 's' */ : case 0x74 /* 't' */ : case 0x75 /* 'u' */ : case 0x76 /* 'v' */ : case 0x77 /* 'w' */ : case 0x78 /* 'x' */ : case 0x79 /* 'y' */ : case 0x7a /* 'z' */ : { mL(false); break; } case 0x30 /* '0' */ : case 0x31 /* '1' */ : case 0x32 /* '2' */ : case 0x33 /* '3' */ : case 0x34 /* '4' */ : case 0x35 /* '5' */ : case 0x36 /* '6' */ : case 0x37 /* '7' */ : case 0x38 /* '8' */ : case 0x39 /* '9' */ : { mD(false); break; } case 0x24 /* '$' */ : { match('$' /* charlit */ ); break; } default: { if ( _cnt476>=1 ) { goto _loop476; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } } _cnt476++; } _loop476:; } // ( ... )+ if ( inputState->guessing==0 ) { std::string s=StrUpCase( text.substr(_begin,text.length()-_begin)); { text.erase(_begin); text += s; }; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEND_MARKER(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = END_MARKER; std::string::size_type _saveIndex; match('&' /* charlit */ ); if ( inputState->guessing==0 ) { _ttype=END_U; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mWHITESPACE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = WHITESPACE; std::string::size_type _saveIndex; { // ( ... )+ int _cnt480=0; for (;;) { if ((LA(1) == 0x9 /* '\t' */ || LA(1) == 0xc /* '\14' */ || LA(1) == 0x20 /* ' ' */ )) { mW(false); } else { if ( _cnt480>=1 ) { goto _loop480; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } _cnt480++; } _loop480:; } // ( ... )+ if ( inputState->guessing==0 ) { _ttype=antlr::Token::SKIP; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mSKIP_LINES(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = SKIP_LINES; std::string::size_type _saveIndex; { // ( ... )* for (;;) { switch ( LA(1)) { case 0x3b /* ';' */ : { mCOMMENT(false); break; } case 0x9 /* '\t' */ : case 0xc /* '\14' */ : case 0x20 /* ' ' */ : { mW(false); break; } case 0xa /* '\n' */ : case 0xd /* '\r' */ : { mEOL(false); break; } default: { goto _loop483; } } } _loop483:; } // ( ... )* if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mCONT_STATEMENT(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = CONT_STATEMENT; std::string::size_type _saveIndex; match('$' /* charlit */ ); { // ( ... )* for (;;) { if ((_tokenSet_2.member(LA(1)))) { { match(_tokenSet_2); } } else { goto _loop487; } } _loop487:; } // ( ... )* mEOL(false); mSKIP_LINES(false); if ( inputState->guessing==0 ) { ++lineContinuation; _ttype=antlr::Token::SKIP; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mEND_OF_LINE(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = END_OF_LINE; std::string::size_type _saveIndex; mEOL(false); mSKIP_LINES(false); if ( inputState->guessing==0 ) { _ttype=END_U; } if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } void GDLLexer::mMAX_TOKEN_NUMBER(bool _createToken) { int _ttype; antlr::RefToken _token; std::string::size_type _begin = text.length(); _ttype = MAX_TOKEN_NUMBER; std::string::size_type _saveIndex; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); _token->setText(text.substr(_begin, text.length()-_begin)); } _returnToken = _token; _saveIndex=0; } const unsigned long GDLLexer::_tokenSet_0_data_[] = { 0UL, 67043344UL, 2147483648UL, 134217726UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // $ 0 1 2 3 4 5 6 7 8 9 _ a b c d e f g h i j k l m n o p q r s t u v // w x y z const antlr::BitSet GDLLexer::_tokenSet_0(_tokenSet_0_data_,10); const unsigned long GDLLexer::_tokenSet_1_data_[] = { 0UL, 0UL, 2147483648UL, 134217726UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // _ a b c d e f g h i j k l m n o p q r s t u v w x y z const antlr::BitSet GDLLexer::_tokenSet_1(_tokenSet_1_data_,10); const unsigned long GDLLexer::_tokenSet_2_data_[] = { 4294958072UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xe 0xf 0x10 0x11 0x12 0x13 0x14 // 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f ! \" # $ % // & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G // H I J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ ` a b c d e f g h // i j k l m n o p q r s t u v w x y z { | } ~ 0x7f 0x80 0x81 0x82 0x83 // 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90 0x91 // 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f // 0xa0 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad // 0xae 0xaf 0xb0 0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb // 0xbc 0xbd 0xbe 0xbf 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 // 0xca 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 // 0xd8 0xd9 0xda 0xdb 0xdc 0xdd 0xde 0xdf 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 // 0xe6 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed const antlr::BitSet GDLLexer::_tokenSet_2(_tokenSet_2_data_,16); const unsigned long GDLLexer::_tokenSet_3_data_[] = { 0UL, 67053568UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // + - 0 1 2 3 4 5 6 7 8 9 const antlr::BitSet GDLLexer::_tokenSet_3(_tokenSet_3_data_,10); const unsigned long GDLLexer::_tokenSet_4_data_[] = { 0UL, 67043328UL, 0UL, 126UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0 1 2 3 4 5 6 7 8 9 a b c d e f const antlr::BitSet GDLLexer::_tokenSet_4(_tokenSet_4_data_,10); const unsigned long GDLLexer::_tokenSet_5_data_[] = { 0UL, 67043456UL, 0UL, 126UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // \' 0 1 2 3 4 5 6 7 8 9 a b c d e f const antlr::BitSet GDLLexer::_tokenSet_5(_tokenSet_5_data_,10); const unsigned long GDLLexer::_tokenSet_6_data_[] = { 0UL, 16711808UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // \' 0 1 2 3 4 5 6 7 const antlr::BitSet GDLLexer::_tokenSet_6(_tokenSet_6_data_,10); const unsigned long GDLLexer::_tokenSet_7_data_[] = { 0UL, 67059712UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // . 0 1 2 3 4 5 6 7 8 9 const antlr::BitSet GDLLexer::_tokenSet_7(_tokenSet_7_data_,10); const unsigned long GDLLexer::_tokenSet_8_data_[] = { 0UL, 67059712UL, 0UL, 16UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // . 0 1 2 3 4 5 6 7 8 9 d const antlr::BitSet GDLLexer::_tokenSet_8(_tokenSet_8_data_,10); const unsigned long GDLLexer::_tokenSet_9_data_[] = { 0UL, 67059712UL, 0UL, 32UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // . 0 1 2 3 4 5 6 7 8 9 e const antlr::BitSet GDLLexer::_tokenSet_9(_tokenSet_9_data_,10); const unsigned long GDLLexer::_tokenSet_10_data_[] = { 4294958072UL, 4294967291UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xe 0xf 0x10 0x11 0x12 0x13 0x14 // 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f ! # $ % & \' // ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I // J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ ` a b c d e f g h i j // k l m n o p q r s t u v w x y z { | } ~ 0x7f 0x80 0x81 0x82 0x83 0x84 // 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90 0x91 0x92 // 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0 // 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae // 0xaf 0xb0 0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb 0xbc // 0xbd 0xbe 0xbf 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 0xca // 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 // 0xd9 0xda 0xdb 0xdc 0xdd 0xde 0xdf 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 // 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed const antlr::BitSet GDLLexer::_tokenSet_10(_tokenSet_10_data_,16); const unsigned long GDLLexer::_tokenSet_11_data_[] = { 4294958072UL, 4294967167UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xe 0xf 0x10 0x11 0x12 0x13 0x14 // 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f ! \" # $ % // & ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H // I J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ ` a b c d e f g h i // j k l m n o p q r s t u v w x y z { | } ~ 0x7f 0x80 0x81 0x82 0x83 0x84 // 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90 0x91 0x92 // 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0 // 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae // 0xaf 0xb0 0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb 0xbc // 0xbd 0xbe 0xbf 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 0xca // 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 // 0xd9 0xda 0xdb 0xdc 0xdd 0xde 0xdf 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 // 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed const antlr::BitSet GDLLexer::_tokenSet_11(_tokenSet_11_data_,16); gdl-0.9.9/src/GDLLexer.hpp000066400000000000000000000237271340051421000152060ustar00rootroot00000000000000#ifndef INC_GDLLexer_hpp_ #define INC_GDLLexer_hpp_ #include /* $ANTLR 2.7.7 (2006-11-01): "gdlc.g" -> "GDLLexer.hpp"$ */ #include #include #include #include "GDLTokenTypes.hpp" #include #include #include "GDLParser.hpp" #include "str.hpp" #include "dnodefactory.hpp" #include "objects.hpp" #include "initsysvar.hpp" #include #include #include #include #include //#include "dinterpreter.hpp" // defintion in dinterpreter.cpp //void SetActualCompileOpt( unsigned int cOpt); class CUSTOM_API GDLLexer : public antlr::CharScanner, public GDLTokenTypes { // Stuff for include files (@filename) private: std::unique_ptr inputFile; // stores ifsteam* and deletes // it when it is deleted itself antlr::TokenStreamSelector* selector; GDLLexer* mainLexerPtr; GDLParser* parserPtr; int lineContinuation; public: ~GDLLexer() { if( mainLexerPtr != this) selector->pop(); // return to old lexer/stream else { delete parserPtr; delete selector; } } // main lexer constructor GDLLexer( std::istream& in, const std::string &f, unsigned int compileOptIn, const std::string &pro="", bool searchForPro=true) : antlr::CharScanner(new antlr::CharBuffer(in),false), lineContinuation( 0) // : antlr::CharScanner(in) { setCaseSensitive(false); initLiterals(); selector= new antlr::TokenStreamSelector(); mainLexerPtr= this; parserPtr= new GDLParser( *selector, pro, searchForPro, compileOptIn); parserPtr->setFilename(f); parserPtr->initializeASTFactory( DNodeFactory); parserPtr->setASTFactory( &DNodeFactory ); // parserPtr->setASTNodeFactory( DNode::factory ); selector->addInputStream(this, f); selector->select(f); // start with main lexer // set line number to 0 in interactive mode if( f == "") { setLine(0); } // p=parserPtr; } // sublexer constructor GDLLexer( std::ifstream& in, const std::string& name, GDLLexer* parent) : antlr::CharScanner(new antlr::CharBuffer(in),false), inputFile( &in) // : antlr::CharScanner(new antlr::CharInputBuffer(in)) // : antlr::CharScanner(new antlr::CharBuffer(in)) { setCaseSensitive(false); initLiterals(); selector= parent->selector; mainLexerPtr= parent->mainLexerPtr; parserPtr= parent->parserPtr; // inputFile.Reset( &in); // make sure file // // gets deleted (closed) // // when lexer finish // make sure errors are reported in right file setFilename(name); parserPtr->setFilename(name); selector->push(this); } GDLParser& Parser() { return *parserPtr; } int LineContinuation() { int lC = lineContinuation; lineContinuation = 0; return lC; } void uponEOF() /*throws TokenStreamException, CharStreamException*/ { if ( selector->getCurrentStream() != mainLexerPtr ) { //if( this != mainLexerPtr ) { // make copy as we delete 'this' antlr::TokenStreamSelector* sel=selector; // here 'this' is deleted (pops selector) delete sel->getCurrentStream(); // make sure errors are reported in right file parserPtr->setFilename( static_cast(selector->getCurrentStream())->getFilename()); // don't allow EOF until main lexer. Force the // selector to retry for another token. sel->retry(); } } private: void initLiterals(); public: bool getCaseSensitiveLiterals() const { return false; } public: GDLLexer(std::istream& in); GDLLexer(antlr::InputBuffer& ib); GDLLexer(const antlr::LexerSharedInputState& state); antlr::RefToken nextToken(); protected: void mSTRING(bool _createToken); public: void mINCLUDE(bool _createToken); public: void mAND_OP_EQ(bool _createToken); public: void mASTERIX_EQ(bool _createToken); public: void mEQ_OP_EQ(bool _createToken); public: void mGE_OP_EQ(bool _createToken); public: void mGTMARK_EQ(bool _createToken); public: void mGT_OP_EQ(bool _createToken); public: void mLE_OP_EQ(bool _createToken); public: void mLTMARK_EQ(bool _createToken); public: void mLT_OP_EQ(bool _createToken); public: void mMATRIX_OP1_EQ(bool _createToken); public: void mMATRIX_OP2_EQ(bool _createToken); public: void mMINUS_EQ(bool _createToken); public: void mMOD_OP_EQ(bool _createToken); public: void mNE_OP_EQ(bool _createToken); public: void mOR_OP_EQ(bool _createToken); public: void mPLUS_EQ(bool _createToken); public: void mPOW_EQ(bool _createToken); public: void mSLASH_EQ(bool _createToken); public: void mXOR_OP_EQ(bool _createToken); public: void mMATRIX_OP1(bool _createToken); public: void mMATRIX_OP2(bool _createToken); public: void mMETHOD(bool _createToken); public: void mMEMBER(bool _createToken); public: void mCOMMA(bool _createToken); public: void mCOLON(bool _createToken); public: void mEQUAL(bool _createToken); public: void mLCURLY(bool _createToken); public: void mRCURLY(bool _createToken); public: void mLSQUARE(bool _createToken); public: void mRSQUARE(bool _createToken); public: void mLBRACE(bool _createToken); public: void mRBRACE(bool _createToken); public: void mQUESTION(bool _createToken); public: void mEXCLAMATION(bool _createToken); public: void mPOW(bool _createToken); public: void mASTERIX(bool _createToken); public: void mSLASH(bool _createToken); public: void mMINUS(bool _createToken); public: void mPLUS(bool _createToken); public: void mINC(bool _createToken); public: void mDEC(bool _createToken); public: void mGTMARK(bool _createToken); public: void mLTMARK(bool _createToken); public: void mLOG_AND(bool _createToken); public: void mLOG_OR(bool _createToken); public: void mLOG_NEG(bool _createToken); protected: void mEND_U(bool _createToken); protected: void mEOL(bool _createToken); protected: void mW(bool _createToken); protected: void mD(bool _createToken); protected: void mL(bool _createToken); protected: void mH(bool _createToken); protected: void mO(bool _createToken); protected: void mB(bool _createToken); protected: void mEXP(bool _createToken); protected: void mDBL_E(bool _createToken); protected: void mDBL(bool _createToken); protected: void mCONSTANT_HEX_BYTE(bool _createToken); protected: void mCONSTANT_HEX_LONG(bool _createToken); protected: void mCONSTANT_HEX_LONG64(bool _createToken); protected: void mCONSTANT_HEX_I(bool _createToken); protected: void mCONSTANT_HEX_INT(bool _createToken); protected: void mCONSTANT_HEX_ULONG(bool _createToken); protected: void mCONSTANT_HEX_ULONG64(bool _createToken); protected: void mCONSTANT_HEX_UI(bool _createToken); protected: void mCONSTANT_HEX_UINT(bool _createToken); protected: void mCONSTANT_BYTE(bool _createToken); protected: void mCONSTANT_LONG(bool _createToken); protected: void mCONSTANT_LONG64(bool _createToken); protected: void mCONSTANT_I(bool _createToken); protected: void mCONSTANT_INT(bool _createToken); protected: void mCONSTANT_ULONG(bool _createToken); protected: void mCONSTANT_ULONG64(bool _createToken); protected: void mCONSTANT_UI(bool _createToken); protected: void mCONSTANT_UINT(bool _createToken); protected: void mCONSTANT_OCT_BYTE(bool _createToken); protected: void mCONSTANT_OCT_LONG(bool _createToken); protected: void mCONSTANT_OCT_LONG64(bool _createToken); protected: void mCONSTANT_OCT_I(bool _createToken); protected: void mCONSTANT_OCT_INT(bool _createToken); protected: void mCONSTANT_OCT_ULONG(bool _createToken); protected: void mCONSTANT_OCT_ULONG64(bool _createToken); protected: void mCONSTANT_OCT_UI(bool _createToken); protected: void mCONSTANT_OCT_UINT(bool _createToken); protected: void mCONSTANT_FLOAT(bool _createToken); protected: void mCONSTANT_DOUBLE(bool _createToken); protected: void mSTRING_LITERAL(bool _createToken); protected: void mDOT(bool _createToken); public: void mCONSTANT_OR_STRING_LITERAL(bool _createToken); public: void mCOMMENT(bool _createToken); public: void mIDENTIFIER(bool _createToken); public: void mSYSVARNAME(bool _createToken); public: void mEND_MARKER(bool _createToken); public: void mWHITESPACE(bool _createToken); protected: void mSKIP_LINES(bool _createToken); public: void mCONT_STATEMENT(bool _createToken); public: void mEND_OF_LINE(bool _createToken); protected: void mMAX_TOKEN_NUMBER(bool _createToken); private: static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; static const unsigned long _tokenSet_2_data_[]; static const antlr::BitSet _tokenSet_2; static const unsigned long _tokenSet_3_data_[]; static const antlr::BitSet _tokenSet_3; static const unsigned long _tokenSet_4_data_[]; static const antlr::BitSet _tokenSet_4; static const unsigned long _tokenSet_5_data_[]; static const antlr::BitSet _tokenSet_5; static const unsigned long _tokenSet_6_data_[]; static const antlr::BitSet _tokenSet_6; static const unsigned long _tokenSet_7_data_[]; static const antlr::BitSet _tokenSet_7; static const unsigned long _tokenSet_8_data_[]; static const antlr::BitSet _tokenSet_8; static const unsigned long _tokenSet_9_data_[]; static const antlr::BitSet _tokenSet_9; static const unsigned long _tokenSet_10_data_[]; static const antlr::BitSet _tokenSet_10; static const unsigned long _tokenSet_11_data_[]; static const antlr::BitSet _tokenSet_11; }; #endif /*INC_GDLLexer_hpp_*/ gdl-0.9.9/src/GDLParser.cpp000066400000000000000000010273651340051421000153610ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "gdlc.g" -> "GDLParser.cpp"$ */ #include "includefirst.hpp" #include "GDLParser.hpp" #include #include #include #include #include GDLParser::GDLParser(antlr::TokenBuffer& tokenBuf, int k) : antlr::LLkParser(tokenBuf,k) { } GDLParser::GDLParser(antlr::TokenBuffer& tokenBuf) : antlr::LLkParser(tokenBuf,2) { } GDLParser::GDLParser(antlr::TokenStream& lexer, int k) : antlr::LLkParser(lexer,k) { } GDLParser::GDLParser(antlr::TokenStream& lexer) : antlr::LLkParser(lexer,2) { } GDLParser::GDLParser(const antlr::ParserSharedInputState& state) : antlr::LLkParser(state,2) { } void GDLParser::identifier() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode identifier_AST = RefDNode(antlr::nullAST); antlr::RefToken a = antlr::nullToken; RefDNode a_AST = RefDNode(antlr::nullAST); antlr::RefToken b = antlr::nullToken; RefDNode b_AST = RefDNode(antlr::nullAST); antlr::RefToken c = antlr::nullToken; RefDNode c_AST = RefDNode(antlr::nullAST); antlr::RefToken co = antlr::nullToken; RefDNode co_AST = RefDNode(antlr::nullAST); antlr::RefToken com = antlr::nullToken; RefDNode com_AST = RefDNode(antlr::nullAST); antlr::RefToken d = antlr::nullToken; RefDNode d_AST = RefDNode(antlr::nullAST); antlr::RefToken e = antlr::nullToken; RefDNode e_AST = RefDNode(antlr::nullAST); antlr::RefToken en = antlr::nullToken; RefDNode en_AST = RefDNode(antlr::nullAST); antlr::RefToken end = antlr::nullToken; RefDNode end_AST = RefDNode(antlr::nullAST); antlr::RefToken ende = antlr::nullToken; RefDNode ende_AST = RefDNode(antlr::nullAST); antlr::RefToken endf = antlr::nullToken; RefDNode endf_AST = RefDNode(antlr::nullAST); antlr::RefToken endfe = antlr::nullToken; RefDNode endfe_AST = RefDNode(antlr::nullAST); antlr::RefToken endi = antlr::nullToken; RefDNode endi_AST = RefDNode(antlr::nullAST); antlr::RefToken endr = antlr::nullToken; RefDNode endr_AST = RefDNode(antlr::nullAST); antlr::RefToken ends = antlr::nullToken; RefDNode ends_AST = RefDNode(antlr::nullAST); antlr::RefToken endw = antlr::nullToken; RefDNode endw_AST = RefDNode(antlr::nullAST); antlr::RefToken eq = antlr::nullToken; RefDNode eq_AST = RefDNode(antlr::nullAST); antlr::RefToken f = antlr::nullToken; RefDNode f_AST = RefDNode(antlr::nullAST); antlr::RefToken fe = antlr::nullToken; RefDNode fe_AST = RefDNode(antlr::nullAST); antlr::RefToken fo = antlr::nullToken; RefDNode fo_AST = RefDNode(antlr::nullAST); antlr::RefToken fu = antlr::nullToken; RefDNode fu_AST = RefDNode(antlr::nullAST); antlr::RefToken g = antlr::nullToken; RefDNode g_AST = RefDNode(antlr::nullAST); antlr::RefToken go = antlr::nullToken; RefDNode go_AST = RefDNode(antlr::nullAST); antlr::RefToken gt = antlr::nullToken; RefDNode gt_AST = RefDNode(antlr::nullAST); antlr::RefToken i = antlr::nullToken; RefDNode i_AST = RefDNode(antlr::nullAST); antlr::RefToken in = antlr::nullToken; RefDNode in_AST = RefDNode(antlr::nullAST); antlr::RefToken l = antlr::nullToken; RefDNode l_AST = RefDNode(antlr::nullAST); antlr::RefToken lt = antlr::nullToken; RefDNode lt_AST = RefDNode(antlr::nullAST); antlr::RefToken m = antlr::nullToken; RefDNode m_AST = RefDNode(antlr::nullAST); antlr::RefToken n = antlr::nullToken; RefDNode n_AST = RefDNode(antlr::nullAST); antlr::RefToken no = antlr::nullToken; RefDNode no_AST = RefDNode(antlr::nullAST); antlr::RefToken o = antlr::nullToken; RefDNode o_AST = RefDNode(antlr::nullAST); antlr::RefToken on = antlr::nullToken; RefDNode on_AST = RefDNode(antlr::nullAST); antlr::RefToken o_ = antlr::nullToken; RefDNode o__AST = RefDNode(antlr::nullAST); antlr::RefToken p = antlr::nullToken; RefDNode p_AST = RefDNode(antlr::nullAST); antlr::RefToken r = antlr::nullToken; RefDNode r_AST = RefDNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefDNode s_AST = RefDNode(antlr::nullAST); antlr::RefToken t = antlr::nullToken; RefDNode t_AST = RefDNode(antlr::nullAST); antlr::RefToken u = antlr::nullToken; RefDNode u_AST = RefDNode(antlr::nullAST); antlr::RefToken w = antlr::nullToken; RefDNode w_AST = RefDNode(antlr::nullAST); antlr::RefToken x = antlr::nullToken; RefDNode x_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: { RefDNode tmp1_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp1_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp1_AST)); } match(IDENTIFIER); identifier_AST = RefDNode(currentAST.root); break; } case AND_OP: { a = LT(1); if ( inputState->guessing == 0 ) { a_AST = astFactory->create(a); astFactory->addASTChild(currentAST, antlr::RefAST(a_AST)); } match(AND_OP); if ( inputState->guessing==0 ) { a_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case BEGIN: { b = LT(1); if ( inputState->guessing == 0 ) { b_AST = astFactory->create(b); astFactory->addASTChild(currentAST, antlr::RefAST(b_AST)); } match(BEGIN); if ( inputState->guessing==0 ) { b_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case CASE: { c = LT(1); if ( inputState->guessing == 0 ) { c_AST = astFactory->create(c); astFactory->addASTChild(currentAST, antlr::RefAST(c_AST)); } match(CASE); if ( inputState->guessing==0 ) { c_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case COMMON: { co = LT(1); if ( inputState->guessing == 0 ) { co_AST = astFactory->create(co); astFactory->addASTChild(currentAST, antlr::RefAST(co_AST)); } match(COMMON); if ( inputState->guessing==0 ) { co_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case COMPILE_OPT: { com = LT(1); if ( inputState->guessing == 0 ) { com_AST = astFactory->create(com); astFactory->addASTChild(currentAST, antlr::RefAST(com_AST)); } match(COMPILE_OPT); if ( inputState->guessing==0 ) { com_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case DO: { d = LT(1); if ( inputState->guessing == 0 ) { d_AST = astFactory->create(d); astFactory->addASTChild(currentAST, antlr::RefAST(d_AST)); } match(DO); if ( inputState->guessing==0 ) { d_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ELSE: { e = LT(1); if ( inputState->guessing == 0 ) { e_AST = astFactory->create(e); astFactory->addASTChild(currentAST, antlr::RefAST(e_AST)); } match(ELSE); if ( inputState->guessing==0 ) { e_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case END: { en = LT(1); if ( inputState->guessing == 0 ) { en_AST = astFactory->create(en); astFactory->addASTChild(currentAST, antlr::RefAST(en_AST)); } match(END); if ( inputState->guessing==0 ) { en_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDCASE: { end = LT(1); if ( inputState->guessing == 0 ) { end_AST = astFactory->create(end); astFactory->addASTChild(currentAST, antlr::RefAST(end_AST)); } match(ENDCASE); if ( inputState->guessing==0 ) { end_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDELSE: { ende = LT(1); if ( inputState->guessing == 0 ) { ende_AST = astFactory->create(ende); astFactory->addASTChild(currentAST, antlr::RefAST(ende_AST)); } match(ENDELSE); if ( inputState->guessing==0 ) { ende_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDFOR: { endf = LT(1); if ( inputState->guessing == 0 ) { endf_AST = astFactory->create(endf); astFactory->addASTChild(currentAST, antlr::RefAST(endf_AST)); } match(ENDFOR); if ( inputState->guessing==0 ) { endf_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDFOREACH: { endfe = LT(1); if ( inputState->guessing == 0 ) { endfe_AST = astFactory->create(endfe); astFactory->addASTChild(currentAST, antlr::RefAST(endfe_AST)); } match(ENDFOREACH); if ( inputState->guessing==0 ) { endf_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDIF: { endi = LT(1); if ( inputState->guessing == 0 ) { endi_AST = astFactory->create(endi); astFactory->addASTChild(currentAST, antlr::RefAST(endi_AST)); } match(ENDIF); if ( inputState->guessing==0 ) { endi_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDREP: { endr = LT(1); if ( inputState->guessing == 0 ) { endr_AST = astFactory->create(endr); astFactory->addASTChild(currentAST, antlr::RefAST(endr_AST)); } match(ENDREP); if ( inputState->guessing==0 ) { endr_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDSWITCH: { ends = LT(1); if ( inputState->guessing == 0 ) { ends_AST = astFactory->create(ends); astFactory->addASTChild(currentAST, antlr::RefAST(ends_AST)); } match(ENDSWITCH); if ( inputState->guessing==0 ) { ends_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ENDWHILE: { endw = LT(1); if ( inputState->guessing == 0 ) { endw_AST = astFactory->create(endw); astFactory->addASTChild(currentAST, antlr::RefAST(endw_AST)); } match(ENDWHILE); if ( inputState->guessing==0 ) { endw_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case EQ_OP: { eq = LT(1); if ( inputState->guessing == 0 ) { eq_AST = astFactory->create(eq); astFactory->addASTChild(currentAST, antlr::RefAST(eq_AST)); } match(EQ_OP); if ( inputState->guessing==0 ) { eq_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case FOR: { f = LT(1); if ( inputState->guessing == 0 ) { f_AST = astFactory->create(f); astFactory->addASTChild(currentAST, antlr::RefAST(f_AST)); } match(FOR); if ( inputState->guessing==0 ) { f_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case FOREACH: { fe = LT(1); if ( inputState->guessing == 0 ) { fe_AST = astFactory->create(fe); astFactory->addASTChild(currentAST, antlr::RefAST(fe_AST)); } match(FOREACH); if ( inputState->guessing==0 ) { f_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case FORWARD: { fo = LT(1); if ( inputState->guessing == 0 ) { fo_AST = astFactory->create(fo); astFactory->addASTChild(currentAST, antlr::RefAST(fo_AST)); } match(FORWARD); if ( inputState->guessing==0 ) { fo_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case FUNCTION: { fu = LT(1); if ( inputState->guessing == 0 ) { fu_AST = astFactory->create(fu); astFactory->addASTChild(currentAST, antlr::RefAST(fu_AST)); } match(FUNCTION); if ( inputState->guessing==0 ) { fu_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case GE_OP: { g = LT(1); if ( inputState->guessing == 0 ) { g_AST = astFactory->create(g); astFactory->addASTChild(currentAST, antlr::RefAST(g_AST)); } match(GE_OP); if ( inputState->guessing==0 ) { g_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case GOTO: { go = LT(1); if ( inputState->guessing == 0 ) { go_AST = astFactory->create(go); astFactory->addASTChild(currentAST, antlr::RefAST(go_AST)); } match(GOTO); if ( inputState->guessing==0 ) { go_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case GT_OP: { gt = LT(1); if ( inputState->guessing == 0 ) { gt_AST = astFactory->create(gt); astFactory->addASTChild(currentAST, antlr::RefAST(gt_AST)); } match(GT_OP); if ( inputState->guessing==0 ) { gt_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case IF: { i = LT(1); if ( inputState->guessing == 0 ) { i_AST = astFactory->create(i); astFactory->addASTChild(currentAST, antlr::RefAST(i_AST)); } match(IF); if ( inputState->guessing==0 ) { i_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case INHERITS: { in = LT(1); if ( inputState->guessing == 0 ) { in_AST = astFactory->create(in); astFactory->addASTChild(currentAST, antlr::RefAST(in_AST)); } match(INHERITS); if ( inputState->guessing==0 ) { in_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case LE_OP: { l = LT(1); if ( inputState->guessing == 0 ) { l_AST = astFactory->create(l); astFactory->addASTChild(currentAST, antlr::RefAST(l_AST)); } match(LE_OP); if ( inputState->guessing==0 ) { l_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case LT_OP: { lt = LT(1); if ( inputState->guessing == 0 ) { lt_AST = astFactory->create(lt); astFactory->addASTChild(currentAST, antlr::RefAST(lt_AST)); } match(LT_OP); if ( inputState->guessing==0 ) { lt_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case MOD_OP: { m = LT(1); if ( inputState->guessing == 0 ) { m_AST = astFactory->create(m); astFactory->addASTChild(currentAST, antlr::RefAST(m_AST)); } match(MOD_OP); if ( inputState->guessing==0 ) { m_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case NE_OP: { n = LT(1); if ( inputState->guessing == 0 ) { n_AST = astFactory->create(n); astFactory->addASTChild(currentAST, antlr::RefAST(n_AST)); } match(NE_OP); if ( inputState->guessing==0 ) { n_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case NOT_OP: { no = LT(1); if ( inputState->guessing == 0 ) { no_AST = astFactory->create(no); astFactory->addASTChild(currentAST, antlr::RefAST(no_AST)); } match(NOT_OP); if ( inputState->guessing==0 ) { no_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case OF: { o = LT(1); if ( inputState->guessing == 0 ) { o_AST = astFactory->create(o); astFactory->addASTChild(currentAST, antlr::RefAST(o_AST)); } match(OF); if ( inputState->guessing==0 ) { o_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case ON_IOERROR: { on = LT(1); if ( inputState->guessing == 0 ) { on_AST = astFactory->create(on); astFactory->addASTChild(currentAST, antlr::RefAST(on_AST)); } match(ON_IOERROR); if ( inputState->guessing==0 ) { on_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case OR_OP: { o_ = LT(1); if ( inputState->guessing == 0 ) { o__AST = astFactory->create(o_); astFactory->addASTChild(currentAST, antlr::RefAST(o__AST)); } match(OR_OP); if ( inputState->guessing==0 ) { o__AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case PRO: { p = LT(1); if ( inputState->guessing == 0 ) { p_AST = astFactory->create(p); astFactory->addASTChild(currentAST, antlr::RefAST(p_AST)); } match(PRO); if ( inputState->guessing==0 ) { p_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case REPEAT: { r = LT(1); if ( inputState->guessing == 0 ) { r_AST = astFactory->create(r); astFactory->addASTChild(currentAST, antlr::RefAST(r_AST)); } match(REPEAT); if ( inputState->guessing==0 ) { r_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case SWITCH: { s = LT(1); if ( inputState->guessing == 0 ) { s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); } match(SWITCH); if ( inputState->guessing==0 ) { s_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case THEN: { t = LT(1); if ( inputState->guessing == 0 ) { t_AST = astFactory->create(t); astFactory->addASTChild(currentAST, antlr::RefAST(t_AST)); } match(THEN); if ( inputState->guessing==0 ) { t_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case UNTIL: { u = LT(1); if ( inputState->guessing == 0 ) { u_AST = astFactory->create(u); astFactory->addASTChild(currentAST, antlr::RefAST(u_AST)); } match(UNTIL); if ( inputState->guessing==0 ) { u_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case WHILE: { w = LT(1); if ( inputState->guessing == 0 ) { w_AST = astFactory->create(w); astFactory->addASTChild(currentAST, antlr::RefAST(w_AST)); } match(WHILE); if ( inputState->guessing==0 ) { w_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } case XOR_OP: { x = LT(1); if ( inputState->guessing == 0 ) { x_AST = astFactory->create(x); astFactory->addASTChild(currentAST, antlr::RefAST(x_AST)); } match(XOR_OP); if ( inputState->guessing==0 ) { x_AST->setType( IDENTIFIER); } identifier_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = identifier_AST; } void GDLParser::translation_unit() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode translation_unit_AST = RefDNode(antlr::nullAST); subReached=false; compileOpt=NONE; // reset compileOpt try { // for error handling { // ( ... )* for (;;) { switch ( LA(1)) { case PRO: { procedure_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { compileOpt=NONE; // reset compileOpt if( subReached) goto bailOut; } break; } case FUNCTION: { function_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { compileOpt=NONE; // reset compileOpt if( subReached) goto bailOut; } break; } default: if ((LA(1) == END_U) && (_tokenSet_0.member(LA(2)))) { end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((LA(1) == FORWARD) && (LA(2) == IDENTIFIER)) { forward_function(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((LA(1) == COMMON) && (LA(2) == IDENTIFIER)) { common_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop4; } } } _loop4:; } // ( ... )* { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case END_U: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(END); { switch ( LA(1)) { case END_U: { end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case antlr::Token::EOF_TYPE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } break; } case antlr::Token::EOF_TYPE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { match(antlr::Token::EOF_TYPE); } if ( inputState->guessing==0 ) { bailOut:; } translation_unit_AST = RefDNode(currentAST.root); } catch ( GDLException& e) { if (inputState->guessing==0) { throw; } else { throw; } } catch ( antlr::NoViableAltException& e) { if (inputState->guessing==0) { // PARSER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Parser syntax error: "+e.getMessage()); } else { throw; } } catch ( antlr::NoViableAltForCharException& e) { if (inputState->guessing==0) { // LEXER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer syntax error: "+e.getMessage()); } else { throw; } } catch ( antlr::RecognitionException& e) { if (inputState->guessing==0) { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer/Parser syntax error: "+e.getMessage()); } else { throw; } } catch ( antlr::TokenStreamIOException& e) { if (inputState->guessing==0) { // IO ERROR throw GDLException( returnAST, "Input/Output error: "+e.getMessage()); } else { throw; } } catch ( antlr::TokenStreamException& e) { if (inputState->guessing==0) { throw GDLException( returnAST, "Token stream error: "+e.getMessage()); } else { throw; } } returnAST = translation_unit_AST; } void GDLParser::end_unit() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode end_unit_AST = RefDNode(antlr::nullAST); { // ( ... )+ int _cnt35=0; for (;;) { if ((LA(1) == END_U) && (_tokenSet_1.member(LA(2)))) { RefDNode tmp4_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp4_AST = astFactory->create(LT(1)); } match(END_U); } else { if ( _cnt35>=1 ) { goto _loop35; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } _cnt35++; } _loop35:; } // ( ... )+ returnAST = end_unit_AST; } void GDLParser::forward_function() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode forward_function_AST = RefDNode(antlr::nullAST); RefDNode tmp5_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp5_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp5_AST)); } match(FORWARD); identifier_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } forward_function_AST = RefDNode(currentAST.root); returnAST = forward_function_AST; } void GDLParser::procedure_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode procedure_def_AST = RefDNode(antlr::nullAST); antlr::RefToken p = antlr::nullToken; RefDNode p_AST = RefDNode(antlr::nullAST); antlr::RefToken n = antlr::nullToken; RefDNode n_AST = RefDNode(antlr::nullAST); std::string name; p = LT(1); if ( inputState->guessing == 0 ) { p_AST = astFactory->create(p); astFactory->makeASTRoot(currentAST, antlr::RefAST(p_AST)); } match(PRO); { if ((LA(1) == IDENTIFIER) && (LA(2) == COMMA || LA(2) == END_U)) { n = LT(1); if ( inputState->guessing == 0 ) { n_AST = astFactory->create(n); astFactory->addASTChild(currentAST, antlr::RefAST(n_AST)); } match(IDENTIFIER); if ( inputState->guessing==0 ) { name=n->getText(); } } else if ((LA(1) == IDENTIFIER) && (LA(2) == METHOD)) { name=object_name(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } { switch ( LA(1)) { case COMMA: { match(COMMA); parameter_declaration(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case END_U: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } match(END); if ( inputState->guessing==0 ) { if( subName == name && searchForPro == true) subReached=true; p_AST->SetCompileOpt( compileOpt); } procedure_def_AST = RefDNode(currentAST.root); returnAST = procedure_def_AST; } void GDLParser::function_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode function_def_AST = RefDNode(antlr::nullAST); antlr::RefToken f = antlr::nullToken; RefDNode f_AST = RefDNode(antlr::nullAST); antlr::RefToken n = antlr::nullToken; RefDNode n_AST = RefDNode(antlr::nullAST); std::string name; f = LT(1); if ( inputState->guessing == 0 ) { f_AST = astFactory->create(f); astFactory->makeASTRoot(currentAST, antlr::RefAST(f_AST)); } match(FUNCTION); { if ((LA(1) == IDENTIFIER) && (LA(2) == COMMA || LA(2) == END_U)) { n = LT(1); if ( inputState->guessing == 0 ) { n_AST = astFactory->create(n); astFactory->addASTChild(currentAST, antlr::RefAST(n_AST)); } match(IDENTIFIER); if ( inputState->guessing==0 ) { name=n->getText(); } } else if ((LA(1) == IDENTIFIER) && (LA(2) == METHOD)) { name=object_name(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } { switch ( LA(1)) { case COMMA: { match(COMMA); parameter_declaration(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case END_U: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } match(END); if ( inputState->guessing==0 ) { if( subName == name && searchForPro == false) subReached=true; f_AST->SetCompileOpt( compileOpt); } function_def_AST = RefDNode(currentAST.root); returnAST = function_def_AST; } void GDLParser::common_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode common_block_AST = RefDNode(antlr::nullAST); match(COMMON); RefDNode tmp11_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp11_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp11_AST)); } match(IDENTIFIER); { switch ( LA(1)) { case antlr::Token::EOF_TYPE: case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case ELSE: case FORWARD: case FUNCTION: case GOTO: case IF: case INHERITS: case ON_IOERROR: case PRO: case SWITCH: case UNTIL: case END_U: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { if ( inputState->guessing==0 ) { common_block_AST = RefDNode(currentAST.root); common_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(COMMONDECL,"commondecl")))->add(antlr::RefAST(common_block_AST)))); currentAST.root = common_block_AST; if ( common_block_AST!=RefDNode(antlr::nullAST) && common_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = common_block_AST->getFirstChild(); else currentAST.child = common_block_AST; currentAST.advanceChildToEnd(); } break; } case COMMA: { match(COMMA); identifier_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { common_block_AST = RefDNode(currentAST.root); common_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(COMMONDEF,"commondef")))->add(antlr::RefAST(common_block_AST)))); currentAST.root = common_block_AST; if ( common_block_AST!=RefDNode(antlr::nullAST) && common_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = common_block_AST->getFirstChild(); else currentAST.child = common_block_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } common_block_AST = RefDNode(currentAST.root); returnAST = common_block_AST; } void GDLParser::statement_list() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode statement_list_AST = RefDNode(antlr::nullAST); { // ( ... )+ int _cnt73=0; for (;;) { if ((LA(1) == END_U)) { end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_3.member(LA(2)))) { compound_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((LA(1) == IDENTIFIER) && (LA(2) == COLON)) { label_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { if ( _cnt73>=1 ) { goto _loop73; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } _cnt73++; } _loop73:; } // ( ... )+ statement_list_AST = RefDNode(currentAST.root); returnAST = statement_list_AST; } void GDLParser::interactive_compile() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode interactive_compile_AST = RefDNode(antlr::nullAST); { switch ( LA(1)) { case FUNCTION: { RefDNode tmp13_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp13_AST = astFactory->create(LT(1)); } match(FUNCTION); break; } case PRO: { RefDNode tmp14_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp14_AST = astFactory->create(LT(1)); } match(PRO); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } RefDNode tmp15_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp15_AST = astFactory->create(LT(1)); } match(IDENTIFIER); if ( inputState->guessing==0 ) { throw GDLException( "Programs can't be compiled from " "single statement mode."); } { switch ( LA(1)) { case METHOD: { RefDNode tmp16_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp16_AST = astFactory->create(LT(1)); } match(METHOD); RefDNode tmp17_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp17_AST = astFactory->create(LT(1)); } match(IDENTIFIER); break; } case COMMA: case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { switch ( LA(1)) { case COMMA: { RefDNode tmp18_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp18_AST = astFactory->create(LT(1)); } match(COMMA); parameter_declaration(); break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); returnAST = interactive_compile_AST; } void GDLParser::parameter_declaration() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode parameter_declaration_AST = RefDNode(antlr::nullAST); { if ((LA(1) == IDENTIFIER) && (LA(2) == COMMA || LA(2) == END_U)) { RefDNode tmp19_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp19_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp19_AST)); } match(IDENTIFIER); } else if ((LA(1) == IDENTIFIER) && (LA(2) == EQUAL)) { keyword_declaration(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); { if ((LA(1) == IDENTIFIER) && (LA(2) == COMMA || LA(2) == END_U)) { RefDNode tmp21_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp21_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp21_AST)); } match(IDENTIFIER); } else if ((LA(1) == IDENTIFIER) && (LA(2) == EQUAL)) { keyword_declaration(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } } else { goto _loop41; } } _loop41:; } // ( ... )* if ( inputState->guessing==0 ) { parameter_declaration_AST = RefDNode(currentAST.root); parameter_declaration_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(PARADECL,"paradecl")))->add(antlr::RefAST(parameter_declaration_AST)))); currentAST.root = parameter_declaration_AST; if ( parameter_declaration_AST!=RefDNode(antlr::nullAST) && parameter_declaration_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = parameter_declaration_AST->getFirstChild(); else currentAST.child = parameter_declaration_AST; currentAST.advanceChildToEnd(); } parameter_declaration_AST = RefDNode(currentAST.root); returnAST = parameter_declaration_AST; } void GDLParser::interactive() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode interactive_AST = RefDNode(antlr::nullAST); try { // for error handling { // ( ... )+ int _cnt15=0; for (;;) { switch ( LA(1)) { case END_U: { end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case END: case ENDCASE: case ENDELSE: case ENDFOR: case ENDFOREACH: case ENDIF: case ENDREP: case ENDSWITCH: case ENDWHILE: { end_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case antlr::Token::EOF_TYPE: case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case FUNCTION: case GOTO: case IF: case INHERITS: case ON_IOERROR: case PRO: case SWITCH: case END_U: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } break; } case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { interactive_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case FUNCTION: case PRO: { interactive_compile(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } default: { if ( _cnt15>=1 ) { goto _loop15; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } } _cnt15++; } _loop15:; } // ( ... )+ interactive_AST = RefDNode(currentAST.root); } catch ( GDLException& e) { if (inputState->guessing==0) { throw; } else { throw; } } catch ( antlr::NoViableAltException& e) { if (inputState->guessing==0) { // PARSER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Parser syntax error: "+ e.getMessage()); } else { throw; } } catch ( antlr::NoViableAltForCharException& e) { if (inputState->guessing==0) { // LEXER SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer syntax error: "+ e.getMessage()); } else { throw; } } catch ( antlr::RecognitionException& e) { if (inputState->guessing==0) { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Lexer/Parser syntax error: "+e.getMessage()); } else { throw; } } catch ( antlr::TokenStreamIOException& e) { if (inputState->guessing==0) { // IO ERROR throw GDLException( returnAST, "Input/Output error: "+e.getMessage()); } else { throw; } } catch ( antlr::TokenStreamException& e) { if (inputState->guessing==0) { throw GDLException( returnAST, "Token stream error: "+e.getMessage()); } else { throw; } } returnAST = interactive_AST; } void GDLParser::end_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode end_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case END: { RefDNode tmp22_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp22_AST = astFactory->create(LT(1)); } match(END); break; } case ENDIF: { RefDNode tmp23_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp23_AST = astFactory->create(LT(1)); } match(ENDIF); break; } case ENDELSE: { RefDNode tmp24_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp24_AST = astFactory->create(LT(1)); } match(ENDELSE); break; } case ENDCASE: { RefDNode tmp25_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp25_AST = astFactory->create(LT(1)); } match(ENDCASE); break; } case ENDSWITCH: { RefDNode tmp26_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp26_AST = astFactory->create(LT(1)); } match(ENDSWITCH); break; } case ENDFOR: { RefDNode tmp27_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp27_AST = astFactory->create(LT(1)); } match(ENDFOR); break; } case ENDFOREACH: { RefDNode tmp28_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp28_AST = astFactory->create(LT(1)); } match(ENDFOREACH); break; } case ENDWHILE: { RefDNode tmp29_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp29_AST = astFactory->create(LT(1)); } match(ENDWHILE); break; } case ENDREP: { RefDNode tmp30_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp30_AST = astFactory->create(LT(1)); } match(ENDREP); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = end_mark_AST; } void GDLParser::interactive_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode interactive_statement_AST = RefDNode(antlr::nullAST); { // ( ... )* for (;;) { if ((LA(1) == BEGIN)) { match(BEGIN); } else if ((LA(1) == IDENTIFIER) && (LA(2) == COLON)) { match(IDENTIFIER); match(COLON); } else { goto _loop18; } } _loop18:; } // ( ... )* statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } interactive_statement_AST = RefDNode(currentAST.root); returnAST = interactive_statement_AST; } void GDLParser::statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode statement_AST = RefDNode(antlr::nullAST); RefDNode d1_AST = RefDNode(antlr::nullAST); RefDNode d2_AST = RefDNode(antlr::nullAST); RefDNode d3_AST = RefDNode(antlr::nullAST); bool parent=false; switch ( LA(1)) { case DEC: case INC: { { switch ( LA(1)) { case DEC: { RefDNode tmp34_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp34_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp34_AST)); } match(DEC); break; } case INC: { RefDNode tmp35_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp35_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp35_AST)); } match(INC); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case FOR: { for_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case FOREACH: { foreach_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case REPEAT: { repeat_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case WHILE: { while_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case GOTO: case ON_IOERROR: { jump_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case IF: { if_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case CASE: { case_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case SWITCH: { switch_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case FORWARD: { forward_function(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case COMMON: { common_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } case COMPILE_OPT: { compile_opt(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); break; } default: bool synPredMatched83 = false; if (((LA(1) == LBRACE) && (_tokenSet_4.member(LA(2))))) { int _m83 = mark(); synPredMatched83 = true; inputState->guessing++; try { { assign_expr(); } } catch (antlr::RecognitionException& pe) { synPredMatched83 = false; } rewind(_m83); inputState->guessing--; } if ( synPredMatched83 ) { assign_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case DEC: { RefDNode tmp36_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp36_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp36_AST)); } match(DEC); break; } case INC: { RefDNode tmp37_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp37_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp37_AST)); } match(INC); break; } case ELSE: case UNTIL: case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } statement_AST = RefDNode(currentAST.root); } else { bool synPredMatched86 = false; if (((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))))) { int _m86 = mark(); synPredMatched86 = true; inputState->guessing++; try { { deref_dot_expr_keeplast(); match(IDENTIFIER); match(COMMA); } } catch (antlr::RecognitionException& pe) { synPredMatched86 = false; } rewind(_m86); inputState->guessing--; } if ( synPredMatched86 ) { deref_dot_expr_keeplast(); if (inputState->guessing==0) { d1_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } formal_procedure_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { statement_AST = RefDNode(currentAST.root); statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MPCALL,"mpcall")))->add(antlr::RefAST(statement_AST)))); statement_AST->SetLine( d1_AST->getLine()); currentAST.root = statement_AST; if ( statement_AST!=RefDNode(antlr::nullAST) && statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = statement_AST->getFirstChild(); else currentAST.child = statement_AST; currentAST.advanceChildToEnd(); } statement_AST = RefDNode(currentAST.root); } else { bool synPredMatched88 = false; if (((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))))) { int _m88 = mark(); synPredMatched88 = true; inputState->guessing++; try { { deref_dot_expr_keeplast(); baseclass_method(); } } catch (antlr::RecognitionException& pe) { synPredMatched88 = false; } rewind(_m88); inputState->guessing--; } if ( synPredMatched88 ) { deref_dot_expr_keeplast(); if (inputState->guessing==0) { d2_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } baseclass_method(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } formal_procedure_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { statement_AST = RefDNode(currentAST.root); statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MPCALL_PARENT,"mpcall::")))->add(antlr::RefAST(statement_AST)))); statement_AST->SetLine( d2_AST->getLine()); currentAST.root = statement_AST; if ( statement_AST!=RefDNode(antlr::nullAST) && statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = statement_AST->getFirstChild(); else currentAST.child = statement_AST; currentAST.advanceChildToEnd(); } statement_AST = RefDNode(currentAST.root); } else { bool synPredMatched91 = false; if (((_tokenSet_4.member(LA(1))) && (_tokenSet_6.member(LA(2))))) { int _m91 = mark(); synPredMatched91 = true; inputState->guessing++; try { { deref_expr(); { switch ( LA(1)) { case EQUAL: { match(EQUAL); break; } case AND_OP_EQ: { match(AND_OP_EQ); break; } case ASTERIX_EQ: { match(ASTERIX_EQ); break; } case EQ_OP_EQ: { match(EQ_OP_EQ); break; } case GE_OP_EQ: { match(GE_OP_EQ); break; } case GTMARK_EQ: { match(GTMARK_EQ); break; } case GT_OP_EQ: { match(GT_OP_EQ); break; } case LE_OP_EQ: { match(LE_OP_EQ); break; } case LTMARK_EQ: { match(LTMARK_EQ); break; } case LT_OP_EQ: { match(LT_OP_EQ); break; } case MATRIX_OP1_EQ: { match(MATRIX_OP1_EQ); break; } case MATRIX_OP2_EQ: { match(MATRIX_OP2_EQ); break; } case MINUS_EQ: { match(MINUS_EQ); break; } case MOD_OP_EQ: { match(MOD_OP_EQ); break; } case NE_OP_EQ: { match(NE_OP_EQ); break; } case OR_OP_EQ: { match(OR_OP_EQ); break; } case PLUS_EQ: { match(PLUS_EQ); break; } case POW_EQ: { match(POW_EQ); break; } case SLASH_EQ: { match(SLASH_EQ); break; } case XOR_OP_EQ: { match(XOR_OP_EQ); break; } case DEC: { match(DEC); break; } case INC: { match(INC); break; } case MEMBER: { match(MEMBER); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } } catch (antlr::RecognitionException& pe) { synPredMatched91 = false; } rewind(_m91); inputState->guessing--; } if ( synPredMatched91 ) { deref_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case EQUAL: { match(EQUAL); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { statement_AST = RefDNode(currentAST.root); statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(statement_AST)))); currentAST.root = statement_AST; if ( statement_AST!=RefDNode(antlr::nullAST) && statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = statement_AST->getFirstChild(); else currentAST.child = statement_AST; currentAST.advanceChildToEnd(); } break; } case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { { switch ( LA(1)) { case AND_OP_EQ: { RefDNode tmp39_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp39_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp39_AST)); } match(AND_OP_EQ); break; } case ASTERIX_EQ: { RefDNode tmp40_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp40_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp40_AST)); } match(ASTERIX_EQ); break; } case EQ_OP_EQ: { RefDNode tmp41_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp41_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp41_AST)); } match(EQ_OP_EQ); break; } case GE_OP_EQ: { RefDNode tmp42_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp42_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp42_AST)); } match(GE_OP_EQ); break; } case GTMARK_EQ: { RefDNode tmp43_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp43_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp43_AST)); } match(GTMARK_EQ); break; } case GT_OP_EQ: { RefDNode tmp44_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp44_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp44_AST)); } match(GT_OP_EQ); break; } case LE_OP_EQ: { RefDNode tmp45_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp45_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp45_AST)); } match(LE_OP_EQ); break; } case LTMARK_EQ: { RefDNode tmp46_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp46_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp46_AST)); } match(LTMARK_EQ); break; } case LT_OP_EQ: { RefDNode tmp47_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp47_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp47_AST)); } match(LT_OP_EQ); break; } case MATRIX_OP1_EQ: { RefDNode tmp48_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp48_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp48_AST)); } match(MATRIX_OP1_EQ); break; } case MATRIX_OP2_EQ: { RefDNode tmp49_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp49_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp49_AST)); } match(MATRIX_OP2_EQ); break; } case MINUS_EQ: { RefDNode tmp50_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp50_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp50_AST)); } match(MINUS_EQ); break; } case MOD_OP_EQ: { RefDNode tmp51_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp51_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp51_AST)); } match(MOD_OP_EQ); break; } case NE_OP_EQ: { RefDNode tmp52_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp52_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp52_AST)); } match(NE_OP_EQ); break; } case OR_OP_EQ: { RefDNode tmp53_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp53_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp53_AST)); } match(OR_OP_EQ); break; } case PLUS_EQ: { RefDNode tmp54_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp54_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp54_AST)); } match(PLUS_EQ); break; } case POW_EQ: { RefDNode tmp55_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp55_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp55_AST)); } match(POW_EQ); break; } case SLASH_EQ: { RefDNode tmp56_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp56_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp56_AST)); } match(SLASH_EQ); break; } case XOR_OP_EQ: { RefDNode tmp57_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp57_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp57_AST)); } match(XOR_OP_EQ); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case DEC: case INC: { { switch ( LA(1)) { case DEC: { RefDNode tmp58_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp58_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp58_AST)); } match(DEC); break; } case INC: { RefDNode tmp59_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp59_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp59_AST)); } match(INC); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } break; } case MEMBER: { match(MEMBER); { if ((LA(1) == IDENTIFIER) && (LA(2) == METHOD)) { baseclass_method(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { parent=true; } } else if ((LA(1) == IDENTIFIER) && (_tokenSet_7.member(LA(2)))) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } formal_procedure_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { statement_AST = RefDNode(currentAST.root); if( parent) statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MPCALL_PARENT,"mpcall::")))->add(antlr::RefAST(statement_AST)))); else statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MPCALL,"mpcall")))->add(antlr::RefAST(statement_AST)))); currentAST.root = statement_AST; if ( statement_AST!=RefDNode(antlr::nullAST) && statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = statement_AST->getFirstChild(); else currentAST.child = statement_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } statement_AST = RefDNode(currentAST.root); } else if ((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2)))) { deref_dot_expr_keeplast(); if (inputState->guessing==0) { d3_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } formal_procedure_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { statement_AST = RefDNode(currentAST.root); statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MPCALL,"mpcall")))->add(antlr::RefAST(statement_AST)))); statement_AST->SetLine( d3_AST->getLine()); currentAST.root = statement_AST; if ( statement_AST!=RefDNode(antlr::nullAST) && statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = statement_AST->getFirstChild(); else currentAST.child = statement_AST; currentAST.advanceChildToEnd(); } statement_AST = RefDNode(currentAST.root); } else if ((LA(1) == IDENTIFIER) && (_tokenSet_7.member(LA(2)))) { procedure_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } statement_AST = RefDNode(currentAST.root); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } }}}} returnAST = statement_AST; } void GDLParser::switch_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode switch_statement_AST = RefDNode(antlr::nullAST); int numBranch=0; RefDNode tmp61_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp61_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp61_AST)); } match(SWITCH); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(OF); { switch ( LA(1)) { case END_U: { end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case IDENTIFIER: case ELSE: case END: case ENDSWITCH: case INHERITS: case NOT_OP: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: case PLUS: case MINUS: case LOG_NEG: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { // ( ... )* for (;;) { if ((_tokenSet_8.member(LA(1)))) { switch_body(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { numBranch++; } } else { goto _loop22; } } _loop22:; } // ( ... )* endswitch_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { tmp61_AST->SetNumBranch(numBranch); } switch_statement_AST = RefDNode(currentAST.root); returnAST = switch_statement_AST; } void GDLParser::expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode expr_AST = RefDNode(antlr::nullAST); logical_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case QUESTION: { RefDNode tmp63_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp63_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp63_AST)); } match(QUESTION); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(COLON); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case antlr::Token::EOF_TYPE: case DO: case ELSE: case OF: case THEN: case UNTIL: case COMMA: case COLON: case END_U: case RBRACE: case RSQUARE: case RCURLY: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } expr_AST = RefDNode(currentAST.root); returnAST = expr_AST; } void GDLParser::switch_body() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode switch_body_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: case INHERITS: case NOT_OP: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: case PLUS: case MINUS: case LOG_NEG: { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(COLON); { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endswitch_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { switch_body_AST = RefDNode(currentAST.root); switch_body_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(switch_body_AST)))); currentAST.root = switch_body_AST; if ( switch_body_AST!=RefDNode(antlr::nullAST) && switch_body_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = switch_body_AST->getFirstChild(); else currentAST.child = switch_body_AST; currentAST.advanceChildToEnd(); } switch_body_AST = RefDNode(currentAST.root); break; } case ELSE: { match(ELSE); match(COLON); { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endswitchelse_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { switch_body_AST = RefDNode(currentAST.root); switch_body_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ELSEBLK,"elseblk")))->add(antlr::RefAST(switch_body_AST)))); currentAST.root = switch_body_AST; if ( switch_body_AST!=RefDNode(antlr::nullAST) && switch_body_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = switch_body_AST->getFirstChild(); else currentAST.child = switch_body_AST; currentAST.advanceChildToEnd(); } switch_body_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = switch_body_AST; } void GDLParser::endswitch_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endswitch_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDSWITCH: { RefDNode tmp70_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp70_AST = astFactory->create(LT(1)); } match(ENDSWITCH); break; } case END: { RefDNode tmp71_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp71_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endswitch_mark_AST; } void GDLParser::endswitchelse_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endswitchelse_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case END: case ENDSWITCH: { endswitch_mark(); break; } case ENDELSE: { RefDNode tmp72_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp72_AST = astFactory->create(LT(1)); } match(ENDELSE); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endswitchelse_mark_AST; } void GDLParser::case_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode case_statement_AST = RefDNode(antlr::nullAST); int numBranch=0; RefDNode tmp73_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp73_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp73_AST)); } match(CASE); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(OF); { switch ( LA(1)) { case END_U: { end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case IDENTIFIER: case ELSE: case END: case ENDCASE: case INHERITS: case NOT_OP: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: case PLUS: case MINUS: case LOG_NEG: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { // ( ... )* for (;;) { if ((_tokenSet_8.member(LA(1)))) { case_body(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { numBranch++; } } else { goto _loop29; } } _loop29:; } // ( ... )* endcase_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { tmp73_AST->SetNumBranch(numBranch); } case_statement_AST = RefDNode(currentAST.root); returnAST = case_statement_AST; } void GDLParser::case_body() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode case_body_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: case INHERITS: case NOT_OP: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: case PLUS: case MINUS: case LOG_NEG: { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(COLON); { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endcase_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { case_body_AST = RefDNode(currentAST.root); case_body_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(case_body_AST)))); currentAST.root = case_body_AST; if ( case_body_AST!=RefDNode(antlr::nullAST) && case_body_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = case_body_AST->getFirstChild(); else currentAST.child = case_body_AST; currentAST.advanceChildToEnd(); } case_body_AST = RefDNode(currentAST.root); break; } case ELSE: { match(ELSE); match(COLON); { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endcaseelse_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } end_unit(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { case_body_AST = RefDNode(currentAST.root); case_body_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ELSEBLK,"elseblk")))->add(antlr::RefAST(case_body_AST)))); currentAST.root = case_body_AST; if ( case_body_AST!=RefDNode(antlr::nullAST) && case_body_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = case_body_AST->getFirstChild(); else currentAST.child = case_body_AST; currentAST.advanceChildToEnd(); } case_body_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = case_body_AST; } void GDLParser::endcase_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endcase_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDCASE: { RefDNode tmp80_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp80_AST = astFactory->create(LT(1)); } match(ENDCASE); break; } case END: { RefDNode tmp81_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp81_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endcase_mark_AST; } void GDLParser::endcaseelse_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endcaseelse_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case END: case ENDCASE: { endcase_mark(); break; } case ENDELSE: { RefDNode tmp82_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp82_AST = astFactory->create(LT(1)); } match(ENDELSE); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endcaseelse_mark_AST; } void GDLParser::identifier_list() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode identifier_list_AST = RefDNode(antlr::nullAST); RefDNode tmp83_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp83_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp83_AST)); } match(IDENTIFIER); { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); RefDNode tmp85_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp85_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp85_AST)); } match(IDENTIFIER); } else { goto _loop59; } } _loop59:; } // ( ... )* identifier_list_AST = RefDNode(currentAST.root); returnAST = identifier_list_AST; } void GDLParser::keyword_declaration() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode keyword_declaration_AST = RefDNode(antlr::nullAST); RefDNode tmp86_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp86_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp86_AST)); } match(IDENTIFIER); match(EQUAL); RefDNode tmp88_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp88_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp88_AST)); } match(IDENTIFIER); if ( inputState->guessing==0 ) { keyword_declaration_AST = RefDNode(currentAST.root); keyword_declaration_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(KEYDECL,"keydecl")))->add(antlr::RefAST(keyword_declaration_AST)))); currentAST.root = keyword_declaration_AST; if ( keyword_declaration_AST!=RefDNode(antlr::nullAST) && keyword_declaration_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = keyword_declaration_AST->getFirstChild(); else currentAST.child = keyword_declaration_AST; currentAST.advanceChildToEnd(); } keyword_declaration_AST = RefDNode(currentAST.root); returnAST = keyword_declaration_AST; } std::string GDLParser::object_name() { std::string name; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode object_name_AST = RefDNode(antlr::nullAST); antlr::RefToken i1 = antlr::nullToken; RefDNode i1_AST = RefDNode(antlr::nullAST); antlr::RefToken m = antlr::nullToken; RefDNode m_AST = RefDNode(antlr::nullAST); antlr::RefToken i2 = antlr::nullToken; RefDNode i2_AST = RefDNode(antlr::nullAST); i1 = LT(1); if ( inputState->guessing == 0 ) { i1_AST = astFactory->create(i1); } match(IDENTIFIER); m = LT(1); if ( inputState->guessing == 0 ) { m_AST = astFactory->create(m); } match(METHOD); i2 = LT(1); if ( inputState->guessing == 0 ) { i2_AST = astFactory->create(i2); } match(IDENTIFIER); if ( inputState->guessing==0 ) { object_name_AST = RefDNode(currentAST.root); // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( i1_AST->getText() == "IDL_OBJECT") i1_AST->setText(GDL_OBJECT_NAME); else if( i1_AST->getText() == "IDL_CONTAINER") i1_AST->setText(GDL_CONTAINER_NAME); } object_name_AST = RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(NULL))->add(antlr::RefAST(i2_AST))->add(antlr::RefAST(m_AST))->add(antlr::RefAST(i1_AST)))); // NULL -> no root name= std::string( i1->getText()+"__"+i2->getText()); currentAST.root = object_name_AST; if ( object_name_AST!=RefDNode(antlr::nullAST) && object_name_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = object_name_AST->getFirstChild(); else currentAST.child = object_name_AST; currentAST.advanceChildToEnd(); } returnAST = object_name_AST; return name; } void GDLParser::compile_opt() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode compile_opt_AST = RefDNode(antlr::nullAST); antlr::RefToken i = antlr::nullToken; RefDNode i_AST = RefDNode(antlr::nullAST); antlr::RefToken ii = antlr::nullToken; RefDNode ii_AST = RefDNode(antlr::nullAST); RefDNode tmp89_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp89_AST = astFactory->create(LT(1)); } match(COMPILE_OPT); i = LT(1); if ( inputState->guessing == 0 ) { i_AST = astFactory->create(i); } match(IDENTIFIER); if ( inputState->guessing==0 ) { AddCompileOpt( i->getText()); } { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { RefDNode tmp90_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp90_AST = astFactory->create(LT(1)); } match(COMMA); ii = LT(1); if ( inputState->guessing == 0 ) { ii_AST = astFactory->create(ii); } match(IDENTIFIER); if ( inputState->guessing==0 ) { AddCompileOpt( ii->getText()); } } else { goto _loop54; } } _loop54:; } // ( ... )* returnAST = compile_opt_AST; } void GDLParser::endforeach_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endforeach_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDFOREACH: { RefDNode tmp91_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp91_AST = astFactory->create(LT(1)); } match(ENDFOREACH); break; } case END: { RefDNode tmp92_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp92_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endforeach_mark_AST; } void GDLParser::endfor_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endfor_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDFOR: { RefDNode tmp93_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp93_AST = astFactory->create(LT(1)); } match(ENDFOR); break; } case END: { RefDNode tmp94_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp94_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endfor_mark_AST; } void GDLParser::endrep_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endrep_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDREP: { RefDNode tmp95_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp95_AST = astFactory->create(LT(1)); } match(ENDREP); break; } case END: { RefDNode tmp96_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp96_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endrep_mark_AST; } void GDLParser::endwhile_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endwhile_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDWHILE: { RefDNode tmp97_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp97_AST = astFactory->create(LT(1)); } match(ENDWHILE); break; } case END: { RefDNode tmp98_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp98_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endwhile_mark_AST; } void GDLParser::endif_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endif_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDIF: { RefDNode tmp99_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp99_AST = astFactory->create(LT(1)); } match(ENDIF); break; } case END: { RefDNode tmp100_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp100_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endif_mark_AST; } void GDLParser::endelse_mark() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode endelse_mark_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case ENDELSE: { RefDNode tmp101_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp101_AST = astFactory->create(LT(1)); } match(ENDELSE); break; } case END: { RefDNode tmp102_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp102_AST = astFactory->create(LT(1)); } match(END); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = endelse_mark_AST; } void GDLParser::compound_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode compound_statement_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } compound_statement_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } end_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { compound_statement_AST = RefDNode(currentAST.root); compound_statement_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(compound_statement_AST)))); currentAST.root = compound_statement_AST; if ( compound_statement_AST!=RefDNode(antlr::nullAST) && compound_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = compound_statement_AST->getFirstChild(); else currentAST.child = compound_statement_AST; currentAST.advanceChildToEnd(); } compound_statement_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = compound_statement_AST; } void GDLParser::label_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode label_statement_AST = RefDNode(antlr::nullAST); { // ( ... )+ int _cnt77=0; for (;;) { if ((LA(1) == IDENTIFIER) && (LA(2) == COLON)) { label(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { if ( _cnt77>=1 ) { goto _loop77; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } _cnt77++; } _loop77:; } // ( ... )+ { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { compound_statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } label_statement_AST = RefDNode(currentAST.root); returnAST = label_statement_AST; } void GDLParser::label() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode label_AST = RefDNode(antlr::nullAST); RefDNode tmp104_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp104_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp104_AST)); } match(IDENTIFIER); RefDNode tmp105_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp105_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp105_AST)); } match(COLON); label_AST = RefDNode(currentAST.root); returnAST = label_AST; } void GDLParser::baseclass_method() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode baseclass_method_AST = RefDNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefDNode s_AST = RefDNode(antlr::nullAST); s = LT(1); if ( inputState->guessing == 0 ) { s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); } match(IDENTIFIER); match(METHOD); if ( inputState->guessing==0 ) { if( s_AST->getText() == "IDL_OBJECT") s_AST->setText(GDL_OBJECT_NAME); else if( s_AST->getText() == "IDL_CONTAINER") s_AST->setText(GDL_CONTAINER_NAME); } baseclass_method_AST = RefDNode(currentAST.root); returnAST = baseclass_method_AST; } void GDLParser::assign_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode assign_expr_AST = RefDNode(antlr::nullAST); match(LBRACE); deref_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(EQUAL); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(RBRACE); if ( inputState->guessing==0 ) { assign_expr_AST = RefDNode(currentAST.root); assign_expr_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(assign_expr_AST)))); currentAST.root = assign_expr_AST; if ( assign_expr_AST!=RefDNode(antlr::nullAST) && assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = assign_expr_AST->getFirstChild(); else currentAST.child = assign_expr_AST; currentAST.advanceChildToEnd(); } assign_expr_AST = RefDNode(currentAST.root); returnAST = assign_expr_AST; } void GDLParser::deref_dot_expr_keeplast() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode deref_dot_expr_keeplast_AST = RefDNode(antlr::nullAST); RefDNode a1_AST = RefDNode(antlr::nullAST); RefDNode dot; int nDot; switch ( LA(1)) { case IDENTIFIER: case INHERITS: case LBRACE: case SYSVARNAME: { array_expr_1st(); if (inputState->guessing==0) { a1_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { nDot=tag_access_keeplast(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { deref_dot_expr_keeplast_AST = RefDNode(currentAST.root); if( --nDot > 0) { dot=astFactory->create(DOT,"."); dot->SetNDot( nDot); dot->SetLine( a1_AST->getLine()); deref_dot_expr_keeplast_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(dot))->add(antlr::RefAST(deref_dot_expr_keeplast_AST)))); } currentAST.root = deref_dot_expr_keeplast_AST; if ( deref_dot_expr_keeplast_AST!=RefDNode(antlr::nullAST) && deref_dot_expr_keeplast_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_dot_expr_keeplast_AST->getFirstChild(); else currentAST.child = deref_dot_expr_keeplast_AST; currentAST.advanceChildToEnd(); } } deref_dot_expr_keeplast_AST = RefDNode(currentAST.root); break; } case ASTERIX: { match(ASTERIX); deref_dot_expr_keeplast(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { deref_dot_expr_keeplast_AST = RefDNode(currentAST.root); deref_dot_expr_keeplast_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(DEREF,"deref")))->add(antlr::RefAST(deref_dot_expr_keeplast_AST)))); currentAST.root = deref_dot_expr_keeplast_AST; if ( deref_dot_expr_keeplast_AST!=RefDNode(antlr::nullAST) && deref_dot_expr_keeplast_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_dot_expr_keeplast_AST->getFirstChild(); else currentAST.child = deref_dot_expr_keeplast_AST; currentAST.advanceChildToEnd(); } deref_dot_expr_keeplast_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = deref_dot_expr_keeplast_AST; } void GDLParser::formal_procedure_call() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode formal_procedure_call_AST = RefDNode(antlr::nullAST); RefDNode tmp111_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp111_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp111_AST)); } match(IDENTIFIER); { switch ( LA(1)) { case COMMA: { match(COMMA); parameter_def_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case ELSE: case UNTIL: case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } formal_procedure_call_AST = RefDNode(currentAST.root); returnAST = formal_procedure_call_AST; } void GDLParser::deref_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode deref_expr_AST = RefDNode(antlr::nullAST); RefDNode a1_AST = RefDNode(antlr::nullAST); RefDNode dot; SizeT nDot; switch ( LA(1)) { case IDENTIFIER: case INHERITS: case LBRACE: case SYSVARNAME: { array_expr_1st(); if (inputState->guessing==0) { a1_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case DOT: { nDot=tag_access(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { deref_expr_AST = RefDNode(currentAST.root); dot=astFactory->create(DOT,"."); dot->SetNDot( nDot); dot->SetLine( a1_AST->getLine()); deref_expr_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(dot))->add(antlr::RefAST(deref_expr_AST)))); currentAST.root = deref_expr_AST; if ( deref_expr_AST!=RefDNode(antlr::nullAST) && deref_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_expr_AST->getFirstChild(); else currentAST.child = deref_expr_AST; currentAST.advanceChildToEnd(); } break; } case antlr::Token::EOF_TYPE: case AND_OP: case DO: case ELSE: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case OF: case OR_OP: case THEN: case UNTIL: case XOR_OP: case COMMA: case COLON: case END_U: case EQUAL: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case MEMBER: case RBRACE: case SLASH: case RSQUARE: case RCURLY: case ASTERIX: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_AND: case LOG_OR: case QUESTION: { if ( inputState->guessing==0 ) { deref_expr_AST = RefDNode(currentAST.root); deref_expr_AST = a1_AST; currentAST.root = deref_expr_AST; if ( deref_expr_AST!=RefDNode(antlr::nullAST) && deref_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_expr_AST->getFirstChild(); else currentAST.child = deref_expr_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } deref_expr_AST = RefDNode(currentAST.root); break; } case ASTERIX: { match(ASTERIX); deref_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { deref_expr_AST = RefDNode(currentAST.root); deref_expr_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(DEREF,"deref")))->add(antlr::RefAST(deref_expr_AST)))); currentAST.root = deref_expr_AST; if ( deref_expr_AST!=RefDNode(antlr::nullAST) && deref_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_expr_AST->getFirstChild(); else currentAST.child = deref_expr_AST; currentAST.advanceChildToEnd(); } deref_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = deref_expr_AST; } void GDLParser::procedure_call() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode procedure_call_AST = RefDNode(antlr::nullAST); antlr::RefToken id = antlr::nullToken; RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode pa_AST = RefDNode(antlr::nullAST); id = LT(1); if ( inputState->guessing == 0 ) { id_AST = astFactory->create(id); } match(IDENTIFIER); { if (((_tokenSet_7.member(LA(1))) && (_tokenSet_1.member(LA(2))))&&(id->getText() == "RETURN")) { { switch ( LA(1)) { case COMMA: { match(COMMA); expr(); if (inputState->guessing==0) { e_AST = returnAST; } break; } case ELSE: case UNTIL: case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } if ( inputState->guessing==0 ) { procedure_call_AST = RefDNode(currentAST.root); id_AST->setType(RETURN); // text is already "return" procedure_call_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(e_AST)))); // make root currentAST.root = procedure_call_AST; if ( procedure_call_AST!=RefDNode(antlr::nullAST) && procedure_call_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = procedure_call_AST->getFirstChild(); else currentAST.child = procedure_call_AST; currentAST.advanceChildToEnd(); } } else if (((LA(1) == ELSE || LA(1) == UNTIL || LA(1) == END_U) && (_tokenSet_1.member(LA(2))))&&(id->getText() == "BREAK")) { if ( inputState->guessing==0 ) { procedure_call_AST = RefDNode(currentAST.root); id_AST->setType(BREAK); // text is already "break" procedure_call_AST = id_AST; currentAST.root = procedure_call_AST; if ( procedure_call_AST!=RefDNode(antlr::nullAST) && procedure_call_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = procedure_call_AST->getFirstChild(); else currentAST.child = procedure_call_AST; currentAST.advanceChildToEnd(); } } else if (((LA(1) == ELSE || LA(1) == UNTIL || LA(1) == END_U) && (_tokenSet_1.member(LA(2))))&&(id->getText() == "CONTINUE")) { if ( inputState->guessing==0 ) { procedure_call_AST = RefDNode(currentAST.root); id_AST->setType(CONTINUE); // text is already "continue" procedure_call_AST = id_AST; currentAST.root = procedure_call_AST; if ( procedure_call_AST!=RefDNode(antlr::nullAST) && procedure_call_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = procedure_call_AST->getFirstChild(); else currentAST.child = procedure_call_AST; currentAST.advanceChildToEnd(); } } else if ((_tokenSet_7.member(LA(1))) && (_tokenSet_9.member(LA(2)))) { { switch ( LA(1)) { case COMMA: { match(COMMA); parameter_def_list(); if (inputState->guessing==0) { pa_AST = returnAST; } break; } case ELSE: case UNTIL: case END_U: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } if ( inputState->guessing==0 ) { procedure_call_AST = RefDNode(currentAST.root); procedure_call_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(PCALL,"pcall")))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(pa_AST)))); procedure_call_AST->SetLine(id->getLine()); currentAST.root = procedure_call_AST; if ( procedure_call_AST!=RefDNode(antlr::nullAST) && procedure_call_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = procedure_call_AST->getFirstChild(); else currentAST.child = procedure_call_AST; currentAST.advanceChildToEnd(); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = procedure_call_AST; } void GDLParser::for_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode for_statement_AST = RefDNode(antlr::nullAST); RefDNode tmp116_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp116_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp116_AST)); } match(FOR); RefDNode tmp117_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp117_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp117_AST)); } match(IDENTIFIER); match(EQUAL); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(COMMA); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case COMMA: { match(COMMA); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case DO: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } match(DO); for_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } for_statement_AST = RefDNode(currentAST.root); returnAST = for_statement_AST; } void GDLParser::foreach_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode foreach_statement_AST = RefDNode(antlr::nullAST); RefDNode tmp122_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp122_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp122_AST)); } match(FOREACH); RefDNode tmp123_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp123_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp123_AST)); } match(IDENTIFIER); match(COMMA); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case COMMA: { match(COMMA); RefDNode tmp126_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp126_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp126_AST)); } match(IDENTIFIER); break; } case DO: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } match(DO); foreach_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } foreach_statement_AST = RefDNode(currentAST.root); returnAST = foreach_statement_AST; } void GDLParser::repeat_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode repeat_statement_AST = RefDNode(antlr::nullAST); RefDNode tmp128_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp128_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp128_AST)); } match(REPEAT); repeat_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(UNTIL); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } repeat_statement_AST = RefDNode(currentAST.root); returnAST = repeat_statement_AST; } void GDLParser::while_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode while_statement_AST = RefDNode(antlr::nullAST); RefDNode tmp130_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp130_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp130_AST)); } match(WHILE); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(DO); while_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } while_statement_AST = RefDNode(currentAST.root); returnAST = while_statement_AST; } void GDLParser::jump_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode jump_statement_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case GOTO: { RefDNode tmp132_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp132_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp132_AST)); } match(GOTO); match(COMMA); RefDNode tmp134_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp134_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp134_AST)); } match(IDENTIFIER); jump_statement_AST = RefDNode(currentAST.root); break; } case ON_IOERROR: { RefDNode tmp135_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp135_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp135_AST)); } match(ON_IOERROR); match(COMMA); RefDNode tmp137_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp137_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp137_AST)); } match(IDENTIFIER); jump_statement_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = jump_statement_AST; } void GDLParser::if_statement() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode if_statement_AST = RefDNode(antlr::nullAST); RefDNode tmp138_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp138_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp138_AST)); } match(IF); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(THEN); if_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { if ((LA(1) == ELSE) && (_tokenSet_2.member(LA(2)))) { match(ELSE); else_block(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((LA(1) == ELSE || LA(1) == UNTIL || LA(1) == END_U) && (_tokenSet_1.member(LA(2)))) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } if_statement_AST = RefDNode(currentAST.root); returnAST = if_statement_AST; } void GDLParser::repeat_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode repeat_block_AST = RefDNode(antlr::nullAST); RefDNode st_AST = RefDNode(antlr::nullAST); RefDNode stl_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { st_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { repeat_block_AST = RefDNode(currentAST.root); repeat_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(st_AST)))); currentAST.root = repeat_block_AST; if ( repeat_block_AST!=RefDNode(antlr::nullAST) && repeat_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = repeat_block_AST->getFirstChild(); else currentAST.child = repeat_block_AST; currentAST.advanceChildToEnd(); } repeat_block_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { stl_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endrep_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { repeat_block_AST = RefDNode(currentAST.root); repeat_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(stl_AST)))); currentAST.root = repeat_block_AST; if ( repeat_block_AST!=RefDNode(antlr::nullAST) && repeat_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = repeat_block_AST->getFirstChild(); else currentAST.child = repeat_block_AST; currentAST.advanceChildToEnd(); } repeat_block_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = repeat_block_AST; } void GDLParser::while_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode while_block_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } while_block_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endwhile_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { while_block_AST = RefDNode(currentAST.root); while_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(while_block_AST)))); currentAST.root = while_block_AST; if ( while_block_AST!=RefDNode(antlr::nullAST) && while_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = while_block_AST->getFirstChild(); else currentAST.child = while_block_AST; currentAST.advanceChildToEnd(); } while_block_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = while_block_AST; } void GDLParser::for_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode for_block_AST = RefDNode(antlr::nullAST); RefDNode st_AST = RefDNode(antlr::nullAST); RefDNode stl_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { st_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { for_block_AST = RefDNode(currentAST.root); for_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(st_AST)))); currentAST.root = for_block_AST; if ( for_block_AST!=RefDNode(antlr::nullAST) && for_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = for_block_AST->getFirstChild(); else currentAST.child = for_block_AST; currentAST.advanceChildToEnd(); } for_block_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { stl_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endfor_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { for_block_AST = RefDNode(currentAST.root); for_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(stl_AST)))); currentAST.root = for_block_AST; if ( for_block_AST!=RefDNode(antlr::nullAST) && for_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = for_block_AST->getFirstChild(); else currentAST.child = for_block_AST; currentAST.advanceChildToEnd(); } for_block_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = for_block_AST; } void GDLParser::foreach_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode foreach_block_AST = RefDNode(antlr::nullAST); RefDNode st_AST = RefDNode(antlr::nullAST); RefDNode stl_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { st_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { foreach_block_AST = RefDNode(currentAST.root); foreach_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(st_AST)))); currentAST.root = foreach_block_AST; if ( foreach_block_AST!=RefDNode(antlr::nullAST) && foreach_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = foreach_block_AST->getFirstChild(); else currentAST.child = foreach_block_AST; currentAST.advanceChildToEnd(); } foreach_block_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { stl_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endforeach_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { foreach_block_AST = RefDNode(currentAST.root); foreach_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(stl_AST)))); currentAST.root = foreach_block_AST; if ( foreach_block_AST!=RefDNode(antlr::nullAST) && foreach_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = foreach_block_AST->getFirstChild(); else currentAST.child = foreach_block_AST; currentAST.advanceChildToEnd(); } foreach_block_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = foreach_block_AST; } void GDLParser::if_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode if_block_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if_block_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endif_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { if_block_AST = RefDNode(currentAST.root); if_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(if_block_AST)))); currentAST.root = if_block_AST; if ( if_block_AST!=RefDNode(antlr::nullAST) && if_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = if_block_AST->getFirstChild(); else currentAST.child = if_block_AST; currentAST.advanceChildToEnd(); } if_block_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = if_block_AST; } void GDLParser::else_block() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode else_block_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case CASE: case COMMON: case COMPILE_OPT: case FORWARD: case GOTO: case IF: case INHERITS: case ON_IOERROR: case SWITCH: case DEC: case INC: case LBRACE: case SYSVARNAME: case ASTERIX: { statement(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else_block_AST = RefDNode(currentAST.root); break; } case BEGIN: { match(BEGIN); statement_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } endelse_mark(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { else_block_AST = RefDNode(currentAST.root); else_block_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(BLOCK,"block")))->add(antlr::RefAST(else_block_AST)))); currentAST.root = else_block_AST; if ( else_block_AST!=RefDNode(antlr::nullAST) && else_block_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = else_block_AST->getFirstChild(); else currentAST.child = else_block_AST; currentAST.advanceChildToEnd(); } else_block_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = else_block_AST; } void GDLParser::parameter_def_list() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode parameter_def_list_AST = RefDNode(antlr::nullAST); parameter_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); parameter_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop123; } } _loop123:; } // ( ... )* parameter_def_list_AST = RefDNode(currentAST.root); returnAST = parameter_def_list_AST; } void GDLParser::formal_function_call() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode formal_function_call_AST = RefDNode(antlr::nullAST); RefDNode tmp148_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp148_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp148_AST)); } match(IDENTIFIER); match(LBRACE); { switch ( LA(1)) { case FOR: case FOREACH: case REPEAT: case WHILE: case IDENTIFIER: case AND_OP: case BEGIN: case CASE: case COMMON: case COMPILE_OPT: case DO: case ELSE: case END: case ENDCASE: case ENDELSE: case ENDFOR: case ENDFOREACH: case ENDIF: case ENDREP: case ENDSWITCH: case ENDWHILE: case EQ_OP: case FORWARD: case FUNCTION: case GE_OP: case GOTO: case GT_OP: case IF: case INHERITS: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OF: case ON_IOERROR: case OR_OP: case PRO: case SWITCH: case THEN: case UNTIL: case XOR_OP: case DEC: case INC: case LBRACE: case SLASH: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: case PLUS: case MINUS: case LOG_NEG: { parameter_def_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case RBRACE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } match(RBRACE); formal_function_call_AST = RefDNode(currentAST.root); returnAST = formal_function_call_AST; } void GDLParser::parameter_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode parameter_def_AST = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); if ((_tokenSet_10.member(LA(1))) && (LA(2) == EQUAL)) { identifier(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(EQUAL); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { parameter_def_AST = RefDNode(currentAST.root); parameter_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(KEYDEF,"!=!")))->add(antlr::RefAST(parameter_def_AST)))); currentAST.root = parameter_def_AST; if ( parameter_def_AST!=RefDNode(antlr::nullAST) && parameter_def_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = parameter_def_AST->getFirstChild(); else currentAST.child = parameter_def_AST; currentAST.advanceChildToEnd(); } parameter_def_AST = RefDNode(currentAST.root); } else if ((_tokenSet_11.member(LA(1))) && (_tokenSet_12.member(LA(2)))) { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } parameter_def_AST = RefDNode(currentAST.root); } else if ((LA(1) == SLASH)) { match(SLASH); identifier(); if (inputState->guessing==0) { id_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { parameter_def_AST = RefDNode(currentAST.root); RefDNode c=static_cast( astFactory->create(CONSTANT,"1")); c->Text2Int(10); c->SetLine( id_AST->getLine()); parameter_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(KEYDEF,"!=!")))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(c)))); currentAST.root = parameter_def_AST; if ( parameter_def_AST!=RefDNode(antlr::nullAST) && parameter_def_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = parameter_def_AST->getFirstChild(); else currentAST.child = parameter_def_AST; currentAST.advanceChildToEnd(); } parameter_def_AST = RefDNode(currentAST.root); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } returnAST = parameter_def_AST; } void GDLParser::array_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_def_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode ee_AST = RefDNode(antlr::nullAST); RefDNode eee_AST = RefDNode(antlr::nullAST); bool constant = true; int flexible_array_def_count=1; match(LSQUARE); expr(); if (inputState->guessing==0) { e_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { if( !ConstantExprNode( e_AST->getType())) constant = false; } { switch ( LA(1)) { case COMMA: case RSQUARE: { { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); expr(); if (inputState->guessing==0) { ee_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { if( !ConstantExprNode( ee_AST->getType())) constant = false; } } else { goto _loop127; } } _loop127:; } // ( ... )* match(RSQUARE); if ( inputState->guessing==0 ) { array_def_AST = RefDNode(currentAST.root); if( constant) array_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ARRAYDEF_CONST,"array_def_const")))->add(antlr::RefAST(array_def_AST)))); else array_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ARRAYDEF,"array_def")))->add(antlr::RefAST(array_def_AST)))); currentAST.root = array_def_AST; if ( array_def_AST!=RefDNode(antlr::nullAST) && array_def_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = array_def_AST->getFirstChild(); else currentAST.child = array_def_AST; currentAST.advanceChildToEnd(); } break; } case COLON: { { // ( ... )+ int _cnt129=0; for (;;) { if ((LA(1) == COLON)) { match(COLON); expr(); if (inputState->guessing==0) { eee_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { flexible_array_def_count++; } } else { if ( _cnt129>=1 ) { goto _loop129; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } _cnt129++; } _loop129:; } // ( ... )+ match(RSQUARE); if ( inputState->guessing==0 ) { array_def_AST = RefDNode(currentAST.root); if (flexible_array_def_count>3 || flexible_array_def_count<2) throw GDLException( "Illegal array creation syntax."); array_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ARRAYDEF_GENERALIZED_INDGEN,"array_def_generalized_indgen")))->add(antlr::RefAST(array_def_AST)))); currentAST.root = array_def_AST; if ( array_def_AST!=RefDNode(antlr::nullAST) && array_def_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = array_def_AST->getFirstChild(); else currentAST.child = array_def_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } array_def_AST = RefDNode(currentAST.root); returnAST = array_def_AST; } void GDLParser::struct_identifier() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode struct_identifier_AST = RefDNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefDNode s_AST = RefDNode(antlr::nullAST); antlr::RefToken e = antlr::nullToken; RefDNode e_AST = RefDNode(antlr::nullAST); antlr::RefToken i = antlr::nullToken; RefDNode i_AST = RefDNode(antlr::nullAST); { switch ( LA(1)) { case IDENTIFIER: { RefDNode tmp158_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp158_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp158_AST)); } match(IDENTIFIER); break; } case SYSVARNAME: { s = LT(1); if ( inputState->guessing == 0 ) { s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); } match(SYSVARNAME); if ( inputState->guessing==0 ) { s_AST->setType( IDENTIFIER); } break; } case EXCLAMATION: { e = LT(1); if ( inputState->guessing == 0 ) { e_AST = astFactory->create(e); astFactory->addASTChild(currentAST, antlr::RefAST(e_AST)); } match(EXCLAMATION); if ( inputState->guessing==0 ) { e_AST->setType( IDENTIFIER); } break; } case INHERITS: { i = LT(1); if ( inputState->guessing == 0 ) { i_AST = astFactory->create(i); astFactory->addASTChild(currentAST, antlr::RefAST(i_AST)); } match(INHERITS); if ( inputState->guessing==0 ) { i_AST->setType( IDENTIFIER); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } struct_identifier_AST = RefDNode(currentAST.root); returnAST = struct_identifier_AST; } void GDLParser::struct_name() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode struct_name_AST = RefDNode(antlr::nullAST); RefDNode s_AST = RefDNode(antlr::nullAST); struct_identifier(); if (inputState->guessing==0) { s_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { if( s_AST->getText() == "IDL_OBJECT") s_AST->setText(GDL_OBJECT_NAME); else if( s_AST->getText() == "IDL_CONTAINER") s_AST->setText(GDL_CONTAINER_NAME); } struct_name_AST = RefDNode(currentAST.root); returnAST = struct_name_AST; } void GDLParser::struct_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode struct_def_AST = RefDNode(antlr::nullAST); match(LCURLY); { if ((_tokenSet_13.member(LA(1))) && (LA(2) == COMMA || LA(2) == RCURLY)) { struct_name(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case COMMA: { match(COMMA); named_tag_def_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case RCURLY: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } match(RCURLY); if ( inputState->guessing==0 ) { struct_def_AST = RefDNode(currentAST.root); struct_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(NSTRUC_REF,"nstruct_ref")))->add(antlr::RefAST(struct_def_AST)))); currentAST.root = struct_def_AST; if ( struct_def_AST!=RefDNode(antlr::nullAST) && struct_def_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = struct_def_AST->getFirstChild(); else currentAST.child = struct_def_AST; currentAST.advanceChildToEnd(); } } else if ((_tokenSet_13.member(LA(1))) && (LA(2) == COLON)) { tag_def_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(RCURLY); if ( inputState->guessing==0 ) { struct_def_AST = RefDNode(currentAST.root); struct_def_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(STRUC,"struct")))->add(antlr::RefAST(struct_def_AST)))); currentAST.root = struct_def_AST; if ( struct_def_AST!=RefDNode(antlr::nullAST) && struct_def_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = struct_def_AST->getFirstChild(); else currentAST.child = struct_def_AST; currentAST.advanceChildToEnd(); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } struct_def_AST = RefDNode(currentAST.root); returnAST = struct_def_AST; } void GDLParser::named_tag_def_list() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode named_tag_def_list_AST = RefDNode(antlr::nullAST); named_tag_def_entry(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); named_tag_def_entry(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop150; } } _loop150:; } // ( ... )* named_tag_def_list_AST = RefDNode(currentAST.root); returnAST = named_tag_def_list_AST; } void GDLParser::tag_def_list() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_def_list_AST = RefDNode(antlr::nullAST); tag_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); tag_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop139; } } _loop139:; } // ( ... )* tag_def_list_AST = RefDNode(currentAST.root); returnAST = tag_def_list_AST; } void GDLParser::tag_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_def_AST = RefDNode(antlr::nullAST); struct_identifier(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(COLON); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } tag_def_AST = RefDNode(currentAST.root); returnAST = tag_def_AST; } void GDLParser::ntag_def() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode ntag_def_AST = RefDNode(antlr::nullAST); if ((_tokenSet_13.member(LA(1))) && (LA(2) == COLON)) { tag_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } ntag_def_AST = RefDNode(currentAST.root); } else if ((_tokenSet_11.member(LA(1))) && (_tokenSet_14.member(LA(2)))) { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } ntag_def_AST = RefDNode(currentAST.root); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } returnAST = ntag_def_AST; } void GDLParser::ntag_defs() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode ntag_defs_AST = RefDNode(antlr::nullAST); ntag_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); ntag_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop143; } } _loop143:; } // ( ... )* ntag_defs_AST = RefDNode(currentAST.root); returnAST = ntag_defs_AST; } void GDLParser::named_tag_def_entry() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode named_tag_def_entry_AST = RefDNode(antlr::nullAST); { bool synPredMatched147 = false; if (((LA(1) == INHERITS) && (_tokenSet_13.member(LA(2))))) { int _m147 = mark(); synPredMatched147 = true; inputState->guessing++; try { { match(INHERITS); } } catch (antlr::RecognitionException& pe) { synPredMatched147 = false; } rewind(_m147); inputState->guessing--; } if ( synPredMatched147 ) { RefDNode tmp167_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp167_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp167_AST)); } match(INHERITS); struct_name(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((_tokenSet_15.member(LA(1))) && (_tokenSet_16.member(LA(2)))) { ntag_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } named_tag_def_entry_AST = RefDNode(currentAST.root); returnAST = named_tag_def_entry_AST; } void GDLParser::numeric_constant() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode numeric_constant_AST = RefDNode(antlr::nullAST); antlr::RefToken c1 = antlr::nullToken; RefDNode c1_AST = RefDNode(antlr::nullAST); antlr::RefToken c2 = antlr::nullToken; RefDNode c2_AST = RefDNode(antlr::nullAST); antlr::RefToken c3 = antlr::nullToken; RefDNode c3_AST = RefDNode(antlr::nullAST); antlr::RefToken c4 = antlr::nullToken; RefDNode c4_AST = RefDNode(antlr::nullAST); antlr::RefToken c44 = antlr::nullToken; RefDNode c44_AST = RefDNode(antlr::nullAST); antlr::RefToken c5 = antlr::nullToken; RefDNode c5_AST = RefDNode(antlr::nullAST); antlr::RefToken c6 = antlr::nullToken; RefDNode c6_AST = RefDNode(antlr::nullAST); antlr::RefToken c77 = antlr::nullToken; RefDNode c77_AST = RefDNode(antlr::nullAST); antlr::RefToken c7 = antlr::nullToken; RefDNode c7_AST = RefDNode(antlr::nullAST); antlr::RefToken c8 = antlr::nullToken; RefDNode c8_AST = RefDNode(antlr::nullAST); antlr::RefToken c9 = antlr::nullToken; RefDNode c9_AST = RefDNode(antlr::nullAST); antlr::RefToken c10 = antlr::nullToken; RefDNode c10_AST = RefDNode(antlr::nullAST); antlr::RefToken c11 = antlr::nullToken; RefDNode c11_AST = RefDNode(antlr::nullAST); antlr::RefToken c111 = antlr::nullToken; RefDNode c111_AST = RefDNode(antlr::nullAST); antlr::RefToken c12 = antlr::nullToken; RefDNode c12_AST = RefDNode(antlr::nullAST); antlr::RefToken c13 = antlr::nullToken; RefDNode c13_AST = RefDNode(antlr::nullAST); antlr::RefToken c144 = antlr::nullToken; RefDNode c144_AST = RefDNode(antlr::nullAST); antlr::RefToken c14 = antlr::nullToken; RefDNode c14_AST = RefDNode(antlr::nullAST); antlr::RefToken c15 = antlr::nullToken; RefDNode c15_AST = RefDNode(antlr::nullAST); antlr::RefToken c16 = antlr::nullToken; RefDNode c16_AST = RefDNode(antlr::nullAST); antlr::RefToken c17 = antlr::nullToken; RefDNode c17_AST = RefDNode(antlr::nullAST); antlr::RefToken c18 = antlr::nullToken; RefDNode c18_AST = RefDNode(antlr::nullAST); antlr::RefToken c188 = antlr::nullToken; RefDNode c188_AST = RefDNode(antlr::nullAST); antlr::RefToken c19 = antlr::nullToken; RefDNode c19_AST = RefDNode(antlr::nullAST); antlr::RefToken c20 = antlr::nullToken; RefDNode c20_AST = RefDNode(antlr::nullAST); antlr::RefToken c211 = antlr::nullToken; RefDNode c211_AST = RefDNode(antlr::nullAST); antlr::RefToken c21 = antlr::nullToken; RefDNode c21_AST = RefDNode(antlr::nullAST); antlr::RefToken c22 = antlr::nullToken; RefDNode c22_AST = RefDNode(antlr::nullAST); antlr::RefToken c23 = antlr::nullToken; RefDNode c23_AST = RefDNode(antlr::nullAST); antlr::RefToken c24 = antlr::nullToken; RefDNode c24_AST = RefDNode(antlr::nullAST); antlr::RefToken c25 = antlr::nullToken; RefDNode c25_AST = RefDNode(antlr::nullAST); antlr::RefToken c26 = antlr::nullToken; RefDNode c26_AST = RefDNode(antlr::nullAST); antlr::RefToken c27 = antlr::nullToken; RefDNode c27_AST = RefDNode(antlr::nullAST); antlr::RefToken c277 = antlr::nullToken; RefDNode c277_AST = RefDNode(antlr::nullAST); antlr::RefToken c28 = antlr::nullToken; RefDNode c28_AST = RefDNode(antlr::nullAST); antlr::RefToken c29 = antlr::nullToken; RefDNode c29_AST = RefDNode(antlr::nullAST); antlr::RefToken c300 = antlr::nullToken; RefDNode c300_AST = RefDNode(antlr::nullAST); antlr::RefToken c30 = antlr::nullToken; RefDNode c30_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case CONSTANT_HEX_BYTE: { c1 = LT(1); if ( inputState->guessing == 0 ) { c1_AST = astFactory->create(c1); } match(CONSTANT_HEX_BYTE); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c1->getText()); numeric_constant_AST->Text2Byte(16); numeric_constant_AST->SetLine( c1->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_LONG: { c2 = LT(1); if ( inputState->guessing == 0 ) { c2_AST = astFactory->create(c2); } match(CONSTANT_HEX_LONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c2->getText()); numeric_constant_AST->Text2Long(16); numeric_constant_AST->SetLine( c2->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_LONG64: { c3 = LT(1); if ( inputState->guessing == 0 ) { c3_AST = astFactory->create(c3); } match(CONSTANT_HEX_LONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c3->getText()); numeric_constant_AST->Text2Long64(16); numeric_constant_AST->SetLine( c3->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_INT: { c4 = LT(1); if ( inputState->guessing == 0 ) { c4_AST = astFactory->create(c4); } match(CONSTANT_HEX_INT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c4->getText()); numeric_constant_AST->Text2Int(16); numeric_constant_AST->SetLine( c4->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_I: { c44 = LT(1); if ( inputState->guessing == 0 ) { c44_AST = astFactory->create(c44); } match(CONSTANT_HEX_I); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c44->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2Long(16,true); else numeric_constant_AST->Text2Int(16,true); numeric_constant_AST->SetLine( c44->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_ULONG: { c5 = LT(1); if ( inputState->guessing == 0 ) { c5_AST = astFactory->create(c5); } match(CONSTANT_HEX_ULONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c5->getText()); numeric_constant_AST->Text2ULong(16); numeric_constant_AST->SetLine( c5->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_ULONG64: { c6 = LT(1); if ( inputState->guessing == 0 ) { c6_AST = astFactory->create(c6); } match(CONSTANT_HEX_ULONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c6->getText()); numeric_constant_AST->Text2ULong64(16); numeric_constant_AST->SetLine( c6->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_UI: { c77 = LT(1); if ( inputState->guessing == 0 ) { c77_AST = astFactory->create(c77); } match(CONSTANT_HEX_UI); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c77->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2ULong(16,true); else numeric_constant_AST->Text2UInt(16,true); numeric_constant_AST->SetLine( c77->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_UINT: { c7 = LT(1); if ( inputState->guessing == 0 ) { c7_AST = astFactory->create(c7); } match(CONSTANT_HEX_UINT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c7->getText()); numeric_constant_AST->Text2UInt(16); numeric_constant_AST->SetLine( c7->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BYTE: { c8 = LT(1); if ( inputState->guessing == 0 ) { c8_AST = astFactory->create(c8); } match(CONSTANT_BYTE); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c8->getText()); numeric_constant_AST->Text2Byte(10); numeric_constant_AST->SetLine( c8->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_LONG: { c9 = LT(1); if ( inputState->guessing == 0 ) { c9_AST = astFactory->create(c9); } match(CONSTANT_LONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c9->getText()); numeric_constant_AST->Text2Long(10); numeric_constant_AST->SetLine( c9->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_LONG64: { c10 = LT(1); if ( inputState->guessing == 0 ) { c10_AST = astFactory->create(c10); } match(CONSTANT_LONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c10->getText()); numeric_constant_AST->Text2Long64(10); numeric_constant_AST->SetLine( c10->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_INT: { c11 = LT(1); if ( inputState->guessing == 0 ) { c11_AST = astFactory->create(c11); } match(CONSTANT_INT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c11->getText()); numeric_constant_AST->Text2Int(10); numeric_constant_AST->SetLine( c11->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_I: { c111 = LT(1); if ( inputState->guessing == 0 ) { c111_AST = astFactory->create(c111); } match(CONSTANT_I); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c111->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2Long(10,true); else numeric_constant_AST->Text2Int(10,true); numeric_constant_AST->SetLine( c111->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_ULONG: { c12 = LT(1); if ( inputState->guessing == 0 ) { c12_AST = astFactory->create(c12); } match(CONSTANT_ULONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c12->getText()); numeric_constant_AST->Text2ULong(10); numeric_constant_AST->SetLine( c12->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_ULONG64: { c13 = LT(1); if ( inputState->guessing == 0 ) { c13_AST = astFactory->create(c13); } match(CONSTANT_ULONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c13->getText()); numeric_constant_AST->Text2ULong64(10); numeric_constant_AST->SetLine( c13->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_UI: { c144 = LT(1); if ( inputState->guessing == 0 ) { c144_AST = astFactory->create(c144); } match(CONSTANT_UI); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c144->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2ULong(10,true); else numeric_constant_AST->Text2UInt(10,true); numeric_constant_AST->SetLine( c144->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_UINT: { c14 = LT(1); if ( inputState->guessing == 0 ) { c14_AST = astFactory->create(c14); } match(CONSTANT_UINT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c14->getText()); numeric_constant_AST->Text2UInt(10); numeric_constant_AST->SetLine( c14->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_BYTE: { c15 = LT(1); if ( inputState->guessing == 0 ) { c15_AST = astFactory->create(c15); } match(CONSTANT_OCT_BYTE); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c15->getText()); numeric_constant_AST->Text2Byte(8); numeric_constant_AST->SetLine( c15->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_LONG: { c16 = LT(1); if ( inputState->guessing == 0 ) { c16_AST = astFactory->create(c16); } match(CONSTANT_OCT_LONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c16->getText()); numeric_constant_AST->Text2Long(8); numeric_constant_AST->SetLine( c16->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_LONG64: { c17 = LT(1); if ( inputState->guessing == 0 ) { c17_AST = astFactory->create(c17); } match(CONSTANT_OCT_LONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c17->getText()); numeric_constant_AST->Text2Long64(8); numeric_constant_AST->SetLine( c17->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_INT: { c18 = LT(1); if ( inputState->guessing == 0 ) { c18_AST = astFactory->create(c18); } match(CONSTANT_OCT_INT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c18->getText()); numeric_constant_AST->Text2Int(8); numeric_constant_AST->SetLine( c18->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_I: { c188 = LT(1); if ( inputState->guessing == 0 ) { c188_AST = astFactory->create(c188); } match(CONSTANT_OCT_I); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c188->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2Long(8,true); else numeric_constant_AST->Text2Int(8,true); numeric_constant_AST->SetLine( c188->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_ULONG: { c19 = LT(1); if ( inputState->guessing == 0 ) { c19_AST = astFactory->create(c19); } match(CONSTANT_OCT_ULONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c19->getText()); numeric_constant_AST->Text2ULong(8); numeric_constant_AST->SetLine( c19->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_ULONG64: { c20 = LT(1); if ( inputState->guessing == 0 ) { c20_AST = astFactory->create(c20); } match(CONSTANT_OCT_ULONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c20->getText()); numeric_constant_AST->Text2ULong64(8); numeric_constant_AST->SetLine( c20->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_UI: { c211 = LT(1); if ( inputState->guessing == 0 ) { c211_AST = astFactory->create(c211); } match(CONSTANT_OCT_UI); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c211->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2ULong(8,true); else numeric_constant_AST->Text2UInt(8,true); numeric_constant_AST->SetLine( c211->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_OCT_UINT: { c21 = LT(1); if ( inputState->guessing == 0 ) { c21_AST = astFactory->create(c21); } match(CONSTANT_OCT_UINT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c21->getText()); numeric_constant_AST->Text2UInt(8); numeric_constant_AST->SetLine( c21->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_FLOAT: { c22 = LT(1); if ( inputState->guessing == 0 ) { c22_AST = astFactory->create(c22); } match(CONSTANT_FLOAT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c22->getText()); numeric_constant_AST->Text2Float(); numeric_constant_AST->SetLine( c22->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_DOUBLE: { c23 = LT(1); if ( inputState->guessing == 0 ) { c23_AST = astFactory->create(c23); } match(CONSTANT_DOUBLE); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c23->getText()); numeric_constant_AST->Text2Double(); numeric_constant_AST->SetLine( c23->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_BYTE: { c24 = LT(1); if ( inputState->guessing == 0 ) { c24_AST = astFactory->create(c24); } match(CONSTANT_BIN_BYTE); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c24->getText()); numeric_constant_AST->Text2Byte(2); numeric_constant_AST->SetLine( c24->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_LONG: { c25 = LT(1); if ( inputState->guessing == 0 ) { c25_AST = astFactory->create(c25); } match(CONSTANT_BIN_LONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c25->getText()); numeric_constant_AST->Text2Long(2); numeric_constant_AST->SetLine( c25->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_LONG64: { c26 = LT(1); if ( inputState->guessing == 0 ) { c26_AST = astFactory->create(c26); } match(CONSTANT_BIN_LONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c26->getText()); numeric_constant_AST->Text2Long64(2); numeric_constant_AST->SetLine( c26->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_INT: { c27 = LT(1); if ( inputState->guessing == 0 ) { c27_AST = astFactory->create(c27); } match(CONSTANT_BIN_INT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c27->getText()); numeric_constant_AST->Text2Int(2); numeric_constant_AST->SetLine( c27->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_I: { c277 = LT(1); if ( inputState->guessing == 0 ) { c277_AST = astFactory->create(c277); } match(CONSTANT_BIN_I); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c277->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2Long(2,true); else numeric_constant_AST->Text2Int(2,true); numeric_constant_AST->SetLine( c277->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_ULONG: { c28 = LT(1); if ( inputState->guessing == 0 ) { c28_AST = astFactory->create(c28); } match(CONSTANT_BIN_ULONG); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c28->getText()); numeric_constant_AST->Text2ULong(2); numeric_constant_AST->SetLine( c28->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_ULONG64: { c29 = LT(1); if ( inputState->guessing == 0 ) { c29_AST = astFactory->create(c29); } match(CONSTANT_BIN_ULONG64); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c29->getText()); numeric_constant_AST->Text2ULong64(2); numeric_constant_AST->SetLine( c29->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_UI: { c300 = LT(1); if ( inputState->guessing == 0 ) { c300_AST = astFactory->create(c300); } match(CONSTANT_BIN_UI); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c300->getText()); if( compileOpt & DEFINT32) numeric_constant_AST->Text2ULong(2,true); else numeric_constant_AST->Text2UInt(2,true); numeric_constant_AST->SetLine( c300->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_BIN_UINT: { c30 = LT(1); if ( inputState->guessing == 0 ) { c30_AST = astFactory->create(c30); } match(CONSTANT_BIN_UINT); if ( inputState->guessing==0 ) { numeric_constant_AST = RefDNode(currentAST.root); numeric_constant_AST=astFactory->create(CONSTANT,c30->getText()); numeric_constant_AST->Text2UInt(2); numeric_constant_AST->SetLine( c30->getLine()); currentAST.root = numeric_constant_AST; if ( numeric_constant_AST!=RefDNode(antlr::nullAST) && numeric_constant_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = numeric_constant_AST->getFirstChild(); else currentAST.child = numeric_constant_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = numeric_constant_AST; } void GDLParser::arrayindex_list() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayindex_list_AST = RefDNode(antlr::nullAST); int rank = 1; if ((LA(1) == LSQUARE)) { match(LSQUARE); arrayindex(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if (((LA(1) == COMMA))&&(++rank <= MAXRANK)) { match(COMMA); arrayindex(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop154; } } _loop154:; } // ( ... )* match(RSQUARE); arrayindex_list_AST = RefDNode(currentAST.root); } else if (((LA(1) == LBRACE))&&( IsRelaxed())) { match(LBRACE); arrayindex(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if (((LA(1) == COMMA))&&(++rank <= MAXRANK)) { match(COMMA); arrayindex(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop156; } } _loop156:; } // ( ... )* match(RBRACE); arrayindex_list_AST = RefDNode(currentAST.root); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } returnAST = arrayindex_list_AST; } void GDLParser::arrayindex() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayindex_AST = RefDNode(antlr::nullAST); { bool synPredMatched162 = false; if (((LA(1) == ASTERIX) && (LA(2) == COMMA || LA(2) == RBRACE || LA(2) == RSQUARE))) { int _m162 = mark(); synPredMatched162 = true; inputState->guessing++; try { { match(ASTERIX); { switch ( LA(1)) { case COMMA: { match(COMMA); break; } case RSQUARE: { match(RSQUARE); break; } default: if (((LA(1) == RBRACE))&&( IsRelaxed())) { match(RBRACE); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } } catch (antlr::RecognitionException& pe) { synPredMatched162 = false; } rewind(_m162); inputState->guessing--; } if ( synPredMatched162 ) { all_elements(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((_tokenSet_11.member(LA(1))) && (_tokenSet_17.member(LA(2)))) { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case COLON: { match(COLON); { bool synPredMatched167 = false; if (((LA(1) == ASTERIX) && (_tokenSet_18.member(LA(2))))) { int _m167 = mark(); synPredMatched167 = true; inputState->guessing++; try { { match(ASTERIX); { switch ( LA(1)) { case COMMA: { match(COMMA); break; } case RSQUARE: { match(RSQUARE); break; } case COLON: { match(COLON); break; } default: if (((LA(1) == RBRACE))&&( IsRelaxed())) { match(RBRACE); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } } catch (antlr::RecognitionException& pe) { synPredMatched167 = false; } rewind(_m167); inputState->guessing--; } if ( synPredMatched167 ) { all_elements(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else if ((_tokenSet_11.member(LA(1))) && (_tokenSet_17.member(LA(2)))) { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } { switch ( LA(1)) { case COLON: { match(COLON); { bool synPredMatched172 = false; if (((LA(1) == ASTERIX) && (LA(2) == COMMA || LA(2) == RBRACE || LA(2) == RSQUARE))) { int _m172 = mark(); synPredMatched172 = true; inputState->guessing++; try { { match(ASTERIX); { switch ( LA(1)) { case COMMA: { match(COMMA); break; } case RSQUARE: { match(RSQUARE); break; } default: if (((LA(1) == RBRACE))&&( IsRelaxed())) { match(RBRACE); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } } catch (antlr::RecognitionException& pe) { synPredMatched172 = false; } rewind(_m172); inputState->guessing--; } if ( synPredMatched172 ) { match(ASTERIX); if ( inputState->guessing==0 ) { throw GDLException( "n:n:* subscript form not allowed."); } } else if ((_tokenSet_11.member(LA(1))) && (_tokenSet_19.member(LA(2)))) { expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } break; } case COMMA: case RBRACE: case RSQUARE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } break; } case COMMA: case RBRACE: case RSQUARE: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } if ( inputState->guessing==0 ) { arrayindex_AST = RefDNode(currentAST.root); arrayindex_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ARRAYIX,"arrayix")))->add(antlr::RefAST(arrayindex_AST)))); currentAST.root = arrayindex_AST; if ( arrayindex_AST!=RefDNode(antlr::nullAST) && arrayindex_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_AST->getFirstChild(); else currentAST.child = arrayindex_AST; currentAST.advanceChildToEnd(); } arrayindex_AST = RefDNode(currentAST.root); returnAST = arrayindex_AST; } void GDLParser::all_elements() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode all_elements_AST = RefDNode(antlr::nullAST); RefDNode tmp177_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp177_AST = astFactory->create(LT(1)); } match(ASTERIX); if ( inputState->guessing==0 ) { all_elements_AST = RefDNode(currentAST.root); all_elements_AST = RefDNode(astFactory->make((new antlr::ASTArray(1))->add(antlr::RefAST(astFactory->create(ALL,"*"))))); currentAST.root = all_elements_AST; if ( all_elements_AST!=RefDNode(antlr::nullAST) && all_elements_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = all_elements_AST->getFirstChild(); else currentAST.child = all_elements_AST; currentAST.advanceChildToEnd(); } returnAST = all_elements_AST; } void GDLParser::sysvar() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode sysvar_AST = RefDNode(antlr::nullAST); RefDNode tmp178_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp178_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp178_AST)); } match(SYSVARNAME); if ( inputState->guessing==0 ) { sysvar_AST = RefDNode(currentAST.root); sysvar_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(SYSVAR,"SYSVAR")))->add(antlr::RefAST(sysvar_AST)))); currentAST.root = sysvar_AST; if ( sysvar_AST!=RefDNode(antlr::nullAST) && sysvar_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = sysvar_AST->getFirstChild(); else currentAST.child = sysvar_AST; currentAST.advanceChildToEnd(); } sysvar_AST = RefDNode(currentAST.root); returnAST = sysvar_AST; } void GDLParser::var() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode var_AST = RefDNode(antlr::nullAST); antlr::RefToken id = antlr::nullToken; RefDNode id_AST = RefDNode(antlr::nullAST); antlr::RefToken ih = antlr::nullToken; RefDNode ih_AST = RefDNode(antlr::nullAST); { switch ( LA(1)) { case IDENTIFIER: { id = LT(1); if ( inputState->guessing == 0 ) { id_AST = astFactory->create(id); } match(IDENTIFIER); if ( inputState->guessing==0 ) { var_AST = RefDNode(currentAST.root); var_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(VAR,"VAR")))->add(antlr::RefAST(id_AST)))); currentAST.root = var_AST; if ( var_AST!=RefDNode(antlr::nullAST) && var_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = var_AST->getFirstChild(); else currentAST.child = var_AST; currentAST.advanceChildToEnd(); } break; } case INHERITS: { ih = LT(1); if ( inputState->guessing == 0 ) { ih_AST = astFactory->create(ih); } match(INHERITS); if ( inputState->guessing==0 ) { var_AST = RefDNode(currentAST.root); ih_AST->setType( IDENTIFIER); var_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(VAR,"VAR")))->add(antlr::RefAST(ih_AST)))); currentAST.root = var_AST; if ( var_AST!=RefDNode(antlr::nullAST) && var_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = var_AST->getFirstChild(); else currentAST.child = var_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } returnAST = var_AST; } void GDLParser::brace_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode brace_expr_AST = RefDNode(antlr::nullAST); match(LBRACE); expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } match(RBRACE); if ( inputState->guessing==0 ) { brace_expr_AST = RefDNode(currentAST.root); brace_expr_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(EXPR,"expr")))->add(antlr::RefAST(brace_expr_AST)))); currentAST.root = brace_expr_AST; if ( brace_expr_AST!=RefDNode(antlr::nullAST) && brace_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = brace_expr_AST->getFirstChild(); else currentAST.child = brace_expr_AST; currentAST.advanceChildToEnd(); } brace_expr_AST = RefDNode(currentAST.root); returnAST = brace_expr_AST; } void GDLParser::array_expr_1st_sub() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_expr_1st_sub_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: case INHERITS: { var(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } array_expr_1st_sub_AST = RefDNode(currentAST.root); break; } case SYSVARNAME: { sysvar(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } array_expr_1st_sub_AST = RefDNode(currentAST.root); break; } case LBRACE: { brace_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } array_expr_1st_sub_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = array_expr_1st_sub_AST; } void GDLParser::array_expr_1st() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_expr_1st_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode al_AST = RefDNode(antlr::nullAST); array_expr_1st_sub(); if (inputState->guessing==0) { e_AST = returnAST; } { switch ( LA(1)) { case LBRACE: case LSQUARE: { arrayindex_list(); if (inputState->guessing==0) { al_AST = returnAST; } if ( inputState->guessing==0 ) { array_expr_1st_AST = RefDNode(currentAST.root); array_expr_1st_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ARRAYEXPR,"arrayexpr")))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(al_AST)))); currentAST.root = array_expr_1st_AST; if ( array_expr_1st_AST!=RefDNode(antlr::nullAST) && array_expr_1st_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = array_expr_1st_AST->getFirstChild(); else currentAST.child = array_expr_1st_AST; currentAST.advanceChildToEnd(); } break; } case antlr::Token::EOF_TYPE: case AND_OP: case DO: case ELSE: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case OF: case OR_OP: case THEN: case UNTIL: case XOR_OP: case COMMA: case COLON: case END_U: case EQUAL: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case MEMBER: case RBRACE: case SLASH: case RSQUARE: case RCURLY: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_AND: case LOG_OR: case QUESTION: { if ( inputState->guessing==0 ) { array_expr_1st_AST = RefDNode(currentAST.root); array_expr_1st_AST = e_AST; currentAST.root = array_expr_1st_AST; if ( array_expr_1st_AST!=RefDNode(antlr::nullAST) && array_expr_1st_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = array_expr_1st_AST->getFirstChild(); else currentAST.child = array_expr_1st_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } returnAST = array_expr_1st_AST; } void GDLParser::array_expr_nth_sub() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_expr_nth_sub_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: { RefDNode tmp181_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp181_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp181_AST)); } match(IDENTIFIER); array_expr_nth_sub_AST = RefDNode(currentAST.root); break; } case LBRACE: { brace_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } array_expr_nth_sub_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = array_expr_nth_sub_AST; } void GDLParser::array_expr_nth() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_expr_nth_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode al_AST = RefDNode(antlr::nullAST); array_expr_nth_sub(); if (inputState->guessing==0) { e_AST = returnAST; } { switch ( LA(1)) { case LBRACE: case LSQUARE: { arrayindex_list(); if (inputState->guessing==0) { al_AST = returnAST; } if ( inputState->guessing==0 ) { array_expr_nth_AST = RefDNode(currentAST.root); array_expr_nth_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ARRAYEXPR,"arrayexpr")))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(al_AST)))); currentAST.root = array_expr_nth_AST; if ( array_expr_nth_AST!=RefDNode(antlr::nullAST) && array_expr_nth_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = array_expr_nth_AST->getFirstChild(); else currentAST.child = array_expr_nth_AST; currentAST.advanceChildToEnd(); } break; } case antlr::Token::EOF_TYPE: { if ( inputState->guessing==0 ) { array_expr_nth_AST = RefDNode(currentAST.root); array_expr_nth_AST = e_AST; currentAST.root = array_expr_nth_AST; if ( array_expr_nth_AST!=RefDNode(antlr::nullAST) && array_expr_nth_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = array_expr_nth_AST->getFirstChild(); else currentAST.child = array_expr_nth_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } returnAST = array_expr_nth_AST; } void GDLParser::tag_array_expr_nth_sub() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_array_expr_nth_sub_AST = RefDNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefDNode s_AST = RefDNode(antlr::nullAST); antlr::RefToken e = antlr::nullToken; RefDNode e_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: { RefDNode tmp182_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp182_AST = astFactory->create(LT(1)); astFactory->addASTChild(currentAST, antlr::RefAST(tmp182_AST)); } match(IDENTIFIER); tag_array_expr_nth_sub_AST = RefDNode(currentAST.root); break; } case SYSVARNAME: { s = LT(1); if ( inputState->guessing == 0 ) { s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); } match(SYSVARNAME); if ( inputState->guessing==0 ) { s_AST->setType( IDENTIFIER); /* #s->setText( "!" + #s->getText()); */ } tag_array_expr_nth_sub_AST = RefDNode(currentAST.root); break; } case EXCLAMATION: { e = LT(1); if ( inputState->guessing == 0 ) { e_AST = astFactory->create(e); astFactory->addASTChild(currentAST, antlr::RefAST(e_AST)); } match(EXCLAMATION); if ( inputState->guessing==0 ) { e_AST->setType( IDENTIFIER); } tag_array_expr_nth_sub_AST = RefDNode(currentAST.root); break; } case LBRACE: { brace_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } tag_array_expr_nth_sub_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = tag_array_expr_nth_sub_AST; } void GDLParser::tag_array_expr_nth() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_array_expr_nth_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode al_AST = RefDNode(antlr::nullAST); tag_array_expr_nth_sub(); if (inputState->guessing==0) { e_AST = returnAST; } { switch ( LA(1)) { case LBRACE: case LSQUARE: { arrayindex_list(); if (inputState->guessing==0) { al_AST = returnAST; } if ( inputState->guessing==0 ) { tag_array_expr_nth_AST = RefDNode(currentAST.root); tag_array_expr_nth_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ARRAYEXPR,"arrayexpr")))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(al_AST)))); currentAST.root = tag_array_expr_nth_AST; if ( tag_array_expr_nth_AST!=RefDNode(antlr::nullAST) && tag_array_expr_nth_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = tag_array_expr_nth_AST->getFirstChild(); else currentAST.child = tag_array_expr_nth_AST; currentAST.advanceChildToEnd(); } break; } case antlr::Token::EOF_TYPE: case AND_OP: case DO: case ELSE: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case OF: case OR_OP: case THEN: case UNTIL: case XOR_OP: case COMMA: case COLON: case END_U: case EQUAL: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case MEMBER: case RBRACE: case SLASH: case RSQUARE: case RCURLY: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_AND: case LOG_OR: case QUESTION: { if ( inputState->guessing==0 ) { tag_array_expr_nth_AST = RefDNode(currentAST.root); tag_array_expr_nth_AST = e_AST; currentAST.root = tag_array_expr_nth_AST; if ( tag_array_expr_nth_AST!=RefDNode(antlr::nullAST) && tag_array_expr_nth_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = tag_array_expr_nth_AST->getFirstChild(); else currentAST.child = tag_array_expr_nth_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } returnAST = tag_array_expr_nth_AST; } int GDLParser::tag_access_keeplast() { int nDot; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_access_keeplast_AST = RefDNode(antlr::nullAST); int t; bool parent = false; nDot=1; match(DOT); { bool synPredMatched189 = false; if (((_tokenSet_20.member(LA(1))) && (_tokenSet_5.member(LA(2))))) { int _m189 = mark(); synPredMatched189 = true; inputState->guessing++; try { { tag_array_expr_nth(); match(DOT); } } catch (antlr::RecognitionException& pe) { synPredMatched189 = false; } rewind(_m189); inputState->guessing--; } if ( synPredMatched189 ) { { tag_array_expr_nth(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } t=tag_access_keeplast(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { nDot += t; } } } else if ((LA(1) == IDENTIFIER) && (_tokenSet_21.member(LA(2)))) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } tag_access_keeplast_AST = RefDNode(currentAST.root); returnAST = tag_access_keeplast_AST; return nDot; } SizeT GDLParser::tag_access() { SizeT nDot; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_access_AST = RefDNode(antlr::nullAST); nDot=0; { // ( ... )+ int _cnt195=0; for (;;) { if ((LA(1) == DOT)) { match(DOT); if ( inputState->guessing==0 ) { ++nDot; } tag_array_expr_nth(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { if ( _cnt195>=1 ) { goto _loop195; } else {throw antlr::NoViableAltException(LT(1), getFilename());} } _cnt195++; } _loop195:; } // ( ... )+ tag_access_AST = RefDNode(currentAST.root); returnAST = tag_access_AST; return nDot; } void GDLParser::deref_dot_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode deref_dot_expr_AST = RefDNode(antlr::nullAST); RefDNode a1_AST = RefDNode(antlr::nullAST); RefDNode dot; SizeT nDot; switch ( LA(1)) { case IDENTIFIER: case INHERITS: case LBRACE: case SYSVARNAME: { array_expr_1st(); if (inputState->guessing==0) { a1_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { nDot=tag_access(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { deref_dot_expr_AST = RefDNode(currentAST.root); dot=astFactory->create(DOT,"."); dot->SetNDot( nDot); dot->SetLine( a1_AST->getLine()); deref_dot_expr_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(dot))->add(antlr::RefAST(deref_dot_expr_AST)))); currentAST.root = deref_dot_expr_AST; if ( deref_dot_expr_AST!=RefDNode(antlr::nullAST) && deref_dot_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_dot_expr_AST->getFirstChild(); else currentAST.child = deref_dot_expr_AST; currentAST.advanceChildToEnd(); } } deref_dot_expr_AST = RefDNode(currentAST.root); break; } case ASTERIX: { match(ASTERIX); deref_dot_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { deref_dot_expr_AST = RefDNode(currentAST.root); deref_dot_expr_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(DEREF,"deref")))->add(antlr::RefAST(deref_dot_expr_AST)))); currentAST.root = deref_dot_expr_AST; if ( deref_dot_expr_AST!=RefDNode(antlr::nullAST) && deref_dot_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = deref_dot_expr_AST->getFirstChild(); else currentAST.child = deref_dot_expr_AST; currentAST.advanceChildToEnd(); } deref_dot_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = deref_dot_expr_AST; } bool GDLParser::member_function_call() { bool parent; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode member_function_call_AST = RefDNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefDNode s_AST = RefDNode(antlr::nullAST); if ( inputState->guessing==0 ) { parent = false; } match(MEMBER); { if ((LA(1) == IDENTIFIER) && (LA(2) == METHOD)) { s = LT(1); if ( inputState->guessing == 0 ) { s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); } match(IDENTIFIER); match(METHOD); if ( inputState->guessing==0 ) { // here we translate IDL_OBECT to GDL_OBJECT for source code compatibility { if( s_AST->getText() == "IDL_OBJECT") s_AST->setText(GDL_OBJECT_NAME); else if( s_AST->getText() == "IDL_CONTAINER") s_AST->setText(GDL_CONTAINER_NAME); } parent = true; } } else if ((LA(1) == IDENTIFIER) && (LA(2) == LBRACE)) { } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } member_function_call_AST = RefDNode(currentAST.root); returnAST = member_function_call_AST; return parent; } void GDLParser::member_function_call_dot() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode member_function_call_dot_AST = RefDNode(antlr::nullAST); antlr::RefToken s = antlr::nullToken; RefDNode s_AST = RefDNode(antlr::nullAST); match(DOT); { s = LT(1); if ( inputState->guessing == 0 ) { s_AST = astFactory->create(s); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); } match(IDENTIFIER); match(METHOD); if ( inputState->guessing==0 ) { if( s_AST->getText() == "IDL_OBJECT") s_AST->setText(GDL_OBJECT_NAME); else if( s_AST->getText() == "IDL_CONTAINER") s_AST->setText(GDL_CONTAINER_NAME); } } formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } member_function_call_dot_AST = RefDNode(currentAST.root); returnAST = member_function_call_dot_AST; } void GDLParser::arrayexpr_mfcall() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayexpr_mfcall_AST = RefDNode(antlr::nullAST); RefDNode a1_AST = RefDNode(antlr::nullAST); RefDNode t1_AST = RefDNode(antlr::nullAST); antlr::RefToken id = antlr::nullToken; RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode al_AST = RefDNode(antlr::nullAST); RefDNode deref_arrayexpr_mfcall_AST = RefDNode(antlr::nullAST); RefDNode dot; RefDNode tag; int nDot; switch ( LA(1)) { case IDENTIFIER: case INHERITS: case LBRACE: case SYSVARNAME: { array_expr_1st(); if (inputState->guessing==0) { a1_AST = returnAST; } { nDot=tag_access_keeplast(); if (inputState->guessing==0) { t1_AST = returnAST; } if ( inputState->guessing==0 ) { if( --nDot > 0) { dot=astFactory->create(DOT,"DOT_A_MF"); dot->SetNDot( nDot); dot->SetLine( a1_AST->getLine()); tag = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(dot))->add(antlr::RefAST(a1_AST))->add(antlr::RefAST(t1_AST)))); } } } id = LT(1); if ( inputState->guessing == 0 ) { id_AST = astFactory->create(id); } match(IDENTIFIER); arrayindex_list(); if (inputState->guessing==0) { al_AST = returnAST; } if ( inputState->guessing==0 ) { arrayexpr_mfcall_AST = RefDNode(currentAST.root); if( nDot > 0) arrayexpr_mfcall_AST = RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(astFactory->create(ARRAYEXPR_MFCALL,"arrayexpr_mfcall")))->add(antlr::RefAST(tag))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(al_AST)))); else arrayexpr_mfcall_AST = RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(astFactory->create(ARRAYEXPR_MFCALL,"arrayexpr_mfcall")))->add(antlr::RefAST(a1_AST))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(al_AST)))); currentAST.root = arrayexpr_mfcall_AST; if ( arrayexpr_mfcall_AST!=RefDNode(antlr::nullAST) && arrayexpr_mfcall_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayexpr_mfcall_AST->getFirstChild(); else currentAST.child = arrayexpr_mfcall_AST; currentAST.advanceChildToEnd(); } break; } case ASTERIX: { RefDNode tmp190_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp190_AST = astFactory->create(LT(1)); } match(ASTERIX); arrayexpr_mfcall(); if (inputState->guessing==0) { deref_arrayexpr_mfcall_AST = returnAST; } if ( inputState->guessing==0 ) { arrayexpr_mfcall_AST = RefDNode(currentAST.root); arrayexpr_mfcall_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(DEREF,"deref")))->add(antlr::RefAST(deref_arrayexpr_mfcall_AST)))); currentAST.root = arrayexpr_mfcall_AST; if ( arrayexpr_mfcall_AST!=RefDNode(antlr::nullAST) && arrayexpr_mfcall_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayexpr_mfcall_AST->getFirstChild(); else currentAST.child = arrayexpr_mfcall_AST; currentAST.advanceChildToEnd(); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = arrayexpr_mfcall_AST; } void GDLParser::primary_expr_tail() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode primary_expr_tail_AST = RefDNode(antlr::nullAST); antlr::RefToken ls = antlr::nullToken; RefDNode ls_AST = RefDNode(antlr::nullAST); antlr::RefToken lc = antlr::nullToken; RefDNode lc_AST = RefDNode(antlr::nullAST); bool parent; bool synPredMatched211 = false; if (((_tokenSet_4.member(LA(1))) && (_tokenSet_22.member(LA(2))))) { int _m211 = mark(); synPredMatched211 = true; inputState->guessing++; try { { deref_dot_expr(); } } catch (antlr::RecognitionException& pe) { synPredMatched211 = false; } rewind(_m211); inputState->guessing--; } if ( synPredMatched211 ) { deref_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case MEMBER: { parent=member_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); if( parent) { primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MFCALL_PARENT,"mfcall::")))->add(antlr::RefAST(primary_expr_tail_AST)))); } else { primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MFCALL,"mfcall")))->add(antlr::RefAST(primary_expr_tail_AST)))); } currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } break; } case antlr::Token::EOF_TYPE: case AND_OP: case DO: case ELSE: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case OF: case OR_OP: case THEN: case UNTIL: case XOR_OP: case COMMA: case COLON: case END_U: case DEC: case INC: case RBRACE: case SLASH: case RSQUARE: case RCURLY: case ASTERIX: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_AND: case LOG_OR: case QUESTION: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } primary_expr_tail_AST = RefDNode(currentAST.root); } else { bool synPredMatched216 = false; if (((LA(1) == IDENTIFIER || LA(1) == INHERITS) && (LA(2) == LBRACE || LA(2) == LSQUARE))) { int _m216 = mark(); synPredMatched216 = true; inputState->guessing++; try { { match(IDENTIFIER); match(LBRACE); expr(); { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); expr(); } else { goto _loop215; } } _loop215:; } // ( ... )* match(RBRACE); } } catch (antlr::RecognitionException& pe) { synPredMatched216 = false; } rewind(_m216); inputState->guessing--; } if ( synPredMatched216 ) { { if (((LA(1) == IDENTIFIER) && (LA(2) == LBRACE))&&( IsFun(LT(1)))) { formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(FCALL,"fcall")))->add(antlr::RefAST(primary_expr_tail_AST)))); currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } } else { bool synPredMatched219 = false; if (((LA(1) == IDENTIFIER || LA(1) == INHERITS) && (LA(2) == LBRACE || LA(2) == LSQUARE))) { int _m219 = mark(); synPredMatched219 = true; inputState->guessing++; try { { var(); arrayindex_list(); } } catch (antlr::RecognitionException& pe) { synPredMatched219 = false; } rewind(_m219); inputState->guessing--; } if ( synPredMatched219 ) { var(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } arrayindex_list(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ARRAYEXPR_FCALL,"arrayexpr_fcall")))->add(antlr::RefAST(primary_expr_tail_AST)))); currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } } else if ((LA(1) == IDENTIFIER) && (LA(2) == LBRACE)) { formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(FCALL,"fcall")))->add(antlr::RefAST(primary_expr_tail_AST)))); currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } } } primary_expr_tail_AST = RefDNode(currentAST.root); } else { bool synPredMatched221 = false; if (((LA(1) == IDENTIFIER) && (LA(2) == LBRACE))) { int _m221 = mark(); synPredMatched221 = true; inputState->guessing++; try { { formal_function_call(); } } catch (antlr::RecognitionException& pe) { synPredMatched221 = false; } rewind(_m221); inputState->guessing--; } if ( synPredMatched221 ) { formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(FCALL,"fcall")))->add(antlr::RefAST(primary_expr_tail_AST)))); currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } primary_expr_tail_AST = RefDNode(currentAST.root); } else { bool synPredMatched223 = false; if (((_tokenSet_4.member(LA(1))) && (_tokenSet_22.member(LA(2))))) { int _m223 = mark(); synPredMatched223 = true; inputState->guessing++; try { { deref_expr(); } } catch (antlr::RecognitionException& pe) { synPredMatched223 = false; } rewind(_m223); inputState->guessing--; } if ( synPredMatched223 ) { deref_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case MEMBER: { parent=member_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); if( parent) { primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MFCALL_PARENT,"mfcall::")))->add(antlr::RefAST(primary_expr_tail_AST)))); } else { primary_expr_tail_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MFCALL,"mfcall")))->add(antlr::RefAST(primary_expr_tail_AST)))); } currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } break; } case antlr::Token::EOF_TYPE: case AND_OP: case DO: case ELSE: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case OF: case OR_OP: case THEN: case UNTIL: case XOR_OP: case COMMA: case COLON: case END_U: case DEC: case INC: case RBRACE: case SLASH: case RSQUARE: case RCURLY: case ASTERIX: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_AND: case LOG_OR: case QUESTION: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } primary_expr_tail_AST = RefDNode(currentAST.root); } else if ((LA(1) == LBRACE) && (_tokenSet_4.member(LA(2)))) { assign_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_tail_AST = RefDNode(currentAST.root); } else if ((LA(1) == LSQUARE) && (_tokenSet_11.member(LA(2)))) { array_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_tail_AST = RefDNode(currentAST.root); } else if ((LA(1) == LCURLY) && (_tokenSet_13.member(LA(2)))) { struct_def(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_tail_AST = RefDNode(currentAST.root); } else if ((LA(1) == LSQUARE) && (LA(2) == RSQUARE)) { ls = LT(1); ls_AST = astFactory->create(ls); match(LSQUARE); RefDNode tmp191_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp191_AST = astFactory->create(LT(1)); } match(RSQUARE); if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); primary_expr_tail_AST=astFactory->create(GDLNULL,"GDLNULL[]"); primary_expr_tail_AST->SetLine( ls_AST->getLine()); currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } } else if ((LA(1) == LCURLY) && (LA(2) == RCURLY)) { lc = LT(1); lc_AST = astFactory->create(lc); match(LCURLY); RefDNode tmp192_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp192_AST = astFactory->create(LT(1)); } match(RCURLY); if ( inputState->guessing==0 ) { primary_expr_tail_AST = RefDNode(currentAST.root); primary_expr_tail_AST=astFactory->create(GDLNULL,"GDLNULL{}"); primary_expr_tail_AST->SetLine( lc_AST->getLine()); currentAST.root = primary_expr_tail_AST; if ( primary_expr_tail_AST!=RefDNode(antlr::nullAST) && primary_expr_tail_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_tail_AST->getFirstChild(); else currentAST.child = primary_expr_tail_AST; currentAST.advanceChildToEnd(); } } else { throw antlr::NoViableAltException(LT(1), getFilename()); } }}} returnAST = primary_expr_tail_AST; } void GDLParser::primary_expr_deref() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode primary_expr_deref_AST = RefDNode(antlr::nullAST); // the following needs to be updated if the symbols are rearranged (e. g. a symbol is inserted) // (it is taken from GDLParser.cpp: const antlr::BitSet GDLParser::_tokenSet_XX) const unsigned long _tokenSet_4_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 536870912UL, 4UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" LBRACE SYSVARNAME ASTERIX const antlr::BitSet _tokenSet_4(_tokenSet_4_data_,16); const unsigned long _tokenSet_5_data_[] = { 0UL, 0UL, 268435456UL, 34603008UL, 536871296UL, 4294967253UL, 5013503UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" "not" DEC INC LBRACE LSQUARE SYSVARNAME LCURLY // CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL // PLUS MINUS LOG_NEG const antlr::BitSet _tokenSet_5(_tokenSet_5_data_,16); const unsigned long _tokenSet_23_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 536870912UL, 21UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" LBRACE LSQUARE SYSVARNAME LCURLY ASTERIX const antlr::BitSet _tokenSet_23(_tokenSet_23_data_,16); const unsigned long _tokenSet_24_data_[] = { 2UL, 0UL, 805306368UL, 2549424140UL, 4026532283UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF IDENTIFIER "and" "do" "else" "eq" "ge" "gt" "inherits" "le" "lt" // "mod" "ne" "not" "of" "or" "then" "until" "xor" COMMA COLON END_U DEC // INC MEMBER LBRACE RBRACE SLASH LSQUARE RSQUARE SYSVARNAME EXCLAMATION // LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 // CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 // CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 // CONSTANT_INT CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI // CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 // CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 // CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE // CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I // CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT // ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 MATRIX_OP2 PLUS MINUS LTMARK // GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet _tokenSet_24(_tokenSet_24_data_,16); bool parent; bool skip; int markIn = mark(); inputState->guessing++; bool tailLa1La2 = (_tokenSet_23.member(LA(1))) && (_tokenSet_24.member(LA(2))); bool derefLa1La2 = (_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))); if ( derefLa1La2) { skip = false; try { deref_dot_expr_keeplast(); } catch (antlr::RecognitionException& pe) { skip = true; } } else skip = true; if( skip && tailLa1La2) { rewind( markIn); inputState->guessing--; primary_expr_tail(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_deref_AST = RefDNode(currentAST.root); returnAST = primary_expr_deref_AST; return; } bool arrayexpr_mfcallParse = false; bool function_callParse = false; int mark2nd = mark(); bool baseclass_methodParse = true; try { { baseclass_method(); } } catch (antlr::RecognitionException& pe) { baseclass_methodParse = false; } rewind( mark2nd); if( !baseclass_methodParse) { int mark3rd = mark(); arrayexpr_mfcallParse = true; try { { match(IDENTIFIER); match(LBRACE); expr(); { // ( ... )* for (;;) { if ((LA(1) == COMMA)) { match(COMMA); expr(); } else { break; } } } // ( ... )* match(RBRACE); } } catch (antlr::RecognitionException& pe) { arrayexpr_mfcallParse = false; } rewind( mark3rd); if( !arrayexpr_mfcallParse) { function_callParse = true; try { { formal_function_call(); } } catch (antlr::RecognitionException& pe) { function_callParse = false; } if( !function_callParse && tailLa1La2) { rewind( markIn); inputState->guessing--; primary_expr_tail(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_deref_AST = RefDNode(currentAST.root); returnAST = primary_expr_deref_AST; return; } } } rewind( markIn); inputState->guessing--; if (((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))))&&(baseclass_methodParse)) { deref_dot_expr_keeplast(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } baseclass_method(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_deref_AST = RefDNode(currentAST.root); primary_expr_deref_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MFCALL_PARENT,"mfcall::")))->add(antlr::RefAST(primary_expr_deref_AST)))); currentAST.root = primary_expr_deref_AST; if ( primary_expr_deref_AST!=RefDNode(antlr::nullAST) && primary_expr_deref_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_deref_AST->getFirstChild(); else currentAST.child = primary_expr_deref_AST; currentAST.advanceChildToEnd(); } primary_expr_deref_AST = RefDNode(currentAST.root); } else if (((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))))&&(arrayexpr_mfcallParse)) { arrayexpr_mfcall(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_deref_AST = RefDNode(currentAST.root); } else if (((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2))))&&(function_callParse)) { deref_dot_expr_keeplast(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } formal_function_call(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { primary_expr_deref_AST = RefDNode(currentAST.root); primary_expr_deref_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(MFCALL,"mfcall")))->add(antlr::RefAST(primary_expr_deref_AST)))); currentAST.root = primary_expr_deref_AST; if ( primary_expr_deref_AST!=RefDNode(antlr::nullAST) && primary_expr_deref_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_deref_AST->getFirstChild(); else currentAST.child = primary_expr_deref_AST; currentAST.advanceChildToEnd(); } primary_expr_deref_AST = RefDNode(currentAST.root); } else if ((_tokenSet_23.member(LA(1))) && (_tokenSet_24.member(LA(2)))) { primary_expr_tail(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_deref_AST = RefDNode(currentAST.root); } else { throw antlr::NoViableAltException(LT(1), getFilename()); } returnAST = primary_expr_deref_AST; } void GDLParser::primary_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode primary_expr_AST = RefDNode(antlr::nullAST); antlr::RefToken sl = antlr::nullToken; RefDNode sl_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case STRING_LITERAL: { sl = LT(1); if ( inputState->guessing == 0 ) { sl_AST = astFactory->create(sl); } match(STRING_LITERAL); if ( inputState->guessing==0 ) { primary_expr_AST = RefDNode(currentAST.root); primary_expr_AST=astFactory->create(CONSTANT,sl->getText()); primary_expr_AST->Text2String(); primary_expr_AST->SetLine( sl_AST->getLine()); currentAST.root = primary_expr_AST; if ( primary_expr_AST!=RefDNode(antlr::nullAST) && primary_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = primary_expr_AST->getFirstChild(); else currentAST.child = primary_expr_AST; currentAST.advanceChildToEnd(); } break; } case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: { numeric_constant(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_AST = RefDNode(currentAST.root); break; } case IDENTIFIER: case INHERITS: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case ASTERIX: { primary_expr_deref(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } primary_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = primary_expr_AST; } void GDLParser::decinc_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode decinc_expr_AST = RefDNode(antlr::nullAST); antlr::RefToken i = antlr::nullToken; RefDNode i_AST = RefDNode(antlr::nullAST); antlr::RefToken d = antlr::nullToken; RefDNode d_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case IDENTIFIER: case INHERITS: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: { primary_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { switch ( LA(1)) { case INC: { i = LT(1); if ( inputState->guessing == 0 ) { i_AST = astFactory->create(i); astFactory->makeASTRoot(currentAST, antlr::RefAST(i_AST)); } match(INC); if ( inputState->guessing==0 ) { i_AST->setType( POSTINC); i_AST->setText( "_++"); } break; } case DEC: { d = LT(1); if ( inputState->guessing == 0 ) { d_AST = astFactory->create(d); astFactory->makeASTRoot(currentAST, antlr::RefAST(d_AST)); } match(DEC); if ( inputState->guessing==0 ) { d_AST->setType( POSTDEC); d_AST->setText( "_--"); } break; } case antlr::Token::EOF_TYPE: case AND_OP: case DO: case ELSE: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case OF: case OR_OP: case THEN: case UNTIL: case XOR_OP: case COMMA: case COLON: case END_U: case RBRACE: case SLASH: case RSQUARE: case RCURLY: case ASTERIX: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_AND: case LOG_OR: case QUESTION: { break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } decinc_expr_AST = RefDNode(currentAST.root); break; } case INC: { RefDNode tmp193_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp193_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp193_AST)); } match(INC); primary_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } decinc_expr_AST = RefDNode(currentAST.root); break; } case DEC: { RefDNode tmp194_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp194_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp194_AST)); } match(DEC); primary_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } decinc_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = decinc_expr_AST; } void GDLParser::exponential_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode exponential_expr_AST = RefDNode(antlr::nullAST); decinc_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == POW)) { RefDNode tmp195_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp195_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp195_AST)); } match(POW); decinc_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop231; } } _loop231:; } // ( ... )* exponential_expr_AST = RefDNode(currentAST.root); returnAST = exponential_expr_AST; } void GDLParser::multiplicative_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode multiplicative_expr_AST = RefDNode(antlr::nullAST); exponential_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((_tokenSet_25.member(LA(1)))) { { switch ( LA(1)) { case ASTERIX: { RefDNode tmp196_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp196_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp196_AST)); } match(ASTERIX); break; } case MATRIX_OP1: { RefDNode tmp197_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp197_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp197_AST)); } match(MATRIX_OP1); break; } case MATRIX_OP2: { RefDNode tmp198_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp198_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp198_AST)); } match(MATRIX_OP2); break; } case SLASH: { RefDNode tmp199_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp199_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp199_AST)); } match(SLASH); break; } case MOD_OP: { RefDNode tmp200_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp200_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp200_AST)); } match(MOD_OP); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } exponential_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop235; } } _loop235:; } // ( ... )* multiplicative_expr_AST = RefDNode(currentAST.root); returnAST = multiplicative_expr_AST; } void GDLParser::signed_multiplicative_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode signed_multiplicative_expr_AST = RefDNode(antlr::nullAST); antlr::RefToken m = antlr::nullToken; RefDNode m_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case PLUS: { match(PLUS); multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } signed_multiplicative_expr_AST = RefDNode(currentAST.root); break; } case MINUS: { m = LT(1); if ( inputState->guessing == 0 ) { m_AST = astFactory->create(m); astFactory->makeASTRoot(currentAST, antlr::RefAST(m_AST)); } match(MINUS); multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } if ( inputState->guessing==0 ) { m_AST->setType( UMINUS); m_AST->setText( "u-"); } signed_multiplicative_expr_AST = RefDNode(currentAST.root); break; } case IDENTIFIER: case INHERITS: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: { multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } signed_multiplicative_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = signed_multiplicative_expr_AST; } void GDLParser::additive_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode additive_expr_AST = RefDNode(antlr::nullAST); { switch ( LA(1)) { case IDENTIFIER: case INHERITS: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: case PLUS: case MINUS: { signed_multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case NOT_OP: case LOG_NEG: { neg_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { // ( ... )* for (;;) { if (((LA(1) >= PLUS && LA(1) <= GTMARK))) { { switch ( LA(1)) { case PLUS: { RefDNode tmp202_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp202_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp202_AST)); } match(PLUS); break; } case MINUS: { RefDNode tmp203_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp203_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp203_AST)); } match(MINUS); break; } case LTMARK: { RefDNode tmp204_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp204_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp204_AST)); } match(LTMARK); break; } case GTMARK: { RefDNode tmp205_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp205_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp205_AST)); } match(GTMARK); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } { switch ( LA(1)) { case IDENTIFIER: case INHERITS: case DEC: case INC: case LBRACE: case LSQUARE: case SYSVARNAME: case LCURLY: case CONSTANT_HEX_BYTE: case CONSTANT_HEX_LONG: case CONSTANT_HEX_LONG64: case CONSTANT_HEX_INT: case CONSTANT_HEX_I: case CONSTANT_HEX_ULONG: case CONSTANT_HEX_ULONG64: case CONSTANT_HEX_UI: case CONSTANT_HEX_UINT: case CONSTANT_BYTE: case CONSTANT_LONG: case CONSTANT_LONG64: case CONSTANT_INT: case CONSTANT_I: case CONSTANT_ULONG: case CONSTANT_ULONG64: case CONSTANT_UI: case CONSTANT_UINT: case CONSTANT_OCT_BYTE: case CONSTANT_OCT_LONG: case CONSTANT_OCT_LONG64: case CONSTANT_OCT_INT: case CONSTANT_OCT_I: case CONSTANT_OCT_ULONG: case CONSTANT_OCT_ULONG64: case CONSTANT_OCT_UI: case CONSTANT_OCT_UINT: case CONSTANT_FLOAT: case CONSTANT_DOUBLE: case CONSTANT_BIN_BYTE: case CONSTANT_BIN_LONG: case CONSTANT_BIN_LONG64: case CONSTANT_BIN_INT: case CONSTANT_BIN_I: case CONSTANT_BIN_ULONG: case CONSTANT_BIN_ULONG64: case CONSTANT_BIN_UI: case CONSTANT_BIN_UINT: case ASTERIX: case STRING_LITERAL: { multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } case NOT_OP: case LOG_NEG: { neg_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } } else { goto _loop242; } } _loop242:; } // ( ... )* additive_expr_AST = RefDNode(currentAST.root); returnAST = additive_expr_AST; } void GDLParser::neg_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode neg_expr_AST = RefDNode(antlr::nullAST); switch ( LA(1)) { case NOT_OP: { RefDNode tmp206_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp206_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp206_AST)); } match(NOT_OP); multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } neg_expr_AST = RefDNode(currentAST.root); break; } case LOG_NEG: { RefDNode tmp207_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp207_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp207_AST)); } match(LOG_NEG); multiplicative_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } neg_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } returnAST = neg_expr_AST; } void GDLParser::relational_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode relational_expr_AST = RefDNode(antlr::nullAST); additive_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((_tokenSet_26.member(LA(1)))) { { switch ( LA(1)) { case EQ_OP: { RefDNode tmp208_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp208_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp208_AST)); } match(EQ_OP); break; } case NE_OP: { RefDNode tmp209_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp209_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp209_AST)); } match(NE_OP); break; } case LE_OP: { RefDNode tmp210_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp210_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp210_AST)); } match(LE_OP); break; } case LT_OP: { RefDNode tmp211_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp211_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp211_AST)); } match(LT_OP); break; } case GE_OP: { RefDNode tmp212_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp212_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp212_AST)); } match(GE_OP); break; } case GT_OP: { RefDNode tmp213_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp213_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp213_AST)); } match(GT_OP); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } additive_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop247; } } _loop247:; } // ( ... )* relational_expr_AST = RefDNode(currentAST.root); returnAST = relational_expr_AST; } void GDLParser::boolean_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode boolean_expr_AST = RefDNode(antlr::nullAST); relational_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == AND_OP || LA(1) == OR_OP || LA(1) == XOR_OP)) { { switch ( LA(1)) { case AND_OP: { RefDNode tmp214_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp214_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp214_AST)); } match(AND_OP); break; } case OR_OP: { RefDNode tmp215_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp215_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp215_AST)); } match(OR_OP); break; } case XOR_OP: { RefDNode tmp216_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp216_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp216_AST)); } match(XOR_OP); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } relational_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop251; } } _loop251:; } // ( ... )* boolean_expr_AST = RefDNode(currentAST.root); returnAST = boolean_expr_AST; } void GDLParser::logical_expr() { returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode logical_expr_AST = RefDNode(antlr::nullAST); boolean_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } { // ( ... )* for (;;) { if ((LA(1) == LOG_AND || LA(1) == LOG_OR)) { { switch ( LA(1)) { case LOG_AND: { RefDNode tmp217_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp217_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp217_AST)); } match(LOG_AND); break; } case LOG_OR: { RefDNode tmp218_AST = RefDNode(antlr::nullAST); if ( inputState->guessing == 0 ) { tmp218_AST = astFactory->create(LT(1)); astFactory->makeASTRoot(currentAST, antlr::RefAST(tmp218_AST)); } match(LOG_OR); break; } default: { throw antlr::NoViableAltException(LT(1), getFilename()); } } } boolean_expr(); if (inputState->guessing==0) { astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } } else { goto _loop255; } } _loop255:; } // ( ... )* logical_expr_AST = RefDNode(currentAST.root); returnAST = logical_expr_AST; } void GDLParser::initializeASTFactory( antlr::ASTFactory& factory ) { factory.setMaxNodeType(237); } const char* GDLParser::tokenNames[] = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "ALL", "ASSIGN", "ASSIGN_INPLACE", "ASSIGN_REPLACE", "ASSIGN_ARRAYEXPR_MFCALL", "ARRAYDEF", "ARRAYDEF_CONST", "ARRAYDEF_GENERALIZED_INDGEN", "ARRAYIX", "ARRAYIX_ALL", "ARRAYIX_ORANGE", "ARRAYIX_RANGE", "ARRAYIX_ORANGE_S", "ARRAYIX_RANGE_S", "ARRAYEXPR", "ARRAYEXPR_FCALL", "ARRAYEXPR_MFCALL", "BLOCK", "BREAK", "CSBLOCK", "CONTINUE", "COMMONDECL", "COMMONDEF", "CONSTANT", "DEREF", "ELSEBLK", "EXPR", "\"for\"", "FOR_STEP", "\"foreach\"", "FOREACH_INDEX", "FOR_LOOP", "FOR_STEP_LOOP", "FOREACH_LOOP", "FOREACH_INDEX_LOOP", "FCALL", "FCALL_LIB", "FCALL_LIB_DIRECT", "FCALL_LIB_N_ELEMENTS", "FCALL_LIB_RETNEW", "GDLNULL", "IF_ELSE", "KEYDECL", "KEYDEF", "KEYDEF_REF", "KEYDEF_REF_CHECK", "KEYDEF_REF_EXPR", "LABEL", "MPCALL", "MPCALL_PARENT", "MFCALL", "MFCALL_LIB", "MFCALL_LIB_RETNEW", "MFCALL_PARENT", "MFCALL_PARENT_LIB", "MFCALL_PARENT_LIB_RETNEW", "NOP", "NSTRUC", "NSTRUC_REF", "ON_IOERROR_NULL", "PCALL", "PCALL_LIB", "PARADECL", "PARAEXPR", "PARAEXPR_VN", "DEC_REF_CHECK", "INC_REF_CHECK", "POSTDEC", "POSTINC", "DECSTATEMENT", "INCSTATEMENT", "REF", "REF_VN", "REF_CHECK", "REF_CHECK_VN", "REF_EXPR", "REF_EXPR_VN", "\"repeat\"", "REPEAT_LOOP", "RETURN", "RETF", "RETP", "STRUC", "SYSVAR", "UMINUS", "VAR", "VARPTR", "\"while\"", "IDENTIFIER", "\"and\"", "\"begin\"", "\"case\"", "\"common\"", "\"compile_opt\"", "\"do\"", "\"else\"", "\"end\"", "\"endcase\"", "\"endelse\"", "\"endfor\"", "\"endforeach\"", "\"endif\"", "\"endrep\"", "\"endswitch\"", "\"endwhile\"", "\"eq\"", "\"forward_function\"", "\"function\"", "\"ge\"", "\"goto\"", "\"gt\"", "\"if\"", "\"inherits\"", "\"le\"", "\"lt\"", "\"mod\"", "\"ne\"", "\"not\"", "\"of\"", "\"on_ioerror\"", "\"or\"", "\"pro\"", "\"switch\"", "\"then\"", "\"until\"", "\"xor\"", "METHOD", "COMMA", "COLON", "END_U", "EQUAL", "DEC", "INC", "AND_OP_EQ", "ASTERIX_EQ", "EQ_OP_EQ", "GE_OP_EQ", "GTMARK_EQ", "GT_OP_EQ", "LE_OP_EQ", "LTMARK_EQ", "LT_OP_EQ", "MATRIX_OP1_EQ", "MATRIX_OP2_EQ", "MINUS_EQ", "MOD_OP_EQ", "NE_OP_EQ", "OR_OP_EQ", "PLUS_EQ", "POW_EQ", "SLASH_EQ", "XOR_OP_EQ", "MEMBER", "LBRACE", "RBRACE", "SLASH", "LSQUARE", "RSQUARE", "SYSVARNAME", "EXCLAMATION", "LCURLY", "RCURLY", "CONSTANT_HEX_BYTE", "CONSTANT_HEX_LONG", "CONSTANT_HEX_LONG64", "CONSTANT_HEX_INT", "CONSTANT_HEX_I", "CONSTANT_HEX_ULONG", "CONSTANT_HEX_ULONG64", "CONSTANT_HEX_UI", "CONSTANT_HEX_UINT", "CONSTANT_BYTE", "CONSTANT_LONG", "CONSTANT_LONG64", "CONSTANT_INT", "CONSTANT_I", "CONSTANT_ULONG", "CONSTANT_ULONG64", "CONSTANT_UI", "CONSTANT_UINT", "CONSTANT_OCT_BYTE", "CONSTANT_OCT_LONG", "CONSTANT_OCT_LONG64", "CONSTANT_OCT_INT", "CONSTANT_OCT_I", "CONSTANT_OCT_ULONG", "CONSTANT_OCT_ULONG64", "CONSTANT_OCT_UI", "CONSTANT_OCT_UINT", "CONSTANT_FLOAT", "CONSTANT_DOUBLE", "CONSTANT_BIN_BYTE", "CONSTANT_BIN_LONG", "CONSTANT_BIN_LONG64", "CONSTANT_BIN_INT", "CONSTANT_BIN_I", "CONSTANT_BIN_ULONG", "CONSTANT_BIN_ULONG64", "CONSTANT_BIN_UI", "CONSTANT_BIN_UINT", "ASTERIX", "DOT", "STRING_LITERAL", "POW", "MATRIX_OP1", "MATRIX_OP2", "PLUS", "MINUS", "LTMARK", "GTMARK", "LOG_NEG", "LOG_AND", "LOG_OR", "QUESTION", "STRING", "INCLUDE", "EOL", "W", "D", "L", "H", "O", "B", "EXP", "DBL_E", "DBL", "CONSTANT_OR_STRING_LITERAL", "COMMENT", "END_MARKER", "WHITESPACE", "SKIP_LINES", "CONT_STATEMENT", "END_OF_LINE", "MAX_TOKEN_NUMBER", 0 }; const unsigned long GDLParser::_tokenSet_0_data_[] = { 2147483650UL, 2UL, 3624009728UL, 1746583555UL, 536871328UL, 4UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF "for" "foreach" "repeat" "while" IDENTIFIER "begin" "case" "common" // "compile_opt" "forward_function" "function" "goto" "if" "inherits" "on_ioerror" // "pro" "switch" END_U DEC INC LBRACE SYSVARNAME ASTERIX const antlr::BitSet GDLParser::_tokenSet_0(_tokenSet_0_data_,16); const unsigned long GDLParser::_tokenSet_1_data_[] = { 2147483650UL, 2UL, 3624009728UL, 1780146171UL, 536871328UL, 4294967253UL, 5005311UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF "for" "foreach" "repeat" "while" IDENTIFIER "begin" "case" "common" // "compile_opt" "else" "end" "endcase" "endelse" "endfor" "endforeach" // "endif" "endrep" "endswitch" "endwhile" "forward_function" "function" // "goto" "if" "inherits" "not" "on_ioerror" "pro" "switch" END_U DEC INC // LBRACE LSQUARE SYSVARNAME LCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG // CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG // CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE // CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I CONSTANT_ULONG // CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG // CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG // CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT // CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX STRING_LITERAL PLUS MINUS // LOG_NEG const antlr::BitSet GDLParser::_tokenSet_1(_tokenSet_1_data_,16); const unsigned long GDLParser::_tokenSet_2_data_[] = { 2147483648UL, 2UL, 3624009728UL, 1209679875UL, 536871296UL, 4UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // "for" "foreach" "repeat" "while" IDENTIFIER "begin" "case" "common" // "compile_opt" "forward_function" "goto" "if" "inherits" "on_ioerror" // "switch" DEC INC LBRACE SYSVARNAME ASTERIX const antlr::BitSet GDLParser::_tokenSet_2(_tokenSet_2_data_,16); const unsigned long GDLParser::_tokenSet_3_data_[] = { 2147483648UL, 2UL, 3624009728UL, 1243234307UL, 1073741800UL, 4294967253UL, 5013503UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // "for" "foreach" "repeat" "while" IDENTIFIER "begin" "case" "common" // "compile_opt" "forward_function" "goto" "if" "inherits" "not" "on_ioerror" // "switch" COMMA END_U EQUAL DEC INC AND_OP_EQ ASTERIX_EQ EQ_OP_EQ GE_OP_EQ // GTMARK_EQ GT_OP_EQ LE_OP_EQ LTMARK_EQ LT_OP_EQ MATRIX_OP1_EQ MATRIX_OP2_EQ // MINUS_EQ MOD_OP_EQ NE_OP_EQ OR_OP_EQ PLUS_EQ POW_EQ SLASH_EQ XOR_OP_EQ // MEMBER LBRACE LSQUARE SYSVARNAME LCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG // CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG // CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE // CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I CONSTANT_ULONG // CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG // CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG // CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT // CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL PLUS MINUS // LOG_NEG const antlr::BitSet GDLParser::_tokenSet_3(_tokenSet_3_data_,16); const unsigned long GDLParser::_tokenSet_4_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 536870912UL, 4UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" LBRACE SYSVARNAME ASTERIX const antlr::BitSet GDLParser::_tokenSet_4(_tokenSet_4_data_,16); const unsigned long GDLParser::_tokenSet_5_data_[] = { 0UL, 0UL, 268435456UL, 34603008UL, 536871296UL, 4294967253UL, 5013503UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" "not" DEC INC LBRACE LSQUARE SYSVARNAME LCURLY // CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL // PLUS MINUS LOG_NEG const antlr::BitSet GDLParser::_tokenSet_5(_tokenSet_5_data_,16); const unsigned long GDLParser::_tokenSet_6_data_[] = { 0UL, 0UL, 268435456UL, 34603008UL, 1073741760UL, 4294967253UL, 5013503UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" "not" EQUAL DEC INC AND_OP_EQ ASTERIX_EQ EQ_OP_EQ // GE_OP_EQ GTMARK_EQ GT_OP_EQ LE_OP_EQ LTMARK_EQ LT_OP_EQ MATRIX_OP1_EQ // MATRIX_OP2_EQ MINUS_EQ MOD_OP_EQ NE_OP_EQ OR_OP_EQ PLUS_EQ POW_EQ SLASH_EQ // XOR_OP_EQ MEMBER LBRACE LSQUARE SYSVARNAME LCURLY CONSTANT_HEX_BYTE // CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I // CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT // CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I // CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE // CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I // CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT // CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL PLUS MINUS // LOG_NEG const antlr::BitSet GDLParser::_tokenSet_6(_tokenSet_6_data_,16); const unsigned long GDLParser::_tokenSet_7_data_[] = { 0UL, 0UL, 0UL, 8UL, 41UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // "else" "until" COMMA END_U const antlr::BitSet GDLParser::_tokenSet_7(_tokenSet_7_data_,12); const unsigned long GDLParser::_tokenSet_8_data_[] = { 0UL, 0UL, 268435456UL, 34603016UL, 536871296UL, 4294967253UL, 5005311UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "else" "inherits" "not" DEC INC LBRACE LSQUARE SYSVARNAME // LCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX STRING_LITERAL // PLUS MINUS LOG_NEG const antlr::BitSet GDLParser::_tokenSet_8(_tokenSet_8_data_,16); const unsigned long GDLParser::_tokenSet_9_data_[] = { 2147483650UL, 2UL, 4160880640UL, 4294967295UL, 2684354979UL, 4294967253UL, 5005311UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF "for" "foreach" "repeat" "while" IDENTIFIER "and" "begin" "case" // "common" "compile_opt" "do" "else" "end" "endcase" "endelse" "endfor" // "endforeach" "endif" "endrep" "endswitch" "endwhile" "eq" "forward_function" // "function" "ge" "goto" "gt" "if" "inherits" "le" "lt" "mod" "ne" "not" // "of" "on_ioerror" "or" "pro" "switch" "then" "until" "xor" END_U DEC // INC LBRACE SLASH LSQUARE SYSVARNAME LCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG // CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG // CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE // CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I CONSTANT_ULONG // CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG // CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG // CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT // CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX STRING_LITERAL PLUS MINUS // LOG_NEG const antlr::BitSet GDLParser::_tokenSet_9(_tokenSet_9_data_,16); const unsigned long GDLParser::_tokenSet_10_data_[] = { 2147483648UL, 2UL, 4160880640UL, 4294967295UL, 3UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // "for" "foreach" "repeat" "while" IDENTIFIER "and" "begin" "case" "common" // "compile_opt" "do" "else" "end" "endcase" "endelse" "endfor" "endforeach" // "endif" "endrep" "endswitch" "endwhile" "eq" "forward_function" "function" // "ge" "goto" "gt" "if" "inherits" "le" "lt" "mod" "ne" "not" "of" "on_ioerror" // "or" "pro" "switch" "then" "until" "xor" const antlr::BitSet GDLParser::_tokenSet_10(_tokenSet_10_data_,12); const unsigned long GDLParser::_tokenSet_11_data_[] = { 0UL, 0UL, 268435456UL, 34603008UL, 536871296UL, 4294967253UL, 5005311UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" "not" DEC INC LBRACE LSQUARE SYSVARNAME LCURLY // CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX STRING_LITERAL // PLUS MINUS LOG_NEG const antlr::BitSet GDLParser::_tokenSet_11(_tokenSet_11_data_,16); const unsigned long GDLParser::_tokenSet_12_data_[] = { 0UL, 0UL, 805306368UL, 334831624UL, 4026532267UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "and" "else" "eq" "ge" "gt" "inherits" "le" "lt" "mod" "ne" // "not" "or" "until" "xor" COMMA END_U DEC INC MEMBER LBRACE RBRACE SLASH // LSQUARE RSQUARE SYSVARNAME EXCLAMATION LCURLY RCURLY CONSTANT_HEX_BYTE // CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I // CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT // CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I // CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE // CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I // CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT // CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 // MATRIX_OP2 PLUS MINUS LTMARK GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLParser::_tokenSet_12(_tokenSet_12_data_,16); const unsigned long GDLParser::_tokenSet_13_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 0UL, 12UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" SYSVARNAME EXCLAMATION const antlr::BitSet GDLParser::_tokenSet_13(_tokenSet_13_data_,12); const unsigned long GDLParser::_tokenSet_14_data_[] = { 2UL, 0UL, 805306368UL, 334831616UL, 2952790410UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF IDENTIFIER "and" "eq" "ge" "gt" "inherits" "le" "lt" "mod" "ne" // "not" "or" "xor" COMMA DEC INC MEMBER LBRACE SLASH LSQUARE RSQUARE SYSVARNAME // EXCLAMATION LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 // CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 // CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 // CONSTANT_INT CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI // CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 // CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 // CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE // CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I // CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT // ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 MATRIX_OP2 PLUS MINUS LTMARK // GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLParser::_tokenSet_14(_tokenSet_14_data_,16); const unsigned long GDLParser::_tokenSet_15_data_[] = { 0UL, 0UL, 268435456UL, 34603008UL, 536871296UL, 4294967261UL, 5005311UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" "not" DEC INC LBRACE LSQUARE SYSVARNAME EXCLAMATION // LCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX STRING_LITERAL // PLUS MINUS LOG_NEG const antlr::BitSet GDLParser::_tokenSet_15(_tokenSet_15_data_,16); const unsigned long GDLParser::_tokenSet_16_data_[] = { 0UL, 0UL, 805306368UL, 334831616UL, 2952790426UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "and" "eq" "ge" "gt" "inherits" "le" "lt" "mod" "ne" "not" // "or" "xor" COMMA COLON DEC INC MEMBER LBRACE SLASH LSQUARE RSQUARE SYSVARNAME // EXCLAMATION LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 // CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 // CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 // CONSTANT_INT CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI // CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 // CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 // CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE // CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I // CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT // ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 MATRIX_OP2 PLUS MINUS LTMARK // GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLParser::_tokenSet_16(_tokenSet_16_data_,16); const unsigned long GDLParser::_tokenSet_17_data_[] = { 0UL, 0UL, 805306368UL, 334831616UL, 4026532250UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "and" "eq" "ge" "gt" "inherits" "le" "lt" "mod" "ne" "not" // "or" "xor" COMMA COLON DEC INC MEMBER LBRACE RBRACE SLASH LSQUARE RSQUARE // SYSVARNAME EXCLAMATION LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG // CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG // CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE // CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I CONSTANT_ULONG // CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG // CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG // CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT // CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 // MATRIX_OP2 PLUS MINUS LTMARK GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLParser::_tokenSet_17(_tokenSet_17_data_,16); const unsigned long GDLParser::_tokenSet_18_data_[] = { 0UL, 0UL, 0UL, 0UL, 1073741848UL, 2UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // COMMA COLON RBRACE RSQUARE const antlr::BitSet GDLParser::_tokenSet_18(_tokenSet_18_data_,12); const unsigned long GDLParser::_tokenSet_19_data_[] = { 0UL, 0UL, 805306368UL, 334831616UL, 4026532234UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "and" "eq" "ge" "gt" "inherits" "le" "lt" "mod" "ne" "not" // "or" "xor" COMMA DEC INC MEMBER LBRACE RBRACE SLASH LSQUARE RSQUARE // SYSVARNAME EXCLAMATION LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG // CONSTANT_HEX_LONG64 CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG // CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE // CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT CONSTANT_I CONSTANT_ULONG // CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG // CONSTANT_OCT_LONG64 CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG // CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT // CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 // CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 // CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 // MATRIX_OP2 PLUS MINUS LTMARK GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLParser::_tokenSet_19(_tokenSet_19_data_,16); const unsigned long GDLParser::_tokenSet_20_data_[] = { 0UL, 0UL, 268435456UL, 0UL, 536870912UL, 12UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER LBRACE SYSVARNAME EXCLAMATION const antlr::BitSet GDLParser::_tokenSet_20(_tokenSet_20_data_,12); const unsigned long GDLParser::_tokenSet_21_data_[] = { 0UL, 0UL, 0UL, 8UL, 536870957UL, 1UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // "else" "until" METHOD COMMA END_U LBRACE LSQUARE const antlr::BitSet GDLParser::_tokenSet_21(_tokenSet_21_data_,12); const unsigned long GDLParser::_tokenSet_22_data_[] = { 2UL, 0UL, 805306368UL, 2549424140UL, 4026532283UL, 4294967287UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF IDENTIFIER "and" "do" "else" "eq" "ge" "gt" "inherits" "le" "lt" // "mod" "ne" "not" "of" "or" "then" "until" "xor" COMMA COLON END_U DEC // INC MEMBER LBRACE RBRACE SLASH LSQUARE RSQUARE SYSVARNAME LCURLY RCURLY // CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 CONSTANT_HEX_INT // CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 CONSTANT_HEX_UI // CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 CONSTANT_INT // CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI CONSTANT_UINT // CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 CONSTANT_OCT_INT // CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 CONSTANT_OCT_UI // CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE CONSTANT_BIN_LONG // CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I CONSTANT_BIN_ULONG // CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT ASTERIX DOT STRING_LITERAL // POW MATRIX_OP1 MATRIX_OP2 PLUS MINUS LTMARK GTMARK LOG_NEG LOG_AND LOG_OR // QUESTION const antlr::BitSet GDLParser::_tokenSet_22(_tokenSet_22_data_,16); const unsigned long GDLParser::_tokenSet_23_data_[] = { 0UL, 0UL, 268435456UL, 1048576UL, 536870912UL, 21UL, 4096UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // IDENTIFIER "inherits" LBRACE LSQUARE SYSVARNAME LCURLY ASTERIX const antlr::BitSet GDLParser::_tokenSet_23(_tokenSet_23_data_,16); const unsigned long GDLParser::_tokenSet_24_data_[] = { 2UL, 0UL, 805306368UL, 2549424140UL, 4026532283UL, 4294967295UL, 67108863UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // EOF IDENTIFIER "and" "do" "else" "eq" "ge" "gt" "inherits" "le" "lt" // "mod" "ne" "not" "of" "or" "then" "until" "xor" COMMA COLON END_U DEC // INC MEMBER LBRACE RBRACE SLASH LSQUARE RSQUARE SYSVARNAME EXCLAMATION // LCURLY RCURLY CONSTANT_HEX_BYTE CONSTANT_HEX_LONG CONSTANT_HEX_LONG64 // CONSTANT_HEX_INT CONSTANT_HEX_I CONSTANT_HEX_ULONG CONSTANT_HEX_ULONG64 // CONSTANT_HEX_UI CONSTANT_HEX_UINT CONSTANT_BYTE CONSTANT_LONG CONSTANT_LONG64 // CONSTANT_INT CONSTANT_I CONSTANT_ULONG CONSTANT_ULONG64 CONSTANT_UI // CONSTANT_UINT CONSTANT_OCT_BYTE CONSTANT_OCT_LONG CONSTANT_OCT_LONG64 // CONSTANT_OCT_INT CONSTANT_OCT_I CONSTANT_OCT_ULONG CONSTANT_OCT_ULONG64 // CONSTANT_OCT_UI CONSTANT_OCT_UINT CONSTANT_FLOAT CONSTANT_DOUBLE CONSTANT_BIN_BYTE // CONSTANT_BIN_LONG CONSTANT_BIN_LONG64 CONSTANT_BIN_INT CONSTANT_BIN_I // CONSTANT_BIN_ULONG CONSTANT_BIN_ULONG64 CONSTANT_BIN_UI CONSTANT_BIN_UINT // ASTERIX DOT STRING_LITERAL POW MATRIX_OP1 MATRIX_OP2 PLUS MINUS LTMARK // GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLParser::_tokenSet_24(_tokenSet_24_data_,16); const unsigned long GDLParser::_tokenSet_25_data_[] = { 0UL, 0UL, 0UL, 8388608UL, 2147483648UL, 0UL, 200704UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // "mod" SLASH ASTERIX MATRIX_OP1 MATRIX_OP2 const antlr::BitSet GDLParser::_tokenSet_25(_tokenSet_25_data_,16); const unsigned long GDLParser::_tokenSet_26_data_[] = { 0UL, 0UL, 0UL, 23404544UL, 0UL, 0UL, 0UL, 0UL }; // "eq" "ge" "gt" "le" "lt" "ne" const antlr::BitSet GDLParser::_tokenSet_26(_tokenSet_26_data_,8); gdl-0.9.9/src/GDLParser.hpp000066400000000000000000000220421340051421000153500ustar00rootroot00000000000000#ifndef INC_GDLParser_hpp_ #define INC_GDLParser_hpp_ #include /* $ANTLR 2.7.7 (2006-11-01): "gdlc.g" -> "GDLParser.hpp"$ */ #include #include #include "GDLTokenTypes.hpp" #include #include #include "GDLParser.hpp" #include "str.hpp" #include "dnodefactory.hpp" #include "objects.hpp" #include "initsysvar.hpp" #include #include #include #include #include //#include "dinterpreter.hpp" // defintion in dinterpreter.cpp //void SetActualCompileOpt( unsigned int cOpt); class CUSTOM_API GDLParser : public antlr::LLkParser, public GDLTokenTypes { public: enum CompileOpt { NONE=0, DEFINT32=1, HIDDEN=2, OBSOLETE=4, STRICTARR=8, LOGICAL_PREDICATE=16, // *** functionality not implemeted yet IDL2=DEFINT32 | STRICTARR, STRICTARRSUBS=32, STATIC=64, NOSAVE=128 }; void SetCompileOpt( unsigned int cOpt) { this->compileOpt = cOpt; } private: void AddCompileOpt( const std::string &opt) { if( opt == "DEFINT32") compileOpt |= DEFINT32; else if( opt == "HIDDEN") compileOpt |= HIDDEN; else if( opt == "OBSOLETE") compileOpt |= OBSOLETE; else if( opt == "STRICTARR") compileOpt |= STRICTARR; else if( opt == "LOGICAL_PREDICATE") compileOpt |= LOGICAL_PREDICATE; else if( opt == "IDL2") compileOpt |= IDL2; else if( opt == "STRICTARRSUBS") compileOpt |= STRICTARRSUBS; else if( opt == "STATIC") compileOpt |= STATIC; else if( opt == "NOSAVE") compileOpt |= NOSAVE; else throw GDLException("Unrecognised COMPILE_OPT option: "+opt); // SetActualCompileOpt( compileOpt); } std::string subName; // name of procedure function to be compiled ("" -> all file) bool searchForPro; // true -> procedure subName, false -> function subName bool subReached; unsigned int compileOpt; bool ConstantExprNode( int t) { return (t == CONSTANT) || (t == ARRAYDEF_CONST); } public: GDLParser(antlr::TokenStream& selector, const std::string& sName, bool searchPro, // true -> search for procedure sName, false -> for function unsigned int compileOptIn): antlr::LLkParser(selector,2), subName(sName), searchForPro( searchPro), subReached(false), compileOpt(compileOptIn) { // setTokenNames(_tokenNames); } public: void initializeASTFactory( antlr::ASTFactory& factory ); protected: GDLParser(antlr::TokenBuffer& tokenBuf, int k); public: GDLParser(antlr::TokenBuffer& tokenBuf); protected: GDLParser(antlr::TokenStream& lexer, int k); public: GDLParser(antlr::TokenStream& lexer); GDLParser(const antlr::ParserSharedInputState& state); int getNumTokens() const { return GDLParser::NUM_TOKENS; } const char* getTokenName( int type ) const { if( type > getNumTokens() ) return 0; return GDLParser::tokenNames[type]; } const char* const* getTokenNames() const { return GDLParser::tokenNames; } public: void identifier(); public: void translation_unit(); public: void end_unit(); public: void forward_function(); public: void procedure_def(); public: void function_def(); public: void common_block(); public: void statement_list(); public: void interactive_compile(); public: void parameter_declaration(); public: void interactive(); public: void end_mark(); public: void interactive_statement(); public: void statement(); public: void switch_statement(); public: void expr(); public: void switch_body(); public: void endswitch_mark(); public: void endswitchelse_mark(); public: void case_statement(); public: void case_body(); public: void endcase_mark(); public: void endcaseelse_mark(); public: void identifier_list(); public: void keyword_declaration(); public: std::string object_name(); public: void compile_opt(); public: void endforeach_mark(); public: void endfor_mark(); public: void endrep_mark(); public: void endwhile_mark(); public: void endif_mark(); public: void endelse_mark(); public: void compound_statement(); public: void label_statement(); public: void label(); public: void baseclass_method(); public: void assign_expr(); public: void deref_dot_expr_keeplast(); public: void formal_procedure_call(); public: void deref_expr(); public: void procedure_call(); public: void for_statement(); public: void foreach_statement(); public: void repeat_statement(); public: void while_statement(); public: void jump_statement(); public: void if_statement(); public: void repeat_block(); public: void while_block(); public: void for_block(); public: void foreach_block(); public: void if_block(); public: void else_block(); public: void parameter_def_list(); public: void formal_function_call(); public: void parameter_def(); public: void array_def(); public: void struct_identifier(); public: void struct_name(); public: void struct_def(); public: void named_tag_def_list(); public: void tag_def_list(); public: void tag_def(); public: void ntag_def(); public: void ntag_defs(); public: void named_tag_def_entry(); public: void numeric_constant(); public: void arrayindex_list(); public: void arrayindex(); public: void all_elements(); public: void sysvar(); public: void var(); public: void brace_expr(); public: void array_expr_1st_sub(); public: void array_expr_1st(); public: void array_expr_nth_sub(); public: void array_expr_nth(); public: void tag_array_expr_nth_sub(); public: void tag_array_expr_nth(); public: int tag_access_keeplast(); public: SizeT tag_access(); public: void deref_dot_expr(); public: bool member_function_call(); public: void member_function_call_dot(); public: void arrayexpr_mfcall(); public: void primary_expr_tail(); public: void primary_expr_deref(); public: void primary_expr(); public: void decinc_expr(); public: void exponential_expr(); public: void multiplicative_expr(); public: void signed_multiplicative_expr(); public: void additive_expr(); public: void neg_expr(); public: void relational_expr(); public: void boolean_expr(); public: void logical_expr(); public: antlr::RefAST getAST() { return antlr::RefAST(returnAST); } protected: RefDNode returnAST; private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS static const int NUM_TOKENS = 238; #else enum { NUM_TOKENS = 238 }; #endif static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; static const unsigned long _tokenSet_2_data_[]; static const antlr::BitSet _tokenSet_2; static const unsigned long _tokenSet_3_data_[]; static const antlr::BitSet _tokenSet_3; static const unsigned long _tokenSet_4_data_[]; static const antlr::BitSet _tokenSet_4; static const unsigned long _tokenSet_5_data_[]; static const antlr::BitSet _tokenSet_5; static const unsigned long _tokenSet_6_data_[]; static const antlr::BitSet _tokenSet_6; static const unsigned long _tokenSet_7_data_[]; static const antlr::BitSet _tokenSet_7; static const unsigned long _tokenSet_8_data_[]; static const antlr::BitSet _tokenSet_8; static const unsigned long _tokenSet_9_data_[]; static const antlr::BitSet _tokenSet_9; static const unsigned long _tokenSet_10_data_[]; static const antlr::BitSet _tokenSet_10; static const unsigned long _tokenSet_11_data_[]; static const antlr::BitSet _tokenSet_11; static const unsigned long _tokenSet_12_data_[]; static const antlr::BitSet _tokenSet_12; static const unsigned long _tokenSet_13_data_[]; static const antlr::BitSet _tokenSet_13; static const unsigned long _tokenSet_14_data_[]; static const antlr::BitSet _tokenSet_14; static const unsigned long _tokenSet_15_data_[]; static const antlr::BitSet _tokenSet_15; static const unsigned long _tokenSet_16_data_[]; static const antlr::BitSet _tokenSet_16; static const unsigned long _tokenSet_17_data_[]; static const antlr::BitSet _tokenSet_17; static const unsigned long _tokenSet_18_data_[]; static const antlr::BitSet _tokenSet_18; static const unsigned long _tokenSet_19_data_[]; static const antlr::BitSet _tokenSet_19; static const unsigned long _tokenSet_20_data_[]; static const antlr::BitSet _tokenSet_20; static const unsigned long _tokenSet_21_data_[]; static const antlr::BitSet _tokenSet_21; static const unsigned long _tokenSet_22_data_[]; static const antlr::BitSet _tokenSet_22; static const unsigned long _tokenSet_23_data_[]; static const antlr::BitSet _tokenSet_23; static const unsigned long _tokenSet_24_data_[]; static const antlr::BitSet _tokenSet_24; static const unsigned long _tokenSet_25_data_[]; static const antlr::BitSet _tokenSet_25; static const unsigned long _tokenSet_26_data_[]; static const antlr::BitSet _tokenSet_26; }; #endif /*INC_GDLParser_hpp_*/ gdl-0.9.9/src/GDLTokenTypes.hpp000066400000000000000000000112611340051421000162220ustar00rootroot00000000000000#ifndef INC_GDLTokenTypes_hpp_ #define INC_GDLTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "gdlc.g" -> "GDLTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API GDLTokenTypes { #endif enum { EOF_ = 1, ALL = 4, ASSIGN = 5, ASSIGN_INPLACE = 6, ASSIGN_REPLACE = 7, ASSIGN_ARRAYEXPR_MFCALL = 8, ARRAYDEF = 9, ARRAYDEF_CONST = 10, ARRAYDEF_GENERALIZED_INDGEN = 11, ARRAYIX = 12, ARRAYIX_ALL = 13, ARRAYIX_ORANGE = 14, ARRAYIX_RANGE = 15, ARRAYIX_ORANGE_S = 16, ARRAYIX_RANGE_S = 17, ARRAYEXPR = 18, ARRAYEXPR_FCALL = 19, ARRAYEXPR_MFCALL = 20, BLOCK = 21, BREAK = 22, CSBLOCK = 23, CONTINUE = 24, COMMONDECL = 25, COMMONDEF = 26, CONSTANT = 27, DEREF = 28, ELSEBLK = 29, EXPR = 30, FOR = 31, FOR_STEP = 32, FOREACH = 33, FOREACH_INDEX = 34, FOR_LOOP = 35, FOR_STEP_LOOP = 36, FOREACH_LOOP = 37, FOREACH_INDEX_LOOP = 38, FCALL = 39, FCALL_LIB = 40, FCALL_LIB_DIRECT = 41, FCALL_LIB_N_ELEMENTS = 42, FCALL_LIB_RETNEW = 43, GDLNULL = 44, IF_ELSE = 45, KEYDECL = 46, KEYDEF = 47, KEYDEF_REF = 48, KEYDEF_REF_CHECK = 49, KEYDEF_REF_EXPR = 50, LABEL = 51, MPCALL = 52, MPCALL_PARENT = 53, MFCALL = 54, MFCALL_LIB = 55, MFCALL_LIB_RETNEW = 56, MFCALL_PARENT = 57, MFCALL_PARENT_LIB = 58, MFCALL_PARENT_LIB_RETNEW = 59, NOP = 60, NSTRUC = 61, NSTRUC_REF = 62, ON_IOERROR_NULL = 63, PCALL = 64, PCALL_LIB = 65, PARADECL = 66, PARAEXPR = 67, PARAEXPR_VN = 68, DEC_REF_CHECK = 69, INC_REF_CHECK = 70, POSTDEC = 71, POSTINC = 72, DECSTATEMENT = 73, INCSTATEMENT = 74, REF = 75, REF_VN = 76, REF_CHECK = 77, REF_CHECK_VN = 78, REF_EXPR = 79, REF_EXPR_VN = 80, REPEAT = 81, REPEAT_LOOP = 82, RETURN = 83, RETF = 84, RETP = 85, STRUC = 86, SYSVAR = 87, UMINUS = 88, VAR = 89, VARPTR = 90, WHILE = 91, IDENTIFIER = 92, AND_OP = 93, BEGIN = 94, CASE = 95, COMMON = 96, COMPILE_OPT = 97, DO = 98, ELSE = 99, END = 100, ENDCASE = 101, ENDELSE = 102, ENDFOR = 103, ENDFOREACH = 104, ENDIF = 105, ENDREP = 106, ENDSWITCH = 107, ENDWHILE = 108, EQ_OP = 109, FORWARD = 110, FUNCTION = 111, GE_OP = 112, GOTO = 113, GT_OP = 114, IF = 115, INHERITS = 116, LE_OP = 117, LT_OP = 118, MOD_OP = 119, NE_OP = 120, NOT_OP = 121, OF = 122, ON_IOERROR = 123, OR_OP = 124, PRO = 125, SWITCH = 126, THEN = 127, UNTIL = 128, XOR_OP = 129, METHOD = 130, COMMA = 131, COLON = 132, END_U = 133, EQUAL = 134, DEC = 135, INC = 136, AND_OP_EQ = 137, ASTERIX_EQ = 138, EQ_OP_EQ = 139, GE_OP_EQ = 140, GTMARK_EQ = 141, GT_OP_EQ = 142, LE_OP_EQ = 143, LTMARK_EQ = 144, LT_OP_EQ = 145, MATRIX_OP1_EQ = 146, MATRIX_OP2_EQ = 147, MINUS_EQ = 148, MOD_OP_EQ = 149, NE_OP_EQ = 150, OR_OP_EQ = 151, PLUS_EQ = 152, POW_EQ = 153, SLASH_EQ = 154, XOR_OP_EQ = 155, MEMBER = 156, LBRACE = 157, RBRACE = 158, SLASH = 159, LSQUARE = 160, RSQUARE = 161, SYSVARNAME = 162, EXCLAMATION = 163, LCURLY = 164, RCURLY = 165, CONSTANT_HEX_BYTE = 166, CONSTANT_HEX_LONG = 167, CONSTANT_HEX_LONG64 = 168, CONSTANT_HEX_INT = 169, CONSTANT_HEX_I = 170, CONSTANT_HEX_ULONG = 171, CONSTANT_HEX_ULONG64 = 172, CONSTANT_HEX_UI = 173, CONSTANT_HEX_UINT = 174, CONSTANT_BYTE = 175, CONSTANT_LONG = 176, CONSTANT_LONG64 = 177, CONSTANT_INT = 178, CONSTANT_I = 179, CONSTANT_ULONG = 180, CONSTANT_ULONG64 = 181, CONSTANT_UI = 182, CONSTANT_UINT = 183, CONSTANT_OCT_BYTE = 184, CONSTANT_OCT_LONG = 185, CONSTANT_OCT_LONG64 = 186, CONSTANT_OCT_INT = 187, CONSTANT_OCT_I = 188, CONSTANT_OCT_ULONG = 189, CONSTANT_OCT_ULONG64 = 190, CONSTANT_OCT_UI = 191, CONSTANT_OCT_UINT = 192, CONSTANT_FLOAT = 193, CONSTANT_DOUBLE = 194, CONSTANT_BIN_BYTE = 195, CONSTANT_BIN_LONG = 196, CONSTANT_BIN_LONG64 = 197, CONSTANT_BIN_INT = 198, CONSTANT_BIN_I = 199, CONSTANT_BIN_ULONG = 200, CONSTANT_BIN_ULONG64 = 201, CONSTANT_BIN_UI = 202, CONSTANT_BIN_UINT = 203, ASTERIX = 204, DOT = 205, STRING_LITERAL = 206, POW = 207, MATRIX_OP1 = 208, MATRIX_OP2 = 209, PLUS = 210, MINUS = 211, LTMARK = 212, GTMARK = 213, LOG_NEG = 214, LOG_AND = 215, LOG_OR = 216, QUESTION = 217, STRING = 218, INCLUDE = 219, EOL = 220, W = 221, D = 222, L = 223, H = 224, O = 225, B = 226, EXP = 227, DBL_E = 228, DBL = 229, CONSTANT_OR_STRING_LITERAL = 230, COMMENT = 231, END_MARKER = 232, WHITESPACE = 233, SKIP_LINES = 234, CONT_STATEMENT = 235, END_OF_LINE = 236, MAX_TOKEN_NUMBER = 237, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_GDLTokenTypes_hpp_*/ gdl-0.9.9/src/GDLTokenTypes.txt000066400000000000000000000071511340051421000162550ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): gdlc.g -> GDLTokenTypes.txt$ GDL // output token vocab name ALL=4 ASSIGN=5 ASSIGN_INPLACE=6 ASSIGN_REPLACE=7 ASSIGN_ARRAYEXPR_MFCALL=8 ARRAYDEF=9 ARRAYDEF_CONST=10 ARRAYDEF_GENERALIZED_INDGEN=11 ARRAYIX=12 ARRAYIX_ALL=13 ARRAYIX_ORANGE=14 ARRAYIX_RANGE=15 ARRAYIX_ORANGE_S=16 ARRAYIX_RANGE_S=17 ARRAYEXPR=18 ARRAYEXPR_FCALL=19 ARRAYEXPR_MFCALL=20 BLOCK=21 BREAK=22 CSBLOCK=23 CONTINUE=24 COMMONDECL=25 COMMONDEF=26 CONSTANT=27 DEREF=28 ELSEBLK=29 EXPR=30 FOR="for"=31 FOR_STEP=32 FOREACH="foreach"=33 FOREACH_INDEX=34 FOR_LOOP=35 FOR_STEP_LOOP=36 FOREACH_LOOP=37 FOREACH_INDEX_LOOP=38 FCALL=39 FCALL_LIB=40 FCALL_LIB_DIRECT=41 FCALL_LIB_N_ELEMENTS=42 FCALL_LIB_RETNEW=43 GDLNULL=44 IF_ELSE=45 KEYDECL=46 KEYDEF=47 KEYDEF_REF=48 KEYDEF_REF_CHECK=49 KEYDEF_REF_EXPR=50 LABEL=51 MPCALL=52 MPCALL_PARENT=53 MFCALL=54 MFCALL_LIB=55 MFCALL_LIB_RETNEW=56 MFCALL_PARENT=57 MFCALL_PARENT_LIB=58 MFCALL_PARENT_LIB_RETNEW=59 NOP=60 NSTRUC=61 NSTRUC_REF=62 ON_IOERROR_NULL=63 PCALL=64 PCALL_LIB=65 PARADECL=66 PARAEXPR=67 PARAEXPR_VN=68 DEC_REF_CHECK=69 INC_REF_CHECK=70 POSTDEC=71 POSTINC=72 DECSTATEMENT=73 INCSTATEMENT=74 REF=75 REF_VN=76 REF_CHECK=77 REF_CHECK_VN=78 REF_EXPR=79 REF_EXPR_VN=80 REPEAT="repeat"=81 REPEAT_LOOP=82 RETURN=83 RETF=84 RETP=85 STRUC=86 SYSVAR=87 UMINUS=88 VAR=89 VARPTR=90 WHILE="while"=91 IDENTIFIER=92 AND_OP="and"=93 BEGIN="begin"=94 CASE="case"=95 COMMON="common"=96 COMPILE_OPT="compile_opt"=97 DO="do"=98 ELSE="else"=99 END="end"=100 ENDCASE="endcase"=101 ENDELSE="endelse"=102 ENDFOR="endfor"=103 ENDFOREACH="endforeach"=104 ENDIF="endif"=105 ENDREP="endrep"=106 ENDSWITCH="endswitch"=107 ENDWHILE="endwhile"=108 EQ_OP="eq"=109 FORWARD="forward_function"=110 FUNCTION="function"=111 GE_OP="ge"=112 GOTO="goto"=113 GT_OP="gt"=114 IF="if"=115 INHERITS="inherits"=116 LE_OP="le"=117 LT_OP="lt"=118 MOD_OP="mod"=119 NE_OP="ne"=120 NOT_OP="not"=121 OF="of"=122 ON_IOERROR="on_ioerror"=123 OR_OP="or"=124 PRO="pro"=125 SWITCH="switch"=126 THEN="then"=127 UNTIL="until"=128 XOR_OP="xor"=129 METHOD=130 COMMA=131 COLON=132 END_U=133 EQUAL=134 DEC=135 INC=136 AND_OP_EQ=137 ASTERIX_EQ=138 EQ_OP_EQ=139 GE_OP_EQ=140 GTMARK_EQ=141 GT_OP_EQ=142 LE_OP_EQ=143 LTMARK_EQ=144 LT_OP_EQ=145 MATRIX_OP1_EQ=146 MATRIX_OP2_EQ=147 MINUS_EQ=148 MOD_OP_EQ=149 NE_OP_EQ=150 OR_OP_EQ=151 PLUS_EQ=152 POW_EQ=153 SLASH_EQ=154 XOR_OP_EQ=155 MEMBER=156 LBRACE=157 RBRACE=158 SLASH=159 LSQUARE=160 RSQUARE=161 SYSVARNAME=162 EXCLAMATION=163 LCURLY=164 RCURLY=165 CONSTANT_HEX_BYTE=166 CONSTANT_HEX_LONG=167 CONSTANT_HEX_LONG64=168 CONSTANT_HEX_INT=169 CONSTANT_HEX_I=170 CONSTANT_HEX_ULONG=171 CONSTANT_HEX_ULONG64=172 CONSTANT_HEX_UI=173 CONSTANT_HEX_UINT=174 CONSTANT_BYTE=175 CONSTANT_LONG=176 CONSTANT_LONG64=177 CONSTANT_INT=178 CONSTANT_I=179 CONSTANT_ULONG=180 CONSTANT_ULONG64=181 CONSTANT_UI=182 CONSTANT_UINT=183 CONSTANT_OCT_BYTE=184 CONSTANT_OCT_LONG=185 CONSTANT_OCT_LONG64=186 CONSTANT_OCT_INT=187 CONSTANT_OCT_I=188 CONSTANT_OCT_ULONG=189 CONSTANT_OCT_ULONG64=190 CONSTANT_OCT_UI=191 CONSTANT_OCT_UINT=192 CONSTANT_FLOAT=193 CONSTANT_DOUBLE=194 CONSTANT_BIN_BYTE=195 CONSTANT_BIN_LONG=196 CONSTANT_BIN_LONG64=197 CONSTANT_BIN_INT=198 CONSTANT_BIN_I=199 CONSTANT_BIN_ULONG=200 CONSTANT_BIN_ULONG64=201 CONSTANT_BIN_UI=202 CONSTANT_BIN_UINT=203 ASTERIX=204 DOT=205 STRING_LITERAL=206 POW=207 MATRIX_OP1=208 MATRIX_OP2=209 PLUS=210 MINUS=211 LTMARK=212 GTMARK=213 LOG_NEG=214 LOG_AND=215 LOG_OR=216 QUESTION=217 STRING=218 INCLUDE=219 EOL=220 W=221 D=222 L=223 H=224 O=225 B=226 EXP=227 DBL_E=228 DBL=229 CONSTANT_OR_STRING_LITERAL=230 COMMENT=231 END_MARKER=232 WHITESPACE=233 SKIP_LINES=234 CONT_STATEMENT=235 END_OF_LINE=236 MAX_TOKEN_NUMBER=237 gdl-0.9.9/src/GDLTreeParser.cpp000066400000000000000000006430741340051421000162010ustar00rootroot00000000000000/* $ANTLR 2.7.7 (2006-11-01): "gdlc.tree.g" -> "GDLTreeParser.cpp"$ */ #include "includefirst.hpp" #include "GDLTreeParser.hpp" #include #include #include #include #include #include #include #include // **** #include "print_tree.hpp" using namespace std; // print out AST tree //#define GDL_DEBUG //#undef GDL_DEBUG GDLTreeParser::GDLTreeParser() : antlr::TreeParser() { } void GDLTreeParser::translation_unit(RefDNode _t) { RefDNode translation_unit_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode translation_unit_AST = RefDNode(antlr::nullAST); RefDNode retAST_AST = RefDNode(antlr::nullAST); RefDNode retAST = RefDNode(antlr::nullAST); // returnProgNodeP = _t; bool mainStarted = false; try { // for error handling { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case PRO: { procedure_def(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case FUNCTION: { function_def(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } default: if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == FORWARD)) { forward_function(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else if ((_t->getType() == COMMONDECL || _t->getType() == COMMONDEF)) { EnvBaseT* envBefore = comp.GetEnv(); if( !mainStarted) { comp.StartPro( "$MAIN$"); mainStarted = true; } comp.ContinueMainPro(); common_block(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); comp.EndInteractiveStatement(); comp.SetEnv( envBefore); } else { goto _loop3; } } } _loop3:; } // ( ... )* { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { if( !mainStarted) { comp.StartPro( "$MAIN$"); mainStarted = true; } comp.ContinueMainPro(); retAST = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; statement_list(_t); _t = _retTree; retAST_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); comp.SetTree( retAST_AST); comp.EndPro(); #ifdef GDL_DEBUG cout << "TreeParser output:" << endl; antlr::print_tree pt; pt.pr_tree(static_cast(retAST)); cout << "CompileFile: TreeParser end." << endl; #endif break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } translation_unit_AST = RefDNode(currentAST.root); } catch ( GDLException& e) { throw; } catch ( antlr::NoViableAltException& e) { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Compiler syntax error: "+e.getMessage()); } catch ( antlr::RecognitionException& e) { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "General syntax error: "+e.getMessage()); } returnAST = translation_unit_AST; _retTree = _t; } void GDLTreeParser::procedure_def(RefDNode _t) { RefDNode procedure_def_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode procedure_def_AST = RefDNode(antlr::nullAST); RefDNode p = RefDNode(antlr::nullAST); RefDNode p_AST = RefDNode(antlr::nullAST); RefDNode name = RefDNode(antlr::nullAST); RefDNode name_AST = RefDNode(antlr::nullAST); RefDNode obj = RefDNode(antlr::nullAST); RefDNode obj_AST = RefDNode(antlr::nullAST); RefDNode __t19 = _t; p = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode p_AST_in = RefDNode(antlr::nullAST); p_AST = astFactory->create(antlr::RefAST(p)); antlr::ASTPair __currentAST19 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),PRO); _t = _t->getFirstChild(); name = _t; RefDNode name_AST_in = RefDNode(antlr::nullAST); name_AST = astFactory->create(antlr::RefAST(name)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case METHOD: { RefDNode tmp1_AST = RefDNode(antlr::nullAST); RefDNode tmp1_AST_in = RefDNode(antlr::nullAST); tmp1_AST = astFactory->create(antlr::RefAST(_t)); tmp1_AST_in = _t; match(antlr::RefAST(_t),METHOD); _t = _t->getNextSibling(); obj = _t; RefDNode obj_AST_in = RefDNode(antlr::nullAST); obj_AST = astFactory->create(antlr::RefAST(obj)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); comp.StartPro(name->getText(),p_AST->GetCompileOpt(),obj->getText()); break; } case 3: case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case PARADECL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { comp.StartPro(name->getText(),p_AST->GetCompileOpt()); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case PARADECL: { parameter_declaration(_t); _t = _retTree; break; } case 3: case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { statement_list(_t); _t = _retTree; comp.SetTree( returnAST); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } if( NCompileErrors() > 0) throw GDLException( i2s(NCompileErrors()) + " compilation error(s) in module " + name->getText() + "."); comp.EndPro(); currentAST = __currentAST19; _t = __t19; _t = _t->getNextSibling(); returnAST = procedure_def_AST; _retTree = _t; } void GDLTreeParser::function_def(RefDNode _t) { RefDNode function_def_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode function_def_AST = RefDNode(antlr::nullAST); RefDNode f = RefDNode(antlr::nullAST); RefDNode f_AST = RefDNode(antlr::nullAST); RefDNode name = RefDNode(antlr::nullAST); RefDNode name_AST = RefDNode(antlr::nullAST); RefDNode obj = RefDNode(antlr::nullAST); RefDNode obj_AST = RefDNode(antlr::nullAST); RefDNode __t24 = _t; f = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode f_AST_in = RefDNode(antlr::nullAST); f_AST = astFactory->create(antlr::RefAST(f)); antlr::ASTPair __currentAST24 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),FUNCTION); _t = _t->getFirstChild(); name = _t; RefDNode name_AST_in = RefDNode(antlr::nullAST); name_AST = astFactory->create(antlr::RefAST(name)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case METHOD: { RefDNode tmp2_AST = RefDNode(antlr::nullAST); RefDNode tmp2_AST_in = RefDNode(antlr::nullAST); tmp2_AST = astFactory->create(antlr::RefAST(_t)); tmp2_AST_in = _t; match(antlr::RefAST(_t),METHOD); _t = _t->getNextSibling(); obj = _t; RefDNode obj_AST_in = RefDNode(antlr::nullAST); obj_AST = astFactory->create(antlr::RefAST(obj)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); comp.StartFun(name->getText(),f_AST->GetCompileOpt(),obj->getText()); break; } case 3: case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case PARADECL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { comp.StartFun(name->getText(),f_AST->GetCompileOpt()); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case PARADECL: { parameter_declaration(_t); _t = _retTree; break; } case 3: case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { statement_list(_t); _t = _retTree; comp.SetTree( returnAST); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } if( NCompileErrors() > 0) throw GDLException( i2s(NCompileErrors()) + " compilation error(s) in module " + name->getText() + "."); comp.EndFun(); currentAST = __currentAST24; _t = __t24; _t = _t->getNextSibling(); returnAST = function_def_AST; _retTree = _t; } void GDLTreeParser::forward_function(RefDNode _t) { RefDNode forward_function_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode forward_function_AST = RefDNode(antlr::nullAST); RefDNode id = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode __t9 = _t; RefDNode tmp3_AST = RefDNode(antlr::nullAST); RefDNode tmp3_AST_in = RefDNode(antlr::nullAST); tmp3_AST = astFactory->create(antlr::RefAST(_t)); tmp3_AST_in = _t; antlr::ASTPair __currentAST9 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),FORWARD); _t = _t->getFirstChild(); { // ( ... )+ int _cnt11=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == IDENTIFIER)) { id = _t; RefDNode id_AST_in = RefDNode(antlr::nullAST); id_AST = astFactory->create(antlr::RefAST(id)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); comp.ForwardFunction(id->getText()); } else { if ( _cnt11>=1 ) { goto _loop11; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt11++; } _loop11:; } // ( ... )+ currentAST = __currentAST9; _t = __t9; _t = _t->getNextSibling(); returnAST = forward_function_AST; _retTree = _t; } void GDLTreeParser::common_block(RefDNode _t) { RefDNode common_block_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode common_block_AST = RefDNode(antlr::nullAST); RefDNode id = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode cv = RefDNode(antlr::nullAST); RefDNode cv_AST = RefDNode(antlr::nullAST); RefDNode id2 = RefDNode(antlr::nullAST); RefDNode id2_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case COMMONDEF: { RefDNode __t29 = _t; RefDNode tmp4_AST = RefDNode(antlr::nullAST); RefDNode tmp4_AST_in = RefDNode(antlr::nullAST); tmp4_AST = astFactory->create(antlr::RefAST(_t)); tmp4_AST_in = _t; antlr::ASTPair __currentAST29 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),COMMONDEF); _t = _t->getFirstChild(); id = _t; RefDNode id_AST_in = RefDNode(antlr::nullAST); id_AST = astFactory->create(antlr::RefAST(id)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); DCommonBase* actCommon=comp.CommonDef(id->getText()); { // ( ... )+ int _cnt31=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == IDENTIFIER)) { cv = _t; RefDNode cv_AST_in = RefDNode(antlr::nullAST); cv_AST = astFactory->create(antlr::RefAST(cv)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); comp.CommonVar(actCommon,cv->getText()); } else { if ( _cnt31>=1 ) { goto _loop31; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt31++; } _loop31:; } // ( ... )+ currentAST = __currentAST29; _t = __t29; _t = _t->getNextSibling(); break; } case COMMONDECL: { RefDNode __t32 = _t; RefDNode tmp5_AST = RefDNode(antlr::nullAST); RefDNode tmp5_AST_in = RefDNode(antlr::nullAST); tmp5_AST = astFactory->create(antlr::RefAST(_t)); tmp5_AST_in = _t; antlr::ASTPair __currentAST32 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),COMMONDECL); _t = _t->getFirstChild(); id2 = _t; RefDNode id2_AST_in = RefDNode(antlr::nullAST); id2_AST = astFactory->create(antlr::RefAST(id2)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); comp.CommonDecl(id2->getText()); currentAST = __currentAST32; _t = __t32; _t = _t->getNextSibling(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = common_block_AST; _retTree = _t; } void GDLTreeParser::statement_list(RefDNode _t) { RefDNode statement_list_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode statement_list_AST = RefDNode(antlr::nullAST); { // ( ... )+ int _cnt57=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case IDENTIFIER: { label(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } default: { if ( _cnt57>=1 ) { goto _loop57; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } } _cnt57++; } _loop57:; } // ( ... )+ statement_list_AST = RefDNode(currentAST.root); returnAST = statement_list_AST; _retTree = _t; } void GDLTreeParser::interactive(RefDNode _t) { RefDNode interactive_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode interactive_AST = RefDNode(antlr::nullAST); try { // for error handling { // ( ... )+ int _cnt7=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_0.member(_t->getType()))) { statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); comp.EndInteractiveStatement(); } else { if ( _cnt7>=1 ) { goto _loop7; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt7++; } _loop7:; } // ( ... )+ interactive_AST = RefDNode(currentAST.root); } catch ( GDLException& e) { throw; } catch ( antlr::NoViableAltException& e) { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "Compiler syntax error: "+e.getMessage()); } catch ( antlr::RecognitionException& e) { // SYNTAX ERROR throw GDLException( e.getLine(), e.getColumn(), "General syntax error: "+e.getMessage()); } returnAST = interactive_AST; _retTree = _t; } void GDLTreeParser::statement(RefDNode _t) { RefDNode statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode statement_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: { assign_expr_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { comp_assign_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case MPCALL: case MPCALL_PARENT: case PCALL: { procedure_call(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case FOR: { for_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case FOREACH: { foreach_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case REPEAT: { repeat_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case WHILE: { while_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case RETURN: case GOTO: case ON_IOERROR: { jump_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case IF: { if_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case CASE: { case_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case SWITCH: { switch_statement(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case FORWARD: { forward_function(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case COMMONDECL: case COMMONDEF: { common_block(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case BLOCK: { block(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); statement_AST = RefDNode(currentAST.root); break; } case DEC: { RefDNode __t59 = _t; RefDNode tmp6_AST = RefDNode(antlr::nullAST); RefDNode tmp6_AST_in = RefDNode(antlr::nullAST); tmp6_AST = astFactory->create(antlr::RefAST(_t)); tmp6_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp6_AST)); antlr::ASTPair __currentAST59 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),DEC); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST59; _t = __t59; _t = _t->getNextSibling(); statement_AST = RefDNode(currentAST.root); break; } case INC: { RefDNode __t60 = _t; RefDNode tmp7_AST = RefDNode(antlr::nullAST); RefDNode tmp7_AST_in = RefDNode(antlr::nullAST); tmp7_AST = astFactory->create(antlr::RefAST(_t)); tmp7_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp7_AST)); antlr::ASTPair __currentAST60 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),INC); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST60; _t = __t60; _t = _t->getNextSibling(); statement_AST = RefDNode(currentAST.root); break; } case BREAK: { RefDNode tmp8_AST = RefDNode(antlr::nullAST); RefDNode tmp8_AST_in = RefDNode(antlr::nullAST); tmp8_AST = astFactory->create(antlr::RefAST(_t)); tmp8_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp8_AST)); match(antlr::RefAST(_t),BREAK); _t = _t->getNextSibling(); statement_AST = RefDNode(currentAST.root); break; } case CONTINUE: { RefDNode tmp9_AST = RefDNode(antlr::nullAST); RefDNode tmp9_AST_in = RefDNode(antlr::nullAST); tmp9_AST = astFactory->create(antlr::RefAST(_t)); tmp9_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp9_AST)); match(antlr::RefAST(_t),CONTINUE); _t = _t->getNextSibling(); statement_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = statement_AST; _retTree = _t; } void GDLTreeParser::parameter_declaration(RefDNode _t) { RefDNode parameter_declaration_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode parameter_declaration_AST = RefDNode(antlr::nullAST); RefDNode id = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode __t13 = _t; RefDNode tmp10_AST = RefDNode(antlr::nullAST); RefDNode tmp10_AST_in = RefDNode(antlr::nullAST); tmp10_AST = astFactory->create(antlr::RefAST(_t)); tmp10_AST_in = _t; antlr::ASTPair __currentAST13 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),PARADECL); _t = _t->getFirstChild(); { // ( ... )+ int _cnt15=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case IDENTIFIER: { id = _t; RefDNode id_AST_in = RefDNode(antlr::nullAST); id_AST = astFactory->create(antlr::RefAST(id)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); comp.AddPar(id->getText()); break; } case KEYDECL: { keyword_declaration(_t); _t = _retTree; break; } default: { if ( _cnt15>=1 ) { goto _loop15; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } } _cnt15++; } _loop15:; } // ( ... )+ currentAST = __currentAST13; _t = __t13; _t = _t->getNextSibling(); returnAST = parameter_declaration_AST; _retTree = _t; } void GDLTreeParser::keyword_declaration(RefDNode _t) { RefDNode keyword_declaration_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode keyword_declaration_AST = RefDNode(antlr::nullAST); RefDNode key = RefDNode(antlr::nullAST); RefDNode key_AST = RefDNode(antlr::nullAST); RefDNode val = RefDNode(antlr::nullAST); RefDNode val_AST = RefDNode(antlr::nullAST); RefDNode __t17 = _t; RefDNode tmp11_AST = RefDNode(antlr::nullAST); RefDNode tmp11_AST_in = RefDNode(antlr::nullAST); tmp11_AST = astFactory->create(antlr::RefAST(_t)); tmp11_AST_in = _t; antlr::ASTPair __currentAST17 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),KEYDECL); _t = _t->getFirstChild(); key = _t; RefDNode key_AST_in = RefDNode(antlr::nullAST); key_AST = astFactory->create(antlr::RefAST(key)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); val = _t; RefDNode val_AST_in = RefDNode(antlr::nullAST); val_AST = astFactory->create(antlr::RefAST(val)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); currentAST = __currentAST17; _t = __t17; _t = _t->getNextSibling(); comp.AddKey(key->getText(),val->getText()); returnAST = keyword_declaration_AST; _retTree = _t; } void GDLTreeParser::caseswitch_body(RefDNode _t) { RefDNode caseswitch_body_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode caseswitch_body_AST = RefDNode(antlr::nullAST); RefDNode b = RefDNode(antlr::nullAST); RefDNode b_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case BLOCK: { RefDNode __t34 = _t; b = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode b_AST_in = RefDNode(antlr::nullAST); b_AST = astFactory->create(antlr::RefAST(b)); astFactory->addASTChild(currentAST, antlr::RefAST(b_AST)); antlr::ASTPair __currentAST34 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),BLOCK); _t = _t->getFirstChild(); b_AST->setType(CSBLOCK);b_AST->setText("csblock"); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { statement_list(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST34; _t = __t34; _t = _t->getNextSibling(); caseswitch_body_AST = RefDNode(currentAST.root); break; } case ELSEBLK: { RefDNode __t36 = _t; RefDNode tmp12_AST = RefDNode(antlr::nullAST); RefDNode tmp12_AST_in = RefDNode(antlr::nullAST); tmp12_AST = astFactory->create(antlr::RefAST(_t)); tmp12_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp12_AST)); antlr::ASTPair __currentAST36 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ELSEBLK); _t = _t->getFirstChild(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { statement_list(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST36; _t = __t36; _t = _t->getNextSibling(); caseswitch_body_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = caseswitch_body_AST; _retTree = _t; } void GDLTreeParser::expr(RefDNode _t) { RefDNode expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: case EXPR: case SYSVAR: case VAR: { array_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr_AST = RefDNode(currentAST.root); break; } case DOT: { RefDNode __t210 = _t; RefDNode tmp13_AST = RefDNode(antlr::nullAST); RefDNode tmp13_AST_in = RefDNode(antlr::nullAST); tmp13_AST = astFactory->create(antlr::RefAST(_t)); tmp13_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp13_AST)); antlr::ASTPair __currentAST210 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),DOT); _t = _t->getFirstChild(); tag_array_expr_1st(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { // ( ... )+ int _cnt212=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == ARRAYEXPR || _t->getType() == EXPR || _t->getType() == IDENTIFIER)) { tag_array_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { if ( _cnt212>=1 ) { goto _loop212; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt212++; } _loop212:; } // ( ... )+ currentAST = __currentAST210; _t = __t210; _t = _t->getNextSibling(); expr_AST = RefDNode(currentAST.root); break; } case DEREF: { RefDNode __t213 = _t; RefDNode tmp14_AST = RefDNode(antlr::nullAST); RefDNode tmp14_AST_in = RefDNode(antlr::nullAST); tmp14_AST = astFactory->create(antlr::RefAST(_t)); tmp14_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp14_AST)); antlr::ASTPair __currentAST213 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),DEREF); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST213; _t = __t213; _t = _t->getNextSibling(); expr_AST = RefDNode(currentAST.root); break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case UMINUS: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { op_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = expr_AST; _retTree = _t; } void GDLTreeParser::switch_statement(RefDNode _t) { RefDNode switch_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode switch_statement_AST = RefDNode(antlr::nullAST); RefDNode s = RefDNode(antlr::nullAST); RefDNode s_AST = RefDNode(antlr::nullAST); int labelStart = comp.NDefLabel(); RefDNode __t39 = _t; s = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode s_AST_in = RefDNode(antlr::nullAST); s_AST = astFactory->create(antlr::RefAST(s)); astFactory->addASTChild(currentAST, antlr::RefAST(s_AST)); antlr::ASTPair __currentAST39 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),SWITCH); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == BLOCK || _t->getType() == ELSEBLK)) { caseswitch_body(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { goto _loop41; } } _loop41:; } // ( ... )* currentAST = __currentAST39; _t = __t39; _t = _t->getNextSibling(); s_AST->SetLabelRange( labelStart, comp.NDefLabel()); switch_statement_AST = RefDNode(currentAST.root); returnAST = switch_statement_AST; _retTree = _t; } void GDLTreeParser::case_statement(RefDNode _t) { RefDNode case_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode case_statement_AST = RefDNode(antlr::nullAST); RefDNode c = RefDNode(antlr::nullAST); RefDNode c_AST = RefDNode(antlr::nullAST); int labelStart = comp.NDefLabel(); RefDNode __t43 = _t; c = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode c_AST_in = RefDNode(antlr::nullAST); c_AST = astFactory->create(antlr::RefAST(c)); astFactory->addASTChild(currentAST, antlr::RefAST(c_AST)); antlr::ASTPair __currentAST43 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),CASE); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == BLOCK || _t->getType() == ELSEBLK)) { caseswitch_body(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { goto _loop45; } } _loop45:; } // ( ... )* currentAST = __currentAST43; _t = __t43; _t = _t->getNextSibling(); c_AST->SetLabelRange( labelStart, comp.NDefLabel()); case_statement_AST = RefDNode(currentAST.root); returnAST = case_statement_AST; _retTree = _t; } void GDLTreeParser::block(RefDNode _t) { RefDNode block_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode block_AST = RefDNode(antlr::nullAST); RefDNode b = RefDNode(antlr::nullAST); RefDNode b_AST = RefDNode(antlr::nullAST); // int labelStart = comp.NDefLabel(); RefDNode __t47 = _t; b = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode b_AST_in = RefDNode(antlr::nullAST); b_AST = astFactory->create(antlr::RefAST(b)); astFactory->addASTChild(currentAST, antlr::RefAST(b_AST)); antlr::ASTPair __currentAST47 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),BLOCK); _t = _t->getFirstChild(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { statement_list(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST47; _t = __t47; _t = _t->getNextSibling(); // #b->SetLabelRange( labelStart, comp.NDefLabel()); block_AST = RefDNode(currentAST.root); returnAST = block_AST; _retTree = _t; } void GDLTreeParser::unblock(RefDNode _t) { RefDNode unblock_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode unblock_AST = RefDNode(antlr::nullAST); RefDNode b = RefDNode(antlr::nullAST); RefDNode b_AST = RefDNode(antlr::nullAST); RefDNode s_AST = RefDNode(antlr::nullAST); RefDNode s = RefDNode(antlr::nullAST); RefDNode __t50 = _t; b = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode b_AST_in = RefDNode(antlr::nullAST); b_AST = astFactory->create(antlr::RefAST(b)); antlr::ASTPair __currentAST50 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),BLOCK); _t = _t->getFirstChild(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { s = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; statement_list(_t); _t = _retTree; s_AST = returnAST; unblock_AST = RefDNode(currentAST.root); unblock_AST = s_AST; currentAST.root = unblock_AST; if ( unblock_AST!=RefDNode(antlr::nullAST) && unblock_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = unblock_AST->getFirstChild(); else currentAST.child = unblock_AST; currentAST.advanceChildToEnd(); break; } case 3: { unblock_AST = RefDNode(currentAST.root); unblock_AST = b_AST; currentAST.root = unblock_AST; if ( unblock_AST!=RefDNode(antlr::nullAST) && unblock_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = unblock_AST->getFirstChild(); else currentAST.child = unblock_AST; currentAST.advanceChildToEnd(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST50; _t = __t50; _t = _t->getNextSibling(); returnAST = unblock_AST; _retTree = _t; } void GDLTreeParser::unblock_empty(RefDNode _t) { RefDNode unblock_empty_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode unblock_empty_AST = RefDNode(antlr::nullAST); RefDNode b = RefDNode(antlr::nullAST); RefDNode b_AST = RefDNode(antlr::nullAST); RefDNode s_AST = RefDNode(antlr::nullAST); RefDNode s = RefDNode(antlr::nullAST); RefDNode __t53 = _t; b = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode b_AST_in = RefDNode(antlr::nullAST); b_AST = astFactory->create(antlr::RefAST(b)); antlr::ASTPair __currentAST53 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),BLOCK); _t = _t->getFirstChild(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case IDENTIFIER: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { s = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; statement_list(_t); _t = _retTree; s_AST = returnAST; unblock_empty_AST = RefDNode(currentAST.root); unblock_empty_AST = s_AST; currentAST.root = unblock_empty_AST; if ( unblock_empty_AST!=RefDNode(antlr::nullAST) && unblock_empty_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = unblock_empty_AST->getFirstChild(); else currentAST.child = unblock_empty_AST; currentAST.advanceChildToEnd(); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST53; _t = __t53; _t = _t->getNextSibling(); returnAST = unblock_empty_AST; _retTree = _t; } void GDLTreeParser::label(RefDNode _t) { RefDNode label_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode label_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode __t72 = _t; i = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); antlr::ASTPair __currentAST72 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getFirstChild(); RefDNode tmp15_AST = RefDNode(antlr::nullAST); RefDNode tmp15_AST_in = RefDNode(antlr::nullAST); tmp15_AST = astFactory->create(antlr::RefAST(_t)); tmp15_AST_in = _t; match(antlr::RefAST(_t),COLON); _t = _t->getNextSibling(); currentAST = __currentAST72; _t = __t72; _t = _t->getNextSibling(); label_AST = RefDNode(currentAST.root); label_AST=astFactory->create(LABEL,i->getText()); label_AST->SetLine( i->getLine()); comp.Label(label_AST); currentAST.root = label_AST; if ( label_AST!=RefDNode(antlr::nullAST) && label_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = label_AST->getFirstChild(); else currentAST.child = label_AST; currentAST.advanceChildToEnd(); returnAST = label_AST; _retTree = _t; } void GDLTreeParser::assign_expr_statement(RefDNode _t) { RefDNode assign_expr_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode assign_expr_statement_AST = RefDNode(antlr::nullAST); RefDNode a = RefDNode(antlr::nullAST); RefDNode a_AST = RefDNode(antlr::nullAST); RefDNode l_AST = RefDNode(antlr::nullAST); RefDNode l = RefDNode(antlr::nullAST); RefDNode r_AST = RefDNode(antlr::nullAST); RefDNode r = RefDNode(antlr::nullAST); RefDNode __t125 = _t; a = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a_AST_in = RefDNode(antlr::nullAST); a_AST = astFactory->create(antlr::RefAST(a)); antlr::ASTPair __currentAST125 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ASSIGN); _t = _t->getFirstChild(); l = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l_AST = returnAST; r = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r_AST = returnAST; currentAST = __currentAST125; _t = __t125; _t = _t->getNextSibling(); assign_expr_statement_AST = RefDNode(currentAST.root); if( !SelfAssignment( l_AST, r_AST)) { AssignReplace( l_AST, a_AST); // int lT = #l->getType(); // if( lT == FCALL || lT == MFCALL || lT == MFCALL_PARENT || // lT == FCALL_LIB || lT == MFCALL_LIB || lT == MFCALL_PARENT_LIB || // lT == DEREF || lT == VAR || lT == VARPTR) // #a->setType( ASSIGN_REPLACE); assign_expr_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(a_AST))->add(antlr::RefAST(r_AST))->add(antlr::RefAST(l_AST)))); } else { assign_expr_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(1))->add(antlr::RefAST(astFactory->create(BLOCK,"block"))))); } currentAST.root = assign_expr_statement_AST; if ( assign_expr_statement_AST!=RefDNode(antlr::nullAST) && assign_expr_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = assign_expr_statement_AST->getFirstChild(); else currentAST.child = assign_expr_statement_AST; currentAST.advanceChildToEnd(); returnAST = assign_expr_statement_AST; _retTree = _t; } void GDLTreeParser::comp_assign_expr(RefDNode _t) { RefDNode comp_assign_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode comp_assign_expr_AST = RefDNode(antlr::nullAST); RefDNode a1 = RefDNode(antlr::nullAST); RefDNode a1_AST = RefDNode(antlr::nullAST); RefDNode l1_AST = RefDNode(antlr::nullAST); RefDNode l1 = RefDNode(antlr::nullAST); RefDNode r1_AST = RefDNode(antlr::nullAST); RefDNode r1 = RefDNode(antlr::nullAST); RefDNode a2 = RefDNode(antlr::nullAST); RefDNode a2_AST = RefDNode(antlr::nullAST); RefDNode l2_AST = RefDNode(antlr::nullAST); RefDNode l2 = RefDNode(antlr::nullAST); RefDNode r2_AST = RefDNode(antlr::nullAST); RefDNode r2 = RefDNode(antlr::nullAST); RefDNode a3 = RefDNode(antlr::nullAST); RefDNode a3_AST = RefDNode(antlr::nullAST); RefDNode l3_AST = RefDNode(antlr::nullAST); RefDNode l3 = RefDNode(antlr::nullAST); RefDNode r3_AST = RefDNode(antlr::nullAST); RefDNode r3 = RefDNode(antlr::nullAST); RefDNode a4 = RefDNode(antlr::nullAST); RefDNode a4_AST = RefDNode(antlr::nullAST); RefDNode l4_AST = RefDNode(antlr::nullAST); RefDNode l4 = RefDNode(antlr::nullAST); RefDNode r4_AST = RefDNode(antlr::nullAST); RefDNode r4 = RefDNode(antlr::nullAST); RefDNode a5 = RefDNode(antlr::nullAST); RefDNode a5_AST = RefDNode(antlr::nullAST); RefDNode l5_AST = RefDNode(antlr::nullAST); RefDNode l5 = RefDNode(antlr::nullAST); RefDNode r5_AST = RefDNode(antlr::nullAST); RefDNode r5 = RefDNode(antlr::nullAST); RefDNode a6 = RefDNode(antlr::nullAST); RefDNode a6_AST = RefDNode(antlr::nullAST); RefDNode l6_AST = RefDNode(antlr::nullAST); RefDNode l6 = RefDNode(antlr::nullAST); RefDNode r6_AST = RefDNode(antlr::nullAST); RefDNode r6 = RefDNode(antlr::nullAST); RefDNode a7 = RefDNode(antlr::nullAST); RefDNode a7_AST = RefDNode(antlr::nullAST); RefDNode l7_AST = RefDNode(antlr::nullAST); RefDNode l7 = RefDNode(antlr::nullAST); RefDNode r7_AST = RefDNode(antlr::nullAST); RefDNode r7 = RefDNode(antlr::nullAST); RefDNode a8 = RefDNode(antlr::nullAST); RefDNode a8_AST = RefDNode(antlr::nullAST); RefDNode l8_AST = RefDNode(antlr::nullAST); RefDNode l8 = RefDNode(antlr::nullAST); RefDNode r8_AST = RefDNode(antlr::nullAST); RefDNode r8 = RefDNode(antlr::nullAST); RefDNode a9 = RefDNode(antlr::nullAST); RefDNode a9_AST = RefDNode(antlr::nullAST); RefDNode l9_AST = RefDNode(antlr::nullAST); RefDNode l9 = RefDNode(antlr::nullAST); RefDNode r9_AST = RefDNode(antlr::nullAST); RefDNode r9 = RefDNode(antlr::nullAST); RefDNode a10 = RefDNode(antlr::nullAST); RefDNode a10_AST = RefDNode(antlr::nullAST); RefDNode l10_AST = RefDNode(antlr::nullAST); RefDNode l10 = RefDNode(antlr::nullAST); RefDNode r10_AST = RefDNode(antlr::nullAST); RefDNode r10 = RefDNode(antlr::nullAST); RefDNode a11 = RefDNode(antlr::nullAST); RefDNode a11_AST = RefDNode(antlr::nullAST); RefDNode l11_AST = RefDNode(antlr::nullAST); RefDNode l11 = RefDNode(antlr::nullAST); RefDNode r11_AST = RefDNode(antlr::nullAST); RefDNode r11 = RefDNode(antlr::nullAST); RefDNode a12 = RefDNode(antlr::nullAST); RefDNode a12_AST = RefDNode(antlr::nullAST); RefDNode l12_AST = RefDNode(antlr::nullAST); RefDNode l12 = RefDNode(antlr::nullAST); RefDNode r12_AST = RefDNode(antlr::nullAST); RefDNode r12 = RefDNode(antlr::nullAST); RefDNode a13 = RefDNode(antlr::nullAST); RefDNode a13_AST = RefDNode(antlr::nullAST); RefDNode l13_AST = RefDNode(antlr::nullAST); RefDNode l13 = RefDNode(antlr::nullAST); RefDNode r13_AST = RefDNode(antlr::nullAST); RefDNode r13 = RefDNode(antlr::nullAST); RefDNode a14 = RefDNode(antlr::nullAST); RefDNode a14_AST = RefDNode(antlr::nullAST); RefDNode l14_AST = RefDNode(antlr::nullAST); RefDNode l14 = RefDNode(antlr::nullAST); RefDNode r14_AST = RefDNode(antlr::nullAST); RefDNode r14 = RefDNode(antlr::nullAST); RefDNode a15 = RefDNode(antlr::nullAST); RefDNode a15_AST = RefDNode(antlr::nullAST); RefDNode l15_AST = RefDNode(antlr::nullAST); RefDNode l15 = RefDNode(antlr::nullAST); RefDNode r15_AST = RefDNode(antlr::nullAST); RefDNode r15 = RefDNode(antlr::nullAST); RefDNode a16 = RefDNode(antlr::nullAST); RefDNode a16_AST = RefDNode(antlr::nullAST); RefDNode l16_AST = RefDNode(antlr::nullAST); RefDNode l16 = RefDNode(antlr::nullAST); RefDNode r16_AST = RefDNode(antlr::nullAST); RefDNode r16 = RefDNode(antlr::nullAST); RefDNode a17 = RefDNode(antlr::nullAST); RefDNode a17_AST = RefDNode(antlr::nullAST); RefDNode l17_AST = RefDNode(antlr::nullAST); RefDNode l17 = RefDNode(antlr::nullAST); RefDNode r17_AST = RefDNode(antlr::nullAST); RefDNode r17 = RefDNode(antlr::nullAST); RefDNode a18 = RefDNode(antlr::nullAST); RefDNode a18_AST = RefDNode(antlr::nullAST); RefDNode l18_AST = RefDNode(antlr::nullAST); RefDNode l18 = RefDNode(antlr::nullAST); RefDNode r18_AST = RefDNode(antlr::nullAST); RefDNode r18 = RefDNode(antlr::nullAST); RefDNode a19 = RefDNode(antlr::nullAST); RefDNode a19_AST = RefDNode(antlr::nullAST); RefDNode l19_AST = RefDNode(antlr::nullAST); RefDNode l19 = RefDNode(antlr::nullAST); RefDNode r19_AST = RefDNode(antlr::nullAST); RefDNode r19 = RefDNode(antlr::nullAST); RefDNode l; { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case AND_OP_EQ: { RefDNode __t128 = _t; a1 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a1_AST_in = RefDNode(antlr::nullAST); a1_AST = astFactory->create(antlr::RefAST(a1)); antlr::ASTPair __currentAST128 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),AND_OP_EQ); _t = _t->getFirstChild(); l1 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l1_AST = returnAST; r1 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r1_AST = returnAST; currentAST = __currentAST128; _t = __t128; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l1_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(AND_OP,"and")))->add(antlr::RefAST(l1_AST))->add(antlr::RefAST(r1_AST))))))->add(antlr::RefAST(RemoveNextSibling(l1_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case ASTERIX_EQ: { RefDNode __t129 = _t; a2 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a2_AST_in = RefDNode(antlr::nullAST); a2_AST = astFactory->create(antlr::RefAST(a2)); antlr::ASTPair __currentAST129 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ASTERIX_EQ); _t = _t->getFirstChild(); l2 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l2_AST = returnAST; r2 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r2_AST = returnAST; currentAST = __currentAST129; _t = __t129; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l2_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASTERIX,"*")))->add(antlr::RefAST(l2_AST))->add(antlr::RefAST(r2_AST))))))->add(antlr::RefAST(RemoveNextSibling(l2_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case EQ_OP_EQ: { RefDNode __t130 = _t; a3 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a3_AST_in = RefDNode(antlr::nullAST); a3_AST = astFactory->create(antlr::RefAST(a3)); antlr::ASTPair __currentAST130 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),EQ_OP_EQ); _t = _t->getFirstChild(); l3 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l3_AST = returnAST; r3 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r3_AST = returnAST; currentAST = __currentAST130; _t = __t130; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l3_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(EQ_OP,"eq")))->add(antlr::RefAST(l3_AST))->add(antlr::RefAST(r3_AST))))))->add(antlr::RefAST(RemoveNextSibling(l3_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case GE_OP_EQ: { RefDNode __t131 = _t; a4 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a4_AST_in = RefDNode(antlr::nullAST); a4_AST = astFactory->create(antlr::RefAST(a4)); antlr::ASTPair __currentAST131 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GE_OP_EQ); _t = _t->getFirstChild(); l4 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l4_AST = returnAST; r4 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r4_AST = returnAST; currentAST = __currentAST131; _t = __t131; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l4_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(GE_OP,"ge")))->add(antlr::RefAST(l4_AST))->add(antlr::RefAST(r4_AST))))))->add(antlr::RefAST(RemoveNextSibling(l4_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case GTMARK_EQ: { RefDNode __t132 = _t; a5 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a5_AST_in = RefDNode(antlr::nullAST); a5_AST = astFactory->create(antlr::RefAST(a5)); antlr::ASTPair __currentAST132 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GTMARK_EQ); _t = _t->getFirstChild(); l5 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l5_AST = returnAST; r5 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r5_AST = returnAST; currentAST = __currentAST132; _t = __t132; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l5_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(GTMARK,">")))->add(antlr::RefAST(l5_AST))->add(antlr::RefAST(r5_AST))))))->add(antlr::RefAST(RemoveNextSibling(l5_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case GT_OP_EQ: { RefDNode __t133 = _t; a6 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a6_AST_in = RefDNode(antlr::nullAST); a6_AST = astFactory->create(antlr::RefAST(a6)); antlr::ASTPair __currentAST133 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GT_OP_EQ); _t = _t->getFirstChild(); l6 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l6_AST = returnAST; r6 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r6_AST = returnAST; currentAST = __currentAST133; _t = __t133; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l6_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(GT_OP,"gt")))->add(antlr::RefAST(l6_AST))->add(antlr::RefAST(r6_AST))))))->add(antlr::RefAST(RemoveNextSibling(l6_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case LE_OP_EQ: { RefDNode __t134 = _t; a7 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a7_AST_in = RefDNode(antlr::nullAST); a7_AST = astFactory->create(antlr::RefAST(a7)); antlr::ASTPair __currentAST134 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LE_OP_EQ); _t = _t->getFirstChild(); l7 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l7_AST = returnAST; r7 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r7_AST = returnAST; currentAST = __currentAST134; _t = __t134; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l7_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(LE_OP,"le")))->add(antlr::RefAST(l7_AST))->add(antlr::RefAST(r7_AST))))))->add(antlr::RefAST(RemoveNextSibling(l7_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case LTMARK_EQ: { RefDNode __t135 = _t; a8 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a8_AST_in = RefDNode(antlr::nullAST); a8_AST = astFactory->create(antlr::RefAST(a8)); antlr::ASTPair __currentAST135 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LTMARK_EQ); _t = _t->getFirstChild(); l8 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l8_AST = returnAST; r8 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r8_AST = returnAST; currentAST = __currentAST135; _t = __t135; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l8_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(LTMARK,"<")))->add(antlr::RefAST(l8_AST))->add(antlr::RefAST(r8_AST))))))->add(antlr::RefAST(RemoveNextSibling(l8_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case LT_OP_EQ: { RefDNode __t136 = _t; a9 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a9_AST_in = RefDNode(antlr::nullAST); a9_AST = astFactory->create(antlr::RefAST(a9)); antlr::ASTPair __currentAST136 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LT_OP_EQ); _t = _t->getFirstChild(); l9 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l9_AST = returnAST; r9 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r9_AST = returnAST; currentAST = __currentAST136; _t = __t136; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l9_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(LT_OP,"lt")))->add(antlr::RefAST(l9_AST))->add(antlr::RefAST(r9_AST))))))->add(antlr::RefAST(RemoveNextSibling(l9_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case MATRIX_OP1_EQ: { RefDNode __t137 = _t; a10 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a10_AST_in = RefDNode(antlr::nullAST); a10_AST = astFactory->create(antlr::RefAST(a10)); antlr::ASTPair __currentAST137 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MATRIX_OP1_EQ); _t = _t->getFirstChild(); l10 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l10_AST = returnAST; r10 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r10_AST = returnAST; currentAST = __currentAST137; _t = __t137; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l10_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(MATRIX_OP1,"#")))->add(antlr::RefAST(l10_AST))->add(antlr::RefAST(r10_AST))))))->add(antlr::RefAST(RemoveNextSibling(l10_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case MATRIX_OP2_EQ: { RefDNode __t138 = _t; a11 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a11_AST_in = RefDNode(antlr::nullAST); a11_AST = astFactory->create(antlr::RefAST(a11)); antlr::ASTPair __currentAST138 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MATRIX_OP2_EQ); _t = _t->getFirstChild(); l11 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l11_AST = returnAST; r11 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r11_AST = returnAST; currentAST = __currentAST138; _t = __t138; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l11_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(MATRIX_OP2,"##")))->add(antlr::RefAST(l11_AST))->add(antlr::RefAST(r11_AST))))))->add(antlr::RefAST(RemoveNextSibling(l11_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case MINUS_EQ: { RefDNode __t139 = _t; a12 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a12_AST_in = RefDNode(antlr::nullAST); a12_AST = astFactory->create(antlr::RefAST(a12)); antlr::ASTPair __currentAST139 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MINUS_EQ); _t = _t->getFirstChild(); l12 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l12_AST = returnAST; r12 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r12_AST = returnAST; currentAST = __currentAST139; _t = __t139; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l12_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(MINUS,"-")))->add(antlr::RefAST(l12_AST))->add(antlr::RefAST(r12_AST))))))->add(antlr::RefAST(RemoveNextSibling(l12_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case MOD_OP_EQ: { RefDNode __t140 = _t; a13 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a13_AST_in = RefDNode(antlr::nullAST); a13_AST = astFactory->create(antlr::RefAST(a13)); antlr::ASTPair __currentAST140 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MOD_OP_EQ); _t = _t->getFirstChild(); l13 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l13_AST = returnAST; r13 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r13_AST = returnAST; currentAST = __currentAST140; _t = __t140; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l13_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(MOD_OP,"mod")))->add(antlr::RefAST(l13_AST))->add(antlr::RefAST(r13_AST))))))->add(antlr::RefAST(RemoveNextSibling(l13_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case NE_OP_EQ: { RefDNode __t141 = _t; a14 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a14_AST_in = RefDNode(antlr::nullAST); a14_AST = astFactory->create(antlr::RefAST(a14)); antlr::ASTPair __currentAST141 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),NE_OP_EQ); _t = _t->getFirstChild(); l14 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l14_AST = returnAST; r14 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r14_AST = returnAST; currentAST = __currentAST141; _t = __t141; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l14_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(NE_OP,"ne")))->add(antlr::RefAST(l14_AST))->add(antlr::RefAST(r14_AST))))))->add(antlr::RefAST(RemoveNextSibling(l14_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case OR_OP_EQ: { RefDNode __t142 = _t; a15 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a15_AST_in = RefDNode(antlr::nullAST); a15_AST = astFactory->create(antlr::RefAST(a15)); antlr::ASTPair __currentAST142 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),OR_OP_EQ); _t = _t->getFirstChild(); l15 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l15_AST = returnAST; r15 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r15_AST = returnAST; currentAST = __currentAST142; _t = __t142; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l15_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(OR_OP,"or")))->add(antlr::RefAST(l15_AST))->add(antlr::RefAST(r15_AST))))))->add(antlr::RefAST(RemoveNextSibling(l15_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case PLUS_EQ: { RefDNode __t143 = _t; a16 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a16_AST_in = RefDNode(antlr::nullAST); a16_AST = astFactory->create(antlr::RefAST(a16)); antlr::ASTPair __currentAST143 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),PLUS_EQ); _t = _t->getFirstChild(); l16 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l16_AST = returnAST; r16 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r16_AST = returnAST; currentAST = __currentAST143; _t = __t143; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l16_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(PLUS,"+")))->add(antlr::RefAST(l16_AST))->add(antlr::RefAST(r16_AST))))))->add(antlr::RefAST(RemoveNextSibling(l16_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case POW_EQ: { RefDNode __t144 = _t; a17 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a17_AST_in = RefDNode(antlr::nullAST); a17_AST = astFactory->create(antlr::RefAST(a17)); antlr::ASTPair __currentAST144 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),POW_EQ); _t = _t->getFirstChild(); l17 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l17_AST = returnAST; r17 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r17_AST = returnAST; currentAST = __currentAST144; _t = __t144; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l17_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(POW,"^")))->add(antlr::RefAST(l17_AST))->add(antlr::RefAST(r17_AST))))))->add(antlr::RefAST(RemoveNextSibling(l17_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case SLASH_EQ: { RefDNode __t145 = _t; a18 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a18_AST_in = RefDNode(antlr::nullAST); a18_AST = astFactory->create(antlr::RefAST(a18)); antlr::ASTPair __currentAST145 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),SLASH_EQ); _t = _t->getFirstChild(); l18 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l18_AST = returnAST; r18 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r18_AST = returnAST; currentAST = __currentAST145; _t = __t145; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l18_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(SLASH,"/")))->add(antlr::RefAST(l18_AST))->add(antlr::RefAST(r18_AST))))))->add(antlr::RefAST(RemoveNextSibling(l18_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } case XOR_OP_EQ: { RefDNode __t146 = _t; a19 = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a19_AST_in = RefDNode(antlr::nullAST); a19_AST = astFactory->create(antlr::RefAST(a19)); antlr::ASTPair __currentAST146 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),XOR_OP_EQ); _t = _t->getFirstChild(); l19 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l19_AST = returnAST; r19 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r19_AST = returnAST; currentAST = __currentAST146; _t = __t146; _t = _t->getNextSibling(); comp_assign_expr_AST = RefDNode(currentAST.root); l=l19_AST; comp_assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ASSIGN,":=")))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(XOR_OP,"xor")))->add(antlr::RefAST(l19_AST))->add(antlr::RefAST(r19_AST))))))->add(antlr::RefAST(RemoveNextSibling(l19_AST))))); currentAST.root = comp_assign_expr_AST; if ( comp_assign_expr_AST!=RefDNode(antlr::nullAST) && comp_assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = comp_assign_expr_AST->getFirstChild(); else currentAST.child = comp_assign_expr_AST; currentAST.advanceChildToEnd(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } comp_assign_expr_AST = RefDNode(currentAST.root); AssignReplace( l, comp_assign_expr_AST); returnAST = comp_assign_expr_AST; _retTree = _t; } void GDLTreeParser::procedure_call(RefDNode _t) { RefDNode procedure_call_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode procedure_call_AST = RefDNode(antlr::nullAST); RefDNode p = RefDNode(antlr::nullAST); RefDNode p_AST = RefDNode(antlr::nullAST); RefDNode id = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode para_AST = RefDNode(antlr::nullAST); RefDNode para = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case MPCALL: { RefDNode __t82 = _t; RefDNode tmp16_AST = RefDNode(antlr::nullAST); RefDNode tmp16_AST_in = RefDNode(antlr::nullAST); tmp16_AST = astFactory->create(antlr::RefAST(_t)); tmp16_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp16_AST)); antlr::ASTPair __currentAST82 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MPCALL); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); RefDNode tmp17_AST = RefDNode(antlr::nullAST); RefDNode tmp17_AST_in = RefDNode(antlr::nullAST); tmp17_AST = astFactory->create(antlr::RefAST(_t)); tmp17_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp17_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); parameter_def(_t, false); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST82; _t = __t82; _t = _t->getNextSibling(); procedure_call_AST = RefDNode(currentAST.root); break; } case MPCALL_PARENT: { RefDNode __t83 = _t; RefDNode tmp18_AST = RefDNode(antlr::nullAST); RefDNode tmp18_AST_in = RefDNode(antlr::nullAST); tmp18_AST = astFactory->create(antlr::RefAST(_t)); tmp18_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp18_AST)); antlr::ASTPair __currentAST83 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MPCALL_PARENT); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); RefDNode tmp19_AST = RefDNode(antlr::nullAST); RefDNode tmp19_AST_in = RefDNode(antlr::nullAST); tmp19_AST = astFactory->create(antlr::RefAST(_t)); tmp19_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp19_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); RefDNode tmp20_AST = RefDNode(antlr::nullAST); RefDNode tmp20_AST_in = RefDNode(antlr::nullAST); tmp20_AST = astFactory->create(antlr::RefAST(_t)); tmp20_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp20_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); parameter_def(_t, false); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST83; _t = __t83; _t = _t->getNextSibling(); procedure_call_AST = RefDNode(currentAST.root); break; } case PCALL: { RefDNode __t84 = _t; p = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode p_AST_in = RefDNode(antlr::nullAST); p_AST = astFactory->create(antlr::RefAST(p)); astFactory->addASTChild(currentAST, antlr::RefAST(p_AST)); antlr::ASTPair __currentAST84 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),PCALL); _t = _t->getFirstChild(); id = _t; RefDNode id_AST_in = RefDNode(antlr::nullAST); id_AST = astFactory->create(antlr::RefAST(id)); astFactory->addASTChild(currentAST, antlr::RefAST(id_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); // first search library procedures int i=LibProIx(id_AST->getText()); para = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; parameter_def(_t, i != -1 && libProList[ i]->NPar() == -1); _t = _retTree; para_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); if( i != -1) { int nParam = 0; if( para_AST != RefDNode(antlr::nullAST)) nParam = para_AST->GetNParam(); int libParam = libProList[i]->NPar(); int libParamMin = libProList[i]->NParMin(); if( libParam != -1 && nParam > libParam) throw GDLException( p, libProList[i]->Name() + ": Too many arguments."); if( libParam != -1 && nParam < libParamMin) throw GDLException( p, libProList[i]->Name() + ": Too few arguments."); p_AST->setType(PCALL_LIB); p_AST->setText("pcall_lib"); id_AST->SetLibPro( libProList[i]); } else { // then search user defined procedures i=ProIx(id_AST->getText()); id_AST->SetProIx(i); } currentAST = __currentAST84; _t = __t84; _t = _t->getNextSibling(); procedure_call_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = procedure_call_AST; _retTree = _t; } void GDLTreeParser::for_statement(RefDNode _t) { RefDNode for_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode for_statement_AST = RefDNode(antlr::nullAST); RefDNode f = RefDNode(antlr::nullAST); RefDNode f_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); StackSizeGuard guard( loopVarStack); int labelStart = comp.NDefLabel(); RefDNode __t66 = _t; f = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode f_AST_in = RefDNode(antlr::nullAST); f_AST = astFactory->create(antlr::RefAST(f)); astFactory->addASTChild(currentAST, antlr::RefAST(f_AST)); antlr::ASTPair __currentAST66 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),FOR); _t = _t->getFirstChild(); i = _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); astFactory->addASTChild(currentAST, antlr::RefAST(i_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); i_AST->setType(VAR); comp.Var(i_AST); loopVarStack.push_back(i_AST->getText()); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); f_AST->setType(FOR_STEP); f_AST->setText("for_step"); break; } case BLOCK: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } unblock_empty(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST66; _t = __t66; _t = _t->getNextSibling(); f_AST->SetLabelRange( labelStart, comp.NDefLabel()); for_statement_AST = RefDNode(currentAST.root); returnAST = for_statement_AST; _retTree = _t; } void GDLTreeParser::foreach_statement(RefDNode _t) { RefDNode foreach_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode foreach_statement_AST = RefDNode(antlr::nullAST); RefDNode f = RefDNode(antlr::nullAST); RefDNode f_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode l = RefDNode(antlr::nullAST); RefDNode l_AST = RefDNode(antlr::nullAST); StackSizeGuard guard( loopVarStack); int labelStart = comp.NDefLabel(); RefDNode __t69 = _t; f = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode f_AST_in = RefDNode(antlr::nullAST); f_AST = astFactory->create(antlr::RefAST(f)); astFactory->addASTChild(currentAST, antlr::RefAST(f_AST)); antlr::ASTPair __currentAST69 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),FOREACH); _t = _t->getFirstChild(); i = _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); astFactory->addASTChild(currentAST, antlr::RefAST(i_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); i_AST->setType(VAR); comp.Var(i_AST); loopVarStack.push_back(i_AST->getText()); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case IDENTIFIER: { l = _t; RefDNode l_AST_in = RefDNode(antlr::nullAST); l_AST = astFactory->create(antlr::RefAST(l)); astFactory->addASTChild(currentAST, antlr::RefAST(l_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); l_AST->setType(VAR); comp.Var(l_AST); loopVarStack.push_back(l_AST->getText()); f_AST->setType(FOREACH_INDEX); f_AST->setText("foreach_index"); break; } case BLOCK: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } unblock_empty(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST69; _t = __t69; _t = _t->getNextSibling(); f_AST->SetLabelRange( labelStart, comp.NDefLabel()); foreach_statement_AST = RefDNode(currentAST.root); returnAST = foreach_statement_AST; _retTree = _t; } void GDLTreeParser::repeat_statement(RefDNode _t) { RefDNode repeat_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode repeat_statement_AST = RefDNode(antlr::nullAST); RefDNode r = RefDNode(antlr::nullAST); RefDNode r_AST = RefDNode(antlr::nullAST); RefDNode b_AST = RefDNode(antlr::nullAST); RefDNode b = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); int labelStart = comp.NDefLabel(); RefDNode __t62 = _t; r = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode r_AST_in = RefDNode(antlr::nullAST); r_AST = astFactory->create(antlr::RefAST(r)); antlr::ASTPair __currentAST62 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),REPEAT); _t = _t->getFirstChild(); b = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; unblock_empty(_t); _t = _retTree; b_AST = returnAST; e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; currentAST = __currentAST62; _t = __t62; _t = _t->getNextSibling(); repeat_statement_AST = RefDNode(currentAST.root); r_AST->SetLabelRange( labelStart, comp.NDefLabel()); repeat_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(r_AST))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(b_AST)))); if( b_AST == static_cast(antlr::nullAST)) Warning( "Warning: Empty REPEAT UNTIL loop detected."); currentAST.root = repeat_statement_AST; if ( repeat_statement_AST!=RefDNode(antlr::nullAST) && repeat_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = repeat_statement_AST->getFirstChild(); else currentAST.child = repeat_statement_AST; currentAST.advanceChildToEnd(); returnAST = repeat_statement_AST; _retTree = _t; } void GDLTreeParser::while_statement(RefDNode _t) { RefDNode while_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode while_statement_AST = RefDNode(antlr::nullAST); RefDNode w = RefDNode(antlr::nullAST); RefDNode w_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode s_AST = RefDNode(antlr::nullAST); RefDNode s = RefDNode(antlr::nullAST); int labelStart = comp.NDefLabel(); RefDNode __t64 = _t; w = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode w_AST_in = RefDNode(antlr::nullAST); w_AST = astFactory->create(antlr::RefAST(w)); antlr::ASTPair __currentAST64 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),WHILE); _t = _t->getFirstChild(); e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; s = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; statement(_t); _t = _retTree; s_AST = returnAST; currentAST = __currentAST64; _t = __t64; _t = _t->getNextSibling(); while_statement_AST = RefDNode(currentAST.root); w_AST->SetLabelRange( labelStart, comp.NDefLabel()); // swap e <-> s for easier access in interpreter while_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(w_AST))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(s_AST)))); currentAST.root = while_statement_AST; if ( while_statement_AST!=RefDNode(antlr::nullAST) && while_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = while_statement_AST->getFirstChild(); else currentAST.child = while_statement_AST; currentAST.advanceChildToEnd(); returnAST = while_statement_AST; _retTree = _t; } void GDLTreeParser::jump_statement(RefDNode _t) { RefDNode jump_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode jump_statement_AST = RefDNode(antlr::nullAST); RefDNode g = RefDNode(antlr::nullAST); RefDNode g_AST = RefDNode(antlr::nullAST); RefDNode i1 = RefDNode(antlr::nullAST); RefDNode i1_AST = RefDNode(antlr::nullAST); RefDNode r = RefDNode(antlr::nullAST); RefDNode r_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode o = RefDNode(antlr::nullAST); RefDNode o_AST = RefDNode(antlr::nullAST); RefDNode i2 = RefDNode(antlr::nullAST); RefDNode i2_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case GOTO: { RefDNode __t74 = _t; g = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode g_AST_in = RefDNode(antlr::nullAST); g_AST = astFactory->create(antlr::RefAST(g)); antlr::ASTPair __currentAST74 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GOTO); _t = _t->getFirstChild(); i1 = _t; RefDNode i1_AST_in = RefDNode(antlr::nullAST); i1_AST = astFactory->create(antlr::RefAST(i1)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); currentAST = __currentAST74; _t = __t74; _t = _t->getNextSibling(); jump_statement_AST = RefDNode(currentAST.root); jump_statement_AST=astFactory->create(GOTO,i1->getText()); jump_statement_AST->SetLine(g->getLine()); // #jump_statement=#[GOTO,i1->getText()]; // doesn't work // comp.Goto(#jump_statement); currentAST.root = jump_statement_AST; if ( jump_statement_AST!=RefDNode(antlr::nullAST) && jump_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = jump_statement_AST->getFirstChild(); else currentAST.child = jump_statement_AST; currentAST.advanceChildToEnd(); break; } case RETURN: { RefDNode __t75 = _t; r = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode r_AST_in = RefDNode(antlr::nullAST); r_AST = astFactory->create(antlr::RefAST(r)); antlr::ASTPair __currentAST75 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),RETURN); _t = _t->getFirstChild(); bool exprThere=false; { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; exprThere=true; break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST75; _t = __t75; _t = _t->getNextSibling(); jump_statement_AST = RefDNode(currentAST.root); if( comp.IsFun()) { if( !exprThere) throw GDLException( r, "Return statement in functions " "must have 1 value."); // // wrong: this is only true for l_function as return value // // a ARRAYEXPR_MFCALL can only be a MFCALL here -> change tree // if( #e->getType() == ARRAYEXPR_MFCALL) // { // #e->setType( MFCALL); // #e->setText( "mfcall"); // RefDNode mfc; // mfc = #e->getFirstChild(); // mfc = mfc->getNextSibling(); // #e->setFirstChild( antlr::RefAST(mfc)); // } jump_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(RETF,"retf")))->add(antlr::RefAST(e_AST)))); jump_statement_AST->SetLine(r->getLine()); } else { if( exprThere) throw GDLException( _t, "Return statement in " "procedures cannot have values."); jump_statement_AST=astFactory->create(RETP,"retp"); // astFactory.create(RETP,"retp"); jump_statement_AST->SetLine(r->getLine()); } currentAST.root = jump_statement_AST; if ( jump_statement_AST!=RefDNode(antlr::nullAST) && jump_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = jump_statement_AST->getFirstChild(); else currentAST.child = jump_statement_AST; currentAST.advanceChildToEnd(); break; } case ON_IOERROR: { RefDNode __t77 = _t; o = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode o_AST_in = RefDNode(antlr::nullAST); o_AST = astFactory->create(antlr::RefAST(o)); antlr::ASTPair __currentAST77 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ON_IOERROR); _t = _t->getFirstChild(); i2 = _t; RefDNode i2_AST_in = RefDNode(antlr::nullAST); i2_AST = astFactory->create(antlr::RefAST(i2)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); currentAST = __currentAST77; _t = __t77; _t = _t->getNextSibling(); jump_statement_AST = RefDNode(currentAST.root); if( i2->getText() == "NULL") { jump_statement_AST=astFactory->create(ON_IOERROR_NULL, "on_ioerror_null"); jump_statement_AST->SetLine(o->getLine()); } else { jump_statement_AST=astFactory->create(ON_IOERROR,i2->getText()); jump_statement_AST->SetLine(o->getLine()); // #jump_statement=#[ON_IOERROR,i2->getText()]; // comp.Goto(#jump_statement); // same handling } currentAST.root = jump_statement_AST; if ( jump_statement_AST!=RefDNode(antlr::nullAST) && jump_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = jump_statement_AST->getFirstChild(); else currentAST.child = jump_statement_AST; currentAST.advanceChildToEnd(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = jump_statement_AST; _retTree = _t; } void GDLTreeParser::if_statement(RefDNode _t) { RefDNode if_statement_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode if_statement_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode s1_AST = RefDNode(antlr::nullAST); RefDNode s1 = RefDNode(antlr::nullAST); RefDNode s2_AST = RefDNode(antlr::nullAST); RefDNode s2 = RefDNode(antlr::nullAST); // int labelStart = comp.NDefLabel(); RefDNode block; RefDNode __t79 = _t; i = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); antlr::ASTPair __currentAST79 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),IF); _t = _t->getFirstChild(); e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; s1 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; statement(_t); _t = _retTree; s1_AST = returnAST; { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case 3: { if_statement_AST = RefDNode(currentAST.root); // #i->SetLabelRange( labelStart, comp.NDefLabel()); if_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(s1_AST)))); currentAST.root = if_statement_AST; if ( if_statement_AST!=RefDNode(antlr::nullAST) && if_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = if_statement_AST->getFirstChild(); else currentAST.child = if_statement_AST; currentAST.advanceChildToEnd(); break; } case ASSIGN: case BLOCK: case BREAK: case CONTINUE: case COMMONDECL: case COMMONDEF: case FOR: case FOREACH: case MPCALL: case MPCALL_PARENT: case PCALL: case REPEAT: case RETURN: case WHILE: case CASE: case FORWARD: case GOTO: case IF: case ON_IOERROR: case SWITCH: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { s2 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; statement(_t); _t = _retTree; s2_AST = returnAST; if_statement_AST = RefDNode(currentAST.root); i_AST->setText( "if_else"); i_AST->setType( IF_ELSE); // #i->SetLabelRange( labelStart, comp.NDefLabel()); if( s1_AST->getType() != BLOCK) { block = astFactory->create(BLOCK,"block"); block->SetLine( s1_AST->getLine()); if_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(block))->add(antlr::RefAST(s1_AST))))))->add(antlr::RefAST(s2_AST)))); } else if_statement_AST=RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(s1_AST))->add(antlr::RefAST(s2_AST)))); currentAST.root = if_statement_AST; if ( if_statement_AST!=RefDNode(antlr::nullAST) && if_statement_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = if_statement_AST->getFirstChild(); else currentAST.child = if_statement_AST; currentAST.advanceChildToEnd(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST79; _t = __t79; _t = _t->getNextSibling(); returnAST = if_statement_AST; _retTree = _t; } void GDLTreeParser::parameter_def(RefDNode _t, bool varNum ) { RefDNode parameter_def_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode parameter_def_AST = RefDNode(antlr::nullAST); // count positional parameters int nKey = 0; int nPar = 0; { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case KEYDEF: { key_parameter(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); ++nKey; break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { pos_parameter(_t, varNum); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); ++nPar; break; } default: { goto _loop87; } } } _loop87:; } // ( ... )* if( nPar > 0 || nKey > 0) { RefDNode(currentAST.root)->SetNParam( nPar); } parameter_def_AST = RefDNode(currentAST.root); returnAST = parameter_def_AST; _retTree = _t; } void GDLTreeParser::key_parameter(RefDNode _t) { RefDNode key_parameter_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode key_parameter_AST = RefDNode(antlr::nullAST); RefDNode d = RefDNode(antlr::nullAST); RefDNode d_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode k_AST = RefDNode(antlr::nullAST); RefDNode k = RefDNode(antlr::nullAST); RefDNode variable; RefDNode __t89 = _t; d = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode d_AST_in = RefDNode(antlr::nullAST); d_AST = astFactory->create(antlr::RefAST(d)); antlr::ASTPair __currentAST89 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),KEYDEF); _t = _t->getFirstChild(); i = _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); k = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; k_AST = returnAST; key_parameter_AST = RefDNode(currentAST.root); variable=comp.ByReference(k_AST); if( variable != static_cast(antlr::nullAST)) { int vT = variable->getType(); if( IsREF_CHECK(vT)) { d_AST=astFactory->create(KEYDEF_REF_CHECK,"keydef_ref_check"); key_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(d_AST))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(k_AST)))); } else if( variable == k_AST) { d_AST=astFactory->create(KEYDEF_REF,"keydef_ref"); key_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(d_AST))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(variable)))); } else { d_AST=astFactory->create(KEYDEF_REF_EXPR,"keydef_ref_expr"); key_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(d_AST))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(k_AST))->add(antlr::RefAST(variable)))); } } else { int t = k_AST->getType(); // Note: Right now there are no MFCALL_LIB or MFCALL_PARENT_LIB nodes if( IsREF_CHECK(t)) // t == FCALL_LIB // || t == MFCALL_LIB // || t == FCALL_LIB_N_ELEMENTS // || t == MFCALL_PARENT_LIB // || t == QUESTION // || t == FCALL || t == MFCALL || t == MFCALL_PARENT // || t == ARRAYEXPR_FCALL // || t == ARRAYEXPR_MFCALL // // t == FCALL_LIB_RETNEW || t == MFCALL_LIB_RETNEW || // // t == MFCALL_PARENT_LIB_RETNEW //|| // // t == ARRARYEXPR_MFCALL_LIB // MFCALL_LIB or VAR or DEREF // // ) { d_AST=astFactory->create(KEYDEF_REF_CHECK,"keydef_ref_check"); key_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(d_AST))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(k_AST)))); } // else if( t == FCALL_LIB_RETNEW || t == MFCALL_LIB_RETNEW) // { // // #d=#[KEYDEF_REF,"keydef_ref"]; // #key_parameter=#(d,i,k); // } else { key_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(d_AST))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(k_AST)))); } } currentAST.root = key_parameter_AST; if ( key_parameter_AST!=RefDNode(antlr::nullAST) && key_parameter_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = key_parameter_AST->getFirstChild(); else currentAST.child = key_parameter_AST; currentAST.advanceChildToEnd(); currentAST = __currentAST89; _t = __t89; _t = _t->getNextSibling(); returnAST = key_parameter_AST; _retTree = _t; } void GDLTreeParser::pos_parameter(RefDNode _t, bool varNum ) { RefDNode pos_parameter_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode pos_parameter_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode variable; e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; pos_parameter_AST = RefDNode(currentAST.root); variable=comp.ByReference(e_AST); if( variable != static_cast(antlr::nullAST)) { int vT = variable->getType(); if( IsREF_CHECK(vT)) { if( varNum) pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(REF_CHECK_VN,"ref_check_vn")))->add(antlr::RefAST(e_AST)))); else pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(REF_CHECK,"ref_check")))->add(antlr::RefAST(e_AST)))); } else if( variable == e_AST) { if( varNum) pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(REF_VN,"ref_vn")))->add(antlr::RefAST(variable)))); else pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(REF,"ref")))->add(antlr::RefAST(variable)))); } else { if( varNum) pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(REF_EXPR_VN,"ref_expr_vn")))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(variable)))); else pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(REF_EXPR,"ref_expr")))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(variable)))); } } else { int t = e_AST->getType(); // Note: Right now there are no MFCALL_LIB or MFCALL_PARENT_LIB nodes if( IsREF_CHECK(t)) // if( t == FCALL_LIB // || t == MFCALL_LIB //t == FCALL_LIB_N_ELEMENTS || // || t == MFCALL_PARENT_LIB // || t == QUESTION // // TODO: These are ref check as well, but parameter nodes need to know // || t == FCALL || t == MFCALL || t == MFCALL_PARENT // || t == ARRAYEXPR_FCALL // || t == ARRAYEXPR_MFCALL // // t == FCALL_LIB_RETNEW || t == MFCALL_LIB_RETNEW || // // t == MFCALL_PARENT_LIB_RETNEW // // t == ARRARYEXPR_MFCALL_LIB // MFCALL_LIB or VAR or DEREF // ) { // something like: CALLAPRO,reform(a,/OVERWRITE) if( varNum) pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(REF_CHECK_VN,"ref_check_vn")))->add(antlr::RefAST(e_AST)))); else pos_parameter_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(REF_CHECK,"ref_check")))->add(antlr::RefAST(e_AST)))); } else { if( varNum) pos_parameter_AST= RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(PARAEXPR_VN,"paraexpr_vn")))->add(antlr::RefAST(e_AST)))); else pos_parameter_AST= RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(PARAEXPR,"paraexpr")))->add(antlr::RefAST(e_AST)))); } } currentAST.root = pos_parameter_AST; if ( pos_parameter_AST!=RefDNode(antlr::nullAST) && pos_parameter_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = pos_parameter_AST->getFirstChild(); else currentAST.child = pos_parameter_AST; currentAST.advanceChildToEnd(); returnAST = pos_parameter_AST; _retTree = _t; } int GDLTreeParser::array_def(RefDNode _t) { int depth; RefDNode array_def_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_def_AST = RefDNode(antlr::nullAST); RefDNode a = RefDNode(antlr::nullAST); RefDNode a_AST = RefDNode(antlr::nullAST); RefDNode aa = RefDNode(antlr::nullAST); RefDNode aa_AST = RefDNode(antlr::nullAST); RefDNode aaa = RefDNode(antlr::nullAST); RefDNode aaa_AST = RefDNode(antlr::nullAST); RefDNode sPos; if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYDEF: { RefDNode __t92 = _t; a = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a_AST_in = RefDNode(antlr::nullAST); a_AST = astFactory->create(antlr::RefAST(a)); astFactory->addASTChild(currentAST, antlr::RefAST(a_AST)); antlr::ASTPair __currentAST92 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYDEF); _t = _t->getFirstChild(); sPos=_t; { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_1.member(_t->getType()))) { expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); /*check for constant expression*/ } else { goto _loop94; } } _loop94:; } // ( ... )* currentAST = __currentAST92; _t = __t92; _t = _t->getNextSibling(); // better check here as then CONSTANT is propagated depth=0; // bool constant = true; // bool depth0 = false; for( RefDNode e=sPos; e != static_cast(antlr::nullAST); e=e->getNextSibling()) { // if( e->getType() != CONSTANT) // constant = false; // if( !depth0) if( (e->getType() != ARRAYDEF) && (e->getType() != ARRAYDEF_CONST) && (e->getType() != ARRAYDEF_GENERALIZED_INDGEN)) { depth=0; break; // depth0 = true; } else { int act=array_def(e); // recursive call act=act+1; if( depth == 0) { depth=act; } else { if( depth > act) depth=act; } } } a_AST->SetArrayDepth(depth); array_def_AST = RefDNode(currentAST.root); break; } case ARRAYDEF_CONST: { RefDNode __t95 = _t; aa = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode aa_AST_in = RefDNode(antlr::nullAST); aa_AST = astFactory->create(antlr::RefAST(aa)); astFactory->addASTChild(currentAST, antlr::RefAST(aa_AST)); antlr::ASTPair __currentAST95 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYDEF_CONST); _t = _t->getFirstChild(); sPos=_t; { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_1.member(_t->getType()))) { expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { goto _loop97; } } _loop97:; } // ( ... )* currentAST = __currentAST95; _t = __t95; _t = _t->getNextSibling(); depth=0; for( RefDNode e=sPos; e != static_cast(antlr::nullAST); e=e->getNextSibling()) { if( (e->getType() != ARRAYDEF) && (e->getType() != ARRAYDEF_CONST) && (e->getType() != ARRAYDEF_GENERALIZED_INDGEN)) { depth=0; break; } else { int act=array_def(e); // recursive call act=act+1; if( depth == 0) { depth=act; } else { if( depth > act) depth=act; } } } aa_AST->SetArrayDepth(depth); array_def_AST = RefDNode(currentAST.root); break; } case ARRAYDEF_GENERALIZED_INDGEN: { RefDNode __t98 = _t; aaa = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode aaa_AST_in = RefDNode(antlr::nullAST); aaa_AST = astFactory->create(antlr::RefAST(aaa)); astFactory->addASTChild(currentAST, antlr::RefAST(aaa_AST)); antlr::ASTPair __currentAST98 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYDEF_GENERALIZED_INDGEN); _t = _t->getFirstChild(); sPos=_t; { // ( ... )* for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_tokenSet_1.member(_t->getType()))) { expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { goto _loop100; } } _loop100:; } // ( ... )* currentAST = __currentAST98; _t = __t98; _t = _t->getNextSibling(); depth=0; for( RefDNode e=sPos; e != static_cast(antlr::nullAST); e=e->getNextSibling()) { if( (e->getType() != ARRAYDEF) && (e->getType() != ARRAYDEF_CONST) && (e->getType() != ARRAYDEF_GENERALIZED_INDGEN)) { depth=0; break; } else { int act=array_def(e); // recursive call act=act+1; if( depth == 0) { depth=act; std::cerr< act) depth=act; } } } aaa_AST->SetArrayDepth(depth); array_def_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = array_def_AST; _retTree = _t; return depth; } void GDLTreeParser::struct_def(RefDNode _t) { RefDNode struct_def_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode struct_def_AST = RefDNode(antlr::nullAST); RefDNode n = RefDNode(antlr::nullAST); RefDNode n_AST = RefDNode(antlr::nullAST); bool noTagName = false; if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case NSTRUC_REF: { RefDNode __t102 = _t; n = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode n_AST_in = RefDNode(antlr::nullAST); n_AST = astFactory->create(antlr::RefAST(n)); astFactory->addASTChild(currentAST, antlr::RefAST(n_AST)); antlr::ASTPair __currentAST102 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),NSTRUC_REF); _t = _t->getFirstChild(); RefDNode tmp21_AST = RefDNode(antlr::nullAST); RefDNode tmp21_AST_in = RefDNode(antlr::nullAST); tmp21_AST = astFactory->create(antlr::RefAST(_t)); tmp21_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp21_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case IDENTIFIER: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case INHERITS: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { { // ( ... )+ int _cnt105=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); noTagName = true; break; } case IDENTIFIER: { RefDNode tmp22_AST = RefDNode(antlr::nullAST); RefDNode tmp22_AST_in = RefDNode(antlr::nullAST); tmp22_AST = astFactory->create(antlr::RefAST(_t)); tmp22_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp22_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); break; } case INHERITS: { RefDNode tmp23_AST = RefDNode(antlr::nullAST); RefDNode tmp23_AST_in = RefDNode(antlr::nullAST); tmp23_AST = astFactory->create(antlr::RefAST(_t)); tmp23_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp23_AST)); match(antlr::RefAST(_t),INHERITS); _t = _t->getNextSibling(); RefDNode tmp24_AST = RefDNode(antlr::nullAST); RefDNode tmp24_AST_in = RefDNode(antlr::nullAST); tmp24_AST = astFactory->create(antlr::RefAST(_t)); tmp24_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp24_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); break; } default: { if ( _cnt105>=1 ) { goto _loop105; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } } _cnt105++; } _loop105:; } // ( ... )+ // set to nstruct if defined here n_AST->setType(NSTRUC); n_AST->setText("nstruct"); n_AST->DefinedStruct( noTagName); break; } case 3: { break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST102; _t = __t102; _t = _t->getNextSibling(); struct_def_AST = RefDNode(currentAST.root); break; } case STRUC: { RefDNode __t106 = _t; RefDNode tmp25_AST = RefDNode(antlr::nullAST); RefDNode tmp25_AST_in = RefDNode(antlr::nullAST); tmp25_AST = astFactory->create(antlr::RefAST(_t)); tmp25_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp25_AST)); antlr::ASTPair __currentAST106 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),STRUC); _t = _t->getFirstChild(); { // ( ... )+ int _cnt108=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == IDENTIFIER)) { tag_def(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { if ( _cnt108>=1 ) { goto _loop108; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt108++; } _loop108:; } // ( ... )+ currentAST = __currentAST106; _t = __t106; _t = _t->getNextSibling(); struct_def_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = struct_def_AST; _retTree = _t; } void GDLTreeParser::tag_def(RefDNode _t) { RefDNode tag_def_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_def_AST = RefDNode(antlr::nullAST); RefDNode tmp26_AST = RefDNode(antlr::nullAST); RefDNode tmp26_AST_in = RefDNode(antlr::nullAST); tmp26_AST = astFactory->create(antlr::RefAST(_t)); tmp26_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp26_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_def_AST = RefDNode(currentAST.root); returnAST = tag_def_AST; _retTree = _t; } void GDLTreeParser::arrayindex(RefDNode _t, ArrayIndexVectorT* ixList ) { RefDNode arrayindex_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayindex_AST = RefDNode(antlr::nullAST); RefDNode e1_AST = RefDNode(antlr::nullAST); RefDNode e1 = RefDNode(antlr::nullAST); RefDNode e2_AST = RefDNode(antlr::nullAST); RefDNode e2 = RefDNode(antlr::nullAST); RefDNode e3_AST = RefDNode(antlr::nullAST); RefDNode e3 = RefDNode(antlr::nullAST); RefDNode e4_AST = RefDNode(antlr::nullAST); RefDNode e4 = RefDNode(antlr::nullAST); BaseGDL *c1, *c2, *c3, *c4; { RefDNode __t112 = _t; RefDNode tmp27_AST = RefDNode(antlr::nullAST); RefDNode tmp27_AST_in = RefDNode(antlr::nullAST); tmp27_AST = astFactory->create(antlr::RefAST(_t)); tmp27_AST_in = _t; antlr::ASTPair __currentAST112 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYIX); _t = _t->getFirstChild(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ALL: { RefDNode tmp28_AST = RefDNode(antlr::nullAST); RefDNode tmp28_AST_in = RefDNode(antlr::nullAST); tmp28_AST = astFactory->create(antlr::RefAST(_t)); tmp28_AST_in = _t; match(antlr::RefAST(_t),ALL); _t = _t->getNextSibling(); ixList->push_back( new ArrayIndexAll()); break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { { e1 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e1_AST = returnAST; // in ConstantIndex the cData of all nodes is stolen // (in case it succeeds) // therefore we build here the new constant node with // proper cData. See below (e2) c1 = comp.ConstantIndex( e1_AST); if( c1 != NULL) { int e1Line = e1_AST->getLine(); e1_AST = astFactory->create(CONSTANT,"CONST_IX"); e1_AST->ResetCData( c1); e1_AST->SetLine( e1Line); } { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case 3: { arrayindex_AST = RefDNode(currentAST.root); bool constantOK = false; if( c1 != NULL) { DType dType = c1->Type(); int typeCheck = DTypeOrder[ dType]; if( dType == GDL_STRING || typeCheck >= 100) { //delete c1; } else { try { // ATTENTION: These two grab c1 (all others don't) // a bit unclean, but for maximum efficiency if( c1->Rank() == 0) ixList->push_back( new CArrayIndexScalar( c1)); else ixList->push_back( new CArrayIndexIndexed( c1)); // prevent c1 from being deleted e1_AST->StealCData(); // ok, as #e1 is not used anymore constantOK = true; } catch( GDLException& e) { //delete c1; // owned by #e1 } } } if( !constantOK) { if( LoopVar( e1_AST)) { if( e1_AST->getType() == VAR) ixList->push_back( new ArrayIndexScalar( e1_AST)); else ixList->push_back( new ArrayIndexScalarVP( e1_AST)); } else { arrayindex_AST = e1_AST; ixList->push_back( new ArrayIndexIndexed()); } } currentAST.root = arrayindex_AST; if ( arrayindex_AST!=RefDNode(antlr::nullAST) && arrayindex_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_AST->getFirstChild(); else currentAST.child = arrayindex_AST; currentAST.advanceChildToEnd(); break; } case ALL: { RefDNode tmp29_AST = RefDNode(antlr::nullAST); RefDNode tmp29_AST_in = RefDNode(antlr::nullAST); tmp29_AST = astFactory->create(antlr::RefAST(_t)); tmp29_AST_in = _t; match(antlr::RefAST(_t),ALL); _t = _t->getNextSibling(); { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case 3: { arrayindex_AST = RefDNode(currentAST.root); //c1 = comp.ConstantIndex( #e1); if( c1 != NULL) { ixList->push_back( new CArrayIndexORange( c1)); } else { arrayindex_AST = e1_AST; ixList->push_back( new ArrayIndexORange()); } currentAST.root = arrayindex_AST; if ( arrayindex_AST!=RefDNode(antlr::nullAST) && arrayindex_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_AST->getFirstChild(); else currentAST.child = arrayindex_AST; currentAST.advanceChildToEnd(); break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { e2 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e2_AST = returnAST; // in ConstantIndex the cData of all nodes is stolen // (in case it succeeds) // therefore we build here the new constant node with // proper cData. This is crucial because if e. g. only e1 but not e2 // is constant, #e1 is put to the output tree (with stolen cData) -> crash c2 = comp.ConstantIndex( e2_AST); if( c2 != NULL) { int e2Line = e2_AST->getLine(); e2_AST = astFactory->create(CONSTANT,"CONST_IX"); e2_AST->ResetCData( c2); e2_AST->SetLine( e2Line); } arrayindex_AST = RefDNode(currentAST.root); //c1 = comp.ConstantIndex( #e1); //c2 = comp.ConstantIndex( #e2); if( c1 != NULL && c2 != NULL) { ixList->push_back( new CArrayIndexORangeS( c1, c2)); } else { //delete c1; //delete c2; arrayindex_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(NULL))->add(antlr::RefAST(e1_AST))->add(antlr::RefAST(e2_AST)))); ixList->push_back( new ArrayIndexORangeS()); } currentAST.root = arrayindex_AST; if ( arrayindex_AST!=RefDNode(antlr::nullAST) && arrayindex_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_AST->getFirstChild(); else currentAST.child = arrayindex_AST; currentAST.advanceChildToEnd(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { e3 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e3_AST = returnAST; // see above (#e2) c3 = comp.ConstantIndex( e3_AST); if( c3 != NULL) { int e3Line = e3_AST->getLine(); e3_AST = astFactory->create(CONSTANT,"CONST_IX"); e3_AST->ResetCData( c3); e3_AST->SetLine( e3Line); } { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case 3: { arrayindex_AST = RefDNode(currentAST.root); //c1 = comp.ConstantIndex( #e1); //c3 = comp.ConstantIndex( #e3); if( c1 != NULL && c3 != NULL) { ixList->push_back( new CArrayIndexRange( c1, c3)); } else { //delete c1; //delete c3; arrayindex_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(NULL))->add(antlr::RefAST(e1_AST))->add(antlr::RefAST(e3_AST)))); ixList->push_back( new ArrayIndexRange()); } currentAST.root = arrayindex_AST; if ( arrayindex_AST!=RefDNode(antlr::nullAST) && arrayindex_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_AST->getFirstChild(); else currentAST.child = arrayindex_AST; currentAST.advanceChildToEnd(); break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case DEREF: case EXPR: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case POSTDEC: case POSTINC: case STRUC: case SYSVAR: case UMINUS: case VAR: case AND_OP: case EQ_OP: case GE_OP: case GT_OP: case LE_OP: case LT_OP: case MOD_OP: case NE_OP: case NOT_OP: case OR_OP: case XOR_OP: case DEC: case INC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: case SLASH: case ASTERIX: case DOT: case POW: case MATRIX_OP1: case MATRIX_OP2: case PLUS: case MINUS: case LTMARK: case GTMARK: case LOG_NEG: case LOG_AND: case LOG_OR: case QUESTION: { e4 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e4_AST = returnAST; // see above (#e2) c4 = comp.ConstantIndex( e4_AST); if( c4 != NULL) { int e4Line = e4_AST->getLine(); e4_AST = astFactory->create(CONSTANT,"CONST_IX"); e4_AST->ResetCData( c4); e4_AST->SetLine( e4Line); } arrayindex_AST = RefDNode(currentAST.root); //c1 = comp.ConstantIndex( #e1); //c3 = comp.ConstantIndex( #e3); //c4 = comp.ConstantIndex( #e4); if( c1 != NULL && c3 != NULL && c4 != NULL) { ixList->push_back( new CArrayIndexRangeS( c1, c3, c4)); } else { //delete c1; //delete c3; //delete c4; arrayindex_AST = RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(NULL))->add(antlr::RefAST(e1_AST))->add(antlr::RefAST(e3_AST))->add(antlr::RefAST(e4_AST)))); ixList->push_back( new ArrayIndexRangeS()); } currentAST.root = arrayindex_AST; if ( arrayindex_AST!=RefDNode(antlr::nullAST) && arrayindex_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_AST->getFirstChild(); else currentAST.child = arrayindex_AST; currentAST.advanceChildToEnd(); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } } break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } } currentAST = __currentAST112; _t = __t112; _t = _t->getNextSibling(); } returnAST = arrayindex_AST; _retTree = _t; } void GDLTreeParser::arrayindex_list(RefDNode _t) { RefDNode arrayindex_list_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayindex_list_AST = RefDNode(antlr::nullAST); ArrayIndexVectorT* ixList = new ArrayIndexVectorT(); PtrGuard< ArrayIndexVectorT> guard( ixList); { // ( ... )+ int _cnt120=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == ARRAYIX)) { arrayindex(_t, ixList); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); } else { if ( _cnt120>=1 ) { goto _loop120; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt120++; } _loop120:; } // ( ... )+ arrayindex_list_AST = RefDNode(currentAST.root); arrayindex_list_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(astFactory->create(ARRAYIX,"[...]")))->add(antlr::RefAST(arrayindex_list_AST)))); // ixList->Freeze(); // do all initial one-time settings // if( ixList->NDim() == 1) // #arrayindex_list = #([ARRAYIX1,"[ix]"], arrayindex_list); // else // { // #arrayindex_list = #([ARRAYIX,"[...]"], arrayindex_list); // ixList->Freeze(); // do all initial one-time settings // } guard.Release(); ArrayIndexListT* arrayIndexNoAssoc; ArrayIndexListT* arrayIndex; MakeArrayIndex( ixList, &arrayIndex, &arrayIndexNoAssoc); delete ixList; arrayindex_list_AST->SetArrayIndexList( arrayIndex, arrayIndexNoAssoc); currentAST.root = arrayindex_list_AST; if ( arrayindex_list_AST!=RefDNode(antlr::nullAST) && arrayindex_list_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_list_AST->getFirstChild(); else currentAST.child = arrayindex_list_AST; currentAST.advanceChildToEnd(); arrayindex_list_AST = RefDNode(currentAST.root); returnAST = arrayindex_list_AST; _retTree = _t; } void GDLTreeParser::lassign_expr(RefDNode _t) { RefDNode lassign_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode lassign_expr_AST = RefDNode(antlr::nullAST); RefDNode ex_AST = RefDNode(antlr::nullAST); RefDNode ex = RefDNode(antlr::nullAST); ex = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; ex_AST = returnAST; lassign_expr_AST = RefDNode(currentAST.root); // remove last pair of braces if( ex_AST->getType()==EXPR) { // int cT = #ex->getFirstChild()->getType(); // if( cT != FCALL && // cT != MFCALL && // cT != MFCALL_PARENT && // cT != FCALL_LIB && // cT != MFCALL_LIB && // cT != MFCALL_PARENT_LIB) ex_AST=ex_AST->getFirstChild(); } if( ex_AST->getType()==ASSIGN) throw GDLException( _t, "Assign expression is not allowed as " "l-expression in assignment"); lassign_expr_AST= ex_AST; //#( NULL, ex); currentAST.root = lassign_expr_AST; if ( lassign_expr_AST!=RefDNode(antlr::nullAST) && lassign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = lassign_expr_AST->getFirstChild(); else currentAST.child = lassign_expr_AST; currentAST.advanceChildToEnd(); returnAST = lassign_expr_AST; _retTree = _t; } void GDLTreeParser::assign_expr(RefDNode _t) { RefDNode assign_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode assign_expr_AST = RefDNode(antlr::nullAST); RefDNode a = RefDNode(antlr::nullAST); RefDNode a_AST = RefDNode(antlr::nullAST); RefDNode l_AST = RefDNode(antlr::nullAST); RefDNode l = RefDNode(antlr::nullAST); RefDNode r_AST = RefDNode(antlr::nullAST); RefDNode r = RefDNode(antlr::nullAST); RefDNode __t123 = _t; a = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a_AST_in = RefDNode(antlr::nullAST); a_AST = astFactory->create(antlr::RefAST(a)); antlr::ASTPair __currentAST123 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ASSIGN); _t = _t->getFirstChild(); l = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; lassign_expr(_t); _t = _retTree; l_AST = returnAST; r = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; r_AST = returnAST; currentAST = __currentAST123; _t = __t123; _t = _t->getNextSibling(); assign_expr_AST = RefDNode(currentAST.root); if( !SelfAssignment( l_AST, r_AST)) { AssignReplace( l_AST, a_AST); // int lT = #l->getType(); // if( lT == FCALL || lT == MFCALL || lT == MFCALL_PARENT || // lT == FCALL_LIB || lT == MFCALL_LIB || lT == MFCALL_PARENT_LIB || // lT == DEREF || lT == VAR || lT == VARPTR) // #a->setType( ASSIGN_REPLACE); assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(a_AST))->add(antlr::RefAST(r_AST))->add(antlr::RefAST(l_AST)))); } else { assign_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(1))->add(antlr::RefAST(l_AST)))); } currentAST.root = assign_expr_AST; if ( assign_expr_AST!=RefDNode(antlr::nullAST) && assign_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = assign_expr_AST->getFirstChild(); else currentAST.child = assign_expr_AST; currentAST.advanceChildToEnd(); returnAST = assign_expr_AST; _retTree = _t; } void GDLTreeParser::sysvar(RefDNode _t) { RefDNode sysvar_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode sysvar_AST = RefDNode(antlr::nullAST); RefDNode s = RefDNode(antlr::nullAST); RefDNode s_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode __t148 = _t; s = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode s_AST_in = RefDNode(antlr::nullAST); s_AST = astFactory->create(antlr::RefAST(s)); antlr::ASTPair __currentAST148 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),SYSVAR); _t = _t->getFirstChild(); i = _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); match(antlr::RefAST(_t),SYSVARNAME); _t = _t->getNextSibling(); currentAST = __currentAST148; _t = __t148; _t = _t->getNextSibling(); sysvar_AST = RefDNode(currentAST.root); std::string sysVarName = i->getText(); // here we create the real sysvar node sysvar_AST=astFactory->create(SYSVAR, sysVarName.substr(1)); sysvar_AST->SetLine(s->getLine()); // #sysvar=#[SYSVAR,i->getText()]; comp.SysVar(sysvar_AST); // sets var to NULL currentAST.root = sysvar_AST; if ( sysvar_AST!=RefDNode(antlr::nullAST) && sysvar_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = sysvar_AST->getFirstChild(); else currentAST.child = sysvar_AST; currentAST.advanceChildToEnd(); returnAST = sysvar_AST; _retTree = _t; } void GDLTreeParser::var(RefDNode _t) { RefDNode var_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode var_AST = RefDNode(antlr::nullAST); RefDNode v = RefDNode(antlr::nullAST); RefDNode v_AST = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode __t150 = _t; v = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode v_AST_in = RefDNode(antlr::nullAST); v_AST = astFactory->create(antlr::RefAST(v)); antlr::ASTPair __currentAST150 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),VAR); _t = _t->getFirstChild(); i = _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); currentAST = __currentAST150; _t = __t150; _t = _t->getNextSibling(); var_AST = RefDNode(currentAST.root); var_AST=astFactory->create(VAR,i->getText()); var_AST->SetLine(v->getLine()); // #var=#[VAR,i->getText()]; comp.Var(var_AST); currentAST.root = var_AST; if ( var_AST!=RefDNode(antlr::nullAST) && var_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = var_AST->getFirstChild(); else currentAST.child = var_AST; currentAST.advanceChildToEnd(); returnAST = var_AST; _retTree = _t; } void GDLTreeParser::arrayindex_list_to_parameter_list(RefDNode _t, bool varNum ) { RefDNode arrayindex_list_to_parameter_list_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayindex_list_to_parameter_list_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); int nPar = 0; { // ( ... )+ int _cnt154=0; for (;;) { if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; if ((_t->getType() == ARRAYIX)) { RefDNode __t153 = _t; RefDNode tmp30_AST = RefDNode(antlr::nullAST); RefDNode tmp30_AST_in = RefDNode(antlr::nullAST); tmp30_AST = astFactory->create(antlr::RefAST(_t)); tmp30_AST_in = _t; antlr::ASTPair __currentAST153 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYIX); _t = _t->getFirstChild(); e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; pos_parameter(_t, varNum); _t = _retTree; e_AST = returnAST; currentAST = __currentAST153; _t = __t153; _t = _t->getNextSibling(); arrayindex_list_to_parameter_list_AST = RefDNode(currentAST.root); arrayindex_list_to_parameter_list_AST= RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(NULL))->add(antlr::RefAST(arrayindex_list_to_parameter_list_AST))->add(antlr::RefAST(e_AST)))); ++nPar; currentAST.root = arrayindex_list_to_parameter_list_AST; if ( arrayindex_list_to_parameter_list_AST!=RefDNode(antlr::nullAST) && arrayindex_list_to_parameter_list_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayindex_list_to_parameter_list_AST->getFirstChild(); else currentAST.child = arrayindex_list_to_parameter_list_AST; currentAST.advanceChildToEnd(); } else { if ( _cnt154>=1 ) { goto _loop154; } else {throw antlr::NoViableAltException(antlr::RefAST(_t));} } _cnt154++; } _loop154:; } // ( ... )+ arrayindex_list_to_parameter_list_AST->SetNParam( nPar); returnAST = arrayindex_list_to_parameter_list_AST; _retTree = _t; } void GDLTreeParser::arrayexpr_fn(RefDNode _t) { RefDNode arrayexpr_fn_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayexpr_fn_AST = RefDNode(antlr::nullAST); RefDNode aIn = RefDNode(antlr::nullAST); RefDNode aIn_AST = RefDNode(antlr::nullAST); RefDNode va = RefDNode(antlr::nullAST); RefDNode va_AST = RefDNode(antlr::nullAST); RefDNode id = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode el_AST = RefDNode(antlr::nullAST); RefDNode el = RefDNode(antlr::nullAST); std::string id_text; bool isVar; RefDNode mark, va2, vaAlt, fn, arrayindex_listAST; RefDNode __t156 = _t; aIn = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode aIn_AST_in = RefDNode(antlr::nullAST); aIn_AST = astFactory->create(antlr::RefAST(aIn)); antlr::ASTPair __currentAST156 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYEXPR_FCALL); _t = _t->getFirstChild(); RefDNode __t157 = _t; va = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode va_AST_in = RefDNode(antlr::nullAST); va_AST = astFactory->create(antlr::RefAST(va)); antlr::ASTPair __currentAST157 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),VAR); _t = _t->getFirstChild(); id = _t; RefDNode id_AST_in = RefDNode(antlr::nullAST); id_AST = astFactory->create(antlr::RefAST(id)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); currentAST = __currentAST157; _t = __t157; _t = _t->getNextSibling(); mark = _t; id_text = id_AST->getText(); // IsVar is not needed, we must emit an ARRAYEXPR_FCALL even if the variable is known // (rule: Accessible functions always override variables //isVar = comp.IsVar( id_text); // isVar == true -> VAR for sure // (== false: maybe VAR nevertheless) int libIx = -1; // if( id_text != "LIST" && id_text != "HASH") libIx = LibFunIx(id_text); { el = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; arrayindex_list_to_parameter_list(_t, libIx != -1 && libFunList[ libIx]->NPar() == -1); _t = _retTree; el_AST = returnAST; } arrayexpr_fn_AST = RefDNode(currentAST.root); // first search library functions if( libIx != -1) { int nParam = 0; if( el_AST != RefDNode(antlr::nullAST)) nParam = el_AST->GetNParam(); int libParam = libFunList[libIx]->NPar(); int libParamMin = libFunList[libIx]->NParMin(); if( libParam != -1 && nParam > libParam) throw GDLException( aIn, libFunList[libIx]->Name() + ": Too many arguments."); if( libParam != -1 && nParam < libParamMin) throw GDLException( aIn, libFunList[libIx]->Name() + ": Too few arguments."); id_AST->SetLibFun( libFunList[libIx]); if( libFunList[ libIx]->RetNew()) { if( libFunList[ libIx]->Name() == "N_ELEMENTS") id_AST->setType( FCALL_LIB_N_ELEMENTS); else if( libFunList[ libIx]->DirectCall()) id_AST->setType( FCALL_LIB_DIRECT); else id_AST->setType( FCALL_LIB_RETNEW); arrayexpr_fn_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(el_AST)))); // #([/*FCALL_LIB_RETNEW,"fcall_lib_retnew"],*/ id, el); } else { id_AST->setType( FCALL_LIB); arrayexpr_fn_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(el_AST)))); // #(/*[FCALL_LIB,"fcall_lib"],*/ id, el); } } // then search user defined functions else { int funIx=FunIx( id_text); // we use #id for the FCALL part id_AST->setType( FCALL); id_AST->SetFunIx( funIx); if( funIx != -1) // found -> FCALL { arrayexpr_fn_AST = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(el_AST)))); // #(/*[FCALL,"fcall"],*/ id, el); } else // function not found -> still ambiguous { // _t = mark; // rewind to parse again arrayindex_list( mark); //_t = _retTree; arrayindex_listAST = returnAST; va2=astFactory->create( VAR, id_text); // #va=#[VAR,id->getText()]; comp.Var( va2); // we declare the variable here! // if IsVar() still would be used this would lead to surprising behavior: // e. g.: function_call(42) & function_call(43) // The first (42) would be an ARRAYEXPR_FCALL the 2nd (43) an ARRAYEXPR // if then at runtime function "function_call" is known, // it will be called only at the first appearance of the call. // that's why we cannot allow unambiguous VAR here vaAlt = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ARRAYEXPR,"arrayexpr")))->add(antlr::RefAST(va2))->add(antlr::RefAST(arrayindex_listAST)))); fn = RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(id_AST))->add(antlr::RefAST(el_AST)))); arrayexpr_fn_AST = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(aIn_AST))->add(antlr::RefAST(vaAlt))->add(antlr::RefAST(fn)))); } } // // not valid s. a. (kept for reference): unambiguous VAR // { // variable -> arrayexpr // // make var // #va=astFactory->create(VAR,#id->getText()); // // #va=#[VAR,id->getText()]; // comp.Var(#va); // #arrayexpr_fn= // #([ARRAYEXPR,"arrayexpr"], va, al); // } currentAST.root = arrayexpr_fn_AST; if ( arrayexpr_fn_AST!=RefDNode(antlr::nullAST) && arrayexpr_fn_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayexpr_fn_AST->getFirstChild(); else currentAST.child = arrayexpr_fn_AST; currentAST.advanceChildToEnd(); currentAST = __currentAST156; _t = __t156; _t = _t->getNextSibling(); returnAST = arrayexpr_fn_AST; _retTree = _t; } void GDLTreeParser::arrayexpr_mfcall(RefDNode _t) { RefDNode arrayexpr_mfcall_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode arrayexpr_mfcall_AST = RefDNode(antlr::nullAST); RefDNode a = RefDNode(antlr::nullAST); RefDNode a_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode i = RefDNode(antlr::nullAST); RefDNode i_AST = RefDNode(antlr::nullAST); RefDNode e2_AST = RefDNode(antlr::nullAST); RefDNode e2 = RefDNode(antlr::nullAST); RefDNode i2 = RefDNode(antlr::nullAST); RefDNode i2_AST = RefDNode(antlr::nullAST); RefDNode a2_AST = RefDNode(antlr::nullAST); RefDNode a2 = RefDNode(antlr::nullAST); RefDNode __t160 = _t; a = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode a_AST_in = RefDNode(antlr::nullAST); a_AST = astFactory->create(antlr::RefAST(a)); antlr::ASTPair __currentAST160 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYEXPR_MFCALL); _t = _t->getFirstChild(); RefDNode mark = _t; // mark e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; i = _t; RefDNode i_AST_in = RefDNode(antlr::nullAST); i_AST = astFactory->create(antlr::RefAST(i)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); bool success = true; RefDNode first; try { arrayindex_list(_t); RefDNode al = returnAST; RefDNode ae = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(ARRAYEXPR,"arrayexpr")))->add(antlr::RefAST(i_AST))->add(antlr::RefAST(al)))); if( e->getType() == DOT) { int nDot = e_AST->GetNDot(); e_AST->SetNDot( ++nDot); e_AST->addChild( ae); first = e_AST; } else { RefDNode dot = RefDNode(astFactory->make((new antlr::ASTArray(3))->add(antlr::RefAST(astFactory->create(DOT,".")))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(ae)))); dot->SetNDot( 1); first = dot; } } catch( GDLException& ex) { Message( "Ambiguity resolved: member function call " "due to invalid array index."); success = false; a_AST->setType( MFCALL); a_AST->setText( "mfcall"); } _t = mark; // rewind to parse again e2 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e2_AST = returnAST; i2 = _t; RefDNode i2_AST_in = RefDNode(antlr::nullAST); i2_AST = astFactory->create(antlr::RefAST(i2)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); a2 = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; arrayindex_list_to_parameter_list(_t, false); _t = _retTree; a2_AST = returnAST; arrayexpr_mfcall_AST = RefDNode(currentAST.root); if( success) arrayexpr_mfcall_AST = RefDNode(astFactory->make((new antlr::ASTArray(5))->add(antlr::RefAST(a_AST))->add(antlr::RefAST(first))->add(antlr::RefAST(e2_AST))->add(antlr::RefAST(i2_AST))->add(antlr::RefAST(a2_AST)))); else arrayexpr_mfcall_AST = RefDNode(astFactory->make((new antlr::ASTArray(4))->add(antlr::RefAST(a_AST))->add(antlr::RefAST(e2_AST))->add(antlr::RefAST(i2_AST))->add(antlr::RefAST(a2_AST)))); currentAST.root = arrayexpr_mfcall_AST; if ( arrayexpr_mfcall_AST!=RefDNode(antlr::nullAST) && arrayexpr_mfcall_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = arrayexpr_mfcall_AST->getFirstChild(); else currentAST.child = arrayexpr_mfcall_AST; currentAST.advanceChildToEnd(); currentAST = __currentAST160; _t = __t160; _t = _t->getNextSibling(); returnAST = arrayexpr_mfcall_AST; _retTree = _t; } void GDLTreeParser::primary_expr(RefDNode _t) { RefDNode primary_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode primary_expr_AST = RefDNode(antlr::nullAST); RefDNode f = RefDNode(antlr::nullAST); RefDNode f_AST = RefDNode(antlr::nullAST); RefDNode id = RefDNode(antlr::nullAST); RefDNode id_AST = RefDNode(antlr::nullAST); RefDNode p_AST = RefDNode(antlr::nullAST); RefDNode p = RefDNode(antlr::nullAST); RefDNode g = RefDNode(antlr::nullAST); RefDNode g_AST = RefDNode(antlr::nullAST); int dummy; RefDNode mark; if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ASSIGN: { assign_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); primary_expr_AST = RefDNode(currentAST.root); break; } case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { comp_assign_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); primary_expr_AST = RefDNode(currentAST.root); break; } case ARRAYEXPR_MFCALL: { arrayexpr_mfcall(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); primary_expr_AST = RefDNode(currentAST.root); break; } case MFCALL: { RefDNode __t162 = _t; RefDNode tmp31_AST = RefDNode(antlr::nullAST); RefDNode tmp31_AST_in = RefDNode(antlr::nullAST); tmp31_AST = astFactory->create(antlr::RefAST(_t)); tmp31_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp31_AST)); antlr::ASTPair __currentAST162 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MFCALL); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); RefDNode tmp32_AST = RefDNode(antlr::nullAST); RefDNode tmp32_AST_in = RefDNode(antlr::nullAST); tmp32_AST = astFactory->create(antlr::RefAST(_t)); tmp32_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp32_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); parameter_def(_t, false); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST162; _t = __t162; _t = _t->getNextSibling(); primary_expr_AST = RefDNode(currentAST.root); break; } case MFCALL_PARENT: { RefDNode __t163 = _t; RefDNode tmp33_AST = RefDNode(antlr::nullAST); RefDNode tmp33_AST_in = RefDNode(antlr::nullAST); tmp33_AST = astFactory->create(antlr::RefAST(_t)); tmp33_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp33_AST)); antlr::ASTPair __currentAST163 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MFCALL_PARENT); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); RefDNode tmp34_AST = RefDNode(antlr::nullAST); RefDNode tmp34_AST_in = RefDNode(antlr::nullAST); tmp34_AST = astFactory->create(antlr::RefAST(_t)); tmp34_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp34_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); RefDNode tmp35_AST = RefDNode(antlr::nullAST); RefDNode tmp35_AST_in = RefDNode(antlr::nullAST); tmp35_AST = astFactory->create(antlr::RefAST(_t)); tmp35_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp35_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); parameter_def(_t, false); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST163; _t = __t163; _t = _t->getNextSibling(); primary_expr_AST = RefDNode(currentAST.root); break; } case FCALL: { RefDNode __t164 = _t; f = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode f_AST_in = RefDNode(antlr::nullAST); f_AST = astFactory->create(antlr::RefAST(f)); astFactory->addASTChild(currentAST, antlr::RefAST(f_AST)); antlr::ASTPair __currentAST164 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),FCALL); _t = _t->getFirstChild(); id = _t; RefDNode id_AST_in = RefDNode(antlr::nullAST); id_AST = astFactory->create(antlr::RefAST(id)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); // first search library functions int i=LibFunIx(id->getText()); p = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; parameter_def(_t, i != -1 && libFunList[ i]->NPar() == -1); _t = _retTree; p_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); if( i != -1) { // N_ELEMENTS must handle exceptions during parameter evaluation // if( StrUpCase( #id->getText()) == "N_ELEMENTS") // { // #f->setType(FCALL_LIB_N_ELEMENTS); // #f->setText(#id->getText()); // #f->SetLibFun( libFunList[i]); // // #id->SetFunIx(i); // } // else { int nParam = 0; if( p_AST != RefDNode(antlr::nullAST)) nParam = p_AST->GetNParam(); int libParam = libFunList[i]->NPar(); int libParamMin = libFunList[i]->NParMin(); if( libParam != -1 && nParam > libParam) throw GDLException( f, libFunList[i]->Name() + ": Too many arguments."); if( libParam != -1 && nParam < libParamMin) throw GDLException( f, libFunList[i]->Name() + ": Too few arguments."); if( libFunList[ i]->RetNew()) { if( libFunList[ i]->Name() == "N_ELEMENTS") f_AST->setType( FCALL_LIB_N_ELEMENTS); else if( libFunList[ i]->DirectCall()) f_AST->setType( FCALL_LIB_DIRECT); else f_AST->setType(FCALL_LIB_RETNEW); f_AST->setText(id_AST->getText()); f_AST->SetLibFun( libFunList[i]); // #id->SetFunIx(i); } else { f_AST->setType(FCALL_LIB); f_AST->setText(id_AST->getText()); f_AST->SetLibFun( libFunList[i]); // #id->SetFunIx(i); } } } else { // then search user defined functions f_AST->setType(FCALL); f_AST->setText(id_AST->getText()); i=FunIx(id_AST->getText()); f_AST->SetFunIx(i); } currentAST = __currentAST164; _t = __t164; _t = _t->getNextSibling(); primary_expr_AST = RefDNode(currentAST.root); break; } case ARRAYEXPR_FCALL: { arrayexpr_fn(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); primary_expr_AST = RefDNode(currentAST.root); break; } case CONSTANT: { RefDNode tmp36_AST = RefDNode(antlr::nullAST); RefDNode tmp36_AST_in = RefDNode(antlr::nullAST); tmp36_AST = astFactory->create(antlr::RefAST(_t)); tmp36_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp36_AST)); match(antlr::RefAST(_t),CONSTANT); _t = _t->getNextSibling(); primary_expr_AST = RefDNode(currentAST.root); break; } case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: { dummy=array_def(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); primary_expr_AST = RefDNode(currentAST.root); break; } case NSTRUC_REF: case STRUC: { struct_def(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); primary_expr_AST = RefDNode(currentAST.root); break; } case GDLNULL: { g = _t; RefDNode g_AST_in = RefDNode(antlr::nullAST); g_AST = astFactory->create(antlr::RefAST(g)); astFactory->addASTChild(currentAST, antlr::RefAST(g_AST)); match(antlr::RefAST(_t),GDLNULL); _t = _t->getNextSibling(); g_AST->setType(SYSVAR); g_AST->setText("NULL"); comp.SysVar(g_AST); // sets var to NULL primary_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = primary_expr_AST; _retTree = _t; } void GDLTreeParser::op_expr(RefDNode _t) { RefDNode op_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode op_expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case QUESTION: { RefDNode __t166 = _t; RefDNode tmp37_AST = RefDNode(antlr::nullAST); RefDNode tmp37_AST_in = RefDNode(antlr::nullAST); tmp37_AST = astFactory->create(antlr::RefAST(_t)); tmp37_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp37_AST)); antlr::ASTPair __currentAST166 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),QUESTION); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST166; _t = __t166; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case AND_OP: { RefDNode __t167 = _t; RefDNode tmp38_AST = RefDNode(antlr::nullAST); RefDNode tmp38_AST_in = RefDNode(antlr::nullAST); tmp38_AST = astFactory->create(antlr::RefAST(_t)); tmp38_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp38_AST)); antlr::ASTPair __currentAST167 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),AND_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST167; _t = __t167; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case OR_OP: { RefDNode __t168 = _t; RefDNode tmp39_AST = RefDNode(antlr::nullAST); RefDNode tmp39_AST_in = RefDNode(antlr::nullAST); tmp39_AST = astFactory->create(antlr::RefAST(_t)); tmp39_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp39_AST)); antlr::ASTPair __currentAST168 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),OR_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST168; _t = __t168; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case XOR_OP: { RefDNode __t169 = _t; RefDNode tmp40_AST = RefDNode(antlr::nullAST); RefDNode tmp40_AST_in = RefDNode(antlr::nullAST); tmp40_AST = astFactory->create(antlr::RefAST(_t)); tmp40_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp40_AST)); antlr::ASTPair __currentAST169 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),XOR_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST169; _t = __t169; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case LOG_AND: { RefDNode __t170 = _t; RefDNode tmp41_AST = RefDNode(antlr::nullAST); RefDNode tmp41_AST_in = RefDNode(antlr::nullAST); tmp41_AST = astFactory->create(antlr::RefAST(_t)); tmp41_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp41_AST)); antlr::ASTPair __currentAST170 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LOG_AND); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST170; _t = __t170; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case LOG_OR: { RefDNode __t171 = _t; RefDNode tmp42_AST = RefDNode(antlr::nullAST); RefDNode tmp42_AST_in = RefDNode(antlr::nullAST); tmp42_AST = astFactory->create(antlr::RefAST(_t)); tmp42_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp42_AST)); antlr::ASTPair __currentAST171 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LOG_OR); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST171; _t = __t171; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case EQ_OP: { RefDNode __t172 = _t; RefDNode tmp43_AST = RefDNode(antlr::nullAST); RefDNode tmp43_AST_in = RefDNode(antlr::nullAST); tmp43_AST = astFactory->create(antlr::RefAST(_t)); tmp43_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp43_AST)); antlr::ASTPair __currentAST172 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),EQ_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST172; _t = __t172; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case NE_OP: { RefDNode __t173 = _t; RefDNode tmp44_AST = RefDNode(antlr::nullAST); RefDNode tmp44_AST_in = RefDNode(antlr::nullAST); tmp44_AST = astFactory->create(antlr::RefAST(_t)); tmp44_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp44_AST)); antlr::ASTPair __currentAST173 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),NE_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST173; _t = __t173; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case LE_OP: { RefDNode __t174 = _t; RefDNode tmp45_AST = RefDNode(antlr::nullAST); RefDNode tmp45_AST_in = RefDNode(antlr::nullAST); tmp45_AST = astFactory->create(antlr::RefAST(_t)); tmp45_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp45_AST)); antlr::ASTPair __currentAST174 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LE_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST174; _t = __t174; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case LT_OP: { RefDNode __t175 = _t; RefDNode tmp46_AST = RefDNode(antlr::nullAST); RefDNode tmp46_AST_in = RefDNode(antlr::nullAST); tmp46_AST = astFactory->create(antlr::RefAST(_t)); tmp46_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp46_AST)); antlr::ASTPair __currentAST175 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LT_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST175; _t = __t175; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case GE_OP: { RefDNode __t176 = _t; RefDNode tmp47_AST = RefDNode(antlr::nullAST); RefDNode tmp47_AST_in = RefDNode(antlr::nullAST); tmp47_AST = astFactory->create(antlr::RefAST(_t)); tmp47_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp47_AST)); antlr::ASTPair __currentAST176 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GE_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST176; _t = __t176; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case GT_OP: { RefDNode __t177 = _t; RefDNode tmp48_AST = RefDNode(antlr::nullAST); RefDNode tmp48_AST_in = RefDNode(antlr::nullAST); tmp48_AST = astFactory->create(antlr::RefAST(_t)); tmp48_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp48_AST)); antlr::ASTPair __currentAST177 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GT_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST177; _t = __t177; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case NOT_OP: { RefDNode __t178 = _t; RefDNode tmp49_AST = RefDNode(antlr::nullAST); RefDNode tmp49_AST_in = RefDNode(antlr::nullAST); tmp49_AST = astFactory->create(antlr::RefAST(_t)); tmp49_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp49_AST)); antlr::ASTPair __currentAST178 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),NOT_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST178; _t = __t178; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case PLUS: { RefDNode __t179 = _t; RefDNode tmp50_AST = RefDNode(antlr::nullAST); RefDNode tmp50_AST_in = RefDNode(antlr::nullAST); tmp50_AST = astFactory->create(antlr::RefAST(_t)); tmp50_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp50_AST)); antlr::ASTPair __currentAST179 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),PLUS); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST179; _t = __t179; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case MINUS: { RefDNode __t180 = _t; RefDNode tmp51_AST = RefDNode(antlr::nullAST); RefDNode tmp51_AST_in = RefDNode(antlr::nullAST); tmp51_AST = astFactory->create(antlr::RefAST(_t)); tmp51_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp51_AST)); antlr::ASTPair __currentAST180 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MINUS); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST180; _t = __t180; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case LTMARK: { RefDNode __t181 = _t; RefDNode tmp52_AST = RefDNode(antlr::nullAST); RefDNode tmp52_AST_in = RefDNode(antlr::nullAST); tmp52_AST = astFactory->create(antlr::RefAST(_t)); tmp52_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp52_AST)); antlr::ASTPair __currentAST181 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LTMARK); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST181; _t = __t181; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case GTMARK: { RefDNode __t182 = _t; RefDNode tmp53_AST = RefDNode(antlr::nullAST); RefDNode tmp53_AST_in = RefDNode(antlr::nullAST); tmp53_AST = astFactory->create(antlr::RefAST(_t)); tmp53_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp53_AST)); antlr::ASTPair __currentAST182 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),GTMARK); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST182; _t = __t182; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case UMINUS: { uminus(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); op_expr_AST = RefDNode(currentAST.root); break; } case LOG_NEG: { RefDNode __t183 = _t; RefDNode tmp54_AST = RefDNode(antlr::nullAST); RefDNode tmp54_AST_in = RefDNode(antlr::nullAST); tmp54_AST = astFactory->create(antlr::RefAST(_t)); tmp54_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp54_AST)); antlr::ASTPair __currentAST183 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),LOG_NEG); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST183; _t = __t183; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case ASTERIX: { RefDNode __t184 = _t; RefDNode tmp55_AST = RefDNode(antlr::nullAST); RefDNode tmp55_AST_in = RefDNode(antlr::nullAST); tmp55_AST = astFactory->create(antlr::RefAST(_t)); tmp55_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp55_AST)); antlr::ASTPair __currentAST184 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ASTERIX); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST184; _t = __t184; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case MATRIX_OP1: { RefDNode __t185 = _t; RefDNode tmp56_AST = RefDNode(antlr::nullAST); RefDNode tmp56_AST_in = RefDNode(antlr::nullAST); tmp56_AST = astFactory->create(antlr::RefAST(_t)); tmp56_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp56_AST)); antlr::ASTPair __currentAST185 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MATRIX_OP1); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST185; _t = __t185; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case MATRIX_OP2: { RefDNode __t186 = _t; RefDNode tmp57_AST = RefDNode(antlr::nullAST); RefDNode tmp57_AST_in = RefDNode(antlr::nullAST); tmp57_AST = astFactory->create(antlr::RefAST(_t)); tmp57_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp57_AST)); antlr::ASTPair __currentAST186 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MATRIX_OP2); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST186; _t = __t186; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case SLASH: { RefDNode __t187 = _t; RefDNode tmp58_AST = RefDNode(antlr::nullAST); RefDNode tmp58_AST_in = RefDNode(antlr::nullAST); tmp58_AST = astFactory->create(antlr::RefAST(_t)); tmp58_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp58_AST)); antlr::ASTPair __currentAST187 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),SLASH); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST187; _t = __t187; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case MOD_OP: { RefDNode __t188 = _t; RefDNode tmp59_AST = RefDNode(antlr::nullAST); RefDNode tmp59_AST_in = RefDNode(antlr::nullAST); tmp59_AST = astFactory->create(antlr::RefAST(_t)); tmp59_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp59_AST)); antlr::ASTPair __currentAST188 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),MOD_OP); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST188; _t = __t188; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case POW: { RefDNode __t189 = _t; RefDNode tmp60_AST = RefDNode(antlr::nullAST); RefDNode tmp60_AST_in = RefDNode(antlr::nullAST); tmp60_AST = astFactory->create(antlr::RefAST(_t)); tmp60_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp60_AST)); antlr::ASTPair __currentAST189 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),POW); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST189; _t = __t189; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case DEC: { RefDNode __t190 = _t; RefDNode tmp61_AST = RefDNode(antlr::nullAST); RefDNode tmp61_AST_in = RefDNode(antlr::nullAST); tmp61_AST = astFactory->create(antlr::RefAST(_t)); tmp61_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp61_AST)); antlr::ASTPair __currentAST190 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),DEC); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST190; _t = __t190; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case INC: { RefDNode __t191 = _t; RefDNode tmp62_AST = RefDNode(antlr::nullAST); RefDNode tmp62_AST_in = RefDNode(antlr::nullAST); tmp62_AST = astFactory->create(antlr::RefAST(_t)); tmp62_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp62_AST)); antlr::ASTPair __currentAST191 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),INC); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST191; _t = __t191; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case POSTDEC: { RefDNode __t192 = _t; RefDNode tmp63_AST = RefDNode(antlr::nullAST); RefDNode tmp63_AST_in = RefDNode(antlr::nullAST); tmp63_AST = astFactory->create(antlr::RefAST(_t)); tmp63_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp63_AST)); antlr::ASTPair __currentAST192 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),POSTDEC); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST192; _t = __t192; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case POSTINC: { RefDNode __t193 = _t; RefDNode tmp64_AST = RefDNode(antlr::nullAST); RefDNode tmp64_AST_in = RefDNode(antlr::nullAST); tmp64_AST = astFactory->create(antlr::RefAST(_t)); tmp64_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp64_AST)); antlr::ASTPair __currentAST193 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),POSTINC); _t = _t->getFirstChild(); expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST193; _t = __t193; _t = _t->getNextSibling(); op_expr_AST = RefDNode(currentAST.root); break; } case ASSIGN: case ARRAYDEF: case ARRAYDEF_CONST: case ARRAYDEF_GENERALIZED_INDGEN: case ARRAYEXPR_FCALL: case ARRAYEXPR_MFCALL: case CONSTANT: case FCALL: case GDLNULL: case MFCALL: case MFCALL_PARENT: case NSTRUC_REF: case STRUC: case AND_OP_EQ: case ASTERIX_EQ: case EQ_OP_EQ: case GE_OP_EQ: case GTMARK_EQ: case GT_OP_EQ: case LE_OP_EQ: case LTMARK_EQ: case LT_OP_EQ: case MATRIX_OP1_EQ: case MATRIX_OP2_EQ: case MINUS_EQ: case MOD_OP_EQ: case NE_OP_EQ: case OR_OP_EQ: case PLUS_EQ: case POW_EQ: case SLASH_EQ: case XOR_OP_EQ: { primary_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); op_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = op_expr_AST; _retTree = _t; } void GDLTreeParser::uminus(RefDNode _t) { RefDNode uminus_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode uminus_AST = RefDNode(antlr::nullAST); RefDNode u = RefDNode(antlr::nullAST); RefDNode u_AST = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode __t195 = _t; u = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode u_AST_in = RefDNode(antlr::nullAST); u_AST = astFactory->create(antlr::RefAST(u)); astFactory->addASTChild(currentAST, antlr::RefAST(u_AST)); antlr::ASTPair __currentAST195 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),UMINUS); _t = _t->getFirstChild(); e = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; e_AST = returnAST; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST195; _t = __t195; _t = _t->getNextSibling(); uminus_AST = RefDNode(currentAST.root); // eliminate (pre-calculate) uminus for constants if( e_AST->getType() == CONSTANT) { e_AST->ResetCData( e_AST->CData()->UMinus()); e_AST->setText( "-"+e_AST->getText()); uminus_AST = e_AST; } // else // { // #uminus = #( [UMINUS,"u-"], e); // } currentAST.root = uminus_AST; if ( uminus_AST!=RefDNode(antlr::nullAST) && uminus_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = uminus_AST->getFirstChild(); else currentAST.child = uminus_AST; currentAST.advanceChildToEnd(); uminus_AST = RefDNode(currentAST.root); returnAST = uminus_AST; _retTree = _t; } void GDLTreeParser::brace_expr(RefDNode _t) { RefDNode brace_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode brace_expr_AST = RefDNode(antlr::nullAST); RefDNode e = RefDNode(antlr::nullAST); RefDNode e_AST = RefDNode(antlr::nullAST); RefDNode ex_AST = RefDNode(antlr::nullAST); RefDNode ex = RefDNode(antlr::nullAST); RefDNode __t197 = _t; e = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; RefDNode e_AST_in = RefDNode(antlr::nullAST); e_AST = astFactory->create(antlr::RefAST(e)); antlr::ASTPair __currentAST197 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),EXPR); _t = _t->getFirstChild(); ex = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; ex_AST = returnAST; currentAST = __currentAST197; _t = __t197; _t = _t->getNextSibling(); brace_expr_AST = RefDNode(currentAST.root); while( ex_AST->getType()==EXPR) ex_AST=ex_AST->getFirstChild(); brace_expr_AST=RefDNode(astFactory->make((new antlr::ASTArray(2))->add(antlr::RefAST(e_AST))->add(antlr::RefAST(ex_AST)))); currentAST.root = brace_expr_AST; if ( brace_expr_AST!=RefDNode(antlr::nullAST) && brace_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = brace_expr_AST->getFirstChild(); else currentAST.child = brace_expr_AST; currentAST.advanceChildToEnd(); returnAST = brace_expr_AST; _retTree = _t; } void GDLTreeParser::unbrace_expr(RefDNode _t) { RefDNode unbrace_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode unbrace_expr_AST = RefDNode(antlr::nullAST); RefDNode ex_AST = RefDNode(antlr::nullAST); RefDNode ex = RefDNode(antlr::nullAST); RefDNode __t199 = _t; RefDNode tmp65_AST = RefDNode(antlr::nullAST); RefDNode tmp65_AST_in = RefDNode(antlr::nullAST); tmp65_AST = astFactory->create(antlr::RefAST(_t)); tmp65_AST_in = _t; antlr::ASTPair __currentAST199 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),EXPR); _t = _t->getFirstChild(); ex = (_t == ASTNULL) ? RefDNode(antlr::nullAST) : _t; expr(_t); _t = _retTree; ex_AST = returnAST; currentAST = __currentAST199; _t = __t199; _t = _t->getNextSibling(); unbrace_expr_AST = RefDNode(currentAST.root); while( ex_AST->getType()==EXPR) ex_AST=ex_AST->getFirstChild(); unbrace_expr_AST=ex_AST; currentAST.root = unbrace_expr_AST; if ( unbrace_expr_AST!=RefDNode(antlr::nullAST) && unbrace_expr_AST->getFirstChild() != RefDNode(antlr::nullAST) ) currentAST.child = unbrace_expr_AST->getFirstChild(); else currentAST.child = unbrace_expr_AST; currentAST.advanceChildToEnd(); returnAST = unbrace_expr_AST; _retTree = _t; } void GDLTreeParser::indexable_expr(RefDNode _t) { RefDNode indexable_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode indexable_expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case VAR: { var(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); indexable_expr_AST = RefDNode(currentAST.root); break; } case SYSVAR: { sysvar(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); indexable_expr_AST = RefDNode(currentAST.root); break; } case EXPR: { unbrace_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); indexable_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = indexable_expr_AST; _retTree = _t; } void GDLTreeParser::array_expr(RefDNode _t) { RefDNode array_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode array_expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { RefDNode __t202 = _t; RefDNode tmp66_AST = RefDNode(antlr::nullAST); RefDNode tmp66_AST_in = RefDNode(antlr::nullAST); tmp66_AST = astFactory->create(antlr::RefAST(_t)); tmp66_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp66_AST)); antlr::ASTPair __currentAST202 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); indexable_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); arrayindex_list(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST202; _t = __t202; _t = _t->getNextSibling(); array_expr_AST = RefDNode(currentAST.root); break; } case EXPR: case SYSVAR: case VAR: { indexable_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); array_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = array_expr_AST; _retTree = _t; } void GDLTreeParser::tag_indexable_expr(RefDNode _t) { RefDNode tag_indexable_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_indexable_expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case VAR: { var(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_indexable_expr_AST = RefDNode(currentAST.root); break; } case SYSVAR: { sysvar(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_indexable_expr_AST = RefDNode(currentAST.root); break; } case EXPR: { brace_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_indexable_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = tag_indexable_expr_AST; _retTree = _t; } void GDLTreeParser::tag_array_expr_1st(RefDNode _t) { RefDNode tag_array_expr_1st_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_array_expr_1st_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { RefDNode __t205 = _t; RefDNode tmp67_AST = RefDNode(antlr::nullAST); RefDNode tmp67_AST_in = RefDNode(antlr::nullAST); tmp67_AST = astFactory->create(antlr::RefAST(_t)); tmp67_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp67_AST)); antlr::ASTPair __currentAST205 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); tag_indexable_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); arrayindex_list(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST205; _t = __t205; _t = _t->getNextSibling(); tag_array_expr_1st_AST = RefDNode(currentAST.root); break; } case EXPR: case SYSVAR: case VAR: { tag_indexable_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_array_expr_1st_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = tag_array_expr_1st_AST; _retTree = _t; } void GDLTreeParser::tag_expr(RefDNode _t) { RefDNode tag_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case EXPR: { brace_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_expr_AST = RefDNode(currentAST.root); break; } case IDENTIFIER: { RefDNode tmp68_AST = RefDNode(antlr::nullAST); RefDNode tmp68_AST_in = RefDNode(antlr::nullAST); tmp68_AST = astFactory->create(antlr::RefAST(_t)); tmp68_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp68_AST)); match(antlr::RefAST(_t),IDENTIFIER); _t = _t->getNextSibling(); tag_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = tag_expr_AST; _retTree = _t; } void GDLTreeParser::tag_array_expr(RefDNode _t) { RefDNode tag_array_expr_AST_in = (_t == RefDNode(ASTNULL)) ? RefDNode(antlr::nullAST) : _t; returnAST = RefDNode(antlr::nullAST); antlr::ASTPair currentAST; RefDNode tag_array_expr_AST = RefDNode(antlr::nullAST); if (_t == RefDNode(antlr::nullAST) ) _t = ASTNULL; switch ( _t->getType()) { case ARRAYEXPR: { RefDNode __t208 = _t; RefDNode tmp69_AST = RefDNode(antlr::nullAST); RefDNode tmp69_AST_in = RefDNode(antlr::nullAST); tmp69_AST = astFactory->create(antlr::RefAST(_t)); tmp69_AST_in = _t; astFactory->addASTChild(currentAST, antlr::RefAST(tmp69_AST)); antlr::ASTPair __currentAST208 = currentAST; currentAST.root = currentAST.child; currentAST.child = RefDNode(antlr::nullAST); match(antlr::RefAST(_t),ARRAYEXPR); _t = _t->getFirstChild(); tag_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); arrayindex_list(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); currentAST = __currentAST208; _t = __t208; _t = _t->getNextSibling(); tag_array_expr_AST = RefDNode(currentAST.root); break; } case EXPR: case IDENTIFIER: { tag_expr(_t); _t = _retTree; astFactory->addASTChild(currentAST, antlr::RefAST(returnAST)); tag_array_expr_AST = RefDNode(currentAST.root); break; } default: { throw antlr::NoViableAltException(antlr::RefAST(_t)); } } returnAST = tag_array_expr_AST; _retTree = _t; } void GDLTreeParser::initializeASTFactory( antlr::ASTFactory& factory ) { factory.setMaxNodeType(237); } const char* GDLTreeParser::tokenNames[] = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "ALL", "ASSIGN", "ASSIGN_INPLACE", "ASSIGN_REPLACE", "ASSIGN_ARRAYEXPR_MFCALL", "ARRAYDEF", "ARRAYDEF_CONST", "ARRAYDEF_GENERALIZED_INDGEN", "ARRAYIX", "ARRAYIX_ALL", "ARRAYIX_ORANGE", "ARRAYIX_RANGE", "ARRAYIX_ORANGE_S", "ARRAYIX_RANGE_S", "ARRAYEXPR", "ARRAYEXPR_FCALL", "ARRAYEXPR_MFCALL", "BLOCK", "BREAK", "CSBLOCK", "CONTINUE", "COMMONDECL", "COMMONDEF", "CONSTANT", "DEREF", "ELSEBLK", "EXPR", "\"for\"", "FOR_STEP", "\"foreach\"", "FOREACH_INDEX", "FOR_LOOP", "FOR_STEP_LOOP", "FOREACH_LOOP", "FOREACH_INDEX_LOOP", "FCALL", "FCALL_LIB", "FCALL_LIB_DIRECT", "FCALL_LIB_N_ELEMENTS", "FCALL_LIB_RETNEW", "GDLNULL", "IF_ELSE", "KEYDECL", "KEYDEF", "KEYDEF_REF", "KEYDEF_REF_CHECK", "KEYDEF_REF_EXPR", "LABEL", "MPCALL", "MPCALL_PARENT", "MFCALL", "MFCALL_LIB", "MFCALL_LIB_RETNEW", "MFCALL_PARENT", "MFCALL_PARENT_LIB", "MFCALL_PARENT_LIB_RETNEW", "NOP", "NSTRUC", "NSTRUC_REF", "ON_IOERROR_NULL", "PCALL", "PCALL_LIB", "PARADECL", "PARAEXPR", "PARAEXPR_VN", "DEC_REF_CHECK", "INC_REF_CHECK", "POSTDEC", "POSTINC", "DECSTATEMENT", "INCSTATEMENT", "REF", "REF_VN", "REF_CHECK", "REF_CHECK_VN", "REF_EXPR", "REF_EXPR_VN", "\"repeat\"", "REPEAT_LOOP", "RETURN", "RETF", "RETP", "STRUC", "SYSVAR", "UMINUS", "VAR", "VARPTR", "\"while\"", "IDENTIFIER", "\"and\"", "\"begin\"", "\"case\"", "\"common\"", "\"compile_opt\"", "\"do\"", "\"else\"", "\"end\"", "\"endcase\"", "\"endelse\"", "\"endfor\"", "\"endforeach\"", "\"endif\"", "\"endrep\"", "\"endswitch\"", "\"endwhile\"", "\"eq\"", "\"forward_function\"", "\"function\"", "\"ge\"", "\"goto\"", "\"gt\"", "\"if\"", "\"inherits\"", "\"le\"", "\"lt\"", "\"mod\"", "\"ne\"", "\"not\"", "\"of\"", "\"on_ioerror\"", "\"or\"", "\"pro\"", "\"switch\"", "\"then\"", "\"until\"", "\"xor\"", "METHOD", "COMMA", "COLON", "END_U", "EQUAL", "DEC", "INC", "AND_OP_EQ", "ASTERIX_EQ", "EQ_OP_EQ", "GE_OP_EQ", "GTMARK_EQ", "GT_OP_EQ", "LE_OP_EQ", "LTMARK_EQ", "LT_OP_EQ", "MATRIX_OP1_EQ", "MATRIX_OP2_EQ", "MINUS_EQ", "MOD_OP_EQ", "NE_OP_EQ", "OR_OP_EQ", "PLUS_EQ", "POW_EQ", "SLASH_EQ", "XOR_OP_EQ", "MEMBER", "LBRACE", "RBRACE", "SLASH", "LSQUARE", "RSQUARE", "SYSVARNAME", "EXCLAMATION", "LCURLY", "RCURLY", "CONSTANT_HEX_BYTE", "CONSTANT_HEX_LONG", "CONSTANT_HEX_LONG64", "CONSTANT_HEX_INT", "CONSTANT_HEX_I", "CONSTANT_HEX_ULONG", "CONSTANT_HEX_ULONG64", "CONSTANT_HEX_UI", "CONSTANT_HEX_UINT", "CONSTANT_BYTE", "CONSTANT_LONG", "CONSTANT_LONG64", "CONSTANT_INT", "CONSTANT_I", "CONSTANT_ULONG", "CONSTANT_ULONG64", "CONSTANT_UI", "CONSTANT_UINT", "CONSTANT_OCT_BYTE", "CONSTANT_OCT_LONG", "CONSTANT_OCT_LONG64", "CONSTANT_OCT_INT", "CONSTANT_OCT_I", "CONSTANT_OCT_ULONG", "CONSTANT_OCT_ULONG64", "CONSTANT_OCT_UI", "CONSTANT_OCT_UINT", "CONSTANT_FLOAT", "CONSTANT_DOUBLE", "CONSTANT_BIN_BYTE", "CONSTANT_BIN_LONG", "CONSTANT_BIN_LONG64", "CONSTANT_BIN_INT", "CONSTANT_BIN_I", "CONSTANT_BIN_ULONG", "CONSTANT_BIN_ULONG64", "CONSTANT_BIN_UI", "CONSTANT_BIN_UINT", "ASTERIX", "DOT", "STRING_LITERAL", "POW", "MATRIX_OP1", "MATRIX_OP2", "PLUS", "MINUS", "LTMARK", "GTMARK", "LOG_NEG", "LOG_AND", "LOG_OR", "QUESTION", "STRING", "INCLUDE", "EOL", "W", "D", "L", "H", "O", "B", "EXP", "DBL_E", "DBL", "CONSTANT_OR_STRING_LITERAL", "COMMENT", "END_MARKER", "WHITESPACE", "SKIP_LINES", "CONT_STATEMENT", "END_OF_LINE", "MAX_TOKEN_NUMBER", 0 }; const unsigned long GDLTreeParser::_tokenSet_0_data_[] = { 2271215648UL, 3145730UL, 2282356737UL, 1208631296UL, 268435328UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // ASSIGN BLOCK BREAK CONTINUE COMMONDECL COMMONDEF "for" "foreach" MPCALL // MPCALL_PARENT PCALL "repeat" RETURN "while" "case" "forward_function" // "goto" "if" "on_ioerror" "switch" DEC INC AND_OP_EQ ASTERIX_EQ EQ_OP_EQ // GE_OP_EQ GTMARK_EQ GT_OP_EQ LE_OP_EQ LTMARK_EQ LT_OP_EQ MATRIX_OP1_EQ // MATRIX_OP2_EQ MINUS_EQ MOD_OP_EQ NE_OP_EQ OR_OP_EQ PLUS_EQ POW_EQ SLASH_EQ // XOR_OP_EQ const antlr::BitSet GDLTreeParser::_tokenSet_0(_tokenSet_0_data_,12); const unsigned long GDLTreeParser::_tokenSet_1_data_[] = { 1478233632UL, 1111494784UL, 599785856UL, 333783040UL, 2415918978UL, 0UL, 67088384UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // ASSIGN ARRAYDEF ARRAYDEF_CONST ARRAYDEF_GENERALIZED_INDGEN ARRAYEXPR // ARRAYEXPR_FCALL ARRAYEXPR_MFCALL CONSTANT DEREF EXPR FCALL GDLNULL MFCALL // MFCALL_PARENT NSTRUC_REF POSTDEC POSTINC STRUC SYSVAR UMINUS VAR "and" // "eq" "ge" "gt" "le" "lt" "mod" "ne" "not" "or" "xor" DEC INC AND_OP_EQ // ASTERIX_EQ EQ_OP_EQ GE_OP_EQ GTMARK_EQ GT_OP_EQ LE_OP_EQ LTMARK_EQ LT_OP_EQ // MATRIX_OP1_EQ MATRIX_OP2_EQ MINUS_EQ MOD_OP_EQ NE_OP_EQ OR_OP_EQ PLUS_EQ // POW_EQ SLASH_EQ XOR_OP_EQ SLASH ASTERIX DOT POW MATRIX_OP1 MATRIX_OP2 // PLUS MINUS LTMARK GTMARK LOG_NEG LOG_AND LOG_OR QUESTION const antlr::BitSet GDLTreeParser::_tokenSet_1(_tokenSet_1_data_,16); gdl-0.9.9/src/GDLTreeParser.hpp000066400000000000000000000152211340051421000161710ustar00rootroot00000000000000#ifndef INC_GDLTreeParser_hpp_ #define INC_GDLTreeParser_hpp_ #include #include "GDLTreeParserTokenTypes.hpp" /* $ANTLR 2.7.7 (2006-11-01): "gdlc.tree.g" -> "GDLTreeParser.hpp"$ */ #include #include "objects.hpp" #include "dcompiler.hpp" #include "dnodefactory.hpp" #include "arrayindexlistt.hpp" class CUSTOM_API GDLTreeParser : public antlr::TreeParser, public GDLTreeParserTokenTypes { private: // ProgNodeP returnProgNodeP; DCompiler comp; // each tree parser has its own compiler IDList loopVarStack; bool LoopVar( RefDNode& lN) { int lT = lN->getType(); if( lT == VAR || lT == VARPTR) return (FindInIDList( loopVarStack, lN->getText()) != -1); return false; } public: static bool IsREF_CHECK(int t) { return t == FCALL_LIB // || t == MFCALL_LIB // //t == FCALL_LIB_N_ELEMENTS || // || t == MFCALL_PARENT_LIB || t == QUESTION // TODO: These are ref check as well, but parameter nodes need to know || t == FCALL || t == MFCALL || t == MFCALL_PARENT || t == ARRAYEXPR_FCALL || t == ARRAYEXPR_MFCALL ; } private: // Replaces ASSIGN with ASSIGN_REPLACE if appropiate void AssignReplace( RefDNode& lN, RefDNode& aN) { if( LoopVar( lN)) { Warning( "Warning: Assignment to loop variable detected."); } int lT = lN->getType(); if( lT == FCALL || lT == MFCALL || lT == MFCALL_PARENT || lT == FCALL_LIB || // lT == FCALL_LIB_N_ELEMENTS || lT == FCALL_LIB_RETNEW || lT == FCALL_LIB_DIRECT || lT == MFCALL_LIB || lT == MFCALL_LIB_RETNEW || lT == MFCALL_PARENT_LIB || lT == MFCALL_PARENT_LIB_RETNEW || lT == DEREF || lT == VAR || lT == VARPTR ) { aN->setType( ASSIGN_REPLACE); aN->setText( "r="); } if( lT == ARRAYEXPR_MFCALL) // is MFCALL or DOT { aN->setType( ASSIGN_ARRAYEXPR_MFCALL); aN->setText( "?="); } } bool SelfAssignment( RefDNode& lN, RefDNode& rN) { int lT = lN->getType(); int rT = rN->getType(); if( rT == VARPTR && lT == VARPTR) { return (lN->GetVar() == rN->GetVar()); } if( rT == VAR && lT == VAR) { return (lN->GetVarIx() == rN->GetVarIx()); } return false; } RefDNode RemoveNextSibling( RefDNode l) { RefDNode newNode = RefDNode(astFactory->dupTree( antlr::RefAST(l))); newNode->SetLine( l->getLine()); return newNode; // newNode->setNextSibling( RefDNode(antlr::nullAST)); } public: // constructor with processed file GDLTreeParser(const std::string& f, const std::string& sub) : antlr::TreeParser(), comp(f, NULL, sub) { // setTokenNames(_tokenNames); // setASTNodeFactory( DNode::factory ); initializeASTFactory( DNodeFactory); setASTFactory( &DNodeFactory ); } // constructor for command line/execute GDLTreeParser( EnvBaseT* env) : antlr::TreeParser(), comp( "", env, "") { initializeASTFactory( DNodeFactory); setASTFactory( &DNodeFactory ); } bool ActiveProCompiled() const { return comp.ActiveProCompiled();} int NCompileErrors() const { return comp.NCompileErrors();} public: GDLTreeParser(); static void initializeASTFactory( antlr::ASTFactory& factory ); int getNumTokens() const { return GDLTreeParser::NUM_TOKENS; } const char* getTokenName( int type ) const { if( type > getNumTokens() ) return 0; return GDLTreeParser::tokenNames[type]; } const char* const* getTokenNames() const { return GDLTreeParser::tokenNames; } public: void translation_unit(RefDNode _t); public: void procedure_def(RefDNode _t); public: void function_def(RefDNode _t); public: void forward_function(RefDNode _t); public: void common_block(RefDNode _t); public: void statement_list(RefDNode _t); public: void interactive(RefDNode _t); public: void statement(RefDNode _t); public: void parameter_declaration(RefDNode _t); public: void keyword_declaration(RefDNode _t); public: void caseswitch_body(RefDNode _t); public: void expr(RefDNode _t); public: void switch_statement(RefDNode _t); public: void case_statement(RefDNode _t); public: void block(RefDNode _t); public: void unblock(RefDNode _t); public: void unblock_empty(RefDNode _t); public: void label(RefDNode _t); public: void assign_expr_statement(RefDNode _t); public: void comp_assign_expr(RefDNode _t); public: void procedure_call(RefDNode _t); public: void for_statement(RefDNode _t); public: void foreach_statement(RefDNode _t); public: void repeat_statement(RefDNode _t); public: void while_statement(RefDNode _t); public: void jump_statement(RefDNode _t); public: void if_statement(RefDNode _t); public: void parameter_def(RefDNode _t, bool varNum ); public: void key_parameter(RefDNode _t); public: void pos_parameter(RefDNode _t, bool varNum ); public: int array_def(RefDNode _t); public: void struct_def(RefDNode _t); public: void tag_def(RefDNode _t); public: void arrayindex(RefDNode _t, ArrayIndexVectorT* ixList ); public: void arrayindex_list(RefDNode _t); public: void lassign_expr(RefDNode _t); public: void assign_expr(RefDNode _t); public: void sysvar(RefDNode _t); public: void var(RefDNode _t); public: void arrayindex_list_to_parameter_list(RefDNode _t, bool varNum ); public: void arrayexpr_fn(RefDNode _t); public: void arrayexpr_mfcall(RefDNode _t); public: void primary_expr(RefDNode _t); public: void op_expr(RefDNode _t); public: void uminus(RefDNode _t); public: void brace_expr(RefDNode _t); public: void unbrace_expr(RefDNode _t); public: void indexable_expr(RefDNode _t); public: void array_expr(RefDNode _t); public: void tag_indexable_expr(RefDNode _t); public: void tag_array_expr_1st(RefDNode _t); public: void tag_expr(RefDNode _t); public: void tag_array_expr(RefDNode _t); public: antlr::RefAST getAST() { return antlr::RefAST(returnAST); } protected: RefDNode returnAST; RefDNode _retTree; private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS static const int NUM_TOKENS = 238; #else enum { NUM_TOKENS = 238 }; #endif static const unsigned long _tokenSet_0_data_[]; static const antlr::BitSet _tokenSet_0; static const unsigned long _tokenSet_1_data_[]; static const antlr::BitSet _tokenSet_1; }; #endif /*INC_GDLTreeParser_hpp_*/ gdl-0.9.9/src/GDLTreeParserTokenTypes.hpp000066400000000000000000000113501340051421000202160ustar00rootroot00000000000000#ifndef INC_GDLTreeParserTokenTypes_hpp_ #define INC_GDLTreeParserTokenTypes_hpp_ /* $ANTLR 2.7.7 (2006-11-01): "gdlc.tree.g" -> "GDLTreeParserTokenTypes.hpp"$ */ #ifndef CUSTOM_API # define CUSTOM_API #endif #ifdef __cplusplus struct CUSTOM_API GDLTreeParserTokenTypes { #endif enum { EOF_ = 1, ALL = 4, ASSIGN = 5, ASSIGN_INPLACE = 6, ASSIGN_REPLACE = 7, ASSIGN_ARRAYEXPR_MFCALL = 8, ARRAYDEF = 9, ARRAYDEF_CONST = 10, ARRAYDEF_GENERALIZED_INDGEN = 11, ARRAYIX = 12, ARRAYIX_ALL = 13, ARRAYIX_ORANGE = 14, ARRAYIX_RANGE = 15, ARRAYIX_ORANGE_S = 16, ARRAYIX_RANGE_S = 17, ARRAYEXPR = 18, ARRAYEXPR_FCALL = 19, ARRAYEXPR_MFCALL = 20, BLOCK = 21, BREAK = 22, CSBLOCK = 23, CONTINUE = 24, COMMONDECL = 25, COMMONDEF = 26, CONSTANT = 27, DEREF = 28, ELSEBLK = 29, EXPR = 30, FOR = 31, FOR_STEP = 32, FOREACH = 33, FOREACH_INDEX = 34, FOR_LOOP = 35, FOR_STEP_LOOP = 36, FOREACH_LOOP = 37, FOREACH_INDEX_LOOP = 38, FCALL = 39, FCALL_LIB = 40, FCALL_LIB_DIRECT = 41, FCALL_LIB_N_ELEMENTS = 42, FCALL_LIB_RETNEW = 43, GDLNULL = 44, IF_ELSE = 45, KEYDECL = 46, KEYDEF = 47, KEYDEF_REF = 48, KEYDEF_REF_CHECK = 49, KEYDEF_REF_EXPR = 50, LABEL = 51, MPCALL = 52, MPCALL_PARENT = 53, MFCALL = 54, MFCALL_LIB = 55, MFCALL_LIB_RETNEW = 56, MFCALL_PARENT = 57, MFCALL_PARENT_LIB = 58, MFCALL_PARENT_LIB_RETNEW = 59, NOP = 60, NSTRUC = 61, NSTRUC_REF = 62, ON_IOERROR_NULL = 63, PCALL = 64, PCALL_LIB = 65, PARADECL = 66, PARAEXPR = 67, PARAEXPR_VN = 68, DEC_REF_CHECK = 69, INC_REF_CHECK = 70, POSTDEC = 71, POSTINC = 72, DECSTATEMENT = 73, INCSTATEMENT = 74, REF = 75, REF_VN = 76, REF_CHECK = 77, REF_CHECK_VN = 78, REF_EXPR = 79, REF_EXPR_VN = 80, REPEAT = 81, REPEAT_LOOP = 82, RETURN = 83, RETF = 84, RETP = 85, STRUC = 86, SYSVAR = 87, UMINUS = 88, VAR = 89, VARPTR = 90, WHILE = 91, IDENTIFIER = 92, AND_OP = 93, BEGIN = 94, CASE = 95, COMMON = 96, COMPILE_OPT = 97, DO = 98, ELSE = 99, END = 100, ENDCASE = 101, ENDELSE = 102, ENDFOR = 103, ENDFOREACH = 104, ENDIF = 105, ENDREP = 106, ENDSWITCH = 107, ENDWHILE = 108, EQ_OP = 109, FORWARD = 110, FUNCTION = 111, GE_OP = 112, GOTO = 113, GT_OP = 114, IF = 115, INHERITS = 116, LE_OP = 117, LT_OP = 118, MOD_OP = 119, NE_OP = 120, NOT_OP = 121, OF = 122, ON_IOERROR = 123, OR_OP = 124, PRO = 125, SWITCH = 126, THEN = 127, UNTIL = 128, XOR_OP = 129, METHOD = 130, COMMA = 131, COLON = 132, END_U = 133, EQUAL = 134, DEC = 135, INC = 136, AND_OP_EQ = 137, ASTERIX_EQ = 138, EQ_OP_EQ = 139, GE_OP_EQ = 140, GTMARK_EQ = 141, GT_OP_EQ = 142, LE_OP_EQ = 143, LTMARK_EQ = 144, LT_OP_EQ = 145, MATRIX_OP1_EQ = 146, MATRIX_OP2_EQ = 147, MINUS_EQ = 148, MOD_OP_EQ = 149, NE_OP_EQ = 150, OR_OP_EQ = 151, PLUS_EQ = 152, POW_EQ = 153, SLASH_EQ = 154, XOR_OP_EQ = 155, MEMBER = 156, LBRACE = 157, RBRACE = 158, SLASH = 159, LSQUARE = 160, RSQUARE = 161, SYSVARNAME = 162, EXCLAMATION = 163, LCURLY = 164, RCURLY = 165, CONSTANT_HEX_BYTE = 166, CONSTANT_HEX_LONG = 167, CONSTANT_HEX_LONG64 = 168, CONSTANT_HEX_INT = 169, CONSTANT_HEX_I = 170, CONSTANT_HEX_ULONG = 171, CONSTANT_HEX_ULONG64 = 172, CONSTANT_HEX_UI = 173, CONSTANT_HEX_UINT = 174, CONSTANT_BYTE = 175, CONSTANT_LONG = 176, CONSTANT_LONG64 = 177, CONSTANT_INT = 178, CONSTANT_I = 179, CONSTANT_ULONG = 180, CONSTANT_ULONG64 = 181, CONSTANT_UI = 182, CONSTANT_UINT = 183, CONSTANT_OCT_BYTE = 184, CONSTANT_OCT_LONG = 185, CONSTANT_OCT_LONG64 = 186, CONSTANT_OCT_INT = 187, CONSTANT_OCT_I = 188, CONSTANT_OCT_ULONG = 189, CONSTANT_OCT_ULONG64 = 190, CONSTANT_OCT_UI = 191, CONSTANT_OCT_UINT = 192, CONSTANT_FLOAT = 193, CONSTANT_DOUBLE = 194, CONSTANT_BIN_BYTE = 195, CONSTANT_BIN_LONG = 196, CONSTANT_BIN_LONG64 = 197, CONSTANT_BIN_INT = 198, CONSTANT_BIN_I = 199, CONSTANT_BIN_ULONG = 200, CONSTANT_BIN_ULONG64 = 201, CONSTANT_BIN_UI = 202, CONSTANT_BIN_UINT = 203, ASTERIX = 204, DOT = 205, STRING_LITERAL = 206, POW = 207, MATRIX_OP1 = 208, MATRIX_OP2 = 209, PLUS = 210, MINUS = 211, LTMARK = 212, GTMARK = 213, LOG_NEG = 214, LOG_AND = 215, LOG_OR = 216, QUESTION = 217, STRING = 218, INCLUDE = 219, EOL = 220, W = 221, D = 222, L = 223, H = 224, O = 225, B = 226, EXP = 227, DBL_E = 228, DBL = 229, CONSTANT_OR_STRING_LITERAL = 230, COMMENT = 231, END_MARKER = 232, WHITESPACE = 233, SKIP_LINES = 234, CONT_STATEMENT = 235, END_OF_LINE = 236, MAX_TOKEN_NUMBER = 237, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus }; #endif #endif /*INC_GDLTreeParserTokenTypes_hpp_*/ gdl-0.9.9/src/GDLTreeParserTokenTypes.txt000066400000000000000000000072021340051421000202470ustar00rootroot00000000000000// $ANTLR 2.7.7 (2006-11-01): gdlc.tree.g -> GDLTreeParserTokenTypes.txt$ GDLTreeParser // output token vocab name ALL=4 ASSIGN=5 ASSIGN_INPLACE=6 ASSIGN_REPLACE=7 ASSIGN_ARRAYEXPR_MFCALL=8 ARRAYDEF=9 ARRAYDEF_CONST=10 ARRAYDEF_GENERALIZED_INDGEN=11 ARRAYIX=12 ARRAYIX_ALL=13 ARRAYIX_ORANGE=14 ARRAYIX_RANGE=15 ARRAYIX_ORANGE_S=16 ARRAYIX_RANGE_S=17 ARRAYEXPR=18 ARRAYEXPR_FCALL=19 ARRAYEXPR_MFCALL=20 BLOCK=21 BREAK=22 CSBLOCK=23 CONTINUE=24 COMMONDECL=25 COMMONDEF=26 CONSTANT=27 DEREF=28 ELSEBLK=29 EXPR=30 FOR="for"=31 FOR_STEP=32 FOREACH="foreach"=33 FOREACH_INDEX=34 FOR_LOOP=35 FOR_STEP_LOOP=36 FOREACH_LOOP=37 FOREACH_INDEX_LOOP=38 FCALL=39 FCALL_LIB=40 FCALL_LIB_DIRECT=41 FCALL_LIB_N_ELEMENTS=42 FCALL_LIB_RETNEW=43 GDLNULL=44 IF_ELSE=45 KEYDECL=46 KEYDEF=47 KEYDEF_REF=48 KEYDEF_REF_CHECK=49 KEYDEF_REF_EXPR=50 LABEL=51 MPCALL=52 MPCALL_PARENT=53 MFCALL=54 MFCALL_LIB=55 MFCALL_LIB_RETNEW=56 MFCALL_PARENT=57 MFCALL_PARENT_LIB=58 MFCALL_PARENT_LIB_RETNEW=59 NOP=60 NSTRUC=61 NSTRUC_REF=62 ON_IOERROR_NULL=63 PCALL=64 PCALL_LIB=65 PARADECL=66 PARAEXPR=67 PARAEXPR_VN=68 DEC_REF_CHECK=69 INC_REF_CHECK=70 POSTDEC=71 POSTINC=72 DECSTATEMENT=73 INCSTATEMENT=74 REF=75 REF_VN=76 REF_CHECK=77 REF_CHECK_VN=78 REF_EXPR=79 REF_EXPR_VN=80 REPEAT="repeat"=81 REPEAT_LOOP=82 RETURN=83 RETF=84 RETP=85 STRUC=86 SYSVAR=87 UMINUS=88 VAR=89 VARPTR=90 WHILE="while"=91 IDENTIFIER=92 AND_OP="and"=93 BEGIN="begin"=94 CASE="case"=95 COMMON="common"=96 COMPILE_OPT="compile_opt"=97 DO="do"=98 ELSE="else"=99 END="end"=100 ENDCASE="endcase"=101 ENDELSE="endelse"=102 ENDFOR="endfor"=103 ENDFOREACH="endforeach"=104 ENDIF="endif"=105 ENDREP="endrep"=106 ENDSWITCH="endswitch"=107 ENDWHILE="endwhile"=108 EQ_OP="eq"=109 FORWARD="forward_function"=110 FUNCTION="function"=111 GE_OP="ge"=112 GOTO="goto"=113 GT_OP="gt"=114 IF="if"=115 INHERITS="inherits"=116 LE_OP="le"=117 LT_OP="lt"=118 MOD_OP="mod"=119 NE_OP="ne"=120 NOT_OP="not"=121 OF="of"=122 ON_IOERROR="on_ioerror"=123 OR_OP="or"=124 PRO="pro"=125 SWITCH="switch"=126 THEN="then"=127 UNTIL="until"=128 XOR_OP="xor"=129 METHOD=130 COMMA=131 COLON=132 END_U=133 EQUAL=134 DEC=135 INC=136 AND_OP_EQ=137 ASTERIX_EQ=138 EQ_OP_EQ=139 GE_OP_EQ=140 GTMARK_EQ=141 GT_OP_EQ=142 LE_OP_EQ=143 LTMARK_EQ=144 LT_OP_EQ=145 MATRIX_OP1_EQ=146 MATRIX_OP2_EQ=147 MINUS_EQ=148 MOD_OP_EQ=149 NE_OP_EQ=150 OR_OP_EQ=151 PLUS_EQ=152 POW_EQ=153 SLASH_EQ=154 XOR_OP_EQ=155 MEMBER=156 LBRACE=157 RBRACE=158 SLASH=159 LSQUARE=160 RSQUARE=161 SYSVARNAME=162 EXCLAMATION=163 LCURLY=164 RCURLY=165 CONSTANT_HEX_BYTE=166 CONSTANT_HEX_LONG=167 CONSTANT_HEX_LONG64=168 CONSTANT_HEX_INT=169 CONSTANT_HEX_I=170 CONSTANT_HEX_ULONG=171 CONSTANT_HEX_ULONG64=172 CONSTANT_HEX_UI=173 CONSTANT_HEX_UINT=174 CONSTANT_BYTE=175 CONSTANT_LONG=176 CONSTANT_LONG64=177 CONSTANT_INT=178 CONSTANT_I=179 CONSTANT_ULONG=180 CONSTANT_ULONG64=181 CONSTANT_UI=182 CONSTANT_UINT=183 CONSTANT_OCT_BYTE=184 CONSTANT_OCT_LONG=185 CONSTANT_OCT_LONG64=186 CONSTANT_OCT_INT=187 CONSTANT_OCT_I=188 CONSTANT_OCT_ULONG=189 CONSTANT_OCT_ULONG64=190 CONSTANT_OCT_UI=191 CONSTANT_OCT_UINT=192 CONSTANT_FLOAT=193 CONSTANT_DOUBLE=194 CONSTANT_BIN_BYTE=195 CONSTANT_BIN_LONG=196 CONSTANT_BIN_LONG64=197 CONSTANT_BIN_INT=198 CONSTANT_BIN_I=199 CONSTANT_BIN_ULONG=200 CONSTANT_BIN_ULONG64=201 CONSTANT_BIN_UI=202 CONSTANT_BIN_UINT=203 ASTERIX=204 DOT=205 STRING_LITERAL=206 POW=207 MATRIX_OP1=208 MATRIX_OP2=209 PLUS=210 MINUS=211 LTMARK=212 GTMARK=213 LOG_NEG=214 LOG_AND=215 LOG_OR=216 QUESTION=217 STRING=218 INCLUDE=219 EOL=220 W=221 D=222 L=223 H=224 O=225 B=226 EXP=227 DBL_E=228 DBL=229 CONSTANT_OR_STRING_LITERAL=230 COMMENT=231 END_MARKER=232 WHITESPACE=233 SKIP_LINES=234 CONT_STATEMENT=235 END_OF_LINE=236 MAX_TOKEN_NUMBER=237 gdl-0.9.9/src/accessdesc.hpp000066400000000000000000000353641340051421000157000ustar00rootroot00000000000000/*************************************************************************** accessdesc.hpp - accessing structs, sometimes also called "extractor" ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ACCESSDESC_HPP_ #define ACCESSDESC_HPP_ #include #include "typedefs.hpp" #include "datatypes.hpp" #include "arrayindexlistt.hpp" #include "assocdata.hpp" #include "initsysvar.hpp" // #ifdef _OPENMP // #include "objects.hpp" // #endif class DotAccessDescT { private: // SizeT targetDepth; bool propertyAccess; DString propertyName; BaseGDL* top; std::vector dStruct; // structures std::vector tag; // tag index std::vector ix; // array index dimension dim; SizeT rStride; SizeT rOffset; bool owner; // delete dStruct[0] upon own destruction // does the assignment void DoAssign( DStructGDL* l, BaseGDL* r, SizeT depth=0) { SizeT nCp; SizeT actTag=tag[ depth]; if( ix[depth] == NULL) { // non-indexed case nCp=dStruct[depth]->N_Elements(); if( (depth+1) == tag.size()) { // the actual assignment for( SizeT c=0; cGetTag( actTag, c); actTop->AssignAt( r, ix[depth+1], rOffset); rOffset += rStride; } } else { for( SizeT c=0; c( l->GetTag( actTag, c)); DoAssign( nextL, r, depth+1); } } } else { // indexed case ArrayIndexListT& actIx= *ix[depth]; nCp=actIx.N_Elements(); AllIxBaseT* allIx = actIx.BuildIx(); if( (depth+1) == tag.size()) { BaseGDL* actTop = l->GetTag( actTag, allIx->InitSeqAccess()); actTop->AssignAt( r, ix[depth+1], rOffset); rOffset += rStride; for( SizeT c=1; cGetTag( actTag, allIx->SeqAccess()); //BaseGDL* actTop = l->Get( actTag, actIx.GetIx( c)); actTop->AssignAt( r, ix[depth+1], rOffset); rOffset += rStride; } } else { DStructGDL* nextL = static_cast( l->GetTag( actTag, allIx->InitSeqAccess())); DoAssign( nextL, r, depth+1); for( SizeT c=1; c( l->GetTag( actTag, allIx->SeqAccess())); //( l->Get( actTag, actIx.GetIx( c))); DoAssign( nextL, r, depth+1); } } } } // does the decrement void DoDec( DStructGDL* l, SizeT depth=0) { SizeT nCp; SizeT actTag=tag[ depth]; if( ix[depth] == NULL) { // non-indexed case nCp=dStruct[depth]->N_Elements(); if( (depth+1) == tag.size()) { // the actual decrement for( SizeT c=0; cGetTag( actTag, c); actTop->DecAt( ix[depth+1]); } } else { for( SizeT c=0; c( l->GetTag( actTag, c)); DoDec( nextL, depth+1); } } } else { // indexed case ArrayIndexListT& actIx= *ix[depth]; nCp=actIx.N_Elements(); AllIxBaseT* allIx = actIx.BuildIx(); if( (depth+1) == tag.size()) { BaseGDL* actTop = l->GetTag( actTag, allIx->InitSeqAccess()); actTop->DecAt( ix[depth+1]); for( SizeT c=1; cGetTag( actTag, allIx->SeqAccess()); //BaseGDL* actTop = l->Get( actTag, actIx.GetIx( c)); actTop->DecAt( ix[depth+1]); } } else { DStructGDL* nextL = static_cast( l->GetTag( actTag, allIx->InitSeqAccess())); DoDec( nextL, depth+1); for( SizeT c=1; c( l->GetTag( actTag, allIx->SeqAccess())); DoDec( nextL, depth+1); } } } } // does the increment void DoInc( DStructGDL* l, SizeT depth=0) { SizeT nCp; SizeT actTag=tag[ depth]; if( ix[depth] == NULL) { // non-indexed case nCp=dStruct[depth]->N_Elements(); if( (depth+1) == tag.size()) { // the actual increment for( SizeT c=0; cGetTag( actTag, c); actTop->IncAt( ix[depth+1]); } } else { for( SizeT c=0; c( l->GetTag( actTag, c)); DoInc( nextL, depth+1); } } } else { // indexed case ArrayIndexListT& actIx= *ix[depth]; nCp=actIx.N_Elements(); AllIxBaseT* allIx = actIx.BuildIx(); if( (depth+1) == tag.size()) { BaseGDL* actTop = l->GetTag( actTag, allIx->InitSeqAccess()); actTop->IncAt( ix[depth+1]); for( SizeT c=1; cGetTag( actTag, allIx->SeqAccess()); //BaseGDL* actTop = l->Get( actTag, actIx.GetIx( c)); actTop->IncAt( ix[depth+1]); } } else { DStructGDL* nextL = static_cast( l->GetTag( actTag, allIx->InitSeqAccess())); DoInc( nextL, depth+1); for( SizeT c=1; c( l->GetTag( actTag, allIx->SeqAccess())); //( l->Get( actTag, actIx.GetIx( c))); DoInc( nextL, depth+1); } } } } // does the actual resolving void DoResolve( BaseGDL* newVar, DStructGDL* l, SizeT depth=0) { SizeT nCp; SizeT actTag=tag[ depth]; if( ix[depth] == NULL) { // non-indexed case nCp=dStruct[depth]->N_Elements(); if( (depth+1) == tag.size()) { // the actual resolving for( SizeT c=0; cGetTag( actTag, c); // newVar is empty -> no deleting of old data in InsertAt newVar->InsertAt( rOffset, actTop, ix[depth+1]); rOffset += rStride; } } else { for( SizeT c=0; c( l->GetTag( actTag, c)); DoResolve( newVar, nextL, depth+1); } } } else { // indexed case ArrayIndexListT& actIx= *ix[depth]; nCp=actIx.N_Elements(); AllIxBaseT* allIx = actIx.BuildIx(); if( (depth+1) == tag.size()) { BaseGDL* actTop = l->GetTag( actTag, allIx->InitSeqAccess()); newVar->InsertAt( rOffset, actTop, ix[depth+1]); rOffset += rStride; for( SizeT c=1; cGetTag( actTag, allIx->SeqAccess()); //BaseGDL* actTop = l->Get( actTag, actIx.GetIx( c)); newVar->InsertAt( rOffset, actTop, ix[depth+1]); rOffset += rStride; } } else { DStructGDL* nextL = static_cast ( l->GetTag( actTag, allIx->InitSeqAccess())); DoResolve( newVar, nextL, depth+1); for( SizeT c=1; c( l->GetTag( actTag, allIx->SeqAccess())); //( l->Get( actTag, actIx.GetIx( c))); DoResolve( newVar, nextL, depth+1); } } } } // intializes dim (implicitely checks rank) void SetupDim() { // calculate dimension SizeT nDot=tag.size(); SizeT d; for (d = 0; d < nDot; ++d) { if (ix[d] == NULL) { // loop over all elements if (dStruct[d]->N_Elements() > 1) dim >> dStruct[d]->Dim(); } else { ix[d]->SetVariable(dStruct[d]); if (ix[d]->N_Elements() > 1) dim >> ix[d]->GetDim(); } } // dimension topDim; if (ix[d] == NULL) { // loop over all elements // topDim=top->Dim(); // dim >> topDim; dim >> top->Dim(); } else { ix[d]->SetVariable(top); // Following code was causing problem #10 in test_bug_709. // dimension addVarDim = ix[d]->GetDim(); // addVarDim.Purge(); // dim >> addVarDim; if( top->Rank() < ix[d]->GetDim().Rank()) { dimension addVarDim = ix[d]->GetDim(); addVarDim.Purge(); dim >> addVarDim; //dim.AddLeft( ix[d]->GetDim(), top->Rank()); } else dim >> ix[d]->GetDim(); } } private: DotAccessDescT() {} public: DotAccessDescT( SizeT depth): propertyAccess(false), top(NULL), dStruct(), tag(), ix(), dim(), owner(false) { dStruct.reserve( depth);//-1); tag.reserve( depth);//-1); ix.reserve( depth); } ~DotAccessDescT() { // delete root struct if owner if( owner && dStruct.size() > 0) delete dStruct[0]; // the indices have to be cleared in any case SizeT nIx=ix.size(); for( SizeT i=0; iClear(); } void SetOwner( bool o) { owner = o;} bool IsOwner() { return owner;} // resloves (structure hierarchy described by) this to BaseGDL BaseGDL* ADResolve() { SetupDim(); BaseGDL* newData; // no zeroing, here the new variable is created // zero only for GDL_PTR and GDL_OBJ (because of ref counting) if( top->Type() == GDL_PTR || top->Type() == GDL_OBJ) newData=top->New( dim);//, BaseGDL::NOZERO); else newData=top->New( dim, BaseGDL::NOZERO); rOffset=0; // crucial line, only with rOffset == 0 var is set if( ix.back() == NULL) rStride=top->N_Elements(); else rStride=ix.back()->N_Elements(); DoResolve( newData, dStruct[0]); return newData; } // assigns r to (structure hierarchy described by) this void ADAssign(BaseGDL* r) { SetupDim(); SizeT lRank = dim.Rank(); SizeT rRank = r->Rank(); // if( rRank > lRank) // throw GDLException(-1,NULL,"Conflicting data structures (rank).",true,false); SizeT topRank=top->Rank(); SizeT rElem = r->N_Elements(); SizeT topElem; if (ix.back() == NULL) topElem = top->N_Elements(); else topElem = ix.back()->N_Elements(); if (rElem <= topElem) { // IDL seems to allow a maximum of one rank more for the r-value // if( rRank > (topRank+1)) // throw GDLException(-1,NULL,"Conflicting data structures (top-rank).",true,false); // inplace copy to every instance of top // just loop over all top elements and insert (at appropriate indices) rStride = 0; rOffset = 0; if (r->Type() != top->Type()) { BaseGDL* rConv = r->Convert2(top->Type(), BaseGDL::COPY); Guard conv_guard(rConv); DoAssign(dStruct[0], rConv); } else DoAssign(dStruct[0], r); } else { // different slices into different top element instances // all dimensions must match here for (SizeT i = 0; i < rRank; i++) if (dim[i] != r->Dim(i)) throw GDLException(-1, NULL, "Conflicting data structures (dim).", true, false); // copy only topRank dimensions each time (topElem elements) // topRank is the dim to start the outer loop with /* if( ix[ tag.size()]->N_Elements() == 1 && ix[ tag.size()]->NDim() == 1) rStride = 1; else*/ rStride = r->Stride(topRank); rOffset = 0; if (r->Type() != top->Type()) { BaseGDL* rConv = r->Convert2(top->Type(), BaseGDL::COPY); Guard conv_guard(rConv); DoAssign(dStruct[0], rConv); } else DoAssign(dStruct[0], r); } /*#ifdef _OPENMP if( dStruct[0] == SysVar::Cpu()) { SysVar::CPUChanged(); } #endif*/ } void Dec() { SetupDim(); DoDec( dStruct[0]); /*#ifdef _OPENMP if( dStruct[0] == SysVar::Cpu()) { SysVar::CPUChanged(); } #endif*/ } void Inc() { SetupDim(); DoInc( dStruct[0]); /*#ifdef _OPENMP if( dStruct[0] == SysVar::Cpu()) { SysVar::CPUChanged(); } #endif*/ } DStructGDL* TopStruct() { return dStruct.back(); } void ADRoot( DStructGDL* s, ArrayIndexListT* ix_=NULL) // root { // if( s->IsAssoc()) // throw GDLException(-1,NULL,"File expression not allowed in this context.",true,false); propertyAccess = false; dStruct.push_back(s); ix.push_back(ix_); } void ADAdd( const std::string& tagName) // tags { if( dStruct.back() == NULL) { // Note: as this is the fail condition, this handling won't slow down normal operation // if( top->Type() == GDL_OBJ) // we must keep "top" as the resolve will be done with this. // { // // must only have one time property access // if( propertyAccess) // { // throw GDLException(-1,NULL,"Cannot access tag: "+ tagName+" [of property: "+propertyName+"].",true,false); // } // propertyName = tagName; // propertyAccess = true; // return; // no further change // // hence "Add( SizeT)" will fail next time as well -> no further action here // } assert( top != NULL); if( top->Type() == GDL_OBJ) throw GDLException(-1,NULL,"Nested structure references are not allowed with objects. Consider using parentheses: "+tagName); else throw GDLException(-1,NULL,"Left side of a tag must be a STRUCT: "+tagName); } int t=dStruct.back()->Desc()->TagIndex( tagName); if( t == -1) { // TODO: Check for call to Get/SetProperty throw GDLException(-1,NULL,"Tag name: "+tagName+" is undefined for STRUCT.",true,false); } // call SizeT version SizeT tagIx=static_cast(t); ADAdd( tagIx); } void ADAdd( SizeT tagN) // tags { DStructGDL* actTop=dStruct.back(); if( actTop == NULL) throw GDLException(-1,NULL,"Expression must be a STRUCT in this context.",true,false); if( actTop->N_Elements() == 0) // maybe not needed throw GDLException(-1,NULL,"Error struct data empty.",true,false); SizeT nTags=actTop->Desc()->NTags(); if( tagN >= nTags) throw GDLException(-1,NULL,"Invalid tag number.",true,false); // TODO: Insert object struct for Get/SetProperty // tagN == -1 (change type to int)? top=actTop->GetTag( tagN, 0); // push struct onto struct stack if( top->Type() == GDL_STRUCT) { DStructGDL* newTop=static_cast(top); dStruct.push_back( newTop); } else { dStruct.push_back( NULL); } tag.push_back(tagN); } void ADAddIx( ArrayIndexListT* ix_) // tags { if( propertyAccess && ix_ != NULL) throw GDLException(-1,NULL,"Property must not be indexed: "+propertyName+".",true,false); ix.push_back(ix_); } }; // typedef std::vector AccessStackT; #endif gdl-0.9.9/src/allix.cpp000066400000000000000000000300451340051421000146730ustar00rootroot00000000000000/*************************************************************************** allix.cpp - indexer definitions ------------------- begin : July 22 2002 copyright : (C) 2011 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "includefirst.hpp" #include "arrayindex.hpp" #include "allix.hpp" // older versions of gcc put the vtable into this file (where destructor is defined) AllIxBaseT::~AllIxBaseT() {} SizeT AllIxIndicesT::operator[]( SizeT i) const { assert( upperSet); SizeT index = ref->GetAsIndex( i); if( index > upper) return upper; return index; } SizeT AllIxIndicesT::InitSeqAccess() { assert( upperSet); seqIx = 0; SizeT index = ref->GetAsIndex( 0); if( index > upper) return upper; return index; } SizeT AllIxIndicesT::SeqAccess() { assert( upperSet); SizeT index = ref->GetAsIndex( ++seqIx); if( index > upper) return upper; return index; } SizeT AllIxIndicesT::size() const { return ref->N_Elements(); } SizeT AllIxIndicesStrictT::operator[]( SizeT i) const { assert( upperSet); SizeT index = ref->GetAsIndexStrict( i); if( index > upper) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range subscript (at index: "+i2s(i)+").",true,false); return index; } SizeT AllIxIndicesStrictT::InitSeqAccess() { assert( upperSet); seqIx = 0; SizeT index = ref->GetAsIndexStrict( 0); if( index > upper) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range subscript (at index: "+i2s(index)+").",true,false); return index; } SizeT AllIxIndicesStrictT::SeqAccess() { assert( upperSet); SizeT index = ref->GetAsIndexStrict( ++seqIx); if( index > upper) throw GDLException(-1,NULL,"Array used to subscript array " "contains out of range subscript (at index: "+i2s(index)+").",true,false); return index; } SizeT AllIxAllIndexedT::operator[]( SizeT i) const { assert( i < nIx); assert( dynamic_cast( (*ixList)[0]) != NULL); SizeT resIndex = static_cast< ArrayIndexIndexed*>( (*ixList)[0])->GetIx( i); for( SizeT l=1; l < acRank; ++l) { assert( dynamic_cast( (*ixList)[l]) != NULL); resIndex += static_cast< ArrayIndexIndexed*>( (*ixList)[l])->GetIx( i) * varStride[l]; } return resIndex; } SizeT AllIxAllIndexedT::InitSeqAccess() { seqIx = 0; assert( dynamic_cast( (*ixList)[0]) != NULL); SizeT resIndex = static_cast< ArrayIndexIndexed*>( (*ixList)[0])->GetIx( 0 /*seqIx*/); for( SizeT l=1; l < acRank; ++l) { assert( dynamic_cast( (*ixList)[l]) != NULL); resIndex += static_cast< ArrayIndexIndexed*>( (*ixList)[l])->GetIx( 0 /*seqIx*/) * varStride[l]; } return resIndex; } SizeT AllIxAllIndexedT::SeqAccess() { ++seqIx; assert( seqIx < nIx); assert( dynamic_cast( (*ixList)[0]) != NULL); SizeT resIndex = static_cast< ArrayIndexIndexed*>( (*ixList)[0])->GetIx( seqIx); for( SizeT l=1; l < acRank; ++l) { assert( dynamic_cast( (*ixList)[l]) != NULL); resIndex += static_cast< ArrayIndexIndexed*>( (*ixList)[l])->GetIx( seqIx) * varStride[l]; } return resIndex; } // Note: mixed indices can expand an array SizeT AllIxNewMultiT::operator[]( SizeT i) const { assert( i < nIx); SizeT resIndex = add; if( (*ixList)[0]->Indexed()) { resIndex += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( i % nIterLimit[0]); } else { // SizeT s = ixList->FrontGetS(); //ixList[0]->GetS(); if( nIterLimit[0] > 1) resIndex += (i % nIterLimit[0]) * ixListStride[0]; // + s[0]; } for( SizeT l=1; l < acRank; ++l) { if( (*ixList)[l]->Indexed()) { resIndex += static_cast< ArrayIndexIndexed*>( (*ixList)[l])->GetIx( (i / stride[l]) % nIterLimit[l]) * varStride[l]; } else { // SizeT s = (*ixList)[l]->GetS(); if( nIterLimit[l] > 1) resIndex += ((i / stride[l]) % nIterLimit[l]) * ixListStride[l]; // + s[l] * varStride[l]; // resIndex += (((i / stride[l]) % nIterLimit[l]) * ixListStride[l] + s[l]) * varStride[l]; } } return resIndex; } SizeT AllIxNewMultiT::InitSeqAccess() { // seqIx = 0; // return (*this)[0]; seqIter = 0; seqIter0 = 0; ix2 = add; for( SizeT l=1; l < acRank; ++l) { if( (*ixList)[l]->Indexed()) { ix2 += static_cast< ArrayIndexIndexed*>( (*ixList)[l])->GetIx( 0) * varStride[l]; } } seqIx = ix2; if( (*ixList)[0]->Indexed()) { seqIx += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( 0); } assert( seqIx == (*this)[seqIter+seqIter0]); return seqIx; //(*this)[0]; } SizeT AllIxNewMultiT::SeqAccess() { // return (*this)[++seqIx]; ++seqIter0; if( seqIter0 >= stride[1]) { seqIter += stride[1]; seqIter0 = 0; ix2 = add; for( SizeT l=1; l < acRank; ++l) { if( (*ixList)[l]->Indexed()) { ix2 += static_cast< ArrayIndexIndexed*>( (*ixList)[l])->GetIx( (seqIter / stride[l]) % nIterLimit[l]) * varStride[l]; } else { if( nIterLimit[l] > 1) ix2 += ((seqIter / stride[l]) % nIterLimit[l]) * ixListStride[l]; } } seqIx = ix2; if( (*ixList)[0]->Indexed()) { seqIx += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( seqIter0); } assert( seqIx == (*this)[seqIter+seqIter0]); return seqIx; } seqIx = ix2; if( (*ixList)[0]->Indexed()) { seqIx += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( seqIter0); } else { if( nIterLimit[0] > 1) seqIx += seqIter0 * ixListStride[0]; // + s[0]; } assert( seqIx == (*this)[seqIter+seqIter0]); return seqIx; } SizeT AllIxNewMulti2DT::operator[]( SizeT i) const { assert( i < nIx); SizeT resIndex = add; if( (*ixList)[0]->Indexed()) { resIndex += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( i % nIterLimit[0]); } else { if( nIterLimit[0] > 1) resIndex += (i % nIterLimit[0]) * ixListStride[0]; // + s[0]; } if( (*ixList)[1]->Indexed()) { return resIndex + static_cast< ArrayIndexIndexed*>( (*ixList)[1])->GetIx( (i / stride[1]) % nIterLimit[1]) * varStride[1]; } else { if( nIterLimit[1] > 1) return resIndex + ((i / stride[1]) % nIterLimit[1]) * ixListStride[1]; else return resIndex; } return resIndex; } SizeT AllIxNewMulti2DT::InitSeqAccess() { // seqIx = 0; // return (*this)[0]; seqIter = 0; seqIter0 = 0; ix2 = add; if( (*ixList)[1]->Indexed()) { ix2 += static_cast< ArrayIndexIndexed*>( (*ixList)[1])->GetIx( 0) * varStride[1]; } seqIx = ix2; if( (*ixList)[0]->Indexed()) { seqIx += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( 0); } assert( seqIx == (*this)[seqIter+seqIter0]); return seqIx; //(*this)[0]; } SizeT AllIxNewMulti2DT::SeqAccess() { // return (*this)[++seqIx]; ++seqIter0; if( seqIter0 >= stride[1]) { seqIter += stride[1]; seqIter0 = 0; ix2 = add; if( (*ixList)[1]->Indexed()) { ix2 += static_cast< ArrayIndexIndexed*>( (*ixList)[1])->GetIx( (seqIter / stride[1]) % nIterLimit[1]) * varStride[1]; } else { if( nIterLimit[1] > 1) ix2 += ((seqIter / stride[1]) % nIterLimit[1]) * ixListStride[1]; } seqIx = ix2; if( (*ixList)[0]->Indexed()) { seqIx += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( seqIter0); } assert( seqIx == (*this)[seqIter+seqIter0]); return seqIx; } seqIx = ix2; if( (*ixList)[0]->Indexed()) { seqIx += static_cast< ArrayIndexIndexed*>((*ixList)[0])->GetIx( seqIter0); } else { if( nIterLimit[0] > 1) seqIx += seqIter0 * ixListStride[0]; // + s[0]; } assert( seqIx == (*this)[seqIter+seqIter0]); return seqIx; } SizeT AllIxNewMultiNoneIndexedT::operator[]( SizeT i) const { assert( i < nIx); SizeT resIndex = add; if( nIterLimit[0] > 1) resIndex += (i % nIterLimit[0]) * ixListStride[0]; for( SizeT l=1; l < acRank; ++l) { if( nIterLimit[l] > 1) resIndex += ((i / stride[l]) % nIterLimit[l]) * ixListStride[l]; // resIndex += (((i / stride[l]) % nIterLimit[l]) * ixListStride[l] + s[l]) * varStride[l]; } return resIndex; } SizeT AllIxNewMultiNoneIndexedT::InitSeqAccess() { // seqIxDebug = 0; // return (*this)[0]; seqIx = add; seqIter = 0; correctionIncrease = stride[1] * ixListStride[0]; nextCorrection = seqIx + correctionIncrease; // stride[1] == nIterLimit[0] return seqIx; //(*this)[0]; } SizeT AllIxNewMultiNoneIndexedT::SeqAccess() // 1st dim linearized { // return (*this)[++seqIx]; seqIx += ixListStride[0]; if( seqIx >= nextCorrection) { seqIter += stride[1]; seqIx = add; for( SizeT l=1; l < acRank; ++l) { if( nIterLimit[l] > 1) seqIx += ((seqIter / stride[l]) % nIterLimit[l]) * ixListStride[l]; } nextCorrection = seqIx + correctionIncrease; // stride[1] == nIterLimit[0] } return seqIx; // fast path } // acRank == 2 SizeT AllIxNewMultiNoneIndexed2DT::operator[]( SizeT i) const { // stride[1] == nIterLimit[0] (see SetVariable(...)) assert( i < nIx); // otherwise AllIxNewMultiOneVariableIndex...T in MakeArrayIndex assert( nIterLimit[0] > 1 && nIterLimit[1] > 1); SizeT resIndex = add; // if( nIterLimit[0] > 1) resIndex += (i % nIterLimit[0]) * ixListStride[0]; // if( nIterLimit[1] > 1) // 2D: nIx == nIterLimit[0] * nIterLimit[1] && stride[1] == nIterLimit[0] // -> nIterLimit[1] > i/stride[1] -> no % resIndex += (i / stride[1]) * ixListStride[1]; // resIndex += ((i / stride[1]) % nIterLimit[1]) * ixListStride[1]; // resIndex += (((i / stride[l]) % nIterLimit[l]) * ixListStride[l] + s[l]) * varStride[l]; return resIndex; } SizeT AllIxNewMultiNoneIndexed2DT::InitSeqAccess() { seqIx = add; correctionIncrease = stride[1] * ixListStride[0]; nextCorrection = seqIx + correctionIncrease; // stride[1] == nIterLimit[0] return seqIx; //(*this)[0]; } SizeT AllIxNewMultiNoneIndexed2DT::SeqAccess() // linearized { // return (*this)[++seqIx]; seqIx += ixListStride[0]; if( seqIx >= nextCorrection) { // increase 2nd dim seqIx += ixListStride[1]; nextCorrection = seqIx; // stride[1] == nIterLimit[0] // correct modulo seqIx -= correctionIncrease; // set new limit // nextCorrection = seqIx + correctionIncrease; // stride[1] == nIterLimit[0] } return seqIx; // fast path } SizeT AllIxNewMultiOneVariableIndexNoIndexT::operator[]( SizeT i) const { assert( i < nIx); return add + i * ixListStride; // + s[l] * varStride[l]; // resIndex += (((i / stride[l]) % nIterLimit[l]) * ixListStride[l] + s[l]) * varStride[l]; } SizeT AllIxNewMultiOneVariableIndexNoIndexT::InitSeqAccess() { seqIx = add; return add; } SizeT AllIxNewMultiOneVariableIndexNoIndexT::SeqAccess() { seqIx += ixListStride; assert( (seqIx - add) / ixListStride < nIx); return seqIx; } SizeT AllIxNewMultiOneVariableIndexIndexedT::operator[]( SizeT i) const { assert( i < nIx); return add + static_cast< ArrayIndexIndexed*>( arrayIndexIndexed)->GetIx( i) * ixListStride; //varStride[l]; } SizeT AllIxNewMultiOneVariableIndexIndexedT::InitSeqAccess() { seqIx = 0; return add + static_cast< ArrayIndexIndexed*>( arrayIndexIndexed)->GetIx( 0) * ixListStride; //varStride[l]; } SizeT AllIxNewMultiOneVariableIndexIndexedT::SeqAccess() { assert( (seqIx+1) < nIx); return add + static_cast< ArrayIndexIndexed*>( arrayIndexIndexed)->GetIx( ++seqIx) * ixListStride; //varStride[l]; } gdl-0.9.9/src/allix.hpp000066400000000000000000000365451340051421000147130ustar00rootroot00000000000000/*************************************************************************** allix.hpp - indexer ------------------- begin : July 22 2002 copyright : (C) 2011 by Marc Schellens email : m_schellens@users.sf.net ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ALLIX_HPP_ #define ALLIX_HPP_ #include "typedefs.hpp" class AllIxBaseT { public: virtual ~AllIxBaseT(); // code in arrayindex.cpp virtual AllIxBaseT* Clone() = 0; virtual SizeT operator[]( SizeT i) const = 0; virtual SizeT size() const = 0; // virtual SizeT max() const = 0; virtual SizeT InitSeqAccess() = 0; virtual SizeT SeqAccess() =0; }; class AllIxT: public AllIxBaseT { protected: SizeT ix; public: AllIxT() {} AllIxT( SizeT i): ix( i) { } ~AllIxT() {} AllIxT* Clone() { return new AllIxT( ix); } SizeT operator[]( SizeT i) const { assert( i == 0); return ix; } SizeT size() const { return 1;} SizeT InitSeqAccess() { return ix;} SizeT SeqAccess() { assert(false); return 0;} // SizeT max() const { return ix;} void Set( SizeT i) { ix = i;} }; // class AllIxMultiT: public AllIxBaseT // { // private: // SizeT* ixArr; // SizeT sz; // // public: // AllIxMultiT( SizeT s): sz( s) // { // assert( s > 0); // ixArr = new SizeT[ s]; // } // ~AllIxMultiT() { delete[] ixArr;} // // AllIxMultiT* Clone() // { // AllIxMultiT* clone = new AllIxMultiT( sz); // for( SizeT i=0; i m) // m = ixArr[ i] ; // return m; // } // // SizeT GetIx( SizeT i) const // { // assert( i < sz); // return ixArr[ i]; // } // void SetIx( SizeT i, SizeT value) // { // assert( i < sz); // ixArr[ i] = value; // } // void SetIxTo0( SizeT i) // { // assert( i < sz); // ixArr[ i] = 0; // } // void AddToIx( SizeT i, SizeT value) // { // assert( i < sz); // ixArr[ i] += value; // } // }; class AllIxRange0T: public AllIxBaseT { private: SizeT sz; SizeT seqIx; public: AllIxRange0T( SizeT sz_): sz( sz_) { } ~AllIxRange0T() {} AllIxRange0T* Clone() { AllIxRange0T* clone = new AllIxRange0T( sz); return clone; } SizeT operator[]( SizeT i) const { assert( i < sz); return i; } SizeT InitSeqAccess() { seqIx = 0; return 0;} SizeT SeqAccess() { assert( (seqIx+1) < sz); return ++seqIx;} SizeT size() const { return sz;} SizeT max() const { return sz - 1; } }; class AllIxRangeT: public AllIxBaseT { private: SizeT sz; SizeT st; SizeT seqIx; public: AllIxRangeT( SizeT sz_, SizeT st_): sz( sz_), st( st_) { } ~AllIxRangeT() {} AllIxRangeT* Clone() { AllIxRangeT* clone = new AllIxRangeT( sz, st); return clone; } SizeT operator[]( SizeT i) const { assert( i < sz); return i + st; } SizeT InitSeqAccess() { seqIx = st; return st;} SizeT SeqAccess() { assert( (seqIx-st+1) < sz); return ++seqIx;} SizeT size() const { return sz;} SizeT max() const { return sz - 1 + st; } }; class AllIxRangeStrideT: public AllIxBaseT { private: SizeT sz; SizeT st; SizeT stride; SizeT seqIx; public: AllIxRangeStrideT( SizeT sz_, SizeT st_, SizeT stride_): sz( sz_), st( st_), stride( stride_) { } ~AllIxRangeStrideT() {} AllIxRangeStrideT* Clone() { AllIxRangeStrideT* clone = new AllIxRangeStrideT( sz, st, stride); return clone; } SizeT operator[]( SizeT i) const { assert( i < sz); return i * stride + st; } SizeT InitSeqAccess() { seqIx = st; return st;} SizeT SeqAccess() { assert( ((seqIx+stride-st)/stride) < sz); seqIx += stride; return seqIx;} SizeT size() const { return sz;} SizeT max() const { return (sz - 1) * stride + st; } }; class AllIxRange0StrideT: public AllIxBaseT { private: SizeT sz; SizeT stride; SizeT seqIx; public: AllIxRange0StrideT( SizeT sz_, SizeT stride_): sz( sz_), stride( stride_) { } ~AllIxRange0StrideT() {} AllIxRange0StrideT* Clone() { AllIxRange0StrideT* clone = new AllIxRange0StrideT( sz, stride); return clone; } SizeT operator[]( SizeT i) const { assert( i < sz); return i * stride; } SizeT InitSeqAccess() { seqIx = 0; return 0;} SizeT SeqAccess() { assert( ((seqIx+stride)/stride) < sz); seqIx += stride; return seqIx;} SizeT size() const { return sz;} SizeT max() const { return (sz - 1) * stride; } }; class BaseGDL; class AllIxIndicesT: public AllIxBaseT { protected: BaseGDL* ref; SizeT upper; SizeT seqIx; #ifndef NDEBUG bool upperSet; #endif public: AllIxIndicesT( BaseGDL* r): ref( r), upper( 0) { #ifndef NDEBUG upperSet = false; #endif } ~AllIxIndicesT() {} AllIxIndicesT* Clone() { AllIxIndicesT* clone = new AllIxIndicesT( ref); return clone; } virtual AllIxIndicesT* CloneAt( char* buf) { AllIxIndicesT* clone = new (buf) AllIxIndicesT( ref); return clone; } SizeT operator[]( SizeT i) const; // code in arrayindex.cpp SizeT InitSeqAccess(); SizeT SeqAccess(); // code in arrayindex.cpp SizeT size() const; void SetUpper( SizeT u) { upper = u; #ifndef NDEBUG upperSet = true; #endif } }; class AllIxIndicesStrictT: public AllIxIndicesT { public: AllIxIndicesStrictT( BaseGDL* r): AllIxIndicesT( r) { } AllIxIndicesStrictT* Clone() { AllIxIndicesStrictT* clone = new AllIxIndicesStrictT( ref); return clone; } AllIxIndicesStrictT* CloneAt( char* buf) { AllIxIndicesStrictT* clone = new (buf) AllIxIndicesStrictT( ref); return clone; } SizeT operator[]( SizeT i) const; // code in arrayindex.cpp SizeT InitSeqAccess(); SizeT SeqAccess(); // code in arrayindex.cpp }; class AllIxAllIndexedT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; const SizeT* varStride; SizeT acRank; SizeT nIx; SizeT seqIx; public: AllIxAllIndexedT( ArrayIndexVectorT* ixList_, SizeT acRank_, SizeT nIx_, const SizeT* varStride_) : ixList( ixList_) , varStride( varStride_) , acRank( acRank_) , nIx( nIx_) {} ~AllIxAllIndexedT() {} AllIxAllIndexedT* Clone() { AllIxAllIndexedT* clone = new AllIxAllIndexedT( ixList, acRank, nIx, varStride); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; class AllIxNewMultiT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; SizeT ixListStride[MAXRANK]; const SizeT* varStride; SizeT* nIterLimit; SizeT* stride; SizeT acRank; SizeT nIx; SizeT seqIx; SizeT add; SizeT ix2; SizeT seqIter; SizeT seqIter0; public: AllIxNewMultiT( ArrayIndexVectorT* ixList_, SizeT acRank_, SizeT nIx_, const SizeT* varStride_, SizeT* nIterLimit_, SizeT* stride_) : ixList( ixList_) , varStride( varStride_) , nIterLimit( nIterLimit_) , stride( stride_) , acRank( acRank_) , nIx( nIx_) { add = 0; assert( varStride[0] == 1); for( SizeT i=0; iIndexed()) { ixListStride[i] = (*ixList)[i]->GetStride() * varStride[i]; assert( ixListStride[i] >= 1); add += (*ixList)[i]->GetS() * varStride[i]; } } } ~AllIxNewMultiT() {} AllIxNewMultiT* Clone() { AllIxNewMultiT* clone = new AllIxNewMultiT( *this); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; // acRank == 2 class AllIxNewMulti2DT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; SizeT ixListStride[2]; const SizeT* varStride; SizeT* nIterLimit; SizeT* stride; SizeT nIx; SizeT seqIx; // SizeT s[MAXRANK]; SizeT add; SizeT ix2; SizeT seqIter; SizeT seqIter0; public: AllIxNewMulti2DT( ArrayIndexVectorT* ixList_, SizeT nIx_, const SizeT* varStride_, SizeT* nIterLimit_, SizeT* stride_) : ixList( ixList_) , varStride( varStride_) , nIterLimit( nIterLimit_) , stride( stride_) , nIx( nIx_) { add = 0; if( !(*ixList)[0]->Indexed()) { assert( varStride[0] == 1); ixListStride[0] = (*ixList)[0]->GetStride(); assert( ixListStride[0] >= 1); add += (*ixList)[0]->GetS(); } if( !(*ixList)[1]->Indexed()) { ixListStride[1] = (*ixList)[1]->GetStride() * varStride[1]; assert( ixListStride[1] >= 1); add += (*ixList)[1]->GetS() * varStride[1]; } } ~AllIxNewMulti2DT() {} AllIxNewMulti2DT* Clone() { AllIxNewMulti2DT* clone = new AllIxNewMulti2DT( *this); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; class AllIxNewMultiNoneIndexedT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; SizeT ixListStride[MAXRANK]; const SizeT* varStride; SizeT* nIterLimit; SizeT* stride; SizeT acRank; SizeT nIx; SizeT seqIx; SizeT add; SizeT seqIter; SizeT correctionIncrease; SizeT nextCorrection; // SizeT seqIxDebug; public: AllIxNewMultiNoneIndexedT( ArrayIndexVectorT* ixList_, SizeT acRank_, SizeT nIx_, const SizeT* varStride_, SizeT* nIterLimit_, SizeT* stride_) : ixList( ixList_) , varStride( varStride_) , nIterLimit( nIterLimit_) , stride( stride_) , acRank( acRank_) , nIx( nIx_) { assert( varStride[0] == 1); add = 0; for( SizeT i=0; iGetStride() * varStride[i]; assert( ixListStride[i] >= 1); add += (*ixList)[i]->GetS() * varStride[i]; } } ~AllIxNewMultiNoneIndexedT() {} AllIxNewMultiNoneIndexedT* Clone() { AllIxNewMultiNoneIndexedT* clone = new AllIxNewMultiNoneIndexedT( *this); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; // acRank == 2 class AllIxNewMultiNoneIndexed2DT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; SizeT ixListStride[2]; const SizeT* varStride; SizeT* nIterLimit; SizeT* stride; SizeT nIx; SizeT seqIx; SizeT add; SizeT nextCorrection; SizeT correctionIncrease; public: AllIxNewMultiNoneIndexed2DT( ArrayIndexVectorT* ixList_, SizeT nIx_, const SizeT* varStride_, SizeT* nIterLimit_, SizeT* stride_) : ixList( ixList_) , varStride( varStride_) , nIterLimit( nIterLimit_) , stride( stride_) , nIx( nIx_) { assert( varStride[0] == 1); ixListStride[0] = (*ixList)[0]->GetStride(); ixListStride[1] = (*ixList)[1]->GetStride() * varStride[1]; add = (*ixList)[0]->GetS() + (*ixList)[1]->GetS() * varStride[1]; } ~AllIxNewMultiNoneIndexed2DT() {} AllIxNewMultiNoneIndexed2DT* Clone() { AllIxNewMultiNoneIndexed2DT* clone = new AllIxNewMultiNoneIndexed2DT( *this); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; class AllIxNewMultiOneVariableIndexNoIndexT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; SizeT ixListStride; const SizeT* varStride; SizeT* nIterLimit; SizeT* stride; SizeT acRank; SizeT nIx; SizeT seqIx; SizeT add; RankT variableIndex; public: AllIxNewMultiOneVariableIndexNoIndexT( RankT gt1Rank, SizeT add_, ArrayIndexVectorT* ixList_, SizeT acRank_, SizeT nIx_, const SizeT* varStride_, SizeT* nIterLimit_, SizeT* stride_) : ixList( ixList_) , varStride( varStride_) , nIterLimit( nIterLimit_) , stride( stride_) , acRank( acRank_) , nIx( nIx_) , add( add_) , variableIndex( gt1Rank) { assert( varStride[0] == 1); ixListStride = (*ixList)[variableIndex]->GetStride() * varStride[variableIndex]; assert( ixListStride >= 1); } ~AllIxNewMultiOneVariableIndexNoIndexT() {} AllIxNewMultiOneVariableIndexNoIndexT* Clone() { AllIxNewMultiOneVariableIndexNoIndexT* clone = new AllIxNewMultiOneVariableIndexNoIndexT( *this); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; class AllIxNewMultiOneVariableIndexIndexedT: public AllIxBaseT { private: ArrayIndexVectorT* ixList; SizeT ixListStride; const SizeT* varStride; SizeT* nIterLimit; SizeT* stride; SizeT acRank; SizeT nIx; SizeT seqIx; SizeT add; RankT variableIndex; ArrayIndexT* arrayIndexIndexed; public: AllIxNewMultiOneVariableIndexIndexedT( RankT gt1Rank, SizeT add_, ArrayIndexVectorT* ixList_, SizeT acRank_, SizeT nIx_, const SizeT* varStride_, SizeT* nIterLimit_, SizeT* stride_) : ixList( ixList_) , varStride( varStride_) , nIterLimit( nIterLimit_) , stride( stride_) , acRank( acRank_) , nIx( nIx_) , add( add_) , variableIndex( gt1Rank) { arrayIndexIndexed = (*ixList)[variableIndex]; ixListStride = varStride[variableIndex]; if( ixListStride < 1) // debug assert( ixListStride >= 1); } ~AllIxNewMultiOneVariableIndexIndexedT() {} AllIxNewMultiOneVariableIndexIndexedT* Clone() { AllIxNewMultiOneVariableIndexIndexedT* clone = new AllIxNewMultiOneVariableIndexIndexedT( *this); return clone; } SizeT operator[]( SizeT i) const; SizeT InitSeqAccess(); SizeT SeqAccess(); SizeT size() const { return nIx;} }; namespace AllIxMaxSizeCalculation { static const int a = sizeof( AllIxRangeT); static const int b = sizeof( AllIxRange0T); static const int c = sizeof( AllIxRangeStrideT); static const int d = sizeof( AllIxRange0StrideT); static const int e = sizeof( AllIxT); static const int f = sizeof( AllIxNewMultiOneVariableIndexIndexedT); static const int g = sizeof( AllIxNewMultiOneVariableIndexNoIndexT); static const int h = sizeof( AllIxNewMulti2DT); static const int i = sizeof( AllIxNewMultiT); static const int j = sizeof( AllIxNewMultiNoneIndexedT); static const int k = sizeof( AllIxNewMultiNoneIndexed2DT); static const int ab = a > b ? a : b; static const int abc = ab > c ? ab : c; static const int abcd = abc > d ? abc : d; static const int abcde = abcd > e ? abcd : e; static const int abcdef = abcde > f ? abcde : f; static const int abcdefg = abcdef > g ? abcdef : g; static const int abcdefgh = abcdefg > h ? abcdefg : h; static const int abcdefghi = abcdefgh > i ? abcdefgh : i; static const int abcdefghij = abcdefghi > j ? abcdefghi : j; static const int abcdefghijk = abcdefghij > k ? abcdefghij : k; static const int Max = abcdefghijk; } static const int AllIxMaxSize = AllIxMaxSizeCalculation::Max; #endif gdl-0.9.9/src/antlr/000077500000000000000000000000001340051421000141745ustar00rootroot00000000000000gdl-0.9.9/src/antlr/ANTLRException.hpp000066400000000000000000000026311340051421000174460ustar00rootroot00000000000000#ifndef INC_ANTLRException_hpp__ #define INC_ANTLRException_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ANTLRException.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API ANTLRException { public: /// Create ANTLR base exception without error message ANTLRException() : text("") { } /// Create ANTLR base exception with error message ANTLRException(const ANTLR_USE_NAMESPACE(std)string& s) : text(s) { } virtual ~ANTLRException() throw() { } /** Return complete error message with line/column number info (if present) * @note for your own exceptions override this one. Call getMessage from * here to get the 'clean' error message stored in the text attribute. */ virtual ANTLR_USE_NAMESPACE(std)string toString() const { return text; } /** Return error message without additional info (if present) * @note when making your own exceptions classes override toString * and call in toString getMessage which relays the text attribute * from here. */ virtual ANTLR_USE_NAMESPACE(std)string getMessage() const { return text; } private: ANTLR_USE_NAMESPACE(std)string text; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ANTLRException_hpp__ gdl-0.9.9/src/antlr/ANTLRUtil.cpp000066400000000000000000000071711340051421000164240ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ANTLRUtil.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** Eat whitespace from the input stream * @param is the stream to read from */ ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is ) { char c; while( is.get(c) ) { #ifdef ANTLR_CCTYPE_NEEDS_STD if( !ANTLR_USE_NAMESPACE(std)isspace(c) ) #else if( !isspace(c) ) #endif { is.putback(c); break; } } return is; } /** Read a string enclosed by '"' from a stream. Also handles escaping of \". * Skips leading whitespace. * @param in the istream to read from. * @returns the string read from file exclusive the '"' * @throws IOException if string is badly formatted */ ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in ) { char ch; ANTLR_USE_NAMESPACE(std)string ret(""); // States for a simple state machine... enum { START, READING, ESCAPE, FINISHED }; int state = START; eatwhite(in); while( state != FINISHED && in.get(ch) ) { switch( state ) { case START: // start state: check wether starting with " then switch to READING if( ch != '"' ) throw IOException("string must start with '\"'"); state = READING; continue; case READING: // reading state: look out for escape sequences and closing " if( ch == '\\' ) // got escape sequence { state = ESCAPE; continue; } if( ch == '"' ) // close quote -> stop { state = FINISHED; continue; } ret += ch; // else append... continue; case ESCAPE: switch(ch) { case '\\': ret += ch; state = READING; continue; case '"': ret += ch; state = READING; continue; case '0': ret += '\0'; state = READING; continue; default: // unrecognized escape is not mapped ret += '\\'; ret += ch; state = READING; continue; } } } if( state != FINISHED ) throw IOException("badly formatted string: "+ret); return ret; } /* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace. * @param in the istream to read from. */ ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in ) { char ch; ANTLR_USE_NAMESPACE(std)string ret(""); eatwhite(in); while( in.get(ch) ) { #ifdef ANTLR_CCTYPE_NEEDS_STD if( ANTLR_USE_NAMESPACE(std)isupper(ch) || ANTLR_USE_NAMESPACE(std)islower(ch) || ANTLR_USE_NAMESPACE(std)isdigit(ch) || ch == '_' ) #else if( isupper(ch) || islower(ch) || isdigit(ch) || ch == '_' ) #endif ret += ch; else { in.putback(ch); break; } } return ret; } /** Read a attribute="value" thing. Leading whitespace is skipped. * Between attribute and '=' no whitespace is allowed. After the '=' it is * permitted. * @param in the istream to read from. * @param attribute string the attribute name is put in * @param value string the value of the attribute is put in * @throws IOException if something is fishy. E.g. malformed quoting * or missing '=' */ void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in, ANTLR_USE_NAMESPACE(std)string& attribute, ANTLR_USE_NAMESPACE(std)string& value ) { attribute = read_identifier(in); char ch; if( in.get(ch) && ch == '=' ) value = read_string(in); else throw IOException("invalid attribute=value thing "+attribute); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/ANTLRUtil.hpp000066400000000000000000000033041340051421000164230ustar00rootroot00000000000000#ifndef INC_ANTLRUtil_hpp__ #define INC_ANTLRUtil_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ANTLRUtil.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** Eat whitespace from the input stream * @param is the stream to read from */ ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is ); /** Read a string enclosed by '"' from a stream. Also handles escaping of \". * Skips leading whitespace. * @param in the istream to read from. * @returns the string read from file exclusive the '"' * @throws ios_base::failure if string is badly formatted */ ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in ); /* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace. * @param in the istream to read from. */ ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in ); /** Read a attribute="value" thing. Leading whitespace is skipped. * Between attribute and '=' no whitespace is allowed. After the '=' it is * permitted. * @param in the istream to read from. * @param attribute string the attribute name is put in * @param value string the value of the attribute is put in * @throws ios_base::failure if something is fishy. E.g. malformed quoting * or missing '=' */ void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in, ANTLR_USE_NAMESPACE(std)string& attribute, ANTLR_USE_NAMESPACE(std)string& value ); #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif gdl-0.9.9/src/antlr/AST.hpp000066400000000000000000000122651340051421000153420ustar00rootroot00000000000000#ifndef INC_AST_hpp__ #define INC_AST_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: AST.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif struct ASTRef; class ANTLR_API AST { public: AST() : ref(0) {} AST(const AST&) : ref(0) {} virtual ~AST() {} /// Return the type name for this AST node. (for XML output) virtual const char* typeName( void ) const = 0; /// Clone this AST node. virtual RefAST clone( void ) const = 0; /// Is node t equal to this in terms of token type and text? virtual bool equals(RefAST t) const = 0; /** Is t an exact structural and equals() match of this tree. The * 'this' reference is considered the start of a sibling list. */ virtual bool equalsList(RefAST t) const = 0; /** Is 't' a subtree of this list? The siblings of the root are NOT ignored. */ virtual bool equalsListPartial(RefAST t) const = 0; /** Is tree rooted at 'this' equal to 't'? The siblings of 'this' are * ignored. */ virtual bool equalsTree(RefAST t) const = 0; /** Is 't' a subtree of the tree rooted at 'this'? The siblings of * 'this' are ignored. */ virtual bool equalsTreePartial(RefAST t) const = 0; /** Walk the tree looking for all exact subtree matches. Return * a vector of RefAST that lets the caller walk the list * of subtree roots found herein. */ virtual ANTLR_USE_NAMESPACE(std)vector findAll(RefAST t) = 0; /** Walk the tree looking for all subtrees. Return * a vector of RefAST that lets the caller walk the list * of subtree roots found herein. */ virtual ANTLR_USE_NAMESPACE(std)vector findAllPartial(RefAST t) = 0; /// Add a node to the end of the child list for this node virtual void addChild(RefAST c) = 0; /// Get the number of children. Returns 0 if the node is a leaf virtual size_t getNumberOfChildren() const = 0; /// Get the first child of this node; null if no children virtual RefAST getFirstChild() const = 0; /// Get the next sibling in line after this one virtual RefAST getNextSibling() const = 0; /// Get the token text for this node virtual ANTLR_USE_NAMESPACE(std)string getText() const = 0; /// Get the token type for this node virtual int getType() const = 0; /** Various initialization routines. Used by several factories to initialize * an AST element. */ virtual void initialize(int t, const ANTLR_USE_NAMESPACE(std)string& txt) = 0; virtual void initialize(RefAST t) = 0; virtual void initialize(RefToken t) = 0; #ifdef ANTLR_SUPPORT_XML /** initialize this node from the contents of a stream. * @param in the stream to read the AST attributes from. */ virtual void initialize( ANTLR_USE_NAMESPACE(std)istream& in ) = 0; #endif /// Set the first child of a node. virtual void setFirstChild(RefAST c) = 0; /// Set the next sibling after this one. virtual void setNextSibling(RefAST n) = 0; /// Set the token text for this node virtual void setText(const ANTLR_USE_NAMESPACE(std)string& txt) = 0; /// Set the token type for this node virtual void setType(int type) = 0; /// Return this AST node as a string virtual ANTLR_USE_NAMESPACE(std)string toString() const = 0; /// Print out a child-sibling tree in LISP notation virtual ANTLR_USE_NAMESPACE(std)string toStringList() const = 0; virtual ANTLR_USE_NAMESPACE(std)string toStringTree() const = 0; #ifdef ANTLR_SUPPORT_XML /** get attributes of this node to 'out'. Override to customize XML * output. * @param out the stream to write the AST attributes to. * @returns if a explicit closetag should be written */ virtual bool attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const = 0; /** Print a symbol over ostream. Overload this one to customize the XML * output for AST derived AST-types * @param output stream */ virtual void toStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const = 0; /** Dump AST contents in XML format to output stream. * Works in conjunction with to_stream method. Overload that one is * derived classes to customize behaviour. * @param output stream to write to string to put the stuff in. * @param ast RefAST object to write. */ friend ANTLR_USE_NAMESPACE(std)ostream& operator<<( ANTLR_USE_NAMESPACE(std)ostream& output, const RefAST& ast ); #endif private: friend struct ASTRef; ASTRef* ref; AST(RefAST other); AST& operator=(const AST& other); AST& operator=(RefAST other); }; #ifdef ANTLR_SUPPORT_XML inline ANTLR_USE_NAMESPACE(std)ostream& operator<<( ANTLR_USE_NAMESPACE(std)ostream& output, const RefAST& ast ) { ast->toStream(output); return output; } #endif extern ANTLR_API RefAST nullAST; extern ANTLR_API AST* const nullASTptr; #ifdef NEEDS_OPERATOR_LESS_THAN // RK: apparently needed by MSVC and a SUN CC, up to and including // 2.7.2 this was undefined ? inline bool operator<( RefAST l, RefAST r ) { return nullAST == l ? ( nullAST == r ? false : true ) : l->getType() < r->getType(); } #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_AST_hpp__ gdl-0.9.9/src/antlr/ASTArray.hpp000066400000000000000000000015671340051421000163440ustar00rootroot00000000000000#ifndef INC_ASTArray_hpp__ #define INC_ASTArray_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTArray.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** ASTArray is a class that allows ANTLR to * generate code that can create and initialize an array * in one expression, like: * (new ASTArray(3))->add(x)->add(y)->add(z) */ class ANTLR_API ASTArray { public: int size; // = 0; ANTLR_USE_NAMESPACE(std)vector array; ASTArray(int capacity) : size(0) , array(capacity) { } ASTArray* add(RefAST node) { array[size++] = node; return this; } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ASTArray_hpp__ gdl-0.9.9/src/antlr/ASTFactory.cpp000066400000000000000000000300721340051421000166610ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTFactory.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/CommonAST.hpp" #include "antlr/ANTLRException.hpp" #include "antlr/IOException.hpp" #include "antlr/ASTFactory.hpp" #include "antlr/ANTLRUtil.hpp" #include #include using namespace std; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** AST Support code shared by TreeParser and Parser. * We use delegation to share code (and have only one * bit of code to maintain) rather than subclassing * or superclassing (forces AST support code to be * loaded even when you don't want to do AST stuff). * * This class collects all factories of AST types used inside the code. * New AST node types are registered with the registerFactory method. * On creation of an ASTFactory object a default AST node factory may be * specified. * * When registering types gaps between different types are filled with entries * for the default factory. */ /// Initialize factory ASTFactory::ASTFactory() : default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(CommonAST::TYPE_NAME,&CommonAST::factory)) { nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor ); } /** Initialize factory with a non default node type. * factory_node_name should be the name of the AST node type the factory * generates. (should exist during the existance of this ASTFactory instance) */ ASTFactory::ASTFactory( const char* factory_node_name, factory_type fact ) : default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(factory_node_name, fact)) { nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor ); } /// Delete ASTFactory ASTFactory::~ASTFactory() { factory_descriptor_list::iterator i = nodeFactories.begin(); while( i != nodeFactories.end() ) { if( *i != &default_factory_descriptor ) delete *i; i++; } } /// Register a factory for a given AST type void ASTFactory::registerFactory( int type, const char* ast_name, factory_type factory ) { // check validity of arguments... if( type < Token::MIN_USER_TYPE ) throw ANTLRException("Internal parser error invalid type passed to RegisterFactory"); if( factory == 0 ) throw ANTLRException("Internal parser error 0 factory passed to RegisterFactory"); // resize up to and including 'type' and initalize any gaps to default // factory. if( nodeFactories.size() < (static_cast(type)+1) ) nodeFactories.resize( type+1, &default_factory_descriptor ); // And add new thing.. nodeFactories[type] = new ANTLR_USE_NAMESPACE(std)pair( ast_name, factory ); } void ASTFactory::setMaxNodeType( int type ) { if( nodeFactories.size() < (static_cast(type)+1) ) nodeFactories.resize( type+1, &default_factory_descriptor ); } /** Create a new empty AST node; if the user did not specify * an AST node type, then create a default one: CommonAST. */ RefAST ASTFactory::create() { RefAST node = nodeFactories[0]->second(); node->setType(Token::INVALID_TYPE); return node; } RefAST ASTFactory::create(int type) { RefAST t = nodeFactories[type]->second(); t->initialize(type,""); return t; } RefAST ASTFactory::create(int type, const ANTLR_USE_NAMESPACE(std)string& txt) { RefAST t = nodeFactories[type]->second(); t->initialize(type,txt); return t; } #ifdef ANTLR_SUPPORT_XML RefAST ASTFactory::create(const ANTLR_USE_NAMESPACE(std)string& type_name, ANTLR_USE_NAMESPACE(std)istream& infile ) { factory_descriptor_list::iterator fact = nodeFactories.begin(); while( fact != nodeFactories.end() ) { if( type_name == (*fact)->first ) { RefAST t = (*fact)->second(); t->initialize(infile); return t; } fact++; } string error = "ASTFactory::create: Unknown AST type '" + type_name + "'"; throw ANTLRException(error); } #endif /** Create a new empty AST node; if the user did not specify * an AST node type, then create a default one: CommonAST. */ RefAST ASTFactory::create(RefAST tr) { if (!tr) return nullAST; // cout << "create(tr)" << endl; RefAST t = nodeFactories[tr->getType()]->second(); t->initialize(tr); return t; } RefAST ASTFactory::create(RefToken tok) { // cout << "create( tok="<< tok->getType() << ", " << tok->getText() << ")" << nodeFactories.size() << endl; RefAST t = nodeFactories[tok->getType()]->second(); t->initialize(tok); return t; } /** Add a child to the current AST */ void ASTFactory::addASTChild(ASTPair& currentAST, RefAST child) { if (child) { if (!currentAST.root) { // Make new child the current root currentAST.root = child; } else { if (!currentAST.child) { // Add new child to current root currentAST.root->setFirstChild(child); } else { currentAST.child->setNextSibling(child); } } // Make new child the current child currentAST.child = child; currentAST.advanceChildToEnd(); } } /** Deep copy a single node. This function the new clone() methods in the AST * interface. Returns nullAST if t is null. */ RefAST ASTFactory::dup(RefAST t) { if( t ) return t->clone(); else return RefAST(nullASTptr); } /** Duplicate tree including siblings of root. */ RefAST ASTFactory::dupList(RefAST t) { RefAST result = dupTree(t); // if t == null, then result==null RefAST nt = result; while( t ) { // for each sibling of the root t = t->getNextSibling(); nt->setNextSibling(dupTree(t)); // dup each subtree, building new tree nt = nt->getNextSibling(); } return result; } /** Duplicate a tree, assuming this is a root node of a tree * duplicate that node and what's below; ignore siblings of root node. */ RefAST ASTFactory::dupTree(RefAST t) { RefAST result = dup(t); // make copy of root // copy all children of root. if( t ) result->setFirstChild( dupList(t->getFirstChild()) ); return result; } /** Make a tree from a list of nodes. The first element in the * array is the root. If the root is null, then the tree is * a simple list not a tree. Handles null children nodes correctly. * For example, make(a, b, null, c) yields tree (a b c). make(null,a,b) * yields tree (nil a b). */ RefAST ASTFactory::make(ANTLR_USE_NAMESPACE(std)vector& nodes) { if ( nodes.size() == 0 ) return RefAST(nullASTptr); RefAST root = nodes[0]; RefAST tail = RefAST(nullASTptr); if( root ) root->setFirstChild(RefAST(nullASTptr)); // don't leave any old pointers set // link in children; for( unsigned int i = 1; i < nodes.size(); i++ ) { if ( nodes[i] == 0 ) // ignore null nodes continue; if ( root == 0 ) // Set the root and set it up for a flat list root = tail = nodes[i]; else if ( tail == 0 ) { root->setFirstChild(nodes[i]); tail = root->getFirstChild(); } else { tail->setNextSibling(nodes[i]); tail = tail->getNextSibling(); } if( tail ) // RK: I cannot fathom why this missing check didn't bite anyone else... { // Chase tail to last sibling while (tail->getNextSibling()) tail = tail->getNextSibling(); } } return root; } /** Make a tree from a list of nodes, where the nodes are contained * in an ASTArray object */ RefAST ASTFactory::make(ASTArray* nodes) { RefAST ret = make(nodes->array); delete nodes; return ret; } /// Make an AST the root of current AST void ASTFactory::makeASTRoot( ASTPair& currentAST, RefAST root ) { if (root) { // Add the current root as a child of new root root->addChild(currentAST.root); // The new current child is the last sibling of the old root currentAST.child = currentAST.root; currentAST.advanceChildToEnd(); // Set the new root currentAST.root = root; } } void ASTFactory::setASTNodeFactory( const char* factory_node_name, factory_type factory ) { default_factory_descriptor.first = factory_node_name; default_factory_descriptor.second = factory; } #ifdef ANTLR_SUPPORT_XML bool ASTFactory::checkCloseTag( ANTLR_USE_NAMESPACE(std)istream& in ) { char ch; if( in.get(ch) ) { if( ch == '<' ) { char ch2; if( in.get(ch2) ) { if( ch2 == '/' ) { in.putback(ch2); in.putback(ch); return true; } in.putback(ch2); in.putback(ch); return false; } } in.putback(ch); return false; } return false; } void ASTFactory::loadChildren( ANTLR_USE_NAMESPACE(std)istream& infile, RefAST current ) { char ch; for(;;) // for all children of this node.... { eatwhite(infile); infile.get(ch); // '<' if( ch != '<' ) { string error = "Invalid XML file... no '<' found ("; error += ch + ")"; throw IOException(error); } infile.get(ch); // / or text.... if( ch == '/' ) // check for close tag... { string temp; // read until '>' and see if it matches the open tag... if not trouble temp = read_identifier( infile ); if( strcmp(temp.c_str(), current->typeName() ) != 0 ) { string error = "Invalid XML file... close tag does not match start tag: "; error += current->typeName(); error += " closed by " + temp; throw IOException(error); } infile.get(ch); // must be a '>' if( ch != '>' ) { string error = "Invalid XML file... no '>' found ("; error += ch + ")"; throw IOException(error); } // close tag => exit loop break; } // put our 'look ahead' back where it came from infile.putback(ch); infile.putback('<'); // and recurse into the tree... RefAST child = LoadAST(infile); current->addChild( child ); } } void ASTFactory::loadSiblings(ANTLR_USE_NAMESPACE(std)istream& infile, RefAST current ) { for(;;) { eatwhite(infile); if( infile.eof() ) break; if( checkCloseTag(infile) ) break; RefAST sibling = LoadAST(infile); current->setNextSibling(sibling); } } RefAST ASTFactory::LoadAST( ANTLR_USE_NAMESPACE(std)istream& infile ) { RefAST current = nullAST; char ch; eatwhite(infile); if( !infile.get(ch) ) return nullAST; if( ch != '<' ) { string error = "Invalid XML file... no '<' found ("; error += ch + ")"; throw IOException(error); } string ast_type = read_identifier(infile); // create the ast of type 'ast_type' current = create( ast_type, infile ); if( current == nullAST ) { string error = "Unsuported AST type: " + ast_type; throw IOException(error); } eatwhite(infile); infile.get(ch); // now if we have a '/' here it's a single node. If it's a '>' we get // a tree with children if( ch == '/' ) { infile.get(ch); // get the closing '>' if( ch != '>' ) { string error = "Invalid XML file... no '>' found after '/' ("; error += ch + ")"; throw IOException(error); } // get the rest on this level loadSiblings( infile, current ); return current; } // and finaly see if we got the close tag... if( ch != '>' ) { string error = "Invalid XML file... no '>' found ("; error += ch + ")"; throw IOException(error); } // handle the ones below this level.. loadChildren( infile, current ); // load the rest on this level... loadSiblings( infile, current ); return current; } #endif // ANTLR_SUPPORT_XML #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif /* Heterogeneous AST/XML-I/O ramblings... * * So there is some heterogeneous AST support.... * basically in the code generators a new custom ast is generated without * going throug the factory. It also expects the RefXAST to be defined. * * Is it maybe better to register all AST types with the ASTFactory class * together with the respective factory methods. * * More and more I get the impression that hetero ast was a kindoff hack * on top of ANTLR's normal AST system. * * The heteroast stuff will generate trouble for all astFactory.create( ... ) * invocations. Most of this is handled via getASTCreateString methods in the * codegenerator. At the moment getASTCreateString(GrammarAtom, String) has * slightly to little info to do it's job (ok the hack that is in now * works, but it's an ugly hack) * * An extra caveat is the 'nice' action.g thing. Which also judiciously calls * getASTCreateString methods because it handles the #( ... ) syntax. * And converts that to ASTFactory calls. * * */ gdl-0.9.9/src/antlr/ASTFactory.hpp000066400000000000000000000132061340051421000166660ustar00rootroot00000000000000#ifndef INC_ASTFactory_hpp__ #define INC_ASTFactory_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTFactory.hpp,v 1.2 2013-09-17 20:12:40 gilles-duvert Exp $ */ #include #include #include #include #ifdef __PATHCC__ #include #endif #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif // Using these extra types to appease MSVC typedef RefAST (*factory_type_)(); typedef ANTLR_USE_NAMESPACE(std)pair< const char*, factory_type_ > factory_descriptor_; typedef ANTLR_USE_NAMESPACE(std)vector< factory_descriptor_* > factory_descriptor_list_; /** AST Super Factory shared by TreeParser and Parser. * This super factory maintains a map of all AST node types to their respective * AST factories. One instance should be shared among a parser/treeparser * chain. * * @todo check all this code for possible use of references in * stead of RefAST's. */ class ANTLR_API ASTFactory { public: typedef factory_type_ factory_type; typedef factory_descriptor_ factory_descriptor; typedef factory_descriptor_list_ factory_descriptor_list; protected: /* The mapping of AST node type to factory.. */ factory_descriptor default_factory_descriptor; factory_descriptor_list nodeFactories; public: /// Make new factory. Per default (Ref)CommonAST instances are generated. ASTFactory(); /** Initialize factory with a non default node type. * factory_node_name should be the name of the AST node type the factory * generates. (should exist during the existance of this ASTFactory * instance) */ ASTFactory( const char* factory_node_name, factory_type factory ); /// Destroy factory virtual ~ASTFactory(); /// Register a node factory for the node type type with name ast_name void registerFactory( int type, const char* ast_name, factory_type factory ); /// Set the maximum node (AST) type this factory may encounter void setMaxNodeType( int type ); /// Add a child to the current AST void addASTChild(ASTPair& currentAST, RefAST child); /// Create new empty AST node. The right default type shou virtual RefAST create(); /// Create AST node of the right type for 'type' RefAST create(int type); /// Create AST node of the right type for 'type' and initialize with txt RefAST create(int type, const ANTLR_USE_NAMESPACE(std)string& txt); /// Create duplicate of tr RefAST create(RefAST tr); /// Create new AST node and initialize contents from a token. RefAST create(RefToken tok); /// Create new AST node and initialize contents from a stream. RefAST create(const ANTLR_USE_NAMESPACE(std)string& txt, ANTLR_USE_NAMESPACE(std)istream& infile ); /** Deep copy a single node. This function the new clone() methods in the * AST interface. Returns a new RefAST(nullASTptr) if t is null. */ RefAST dup(RefAST t); /// Duplicate tree including siblings of root. RefAST dupList(RefAST t); /** Duplicate a tree, assuming this is a root node of a tree-- * duplicate that node and what's below; ignore siblings of root node. */ RefAST dupTree(RefAST t); /** Make a tree from a list of nodes. The first element in the * array is the root. If the root is null, then the tree is * a simple list not a tree. Handles null children nodes correctly. * For example, make(a, b, null, c) yields tree (a b c). make(null,a,b) * yields tree (nil a b). */ RefAST make(ANTLR_USE_NAMESPACE(std)vector& nodes); /** Make a tree from a list of nodes, where the nodes are contained * in an ASTArray object. The ASTArray is deleted after use. * @todo FIXME! I have a feeling we can get rid of this ugly ASTArray thing */ RefAST make(ASTArray* nodes); /// Make an AST the root of current AST void makeASTRoot(ASTPair& currentAST, RefAST root); /** Set a new default AST type. * factory_node_name should be the name of the AST node type the factory * generates. (should exist during the existance of this ASTFactory * instance). * Only change factory between parser runs. You might get unexpected results * otherwise. */ void setASTNodeFactory( const char* factory_node_name, factory_type factory ); #ifdef ANTLR_SUPPORT_XML /** Load a XML AST from stream. Make sure you have all the factories * registered before use. * @note this 'XML' stuff is quite rough still. YMMV. */ RefAST LoadAST( ANTLR_USE_NAMESPACE(std)istream& infile ); #endif protected: void loadChildren( ANTLR_USE_NAMESPACE(std)istream& infile, RefAST current ); void loadSiblings( ANTLR_USE_NAMESPACE(std)istream& infile, RefAST current ); bool checkCloseTag( ANTLR_USE_NAMESPACE(std)istream& infile ); #ifdef ANTLR_VECTOR_HAS_AT /// construct a node of 'type' inline RefAST getNodeOfType( unsigned int type ) { return RefAST(nodeFactories.at(type)->second()); } /// get the name of the node 'type' const char* getASTNodeType( unsigned int type ) { return nodeFactories.at(type)->first; } /// get the factory used for node 'type' factory_type getASTNodeFactory( unsigned int type ) { return nodeFactories.at(type)->second; } #else inline RefAST getNodeOfType( unsigned int type ) { return RefAST(nodeFactories[type]->second()); } /// get the name of the node 'type' const char* getASTNodeType( unsigned int type ) { return nodeFactories[type]->first; } factory_type getASTNodeFactory( unsigned int type ) { return nodeFactories[type]->second; } #endif private: // no copying and such.. ASTFactory( const ASTFactory& ); ASTFactory& operator=( const ASTFactory& ); }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ASTFactory_hpp__ gdl-0.9.9/src/antlr/ASTNULLType.cpp000066400000000000000000000043151340051421000166670ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTNULLType.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/config.hpp" #include "antlr/AST.hpp" #include "antlr/ASTNULLType.hpp" #include ANTLR_USING_NAMESPACE(std) #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif RefAST ASTNULLType::clone( void ) const { return RefAST(this); } void ASTNULLType::addChild( RefAST ) { } size_t ASTNULLType::getNumberOfChildren() const { return 0; } bool ASTNULLType::equals( RefAST ) const { return false; } bool ASTNULLType::equalsList( RefAST ) const { return false; } bool ASTNULLType::equalsListPartial( RefAST ) const { return false; } bool ASTNULLType::equalsTree( RefAST ) const { return false; } bool ASTNULLType::equalsTreePartial( RefAST ) const { return false; } vector ASTNULLType::findAll( RefAST ) { return vector(); } vector ASTNULLType::findAllPartial( RefAST ) { return vector(); } RefAST ASTNULLType::getFirstChild() const { return this; } RefAST ASTNULLType::getNextSibling() const { return this; } string ASTNULLType::getText() const { return ""; } int ASTNULLType::getType() const { return Token::NULL_TREE_LOOKAHEAD; } void ASTNULLType::initialize( int, const string& ) { } void ASTNULLType::initialize( RefAST ) { } void ASTNULLType::initialize( RefToken ) { } #ifdef ANTLR_SUPPORT_XML void ASTNULLType::initialize( istream& ) { } #endif void ASTNULLType::setFirstChild( RefAST ) { } void ASTNULLType::setNextSibling( RefAST ) { } void ASTNULLType::setText( const string& ) { } void ASTNULLType::setType( int ) { } string ASTNULLType::toString() const { return getText(); } string ASTNULLType::toStringList() const { return getText(); } string ASTNULLType::toStringTree() const { return getText(); } #ifdef ANTLR_SUPPORT_XML bool ASTNULLType::attributesToStream( ostream& ) const { return false; } void ASTNULLType::toStream( ostream& out ) const { out << "" << endl; } #endif const char* ASTNULLType::typeName( void ) const { return "ASTNULLType"; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/ASTNULLType.hpp000066400000000000000000000034171340051421000166760ustar00rootroot00000000000000#ifndef INC_ASTNULLType_hpp__ #define INC_ASTNULLType_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTNULLType.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** There is only one instance of this class **/ class ANTLR_API ASTNULLType : public AST { public: const char* typeName( void ) const; RefAST clone( void ) const; void addChild(RefAST c); size_t getNumberOfChildren() const; void setFirstChild(RefAST c); void setNextSibling(RefAST n); bool equals(RefAST t) const; bool equalsList(RefAST t) const; bool equalsListPartial(RefAST t) const; bool equalsTree(RefAST t) const; bool equalsTreePartial(RefAST t) const; ANTLR_USE_NAMESPACE(std)vector findAll(RefAST tree); ANTLR_USE_NAMESPACE(std)vector findAllPartial(RefAST subtree); RefAST getFirstChild() const; RefAST getNextSibling() const; ANTLR_USE_NAMESPACE(std)string getText() const; int getType() const; void initialize(int t, const ANTLR_USE_NAMESPACE(std)string& txt); void initialize(RefAST t); void initialize(RefToken t); void initialize(ANTLR_USE_NAMESPACE(std)istream& infile); void setText(const ANTLR_USE_NAMESPACE(std)string& text); void setType(int ttype); ANTLR_USE_NAMESPACE(std)string toString() const; ANTLR_USE_NAMESPACE(std)string toStringList() const; ANTLR_USE_NAMESPACE(std)string toStringTree() const; bool attributesToStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const; void toStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ASTNULLType_hpp__ gdl-0.9.9/src/antlr/ASTPair.hpp000066400000000000000000000030601340051421000161470ustar00rootroot00000000000000#ifndef INC_ASTPair_hpp__ #define INC_ASTPair_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTPair.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** ASTPair: utility class used for manipulating a pair of ASTs * representing the current AST root and current AST sibling. * This exists to compensate for the lack of pointers or 'var' * arguments in Java. * * OK, so we can do those things in C++, but it seems easier * to stick with the Java way for now. */ class ANTLR_API ASTPair { public: RefAST root; // current root of tree RefAST child; // current child to which siblings are added /** Make sure that child is the last sibling */ void advanceChildToEnd() { if (child) { while (child->getNextSibling()) { child = child->getNextSibling(); } } } // /** Copy an ASTPair. Don't call it clone() because we want type-safety */ // ASTPair copy() { // ASTPair tmp = new ASTPair(); // tmp.root = root; // tmp.child = child; // return tmp; // } ANTLR_USE_NAMESPACE(std)string toString() const { ANTLR_USE_NAMESPACE(std)string r = !root ? ANTLR_USE_NAMESPACE(std)string("null") : root->getText(); ANTLR_USE_NAMESPACE(std)string c = !child ? ANTLR_USE_NAMESPACE(std)string("null") : child->getText(); return "["+r+","+c+"]"; } }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ASTPair_hpp__ gdl-0.9.9/src/antlr/ASTRefCount.cpp000066400000000000000000000012611340051421000167750ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTRefCount.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/ASTRefCount.hpp" #include "antlr/AST.hpp" #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif ASTRef::ASTRef(AST* p) : ptr(p), count(1) { if (p && !p->ref) p->ref = this; } ASTRef::~ASTRef() { delete ptr; } ASTRef* ASTRef::getRef(const AST* p) { if (p) { AST* pp = const_cast(p); if (pp->ref) return pp->ref->increment(); else return new ASTRef(pp); } else return 0; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/ASTRefCount.hpp000066400000000000000000000032771340051421000170130ustar00rootroot00000000000000#ifndef INC_ASTRefCount_hpp__ # define INC_ASTRefCount_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: ASTRefCount.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ # include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class AST; struct ANTLR_API ASTRef { AST* const ptr; unsigned int count; ASTRef(AST* p); ~ASTRef(); ASTRef* increment() { ++count; return this; } bool decrement() { return (--count==0); } static ASTRef* getRef(const AST* p); private: ASTRef( const ASTRef& ); ASTRef& operator=( const ASTRef& ); }; template class ANTLR_API ASTRefCount { private: ASTRef* ref; public: ASTRefCount(const AST* p=0) : ref(p ? ASTRef::getRef(p) : 0) { } ASTRefCount(const ASTRefCount& other) : ref(other.ref ? other.ref->increment() : 0) { } ~ASTRefCount() { if (ref && ref->decrement()) delete ref; } ASTRefCount& operator=(AST* other) { ASTRef* tmp = ASTRef::getRef(other); if (ref && ref->decrement()) delete ref; ref=tmp; return *this; } ASTRefCount& operator=(const ASTRefCount& other) { if( other.ref != ref ) { ASTRef* tmp = other.ref ? other.ref->increment() : 0; if (ref && ref->decrement()) delete ref; ref=tmp; } return *this; } operator T* () const { return ref ? static_cast(ref->ptr) : 0; } T* operator->() const { return ref ? static_cast(ref->ptr) : 0; } T* get() const { return ref ? static_cast(ref->ptr) : 0; } }; typedef ASTRefCount RefAST; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_ASTRefCount_hpp__ gdl-0.9.9/src/antlr/BaseAST.cpp000066400000000000000000000167471340051421000161410ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: BaseAST.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include "antlr/config.hpp" #include "antlr/AST.hpp" #include "antlr/BaseAST.hpp" ANTLR_USING_NAMESPACE(std) #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif const char* const BaseAST::TYPE_NAME = "BaseAST"; //bool BaseAST::verboseStringConversion; //ANTLR_USE_NAMESPACE(std)vector BaseAST::tokenNames; BaseAST::BaseAST() : AST() { } BaseAST::~BaseAST() { } BaseAST::BaseAST(const BaseAST& other) : AST(other) // RK: don't copy links! , down(other.down), right(other.right) { } const char* BaseAST::typeName( void ) const { return BaseAST::TYPE_NAME; } RefAST BaseAST::clone( void ) const { ANTLR_USE_NAMESPACE(std)cerr << "BaseAST::clone()" << ANTLR_USE_NAMESPACE(std)endl; return nullAST; } void BaseAST::addChild( RefAST c ) { if( !c ) return; RefBaseAST tmp = down; if (tmp) { while (tmp->right) tmp = tmp->right; tmp->right = c; } else down = c; } size_t BaseAST::getNumberOfChildren() const { RefBaseAST t = this->down; size_t n = 0; if( t ) { n = 1; while( t->right ) { t = t->right; n++; } return n; } return n; } void BaseAST::doWorkForFindAll( ANTLR_USE_NAMESPACE(std)vector& v, RefAST target,bool partialMatch) { // Start walking sibling lists, looking for matches. for (RefAST sibling=this; sibling; sibling=sibling->getNextSibling()) { if ( (partialMatch && sibling->equalsTreePartial(target)) || (!partialMatch && sibling->equalsTree(target)) ) { v.push_back(sibling); } // regardless of match or not, check any children for matches if ( sibling->getFirstChild() ) { RefBaseAST(sibling->getFirstChild())->doWorkForFindAll(v, target, partialMatch); } } } /** Is t an exact structural and equals() match of this tree. The * 'this' reference is considered the start of a sibling list. */ bool BaseAST::equalsList(RefAST t) const { // the empty tree is not a match of any non-null tree. if (!t) return false; // Otherwise, start walking sibling lists. First mismatch, return false. RefAST sibling=this; for (;sibling && t; sibling=sibling->getNextSibling(), t=t->getNextSibling()) { // as a quick optimization, check roots first. if (!sibling->equals(t)) return false; // if roots match, do full list match test on children. if (sibling->getFirstChild()) { if (!sibling->getFirstChild()->equalsList(t->getFirstChild())) return false; } // sibling has no kids, make sure t doesn't either else if (t->getFirstChild()) return false; } if (!sibling && !t) return true; // one sibling list has more than the other return false; } /** Is 'sub' a subtree of this list? * The siblings of the root are NOT ignored. */ bool BaseAST::equalsListPartial(RefAST sub) const { // the empty tree is always a subset of any tree. if (!sub) return true; // Otherwise, start walking sibling lists. First mismatch, return false. RefAST sibling=this; for (;sibling && sub; sibling=sibling->getNextSibling(), sub=sub->getNextSibling()) { // as a quick optimization, check roots first. if (!sibling->equals(sub)) return false; // if roots match, do partial list match test on children. if (sibling->getFirstChild()) if (!sibling->getFirstChild()->equalsListPartial(sub->getFirstChild())) return false; } if (!sibling && sub) // nothing left to match in this tree, but subtree has more return false; // either both are null or sibling has more, but subtree doesn't return true; } /** Is tree rooted at 'this' equal to 't'? The siblings * of 'this' are ignored. */ bool BaseAST::equalsTree(RefAST t) const { // check roots first if (!equals(t)) return false; // if roots match, do full list match test on children. if (getFirstChild()) { if (!getFirstChild()->equalsList(t->getFirstChild())) return false; } // sibling has no kids, make sure t doesn't either else if (t->getFirstChild()) return false; return true; } /** Is 'sub' a subtree of the tree rooted at 'this'? The siblings * of 'this' are ignored. */ bool BaseAST::equalsTreePartial(RefAST sub) const { // the empty tree is always a subset of any tree. if (!sub) return true; // check roots first if (!equals(sub)) return false; // if roots match, do full list partial match test on children. if (getFirstChild()) if (!getFirstChild()->equalsListPartial(sub->getFirstChild())) return false; return true; } /** Walk the tree looking for all exact subtree matches. Return * an ASTEnumerator that lets the caller walk the list * of subtree roots found herein. */ ANTLR_USE_NAMESPACE(std)vector BaseAST::findAll(RefAST target) { ANTLR_USE_NAMESPACE(std)vector roots; // the empty tree cannot result in an enumeration if (target) { doWorkForFindAll(roots,target,false); // find all matches recursively } return roots; } /** Walk the tree looking for all subtrees. Return * an ASTEnumerator that lets the caller walk the list * of subtree roots found herein. */ ANTLR_USE_NAMESPACE(std)vector BaseAST::findAllPartial(RefAST target) { ANTLR_USE_NAMESPACE(std)vector roots; // the empty tree cannot result in an enumeration if (target) doWorkForFindAll(roots,target,true); // find all matches recursively return roots; } void BaseAST::setText( const ANTLR_USE_NAMESPACE(std)string& ) { } void BaseAST::setType( int ) { } ANTLR_USE_NAMESPACE(std)string BaseAST::toString() const { return getText(); } ANTLR_USE_NAMESPACE(std)string BaseAST::toStringList() const { ANTLR_USE_NAMESPACE(std)string ts=""; if (getFirstChild()) { ts+=" ( "; ts+=toString(); ts+=getFirstChild()->toStringList(); ts+=" )"; } else { ts+=" "; ts+=toString(); } if (getNextSibling()) ts+=getNextSibling()->toStringList(); return ts; } ANTLR_USE_NAMESPACE(std)string BaseAST::toStringTree() const { ANTLR_USE_NAMESPACE(std)string ts = ""; if (getFirstChild()) { ts+=" ( "; ts+=toString(); ts+=getFirstChild()->toStringList(); ts+=" )"; } else { ts+=" "; ts+=toString(); } return ts; } #ifdef ANTLR_SUPPORT_XML /* This whole XML output stuff needs a little bit more thought * I'd like to store extra XML data in the node. e.g. for custom ast's * with for instance symboltable references. This * should be more pluggable.. * @returns boolean value indicating wether a closetag should be produced. */ bool BaseAST::attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const { out << "text=\"" << this->getText() << "\" type=\"" << this->getType() << "\""; return false; } void BaseAST::toStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const { for( RefAST node = this; node != 0; node = node->getNextSibling() ) { out << "<" << this->typeName() << " "; // Write out attributes and if there is extra data... bool need_close_tag = node->attributesToStream( out ); if( need_close_tag ) { // got children so write them... if( node->getFirstChild() != 0 ) node->getFirstChild()->toStream( out ); // and a closing tag.. out << "typeName() << ">" << endl; } } } #endif // this is nasty, but it makes the code generation easier ANTLR_API RefAST nullAST; #if defined(_MSC_VER) && !defined(__ICL) // Microsoft Visual C++ extern ANTLR_API AST* const nullASTptr = 0; #else ANTLR_API AST* const nullASTptr = 0; #endif #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/BaseAST.hpp000066400000000000000000000104371340051421000161340ustar00rootroot00000000000000#ifndef INC_BaseAST_hpp__ #define INC_BaseAST_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: BaseAST.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif class ANTLR_API BaseAST; typedef ASTRefCount RefBaseAST; class ANTLR_API BaseAST : public AST { public: BaseAST(); BaseAST(const BaseAST& other); virtual ~BaseAST(); /// Return the class name virtual const char* typeName( void ) const; /// Clone this AST node. virtual RefAST clone( void ) const; /// Is node t equal to this in terms of token type and text? virtual bool equals(RefAST t) const; /** Is t an exact structural and equals() match of this tree. The * 'this' reference is considered the start of a sibling list. */ virtual bool equalsList(RefAST t) const; /** Is 't' a subtree of this list? The siblings of the root are NOT ignored. */ virtual bool equalsListPartial(RefAST t) const; /** Is tree rooted at 'this' equal to 't'? The siblings of 'this' are * ignored. */ virtual bool equalsTree(RefAST t) const; /** Is 't' a subtree of the tree rooted at 'this'? The siblings of * 'this' are ignored. */ virtual bool equalsTreePartial(RefAST t) const; /** Walk the tree looking for all exact subtree matches. Return * an ASTEnumerator that lets the caller walk the list * of subtree roots found herein. */ virtual ANTLR_USE_NAMESPACE(std)vector findAll(RefAST t); /** Walk the tree looking for all subtrees. Return * an ASTEnumerator that lets the caller walk the list * of subtree roots found herein. */ virtual ANTLR_USE_NAMESPACE(std)vector findAllPartial(RefAST t); /// Add a node to the end of the child list for this node virtual void addChild(RefAST c); /** Get the number of child nodes of this node (shallow e.g. not of the * whole tree it spans). */ virtual size_t getNumberOfChildren() const; /// Get the first child of this node; null if no children virtual RefAST getFirstChild() const { return RefAST(down); } /// Get the next sibling in line after this one virtual RefAST getNextSibling() const { return RefAST(right); } /// Get the token text for this node virtual ANTLR_USE_NAMESPACE(std)string getText() const { return ""; } /// Get the token type for this node virtual int getType() const { return 0; } /// Remove all children virtual void removeChildren() { down = static_cast(static_cast(nullAST)); } /// Set the first child of a node. virtual void setFirstChild(RefAST c) { down = static_cast(static_cast(c)); } /// Set the next sibling after this one. void setNextSibling(RefAST n) { right = static_cast(static_cast(n)); } /// Set the token text for this node virtual void setText(const ANTLR_USE_NAMESPACE(std)string& txt); /// Set the token type for this node virtual void setType(int type); #ifdef ANTLR_SUPPORT_XML /** print attributes of this node to 'out'. Override to customize XML * output. * @param out the stream to write the AST attributes to. */ virtual bool attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const; /** Write this subtree to a stream. Overload this one to customize the XML * output for AST derived AST-types * @param output stream */ virtual void toStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const; #endif /// Return string representation for the AST virtual ANTLR_USE_NAMESPACE(std)string toString() const; /// Print out a child sibling tree in LISP notation virtual ANTLR_USE_NAMESPACE(std)string toStringList() const; virtual ANTLR_USE_NAMESPACE(std)string toStringTree() const; static const char* const TYPE_NAME; protected: RefBaseAST down; RefBaseAST right; private: void doWorkForFindAll(ANTLR_USE_NAMESPACE(std)vector& v, RefAST target, bool partialMatch); }; /** Is node t equal to this in terms of token type and text? */ inline bool BaseAST::equals(RefAST t) const { if (!t) return false; return ((getType() == t->getType()) && (getText() == t->getText())); } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_BaseAST_hpp__ gdl-0.9.9/src/antlr/BitSet.cpp000066400000000000000000000022551340051421000160760ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: BitSet.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/BitSet.hpp" #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif BitSet::BitSet(unsigned int nbits) : storage(nbits) { for (unsigned int i = 0; i < nbits ; i++ ) storage[i] = false; } BitSet::BitSet( const unsigned long* bits_, unsigned int nlongs ) : storage(nlongs*32) { for ( unsigned int i = 0 ; i < (nlongs * 32); i++) storage[i] = (bits_[i>>5] & (1UL << (i&31))) ? true : false; } BitSet::~BitSet() { } void BitSet::add(unsigned int el) { if( el >= storage.size() ) storage.resize( el+1, false ); storage[el] = true; } bool BitSet::member(unsigned int el) const { if ( el >= storage.size()) return false; return storage[el]; } ANTLR_USE_NAMESPACE(std)vector BitSet::toArray() const { ANTLR_USE_NAMESPACE(std)vector elems; for (unsigned int i = 0; i < storage.size(); i++) { if (storage[i]) elems.push_back(i); } return elems; } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/BitSet.hpp000066400000000000000000000034611340051421000161030ustar00rootroot00000000000000#ifndef INC_BitSet_hpp__ #define INC_BitSet_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: BitSet.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /** A BitSet to replace java.util.BitSet. * Primary differences are that most set operators return new sets * as opposed to oring and anding "in place". Further, a number of * operations were added. I cannot contain a BitSet because there * is no way to access the internal bits (which I need for speed) * and, because it is final, I cannot subclass to add functionality. * Consider defining set degree. Without access to the bits, I must * call a method n times to test the ith bit...ack! * * Also seems like or() from util is wrong when size of incoming set is bigger * than this.length. * * This is a C++ version of the Java class described above, with only * a handful of the methods implemented, because we don't need the * others at runtime. It's really just a wrapper around vector, * which should probably be changed to a wrapper around bitset, once * bitset is more widely available. * * @author Terence Parr, MageLang Institute * @author
Pete Wells */ class ANTLR_API BitSet { private: ANTLR_USE_NAMESPACE(std)vector storage; public: BitSet( unsigned int nbits=64 ); BitSet( const unsigned long* bits_, unsigned int nlongs); ~BitSet(); void add( unsigned int el ); bool member( unsigned int el ) const; ANTLR_USE_NAMESPACE(std)vector toArray() const; }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif #endif //INC_BitSet_hpp__ gdl-0.9.9/src/antlr/CMakeLists.txt000066400000000000000000000006331340051421000167360ustar00rootroot00000000000000aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} ANTLRSOURCES) list(REMOVE_ITEM ANTLRSOURCES ${CMAKE_CURRENT_SOURCE_DIR}/dll.cpp) include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src/antlr) if(PYTHON_MODULE) add_library(antlr SHARED ${ANTLRSOURCES}) install(TARGETS antlr DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) else(PYTHON_MODULE) add_library(antlr STATIC ${ANTLRSOURCES}) endif(PYTHON_MODULE) gdl-0.9.9/src/antlr/CharBuffer.cpp000066400000000000000000000025771340051421000167220ustar00rootroot00000000000000/* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharBuffer.cpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include "antlr/CharBuffer.hpp" #include //#include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /* RK: Per default istream does not throw exceptions. This can be * enabled with: * stream.exceptions(ios_base::badbit|ios_base::failbit|ios_base::eofbit); * * We could try catching the bad/fail stuff. But handling eof via this is * not a good idea. EOF is best handled as a 'normal' character. * * So this does not work yet with gcc... Comment it until I get to a platform * that does.. */ /** Create a character buffer. Enable fail and bad exceptions, if supported * by platform. */ CharBuffer::CharBuffer(ANTLR_USE_NAMESPACE(std)istream& input_) : input(input_) { // input.exceptions(ANTLR_USE_NAMESPACE(std)ios_base::badbit| // ANTLR_USE_NAMESPACE(std)ios_base::failbit); } /** Get the next character from the stream. May throw CharStreamIOException * when something bad happens (not EOF) (if supported by platform). */ int CharBuffer::getChar() { // try { return input.get(); // } // catch (ANTLR_USE_NAMESPACE(std)ios_base::failure& e) { // throw CharStreamIOException(e); // } } #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE } #endif gdl-0.9.9/src/antlr/CharBuffer.hpp000066400000000000000000000026501340051421000167170ustar00rootroot00000000000000#ifndef INC_CharBuffer_hpp__ #define INC_CharBuffer_hpp__ /* ANTLR Translator Generator * Project led by Terence Parr at http://www.jGuru.com * Software rights: http://www.antlr.org/license.html * * $Id: CharBuffer.hpp,v 1.1.1.1 2004-12-09 15:10:20 m_schellens Exp $ */ #include #include #include #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE namespace antlr { #endif /**A Stream of characters fed to the lexer from a InputStream that can * be rewound via mark()/rewind() methods. *